| author | |
| committer | |
| log | 3edaef9e011ac500f66c9ee0ba3ea24be905bcde |
| tree | cc2ececf026f2098b375267bb07a342d4b83212f |
| parent | b80abf0296de5034ddaf149074fe7de18347bc20 |
| parent | 502cab9ae30b001a8da2f724711330a73e7e2e4f |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31403272 files changed, 26992 insertions(+), 33526 deletions(-)
CMakeLists.txt+12-4| ... | ... | @@ -330,7 +330,6 @@ set(ZIG_STAGE2_SOURCES |
| 330 | 330 | src/Air/Liveness.zig |
| 331 | 331 | src/Air/Liveness/Verify.zig |
| 332 | 332 | src/Air/print.zig |
| 333 | src/Air/types_resolved.zig | |
| 334 | 333 | src/Builtin.zig |
| 335 | 334 | src/Compilation.zig |
| 336 | 335 | src/Compilation/Config.zig |
| ... | ... | @@ -344,6 +343,7 @@ set(ZIG_STAGE2_SOURCES |
| 344 | 343 | src/Sema.zig |
| 345 | 344 | src/Sema/bitcast.zig |
| 346 | 345 | src/Sema/comptime_ptr_access.zig |
| 346 | src/Sema/type_resolution.zig | |
| 347 | 347 | src/Type.zig |
| 348 | 348 | src/Value.zig |
| 349 | 349 | src/Zcu.zig |
| ... | ... | @@ -360,7 +360,8 @@ set(ZIG_STAGE2_SOURCES |
| 360 | 360 | src/codegen/aarch64/Mir.zig |
| 361 | 361 | src/codegen/aarch64/Select.zig |
| 362 | 362 | src/codegen/c.zig |
| 363 | src/codegen/c/Type.zig | |
| 363 | src/codegen/c/type.zig | |
| 364 | src/codegen/c/type/render_defs.zig | |
| 364 | 365 | src/codegen/llvm.zig |
| 365 | 366 | src/codegen/llvm/bindings.zig |
| 366 | 367 | src/crash_report.zig |
| ... | ... | @@ -375,6 +376,7 @@ set(ZIG_STAGE2_SOURCES |
| 375 | 376 | src/libs/libunwind.zig |
| 376 | 377 | src/link.zig |
| 377 | 378 | src/link/C.zig |
| 379 | src/link/ConstPool.zig | |
| 378 | 380 | src/link/Coff.zig |
| 379 | 381 | src/link/Dwarf.zig |
| 380 | 382 | src/link/Elf.zig |
| ... | ... | @@ -606,8 +608,8 @@ if(MSVC) |
| 606 | 608 | set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE") |
| 607 | 609 | else() |
| 608 | 610 | set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2") |
| 609 | set(ZIG1_COMPILE_FLAGS "-std=c99 -Os") | |
| 610 | set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector") | |
| 611 | set(ZIG1_COMPILE_FLAGS "-std=c99 -Os -fno-strict-aliasing") | |
| 612 | set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing") | |
| 611 | 613 | # Must match the condition in build.zig. |
| 612 | 614 | if(ZIG_HOST_TARGET_ARCH MATCHES "^(arm|thumb)(eb)?$" OR ZIG_HOST_TARGET_ARCH MATCHES "^powerpc(64)?(le)?$") |
| 613 | 615 | set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections") |
| ... | ... | @@ -623,6 +625,12 @@ else() |
| 623 | 625 | else() |
| 624 | 626 | set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000") |
| 625 | 627 | endif() |
| 628 | # Prevent GCC from miscompiling 'zig2.c'. See also 'workaround_gcc_sra_miscomp' in 'bootstrap.c'. | |
| 629 | if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND | |
| 630 | CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "13.0" AND | |
| 631 | CMAKE_C_COMPILER_VERSION VERSION_LESS_EQUAL "15.2") | |
| 632 | set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -fno-tree-sra") | |
| 633 | endif() | |
| 626 | 634 | endif() |
| 627 | 635 | |
| 628 | 636 | set(ZIG1_WASM_MODULE "${PROJECT_SOURCE_DIR}/stage1/zig1.wasm") |
bootstrap.c+23-1| ... | ... | @@ -102,6 +102,26 @@ int main(int argc, char **argv) { |
| 102 | 102 | const char *cc = get_c_compiler(); |
| 103 | 103 | const char *host_triple = get_host_triple(); |
| 104 | 104 | |
| 105 | // GCC versions 13.0--14.1 have a miscompilation where some bytes of a union may get clobbered | |
| 106 | // depending on the union layout and the order in which types are defined. This miscompilation | |
| 107 | // affects the output of the C backend, and thus can affect the bootstrap process. Specifically, | |
| 108 | // we observe that using the self-hosted x86_64 backend in 'zig2' will cause all function calls | |
| 109 | // to be relocated incorrectly, causing immediate crashes on any binary produced by it. | |
| 110 | // | |
| 111 | // The only reliable workaround for this bug is to disable the optimization pass containing it, | |
| 112 | // so here we check for a CLI flag requesting that workaround. | |
| 113 | // | |
| 114 | // The upstream bug is fixed in GCC version 15.2 onwards (and was also backported to the 13 and | |
| 115 | // 14 branches). Once this bug is no longer widespread, we can remove this CLI flag. | |
| 116 | // | |
| 117 | // Upstream bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119085 | |
| 118 | bool workaround_gcc_sra_miscomp = false; | |
| 119 | for (int i = 1; i < argc; ++i) { | |
| 120 | if (!strcmp(argv[i], "--workaround-gcc-sra-miscomp")) { | |
| 121 | workaround_gcc_sra_miscomp = true; | |
| 122 | } | |
| 123 | } | |
| 124 | ||
| 105 | 125 | { |
| 106 | 126 | const char *child_argv[] = { |
| 107 | 127 | cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL, |
| ... | ... | @@ -116,7 +136,7 @@ int main(int argc, char **argv) { |
| 116 | 136 | } |
| 117 | 137 | { |
| 118 | 138 | const char *child_argv[] = { |
| 119 | cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-lm", NULL, | |
| 139 | cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-fno-strict-aliasing", "-lm", NULL, | |
| 120 | 140 | }; |
| 121 | 141 | print_and_run(child_argv); |
| 122 | 142 | } |
| ... | ... | @@ -193,6 +213,8 @@ int main(int argc, char **argv) { |
| 193 | 213 | #if defined(__GNUC__) |
| 194 | 214 | "-pthread", |
| 195 | 215 | #endif |
| 216 | "-fno-strict-aliasing", | |
| 217 | workaround_gcc_sra_miscomp ? "-fno-tree-sra" : NULL, | |
| 196 | 218 | NULL, |
| 197 | 219 | }; |
| 198 | 220 | print_and_run(child_argv); |
build.zig+4-4| ... | ... | @@ -568,7 +568,7 @@ pub fn build(b: *std.Build) !void { |
| 568 | 568 | .skip_linux = skip_linux, |
| 569 | 569 | .skip_llvm = skip_llvm, |
| 570 | 570 | .skip_libc = skip_libc, |
| 571 | .max_rss = 8_500_000_000, | |
| 571 | .max_rss = 9_300_000_000, | |
| 572 | 572 | })); |
| 573 | 573 | |
| 574 | 574 | const unit_tests_step = b.step("test-unit", "Run the compiler source unit tests"); |
| ... | ... | @@ -584,7 +584,7 @@ pub fn build(b: *std.Build) !void { |
| 584 | 584 | .use_llvm = use_llvm, |
| 585 | 585 | .use_lld = use_llvm, |
| 586 | 586 | .zig_lib_dir = b.path("lib"), |
| 587 | .max_rss = 2_500_000_000, | |
| 587 | .max_rss = 2_700_000_000, | |
| 588 | 588 | }); |
| 589 | 589 | if (link_libc) { |
| 590 | 590 | unit_tests.root_module.link_libc = true; |
| ... | ... | @@ -611,7 +611,7 @@ pub fn build(b: *std.Build) !void { |
| 611 | 611 | .skip_linux = skip_linux, |
| 612 | 612 | .skip_llvm = skip_llvm, |
| 613 | 613 | .skip_release = skip_release, |
| 614 | .max_rss = 3_000_000_000, | |
| 614 | .max_rss = 3_300_000_000, | |
| 615 | 615 | })); |
| 616 | 616 | test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows)); |
| 617 | 617 | test_step.dependOn(tests.addStackTraceTests(b, test_filters, skip_non_native)); |
| ... | ... | @@ -767,7 +767,7 @@ fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Modu |
| 767 | 767 | fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Step.Compile { |
| 768 | 768 | const exe = b.addExecutable(.{ |
| 769 | 769 | .name = "zig", |
| 770 | .max_rss = 7_900_000_000, | |
| 770 | .max_rss = 8_700_000_000, | |
| 771 | 771 | .root_module = addCompilerMod(b, options), |
| 772 | 772 | }); |
| 773 | 773 | exe.stack_size = stack_size; |
ci/aarch64-freebsd-debug.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 2m |
ci/aarch64-freebsd-release.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 2m |
ci/aarch64-linux-debug.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | -Dtarget=native-native-musl \ |
| 52 | 51 | --search-prefix "$PREFIX" \ |
| 53 | 52 | --zig-lib-dir "$PWD/../lib" \ |
ci/aarch64-linux-release.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | -Dtarget=native-native-musl \ |
| 52 | 51 | --search-prefix "$PREFIX" \ |
| 53 | 52 | --zig-lib-dir "$PWD/../lib" \ |
ci/aarch64-macos-debug.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ |
| 47 | 47 | -Denable-macos-sdk \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --test-timeout 2m |
| 53 | 52 |
ci/aarch64-macos-release.sh-1| ... | ... | @@ -46,7 +46,6 @@ stage3-release/bin/zig build test docs \ |
| 46 | 46 | -Denable-macos-sdk \ |
| 47 | 47 | -Dstatic-llvm \ |
| 48 | 48 | -Dskip-non-native \ |
| 49 | -Dskip-test-incremental \ | |
| 50 | 49 | --search-prefix "$PREFIX" \ |
| 51 | 50 | --test-timeout 2m |
| 52 | 51 |
ci/aarch64-netbsd-debug.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 4m |
ci/aarch64-netbsd-release.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 4m |
ci/aarch64-windows.ps1-1| ... | ... | @@ -60,7 +60,6 @@ Write-Output "Main test suite..." |
| 60 | 60 | --search-prefix "$PREFIX_PATH" ` |
| 61 | 61 | -Dstatic-llvm ` |
| 62 | 62 | -Dskip-non-native ` |
| 63 | -Dskip-test-incremental ` | |
| 64 | 63 | -Denable-symlinks-windows ` |
| 65 | 64 | --test-timeout 30m |
| 66 | 65 | CheckLastExitCode |
ci/loongarch64-linux-debug.sh-1| ... | ... | @@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \ |
| 48 | 48 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 49 | 49 | -Dstatic-llvm \ |
| 50 | 50 | -Dskip-non-native \ |
| 51 | -Dskip-test-incremental \ | |
| 52 | 51 | -Dtarget=native-native-musl \ |
| 53 | 52 | --search-prefix "$PREFIX" \ |
| 54 | 53 | --zig-lib-dir "$PWD/../lib" \ |
ci/loongarch64-linux-release.sh-1| ... | ... | @@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \ |
| 48 | 48 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 49 | 49 | -Dstatic-llvm \ |
| 50 | 50 | -Dskip-non-native \ |
| 51 | -Dskip-test-incremental \ | |
| 52 | 51 | -Dtarget=native-native-musl \ |
| 53 | 52 | --search-prefix "$PREFIX" \ |
| 54 | 53 | --zig-lib-dir "$PWD/../lib" \ |
ci/powerpc64le-linux-debug.sh-1| ... | ... | @@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \ |
| 48 | 48 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 49 | 49 | -Dstatic-llvm \ |
| 50 | 50 | -Dskip-non-native \ |
| 51 | -Dskip-test-incremental \ | |
| 52 | 51 | -Dtarget=native-native-musl \ |
| 53 | 52 | -Dcpu=native+longcall \ |
| 54 | 53 | --search-prefix "$PREFIX" \ |
ci/powerpc64le-linux-release.sh-1| ... | ... | @@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \ |
| 48 | 48 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 49 | 49 | -Dstatic-llvm \ |
| 50 | 50 | -Dskip-non-native \ |
| 51 | -Dskip-test-incremental \ | |
| 52 | 51 | -Dtarget=native-native-musl \ |
| 53 | 52 | -Dcpu=native+longcall \ |
| 54 | 53 | --search-prefix "$PREFIX" \ |
ci/s390x-linux-debug.sh-1| ... | ... | @@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \ |
| 48 | 48 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 49 | 49 | -Dstatic-llvm \ |
| 50 | 50 | -Dskip-non-native \ |
| 51 | -Dskip-test-incremental \ | |
| 52 | 51 | -Dtarget=native-native-musl \ |
| 53 | 52 | --search-prefix "$PREFIX" \ |
| 54 | 53 | --zig-lib-dir "$PWD/../lib" \ |
ci/s390x-linux-release.sh-1| ... | ... | @@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \ |
| 48 | 48 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 49 | 49 | -Dstatic-llvm \ |
| 50 | 50 | -Dskip-non-native \ |
| 51 | -Dskip-test-incremental \ | |
| 52 | 51 | -Dtarget=native-native-musl \ |
| 53 | 52 | --search-prefix "$PREFIX" \ |
| 54 | 53 | --zig-lib-dir "$PWD/../lib" \ |
ci/x86_64-freebsd-debug.sh-1| ... | ... | @@ -53,7 +53,6 @@ stage3-debug/bin/zig build test docs \ |
| 53 | 53 | -Dskip-openbsd \ |
| 54 | 54 | -Dskip-windows \ |
| 55 | 55 | -Dskip-darwin \ |
| 56 | -Dskip-test-incremental \ | |
| 57 | 56 | --search-prefix "$PREFIX" \ |
| 58 | 57 | --zig-lib-dir "$PWD/../lib" \ |
| 59 | 58 | --test-timeout 2m |
ci/x86_64-freebsd-release.sh-1| ... | ... | @@ -53,7 +53,6 @@ stage3-release/bin/zig build test docs \ |
| 53 | 53 | -Dskip-openbsd \ |
| 54 | 54 | -Dskip-windows \ |
| 55 | 55 | -Dskip-darwin \ |
| 56 | -Dskip-test-incremental \ | |
| 57 | 56 | --search-prefix "$PREFIX" \ |
| 58 | 57 | --zig-lib-dir "$PWD/../lib" \ |
| 59 | 58 | --test-timeout 2m |
ci/x86_64-linux-debug-llvm.sh-1| ... | ... | @@ -64,7 +64,6 @@ stage3-debug/bin/zig build test docs \ |
| 64 | 64 | -Dskip-openbsd \ |
| 65 | 65 | -Dskip-windows \ |
| 66 | 66 | -Dskip-darwin \ |
| 67 | -Dskip-test-incremental \ | |
| 68 | 67 | -Dtarget=native-native-musl \ |
| 69 | 68 | --search-prefix "$PREFIX" \ |
| 70 | 69 | --zig-lib-dir "$PWD/../lib" \ |
ci/x86_64-linux-debug.sh-1| ... | ... | @@ -63,7 +63,6 @@ stage3-debug/bin/zig build test docs \ |
| 63 | 63 | -Dskip-windows \ |
| 64 | 64 | -Dskip-darwin \ |
| 65 | 65 | -Dskip-llvm \ |
| 66 | -Dskip-test-incremental \ | |
| 67 | 66 | -Dtarget=native-native-musl \ |
| 68 | 67 | --search-prefix "$PREFIX" \ |
| 69 | 68 | --zig-lib-dir "$PWD/../lib" \ |
ci/x86_64-linux-release.sh+2-2| ... | ... | @@ -21,7 +21,8 @@ export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" |
| 21 | 21 | |
| 22 | 22 | # Test building from source without LLVM. |
| 23 | 23 | cc -o bootstrap bootstrap.c |
| 24 | ./bootstrap | |
| 24 | # See comments in bootstrap.c for an explanation of the flag given here. | |
| 25 | ./bootstrap --workaround-gcc-sra-miscomp | |
| 25 | 26 | ./zig2 build -Dno-lib |
| 26 | 27 | ./zig-out/bin/zig test test/behavior.zig |
| 27 | 28 | |
| ... | ... | @@ -64,7 +65,6 @@ stage3-release/bin/zig build test docs \ |
| 64 | 65 | --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ |
| 65 | 66 | -fwasmtime \ |
| 66 | 67 | -Dstatic-llvm \ |
| 67 | -Dskip-test-incremental \ | |
| 68 | 68 | -Dtarget=native-native-musl \ |
| 69 | 69 | --search-prefix "$PREFIX" \ |
| 70 | 70 | --zig-lib-dir "$PWD/../lib" \ |
ci/x86_64-netbsd-debug.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 2m |
ci/x86_64-netbsd-release.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 2m |
ci/x86_64-openbsd-debug.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 2m |
ci/x86_64-openbsd-release.sh-1| ... | ... | @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | 49 | -Dskip-non-native \ |
| 50 | -Dskip-test-incremental \ | |
| 51 | 50 | --search-prefix "$PREFIX" \ |
| 52 | 51 | --zig-lib-dir "$PWD/../lib" \ |
| 53 | 52 | --test-timeout 2m |
doc/langref.html.in+3-2| ... | ... | @@ -2103,8 +2103,9 @@ or |
| 2103 | 2103 | less than {#syntax#}1 << 29{#endsyntax#}. |
| 2104 | 2104 | </p> |
| 2105 | 2105 | <p> |
| 2106 | In Zig, a pointer type has an alignment value. If the value is equal to the | |
| 2107 | alignment of the underlying type, it can be omitted from the type: | |
| 2106 | Pointer types may explicitly specify an alignment in bytes. If it is not | |
| 2107 | specified, the alignment is assumed to be equal to the alignment of the | |
| 2108 | underlying type. | |
| 2108 | 2109 | </p> |
| 2109 | 2110 | {#code|test_variable_alignment.zig#} |
| 2110 | 2111 |
doc/langref/test_comptime_invalid_error_code.zig+2-5| ... | ... | @@ -1,8 +1,5 @@ |
| 1 | 1 | comptime { |
| 2 | const err = error.AnError; | |
| 3 | const number = @intFromError(err) + 10; | |
| 4 | const invalid_err = @errorFromInt(number); | |
| 5 | _ = invalid_err; | |
| 2 | _ = @errorFromInt(12345); | |
| 6 | 3 | } |
| 7 | 4 | |
| 8 | // test_error=integer value '11' represents no error | |
| 5 | // test_error=integer value '12345' represents no error |
doc/langref/test_missized_packed_struct.zig+1-1| ... | ... | @@ -3,4 +3,4 @@ test "missized packed struct" { |
| 3 | 3 | _ = S{ .a = 4, .b = 2 }; |
| 4 | 4 | } |
| 5 | 5 | |
| 6 | // test_error=backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 24 | |
| 6 | // test_error=backing integer bit width does not match total bit width of fields |
doc/langref/test_variable_alignment.zig+10-5| ... | ... | @@ -1,15 +1,20 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const expect = std.testing.expect; | |
| 3 | 4 | const expectEqual = std.testing.expectEqual; |
| 4 | 5 | |
| 5 | 6 | test "variable alignment" { |
| 6 | 7 | var x: i32 = 1234; |
| 7 | const align_of_i32 = @alignOf(@TypeOf(x)); | |
| 8 | ||
| 8 | 9 | try expectEqual(*i32, @TypeOf(&x)); |
| 9 | try expectEqual(*align(align_of_i32) i32, *i32); | |
| 10 | if (builtin.target.cpu.arch == .x86_64) { | |
| 11 | try expectEqual(4, @typeInfo(*i32).pointer.alignment); | |
| 12 | } | |
| 10 | ||
| 11 | try expect(@intFromPtr(&x) % @alignOf(i32) == 0); | |
| 12 | ||
| 13 | // The implicitly-aligned pointer can be coerced to be explicitly-aligned to | |
| 14 | // the alignment of the underlying type `i32`: | |
| 15 | const ptr: *align(@alignOf(i32)) i32 = &x; | |
| 16 | ||
| 17 | try expectEqual(1234, ptr.*); | |
| 13 | 18 | } |
| 14 | 19 | |
| 15 | 20 | // test |
lib/compiler/aro/aro/InitList.zig+13-7| ... | ... | @@ -22,9 +22,15 @@ const Item = struct { |
| 22 | 22 | |
| 23 | 23 | const InitList = @This(); |
| 24 | 24 | |
| 25 | list: std.ArrayList(Item) = .empty, | |
| 26 | node: Node.OptIndex = .null, | |
| 27 | tok: TokenIndex = 0, | |
| 25 | list: std.ArrayList(Item), | |
| 26 | node: Node.OptIndex, | |
| 27 | tok: TokenIndex, | |
| 28 | ||
| 29 | pub const empty: InitList = .{ | |
| 30 | .list = .empty, | |
| 31 | .node = .null, | |
| 32 | .tok = 0, | |
| 33 | }; | |
| 28 | 34 | |
| 29 | 35 | /// Deinitialize freeing all memory. |
| 30 | 36 | pub fn deinit(il: *InitList, gpa: Allocator) void { |
| ... | ... | @@ -43,7 +49,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { |
| 43 | 49 | if (il.list.items.len == 0) { |
| 44 | 50 | const item = try il.list.addOne(gpa); |
| 45 | 51 | item.* = .{ |
| 46 | .list = .{}, | |
| 52 | .list = .empty, | |
| 47 | 53 | .index = index, |
| 48 | 54 | }; |
| 49 | 55 | return &item.list; |
| ... | ... | @@ -51,7 +57,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { |
| 51 | 57 | // Append a new value to the end of the list. |
| 52 | 58 | const new = try il.list.addOne(gpa); |
| 53 | 59 | new.* = .{ |
| 54 | .list = .{}, | |
| 60 | .list = .empty, | |
| 55 | 61 | .index = index, |
| 56 | 62 | }; |
| 57 | 63 | return &new.list; |
| ... | ... | @@ -70,7 +76,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { |
| 70 | 76 | |
| 71 | 77 | // Insert a new value into a sorted position. |
| 72 | 78 | try il.list.insert(gpa, left, .{ |
| 73 | .list = .{}, | |
| 79 | .list = .empty, | |
| 74 | 80 | .index = index, |
| 75 | 81 | }); |
| 76 | 82 | return &il.list.items[left].list; |
| ... | ... | @@ -78,7 +84,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { |
| 78 | 84 | |
| 79 | 85 | test "basic usage" { |
| 80 | 86 | const gpa = testing.allocator; |
| 81 | var il: InitList = .{}; | |
| 87 | var il: InitList = .empty; | |
| 82 | 88 | defer il.deinit(gpa); |
| 83 | 89 | |
| 84 | 90 | { |
lib/compiler/aro/aro/Parser.zig+3-3| ... | ... | @@ -3977,7 +3977,7 @@ fn initializer(p: *Parser, init_qt: QualType) Error!Result { |
| 3977 | 3977 | final_init_qt = .invalid; |
| 3978 | 3978 | } |
| 3979 | 3979 | |
| 3980 | var il: InitList = .{}; | |
| 3980 | var il: InitList = .empty; | |
| 3981 | 3981 | defer il.deinit(p.comp.gpa); |
| 3982 | 3982 | |
| 3983 | 3983 | try p.initializerItem(&il, final_init_qt, l_brace); |
| ... | ... | @@ -4028,12 +4028,12 @@ fn initializerItem(p: *Parser, il: *InitList, init_qt: QualType, l_brace: TokenI |
| 4028 | 4028 | try p.err(first_tok, .initializer_overrides, .{}); |
| 4029 | 4029 | try p.err(item.il.tok, .previous_initializer, .{}); |
| 4030 | 4030 | item.il.deinit(gpa); |
| 4031 | item.il.* = .{}; | |
| 4031 | item.il.* = .empty; | |
| 4032 | 4032 | } |
| 4033 | 4033 | try p.initializerItem(item.il, item.qt, inner_l_brace); |
| 4034 | 4034 | } else { |
| 4035 | 4035 | // discard further values |
| 4036 | var tmp_il: InitList = .{}; | |
| 4036 | var tmp_il: InitList = .empty; | |
| 4037 | 4037 | defer tmp_il.deinit(gpa); |
| 4038 | 4038 | try p.initializerItem(&tmp_il, .invalid, inner_l_brace); |
| 4039 | 4039 | if (!warned_excess) try p.err(first_tok, switch (init_qt.base(p.comp).type) { |
lib/compiler/aro/aro/Toolchain.zig+3-3| ... | ... | @@ -43,13 +43,13 @@ const Toolchain = @This(); |
| 43 | 43 | driver: *Driver, |
| 44 | 44 | |
| 45 | 45 | /// The list of toolchain specific path prefixes to search for libraries. |
| 46 | library_paths: PathList = .{}, | |
| 46 | library_paths: PathList = .empty, | |
| 47 | 47 | |
| 48 | 48 | /// The list of toolchain specific path prefixes to search for files. |
| 49 | file_paths: PathList = .{}, | |
| 49 | file_paths: PathList = .empty, | |
| 50 | 50 | |
| 51 | 51 | /// The list of toolchain specific path prefixes to search for programs. |
| 52 | program_paths: PathList = .{}, | |
| 52 | program_paths: PathList = .empty, | |
| 53 | 53 | |
| 54 | 54 | selected_multilib: Multilib = .{}, |
| 55 | 55 |
lib/compiler/objcopy.zig+2-2| ... | ... | @@ -388,8 +388,8 @@ const BinaryElfOutput = struct { |
| 388 | 388 | |
| 389 | 389 | pub fn parse(allocator: Allocator, in: *File.Reader, elf_hdr: elf.Header) !Self { |
| 390 | 390 | var self: Self = .{ |
| 391 | .segments = .{}, | |
| 392 | .sections = .{}, | |
| 391 | .segments = .empty, | |
| 392 | .sections = .empty, | |
| 393 | 393 | .allocator = allocator, |
| 394 | 394 | .shstrtab = null, |
| 395 | 395 | }; |
lib/compiler/resinator/cvtres.zig+1-1| ... | ... | @@ -410,7 +410,7 @@ pub const ResourceDirectoryTable = extern struct { |
| 410 | 410 | }; |
| 411 | 411 | |
| 412 | 412 | pub const ResourceDirectoryEntry = extern struct { |
| 413 | entry: packed union { | |
| 413 | entry: packed union(u32) { | |
| 414 | 414 | name_offset: packed struct(u32) { |
| 415 | 415 | address: u31, |
| 416 | 416 | /// This is undocumented in the PE/COFF spec, but the high bit |
lib/compiler/test_runner.zig+4-4| ... | ... | @@ -38,10 +38,10 @@ pub fn main(init: std.process.Init.Minimal) void { |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | if (need_simple) { |
| 41 | return mainSimple() catch @panic("test failure"); | |
| 41 | return mainSimple() catch |err| std.debug.panic("test failure: {t}", .{err}); | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | const args = init.args.toSlice(fba.allocator()) catch @panic("unable to parse command line args"); | |
| 44 | const args = init.args.toSlice(fba.allocator()) catch |err| std.debug.panic("unable to parse command line args: {t}", .{err}); | |
| 45 | 45 | |
| 46 | 46 | var listen = false; |
| 47 | 47 | var opt_cache_dir: ?[]const u8 = null; |
| ... | ... | @@ -55,7 +55,7 @@ pub fn main(init: std.process.Init.Minimal) void { |
| 55 | 55 | } else if (std.mem.startsWith(u8, arg, "--cache-dir")) { |
| 56 | 56 | opt_cache_dir = arg["--cache-dir=".len..]; |
| 57 | 57 | } else { |
| 58 | @panic("unrecognized command line argument"); | |
| 58 | std.debug.panic("unrecognized command line argument: {s}", .{arg}); | |
| 59 | 59 | } |
| 60 | 60 | } |
| 61 | 61 | |
| ... | ... | @@ -65,7 +65,7 @@ pub fn main(init: std.process.Init.Minimal) void { |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | if (listen) { |
| 68 | return mainServer(init) catch @panic("internal test runner failure"); | |
| 68 | return mainServer(init) catch |err| std.debug.panic("internal test runner failure: {t}", .{err}); | |
| 69 | 69 | } else { |
| 70 | 70 | return mainTerminal(init); |
| 71 | 71 | } |
lib/std/Build/Fuzz.zig+2-2| ... | ... | @@ -390,7 +390,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO |
| 390 | 390 | .coverage = std.debug.Coverage.init, |
| 391 | 391 | .mapped_memory = undefined, // populated below |
| 392 | 392 | .source_locations = undefined, // populated below |
| 393 | .entry_points = .{}, | |
| 393 | .entry_points = .empty, | |
| 394 | 394 | .start_timestamp = ws.now(), |
| 395 | 395 | .start_n_runs = undefined, // populated below |
| 396 | 396 | }; |
| ... | ... | @@ -450,7 +450,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO |
| 450 | 450 | |
| 451 | 451 | // Unfortunately the PCs array that LLVM gives us from the 8-bit PC |
| 452 | 452 | // counters feature is not sorted. |
| 453 | var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .{}; | |
| 453 | var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .empty; | |
| 454 | 454 | defer sorted_pcs.deinit(gpa); |
| 455 | 455 | try sorted_pcs.resize(gpa, pcs.len); |
| 456 | 456 | @memcpy(sorted_pcs.items(.pc), pcs); |
lib/std/Build/Module.zig+7-7| ... | ... | @@ -275,18 +275,18 @@ pub fn init( |
| 275 | 275 | m.* = .{ |
| 276 | 276 | .owner = owner, |
| 277 | 277 | .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null, |
| 278 | .import_table = .{}, | |
| 278 | .import_table = .empty, | |
| 279 | 279 | .resolved_target = options.target, |
| 280 | 280 | .optimize = options.optimize, |
| 281 | 281 | .link_libc = options.link_libc, |
| 282 | 282 | .link_libcpp = options.link_libcpp, |
| 283 | 283 | .dwarf_format = options.dwarf_format, |
| 284 | .c_macros = .{}, | |
| 285 | .include_dirs = .{}, | |
| 286 | .lib_paths = .{}, | |
| 287 | .rpaths = .{}, | |
| 288 | .frameworks = .{}, | |
| 289 | .link_objects = .{}, | |
| 284 | .c_macros = .empty, | |
| 285 | .include_dirs = .empty, | |
| 286 | .lib_paths = .empty, | |
| 287 | .rpaths = .empty, | |
| 288 | .frameworks = .empty, | |
| 289 | .link_objects = .empty, | |
| 290 | 290 | .strip = options.strip, |
| 291 | 291 | .unwind_tables = options.unwind_tables, |
| 292 | 292 | .single_threaded = options.single_threaded, |
lib/std/Build/Step.zig+1-1| ... | ... | @@ -250,7 +250,7 @@ pub fn init(options: StepOptions) Step { |
| 250 | 250 | const first_ret_addr = options.first_ret_addr orelse @returnAddress(); |
| 251 | 251 | break :blk std.debug.captureCurrentStackTrace(.{ .first_address = first_ret_addr }, addr_buf); |
| 252 | 252 | }, |
| 253 | .result_error_msgs = .{}, | |
| 253 | .result_error_msgs = .empty, | |
| 254 | 254 | .result_error_bundle = std.zig.ErrorBundle.empty, |
| 255 | 255 | .result_stderr = "", |
| 256 | 256 | .result_cached = false, |
lib/std/Build/Step/Run.zig+4-4| ... | ... | @@ -213,13 +213,13 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { |
| 213 | 213 | .owner = owner, |
| 214 | 214 | .makeFn = make, |
| 215 | 215 | }), |
| 216 | .argv = .{}, | |
| 216 | .argv = .empty, | |
| 217 | 217 | .cwd = null, |
| 218 | 218 | .environ_map = null, |
| 219 | 219 | .disable_zig_progress = false, |
| 220 | 220 | .stdio = .infer_from_args, |
| 221 | 221 | .stdin = .none, |
| 222 | .file_inputs = .{}, | |
| 222 | .file_inputs = .empty, | |
| 223 | 223 | .rename_step_with_output_arg = true, |
| 224 | 224 | .skip_foreign_checks = false, |
| 225 | 225 | .failing_to_execute_foreign_is_an_error = true, |
| ... | ... | @@ -228,7 +228,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { |
| 228 | 228 | .captured_stderr = null, |
| 229 | 229 | .dep_output_file = null, |
| 230 | 230 | .has_side_effects = false, |
| 231 | .fuzz_tests = .{}, | |
| 231 | .fuzz_tests = .empty, | |
| 232 | 232 | .rebuilt_executable = null, |
| 233 | 233 | .producer = null, |
| 234 | 234 | }; |
| ... | ... | @@ -642,7 +642,7 @@ pub fn addCheck(run: *Run, new_check: StdIo.Check) void { |
| 642 | 642 | |
| 643 | 643 | switch (run.stdio) { |
| 644 | 644 | .infer_from_args => { |
| 645 | run.stdio = .{ .check = .{} }; | |
| 645 | run.stdio = .{ .check = .empty }; | |
| 646 | 646 | run.stdio.check.append(b.allocator, new_check) catch @panic("OOM"); |
| 647 | 647 | }, |
| 648 | 648 | .check => |*checks| checks.append(b.allocator, new_check) catch @panic("OOM"), |
lib/std/Build/Step/UpdateSourceFiles.zig+1-1| ... | ... | @@ -35,7 +35,7 @@ pub fn create(owner: *std.Build) *UpdateSourceFiles { |
| 35 | 35 | .owner = owner, |
| 36 | 36 | .makeFn = make, |
| 37 | 37 | }), |
| 38 | .output_source_files = .{}, | |
| 38 | .output_source_files = .empty, | |
| 39 | 39 | }; |
| 40 | 40 | return usf; |
| 41 | 41 | } |
lib/std/Build/Step/WriteFile.zig+2-2| ... | ... | @@ -94,8 +94,8 @@ pub fn create(owner: *std.Build) *WriteFile { |
| 94 | 94 | .owner = owner, |
| 95 | 95 | .makeFn = make, |
| 96 | 96 | }), |
| 97 | .files = .{}, | |
| 98 | .directories = .{}, | |
| 97 | .files = .empty, | |
| 98 | .directories = .empty, | |
| 99 | 99 | .generated_directory = .{ .step = &write_file.step }, |
| 100 | 100 | }; |
| 101 | 101 | return write_file; |
lib/std/Io/Dir.zig+1-1| ... | ... | @@ -334,7 +334,7 @@ pub fn walkSelectively(dir: Dir, allocator: Allocator) !SelectiveWalker { |
| 334 | 334 | |
| 335 | 335 | return .{ |
| 336 | 336 | .stack = stack, |
| 337 | .name_buffer = .{}, | |
| 337 | .name_buffer = .empty, | |
| 338 | 338 | .allocator = allocator, |
| 339 | 339 | }; |
| 340 | 340 | } |
lib/std/array_list.zig+2-2| ... | ... | @@ -582,10 +582,10 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 582 | 582 | /// functions of this ArrayList in accordance with the respective |
| 583 | 583 | /// documentation. In all cases, "invalidated" means that the memory |
| 584 | 584 | /// has been passed to an allocator's resize or free function. |
| 585 | items: Slice = &[_]T{}, | |
| 585 | items: Slice, | |
| 586 | 586 | /// How many T values this list can hold without allocating |
| 587 | 587 | /// additional memory. |
| 588 | capacity: usize = 0, | |
| 588 | capacity: usize, | |
| 589 | 589 | |
| 590 | 590 | /// An ArrayList containing no elements. |
| 591 | 591 | pub const empty: Self = .{ |
lib/std/builtin.zig+8-4| ... | ... | @@ -592,8 +592,8 @@ pub const Type = union(enum) { |
| 592 | 592 | size: Size, |
| 593 | 593 | is_const: bool, |
| 594 | 594 | is_volatile: bool, |
| 595 | /// TODO make this u16 instead of comptime_int | |
| 596 | alignment: comptime_int, | |
| 595 | /// `null` means implicit alignment, which is equivalent to `@alignOf(child)`. | |
| 596 | alignment: ?usize, | |
| 597 | 597 | address_space: AddressSpace, |
| 598 | 598 | child: type, |
| 599 | 599 | is_allowzero: bool, |
| ... | ... | @@ -670,7 +670,9 @@ pub const Type = union(enum) { |
| 670 | 670 | /// See also: `defaultValue`. |
| 671 | 671 | default_value_ptr: ?*const anyopaque, |
| 672 | 672 | is_comptime: bool, |
| 673 | alignment: comptime_int, | |
| 673 | /// `null` means the field alignment was not explicitly specified. The | |
| 674 | /// field will still be aligned to at least `@alignOf` its `type`. | |
| 675 | alignment: ?usize, | |
| 674 | 676 | |
| 675 | 677 | /// Loads the field's default value from `default_value_ptr`. |
| 676 | 678 | /// Returns `null` if the field has no default value. |
| ... | ... | @@ -747,7 +749,9 @@ pub const Type = union(enum) { |
| 747 | 749 | pub const UnionField = struct { |
| 748 | 750 | name: [:0]const u8, |
| 749 | 751 | type: type, |
| 750 | alignment: comptime_int, | |
| 752 | /// `null` means the field alignment was not explicitly specified. The | |
| 753 | /// field will still be aligned to at least `@alignOf` its `type`. | |
| 754 | alignment: ?usize, | |
| 751 | 755 | |
| 752 | 756 | /// This data structure is used by the Zig language code generation and |
| 753 | 757 | /// therefore must be kept in sync with the compiler implementation. |
lib/std/c/darwin.zig+1-1| ... | ... | @@ -436,7 +436,7 @@ pub const thread_state_flavor_t = c_int; |
| 436 | 436 | pub const ipc_space_t = mach_port_t; |
| 437 | 437 | pub const ipc_space_port_t = ipc_space_t; |
| 438 | 438 | |
| 439 | pub const mach_msg_option_t = packed union { | |
| 439 | pub const mach_msg_option_t = packed union(integer_t) { | |
| 440 | 440 | RCV: MACH.RCV, |
| 441 | 441 | SEND: MACH.SEND, |
| 442 | 442 |
lib/std/c/darwin/dispatch.zig+1-1| ... | ... | @@ -210,7 +210,7 @@ pub const source_timer_flags_t = packed struct(usize) { |
| 210 | 210 | STRICT: bool = false, |
| 211 | 211 | unused1: @Int(.unsigned, @bitSizeOf(usize) - 1) = 0, |
| 212 | 212 | }; |
| 213 | pub const source_flags_t = packed union { | |
| 213 | pub const source_flags_t = packed union(usize) { | |
| 214 | 214 | raw: usize, |
| 215 | 215 | MACH_SEND: source_mach_send_flags_t, |
| 216 | 216 | MACH_RECV: source_mach_recv_flags_t, |
lib/std/compress/lzma.zig+1-1| ... | ... | @@ -349,7 +349,7 @@ pub const Decode = struct { |
| 349 | 349 | |
| 350 | 350 | pub fn init(dict_size: usize, mem_limit: usize) CircularBuffer { |
| 351 | 351 | return .{ |
| 352 | .buf = .{}, | |
| 352 | .buf = .empty, | |
| 353 | 353 | .dict_size = dict_size, |
| 354 | 354 | .mem_limit = mem_limit, |
| 355 | 355 | .cursor = 0, |
lib/std/compress/lzma2.zig+1-1| ... | ... | @@ -16,7 +16,7 @@ pub const AccumBuffer = struct { |
| 16 | 16 | |
| 17 | 17 | pub fn init(memlimit: usize) AccumBuffer { |
| 18 | 18 | return .{ |
| 19 | .buf = .{}, | |
| 19 | .buf = .empty, | |
| 20 | 20 | .memlimit = memlimit, |
| 21 | 21 | .len = 0, |
| 22 | 22 | }; |
lib/std/debug/Coverage.zig+3-3| ... | ... | @@ -27,10 +27,10 @@ string_bytes: std.ArrayList(u8), |
| 27 | 27 | mutex: Io.Mutex, |
| 28 | 28 | |
| 29 | 29 | pub const init: Coverage = .{ |
| 30 | .directories = .{}, | |
| 31 | .files = .{}, | |
| 30 | .directories = .empty, | |
| 31 | .files = .empty, | |
| 32 | 32 | .mutex = .init, |
| 33 | .string_bytes = .{}, | |
| 33 | .string_bytes = .empty, | |
| 34 | 34 | }; |
| 35 | 35 | |
| 36 | 36 | pub const String = enum(u32) { |
lib/std/elf.zig+2-2| ... | ... | @@ -1071,7 +1071,7 @@ pub const Elf32 = struct { |
| 1071 | 1071 | pub const Shdr = extern struct { |
| 1072 | 1072 | name: Word, |
| 1073 | 1073 | type: SHT, |
| 1074 | flags: packed struct { shf: SHF }, | |
| 1074 | flags: packed struct(Word) { shf: SHF }, | |
| 1075 | 1075 | addr: Elf32.Addr, |
| 1076 | 1076 | offset: Elf32.Off, |
| 1077 | 1077 | size: Word, |
| ... | ... | @@ -1161,7 +1161,7 @@ pub const Elf64 = struct { |
| 1161 | 1161 | pub const Shdr = extern struct { |
| 1162 | 1162 | name: Word, |
| 1163 | 1163 | type: SHT, |
| 1164 | flags: packed struct { shf: SHF, unused: Word = 0 }, | |
| 1164 | flags: packed struct(Xword) { shf: SHF, unused: Word = 0 }, | |
| 1165 | 1165 | addr: Elf64.Addr, |
| 1166 | 1166 | offset: Elf64.Off, |
| 1167 | 1167 | size: Xword, |
lib/std/hash_map.zig+3-3| ... | ... | @@ -1526,9 +1526,9 @@ pub fn HashMapUnmanaged( |
| 1526 | 1526 | } |
| 1527 | 1527 | |
| 1528 | 1528 | comptime { |
| 1529 | if (!builtin.strip_debug_info) _ = switch (builtin.zig_backend) { | |
| 1530 | .stage2_llvm => &dbHelper, | |
| 1531 | .stage2_x86_64 => KV, | |
| 1529 | if (!builtin.strip_debug_info) switch (builtin.zig_backend) { | |
| 1530 | .stage2_llvm => _ = &dbHelper, | |
| 1531 | .stage2_x86_64 => _ = @as(KV, undefined), | |
| 1532 | 1532 | else => {}, |
| 1533 | 1533 | }; |
| 1534 | 1534 | } |
lib/std/macho.zig+1-1| ... | ... | @@ -851,7 +851,7 @@ pub const nlist = extern struct { |
| 851 | 851 | |
| 852 | 852 | pub const nlist_64 = extern struct { |
| 853 | 853 | n_strx: u32, |
| 854 | n_type: packed union { | |
| 854 | n_type: packed union(u8) { | |
| 855 | 855 | bits: packed struct(u8) { |
| 856 | 856 | ext: bool, |
| 857 | 857 | type: enum(u3) { |
lib/std/math/big/int.zig+12-2| ... | ... | @@ -924,7 +924,12 @@ pub const Mutable = struct { |
| 924 | 924 | /// Asserts the result fits in `r`. Upper bound on the number of limbs needed by |
| 925 | 925 | /// r is `calcTwosCompLimbCount(bit_count)`. |
| 926 | 926 | pub fn bitReverse(r: *Mutable, a: Const, signedness: Signedness, bit_count: usize) void { |
| 927 | if (bit_count == 0) return; | |
| 927 | if (bit_count == 0) { | |
| 928 | r.limbs[0] = 0; | |
| 929 | r.len = 1; | |
| 930 | r.positive = true; | |
| 931 | return; | |
| 932 | } | |
| 928 | 933 | |
| 929 | 934 | r.copy(a); |
| 930 | 935 | |
| ... | ... | @@ -986,7 +991,12 @@ pub const Mutable = struct { |
| 986 | 991 | /// Asserts the result fits in `r`. Upper bound on the number of limbs needed by |
| 987 | 992 | /// r is `calcTwosCompLimbCount(8*byte_count)`. |
| 988 | 993 | pub fn byteSwap(r: *Mutable, a: Const, signedness: Signedness, byte_count: usize) void { |
| 989 | if (byte_count == 0) return; | |
| 994 | if (byte_count == 0) { | |
| 995 | r.limbs[0] = 0; | |
| 996 | r.len = 1; | |
| 997 | r.positive = true; | |
| 998 | return; | |
| 999 | } | |
| 990 | 1000 | |
| 991 | 1001 | r.copy(a); |
| 992 | 1002 | const limbs_required = calcTwosCompLimbCount(8 * byte_count); |
lib/std/mem.zig+12-4| ... | ... | @@ -38,6 +38,10 @@ pub const Alignment = enum(math.Log2Int(usize)) { |
| 38 | 38 | return @enumFromInt(@ctz(n)); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | pub fn fromByteUnitsOptional(maybe_n: ?usize) ?Alignment { | |
| 42 | return if (maybe_n) |n| .fromByteUnits(n) else null; | |
| 43 | } | |
| 44 | ||
| 41 | 45 | pub inline fn of(comptime T: type) Alignment { |
| 42 | 46 | return comptime fromByteUnits(@alignOf(T)); |
| 43 | 47 | } |
| ... | ... | @@ -2287,8 +2291,8 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a |
| 2287 | 2291 | ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); |
| 2288 | 2292 | } else inline for (std.meta.fields(S)) |f| { |
| 2289 | 2293 | switch (@typeInfo(f.type)) { |
| 2290 | .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)), | |
| 2291 | .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)), | |
| 2294 | .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)), | |
| 2295 | .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)), | |
| 2292 | 2296 | .@"enum" => { |
| 2293 | 2297 | @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name)))); |
| 2294 | 2298 | }, |
| ... | ... | @@ -4330,7 +4334,7 @@ pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize { |
| 4330 | 4334 | @compileError("expected many item pointer, got " ++ @typeName(T)); |
| 4331 | 4335 | |
| 4332 | 4336 | // Do nothing if the pointer is already well-aligned. |
| 4333 | if (align_to <= info.pointer.alignment) | |
| 4337 | if (align_to <= info.pointer.alignment orelse @alignOf(info.pointer.child)) | |
| 4334 | 4338 | return 0; |
| 4335 | 4339 | |
| 4336 | 4340 | // Calculate the aligned base address with an eye out for overflow. |
| ... | ... | @@ -4388,7 +4392,11 @@ fn CopyPtrAttrs( |
| 4388 | 4392 | .@"const" = ptr.is_const, |
| 4389 | 4393 | .@"volatile" = ptr.is_volatile, |
| 4390 | 4394 | .@"allowzero" = ptr.is_allowzero, |
| 4391 | .@"align" = ptr.alignment, | |
| 4395 | .@"align" = ptr.alignment orelse a: { | |
| 4396 | // If the new child is aligned differently than the old one, explicitly align the type. | |
| 4397 | const want = @alignOf(ptr.child); | |
| 4398 | break :a if (@alignOf(child) == want) null else want; | |
| 4399 | }, | |
| 4392 | 4400 | .@"addrspace" = ptr.address_space, |
| 4393 | 4401 | }, child, null); |
| 4394 | 4402 | } |
lib/std/mem/Allocator.zig+52-47| ... | ... | @@ -179,7 +179,11 @@ pub fn destroy(self: Allocator, ptr: anytype) void { |
| 179 | 179 | const T = info.child; |
| 180 | 180 | if (@sizeOf(T) == 0) return; |
| 181 | 181 | const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr))); |
| 182 | self.rawFree(non_const_ptr[0..@sizeOf(T)], .fromByteUnits(info.alignment), @returnAddress()); | |
| 182 | self.rawFree( | |
| 183 | non_const_ptr[0..@sizeOf(T)], | |
| 184 | .fromByteUnits(info.alignment orelse @alignOf(T)), | |
| 185 | @returnAddress(), | |
| 186 | ); | |
| 183 | 187 | } |
| 184 | 188 | |
| 185 | 189 | /// Allocates an array of `n` items of type `T` and sets all the |
| ... | ... | @@ -266,7 +270,7 @@ pub inline fn allocAdvancedWithRetAddr( |
| 266 | 270 | n: usize, |
| 267 | 271 | return_address: usize, |
| 268 | 272 | ) Error![]align(if (alignment) |a| a.toByteUnits() else @alignOf(T)) T { |
| 269 | const a = comptime (alignment orelse Alignment.of(T)); | |
| 273 | const a: Alignment = alignment orelse comptime .of(T); | |
| 270 | 274 | const ptr: [*]align(a.toByteUnits()) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address)); |
| 271 | 275 | return ptr[0..n]; |
| 272 | 276 | } |
| ... | ... | @@ -278,7 +282,7 @@ fn allocWithSizeAndAlignment( |
| 278 | 282 | n: usize, |
| 279 | 283 | return_address: usize, |
| 280 | 284 | ) Error![*]align(alignment.toByteUnits()) u8 { |
| 281 | const byte_count = math.mul(usize, size, n) catch return Error.OutOfMemory; | |
| 285 | const byte_count = math.mul(usize, size, n) catch return error.OutOfMemory; | |
| 282 | 286 | return self.allocBytesWithAlignment(alignment, byte_count, return_address); |
| 283 | 287 | } |
| 284 | 288 | |
| ... | ... | @@ -293,7 +297,7 @@ fn allocBytesWithAlignment( |
| 293 | 297 | return @as([*]align(alignment.toByteUnits()) u8, @ptrFromInt(ptr)); |
| 294 | 298 | } |
| 295 | 299 | |
| 296 | const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return Error.OutOfMemory; | |
| 300 | const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return error.OutOfMemory; | |
| 297 | 301 | @memset(byte_ptr[0..byte_count], undefined); |
| 298 | 302 | return @alignCast(byte_ptr); |
| 299 | 303 | } |
| ... | ... | @@ -308,9 +312,9 @@ fn allocBytesWithAlignment( |
| 308 | 312 | /// |
| 309 | 313 | /// `new_len` may be zero, in which case the allocation is freed. |
| 310 | 314 | pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 311 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | |
| 312 | const T = Slice.child; | |
| 313 | const alignment = Slice.alignment; | |
| 315 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; | |
| 316 | comptime assert(slice_info.size == .slice); | |
| 317 | const T = slice_info.child; | |
| 314 | 318 | if (new_len == 0) { |
| 315 | 319 | self.free(allocation); |
| 316 | 320 | return true; |
| ... | ... | @@ -323,7 +327,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 323 | 327 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |
| 324 | 328 | //const new_len_bytes = new_len *| @sizeOf(T); |
| 325 | 329 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false; |
| 326 | return self.rawResize(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()); | |
| 330 | return self.rawResize( | |
| 331 | old_memory, | |
| 332 | .fromByteUnits(slice_info.alignment orelse @alignOf(T)), | |
| 333 | new_len_bytes, | |
| 334 | @returnAddress(), | |
| 335 | ); | |
| 327 | 336 | } |
| 328 | 337 | |
| 329 | 338 | /// Request to modify the size of an allocation, allowing relocation. |
| ... | ... | @@ -342,14 +351,11 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 342 | 351 | /// `new_len` may be zero, in which case the allocation is freed. |
| 343 | 352 | /// |
| 344 | 353 | /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. |
| 345 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { | |
| 346 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | |
| 347 | break :t ?[]align(Slice.alignment) Slice.child; | |
| 348 | } { | |
| 349 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | |
| 350 | const T = Slice.child; | |
| 351 | ||
| 352 | const alignment = Slice.alignment; | |
| 354 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) { | |
| 355 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; | |
| 356 | comptime assert(slice_info.size == .slice); | |
| 357 | const T = slice_info.child; | |
| 358 | ||
| 353 | 359 | if (new_len == 0) { |
| 354 | 360 | self.free(allocation); |
| 355 | 361 | return allocation[0..0]; |
| ... | ... | @@ -367,9 +373,13 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 367 | 373 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |
| 368 | 374 | //const new_len_bytes = new_len *| @sizeOf(T); |
| 369 | 375 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null; |
| 370 | const new_ptr = self.rawRemap(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()) orelse return null; | |
| 371 | const new_memory: []align(alignment) u8 = @alignCast(new_ptr[0..new_len_bytes]); | |
| 372 | return mem.bytesAsSlice(T, new_memory); | |
| 376 | const new_ptr = self.rawRemap( | |
| 377 | old_memory, | |
| 378 | .fromByteUnits(slice_info.alignment orelse @alignOf(T)), | |
| 379 | new_len_bytes, | |
| 380 | @returnAddress(), | |
| 381 | ) orelse return null; | |
| 382 | return @ptrCast(@alignCast(new_ptr[0..new_len_bytes])); | |
| 373 | 383 | } |
| 374 | 384 | |
| 375 | 385 | /// This function requests a new size for an existing allocation, which |
| ... | ... | @@ -386,10 +396,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 386 | 396 | /// do the realloc more efficiently than the caller |
| 387 | 397 | /// * `resize` which returns `false` when the `Allocator` implementation cannot |
| 388 | 398 | /// change the size without relocating the allocation. |
| 389 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: { | |
| 390 | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; | |
| 391 | break :t Error![]align(Slice.alignment) Slice.child; | |
| 392 | } { | |
| 399 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) { | |
| 393 | 400 | return self.reallocAdvanced(old_mem, new_n, @returnAddress()); |
| 394 | 401 | } |
| 395 | 402 | |
| ... | ... | @@ -398,51 +405,49 @@ pub fn reallocAdvanced( |
| 398 | 405 | old_mem: anytype, |
| 399 | 406 | new_n: usize, |
| 400 | 407 | return_address: usize, |
| 401 | ) t: { | |
| 402 | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; | |
| 403 | break :t Error![]align(Slice.alignment) Slice.child; | |
| 404 | } { | |
| 405 | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; | |
| 406 | const T = Slice.child; | |
| 408 | ) Error!@TypeOf(old_mem) { | |
| 409 | const slice_info = @typeInfo(@TypeOf(old_mem)).pointer; | |
| 410 | comptime assert(slice_info.size == .slice); | |
| 411 | const T = slice_info.child; | |
| 407 | 412 | if (old_mem.len == 0) { |
| 408 | return self.allocAdvancedWithRetAddr(T, .fromByteUnits(Slice.alignment), new_n, return_address); | |
| 413 | return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.alignment), new_n, return_address); | |
| 409 | 414 | } |
| 410 | 415 | if (new_n == 0) { |
| 411 | 416 | self.free(old_mem); |
| 412 | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), Slice.alignment); | |
| 413 | return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0]; | |
| 417 | const alignment = slice_info.alignment orelse @alignOf(T); | |
| 418 | const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment); | |
| 419 | const ptr: *align(alignment) [0]T = @ptrFromInt(addr); | |
| 420 | return ptr; | |
| 414 | 421 | } |
| 415 | 422 | |
| 416 | 423 | const old_byte_slice = mem.sliceAsBytes(old_mem); |
| 417 | const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; | |
| 424 | const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory; | |
| 418 | 425 | // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure |
| 419 | if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| { | |
| 420 | const new_bytes: []align(Slice.alignment) u8 = @alignCast(p[0..byte_count]); | |
| 421 | return mem.bytesAsSlice(T, new_bytes); | |
| 426 | if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), byte_count, return_address)) |p| { | |
| 427 | return @ptrCast(@alignCast(p[0..byte_count])); | |
| 422 | 428 | } |
| 423 | 429 | |
| 424 | const new_mem = self.rawAlloc(byte_count, .fromByteUnits(Slice.alignment), return_address) orelse | |
| 430 | const new_mem = self.rawAlloc(byte_count, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address) orelse | |
| 425 | 431 | return error.OutOfMemory; |
| 426 | 432 | const copy_len = @min(byte_count, old_byte_slice.len); |
| 427 | 433 | @memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]); |
| 428 | 434 | @memset(old_byte_slice, undefined); |
| 429 | self.rawFree(old_byte_slice, .fromByteUnits(Slice.alignment), return_address); | |
| 435 | self.rawFree(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address); | |
| 430 | 436 | |
| 431 | const new_bytes: []align(Slice.alignment) u8 = @alignCast(new_mem[0..byte_count]); | |
| 432 | return mem.bytesAsSlice(T, new_bytes); | |
| 437 | return @ptrCast(@alignCast(new_mem[0..byte_count])); | |
| 433 | 438 | } |
| 434 | 439 | |
| 435 | 440 | /// Free an array allocated with `alloc`. |
| 436 | 441 | /// If memory has length 0, free is a no-op. |
| 437 | 442 | /// To free a single item, see `destroy`. |
| 438 | 443 | pub fn free(self: Allocator, memory: anytype) void { |
| 439 | const Slice = @typeInfo(@TypeOf(memory)).pointer; | |
| 440 | const bytes = mem.sliceAsBytes(memory); | |
| 441 | const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0; | |
| 442 | if (bytes_len == 0) return; | |
| 443 | const non_const_ptr = @constCast(bytes.ptr); | |
| 444 | @memset(non_const_ptr[0..bytes_len], undefined); | |
| 445 | self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress()); | |
| 444 | const slice_info = @typeInfo(@TypeOf(memory)).pointer; | |
| 445 | comptime assert(slice_info.size == .slice); | |
| 446 | const mem_with_sent = memory[0 .. memory.len + @intFromBool(slice_info.sentinel() != null)]; | |
| 447 | const bytes: []u8 = @ptrCast(@constCast(mem_with_sent)); | |
| 448 | if (bytes.len == 0) return; | |
| 449 | @memset(bytes, undefined); | |
| 450 | self.rawFree(bytes, .fromByteUnits(slice_info.alignment orelse @alignOf(slice_info.child)), @returnAddress()); | |
| 446 | 451 | } |
| 447 | 452 | |
| 448 | 453 | /// Copies `m` to newly allocated memory. Caller owns the memory. |
lib/std/meta.zig+2-2| ... | ... | @@ -63,7 +63,7 @@ pub fn alignment(comptime T: type) comptime_int { |
| 63 | 63 | .pointer, .@"fn" => alignment(info.child), |
| 64 | 64 | else => @alignOf(T), |
| 65 | 65 | }, |
| 66 | .pointer => |info| info.alignment, | |
| 66 | .pointer => |info| info.alignment orelse @alignOf(info.child), | |
| 67 | 67 | else => @alignOf(T), |
| 68 | 68 | }; |
| 69 | 69 | } |
| ... | ... | @@ -315,7 +315,7 @@ test declarationInfo { |
| 315 | 315 | try testing.expect(comptime mem.eql(u8, info.name, "a")); |
| 316 | 316 | } |
| 317 | 317 | } |
| 318 | pub fn fields(comptime T: type) switch (@typeInfo(T)) { | |
| 318 | pub inline fn fields(comptime T: type) switch (@typeInfo(T)) { | |
| 319 | 319 | .@"struct" => []const Type.StructField, |
| 320 | 320 | .@"union" => []const Type.UnionField, |
| 321 | 321 | .@"enum" => []const Type.EnumField, |
lib/std/multi_array_list.zig+15-9| ... | ... | @@ -19,7 +19,11 @@ const testing = std.testing; |
| 19 | 19 | /// For unions you can call `.items(.tags)` or `.items(.data)`. |
| 20 | 20 | pub fn MultiArrayList(comptime T: type) type { |
| 21 | 21 | return struct { |
| 22 | bytes: [*]align(@alignOf(T)) u8 = undefined, | |
| 22 | /// This pointer is always aligned to the boundary `sizes.big_align`; this is not specified | |
| 23 | /// in the type to avoid `MultiArrayList(T)` depending on the alignment of `T` because this | |
| 24 | /// can lead to dependency loops. See `allocatedBytes` which `@alignCast`s this pointer to | |
| 25 | /// the correct type. | |
| 26 | bytes: [*]u8 = undefined, | |
| 23 | 27 | len: usize = 0, |
| 24 | 28 | capacity: usize = 0, |
| 25 | 29 | |
| ... | ... | @@ -133,10 +137,8 @@ pub fn MultiArrayList(comptime T: type) type { |
| 133 | 137 | if (self.ptrs.len == 0 or self.capacity == 0) { |
| 134 | 138 | return .{}; |
| 135 | 139 | } |
| 136 | const unaligned_ptr = self.ptrs[sizes.fields[0]]; | |
| 137 | const aligned_ptr: [*]align(@alignOf(Elem)) u8 = @alignCast(unaligned_ptr); | |
| 138 | 140 | return .{ |
| 139 | .bytes = aligned_ptr, | |
| 141 | .bytes = self.ptrs[sizes.fields[0]], | |
| 140 | 142 | .len = self.len, |
| 141 | 143 | .capacity = self.capacity, |
| 142 | 144 | }; |
| ... | ... | @@ -179,6 +181,7 @@ pub fn MultiArrayList(comptime T: type) type { |
| 179 | 181 | const fields = meta.fields(Elem); |
| 180 | 182 | /// `sizes.bytes` is an array of @sizeOf each T field. Sorted by alignment, descending. |
| 181 | 183 | /// `sizes.fields` is an array mapping from `sizes.bytes` array index to field index. |
| 184 | /// `sizes.big_align` is the overall alignment of the allocation, which equals the maximum field alignment. | |
| 182 | 185 | const sizes = blk: { |
| 183 | 186 | const Data = struct { |
| 184 | 187 | size: usize, |
| ... | ... | @@ -186,12 +189,14 @@ pub fn MultiArrayList(comptime T: type) type { |
| 186 | 189 | alignment: usize, |
| 187 | 190 | }; |
| 188 | 191 | var data: [fields.len]Data = undefined; |
| 192 | var big_align: usize = 1; | |
| 189 | 193 | for (fields, 0..) |field_info, i| { |
| 190 | 194 | data[i] = .{ |
| 191 | 195 | .size = @sizeOf(field_info.type), |
| 192 | 196 | .size_index = i, |
| 193 | .alignment = if (@sizeOf(field_info.type) == 0) 1 else field_info.alignment, | |
| 197 | .alignment = field_info.alignment orelse @alignOf(field_info.type), | |
| 194 | 198 | }; |
| 199 | big_align = @max(big_align, data[i].alignment); | |
| 195 | 200 | } |
| 196 | 201 | const Sort = struct { |
| 197 | 202 | fn lessThan(context: void, lhs: Data, rhs: Data) bool { |
| ... | ... | @@ -210,6 +215,7 @@ pub fn MultiArrayList(comptime T: type) type { |
| 210 | 215 | break :blk .{ |
| 211 | 216 | .bytes = sizes_bytes, |
| 212 | 217 | .fields = field_indexes, |
| 218 | .big_align = mem.Alignment.fromByteUnits(big_align), | |
| 213 | 219 | }; |
| 214 | 220 | }; |
| 215 | 221 | |
| ... | ... | @@ -452,7 +458,7 @@ pub fn MultiArrayList(comptime T: type) type { |
| 452 | 458 | assert(new_len <= self.capacity); |
| 453 | 459 | assert(new_len <= self.len); |
| 454 | 460 | |
| 455 | const other_bytes = gpa.alignedAlloc(u8, .of(Elem), capacityInBytes(new_len)) catch { | |
| 461 | const other_bytes = gpa.alignedAlloc(u8, sizes.big_align, capacityInBytes(new_len)) catch { | |
| 456 | 462 | const self_slice = self.slice(); |
| 457 | 463 | inline for (fields, 0..) |field_info, i| { |
| 458 | 464 | if (@sizeOf(field_info.type) != 0) { |
| ... | ... | @@ -533,7 +539,7 @@ pub fn MultiArrayList(comptime T: type) type { |
| 533 | 539 | /// `new_capacity` must be greater or equal to `len`. |
| 534 | 540 | pub fn setCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { |
| 535 | 541 | assert(new_capacity >= self.len); |
| 536 | const new_bytes = try gpa.alignedAlloc(u8, .of(Elem), capacityInBytes(new_capacity)); | |
| 542 | const new_bytes = try gpa.alignedAlloc(u8, sizes.big_align, capacityInBytes(new_capacity)); | |
| 537 | 543 | if (self.len == 0) { |
| 538 | 544 | gpa.free(self.allocatedBytes()); |
| 539 | 545 | self.bytes = new_bytes.ptr; |
| ... | ... | @@ -650,8 +656,8 @@ pub fn MultiArrayList(comptime T: type) type { |
| 650 | 656 | return elem_bytes * capacity; |
| 651 | 657 | } |
| 652 | 658 | |
| 653 | fn allocatedBytes(self: Self) []align(@alignOf(Elem)) u8 { | |
| 654 | return self.bytes[0..capacityInBytes(self.capacity)]; | |
| 659 | fn allocatedBytes(self: Self) []align(sizes.big_align.toByteUnits()) u8 { | |
| 660 | return @alignCast(self.bytes[0..capacityInBytes(self.capacity)]); | |
| 655 | 661 | } |
| 656 | 662 | |
| 657 | 663 | fn FieldType(comptime field: Field) type { |
lib/std/os/linux.zig+1-1| ... | ... | @@ -7113,7 +7113,7 @@ pub const io_uring_buf_reg = extern struct { |
| 7113 | 7113 | flags: Flags, |
| 7114 | 7114 | resv: [3]u64, |
| 7115 | 7115 | |
| 7116 | pub const Flags = packed struct { | |
| 7116 | pub const Flags = packed struct(u16) { | |
| 7117 | 7117 | _0: u1 = 0, |
| 7118 | 7118 | /// Incremental buffer consumption. |
| 7119 | 7119 | inc: bool, |
lib/std/os/windows.zig+5-5| ... | ... | @@ -4160,7 +4160,7 @@ pub const RUNTIME_FUNCTION = switch (native_arch) { |
| 4160 | 4160 | BeginAddress: DWORD, |
| 4161 | 4161 | DUMMYUNIONNAME: extern union { |
| 4162 | 4162 | UnwindData: DWORD, |
| 4163 | DUMMYSTRUCTNAME: packed struct { | |
| 4163 | DUMMYSTRUCTNAME: packed struct(u32) { | |
| 4164 | 4164 | Flag: u2, |
| 4165 | 4165 | FunctionLength: u11, |
| 4166 | 4166 | Ret: u2, |
| ... | ... | @@ -4177,7 +4177,7 @@ pub const RUNTIME_FUNCTION = switch (native_arch) { |
| 4177 | 4177 | BeginAddress: DWORD, |
| 4178 | 4178 | DUMMYUNIONNAME: extern union { |
| 4179 | 4179 | UnwindData: DWORD, |
| 4180 | DUMMYSTRUCTNAME: packed struct { | |
| 4180 | DUMMYSTRUCTNAME: packed struct(u32) { | |
| 4181 | 4181 | Flag: u2, |
| 4182 | 4182 | FunctionLength: u11, |
| 4183 | 4183 | RegF: u3, |
| ... | ... | @@ -5013,7 +5013,7 @@ pub const KUSER_SHARED_DATA = extern struct { |
| 5013 | 5013 | KdDebuggerEnabled: BOOLEAN, |
| 5014 | 5014 | DummyUnion1: extern union { |
| 5015 | 5015 | MitigationPolicies: UCHAR, |
| 5016 | Alt: packed struct { | |
| 5016 | Alt: packed struct(u8) { | |
| 5017 | 5017 | NXSupportPolicy: u2, |
| 5018 | 5018 | SEHValidationPolicy: u2, |
| 5019 | 5019 | CurDirDevicesSkippedForDlls: u2, |
| ... | ... | @@ -5029,7 +5029,7 @@ pub const KUSER_SHARED_DATA = extern struct { |
| 5029 | 5029 | SafeBootMode: BOOLEAN, |
| 5030 | 5030 | DummyUnion2: extern union { |
| 5031 | 5031 | VirtualizationFlags: UCHAR, |
| 5032 | Alt: packed struct { | |
| 5032 | Alt: packed struct(u8) { | |
| 5033 | 5033 | ArchStartedInEl2: u1, |
| 5034 | 5034 | QcSlIsSupported: u1, |
| 5035 | 5035 | SpareBits: u6, |
| ... | ... | @@ -5038,7 +5038,7 @@ pub const KUSER_SHARED_DATA = extern struct { |
| 5038 | 5038 | Reserved12: [2]UCHAR, |
| 5039 | 5039 | DummyUnion3: extern union { |
| 5040 | 5040 | SharedDataFlags: ULONG, |
| 5041 | Alt: packed struct { | |
| 5041 | Alt: packed struct(u32) { | |
| 5042 | 5042 | DbgErrorPortPresent: u1, |
| 5043 | 5043 | DbgElevationEnabled: u1, |
| 5044 | 5044 | DbgVirtEnabled: u1, |
lib/std/pdb.zig+2-2| ... | ... | @@ -332,7 +332,7 @@ pub const ProcSym = extern struct { |
| 332 | 332 | name: [1]u8, // null-terminated |
| 333 | 333 | }; |
| 334 | 334 | |
| 335 | pub const ProcSymFlags = packed struct { | |
| 335 | pub const ProcSymFlags = packed struct(u8) { | |
| 336 | 336 | has_fp: bool, |
| 337 | 337 | has_iret: bool, |
| 338 | 338 | has_fret: bool, |
| ... | ... | @@ -373,7 +373,7 @@ pub const LineFragmentHeader = extern struct { |
| 373 | 373 | code_size: u32, |
| 374 | 374 | }; |
| 375 | 375 | |
| 376 | pub const LineFlags = packed struct { | |
| 376 | pub const LineFlags = packed struct(u16) { | |
| 377 | 377 | /// CV_LINES_HAVE_COLUMNS |
| 378 | 378 | have_columns: bool, |
| 379 | 379 | unused: u15, |
lib/std/testing.zig+2-3| ... | ... | @@ -950,9 +950,8 @@ test "expectEqualDeep primitive type" { |
| 950 | 950 | } |
| 951 | 951 | |
| 952 | 952 | test "expectEqualDeep pointer" { |
| 953 | const a = 1; | |
| 954 | const b = 1; | |
| 955 | try expectEqualDeep(&a, &b); | |
| 953 | try comptime expectEqualDeep(&1, &1); | |
| 954 | try expectEqualDeep(&@as(u32, 1), &@as(u32, 1)); | |
| 956 | 955 | } |
| 957 | 956 | |
| 958 | 957 | test "expectEqualDeep composite type" { |
lib/std/zig.zig+11-2| ... | ... | @@ -837,6 +837,10 @@ pub const SimpleComptimeReason = enum(u32) { |
| 837 | 837 | tuple_field_types, |
| 838 | 838 | enum_field_names, |
| 839 | 839 | enum_field_values, |
| 840 | union_enum_tag_type, | |
| 841 | enum_int_tag_type, | |
| 842 | packed_struct_backing_int_type, | |
| 843 | packed_union_backing_int_type, | |
| 840 | 844 | |
| 841 | 845 | // Evaluating at comptime because decl/field name must be comptime-known. |
| 842 | 846 | decl_name, |
| ... | ... | @@ -864,7 +868,7 @@ pub const SimpleComptimeReason = enum(u32) { |
| 864 | 868 | casted_to_comptime_enum, |
| 865 | 869 | casted_to_comptime_int, |
| 866 | 870 | casted_to_comptime_float, |
| 867 | panic_handler, | |
| 871 | std_builtin_decl, | |
| 868 | 872 | |
| 869 | 873 | pub fn message(r: SimpleComptimeReason) []const u8 { |
| 870 | 874 | return switch (r) { |
| ... | ... | @@ -925,6 +929,11 @@ pub const SimpleComptimeReason = enum(u32) { |
| 925 | 929 | .enum_field_names => "enum field names must be comptime-known", |
| 926 | 930 | .enum_field_values => "enum field values must be comptime-known", |
| 927 | 931 | |
| 932 | .union_enum_tag_type => "enum tag type of union must be comptime-known", | |
| 933 | .enum_int_tag_type => "integer tag type of enum must be comptime-known", | |
| 934 | .packed_struct_backing_int_type => "packed struct backing integer type must be comptime-known", | |
| 935 | .packed_union_backing_int_type => "packed struct backing integer type must be comptime-known", | |
| 936 | ||
| 928 | 937 | .decl_name => "declaration name must be comptime-known", |
| 929 | 938 | .field_name => "field name must be comptime-known", |
| 930 | 939 | .tuple_field_index => "tuple field index must be comptime-known", |
| ... | ... | @@ -948,7 +957,7 @@ pub const SimpleComptimeReason = enum(u32) { |
| 948 | 957 | .casted_to_comptime_enum => "value casted to enum with 'comptime_int' tag type must be comptime-known", |
| 949 | 958 | .casted_to_comptime_int => "value casted to 'comptime_int' must be comptime-known", |
| 950 | 959 | .casted_to_comptime_float => "value casted to 'comptime_float' must be comptime-known", |
| 951 | .panic_handler => "panic handler must be comptime-known", | |
| 960 | .std_builtin_decl => "'std.builtin' declaration values must be comptime-known", | |
| 952 | 961 | // zig fmt: on |
| 953 | 962 | }; |
| 954 | 963 | } |
lib/std/zig/Ast.zig+4-4| ... | ... | @@ -175,10 +175,10 @@ pub fn parseTokens( |
| 175 | 175 | .source = source, |
| 176 | 176 | .gpa = gpa, |
| 177 | 177 | .tokens = tokens, |
| 178 | .errors = .{}, | |
| 179 | .nodes = .{}, | |
| 180 | .extra_data = .{}, | |
| 181 | .scratch = .{}, | |
| 178 | .errors = .empty, | |
| 179 | .nodes = .empty, | |
| 180 | .extra_data = .empty, | |
| 181 | .scratch = .empty, | |
| 182 | 182 | .tok_i = 0, |
| 183 | 183 | }; |
| 184 | 184 | defer parser.errors.deinit(gpa); |
lib/std/zig/AstGen.zig+530-1102| ... | ... | @@ -1780,7 +1780,7 @@ fn structInitExpr( |
| 1780 | 1780 | try gop.value_ptr.append(sfba_allocator, name_token); |
| 1781 | 1781 | any_duplicate = true; |
| 1782 | 1782 | } else { |
| 1783 | gop.value_ptr.* = .{}; | |
| 1783 | gop.value_ptr.* = .empty; | |
| 1784 | 1784 | try gop.value_ptr.append(sfba_allocator, name_token); |
| 1785 | 1785 | } |
| 1786 | 1786 | } |
| ... | ... | @@ -3975,81 +3975,67 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. |
| 3975 | 3975 | return rvalue(gz, ri, result, node); |
| 3976 | 3976 | } |
| 3977 | 3977 | |
| 3978 | const WipMembers = struct { | |
| 3979 | payload: *ArrayList(u32), | |
| 3980 | payload_top: usize, | |
| 3981 | field_bits_start: u32, | |
| 3982 | fields_start: u32, | |
| 3983 | fields_end: u32, | |
| 3984 | decl_index: u32 = 0, | |
| 3985 | field_index: u32 = 0, | |
| 3986 | ||
| 3987 | const Self = @This(); | |
| 3988 | ||
| 3989 | fn init(gpa: Allocator, payload: *ArrayList(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { | |
| 3990 | const payload_top: u32 = @intCast(payload.items.len); | |
| 3991 | const field_bits_start = payload_top + decl_count; | |
| 3992 | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { | |
| 3993 | const fields_per_u32 = 32 / bits_per_field; | |
| 3994 | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; | |
| 3995 | } else 0; | |
| 3996 | const payload_end = fields_start + field_count * max_field_size; | |
| 3997 | try payload.resize(gpa, payload_end); | |
| 3978 | const Scratch = struct { | |
| 3979 | astgen: *AstGen, | |
| 3980 | scratch_top: u32, | |
| 3981 | fn init(astgen: *AstGen) Scratch { | |
| 3998 | 3982 | return .{ |
| 3999 | .payload = payload, | |
| 4000 | .payload_top = payload_top, | |
| 4001 | .field_bits_start = field_bits_start, | |
| 4002 | .fields_start = fields_start, | |
| 4003 | .fields_end = fields_start, | |
| 3983 | .astgen = astgen, | |
| 3984 | .scratch_top = @intCast(astgen.scratch.items.len), | |
| 4004 | 3985 | }; |
| 4005 | 3986 | } |
| 4006 | ||
| 4007 | fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void { | |
| 4008 | self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst); | |
| 4009 | self.decl_index += 1; | |
| 3987 | fn reset(s: *Scratch) void { | |
| 3988 | s.astgen.scratch.shrinkRetainingCapacity(s.scratch_top); | |
| 3989 | s.* = undefined; | |
| 4010 | 3990 | } |
| 4011 | ||
| 4012 | fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void { | |
| 4013 | const fields_per_u32 = 32 / bits_per_field; | |
| 4014 | const index = self.field_bits_start + self.field_index / fields_per_u32; | |
| 4015 | assert(index < self.fields_start); | |
| 4016 | var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index]; | |
| 4017 | bit_bag >>= bits_per_field; | |
| 4018 | comptime var i = 0; | |
| 4019 | inline while (i < bits_per_field) : (i += 1) { | |
| 4020 | bit_bag |= @as(u32, @intFromBool(bits[i])) << (32 - bits_per_field + i); | |
| 4021 | } | |
| 4022 | self.payload.items[index] = bit_bag; | |
| 4023 | self.field_index += 1; | |
| 3991 | fn addSlice(s: *Scratch, len: u32) Allocator.Error!Slice { | |
| 3992 | const start: u32 = @intCast(s.astgen.scratch.items.len); | |
| 3993 | try s.astgen.scratch.resize(s.astgen.gpa, start + len); | |
| 3994 | return .{ .start = start, .len = len }; | |
| 4024 | 3995 | } |
| 4025 | ||
| 4026 | fn appendToField(self: *Self, data: u32) void { | |
| 4027 | assert(self.fields_end < self.payload.items.len); | |
| 4028 | self.payload.items[self.fields_end] = data; | |
| 4029 | self.fields_end += 1; | |
| 3996 | fn addOptionalSlice(s: *Scratch, present: bool, len: u32) Allocator.Error!?Slice { | |
| 3997 | if (!present) return null; | |
| 3998 | return try addSlice(s, len); | |
| 4030 | 3999 | } |
| 4031 | ||
| 4032 | fn finishBits(self: *Self, comptime bits_per_field: u32) void { | |
| 4033 | if (bits_per_field > 0) { | |
| 4034 | const fields_per_u32 = 32 / bits_per_field; | |
| 4035 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); | |
| 4036 | if (self.field_index > 0 and empty_field_slots < fields_per_u32) { | |
| 4037 | const index = self.field_bits_start + self.field_index / fields_per_u32; | |
| 4038 | self.payload.items[index] >>= @intCast(empty_field_slots * bits_per_field); | |
| 4039 | } | |
| 4040 | } | |
| 4000 | fn appendBodyWithFixups(s: *Scratch, body: []const Zir.Inst.Index) Allocator.Error!u32 { | |
| 4001 | const len = countBodyLenAfterFixups(s.astgen, body); | |
| 4002 | try s.astgen.scratch.ensureUnusedCapacity(s.astgen.gpa, len); | |
| 4003 | appendBodyWithFixupsArrayList(s.astgen, &s.astgen.scratch, body); | |
| 4004 | return len; | |
| 4041 | 4005 | } |
| 4042 | ||
| 4043 | fn declsSlice(self: *Self) []u32 { | |
| 4044 | return self.payload.items[self.payload_top..][0..self.decl_index]; | |
| 4006 | /// Returns the slice containing all data added to this `Scratch`. | |
| 4007 | fn all(s: *Scratch) Slice { | |
| 4008 | const len = s.astgen.scratch.items.len - s.scratch_top; | |
| 4009 | return .{ .start = s.scratch_top, .len = @intCast(len) }; | |
| 4045 | 4010 | } |
| 4011 | const Slice = struct { | |
| 4012 | start: u32, | |
| 4013 | len: u32, | |
| 4014 | fn get(s: Slice, astgen: *AstGen) []u32 { | |
| 4015 | return astgen.scratch.items[s.start..][0..s.len]; | |
| 4016 | } | |
| 4017 | }; | |
| 4018 | }; | |
| 4046 | 4019 | |
| 4047 | fn fieldsSlice(self: *Self) []u32 { | |
| 4048 | return self.payload.items[self.field_bits_start..self.fields_end]; | |
| 4049 | } | |
| 4020 | const WipDecls = struct { | |
| 4021 | astgen: *AstGen, | |
| 4022 | slice: Scratch.Slice, | |
| 4023 | index: u32, | |
| 4050 | 4024 | |
| 4051 | fn deinit(self: *Self) void { | |
| 4052 | self.payload.items.len = self.payload_top; | |
| 4025 | fn init(scratch: *Scratch, decls_len: u32) Allocator.Error!WipDecls { | |
| 4026 | return .{ | |
| 4027 | .astgen = scratch.astgen, | |
| 4028 | .slice = try scratch.addSlice(decls_len), | |
| 4029 | .index = 0, | |
| 4030 | }; | |
| 4031 | } | |
| 4032 | fn finish(wip: *WipDecls) void { | |
| 4033 | assert(wip.index == wip.slice.len); | |
| 4034 | wip.* = undefined; | |
| 4035 | } | |
| 4036 | fn nextDecl(wip: *WipDecls, decl_inst: Zir.Inst.Index) void { | |
| 4037 | wip.slice.get(wip.astgen)[wip.index] = @intFromEnum(decl_inst); | |
| 4038 | wip.index += 1; | |
| 4053 | 4039 | } |
| 4054 | 4040 | }; |
| 4055 | 4041 | |
| ... | ... | @@ -4057,7 +4043,7 @@ fn fnDecl( |
| 4057 | 4043 | astgen: *AstGen, |
| 4058 | 4044 | gz: *GenZir, |
| 4059 | 4045 | scope: *Scope, |
| 4060 | wip_members: *WipMembers, | |
| 4046 | wip_decls: *WipDecls, | |
| 4061 | 4047 | decl_node: Ast.Node.Index, |
| 4062 | 4048 | body_node: Ast.Node.OptionalIndex, |
| 4063 | 4049 | fn_proto: Ast.full.FnProto, |
| ... | ... | @@ -4133,7 +4119,7 @@ fn fnDecl( |
| 4133 | 4119 | assert(!is_extern); // validated by parser (TODO why???) |
| 4134 | 4120 | } |
| 4135 | 4121 | |
| 4136 | wip_members.nextDecl(decl_inst); | |
| 4122 | wip_decls.nextDecl(decl_inst); | |
| 4137 | 4123 | |
| 4138 | 4124 | var type_gz: GenZir = .{ |
| 4139 | 4125 | .is_comptime = true, |
| ... | ... | @@ -4488,7 +4474,7 @@ fn globalVarDecl( |
| 4488 | 4474 | astgen: *AstGen, |
| 4489 | 4475 | gz: *GenZir, |
| 4490 | 4476 | scope: *Scope, |
| 4491 | wip_members: *WipMembers, | |
| 4477 | wip_decls: *WipDecls, | |
| 4492 | 4478 | node: Ast.Node.Index, |
| 4493 | 4479 | var_decl: Ast.full.VarDecl, |
| 4494 | 4480 | ) InnerError!void { |
| ... | ... | @@ -4533,7 +4519,7 @@ fn globalVarDecl( |
| 4533 | 4519 | const decl_column = astgen.source_column; |
| 4534 | 4520 | |
| 4535 | 4521 | const decl_inst = try gz.makeDeclaration(node); |
| 4536 | wip_members.nextDecl(decl_inst); | |
| 4522 | wip_decls.nextDecl(decl_inst); | |
| 4537 | 4523 | |
| 4538 | 4524 | if (var_decl.ast.init_node.unwrap()) |init_node| { |
| 4539 | 4525 | if (is_extern) { |
| ... | ... | @@ -4635,7 +4621,7 @@ fn comptimeDecl( |
| 4635 | 4621 | astgen: *AstGen, |
| 4636 | 4622 | gz: *GenZir, |
| 4637 | 4623 | scope: *Scope, |
| 4638 | wip_members: *WipMembers, | |
| 4624 | wip_decls: *WipDecls, | |
| 4639 | 4625 | node: Ast.Node.Index, |
| 4640 | 4626 | ) InnerError!void { |
| 4641 | 4627 | const tree = astgen.tree; |
| ... | ... | @@ -4650,7 +4636,7 @@ fn comptimeDecl( |
| 4650 | 4636 | // Up top so the ZIR instruction index marks the start range of this |
| 4651 | 4637 | // top-level declaration. |
| 4652 | 4638 | const decl_inst = try gz.makeDeclaration(node); |
| 4653 | wip_members.nextDecl(decl_inst); | |
| 4639 | wip_decls.nextDecl(decl_inst); | |
| 4654 | 4640 | astgen.advanceSourceCursorToNode(node); |
| 4655 | 4641 | |
| 4656 | 4642 | // This is just needed for the `setDeclaration` call. |
| ... | ... | @@ -4698,7 +4684,7 @@ fn testDecl( |
| 4698 | 4684 | astgen: *AstGen, |
| 4699 | 4685 | gz: *GenZir, |
| 4700 | 4686 | scope: *Scope, |
| 4701 | wip_members: *WipMembers, | |
| 4687 | wip_decls: *WipDecls, | |
| 4702 | 4688 | node: Ast.Node.Index, |
| 4703 | 4689 | ) InnerError!void { |
| 4704 | 4690 | const tree = astgen.tree; |
| ... | ... | @@ -4714,7 +4700,7 @@ fn testDecl( |
| 4714 | 4700 | // top-level declaration. |
| 4715 | 4701 | const decl_inst = try gz.makeDeclaration(node); |
| 4716 | 4702 | |
| 4717 | wip_members.nextDecl(decl_inst); | |
| 4703 | wip_decls.nextDecl(decl_inst); | |
| 4718 | 4704 | astgen.advanceSourceCursorToNode(node); |
| 4719 | 4705 | |
| 4720 | 4706 | // This is just needed for the `setDeclaration` call. |
| ... | ... | @@ -4914,7 +4900,7 @@ fn structDeclInner( |
| 4914 | 4900 | node: Ast.Node.Index, |
| 4915 | 4901 | container_decl: Ast.full.ContainerDecl, |
| 4916 | 4902 | layout: std.builtin.Type.ContainerLayout, |
| 4917 | backing_int_node: Ast.Node.OptionalIndex, | |
| 4903 | maybe_backing_int_node: Ast.Node.OptionalIndex, | |
| 4918 | 4904 | name_strat: Zir.Inst.NameStrategy, |
| 4919 | 4905 | ) InnerError!Zir.Inst.Ref { |
| 4920 | 4906 | const astgen = gz.astgen; |
| ... | ... | @@ -4930,27 +4916,29 @@ fn structDeclInner( |
| 4930 | 4916 | if (node == .root) { |
| 4931 | 4917 | return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); |
| 4932 | 4918 | } else { |
| 4933 | return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node); | |
| 4919 | return tupleDecl(gz, scope, node, container_decl, layout, maybe_backing_int_node); | |
| 4934 | 4920 | } |
| 4935 | 4921 | } |
| 4936 | 4922 | |
| 4923 | astgen.advanceSourceCursorToNode(node); | |
| 4924 | ||
| 4937 | 4925 | const decl_inst = try gz.reserveInstructionIndex(); |
| 4938 | 4926 | |
| 4939 | if (container_decl.ast.members.len == 0 and backing_int_node == .none) { | |
| 4927 | if (container_decl.ast.members.len == 0 and maybe_backing_int_node == .none) { | |
| 4940 | 4928 | try gz.setStruct(decl_inst, .{ |
| 4941 | 4929 | .src_node = node, |
| 4930 | .name_strat = name_strat, | |
| 4942 | 4931 | .layout = layout, |
| 4943 | .captures_len = 0, | |
| 4944 | .fields_len = 0, | |
| 4932 | .backing_int_type_body_len = null, | |
| 4945 | 4933 | .decls_len = 0, |
| 4946 | .has_backing_int = false, | |
| 4947 | .known_non_opv = false, | |
| 4948 | .known_comptime_only = false, | |
| 4934 | .fields_len = 0, | |
| 4935 | .any_field_aligns = false, | |
| 4936 | .any_field_defaults = false, | |
| 4949 | 4937 | .any_comptime_fields = false, |
| 4950 | .any_default_inits = false, | |
| 4951 | .any_aligned_fields = false, | |
| 4952 | .fields_hash = std.zig.hashSrc(@tagName(layout)), | |
| 4953 | .name_strat = name_strat, | |
| 4938 | .fields_hash = @splat(0), | |
| 4939 | .captures = &.{}, | |
| 4940 | .capture_names = &.{}, | |
| 4941 | .remaining = &.{}, | |
| 4954 | 4942 | }); |
| 4955 | 4943 | return decl_inst.toRef(); |
| 4956 | 4944 | } |
| ... | ... | @@ -4967,7 +4955,6 @@ fn structDeclInner( |
| 4967 | 4955 | // The struct_decl instruction introduces a scope in which the decls of the struct |
| 4968 | 4956 | // are in scope, so that field types, alignments, and default value expressions |
| 4969 | 4957 | // can refer to decls within the struct itself. |
| 4970 | astgen.advanceSourceCursorToNode(node); | |
| 4971 | 4958 | var block_scope: GenZir = .{ |
| 4972 | 4959 | .parent = &namespace.base, |
| 4973 | 4960 | .decl_node_index = node, |
| ... | ... | @@ -4979,197 +4966,134 @@ fn structDeclInner( |
| 4979 | 4966 | }; |
| 4980 | 4967 | defer block_scope.unstack(); |
| 4981 | 4968 | |
| 4982 | const scratch_top = astgen.scratch.items.len; | |
| 4983 | defer astgen.scratch.items.len = scratch_top; | |
| 4984 | ||
| 4985 | var backing_int_body_len: usize = 0; | |
| 4986 | const backing_int_ref: Zir.Inst.Ref = blk: { | |
| 4987 | if (backing_int_node.unwrap()) |arg| { | |
| 4988 | if (layout != .@"packed") { | |
| 4989 | return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{}); | |
| 4990 | } else { | |
| 4991 | const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg); | |
| 4992 | if (!block_scope.isEmpty()) { | |
| 4993 | if (!block_scope.endsWithNoReturn()) { | |
| 4994 | _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref); | |
| 4995 | } | |
| 4996 | ||
| 4997 | const body = block_scope.instructionsSlice(); | |
| 4998 | const old_scratch_len = astgen.scratch.items.len; | |
| 4999 | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); | |
| 5000 | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); | |
| 5001 | backing_int_body_len = astgen.scratch.items.len - old_scratch_len; | |
| 5002 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5003 | } | |
| 5004 | break :blk backing_int_ref; | |
| 5005 | } | |
| 5006 | } else { | |
| 5007 | break :blk .none; | |
| 5008 | } | |
| 5009 | }; | |
| 4969 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); | |
| 5010 | 4970 | |
| 5011 | const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); | |
| 5012 | const field_count: u32 = @intCast(container_decl.ast.members.len - decl_count); | |
| 4971 | var scratch: Scratch = .init(astgen); | |
| 4972 | defer scratch.reset(); | |
| 5013 | 4973 | |
| 5014 | const bits_per_field = 4; | |
| 5015 | const max_field_size = 5; | |
| 5016 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); | |
| 5017 | defer wip_members.deinit(); | |
| 4974 | // Replicate the structure of the ZIR trailing data in `scratch` | |
| 4975 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); | |
| 4976 | const field_names = try scratch.addSlice(scan_result.fields_len); | |
| 4977 | const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); | |
| 4978 | const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); | |
| 4979 | const field_default_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); | |
| 4980 | const field_comptime_bits = try scratch.addOptionalSlice( | |
| 4981 | scan_result.any_comptime_fields, | |
| 4982 | std.math.divCeil(u32, scan_result.fields_len, 32) catch unreachable, | |
| 4983 | ); | |
| 4984 | if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0); | |
| 5018 | 4985 | |
| 5019 | // We will use the scratch buffer, starting here, for the bodies: | |
| 5020 | // bodies: { // for every fields_len | |
| 5021 | // field_type_body_inst: Inst, // for each field_type_body_len | |
| 5022 | // align_body_inst: Inst, // for each align_body_len | |
| 5023 | // init_body_inst: Inst, // for each init_body_len | |
| 5024 | // } | |
| 5025 | // Note that the scratch buffer is simultaneously being used by WipMembers, however | |
| 5026 | // it will not access any elements beyond this point in the ArrayList. It also | |
| 5027 | // accesses via the ArrayList items field so it can handle the scratch buffer being | |
| 5028 | // reallocated. | |
| 5029 | // No defer needed here because it is handled by `wip_members.deinit()` above. | |
| 5030 | const bodies_start = astgen.scratch.items.len; | |
| 4986 | // Before any field bodies comes the backing int type, if specified. | |
| 4987 | const backing_int_type_body_len: ?u32 = if (maybe_backing_int_node.unwrap()) |backing_int_node| len: { | |
| 4988 | if (layout != .@"packed") return astgen.failNode( | |
| 4989 | backing_int_node, | |
| 4990 | "non-packed struct does not support backing integer type", | |
| 4991 | .{}, | |
| 4992 | ); | |
| 4993 | const type_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node); | |
| 4994 | if (!block_scope.endsWithNoReturn()) { | |
| 4995 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); | |
| 4996 | } | |
| 4997 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 4998 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 4999 | break :len body_len; | |
| 5000 | } else null; | |
| 5031 | 5001 | |
| 5032 | 5002 | const old_hasher = astgen.src_hasher; |
| 5033 | 5003 | defer astgen.src_hasher = old_hasher; |
| 5034 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 5035 | astgen.src_hasher.update(@tagName(layout)); | |
| 5036 | if (backing_int_node.unwrap()) |arg| { | |
| 5037 | astgen.src_hasher.update(tree.getNodeSource(arg)); | |
| 5038 | } | |
| 5004 | astgen.src_hasher = .init(.{}); | |
| 5039 | 5005 | |
| 5040 | var known_non_opv = false; | |
| 5041 | var known_comptime_only = false; | |
| 5042 | var any_comptime_fields = false; | |
| 5043 | var any_aligned_fields = false; | |
| 5044 | var any_default_inits = false; | |
| 5006 | var next_field_idx: u32 = 0; | |
| 5045 | 5007 | for (container_decl.ast.members) |member_node| { |
| 5046 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { | |
| 5008 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { | |
| 5047 | 5009 | .decl => continue, |
| 5048 | 5010 | .field => |field| field, |
| 5049 | 5011 | }; |
| 5012 | const field_idx = next_field_idx; | |
| 5013 | next_field_idx += 1; | |
| 5050 | 5014 | |
| 5051 | 5015 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5052 | 5016 | |
| 5053 | const field_name = try astgen.identAsString(member.ast.main_token); | |
| 5054 | 5017 | member.convertToNonTupleLike(astgen.tree); |
| 5055 | 5018 | assert(!member.ast.tuple_like); |
| 5056 | wip_members.appendToField(@intFromEnum(field_name)); | |
| 5057 | ||
| 5058 | const type_expr = member.ast.type_expr.unwrap() orelse { | |
| 5059 | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); | |
| 5060 | }; | |
| 5061 | 5019 | |
| 5062 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | |
| 5063 | const have_type_body = !block_scope.isEmpty(); | |
| 5064 | const have_align = member.ast.align_expr != .none; | |
| 5065 | const have_value = member.ast.value_expr != .none; | |
| 5066 | const is_comptime = member.comptime_token != null; | |
| 5020 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); | |
| 5067 | 5021 | |
| 5068 | if (is_comptime) { | |
| 5069 | switch (layout) { | |
| 5070 | .@"packed", .@"extern" => return astgen.failTok(member.comptime_token.?, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}), | |
| 5071 | .auto => any_comptime_fields = true, | |
| 5072 | } | |
| 5073 | } else { | |
| 5074 | known_non_opv = known_non_opv or | |
| 5075 | nodeImpliesMoreThanOnePossibleValue(tree, type_expr); | |
| 5076 | known_comptime_only = known_comptime_only or | |
| 5077 | nodeImpliesComptimeOnly(tree, type_expr); | |
| 5078 | } | |
| 5079 | wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body }); | |
| 5080 | ||
| 5081 | if (have_type_body) { | |
| 5022 | { | |
| 5023 | const type_node = member.ast.type_expr.unwrap() orelse { | |
| 5024 | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); | |
| 5025 | }; | |
| 5026 | const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); | |
| 5082 | 5027 | if (!block_scope.endsWithNoReturn()) { |
| 5083 | _ = try block_scope.addBreak(.break_inline, decl_inst, field_type); | |
| 5028 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); | |
| 5084 | 5029 | } |
| 5085 | const body = block_scope.instructionsSlice(); | |
| 5086 | const old_scratch_len = astgen.scratch.items.len; | |
| 5087 | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); | |
| 5088 | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); | |
| 5089 | wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); | |
| 5030 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5031 | field_type_body_lens.get(astgen)[field_idx] = body_len; | |
| 5090 | 5032 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5091 | } else { | |
| 5092 | wip_members.appendToField(@intFromEnum(field_type)); | |
| 5093 | 5033 | } |
| 5094 | 5034 | |
| 5095 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5035 | if (member.ast.align_expr.unwrap()) |align_node| { | |
| 5096 | 5036 | if (layout == .@"packed") { |
| 5097 | return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{}); | |
| 5037 | return astgen.failNode(align_node, "unable to override alignment of packed struct fields", .{}); | |
| 5098 | 5038 | } |
| 5099 | any_aligned_fields = true; | |
| 5100 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr); | |
| 5039 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); | |
| 5101 | 5040 | if (!block_scope.endsWithNoReturn()) { |
| 5102 | 5041 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 5103 | 5042 | } |
| 5104 | const body = block_scope.instructionsSlice(); | |
| 5105 | const old_scratch_len = astgen.scratch.items.len; | |
| 5106 | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); | |
| 5107 | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); | |
| 5108 | wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); | |
| 5043 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5044 | field_align_body_lens.?.get(astgen)[field_idx] = body_len; | |
| 5109 | 5045 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5046 | } else if (field_align_body_lens) |lens| { | |
| 5047 | lens.get(astgen)[field_idx] = 0; | |
| 5110 | 5048 | } |
| 5111 | 5049 | |
| 5112 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5113 | any_default_inits = true; | |
| 5114 | ||
| 5115 | // The decl_inst is used as here so that we can easily reconstruct a mapping | |
| 5116 | // between it and the field type when the fields inits are analyzed. | |
| 5117 | const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } }; | |
| 5118 | ||
| 5119 | const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr); | |
| 5050 | if (member.ast.value_expr.unwrap()) |default_node| { | |
| 5051 | const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; | |
| 5052 | const default_ref = try expr(&block_scope, &namespace.base, ri, default_node); | |
| 5120 | 5053 | if (!block_scope.endsWithNoReturn()) { |
| 5121 | _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); | |
| 5054 | _ = try block_scope.addBreak(.break_inline, decl_inst, default_ref); | |
| 5122 | 5055 | } |
| 5123 | const body = block_scope.instructionsSlice(); | |
| 5124 | const old_scratch_len = astgen.scratch.items.len; | |
| 5125 | try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); | |
| 5126 | appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); | |
| 5127 | wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); | |
| 5056 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5057 | field_default_body_lens.?.get(astgen)[field_idx] = body_len; | |
| 5128 | 5058 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5129 | } else if (member.comptime_token) |comptime_token| { | |
| 5130 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); | |
| 5059 | } else if (field_default_body_lens) |lens| { | |
| 5060 | lens.get(astgen)[field_idx] = 0; | |
| 5061 | } | |
| 5062 | ||
| 5063 | if (member.comptime_token) |comptime_token| { | |
| 5064 | switch (layout) { | |
| 5065 | .@"packed", .@"extern" => return astgen.failTok(comptime_token, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}), | |
| 5066 | .auto => {}, | |
| 5067 | } | |
| 5068 | if (member.ast.value_expr == .none) { | |
| 5069 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); | |
| 5070 | } | |
| 5071 | const mask = @as(u32, 1) << @intCast(field_idx % 32); | |
| 5072 | field_comptime_bits.?.get(astgen)[field_idx / 32] |= mask; | |
| 5131 | 5073 | } |
| 5132 | 5074 | } |
| 5075 | assert(next_field_idx == scan_result.fields_len); | |
| 5076 | wip_decls.finish(); | |
| 5133 | 5077 | |
| 5134 | 5078 | var fields_hash: std.zig.SrcHash = undefined; |
| 5135 | 5079 | astgen.src_hasher.final(&fields_hash); |
| 5136 | 5080 | |
| 5137 | 5081 | try gz.setStruct(decl_inst, .{ |
| 5138 | 5082 | .src_node = node, |
| 5083 | .name_strat = name_strat, | |
| 5139 | 5084 | .layout = layout, |
| 5140 | .captures_len = @intCast(namespace.captures.count()), | |
| 5141 | .fields_len = field_count, | |
| 5142 | .decls_len = decl_count, | |
| 5143 | .has_backing_int = backing_int_ref != .none, | |
| 5144 | .known_non_opv = known_non_opv, | |
| 5145 | .known_comptime_only = known_comptime_only, | |
| 5146 | .any_comptime_fields = any_comptime_fields, | |
| 5147 | .any_default_inits = any_default_inits, | |
| 5148 | .any_aligned_fields = any_aligned_fields, | |
| 5085 | .backing_int_type_body_len = backing_int_type_body_len, | |
| 5086 | .decls_len = scan_result.decls_len, | |
| 5087 | .fields_len = scan_result.fields_len, | |
| 5088 | .any_field_aligns = scan_result.any_field_aligns, | |
| 5089 | .any_field_defaults = scan_result.any_field_values, | |
| 5090 | .any_comptime_fields = scan_result.any_comptime_fields, | |
| 5149 | 5091 | .fields_hash = fields_hash, |
| 5150 | .name_strat = name_strat, | |
| 5092 | .captures = namespace.captures.keys(), | |
| 5093 | .capture_names = namespace.captures.values(), | |
| 5094 | .remaining = scratch.all().get(astgen), | |
| 5151 | 5095 | }); |
| 5152 | 5096 | |
| 5153 | wip_members.finishBits(bits_per_field); | |
| 5154 | const decls_slice = wip_members.declsSlice(); | |
| 5155 | const fields_slice = wip_members.fieldsSlice(); | |
| 5156 | const bodies_slice = astgen.scratch.items[bodies_start..]; | |
| 5157 | try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 + | |
| 5158 | decls_slice.len + namespace.captures.count() * 2 + fields_slice.len + bodies_slice.len); | |
| 5159 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | |
| 5160 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); | |
| 5161 | if (backing_int_ref != .none) { | |
| 5162 | astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len)); | |
| 5163 | if (backing_int_body_len == 0) { | |
| 5164 | astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref)); | |
| 5165 | } else { | |
| 5166 | astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); | |
| 5167 | } | |
| 5168 | } | |
| 5169 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | |
| 5170 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | |
| 5171 | astgen.extra.appendSliceAssumeCapacity(bodies_slice); | |
| 5172 | ||
| 5173 | 5097 | block_scope.unstack(); |
| 5174 | 5098 | return decl_inst.toRef(); |
| 5175 | 5099 | } |
| ... | ... | @@ -5281,11 +5205,29 @@ fn unionDeclInner( |
| 5281 | 5205 | auto_enum_tok: ?Ast.TokenIndex, |
| 5282 | 5206 | name_strat: Zir.Inst.NameStrategy, |
| 5283 | 5207 | ) InnerError!Zir.Inst.Ref { |
| 5284 | const decl_inst = try gz.reserveInstructionIndex(); | |
| 5285 | ||
| 5286 | 5208 | const astgen = gz.astgen; |
| 5287 | 5209 | const gpa = astgen.gpa; |
| 5288 | 5210 | |
| 5211 | const explicit_int_or_enum_tag = switch (layout) { | |
| 5212 | .auto => opt_arg_node != .none, | |
| 5213 | .@"extern" => if (opt_arg_node.unwrap()) |arg_node| { | |
| 5214 | return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); | |
| 5215 | } else false, | |
| 5216 | .@"packed" => false, | |
| 5217 | }; | |
| 5218 | ||
| 5219 | if (auto_enum_tok) |t| { | |
| 5220 | if (layout != .auto) { | |
| 5221 | return astgen.failTok(t, "{s} union does not support enum tag type", .{@tagName(layout)}); | |
| 5222 | } | |
| 5223 | } | |
| 5224 | ||
| 5225 | const is_tagged = explicit_int_or_enum_tag or auto_enum_tok != null; | |
| 5226 | ||
| 5227 | astgen.advanceSourceCursorToNode(node); | |
| 5228 | ||
| 5229 | const decl_inst = try gz.reserveInstructionIndex(); | |
| 5230 | ||
| 5289 | 5231 | var namespace: Scope.Namespace = .{ |
| 5290 | 5232 | .parent = scope, |
| 5291 | 5233 | .node = node, |
| ... | ... | @@ -5298,7 +5240,6 @@ fn unionDeclInner( |
| 5298 | 5240 | // The union_decl instruction introduces a scope in which the decls of the union |
| 5299 | 5241 | // are in scope, so that field types, alignments, and default value expressions |
| 5300 | 5242 | // can refer to decls within the union itself. |
| 5301 | astgen.advanceSourceCursorToNode(node); | |
| 5302 | 5243 | var block_scope: GenZir = .{ |
| 5303 | 5244 | .parent = &namespace.base, |
| 5304 | 5245 | .decl_node_index = node, |
| ... | ... | @@ -5310,42 +5251,42 @@ fn unionDeclInner( |
| 5310 | 5251 | }; |
| 5311 | 5252 | defer block_scope.unstack(); |
| 5312 | 5253 | |
| 5313 | const decl_count = try astgen.scanContainer(&namespace, members, .@"union"); | |
| 5314 | const field_count: u32 = @intCast(members.len - decl_count); | |
| 5254 | const scan_result = try astgen.scanContainer(&namespace, members, .@"union"); | |
| 5315 | 5255 | |
| 5316 | if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) { | |
| 5317 | if (opt_arg_node.unwrap()) |arg_node| { | |
| 5318 | return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); | |
| 5319 | } else { | |
| 5320 | return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)}); | |
| 5321 | } | |
| 5322 | } | |
| 5256 | var scratch: Scratch = .init(astgen); | |
| 5257 | defer scratch.reset(); | |
| 5323 | 5258 | |
| 5324 | const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node| | |
| 5325 | try typeExpr(&block_scope, &namespace.base, arg_node) | |
| 5326 | else | |
| 5327 | .none; | |
| 5259 | // Replicate the structure of the ZIR trailing data in `scratch` | |
| 5260 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); | |
| 5261 | const field_names = try scratch.addSlice(scan_result.fields_len); | |
| 5262 | const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); | |
| 5263 | const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); | |
| 5264 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); | |
| 5328 | 5265 | |
| 5329 | const bits_per_field = 4; | |
| 5330 | const max_field_size = 4; | |
| 5331 | var any_aligned_fields = false; | |
| 5332 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); | |
| 5333 | defer wip_members.deinit(); | |
| 5266 | // Before any field bodies comes the tag/backing type, if specified. | |
| 5267 | const arg_type_body_len: ?u32 = if (opt_arg_node.unwrap()) |arg_node| len: { | |
| 5268 | const type_ref = try typeExpr(&block_scope, &namespace.base, arg_node); | |
| 5269 | if (!block_scope.endsWithNoReturn()) { | |
| 5270 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); | |
| 5271 | } | |
| 5272 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5273 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5274 | break :len body_len; | |
| 5275 | } else null; | |
| 5334 | 5276 | |
| 5335 | 5277 | const old_hasher = astgen.src_hasher; |
| 5336 | 5278 | defer astgen.src_hasher = old_hasher; |
| 5337 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 5338 | astgen.src_hasher.update(@tagName(layout)); | |
| 5339 | astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); | |
| 5340 | if (opt_arg_node.unwrap()) |arg_node| { | |
| 5341 | astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); | |
| 5342 | } | |
| 5279 | astgen.src_hasher = .init(.{}); | |
| 5343 | 5280 | |
| 5281 | var next_field_idx: u32 = 0; | |
| 5344 | 5282 | for (members) |member_node| { |
| 5345 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { | |
| 5283 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { | |
| 5346 | 5284 | .decl => continue, |
| 5347 | 5285 | .field => |field| field, |
| 5348 | 5286 | }; |
| 5287 | const field_idx = next_field_idx; | |
| 5288 | next_field_idx += 1; | |
| 5289 | ||
| 5349 | 5290 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); |
| 5350 | 5291 | member.convertToNonTupleLike(astgen.tree); |
| 5351 | 5292 | if (member.ast.tuple_like) { |
| ... | ... | @@ -5355,97 +5296,91 @@ fn unionDeclInner( |
| 5355 | 5296 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 5356 | 5297 | } |
| 5357 | 5298 | |
| 5358 | const field_name = try astgen.identAsString(member.ast.main_token); | |
| 5359 | wip_members.appendToField(@intFromEnum(field_name)); | |
| 5360 | ||
| 5361 | const have_type = member.ast.type_expr != .none; | |
| 5362 | const have_align = member.ast.align_expr != .none; | |
| 5363 | const have_value = member.ast.value_expr != .none; | |
| 5364 | const unused = false; | |
| 5365 | wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); | |
| 5299 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); | |
| 5366 | 5300 | |
| 5367 | if (member.ast.type_expr.unwrap()) |type_expr| { | |
| 5368 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | |
| 5369 | wip_members.appendToField(@intFromEnum(field_type)); | |
| 5370 | } else if (arg_inst == .none and auto_enum_tok == null) { | |
| 5301 | if (member.ast.type_expr.unwrap()) |type_node| { | |
| 5302 | const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); | |
| 5303 | if (!block_scope.endsWithNoReturn()) { | |
| 5304 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); | |
| 5305 | } | |
| 5306 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5307 | field_type_body_lens.get(astgen)[field_idx] = body_len; | |
| 5308 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5309 | } else if (!is_tagged) { | |
| 5371 | 5310 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 5311 | } else { | |
| 5312 | field_type_body_lens.get(astgen)[field_idx] = 0; | |
| 5372 | 5313 | } |
| 5373 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5314 | ||
| 5315 | if (member.ast.align_expr.unwrap()) |align_node| { | |
| 5374 | 5316 | if (layout == .@"packed") { |
| 5375 | return astgen.failNode(align_expr, "unable to override alignment of packed union fields", .{}); | |
| 5317 | return astgen.failNode(align_node, "unable to override alignment of packed union fields", .{}); | |
| 5376 | 5318 | } |
| 5377 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); | |
| 5378 | wip_members.appendToField(@intFromEnum(align_inst)); | |
| 5379 | any_aligned_fields = true; | |
| 5380 | } | |
| 5381 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5382 | if (arg_inst == .none) { | |
| 5383 | return astgen.failNodeNotes( | |
| 5384 | node, | |
| 5385 | "explicitly valued tagged union missing integer tag type", | |
| 5386 | .{}, | |
| 5387 | &[_]u32{ | |
| 5388 | try astgen.errNoteNode( | |
| 5389 | value_expr, | |
| 5390 | "tag value specified here", | |
| 5391 | .{}, | |
| 5392 | ), | |
| 5393 | }, | |
| 5394 | ); | |
| 5319 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); | |
| 5320 | if (!block_scope.endsWithNoReturn()) { | |
| 5321 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); | |
| 5395 | 5322 | } |
| 5396 | if (auto_enum_tok == null) { | |
| 5397 | return astgen.failNodeNotes( | |
| 5398 | node, | |
| 5399 | "explicitly valued tagged union requires inferred enum tag type", | |
| 5400 | .{}, | |
| 5401 | &[_]u32{ | |
| 5402 | try astgen.errNoteNode( | |
| 5403 | value_expr, | |
| 5404 | "tag value specified here", | |
| 5405 | .{}, | |
| 5406 | ), | |
| 5407 | }, | |
| 5408 | ); | |
| 5323 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5324 | field_align_body_lens.?.get(astgen)[field_idx] = body_len; | |
| 5325 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5326 | } else if (field_align_body_lens) |lens| { | |
| 5327 | lens.get(astgen)[field_idx] = 0; | |
| 5328 | } | |
| 5329 | ||
| 5330 | if (member.ast.value_expr.unwrap()) |value_node| { | |
| 5331 | if (!explicit_int_or_enum_tag) return astgen.failNodeNotes( | |
| 5332 | node, | |
| 5333 | "explicitly valued tagged union missing integer tag type", | |
| 5334 | .{}, | |
| 5335 | &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})}, | |
| 5336 | ); | |
| 5337 | if (auto_enum_tok == null) return astgen.failNodeNotes( | |
| 5338 | node, | |
| 5339 | "explicitly valued tagged union requires inferred enum tag type", | |
| 5340 | .{}, | |
| 5341 | &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})}, | |
| 5342 | ); | |
| 5343 | const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; | |
| 5344 | const value_ref = try expr(&block_scope, &namespace.base, ri, value_node); | |
| 5345 | if (!block_scope.endsWithNoReturn()) { | |
| 5346 | _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); | |
| 5409 | 5347 | } |
| 5410 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | |
| 5411 | wip_members.appendToField(@intFromEnum(tag_value)); | |
| 5348 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5349 | field_value_body_lens.?.get(astgen)[field_idx] = body_len; | |
| 5350 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5351 | } else if (field_value_body_lens) |lens| { | |
| 5352 | lens.get(astgen)[field_idx] = 0; | |
| 5412 | 5353 | } |
| 5413 | 5354 | } |
| 5355 | assert(next_field_idx == scan_result.fields_len); | |
| 5356 | wip_decls.finish(); | |
| 5414 | 5357 | |
| 5415 | 5358 | var fields_hash: std.zig.SrcHash = undefined; |
| 5416 | 5359 | astgen.src_hasher.final(&fields_hash); |
| 5417 | 5360 | |
| 5418 | if (!block_scope.isEmpty()) { | |
| 5419 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | |
| 5420 | } | |
| 5421 | ||
| 5422 | const body = block_scope.instructionsSlice(); | |
| 5423 | const body_len = astgen.countBodyLenAfterFixups(body); | |
| 5424 | ||
| 5425 | 5361 | try gz.setUnion(decl_inst, .{ |
| 5426 | 5362 | .src_node = node, |
| 5427 | .layout = layout, | |
| 5428 | .tag_type = arg_inst, | |
| 5429 | .captures_len = @intCast(namespace.captures.count()), | |
| 5430 | .body_len = body_len, | |
| 5431 | .fields_len = field_count, | |
| 5432 | .decls_len = decl_count, | |
| 5433 | .auto_enum_tag = auto_enum_tok != null, | |
| 5434 | .any_aligned_fields = any_aligned_fields, | |
| 5435 | .fields_hash = fields_hash, | |
| 5436 | 5363 | .name_strat = name_strat, |
| 5364 | .kind = switch (layout) { | |
| 5365 | .auto => if (auto_enum_tok == null) l: { | |
| 5366 | break :l if (opt_arg_node == .none) .auto else .tagged_explicit; | |
| 5367 | } else l: { | |
| 5368 | break :l if (opt_arg_node == .none) .tagged_enum else .tagged_enum_explicit; | |
| 5369 | }, | |
| 5370 | .@"extern" => .@"extern", | |
| 5371 | .@"packed" => if (opt_arg_node != .none) .packed_explicit else .@"packed", | |
| 5372 | }, | |
| 5373 | .arg_type_body_len = arg_type_body_len, | |
| 5374 | .decls_len = scan_result.decls_len, | |
| 5375 | .fields_len = scan_result.fields_len, | |
| 5376 | .any_field_aligns = scan_result.any_field_aligns, | |
| 5377 | .any_field_values = scan_result.any_field_values, | |
| 5378 | .fields_hash = fields_hash, | |
| 5379 | .captures = namespace.captures.keys(), | |
| 5380 | .capture_names = namespace.captures.values(), | |
| 5381 | .remaining = scratch.all().get(astgen), | |
| 5437 | 5382 | }); |
| 5438 | 5383 | |
| 5439 | wip_members.finishBits(bits_per_field); | |
| 5440 | const decls_slice = wip_members.declsSlice(); | |
| 5441 | const fields_slice = wip_members.fieldsSlice(); | |
| 5442 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len); | |
| 5443 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | |
| 5444 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); | |
| 5445 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | |
| 5446 | astgen.appendBodyWithFixups(body); | |
| 5447 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | |
| 5448 | ||
| 5449 | 5384 | block_scope.unstack(); |
| 5450 | 5385 | return decl_inst.toRef(); |
| 5451 | 5386 | } |
| ... | ... | @@ -5494,103 +5429,8 @@ fn containerDecl( |
| 5494 | 5429 | if (container_decl.layout_token) |t| { |
| 5495 | 5430 | return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{}); |
| 5496 | 5431 | } |
| 5497 | // Count total fields as well as how many have explicitly provided tag values. | |
| 5498 | const counts = blk: { | |
| 5499 | var values: usize = 0; | |
| 5500 | var total_fields: usize = 0; | |
| 5501 | var decls: usize = 0; | |
| 5502 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; | |
| 5503 | var nonfinal_nonexhaustive = false; | |
| 5504 | for (container_decl.ast.members) |member_node| { | |
| 5505 | var member = tree.fullContainerField(member_node) orelse { | |
| 5506 | decls += 1; | |
| 5507 | continue; | |
| 5508 | }; | |
| 5509 | member.convertToNonTupleLike(astgen.tree); | |
| 5510 | if (member.ast.tuple_like) { | |
| 5511 | return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); | |
| 5512 | } | |
| 5513 | if (member.comptime_token) |comptime_token| { | |
| 5514 | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); | |
| 5515 | } | |
| 5516 | if (member.ast.type_expr.unwrap()) |type_expr| { | |
| 5517 | return astgen.failNodeNotes( | |
| 5518 | type_expr, | |
| 5519 | "enum fields do not have types", | |
| 5520 | .{}, | |
| 5521 | &[_]u32{ | |
| 5522 | try astgen.errNoteNode( | |
| 5523 | node, | |
| 5524 | "consider 'union(enum)' here to make it a tagged union", | |
| 5525 | .{}, | |
| 5526 | ), | |
| 5527 | }, | |
| 5528 | ); | |
| 5529 | } | |
| 5530 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5531 | return astgen.failNode(align_expr, "enum fields cannot be aligned", .{}); | |
| 5532 | } | |
| 5533 | 5432 | |
| 5534 | const name_token = member.ast.main_token; | |
| 5535 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { | |
| 5536 | if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| { | |
| 5537 | return astgen.failNodeNotes( | |
| 5538 | member_node, | |
| 5539 | "redundant non-exhaustive enum mark", | |
| 5540 | .{}, | |
| 5541 | &[_]u32{ | |
| 5542 | try astgen.errNoteNode( | |
| 5543 | nonexhaustive_node, | |
| 5544 | "other mark here", | |
| 5545 | .{}, | |
| 5546 | ), | |
| 5547 | }, | |
| 5548 | ); | |
| 5549 | } | |
| 5550 | opt_nonexhaustive_node = member_node.toOptional(); | |
| 5551 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5552 | return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); | |
| 5553 | } | |
| 5554 | continue; | |
| 5555 | } else if (opt_nonexhaustive_node != .none) { | |
| 5556 | nonfinal_nonexhaustive = true; | |
| 5557 | } | |
| 5558 | total_fields += 1; | |
| 5559 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5560 | if (container_decl.ast.arg == .none) { | |
| 5561 | return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{}); | |
| 5562 | } | |
| 5563 | values += 1; | |
| 5564 | } | |
| 5565 | } | |
| 5566 | if (nonfinal_nonexhaustive) { | |
| 5567 | return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{}); | |
| 5568 | } | |
| 5569 | break :blk .{ | |
| 5570 | .total_fields = total_fields, | |
| 5571 | .values = values, | |
| 5572 | .decls = decls, | |
| 5573 | .nonexhaustive_node = opt_nonexhaustive_node, | |
| 5574 | }; | |
| 5575 | }; | |
| 5576 | if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) { | |
| 5577 | const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?; | |
| 5578 | return astgen.failNodeNotes( | |
| 5579 | node, | |
| 5580 | "non-exhaustive enum missing integer tag type", | |
| 5581 | .{}, | |
| 5582 | &[_]u32{ | |
| 5583 | try astgen.errNoteNode( | |
| 5584 | nonexhaustive_node, | |
| 5585 | "marked non-exhaustive here", | |
| 5586 | .{}, | |
| 5587 | ), | |
| 5588 | }, | |
| 5589 | ); | |
| 5590 | } | |
| 5591 | // In this case we must generate ZIR code for the tag values, similar to | |
| 5592 | // how structs are handled above. | |
| 5593 | const nonexhaustive = counts.nonexhaustive_node != .none; | |
| 5433 | astgen.advanceSourceCursorToNode(node); | |
| 5594 | 5434 | |
| 5595 | 5435 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5596 | 5436 | |
| ... | ... | @@ -5605,7 +5445,6 @@ fn containerDecl( |
| 5605 | 5445 | |
| 5606 | 5446 | // The enum_decl instruction introduces a scope in which the decls of the enum |
| 5607 | 5447 | // are in scope, so that tag values can refer to decls within the enum itself. |
| 5608 | astgen.advanceSourceCursorToNode(node); | |
| 5609 | 5448 | var block_scope: GenZir = .{ |
| 5610 | 5449 | .parent = &namespace.base, |
| 5611 | 5450 | .decl_node_index = node, |
| ... | ... | @@ -5617,104 +5456,127 @@ fn containerDecl( |
| 5617 | 5456 | }; |
| 5618 | 5457 | defer block_scope.unstack(); |
| 5619 | 5458 | |
| 5620 | _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); | |
| 5621 | namespace.base.tag = .namespace; | |
| 5459 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); | |
| 5460 | // The name `_` is not actually a field; it marks a non-exhaustive enum. | |
| 5461 | const fields_len: u32 = scan_result.fields_len - @intFromBool(scan_result.has_underscore_field); | |
| 5622 | 5462 | |
| 5623 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg| | |
| 5624 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type) | |
| 5625 | else | |
| 5626 | .none; | |
| 5463 | var scratch: Scratch = .init(astgen); | |
| 5464 | defer scratch.reset(); | |
| 5627 | 5465 | |
| 5628 | const bits_per_field = 1; | |
| 5629 | const max_field_size = 2; | |
| 5630 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); | |
| 5631 | defer wip_members.deinit(); | |
| 5466 | // Replicate the structure of the ZIR trailing data in `scratch` | |
| 5467 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); | |
| 5468 | const field_names = try scratch.addSlice(fields_len); | |
| 5469 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len); | |
| 5470 | ||
| 5471 | // Before any field bodies comes the tag type, if specified. | |
| 5472 | const tag_type_body_len: ?u32 = if (container_decl.ast.arg.unwrap()) |tag_type_node| len: { | |
| 5473 | const type_ref = try typeExpr(&block_scope, &namespace.base, tag_type_node); | |
| 5474 | if (!block_scope.endsWithNoReturn()) { | |
| 5475 | _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); | |
| 5476 | } | |
| 5477 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5478 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5479 | break :len body_len; | |
| 5480 | } else null; | |
| 5632 | 5481 | |
| 5633 | 5482 | const old_hasher = astgen.src_hasher; |
| 5634 | 5483 | defer astgen.src_hasher = old_hasher; |
| 5635 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | |
| 5636 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 5637 | astgen.src_hasher.update(tree.getNodeSource(arg)); | |
| 5638 | } | |
| 5639 | astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)}); | |
| 5484 | astgen.src_hasher = .init(.{}); | |
| 5640 | 5485 | |
| 5486 | var next_field_idx: u32 = 0; | |
| 5487 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; | |
| 5641 | 5488 | for (container_decl.ast.members) |member_node| { |
| 5642 | if (member_node.toOptional() == counts.nonexhaustive_node) | |
| 5643 | continue; | |
| 5644 | astgen.src_hasher.update(tree.getNodeSource(member_node)); | |
| 5645 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { | |
| 5489 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { | |
| 5646 | 5490 | .decl => continue, |
| 5647 | 5491 | .field => |field| field, |
| 5648 | 5492 | }; |
| 5649 | 5493 | member.convertToNonTupleLike(astgen.tree); |
| 5650 | assert(member.comptime_token == null); | |
| 5651 | assert(member.ast.type_expr == .none); | |
| 5652 | assert(member.ast.align_expr == .none); | |
| 5494 | if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); | |
| 5495 | if (member.comptime_token) |t| return astgen.failTok(t, "enum fields cannot be marked comptime", .{}); | |
| 5496 | if (member.ast.type_expr.unwrap()) |type_node| { | |
| 5497 | return astgen.failNodeNotes(type_node, "enum fields do not have types", .{}, &.{ | |
| 5498 | try astgen.errNoteNode(node, "consider 'union(enum)' here to make it a tagged union", .{}), | |
| 5499 | }); | |
| 5500 | } | |
| 5501 | if (member.ast.align_expr.unwrap()) |n| return astgen.failNode(n, "enum fields cannot be aligned", .{}); | |
| 5502 | if (mem.eql(u8, tree.tokenSlice(member.ast.main_token), "_")) { | |
| 5503 | // non-exhaustive mark | |
| 5504 | assert(scan_result.has_underscore_field); | |
| 5505 | if (opt_nonexhaustive_node.unwrap()) |prev_node| { | |
| 5506 | return astgen.failNodeNotes(member_node, "redundant non-exhaustive enum mark", .{}, &.{ | |
| 5507 | try astgen.errNoteNode(prev_node, "other mark here", .{}), | |
| 5508 | }); | |
| 5509 | } | |
| 5510 | if (member.ast.value_expr.unwrap()) |value_node| { | |
| 5511 | return astgen.failNode(value_node, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); | |
| 5512 | } | |
| 5513 | if (next_field_idx != fields_len) { | |
| 5514 | return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{}); | |
| 5515 | } | |
| 5516 | if (tag_type_body_len == null) { | |
| 5517 | return astgen.failNodeNotes(node, "non-exhaustive enum missing integer tag type", .{}, &.{ | |
| 5518 | try astgen.errNoteNode(member_node, "marked non-exhaustive here", .{}), | |
| 5519 | }); | |
| 5520 | } | |
| 5521 | opt_nonexhaustive_node = member_node.toOptional(); | |
| 5522 | continue; | |
| 5523 | } | |
| 5653 | 5524 | |
| 5654 | const field_name = try astgen.identAsString(member.ast.main_token); | |
| 5655 | wip_members.appendToField(@intFromEnum(field_name)); | |
| 5525 | // This is a real field rather than a non-exhaustive mark. | |
| 5526 | const field_idx = next_field_idx; | |
| 5527 | next_field_idx += 1; | |
| 5656 | 5528 | |
| 5657 | const have_value = member.ast.value_expr != .none; | |
| 5658 | wip_members.nextField(bits_per_field, .{have_value}); | |
| 5529 | astgen.src_hasher.update(tree.getNodeSource(member_node)); | |
| 5659 | 5530 | |
| 5660 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5661 | if (arg_inst == .none) { | |
| 5662 | return astgen.failNodeNotes( | |
| 5663 | node, | |
| 5664 | "explicitly valued enum missing integer tag type", | |
| 5665 | .{}, | |
| 5666 | &[_]u32{ | |
| 5667 | try astgen.errNoteNode( | |
| 5668 | value_expr, | |
| 5669 | "tag value specified here", | |
| 5670 | .{}, | |
| 5671 | ), | |
| 5672 | }, | |
| 5673 | ); | |
| 5531 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); | |
| 5532 | ||
| 5533 | if (member.ast.value_expr.unwrap()) |value_node| { | |
| 5534 | if (tag_type_body_len == null) { | |
| 5535 | return astgen.failNodeNotes(node, "explicitly valued enum missing integer tag type", .{}, &.{ | |
| 5536 | try astgen.errNoteNode(value_node, "tag value specified here", .{}), | |
| 5537 | }); | |
| 5538 | } | |
| 5539 | const val_ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; | |
| 5540 | const value_ref = try expr(&block_scope, &namespace.base, val_ri, value_node); | |
| 5541 | if (!block_scope.endsWithNoReturn()) { | |
| 5542 | _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); | |
| 5674 | 5543 | } |
| 5675 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | |
| 5676 | wip_members.appendToField(@intFromEnum(tag_value_inst)); | |
| 5544 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); | |
| 5545 | field_value_body_lens.?.get(astgen)[field_idx] = body_len; | |
| 5546 | block_scope.instructions.items.len = block_scope.instructions_top; | |
| 5547 | } else if (field_value_body_lens) |lens| { | |
| 5548 | lens.get(astgen)[field_idx] = 0; | |
| 5677 | 5549 | } |
| 5678 | 5550 | } |
| 5679 | ||
| 5680 | if (!block_scope.isEmpty()) { | |
| 5681 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | |
| 5682 | } | |
| 5551 | assert(scan_result.has_underscore_field == (opt_nonexhaustive_node != .none)); | |
| 5552 | assert(next_field_idx == fields_len); | |
| 5553 | wip_decls.finish(); | |
| 5683 | 5554 | |
| 5684 | 5555 | var fields_hash: std.zig.SrcHash = undefined; |
| 5685 | 5556 | astgen.src_hasher.final(&fields_hash); |
| 5686 | 5557 | |
| 5687 | const body = block_scope.instructionsSlice(); | |
| 5688 | const body_len = astgen.countBodyLenAfterFixups(body); | |
| 5689 | ||
| 5690 | 5558 | try gz.setEnum(decl_inst, .{ |
| 5691 | 5559 | .src_node = node, |
| 5692 | .nonexhaustive = nonexhaustive, | |
| 5693 | .tag_type = arg_inst, | |
| 5694 | .captures_len = @intCast(namespace.captures.count()), | |
| 5695 | .body_len = body_len, | |
| 5696 | .fields_len = @intCast(counts.total_fields), | |
| 5697 | .decls_len = @intCast(counts.decls), | |
| 5698 | .fields_hash = fields_hash, | |
| 5699 | 5560 | .name_strat = name_strat, |
| 5561 | .tag_type_body_len = tag_type_body_len, | |
| 5562 | .nonexhaustive = scan_result.has_underscore_field, | |
| 5563 | .decls_len = scan_result.decls_len, | |
| 5564 | .fields_len = fields_len, | |
| 5565 | .any_field_values = scan_result.any_field_values, | |
| 5566 | .fields_hash = fields_hash, | |
| 5567 | .captures = namespace.captures.keys(), | |
| 5568 | .capture_names = namespace.captures.values(), | |
| 5569 | .remaining = scratch.all().get(astgen), | |
| 5700 | 5570 | }); |
| 5701 | 5571 | |
| 5702 | wip_members.finishBits(bits_per_field); | |
| 5703 | const decls_slice = wip_members.declsSlice(); | |
| 5704 | const fields_slice = wip_members.fieldsSlice(); | |
| 5705 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len); | |
| 5706 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | |
| 5707 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); | |
| 5708 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | |
| 5709 | astgen.appendBodyWithFixups(body); | |
| 5710 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | |
| 5711 | ||
| 5712 | 5572 | block_scope.unstack(); |
| 5713 | 5573 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5714 | 5574 | }, |
| 5715 | 5575 | .keyword_opaque => { |
| 5716 | 5576 | assert(container_decl.ast.arg == .none); |
| 5717 | 5577 | |
| 5578 | astgen.advanceSourceCursorToNode(node); | |
| 5579 | ||
| 5718 | 5580 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5719 | 5581 | |
| 5720 | 5582 | var namespace: Scope.Namespace = .{ |
| ... | ... | @@ -5726,7 +5588,6 @@ fn containerDecl( |
| 5726 | 5588 | }; |
| 5727 | 5589 | defer namespace.deinit(gpa); |
| 5728 | 5590 | |
| 5729 | astgen.advanceSourceCursorToNode(node); | |
| 5730 | 5591 | var block_scope: GenZir = .{ |
| 5731 | 5592 | .parent = &namespace.base, |
| 5732 | 5593 | .decl_node_index = node, |
| ... | ... | @@ -5738,36 +5599,34 @@ fn containerDecl( |
| 5738 | 5599 | }; |
| 5739 | 5600 | defer block_scope.unstack(); |
| 5740 | 5601 | |
| 5741 | const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque"); | |
| 5602 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque"); | |
| 5742 | 5603 | |
| 5743 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0); | |
| 5744 | defer wip_members.deinit(); | |
| 5604 | var scratch: Scratch = .init(astgen); | |
| 5605 | defer scratch.reset(); | |
| 5606 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); | |
| 5745 | 5607 | |
| 5746 | 5608 | if (container_decl.layout_token) |layout_token| { |
| 5747 | 5609 | return astgen.failTok(layout_token, "opaque types do not support 'packed' or 'extern'", .{}); |
| 5748 | 5610 | } |
| 5749 | 5611 | |
| 5750 | 5612 | for (container_decl.ast.members) |member_node| { |
| 5751 | const res = try containerMember(&block_scope, &namespace.base, &wip_members, member_node); | |
| 5752 | if (res == .field) { | |
| 5753 | return astgen.failNode(member_node, "opaque types cannot have fields", .{}); | |
| 5613 | switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { | |
| 5614 | .decl => {}, | |
| 5615 | .field => return astgen.failNode(member_node, "opaque types cannot have fields", .{}), | |
| 5754 | 5616 | } |
| 5755 | 5617 | } |
| 5756 | 5618 | |
| 5619 | wip_decls.finish(); | |
| 5620 | ||
| 5757 | 5621 | try gz.setOpaque(decl_inst, .{ |
| 5758 | 5622 | .src_node = node, |
| 5759 | .captures_len = @intCast(namespace.captures.count()), | |
| 5760 | .decls_len = decl_count, | |
| 5761 | 5623 | .name_strat = name_strat, |
| 5624 | .decls_len = scan_result.decls_len, | |
| 5625 | .captures = namespace.captures.keys(), | |
| 5626 | .capture_names = namespace.captures.values(), | |
| 5627 | .decls = @ptrCast(scratch.all().get(astgen)), | |
| 5762 | 5628 | }); |
| 5763 | 5629 | |
| 5764 | wip_members.finishBits(0); | |
| 5765 | const decls_slice = wip_members.declsSlice(); | |
| 5766 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len); | |
| 5767 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | |
| 5768 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); | |
| 5769 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | |
| 5770 | ||
| 5771 | 5630 | block_scope.unstack(); |
| 5772 | 5631 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5773 | 5632 | }, |
| ... | ... | @@ -5780,7 +5639,7 @@ const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField |
| 5780 | 5639 | fn containerMember( |
| 5781 | 5640 | gz: *GenZir, |
| 5782 | 5641 | scope: *Scope, |
| 5783 | wip_members: *WipMembers, | |
| 5642 | wip_decls: *WipDecls, | |
| 5784 | 5643 | member_node: Ast.Node.Index, |
| 5785 | 5644 | ) InnerError!ContainerMemberResult { |
| 5786 | 5645 | const astgen = gz.astgen; |
| ... | ... | @@ -5805,13 +5664,13 @@ fn containerMember( |
| 5805 | 5664 | else |
| 5806 | 5665 | .none; |
| 5807 | 5666 | |
| 5808 | const prev_decl_index = wip_members.decl_index; | |
| 5809 | astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) { | |
| 5667 | const prev_decl_index = wip_decls.index; | |
| 5668 | astgen.fnDecl(gz, scope, wip_decls, member_node, body, full) catch |err| switch (err) { | |
| 5810 | 5669 | error.OutOfMemory => return error.OutOfMemory, |
| 5811 | 5670 | error.AnalysisFail => { |
| 5812 | wip_members.decl_index = prev_decl_index; | |
| 5671 | wip_decls.index = prev_decl_index; | |
| 5813 | 5672 | try addFailedDeclaration( |
| 5814 | wip_members, | |
| 5673 | wip_decls, | |
| 5815 | 5674 | gz, |
| 5816 | 5675 | .@"const", |
| 5817 | 5676 | try astgen.identAsString(full.name_token.?), |
| ... | ... | @@ -5828,13 +5687,13 @@ fn containerMember( |
| 5828 | 5687 | .aligned_var_decl, |
| 5829 | 5688 | => { |
| 5830 | 5689 | const full = tree.fullVarDecl(member_node).?; |
| 5831 | const prev_decl_index = wip_members.decl_index; | |
| 5832 | astgen.globalVarDecl(gz, scope, wip_members, member_node, full) catch |err| switch (err) { | |
| 5690 | const prev_decl_index = wip_decls.index; | |
| 5691 | astgen.globalVarDecl(gz, scope, wip_decls, member_node, full) catch |err| switch (err) { | |
| 5833 | 5692 | error.OutOfMemory => return error.OutOfMemory, |
| 5834 | 5693 | error.AnalysisFail => { |
| 5835 | wip_members.decl_index = prev_decl_index; | |
| 5694 | wip_decls.index = prev_decl_index; | |
| 5836 | 5695 | try addFailedDeclaration( |
| 5837 | wip_members, | |
| 5696 | wip_decls, | |
| 5838 | 5697 | gz, |
| 5839 | 5698 | .@"const", // doesn't really matter |
| 5840 | 5699 | try astgen.identAsString(full.ast.mut_token + 1), |
| ... | ... | @@ -5846,13 +5705,13 @@ fn containerMember( |
| 5846 | 5705 | }, |
| 5847 | 5706 | |
| 5848 | 5707 | .@"comptime" => { |
| 5849 | const prev_decl_index = wip_members.decl_index; | |
| 5850 | astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { | |
| 5708 | const prev_decl_index = wip_decls.index; | |
| 5709 | astgen.comptimeDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { | |
| 5851 | 5710 | error.OutOfMemory => return error.OutOfMemory, |
| 5852 | 5711 | error.AnalysisFail => { |
| 5853 | wip_members.decl_index = prev_decl_index; | |
| 5712 | wip_decls.index = prev_decl_index; | |
| 5854 | 5713 | try addFailedDeclaration( |
| 5855 | wip_members, | |
| 5714 | wip_decls, | |
| 5856 | 5715 | gz, |
| 5857 | 5716 | .@"comptime", |
| 5858 | 5717 | .empty, |
| ... | ... | @@ -5863,16 +5722,16 @@ fn containerMember( |
| 5863 | 5722 | }; |
| 5864 | 5723 | }, |
| 5865 | 5724 | .test_decl => { |
| 5866 | const prev_decl_index = wip_members.decl_index; | |
| 5725 | const prev_decl_index = wip_decls.index; | |
| 5867 | 5726 | // We need to have *some* decl here so that the decl count matches what's expected. |
| 5868 | 5727 | // Since it doesn't strictly matter *what* this is, let's save ourselves the trouble |
| 5869 | 5728 | // of duplicating the test name logic, and just assume this is an unnamed test. |
| 5870 | astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { | |
| 5729 | astgen.testDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { | |
| 5871 | 5730 | error.OutOfMemory => return error.OutOfMemory, |
| 5872 | 5731 | error.AnalysisFail => { |
| 5873 | wip_members.decl_index = prev_decl_index; | |
| 5732 | wip_decls.index = prev_decl_index; | |
| 5874 | 5733 | try addFailedDeclaration( |
| 5875 | wip_members, | |
| 5734 | wip_decls, | |
| 5876 | 5735 | gz, |
| 5877 | 5736 | .unnamed_test, |
| 5878 | 5737 | .empty, |
| ... | ... | @@ -10619,482 +10478,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10619 | 10478 | } |
| 10620 | 10479 | } |
| 10621 | 10480 | |
| 10622 | /// Returns `true` if it is known the type expression has more than one possible value; | |
| 10623 | /// `false` otherwise. | |
| 10624 | fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { | |
| 10625 | var node = start_node; | |
| 10626 | while (true) { | |
| 10627 | switch (tree.nodeTag(node)) { | |
| 10628 | .root, | |
| 10629 | .test_decl, | |
| 10630 | .switch_case, | |
| 10631 | .switch_case_inline, | |
| 10632 | .switch_case_one, | |
| 10633 | .switch_case_inline_one, | |
| 10634 | .container_field_init, | |
| 10635 | .container_field_align, | |
| 10636 | .container_field, | |
| 10637 | .asm_output, | |
| 10638 | .asm_input, | |
| 10639 | .global_var_decl, | |
| 10640 | .local_var_decl, | |
| 10641 | .simple_var_decl, | |
| 10642 | .aligned_var_decl, | |
| 10643 | => unreachable, | |
| 10644 | ||
| 10645 | .@"return", | |
| 10646 | .@"break", | |
| 10647 | .@"continue", | |
| 10648 | .bit_not, | |
| 10649 | .bool_not, | |
| 10650 | .@"defer", | |
| 10651 | .@"errdefer", | |
| 10652 | .address_of, | |
| 10653 | .negation, | |
| 10654 | .negation_wrap, | |
| 10655 | .@"resume", | |
| 10656 | .array_type, | |
| 10657 | .@"suspend", | |
| 10658 | .fn_decl, | |
| 10659 | .anyframe_literal, | |
| 10660 | .number_literal, | |
| 10661 | .enum_literal, | |
| 10662 | .string_literal, | |
| 10663 | .multiline_string_literal, | |
| 10664 | .char_literal, | |
| 10665 | .unreachable_literal, | |
| 10666 | .error_set_decl, | |
| 10667 | .container_decl, | |
| 10668 | .container_decl_trailing, | |
| 10669 | .container_decl_two, | |
| 10670 | .container_decl_two_trailing, | |
| 10671 | .container_decl_arg, | |
| 10672 | .container_decl_arg_trailing, | |
| 10673 | .tagged_union, | |
| 10674 | .tagged_union_trailing, | |
| 10675 | .tagged_union_two, | |
| 10676 | .tagged_union_two_trailing, | |
| 10677 | .tagged_union_enum_tag, | |
| 10678 | .tagged_union_enum_tag_trailing, | |
| 10679 | .@"asm", | |
| 10680 | .asm_simple, | |
| 10681 | .add, | |
| 10682 | .add_wrap, | |
| 10683 | .add_sat, | |
| 10684 | .array_cat, | |
| 10685 | .array_mult, | |
| 10686 | .assign, | |
| 10687 | .assign_destructure, | |
| 10688 | .assign_bit_and, | |
| 10689 | .assign_bit_or, | |
| 10690 | .assign_shl, | |
| 10691 | .assign_shl_sat, | |
| 10692 | .assign_shr, | |
| 10693 | .assign_bit_xor, | |
| 10694 | .assign_div, | |
| 10695 | .assign_sub, | |
| 10696 | .assign_sub_wrap, | |
| 10697 | .assign_sub_sat, | |
| 10698 | .assign_mod, | |
| 10699 | .assign_add, | |
| 10700 | .assign_add_wrap, | |
| 10701 | .assign_add_sat, | |
| 10702 | .assign_mul, | |
| 10703 | .assign_mul_wrap, | |
| 10704 | .assign_mul_sat, | |
| 10705 | .bang_equal, | |
| 10706 | .bit_and, | |
| 10707 | .bit_or, | |
| 10708 | .shl, | |
| 10709 | .shl_sat, | |
| 10710 | .shr, | |
| 10711 | .bit_xor, | |
| 10712 | .bool_and, | |
| 10713 | .bool_or, | |
| 10714 | .div, | |
| 10715 | .equal_equal, | |
| 10716 | .error_union, | |
| 10717 | .greater_or_equal, | |
| 10718 | .greater_than, | |
| 10719 | .less_or_equal, | |
| 10720 | .less_than, | |
| 10721 | .merge_error_sets, | |
| 10722 | .mod, | |
| 10723 | .mul, | |
| 10724 | .mul_wrap, | |
| 10725 | .mul_sat, | |
| 10726 | .switch_range, | |
| 10727 | .for_range, | |
| 10728 | .field_access, | |
| 10729 | .sub, | |
| 10730 | .sub_wrap, | |
| 10731 | .sub_sat, | |
| 10732 | .slice, | |
| 10733 | .slice_open, | |
| 10734 | .slice_sentinel, | |
| 10735 | .deref, | |
| 10736 | .array_access, | |
| 10737 | .error_value, | |
| 10738 | .while_simple, | |
| 10739 | .while_cont, | |
| 10740 | .for_simple, | |
| 10741 | .if_simple, | |
| 10742 | .@"catch", | |
| 10743 | .@"orelse", | |
| 10744 | .array_init_one, | |
| 10745 | .array_init_one_comma, | |
| 10746 | .array_init_dot_two, | |
| 10747 | .array_init_dot_two_comma, | |
| 10748 | .array_init_dot, | |
| 10749 | .array_init_dot_comma, | |
| 10750 | .array_init, | |
| 10751 | .array_init_comma, | |
| 10752 | .struct_init_one, | |
| 10753 | .struct_init_one_comma, | |
| 10754 | .struct_init_dot_two, | |
| 10755 | .struct_init_dot_two_comma, | |
| 10756 | .struct_init_dot, | |
| 10757 | .struct_init_dot_comma, | |
| 10758 | .struct_init, | |
| 10759 | .struct_init_comma, | |
| 10760 | .@"while", | |
| 10761 | .@"if", | |
| 10762 | .@"for", | |
| 10763 | .@"switch", | |
| 10764 | .switch_comma, | |
| 10765 | .call_one, | |
| 10766 | .call_one_comma, | |
| 10767 | .call, | |
| 10768 | .call_comma, | |
| 10769 | .block_two, | |
| 10770 | .block_two_semicolon, | |
| 10771 | .block, | |
| 10772 | .block_semicolon, | |
| 10773 | .builtin_call, | |
| 10774 | .builtin_call_comma, | |
| 10775 | .builtin_call_two, | |
| 10776 | .builtin_call_two_comma, | |
| 10777 | // these are function bodies, not pointers | |
| 10778 | .fn_proto_simple, | |
| 10779 | .fn_proto_multi, | |
| 10780 | .fn_proto_one, | |
| 10781 | .fn_proto, | |
| 10782 | => return false, | |
| 10783 | ||
| 10784 | // Forward the question to the LHS sub-expression. | |
| 10785 | .@"try", | |
| 10786 | .@"comptime", | |
| 10787 | .@"nosuspend", | |
| 10788 | => node = tree.nodeData(node).node, | |
| 10789 | .grouped_expression, | |
| 10790 | .unwrap_optional, | |
| 10791 | => node = tree.nodeData(node).node_and_token[0], | |
| 10792 | ||
| 10793 | .ptr_type_aligned, | |
| 10794 | .ptr_type_sentinel, | |
| 10795 | .ptr_type, | |
| 10796 | .ptr_type_bit_range, | |
| 10797 | .optional_type, | |
| 10798 | .anyframe_type, | |
| 10799 | .array_type_sentinel, | |
| 10800 | => return true, | |
| 10801 | ||
| 10802 | .identifier => { | |
| 10803 | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); | |
| 10804 | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { | |
| 10805 | .anyerror_type, | |
| 10806 | .anyframe_type, | |
| 10807 | .anyopaque_type, | |
| 10808 | .bool_type, | |
| 10809 | .c_int_type, | |
| 10810 | .c_long_type, | |
| 10811 | .c_longdouble_type, | |
| 10812 | .c_longlong_type, | |
| 10813 | .c_char_type, | |
| 10814 | .c_short_type, | |
| 10815 | .c_uint_type, | |
| 10816 | .c_ulong_type, | |
| 10817 | .c_ulonglong_type, | |
| 10818 | .c_ushort_type, | |
| 10819 | .comptime_float_type, | |
| 10820 | .comptime_int_type, | |
| 10821 | .f16_type, | |
| 10822 | .f32_type, | |
| 10823 | .f64_type, | |
| 10824 | .f80_type, | |
| 10825 | .f128_type, | |
| 10826 | .i16_type, | |
| 10827 | .i32_type, | |
| 10828 | .i64_type, | |
| 10829 | .i128_type, | |
| 10830 | .i8_type, | |
| 10831 | .isize_type, | |
| 10832 | .type_type, | |
| 10833 | .u16_type, | |
| 10834 | .u29_type, | |
| 10835 | .u32_type, | |
| 10836 | .u64_type, | |
| 10837 | .u128_type, | |
| 10838 | .u1_type, | |
| 10839 | .u8_type, | |
| 10840 | .usize_type, | |
| 10841 | => return true, | |
| 10842 | ||
| 10843 | .void_type, | |
| 10844 | .bool_false, | |
| 10845 | .bool_true, | |
| 10846 | .null_value, | |
| 10847 | .undef, | |
| 10848 | .noreturn_type, | |
| 10849 | => return false, | |
| 10850 | ||
| 10851 | else => unreachable, // that's all the values from `primitives`. | |
| 10852 | } else { | |
| 10853 | return false; | |
| 10854 | } | |
| 10855 | }, | |
| 10856 | } | |
| 10857 | } | |
| 10858 | } | |
| 10859 | ||
| 10860 | /// Returns `true` if it is known the expression is a type that cannot be used at runtime; | |
| 10861 | /// `false` otherwise. | |
| 10862 | fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { | |
| 10863 | var node = start_node; | |
| 10864 | while (true) { | |
| 10865 | switch (tree.nodeTag(node)) { | |
| 10866 | .root, | |
| 10867 | .test_decl, | |
| 10868 | .switch_case, | |
| 10869 | .switch_case_inline, | |
| 10870 | .switch_case_one, | |
| 10871 | .switch_case_inline_one, | |
| 10872 | .container_field_init, | |
| 10873 | .container_field_align, | |
| 10874 | .container_field, | |
| 10875 | .asm_output, | |
| 10876 | .asm_input, | |
| 10877 | .global_var_decl, | |
| 10878 | .local_var_decl, | |
| 10879 | .simple_var_decl, | |
| 10880 | .aligned_var_decl, | |
| 10881 | => unreachable, | |
| 10882 | ||
| 10883 | .@"return", | |
| 10884 | .@"break", | |
| 10885 | .@"continue", | |
| 10886 | .bit_not, | |
| 10887 | .bool_not, | |
| 10888 | .@"defer", | |
| 10889 | .@"errdefer", | |
| 10890 | .address_of, | |
| 10891 | .negation, | |
| 10892 | .negation_wrap, | |
| 10893 | .@"resume", | |
| 10894 | .array_type, | |
| 10895 | .@"suspend", | |
| 10896 | .fn_decl, | |
| 10897 | .anyframe_literal, | |
| 10898 | .number_literal, | |
| 10899 | .enum_literal, | |
| 10900 | .string_literal, | |
| 10901 | .multiline_string_literal, | |
| 10902 | .char_literal, | |
| 10903 | .unreachable_literal, | |
| 10904 | .error_set_decl, | |
| 10905 | .container_decl, | |
| 10906 | .container_decl_trailing, | |
| 10907 | .container_decl_two, | |
| 10908 | .container_decl_two_trailing, | |
| 10909 | .container_decl_arg, | |
| 10910 | .container_decl_arg_trailing, | |
| 10911 | .tagged_union, | |
| 10912 | .tagged_union_trailing, | |
| 10913 | .tagged_union_two, | |
| 10914 | .tagged_union_two_trailing, | |
| 10915 | .tagged_union_enum_tag, | |
| 10916 | .tagged_union_enum_tag_trailing, | |
| 10917 | .@"asm", | |
| 10918 | .asm_simple, | |
| 10919 | .add, | |
| 10920 | .add_wrap, | |
| 10921 | .add_sat, | |
| 10922 | .array_cat, | |
| 10923 | .array_mult, | |
| 10924 | .assign, | |
| 10925 | .assign_destructure, | |
| 10926 | .assign_bit_and, | |
| 10927 | .assign_bit_or, | |
| 10928 | .assign_shl, | |
| 10929 | .assign_shl_sat, | |
| 10930 | .assign_shr, | |
| 10931 | .assign_bit_xor, | |
| 10932 | .assign_div, | |
| 10933 | .assign_sub, | |
| 10934 | .assign_sub_wrap, | |
| 10935 | .assign_sub_sat, | |
| 10936 | .assign_mod, | |
| 10937 | .assign_add, | |
| 10938 | .assign_add_wrap, | |
| 10939 | .assign_add_sat, | |
| 10940 | .assign_mul, | |
| 10941 | .assign_mul_wrap, | |
| 10942 | .assign_mul_sat, | |
| 10943 | .bang_equal, | |
| 10944 | .bit_and, | |
| 10945 | .bit_or, | |
| 10946 | .shl, | |
| 10947 | .shl_sat, | |
| 10948 | .shr, | |
| 10949 | .bit_xor, | |
| 10950 | .bool_and, | |
| 10951 | .bool_or, | |
| 10952 | .div, | |
| 10953 | .equal_equal, | |
| 10954 | .error_union, | |
| 10955 | .greater_or_equal, | |
| 10956 | .greater_than, | |
| 10957 | .less_or_equal, | |
| 10958 | .less_than, | |
| 10959 | .merge_error_sets, | |
| 10960 | .mod, | |
| 10961 | .mul, | |
| 10962 | .mul_wrap, | |
| 10963 | .mul_sat, | |
| 10964 | .switch_range, | |
| 10965 | .for_range, | |
| 10966 | .field_access, | |
| 10967 | .sub, | |
| 10968 | .sub_wrap, | |
| 10969 | .sub_sat, | |
| 10970 | .slice, | |
| 10971 | .slice_open, | |
| 10972 | .slice_sentinel, | |
| 10973 | .deref, | |
| 10974 | .array_access, | |
| 10975 | .error_value, | |
| 10976 | .while_simple, | |
| 10977 | .while_cont, | |
| 10978 | .for_simple, | |
| 10979 | .if_simple, | |
| 10980 | .@"catch", | |
| 10981 | .@"orelse", | |
| 10982 | .array_init_one, | |
| 10983 | .array_init_one_comma, | |
| 10984 | .array_init_dot_two, | |
| 10985 | .array_init_dot_two_comma, | |
| 10986 | .array_init_dot, | |
| 10987 | .array_init_dot_comma, | |
| 10988 | .array_init, | |
| 10989 | .array_init_comma, | |
| 10990 | .struct_init_one, | |
| 10991 | .struct_init_one_comma, | |
| 10992 | .struct_init_dot_two, | |
| 10993 | .struct_init_dot_two_comma, | |
| 10994 | .struct_init_dot, | |
| 10995 | .struct_init_dot_comma, | |
| 10996 | .struct_init, | |
| 10997 | .struct_init_comma, | |
| 10998 | .@"while", | |
| 10999 | .@"if", | |
| 11000 | .@"for", | |
| 11001 | .@"switch", | |
| 11002 | .switch_comma, | |
| 11003 | .call_one, | |
| 11004 | .call_one_comma, | |
| 11005 | .call, | |
| 11006 | .call_comma, | |
| 11007 | .block_two, | |
| 11008 | .block_two_semicolon, | |
| 11009 | .block, | |
| 11010 | .block_semicolon, | |
| 11011 | .builtin_call, | |
| 11012 | .builtin_call_comma, | |
| 11013 | .builtin_call_two, | |
| 11014 | .builtin_call_two_comma, | |
| 11015 | .ptr_type_aligned, | |
| 11016 | .ptr_type_sentinel, | |
| 11017 | .ptr_type, | |
| 11018 | .ptr_type_bit_range, | |
| 11019 | .optional_type, | |
| 11020 | .anyframe_type, | |
| 11021 | .array_type_sentinel, | |
| 11022 | => return false, | |
| 11023 | ||
| 11024 | // these are function bodies, not pointers | |
| 11025 | .fn_proto_simple, | |
| 11026 | .fn_proto_multi, | |
| 11027 | .fn_proto_one, | |
| 11028 | .fn_proto, | |
| 11029 | => return true, | |
| 11030 | ||
| 11031 | // Forward the question to the LHS sub-expression. | |
| 11032 | .@"try", | |
| 11033 | .@"comptime", | |
| 11034 | .@"nosuspend", | |
| 11035 | => node = tree.nodeData(node).node, | |
| 11036 | .grouped_expression, | |
| 11037 | .unwrap_optional, | |
| 11038 | => node = tree.nodeData(node).node_and_token[0], | |
| 11039 | ||
| 11040 | .identifier => { | |
| 11041 | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); | |
| 11042 | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { | |
| 11043 | .anyerror_type, | |
| 11044 | .anyframe_type, | |
| 11045 | .anyopaque_type, | |
| 11046 | .bool_type, | |
| 11047 | .c_int_type, | |
| 11048 | .c_long_type, | |
| 11049 | .c_longdouble_type, | |
| 11050 | .c_longlong_type, | |
| 11051 | .c_char_type, | |
| 11052 | .c_short_type, | |
| 11053 | .c_uint_type, | |
| 11054 | .c_ulong_type, | |
| 11055 | .c_ulonglong_type, | |
| 11056 | .c_ushort_type, | |
| 11057 | .f16_type, | |
| 11058 | .f32_type, | |
| 11059 | .f64_type, | |
| 11060 | .f80_type, | |
| 11061 | .f128_type, | |
| 11062 | .i16_type, | |
| 11063 | .i32_type, | |
| 11064 | .i64_type, | |
| 11065 | .i128_type, | |
| 11066 | .i8_type, | |
| 11067 | .isize_type, | |
| 11068 | .u16_type, | |
| 11069 | .u29_type, | |
| 11070 | .u32_type, | |
| 11071 | .u64_type, | |
| 11072 | .u128_type, | |
| 11073 | .u1_type, | |
| 11074 | .u8_type, | |
| 11075 | .usize_type, | |
| 11076 | .void_type, | |
| 11077 | .bool_false, | |
| 11078 | .bool_true, | |
| 11079 | .null_value, | |
| 11080 | .undef, | |
| 11081 | .noreturn_type, | |
| 11082 | => return false, | |
| 11083 | ||
| 11084 | .comptime_float_type, | |
| 11085 | .comptime_int_type, | |
| 11086 | .type_type, | |
| 11087 | => return true, | |
| 11088 | ||
| 11089 | else => unreachable, // that's all the values from `primitives`. | |
| 11090 | } else { | |
| 11091 | return false; | |
| 11092 | } | |
| 11093 | }, | |
| 11094 | } | |
| 11095 | } | |
| 11096 | } | |
| 11097 | ||
| 11098 | 10481 | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of |
| 11099 | 10482 | /// result locations must call this function on their result. |
| 11100 | 10483 | /// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer. |
| ... | ... | @@ -13044,18 +12427,19 @@ const GenZir = struct { |
| 13044 | 12427 | |
| 13045 | 12428 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13046 | 12429 | src_node: Ast.Node.Index, |
| 13047 | captures_len: u32, | |
| 13048 | fields_len: u32, | |
| 13049 | decls_len: u32, | |
| 13050 | has_backing_int: bool, | |
| 12430 | name_strat: Zir.Inst.NameStrategy, | |
| 13051 | 12431 | layout: std.builtin.Type.ContainerLayout, |
| 13052 | known_non_opv: bool, | |
| 13053 | known_comptime_only: bool, | |
| 12432 | backing_int_type_body_len: ?u32, | |
| 12433 | decls_len: u32, | |
| 12434 | fields_len: u32, | |
| 12435 | any_field_aligns: bool, | |
| 12436 | any_field_defaults: bool, | |
| 13054 | 12437 | any_comptime_fields: bool, |
| 13055 | any_default_inits: bool, | |
| 13056 | any_aligned_fields: bool, | |
| 13057 | 12438 | fields_hash: std.zig.SrcHash, |
| 13058 | name_strat: Zir.Inst.NameStrategy, | |
| 12439 | captures: []const Zir.Inst.Capture, | |
| 12440 | capture_names: []const Zir.NullTerminatedString, | |
| 12441 | /// The trailing declaration list, field information, and body instructions. | |
| 12442 | remaining: []const u32, | |
| 13059 | 12443 | }) !void { |
| 13060 | 12444 | const astgen = gz.astgen; |
| 13061 | 12445 | const gpa = astgen.gpa; |
| ... | ... | @@ -13063,9 +12447,16 @@ const GenZir = struct { |
| 13063 | 12447 | // Node .root is valid for the root `struct_decl` of a file! |
| 13064 | 12448 | assert(args.src_node != .root or gz.parent.tag == .top); |
| 13065 | 12449 | |
| 12450 | const captures_len: u32 = @intCast(args.captures.len); | |
| 12451 | assert(args.capture_names.len == captures_len); | |
| 12452 | ||
| 13066 | 12453 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13067 | 12454 | |
| 13068 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + 3); | |
| 12455 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + | |
| 12456 | 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type_body_len` | |
| 12457 | captures_len * 2 + // `capture`, `capture_name` | |
| 12458 | args.remaining.len); | |
| 12459 | ||
| 13069 | 12460 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ |
| 13070 | 12461 | .fields_hash_0 = fields_hash_arr[0], |
| 13071 | 12462 | .fields_hash_1 = fields_hash_arr[1], |
| ... | ... | @@ -13075,31 +12466,28 @@ const GenZir = struct { |
| 13075 | 12466 | .src_node = args.src_node, |
| 13076 | 12467 | }); |
| 13077 | 12468 | |
| 13078 | if (args.captures_len != 0) { | |
| 13079 | astgen.extra.appendAssumeCapacity(args.captures_len); | |
| 13080 | } | |
| 13081 | if (args.fields_len != 0) { | |
| 13082 | astgen.extra.appendAssumeCapacity(args.fields_len); | |
| 13083 | } | |
| 13084 | if (args.decls_len != 0) { | |
| 13085 | astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 13086 | } | |
| 12469 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); | |
| 12470 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 12471 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); | |
| 12472 | if (args.backing_int_type_body_len) |n| astgen.extra.appendAssumeCapacity(n); | |
| 12473 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); | |
| 12474 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); | |
| 12475 | astgen.extra.appendSliceAssumeCapacity(args.remaining); | |
| 12476 | ||
| 13087 | 12477 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13088 | 12478 | .tag = .extended, |
| 13089 | 12479 | .data = .{ .extended = .{ |
| 13090 | 12480 | .opcode = .struct_decl, |
| 13091 | 12481 | .small = @bitCast(Zir.Inst.StructDecl.Small{ |
| 13092 | .has_captures_len = args.captures_len != 0, | |
| 13093 | .has_fields_len = args.fields_len != 0, | |
| 12482 | .has_captures_len = captures_len != 0, | |
| 13094 | 12483 | .has_decls_len = args.decls_len != 0, |
| 13095 | .has_backing_int = args.has_backing_int, | |
| 13096 | .known_non_opv = args.known_non_opv, | |
| 13097 | .known_comptime_only = args.known_comptime_only, | |
| 12484 | .has_fields_len = args.fields_len != 0, | |
| 13098 | 12485 | .name_strategy = args.name_strat, |
| 13099 | 12486 | .layout = args.layout, |
| 12487 | .has_backing_int_type = args.backing_int_type_body_len != null, | |
| 12488 | .any_field_aligns = args.any_field_aligns, | |
| 12489 | .any_field_defaults = args.any_field_defaults, | |
| 13100 | 12490 | .any_comptime_fields = args.any_comptime_fields, |
| 13101 | .any_default_inits = args.any_default_inits, | |
| 13102 | .any_aligned_fields = args.any_aligned_fields, | |
| 13103 | 12491 | }), |
| 13104 | 12492 | .operand = payload_index, |
| 13105 | 12493 | } }, |
| ... | ... | @@ -13108,25 +12496,34 @@ const GenZir = struct { |
| 13108 | 12496 | |
| 13109 | 12497 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13110 | 12498 | src_node: Ast.Node.Index, |
| 13111 | tag_type: Zir.Inst.Ref, | |
| 13112 | captures_len: u32, | |
| 13113 | body_len: u32, | |
| 13114 | fields_len: u32, | |
| 12499 | name_strat: Zir.Inst.NameStrategy, | |
| 12500 | kind: Zir.Inst.UnionDecl.Kind, | |
| 12501 | arg_type_body_len: ?u32, | |
| 13115 | 12502 | decls_len: u32, |
| 13116 | layout: std.builtin.Type.ContainerLayout, | |
| 13117 | auto_enum_tag: bool, | |
| 13118 | any_aligned_fields: bool, | |
| 12503 | fields_len: u32, | |
| 12504 | any_field_aligns: bool, | |
| 12505 | any_field_values: bool, | |
| 13119 | 12506 | fields_hash: std.zig.SrcHash, |
| 13120 | name_strat: Zir.Inst.NameStrategy, | |
| 12507 | captures: []const Zir.Inst.Capture, | |
| 12508 | capture_names: []const Zir.NullTerminatedString, | |
| 12509 | /// The trailing declaration list, field information, and body instructions. | |
| 12510 | remaining: []const u32, | |
| 13121 | 12511 | }) !void { |
| 13122 | 12512 | const astgen = gz.astgen; |
| 13123 | 12513 | const gpa = astgen.gpa; |
| 13124 | 12514 | |
| 13125 | 12515 | assert(args.src_node != .root); |
| 13126 | 12516 | |
| 12517 | const captures_len: u32 = @intCast(args.captures.len); | |
| 12518 | assert(args.capture_names.len == captures_len); | |
| 12519 | ||
| 13127 | 12520 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13128 | 12521 | |
| 13129 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + 5); | |
| 12522 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + | |
| 12523 | 4 + // `captures_len`, `decls_len`, `fields_len`, `arg_type_body_len` | |
| 12524 | captures_len * 2 + // `capture`, `capture_name` | |
| 12525 | args.remaining.len); | |
| 12526 | ||
| 13130 | 12527 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ |
| 13131 | 12528 | .fields_hash_0 = fields_hash_arr[0], |
| 13132 | 12529 | .fields_hash_1 = fields_hash_arr[1], |
| ... | ... | @@ -13136,35 +12533,30 @@ const GenZir = struct { |
| 13136 | 12533 | .src_node = args.src_node, |
| 13137 | 12534 | }); |
| 13138 | 12535 | |
| 13139 | if (args.tag_type != .none) { | |
| 13140 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | |
| 13141 | } | |
| 13142 | if (args.captures_len != 0) { | |
| 13143 | astgen.extra.appendAssumeCapacity(args.captures_len); | |
| 13144 | } | |
| 13145 | if (args.body_len != 0) { | |
| 13146 | astgen.extra.appendAssumeCapacity(args.body_len); | |
| 13147 | } | |
| 13148 | if (args.fields_len != 0) { | |
| 13149 | astgen.extra.appendAssumeCapacity(args.fields_len); | |
| 13150 | } | |
| 13151 | if (args.decls_len != 0) { | |
| 13152 | astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 12536 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); | |
| 12537 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 12538 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); | |
| 12539 | if (args.kind.hasArgType()) { | |
| 12540 | astgen.extra.appendAssumeCapacity(args.arg_type_body_len.?); | |
| 12541 | } else { | |
| 12542 | assert(args.arg_type_body_len == null); | |
| 13153 | 12543 | } |
| 12544 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); | |
| 12545 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); | |
| 12546 | astgen.extra.appendSliceAssumeCapacity(args.remaining); | |
| 12547 | ||
| 13154 | 12548 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13155 | 12549 | .tag = .extended, |
| 13156 | 12550 | .data = .{ .extended = .{ |
| 13157 | 12551 | .opcode = .union_decl, |
| 13158 | 12552 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ |
| 13159 | .has_tag_type = args.tag_type != .none, | |
| 13160 | .has_captures_len = args.captures_len != 0, | |
| 13161 | .has_body_len = args.body_len != 0, | |
| 13162 | .has_fields_len = args.fields_len != 0, | |
| 12553 | .has_captures_len = captures_len != 0, | |
| 13163 | 12554 | .has_decls_len = args.decls_len != 0, |
| 12555 | .has_fields_len = args.fields_len != 0, | |
| 13164 | 12556 | .name_strategy = args.name_strat, |
| 13165 | .layout = args.layout, | |
| 13166 | .auto_enum_tag = args.auto_enum_tag, | |
| 13167 | .any_aligned_fields = args.any_aligned_fields, | |
| 12557 | .kind = args.kind, | |
| 12558 | .any_field_aligns = args.any_field_aligns, | |
| 12559 | .any_field_values = args.any_field_values, | |
| 13168 | 12560 | }), |
| 13169 | 12561 | .operand = payload_index, |
| 13170 | 12562 | } }, |
| ... | ... | @@ -13173,23 +12565,33 @@ const GenZir = struct { |
| 13173 | 12565 | |
| 13174 | 12566 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13175 | 12567 | src_node: Ast.Node.Index, |
| 13176 | tag_type: Zir.Inst.Ref, | |
| 13177 | captures_len: u32, | |
| 13178 | body_len: u32, | |
| 13179 | fields_len: u32, | |
| 13180 | decls_len: u32, | |
| 12568 | name_strat: Zir.Inst.NameStrategy, | |
| 12569 | tag_type_body_len: ?u32, | |
| 13181 | 12570 | nonexhaustive: bool, |
| 12571 | decls_len: u32, | |
| 12572 | fields_len: u32, | |
| 12573 | any_field_values: bool, | |
| 13182 | 12574 | fields_hash: std.zig.SrcHash, |
| 13183 | name_strat: Zir.Inst.NameStrategy, | |
| 12575 | captures: []const Zir.Inst.Capture, | |
| 12576 | capture_names: []const Zir.NullTerminatedString, | |
| 12577 | /// The trailing declaration list, field information, and body instructions. | |
| 12578 | remaining: []const u32, | |
| 13184 | 12579 | }) !void { |
| 13185 | 12580 | const astgen = gz.astgen; |
| 13186 | 12581 | const gpa = astgen.gpa; |
| 13187 | 12582 | |
| 13188 | 12583 | assert(args.src_node != .root); |
| 13189 | 12584 | |
| 12585 | const captures_len: u32 = @intCast(args.captures.len); | |
| 12586 | assert(args.capture_names.len == captures_len); | |
| 12587 | ||
| 13190 | 12588 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13191 | 12589 | |
| 13192 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + 5); | |
| 12590 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + | |
| 12591 | 4 + // `captures_len`, `decls_len`, `fields_len`, `tag_type_body_len` | |
| 12592 | captures_len * 2 + // `capture`, `capture_name` | |
| 12593 | args.remaining.len); | |
| 12594 | ||
| 13193 | 12595 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ |
| 13194 | 12596 | .fields_hash_0 = fields_hash_arr[0], |
| 13195 | 12597 | .fields_hash_1 = fields_hash_arr[1], |
| ... | ... | @@ -13199,33 +12601,26 @@ const GenZir = struct { |
| 13199 | 12601 | .src_node = args.src_node, |
| 13200 | 12602 | }); |
| 13201 | 12603 | |
| 13202 | if (args.tag_type != .none) { | |
| 13203 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | |
| 13204 | } | |
| 13205 | if (args.captures_len != 0) { | |
| 13206 | astgen.extra.appendAssumeCapacity(args.captures_len); | |
| 13207 | } | |
| 13208 | if (args.body_len != 0) { | |
| 13209 | astgen.extra.appendAssumeCapacity(args.body_len); | |
| 13210 | } | |
| 13211 | if (args.fields_len != 0) { | |
| 13212 | astgen.extra.appendAssumeCapacity(args.fields_len); | |
| 13213 | } | |
| 13214 | if (args.decls_len != 0) { | |
| 13215 | astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 13216 | } | |
| 12604 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); | |
| 12605 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 12606 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); | |
| 12607 | if (args.tag_type_body_len) |n| astgen.extra.appendAssumeCapacity(n); | |
| 12608 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); | |
| 12609 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); | |
| 12610 | astgen.extra.appendSliceAssumeCapacity(args.remaining); | |
| 12611 | ||
| 13217 | 12612 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13218 | 12613 | .tag = .extended, |
| 13219 | 12614 | .data = .{ .extended = .{ |
| 13220 | 12615 | .opcode = .enum_decl, |
| 13221 | 12616 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ |
| 13222 | .has_tag_type = args.tag_type != .none, | |
| 13223 | .has_captures_len = args.captures_len != 0, | |
| 13224 | .has_body_len = args.body_len != 0, | |
| 13225 | .has_fields_len = args.fields_len != 0, | |
| 12617 | .has_captures_len = captures_len != 0, | |
| 13226 | 12618 | .has_decls_len = args.decls_len != 0, |
| 12619 | .has_fields_len = args.fields_len != 0, | |
| 13227 | 12620 | .name_strategy = args.name_strat, |
| 12621 | .has_tag_type = args.tag_type_body_len != null, | |
| 13228 | 12622 | .nonexhaustive = args.nonexhaustive, |
| 12623 | .any_field_values = args.any_field_values, | |
| 13229 | 12624 | }), |
| 13230 | 12625 | .operand = payload_index, |
| 13231 | 12626 | } }, |
| ... | ... | @@ -13234,33 +12629,41 @@ const GenZir = struct { |
| 13234 | 12629 | |
| 13235 | 12630 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13236 | 12631 | src_node: Ast.Node.Index, |
| 13237 | captures_len: u32, | |
| 13238 | decls_len: u32, | |
| 13239 | 12632 | name_strat: Zir.Inst.NameStrategy, |
| 12633 | decls_len: u32, | |
| 12634 | captures: []const Zir.Inst.Capture, | |
| 12635 | capture_names: []const Zir.NullTerminatedString, | |
| 12636 | decls: []const Zir.Inst.Index, | |
| 13240 | 12637 | }) !void { |
| 13241 | 12638 | const astgen = gz.astgen; |
| 13242 | 12639 | const gpa = astgen.gpa; |
| 13243 | 12640 | |
| 13244 | 12641 | assert(args.src_node != .root); |
| 13245 | 12642 | |
| 13246 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2); | |
| 12643 | const captures_len: u32 = @intCast(args.captures.len); | |
| 12644 | assert(args.capture_names.len == captures_len); | |
| 12645 | ||
| 12646 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + | |
| 12647 | 2 + // `captures_len`, `decls_len` | |
| 12648 | captures_len * 2 + // `capture`, `capture_name` | |
| 12649 | args.decls.len); | |
| 12650 | ||
| 13247 | 12651 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| 13248 | 12652 | .src_line = astgen.source_line, |
| 13249 | 12653 | .src_node = args.src_node, |
| 13250 | 12654 | }); |
| 12655 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); | |
| 12656 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 12657 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); | |
| 12658 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); | |
| 12659 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.decls)); | |
| 13251 | 12660 | |
| 13252 | if (args.captures_len != 0) { | |
| 13253 | astgen.extra.appendAssumeCapacity(args.captures_len); | |
| 13254 | } | |
| 13255 | if (args.decls_len != 0) { | |
| 13256 | astgen.extra.appendAssumeCapacity(args.decls_len); | |
| 13257 | } | |
| 13258 | 12661 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13259 | 12662 | .tag = .extended, |
| 13260 | 12663 | .data = .{ .extended = .{ |
| 13261 | 12664 | .opcode = .opaque_decl, |
| 13262 | 12665 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ |
| 13263 | .has_captures_len = args.captures_len != 0, | |
| 12666 | .has_captures_len = captures_len != 0, | |
| 13264 | 12667 | .has_decls_len = args.decls_len != 0, |
| 13265 | 12668 | .name_strategy = args.name_strat, |
| 13266 | 12669 | }), |
| ... | ... | @@ -13484,14 +12887,24 @@ fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void { |
| 13484 | 12887 | astgen.source_column = cursor.column; |
| 13485 | 12888 | } |
| 13486 | 12889 | |
| 12890 | const ScanContainerResult = struct { | |
| 12891 | /// Includes unnamed declarations (e.g. `comptime` decls) | |
| 12892 | decls_len: u32, | |
| 12893 | fields_len: u32, | |
| 12894 | any_field_aligns: bool, | |
| 12895 | any_field_values: bool, | |
| 12896 | any_comptime_fields: bool, | |
| 12897 | /// Whether there is a field named `_` (indicating a non-exhaustive enum) | |
| 12898 | has_underscore_field: bool, | |
| 12899 | }; | |
| 12900 | ||
| 13487 | 12901 | /// Detects name conflicts for decls and fields, and populates `namespace.decls` with all named declarations. |
| 13488 | /// Returns the number of declarations in the namespace, including unnamed declarations (e.g. `comptime` decls). | |
| 13489 | 12902 | fn scanContainer( |
| 13490 | 12903 | astgen: *AstGen, |
| 13491 | 12904 | namespace: *Scope.Namespace, |
| 13492 | 12905 | members: []const Ast.Node.Index, |
| 13493 | 12906 | container_kind: enum { @"struct", @"union", @"enum", @"opaque" }, |
| 13494 | ) !u32 { | |
| 12907 | ) !ScanContainerResult { | |
| 13495 | 12908 | const gpa = astgen.gpa; |
| 13496 | 12909 | const tree = astgen.tree; |
| 13497 | 12910 | |
| ... | ... | @@ -13521,6 +12934,10 @@ fn scanContainer( |
| 13521 | 12934 | |
| 13522 | 12935 | var any_duplicates = false; |
| 13523 | 12936 | var decl_count: u32 = 0; |
| 12937 | var any_field_aligns = false; | |
| 12938 | var any_field_values = false; | |
| 12939 | var any_comptime_fields = false; | |
| 12940 | var has_underscore_field = false; | |
| 13524 | 12941 | for (members) |member_node| { |
| 13525 | 12942 | const Kind = enum { decl, field }; |
| 13526 | 12943 | const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { |
| ... | ... | @@ -13533,6 +12950,10 @@ fn scanContainer( |
| 13533 | 12950 | .@"struct", .@"opaque" => {}, |
| 13534 | 12951 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), |
| 13535 | 12952 | } |
| 12953 | if (full.ast.align_expr != .none) any_field_aligns = true; | |
| 12954 | if (full.ast.value_expr != .none) any_field_values = true; | |
| 12955 | if (full.comptime_token != null) any_comptime_fields = true; | |
| 12956 | if (mem.eql(u8, tree.tokenSlice(full.ast.main_token), "_")) has_underscore_field = true; | |
| 13536 | 12957 | if (full.ast.tuple_like) continue; |
| 13537 | 12958 | break :blk .{ .field, full.ast.main_token }; |
| 13538 | 12959 | }, |
| ... | ... | @@ -13698,7 +13119,14 @@ fn scanContainer( |
| 13698 | 13119 | |
| 13699 | 13120 | if (!any_duplicates) { |
| 13700 | 13121 | if (any_invalid_declarations) return error.AnalysisFail; |
| 13701 | return decl_count; | |
| 13122 | return .{ | |
| 13123 | .decls_len = decl_count, | |
| 13124 | .fields_len = @intCast(members.len - decl_count), | |
| 13125 | .any_field_aligns = any_field_aligns, | |
| 13126 | .any_field_values = any_field_values, | |
| 13127 | .any_comptime_fields = any_comptime_fields, | |
| 13128 | .has_underscore_field = has_underscore_field, | |
| 13129 | }; | |
| 13702 | 13130 | } |
| 13703 | 13131 | |
| 13704 | 13132 | for (names.keys(), names.values()) |name, first| { |
| ... | ... | @@ -13954,7 +13382,7 @@ const DeclarationName = union(enum) { |
| 13954 | 13382 | }; |
| 13955 | 13383 | |
| 13956 | 13384 | fn addFailedDeclaration( |
| 13957 | wip_members: *WipMembers, | |
| 13385 | wip_decls: *WipDecls, | |
| 13958 | 13386 | gz: *GenZir, |
| 13959 | 13387 | kind: Zir.Inst.Declaration.Unwrapped.Kind, |
| 13960 | 13388 | name: Zir.NullTerminatedString, |
| ... | ... | @@ -13962,7 +13390,7 @@ fn addFailedDeclaration( |
| 13962 | 13390 | is_pub: bool, |
| 13963 | 13391 | ) !void { |
| 13964 | 13392 | const decl_inst = try gz.makeDeclaration(src_node); |
| 13965 | wip_members.nextDecl(decl_inst); | |
| 13393 | wip_decls.nextDecl(decl_inst); | |
| 13966 | 13394 | |
| 13967 | 13395 | var dummy_gz = gz.makeSubBlock(&gz.base); |
| 13968 | 13396 |
lib/std/zig/ErrorBundle.zig+10-6| ... | ... | @@ -243,12 +243,14 @@ fn renderErrorMessage( |
| 243 | 243 | } |
| 244 | 244 | try t.setColor(.reset); |
| 245 | 245 | if (src.data.source_line != 0 and options.include_source_line) { |
| 246 | try w.splatByteAll(' ', indent); | |
| 246 | 247 | const line = eb.nullTerminatedString(src.data.source_line); |
| 247 | 248 | for (line) |b| switch (b) { |
| 248 | 249 | '\t' => try w.writeByte(' '), |
| 249 | 250 | else => try w.writeByte(b), |
| 250 | 251 | }; |
| 251 | 252 | try w.writeByte('\n'); |
| 253 | try w.splatByteAll(' ', indent); | |
| 252 | 254 | // TODO basic unicode code point monospace width |
| 253 | 255 | const before_caret = src.data.span_main - src.data.span_start; |
| 254 | 256 | // -1 since span.main includes the caret |
| ... | ... | @@ -267,11 +269,13 @@ fn renderErrorMessage( |
| 267 | 269 | if (src.data.reference_trace_len > 0 and options.include_reference_trace) { |
| 268 | 270 | try t.setColor(.reset); |
| 269 | 271 | try t.setColor(.dim); |
| 272 | try w.splatByteAll(' ', indent); | |
| 270 | 273 | try w.print("referenced by:\n", .{}); |
| 271 | 274 | var ref_index = src.end; |
| 272 | 275 | for (0..src.data.reference_trace_len) |_| { |
| 273 | 276 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); |
| 274 | 277 | ref_index = ref_trace.end; |
| 278 | try w.splatByteAll(' ', indent); | |
| 275 | 279 | if (ref_trace.data.src_loc != .none) { |
| 276 | 280 | const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); |
| 277 | 281 | try w.print(" {s}: {s}:{d}:{d}\n", .{ |
| ... | ... | @@ -340,9 +344,9 @@ pub const Wip = struct { |
| 340 | 344 | pub fn init(wip: *Wip, gpa: Allocator) !void { |
| 341 | 345 | wip.* = .{ |
| 342 | 346 | .gpa = gpa, |
| 343 | .string_bytes = .{}, | |
| 344 | .extra = .{}, | |
| 345 | .root_list = .{}, | |
| 347 | .string_bytes = .empty, | |
| 348 | .extra = .empty, | |
| 349 | .root_list = .empty, | |
| 346 | 350 | }; |
| 347 | 351 | |
| 348 | 352 | // So that 0 can be used to indicate a null string. |
| ... | ... | @@ -371,9 +375,9 @@ pub const Wip = struct { |
| 371 | 375 | wip.deinit(); |
| 372 | 376 | wip.* = .{ |
| 373 | 377 | .gpa = gpa, |
| 374 | .string_bytes = .{}, | |
| 375 | .extra = .{}, | |
| 376 | .root_list = .{}, | |
| 378 | .string_bytes = .empty, | |
| 379 | .extra = .empty, | |
| 380 | .root_list = .empty, | |
| 377 | 381 | }; |
| 378 | 382 | return empty; |
| 379 | 383 | } |
lib/std/zig/Zir.zig+564-386| ... | ... | @@ -2443,7 +2443,7 @@ pub const Inst = struct { |
| 2443 | 2443 | has_align: bool, |
| 2444 | 2444 | has_addrspace: bool, |
| 2445 | 2445 | has_bit_range: bool, |
| 2446 | _: u1 = undefined, | |
| 2446 | _: u1 = 0, | |
| 2447 | 2447 | }, |
| 2448 | 2448 | size: std.builtin.Type.Pointer.Size, |
| 2449 | 2449 | /// Index into extra. See `PtrType`. |
| ... | ... | @@ -2668,7 +2668,7 @@ pub const Inst = struct { |
| 2668 | 2668 | has_ret_ty_body: bool, |
| 2669 | 2669 | has_any_noalias: bool, |
| 2670 | 2670 | ret_ty_is_generic: bool, |
| 2671 | _: u23 = undefined, | |
| 2671 | _: u23 = 0, | |
| 2672 | 2672 | }; |
| 2673 | 2673 | }; |
| 2674 | 2674 | |
| ... | ... | @@ -3134,7 +3134,7 @@ pub const Inst = struct { |
| 3134 | 3134 | pub const Flags = packed struct { |
| 3135 | 3135 | is_nosuspend: bool, |
| 3136 | 3136 | ensure_result_used: bool, |
| 3137 | _: u30 = undefined, | |
| 3137 | _: u30 = 0, | |
| 3138 | 3138 | |
| 3139 | 3139 | comptime { |
| 3140 | 3140 | if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32) |
| ... | ... | @@ -3462,33 +3462,21 @@ pub const Inst = struct { |
| 3462 | 3462 | }; |
| 3463 | 3463 | |
| 3464 | 3464 | /// Trailing: |
| 3465 | /// 0. captures_len: u32 // if has_captures_len | |
| 3466 | /// 1. fields_len: u32, // if has_fields_len | |
| 3467 | /// 2. decls_len: u32, // if has_decls_len | |
| 3468 | /// 3. capture: Capture // for every captures_len | |
| 3469 | /// 4. capture_name: NullTerminatedString // for every captures_len | |
| 3470 | /// 5. backing_int_body_len: u32, // if has_backing_int | |
| 3471 | /// 6. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 | |
| 3472 | /// 7. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 | |
| 3473 | /// 8. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3474 | /// 9. flags: u32 // for every 8 fields | |
| 3475 | /// - sets of 4 bits: | |
| 3476 | /// 0b000X: whether corresponding field has an align expression | |
| 3477 | /// 0b00X0: whether corresponding field has a default expression | |
| 3478 | /// 0b0X00: whether corresponding field is comptime | |
| 3479 | /// 0bX000: whether corresponding field has a type expression | |
| 3480 | /// 10. fields: { // for every fields_len | |
| 3481 | /// field_name: u32, | |
| 3482 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. | |
| 3483 | /// field_type_body_len: u32, // if corresponding bit is set | |
| 3484 | /// align_body_len: u32, // if corresponding bit is set | |
| 3485 | /// init_body_len: u32, // if corresponding bit is set | |
| 3486 | /// } | |
| 3487 | /// 11. bodies: { // for every fields_len | |
| 3488 | /// field_type_body_inst: Inst, // for each field_type_body_len | |
| 3489 | /// align_body_inst: Inst, // for each align_body_len | |
| 3490 | /// init_body_inst: Inst, // for each init_body_len | |
| 3491 | /// } | |
| 3465 | /// 0. captures_len: u32 // if `has_captures_len` | |
| 3466 | /// 1. decls_len: u32, // if `has_decls_len` | |
| 3467 | /// 2. fields_len: u32, // if `has_fields_len` | |
| 3468 | /// 3. backing_int_body_len: u32 // if `has_backing_int` | |
| 3469 | /// 4. capture: Capture // for every `captures_len` | |
| 3470 | /// 5. capture_name: NullTerminatedString // for every `captures_len` | |
| 3471 | /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction | |
| 3472 | /// 7. field_name: NullTerminatedString // for every `fields_len` | |
| 3473 | /// 8. field_type_body_len: u32 // for every `fields_len` | |
| 3474 | /// 9. field_align_body_len: u32 // for every `fields_len` if `any_field_aligns` | |
| 3475 | /// 10. field_default_body_len: u32 // for every `fields_len` if `any_field_defaults` | |
| 3476 | /// 11. field_comptime_bits: u32 // one bit per `fields_len` if `any_comptime_fields` | |
| 3477 | /// // LSB is first field, minimum number of `u32` needed | |
| 3478 | /// 12. backing_int_body_inst: Inst.Index // for each `backing_int_body_len` | |
| 3479 | /// 13. body_inst: Inst.Index // type body, then align body, then default body, for each field | |
| 3492 | 3480 | pub const StructDecl = struct { |
| 3493 | 3481 | // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. |
| 3494 | 3482 | // This hash contains the source of all fields, and any specified attributes (`extern`, backing type, etc). |
| ... | ... | @@ -3500,19 +3488,18 @@ pub const Inst = struct { |
| 3500 | 3488 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3501 | 3489 | src_node: Ast.Node.Index, |
| 3502 | 3490 | |
| 3503 | pub const Small = packed struct { | |
| 3491 | pub const Small = packed struct(u16) { | |
| 3504 | 3492 | has_captures_len: bool, |
| 3505 | has_fields_len: bool, | |
| 3506 | 3493 | has_decls_len: bool, |
| 3507 | has_backing_int: bool, | |
| 3508 | known_non_opv: bool, | |
| 3509 | known_comptime_only: bool, | |
| 3494 | has_fields_len: bool, | |
| 3510 | 3495 | name_strategy: NameStrategy, |
| 3511 | 3496 | layout: std.builtin.Type.ContainerLayout, |
| 3512 | any_default_inits: bool, | |
| 3497 | /// Always `false` if `layout != .@"packed"`. | |
| 3498 | has_backing_int_type: bool, | |
| 3499 | any_field_aligns: bool, | |
| 3500 | any_field_defaults: bool, | |
| 3513 | 3501 | any_comptime_fields: bool, |
| 3514 | any_aligned_fields: bool, | |
| 3515 | _: u3 = undefined, | |
| 3502 | _: u5 = 0, | |
| 3516 | 3503 | }; |
| 3517 | 3504 | }; |
| 3518 | 3505 | |
| ... | ... | @@ -3633,21 +3620,17 @@ pub const Inst = struct { |
| 3633 | 3620 | }; |
| 3634 | 3621 | |
| 3635 | 3622 | /// Trailing: |
| 3636 | /// 0. tag_type: Ref, // if has_tag_type | |
| 3637 | /// 1. captures_len: u32, // if has_captures_len | |
| 3638 | /// 2. body_len: u32, // if has_body_len | |
| 3639 | /// 3. fields_len: u32, // if has_fields_len | |
| 3640 | /// 4. decls_len: u32, // if has_decls_len | |
| 3641 | /// 5. capture: Capture // for every captures_len | |
| 3642 | /// 6. capture_name: NullTerminatedString // for every captures_len | |
| 3643 | /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3644 | /// 8. inst: Index // for every body_len | |
| 3645 | /// 9. has_bits: u32 // for every 32 fields | |
| 3646 | /// - the bit is whether corresponding field has an value expression | |
| 3647 | /// 10. fields: { // for every fields_len | |
| 3648 | /// field_name: u32, | |
| 3649 | /// value: Ref, // if corresponding bit is set | |
| 3650 | /// } | |
| 3623 | /// 0. captures_len: u32, // if has_captures_len | |
| 3624 | /// 1. decls_len: u32, // if has_decls_len | |
| 3625 | /// 2. fields_len: u32, // if has_fields_len | |
| 3626 | /// 3. tag_type_body_len: u32, // if has_tag_type | |
| 3627 | /// 4. capture: Capture // for every `captures_len` | |
| 3628 | /// 5. capture_name: NullTerminatedString // for every `captures_len` | |
| 3629 | /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction | |
| 3630 | /// 7. field_name: NullTerminatedString // for every `fields_len` | |
| 3631 | /// 8. field_value_body_len: u32 // for every `fields_len` if `any_field_values` | |
| 3632 | /// 9. tag_type_body_inst: Inst.Index // for each `tag_type_body_len` | |
| 3633 | /// 10. body_inst: Inst.Index // value body for each field | |
| 3651 | 3634 | pub const EnumDecl = struct { |
| 3652 | 3635 | // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. |
| 3653 | 3636 | // This hash contains the source of all fields, and the backing type if specified. |
| ... | ... | @@ -3659,40 +3642,32 @@ pub const Inst = struct { |
| 3659 | 3642 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3660 | 3643 | src_node: Ast.Node.Index, |
| 3661 | 3644 | |
| 3662 | pub const Small = packed struct { | |
| 3663 | has_tag_type: bool, | |
| 3645 | pub const Small = packed struct(u16) { | |
| 3664 | 3646 | has_captures_len: bool, |
| 3665 | has_body_len: bool, | |
| 3666 | has_fields_len: bool, | |
| 3667 | 3647 | has_decls_len: bool, |
| 3648 | has_fields_len: bool, | |
| 3668 | 3649 | name_strategy: NameStrategy, |
| 3650 | has_tag_type: bool, | |
| 3669 | 3651 | nonexhaustive: bool, |
| 3670 | _: u8 = undefined, | |
| 3652 | any_field_values: bool, | |
| 3653 | _: u8 = 0, | |
| 3671 | 3654 | }; |
| 3672 | 3655 | }; |
| 3673 | 3656 | |
| 3674 | 3657 | /// Trailing: |
| 3675 | /// 0. tag_type: Ref, // if has_tag_type | |
| 3676 | /// 1. captures_len: u32 // if has_captures_len | |
| 3677 | /// 2. body_len: u32, // if has_body_len | |
| 3678 | /// 3. fields_len: u32, // if has_fields_len | |
| 3679 | /// 4. decls_len: u32, // if has_decls_len | |
| 3680 | /// 5. capture: Capture // for every captures_len | |
| 3681 | /// 6. capture_name: NullTerminatedString // for every captures_len | |
| 3682 | /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3683 | /// 8. inst: Index // for every body_len | |
| 3684 | /// 9. has_bits: u32 // for every 8 fields | |
| 3685 | /// - sets of 4 bits: | |
| 3686 | /// 0b000X: whether corresponding field has a type expression | |
| 3687 | /// 0b00X0: whether corresponding field has a align expression | |
| 3688 | /// 0b0X00: whether corresponding field has a tag value expression | |
| 3689 | /// 0bX000: unused | |
| 3690 | /// 10. fields: { // for every fields_len | |
| 3691 | /// field_name: NullTerminatedString, // null terminated string index | |
| 3692 | /// field_type: Ref, // if corresponding bit is set | |
| 3693 | /// align: Ref, // if corresponding bit is set | |
| 3694 | /// tag_value: Ref, // if corresponding bit is set | |
| 3695 | /// } | |
| 3658 | /// 0. captures_len: u32 // if `has_captures_len` | |
| 3659 | /// 1. decls_len: u32, // if `has_decls_len` | |
| 3660 | /// 2. fields_len: u32, // if `has_fields_len` | |
| 3661 | /// 3. arg_type_body_len: u32, // if `kind.hasArgType()` | |
| 3662 | /// 4. capture: Capture // for every `captures_len` | |
| 3663 | /// 5. capture_name: NullTerminatedString // for every `captures_len` | |
| 3664 | /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction | |
| 3665 | /// 7. field_name: NullTerminatedString // for every `fields_len` | |
| 3666 | /// 8. field_type_body_len: u32 // for every `fields_len` | |
| 3667 | /// 9 . field_align_body_len: u32 // for every `fields_len` if `any_field_aligns` | |
| 3668 | /// 10. field_value_body_len: u32 // for every `fields_len` if `any_field_values` | |
| 3669 | /// 11. arg_type_body_inst: Inst.Index // for each `arg_type_body_len` | |
| 3670 | /// 12. body_inst: Inst.Index // type body, then align body, then value body, for each field | |
| 3696 | 3671 | pub const UnionDecl = struct { |
| 3697 | 3672 | // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. |
| 3698 | 3673 | // This hash contains the source of all fields, and any specified attributes (`extern` etc). |
| ... | ... | @@ -3704,23 +3679,47 @@ pub const Inst = struct { |
| 3704 | 3679 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3705 | 3680 | src_node: Ast.Node.Index, |
| 3706 | 3681 | |
| 3707 | pub const Small = packed struct { | |
| 3708 | has_tag_type: bool, | |
| 3682 | pub const Small = packed struct(u16) { | |
| 3709 | 3683 | has_captures_len: bool, |
| 3710 | has_body_len: bool, | |
| 3711 | has_fields_len: bool, | |
| 3712 | 3684 | has_decls_len: bool, |
| 3685 | has_fields_len: bool, | |
| 3713 | 3686 | name_strategy: NameStrategy, |
| 3714 | layout: std.builtin.Type.ContainerLayout, | |
| 3715 | /// has_tag_type | auto_enum_tag | result | |
| 3716 | /// ------------------------------------- | |
| 3717 | /// false | false | union { } | |
| 3718 | /// false | true | union(enum) { } | |
| 3719 | /// true | true | union(enum(T)) { } | |
| 3720 | /// true | false | union(T) { } | |
| 3721 | auto_enum_tag: bool, | |
| 3722 | any_aligned_fields: bool, | |
| 3723 | _: u5 = undefined, | |
| 3687 | kind: Kind, | |
| 3688 | any_field_aligns: bool, | |
| 3689 | any_field_values: bool, | |
| 3690 | _: u6 = 0, | |
| 3691 | }; | |
| 3692 | ||
| 3693 | pub const Kind = enum(u3) { | |
| 3694 | /// `union` | |
| 3695 | auto, | |
| 3696 | /// `union(T)` | |
| 3697 | tagged_explicit, | |
| 3698 | /// `union(enum)` | |
| 3699 | tagged_enum, | |
| 3700 | /// `union(enum(T))` | |
| 3701 | tagged_enum_explicit, | |
| 3702 | /// `extern union` | |
| 3703 | @"extern", | |
| 3704 | /// `packed union` | |
| 3705 | @"packed", | |
| 3706 | /// `packed union(T)` | |
| 3707 | packed_explicit, | |
| 3708 | ||
| 3709 | pub fn hasArgType(k: Kind) bool { | |
| 3710 | return switch (k) { | |
| 3711 | .auto, .tagged_enum, .@"extern", .@"packed" => false, | |
| 3712 | .tagged_explicit, .tagged_enum_explicit, .packed_explicit => true, | |
| 3713 | }; | |
| 3714 | } | |
| 3715 | ||
| 3716 | pub fn layout(k: Kind) std.builtin.Type.ContainerLayout { | |
| 3717 | return switch (k) { | |
| 3718 | .auto, .tagged_explicit, .tagged_enum, .tagged_enum_explicit => .auto, | |
| 3719 | .@"extern" => .@"extern", | |
| 3720 | .@"packed", .packed_explicit => .@"packed", | |
| 3721 | }; | |
| 3722 | } | |
| 3724 | 3723 | }; |
| 3725 | 3724 | }; |
| 3726 | 3725 | |
| ... | ... | @@ -3735,11 +3734,11 @@ pub const Inst = struct { |
| 3735 | 3734 | /// This node provides a new absolute baseline node for all instructions within this struct. |
| 3736 | 3735 | src_node: Ast.Node.Index, |
| 3737 | 3736 | |
| 3738 | pub const Small = packed struct { | |
| 3737 | pub const Small = packed struct(u16) { | |
| 3739 | 3738 | has_captures_len: bool, |
| 3740 | 3739 | has_decls_len: bool, |
| 3741 | 3740 | name_strategy: NameStrategy, |
| 3742 | _: u12 = undefined, | |
| 3741 | _: u12 = 0, | |
| 3743 | 3742 | }; |
| 3744 | 3743 | }; |
| 3745 | 3744 | |
| ... | ... | @@ -3904,12 +3903,12 @@ pub const Inst = struct { |
| 3904 | 3903 | pub const AllocExtended = struct { |
| 3905 | 3904 | src_node: Ast.Node.Offset, |
| 3906 | 3905 | |
| 3907 | pub const Small = packed struct { | |
| 3906 | pub const Small = packed struct(u16) { | |
| 3908 | 3907 | has_type: bool, |
| 3909 | 3908 | has_align: bool, |
| 3910 | 3909 | is_const: bool, |
| 3911 | 3910 | is_comptime: bool, |
| 3912 | _: u12 = undefined, | |
| 3911 | _: u12 = 0, | |
| 3913 | 3912 | }; |
| 3914 | 3913 | }; |
| 3915 | 3914 | |
| ... | ... | @@ -4012,135 +4011,6 @@ pub const Inst = struct { |
| 4012 | 4011 | }; |
| 4013 | 4012 | }; |
| 4014 | 4013 | |
| 4015 | pub const DeclIterator = struct { | |
| 4016 | extra_index: u32, | |
| 4017 | decls_remaining: u32, | |
| 4018 | zir: Zir, | |
| 4019 | ||
| 4020 | pub fn next(it: *DeclIterator) ?Inst.Index { | |
| 4021 | if (it.decls_remaining == 0) return null; | |
| 4022 | const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]); | |
| 4023 | it.extra_index += 1; | |
| 4024 | it.decls_remaining -= 1; | |
| 4025 | assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration); | |
| 4026 | return decl_inst; | |
| 4027 | } | |
| 4028 | }; | |
| 4029 | ||
| 4030 | pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | |
| 4031 | const inst = zir.instructions.get(@intFromEnum(decl_inst)); | |
| 4032 | assert(inst.tag == .extended); | |
| 4033 | const extended = inst.data.extended; | |
| 4034 | switch (extended.opcode) { | |
| 4035 | .struct_decl => { | |
| 4036 | const small: Inst.StructDecl.Small = @bitCast(extended.small); | |
| 4037 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).@"struct".fields.len); | |
| 4038 | const captures_len = if (small.has_captures_len) captures_len: { | |
| 4039 | const captures_len = zir.extra[extra_index]; | |
| 4040 | extra_index += 1; | |
| 4041 | break :captures_len captures_len; | |
| 4042 | } else 0; | |
| 4043 | extra_index += @intFromBool(small.has_fields_len); | |
| 4044 | const decls_len = if (small.has_decls_len) decls_len: { | |
| 4045 | const decls_len = zir.extra[extra_index]; | |
| 4046 | extra_index += 1; | |
| 4047 | break :decls_len decls_len; | |
| 4048 | } else 0; | |
| 4049 | ||
| 4050 | extra_index += captures_len * 2; | |
| 4051 | ||
| 4052 | if (small.has_backing_int) { | |
| 4053 | const backing_int_body_len = zir.extra[extra_index]; | |
| 4054 | extra_index += 1; // backing_int_body_len | |
| 4055 | if (backing_int_body_len == 0) { | |
| 4056 | extra_index += 1; // backing_int_ref | |
| 4057 | } else { | |
| 4058 | extra_index += backing_int_body_len; // backing_int_body_inst | |
| 4059 | } | |
| 4060 | } | |
| 4061 | ||
| 4062 | return .{ | |
| 4063 | .extra_index = extra_index, | |
| 4064 | .decls_remaining = decls_len, | |
| 4065 | .zir = zir, | |
| 4066 | }; | |
| 4067 | }, | |
| 4068 | .enum_decl => { | |
| 4069 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); | |
| 4070 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).@"struct".fields.len); | |
| 4071 | extra_index += @intFromBool(small.has_tag_type); | |
| 4072 | const captures_len = if (small.has_captures_len) captures_len: { | |
| 4073 | const captures_len = zir.extra[extra_index]; | |
| 4074 | extra_index += 1; | |
| 4075 | break :captures_len captures_len; | |
| 4076 | } else 0; | |
| 4077 | extra_index += @intFromBool(small.has_body_len); | |
| 4078 | extra_index += @intFromBool(small.has_fields_len); | |
| 4079 | const decls_len = if (small.has_decls_len) decls_len: { | |
| 4080 | const decls_len = zir.extra[extra_index]; | |
| 4081 | extra_index += 1; | |
| 4082 | break :decls_len decls_len; | |
| 4083 | } else 0; | |
| 4084 | ||
| 4085 | extra_index += captures_len * 2; | |
| 4086 | ||
| 4087 | return .{ | |
| 4088 | .extra_index = extra_index, | |
| 4089 | .decls_remaining = decls_len, | |
| 4090 | .zir = zir, | |
| 4091 | }; | |
| 4092 | }, | |
| 4093 | .union_decl => { | |
| 4094 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); | |
| 4095 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).@"struct".fields.len); | |
| 4096 | extra_index += @intFromBool(small.has_tag_type); | |
| 4097 | const captures_len = if (small.has_captures_len) captures_len: { | |
| 4098 | const captures_len = zir.extra[extra_index]; | |
| 4099 | extra_index += 1; | |
| 4100 | break :captures_len captures_len; | |
| 4101 | } else 0; | |
| 4102 | extra_index += @intFromBool(small.has_body_len); | |
| 4103 | extra_index += @intFromBool(small.has_fields_len); | |
| 4104 | const decls_len = if (small.has_decls_len) decls_len: { | |
| 4105 | const decls_len = zir.extra[extra_index]; | |
| 4106 | extra_index += 1; | |
| 4107 | break :decls_len decls_len; | |
| 4108 | } else 0; | |
| 4109 | ||
| 4110 | extra_index += captures_len * 2; | |
| 4111 | ||
| 4112 | return .{ | |
| 4113 | .extra_index = extra_index, | |
| 4114 | .decls_remaining = decls_len, | |
| 4115 | .zir = zir, | |
| 4116 | }; | |
| 4117 | }, | |
| 4118 | .opaque_decl => { | |
| 4119 | const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); | |
| 4120 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.OpaqueDecl).@"struct".fields.len); | |
| 4121 | const decls_len = if (small.has_decls_len) decls_len: { | |
| 4122 | const decls_len = zir.extra[extra_index]; | |
| 4123 | extra_index += 1; | |
| 4124 | break :decls_len decls_len; | |
| 4125 | } else 0; | |
| 4126 | const captures_len = if (small.has_captures_len) captures_len: { | |
| 4127 | const captures_len = zir.extra[extra_index]; | |
| 4128 | extra_index += 1; | |
| 4129 | break :captures_len captures_len; | |
| 4130 | } else 0; | |
| 4131 | ||
| 4132 | extra_index += captures_len * 2; | |
| 4133 | ||
| 4134 | return .{ | |
| 4135 | .extra_index = extra_index, | |
| 4136 | .decls_remaining = decls_len, | |
| 4137 | .zir = zir, | |
| 4138 | }; | |
| 4139 | }, | |
| 4140 | else => unreachable, | |
| 4141 | } | |
| 4142 | } | |
| 4143 | ||
| 4144 | 4014 | /// `DeclContents` contains all "interesting" instructions found within a declaration by `findTrackable`. |
| 4145 | 4015 | /// These instructions are partitioned into a few different sets, since this makes ZIR instruction mapping |
| 4146 | 4016 | /// more effective. |
| ... | ... | @@ -4524,7 +4394,7 @@ fn findTrackableInner( |
| 4524 | 4394 | try zir.findTrackableBody(gpa, contents, defers, body); |
| 4525 | 4395 | }, |
| 4526 | 4396 | |
| 4527 | // Reifications and opaque declarations need tracking, but have no body. | |
| 4397 | // Reifications and opaque declarations need tracking, but have no bodies. | |
| 4528 | 4398 | .reify_enum, |
| 4529 | 4399 | .reify_struct, |
| 4530 | 4400 | .reify_union, |
| ... | ... | @@ -4535,150 +4405,37 @@ fn findTrackableInner( |
| 4535 | 4405 | .struct_decl => { |
| 4536 | 4406 | try contents.explicit_types.append(gpa, inst); |
| 4537 | 4407 | |
| 4538 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 4539 | const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); | |
| 4540 | var extra_index = extra.end; | |
| 4541 | const captures_len = if (small.has_captures_len) blk: { | |
| 4542 | const captures_len = zir.extra[extra_index]; | |
| 4543 | extra_index += 1; | |
| 4544 | break :blk captures_len; | |
| 4545 | } else 0; | |
| 4546 | const fields_len = if (small.has_fields_len) blk: { | |
| 4547 | const fields_len = zir.extra[extra_index]; | |
| 4548 | extra_index += 1; | |
| 4549 | break :blk fields_len; | |
| 4550 | } else 0; | |
| 4551 | const decls_len = if (small.has_decls_len) blk: { | |
| 4552 | const decls_len = zir.extra[extra_index]; | |
| 4553 | extra_index += 1; | |
| 4554 | break :blk decls_len; | |
| 4555 | } else 0; | |
| 4556 | extra_index += captures_len * 2; | |
| 4557 | if (small.has_backing_int) { | |
| 4558 | const backing_int_body_len = zir.extra[extra_index]; | |
| 4559 | extra_index += 1; | |
| 4560 | if (backing_int_body_len == 0) { | |
| 4561 | extra_index += 1; // backing_int_ref | |
| 4562 | } else { | |
| 4563 | const body = zir.bodySlice(extra_index, backing_int_body_len); | |
| 4564 | extra_index += backing_int_body_len; | |
| 4565 | try zir.findTrackableBody(gpa, contents, defers, body); | |
| 4566 | } | |
| 4408 | const struct_decl = zir.getStructDecl(inst); | |
| 4409 | var it = struct_decl.iterateFields(); | |
| 4410 | while (it.next()) |field| { | |
| 4411 | try zir.findTrackableBody(gpa, contents, defers, field.type_body); | |
| 4412 | if (field.align_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); | |
| 4413 | if (field.default_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); | |
| 4567 | 4414 | } |
| 4568 | extra_index += decls_len; | |
| 4569 | ||
| 4570 | // This ZIR is structured in a slightly awkward way, so we have to split up the iteration. | |
| 4571 | // `extra_index` iterates `flags` (bags of bits). | |
| 4572 | // `fields_extra_index` iterates `fields`. | |
| 4573 | // We accumulate the total length of bodies into `total_bodies_len`. This is sufficient because | |
| 4574 | // the bodies are packed together in `extra` and we only need to traverse their instructions (we | |
| 4575 | // don't really care about the structure). | |
| 4576 | ||
| 4577 | const bits_per_field = 4; | |
| 4578 | const fields_per_u32 = 32 / bits_per_field; | |
| 4579 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 4580 | var cur_bit_bag: u32 = undefined; | |
| 4581 | ||
| 4582 | var fields_extra_index = extra_index + bit_bags_count; | |
| 4583 | var total_bodies_len: u32 = 0; | |
| 4584 | ||
| 4585 | for (0..fields_len) |field_i| { | |
| 4586 | if (field_i % fields_per_u32 == 0) { | |
| 4587 | cur_bit_bag = zir.extra[extra_index]; | |
| 4588 | extra_index += 1; | |
| 4589 | } | |
| 4590 | ||
| 4591 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 4592 | cur_bit_bag >>= 1; | |
| 4593 | const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 4594 | cur_bit_bag >>= 2; // also skip `is_comptime`; we don't care | |
| 4595 | const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 4596 | cur_bit_bag >>= 1; | |
| 4597 | ||
| 4598 | fields_extra_index += 1; // field_name | |
| 4599 | ||
| 4600 | if (has_type_body) { | |
| 4601 | const field_type_body_len = zir.extra[fields_extra_index]; | |
| 4602 | total_bodies_len += field_type_body_len; | |
| 4603 | } | |
| 4604 | fields_extra_index += 1; // field_type or field_type_body_len | |
| 4605 | ||
| 4606 | if (has_align) { | |
| 4607 | const align_body_len = zir.extra[fields_extra_index]; | |
| 4608 | fields_extra_index += 1; | |
| 4609 | total_bodies_len += align_body_len; | |
| 4610 | } | |
| 4611 | ||
| 4612 | if (has_init) { | |
| 4613 | const init_body_len = zir.extra[fields_extra_index]; | |
| 4614 | fields_extra_index += 1; | |
| 4615 | total_bodies_len += init_body_len; | |
| 4616 | } | |
| 4617 | } | |
| 4618 | ||
| 4619 | // Now, `fields_extra_index` points to `bodies`. Let's treat this as one big body. | |
| 4620 | const merged_bodies = zir.bodySlice(fields_extra_index, total_bodies_len); | |
| 4621 | try zir.findTrackableBody(gpa, contents, defers, merged_bodies); | |
| 4622 | 4415 | }, |
| 4623 | 4416 | |
| 4624 | // Union declarations need tracking and have a body. | |
| 4417 | // Union declarations need tracking and have bodies. | |
| 4625 | 4418 | .union_decl => { |
| 4626 | 4419 | try contents.explicit_types.append(gpa, inst); |
| 4627 | 4420 | |
| 4628 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | |
| 4629 | const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); | |
| 4630 | var extra_index = extra.end; | |
| 4631 | extra_index += @intFromBool(small.has_tag_type); | |
| 4632 | const captures_len = if (small.has_captures_len) blk: { | |
| 4633 | const captures_len = zir.extra[extra_index]; | |
| 4634 | extra_index += 1; | |
| 4635 | break :blk captures_len; | |
| 4636 | } else 0; | |
| 4637 | const body_len = if (small.has_body_len) blk: { | |
| 4638 | const body_len = zir.extra[extra_index]; | |
| 4639 | extra_index += 1; | |
| 4640 | break :blk body_len; | |
| 4641 | } else 0; | |
| 4642 | extra_index += @intFromBool(small.has_fields_len); | |
| 4643 | const decls_len = if (small.has_decls_len) blk: { | |
| 4644 | const decls_len = zir.extra[extra_index]; | |
| 4645 | extra_index += 1; | |
| 4646 | break :blk decls_len; | |
| 4647 | } else 0; | |
| 4648 | extra_index += captures_len * 2; | |
| 4649 | extra_index += decls_len; | |
| 4650 | const body = zir.bodySlice(extra_index, body_len); | |
| 4651 | try zir.findTrackableBody(gpa, contents, defers, body); | |
| 4421 | const union_decl = zir.getUnionDecl(inst); | |
| 4422 | var it = union_decl.iterateFields(); | |
| 4423 | while (it.next()) |field| { | |
| 4424 | if (field.type_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); | |
| 4425 | if (field.align_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); | |
| 4426 | if (field.value_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); | |
| 4427 | } | |
| 4652 | 4428 | }, |
| 4653 | 4429 | |
| 4654 | // Enum declarations need tracking and have a body. | |
| 4430 | // Enum declarations need tracking and have bodies. | |
| 4655 | 4431 | .enum_decl => { |
| 4656 | 4432 | try contents.explicit_types.append(gpa, inst); |
| 4657 | 4433 | |
| 4658 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); | |
| 4659 | const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); | |
| 4660 | var extra_index = extra.end; | |
| 4661 | extra_index += @intFromBool(small.has_tag_type); | |
| 4662 | const captures_len = if (small.has_captures_len) blk: { | |
| 4663 | const captures_len = zir.extra[extra_index]; | |
| 4664 | extra_index += 1; | |
| 4665 | break :blk captures_len; | |
| 4666 | } else 0; | |
| 4667 | const body_len = if (small.has_body_len) blk: { | |
| 4668 | const body_len = zir.extra[extra_index]; | |
| 4669 | extra_index += 1; | |
| 4670 | break :blk body_len; | |
| 4671 | } else 0; | |
| 4672 | extra_index += @intFromBool(small.has_fields_len); | |
| 4673 | const decls_len = if (small.has_decls_len) blk: { | |
| 4674 | const decls_len = zir.extra[extra_index]; | |
| 4675 | extra_index += 1; | |
| 4676 | break :blk decls_len; | |
| 4677 | } else 0; | |
| 4678 | extra_index += captures_len * 2; | |
| 4679 | extra_index += decls_len; | |
| 4680 | const body = zir.bodySlice(extra_index, body_len); | |
| 4681 | try zir.findTrackableBody(gpa, contents, defers, body); | |
| 4434 | const enum_decl = zir.getEnumDecl(inst); | |
| 4435 | var it = enum_decl.iterateFields(); | |
| 4436 | while (it.next()) |field| { | |
| 4437 | if (field.value_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); | |
| 4438 | } | |
| 4682 | 4439 | }, |
| 4683 | 4440 | } |
| 4684 | 4441 | }, |
| ... | ... | @@ -5481,34 +5238,455 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void { |
| 5481 | 5238 | } |
| 5482 | 5239 | } |
| 5483 | 5240 | |
| 5484 | pub fn typeCapturesLen(zir: Zir, type_decl: Inst.Index) u32 { | |
| 5241 | pub fn typeDecls(zir: Zir, type_decl: Inst.Index) []const Zir.Inst.Index { | |
| 5485 | 5242 | const inst = zir.instructions.get(@intFromEnum(type_decl)); |
| 5486 | 5243 | assert(inst.tag == .extended); |
| 5487 | switch (inst.data.extended.opcode) { | |
| 5488 | .struct_decl => { | |
| 5489 | const small: Inst.StructDecl.Small = @bitCast(inst.data.extended.small); | |
| 5490 | if (!small.has_captures_len) return 0; | |
| 5491 | const extra = zir.extraData(Inst.StructDecl, inst.data.extended.operand); | |
| 5492 | return zir.extra[extra.end]; | |
| 5493 | }, | |
| 5494 | .union_decl => { | |
| 5495 | const small: Inst.UnionDecl.Small = @bitCast(inst.data.extended.small); | |
| 5496 | if (!small.has_captures_len) return 0; | |
| 5497 | const extra = zir.extraData(Inst.UnionDecl, inst.data.extended.operand); | |
| 5498 | return zir.extra[extra.end + @intFromBool(small.has_tag_type)]; | |
| 5499 | }, | |
| 5500 | .enum_decl => { | |
| 5501 | const small: Inst.EnumDecl.Small = @bitCast(inst.data.extended.small); | |
| 5502 | if (!small.has_captures_len) return 0; | |
| 5503 | const extra = zir.extraData(Inst.EnumDecl, inst.data.extended.operand); | |
| 5504 | return zir.extra[extra.end + @intFromBool(small.has_tag_type)]; | |
| 5505 | }, | |
| 5506 | .opaque_decl => { | |
| 5507 | const small: Inst.OpaqueDecl.Small = @bitCast(inst.data.extended.small); | |
| 5508 | if (!small.has_captures_len) return 0; | |
| 5509 | const extra = zir.extraData(Inst.OpaqueDecl, inst.data.extended.operand); | |
| 5510 | return zir.extra[extra.end]; | |
| 5511 | }, | |
| 5244 | return switch (inst.data.extended.opcode) { | |
| 5245 | .struct_decl => zir.getStructDecl(type_decl).decls, | |
| 5246 | .union_decl => zir.getUnionDecl(type_decl).decls, | |
| 5247 | .enum_decl => zir.getEnumDecl(type_decl).decls, | |
| 5248 | .opaque_decl => zir.getOpaqueDecl(type_decl).decls, | |
| 5512 | 5249 | else => unreachable, |
| 5250 | }; | |
| 5251 | } | |
| 5252 | ||
| 5253 | pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDecl { | |
| 5254 | const inst_data = zir.instructions.get(@intFromEnum(struct_decl)); | |
| 5255 | assert(inst_data.tag == .extended); | |
| 5256 | assert(inst_data.data.extended.opcode == .struct_decl); | |
| 5257 | const small: Inst.StructDecl.Small = @bitCast(inst_data.data.extended.small); | |
| 5258 | const extra = zir.extraData(Inst.StructDecl, inst_data.data.extended.operand); | |
| 5259 | var extra_index = extra.end; | |
| 5260 | const captures_len: u32 = if (small.has_captures_len) blk: { | |
| 5261 | const captures_len = zir.extra[extra_index]; | |
| 5262 | extra_index += 1; | |
| 5263 | break :blk captures_len; | |
| 5264 | } else 0; | |
| 5265 | const decls_len: u32 = if (small.has_decls_len) blk: { | |
| 5266 | const decls_len = zir.extra[extra_index]; | |
| 5267 | extra_index += 1; | |
| 5268 | break :blk decls_len; | |
| 5269 | } else 0; | |
| 5270 | const fields_len: u32 = if (small.has_fields_len) blk: { | |
| 5271 | const fields_len = zir.extra[extra_index]; | |
| 5272 | extra_index += 1; | |
| 5273 | break :blk fields_len; | |
| 5274 | } else 0; | |
| 5275 | const backing_int_type_body_len: u32 = if (small.has_backing_int_type) len: { | |
| 5276 | const body_len = zir.extra[extra_index]; | |
| 5277 | extra_index += 1; | |
| 5278 | break :len body_len; | |
| 5279 | } else 0; | |
| 5280 | const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5281 | extra_index += captures_len; | |
| 5282 | const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5283 | extra_index += captures_len; | |
| 5284 | const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); | |
| 5285 | extra_index += decls_len; | |
| 5286 | const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]); | |
| 5287 | extra_index += fields_len; | |
| 5288 | const field_type_body_lens: []const u32 = @ptrCast(zir.extra[extra_index..][0..fields_len]); | |
| 5289 | extra_index += fields_len; | |
| 5290 | const field_align_body_lens: ?[]const u32 = if (small.any_field_aligns) lens: { | |
| 5291 | const lens = zir.extra[extra_index..][0..fields_len]; | |
| 5292 | extra_index += fields_len; | |
| 5293 | break :lens @ptrCast(lens); | |
| 5294 | } else null; | |
| 5295 | const field_default_body_lens: ?[]const u32 = if (small.any_field_defaults) lens: { | |
| 5296 | const lens = zir.extra[extra_index..][0..fields_len]; | |
| 5297 | extra_index += fields_len; | |
| 5298 | break :lens @ptrCast(lens); | |
| 5299 | } else null; | |
| 5300 | const field_comptime_bits: ?[]const u32 = if (small.any_comptime_fields) bits: { | |
| 5301 | const bits_len = std.math.divCeil(u32, fields_len, 32) catch unreachable; | |
| 5302 | const bits = zir.extra[extra_index..][0..bits_len]; | |
| 5303 | extra_index += bits_len; | |
| 5304 | break :bits bits; | |
| 5305 | } else null; | |
| 5306 | const backing_int_type_body: ?[]const Zir.Inst.Index = switch (backing_int_type_body_len) { | |
| 5307 | 0 => null, | |
| 5308 | else => |n| zir.bodySlice(extra_index, n), | |
| 5309 | }; | |
| 5310 | extra_index += backing_int_type_body_len; | |
| 5311 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); | |
| 5312 | return .{ | |
| 5313 | .src_line = extra.data.src_line, | |
| 5314 | .src_node = extra.data.src_node, | |
| 5315 | .name_strategy = small.name_strategy, | |
| 5316 | .captures = captures, | |
| 5317 | .capture_names = capture_names, | |
| 5318 | .decls = decls, | |
| 5319 | .layout = small.layout, | |
| 5320 | .backing_int_type_body = backing_int_type_body, | |
| 5321 | .field_names = field_names, | |
| 5322 | .field_type_body_lens = field_type_body_lens, | |
| 5323 | .field_align_body_lens = field_align_body_lens, | |
| 5324 | .field_default_body_lens = field_default_body_lens, | |
| 5325 | .field_comptime_bits = field_comptime_bits, | |
| 5326 | .field_bodies_overlong = field_bodies_overlong, | |
| 5327 | }; | |
| 5328 | } | |
| 5329 | pub const UnwrappedStructDecl = struct { | |
| 5330 | src_line: u32, | |
| 5331 | src_node: Ast.Node.Index, | |
| 5332 | name_strategy: Inst.NameStrategy, | |
| 5333 | ||
| 5334 | captures: []const Inst.Capture, | |
| 5335 | capture_names: []const NullTerminatedString, | |
| 5336 | ||
| 5337 | decls: []const Inst.Index, | |
| 5338 | ||
| 5339 | layout: std.builtin.Type.ContainerLayout, | |
| 5340 | backing_int_type_body: ?[]const Inst.Index, | |
| 5341 | ||
| 5342 | field_names: []const NullTerminatedString, | |
| 5343 | field_type_body_lens: []const u32, | |
| 5344 | field_align_body_lens: ?[]const u32, | |
| 5345 | field_default_body_lens: ?[]const u32, | |
| 5346 | field_comptime_bits: ?[]const u32, | |
| 5347 | field_bodies_overlong: []const Inst.Index, | |
| 5348 | ||
| 5349 | pub fn iterateFields(struct_decl: UnwrappedStructDecl) FieldIterator { | |
| 5350 | return .{ | |
| 5351 | .next_idx = 0, | |
| 5352 | .names = struct_decl.field_names, | |
| 5353 | .type_body_lens = struct_decl.field_type_body_lens, | |
| 5354 | .align_body_lens = struct_decl.field_align_body_lens, | |
| 5355 | .default_body_lens = struct_decl.field_default_body_lens, | |
| 5356 | .comptime_bits = struct_decl.field_comptime_bits, | |
| 5357 | .bodies_overlong = struct_decl.field_bodies_overlong, | |
| 5358 | }; | |
| 5513 | 5359 | } |
| 5360 | ||
| 5361 | pub const FieldIterator = struct { | |
| 5362 | next_idx: u32, | |
| 5363 | names: []const NullTerminatedString, | |
| 5364 | type_body_lens: []const u32, | |
| 5365 | align_body_lens: ?[]const u32, | |
| 5366 | default_body_lens: ?[]const u32, | |
| 5367 | comptime_bits: ?[]const u32, | |
| 5368 | bodies_overlong: []const Inst.Index, | |
| 5369 | pub const Field = struct { | |
| 5370 | idx: u32, | |
| 5371 | name: NullTerminatedString, | |
| 5372 | type_body: []const Inst.Index, | |
| 5373 | align_body: ?[]const Inst.Index, | |
| 5374 | default_body: ?[]const Inst.Index, | |
| 5375 | is_comptime: bool, | |
| 5376 | }; | |
| 5377 | pub fn next(it: *FieldIterator) ?Field { | |
| 5378 | const idx = it.next_idx; | |
| 5379 | if (idx == it.names.len) return null; | |
| 5380 | it.next_idx += 1; | |
| 5381 | return .{ | |
| 5382 | .idx = idx, | |
| 5383 | .name = it.names[idx], | |
| 5384 | .type_body = it.body(it.type_body_lens[idx]).?, | |
| 5385 | .align_body = it.body(if (it.align_body_lens) |l| l[idx] else 0), | |
| 5386 | .default_body = it.body(if (it.default_body_lens) |l| l[idx] else 0), | |
| 5387 | .is_comptime = ct: { | |
| 5388 | const bits = it.comptime_bits orelse break :ct false; | |
| 5389 | const big = bits[idx / 32]; | |
| 5390 | const shifted = big >> @intCast(idx % 32); | |
| 5391 | break :ct @as(u1, @truncate(shifted)) == 1; | |
| 5392 | }, | |
| 5393 | }; | |
| 5394 | } | |
| 5395 | fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index { | |
| 5396 | if (len == 0) return null; | |
| 5397 | const b = it.bodies_overlong[0..len]; | |
| 5398 | it.bodies_overlong = it.bodies_overlong[len..]; | |
| 5399 | return b; | |
| 5400 | } | |
| 5401 | }; | |
| 5402 | }; | |
| 5403 | ||
| 5404 | pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl { | |
| 5405 | const inst_data = zir.instructions.get(@intFromEnum(union_decl)); | |
| 5406 | assert(inst_data.tag == .extended); | |
| 5407 | assert(inst_data.data.extended.opcode == .union_decl); | |
| 5408 | const small: Inst.UnionDecl.Small = @bitCast(inst_data.data.extended.small); | |
| 5409 | const extra = zir.extraData(Inst.UnionDecl, inst_data.data.extended.operand); | |
| 5410 | var extra_index = extra.end; | |
| 5411 | const captures_len: u32 = if (small.has_captures_len) blk: { | |
| 5412 | const captures_len = zir.extra[extra_index]; | |
| 5413 | extra_index += 1; | |
| 5414 | break :blk captures_len; | |
| 5415 | } else 0; | |
| 5416 | const decls_len: u32 = if (small.has_decls_len) blk: { | |
| 5417 | const decls_len = zir.extra[extra_index]; | |
| 5418 | extra_index += 1; | |
| 5419 | break :blk decls_len; | |
| 5420 | } else 0; | |
| 5421 | const fields_len: u32 = if (small.has_fields_len) blk: { | |
| 5422 | const fields_len = zir.extra[extra_index]; | |
| 5423 | extra_index += 1; | |
| 5424 | break :blk fields_len; | |
| 5425 | } else 0; | |
| 5426 | const arg_type_body_len: u32 = if (small.kind.hasArgType()) len: { | |
| 5427 | const body_len = zir.extra[extra_index]; | |
| 5428 | extra_index += 1; | |
| 5429 | break :len body_len; | |
| 5430 | } else 0; | |
| 5431 | const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5432 | extra_index += captures_len; | |
| 5433 | const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5434 | extra_index += captures_len; | |
| 5435 | const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); | |
| 5436 | extra_index += decls_len; | |
| 5437 | const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]); | |
| 5438 | extra_index += fields_len; | |
| 5439 | const field_type_body_lens: []const u32 = @ptrCast(zir.extra[extra_index..][0..fields_len]); | |
| 5440 | extra_index += fields_len; | |
| 5441 | const field_align_body_lens: ?[]const u32 = if (small.any_field_aligns) lens: { | |
| 5442 | const lens = zir.extra[extra_index..][0..fields_len]; | |
| 5443 | extra_index += fields_len; | |
| 5444 | break :lens @ptrCast(lens); | |
| 5445 | } else null; | |
| 5446 | const field_value_body_lens: ?[]const u32 = if (small.any_field_values) lens: { | |
| 5447 | const lens = zir.extra[extra_index..][0..fields_len]; | |
| 5448 | extra_index += fields_len; | |
| 5449 | break :lens @ptrCast(lens); | |
| 5450 | } else null; | |
| 5451 | const arg_type_body: ?[]const Zir.Inst.Index = switch (arg_type_body_len) { | |
| 5452 | 0 => null, | |
| 5453 | else => |n| zir.bodySlice(extra_index, n), | |
| 5454 | }; | |
| 5455 | extra_index += arg_type_body_len; | |
| 5456 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); | |
| 5457 | return .{ | |
| 5458 | .src_line = extra.data.src_line, | |
| 5459 | .src_node = extra.data.src_node, | |
| 5460 | .name_strategy = small.name_strategy, | |
| 5461 | .captures = captures, | |
| 5462 | .capture_names = capture_names, | |
| 5463 | .decls = decls, | |
| 5464 | .kind = small.kind, | |
| 5465 | .arg_type_body = arg_type_body, | |
| 5466 | .field_names = field_names, | |
| 5467 | .field_type_body_lens = field_type_body_lens, | |
| 5468 | .field_align_body_lens = field_align_body_lens, | |
| 5469 | .field_value_body_lens = field_value_body_lens, | |
| 5470 | .field_bodies_overlong = field_bodies_overlong, | |
| 5471 | }; | |
| 5514 | 5472 | } |
| 5473 | pub const UnwrappedUnionDecl = struct { | |
| 5474 | src_line: u32, | |
| 5475 | src_node: Ast.Node.Index, | |
| 5476 | name_strategy: Inst.NameStrategy, | |
| 5477 | ||
| 5478 | captures: []const Inst.Capture, | |
| 5479 | capture_names: []const NullTerminatedString, | |
| 5480 | ||
| 5481 | decls: []const Inst.Index, | |
| 5482 | ||
| 5483 | kind: Inst.UnionDecl.Kind, | |
| 5484 | arg_type_body: ?[]const Inst.Index, | |
| 5485 | ||
| 5486 | field_names: []const NullTerminatedString, | |
| 5487 | field_type_body_lens: []const u32, | |
| 5488 | field_align_body_lens: ?[]const u32, | |
| 5489 | field_value_body_lens: ?[]const u32, | |
| 5490 | field_bodies_overlong: []const Inst.Index, | |
| 5491 | ||
| 5492 | pub fn iterateFields(union_decl: UnwrappedUnionDecl) FieldIterator { | |
| 5493 | return .{ | |
| 5494 | .next_idx = 0, | |
| 5495 | .names = union_decl.field_names, | |
| 5496 | .type_body_lens = union_decl.field_type_body_lens, | |
| 5497 | .align_body_lens = union_decl.field_align_body_lens, | |
| 5498 | .value_body_lens = union_decl.field_value_body_lens, | |
| 5499 | .bodies_overlong = union_decl.field_bodies_overlong, | |
| 5500 | }; | |
| 5501 | } | |
| 5502 | ||
| 5503 | pub const FieldIterator = struct { | |
| 5504 | next_idx: u32, | |
| 5505 | names: []const NullTerminatedString, | |
| 5506 | type_body_lens: []const u32, | |
| 5507 | align_body_lens: ?[]const u32, | |
| 5508 | value_body_lens: ?[]const u32, | |
| 5509 | bodies_overlong: []const Inst.Index, | |
| 5510 | pub const Field = struct { | |
| 5511 | idx: u32, | |
| 5512 | name: NullTerminatedString, | |
| 5513 | type_body: ?[]const Inst.Index, | |
| 5514 | align_body: ?[]const Inst.Index, | |
| 5515 | value_body: ?[]const Inst.Index, | |
| 5516 | }; | |
| 5517 | pub fn next(it: *FieldIterator) ?Field { | |
| 5518 | const idx = it.next_idx; | |
| 5519 | if (idx == it.names.len) return null; | |
| 5520 | it.next_idx += 1; | |
| 5521 | return .{ | |
| 5522 | .idx = idx, | |
| 5523 | .name = it.names[idx], | |
| 5524 | .type_body = it.body(it.type_body_lens[idx]), | |
| 5525 | .align_body = it.body(if (it.align_body_lens) |l| l[idx] else 0), | |
| 5526 | .value_body = it.body(if (it.value_body_lens) |l| l[idx] else 0), | |
| 5527 | }; | |
| 5528 | } | |
| 5529 | fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index { | |
| 5530 | if (len == 0) return null; | |
| 5531 | const b = it.bodies_overlong[0..len]; | |
| 5532 | it.bodies_overlong = it.bodies_overlong[len..]; | |
| 5533 | return b; | |
| 5534 | } | |
| 5535 | }; | |
| 5536 | }; | |
| 5537 | ||
| 5538 | pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { | |
| 5539 | const inst_data = zir.instructions.get(@intFromEnum(enum_decl)); | |
| 5540 | assert(inst_data.tag == .extended); | |
| 5541 | assert(inst_data.data.extended.opcode == .enum_decl); | |
| 5542 | const small: Inst.EnumDecl.Small = @bitCast(inst_data.data.extended.small); | |
| 5543 | const extra = zir.extraData(Inst.EnumDecl, inst_data.data.extended.operand); | |
| 5544 | var extra_index = extra.end; | |
| 5545 | const captures_len: u32 = if (small.has_captures_len) blk: { | |
| 5546 | const captures_len = zir.extra[extra_index]; | |
| 5547 | extra_index += 1; | |
| 5548 | break :blk captures_len; | |
| 5549 | } else 0; | |
| 5550 | const decls_len: u32 = if (small.has_decls_len) blk: { | |
| 5551 | const decls_len = zir.extra[extra_index]; | |
| 5552 | extra_index += 1; | |
| 5553 | break :blk decls_len; | |
| 5554 | } else 0; | |
| 5555 | const fields_len: u32 = if (small.has_fields_len) blk: { | |
| 5556 | const fields_len = zir.extra[extra_index]; | |
| 5557 | extra_index += 1; | |
| 5558 | break :blk fields_len; | |
| 5559 | } else 0; | |
| 5560 | const tag_type_body_len: u32 = if (small.has_tag_type) len: { | |
| 5561 | const body_len = zir.extra[extra_index]; | |
| 5562 | extra_index += 1; | |
| 5563 | break :len body_len; | |
| 5564 | } else 0; | |
| 5565 | const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5566 | extra_index += captures_len; | |
| 5567 | const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5568 | extra_index += captures_len; | |
| 5569 | const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); | |
| 5570 | extra_index += decls_len; | |
| 5571 | const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]); | |
| 5572 | extra_index += fields_len; | |
| 5573 | const field_value_body_lens: ?[]const u32 = if (small.any_field_values) lens: { | |
| 5574 | const lens = zir.extra[extra_index..][0..fields_len]; | |
| 5575 | extra_index += fields_len; | |
| 5576 | break :lens @ptrCast(lens); | |
| 5577 | } else null; | |
| 5578 | const tag_type_body: ?[]const Zir.Inst.Index = switch (tag_type_body_len) { | |
| 5579 | 0 => null, | |
| 5580 | else => |n| zir.bodySlice(extra_index, n), | |
| 5581 | }; | |
| 5582 | extra_index += tag_type_body_len; | |
| 5583 | const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); | |
| 5584 | return .{ | |
| 5585 | .src_line = extra.data.src_line, | |
| 5586 | .src_node = extra.data.src_node, | |
| 5587 | .name_strategy = small.name_strategy, | |
| 5588 | .captures = captures, | |
| 5589 | .capture_names = capture_names, | |
| 5590 | .decls = decls, | |
| 5591 | .tag_type_body = tag_type_body, | |
| 5592 | .nonexhaustive = small.nonexhaustive, | |
| 5593 | .field_names = field_names, | |
| 5594 | .field_value_body_lens = field_value_body_lens, | |
| 5595 | .field_bodies_overlong = field_bodies_overlong, | |
| 5596 | }; | |
| 5597 | } | |
| 5598 | pub const UnwrappedEnumDecl = struct { | |
| 5599 | src_line: u32, | |
| 5600 | src_node: Ast.Node.Index, | |
| 5601 | name_strategy: Inst.NameStrategy, | |
| 5602 | ||
| 5603 | captures: []const Inst.Capture, | |
| 5604 | capture_names: []const NullTerminatedString, | |
| 5605 | ||
| 5606 | decls: []const Inst.Index, | |
| 5607 | ||
| 5608 | tag_type_body: ?[]const Inst.Index, | |
| 5609 | nonexhaustive: bool, | |
| 5610 | ||
| 5611 | field_names: []const NullTerminatedString, | |
| 5612 | field_value_body_lens: ?[]const u32, | |
| 5613 | field_bodies_overlong: []const Inst.Index, | |
| 5614 | ||
| 5615 | pub fn iterateFields(enum_decl: UnwrappedEnumDecl) FieldIterator { | |
| 5616 | return .{ | |
| 5617 | .next_idx = 0, | |
| 5618 | .names = enum_decl.field_names, | |
| 5619 | .value_body_lens = enum_decl.field_value_body_lens, | |
| 5620 | .bodies_overlong = enum_decl.field_bodies_overlong, | |
| 5621 | }; | |
| 5622 | } | |
| 5623 | ||
| 5624 | pub const FieldIterator = struct { | |
| 5625 | next_idx: u32, | |
| 5626 | names: []const NullTerminatedString, | |
| 5627 | value_body_lens: ?[]const u32, | |
| 5628 | bodies_overlong: []const Inst.Index, | |
| 5629 | pub const Field = struct { | |
| 5630 | idx: u32, | |
| 5631 | name: NullTerminatedString, | |
| 5632 | value_body: ?[]const Inst.Index, | |
| 5633 | }; | |
| 5634 | pub fn next(it: *FieldIterator) ?Field { | |
| 5635 | const idx = it.next_idx; | |
| 5636 | if (idx == it.names.len) return null; | |
| 5637 | it.next_idx += 1; | |
| 5638 | return .{ | |
| 5639 | .idx = idx, | |
| 5640 | .name = it.names[idx], | |
| 5641 | .value_body = it.body(if (it.value_body_lens) |l| l[idx] else 0), | |
| 5642 | }; | |
| 5643 | } | |
| 5644 | fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index { | |
| 5645 | if (len == 0) return null; | |
| 5646 | const b = it.bodies_overlong[0..len]; | |
| 5647 | it.bodies_overlong = it.bodies_overlong[len..]; | |
| 5648 | return b; | |
| 5649 | } | |
| 5650 | }; | |
| 5651 | }; | |
| 5652 | ||
| 5653 | pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDecl { | |
| 5654 | const inst_data = zir.instructions.get(@intFromEnum(opaque_decl)); | |
| 5655 | assert(inst_data.tag == .extended); | |
| 5656 | assert(inst_data.data.extended.opcode == .opaque_decl); | |
| 5657 | const small: Inst.OpaqueDecl.Small = @bitCast(inst_data.data.extended.small); | |
| 5658 | const extra = zir.extraData(Inst.OpaqueDecl, inst_data.data.extended.operand); | |
| 5659 | var extra_index = extra.end; | |
| 5660 | const captures_len: u32 = if (small.has_captures_len) blk: { | |
| 5661 | const captures_len = zir.extra[extra_index]; | |
| 5662 | extra_index += 1; | |
| 5663 | break :blk captures_len; | |
| 5664 | } else 0; | |
| 5665 | const decls_len: u32 = if (small.has_decls_len) blk: { | |
| 5666 | const decls_len = zir.extra[extra_index]; | |
| 5667 | extra_index += 1; | |
| 5668 | break :blk decls_len; | |
| 5669 | } else 0; | |
| 5670 | const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5671 | extra_index += captures_len; | |
| 5672 | const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); | |
| 5673 | extra_index += captures_len; | |
| 5674 | const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); | |
| 5675 | extra_index += decls_len; | |
| 5676 | return .{ | |
| 5677 | .src_line = extra.data.src_line, | |
| 5678 | .src_node = extra.data.src_node, | |
| 5679 | .name_strategy = small.name_strategy, | |
| 5680 | .captures = captures, | |
| 5681 | .capture_names = capture_names, | |
| 5682 | .decls = decls, | |
| 5683 | }; | |
| 5684 | } | |
| 5685 | pub const UnwrappedOpaqueDecl = struct { | |
| 5686 | src_line: u32, | |
| 5687 | src_node: Ast.Node.Index, | |
| 5688 | name_strategy: Inst.NameStrategy, | |
| 5689 | captures: []const Inst.Capture, | |
| 5690 | capture_names: []const NullTerminatedString, | |
| 5691 | decls: []const Inst.Index, | |
| 5692 | }; |
lib/std/zig/llvm/BitcodeReader.zig+5-5| ... | ... | @@ -34,8 +34,8 @@ pub const Block = struct { |
| 34 | 34 | |
| 35 | 35 | const default: Info = .{ |
| 36 | 36 | .block_name = &.{}, |
| 37 | .record_names = .{}, | |
| 38 | .abbrevs = .{ .abbrevs = .{} }, | |
| 37 | .record_names = .empty, | |
| 38 | .abbrevs = .{ .abbrevs = .empty }, | |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | 41 | const set_bid_id: u32 = 1; |
| ... | ... | @@ -109,8 +109,8 @@ pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader { |
| 109 | 109 | .keep_names = options.keep_names, |
| 110 | 110 | .bit_buffer = 0, |
| 111 | 111 | .bit_offset = 0, |
| 112 | .stack = .{}, | |
| 113 | .block_info = .{}, | |
| 112 | .stack = .empty, | |
| 113 | .block_info = .empty, | |
| 114 | 114 | }; |
| 115 | 115 | } |
| 116 | 116 | |
| ... | ... | @@ -278,7 +278,7 @@ fn startBlock(bc: *BitcodeReader, block_id: ?u32, new_abbrev_len: u6) !void { |
| 278 | 278 | state.* = .{ |
| 279 | 279 | .block_id = block_id, |
| 280 | 280 | .abbrev_id_width = new_abbrev_len, |
| 281 | .abbrevs = .{ .abbrevs = .{} }, | |
| 281 | .abbrevs = .{ .abbrevs = .empty }, | |
| 282 | 282 | }; |
| 283 | 283 | try state.abbrevs.abbrevs.ensureTotalCapacity( |
| 284 | 284 | bc.allocator, |
lib/std/zig/llvm/Builder.zig+238-126| ... | ... | @@ -7,6 +7,7 @@ const Allocator = std.mem.Allocator; |
| 7 | 7 | const assert = std.debug.assert; |
| 8 | 8 | const DW = std.dwarf; |
| 9 | 9 | const log = std.log.scoped(.llvm); |
| 10 | const maxInt = std.math.maxInt; | |
| 10 | 11 | const Writer = std.Io.Writer; |
| 11 | 12 | |
| 12 | 13 | const bitcode_writer = @import("bitcode_writer.zig"); |
| ... | ... | @@ -55,6 +56,8 @@ constant_items: std.MultiArrayList(Constant.Item), |
| 55 | 56 | constant_extra: std.ArrayList(u32), |
| 56 | 57 | constant_limbs: std.ArrayList(std.math.big.Limb), |
| 57 | 58 | |
| 59 | alignment_forward_references: std.ArrayList(Alignment), | |
| 60 | ||
| 58 | 61 | metadata_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 59 | 62 | metadata_items: std.MultiArrayList(Metadata.Item), |
| 60 | 63 | metadata_extra: std.ArrayList(u32), |
| ... | ... | @@ -85,7 +88,7 @@ pub const Options = struct { |
| 85 | 88 | }; |
| 86 | 89 | |
| 87 | 90 | pub const String = enum(u32) { |
| 88 | none = std.math.maxInt(u31), | |
| 91 | none = maxInt(u31), | |
| 89 | 92 | empty, |
| 90 | 93 | _, |
| 91 | 94 | |
| ... | ... | @@ -245,7 +248,7 @@ pub const Type = enum(u32) { |
| 245 | 248 | ptr, |
| 246 | 249 | @"ptr addrspace(4)", |
| 247 | 250 | |
| 248 | none = std.math.maxInt(u32), | |
| 251 | none = maxInt(u32), | |
| 249 | 252 | _, |
| 250 | 253 | |
| 251 | 254 | pub const ptr_amdgpu_constant = |
| ... | ... | @@ -941,7 +944,7 @@ pub const Attribute = union(Kind) { |
| 941 | 944 | inalloca: Type, |
| 942 | 945 | sret: Type, |
| 943 | 946 | elementtype: Type, |
| 944 | @"align": Alignment, | |
| 947 | @"align": Alignment.Lazy, | |
| 945 | 948 | @"noalias", |
| 946 | 949 | nocapture, |
| 947 | 950 | nofree, |
| ... | ... | @@ -956,7 +959,7 @@ pub const Attribute = union(Kind) { |
| 956 | 959 | immarg, |
| 957 | 960 | noundef, |
| 958 | 961 | nofpclass: FpClass, |
| 959 | alignstack: Alignment, | |
| 962 | alignstack: Alignment.Lazy, | |
| 960 | 963 | allocalign, |
| 961 | 964 | allocptr, |
| 962 | 965 | readnone, |
| ... | ... | @@ -964,7 +967,7 @@ pub const Attribute = union(Kind) { |
| 964 | 967 | writeonly, |
| 965 | 968 | |
| 966 | 969 | // Function Attributes |
| 967 | //alignstack: Alignment, | |
| 970 | //alignstack: Alignment.Lazy, | |
| 968 | 971 | allockind: AllocKind, |
| 969 | 972 | allocsize: AllocSize, |
| 970 | 973 | alwaysinline, |
| ... | ... | @@ -1145,7 +1148,7 @@ pub const Attribute = union(Kind) { |
| 1145 | 1148 | return @unionInit(Attribute, field.name, switch (field.type) { |
| 1146 | 1149 | void => {}, |
| 1147 | 1150 | u32 => storage.value, |
| 1148 | Alignment, String, Type, UwTable => @enumFromInt(storage.value), | |
| 1151 | Alignment.Lazy, String, Type, UwTable => @enumFromInt(storage.value), | |
| 1149 | 1152 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), |
| 1150 | 1153 | else => @compileError("bad payload type: " ++ field.name ++ ": " ++ |
| 1151 | 1154 | @typeName(field.type)), |
| ... | ... | @@ -1246,7 +1249,7 @@ pub const Attribute = union(Kind) { |
| 1246 | 1249 | .sret, |
| 1247 | 1250 | .elementtype, |
| 1248 | 1251 | => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }), |
| 1249 | .@"align" => |alignment| try w.print("{f}", .{alignment.fmt(" ")}), | |
| 1252 | .@"align" => |alignment| try w.print("{f}", .{alignment.resolve(data.builder).fmt(" ")}), | |
| 1250 | 1253 | .dereferenceable, |
| 1251 | 1254 | .dereferenceable_or_null, |
| 1252 | 1255 | => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }), |
| ... | ... | @@ -1270,7 +1273,7 @@ pub const Attribute = union(Kind) { |
| 1270 | 1273 | }, |
| 1271 | 1274 | .alignstack => |alignment| { |
| 1272 | 1275 | try w.print(" {t}", .{attribute}); |
| 1273 | const alignment_bytes = alignment.toByteUnits() orelse return; | |
| 1276 | const alignment_bytes = alignment.resolve(data.builder).toByteUnits() orelse return; | |
| 1274 | 1277 | if (data.flags.pound) { |
| 1275 | 1278 | try w.print("={d}", .{alignment_bytes}); |
| 1276 | 1279 | } else { |
| ... | ... | @@ -1435,8 +1438,8 @@ pub const Attribute = union(Kind) { |
| 1435 | 1438 | //sanitize_memtag, |
| 1436 | 1439 | sanitize_address_dyninit = 102, |
| 1437 | 1440 | |
| 1438 | string = std.math.maxInt(u31), | |
| 1439 | none = std.math.maxInt(u32), | |
| 1441 | string = maxInt(u31), | |
| 1442 | none = maxInt(u32), | |
| 1440 | 1443 | _, |
| 1441 | 1444 | |
| 1442 | 1445 | pub const len = @typeInfo(Kind).@"enum".fields.len - 2; |
| ... | ... | @@ -1516,12 +1519,12 @@ pub const Attribute = union(Kind) { |
| 1516 | 1519 | elem_size: u16, |
| 1517 | 1520 | num_elems: u16, |
| 1518 | 1521 | |
| 1519 | pub const none = std.math.maxInt(u16); | |
| 1522 | pub const none = maxInt(u16); | |
| 1520 | 1523 | |
| 1521 | 1524 | fn toLlvm(self: AllocSize) packed struct(u64) { num_elems: u32, elem_size: u32 } { |
| 1522 | 1525 | return .{ .num_elems = switch (self.num_elems) { |
| 1523 | 1526 | else => self.num_elems, |
| 1524 | none => std.math.maxInt(u32), | |
| 1527 | none => maxInt(u32), | |
| 1525 | 1528 | }, .elem_size = self.elem_size }; |
| 1526 | 1529 | } |
| 1527 | 1530 | }; |
| ... | ... | @@ -1577,7 +1580,7 @@ pub const Attribute = union(Kind) { |
| 1577 | 1580 | inline else => |value, tag| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) { |
| 1578 | 1581 | void => 0, |
| 1579 | 1582 | u32 => value, |
| 1580 | Alignment, String, Type, UwTable => @intFromEnum(value), | |
| 1583 | Alignment.Lazy, String, Type, UwTable => @intFromEnum(value), | |
| 1581 | 1584 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), |
| 1582 | 1585 | else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))), |
| 1583 | 1586 | } }, |
| ... | ... | @@ -1627,7 +1630,7 @@ pub const FunctionAttributes = enum(u32) { |
| 1627 | 1630 | const params_index = 2; |
| 1628 | 1631 | |
| 1629 | 1632 | pub const Wip = struct { |
| 1630 | maps: Maps = .{}, | |
| 1633 | maps: Maps = .empty, | |
| 1631 | 1634 | |
| 1632 | 1635 | const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index); |
| 1633 | 1636 | const Maps = std.ArrayList(Map); |
| ... | ... | @@ -2017,9 +2020,32 @@ pub const ExternallyInitialized = enum { |
| 2017 | 2020 | }; |
| 2018 | 2021 | |
| 2019 | 2022 | pub const Alignment = enum(u6) { |
| 2020 | default = std.math.maxInt(u6), | |
| 2023 | default = maxInt(u6), | |
| 2021 | 2024 | _, |
| 2022 | 2025 | |
| 2026 | pub const Lazy = enum(u32) { | |
| 2027 | /// Values which fit in a `u6` are already-resolved `Alignment` values. Other values are | |
| 2028 | /// indices into `Builder.alignment_forward_references`, offset by `maxInt(u6)`. | |
| 2029 | _, | |
| 2030 | ||
| 2031 | pub fn wrap(a: Alignment) Lazy { | |
| 2032 | return @enumFromInt(@intFromEnum(a)); | |
| 2033 | } | |
| 2034 | pub fn resolve(l: Lazy, b: *const Builder) Alignment { | |
| 2035 | return switch (@intFromEnum(l)) { | |
| 2036 | 0...maxInt(u6) => |raw| @enumFromInt(raw), | |
| 2037 | else => |offset_index| b.alignment_forward_references.items[offset_index - maxInt(u6)], | |
| 2038 | }; | |
| 2039 | } | |
| 2040 | ||
| 2041 | fn fromFwdRefIndex(index: usize) Lazy { | |
| 2042 | return @enumFromInt(index + maxInt(u6)); | |
| 2043 | } | |
| 2044 | fn toFwdRefIndex(l: Lazy) usize { | |
| 2045 | return @intFromEnum(l) - maxInt(u6); | |
| 2046 | } | |
| 2047 | }; | |
| 2048 | ||
| 2023 | 2049 | pub fn fromByteUnits(bytes: u64) Alignment { |
| 2024 | 2050 | if (bytes == 0) return .default; |
| 2025 | 2051 | assert(std.math.isPowerOfTwo(bytes)); |
| ... | ... | @@ -2028,11 +2054,17 @@ pub const Alignment = enum(u6) { |
| 2028 | 2054 | } |
| 2029 | 2055 | |
| 2030 | 2056 | pub fn toByteUnits(self: Alignment) ?u64 { |
| 2031 | return if (self == .default) null else @as(u64, 1) << @intFromEnum(self); | |
| 2057 | return switch (self) { | |
| 2058 | .default => null, | |
| 2059 | else => @as(u64, 1) << @intFromEnum(self), | |
| 2060 | }; | |
| 2032 | 2061 | } |
| 2033 | 2062 | |
| 2034 | 2063 | pub fn toLlvm(self: Alignment) u6 { |
| 2035 | return if (self == .default) 0 else (@intFromEnum(self) + 1); | |
| 2064 | return switch (self) { | |
| 2065 | .default => 0, | |
| 2066 | else => @intFromEnum(self) + 1, | |
| 2067 | }; | |
| 2036 | 2068 | } |
| 2037 | 2069 | |
| 2038 | 2070 | pub const Prefixed = struct { |
| ... | ... | @@ -2180,7 +2212,7 @@ pub const CallConv = enum(u10) { |
| 2180 | 2212 | }; |
| 2181 | 2213 | |
| 2182 | 2214 | pub const StrtabString = enum(u32) { |
| 2183 | none = std.math.maxInt(u31), | |
| 2215 | none = maxInt(u31), | |
| 2184 | 2216 | empty, |
| 2185 | 2217 | _, |
| 2186 | 2218 | |
| ... | ... | @@ -2308,7 +2340,7 @@ pub const Global = struct { |
| 2308 | 2340 | }, |
| 2309 | 2341 | |
| 2310 | 2342 | pub const Index = enum(u32) { |
| 2311 | none = std.math.maxInt(u32), | |
| 2343 | none = maxInt(u32), | |
| 2312 | 2344 | _, |
| 2313 | 2345 | |
| 2314 | 2346 | pub fn unwrap(self: Index, builder: *const Builder) Index { |
| ... | ... | @@ -2478,7 +2510,7 @@ pub const Alias = struct { |
| 2478 | 2510 | aliasee: Constant = .no_init, |
| 2479 | 2511 | |
| 2480 | 2512 | pub const Index = enum(u32) { |
| 2481 | none = std.math.maxInt(u32), | |
| 2513 | none = maxInt(u32), | |
| 2482 | 2514 | _, |
| 2483 | 2515 | |
| 2484 | 2516 | pub fn ptr(self: Index, builder: *Builder) *Alias { |
| ... | ... | @@ -2530,7 +2562,7 @@ pub const Variable = struct { |
| 2530 | 2562 | alignment: Alignment = .default, |
| 2531 | 2563 | |
| 2532 | 2564 | pub const Index = enum(u32) { |
| 2533 | none = std.math.maxInt(u32), | |
| 2565 | none = maxInt(u32), | |
| 2534 | 2566 | _, |
| 2535 | 2567 | |
| 2536 | 2568 | pub fn ptr(self: Index, builder: *Builder) *Variable { |
| ... | ... | @@ -3949,7 +3981,7 @@ pub const Intrinsic = enum { |
| 3949 | 3981 | .params = &.{ |
| 3950 | 3982 | .{ |
| 3951 | 3983 | .kind = .{ .type = Type.ptr_amdgpu_constant }, |
| 3952 | .attrs = &.{.{ .@"align" = Builder.Alignment.fromByteUnits(4) }}, | |
| 3984 | .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }}, | |
| 3953 | 3985 | }, |
| 3954 | 3986 | }, |
| 3955 | 3987 | .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, |
| ... | ... | @@ -4048,7 +4080,7 @@ pub const Function = struct { |
| 4048 | 4080 | section: String = .none, |
| 4049 | 4081 | alignment: Alignment = .default, |
| 4050 | 4082 | blocks: []const Block = &.{}, |
| 4051 | instructions: std.MultiArrayList(Instruction) = .{}, | |
| 4083 | instructions: std.MultiArrayList(Instruction) = .empty, | |
| 4052 | 4084 | names: [*]const String = &[0]String{}, |
| 4053 | 4085 | value_indices: [*]const u32 = &[0]u32{}, |
| 4054 | 4086 | strip: bool, |
| ... | ... | @@ -4057,7 +4089,7 @@ pub const Function = struct { |
| 4057 | 4089 | extra: []const u32 = &.{}, |
| 4058 | 4090 | |
| 4059 | 4091 | pub const Index = enum(u32) { |
| 4060 | none = std.math.maxInt(u32), | |
| 4092 | none = maxInt(u32), | |
| 4061 | 4093 | _, |
| 4062 | 4094 | |
| 4063 | 4095 | pub fn ptr(self: Index, builder: *Builder) *Function { |
| ... | ... | @@ -4411,7 +4443,7 @@ pub const Function = struct { |
| 4411 | 4443 | }; |
| 4412 | 4444 | |
| 4413 | 4445 | pub const Index = enum(u32) { |
| 4414 | none = std.math.maxInt(u31), | |
| 4446 | none = maxInt(u31), | |
| 4415 | 4447 | _, |
| 4416 | 4448 | |
| 4417 | 4449 | pub fn name(self: Instruction.Index, function: *const Function) String { |
| ... | ... | @@ -5007,7 +5039,7 @@ pub const Function = struct { |
| 5007 | 5039 | fsub = 12, |
| 5008 | 5040 | fmax = 13, |
| 5009 | 5041 | fmin = 14, |
| 5010 | none = std.math.maxInt(u5), | |
| 5042 | none = maxInt(u5), | |
| 5011 | 5043 | }; |
| 5012 | 5044 | }; |
| 5013 | 5045 | |
| ... | ... | @@ -5222,13 +5254,13 @@ pub const WipFunction = struct { |
| 5222 | 5254 | .prev_debug_location = .no_location, |
| 5223 | 5255 | .debug_location = .no_location, |
| 5224 | 5256 | .cursor = undefined, |
| 5225 | .blocks = .{}, | |
| 5226 | .instructions = .{}, | |
| 5227 | .names = .{}, | |
| 5257 | .blocks = .empty, | |
| 5258 | .instructions = .empty, | |
| 5259 | .names = .empty, | |
| 5228 | 5260 | .strip = options.strip, |
| 5229 | .debug_locations = .{}, | |
| 5230 | .debug_values = .{}, | |
| 5231 | .extra = .{}, | |
| 5261 | .debug_locations = .empty, | |
| 5262 | .debug_values = .empty, | |
| 5263 | .extra = .empty, | |
| 5232 | 5264 | }; |
| 5233 | 5265 | errdefer self.deinit(); |
| 5234 | 5266 | |
| ... | ... | @@ -5265,7 +5297,7 @@ pub const WipFunction = struct { |
| 5265 | 5297 | self.blocks.appendAssumeCapacity(.{ |
| 5266 | 5298 | .name = final_name, |
| 5267 | 5299 | .incoming = incoming, |
| 5268 | .instructions = .{}, | |
| 5300 | .instructions = .empty, | |
| 5269 | 5301 | }); |
| 5270 | 5302 | return index; |
| 5271 | 5303 | } |
| ... | ... | @@ -6132,8 +6164,8 @@ pub const WipFunction = struct { |
| 6132 | 6164 | kind: MemoryAccessKind, |
| 6133 | 6165 | @"inline": bool, |
| 6134 | 6166 | ) Allocator.Error!Instruction.Index { |
| 6135 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; | |
| 6136 | var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })}; | |
| 6167 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(dst_align) })}; | |
| 6168 | var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(src_align) })}; | |
| 6137 | 6169 | const value = try self.callIntrinsic( |
| 6138 | 6170 | .normal, |
| 6139 | 6171 | try self.builder.fnAttrs(&.{ |
| ... | ... | @@ -6162,8 +6194,8 @@ pub const WipFunction = struct { |
| 6162 | 6194 | len: Value, |
| 6163 | 6195 | kind: MemoryAccessKind, |
| 6164 | 6196 | ) Allocator.Error!Instruction.Index { |
| 6165 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; | |
| 6166 | var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })}; | |
| 6197 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(dst_align) })}; | |
| 6198 | var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(src_align) })}; | |
| 6167 | 6199 | const value = try self.callIntrinsic( |
| 6168 | 6200 | .normal, |
| 6169 | 6201 | try self.builder.fnAttrs(&.{ |
| ... | ... | @@ -6192,7 +6224,7 @@ pub const WipFunction = struct { |
| 6192 | 6224 | kind: MemoryAccessKind, |
| 6193 | 6225 | @"inline": bool, |
| 6194 | 6226 | ) Allocator.Error!Instruction.Index { |
| 6195 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; | |
| 6227 | var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(dst_align) })}; | |
| 6196 | 6228 | const value = try self.callIntrinsic( |
| 6197 | 6229 | .normal, |
| 6198 | 6230 | try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }), |
| ... | ... | @@ -6325,7 +6357,7 @@ pub const WipFunction = struct { |
| 6325 | 6357 | function.blocks = &.{}; |
| 6326 | 6358 | gpa.free(function.names[0..function.instructions.len]); |
| 6327 | 6359 | function.debug_locations.deinit(gpa); |
| 6328 | function.debug_locations = .{}; | |
| 6360 | function.debug_locations = .empty; | |
| 6329 | 6361 | gpa.free(function.debug_values); |
| 6330 | 6362 | function.debug_values = &.{}; |
| 6331 | 6363 | gpa.free(function.extra); |
| ... | ... | @@ -7329,7 +7361,7 @@ pub const Constant = enum(u32) { |
| 7329 | 7361 | //indices: [info.indices_len]Constant, |
| 7330 | 7362 | |
| 7331 | 7363 | pub const Kind = enum { normal, inbounds }; |
| 7332 | pub const InRangeIndex = enum(u16) { none = std.math.maxInt(u16), _ }; | |
| 7364 | pub const InRangeIndex = enum(u16) { none = maxInt(u16), _ }; | |
| 7333 | 7365 | pub const Info = packed struct(u32) { indices_len: u16, inrange: InRangeIndex }; |
| 7334 | 7366 | }; |
| 7335 | 7367 | |
| ... | ... | @@ -7579,7 +7611,7 @@ pub const Constant = enum(u32) { |
| 7579 | 7611 | string: [ |
| 7580 | 7612 | (std.math.big.int.Const{ |
| 7581 | 7613 | .limbs = &([1]std.math.big.Limb{ |
| 7582 | std.math.maxInt(std.math.big.Limb), | |
| 7614 | maxInt(std.math.big.Limb), | |
| 7583 | 7615 | } ** expected_limbs), |
| 7584 | 7616 | .positive = false, |
| 7585 | 7617 | }).sizeInBaseUpperBound(10) |
| ... | ... | @@ -7643,7 +7675,7 @@ pub const Constant = enum(u32) { |
| 7643 | 7675 | std.math.minInt(Exponent64), |
| 7644 | 7676 | else => @as(Exponent64, repr.exponent) + |
| 7645 | 7677 | (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)), |
| 7646 | std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64), | |
| 7678 | maxInt(Exponent32) => maxInt(Exponent64), | |
| 7647 | 7679 | }, |
| 7648 | 7680 | .sign = repr.sign, |
| 7649 | 7681 | }))}); |
| ... | ... | @@ -7820,7 +7852,7 @@ pub const Constant = enum(u32) { |
| 7820 | 7852 | }; |
| 7821 | 7853 | |
| 7822 | 7854 | pub const Value = enum(u32) { |
| 7823 | none = std.math.maxInt(u31), | |
| 7855 | none = maxInt(u31), | |
| 7824 | 7856 | false = first_constant + @intFromEnum(Constant.false), |
| 7825 | 7857 | true = first_constant + @intFromEnum(Constant.true), |
| 7826 | 7858 | @"0" = first_constant + @intFromEnum(Constant.@"0"), |
| ... | ... | @@ -8021,6 +8053,7 @@ pub const Metadata = packed struct(u32) { |
| 8021 | 8053 | composite_vector_type, |
| 8022 | 8054 | derived_pointer_type, |
| 8023 | 8055 | derived_member_type, |
| 8056 | derived_typedef_type, | |
| 8024 | 8057 | subroutine_type, |
| 8025 | 8058 | enumerator_unsigned, |
| 8026 | 8059 | enumerator_signed_positive, |
| ... | ... | @@ -8064,6 +8097,7 @@ pub const Metadata = packed struct(u32) { |
| 8064 | 8097 | .composite_vector_type, |
| 8065 | 8098 | .derived_pointer_type, |
| 8066 | 8099 | .derived_member_type, |
| 8100 | .derived_typedef_type, | |
| 8067 | 8101 | .subroutine_type, |
| 8068 | 8102 | .enumerator_unsigned, |
| 8069 | 8103 | .enumerator_signed_positive, |
| ... | ... | @@ -8391,7 +8425,7 @@ pub const Metadata = packed struct(u32) { |
| 8391 | 8425 | map: std.AutoArrayHashMapUnmanaged(union(enum) { |
| 8392 | 8426 | metadata: Metadata, |
| 8393 | 8427 | debug_location: DebugLocation.Location, |
| 8394 | }, void) = .{}, | |
| 8428 | }, void) = .empty, | |
| 8395 | 8429 | |
| 8396 | 8430 | const FormatData = struct { |
| 8397 | 8431 | formatter: *Formatter, |
| ... | ... | @@ -8649,52 +8683,54 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8649 | 8683 | .source_filename = .none, |
| 8650 | 8684 | .data_layout = .none, |
| 8651 | 8685 | .target_triple = .none, |
| 8652 | .module_asm = .{}, | |
| 8686 | .module_asm = .empty, | |
| 8653 | 8687 | |
| 8654 | .string_map = .{}, | |
| 8655 | .string_indices = .{}, | |
| 8656 | .string_bytes = .{}, | |
| 8688 | .string_map = .empty, | |
| 8689 | .string_indices = .empty, | |
| 8690 | .string_bytes = .empty, | |
| 8657 | 8691 | |
| 8658 | .types = .{}, | |
| 8692 | .types = .empty, | |
| 8659 | 8693 | .next_unnamed_type = @enumFromInt(0), |
| 8660 | .next_unique_type_id = .{}, | |
| 8661 | .type_map = .{}, | |
| 8662 | .type_items = .{}, | |
| 8663 | .type_extra = .{}, | |
| 8694 | .next_unique_type_id = .empty, | |
| 8695 | .type_map = .empty, | |
| 8696 | .type_items = .empty, | |
| 8697 | .type_extra = .empty, | |
| 8664 | 8698 | |
| 8665 | .attributes = .{}, | |
| 8666 | .attributes_map = .{}, | |
| 8667 | .attributes_indices = .{}, | |
| 8668 | .attributes_extra = .{}, | |
| 8699 | .attributes = .empty, | |
| 8700 | .attributes_map = .empty, | |
| 8701 | .attributes_indices = .empty, | |
| 8702 | .attributes_extra = .empty, | |
| 8669 | 8703 | |
| 8670 | .function_attributes_set = .{}, | |
| 8704 | .function_attributes_set = .empty, | |
| 8671 | 8705 | |
| 8672 | .globals = .{}, | |
| 8706 | .globals = .empty, | |
| 8673 | 8707 | .next_unnamed_global = @enumFromInt(0), |
| 8674 | 8708 | .next_replaced_global = .none, |
| 8675 | .next_unique_global_id = .{}, | |
| 8676 | .aliases = .{}, | |
| 8677 | .variables = .{}, | |
| 8678 | .functions = .{}, | |
| 8679 | ||
| 8680 | .strtab_string_map = .{}, | |
| 8681 | .strtab_string_indices = .{}, | |
| 8682 | .strtab_string_bytes = .{}, | |
| 8683 | ||
| 8684 | .constant_map = .{}, | |
| 8685 | .constant_items = .{}, | |
| 8686 | .constant_extra = .{}, | |
| 8687 | .constant_limbs = .{}, | |
| 8688 | ||
| 8689 | .metadata_map = .{}, | |
| 8690 | .metadata_items = .{}, | |
| 8691 | .metadata_extra = .{}, | |
| 8692 | .metadata_limbs = .{}, | |
| 8693 | .metadata_forward_references = .{}, | |
| 8694 | .metadata_named = .{}, | |
| 8695 | .metadata_string_map = .{}, | |
| 8696 | .metadata_string_indices = .{}, | |
| 8697 | .metadata_string_bytes = .{}, | |
| 8709 | .next_unique_global_id = .empty, | |
| 8710 | .aliases = .empty, | |
| 8711 | .variables = .empty, | |
| 8712 | .functions = .empty, | |
| 8713 | ||
| 8714 | .strtab_string_map = .empty, | |
| 8715 | .strtab_string_indices = .empty, | |
| 8716 | .strtab_string_bytes = .empty, | |
| 8717 | ||
| 8718 | .constant_map = .empty, | |
| 8719 | .constant_items = .empty, | |
| 8720 | .constant_extra = .empty, | |
| 8721 | .constant_limbs = .empty, | |
| 8722 | ||
| 8723 | .alignment_forward_references = .empty, | |
| 8724 | ||
| 8725 | .metadata_map = .empty, | |
| 8726 | .metadata_items = .empty, | |
| 8727 | .metadata_extra = .empty, | |
| 8728 | .metadata_limbs = .empty, | |
| 8729 | .metadata_forward_references = .empty, | |
| 8730 | .metadata_named = .empty, | |
| 8731 | .metadata_string_map = .empty, | |
| 8732 | .metadata_string_indices = .empty, | |
| 8733 | .metadata_string_bytes = .empty, | |
| 8698 | 8734 | }; |
| 8699 | 8735 | errdefer self.deinit(); |
| 8700 | 8736 | |
| ... | ... | @@ -8798,51 +8834,55 @@ pub fn clearAndFree(self: *Builder) void { |
| 8798 | 8834 | } |
| 8799 | 8835 | |
| 8800 | 8836 | pub fn deinit(self: *Builder) void { |
| 8801 | self.module_asm.deinit(self.gpa); | |
| 8837 | const gpa = self.gpa; | |
| 8802 | 8838 | |
| 8803 | self.string_map.deinit(self.gpa); | |
| 8804 | self.string_indices.deinit(self.gpa); | |
| 8805 | self.string_bytes.deinit(self.gpa); | |
| 8839 | self.module_asm.deinit(gpa); | |
| 8806 | 8840 | |
| 8807 | self.types.deinit(self.gpa); | |
| 8808 | self.next_unique_type_id.deinit(self.gpa); | |
| 8809 | self.type_map.deinit(self.gpa); | |
| 8810 | self.type_items.deinit(self.gpa); | |
| 8811 | self.type_extra.deinit(self.gpa); | |
| 8841 | self.string_map.deinit(gpa); | |
| 8842 | self.string_indices.deinit(gpa); | |
| 8843 | self.string_bytes.deinit(gpa); | |
| 8812 | 8844 | |
| 8813 | self.attributes.deinit(self.gpa); | |
| 8814 | self.attributes_map.deinit(self.gpa); | |
| 8815 | self.attributes_indices.deinit(self.gpa); | |
| 8816 | self.attributes_extra.deinit(self.gpa); | |
| 8845 | self.types.deinit(gpa); | |
| 8846 | self.next_unique_type_id.deinit(gpa); | |
| 8847 | self.type_map.deinit(gpa); | |
| 8848 | self.type_items.deinit(gpa); | |
| 8849 | self.type_extra.deinit(gpa); | |
| 8817 | 8850 | |
| 8818 | self.function_attributes_set.deinit(self.gpa); | |
| 8851 | self.attributes.deinit(gpa); | |
| 8852 | self.attributes_map.deinit(gpa); | |
| 8853 | self.attributes_indices.deinit(gpa); | |
| 8854 | self.attributes_extra.deinit(gpa); | |
| 8819 | 8855 | |
| 8820 | self.globals.deinit(self.gpa); | |
| 8821 | self.next_unique_global_id.deinit(self.gpa); | |
| 8822 | self.aliases.deinit(self.gpa); | |
| 8823 | self.variables.deinit(self.gpa); | |
| 8824 | for (self.functions.items) |*function| function.deinit(self.gpa); | |
| 8825 | self.functions.deinit(self.gpa); | |
| 8856 | self.function_attributes_set.deinit(gpa); | |
| 8857 | ||
| 8858 | self.globals.deinit(gpa); | |
| 8859 | self.next_unique_global_id.deinit(gpa); | |
| 8860 | self.aliases.deinit(gpa); | |
| 8861 | self.variables.deinit(gpa); | |
| 8862 | for (self.functions.items) |*function| function.deinit(gpa); | |
| 8863 | self.functions.deinit(gpa); | |
| 8864 | ||
| 8865 | self.strtab_string_map.deinit(gpa); | |
| 8866 | self.strtab_string_indices.deinit(gpa); | |
| 8867 | self.strtab_string_bytes.deinit(gpa); | |
| 8826 | 8868 | |
| 8827 | self.strtab_string_map.deinit(self.gpa); | |
| 8828 | self.strtab_string_indices.deinit(self.gpa); | |
| 8829 | self.strtab_string_bytes.deinit(self.gpa); | |
| 8869 | self.constant_map.deinit(gpa); | |
| 8870 | self.constant_items.deinit(gpa); | |
| 8871 | self.constant_extra.deinit(gpa); | |
| 8872 | self.constant_limbs.deinit(gpa); | |
| 8830 | 8873 | |
| 8831 | self.constant_map.deinit(self.gpa); | |
| 8832 | self.constant_items.deinit(self.gpa); | |
| 8833 | self.constant_extra.deinit(self.gpa); | |
| 8834 | self.constant_limbs.deinit(self.gpa); | |
| 8874 | self.alignment_forward_references.deinit(gpa); | |
| 8835 | 8875 | |
| 8836 | self.metadata_map.deinit(self.gpa); | |
| 8837 | self.metadata_items.deinit(self.gpa); | |
| 8838 | self.metadata_extra.deinit(self.gpa); | |
| 8839 | self.metadata_limbs.deinit(self.gpa); | |
| 8840 | self.metadata_forward_references.deinit(self.gpa); | |
| 8841 | self.metadata_named.deinit(self.gpa); | |
| 8876 | self.metadata_map.deinit(gpa); | |
| 8877 | self.metadata_items.deinit(gpa); | |
| 8878 | self.metadata_extra.deinit(gpa); | |
| 8879 | self.metadata_limbs.deinit(gpa); | |
| 8880 | self.metadata_forward_references.deinit(gpa); | |
| 8881 | self.metadata_named.deinit(gpa); | |
| 8842 | 8882 | |
| 8843 | self.metadata_string_map.deinit(self.gpa); | |
| 8844 | self.metadata_string_indices.deinit(self.gpa); | |
| 8845 | self.metadata_string_bytes.deinit(self.gpa); | |
| 8883 | self.metadata_string_map.deinit(gpa); | |
| 8884 | self.metadata_string_indices.deinit(gpa); | |
| 8885 | self.metadata_string_bytes.deinit(gpa); | |
| 8846 | 8886 | |
| 8847 | 8887 | self.* = undefined; |
| 8848 | 8888 | } |
| ... | ... | @@ -8960,7 +9000,7 @@ pub fn structType( |
| 8960 | 9000 | pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type { |
| 8961 | 9001 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| 8962 | 9002 | if (name.slice(self)) |id| { |
| 8963 | const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); | |
| 9003 | const count: usize = comptime std.fmt.count("{d}", .{maxInt(u32)}); | |
| 8964 | 9004 | try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); |
| 8965 | 9005 | } |
| 8966 | 9006 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | ... | @@ -9576,6 +9616,21 @@ pub fn asmValue( |
| 9576 | 9616 | return (try self.asmConst(ty, info, assembly, constraints)).toValue(); |
| 9577 | 9617 | } |
| 9578 | 9618 | |
| 9619 | /// The initial "resolved" value of the forward reference is `Alignment.default`. | |
| 9620 | pub fn alignmentForwardReference(b: *Builder) Allocator.Error!Alignment.Lazy { | |
| 9621 | const index = b.alignment_forward_references.items.len; | |
| 9622 | try b.alignment_forward_references.append(b.gpa, .default); | |
| 9623 | return .fromFwdRefIndex(index); | |
| 9624 | } | |
| 9625 | ||
| 9626 | /// Updates the "resolved" value of the alignment forward reference `fwd_ref` to `value`. | |
| 9627 | /// | |
| 9628 | /// Asserts that `fwd_ref` is a forward reference, as opposed to a resolved alignment value. | |
| 9629 | pub fn resolveAlignmentForwardReference(b: *Builder, fwd_ref: Alignment.Lazy, value: Alignment) void { | |
| 9630 | const index = fwd_ref.toFwdRefIndex(); | |
| 9631 | b.alignment_forward_references.items[index] = value; | |
| 9632 | } | |
| 9633 | ||
| 9579 | 9634 | pub fn dump(b: *Builder, io: Io) void { |
| 9580 | 9635 | var buffer: [4000]u8 = undefined; |
| 9581 | 9636 | const stderr: Io.File = .stderr(); |
| ... | ... | @@ -10463,15 +10518,18 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10463 | 10518 | }, |
| 10464 | 10519 | .derived_pointer_type, |
| 10465 | 10520 | .derived_member_type, |
| 10521 | .derived_typedef_type, | |
| 10466 | 10522 | => |kind| { |
| 10467 | 10523 | const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data); |
| 10468 | 10524 | try metadata_formatter.specialized(.@"!", .DIDerivedType, .{ |
| 10469 | 10525 | .tag = @as(enum { |
| 10470 | 10526 | DW_TAG_pointer_type, |
| 10471 | 10527 | DW_TAG_member, |
| 10528 | DW_TAG_typedef, | |
| 10472 | 10529 | }, switch (kind) { |
| 10473 | 10530 | .derived_pointer_type => .DW_TAG_pointer_type, |
| 10474 | 10531 | .derived_member_type => .DW_TAG_member, |
| 10532 | .derived_typedef_type => .DW_TAG_typedef, | |
| 10475 | 10533 | else => unreachable, |
| 10476 | 10534 | }), |
| 10477 | 10535 | .name = extra.name, |
| ... | ... | @@ -10510,7 +10568,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10510 | 10568 | string: [ |
| 10511 | 10569 | (std.math.big.int.Const{ |
| 10512 | 10570 | .limbs = &([1]std.math.big.Limb{ |
| 10513 | std.math.maxInt(std.math.big.Limb), | |
| 10571 | maxInt(std.math.big.Limb), | |
| 10514 | 10572 | } ** expected_limbs), |
| 10515 | 10573 | .positive = false, |
| 10516 | 10574 | }).sizeInBaseUpperBound(10) |
| ... | ... | @@ -10660,7 +10718,7 @@ fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, w: *Writer) Writ |
| 10660 | 10718 | fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void { |
| 10661 | 10719 | try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1); |
| 10662 | 10720 | if (name.slice(self)) |id| { |
| 10663 | const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); | |
| 10721 | const count: usize = comptime std.fmt.count("{d}", .{maxInt(u32)}); | |
| 10664 | 10722 | try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); |
| 10665 | 10723 | } |
| 10666 | 10724 | try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | ... | @@ -12069,7 +12127,7 @@ pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String { |
| 12069 | 12127 | const start = self.metadata_string_indices.getLast(); |
| 12070 | 12128 | const bytes: []const u8 = self.metadata_string_bytes.items[start..]; |
| 12071 | 12129 | assert(bytes.len > 0); |
| 12072 | const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); | |
| 12130 | const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, Metadata.String.Adapter{ .builder = self }); | |
| 12073 | 12131 | if (gop.found_existing) { |
| 12074 | 12132 | self.metadata_string_bytes.shrinkRetainingCapacity(start); |
| 12075 | 12133 | } else { |
| ... | ... | @@ -12360,6 +12418,30 @@ pub fn debugMemberType( |
| 12360 | 12418 | ); |
| 12361 | 12419 | } |
| 12362 | 12420 | |
| 12421 | pub fn debugTypedefType( | |
| 12422 | self: *Builder, | |
| 12423 | name: ?Metadata.String, | |
| 12424 | file: ?Metadata, | |
| 12425 | scope: ?Metadata, | |
| 12426 | line: u32, | |
| 12427 | underlying_type: ?Metadata, | |
| 12428 | size_in_bits: u64, | |
| 12429 | align_in_bits: u64, | |
| 12430 | offset_in_bits: u64, | |
| 12431 | ) Allocator.Error!Metadata { | |
| 12432 | try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); | |
| 12433 | return self.debugTypedefTypeAssumeCapacity( | |
| 12434 | name, | |
| 12435 | file, | |
| 12436 | scope, | |
| 12437 | line, | |
| 12438 | underlying_type, | |
| 12439 | size_in_bits, | |
| 12440 | align_in_bits, | |
| 12441 | offset_in_bits, | |
| 12442 | ); | |
| 12443 | } | |
| 12444 | ||
| 12363 | 12445 | pub fn debugSubroutineType(self: *Builder, types_tuple: ?Metadata) Allocator.Error!Metadata { |
| 12364 | 12446 | try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0); |
| 12365 | 12447 | return self.debugSubroutineTypeAssumeCapacity(types_tuple); |
| ... | ... | @@ -12467,11 +12549,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat |
| 12467 | 12549 | return self.metadataConstantAssumeCapacity(value); |
| 12468 | 12550 | } |
| 12469 | 12551 | |
| 12552 | /// Resolves the given forward reference to the given value (which is not itself a forward | |
| 12553 | /// reference). If the forward reference is already resolved, its target is replaced. | |
| 12470 | 12554 | pub fn resolveDebugForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void { |
| 12471 | 12555 | assert(fwd_ref.kind == .forward); |
| 12472 | const resolved = &self.metadata_forward_references.items[fwd_ref.index]; | |
| 12473 | assert(resolved.is_none); | |
| 12474 | resolved.* = value.toOptional(); | |
| 12556 | assert(value.kind != .forward); | |
| 12557 | self.metadata_forward_references.items[fwd_ref.index] = value.toOptional(); | |
| 12475 | 12558 | } |
| 12476 | 12559 | |
| 12477 | 12560 | fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata { |
| ... | ... | @@ -12874,6 +12957,33 @@ fn debugMemberTypeAssumeCapacity( |
| 12874 | 12957 | }); |
| 12875 | 12958 | } |
| 12876 | 12959 | |
| 12960 | fn debugTypedefTypeAssumeCapacity( | |
| 12961 | self: *Builder, | |
| 12962 | name: ?Metadata.String, | |
| 12963 | file: ?Metadata, | |
| 12964 | scope: ?Metadata, | |
| 12965 | line: u32, | |
| 12966 | underlying_type: ?Metadata, | |
| 12967 | size_in_bits: u64, | |
| 12968 | align_in_bits: u64, | |
| 12969 | offset_in_bits: u64, | |
| 12970 | ) Metadata { | |
| 12971 | assert(!self.strip); | |
| 12972 | return self.metadataSimpleAssumeCapacity(.derived_typedef_type, Metadata.DerivedType{ | |
| 12973 | .name = .wrap(name), | |
| 12974 | .file = .wrap(file), | |
| 12975 | .scope = .wrap(scope), | |
| 12976 | .line = line, | |
| 12977 | .underlying_type = .wrap(underlying_type), | |
| 12978 | .size_in_bits_lo = @truncate(size_in_bits), | |
| 12979 | .size_in_bits_hi = @truncate(size_in_bits >> 32), | |
| 12980 | .align_in_bits_lo = @truncate(align_in_bits), | |
| 12981 | .align_in_bits_hi = @truncate(align_in_bits >> 32), | |
| 12982 | .offset_in_bits_lo = @truncate(offset_in_bits), | |
| 12983 | .offset_in_bits_hi = @truncate(offset_in_bits >> 32), | |
| 12984 | }); | |
| 12985 | } | |
| 12986 | ||
| 12877 | 12987 | fn debugSubroutineTypeAssumeCapacity(self: *Builder, types_tuple: ?Metadata) Metadata { |
| 12878 | 12988 | assert(!self.strip); |
| 12879 | 12989 | return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{ |
| ... | ... | @@ -13461,7 +13571,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13461 | 13571 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13462 | 13572 | record.appendAssumeCapacity(1); |
| 13463 | 13573 | record.appendAssumeCapacity(@intFromEnum(kind)); |
| 13464 | record.appendAssumeCapacity(alignment.toByteUnits() orelse 0); | |
| 13574 | record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0); | |
| 13465 | 13575 | }, |
| 13466 | 13576 | .dereferenceable, |
| 13467 | 13577 | .dereferenceable_or_null, |
| ... | ... | @@ -14222,12 +14332,14 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 14222 | 14332 | }, |
| 14223 | 14333 | .derived_pointer_type, |
| 14224 | 14334 | .derived_member_type, |
| 14335 | .derived_typedef_type, | |
| 14225 | 14336 | => |kind| { |
| 14226 | 14337 | const extra = self.metadataExtraData(Metadata.DerivedType, data); |
| 14227 | 14338 | try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{ |
| 14228 | 14339 | .tag = switch (kind) { |
| 14229 | 14340 | .derived_pointer_type => DW.TAG.pointer_type, |
| 14230 | 14341 | .derived_member_type => DW.TAG.member, |
| 14342 | .derived_typedef_type => DW.TAG.typedef, | |
| 14231 | 14343 | else => unreachable, |
| 14232 | 14344 | }, |
| 14233 | 14345 | .name = extra.name, |
lib/std/zig/target.zig+9-8| ... | ... | @@ -503,8 +503,7 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 { |
| 503 | 503 | pub fn intAlignment(target: *const std.Target, bits: u16) u16 { |
| 504 | 504 | return switch (target.cpu.arch) { |
| 505 | 505 | .x86 => switch (bits) { |
| 506 | 0 => 0, | |
| 507 | 1...8 => 1, | |
| 506 | 0...8 => 1, | |
| 508 | 507 | 9...16 => 2, |
| 509 | 508 | 17...32 => 4, |
| 510 | 509 | 33...64 => switch (target.os.tag) { |
| ... | ... | @@ -514,17 +513,19 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 { |
| 514 | 513 | else => 16, |
| 515 | 514 | }, |
| 516 | 515 | .x86_64 => switch (bits) { |
| 517 | 0 => 0, | |
| 518 | 1...8 => 1, | |
| 516 | 0...8 => 1, | |
| 519 | 517 | 9...16 => 2, |
| 520 | 518 | 17...32 => 4, |
| 521 | 519 | 33...64 => 8, |
| 522 | 520 | else => 16, |
| 523 | 521 | }, |
| 524 | else => return @min( | |
| 525 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), | |
| 526 | target.cMaxIntAlignment(), | |
| 527 | ), | |
| 522 | else => switch (bits) { | |
| 523 | 0 => 1, | |
| 524 | else => @min( | |
| 525 | std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), | |
| 526 | target.cMaxIntAlignment(), | |
| 527 | ), | |
| 528 | }, | |
| 528 | 529 | }; |
| 529 | 530 | } |
| 530 | 531 |
lib/std/zon/Serializer.zig+3-1| ... | ... | @@ -793,9 +793,11 @@ test checkValueDepth { |
| 793 | 793 | try expectValueDepthEquals(2, @as(?u32, 1)); |
| 794 | 794 | try expectValueDepthEquals(1, @as(?u32, null)); |
| 795 | 795 | try expectValueDepthEquals(1, null); |
| 796 | try expectValueDepthEquals(2, &1); | |
| 797 | 796 | try expectValueDepthEquals(3, &@as(?u32, 1)); |
| 798 | 797 | |
| 798 | // The pointer drops the implicit comptime-ness, so we need to specify 'comptime' here | |
| 799 | try comptime expectValueDepthEquals(2, &1); | |
| 800 | ||
| 799 | 801 | const Union = union(enum) { |
| 800 | 802 | x: u32, |
| 801 | 803 | y: struct { x: u32 }, |
lib/std/zon/parse.zig+3-3| ... | ... | @@ -591,7 +591,7 @@ const Parser = struct { |
| 591 | 591 | if (pointer.child == u8 and |
| 592 | 592 | pointer.is_const and |
| 593 | 593 | (pointer.sentinel() == null or pointer.sentinel() == 0) and |
| 594 | pointer.alignment == 1) | |
| 594 | (pointer.alignment == null or pointer.alignment == 1)) | |
| 595 | 595 | { |
| 596 | 596 | if (opt) { |
| 597 | 597 | return self.failNode(node, "expected optional string"); |
| ... | ... | @@ -717,7 +717,7 @@ const Parser = struct { |
| 717 | 717 | pointer.size != .slice or |
| 718 | 718 | !pointer.is_const or |
| 719 | 719 | (pointer.sentinel() != null and pointer.sentinel() != 0) or |
| 720 | pointer.alignment != 1) | |
| 720 | (pointer.alignment != null and pointer.alignment != 1)) | |
| 721 | 721 | { |
| 722 | 722 | return error.WrongType; |
| 723 | 723 | } |
| ... | ... | @@ -742,7 +742,7 @@ const Parser = struct { |
| 742 | 742 | const slice = try self.gpa.allocWithOptions( |
| 743 | 743 | pointer.child, |
| 744 | 744 | nodes.len, |
| 745 | .fromByteUnits(pointer.alignment), | |
| 745 | .fromByteUnitsOptional(pointer.alignment), | |
| 746 | 746 | pointer.sentinel(), |
| 747 | 747 | ); |
| 748 | 748 | errdefer self.gpa.free(slice); |
lib/zig.h+9-1| ... | ... | @@ -151,6 +151,14 @@ |
| 151 | 151 | #define zig_has_attribute(attribute) 0 |
| 152 | 152 | #endif |
| 153 | 153 | |
| 154 | #if __STDC_VERSION__ >= 201112L | |
| 155 | #define zig_static_assert(cond, msg) _Static_assert(cond, msg) | |
| 156 | #elif zig_has_attribute(unused) | |
| 157 | #define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) | |
| 158 | #else | |
| 159 | #define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] | |
| 160 | #endif | |
| 161 | ||
| 154 | 162 | #if __STDC_VERSION__ >= 202311L |
| 155 | 163 | #define zig_threadlocal thread_local |
| 156 | 164 | #elif __STDC_VERSION__ >= 201112L |
| ... | ... | @@ -259,7 +267,7 @@ |
| 259 | 267 | #endif |
| 260 | 268 | |
| 261 | 269 | #if zig_has_attribute(packed) || defined(zig_tinyc) |
| 262 | #define zig_packed(definition) __attribute__((packed)) definition | |
| 270 | #define zig_packed(definition) definition __attribute__((packed)) | |
| 263 | 271 | #elif defined(zig_msvc) |
| 264 | 272 | #define zig_packed(definition) __pragma(pack(1)) definition __pragma(pack()) |
| 265 | 273 | #else |
src/Air.zig+5-8| ... | ... | @@ -14,7 +14,6 @@ const Type = @import("Type.zig"); |
| 14 | 14 | const Value = @import("Value.zig"); |
| 15 | 15 | const Zcu = @import("Zcu.zig"); |
| 16 | 16 | const print = @import("Air/print.zig"); |
| 17 | const types_resolved = @import("Air/types_resolved.zig"); | |
| 18 | 17 | |
| 19 | 18 | pub const Legalize = @import("Air/Legalize.zig"); |
| 20 | 19 | pub const Liveness = @import("Air/Liveness.zig"); |
| ... | ... | @@ -173,8 +172,8 @@ pub const Inst = struct { |
| 173 | 172 | /// outside the provenance of the operand, the result is undefined. |
| 174 | 173 | /// |
| 175 | 174 | /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer, |
| 176 | /// rhs is the offset. Result type is the same as lhs. The operand may | |
| 177 | /// be a slice. | |
| 175 | /// rhs is the offset. Result type is the same as lhs. The operand type's | |
| 176 | /// pointer size may be `.slice`, `.many`, or `.c`. | |
| 178 | 177 | ptr_add, |
| 179 | 178 | /// Subtract an offset, in element type units, from a pointer, |
| 180 | 179 | /// returning a new pointer. Element type may not be zero bits. |
| ... | ... | @@ -183,8 +182,8 @@ pub const Inst = struct { |
| 183 | 182 | /// outside the provenance of the operand, the result is undefined. |
| 184 | 183 | /// |
| 185 | 184 | /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer, |
| 186 | /// rhs is the offset. Result type is the same as lhs. The operand may | |
| 187 | /// be a slice. | |
| 185 | /// rhs is the offset. Result type is the same as lhs. The operand type's | |
| 186 | /// pointer size may be `.slice`, `.many`, or `.c`. | |
| 188 | 187 | ptr_sub, |
| 189 | 188 | /// Given two operands which can be floats, integers, or vectors, returns the |
| 190 | 189 | /// greater of the operands. For vectors it operates element-wise. |
| ... | ... | @@ -693,6 +692,7 @@ pub const Inst = struct { |
| 693 | 692 | /// Uses the `ty_pl` field with payload `Bin`. |
| 694 | 693 | slice_elem_ptr, |
| 695 | 694 | /// Given a pointer value, and element index, return the element value at that index. |
| 695 | /// The pointer size is either `.c` or `.many`. | |
| 696 | 696 | /// Result type is the element type of the pointer operand. |
| 697 | 697 | /// Uses the `bin_op` field. |
| 698 | 698 | ptr_elem_val, |
| ... | ... | @@ -2440,9 +2440,6 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index |
| 2440 | 2440 | }; |
| 2441 | 2441 | } |
| 2442 | 2442 | |
| 2443 | pub const typesFullyResolved = types_resolved.typesFullyResolved; | |
| 2444 | pub const typeFullyResolved = types_resolved.checkType; | |
| 2445 | pub const valFullyResolved = types_resolved.checkVal; | |
| 2446 | 2443 | pub const legalize = Legalize.legalize; |
| 2447 | 2444 | pub const write = print.write; |
| 2448 | 2445 | pub const writeInst = print.writeInst; |
src/Air/Liveness.zig+5-5| ... | ... | @@ -153,8 +153,8 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li |
| 153 | 153 | usize, |
| 154 | 154 | (air.instructions.len * bpi + @bitSizeOf(usize) - 1) / @bitSizeOf(usize), |
| 155 | 155 | ), |
| 156 | .extra = .{}, | |
| 157 | .special = .{}, | |
| 156 | .extra = .empty, | |
| 157 | .special = .empty, | |
| 158 | 158 | .intern_pool = intern_pool, |
| 159 | 159 | }; |
| 160 | 160 | errdefer gpa.free(a.tomb_bits); |
| ... | ... | @@ -175,7 +175,7 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li |
| 175 | 175 | var data: LivenessPassData(.main_analysis) = .{}; |
| 176 | 176 | defer data.deinit(gpa); |
| 177 | 177 | data.old_extra = a.extra; |
| 178 | a.extra = .{}; | |
| 178 | a.extra = .empty; | |
| 179 | 179 | try analyzeBody(&a, .main_analysis, &data, main_body); |
| 180 | 180 | assert(data.live_set.count() == 0); |
| 181 | 181 | } |
| ... | ... | @@ -999,7 +999,7 @@ fn analyzeInstBlock( |
| 999 | 999 | |
| 1000 | 1000 | // If the block is noreturn, block deaths not only aren't useful, they're impossible to |
| 1001 | 1001 | // find: there could be more stuff alive after the block than before it! |
| 1002 | if (!a.intern_pool.isNoReturn(ty.toIntern())) { | |
| 1002 | if (!ty.isNoReturn(a.zcu)) { | |
| 1003 | 1003 | // The block kills the difference in the live sets |
| 1004 | 1004 | const block_scope = data.block_scopes.get(inst).?; |
| 1005 | 1005 | const num_deaths = data.live_set.count() - block_scope.live_set.count(); |
| ... | ... | @@ -1360,7 +1360,7 @@ fn analyzeInstSwitchBr( |
| 1360 | 1360 | const mirrored_deaths = try gpa.alloc(DeathList, ncases + 1); |
| 1361 | 1361 | defer gpa.free(mirrored_deaths); |
| 1362 | 1362 | |
| 1363 | @memset(mirrored_deaths, .{}); | |
| 1363 | @memset(mirrored_deaths, .empty); | |
| 1364 | 1364 | defer for (mirrored_deaths) |*md| md.deinit(gpa); |
| 1365 | 1365 | |
| 1366 | 1366 | { |
src/Air/Liveness/Verify.zig+1-1| ... | ... | @@ -465,7 +465,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 465 | 465 | |
| 466 | 466 | for (block_liveness.deaths) |death| try self.verifyDeath(inst, death); |
| 467 | 467 | |
| 468 | if (ip.isNoReturn(block_ty.toIntern())) { | |
| 468 | if (block_ty.isNoReturn(self.zcu)) { | |
| 469 | 469 | assert(!self.blocks.contains(inst)); |
| 470 | 470 | } else { |
| 471 | 471 | var live = if (self.blocks.fetchRemove(inst)) |kv| kv.value else { |
src/Air/print.zig+17-27| ... | ... | @@ -692,33 +692,23 @@ const Writer = struct { |
| 692 | 692 | |
| 693 | 693 | const zcu = w.pt.zcu; |
| 694 | 694 | const ip = &zcu.intern_pool; |
| 695 | const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; | |
| 696 | const struct_type: Type = .fromInterned(aggregate.ty); | |
| 697 | switch (aggregate.storage) { | |
| 698 | .elems => |elems| for (elems, 0..) |elem, i| { | |
| 699 | switch (elem) { | |
| 700 | .bool_true => { | |
| 701 | const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 702 | assert(clobber.len != 0); | |
| 703 | try s.writeAll(", ~{"); | |
| 704 | try s.writeAll(clobber); | |
| 705 | try s.writeAll("}"); | |
| 706 | }, | |
| 707 | .bool_false => continue, | |
| 708 | else => unreachable, | |
| 709 | } | |
| 710 | }, | |
| 711 | .repeated_elem => |elem| { | |
| 712 | try s.writeAll(", "); | |
| 713 | try s.writeAll(switch (elem) { | |
| 714 | .bool_true => "<all clobbers>", | |
| 715 | .bool_false => "<no clobbers>", | |
| 716 | else => unreachable, | |
| 717 | }); | |
| 718 | }, | |
| 719 | .bytes => |bytes| { | |
| 720 | try s.print(", {x}", .{bytes}); | |
| 721 | }, | |
| 695 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 696 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 697 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 698 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 699 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 700 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 701 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 702 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 703 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 704 | 0 => continue, // field is false | |
| 705 | 1 => {}, // field is true | |
| 706 | } | |
| 707 | const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 708 | assert(clobber.len != 0); | |
| 709 | try s.writeAll(", ~{"); | |
| 710 | try s.writeAll(clobber); | |
| 711 | try s.writeAll("}"); | |
| 722 | 712 | } |
| 723 | 713 | const asm_source = unwrapped_asm.source; |
| 724 | 714 | try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)}); |
src/Air/types_resolved.zig deleted-536| ... | ... | @@ -1,536 +0,0 @@ |
| 1 | const Air = @import("../Air.zig"); | |
| 2 | const Zcu = @import("../Zcu.zig"); | |
| 3 | const Type = @import("../Type.zig"); | |
| 4 | const Value = @import("../Value.zig"); | |
| 5 | const InternPool = @import("../InternPool.zig"); | |
| 6 | ||
| 7 | /// Given a body of AIR instructions, returns whether all type resolution necessary for codegen is complete. | |
| 8 | /// If `false`, then type resolution must have failed, so codegen cannot proceed. | |
| 9 | pub fn typesFullyResolved(air: Air, zcu: *Zcu) bool { | |
| 10 | return checkBody(air, air.getMainBody(), zcu); | |
| 11 | } | |
| 12 | ||
| 13 | fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { | |
| 14 | const tags = air.instructions.items(.tag); | |
| 15 | const datas = air.instructions.items(.data); | |
| 16 | ||
| 17 | for (body) |inst| { | |
| 18 | const data = datas[@intFromEnum(inst)]; | |
| 19 | switch (tags[@intFromEnum(inst)]) { | |
| 20 | .inferred_alloc, .inferred_alloc_comptime => unreachable, | |
| 21 | ||
| 22 | .arg => { | |
| 23 | if (!checkType(data.arg.ty.toType(), zcu)) return false; | |
| 24 | }, | |
| 25 | ||
| 26 | .add, | |
| 27 | .add_safe, | |
| 28 | .add_optimized, | |
| 29 | .add_wrap, | |
| 30 | .add_sat, | |
| 31 | .sub, | |
| 32 | .sub_safe, | |
| 33 | .sub_optimized, | |
| 34 | .sub_wrap, | |
| 35 | .sub_sat, | |
| 36 | .mul, | |
| 37 | .mul_safe, | |
| 38 | .mul_optimized, | |
| 39 | .mul_wrap, | |
| 40 | .mul_sat, | |
| 41 | .div_float, | |
| 42 | .div_float_optimized, | |
| 43 | .div_trunc, | |
| 44 | .div_trunc_optimized, | |
| 45 | .div_floor, | |
| 46 | .div_floor_optimized, | |
| 47 | .div_exact, | |
| 48 | .div_exact_optimized, | |
| 49 | .rem, | |
| 50 | .rem_optimized, | |
| 51 | .mod, | |
| 52 | .mod_optimized, | |
| 53 | .max, | |
| 54 | .min, | |
| 55 | .bit_and, | |
| 56 | .bit_or, | |
| 57 | .shr, | |
| 58 | .shr_exact, | |
| 59 | .shl, | |
| 60 | .shl_exact, | |
| 61 | .shl_sat, | |
| 62 | .xor, | |
| 63 | .cmp_lt, | |
| 64 | .cmp_lt_optimized, | |
| 65 | .cmp_lte, | |
| 66 | .cmp_lte_optimized, | |
| 67 | .cmp_eq, | |
| 68 | .cmp_eq_optimized, | |
| 69 | .cmp_gte, | |
| 70 | .cmp_gte_optimized, | |
| 71 | .cmp_gt, | |
| 72 | .cmp_gt_optimized, | |
| 73 | .cmp_neq, | |
| 74 | .cmp_neq_optimized, | |
| 75 | .bool_and, | |
| 76 | .bool_or, | |
| 77 | .store, | |
| 78 | .store_safe, | |
| 79 | .set_union_tag, | |
| 80 | .array_elem_val, | |
| 81 | .slice_elem_val, | |
| 82 | .ptr_elem_val, | |
| 83 | .memset, | |
| 84 | .memset_safe, | |
| 85 | .memcpy, | |
| 86 | .memmove, | |
| 87 | .atomic_store_unordered, | |
| 88 | .atomic_store_monotonic, | |
| 89 | .atomic_store_release, | |
| 90 | .atomic_store_seq_cst, | |
| 91 | .legalize_vec_elem_val, | |
| 92 | => { | |
| 93 | if (!checkRef(data.bin_op.lhs, zcu)) return false; | |
| 94 | if (!checkRef(data.bin_op.rhs, zcu)) return false; | |
| 95 | }, | |
| 96 | ||
| 97 | .not, | |
| 98 | .bitcast, | |
| 99 | .clz, | |
| 100 | .ctz, | |
| 101 | .popcount, | |
| 102 | .byte_swap, | |
| 103 | .bit_reverse, | |
| 104 | .abs, | |
| 105 | .load, | |
| 106 | .fptrunc, | |
| 107 | .fpext, | |
| 108 | .intcast, | |
| 109 | .intcast_safe, | |
| 110 | .trunc, | |
| 111 | .optional_payload, | |
| 112 | .optional_payload_ptr, | |
| 113 | .optional_payload_ptr_set, | |
| 114 | .wrap_optional, | |
| 115 | .unwrap_errunion_payload, | |
| 116 | .unwrap_errunion_err, | |
| 117 | .unwrap_errunion_payload_ptr, | |
| 118 | .unwrap_errunion_err_ptr, | |
| 119 | .errunion_payload_ptr_set, | |
| 120 | .wrap_errunion_payload, | |
| 121 | .wrap_errunion_err, | |
| 122 | .struct_field_ptr_index_0, | |
| 123 | .struct_field_ptr_index_1, | |
| 124 | .struct_field_ptr_index_2, | |
| 125 | .struct_field_ptr_index_3, | |
| 126 | .get_union_tag, | |
| 127 | .slice_len, | |
| 128 | .slice_ptr, | |
| 129 | .ptr_slice_len_ptr, | |
| 130 | .ptr_slice_ptr_ptr, | |
| 131 | .array_to_slice, | |
| 132 | .int_from_float, | |
| 133 | .int_from_float_optimized, | |
| 134 | .int_from_float_safe, | |
| 135 | .int_from_float_optimized_safe, | |
| 136 | .float_from_int, | |
| 137 | .splat, | |
| 138 | .error_set_has_value, | |
| 139 | .addrspace_cast, | |
| 140 | .c_va_arg, | |
| 141 | .c_va_copy, | |
| 142 | => { | |
| 143 | if (!checkType(data.ty_op.ty.toType(), zcu)) return false; | |
| 144 | if (!checkRef(data.ty_op.operand, zcu)) return false; | |
| 145 | }, | |
| 146 | ||
| 147 | .alloc, | |
| 148 | .ret_ptr, | |
| 149 | .c_va_start, | |
| 150 | => { | |
| 151 | if (!checkType(data.ty, zcu)) return false; | |
| 152 | }, | |
| 153 | ||
| 154 | .ptr_add, | |
| 155 | .ptr_sub, | |
| 156 | .add_with_overflow, | |
| 157 | .sub_with_overflow, | |
| 158 | .mul_with_overflow, | |
| 159 | .shl_with_overflow, | |
| 160 | .slice, | |
| 161 | .slice_elem_ptr, | |
| 162 | .ptr_elem_ptr, | |
| 163 | => { | |
| 164 | const bin = air.extraData(Air.Bin, data.ty_pl.payload).data; | |
| 165 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 166 | if (!checkRef(bin.lhs, zcu)) return false; | |
| 167 | if (!checkRef(bin.rhs, zcu)) return false; | |
| 168 | }, | |
| 169 | ||
| 170 | .block, | |
| 171 | .loop, | |
| 172 | => { | |
| 173 | const block = air.unwrapBlock(inst); | |
| 174 | if (!checkType(block.ty, zcu)) return false; | |
| 175 | if (!checkBody( | |
| 176 | air, | |
| 177 | block.body, | |
| 178 | zcu, | |
| 179 | )) return false; | |
| 180 | }, | |
| 181 | ||
| 182 | .dbg_inline_block => { | |
| 183 | const block = air.unwrapDbgBlock(inst); | |
| 184 | if (!checkType(block.ty, zcu)) return false; | |
| 185 | if (!checkBody( | |
| 186 | air, | |
| 187 | block.body, | |
| 188 | zcu, | |
| 189 | )) return false; | |
| 190 | }, | |
| 191 | ||
| 192 | .sqrt, | |
| 193 | .sin, | |
| 194 | .cos, | |
| 195 | .tan, | |
| 196 | .exp, | |
| 197 | .exp2, | |
| 198 | .log, | |
| 199 | .log2, | |
| 200 | .log10, | |
| 201 | .floor, | |
| 202 | .ceil, | |
| 203 | .round, | |
| 204 | .trunc_float, | |
| 205 | .neg, | |
| 206 | .neg_optimized, | |
| 207 | .is_null, | |
| 208 | .is_non_null, | |
| 209 | .is_null_ptr, | |
| 210 | .is_non_null_ptr, | |
| 211 | .is_err, | |
| 212 | .is_non_err, | |
| 213 | .is_err_ptr, | |
| 214 | .is_non_err_ptr, | |
| 215 | .ret, | |
| 216 | .ret_safe, | |
| 217 | .ret_load, | |
| 218 | .is_named_enum_value, | |
| 219 | .tag_name, | |
| 220 | .error_name, | |
| 221 | .cmp_lt_errors_len, | |
| 222 | .c_va_end, | |
| 223 | .set_err_return_trace, | |
| 224 | => { | |
| 225 | if (!checkRef(data.un_op, zcu)) return false; | |
| 226 | }, | |
| 227 | ||
| 228 | .br, .switch_dispatch => { | |
| 229 | if (!checkRef(data.br.operand, zcu)) return false; | |
| 230 | }, | |
| 231 | ||
| 232 | .cmp_vector, | |
| 233 | .cmp_vector_optimized, | |
| 234 | => { | |
| 235 | const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data; | |
| 236 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 237 | if (!checkRef(extra.lhs, zcu)) return false; | |
| 238 | if (!checkRef(extra.rhs, zcu)) return false; | |
| 239 | }, | |
| 240 | ||
| 241 | .reduce, | |
| 242 | .reduce_optimized, | |
| 243 | => { | |
| 244 | if (!checkRef(data.reduce.operand, zcu)) return false; | |
| 245 | }, | |
| 246 | ||
| 247 | .struct_field_ptr, | |
| 248 | .struct_field_val, | |
| 249 | => { | |
| 250 | const extra = air.extraData(Air.StructField, data.ty_pl.payload).data; | |
| 251 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 252 | if (!checkRef(extra.struct_operand, zcu)) return false; | |
| 253 | }, | |
| 254 | ||
| 255 | .shuffle_one => { | |
| 256 | const unwrapped = air.unwrapShuffleOne(zcu, inst); | |
| 257 | if (!checkType(unwrapped.result_ty, zcu)) return false; | |
| 258 | if (!checkRef(unwrapped.operand, zcu)) return false; | |
| 259 | for (unwrapped.mask) |m| switch (m.unwrap()) { | |
| 260 | .elem => {}, | |
| 261 | .value => |val| if (!checkVal(.fromInterned(val), zcu)) return false, | |
| 262 | }; | |
| 263 | }, | |
| 264 | ||
| 265 | .shuffle_two => { | |
| 266 | const unwrapped = air.unwrapShuffleTwo(zcu, inst); | |
| 267 | if (!checkType(unwrapped.result_ty, zcu)) return false; | |
| 268 | if (!checkRef(unwrapped.operand_a, zcu)) return false; | |
| 269 | if (!checkRef(unwrapped.operand_b, zcu)) return false; | |
| 270 | // No values to check because there are no comptime-known values other than undef | |
| 271 | }, | |
| 272 | ||
| 273 | .cmpxchg_weak, | |
| 274 | .cmpxchg_strong, | |
| 275 | => { | |
| 276 | const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data; | |
| 277 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 278 | if (!checkRef(extra.ptr, zcu)) return false; | |
| 279 | if (!checkRef(extra.expected_value, zcu)) return false; | |
| 280 | if (!checkRef(extra.new_value, zcu)) return false; | |
| 281 | }, | |
| 282 | ||
| 283 | .aggregate_init => { | |
| 284 | const ty = data.ty_pl.ty.toType(); | |
| 285 | const elems_len: usize = @intCast(ty.arrayLen(zcu)); | |
| 286 | const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]); | |
| 287 | if (!checkType(ty, zcu)) return false; | |
| 288 | if (ty.zigTypeTag(zcu) == .@"struct") { | |
| 289 | for (elems, 0..) |elem, elem_idx| { | |
| 290 | if (ty.structFieldIsComptime(elem_idx, zcu)) continue; | |
| 291 | if (!checkRef(elem, zcu)) return false; | |
| 292 | } | |
| 293 | } else { | |
| 294 | for (elems) |elem| { | |
| 295 | if (!checkRef(elem, zcu)) return false; | |
| 296 | } | |
| 297 | } | |
| 298 | }, | |
| 299 | ||
| 300 | .union_init => { | |
| 301 | const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data; | |
| 302 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 303 | if (!checkRef(extra.init, zcu)) return false; | |
| 304 | }, | |
| 305 | ||
| 306 | .field_parent_ptr => { | |
| 307 | const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data; | |
| 308 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 309 | if (!checkRef(extra.field_ptr, zcu)) return false; | |
| 310 | }, | |
| 311 | ||
| 312 | .atomic_load => { | |
| 313 | if (!checkRef(data.atomic_load.ptr, zcu)) return false; | |
| 314 | }, | |
| 315 | ||
| 316 | .prefetch => { | |
| 317 | if (!checkRef(data.prefetch.ptr, zcu)) return false; | |
| 318 | }, | |
| 319 | ||
| 320 | .runtime_nav_ptr => { | |
| 321 | if (!checkType(.fromInterned(data.ty_nav.ty), zcu)) return false; | |
| 322 | }, | |
| 323 | ||
| 324 | .select, | |
| 325 | .mul_add, | |
| 326 | .legalize_vec_store_elem, | |
| 327 | => { | |
| 328 | const bin = air.extraData(Air.Bin, data.pl_op.payload).data; | |
| 329 | if (!checkRef(data.pl_op.operand, zcu)) return false; | |
| 330 | if (!checkRef(bin.lhs, zcu)) return false; | |
| 331 | if (!checkRef(bin.rhs, zcu)) return false; | |
| 332 | }, | |
| 333 | ||
| 334 | .atomic_rmw => { | |
| 335 | const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data; | |
| 336 | if (!checkRef(data.pl_op.operand, zcu)) return false; | |
| 337 | if (!checkRef(extra.operand, zcu)) return false; | |
| 338 | }, | |
| 339 | ||
| 340 | .call, | |
| 341 | .call_always_tail, | |
| 342 | .call_never_tail, | |
| 343 | .call_never_inline, | |
| 344 | => { | |
| 345 | const call = air.unwrapCall(inst); | |
| 346 | const args = call.args; | |
| 347 | if (!checkRef(call.callee, zcu)) return false; | |
| 348 | for (args) |arg| if (!checkRef(arg, zcu)) return false; | |
| 349 | }, | |
| 350 | ||
| 351 | .dbg_var_ptr, | |
| 352 | .dbg_var_val, | |
| 353 | .dbg_arg_inline, | |
| 354 | => { | |
| 355 | if (!checkRef(data.pl_op.operand, zcu)) return false; | |
| 356 | }, | |
| 357 | ||
| 358 | .@"try", .try_cold => { | |
| 359 | const unwrapped_try = air.unwrapTry(inst); | |
| 360 | if (!checkRef(unwrapped_try.error_union, zcu)) return false; | |
| 361 | if (!checkBody( | |
| 362 | air, | |
| 363 | unwrapped_try.else_body, | |
| 364 | zcu, | |
| 365 | )) return false; | |
| 366 | }, | |
| 367 | ||
| 368 | .try_ptr, .try_ptr_cold => { | |
| 369 | const unwrapped_try = air.unwrapTryPtr(inst); | |
| 370 | if (!checkType(unwrapped_try.error_union_payload_ptr_ty.toType(), zcu)) return false; | |
| 371 | if (!checkRef(unwrapped_try.error_union_ptr, zcu)) return false; | |
| 372 | if (!checkBody( | |
| 373 | air, | |
| 374 | unwrapped_try.else_body, | |
| 375 | zcu, | |
| 376 | )) return false; | |
| 377 | }, | |
| 378 | ||
| 379 | .cond_br => { | |
| 380 | const cond_br = air.unwrapCondBr(inst); | |
| 381 | if (!checkRef(cond_br.condition, zcu)) return false; | |
| 382 | if (!checkBody( | |
| 383 | air, | |
| 384 | cond_br.then_body, | |
| 385 | zcu, | |
| 386 | )) return false; | |
| 387 | if (!checkBody( | |
| 388 | air, | |
| 389 | cond_br.else_body, | |
| 390 | zcu, | |
| 391 | )) return false; | |
| 392 | }, | |
| 393 | ||
| 394 | .switch_br, .loop_switch_br => { | |
| 395 | const switch_br = air.unwrapSwitch(inst); | |
| 396 | if (!checkRef(switch_br.operand, zcu)) return false; | |
| 397 | var it = switch_br.iterateCases(); | |
| 398 | while (it.next()) |case| { | |
| 399 | for (case.items) |item| if (!checkRef(item, zcu)) return false; | |
| 400 | for (case.ranges) |range| { | |
| 401 | if (!checkRef(range[0], zcu)) return false; | |
| 402 | if (!checkRef(range[1], zcu)) return false; | |
| 403 | } | |
| 404 | if (!checkBody(air, case.body, zcu)) return false; | |
| 405 | } | |
| 406 | if (!checkBody(air, it.elseBody(), zcu)) return false; | |
| 407 | }, | |
| 408 | ||
| 409 | .assembly => { | |
| 410 | const unwrapped_asm = air.unwrapAsm(inst); | |
| 411 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 412 | // Luckily, we only care about the inputs and outputs, so we don't have to do | |
| 413 | // the whole null-terminated string dance. | |
| 414 | const outputs = unwrapped_asm.outputs; | |
| 415 | const inputs = unwrapped_asm.inputs; | |
| 416 | ||
| 417 | for (outputs) |output| if (output != .none and !checkRef(output, zcu)) return false; | |
| 418 | for (inputs) |input| if (input != .none and !checkRef(input, zcu)) return false; | |
| 419 | }, | |
| 420 | ||
| 421 | .legalize_compiler_rt_call => { | |
| 422 | const rt_call = air.unwrapCompilerRtCall(inst); | |
| 423 | const args = rt_call.args; | |
| 424 | for (args) |arg| if (!checkRef(arg, zcu)) return false; | |
| 425 | }, | |
| 426 | ||
| 427 | .trap, | |
| 428 | .breakpoint, | |
| 429 | .ret_addr, | |
| 430 | .frame_addr, | |
| 431 | .unreach, | |
| 432 | .wasm_memory_size, | |
| 433 | .wasm_memory_grow, | |
| 434 | .work_item_id, | |
| 435 | .work_group_size, | |
| 436 | .work_group_id, | |
| 437 | .dbg_stmt, | |
| 438 | .dbg_empty_stmt, | |
| 439 | .err_return_trace, | |
| 440 | .save_err_return_trace_index, | |
| 441 | .repeat, | |
| 442 | => {}, | |
| 443 | } | |
| 444 | } | |
| 445 | return true; | |
| 446 | } | |
| 447 | ||
| 448 | fn checkRef(ref: Air.Inst.Ref, zcu: *Zcu) bool { | |
| 449 | const ip_index = ref.toInterned() orelse { | |
| 450 | // This operand refers back to a previous instruction. | |
| 451 | // We have already checked that instruction's type. | |
| 452 | // So, there's no need to check this operand's type. | |
| 453 | return true; | |
| 454 | }; | |
| 455 | return checkVal(Value.fromInterned(ip_index), zcu); | |
| 456 | } | |
| 457 | ||
| 458 | pub fn checkVal(val: Value, zcu: *Zcu) bool { | |
| 459 | const ty = val.typeOf(zcu); | |
| 460 | if (!checkType(ty, zcu)) return false; | |
| 461 | if (val.isUndef(zcu)) return true; | |
| 462 | if (ty.toIntern() == .type_type and !checkType(val.toType(), zcu)) return false; | |
| 463 | // Check for lazy values | |
| 464 | switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 465 | .int => |int| switch (int.storage) { | |
| 466 | .u64, .i64, .big_int => return true, | |
| 467 | .lazy_align, .lazy_size => |ty_index| { | |
| 468 | return checkType(Type.fromInterned(ty_index), zcu); | |
| 469 | }, | |
| 470 | }, | |
| 471 | else => return true, | |
| 472 | } | |
| 473 | } | |
| 474 | ||
| 475 | pub fn checkType(ty: Type, zcu: *Zcu) bool { | |
| 476 | const ip = &zcu.intern_pool; | |
| 477 | if (ty.isGenericPoison()) return true; | |
| 478 | return switch (ty.zigTypeTag(zcu)) { | |
| 479 | .type, | |
| 480 | .void, | |
| 481 | .bool, | |
| 482 | .noreturn, | |
| 483 | .int, | |
| 484 | .float, | |
| 485 | .error_set, | |
| 486 | .@"enum", | |
| 487 | .@"opaque", | |
| 488 | .vector, | |
| 489 | // These types can appear due to some dummy instructions Sema introduces and expects to be omitted by Liveness. | |
| 490 | // It's a little silly -- but fine, we'll return `true`. | |
| 491 | .comptime_float, | |
| 492 | .comptime_int, | |
| 493 | .undefined, | |
| 494 | .null, | |
| 495 | .enum_literal, | |
| 496 | => true, | |
| 497 | ||
| 498 | .frame, | |
| 499 | .@"anyframe", | |
| 500 | => @panic("TODO Air.types_resolved.checkType async frames"), | |
| 501 | ||
| 502 | .optional => checkType(ty.childType(zcu), zcu), | |
| 503 | .error_union => checkType(ty.errorUnionPayload(zcu), zcu), | |
| 504 | .pointer => checkType(ty.childType(zcu), zcu), | |
| 505 | .array => checkType(ty.childType(zcu), zcu), | |
| 506 | ||
| 507 | .@"fn" => { | |
| 508 | const info = zcu.typeToFunc(ty).?; | |
| 509 | for (0..info.param_types.len) |i| { | |
| 510 | const param_ty = info.param_types.get(ip)[i]; | |
| 511 | if (!checkType(Type.fromInterned(param_ty), zcu)) return false; | |
| 512 | } | |
| 513 | return checkType(Type.fromInterned(info.return_type), zcu); | |
| 514 | }, | |
| 515 | .@"struct" => switch (ip.indexToKey(ty.toIntern())) { | |
| 516 | .struct_type => { | |
| 517 | const struct_obj = zcu.typeToStruct(ty).?; | |
| 518 | return switch (struct_obj.layout) { | |
| 519 | .@"packed" => struct_obj.backingIntTypeUnordered(ip) != .none, | |
| 520 | .auto, .@"extern" => struct_obj.flagsUnordered(ip).fully_resolved, | |
| 521 | }; | |
| 522 | }, | |
| 523 | .tuple_type => |tuple| { | |
| 524 | for (0..tuple.types.len) |i| { | |
| 525 | const field_is_comptime = tuple.values.get(ip)[i] != .none; | |
| 526 | if (field_is_comptime) continue; | |
| 527 | const field_ty = tuple.types.get(ip)[i]; | |
| 528 | if (!checkType(Type.fromInterned(field_ty), zcu)) return false; | |
| 529 | } | |
| 530 | return true; | |
| 531 | }, | |
| 532 | else => unreachable, | |
| 533 | }, | |
| 534 | .@"union" => return zcu.typeToUnion(ty).?.flagsUnordered(ip).status == .fully_resolved, | |
| 535 | }; | |
| 536 | } |
src/Compilation.zig+57-718| ... | ... | @@ -21,7 +21,6 @@ const introspect = @import("introspect.zig"); |
| 21 | 21 | const link = @import("link.zig"); |
| 22 | 22 | const tracy = @import("tracy.zig"); |
| 23 | 23 | const trace = tracy.trace; |
| 24 | const traceNamed = tracy.traceNamed; | |
| 25 | 24 | const build_options = @import("build_options"); |
| 26 | 25 | const LibCInstallation = std.zig.LibCInstallation; |
| 27 | 26 | const glibc = @import("libs/glibc.zig"); |
| ... | ... | @@ -89,6 +88,9 @@ framework_dirs: []const []const u8, |
| 89 | 88 | /// These are only for DLLs dependencies fulfilled by the `.def` files shipped |
| 90 | 89 | /// with Zig. Static libraries are provided as `link.Input` values. |
| 91 | 90 | windows_libs: std.StringArrayHashMapUnmanaged(void), |
| 91 | /// The number of items in `windows_libs` which we have already built. All items at or after this | |
| 92 | /// index will be built in `performAllTheWork`. | |
| 93 | windows_libs_num_done: u32, | |
| 92 | 94 | version: ?std.SemanticVersion, |
| 93 | 95 | libc_installation: ?*const LibCInstallation, |
| 94 | 96 | skip_linker_dependencies: bool, |
| ... | ... | @@ -126,16 +128,6 @@ oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask), |
| 126 | 128 | /// work is queued or not. |
| 127 | 129 | queued_jobs: QueuedJobs, |
| 128 | 130 | |
| 129 | work_queues: [ | |
| 130 | len: { | |
| 131 | var len: usize = 0; | |
| 132 | for (std.enums.values(Job.Tag)) |tag| { | |
| 133 | len = @max(Job.stage(tag) + 1, len); | |
| 134 | } | |
| 135 | break :len len; | |
| 136 | } | |
| 137 | ]std.Deque(Job), | |
| 138 | ||
| 139 | 131 | /// These jobs are to invoke the Clang compiler to create an object file, which |
| 140 | 132 | /// gets linked with the Compilation. |
| 141 | 133 | c_object_work_queue: std.Deque(*CObject), |
| ... | ... | @@ -962,65 +954,6 @@ pub const RcSourceFile = struct { |
| 962 | 954 | extra_flags: []const []const u8 = &.{}, |
| 963 | 955 | }; |
| 964 | 956 | |
| 965 | const Job = union(enum) { | |
| 966 | /// Given the generated AIR for a function, put it onto the code generation queue. | |
| 967 | /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that | |
| 968 | /// all types are resolved before the linker task is queued. | |
| 969 | /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately. | |
| 970 | /// Before queueing this `Job`, increase the estimated total item count for both | |
| 971 | /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`. | |
| 972 | codegen_func: struct { | |
| 973 | func: InternPool.Index, | |
| 974 | /// The AIR emitted from analyzing `func`; owned by this `Job` in `gpa`. | |
| 975 | air: Air, | |
| 976 | }, | |
| 977 | /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary. | |
| 978 | /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that | |
| 979 | /// all types are resolved before the linker task is queued. | |
| 980 | /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately. | |
| 981 | /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. | |
| 982 | link_nav: InternPool.Nav.Index, | |
| 983 | /// Queue a `link.ZcuTask` to emit debug information for this container type. | |
| 984 | /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that | |
| 985 | /// all types are resolved before the linker task is queued. | |
| 986 | /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately. | |
| 987 | /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. | |
| 988 | link_type: InternPool.Index, | |
| 989 | /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. | |
| 990 | update_line_number: InternPool.TrackedInst.Index, | |
| 991 | /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed. | |
| 992 | /// This may be its first time being analyzed, or it may be outdated. | |
| 993 | /// If the unit is a test function, an `analyze_func` job will then be queued. | |
| 994 | analyze_comptime_unit: InternPool.AnalUnit, | |
| 995 | /// This function must be semantically analyzed. | |
| 996 | /// This may be its first time being analyzed, or it may be outdated. | |
| 997 | /// After analysis, a `codegen_func` job will be queued. | |
| 998 | /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen. | |
| 999 | /// This job is separate from `analyze_comptime_unit` because it has a different priority. | |
| 1000 | analyze_func: InternPool.Index, | |
| 1001 | /// The main source file for the module needs to be analyzed. | |
| 1002 | analyze_mod: *Package.Module, | |
| 1003 | /// Fully resolve the given `struct` or `union` type. | |
| 1004 | resolve_type_fully: InternPool.Index, | |
| 1005 | ||
| 1006 | /// The value is the index into `windows_libs`. | |
| 1007 | windows_import_lib: usize, | |
| 1008 | ||
| 1009 | const Tag = @typeInfo(Job).@"union".tag_type.?; | |
| 1010 | fn stage(tag: Tag) usize { | |
| 1011 | return switch (tag) { | |
| 1012 | // Prioritize functions so that codegen can get to work on them on a | |
| 1013 | // separate thread, while Sema goes back to its own work. | |
| 1014 | .resolve_type_fully, .analyze_func, .codegen_func => 0, | |
| 1015 | else => 1, | |
| 1016 | }; | |
| 1017 | } | |
| 1018 | comptime { | |
| 1019 | // Job dependencies | |
| 1020 | assert(stage(.resolve_type_fully) <= stage(.codegen_func)); | |
| 1021 | } | |
| 1022 | }; | |
| 1023 | ||
| 1024 | 957 | pub const CObject = struct { |
| 1025 | 958 | /// Relative to cwd. Owned by arena. |
| 1026 | 959 | src: CSourceFile, |
| ... | ... | @@ -1412,7 +1345,6 @@ pub const MiscTask = enum { |
| 1412 | 1345 | wasi_libc_crt_file, |
| 1413 | 1346 | compiler_rt, |
| 1414 | 1347 | libzigc, |
| 1415 | analyze_mod, | |
| 1416 | 1348 | link_depfile, |
| 1417 | 1349 | docs_copy, |
| 1418 | 1350 | docs_wasm, |
| ... | ... | @@ -2297,7 +2229,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2297 | 2229 | .root_mod = options.root_mod, |
| 2298 | 2230 | .config = options.config, |
| 2299 | 2231 | .dirs = options.dirs, |
| 2300 | .work_queues = @splat(.empty), | |
| 2301 | 2232 | .c_object_work_queue = .empty, |
| 2302 | 2233 | .win32_resource_work_queue = .empty, |
| 2303 | 2234 | .c_source_files = options.c_source_files, |
| ... | ... | @@ -2331,6 +2262,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2331 | 2262 | .root_name = root_name, |
| 2332 | 2263 | .sysroot = sysroot, |
| 2333 | 2264 | .windows_libs = .empty, |
| 2265 | .windows_libs_num_done = 0, | |
| 2334 | 2266 | .version = options.version, |
| 2335 | 2267 | .libc_installation = libc_dirs.libc_installation, |
| 2336 | 2268 | .compiler_rt_strat = compiler_rt_strat, |
| ... | ... | @@ -2693,16 +2625,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2693 | 2625 | } |
| 2694 | 2626 | } |
| 2695 | 2627 | |
| 2696 | // Generate Windows import libs. | |
| 2697 | if (target.os.tag == .windows) { | |
| 2698 | const count = comp.windows_libs.count(); | |
| 2699 | for (0..count) |i| { | |
| 2700 | try comp.queueJob(.{ .windows_import_lib = i }); | |
| 2701 | } | |
| 2702 | // when integrating coff linker with prelink, the above `queueJob` will need to move | |
| 2703 | // to something in `dispatchPrelinkWork`, which must queue all prelink link tasks | |
| 2704 | // *before* we begin working on the main job queue. | |
| 2705 | } | |
| 2706 | 2628 | if (comp.wantBuildLibUnwindFromSource()) { |
| 2707 | 2629 | comp.queued_jobs.libunwind = true; |
| 2708 | 2630 | } |
| ... | ... | @@ -2786,7 +2708,6 @@ pub fn destroy(comp: *Compilation) void { |
| 2786 | 2708 | if (comp.zcu) |zcu| zcu.deinit(); |
| 2787 | 2709 | comp.cache_use.deinit(io); |
| 2788 | 2710 | |
| 2789 | for (&comp.work_queues) |*work_queue| work_queue.deinit(gpa); | |
| 2790 | 2711 | comp.c_object_work_queue.deinit(gpa); |
| 2791 | 2712 | comp.win32_resource_work_queue.deinit(gpa); |
| 2792 | 2713 | |
| ... | ... | @@ -3461,9 +3382,6 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel |
| 3461 | 3382 | error.OutOfMemory, error.Canceled => |e| return e, |
| 3462 | 3383 | }; |
| 3463 | 3384 | } |
| 3464 | if (comp.zcu) |zcu| { | |
| 3465 | try link.File.C.flushEmitH(zcu); | |
| 3466 | } | |
| 3467 | 3385 | } |
| 3468 | 3386 | |
| 3469 | 3387 | /// This function is called by the frontend before flush(). It communicates that |
| ... | ... | @@ -3728,7 +3646,9 @@ const Header = extern struct { |
| 3728 | 3646 | src_hash_deps_len: u32, |
| 3729 | 3647 | nav_val_deps_len: u32, |
| 3730 | 3648 | nav_ty_deps_len: u32, |
| 3731 | interned_deps_len: u32, | |
| 3649 | type_layout_deps_len: u32, | |
| 3650 | struct_defaults_deps_len: u32, | |
| 3651 | func_ies_deps_len: u32, | |
| 3732 | 3652 | zon_file_deps_len: u32, |
| 3733 | 3653 | embed_file_deps_len: u32, |
| 3734 | 3654 | namespace_deps_len: u32, |
| ... | ... | @@ -3776,7 +3696,9 @@ pub fn saveState(comp: *Compilation) !void { |
| 3776 | 3696 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), |
| 3777 | 3697 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), |
| 3778 | 3698 | .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), |
| 3779 | .interned_deps_len = @intCast(ip.interned_deps.count()), | |
| 3699 | .type_layout_deps_len = @intCast(ip.type_layout_deps.count()), | |
| 3700 | .struct_defaults_deps_len = @intCast(ip.struct_defaults_deps.count()), | |
| 3701 | .func_ies_deps_len = @intCast(ip.func_ies_deps.count()), | |
| 3780 | 3702 | .zon_file_deps_len = @intCast(ip.zon_file_deps.count()), |
| 3781 | 3703 | .embed_file_deps_len = @intCast(ip.embed_file_deps.count()), |
| 3782 | 3704 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), |
| ... | ... | @@ -3800,7 +3722,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 3800 | 3722 | }, |
| 3801 | 3723 | }); |
| 3802 | 3724 | |
| 3803 | try bufs.ensureTotalCapacityPrecise(22 + 9 * pt_headers.items.len); | |
| 3725 | try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len); | |
| 3804 | 3726 | addBuf(&bufs, mem.asBytes(&header)); |
| 3805 | 3727 | addBuf(&bufs, @ptrCast(pt_headers.items)); |
| 3806 | 3728 | |
| ... | ... | @@ -3810,8 +3732,12 @@ pub fn saveState(comp: *Compilation) !void { |
| 3810 | 3732 | addBuf(&bufs, @ptrCast(ip.nav_val_deps.values())); |
| 3811 | 3733 | addBuf(&bufs, @ptrCast(ip.nav_ty_deps.keys())); |
| 3812 | 3734 | addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values())); |
| 3813 | addBuf(&bufs, @ptrCast(ip.interned_deps.keys())); | |
| 3814 | addBuf(&bufs, @ptrCast(ip.interned_deps.values())); | |
| 3735 | addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys())); | |
| 3736 | addBuf(&bufs, @ptrCast(ip.type_layout_deps.values())); | |
| 3737 | addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.keys())); | |
| 3738 | addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.values())); | |
| 3739 | addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys())); | |
| 3740 | addBuf(&bufs, @ptrCast(ip.func_ies_deps.values())); | |
| 3815 | 3741 | addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys())); |
| 3816 | 3742 | addBuf(&bufs, @ptrCast(ip.zon_file_deps.values())); |
| 3817 | 3743 | addBuf(&bufs, @ptrCast(ip.embed_file_deps.keys())); |
| ... | ... | @@ -4128,21 +4054,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4128 | 4054 | const SortOrder = struct { |
| 4129 | 4055 | zcu: *Zcu, |
| 4130 | 4056 | errors: []const *Zcu.ErrorMsg, |
| 4131 | read_err: *?ReadError, | |
| 4132 | const ReadError = struct { | |
| 4133 | file: *Zcu.File, | |
| 4134 | err: Zcu.File.GetSourceError, | |
| 4135 | }; | |
| 4136 | 4057 | pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { |
| 4137 | if (ctx.read_err.* != null) return lhs_index < rhs_index; | |
| 4138 | var bad_file: *Zcu.File = undefined; | |
| 4139 | return ctx.errors[lhs_index].src_loc.lessThan(ctx.errors[rhs_index].src_loc, ctx.zcu, &bad_file) catch |err| { | |
| 4140 | ctx.read_err.* = .{ | |
| 4141 | .file = bad_file, | |
| 4142 | .err = err, | |
| 4143 | }; | |
| 4144 | return lhs_index < rhs_index; | |
| 4145 | }; | |
| 4058 | return Zcu.ErrorMsg.order( | |
| 4059 | ctx.errors[lhs_index], | |
| 4060 | ctx.errors[rhs_index], | |
| 4061 | ctx.zcu, | |
| 4062 | ).compare(.lt); | |
| 4146 | 4063 | } |
| 4147 | 4064 | }; |
| 4148 | 4065 | |
| ... | ... | @@ -4152,16 +4069,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4152 | 4069 | var entries = try zcu.failed_analysis.entries.clone(gpa); |
| 4153 | 4070 | errdefer entries.deinit(gpa); |
| 4154 | 4071 | |
| 4155 | var read_err: ?SortOrder.ReadError = null; | |
| 4156 | 4072 | entries.sort(SortOrder{ |
| 4157 | 4073 | .zcu = zcu, |
| 4158 | 4074 | .errors = entries.items(.value), |
| 4159 | .read_err = &read_err, | |
| 4160 | 4075 | }); |
| 4161 | if (read_err) |e| { | |
| 4162 | try unableToLoadZcuFile(zcu, &bundle, e.file, e.err); | |
| 4163 | break :zcu_errors; | |
| 4164 | } | |
| 4165 | 4076 | break :s entries.slice(); |
| 4166 | 4077 | }; |
| 4167 | 4078 | defer sorted_failed_analysis.deinit(gpa); |
| ... | ... | @@ -4200,6 +4111,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4200 | 4111 | } |
| 4201 | 4112 | } |
| 4202 | 4113 | } |
| 4114 | try zcu.addDependencyLoopErrors(&bundle); | |
| 4203 | 4115 | for (zcu.failed_codegen.values()) |error_msg| { |
| 4204 | 4116 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, false); |
| 4205 | 4117 | } |
| ... | ... | @@ -4219,7 +4131,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4219 | 4131 | .notes_len = 1, |
| 4220 | 4132 | }); |
| 4221 | 4133 | const notes_start = try bundle.reserveNotes(1); |
| 4222 | bundle.extra.items[notes_start] = @intFromEnum(try bundle.addErrorMessage(.{ | |
| 4134 | bundle.extra.items[notes_start] = @intFromEnum(bundle.addErrorMessageAssumeCapacity(.{ | |
| 4223 | 4135 | .msg = try bundle.printString("use '--error-limit {d}' to increase limit", .{ |
| 4224 | 4136 | actual_error_count, |
| 4225 | 4137 | }), |
| ... | ... | @@ -4241,10 +4153,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4241 | 4153 | .notes_len = 2, |
| 4242 | 4154 | }); |
| 4243 | 4155 | const notes_start = try bundle.reserveNotes(2); |
| 4244 | bundle.extra.items[notes_start + 0] = @intFromEnum(try bundle.addErrorMessage(.{ | |
| 4156 | bundle.extra.items[notes_start + 0] = @intFromEnum(bundle.addErrorMessageAssumeCapacity(.{ | |
| 4245 | 4157 | .msg = try bundle.addString("run 'zig libc -h' to learn about libc installations"), |
| 4246 | 4158 | })); |
| 4247 | bundle.extra.items[notes_start + 1] = @intFromEnum(try bundle.addErrorMessage(.{ | |
| 4159 | bundle.extra.items[notes_start + 1] = @intFromEnum(bundle.addErrorMessageAssumeCapacity(.{ | |
| 4248 | 4160 | .msg = try bundle.addString("run 'zig targets' to see the targets for which zig can always provide libc"), |
| 4249 | 4161 | })); |
| 4250 | 4162 | } |
| ... | ... | @@ -4268,7 +4180,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4268 | 4180 | if (!refs.contains(logging_unit)) continue; |
| 4269 | 4181 | try messages.append(gpa, .{ |
| 4270 | 4182 | .src_loc = compile_log.src(), |
| 4271 | .msg = undefined, // populated later | |
| 4183 | .msg = "", // populated later, but must be valid for `sort` call below | |
| 4272 | 4184 | .notes = &.{}, |
| 4273 | 4185 | // We actually clear this later for most of these, but we populate |
| 4274 | 4186 | // this field for now to avoid having to allocate more data to track |
| ... | ... | @@ -4281,33 +4193,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4281 | 4193 | |
| 4282 | 4194 | // Okay, there *are* referenced compile logs. Sort them into a consistent order. |
| 4283 | 4195 | |
| 4284 | { | |
| 4285 | const SortContext = struct { | |
| 4286 | zcu: *Zcu, | |
| 4287 | read_err: *?ReadError, | |
| 4288 | const ReadError = struct { | |
| 4289 | file: *Zcu.File, | |
| 4290 | err: Zcu.File.GetSourceError, | |
| 4291 | }; | |
| 4292 | fn lessThan(ctx: @This(), lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool { | |
| 4293 | if (ctx.read_err.* != null) return false; | |
| 4294 | var bad_file: *Zcu.File = undefined; | |
| 4295 | return lhs.src_loc.lessThan(rhs.src_loc, ctx.zcu, &bad_file) catch |err| { | |
| 4296 | ctx.read_err.* = .{ | |
| 4297 | .file = bad_file, | |
| 4298 | .err = err, | |
| 4299 | }; | |
| 4300 | return false; | |
| 4301 | }; | |
| 4302 | } | |
| 4303 | }; | |
| 4304 | var read_err: ?SortContext.ReadError = null; | |
| 4305 | std.mem.sort(Zcu.ErrorMsg, messages.items, @as(SortContext, .{ .read_err = &read_err, .zcu = zcu }), SortContext.lessThan); | |
| 4306 | if (read_err) |e| { | |
| 4307 | try unableToLoadZcuFile(zcu, &bundle, e.file, e.err); | |
| 4308 | break :compile_log_text ""; | |
| 4196 | std.mem.sort(Zcu.ErrorMsg, messages.items, zcu, struct { | |
| 4197 | fn lessThan(zcu_inner: *Zcu, lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool { | |
| 4198 | return Zcu.ErrorMsg.order(&lhs, &rhs, zcu_inner).compare(.lt); | |
| 4309 | 4199 | } |
| 4310 | } | |
| 4200 | }.lessThan); | |
| 4311 | 4201 | |
| 4312 | 4202 | var log_text: std.ArrayList(u8) = .empty; |
| 4313 | 4203 | defer log_text.deinit(gpa); |
| ... | ... | @@ -4331,6 +4221,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4331 | 4221 | |
| 4332 | 4222 | break :compile_log_text try log_text.toOwnedSlice(gpa); |
| 4333 | 4223 | }; |
| 4224 | defer gpa.free(compile_log_text); | |
| 4334 | 4225 | |
| 4335 | 4226 | // TODO: eventually, this should be behind `std.debug.runtime_safety`. But right now, this is a |
| 4336 | 4227 | // very common way for incremental compilation bugs to manifest, so let's always check it. |
| ... | ... | @@ -4439,7 +4330,6 @@ pub fn addModuleErrorMsg( |
| 4439 | 4330 | already_added_error: bool, |
| 4440 | 4331 | ) Allocator.Error!void { |
| 4441 | 4332 | const gpa = eb.gpa; |
| 4442 | const ip = &zcu.intern_pool; | |
| 4443 | 4333 | const err_src_loc = module_err_msg.src_loc.upgrade(zcu); |
| 4444 | 4334 | const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| { |
| 4445 | 4335 | return unableToLoadZcuFile(zcu, eb, err_src_loc.file_scope, err); |
| ... | ... | @@ -4452,66 +4342,12 @@ pub fn addModuleErrorMsg( |
| 4452 | 4342 | var ref_traces: std.ArrayList(ErrorBundle.ReferenceTrace) = .empty; |
| 4453 | 4343 | defer ref_traces.deinit(gpa); |
| 4454 | 4344 | |
| 4455 | rt: { | |
| 4456 | const rt_root = module_err_msg.reference_trace_root.unwrap() orelse break :rt; | |
| 4457 | const max_references = zcu.comp.reference_trace orelse refs: { | |
| 4458 | if (already_added_error) break :rt; | |
| 4345 | if (module_err_msg.reference_trace_root.unwrap()) |root| { | |
| 4346 | const frame_limit: u32 = zcu.comp.reference_trace orelse refs: { | |
| 4347 | if (already_added_error) break :refs 0; | |
| 4459 | 4348 | break :refs default_reference_trace_len; |
| 4460 | 4349 | }; |
| 4461 | ||
| 4462 | const all_references = try zcu.resolveReferences(); | |
| 4463 | ||
| 4464 | var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty; | |
| 4465 | defer seen.deinit(gpa); | |
| 4466 | ||
| 4467 | var referenced_by = rt_root; | |
| 4468 | while (all_references.get(referenced_by)) |maybe_ref| { | |
| 4469 | const ref = maybe_ref orelse break; | |
| 4470 | const gop = try seen.getOrPut(gpa, ref.referencer); | |
| 4471 | if (gop.found_existing) break; | |
| 4472 | if (ref_traces.items.len < max_references) { | |
| 4473 | var last_call_src = ref.src; | |
| 4474 | var opt_inline_frame = ref.inline_frame; | |
| 4475 | while (opt_inline_frame.unwrap()) |inline_frame| { | |
| 4476 | const f = inline_frame.ptr(zcu).*; | |
| 4477 | const func_nav = ip.indexToKey(f.callee).func.owner_nav; | |
| 4478 | const func_name = ip.getNav(func_nav).name.toSlice(ip); | |
| 4479 | addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true) catch |err| switch (err) { | |
| 4480 | error.OutOfMemory => |e| return e, | |
| 4481 | error.AlreadyReported => { | |
| 4482 | // An incomplete reference trace isn't the end of the world; just cut it off. | |
| 4483 | break :rt; | |
| 4484 | }, | |
| 4485 | }; | |
| 4486 | last_call_src = f.call_src; | |
| 4487 | opt_inline_frame = f.parent; | |
| 4488 | } | |
| 4489 | const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { | |
| 4490 | .@"comptime" => "comptime", | |
| 4491 | .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), | |
| 4492 | .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), | |
| 4493 | .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), | |
| 4494 | .memoized_state => null, | |
| 4495 | }; | |
| 4496 | if (root_name) |n| { | |
| 4497 | addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false) catch |err| switch (err) { | |
| 4498 | error.OutOfMemory => |e| return e, | |
| 4499 | error.AlreadyReported => { | |
| 4500 | // An incomplete reference trace isn't the end of the world; just cut it off. | |
| 4501 | break :rt; | |
| 4502 | }, | |
| 4503 | }; | |
| 4504 | } | |
| 4505 | } | |
| 4506 | referenced_by = ref.referencer; | |
| 4507 | } | |
| 4508 | ||
| 4509 | if (seen.count() > ref_traces.items.len) { | |
| 4510 | try ref_traces.append(gpa, .{ | |
| 4511 | .decl_name = @intCast(seen.count() - ref_traces.items.len), | |
| 4512 | .src_loc = .none, | |
| 4513 | }); | |
| 4514 | } | |
| 4350 | try zcu.populateReferenceTrace(root, frame_limit, eb, &ref_traces); | |
| 4515 | 4351 | } |
| 4516 | 4352 | |
| 4517 | 4353 | const src_loc = try eb.addSourceLocation(.{ |
| ... | ... | @@ -4576,43 +4412,10 @@ pub fn addModuleErrorMsg( |
| 4576 | 4412 | const notes_start = try eb.reserveNotes(notes_len); |
| 4577 | 4413 | |
| 4578 | 4414 | for (notes_start.., notes.keys()) |i, note| { |
| 4579 | eb.extra.items[i] = @intFromEnum(try eb.addErrorMessage(note)); | |
| 4415 | eb.extra.items[i] = @intFromEnum(eb.addErrorMessageAssumeCapacity(note)); | |
| 4580 | 4416 | } |
| 4581 | 4417 | } |
| 4582 | 4418 | |
| 4583 | fn addReferenceTraceFrame( | |
| 4584 | zcu: *Zcu, | |
| 4585 | eb: *ErrorBundle.Wip, | |
| 4586 | ref_traces: *std.ArrayList(ErrorBundle.ReferenceTrace), | |
| 4587 | name: []const u8, | |
| 4588 | lazy_src: Zcu.LazySrcLoc, | |
| 4589 | inlined: bool, | |
| 4590 | ) error{ OutOfMemory, AlreadyReported }!void { | |
| 4591 | const gpa = zcu.gpa; | |
| 4592 | const src = lazy_src.upgrade(zcu); | |
| 4593 | const source = src.file_scope.getSource(zcu) catch |err| { | |
| 4594 | try unableToLoadZcuFile(zcu, eb, src.file_scope, err); | |
| 4595 | return error.AlreadyReported; | |
| 4596 | }; | |
| 4597 | const span = src.span(zcu) catch |err| { | |
| 4598 | try unableToLoadZcuFile(zcu, eb, src.file_scope, err); | |
| 4599 | return error.AlreadyReported; | |
| 4600 | }; | |
| 4601 | const loc = std.zig.findLineColumn(source, span.main); | |
| 4602 | try ref_traces.append(gpa, .{ | |
| 4603 | .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }), | |
| 4604 | .src_loc = try eb.addSourceLocation(.{ | |
| 4605 | .src_path = try eb.printString("{f}", .{src.file_scope.path.fmt(zcu.comp)}), | |
| 4606 | .span_start = span.start, | |
| 4607 | .span_main = span.main, | |
| 4608 | .span_end = span.end, | |
| 4609 | .line = @intCast(loc.line), | |
| 4610 | .column = @intCast(loc.column), | |
| 4611 | .source_line = 0, | |
| 4612 | }), | |
| 4613 | }); | |
| 4614 | } | |
| 4615 | ||
| 4616 | 4419 | fn addWholeFileError( |
| 4617 | 4420 | zcu: *Zcu, |
| 4618 | 4421 | eb: *ErrorBundle.Wip, |
| ... | ... | @@ -4669,13 +4472,7 @@ fn performAllTheWork( |
| 4669 | 4472 | comp: *Compilation, |
| 4670 | 4473 | main_progress_node: std.Progress.Node, |
| 4671 | 4474 | update_arena: Allocator, |
| 4672 | ) JobError!void { | |
| 4673 | defer if (comp.zcu) |zcu| { | |
| 4674 | zcu.codegen_task_pool.cancel(zcu); | |
| 4675 | // Regardless of errors, `comp.zcu` needs to update its generation number. | |
| 4676 | zcu.generation += 1; | |
| 4677 | }; | |
| 4678 | ||
| 4475 | ) (Allocator.Error || Io.Cancelable)!void { | |
| 4679 | 4476 | const io = comp.io; |
| 4680 | 4477 | |
| 4681 | 4478 | // This is awkward: we don't want to start the timer until later, but we won't want to stop it |
| ... | ... | @@ -4708,216 +4505,32 @@ fn performAllTheWork( |
| 4708 | 4505 | misc_group.async(io, workerDocsWasm, .{ comp, main_progress_node }); |
| 4709 | 4506 | } |
| 4710 | 4507 | |
| 4711 | if (comp.zcu) |zcu| { | |
| 4712 | const tracy_trace = traceNamed(@src(), "astgen"); | |
| 4713 | defer tracy_trace.end(); | |
| 4714 | ||
| 4715 | const zir_prog_node = main_progress_node.start("AST Lowering", 0); | |
| 4716 | defer zir_prog_node.end(); | |
| 4717 | ||
| 4718 | var timer = comp.startTimer(); | |
| 4719 | defer if (timer.finish(io)) |ns| { | |
| 4720 | comp.mutex.lockUncancelable(io); | |
| 4721 | defer comp.mutex.unlock(io); | |
| 4722 | comp.time_report.?.stats.real_ns_files = ns; | |
| 4723 | }; | |
| 4724 | ||
| 4725 | const gpa = comp.gpa; | |
| 4726 | ||
| 4727 | var astgen_group: Io.Group = .init; | |
| 4728 | defer astgen_group.cancel(io); | |
| 4729 | ||
| 4730 | // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs, | |
| 4731 | // because on single-threaded targets the worker will be run eagerly, meaning the | |
| 4732 | // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So, | |
| 4733 | // build up a list of the files to update *before* we spawn any jobs. | |
| 4734 | var astgen_work_items: std.MultiArrayList(struct { | |
| 4735 | file_index: Zcu.File.Index, | |
| 4736 | file: *Zcu.File, | |
| 4737 | }) = .empty; | |
| 4738 | defer astgen_work_items.deinit(gpa); | |
| 4739 | // Not every item in `import_table` will need updating, because some are builtin.zig | |
| 4740 | // files. However, most will, so let's just reserve sufficient capacity upfront. | |
| 4741 | try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count()); | |
| 4742 | for (zcu.import_table.keys()) |file_index| { | |
| 4743 | const file = zcu.fileByIndex(file_index); | |
| 4744 | if (file.is_builtin) { | |
| 4745 | // This is a `builtin.zig`, so updating is redundant. However, we want to make | |
| 4746 | // sure the file contents are still correct on disk, since it can improve the | |
| 4747 | // debugging experience better. That job only needs `file`, so we can kick it | |
| 4748 | // off right now. | |
| 4749 | astgen_group.async(io, workerUpdateBuiltinFile, .{ comp, file }); | |
| 4750 | continue; | |
| 4751 | } | |
| 4752 | astgen_work_items.appendAssumeCapacity(.{ | |
| 4753 | .file_index = file_index, | |
| 4754 | .file = file, | |
| 4755 | }); | |
| 4756 | } | |
| 4757 | ||
| 4758 | // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs. | |
| 4759 | for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| { | |
| 4760 | astgen_group.async(io, workerUpdateFile, .{ | |
| 4761 | comp, file, file_index, zir_prog_node, &astgen_group, | |
| 4762 | }); | |
| 4763 | } | |
| 4764 | ||
| 4765 | // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here | |
| 4766 | // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one | |
| 4767 | // `@embedFile` can't trigger analysis of a new `@embedFile`! | |
| 4768 | for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| { | |
| 4769 | const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); | |
| 4770 | astgen_group.async(io, workerUpdateEmbedFile, .{ | |
| 4771 | comp, ef_index, ef, | |
| 4772 | }); | |
| 4773 | } | |
| 4774 | ||
| 4775 | try astgen_group.await(io); | |
| 4776 | } | |
| 4777 | ||
| 4508 | defer if (comp.zcu) |zcu| zcu.codegen_task_pool.cancel(zcu); | |
| 4778 | 4509 | if (comp.zcu) |zcu| { |
| 4779 | 4510 | const pt: Zcu.PerThread = .activate(zcu, .main); |
| 4780 | defer pt.deactivate(); | |
| 4781 | ||
| 4782 | const gpa = zcu.gpa; | |
| 4783 | ||
| 4784 | // On an incremental update, a source file might become "dead", in that all imports of | |
| 4785 | // the file were removed. This could even change what module the file belongs to! As such, | |
| 4786 | // we do a traversal over the files, to figure out which ones are alive and the modules | |
| 4787 | // they belong to. | |
| 4788 | const any_fatal_files = try pt.computeAliveFiles(); | |
| 4789 | ||
| 4790 | // If the cache mode is `whole`, add every alive source file to the manifest. | |
| 4791 | switch (comp.cache_use) { | |
| 4792 | .whole => |whole| if (whole.cache_manifest) |man| { | |
| 4793 | for (zcu.alive_files.keys()) |file_index| { | |
| 4794 | const file = zcu.fileByIndex(file_index); | |
| 4795 | ||
| 4796 | switch (file.status) { | |
| 4797 | .never_loaded => unreachable, // AstGen tried to load it | |
| 4798 | .retryable_failure => continue, // the file cannot be read; this is a guaranteed error | |
| 4799 | .astgen_failure, .success => {}, // the file was read successfully | |
| 4800 | } | |
| 4801 | ||
| 4802 | const path = try file.path.toAbsolute(comp.dirs, gpa); | |
| 4803 | defer gpa.free(path); | |
| 4804 | ||
| 4805 | const result = res: { | |
| 4806 | try whole.cache_manifest_mutex.lock(io); | |
| 4807 | defer whole.cache_manifest_mutex.unlock(io); | |
| 4808 | if (file.source) |source| { | |
| 4809 | break :res man.addFilePostContents(path, source, file.stat); | |
| 4810 | } else { | |
| 4811 | break :res man.addFilePost(path); | |
| 4812 | } | |
| 4813 | }; | |
| 4814 | result catch |err| switch (err) { | |
| 4815 | error.OutOfMemory => |e| return e, | |
| 4816 | else => { | |
| 4817 | try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); | |
| 4818 | continue; | |
| 4819 | }, | |
| 4820 | }; | |
| 4821 | } | |
| 4822 | }, | |
| 4823 | .none, .incremental => {}, | |
| 4824 | } | |
| 4825 | ||
| 4826 | if (any_fatal_files or | |
| 4827 | zcu.multi_module_err != null or | |
| 4828 | zcu.failed_imports.items.len > 0 or | |
| 4829 | comp.alloc_failure_occurred) | |
| 4830 | { | |
| 4831 | // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents | |
| 4832 | // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. | |
| 4833 | // However, this means our analysis data is invalid, so we want to omit all analysis errors. | |
| 4834 | zcu.skip_analysis_this_update = true; | |
| 4835 | // Since we're skipping analysis, there are no ZCU link tasks. | |
| 4836 | comp.link_queue.finishZcuQueue(comp); | |
| 4837 | // Let other compilation work finish to collect as many errors as possible. | |
| 4838 | try misc_group.await(io); | |
| 4839 | comp.link_queue.wait(io); | |
| 4840 | return; | |
| 4841 | } | |
| 4842 | ||
| 4843 | if (comp.time_report) |*tr| { | |
| 4844 | tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); | |
| 4845 | } | |
| 4846 | ||
| 4847 | if (comp.config.incremental) { | |
| 4848 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); | |
| 4849 | defer update_zir_refs_node.end(); | |
| 4850 | try pt.updateZirRefs(); | |
| 4851 | } | |
| 4852 | try zcu.flushRetryableFailures(); | |
| 4853 | ||
| 4854 | // It's analysis time! Queue up our initial analysis. | |
| 4855 | for (zcu.analysisRoots()) |mod| { | |
| 4856 | try comp.queueJob(.{ .analyze_mod = mod }); | |
| 4857 | } | |
| 4858 | ||
| 4859 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | |
| 4860 | if (comp.bin_file != null) { | |
| 4861 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); | |
| 4862 | } | |
| 4863 | // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. | |
| 4864 | // That prevents the "Code Generation" node from constantly disappearing and reappearing when | |
| 4865 | // we're probably going to analyze more functions at some point. | |
| 4866 | assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes | |
| 4867 | } | |
| 4868 | // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation". | |
| 4869 | defer if (comp.zcu) |zcu| { | |
| 4870 | zcu.sema_prog_node.end(); | |
| 4871 | zcu.sema_prog_node = .none; | |
| 4872 | if (zcu.pending_codegen_jobs.fetchSub(1, .monotonic) == 1) { | |
| 4873 | // Decremented to 0, so all done. | |
| 4874 | zcu.codegen_prog_node.end(); | |
| 4875 | zcu.codegen_prog_node = .none; | |
| 4876 | } | |
| 4877 | }; | |
| 4878 | ||
| 4879 | if (comp.zcu) |zcu| { | |
| 4880 | if (!zcu.backendSupportsFeature(.separate_thread)) { | |
| 4881 | // Close the ZCU task queue. Prelink may still be running, but the closed | |
| 4882 | // queue will cause the linker task to exit once prelink finishes. The | |
| 4883 | // closed queue also communicates to `enqueueZcu` that it should wait for | |
| 4884 | // the linker task to finish and then run ZCU tasks serially. | |
| 4885 | comp.link_queue.finishZcuQueue(comp); | |
| 4511 | defer { | |
| 4512 | pt.deactivate(); | |
| 4513 | // Regardless of errors, `comp.zcu` needs to update its generation number. | |
| 4514 | zcu.generation += 1; | |
| 4886 | 4515 | } |
| 4516 | try pt.update(main_progress_node, &decl_work_timer); | |
| 4887 | 4517 | } |
| 4888 | 4518 | |
| 4889 | if (comp.zcu != null) { | |
| 4890 | // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). | |
| 4891 | decl_work_timer = comp.startTimer(); | |
| 4892 | } | |
| 4519 | comp.link_queue.finishZcuQueue(comp); | |
| 4893 | 4520 | |
| 4894 | work: while (true) { | |
| 4895 | for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| { | |
| 4896 | try processOneJob(.main, comp, job); | |
| 4897 | continue :work; | |
| 4521 | // This has to happen after the main semantic analysis loop because it is possible for Sema to | |
| 4522 | // call `addLinkLib` and hence add more items to `comp.windows_libs`. | |
| 4523 | for (comp.windows_libs.keys()[comp.windows_libs_num_done..]) |link_lib| { | |
| 4524 | mingw.buildImportLib(comp, link_lib) catch |err| { | |
| 4525 | // TODO Surface more error details. | |
| 4526 | comp.lockAndSetMiscFailure( | |
| 4527 | .windows_import_lib, | |
| 4528 | "unable to generate DLL import .lib file for {s}: {t}", | |
| 4529 | .{ link_lib, err }, | |
| 4530 | ); | |
| 4898 | 4531 | }; |
| 4899 | if (comp.zcu) |zcu| { | |
| 4900 | // If there's no work queued, check if there's anything outdated | |
| 4901 | // which we need to work on, and queue it if so. | |
| 4902 | if (try zcu.findOutdatedToAnalyze()) |outdated| { | |
| 4903 | try comp.queueJob(switch (outdated.unwrap()) { | |
| 4904 | .func => |f| .{ .analyze_func = f }, | |
| 4905 | .memoized_state, | |
| 4906 | .@"comptime", | |
| 4907 | .nav_ty, | |
| 4908 | .nav_val, | |
| 4909 | .type, | |
| 4910 | => .{ .analyze_comptime_unit = outdated }, | |
| 4911 | }); | |
| 4912 | continue; | |
| 4913 | } | |
| 4914 | zcu.sema_prog_node.end(); | |
| 4915 | zcu.sema_prog_node = .none; | |
| 4916 | } | |
| 4917 | break; | |
| 4918 | 4532 | } |
| 4919 | ||
| 4920 | comp.link_queue.finishZcuQueue(comp); | |
| 4533 | comp.windows_libs_num_done = @intCast(comp.windows_libs.count()); | |
| 4921 | 4534 | |
| 4922 | 4535 | // Main thread work is all done, now just wait for all async work. |
| 4923 | 4536 | try misc_group.await(io); |
| ... | ... | @@ -5148,172 +4761,6 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node |
| 5148 | 4761 | }; |
| 5149 | 4762 | } |
| 5150 | 4763 | |
| 5151 | const JobError = Allocator.Error || Io.Cancelable; | |
| 5152 | ||
| 5153 | pub fn queueJob(comp: *Compilation, job: Job) !void { | |
| 5154 | try comp.work_queues[Job.stage(job)].pushBack(comp.gpa, job); | |
| 5155 | } | |
| 5156 | ||
| 5157 | pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { | |
| 5158 | for (jobs) |job| try comp.queueJob(job); | |
| 5159 | } | |
| 5160 | ||
| 5161 | fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!void { | |
| 5162 | switch (job) { | |
| 5163 | .codegen_func => |func| { | |
| 5164 | const zcu = comp.zcu.?; | |
| 5165 | const gpa = zcu.gpa; | |
| 5166 | var owned_air: ?Air = func.air; | |
| 5167 | defer if (owned_air) |*air| air.deinit(gpa); | |
| 5168 | ||
| 5169 | if (!owned_air.?.typesFullyResolved(zcu)) { | |
| 5170 | // Type resolution failed in a way which affects this function. This is a transitive | |
| 5171 | // failure, but it doesn't need recording, because this function semantically depends | |
| 5172 | // on the failed type, so when it is changed the function is updated. | |
| 5173 | zcu.codegen_prog_node.completeOne(); | |
| 5174 | comp.link_prog_node.completeOne(); | |
| 5175 | return; | |
| 5176 | } | |
| 5177 | ||
| 5178 | // Some linkers need to refer to the AIR. In that case, the linker is not running | |
| 5179 | // concurrently, so we'll just keep ownership of the AIR for ourselves instead of | |
| 5180 | // letting the codegen job destroy it. | |
| 5181 | const disown_air = zcu.backendSupportsFeature(.separate_thread); | |
| 5182 | ||
| 5183 | // Begin the codegen task. If the codegen/link queue is backed up, this might | |
| 5184 | // block until the linker is able to process some tasks. | |
| 5185 | const codegen_task = try zcu.codegen_task_pool.start(zcu, func.func, &owned_air.?, disown_air); | |
| 5186 | if (disown_air) owned_air = null; | |
| 5187 | ||
| 5188 | try comp.link_queue.enqueueZcu(comp, tid, .{ .link_func = codegen_task }); | |
| 5189 | }, | |
| 5190 | .link_nav => |nav_index| { | |
| 5191 | const zcu = comp.zcu.?; | |
| 5192 | const nav = zcu.intern_pool.getNav(nav_index); | |
| 5193 | if (nav.analysis != null) { | |
| 5194 | const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index }); | |
| 5195 | if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) { | |
| 5196 | comp.link_prog_node.completeOne(); | |
| 5197 | return; | |
| 5198 | } | |
| 5199 | } | |
| 5200 | assert(nav.status == .fully_resolved); | |
| 5201 | if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) { | |
| 5202 | // Type resolution failed in a way which affects this `Nav`. This is a transitive | |
| 5203 | // failure, but it doesn't need recording, because this `Nav` semantically depends | |
| 5204 | // on the failed type, so when it is changed the `Nav` will be updated. | |
| 5205 | comp.link_prog_node.completeOne(); | |
| 5206 | return; | |
| 5207 | } | |
| 5208 | try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index }); | |
| 5209 | }, | |
| 5210 | .link_type => |ty| { | |
| 5211 | const zcu = comp.zcu.?; | |
| 5212 | if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa); | |
| 5213 | if (!Air.typeFullyResolved(.fromInterned(ty), zcu)) { | |
| 5214 | // Type resolution failed in a way which affects this type. This is a transitive | |
| 5215 | // failure, but it doesn't need recording, because this type semantically depends | |
| 5216 | // on the failed type, so when that is changed, this type will be updated. | |
| 5217 | comp.link_prog_node.completeOne(); | |
| 5218 | return; | |
| 5219 | } | |
| 5220 | try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty }); | |
| 5221 | }, | |
| 5222 | .update_line_number => |tracked_inst| { | |
| 5223 | try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst }); | |
| 5224 | }, | |
| 5225 | .analyze_func => |func| { | |
| 5226 | const tracy_trace = traceNamed(@src(), "analyze_func"); | |
| 5227 | defer tracy_trace.end(); | |
| 5228 | ||
| 5229 | const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); | |
| 5230 | defer pt.deactivate(); | |
| 5231 | ||
| 5232 | pt.ensureFuncBodyUpToDate(func) catch |err| switch (err) { | |
| 5233 | error.OutOfMemory => |e| return e, | |
| 5234 | error.Canceled => |e| return e, | |
| 5235 | error.AnalysisFail => return, | |
| 5236 | }; | |
| 5237 | }, | |
| 5238 | .analyze_comptime_unit => |unit| { | |
| 5239 | const tracy_trace = traceNamed(@src(), "analyze_comptime_unit"); | |
| 5240 | defer tracy_trace.end(); | |
| 5241 | ||
| 5242 | const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); | |
| 5243 | defer pt.deactivate(); | |
| 5244 | ||
| 5245 | const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) { | |
| 5246 | .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), | |
| 5247 | .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav), | |
| 5248 | .nav_val => |nav| pt.ensureNavValUpToDate(nav), | |
| 5249 | .type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err, | |
| 5250 | .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage), | |
| 5251 | .func => unreachable, | |
| 5252 | }; | |
| 5253 | maybe_err catch |err| switch (err) { | |
| 5254 | error.OutOfMemory => |e| return e, | |
| 5255 | error.Canceled => |e| return e, | |
| 5256 | error.AnalysisFail => return, | |
| 5257 | }; | |
| 5258 | ||
| 5259 | queue_test_analysis: { | |
| 5260 | if (!comp.config.is_test) break :queue_test_analysis; | |
| 5261 | const nav = switch (unit.unwrap()) { | |
| 5262 | .nav_val => |nav| nav, | |
| 5263 | else => break :queue_test_analysis, | |
| 5264 | }; | |
| 5265 | ||
| 5266 | // Check if this is a test function. | |
| 5267 | const ip = &pt.zcu.intern_pool; | |
| 5268 | if (!pt.zcu.test_functions.contains(nav)) { | |
| 5269 | break :queue_test_analysis; | |
| 5270 | } | |
| 5271 | ||
| 5272 | // Tests are always emitted in test binaries. The decl_refs are created by | |
| 5273 | // Zcu.populateTestFunctions, but this will not queue body analysis, so do | |
| 5274 | // that now. | |
| 5275 | try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.fully_resolved.val); | |
| 5276 | } | |
| 5277 | }, | |
| 5278 | .resolve_type_fully => |ty| { | |
| 5279 | const tracy_trace = traceNamed(@src(), "resolve_type_fully"); | |
| 5280 | defer tracy_trace.end(); | |
| 5281 | ||
| 5282 | const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); | |
| 5283 | defer pt.deactivate(); | |
| 5284 | Type.fromInterned(ty).resolveFully(pt) catch |err| switch (err) { | |
| 5285 | error.OutOfMemory, error.Canceled => |e| return e, | |
| 5286 | error.AnalysisFail => return, | |
| 5287 | }; | |
| 5288 | }, | |
| 5289 | .analyze_mod => |mod| { | |
| 5290 | const tracy_trace = traceNamed(@src(), "analyze_mod"); | |
| 5291 | defer tracy_trace.end(); | |
| 5292 | ||
| 5293 | const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); | |
| 5294 | defer pt.deactivate(); | |
| 5295 | pt.semaMod(mod) catch |err| switch (err) { | |
| 5296 | error.OutOfMemory, error.Canceled => |e| return e, | |
| 5297 | error.AnalysisFail => return, | |
| 5298 | }; | |
| 5299 | }, | |
| 5300 | .windows_import_lib => |index| { | |
| 5301 | const tracy_trace = traceNamed(@src(), "windows_import_lib"); | |
| 5302 | defer tracy_trace.end(); | |
| 5303 | ||
| 5304 | const link_lib = comp.windows_libs.keys()[index]; | |
| 5305 | mingw.buildImportLib(comp, link_lib) catch |err| { | |
| 5306 | // TODO Surface more error details. | |
| 5307 | comp.lockAndSetMiscFailure( | |
| 5308 | .windows_import_lib, | |
| 5309 | "unable to generate DLL import .lib file for {s}: {t}", | |
| 5310 | .{ link_lib, err }, | |
| 5311 | ); | |
| 5312 | }; | |
| 5313 | }, | |
| 5314 | } | |
| 5315 | } | |
| 5316 | ||
| 5317 | 4764 | fn createDepFile(comp: *Compilation, dep_file: []const u8, bin_file: Cache.Path) anyerror!void { |
| 5318 | 4765 | const io = comp.io; |
| 5319 | 4766 | |
| ... | ... | @@ -5641,112 +5088,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 5641 | 5088 | }; |
| 5642 | 5089 | } |
| 5643 | 5090 | |
| 5644 | fn workerUpdateFile( | |
| 5645 | comp: *Compilation, | |
| 5646 | file: *Zcu.File, | |
| 5647 | file_index: Zcu.File.Index, | |
| 5648 | prog_node: std.Progress.Node, | |
| 5649 | group: *Io.Group, | |
| 5650 | ) void { | |
| 5651 | const io = comp.io; | |
| 5652 | const tid: Zcu.PerThread.Id = .acquire(io); | |
| 5653 | defer tid.release(io); | |
| 5654 | ||
| 5655 | const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0); | |
| 5656 | defer child_prog_node.end(); | |
| 5657 | ||
| 5658 | const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); | |
| 5659 | defer pt.deactivate(); | |
| 5660 | pt.updateFile(file_index, file) catch |err| { | |
| 5661 | pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) { | |
| 5662 | error.OutOfMemory => { | |
| 5663 | comp.mutex.lockUncancelable(io); | |
| 5664 | defer comp.mutex.unlock(io); | |
| 5665 | comp.setAllocFailure(); | |
| 5666 | }, | |
| 5667 | }; | |
| 5668 | return; | |
| 5669 | }; | |
| 5670 | ||
| 5671 | switch (file.getMode()) { | |
| 5672 | .zig => {}, // continue to logic below | |
| 5673 | .zon => return, // ZON can't import anything so we're done | |
| 5674 | } | |
| 5675 | ||
| 5676 | // Discover all imports in the file. Imports of modules we ignore for now since we don't | |
| 5677 | // know which module we're in, but imports of file paths might need us to queue up other | |
| 5678 | // AstGen jobs. | |
| 5679 | const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 5680 | if (imports_index != 0) { | |
| 5681 | const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); | |
| 5682 | var import_i: u32 = 0; | |
| 5683 | var extra_index = extra.end; | |
| 5684 | ||
| 5685 | while (import_i < extra.data.imports_len) : (import_i += 1) { | |
| 5686 | const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 5687 | extra_index = item.end; | |
| 5688 | ||
| 5689 | const import_path = file.zir.?.nullTerminatedString(item.data.name); | |
| 5690 | ||
| 5691 | if (pt.discoverImport(file.path, import_path)) |res| switch (res) { | |
| 5692 | .module, .existing_file => {}, | |
| 5693 | .new_file => |new| { | |
| 5694 | group.async(io, workerUpdateFile, .{ | |
| 5695 | comp, new.file, new.index, prog_node, group, | |
| 5696 | }); | |
| 5697 | }, | |
| 5698 | } else |err| switch (err) { | |
| 5699 | error.OutOfMemory => { | |
| 5700 | comp.mutex.lockUncancelable(io); | |
| 5701 | defer comp.mutex.unlock(io); | |
| 5702 | comp.setAllocFailure(); | |
| 5703 | }, | |
| 5704 | } | |
| 5705 | } | |
| 5706 | } | |
| 5707 | } | |
| 5708 | ||
| 5709 | fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { | |
| 5710 | Builtin.updateFileOnDisk(file, comp) catch |err| comp.lockAndSetMiscFailure( | |
| 5711 | .write_builtin_zig, | |
| 5712 | "unable to write '{f}': {s}", | |
| 5713 | .{ file.path.fmt(comp), @errorName(err) }, | |
| 5714 | ); | |
| 5715 | } | |
| 5716 | ||
| 5717 | fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { | |
| 5718 | const io = comp.io; | |
| 5719 | const tid: Zcu.PerThread.Id = .acquire(io); | |
| 5720 | defer tid.release(io); | |
| 5721 | comp.detectEmbedFileUpdate(tid, ef_index, ef) catch |err| switch (err) { | |
| 5722 | error.OutOfMemory => { | |
| 5723 | comp.mutex.lockUncancelable(io); | |
| 5724 | defer comp.mutex.unlock(io); | |
| 5725 | comp.setAllocFailure(); | |
| 5726 | }, | |
| 5727 | }; | |
| 5728 | } | |
| 5729 | ||
| 5730 | fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void { | |
| 5731 | const io = comp.io; | |
| 5732 | const zcu = comp.zcu.?; | |
| 5733 | const pt: Zcu.PerThread = .activate(zcu, tid); | |
| 5734 | defer pt.deactivate(); | |
| 5735 | ||
| 5736 | const old_val = ef.val; | |
| 5737 | const old_err = ef.err; | |
| 5738 | ||
| 5739 | try pt.updateEmbedFile(ef, null); | |
| 5740 | ||
| 5741 | if (ef.val != .none and ef.val == old_val) return; // success, value unchanged | |
| 5742 | if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged | |
| 5743 | ||
| 5744 | comp.mutex.lockUncancelable(io); | |
| 5745 | defer comp.mutex.unlock(io); | |
| 5746 | ||
| 5747 | try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index }); | |
| 5748 | } | |
| 5749 | ||
| 5750 | 5091 | pub fn obtainCObjectCacheManifest( |
| 5751 | 5092 | comp: *const Compilation, |
| 5752 | 5093 | owner_mod: *Package.Module, |
| ... | ... | @@ -8375,12 +7716,10 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { |
| 8375 | 7716 | // If we haven't seen this library yet and we're targeting Windows, we need |
| 8376 | 7717 | // to queue up a work item to produce the DLL import library for this. |
| 8377 | 7718 | const gop = try comp.windows_libs.getOrPut(comp.gpa, lib_name); |
| 8378 | if (gop.found_existing) return; | |
| 8379 | { | |
| 7719 | if (!gop.found_existing) { | |
| 8380 | 7720 | errdefer _ = comp.windows_libs.pop(); |
| 8381 | 7721 | gop.key_ptr.* = try comp.gpa.dupe(u8, lib_name); |
| 8382 | 7722 | } |
| 8383 | try comp.queueJob(.{ .windows_import_lib = gop.index }); | |
| 8384 | 7723 | } |
| 8385 | 7724 | |
| 8386 | 7725 | /// This decides the optimization mode for all zig-provided libraries, including |
src/IncrementalDebugServer.zig+6-8| ... | ... | @@ -306,12 +306,8 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const |
| 306 | 306 | try w.print("[{d}] ", .{i}); |
| 307 | 307 | switch (dependee) { |
| 308 | 308 | .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}), |
| 309 | .nav_val, .nav_ty => |nav| try w.print("{s} {d}", .{ @tagName(dependee), @intFromEnum(nav) }), | |
| 310 | .interned => |ip_index| switch (ip.indexToKey(ip_index)) { | |
| 311 | .struct_type, .union_type, .enum_type => try w.print("type {d}", .{@intFromEnum(ip_index)}), | |
| 312 | .func => try w.print("func {d}", .{@intFromEnum(ip_index)}), | |
| 313 | else => unreachable, | |
| 314 | }, | |
| 309 | .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }), | |
| 310 | .type_layout, .struct_defaults, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), | |
| 315 | 311 | .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}), |
| 316 | 312 | } |
| 317 | 313 | try w.writeByte('\n'); |
| ... | ... | @@ -376,8 +372,10 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit { |
| 376 | 372 | return .wrap(.{ .nav_val = @enumFromInt(parseIndex(idx_str) orelse return null) }); |
| 377 | 373 | } else if (std.mem.eql(u8, kind, "nav_ty")) { |
| 378 | 374 | return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) }); |
| 379 | } else if (std.mem.eql(u8, kind, "type")) { | |
| 380 | return .wrap(.{ .type = @enumFromInt(parseIndex(idx_str) orelse return null) }); | |
| 375 | } else if (std.mem.eql(u8, kind, "type_layout")) { | |
| 376 | return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) }); | |
| 377 | } else if (std.mem.eql(u8, kind, "struct_defaults")) { | |
| 378 | return .wrap(.{ .struct_defaults = @enumFromInt(parseIndex(idx_str) orelse return null) }); | |
| 381 | 379 | } else if (std.mem.eql(u8, kind, "func")) { |
| 382 | 380 | return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) }); |
| 383 | 381 | } else if (std.mem.eql(u8, kind, "memoized_state")) { |
src/InternPool.zig+2670-2835| ... | ... | @@ -17,6 +17,7 @@ const Hash = std.hash.Wyhash; |
| 17 | 17 | const Zir = std.zig.Zir; |
| 18 | 18 | |
| 19 | 19 | const Zcu = @import("Zcu.zig"); |
| 20 | const TypeClass = @import("Type.zig").Class; | |
| 20 | 21 | |
| 21 | 22 | /// One item per thread, indexed by `tid`, which is dense and unique per thread. |
| 22 | 23 | locals: []Local, |
| ... | ... | @@ -47,11 +48,15 @@ nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), |
| 47 | 48 | /// Dependencies on the type of a Nav. |
| 48 | 49 | /// Value is index into `dep_entries` of the first dependency on this Nav value. |
| 49 | 50 | nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), |
| 50 | /// Dependencies on an interned value, either: | |
| 51 | /// * a runtime function (invalidated when its IES changes) | |
| 52 | /// * a container type requiring resolution (invalidated when the type must be recreated at a new index) | |
| 53 | /// Value is index into `dep_entries` of the first dependency on this interned value. | |
| 54 | interned_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), | |
| 51 | /// Dependencies on a function's inferred error set. Key is the function body, not the IES. | |
| 52 | /// Value is index into `dep_entries` of the first dependency on this function's IES. | |
| 53 | func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), | |
| 54 | /// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type. | |
| 55 | /// Value is index into `dep_entries` of the first dependency on this type's layout. | |
| 56 | type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), | |
| 57 | /// Dependencies on the resolved default field values of a `struct` type. | |
| 58 | /// Value is index into `dep_entries` of the first dependency on this type's inits. | |
| 59 | struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), | |
| 55 | 60 | /// Dependencies on a ZON file. Triggered by `@import` of ZON. |
| 56 | 61 | /// Value is index into `dep_entries` of the first dependency on this ZON file. |
| 57 | 62 | zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), |
| ... | ... | @@ -104,7 +109,9 @@ pub const empty: InternPool = .{ |
| 104 | 109 | .src_hash_deps = .empty, |
| 105 | 110 | .nav_val_deps = .empty, |
| 106 | 111 | .nav_ty_deps = .empty, |
| 107 | .interned_deps = .empty, | |
| 112 | .func_ies_deps = .empty, | |
| 113 | .type_layout_deps = .empty, | |
| 114 | .struct_defaults_deps = .empty, | |
| 108 | 115 | .zon_file_deps = .empty, |
| 109 | 116 | .embed_file_deps = .empty, |
| 110 | 117 | .namespace_deps = .empty, |
| ... | ... | @@ -415,7 +422,8 @@ pub const AnalUnit = packed struct(u64) { |
| 415 | 422 | @"comptime", |
| 416 | 423 | nav_val, |
| 417 | 424 | nav_ty, |
| 418 | type, | |
| 425 | type_layout, | |
| 426 | struct_defaults, | |
| 419 | 427 | func, |
| 420 | 428 | memoized_state, |
| 421 | 429 | }; |
| ... | ... | @@ -427,9 +435,10 @@ pub const AnalUnit = packed struct(u64) { |
| 427 | 435 | nav_val: Nav.Index, |
| 428 | 436 | /// This `AnalUnit` resolves the type of the given `Nav`. |
| 429 | 437 | nav_ty: Nav.Index, |
| 430 | /// This `AnalUnit` resolves the given `struct`/`union`/`enum` type. | |
| 431 | /// Generated tag enums are never used here (they do not undergo type resolution). | |
| 432 | type: InternPool.Index, | |
| 438 | /// This `AnalUnit` resolves the layout of the given `struct`, `union`, or `enum` type. | |
| 439 | type_layout: InternPool.Index, | |
| 440 | /// This `AnalUnit` resolves the default field values of the given `struct` type. | |
| 441 | struct_defaults: InternPool.Index, | |
| 433 | 442 | /// This `AnalUnit` analyzes the body of the given runtime function. |
| 434 | 443 | func: InternPool.Index, |
| 435 | 444 | /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`. |
| ... | ... | @@ -538,6 +547,8 @@ pub const Nav = struct { |
| 538 | 547 | analysis: ?struct { |
| 539 | 548 | namespace: NamespaceIndex, |
| 540 | 549 | zir_index: TrackedInst.Index, |
| 550 | /// Initially `false`. Set to `true` by `setWantNavAnalysis`. | |
| 551 | wanted: bool, | |
| 541 | 552 | }, |
| 542 | 553 | status: union(enum) { |
| 543 | 554 | /// This `Nav` is pending semantic analysis. |
| ... | ... | @@ -735,7 +746,7 @@ pub const Nav = struct { |
| 735 | 746 | const Repr = struct { |
| 736 | 747 | name: NullTerminatedString, |
| 737 | 748 | fqn: NullTerminatedString, |
| 738 | // The following 1 fields are either both populated, or both `.none`. | |
| 749 | // The following 2 fields are either both populated, or both `.none`. | |
| 739 | 750 | analysis_namespace: OptionalNamespaceIndex, |
| 740 | 751 | analysis_zir_index: TrackedInst.Index.Optional, |
| 741 | 752 | /// Populated only if `bits.status != .unresolved`. |
| ... | ... | @@ -754,7 +765,7 @@ pub const Nav = struct { |
| 754 | 765 | @"addrspace": std.builtin.AddressSpace, |
| 755 | 766 | /// Populated only if `bits.status == .type_resolved`. |
| 756 | 767 | is_threadlocal: bool, |
| 757 | _: u1 = 0, | |
| 768 | want_analysis: bool, | |
| 758 | 769 | }; |
| 759 | 770 | |
| 760 | 771 | fn unpack(repr: Repr) Nav { |
| ... | ... | @@ -764,6 +775,7 @@ pub const Nav = struct { |
| 764 | 775 | .analysis = if (repr.analysis_namespace.unwrap()) |namespace| .{ |
| 765 | 776 | .namespace = namespace, |
| 766 | 777 | .zir_index = repr.analysis_zir_index.unwrap().?, |
| 778 | .wanted = repr.bits.want_analysis, | |
| 767 | 779 | } else a: { |
| 768 | 780 | assert(repr.analysis_zir_index == .none); |
| 769 | 781 | break :a null; |
| ... | ... | @@ -816,6 +828,7 @@ pub const Nav = struct { |
| 816 | 828 | .alignment = .none, |
| 817 | 829 | .@"addrspace" = .generic, |
| 818 | 830 | .is_threadlocal = false, |
| 831 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 819 | 832 | }, |
| 820 | 833 | .type_resolved => |r| .{ |
| 821 | 834 | .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, |
| ... | ... | @@ -823,6 +836,7 @@ pub const Nav = struct { |
| 823 | 836 | .alignment = r.alignment, |
| 824 | 837 | .@"addrspace" = r.@"addrspace", |
| 825 | 838 | .is_threadlocal = r.is_threadlocal, |
| 839 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 826 | 840 | }, |
| 827 | 841 | .fully_resolved => |r| .{ |
| 828 | 842 | .status = .fully_resolved, |
| ... | ... | @@ -830,6 +844,7 @@ pub const Nav = struct { |
| 830 | 844 | .alignment = r.alignment, |
| 831 | 845 | .@"addrspace" = r.@"addrspace", |
| 832 | 846 | .is_threadlocal = false, |
| 847 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 833 | 848 | }, |
| 834 | 849 | }, |
| 835 | 850 | }; |
| ... | ... | @@ -840,7 +855,10 @@ pub const Dependee = union(enum) { |
| 840 | 855 | src_hash: TrackedInst.Index, |
| 841 | 856 | nav_val: Nav.Index, |
| 842 | 857 | nav_ty: Nav.Index, |
| 843 | interned: Index, | |
| 858 | /// Index is the function, not its IES. | |
| 859 | func_ies: Index, | |
| 860 | type_layout: Index, | |
| 861 | struct_defaults: Index, | |
| 844 | 862 | zon_file: FileIndex, |
| 845 | 863 | embed_file: Zcu.EmbedFile.Index, |
| 846 | 864 | namespace: TrackedInst.Index, |
| ... | ... | @@ -892,7 +910,9 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI |
| 892 | 910 | .src_hash => |x| ip.src_hash_deps.get(x), |
| 893 | 911 | .nav_val => |x| ip.nav_val_deps.get(x), |
| 894 | 912 | .nav_ty => |x| ip.nav_ty_deps.get(x), |
| 895 | .interned => |x| ip.interned_deps.get(x), | |
| 913 | .func_ies => |x| ip.func_ies_deps.get(x), | |
| 914 | .type_layout => |x| ip.type_layout_deps.get(x), | |
| 915 | .struct_defaults => |x| ip.struct_defaults_deps.get(x), | |
| 896 | 916 | .zon_file => |x| ip.zon_file_deps.get(x), |
| 897 | 917 | .embed_file => |x| ip.embed_file_deps.get(x), |
| 898 | 918 | .namespace => |x| ip.namespace_deps.get(x), |
| ... | ... | @@ -965,7 +985,9 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend |
| 965 | 985 | .src_hash => ip.src_hash_deps, |
| 966 | 986 | .nav_val => ip.nav_val_deps, |
| 967 | 987 | .nav_ty => ip.nav_ty_deps, |
| 968 | .interned => ip.interned_deps, | |
| 988 | .func_ies => ip.func_ies_deps, | |
| 989 | .type_layout => ip.type_layout_deps, | |
| 990 | .struct_defaults => ip.struct_defaults_deps, | |
| 969 | 991 | .zon_file => ip.zon_file_deps, |
| 970 | 992 | .embed_file => ip.embed_file_deps, |
| 971 | 993 | .namespace => ip.namespace_deps, |
| ... | ... | @@ -2065,15 +2087,15 @@ pub const Key = union(enum) { |
| 2065 | 2087 | simple_type: SimpleType, |
| 2066 | 2088 | /// This represents a struct that has been explicitly declared in source code, |
| 2067 | 2089 | /// or was created with `@Struct`. It is unique and based on a declaration. |
| 2068 | struct_type: NamespaceType, | |
| 2090 | struct_type: ContainerType, | |
| 2069 | 2091 | /// This is a tuple type. Tuples are logically similar to structs, but have some |
| 2070 | 2092 | /// important differences in semantics; they do not undergo staged type resolution, |
| 2071 | 2093 | /// so cannot be self-referential, and they are not considered container/namespace |
| 2072 | 2094 | /// types, so cannot have declarations and have structural equality properties. |
| 2073 | 2095 | tuple_type: TupleType, |
| 2074 | union_type: NamespaceType, | |
| 2075 | opaque_type: NamespaceType, | |
| 2076 | enum_type: NamespaceType, | |
| 2096 | union_type: ContainerType, | |
| 2097 | opaque_type: ContainerType, | |
| 2098 | enum_type: ContainerType, | |
| 2077 | 2099 | func_type: FuncType, |
| 2078 | 2100 | error_set_type: ErrorSetType, |
| 2079 | 2101 | /// The payload is the function body, either a `func_decl` or `func_instance`. |
| ... | ... | @@ -2092,10 +2114,6 @@ pub const Key = union(enum) { |
| 2092 | 2114 | enum_literal: NullTerminatedString, |
| 2093 | 2115 | /// A specific enum tag, indicated by the integer tag value. |
| 2094 | 2116 | enum_tag: EnumTag, |
| 2095 | /// An empty enum or union. TODO: this value's existence is strange, because such a type in | |
| 2096 | /// reality has no values. See #15909. | |
| 2097 | /// Payload is the type for which we are an empty value. | |
| 2098 | empty_enum_value: Index, | |
| 2099 | 2117 | float: Float, |
| 2100 | 2118 | ptr: Ptr, |
| 2101 | 2119 | slice: Slice, |
| ... | ... | @@ -2109,6 +2127,8 @@ pub const Key = union(enum) { |
| 2109 | 2127 | aggregate: Aggregate, |
| 2110 | 2128 | /// An instance of a union. |
| 2111 | 2129 | un: Union, |
| 2130 | /// An instance of a `packed struct` or `packed union`. | |
| 2131 | bitpack: Bitpack, | |
| 2112 | 2132 | |
| 2113 | 2133 | /// A comptime function call with a memoized result. |
| 2114 | 2134 | memoized_call: Key.MemoizedCall, |
| ... | ... | @@ -2211,16 +2231,10 @@ pub const Key = union(enum) { |
| 2211 | 2231 | /// * `loadUnionType` |
| 2212 | 2232 | /// * `loadEnumType` |
| 2213 | 2233 | /// * `loadOpaqueType` |
| 2214 | pub const NamespaceType = union(enum) { | |
| 2234 | pub const ContainerType = union(enum) { | |
| 2215 | 2235 | /// This type corresponds to an actual source declaration, e.g. `struct { ... }`. |
| 2216 | 2236 | /// It is hashed based on its ZIR instruction index and set of captures. |
| 2217 | 2237 | declared: Declared, |
| 2218 | /// This type is an automatically-generated enum tag type for a union. | |
| 2219 | /// It is hashed based on the index of the union type it corresponds to. | |
| 2220 | generated_tag: struct { | |
| 2221 | /// The union for which this is a tag type. | |
| 2222 | union_type: Index, | |
| 2223 | }, | |
| 2224 | 2238 | /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization. |
| 2225 | 2239 | /// It is hashed based on its ZIR instruction index and fields, attributes, etc. |
| 2226 | 2240 | /// To avoid making this key overly complex, the type-specific data is hashed by Sema. |
| ... | ... | @@ -2231,6 +2245,9 @@ pub const Key = union(enum) { |
| 2231 | 2245 | /// A hash of this type's attributes, fields, etc, generated by Sema. |
| 2232 | 2246 | type_hash: u64, |
| 2233 | 2247 | }, |
| 2248 | /// This type is an automatically-generated enum tag type for this union type. | |
| 2249 | /// It is hashed based on the index of the union type it corresponds to. | |
| 2250 | generated_union_tag: Index, | |
| 2234 | 2251 | |
| 2235 | 2252 | pub const Declared = struct { |
| 2236 | 2253 | /// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction. |
| ... | ... | @@ -2254,7 +2271,6 @@ pub const Key = union(enum) { |
| 2254 | 2271 | noalias_bits: u32, |
| 2255 | 2272 | cc: std.builtin.CallingConvention, |
| 2256 | 2273 | is_var_args: bool, |
| 2257 | is_generic: bool, | |
| 2258 | 2274 | is_noinline: bool, |
| 2259 | 2275 | |
| 2260 | 2276 | pub fn paramIsComptime(self: @This(), i: u5) bool { |
| ... | ... | @@ -2273,7 +2289,6 @@ pub const Key = union(enum) { |
| 2273 | 2289 | a.comptime_bits == b.comptime_bits and |
| 2274 | 2290 | a.noalias_bits == b.noalias_bits and |
| 2275 | 2291 | a.is_var_args == b.is_var_args and |
| 2276 | a.is_generic == b.is_generic and | |
| 2277 | 2292 | a.is_noinline == b.is_noinline and |
| 2278 | 2293 | std.meta.eql(a.cc, b.cc); |
| 2279 | 2294 | } |
| ... | ... | @@ -2287,7 +2302,6 @@ pub const Key = union(enum) { |
| 2287 | 2302 | std.hash.autoHash(hasher, self.noalias_bits); |
| 2288 | 2303 | std.hash.autoHash(hasher, self.cc); |
| 2289 | 2304 | std.hash.autoHash(hasher, self.is_var_args); |
| 2290 | std.hash.autoHash(hasher, self.is_generic); | |
| 2291 | 2305 | std.hash.autoHash(hasher, self.is_noinline); |
| 2292 | 2306 | } |
| 2293 | 2307 | }; |
| ... | ... | @@ -2403,17 +2417,6 @@ pub const Key = union(enum) { |
| 2403 | 2417 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); |
| 2404 | 2418 | } |
| 2405 | 2419 | |
| 2406 | pub fn setAnalyzed(func: Func, ip: *InternPool, io: Io) void { | |
| 2407 | const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; | |
| 2408 | extra_mutex.lockUncancelable(io); | |
| 2409 | defer extra_mutex.unlock(io); | |
| 2410 | ||
| 2411 | const analysis_ptr = func.analysisPtr(ip); | |
| 2412 | var analysis = analysis_ptr.*; | |
| 2413 | analysis.is_analyzed = true; | |
| 2414 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); | |
| 2415 | } | |
| 2416 | ||
| 2417 | 2420 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. |
| 2418 | 2421 | fn zirBodyInstPtr(func: Func, ip: *const InternPool) *TrackedInst.Index { |
| 2419 | 2422 | const extra = ip.getLocalShared(func.tid).extra.acquire(); |
| ... | ... | @@ -2471,8 +2474,6 @@ pub const Key = union(enum) { |
| 2471 | 2474 | u64: u64, |
| 2472 | 2475 | i64: i64, |
| 2473 | 2476 | big_int: BigIntConst, |
| 2474 | lazy_align: Index, | |
| 2475 | lazy_size: Index, | |
| 2476 | 2477 | |
| 2477 | 2478 | /// Big enough to fit any non-BigInt value |
| 2478 | 2479 | pub const BigIntSpace = struct { |
| ... | ... | @@ -2485,7 +2486,6 @@ pub const Key = union(enum) { |
| 2485 | 2486 | return switch (storage) { |
| 2486 | 2487 | .big_int => |x| x, |
| 2487 | 2488 | inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(), |
| 2488 | .lazy_align, .lazy_size => unreachable, | |
| 2489 | 2489 | }; |
| 2490 | 2490 | } |
| 2491 | 2491 | }; |
| ... | ... | @@ -2680,6 +2680,15 @@ pub const Key = union(enum) { |
| 2680 | 2680 | }; |
| 2681 | 2681 | }; |
| 2682 | 2682 | |
| 2683 | /// As well as a key, this type doubles as the payload in `extra` for `Tag.bitpack`. | |
| 2684 | pub const Bitpack = struct { | |
| 2685 | /// The `packed struct` or `packed union` type. | |
| 2686 | ty: Index, | |
| 2687 | /// The contents of the bitpack, represented as the backing integer value. The type of this | |
| 2688 | /// value is the same as the backing integer type of `ty`. | |
| 2689 | backing_int_val: Index, | |
| 2690 | }; | |
| 2691 | ||
| 2683 | 2692 | pub const MemoizedCall = struct { |
| 2684 | 2693 | func: Index, |
| 2685 | 2694 | arg_values: []const Index, |
| ... | ... | @@ -2710,7 +2719,6 @@ pub const Key = union(enum) { |
| 2710 | 2719 | .err, |
| 2711 | 2720 | .enum_literal, |
| 2712 | 2721 | .enum_tag, |
| 2713 | .empty_enum_value, | |
| 2714 | 2722 | .inferred_error_set_type, |
| 2715 | 2723 | .un, |
| 2716 | 2724 | => |x| Hash.hash(seed, asBytes(&x)), |
| ... | ... | @@ -2742,13 +2750,13 @@ pub const Key = union(enum) { |
| 2742 | 2750 | std.hash.autoHash(&hasher, cv); |
| 2743 | 2751 | } |
| 2744 | 2752 | }, |
| 2745 | .generated_tag => |generated_tag| { | |
| 2746 | std.hash.autoHash(&hasher, generated_tag.union_type); | |
| 2747 | }, | |
| 2748 | 2753 | .reified => |reified| { |
| 2749 | 2754 | std.hash.autoHash(&hasher, reified.zir_index); |
| 2750 | 2755 | std.hash.autoHash(&hasher, reified.type_hash); |
| 2751 | 2756 | }, |
| 2757 | .generated_union_tag => |union_type| { | |
| 2758 | std.hash.autoHash(&hasher, union_type); | |
| 2759 | }, | |
| 2752 | 2760 | } |
| 2753 | 2761 | return hasher.final(); |
| 2754 | 2762 | }, |
| ... | ... | @@ -2756,23 +2764,12 @@ pub const Key = union(enum) { |
| 2756 | 2764 | .int => |int| { |
| 2757 | 2765 | var hasher = Hash.init(seed); |
| 2758 | 2766 | // Canonicalize all integers by converting them to BigIntConst. |
| 2759 | switch (int.storage) { | |
| 2760 | .u64, .i64, .big_int => { | |
| 2761 | var buffer: Key.Int.Storage.BigIntSpace = undefined; | |
| 2762 | const big_int = int.storage.toBigInt(&buffer); | |
| 2763 | ||
| 2764 | std.hash.autoHash(&hasher, int.ty); | |
| 2765 | std.hash.autoHash(&hasher, big_int.positive); | |
| 2766 | for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb); | |
| 2767 | }, | |
| 2768 | .lazy_align, .lazy_size => |lazy_ty| { | |
| 2769 | std.hash.autoHash( | |
| 2770 | &hasher, | |
| 2771 | @as(@typeInfo(Key.Int.Storage).@"union".tag_type.?, int.storage), | |
| 2772 | ); | |
| 2773 | std.hash.autoHash(&hasher, lazy_ty); | |
| 2774 | }, | |
| 2775 | } | |
| 2767 | var buffer: Key.Int.Storage.BigIntSpace = undefined; | |
| 2768 | const big_int = int.storage.toBigInt(&buffer); | |
| 2769 | ||
| 2770 | std.hash.autoHash(&hasher, int.ty); | |
| 2771 | std.hash.autoHash(&hasher, big_int.positive); | |
| 2772 | for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb); | |
| 2776 | 2773 | return hasher.final(); |
| 2777 | 2774 | }, |
| 2778 | 2775 | |
| ... | ... | @@ -2929,6 +2926,8 @@ pub const Key = union(enum) { |
| 2929 | 2926 | asBytes(&e.relocation) ++ |
| 2930 | 2927 | asBytes(&e.is_const) ++ asBytes(&e.alignment) ++ asBytes(&e.@"addrspace") ++ |
| 2931 | 2928 | asBytes(&e.zir_index) ++ &[1]u8{@intFromEnum(e.source)}), |
| 2929 | ||
| 2930 | .bitpack => |bitpack| Hash.hash(seed, asBytes(&bitpack.ty) ++ asBytes(&bitpack.backing_int_val)), | |
| 2932 | 2931 | }; |
| 2933 | 2932 | } |
| 2934 | 2933 | |
| ... | ... | @@ -3002,9 +3001,9 @@ pub const Key = union(enum) { |
| 3002 | 3001 | const b_info = b.enum_tag; |
| 3003 | 3002 | return std.meta.eql(a_info, b_info); |
| 3004 | 3003 | }, |
| 3005 | .empty_enum_value => |a_info| { | |
| 3006 | const b_info = b.empty_enum_value; | |
| 3007 | return a_info == b_info; | |
| 3004 | .bitpack => |a_info| { | |
| 3005 | const b_info = b.bitpack; | |
| 3006 | return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val; | |
| 3008 | 3007 | }, |
| 3009 | 3008 | |
| 3010 | 3009 | .variable => |a_info| { |
| ... | ... | @@ -3102,27 +3101,16 @@ pub const Key = union(enum) { |
| 3102 | 3101 | .u64 => |bb| aa == bb, |
| 3103 | 3102 | .i64 => |bb| aa == bb, |
| 3104 | 3103 | .big_int => |bb| bb.orderAgainstScalar(aa) == .eq, |
| 3105 | .lazy_align, .lazy_size => false, | |
| 3106 | 3104 | }, |
| 3107 | 3105 | .i64 => |aa| switch (b_info.storage) { |
| 3108 | 3106 | .u64 => |bb| aa == bb, |
| 3109 | 3107 | .i64 => |bb| aa == bb, |
| 3110 | 3108 | .big_int => |bb| bb.orderAgainstScalar(aa) == .eq, |
| 3111 | .lazy_align, .lazy_size => false, | |
| 3112 | 3109 | }, |
| 3113 | 3110 | .big_int => |aa| switch (b_info.storage) { |
| 3114 | 3111 | .u64 => |bb| aa.orderAgainstScalar(bb) == .eq, |
| 3115 | 3112 | .i64 => |bb| aa.orderAgainstScalar(bb) == .eq, |
| 3116 | 3113 | .big_int => |bb| aa.eql(bb), |
| 3117 | .lazy_align, .lazy_size => false, | |
| 3118 | }, | |
| 3119 | .lazy_align => |aa| switch (b_info.storage) { | |
| 3120 | .u64, .i64, .big_int, .lazy_size => false, | |
| 3121 | .lazy_align => |bb| aa == bb, | |
| 3122 | }, | |
| 3123 | .lazy_size => |aa| switch (b_info.storage) { | |
| 3124 | .u64, .i64, .big_int, .lazy_align => false, | |
| 3125 | .lazy_size => |bb| aa == bb, | |
| 3126 | 3114 | }, |
| 3127 | 3115 | }; |
| 3128 | 3116 | }, |
| ... | ... | @@ -3175,12 +3163,12 @@ pub const Key = union(enum) { |
| 3175 | 3163 | }; |
| 3176 | 3164 | return std.mem.eql(u32, @ptrCast(a_captures), @ptrCast(b_captures)); |
| 3177 | 3165 | }, |
| 3178 | .generated_tag => |a_gt| return a_gt.union_type == b_info.generated_tag.union_type, | |
| 3179 | 3166 | .reified => |a_r| { |
| 3180 | 3167 | const b_r = b_info.reified; |
| 3181 | 3168 | return a_r.zir_index == b_r.zir_index and |
| 3182 | 3169 | a_r.type_hash == b_r.type_hash; |
| 3183 | 3170 | }, |
| 3171 | .generated_union_tag => |a_union_ty| return a_union_ty == b_info.generated_union_tag, | |
| 3184 | 3172 | } |
| 3185 | 3173 | }, |
| 3186 | 3174 | .aggregate => |a_info| { |
| ... | ... | @@ -3292,19 +3280,17 @@ pub const Key = union(enum) { |
| 3292 | 3280 | .enum_tag, |
| 3293 | 3281 | .aggregate, |
| 3294 | 3282 | .un, |
| 3283 | .bitpack, | |
| 3295 | 3284 | => |x| x.ty, |
| 3296 | 3285 | |
| 3297 | 3286 | .enum_literal => .enum_literal_type, |
| 3298 | 3287 | |
| 3299 | 3288 | .undef => |x| x, |
| 3300 | .empty_enum_value => |x| x, | |
| 3301 | 3289 | |
| 3302 | 3290 | .simple_value => |s| switch (s) { |
| 3303 | .undefined => .undefined_type, | |
| 3304 | 3291 | .void => .void_type, |
| 3305 | 3292 | .null => .null_type, |
| 3306 | 3293 | .false, .true => .bool_type, |
| 3307 | .empty_tuple => .empty_tuple_type, | |
| 3308 | 3294 | .@"unreachable" => .noreturn_type, |
| 3309 | 3295 | }, |
| 3310 | 3296 | |
| ... | ... | @@ -3313,374 +3299,53 @@ pub const Key = union(enum) { |
| 3313 | 3299 | } |
| 3314 | 3300 | }; |
| 3315 | 3301 | |
| 3316 | pub const RequiresComptime = enum(u2) { no, yes, unknown, wip }; | |
| 3317 | ||
| 3318 | // Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a | |
| 3319 | // minimal hashmap key, this type is a convenience type that contains info | |
| 3320 | // needed by semantic analysis. | |
| 3321 | pub const LoadedUnionType = struct { | |
| 3322 | tid: Zcu.PerThread.Id, | |
| 3323 | /// The index of the `Tag.TypeUnion` payload. | |
| 3324 | extra_index: u32, | |
| 3325 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 3326 | /// The name of this union type. | |
| 3327 | name: NullTerminatedString, | |
| 3328 | /// Represents the declarations inside this union. | |
| 3329 | namespace: NamespaceIndex, | |
| 3330 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | |
| 3331 | /// Otherwise, this is `.none`. | |
| 3332 | name_nav: Nav.Index.Optional, | |
| 3333 | /// The enum tag type. | |
| 3334 | enum_tag_ty: Index, | |
| 3335 | /// List of field types in declaration order. | |
| 3336 | /// These are `none` until `status` is `have_field_types` or `have_layout`. | |
| 3337 | field_types: Index.Slice, | |
| 3338 | /// List of field alignments in declaration order. | |
| 3339 | /// `none` means the ABI alignment of the type. | |
| 3340 | /// If this slice has length 0 it means all elements are `none`. | |
| 3341 | field_aligns: Alignment.Slice, | |
| 3342 | /// Index of the union_decl or reify ZIR instruction. | |
| 3302 | pub const LoadedStructType = struct { | |
| 3303 | /// Index of the `struct_decl` or `reify` ZIR instruction. | |
| 3343 | 3304 | zir_index: TrackedInst.Index, |
| 3344 | 3305 | captures: CaptureValue.Slice, |
| 3306 | is_reified: bool, | |
| 3345 | 3307 | |
| 3346 | pub const RuntimeTag = enum(u2) { | |
| 3347 | none, | |
| 3348 | safety, | |
| 3349 | tagged, | |
| 3350 | ||
| 3351 | pub fn hasTag(self: RuntimeTag) bool { | |
| 3352 | return switch (self) { | |
| 3353 | .none => false, | |
| 3354 | .tagged, .safety => true, | |
| 3355 | }; | |
| 3356 | } | |
| 3357 | }; | |
| 3358 | ||
| 3359 | pub const Status = enum(u3) { | |
| 3360 | none, | |
| 3361 | field_types_wip, | |
| 3362 | have_field_types, | |
| 3363 | layout_wip, | |
| 3364 | have_layout, | |
| 3365 | fully_resolved_wip, | |
| 3366 | /// The types and all its fields have had their layout resolved. | |
| 3367 | /// Even through pointer, which `have_layout` does not ensure. | |
| 3368 | fully_resolved, | |
| 3369 | ||
| 3370 | pub fn haveFieldTypes(status: Status) bool { | |
| 3371 | return switch (status) { | |
| 3372 | .none, | |
| 3373 | .field_types_wip, | |
| 3374 | => false, | |
| 3375 | .have_field_types, | |
| 3376 | .layout_wip, | |
| 3377 | .have_layout, | |
| 3378 | .fully_resolved_wip, | |
| 3379 | .fully_resolved, | |
| 3380 | => true, | |
| 3381 | }; | |
| 3382 | } | |
| 3383 | ||
| 3384 | pub fn haveLayout(status: Status) bool { | |
| 3385 | return switch (status) { | |
| 3386 | .none, | |
| 3387 | .field_types_wip, | |
| 3388 | .have_field_types, | |
| 3389 | .layout_wip, | |
| 3390 | => false, | |
| 3391 | .have_layout, | |
| 3392 | .fully_resolved_wip, | |
| 3393 | .fully_resolved, | |
| 3394 | => true, | |
| 3395 | }; | |
| 3396 | } | |
| 3397 | }; | |
| 3398 | ||
| 3399 | pub fn loadTagType(self: LoadedUnionType, ip: *const InternPool) LoadedEnumType { | |
| 3400 | return ip.loadEnumType(self.enum_tag_ty); | |
| 3401 | } | |
| 3402 | ||
| 3403 | /// Pointer to an enum type which is used for the tag of the union. | |
| 3404 | /// This type is created even for untagged unions, even when the memory | |
| 3405 | /// layout does not store the tag. | |
| 3406 | /// Whether zig chooses this type or the user specifies it, it is stored here. | |
| 3407 | /// This will be set to the null type until status is `have_field_types`. | |
| 3408 | /// This accessor is provided so that the tag type can be mutated, and so that | |
| 3409 | /// when it is mutated, the mutations are observed. | |
| 3410 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 3411 | fn tagTypePtr(self: LoadedUnionType, ip: *const InternPool) *Index { | |
| 3412 | const extra = ip.getLocalShared(self.tid).extra.acquire(); | |
| 3413 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?; | |
| 3414 | return @ptrCast(&extra.view().items(.@"0")[self.extra_index + field_index]); | |
| 3415 | } | |
| 3416 | ||
| 3417 | pub fn tagTypeUnordered(u: LoadedUnionType, ip: *const InternPool) Index { | |
| 3418 | return @atomicLoad(Index, u.tagTypePtr(ip), .unordered); | |
| 3419 | } | |
| 3420 | ||
| 3421 | pub fn setTagType(u: LoadedUnionType, ip: *InternPool, io: Io, tag_type: Index) void { | |
| 3422 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3423 | extra_mutex.lockUncancelable(io); | |
| 3424 | defer extra_mutex.unlock(io); | |
| 3425 | ||
| 3426 | @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release); | |
| 3427 | } | |
| 3428 | ||
| 3429 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 3430 | fn flagsPtr(self: LoadedUnionType, ip: *const InternPool) *Tag.TypeUnion.Flags { | |
| 3431 | const extra = ip.getLocalShared(self.tid).extra.acquire(); | |
| 3432 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | |
| 3433 | return @ptrCast(&extra.view().items(.@"0")[self.extra_index + field_index]); | |
| 3434 | } | |
| 3435 | ||
| 3436 | pub fn flagsUnordered(u: LoadedUnionType, ip: *const InternPool) Tag.TypeUnion.Flags { | |
| 3437 | return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered); | |
| 3438 | } | |
| 3439 | ||
| 3440 | pub fn setStatus(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void { | |
| 3441 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3442 | extra_mutex.lockUncancelable(io); | |
| 3443 | defer extra_mutex.unlock(io); | |
| 3444 | ||
| 3445 | const flags_ptr = u.flagsPtr(ip); | |
| 3446 | var flags = flags_ptr.*; | |
| 3447 | flags.status = status; | |
| 3448 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3449 | } | |
| 3450 | ||
| 3451 | pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void { | |
| 3452 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3453 | extra_mutex.lockUncancelable(io); | |
| 3454 | defer extra_mutex.unlock(io); | |
| 3455 | ||
| 3456 | const flags_ptr = u.flagsPtr(ip); | |
| 3457 | var flags = flags_ptr.*; | |
| 3458 | if (flags.status == .layout_wip) flags.status = status; | |
| 3459 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3460 | } | |
| 3461 | ||
| 3462 | pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, io: Io, alignment: Alignment) void { | |
| 3463 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3464 | extra_mutex.lockUncancelable(io); | |
| 3465 | defer extra_mutex.unlock(io); | |
| 3466 | ||
| 3467 | const flags_ptr = u.flagsPtr(ip); | |
| 3468 | var flags = flags_ptr.*; | |
| 3469 | flags.alignment = alignment; | |
| 3470 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3471 | } | |
| 3472 | ||
| 3473 | pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io) bool { | |
| 3474 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3475 | extra_mutex.lockUncancelable(io); | |
| 3476 | defer extra_mutex.unlock(io); | |
| 3477 | ||
| 3478 | const flags_ptr = u.flagsPtr(ip); | |
| 3479 | var flags = flags_ptr.*; | |
| 3480 | defer if (flags.status == .field_types_wip) { | |
| 3481 | flags.assumed_runtime_bits = true; | |
| 3482 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3483 | }; | |
| 3484 | return flags.status == .field_types_wip; | |
| 3485 | } | |
| 3486 | ||
| 3487 | pub fn requiresComptime(u: LoadedUnionType, ip: *const InternPool) RequiresComptime { | |
| 3488 | return u.flagsUnordered(ip).requires_comptime; | |
| 3489 | } | |
| 3490 | ||
| 3491 | pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool, io: Io) RequiresComptime { | |
| 3492 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3493 | extra_mutex.lockUncancelable(io); | |
| 3494 | defer extra_mutex.unlock(io); | |
| 3495 | ||
| 3496 | const flags_ptr = u.flagsPtr(ip); | |
| 3497 | var flags = flags_ptr.*; | |
| 3498 | defer if (flags.requires_comptime == .unknown) { | |
| 3499 | flags.requires_comptime = .wip; | |
| 3500 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3501 | }; | |
| 3502 | return flags.requires_comptime; | |
| 3503 | } | |
| 3504 | ||
| 3505 | pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void { | |
| 3506 | assert(requires_comptime != .wip); // see setRequiresComptimeWip | |
| 3507 | ||
| 3508 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3509 | extra_mutex.lockUncancelable(io); | |
| 3510 | defer extra_mutex.unlock(io); | |
| 3511 | ||
| 3512 | const flags_ptr = u.flagsPtr(ip); | |
| 3513 | var flags = flags_ptr.*; | |
| 3514 | flags.requires_comptime = requires_comptime; | |
| 3515 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3516 | } | |
| 3517 | ||
| 3518 | pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { | |
| 3519 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3520 | extra_mutex.lockUncancelable(io); | |
| 3521 | defer extra_mutex.unlock(io); | |
| 3522 | ||
| 3523 | const flags_ptr = u.flagsPtr(ip); | |
| 3524 | var flags = flags_ptr.*; | |
| 3525 | defer if (flags.status == .field_types_wip) { | |
| 3526 | flags.alignment = ptr_align; | |
| 3527 | flags.assumed_pointer_aligned = true; | |
| 3528 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3529 | }; | |
| 3530 | return flags.status == .field_types_wip; | |
| 3531 | } | |
| 3532 | ||
| 3533 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 3534 | fn sizePtr(self: LoadedUnionType, ip: *const InternPool) *u32 { | |
| 3535 | const extra = ip.getLocalShared(self.tid).extra.acquire(); | |
| 3536 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?; | |
| 3537 | return &extra.view().items(.@"0")[self.extra_index + field_index]; | |
| 3538 | } | |
| 3539 | ||
| 3540 | pub fn sizeUnordered(u: LoadedUnionType, ip: *const InternPool) u32 { | |
| 3541 | return @atomicLoad(u32, u.sizePtr(ip), .unordered); | |
| 3542 | } | |
| 3543 | ||
| 3544 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 3545 | fn paddingPtr(self: LoadedUnionType, ip: *const InternPool) *u32 { | |
| 3546 | const extra = ip.getLocalShared(self.tid).extra.acquire(); | |
| 3547 | const field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?; | |
| 3548 | return &extra.view().items(.@"0")[self.extra_index + field_index]; | |
| 3549 | } | |
| 3550 | ||
| 3551 | pub fn paddingUnordered(u: LoadedUnionType, ip: *const InternPool) u32 { | |
| 3552 | return @atomicLoad(u32, u.paddingPtr(ip), .unordered); | |
| 3553 | } | |
| 3554 | ||
| 3555 | pub fn hasTag(self: LoadedUnionType, ip: *const InternPool) bool { | |
| 3556 | return self.flagsUnordered(ip).runtime_tag.hasTag(); | |
| 3557 | } | |
| 3558 | ||
| 3559 | pub fn haveFieldTypes(self: LoadedUnionType, ip: *const InternPool) bool { | |
| 3560 | return self.flagsUnordered(ip).status.haveFieldTypes(); | |
| 3561 | } | |
| 3562 | ||
| 3563 | pub fn haveLayout(self: LoadedUnionType, ip: *const InternPool) bool { | |
| 3564 | return self.flagsUnordered(ip).status.haveLayout(); | |
| 3565 | } | |
| 3566 | ||
| 3567 | pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, io: Io, size: u32, padding: u32, alignment: Alignment) void { | |
| 3568 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; | |
| 3569 | extra_mutex.lockUncancelable(io); | |
| 3570 | defer extra_mutex.unlock(io); | |
| 3571 | ||
| 3572 | @atomicStore(u32, u.sizePtr(ip), size, .unordered); | |
| 3573 | @atomicStore(u32, u.paddingPtr(ip), padding, .unordered); | |
| 3574 | const flags_ptr = u.flagsPtr(ip); | |
| 3575 | var flags = flags_ptr.*; | |
| 3576 | flags.alignment = alignment; | |
| 3577 | flags.status = .have_layout; | |
| 3578 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); | |
| 3579 | } | |
| 3580 | ||
| 3581 | pub fn fieldAlign(self: LoadedUnionType, ip: *const InternPool, field_index: usize) Alignment { | |
| 3582 | if (self.field_aligns.len == 0) return .none; | |
| 3583 | return self.field_aligns.get(ip)[field_index]; | |
| 3584 | } | |
| 3585 | ||
| 3586 | /// This does not mutate the field of LoadedUnionType. | |
| 3587 | pub fn setZirIndex(self: LoadedUnionType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | |
| 3588 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | |
| 3589 | const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; | |
| 3590 | const ptr: *TrackedInst.Index.Optional = | |
| 3591 | @ptrCast(&ip.extra_.items[self.flags_index - flags_field_index + zir_index_field_index]); | |
| 3592 | ptr.* = new_zir_index; | |
| 3593 | } | |
| 3594 | ||
| 3595 | pub fn setFieldTypes(self: LoadedUnionType, ip: *const InternPool, types: []const Index) void { | |
| 3596 | @memcpy(self.field_types.get(ip), types); | |
| 3597 | } | |
| 3598 | ||
| 3599 | pub fn setFieldAligns(self: LoadedUnionType, ip: *const InternPool, aligns: []const Alignment) void { | |
| 3600 | if (aligns.len == 0) return; | |
| 3601 | assert(self.flagsUnordered(ip).any_aligned_fields); | |
| 3602 | @memcpy(self.field_aligns.get(ip), aligns); | |
| 3603 | } | |
| 3604 | }; | |
| 3605 | ||
| 3606 | pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { | |
| 3607 | const unwrapped_index = index.unwrap(ip); | |
| 3608 | const extra_list = unwrapped_index.getExtra(ip); | |
| 3609 | const data = unwrapped_index.getData(ip); | |
| 3610 | const type_union = extraDataTrail(extra_list, Tag.TypeUnion, data); | |
| 3611 | const fields_len = type_union.data.fields_len; | |
| 3612 | ||
| 3613 | var extra_index = type_union.end; | |
| 3614 | const captures_len = if (type_union.data.flags.any_captures) c: { | |
| 3615 | const len = extra_list.view().items(.@"0")[extra_index]; | |
| 3616 | extra_index += 1; | |
| 3617 | break :c len; | |
| 3618 | } else 0; | |
| 3619 | ||
| 3620 | const captures: CaptureValue.Slice = .{ | |
| 3621 | .tid = unwrapped_index.tid, | |
| 3622 | .start = extra_index, | |
| 3623 | .len = captures_len, | |
| 3624 | }; | |
| 3625 | extra_index += captures_len; | |
| 3626 | if (type_union.data.flags.is_reified) { | |
| 3627 | extra_index += 2; // PackedU64 | |
| 3628 | } | |
| 3629 | ||
| 3630 | const field_types: Index.Slice = .{ | |
| 3631 | .tid = unwrapped_index.tid, | |
| 3632 | .start = extra_index, | |
| 3633 | .len = fields_len, | |
| 3634 | }; | |
| 3635 | extra_index += fields_len; | |
| 3636 | ||
| 3637 | const field_aligns = if (type_union.data.flags.any_aligned_fields) a: { | |
| 3638 | const a: Alignment.Slice = .{ | |
| 3639 | .tid = unwrapped_index.tid, | |
| 3640 | .start = extra_index, | |
| 3641 | .len = fields_len, | |
| 3642 | }; | |
| 3643 | extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable; | |
| 3644 | break :a a; | |
| 3645 | } else Alignment.Slice.empty; | |
| 3646 | ||
| 3647 | return .{ | |
| 3648 | .tid = unwrapped_index.tid, | |
| 3649 | .extra_index = data, | |
| 3650 | .name = type_union.data.name, | |
| 3651 | .name_nav = type_union.data.name_nav, | |
| 3652 | .namespace = type_union.data.namespace, | |
| 3653 | .enum_tag_ty = type_union.data.tag_ty, | |
| 3654 | .field_types = field_types, | |
| 3655 | .field_aligns = field_aligns, | |
| 3656 | .zir_index = type_union.data.zir_index, | |
| 3657 | .captures = captures, | |
| 3658 | }; | |
| 3659 | } | |
| 3660 | ||
| 3661 | pub const LoadedStructType = struct { | |
| 3662 | tid: Zcu.PerThread.Id, | |
| 3663 | /// The index of the `Tag.TypeStruct` or `Tag.TypeStructPacked` payload. | |
| 3664 | extra_index: u32, | |
| 3665 | 3308 | // TODO: the non-fqn will be needed by the new dwarf structure |
| 3666 | 3309 | /// The name of this struct type. |
| 3667 | 3310 | name: NullTerminatedString, |
| 3668 | namespace: NamespaceIndex, | |
| 3669 | 3311 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. |
| 3670 | 3312 | /// Otherwise, or if this is a file's root struct type, this is `.none`. |
| 3671 | 3313 | name_nav: Nav.Index.Optional, |
| 3672 | /// Index of the `struct_decl` or `reify` ZIR instruction. | |
| 3673 | zir_index: TrackedInst.Index, | |
| 3314 | namespace: NamespaceIndex, | |
| 3315 | ||
| 3674 | 3316 | layout: std.builtin.Type.ContainerLayout, |
| 3317 | /// May be `undefined` if `layout != .@"packed"`. | |
| 3318 | packed_backing_mode: BackingTypeMode, | |
| 3319 | ||
| 3320 | /// Initially `false`, and set to `true` once any dependency on or reference to the struct's | |
| 3321 | /// layout is encountered, after which it is never reset to `false`, even across incremental | |
| 3322 | /// updates. | |
| 3323 | /// | |
| 3324 | /// This field is purely an optimization to avoid resolving the layout of types whose layouts | |
| 3325 | /// are never demanded. If this field is `true` but the layout is not actually needed, the | |
| 3326 | /// compiler frontend resolves this by traversing the reference graph at the end of each update | |
| 3327 | /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. | |
| 3328 | want_layout: bool, | |
| 3329 | ||
| 3330 | // The remaining fields are only valid once the struct's layout is resolved. | |
| 3331 | field_name_map: MapIndex, | |
| 3675 | 3332 | field_names: NullTerminatedString.Slice, |
| 3676 | 3333 | field_types: Index.Slice, |
| 3677 | field_inits: Index.Slice, | |
| 3334 | field_defaults: Index.Slice, | |
| 3678 | 3335 | field_aligns: Alignment.Slice, |
| 3679 | runtime_order: RuntimeOrder.Slice, | |
| 3680 | comptime_bits: ComptimeBits, | |
| 3681 | offsets: Offsets, | |
| 3682 | names_map: OptionalMapIndex, | |
| 3683 | captures: CaptureValue.Slice, | |
| 3336 | field_is_comptime_bits: ComptimeBits, | |
| 3337 | /// If `layout` is `.@"packed"`, this is `.empty`. | |
| 3338 | field_runtime_order: RuntimeOrder.Slice, | |
| 3339 | /// If `layout` is `.@"packed"`, this is `.empty`. | |
| 3340 | field_offsets: Offsets, | |
| 3341 | /// Only valid if `layout` is `.@"packed"`. | |
| 3342 | packed_backing_int_type: Index, | |
| 3343 | /// Only valid if `layout` is *not* `.@"packed"`. | |
| 3344 | class: TypeClass, | |
| 3345 | /// Only valid if `layout` is *not* `.@"packed"`. | |
| 3346 | size: u32, | |
| 3347 | /// Only valid if `layout` is *not* `.@"packed"`. | |
| 3348 | alignment: Alignment, | |
| 3684 | 3349 | |
| 3685 | 3350 | pub const ComptimeBits = struct { |
| 3686 | 3351 | tid: Zcu.PerThread.Id, |
| ... | ... | @@ -3690,22 +3355,14 @@ pub const LoadedStructType = struct { |
| 3690 | 3355 | |
| 3691 | 3356 | pub const empty: ComptimeBits = .{ .tid = .main, .start = 0, .len = 0 }; |
| 3692 | 3357 | |
| 3693 | pub fn get(this: ComptimeBits, ip: *const InternPool) []u32 { | |
| 3358 | pub fn getAll(this: ComptimeBits, ip: *const InternPool) []u32 { | |
| 3694 | 3359 | const extra = ip.getLocalShared(this.tid).extra.acquire(); |
| 3695 | 3360 | return extra.view().items(.@"0")[this.start..][0..this.len]; |
| 3696 | 3361 | } |
| 3697 | 3362 | |
| 3698 | pub fn getBit(this: ComptimeBits, ip: *const InternPool, i: usize) bool { | |
| 3363 | pub fn get(this: ComptimeBits, ip: *const InternPool, i: usize) bool { | |
| 3699 | 3364 | if (this.len == 0) return false; |
| 3700 | return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0; | |
| 3701 | } | |
| 3702 | ||
| 3703 | pub fn setBit(this: ComptimeBits, ip: *const InternPool, i: usize) void { | |
| 3704 | this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32); | |
| 3705 | } | |
| 3706 | ||
| 3707 | pub fn clearBit(this: ComptimeBits, ip: *const InternPool, i: usize) void { | |
| 3708 | this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32)); | |
| 3365 | return @as(u1, @truncate(this.getAll(ip)[i / 32] >> @intCast(i % 32))) != 0; | |
| 3709 | 3366 | } |
| 3710 | 3367 | }; |
| 3711 | 3368 | |
| ... | ... | @@ -3753,865 +3410,602 @@ pub const LoadedStructType = struct { |
| 3753 | 3410 | |
| 3754 | 3411 | /// Look up field index based on field name. |
| 3755 | 3412 | pub fn nameIndex(s: LoadedStructType, ip: *const InternPool, name: NullTerminatedString) ?u32 { |
| 3756 | const names_map = s.names_map.unwrap() orelse { | |
| 3757 | const i = name.toUnsigned(ip) orelse return null; | |
| 3758 | if (i >= s.field_types.len) return null; | |
| 3759 | return i; | |
| 3760 | }; | |
| 3761 | const map = names_map.get(ip); | |
| 3413 | const map = s.field_name_map.get(ip); | |
| 3762 | 3414 | const adapter: NullTerminatedString.Adapter = .{ .strings = s.field_names.get(ip) }; |
| 3763 | 3415 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; |
| 3764 | 3416 | return @intCast(field_index); |
| 3765 | 3417 | } |
| 3766 | 3418 | |
| 3767 | /// Returns the already-existing field with the same name, if any. | |
| 3768 | pub fn addFieldName( | |
| 3769 | s: LoadedStructType, | |
| 3770 | ip: *InternPool, | |
| 3771 | name: NullTerminatedString, | |
| 3772 | ) ?u32 { | |
| 3773 | const extra = ip.getLocalShared(s.tid).extra.acquire(); | |
| 3774 | return ip.addFieldName(extra, s.names_map.unwrap().?, s.field_names.start, name); | |
| 3419 | /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. | |
| 3420 | /// May or may not include zero-bit fields. | |
| 3421 | /// Asserts the struct is not packed. | |
| 3422 | pub fn iterateRuntimeOrder(s: *const LoadedStructType, ip: *const InternPool) RuntimeOrderIterator { | |
| 3423 | switch (s.layout) { | |
| 3424 | .auto => { | |
| 3425 | const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); | |
| 3426 | return .{ | |
| 3427 | .runtime_order = ro, | |
| 3428 | .fields_len = @intCast(ro.len), | |
| 3429 | .next_index = 0, | |
| 3430 | }; | |
| 3431 | }, | |
| 3432 | .@"extern" => return .{ | |
| 3433 | .runtime_order = null, | |
| 3434 | .fields_len = s.field_names.len, | |
| 3435 | .next_index = 0, | |
| 3436 | }, | |
| 3437 | .@"packed" => unreachable, | |
| 3438 | } | |
| 3775 | 3439 | } |
| 3440 | pub const RuntimeOrderIterator = struct { | |
| 3441 | runtime_order: ?[]const RuntimeOrder, | |
| 3442 | fields_len: u32, | |
| 3443 | next_index: u32, | |
| 3444 | pub fn next(it: *RuntimeOrderIterator) ?u32 { | |
| 3445 | const i = it.next_index; | |
| 3446 | if (i == it.fields_len) return null; | |
| 3447 | it.next_index = i + 1; | |
| 3448 | const ro = it.runtime_order orelse return i; | |
| 3449 | return ro[i].toInt().?; | |
| 3450 | } | |
| 3451 | }; | |
| 3776 | 3452 | |
| 3777 | pub fn fieldAlign(s: LoadedStructType, ip: *const InternPool, i: usize) Alignment { | |
| 3778 | if (s.field_aligns.len == 0) return .none; | |
| 3779 | return s.field_aligns.get(ip)[i]; | |
| 3453 | pub fn iterateRuntimeOrderReverse(s: *const LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator { | |
| 3454 | switch (s.layout) { | |
| 3455 | .auto => { | |
| 3456 | const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); | |
| 3457 | return .{ | |
| 3458 | .runtime_order = ro, | |
| 3459 | .last_index = @intCast(ro.len), | |
| 3460 | }; | |
| 3461 | }, | |
| 3462 | .@"extern" => return .{ | |
| 3463 | .runtime_order = null, | |
| 3464 | .last_index = s.field_names.len, | |
| 3465 | }, | |
| 3466 | .@"packed" => unreachable, | |
| 3467 | } | |
| 3780 | 3468 | } |
| 3469 | pub const ReverseRuntimeOrderIterator = struct { | |
| 3470 | runtime_order: ?[]const RuntimeOrder, | |
| 3471 | last_index: u32, | |
| 3472 | pub fn next(it: *ReverseRuntimeOrderIterator) ?u32 { | |
| 3473 | if (it.last_index == 0) return null; | |
| 3474 | const i = it.last_index - 1; | |
| 3475 | it.last_index = i; | |
| 3476 | const ro = it.runtime_order orelse return i; | |
| 3477 | return ro[i].toInt().?; | |
| 3478 | } | |
| 3479 | }; | |
| 3480 | }; | |
| 3781 | 3481 | |
| 3782 | pub fn fieldInit(s: LoadedStructType, ip: *const InternPool, i: usize) Index { | |
| 3783 | if (s.field_inits.len == 0) return .none; | |
| 3784 | assert(s.haveFieldInits(ip)); | |
| 3785 | return s.field_inits.get(ip)[i]; | |
| 3786 | } | |
| 3482 | /// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a | |
| 3483 | /// minimal hashmap key, this type is a convenience type that contains info | |
| 3484 | /// needed by semantic analysis. | |
| 3485 | pub const LoadedUnionType = struct { | |
| 3486 | /// Index of the `union_decl` or `reify` ZIR instruction. | |
| 3487 | zir_index: TrackedInst.Index, | |
| 3488 | captures: CaptureValue.Slice, | |
| 3489 | is_reified: bool, | |
| 3787 | 3490 | |
| 3788 | pub fn fieldName(s: LoadedStructType, ip: *const InternPool, i: usize) NullTerminatedString { | |
| 3789 | return s.field_names.get(ip)[i]; | |
| 3790 | } | |
| 3491 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 3492 | /// The name of this union type. | |
| 3493 | name: NullTerminatedString, | |
| 3494 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | |
| 3495 | /// Otherwise, this is `.none`. | |
| 3496 | name_nav: Nav.Index.Optional, | |
| 3497 | namespace: NamespaceIndex, | |
| 3791 | 3498 | |
| 3792 | pub fn fieldIsComptime(s: LoadedStructType, ip: *const InternPool, i: usize) bool { | |
| 3793 | return s.comptime_bits.getBit(ip, i); | |
| 3794 | } | |
| 3499 | layout: std.builtin.Type.ContainerLayout, | |
| 3500 | enum_tag_mode: BackingTypeMode, | |
| 3501 | /// May be `undefined` if `layout != .@"packed"`. | |
| 3502 | packed_backing_mode: BackingTypeMode, | |
| 3503 | ||
| 3504 | /// Only reified unions store field names; typically they should be loaded from `enum_tag_type` | |
| 3505 | /// instead. Reified unions store them because type resolution needs them in order to validate | |
| 3506 | /// or populate `enum_tag_type`. | |
| 3507 | reified_field_names: NullTerminatedString.Slice, | |
| 3508 | ||
| 3509 | /// Initially `false`, and set to `true` once any dependency on or reference to the struct's | |
| 3510 | /// layout is encountered, after which it is never reset to `false`, even across incremental | |
| 3511 | /// updates. | |
| 3512 | /// | |
| 3513 | /// This field is purely an optimization to avoid resolving the layout of types whose layouts | |
| 3514 | /// are never demanded. If this field is `true` but the layout is not actually needed, the | |
| 3515 | /// compiler frontend resolves this by traversing the reference graph at the end of each update | |
| 3516 | /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. | |
| 3517 | want_layout: bool, | |
| 3795 | 3518 | |
| 3796 | pub fn setFieldComptime(s: LoadedStructType, ip: *InternPool, i: usize) void { | |
| 3797 | s.comptime_bits.setBit(ip, i); | |
| 3798 | } | |
| 3519 | // The remaining fields are only valid once the union's layout is resolved. | |
| 3520 | field_types: Index.Slice, | |
| 3521 | field_aligns: Alignment.Slice, | |
| 3522 | tag_usage: TagUsage, | |
| 3523 | /// While `tag_usage` indicates whether the union should logically contain a tag, it may be | |
| 3524 | /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an | |
| 3525 | /// actual runtime tag, with one or more runtime bits, in the union layout. It is always `false` | |
| 3526 | /// if `layout` is not `.auto`. | |
| 3527 | has_runtime_tag: bool, | |
| 3528 | /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with | |
| 3529 | /// the union's "hypothetical" tag type. | |
| 3530 | enum_tag_type: Index, | |
| 3531 | /// Only valid if `layout` is `.@"packed"`. | |
| 3532 | packed_backing_int_type: Index, | |
| 3533 | /// Not valid if `layout` is `.@"packed"`. | |
| 3534 | class: TypeClass, | |
| 3535 | /// Not valid if `layout` is `.@"packed"`. | |
| 3536 | size: u32, | |
| 3537 | /// Not valid if `layout` is `.@"packed"`. | |
| 3538 | padding: u32, | |
| 3539 | /// Not valid if `layout` is `.@"packed"`. | |
| 3540 | alignment: Alignment, | |
| 3541 | ||
| 3542 | pub const TagUsage = enum(u2) { | |
| 3543 | none, | |
| 3544 | safety, | |
| 3545 | tagged, | |
| 3546 | }; | |
| 3547 | }; | |
| 3799 | 3548 | |
| 3800 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 3801 | /// Asserts the struct is not packed. | |
| 3802 | fn flagsPtr(s: LoadedStructType, ip: *const InternPool) *Tag.TypeStruct.Flags { | |
| 3803 | assert(s.layout != .@"packed"); | |
| 3804 | const extra = ip.getLocalShared(s.tid).extra.acquire(); | |
| 3805 | const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?; | |
| 3806 | return @ptrCast(&extra.view().items(.@"0")[s.extra_index + flags_field_index]); | |
| 3807 | } | |
| 3549 | pub const LoadedEnumType = struct { | |
| 3550 | /// This is `none` iff this is a generated tag type. | |
| 3551 | /// Otherwise, index of the `enum_decl` or `reify` ZIR instruction. | |
| 3552 | zir_index: TrackedInst.Index.Optional, | |
| 3553 | captures: CaptureValue.Slice, | |
| 3554 | /// If `zir_index` is `.none`, this is the union type for which this enum is the tag type. | |
| 3555 | owner_union: Index, | |
| 3556 | is_reified: bool, | |
| 3808 | 3557 | |
| 3809 | pub fn flagsUnordered(s: LoadedStructType, ip: *const InternPool) Tag.TypeStruct.Flags { | |
| 3810 | return @atomicLoad(Tag.TypeStruct.Flags, s.flagsPtr(ip), .unordered); | |
| 3811 | } | |
| 3558 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 3559 | /// The name of this enum type. | |
| 3560 | name: NullTerminatedString, | |
| 3561 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | |
| 3562 | /// Otherwise, this is `.none`. | |
| 3563 | name_nav: Nav.Index.Optional, | |
| 3564 | namespace: NamespaceIndex, | |
| 3812 | 3565 | |
| 3813 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 3814 | /// Asserts that the struct is packed. | |
| 3815 | fn packedFlagsPtr(s: LoadedStructType, ip: *const InternPool) *Tag.TypeStructPacked.Flags { | |
| 3816 | assert(s.layout == .@"packed"); | |
| 3817 | const extra = ip.getLocalShared(s.tid).extra.acquire(); | |
| 3818 | const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?; | |
| 3819 | return @ptrCast(&extra.view().items(.@"0")[s.extra_index + flags_field_index]); | |
| 3820 | } | |
| 3566 | int_tag_mode: BackingTypeMode, | |
| 3567 | nonexhaustive: bool, | |
| 3821 | 3568 | |
| 3822 | pub fn packedFlagsUnordered(s: LoadedStructType, ip: *const InternPool) Tag.TypeStructPacked.Flags { | |
| 3823 | return @atomicLoad(Tag.TypeStructPacked.Flags, s.packedFlagsPtr(ip), .unordered); | |
| 3824 | } | |
| 3569 | /// Initially `false`, and set to `true` once any dependency on or reference to the struct's | |
| 3570 | /// layout is encountered, after which it is never reset to `false`, even across incremental | |
| 3571 | /// updates. | |
| 3572 | /// | |
| 3573 | /// This field is purely an optimization to avoid resolving the layout of types whose layouts | |
| 3574 | /// are never demanded. If this field is `true` but the layout is not actually needed, the | |
| 3575 | /// compiler frontend resolves this by traversing the reference graph at the end of each update | |
| 3576 | /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. | |
| 3577 | want_layout: bool, | |
| 3825 | 3578 | |
| 3826 | /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more | |
| 3827 | /// complicated logic. | |
| 3828 | pub fn knownNonOpv(s: LoadedStructType, ip: *const InternPool) bool { | |
| 3829 | return switch (s.layout) { | |
| 3830 | .@"packed" => false, | |
| 3831 | .auto, .@"extern" => s.flagsUnordered(ip).known_non_opv, | |
| 3832 | }; | |
| 3833 | } | |
| 3579 | // The remaining fields are only valid once the enum's layout is resolved. | |
| 3580 | int_tag_type: Index, | |
| 3581 | field_name_map: MapIndex, | |
| 3582 | field_names: NullTerminatedString.Slice, | |
| 3583 | field_value_map: OptionalMapIndex, | |
| 3584 | field_values: Index.Slice, | |
| 3834 | 3585 | |
| 3835 | pub fn requiresComptime(s: LoadedStructType, ip: *const InternPool) RequiresComptime { | |
| 3836 | return s.flagsUnordered(ip).requires_comptime; | |
| 3586 | /// Look up field index based on field name. | |
| 3587 | pub fn nameIndex(e: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | |
| 3588 | const map = e.field_name_map.get(ip); | |
| 3589 | const adapter: NullTerminatedString.Adapter = .{ .strings = e.field_names.get(ip) }; | |
| 3590 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | |
| 3591 | return @intCast(field_index); | |
| 3837 | 3592 | } |
| 3838 | 3593 | |
| 3839 | pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool, io: Io) RequiresComptime { | |
| 3840 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3841 | extra_mutex.lockUncancelable(io); | |
| 3842 | defer extra_mutex.unlock(io); | |
| 3843 | ||
| 3844 | const flags_ptr = s.flagsPtr(ip); | |
| 3845 | var flags = flags_ptr.*; | |
| 3846 | defer if (flags.requires_comptime == .unknown) { | |
| 3847 | flags.requires_comptime = .wip; | |
| 3848 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3594 | /// Look up field index based on integer tag value. | |
| 3595 | /// Asserts that the type of `tag_val` is `enum_obj.int_tag_type`. | |
| 3596 | /// Asserts that `tag_val` is not `undefined`. | |
| 3597 | pub fn tagValueIndex(e: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 { | |
| 3598 | assert(ip.typeOf(tag_val) == e.int_tag_type); | |
| 3599 | assert(ip.indexToKey(tag_val) == .int); | |
| 3600 | if (e.field_value_map.unwrap()) |field_value_map| { | |
| 3601 | const map = field_value_map.get(ip); | |
| 3602 | const adapter: Index.Adapter = .{ .indexes = e.field_values.get(ip) }; | |
| 3603 | const field_index = map.getIndexAdapted(tag_val, adapter) orelse return null; | |
| 3604 | return @intCast(field_index); | |
| 3605 | } | |
| 3606 | // Auto-numbered enum, so convert `tag_val` to field index | |
| 3607 | const field_index = switch (ip.indexToKey(tag_val).int.storage) { | |
| 3608 | inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, | |
| 3609 | .big_int => |x| x.toInt(u32) catch return null, | |
| 3849 | 3610 | }; |
| 3850 | return flags.requires_comptime; | |
| 3611 | return if (field_index < e.field_names.len) field_index else null; | |
| 3851 | 3612 | } |
| 3613 | }; | |
| 3852 | 3614 | |
| 3853 | pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void { | |
| 3854 | assert(requires_comptime != .wip); // see setRequiresComptimeWip | |
| 3615 | pub const LoadedOpaqueType = struct { | |
| 3616 | /// Index of the `opaque_decl` instruction. | |
| 3617 | zir_index: TrackedInst.Index, | |
| 3618 | captures: CaptureValue.Slice, | |
| 3855 | 3619 | |
| 3856 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3857 | extra_mutex.lockUncancelable(io); | |
| 3858 | defer extra_mutex.unlock(io); | |
| 3859 | ||
| 3860 | const flags_ptr = s.flagsPtr(ip); | |
| 3861 | var flags = flags_ptr.*; | |
| 3862 | flags.requires_comptime = requires_comptime; | |
| 3863 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3864 | } | |
| 3865 | ||
| 3866 | pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3867 | if (s.layout == .@"packed") return false; | |
| 3868 | ||
| 3869 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3870 | extra_mutex.lockUncancelable(io); | |
| 3871 | defer extra_mutex.unlock(io); | |
| 3872 | ||
| 3873 | const flags_ptr = s.flagsPtr(ip); | |
| 3874 | var flags = flags_ptr.*; | |
| 3875 | defer if (flags.field_types_wip) { | |
| 3876 | flags.assumed_runtime_bits = true; | |
| 3877 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3878 | }; | |
| 3879 | return flags.field_types_wip; | |
| 3880 | } | |
| 3881 | ||
| 3882 | pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3883 | if (s.layout == .@"packed") return false; | |
| 3884 | ||
| 3885 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3886 | extra_mutex.lockUncancelable(io); | |
| 3887 | defer extra_mutex.unlock(io); | |
| 3888 | ||
| 3889 | const flags_ptr = s.flagsPtr(ip); | |
| 3890 | var flags = flags_ptr.*; | |
| 3891 | defer { | |
| 3892 | flags.field_types_wip = true; | |
| 3893 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3894 | } | |
| 3895 | return flags.field_types_wip; | |
| 3896 | } | |
| 3897 | ||
| 3898 | pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3899 | if (s.layout == .@"packed") return; | |
| 3900 | ||
| 3901 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3902 | extra_mutex.lockUncancelable(io); | |
| 3903 | defer extra_mutex.unlock(io); | |
| 3904 | ||
| 3905 | const flags_ptr = s.flagsPtr(ip); | |
| 3906 | var flags = flags_ptr.*; | |
| 3907 | flags.field_types_wip = false; | |
| 3908 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3909 | } | |
| 3910 | ||
| 3911 | pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3912 | if (s.layout == .@"packed") return false; | |
| 3913 | ||
| 3914 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3915 | extra_mutex.lockUncancelable(io); | |
| 3916 | defer extra_mutex.unlock(io); | |
| 3917 | ||
| 3918 | const flags_ptr = s.flagsPtr(ip); | |
| 3919 | var flags = flags_ptr.*; | |
| 3920 | defer { | |
| 3921 | flags.layout_wip = true; | |
| 3922 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3923 | } | |
| 3924 | return flags.layout_wip; | |
| 3925 | } | |
| 3926 | ||
| 3927 | pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3928 | if (s.layout == .@"packed") return; | |
| 3929 | ||
| 3930 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3931 | extra_mutex.lockUncancelable(io); | |
| 3932 | defer extra_mutex.unlock(io); | |
| 3933 | ||
| 3934 | const flags_ptr = s.flagsPtr(ip); | |
| 3935 | var flags = flags_ptr.*; | |
| 3936 | flags.layout_wip = false; | |
| 3937 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3938 | } | |
| 3939 | ||
| 3940 | pub fn setAlignment(s: LoadedStructType, ip: *InternPool, io: Io, alignment: Alignment) void { | |
| 3941 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3942 | extra_mutex.lockUncancelable(io); | |
| 3943 | defer extra_mutex.unlock(io); | |
| 3944 | ||
| 3945 | const flags_ptr = s.flagsPtr(ip); | |
| 3946 | var flags = flags_ptr.*; | |
| 3947 | flags.alignment = alignment; | |
| 3948 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3949 | } | |
| 3950 | ||
| 3951 | pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { | |
| 3952 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3953 | extra_mutex.lockUncancelable(io); | |
| 3954 | defer extra_mutex.unlock(io); | |
| 3955 | ||
| 3956 | const flags_ptr = s.flagsPtr(ip); | |
| 3957 | var flags = flags_ptr.*; | |
| 3958 | defer if (flags.field_types_wip) { | |
| 3959 | flags.alignment = ptr_align; | |
| 3960 | flags.assumed_pointer_aligned = true; | |
| 3961 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3962 | }; | |
| 3963 | return flags.field_types_wip; | |
| 3964 | } | |
| 3965 | ||
| 3966 | pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { | |
| 3967 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3968 | extra_mutex.lockUncancelable(io); | |
| 3969 | defer extra_mutex.unlock(io); | |
| 3970 | ||
| 3971 | const flags_ptr = s.flagsPtr(ip); | |
| 3972 | var flags = flags_ptr.*; | |
| 3973 | defer { | |
| 3974 | if (flags.alignment_wip) { | |
| 3975 | flags.alignment = ptr_align; | |
| 3976 | flags.assumed_pointer_aligned = true; | |
| 3977 | } else flags.alignment_wip = true; | |
| 3978 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3979 | } | |
| 3980 | return flags.alignment_wip; | |
| 3981 | } | |
| 3982 | ||
| 3983 | pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3984 | if (s.layout == .@"packed") return; | |
| 3985 | ||
| 3986 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3987 | extra_mutex.lockUncancelable(io); | |
| 3988 | defer extra_mutex.unlock(io); | |
| 3989 | ||
| 3990 | const flags_ptr = s.flagsPtr(ip); | |
| 3991 | var flags = flags_ptr.*; | |
| 3992 | flags.alignment_wip = false; | |
| 3993 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 3994 | } | |
| 3995 | ||
| 3996 | pub fn setInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3997 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 3998 | extra_mutex.lockUncancelable(io); | |
| 3999 | defer extra_mutex.unlock(io); | |
| 4000 | ||
| 4001 | switch (s.layout) { | |
| 4002 | .@"packed" => { | |
| 4003 | const flags_ptr = s.packedFlagsPtr(ip); | |
| 4004 | var flags = flags_ptr.*; | |
| 4005 | defer { | |
| 4006 | flags.field_inits_wip = true; | |
| 4007 | @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release); | |
| 4008 | } | |
| 4009 | return flags.field_inits_wip; | |
| 4010 | }, | |
| 4011 | .auto, .@"extern" => { | |
| 4012 | const flags_ptr = s.flagsPtr(ip); | |
| 4013 | var flags = flags_ptr.*; | |
| 4014 | defer { | |
| 4015 | flags.field_inits_wip = true; | |
| 4016 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 4017 | } | |
| 4018 | return flags.field_inits_wip; | |
| 4019 | }, | |
| 4020 | } | |
| 4021 | } | |
| 4022 | ||
| 4023 | pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 4024 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 4025 | extra_mutex.lockUncancelable(io); | |
| 4026 | defer extra_mutex.unlock(io); | |
| 4027 | ||
| 4028 | switch (s.layout) { | |
| 4029 | .@"packed" => { | |
| 4030 | const flags_ptr = s.packedFlagsPtr(ip); | |
| 4031 | var flags = flags_ptr.*; | |
| 4032 | flags.field_inits_wip = false; | |
| 4033 | @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release); | |
| 4034 | }, | |
| 4035 | .auto, .@"extern" => { | |
| 4036 | const flags_ptr = s.flagsPtr(ip); | |
| 4037 | var flags = flags_ptr.*; | |
| 4038 | flags.field_inits_wip = false; | |
| 4039 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 4040 | }, | |
| 4041 | } | |
| 4042 | } | |
| 4043 | ||
| 4044 | pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 4045 | if (s.layout == .@"packed") return true; | |
| 4046 | ||
| 4047 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 4048 | extra_mutex.lockUncancelable(io); | |
| 4049 | defer extra_mutex.unlock(io); | |
| 4050 | ||
| 4051 | const flags_ptr = s.flagsPtr(ip); | |
| 4052 | var flags = flags_ptr.*; | |
| 4053 | defer { | |
| 4054 | flags.fully_resolved = true; | |
| 4055 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 4056 | } | |
| 4057 | return flags.fully_resolved; | |
| 4058 | } | |
| 4059 | ||
| 4060 | pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 4061 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 4062 | extra_mutex.lockUncancelable(io); | |
| 4063 | defer extra_mutex.unlock(io); | |
| 4064 | ||
| 4065 | const flags_ptr = s.flagsPtr(ip); | |
| 4066 | var flags = flags_ptr.*; | |
| 4067 | flags.fully_resolved = false; | |
| 4068 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 4069 | } | |
| 4070 | ||
| 4071 | /// The returned pointer expires with any addition to the `InternPool`. | |
| 4072 | /// Asserts the struct is not packed. | |
| 4073 | fn sizePtr(s: LoadedStructType, ip: *const InternPool) *u32 { | |
| 4074 | assert(s.layout != .@"packed"); | |
| 4075 | const extra = ip.getLocalShared(s.tid).extra.acquire(); | |
| 4076 | const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?; | |
| 4077 | return @ptrCast(&extra.view().items(.@"0")[s.extra_index + size_field_index]); | |
| 4078 | } | |
| 4079 | ||
| 4080 | pub fn sizeUnordered(s: LoadedStructType, ip: *const InternPool) u32 { | |
| 4081 | return @atomicLoad(u32, s.sizePtr(ip), .unordered); | |
| 4082 | } | |
| 4083 | ||
| 4084 | /// The backing integer type of the packed struct. Whether zig chooses | |
| 4085 | /// this type or the user specifies it, it is stored here. This will be | |
| 4086 | /// set to `none` until the layout is resolved. | |
| 4087 | /// Asserts the struct is packed. | |
| 4088 | fn backingIntTypePtr(s: LoadedStructType, ip: *const InternPool) *Index { | |
| 4089 | assert(s.layout == .@"packed"); | |
| 4090 | const extra = ip.getLocalShared(s.tid).extra.acquire(); | |
| 4091 | const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?; | |
| 4092 | return @ptrCast(&extra.view().items(.@"0")[s.extra_index + field_index]); | |
| 4093 | } | |
| 4094 | ||
| 4095 | pub fn backingIntTypeUnordered(s: LoadedStructType, ip: *const InternPool) Index { | |
| 4096 | return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered); | |
| 4097 | } | |
| 4098 | ||
| 4099 | pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, io: Io, backing_int_ty: Index) void { | |
| 4100 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 4101 | extra_mutex.lockUncancelable(io); | |
| 4102 | defer extra_mutex.unlock(io); | |
| 4103 | ||
| 4104 | @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release); | |
| 4105 | } | |
| 4106 | ||
| 4107 | /// Asserts the struct is not packed. | |
| 4108 | pub fn setZirIndex(s: LoadedStructType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | |
| 4109 | assert(s.layout != .@"packed"); | |
| 4110 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; | |
| 4111 | ip.extra_.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); | |
| 4112 | } | |
| 4113 | ||
| 4114 | pub fn haveFieldTypes(s: LoadedStructType, ip: *const InternPool) bool { | |
| 4115 | const types = s.field_types.get(ip); | |
| 4116 | return types.len == 0 or types[types.len - 1] != .none; | |
| 4117 | } | |
| 4118 | ||
| 4119 | pub fn haveFieldInits(s: LoadedStructType, ip: *const InternPool) bool { | |
| 4120 | return switch (s.layout) { | |
| 4121 | .@"packed" => s.packedFlagsUnordered(ip).inits_resolved, | |
| 4122 | .auto, .@"extern" => s.flagsUnordered(ip).inits_resolved, | |
| 4123 | }; | |
| 4124 | } | |
| 4125 | ||
| 4126 | pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 4127 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 4128 | extra_mutex.lockUncancelable(io); | |
| 4129 | defer extra_mutex.unlock(io); | |
| 4130 | ||
| 4131 | switch (s.layout) { | |
| 4132 | .@"packed" => { | |
| 4133 | const flags_ptr = s.packedFlagsPtr(ip); | |
| 4134 | var flags = flags_ptr.*; | |
| 4135 | flags.inits_resolved = true; | |
| 4136 | @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release); | |
| 4137 | }, | |
| 4138 | .auto, .@"extern" => { | |
| 4139 | const flags_ptr = s.flagsPtr(ip); | |
| 4140 | var flags = flags_ptr.*; | |
| 4141 | flags.inits_resolved = true; | |
| 4142 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 4143 | }, | |
| 4144 | } | |
| 4145 | } | |
| 4146 | ||
| 4147 | pub fn haveLayout(s: LoadedStructType, ip: *const InternPool) bool { | |
| 4148 | return switch (s.layout) { | |
| 4149 | .@"packed" => s.backingIntTypeUnordered(ip) != .none, | |
| 4150 | .auto, .@"extern" => s.flagsUnordered(ip).layout_resolved, | |
| 4151 | }; | |
| 4152 | } | |
| 4153 | ||
| 4154 | pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, io: Io, size: u32, alignment: Alignment) void { | |
| 4155 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; | |
| 4156 | extra_mutex.lockUncancelable(io); | |
| 4157 | defer extra_mutex.unlock(io); | |
| 4158 | ||
| 4159 | @atomicStore(u32, s.sizePtr(ip), size, .unordered); | |
| 4160 | const flags_ptr = s.flagsPtr(ip); | |
| 4161 | var flags = flags_ptr.*; | |
| 4162 | flags.alignment = alignment; | |
| 4163 | flags.layout_resolved = true; | |
| 4164 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); | |
| 4165 | } | |
| 4166 | ||
| 4167 | pub fn hasReorderedFields(s: LoadedStructType) bool { | |
| 4168 | return s.layout == .auto; | |
| 4169 | } | |
| 4170 | ||
| 4171 | pub const RuntimeOrderIterator = struct { | |
| 4172 | ip: *InternPool, | |
| 4173 | field_index: u32, | |
| 4174 | struct_type: InternPool.LoadedStructType, | |
| 4175 | ||
| 4176 | pub fn next(it: *@This()) ?u32 { | |
| 4177 | var i = it.field_index; | |
| 4178 | ||
| 4179 | if (i >= it.struct_type.field_types.len) | |
| 4180 | return null; | |
| 4181 | ||
| 4182 | if (it.struct_type.hasReorderedFields()) { | |
| 4183 | it.field_index += 1; | |
| 4184 | return it.struct_type.runtime_order.get(it.ip)[i].toInt(); | |
| 4185 | } | |
| 4186 | ||
| 4187 | while (it.struct_type.fieldIsComptime(it.ip, i)) { | |
| 4188 | i += 1; | |
| 4189 | if (i >= it.struct_type.field_types.len) | |
| 4190 | return null; | |
| 4191 | } | |
| 4192 | ||
| 4193 | it.field_index = i + 1; | |
| 4194 | return i; | |
| 4195 | } | |
| 4196 | }; | |
| 4197 | ||
| 4198 | /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. | |
| 4199 | /// May or may not include zero-bit fields. | |
| 4200 | /// Asserts the struct is not packed. | |
| 4201 | pub fn iterateRuntimeOrder(s: LoadedStructType, ip: *InternPool) RuntimeOrderIterator { | |
| 4202 | assert(s.layout != .@"packed"); | |
| 4203 | return .{ | |
| 4204 | .ip = ip, | |
| 4205 | .field_index = 0, | |
| 4206 | .struct_type = s, | |
| 4207 | }; | |
| 4208 | } | |
| 4209 | ||
| 4210 | pub const ReverseRuntimeOrderIterator = struct { | |
| 4211 | ip: *InternPool, | |
| 4212 | last_index: u32, | |
| 4213 | struct_type: InternPool.LoadedStructType, | |
| 4214 | ||
| 4215 | pub fn next(it: *@This()) ?u32 { | |
| 4216 | if (it.last_index == 0) | |
| 4217 | return null; | |
| 4218 | ||
| 4219 | if (it.struct_type.hasReorderedFields()) { | |
| 4220 | it.last_index -= 1; | |
| 4221 | const order = it.struct_type.runtime_order.get(it.ip); | |
| 4222 | while (order[it.last_index] == .omitted) { | |
| 4223 | it.last_index -= 1; | |
| 4224 | if (it.last_index == 0) | |
| 4225 | return null; | |
| 4226 | } | |
| 4227 | return order[it.last_index].toInt(); | |
| 4228 | } | |
| 4229 | ||
| 4230 | it.last_index -= 1; | |
| 4231 | while (it.struct_type.fieldIsComptime(it.ip, it.last_index)) { | |
| 4232 | it.last_index -= 1; | |
| 4233 | if (it.last_index == 0) | |
| 4234 | return null; | |
| 4235 | } | |
| 4236 | ||
| 4237 | return it.last_index; | |
| 4238 | } | |
| 4239 | }; | |
| 4240 | ||
| 4241 | pub fn iterateRuntimeOrderReverse(s: LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator { | |
| 4242 | assert(s.layout != .@"packed"); | |
| 4243 | return .{ | |
| 4244 | .ip = ip, | |
| 4245 | .last_index = s.field_types.len, | |
| 4246 | .struct_type = s, | |
| 4247 | }; | |
| 4248 | } | |
| 4249 | }; | |
| 3620 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 3621 | /// The name of this opaque type. | |
| 3622 | name: NullTerminatedString, | |
| 3623 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | |
| 3624 | /// Otherwise, this is `.none`. | |
| 3625 | name_nav: Nav.Index.Optional, | |
| 3626 | namespace: NamespaceIndex, | |
| 3627 | }; | |
| 4250 | 3628 | |
| 4251 | 3629 | pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { |
| 4252 | 3630 | const unwrapped_index = index.unwrap(ip); |
| 4253 | 3631 | const extra_list = unwrapped_index.getExtra(ip); |
| 4254 | 3632 | const extra_items = extra_list.view().items(.@"0"); |
| 4255 | 3633 | const item = unwrapped_index.getItem(ip); |
| 4256 | switch (item.tag) { | |
| 3634 | // Exiting this `switch` means this is a `packed struct`. | |
| 3635 | const backing_mode: BackingTypeMode, const any_defaults: bool = switch (item.tag) { | |
| 3636 | .type_struct_packed_auto => .{ .auto, false }, | |
| 3637 | .type_struct_packed_explicit => .{ .explicit, false }, | |
| 3638 | .type_struct_packed_auto_defaults => .{ .auto, true }, | |
| 3639 | .type_struct_packed_explicit_defaults => .{ .explicit, true }, | |
| 4257 | 3640 | .type_struct => { |
| 4258 | const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]); | |
| 4259 | const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?]); | |
| 4260 | const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]); | |
| 4261 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]); | |
| 4262 | const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?]; | |
| 4263 | const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered)); | |
| 4264 | var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStruct).@"struct".fields.len); | |
| 4265 | const captures_len = if (flags.any_captures) c: { | |
| 4266 | const len = extra_list.view().items(.@"0")[extra_index]; | |
| 4267 | extra_index += 1; | |
| 4268 | break :c len; | |
| 4269 | } else 0; | |
| 4270 | const captures: CaptureValue.Slice = .{ | |
| 3641 | const extra = extraDataTrail(extra_list, Tag.TypeStruct, item.data); | |
| 3642 | var extra_index = extra.end; | |
| 3643 | const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) { | |
| 3644 | .reified => captures: { | |
| 3645 | extra_index += 2; // type_hash: PackedU64 | |
| 3646 | break :captures .empty; | |
| 3647 | }, | |
| 3648 | .false => .empty, | |
| 3649 | .true => captures: { | |
| 3650 | const len = extra_items[extra_index]; | |
| 3651 | extra_index += 1; | |
| 3652 | break :captures .{ | |
| 3653 | .tid = unwrapped_index.tid, | |
| 3654 | .start = extra_index, | |
| 3655 | .len = len, | |
| 3656 | }; | |
| 3657 | }, | |
| 3658 | }; | |
| 3659 | extra_index += captures.len; | |
| 3660 | const field_names: NullTerminatedString.Slice = .{ | |
| 4271 | 3661 | .tid = unwrapped_index.tid, |
| 4272 | 3662 | .start = extra_index, |
| 4273 | .len = captures_len, | |
| 3663 | .len = extra.data.fields_len, | |
| 4274 | 3664 | }; |
| 4275 | extra_index += captures_len; | |
| 4276 | if (flags.is_reified) { | |
| 4277 | extra_index += 2; // type_hash: PackedU64 | |
| 4278 | } | |
| 3665 | extra_index += field_names.len; | |
| 4279 | 3666 | const field_types: Index.Slice = .{ |
| 4280 | 3667 | .tid = unwrapped_index.tid, |
| 4281 | 3668 | .start = extra_index, |
| 4282 | .len = fields_len, | |
| 3669 | .len = extra.data.fields_len, | |
| 4283 | 3670 | }; |
| 4284 | extra_index += fields_len; | |
| 4285 | const names_map: OptionalMapIndex, const names = n: { | |
| 4286 | const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]); | |
| 4287 | extra_index += 1; | |
| 4288 | const names: NullTerminatedString.Slice = .{ | |
| 4289 | .tid = unwrapped_index.tid, | |
| 4290 | .start = extra_index, | |
| 4291 | .len = fields_len, | |
| 4292 | }; | |
| 4293 | extra_index += fields_len; | |
| 4294 | break :n .{ names_map, names }; | |
| 4295 | }; | |
| 4296 | const inits: Index.Slice = if (flags.any_default_inits) i: { | |
| 4297 | const inits: Index.Slice = .{ | |
| 4298 | .tid = unwrapped_index.tid, | |
| 4299 | .start = extra_index, | |
| 4300 | .len = fields_len, | |
| 4301 | }; | |
| 4302 | extra_index += fields_len; | |
| 4303 | break :i inits; | |
| 4304 | } else Index.Slice.empty; | |
| 4305 | const aligns: Alignment.Slice = if (flags.any_aligned_fields) a: { | |
| 4306 | const a: Alignment.Slice = .{ | |
| 4307 | .tid = unwrapped_index.tid, | |
| 4308 | .start = extra_index, | |
| 4309 | .len = fields_len, | |
| 4310 | }; | |
| 4311 | extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable; | |
| 4312 | break :a a; | |
| 4313 | } else Alignment.Slice.empty; | |
| 4314 | const comptime_bits: LoadedStructType.ComptimeBits = if (flags.any_comptime_fields) c: { | |
| 4315 | const len = std.math.divCeil(u32, fields_len, 32) catch unreachable; | |
| 4316 | const c: LoadedStructType.ComptimeBits = .{ | |
| 4317 | .tid = unwrapped_index.tid, | |
| 4318 | .start = extra_index, | |
| 4319 | .len = len, | |
| 4320 | }; | |
| 4321 | extra_index += len; | |
| 4322 | break :c c; | |
| 4323 | } else LoadedStructType.ComptimeBits.empty; | |
| 4324 | const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!flags.is_extern) ro: { | |
| 4325 | const ro: LoadedStructType.RuntimeOrder.Slice = .{ | |
| 4326 | .tid = unwrapped_index.tid, | |
| 4327 | .start = extra_index, | |
| 4328 | .len = fields_len, | |
| 4329 | }; | |
| 4330 | extra_index += fields_len; | |
| 4331 | break :ro ro; | |
| 4332 | } else LoadedStructType.RuntimeOrder.Slice.empty; | |
| 4333 | const offsets: LoadedStructType.Offsets = o: { | |
| 4334 | const o: LoadedStructType.Offsets = .{ | |
| 4335 | .tid = unwrapped_index.tid, | |
| 4336 | .start = extra_index, | |
| 4337 | .len = fields_len, | |
| 4338 | }; | |
| 4339 | extra_index += fields_len; | |
| 4340 | break :o o; | |
| 4341 | }; | |
| 4342 | return .{ | |
| 3671 | extra_index += field_types.len; | |
| 3672 | const field_defaults: Index.Slice = if (extra.data.flags.any_field_defaults) .{ | |
| 4343 | 3673 | .tid = unwrapped_index.tid, |
| 4344 | .extra_index = item.data, | |
| 4345 | .name = name, | |
| 4346 | .name_nav = name_nav, | |
| 4347 | .namespace = namespace, | |
| 4348 | .zir_index = zir_index, | |
| 4349 | .layout = if (flags.is_extern) .@"extern" else .auto, | |
| 4350 | .field_names = names, | |
| 4351 | .field_types = field_types, | |
| 4352 | .field_inits = inits, | |
| 4353 | .field_aligns = aligns, | |
| 4354 | .runtime_order = runtime_order, | |
| 4355 | .comptime_bits = comptime_bits, | |
| 4356 | .offsets = offsets, | |
| 4357 | .names_map = names_map, | |
| 4358 | .captures = captures, | |
| 4359 | }; | |
| 4360 | }, | |
| 4361 | .type_struct_packed, .type_struct_packed_inits => { | |
| 4362 | const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]); | |
| 4363 | const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?]); | |
| 4364 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]); | |
| 4365 | const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?]; | |
| 4366 | const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]); | |
| 4367 | const names_map: MapIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "names_map").?]); | |
| 4368 | const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered)); | |
| 4369 | var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStructPacked).@"struct".fields.len); | |
| 4370 | const has_inits = item.tag == .type_struct_packed_inits; | |
| 4371 | const captures_len = if (flags.any_captures) c: { | |
| 4372 | const len = extra_list.view().items(.@"0")[extra_index]; | |
| 4373 | extra_index += 1; | |
| 4374 | break :c len; | |
| 4375 | } else 0; | |
| 4376 | const captures: CaptureValue.Slice = .{ | |
| 3674 | .start = extra_index, | |
| 3675 | .len = extra.data.fields_len, | |
| 3676 | } else .empty; | |
| 3677 | extra_index += field_defaults.len; | |
| 3678 | const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{ | |
| 4377 | 3679 | .tid = unwrapped_index.tid, |
| 4378 | 3680 | .start = extra_index, |
| 4379 | .len = captures_len, | |
| 4380 | }; | |
| 4381 | extra_index += captures_len; | |
| 4382 | if (flags.is_reified) { | |
| 4383 | extra_index += 2; // PackedU64 | |
| 4384 | } | |
| 4385 | const field_types: Index.Slice = .{ | |
| 3681 | .len = extra.data.fields_len, | |
| 3682 | } else .empty; | |
| 3683 | extra_index += std.math.divCeil(u32, field_aligns.len, 4) catch unreachable; | |
| 3684 | const field_is_comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) .{ | |
| 4386 | 3685 | .tid = unwrapped_index.tid, |
| 4387 | 3686 | .start = extra_index, |
| 4388 | .len = fields_len, | |
| 4389 | }; | |
| 4390 | extra_index += fields_len; | |
| 4391 | const field_names: NullTerminatedString.Slice = .{ | |
| 3687 | .len = std.math.divCeil(u32, extra.data.fields_len, 32) catch unreachable, | |
| 3688 | } else .empty; | |
| 3689 | extra_index += field_is_comptime_bits.len; | |
| 3690 | const field_runtime_order: LoadedStructType.RuntimeOrder.Slice = if (extra.data.flags.layout == .auto) .{ | |
| 4392 | 3691 | .tid = unwrapped_index.tid, |
| 4393 | 3692 | .start = extra_index, |
| 4394 | .len = fields_len, | |
| 3693 | .len = extra.data.fields_len, | |
| 3694 | } else .empty; | |
| 3695 | extra_index += field_runtime_order.len; | |
| 3696 | const field_offsets: LoadedStructType.Offsets = .{ | |
| 3697 | .tid = unwrapped_index.tid, | |
| 3698 | .start = extra_index, | |
| 3699 | .len = extra.data.fields_len, | |
| 4395 | 3700 | }; |
| 4396 | extra_index += fields_len; | |
| 4397 | const field_inits: Index.Slice = if (has_inits) inits: { | |
| 4398 | const i: Index.Slice = .{ | |
| 4399 | .tid = unwrapped_index.tid, | |
| 4400 | .start = extra_index, | |
| 4401 | .len = fields_len, | |
| 4402 | }; | |
| 4403 | extra_index += fields_len; | |
| 4404 | break :inits i; | |
| 4405 | } else Index.Slice.empty; | |
| 3701 | extra_index += field_offsets.len; | |
| 3702 | ||
| 4406 | 3703 | return .{ |
| 4407 | .tid = unwrapped_index.tid, | |
| 4408 | .extra_index = item.data, | |
| 4409 | .name = name, | |
| 4410 | .name_nav = name_nav, | |
| 4411 | .namespace = namespace, | |
| 4412 | .zir_index = zir_index, | |
| 4413 | .layout = .@"packed", | |
| 3704 | .zir_index = extra.data.zir_index, | |
| 3705 | .captures = captures, | |
| 3706 | .is_reified = extra.data.flags.any_captures == .reified, | |
| 3707 | .name = extra.data.name, | |
| 3708 | .name_nav = extra.data.name_nav, | |
| 3709 | .namespace = extra.data.namespace, | |
| 3710 | .layout = switch (extra.data.flags.layout) { | |
| 3711 | .auto => .auto, | |
| 3712 | .@"extern" => .@"extern", | |
| 3713 | }, | |
| 3714 | .packed_backing_mode = undefined, | |
| 3715 | ||
| 3716 | .want_layout = extra.data.flags.want_layout, | |
| 3717 | ||
| 3718 | .field_name_map = extra.data.field_name_map, | |
| 4414 | 3719 | .field_names = field_names, |
| 4415 | 3720 | .field_types = field_types, |
| 4416 | .field_inits = field_inits, | |
| 4417 | .field_aligns = Alignment.Slice.empty, | |
| 4418 | .runtime_order = LoadedStructType.RuntimeOrder.Slice.empty, | |
| 4419 | .comptime_bits = LoadedStructType.ComptimeBits.empty, | |
| 4420 | .offsets = LoadedStructType.Offsets.empty, | |
| 4421 | .names_map = names_map.toOptional(), | |
| 4422 | .captures = captures, | |
| 3721 | .field_defaults = field_defaults, | |
| 3722 | .field_aligns = field_aligns, | |
| 3723 | .field_is_comptime_bits = field_is_comptime_bits, | |
| 3724 | .field_runtime_order = field_runtime_order, | |
| 3725 | .field_offsets = field_offsets, | |
| 3726 | .packed_backing_int_type = .none, | |
| 3727 | .class = extra.data.flags.class, | |
| 3728 | .size = extra.data.size, | |
| 3729 | .alignment = extra.data.flags.alignment, | |
| 4423 | 3730 | }; |
| 4424 | 3731 | }, |
| 4425 | 3732 | else => unreachable, |
| 4426 | } | |
| 4427 | } | |
| 4428 | ||
| 4429 | pub const LoadedEnumType = struct { | |
| 4430 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 4431 | /// The name of this enum type. | |
| 4432 | name: NullTerminatedString, | |
| 4433 | /// Represents the declarations inside this enum. | |
| 4434 | namespace: NamespaceIndex, | |
| 4435 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | |
| 4436 | /// Otherwise, this is `.none`. | |
| 4437 | name_nav: Nav.Index.Optional, | |
| 4438 | /// An integer type which is used for the numerical value of the enum. | |
| 4439 | /// This field is present regardless of whether the enum has an | |
| 4440 | /// explicitly provided tag type or auto-numbered. | |
| 4441 | tag_ty: Index, | |
| 4442 | /// Set of field names in declaration order. | |
| 4443 | names: NullTerminatedString.Slice, | |
| 4444 | /// Maps integer tag value to field index. | |
| 4445 | /// Entries are in declaration order, same as `fields`. | |
| 4446 | /// If this is empty, it means the enum tags are auto-numbered. | |
| 4447 | values: Index.Slice, | |
| 4448 | tag_mode: TagMode, | |
| 4449 | names_map: MapIndex, | |
| 4450 | /// This is guaranteed to not be `.none` if explicit values are provided. | |
| 4451 | values_map: OptionalMapIndex, | |
| 4452 | /// This is `none` only if this is a generated tag type. | |
| 4453 | zir_index: TrackedInst.Index.Optional, | |
| 4454 | captures: CaptureValue.Slice, | |
| 4455 | ||
| 4456 | pub const TagMode = enum { | |
| 4457 | /// The integer tag type was auto-numbered by zig. | |
| 4458 | auto, | |
| 4459 | /// The integer tag type was provided by the enum declaration, and the enum | |
| 4460 | /// is exhaustive. | |
| 4461 | explicit, | |
| 4462 | /// The integer tag type was provided by the enum declaration, and the enum | |
| 4463 | /// is non-exhaustive. | |
| 4464 | nonexhaustive, | |
| 4465 | 3733 | }; |
| 3734 | const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, item.data); | |
| 3735 | var extra_index = extra.end; | |
| 3736 | const captures: CaptureValue.Slice = switch (extra.data.bits.captures_len) { | |
| 3737 | .reified => captures: { | |
| 3738 | extra_index += 2; // type_hash: PackedU64 | |
| 3739 | break :captures .empty; | |
| 3740 | }, | |
| 3741 | _ => |n| .{ | |
| 3742 | .tid = unwrapped_index.tid, | |
| 3743 | .start = extra_index, | |
| 3744 | .len = @intFromEnum(n), | |
| 3745 | }, | |
| 3746 | }; | |
| 3747 | extra_index += captures.len; | |
| 3748 | const field_names: NullTerminatedString.Slice = .{ | |
| 3749 | .tid = unwrapped_index.tid, | |
| 3750 | .start = extra_index, | |
| 3751 | .len = extra.data.fields_len, | |
| 3752 | }; | |
| 3753 | extra_index += field_names.len; | |
| 3754 | const field_types: Index.Slice = .{ | |
| 3755 | .tid = unwrapped_index.tid, | |
| 3756 | .start = extra_index, | |
| 3757 | .len = extra.data.fields_len, | |
| 3758 | }; | |
| 3759 | extra_index += field_types.len; | |
| 3760 | const field_defaults: Index.Slice = if (any_defaults) .{ | |
| 3761 | .tid = unwrapped_index.tid, | |
| 3762 | .start = extra_index, | |
| 3763 | .len = extra.data.fields_len, | |
| 3764 | } else .empty; | |
| 3765 | extra_index += field_defaults.len; | |
| 3766 | return .{ | |
| 3767 | .zir_index = extra.data.zir_index, | |
| 3768 | .captures = captures, | |
| 3769 | .is_reified = extra.data.bits.captures_len == .reified, | |
| 3770 | .name = extra.data.name, | |
| 3771 | .name_nav = extra.data.name_nav, | |
| 3772 | .namespace = extra.data.namespace, | |
| 3773 | .layout = .@"packed", | |
| 3774 | .packed_backing_mode = backing_mode, | |
| 4466 | 3775 | |
| 4467 | /// Look up field index based on field name. | |
| 4468 | pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | |
| 4469 | const map = self.names_map.get(ip); | |
| 4470 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; | |
| 4471 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | |
| 4472 | return @intCast(field_index); | |
| 4473 | } | |
| 3776 | .want_layout = extra.data.bits.want_layout, | |
| 4474 | 3777 | |
| 4475 | /// Look up field index based on tag value. | |
| 4476 | /// Asserts that `values_map` is not `none`. | |
| 4477 | /// This function returns `null` when `tag_val` does not have the | |
| 4478 | /// integer tag type of the enum. | |
| 4479 | pub fn tagValueIndex(self: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 { | |
| 4480 | assert(tag_val != .none); | |
| 4481 | // TODO: we should probably decide a single interface for this function, but currently | |
| 4482 | // it's being called with both tag values and underlying ints. Fix this! | |
| 4483 | const int_tag_val = switch (ip.indexToKey(tag_val)) { | |
| 4484 | .enum_tag => |enum_tag| enum_tag.int, | |
| 4485 | .int => tag_val, | |
| 4486 | else => unreachable, | |
| 4487 | }; | |
| 4488 | if (self.values_map.unwrap()) |values_map| { | |
| 4489 | const map = values_map.get(ip); | |
| 4490 | const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) }; | |
| 4491 | const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null; | |
| 4492 | return @intCast(field_index); | |
| 4493 | } | |
| 4494 | // Auto-numbered enum. Convert `int_tag_val` to field index. | |
| 4495 | const field_index = switch (ip.indexToKey(int_tag_val).int.storage) { | |
| 4496 | inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, | |
| 4497 | .big_int => |x| x.toInt(u32) catch return null, | |
| 4498 | .lazy_align, .lazy_size => unreachable, | |
| 4499 | }; | |
| 4500 | return if (field_index < self.names.len) field_index else null; | |
| 4501 | } | |
| 4502 | }; | |
| 3778 | .field_name_map = extra.data.field_name_map, | |
| 3779 | .field_names = field_names, | |
| 3780 | .field_types = field_types, | |
| 3781 | .field_defaults = field_defaults, | |
| 3782 | .field_aligns = .empty, | |
| 3783 | .field_is_comptime_bits = .empty, | |
| 3784 | .field_runtime_order = .empty, | |
| 3785 | .field_offsets = .empty, | |
| 3786 | .packed_backing_int_type = extra.data.backing_int_type, | |
| 3787 | .class = undefined, | |
| 3788 | .size = undefined, | |
| 3789 | .alignment = undefined, | |
| 3790 | }; | |
| 3791 | } | |
| 4503 | 3792 | |
| 4504 | pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { | |
| 3793 | pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { | |
| 4505 | 3794 | const unwrapped_index = index.unwrap(ip); |
| 4506 | 3795 | const extra_list = unwrapped_index.getExtra(ip); |
| 3796 | const extra_items = extra_list.view().items(.@"0"); | |
| 4507 | 3797 | const item = unwrapped_index.getItem(ip); |
| 4508 | const tag_mode: LoadedEnumType.TagMode = switch (item.tag) { | |
| 4509 | .type_enum_auto => { | |
| 4510 | const extra = extraDataTrail(extra_list, EnumAuto, item.data); | |
| 4511 | var extra_index: u32 = @intCast(extra.end); | |
| 4512 | if (extra.data.zir_index == .none) { | |
| 4513 | extra_index += 1; // owner_union | |
| 4514 | } | |
| 4515 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { | |
| 4516 | extra_index += 2; // type_hash: PackedU64 | |
| 4517 | break :c 0; | |
| 4518 | } else extra.data.captures_len; | |
| 3798 | // Exiting this `switch` means this is a `packed union`. | |
| 3799 | const backing_mode: BackingTypeMode = switch (item.tag) { | |
| 3800 | .type_union_packed_auto => .auto, | |
| 3801 | .type_union_packed_explicit => .explicit, | |
| 3802 | .type_union => { | |
| 3803 | const extra = extraDataTrail(extra_list, Tag.TypeUnion, item.data); | |
| 3804 | var extra_index = extra.end; | |
| 3805 | const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) { | |
| 3806 | .reified => captures: { | |
| 3807 | extra_index += 2; // type_hash: PackedU64 | |
| 3808 | break :captures .empty; | |
| 3809 | }, | |
| 3810 | .false => .empty, | |
| 3811 | .true => captures: { | |
| 3812 | const len = extra_items[extra_index]; | |
| 3813 | extra_index += 1; | |
| 3814 | break :captures .{ | |
| 3815 | .tid = unwrapped_index.tid, | |
| 3816 | .start = extra_index, | |
| 3817 | .len = len, | |
| 3818 | }; | |
| 3819 | }, | |
| 3820 | }; | |
| 3821 | extra_index += captures.len; | |
| 3822 | const reified_field_names: NullTerminatedString.Slice = if (extra.data.flags.any_captures == .reified) .{ | |
| 3823 | .tid = unwrapped_index.tid, | |
| 3824 | .start = extra_index, | |
| 3825 | .len = extra.data.fields_len, | |
| 3826 | } else .empty; | |
| 3827 | extra_index += reified_field_names.len; | |
| 3828 | const field_types: Index.Slice = .{ | |
| 3829 | .tid = unwrapped_index.tid, | |
| 3830 | .start = extra_index, | |
| 3831 | .len = extra.data.fields_len, | |
| 3832 | }; | |
| 3833 | extra_index += field_types.len; | |
| 3834 | const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{ | |
| 3835 | .tid = unwrapped_index.tid, | |
| 3836 | .start = extra_index, | |
| 3837 | .len = extra.data.fields_len, | |
| 3838 | } else .empty; | |
| 3839 | extra_index += std.math.divCeil(u32, field_aligns.len, 4) catch unreachable; | |
| 3840 | ||
| 4519 | 3841 | return .{ |
| 3842 | .zir_index = extra.data.zir_index, | |
| 3843 | .captures = captures, | |
| 3844 | .is_reified = extra.data.flags.any_captures == .reified, | |
| 4520 | 3845 | .name = extra.data.name, |
| 4521 | 3846 | .name_nav = extra.data.name_nav, |
| 4522 | 3847 | .namespace = extra.data.namespace, |
| 4523 | .tag_ty = extra.data.int_tag_type, | |
| 4524 | .names = .{ | |
| 4525 | .tid = unwrapped_index.tid, | |
| 4526 | .start = extra_index + captures_len, | |
| 4527 | .len = extra.data.fields_len, | |
| 4528 | }, | |
| 4529 | .values = Index.Slice.empty, | |
| 4530 | .tag_mode = .auto, | |
| 4531 | .names_map = extra.data.names_map, | |
| 4532 | .values_map = .none, | |
| 4533 | .zir_index = extra.data.zir_index, | |
| 4534 | .captures = .{ | |
| 4535 | .tid = unwrapped_index.tid, | |
| 4536 | .start = extra_index, | |
| 4537 | .len = captures_len, | |
| 3848 | .layout = switch (extra.data.flags.layout) { | |
| 3849 | .auto => .auto, | |
| 3850 | .@"extern" => .@"extern", | |
| 4538 | 3851 | }, |
| 3852 | .tag_usage = extra.data.flags.tag_usage, | |
| 3853 | .enum_tag_mode = extra.data.flags.enum_tag_mode, | |
| 3854 | .enum_tag_type = extra.data.enum_tag_type, | |
| 3855 | .packed_backing_mode = undefined, | |
| 3856 | .packed_backing_int_type = undefined, | |
| 3857 | .reified_field_names = reified_field_names, | |
| 3858 | .want_layout = extra.data.flags.want_layout, | |
| 3859 | .field_types = field_types, | |
| 3860 | .field_aligns = field_aligns, | |
| 3861 | .has_runtime_tag = extra.data.flags.has_runtime_tag, | |
| 3862 | .class = extra.data.flags.class, | |
| 3863 | .size = extra.data.size, | |
| 3864 | .padding = extra.data.padding, | |
| 3865 | .alignment = extra.data.flags.alignment, | |
| 4539 | 3866 | }; |
| 4540 | 3867 | }, |
| 4541 | .type_enum_explicit => .explicit, | |
| 4542 | .type_enum_nonexhaustive => .nonexhaustive, | |
| 4543 | 3868 | else => unreachable, |
| 4544 | 3869 | }; |
| 4545 | const extra = extraDataTrail(extra_list, EnumExplicit, item.data); | |
| 4546 | var extra_index: u32 = @intCast(extra.end); | |
| 4547 | if (extra.data.zir_index == .none) { | |
| 4548 | extra_index += 1; // owner_union | |
| 4549 | } | |
| 4550 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { | |
| 4551 | extra_index += 2; // type_hash: PackedU64 | |
| 4552 | break :c 0; | |
| 4553 | } else extra.data.captures_len; | |
| 4554 | return .{ | |
| 4555 | .name = extra.data.name, | |
| 4556 | .name_nav = extra.data.name_nav, | |
| 4557 | .namespace = extra.data.namespace, | |
| 4558 | .tag_ty = extra.data.int_tag_type, | |
| 4559 | .names = .{ | |
| 4560 | .tid = unwrapped_index.tid, | |
| 4561 | .start = extra_index + captures_len, | |
| 4562 | .len = extra.data.fields_len, | |
| 3870 | const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, item.data); | |
| 3871 | var extra_index = extra.end; | |
| 3872 | const captures: CaptureValue.Slice = switch (extra.data.bits.captures_len) { | |
| 3873 | .reified => captures: { | |
| 3874 | extra_index += 2; // type_hash: PackedU64 | |
| 3875 | break :captures .empty; | |
| 4563 | 3876 | }, |
| 4564 | .values = .{ | |
| 4565 | .tid = unwrapped_index.tid, | |
| 4566 | .start = extra_index + captures_len + extra.data.fields_len, | |
| 4567 | .len = if (extra.data.values_map != .none) extra.data.fields_len else 0, | |
| 4568 | }, | |
| 4569 | .tag_mode = tag_mode, | |
| 4570 | .names_map = extra.data.names_map, | |
| 4571 | .values_map = extra.data.values_map, | |
| 4572 | .zir_index = extra.data.zir_index, | |
| 4573 | .captures = .{ | |
| 3877 | _ => |n| .{ | |
| 4574 | 3878 | .tid = unwrapped_index.tid, |
| 4575 | 3879 | .start = extra_index, |
| 4576 | .len = captures_len, | |
| 3880 | .len = @intFromEnum(n), | |
| 4577 | 3881 | }, |
| 4578 | 3882 | }; |
| 3883 | extra_index += captures.len; | |
| 3884 | const reified_field_names: NullTerminatedString.Slice = if (extra.data.bits.captures_len == .reified) .{ | |
| 3885 | .tid = unwrapped_index.tid, | |
| 3886 | .start = extra_index, | |
| 3887 | .len = extra.data.fields_len, | |
| 3888 | } else .empty; | |
| 3889 | extra_index += reified_field_names.len; | |
| 3890 | const field_types: Index.Slice = .{ | |
| 3891 | .tid = unwrapped_index.tid, | |
| 3892 | .start = extra_index, | |
| 3893 | .len = extra.data.fields_len, | |
| 3894 | }; | |
| 3895 | extra_index += field_types.len; | |
| 3896 | return .{ | |
| 3897 | .zir_index = extra.data.zir_index, | |
| 3898 | .captures = captures, | |
| 3899 | .is_reified = extra.data.bits.captures_len == .reified, | |
| 3900 | .name = extra.data.name, | |
| 3901 | .name_nav = extra.data.name_nav, | |
| 3902 | .namespace = extra.data.namespace, | |
| 3903 | .layout = .@"packed", | |
| 3904 | .tag_usage = .none, | |
| 3905 | .enum_tag_mode = .auto, | |
| 3906 | .enum_tag_type = extra.data.enum_tag_type, | |
| 3907 | .packed_backing_mode = backing_mode, | |
| 3908 | .packed_backing_int_type = extra.data.backing_int_type, | |
| 3909 | .reified_field_names = reified_field_names, | |
| 3910 | .want_layout = extra.data.bits.want_layout, | |
| 3911 | .field_types = field_types, | |
| 3912 | .field_aligns = .empty, | |
| 3913 | .has_runtime_tag = false, | |
| 3914 | .class = undefined, | |
| 3915 | .size = undefined, | |
| 3916 | .padding = undefined, | |
| 3917 | .alignment = undefined, | |
| 3918 | }; | |
| 4579 | 3919 | } |
| 4580 | 3920 | |
| 4581 | /// Note that this type doubles as the payload for `Tag.type_opaque`. | |
| 4582 | pub const LoadedOpaqueType = struct { | |
| 4583 | /// Contains the declarations inside this opaque. | |
| 4584 | namespace: NamespaceIndex, | |
| 4585 | // TODO: the non-fqn will be needed by the new dwarf structure | |
| 4586 | /// The name of this opaque type. | |
| 4587 | name: NullTerminatedString, | |
| 4588 | /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. | |
| 4589 | /// Otherwise, this is `.none`. | |
| 4590 | name_nav: Nav.Index.Optional, | |
| 4591 | /// Index of the `opaque_decl` or `reify` instruction. | |
| 4592 | zir_index: TrackedInst.Index, | |
| 4593 | captures: CaptureValue.Slice, | |
| 4594 | }; | |
| 3921 | pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { | |
| 3922 | const unwrapped_index = index.unwrap(ip); | |
| 3923 | const extra_list = unwrapped_index.getExtra(ip); | |
| 3924 | const extra_items = extra_list.view().items(.@"0"); | |
| 3925 | const item = unwrapped_index.getItem(ip); | |
| 3926 | const explicit_int_tag: bool, const nonexhaustive: bool = switch (item.tag) { | |
| 3927 | .type_enum_auto => .{ false, false }, | |
| 3928 | .type_enum_explicit => .{ true, false }, | |
| 3929 | .type_enum_nonexhaustive => .{ true, true }, | |
| 3930 | else => unreachable, | |
| 3931 | }; | |
| 3932 | const extra = extraDataTrail(extra_list, Tag.TypeEnum, item.data); | |
| 3933 | var extra_index: u32 = @intCast(extra.end); | |
| 3934 | const zir_index: TrackedInst.Index.Optional, const captures: CaptureValue.Slice, const owner_union: Index = switch (extra.data.bits.captures_len) { | |
| 3935 | .reified => info: { | |
| 3936 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]); | |
| 3937 | extra_index += 1; | |
| 3938 | extra_index += 2; // type_hash: PackedU64 | |
| 3939 | break :info .{ zir_index.toOptional(), .empty, .none }; | |
| 3940 | }, | |
| 3941 | .generated_union_tag => info: { | |
| 3942 | const owner_union: Index = @enumFromInt(extra_items[extra_index]); | |
| 3943 | extra_index += 1; | |
| 3944 | break :info .{ .none, .empty, owner_union }; | |
| 3945 | }, | |
| 3946 | _ => |n| info: { | |
| 3947 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]); | |
| 3948 | extra_index += 1; | |
| 3949 | const captures: CaptureValue.Slice = .{ | |
| 3950 | .tid = unwrapped_index.tid, | |
| 3951 | .start = extra_index, | |
| 3952 | .len = @intFromEnum(n), | |
| 3953 | }; | |
| 3954 | extra_index += captures.len; | |
| 3955 | break :info .{ zir_index.toOptional(), captures, .none }; | |
| 3956 | }, | |
| 3957 | }; | |
| 3958 | const field_value_map: OptionalMapIndex = if (explicit_int_tag) m: { | |
| 3959 | const map: MapIndex = @enumFromInt(extra_items[extra_index]); | |
| 3960 | extra_index += 1; | |
| 3961 | break :m map.toOptional(); | |
| 3962 | } else .none; | |
| 3963 | const field_names: NullTerminatedString.Slice = .{ | |
| 3964 | .tid = unwrapped_index.tid, | |
| 3965 | .start = extra_index, | |
| 3966 | .len = extra.data.fields_len, | |
| 3967 | }; | |
| 3968 | extra_index += field_names.len; | |
| 3969 | const field_values: Index.Slice = if (explicit_int_tag) .{ | |
| 3970 | .tid = unwrapped_index.tid, | |
| 3971 | .start = extra_index, | |
| 3972 | .len = extra.data.fields_len, | |
| 3973 | } else .empty; | |
| 3974 | extra_index += field_values.len; | |
| 3975 | return .{ | |
| 3976 | .zir_index = zir_index, | |
| 3977 | .captures = captures, | |
| 3978 | .is_reified = extra.data.bits.captures_len == .reified, | |
| 3979 | .owner_union = owner_union, | |
| 3980 | .name = extra.data.name, | |
| 3981 | .name_nav = extra.data.name_nav, | |
| 3982 | .namespace = extra.data.namespace, | |
| 3983 | .int_tag_type = extra.data.int_tag_type, | |
| 3984 | .int_tag_mode = if (explicit_int_tag) .explicit else .auto, | |
| 3985 | .nonexhaustive = nonexhaustive, | |
| 3986 | .want_layout = extra.data.bits.want_layout, | |
| 3987 | .field_name_map = extra.data.field_name_map, | |
| 3988 | .field_value_map = field_value_map, | |
| 3989 | .field_names = field_names, | |
| 3990 | .field_values = field_values, | |
| 3991 | }; | |
| 3992 | } | |
| 4595 | 3993 | |
| 4596 | 3994 | pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { |
| 4597 | 3995 | const unwrapped_index = index.unwrap(ip); |
| 4598 | 3996 | const item = unwrapped_index.getItem(ip); |
| 4599 | 3997 | assert(item.tag == .type_opaque); |
| 4600 | 3998 | const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, item.data); |
| 4601 | const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) | |
| 4602 | 0 | |
| 4603 | else | |
| 4604 | extra.data.captures_len; | |
| 4605 | 3999 | return .{ |
| 4606 | .name = extra.data.name, | |
| 4607 | .name_nav = extra.data.name_nav, | |
| 4608 | .namespace = extra.data.namespace, | |
| 4609 | 4000 | .zir_index = extra.data.zir_index, |
| 4610 | 4001 | .captures = .{ |
| 4611 | 4002 | .tid = unwrapped_index.tid, |
| 4612 | 4003 | .start = extra.end, |
| 4613 | .len = captures_len, | |
| 4004 | .len = extra.data.captures_len, | |
| 4614 | 4005 | }, |
| 4006 | .name = extra.data.name, | |
| 4007 | .name_nav = extra.data.name_nav, | |
| 4008 | .namespace = extra.data.namespace, | |
| 4615 | 4009 | }; |
| 4616 | 4010 | } |
| 4617 | 4011 | |
| ... | ... | @@ -4816,6 +4210,13 @@ pub const Index = enum(u32) { |
| 4816 | 4210 | const extra = ip.getLocalShared(slice.tid).extra.acquire(); |
| 4817 | 4211 | return @ptrCast(extra.view().items(.@"0")[slice.start..][0..slice.len]); |
| 4818 | 4212 | } |
| 4213 | ||
| 4214 | /// If `slice` is empty (`slice.len == 0`), returns `.none`. | |
| 4215 | /// Otherwise, asserts that `index < slice.len`, and returns the value at `index`. | |
| 4216 | pub fn getOrNone(slice: Slice, ip: *const InternPool, index: usize) Index { | |
| 4217 | if (slice.len == 0) return .none; | |
| 4218 | return slice.get(ip)[index]; | |
| 4219 | } | |
| 4819 | 4220 | }; |
| 4820 | 4221 | |
| 4821 | 4222 | /// Used for a map of `Index` values to the index within a list of `Index` values. |
| ... | ... | @@ -4891,26 +4292,6 @@ pub const Index = enum(u32) { |
| 4891 | 4292 | /// Tag to encoding mapping to facilitate fancy debug printing for this type. |
| 4892 | 4293 | fn dbHelper(self: *Index, tag_to_encoding_map: *struct { |
| 4893 | 4294 | const DataIsIndex = struct { data: Index }; |
| 4894 | const DataIsExtraIndexOfEnumExplicit = struct { | |
| 4895 | const @"data.fields_len" = opaque {}; | |
| 4896 | data: *EnumExplicit, | |
| 4897 | @"trailing.names.len": *@"data.fields_len", | |
| 4898 | @"trailing.values.len": *@"data.fields_len", | |
| 4899 | trailing: struct { | |
| 4900 | names: []NullTerminatedString, | |
| 4901 | values: []Index, | |
| 4902 | }, | |
| 4903 | }; | |
| 4904 | const DataIsExtraIndexOfTypeTuple = struct { | |
| 4905 | const @"data.fields_len" = opaque {}; | |
| 4906 | data: *TypeTuple, | |
| 4907 | @"trailing.types.len": *@"data.fields_len", | |
| 4908 | @"trailing.values.len": *@"data.fields_len", | |
| 4909 | trailing: struct { | |
| 4910 | types: []Index, | |
| 4911 | values: []Index, | |
| 4912 | }, | |
| 4913 | }; | |
| 4914 | 4295 | |
| 4915 | 4296 | removed: void, |
| 4916 | 4297 | type_int_signed: struct { data: u32 }, |
| ... | ... | @@ -4931,31 +4312,40 @@ pub const Index = enum(u32) { |
| 4931 | 4312 | trailing: struct { names: []NullTerminatedString }, |
| 4932 | 4313 | }, |
| 4933 | 4314 | type_inferred_error_set: DataIsIndex, |
| 4934 | type_enum_auto: struct { | |
| 4315 | simple_type: void, | |
| 4316 | type_function: struct { | |
| 4317 | const @"data.flags.has_comptime_bits" = opaque {}; | |
| 4318 | const @"data.flags.has_noalias_bits" = opaque {}; | |
| 4319 | const @"data.params_len" = opaque {}; | |
| 4320 | data: *Tag.TypeFunction, | |
| 4321 | @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits", | |
| 4322 | @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits", | |
| 4323 | @"trailing.param_types.len": *@"data.params_len", | |
| 4324 | trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index }, | |
| 4325 | }, | |
| 4326 | type_tuple: struct { | |
| 4935 | 4327 | const @"data.fields_len" = opaque {}; |
| 4936 | data: *EnumAuto, | |
| 4937 | @"trailing.names.len": *@"data.fields_len", | |
| 4938 | trailing: struct { names: []NullTerminatedString }, | |
| 4328 | data: *TypeTuple, | |
| 4329 | @"trailing.types.len": *@"data.fields_len", | |
| 4330 | @"trailing.values.len": *@"data.fields_len", | |
| 4331 | trailing: struct { | |
| 4332 | types: []Index, | |
| 4333 | values: []Index, | |
| 4334 | }, | |
| 4939 | 4335 | }, |
| 4940 | type_enum_explicit: DataIsExtraIndexOfEnumExplicit, | |
| 4941 | type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit, | |
| 4942 | simple_type: void, | |
| 4943 | type_opaque: struct { data: *Tag.TypeOpaque }, | |
| 4336 | ||
| 4944 | 4337 | type_struct: struct { data: *Tag.TypeStruct }, |
| 4945 | type_struct_packed: struct { data: *Tag.TypeStructPacked }, | |
| 4946 | type_struct_packed_inits: struct { data: *Tag.TypeStructPacked }, | |
| 4947 | type_tuple: DataIsExtraIndexOfTypeTuple, | |
| 4338 | type_struct_packed_auto: struct { data: *Tag.TypeStructPacked }, | |
| 4339 | type_struct_packed_explicit: struct { data: *Tag.TypeStructPacked }, | |
| 4340 | type_struct_packed_auto_defaults: struct { data: *Tag.TypeStructPacked }, | |
| 4341 | type_struct_packed_explicit_defaults: struct { data: *Tag.TypeStructPacked }, | |
| 4948 | 4342 | type_union: struct { data: *Tag.TypeUnion }, |
| 4949 | type_function: struct { | |
| 4950 | const @"data.flags.has_comptime_bits" = opaque {}; | |
| 4951 | const @"data.flags.has_noalias_bits" = opaque {}; | |
| 4952 | const @"data.params_len" = opaque {}; | |
| 4953 | data: *Tag.TypeFunction, | |
| 4954 | @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits", | |
| 4955 | @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits", | |
| 4956 | @"trailing.param_types.len": *@"data.params_len", | |
| 4957 | trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index }, | |
| 4958 | }, | |
| 4343 | type_union_packed_auto: struct { data: *Tag.TypeUnionPacked }, | |
| 4344 | type_union_packed_explicit: struct { data: *Tag.TypeUnionPacked }, | |
| 4345 | type_enum_auto: struct { data: *Tag.TypeEnum }, | |
| 4346 | type_enum_explicit: struct { data: *Tag.TypeEnum }, | |
| 4347 | type_enum_nonexhaustive: struct { data: *Tag.TypeEnum }, | |
| 4348 | type_opaque: struct { data: *Tag.TypeOpaque }, | |
| 4959 | 4349 | |
| 4960 | 4350 | undef: DataIsIndex, |
| 4961 | 4351 | simple_value: void, |
| ... | ... | @@ -4982,8 +4372,6 @@ pub const Index = enum(u32) { |
| 4982 | 4372 | int_small: struct { data: *IntSmall }, |
| 4983 | 4373 | int_positive: struct { data: u32 }, |
| 4984 | 4374 | int_negative: struct { data: u32 }, |
| 4985 | int_lazy_align: struct { data: *IntLazy }, | |
| 4986 | int_lazy_size: struct { data: *IntLazy }, | |
| 4987 | 4375 | error_set_error: struct { data: *Key.Error }, |
| 4988 | 4376 | error_union_error: struct { data: *Key.Error }, |
| 4989 | 4377 | error_union_payload: struct { data: *Tag.TypeValue }, |
| ... | ... | @@ -5027,6 +4415,7 @@ pub const Index = enum(u32) { |
| 5027 | 4415 | trailing: struct { element_values: []Index }, |
| 5028 | 4416 | }, |
| 5029 | 4417 | repeated: struct { data: *Repeated }, |
| 4418 | bitpack: struct { data: *Key.Bitpack }, | |
| 5030 | 4419 | |
| 5031 | 4420 | memoized_call: struct { |
| 5032 | 4421 | const @"data.args_len" = opaque {}; |
| ... | ... | @@ -5037,7 +4426,7 @@ pub const Index = enum(u32) { |
| 5037 | 4426 | }) void { |
| 5038 | 4427 | _ = self; |
| 5039 | 4428 | const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).pointer.child).@"struct".fields; |
| 5040 | @setEvalBranchQuota(2_000); | |
| 4429 | @setEvalBranchQuota(3_000); | |
| 5041 | 4430 | inline for (@typeInfo(Tag).@"enum".fields, 0..) |tag, start| { |
| 5042 | 4431 | inline for (0..map_fields.len) |offset| { |
| 5043 | 4432 | if (comptime std.mem.eql(u8, tag.name, map_fields[(start + offset) % map_fields.len].name)) break; |
| ... | ... | @@ -5409,7 +4798,7 @@ pub const static_keys: [static_len]Key = .{ |
| 5409 | 4798 | .values = .empty, |
| 5410 | 4799 | } }, |
| 5411 | 4800 | |
| 5412 | .{ .simple_value = .undefined }, | |
| 4801 | .{ .undef = .undefined_type }, | |
| 5413 | 4802 | .{ .undef = .bool_type }, |
| 5414 | 4803 | .{ .undef = .usize_type }, |
| 5415 | 4804 | .{ .undef = .u1_type }, |
| ... | ... | @@ -5469,7 +4858,11 @@ pub const static_keys: [static_len]Key = .{ |
| 5469 | 4858 | .{ .simple_value = .null }, |
| 5470 | 4859 | .{ .simple_value = .true }, |
| 5471 | 4860 | .{ .simple_value = .false }, |
| 5472 | .{ .simple_value = .empty_tuple }, | |
| 4861 | ||
| 4862 | .{ .aggregate = .{ | |
| 4863 | .ty = .empty_tuple_type, | |
| 4864 | .storage = .{ .elems = &.{} }, | |
| 4865 | } }, | |
| 5473 | 4866 | }; |
| 5474 | 4867 | |
| 5475 | 4868 | /// How many items in the InternPool are statically known. |
| ... | ... | @@ -5485,6 +4878,8 @@ pub const Tag = enum(u8) { |
| 5485 | 4878 | /// assert not this tag. `data` is unused. |
| 5486 | 4879 | removed, |
| 5487 | 4880 | |
| 4881 | /// A type that can be represented with only an enum tag. | |
| 4882 | simple_type, | |
| 5488 | 4883 | /// An integer type. |
| 5489 | 4884 | /// data is number of bits |
| 5490 | 4885 | type_int_signed, |
| ... | ... | @@ -5524,41 +4919,68 @@ pub const Tag = enum(u8) { |
| 5524 | 4919 | /// The inferred error set type of a function. |
| 5525 | 4920 | /// data is `Index` of a `func_decl` or `func_instance`. |
| 5526 | 4921 | type_inferred_error_set, |
| 5527 | /// An enum type with auto-numbered tag values. | |
| 5528 | /// The enum is exhaustive. | |
| 5529 | /// data is payload index to `EnumAuto`. | |
| 5530 | type_enum_auto, | |
| 5531 | /// An enum type with an explicitly provided integer tag type. | |
| 5532 | /// The enum is exhaustive. | |
| 5533 | /// data is payload index to `EnumExplicit`. | |
| 5534 | type_enum_explicit, | |
| 5535 | /// An enum type with an explicitly provided integer tag type. | |
| 5536 | /// The enum is non-exhaustive. | |
| 5537 | /// data is payload index to `EnumExplicit`. | |
| 5538 | type_enum_nonexhaustive, | |
| 5539 | /// A type that can be represented with only an enum tag. | |
| 5540 | simple_type, | |
| 5541 | /// An opaque type. | |
| 5542 | /// data is index of Tag.TypeOpaque in extra. | |
| 5543 | type_opaque, | |
| 4922 | /// A function body type. | |
| 4923 | /// `data` is extra index to `TypeFunction`. | |
| 4924 | type_function, | |
| 4925 | /// A `TupleType`. | |
| 4926 | /// data is extra index of `TypeTuple`. | |
| 4927 | type_tuple, | |
| 4928 | ||
| 5544 | 4929 | /// A non-packed struct type. |
| 5545 | /// data is 0 or extra index of `TypeStruct`. | |
| 4930 | /// data is extra index of `TypeStruct`. | |
| 5546 | 4931 | type_struct, |
| 5547 | /// A packed struct, no fields have any init values. | |
| 4932 | /// `packed struct { ... }` with no default field values. | |
| 5548 | 4933 | /// data is extra index of `TypeStructPacked`. |
| 5549 | type_struct_packed, | |
| 5550 | /// A packed struct, one or more fields have init values. | |
| 4934 | type_struct_packed_auto, | |
| 4935 | /// `packed struct(T) { ... }` with no default field values. | |
| 5551 | 4936 | /// data is extra index of `TypeStructPacked`. |
| 5552 | type_struct_packed_inits, | |
| 5553 | /// A `TupleType`. | |
| 5554 | /// data is extra index of `TypeTuple`. | |
| 5555 | type_tuple, | |
| 5556 | /// A union type. | |
| 5557 | /// `data` is extra index of `TypeUnion`. | |
| 4937 | type_struct_packed_explicit, | |
| 4938 | /// `packed struct { ... }` with one or more default field values. | |
| 4939 | /// data is extra index of `TypeStructPacked`. | |
| 4940 | type_struct_packed_auto_defaults, | |
| 4941 | /// `packed struct(T) { ... }` with one or more default field values. | |
| 4942 | /// data is extra index of `TypeStructPacked`. | |
| 4943 | type_struct_packed_explicit_defaults, | |
| 4944 | ||
| 4945 | /// A non-packed union type. | |
| 4946 | /// data is extra index of `TypeUnion`. | |
| 5558 | 4947 | type_union, |
| 5559 | /// A function body type. | |
| 5560 | /// `data` is extra index to `TypeFunction`. | |
| 5561 | type_function, | |
| 4948 | /// `packed union { ... }`. | |
| 4949 | /// data is extra index of `TypeUnionPacked`. | |
| 4950 | type_union_packed_auto, | |
| 4951 | /// `packed union(T) { ... }`. | |
| 4952 | /// data is extra index of `TypeUnionPacked`. | |
| 4953 | type_union_packed_explicit, | |
| 4954 | ||
| 4955 | /// An exhaustive enum type *without* an explicit integer tag type. The tag type is inferred. | |
| 4956 | /// | |
| 4957 | /// Because the tag type is inferred, there are no explicit field values. | |
| 4958 | /// | |
| 4959 | /// May be the generated tag type for a `union(enum)`. | |
| 4960 | /// | |
| 4961 | /// data is extra index of `TypeEnum`. | |
| 4962 | type_enum_auto, | |
| 4963 | /// An exhaustive enum type *with* an explicit integer tag type. | |
| 4964 | /// | |
| 4965 | /// May have explicit field values. | |
| 4966 | /// | |
| 4967 | /// May be the generated tag type for a `union(enum(T))`. | |
| 4968 | /// | |
| 4969 | /// data is extra index of `TypeEnum`. | |
| 4970 | type_enum_explicit, | |
| 4971 | /// An non-exhaustive enum type (with an explicit integer tag type, since it is required for | |
| 4972 | /// non-exhaustive enums). | |
| 4973 | /// | |
| 4974 | /// May have explicit field values. | |
| 4975 | /// | |
| 4976 | /// This is *not* a union's generated tag type, because such types are always exhaustive. | |
| 4977 | /// | |
| 4978 | /// data is extra index of `TypeEnum`. | |
| 4979 | type_enum_nonexhaustive, | |
| 4980 | ||
| 4981 | /// An opaque type. | |
| 4982 | /// data is extra index of `TypeOpaque`. | |
| 4983 | type_opaque, | |
| 5562 | 4984 | |
| 5563 | 4985 | /// Typed `undefined`. |
| 5564 | 4986 | /// `data` is `Index` of the type. |
| ... | ... | @@ -5644,12 +5066,6 @@ pub const Tag = enum(u8) { |
| 5644 | 5066 | /// A negative integer value. |
| 5645 | 5067 | /// data is a limbs index to `Int`. |
| 5646 | 5068 | int_negative, |
| 5647 | /// The ABI alignment of a lazy type. | |
| 5648 | /// data is extra index of `IntLazy`. | |
| 5649 | int_lazy_align, | |
| 5650 | /// The ABI size of a lazy type. | |
| 5651 | /// data is extra index of `IntLazy`. | |
| 5652 | int_lazy_size, | |
| 5653 | 5069 | /// An error value. |
| 5654 | 5070 | /// data is extra index of `Key.Error`. |
| 5655 | 5071 | error_set_error, |
| ... | ... | @@ -5735,6 +5151,9 @@ pub const Tag = enum(u8) { |
| 5735 | 5151 | /// An instance of an array or vector with every element being the same value. |
| 5736 | 5152 | /// data is extra index to `Repeated`. |
| 5737 | 5153 | repeated, |
| 5154 | /// An instance of a `packed struct` or `packed union`. | |
| 5155 | /// data is extra index to `Key.Bitpack`. | |
| 5156 | bitpack, | |
| 5738 | 5157 | |
| 5739 | 5158 | /// A memoized comptime function call result. |
| 5740 | 5159 | /// data is extra index to `MemoizedCall` |
| ... | ... | @@ -5747,24 +5166,77 @@ pub const Tag = enum(u8) { |
| 5747 | 5166 | const Union = Key.Union; |
| 5748 | 5167 | const TypePointer = Key.PtrType; |
| 5749 | 5168 | |
| 5750 | const enum_explicit_encoding = .{ | |
| 5169 | const struct_packed_encoding = .{ | |
| 5170 | .summary = .@"{.payload.name%summary#\"}", | |
| 5171 | .payload = TypeStructPacked, | |
| 5172 | .trailing = struct { | |
| 5173 | type_hash: ?u64, | |
| 5174 | captures: ?[]CaptureValue, | |
| 5175 | field_names: []NullTerminatedString, | |
| 5176 | field_types: []Index, | |
| 5177 | }, | |
| 5178 | .config = .{ | |
| 5179 | .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", | |
| 5180 | .@"trailing.captures.?" = .@"payload.captures_len != .reified", | |
| 5181 | .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", | |
| 5182 | .@"trailing.field_names.len" = .@"payload.fields_len", | |
| 5183 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5184 | }, | |
| 5185 | }; | |
| 5186 | const struct_packed_defaults_encoding = .{ | |
| 5187 | .summary = .@"{.payload.name%summary#\"}", | |
| 5188 | .payload = TypeStructPacked, | |
| 5189 | .trailing = struct { | |
| 5190 | type_hash: ?u64, | |
| 5191 | captures: ?[]CaptureValue, | |
| 5192 | field_names: []NullTerminatedString, | |
| 5193 | field_types: []Index, | |
| 5194 | field_defaults: []Index, | |
| 5195 | }, | |
| 5196 | .config = .{ | |
| 5197 | .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", | |
| 5198 | .@"trailing.captures.?" = .@"payload.captures_len != .reified", | |
| 5199 | .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", | |
| 5200 | .@"trailing.field_names.len" = .@"payload.fields_len", | |
| 5201 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5202 | .@"trailing.field_defaults.len" = .@"payload.fields_len", | |
| 5203 | }, | |
| 5204 | }; | |
| 5205 | const union_packed_encoding = .{ | |
| 5751 | 5206 | .summary = .@"{.payload.name%summary#\"}", |
| 5752 | .payload = EnumExplicit, | |
| 5207 | .payload = TypeUnionPacked, | |
| 5753 | 5208 | .trailing = struct { |
| 5754 | owner_union: Index, | |
| 5209 | type_hash: ?u64, | |
| 5755 | 5210 | captures: ?[]CaptureValue, |
| 5211 | field_types: []Index, | |
| 5212 | }, | |
| 5213 | .config = .{ | |
| 5214 | .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", | |
| 5215 | .@"trailing.captures.?" = .@"payload.captures_len != .reified", | |
| 5216 | .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", | |
| 5217 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5218 | }, | |
| 5219 | }; | |
| 5220 | const enum_explicit_encoding = .{ | |
| 5221 | .summary = .@"{.payload.name%summary#\"}", | |
| 5222 | .payload = TypeEnum, | |
| 5223 | .trailing = struct { | |
| 5224 | owner_union: ?Index, | |
| 5225 | zir_index: ?TrackedInst.Index, | |
| 5756 | 5226 | type_hash: ?u64, |
| 5227 | captures: ?[]CaptureValue, | |
| 5228 | field_value_map: MapIndex, | |
| 5757 | 5229 | field_names: []NullTerminatedString, |
| 5758 | tag_values: []Index, | |
| 5230 | field_values: []Index, | |
| 5759 | 5231 | }, |
| 5760 | 5232 | .config = .{ |
| 5761 | .@"trailing.owner_union.?" = .@"payload.zir_index == .none", | |
| 5762 | .@"trailing.cau.?" = .@"payload.zir_index != .none", | |
| 5763 | .@"trailing.captures.?" = .@"payload.captures_len < 0xffffffff", | |
| 5764 | .@"trailing.captures.?.len" = .@"payload.captures_len", | |
| 5765 | .@"trailing.type_hash.?" = .@"payload.captures_len == 0xffffffff", | |
| 5233 | .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag", | |
| 5234 | .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag", | |
| 5235 | .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", | |
| 5236 | .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag", | |
| 5237 | .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", | |
| 5766 | 5238 | .@"trailing.field_names.len" = .@"payload.fields_len", |
| 5767 | .@"trailing.tag_values.len" = .@"payload.fields_len", | |
| 5239 | .@"trailing.field_values.len" = .@"payload.fields_len", | |
| 5768 | 5240 | }, |
| 5769 | 5241 | }; |
| 5770 | 5242 | const encodings = .{ |
| ... | ... | @@ -5792,153 +5264,121 @@ pub const Tag = enum(u8) { |
| 5792 | 5264 | .summary = .@"@typeInfo(@typeInfo(@TypeOf({.data%summary})).@\"fn\".return_type.?).error_union.error_set", |
| 5793 | 5265 | .data = Index, |
| 5794 | 5266 | }, |
| 5795 | .type_enum_auto = .{ | |
| 5796 | .summary = .@"{.payload.name%summary#\"}", | |
| 5797 | .payload = EnumAuto, | |
| 5267 | .simple_type = .{ .summary = .@"{.index%value#.}", .index = SimpleType }, | |
| 5268 | .type_tuple = .{ | |
| 5269 | .summary = .@"struct {...}", | |
| 5270 | .payload = TypeTuple, | |
| 5798 | 5271 | .trailing = struct { |
| 5799 | owner_union: ?Index, | |
| 5800 | captures: ?[]CaptureValue, | |
| 5801 | type_hash: ?u64, | |
| 5802 | field_names: []NullTerminatedString, | |
| 5272 | field_types: []Index, | |
| 5273 | field_values: []Index, | |
| 5803 | 5274 | }, |
| 5804 | 5275 | .config = .{ |
| 5805 | .@"trailing.owner_union.?" = .@"payload.zir_index == .none", | |
| 5806 | .@"trailing.cau.?" = .@"payload.zir_index != .none", | |
| 5807 | .@"trailing.captures.?" = .@"payload.captures_len < 0xffffffff", | |
| 5808 | .@"trailing.captures.?.len" = .@"payload.captures_len", | |
| 5809 | .@"trailing.type_hash.?" = .@"payload.captures_len == 0xffffffff", | |
| 5810 | .@"trailing.field_names.len" = .@"payload.fields_len", | |
| 5276 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5277 | .@"trailing.field_values.len" = .@"payload.fields_len", | |
| 5811 | 5278 | }, |
| 5812 | 5279 | }, |
| 5813 | .type_enum_explicit = enum_explicit_encoding, | |
| 5814 | .type_enum_nonexhaustive = enum_explicit_encoding, | |
| 5815 | .simple_type = .{ .summary = .@"{.index%value#.}", .index = SimpleType }, | |
| 5816 | .type_opaque = .{ | |
| 5817 | .summary = .@"{.payload.name%summary#\"}", | |
| 5818 | .payload = TypeOpaque, | |
| 5819 | .trailing = struct { captures: []CaptureValue }, | |
| 5820 | .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" }, | |
| 5280 | .type_function = .{ | |
| 5281 | .summary = .@"fn (...) ... {.payload.return_type%summary}", | |
| 5282 | .payload = TypeFunction, | |
| 5283 | .trailing = struct { | |
| 5284 | param_comptime_bits: ?[]u32, | |
| 5285 | param_noalias_bits: ?[]u32, | |
| 5286 | param_type: []Index, | |
| 5287 | }, | |
| 5288 | .config = .{ | |
| 5289 | .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits", | |
| 5290 | .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32", | |
| 5291 | .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits", | |
| 5292 | .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32", | |
| 5293 | .@"trailing.param_type.len" = .@"payload.params_len", | |
| 5294 | }, | |
| 5821 | 5295 | }, |
| 5296 | ||
| 5822 | 5297 | .type_struct = .{ |
| 5823 | 5298 | .summary = .@"{.payload.name%summary#\"}", |
| 5824 | 5299 | .payload = TypeStruct, |
| 5825 | 5300 | .trailing = struct { |
| 5301 | type_hash: ?u64, | |
| 5826 | 5302 | captures_len: ?u32, |
| 5827 | 5303 | captures: ?[]CaptureValue, |
| 5828 | type_hash: ?u64, | |
| 5829 | field_types: []Index, | |
| 5830 | field_names_map: OptionalMapIndex, | |
| 5831 | 5304 | field_names: []NullTerminatedString, |
| 5832 | field_inits: ?[]Index, | |
| 5305 | field_types: []Index, | |
| 5306 | field_defaults: ?[]Index, | |
| 5833 | 5307 | field_aligns: ?[]Alignment, |
| 5834 | 5308 | field_is_comptime_bits: ?[]u32, |
| 5835 | field_index: ?[]LoadedStructType.RuntimeOrder, | |
| 5836 | field_offset: []u32, | |
| 5309 | field_runtime_order: ?[]u32, | |
| 5310 | field_offsets: []u32, | |
| 5837 | 5311 | }, |
| 5838 | 5312 | .config = .{ |
| 5839 | .@"trailing.captures_len.?" = .@"payload.flags.any_captures", | |
| 5840 | .@"trailing.captures.?" = .@"payload.flags.any_captures", | |
| 5313 | .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified", | |
| 5314 | .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true", | |
| 5315 | .@"trailing.captures.?" = .@"payload.flags.any_captures == .true", | |
| 5841 | 5316 | .@"trailing.captures.?.len" = .@"trailing.captures_len.?", |
| 5842 | .@"trailing.type_hash.?" = .@"payload.flags.is_reified", | |
| 5843 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5844 | 5317 | .@"trailing.field_names.len" = .@"payload.fields_len", |
| 5845 | .@"trailing.field_inits.?" = .@"payload.flags.any_default_inits", | |
| 5846 | .@"trailing.field_inits.?.len" = .@"payload.fields_len", | |
| 5847 | .@"trailing.field_aligns.?" = .@"payload.flags.any_aligned_fields", | |
| 5318 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5319 | .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults", | |
| 5320 | .@"trailing.field_defaults.?.len" = .@"payload.fields_len", | |
| 5321 | .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns", | |
| 5848 | 5322 | .@"trailing.field_aligns.?.len" = .@"payload.fields_len", |
| 5849 | 5323 | .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", |
| 5850 | 5324 | .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", |
| 5851 | .@"trailing.field_index.?" = .@"!payload.flags.is_extern", | |
| 5852 | .@"trailing.field_index.?.len" = .@"payload.fields_len", | |
| 5853 | .@"trailing.field_offset.len" = .@"payload.fields_len", | |
| 5325 | .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto", | |
| 5326 | .@"trailing.field_runtime_order.?.len" = .@"payload.fields_len", | |
| 5327 | .@"trailing.field_offsets.len" = .@"payload.fields_len", | |
| 5854 | 5328 | }, |
| 5855 | 5329 | }, |
| 5856 | .type_struct_packed = .{ | |
| 5330 | .type_struct_packed_auto = struct_packed_encoding, | |
| 5331 | .type_struct_packed_explicit = struct_packed_encoding, | |
| 5332 | .type_struct_packed_auto_defaults = struct_packed_defaults_encoding, | |
| 5333 | .type_struct_packed_explicit_defaults = struct_packed_defaults_encoding, | |
| 5334 | .type_union = .{ | |
| 5857 | 5335 | .summary = .@"{.payload.name%summary#\"}", |
| 5858 | .payload = TypeStructPacked, | |
| 5336 | .payload = TypeUnion, | |
| 5859 | 5337 | .trailing = struct { |
| 5338 | type_hash: ?u64, | |
| 5860 | 5339 | captures_len: ?u32, |
| 5861 | 5340 | captures: ?[]CaptureValue, |
| 5862 | type_hash: ?u64, | |
| 5863 | 5341 | field_types: []Index, |
| 5864 | field_names: []NullTerminatedString, | |
| 5342 | field_aligns: ?[]Alignment, | |
| 5865 | 5343 | }, |
| 5866 | 5344 | .config = .{ |
| 5867 | .@"trailing.captures_len.?" = .@"payload.flags.any_captures", | |
| 5868 | .@"trailing.captures.?" = .@"payload.flags.any_captures", | |
| 5345 | .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified", | |
| 5346 | .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true", | |
| 5347 | .@"trailing.captures.?" = .@"payload.flags.any_captures == .true", | |
| 5869 | 5348 | .@"trailing.captures.?.len" = .@"trailing.captures_len.?", |
| 5870 | .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified", | |
| 5871 | 5349 | .@"trailing.field_types.len" = .@"payload.fields_len", |
| 5872 | .@"trailing.field_names.len" = .@"payload.fields_len", | |
| 5350 | .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns", | |
| 5351 | .@"trailing.field_aligns.?.len" = .@"payload.fields_len", | |
| 5873 | 5352 | }, |
| 5874 | 5353 | }, |
| 5875 | .type_struct_packed_inits = .{ | |
| 5354 | .type_union_packed_auto = union_packed_encoding, | |
| 5355 | .type_union_packed_explicit = union_packed_encoding, | |
| 5356 | .type_enum_auto = .{ | |
| 5876 | 5357 | .summary = .@"{.payload.name%summary#\"}", |
| 5877 | .payload = TypeStructPacked, | |
| 5358 | .payload = TypeEnum, | |
| 5878 | 5359 | .trailing = struct { |
| 5879 | captures_len: ?u32, | |
| 5880 | captures: ?[]CaptureValue, | |
| 5360 | owner_union: ?Index, | |
| 5361 | zir_index: ?TrackedInst.Index, | |
| 5881 | 5362 | type_hash: ?u64, |
| 5882 | field_types: []Index, | |
| 5363 | captures: ?[]CaptureValue, | |
| 5883 | 5364 | field_names: []NullTerminatedString, |
| 5884 | field_inits: []Index, | |
| 5885 | 5365 | }, |
| 5886 | 5366 | .config = .{ |
| 5887 | .@"trailing.captures_len.?" = .@"payload.flags.any_captures", | |
| 5888 | .@"trailing.captures.?" = .@"payload.flags.any_captures", | |
| 5889 | .@"trailing.captures.?.len" = .@"trailing.captures_len.?", | |
| 5890 | .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified", | |
| 5891 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5367 | .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag", | |
| 5368 | .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag", | |
| 5369 | .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", | |
| 5370 | .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag", | |
| 5371 | .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", | |
| 5892 | 5372 | .@"trailing.field_names.len" = .@"payload.fields_len", |
| 5893 | .@"trailing.field_inits.len" = .@"payload.fields_len", | |
| 5894 | }, | |
| 5895 | }, | |
| 5896 | .type_tuple = .{ | |
| 5897 | .summary = .@"struct {...}", | |
| 5898 | .payload = TypeTuple, | |
| 5899 | .trailing = struct { | |
| 5900 | field_types: []Index, | |
| 5901 | field_values: []Index, | |
| 5902 | }, | |
| 5903 | .config = .{ | |
| 5904 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5905 | .@"trailing.field_values.len" = .@"payload.fields_len", | |
| 5906 | 5373 | }, |
| 5907 | 5374 | }, |
| 5908 | .type_union = .{ | |
| 5375 | .type_enum_explicit = enum_explicit_encoding, | |
| 5376 | .type_enum_nonexhaustive = enum_explicit_encoding, | |
| 5377 | .type_opaque = .{ | |
| 5909 | 5378 | .summary = .@"{.payload.name%summary#\"}", |
| 5910 | .payload = TypeUnion, | |
| 5911 | .trailing = struct { | |
| 5912 | captures_len: ?u32, | |
| 5913 | captures: ?[]CaptureValue, | |
| 5914 | type_hash: ?u64, | |
| 5915 | field_types: []Index, | |
| 5916 | field_aligns: []Alignment, | |
| 5917 | }, | |
| 5918 | .config = .{ | |
| 5919 | .@"trailing.captures_len.?" = .@"payload.flags.any_captures", | |
| 5920 | .@"trailing.captures.?" = .@"payload.flags.any_captures", | |
| 5921 | .@"trailing.captures.?.len" = .@"trailing.captures_len.?", | |
| 5922 | .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified", | |
| 5923 | .@"trailing.field_types.len" = .@"payload.fields_len", | |
| 5924 | .@"trailing.field_aligns.len" = .@"payload.fields_len", | |
| 5925 | }, | |
| 5926 | }, | |
| 5927 | .type_function = .{ | |
| 5928 | .summary = .@"fn (...) ... {.payload.return_type%summary}", | |
| 5929 | .payload = TypeFunction, | |
| 5930 | .trailing = struct { | |
| 5931 | param_comptime_bits: ?[]u32, | |
| 5932 | param_noalias_bits: ?[]u32, | |
| 5933 | param_type: []Index, | |
| 5934 | }, | |
| 5935 | .config = .{ | |
| 5936 | .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits", | |
| 5937 | .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32", | |
| 5938 | .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits", | |
| 5939 | .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32", | |
| 5940 | .@"trailing.param_type.len" = .@"payload.params_len", | |
| 5941 | }, | |
| 5379 | .payload = TypeOpaque, | |
| 5380 | .trailing = struct { captures: []CaptureValue }, | |
| 5381 | .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" }, | |
| 5942 | 5382 | }, |
| 5943 | 5383 | |
| 5944 | 5384 | .undef = .{ .summary = .@"@as({.data%summary}, undefined)", .data = Index }, |
| ... | ... | @@ -5999,8 +5439,6 @@ pub const Tag = enum(u8) { |
| 5999 | 5439 | .int_small = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.value%value})", .payload = IntSmall }, |
| 6000 | 5440 | .int_positive = .{}, |
| 6001 | 5441 | .int_negative = .{}, |
| 6002 | .int_lazy_align = .{ .summary = .@"@as({.payload.ty%summary}, @alignOf({.payload.lazy_ty%summary}))", .payload = IntLazy }, | |
| 6003 | .int_lazy_size = .{ .summary = .@"@as({.payload.ty%summary}, @sizeOf({.payload.lazy_ty%summary}))", .payload = IntLazy }, | |
| 6004 | 5442 | .error_set_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error }, |
| 6005 | 5443 | .error_union_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error }, |
| 6006 | 5444 | .error_union_payload = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.val%summary})", .payload = TypeValue }, |
| ... | ... | @@ -6049,6 +5487,7 @@ pub const Tag = enum(u8) { |
| 6049 | 5487 | .config = .{ .@"trailing.elements.len" = .@"payload.ty.payload.fields_len" }, |
| 6050 | 5488 | }, |
| 6051 | 5489 | .repeated = .{ .summary = .@"@as({.payload.ty%summary}, @splat({.payload.elem_val%summary}))", .payload = Repeated }, |
| 5490 | .bitpack = .{ .summary = .@"@as({.payload.ty%summary}, {})", .payload = Key.Bitpack }, | |
| 6052 | 5491 | |
| 6053 | 5492 | .memoized_call = .{ |
| 6054 | 5493 | .summary = .@"@memoize({.payload.func%summary})", |
| ... | ... | @@ -6141,194 +5580,288 @@ pub const Tag = enum(u8) { |
| 6141 | 5580 | generic_owner: Index, |
| 6142 | 5581 | }; |
| 6143 | 5582 | |
| 6144 | pub const FuncCoerced = struct { | |
| 6145 | ty: Index, | |
| 6146 | func: Index, | |
| 6147 | }; | |
| 5583 | pub const FuncCoerced = struct { | |
| 5584 | ty: Index, | |
| 5585 | func: Index, | |
| 5586 | }; | |
| 5587 | ||
| 5588 | /// Trailing: | |
| 5589 | /// 0. name: NullTerminatedString for each names_len | |
| 5590 | pub const ErrorSet = struct { | |
| 5591 | names_len: u32, | |
| 5592 | /// Maps error names to declaration index. | |
| 5593 | names_map: MapIndex, | |
| 5594 | }; | |
| 5595 | ||
| 5596 | /// Trailing: | |
| 5597 | /// 0. comptime_bits: u32, // if has_comptime_bits | |
| 5598 | /// 1. noalias_bits: u32, // if has_noalias_bits | |
| 5599 | /// 2. param_type: Index for each params_len | |
| 5600 | pub const TypeFunction = struct { | |
| 5601 | params_len: u32, | |
| 5602 | return_type: Index, | |
| 5603 | flags: Flags, | |
| 5604 | ||
| 5605 | pub const Flags = packed struct(u32) { | |
| 5606 | cc: PackedCallingConvention, | |
| 5607 | is_var_args: bool, | |
| 5608 | has_comptime_bits: bool, | |
| 5609 | has_noalias_bits: bool, | |
| 5610 | is_noinline: bool, | |
| 5611 | _: u10 = 0, | |
| 5612 | }; | |
| 5613 | }; | |
| 5614 | ||
| 5615 | /// At first I thought of storing the denormalized data externally, such as... | |
| 5616 | /// | |
| 5617 | /// * runtime field order | |
| 5618 | /// * calculated field offsets | |
| 5619 | /// * size and alignment of the struct | |
| 5620 | /// | |
| 5621 | /// ...since these can be computed based on the other data here. However, | |
| 5622 | /// this data does need to be memoized, and therefore stored in memory | |
| 5623 | /// while the compiler is running, in order to avoid O(N^2) logic in many | |
| 5624 | /// places. Since the data can be stored compactly in the InternPool | |
| 5625 | /// representation, it is better for memory usage to store denormalized data | |
| 5626 | /// here, and potentially also better for performance as well. It's also simpler | |
| 5627 | /// than coming up with some other scheme for the data. | |
| 5628 | /// | |
| 5629 | /// Trailing: | |
| 5630 | /// 0. type_hash: PackedU64 // if `any_captures == .reified` | |
| 5631 | /// 1. captures_len: u32 // if `any_captures == .true` | |
| 5632 | /// 2. capture: CaptureValue // for each `captures_len` | |
| 5633 | /// 3. field_name: NullTerminatedString // for each `fields_len` | |
| 5634 | /// 4. field_type: Index // for each `fields_len` | |
| 5635 | /// 5. field_default: Index // if `any_field_defaults`; for each `fields_len` | |
| 5636 | /// 6. field_align: Alignment // if `any_field_aligns`; for each `fields_len` | |
| 5637 | /// 7. field_is_comptime_bits: u32 // if `any_comptime_fields`; minimum `u32` for `fields_len`; LSB is field 0 | |
| 5638 | /// 8. field_runtime_order: RuntimeOrder // if `layout == .auto`; for each `fields_len` | |
| 5639 | /// 9. field_offset: u32 // for each `fields_len` | |
| 5640 | pub const TypeStruct = struct { | |
| 5641 | zir_index: TrackedInst.Index, | |
| 5642 | ||
| 5643 | name: NullTerminatedString, | |
| 5644 | name_nav: Nav.Index.Optional, | |
| 5645 | namespace: NamespaceIndex, | |
| 5646 | ||
| 5647 | fields_len: u32, | |
| 5648 | field_name_map: MapIndex, | |
| 5649 | ||
| 5650 | /// Size in bytes of the whole struct. Always 0 until layout resolved. | |
| 5651 | size: u32, | |
| 5652 | ||
| 5653 | flags: Flags, | |
| 5654 | ||
| 5655 | pub const Flags = packed struct(u32) { | |
| 5656 | any_captures: enum(u2) { true, false, reified }, | |
| 5657 | ||
| 5658 | /// `packed` layout is represented separately by `TypeStructPacked`. | |
| 5659 | layout: enum(u1) { auto, @"extern" }, | |
| 5660 | ||
| 5661 | any_comptime_fields: bool, | |
| 5662 | any_field_defaults: bool, | |
| 5663 | any_field_aligns: bool, | |
| 5664 | ||
| 5665 | class: TypeClass, | |
| 5666 | /// Alignment of the whole struct. Always `.none` until layout resolved. | |
| 5667 | alignment: Alignment, | |
| 5668 | ||
| 5669 | want_layout: bool, | |
| 6148 | 5670 | |
| 6149 | /// Trailing: | |
| 6150 | /// 0. name: NullTerminatedString for each names_len | |
| 6151 | pub const ErrorSet = struct { | |
| 6152 | names_len: u32, | |
| 6153 | /// Maps error names to declaration index. | |
| 6154 | names_map: MapIndex, | |
| 5671 | _: u16 = 0, | |
| 5672 | }; | |
| 6155 | 5673 | }; |
| 6156 | 5674 | |
| 6157 | 5675 | /// Trailing: |
| 6158 | /// 0. comptime_bits: u32, // if has_comptime_bits | |
| 6159 | /// 1. noalias_bits: u32, // if has_noalias_bits | |
| 6160 | /// 2. param_type: Index for each params_len | |
| 6161 | pub const TypeFunction = struct { | |
| 6162 | params_len: u32, | |
| 6163 | return_type: Index, | |
| 6164 | flags: Flags, | |
| 5676 | /// 0. type_hash: PackedU64 // if `captures_len == .reified` | |
| 5677 | /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` | |
| 5678 | /// 2. field_name: NullTerminatedString // for each `fields_len` | |
| 5679 | /// 3. field_type: Index // for each `fields_len` | |
| 5680 | /// 4. field_default: Index // if item tag implies field defaults; for each `fields_len` | |
| 5681 | pub const TypeStructPacked = struct { | |
| 5682 | zir_index: TrackedInst.Index, | |
| 5683 | bits: Bits, | |
| 6165 | 5684 | |
| 6166 | pub const Flags = packed struct(u32) { | |
| 6167 | cc: PackedCallingConvention, | |
| 6168 | is_var_args: bool, | |
| 6169 | is_generic: bool, | |
| 6170 | has_comptime_bits: bool, | |
| 6171 | has_noalias_bits: bool, | |
| 6172 | is_noinline: bool, | |
| 6173 | _: u9 = 0, | |
| 5685 | name: NullTerminatedString, | |
| 5686 | name_nav: Nav.Index.Optional, | |
| 5687 | namespace: NamespaceIndex, | |
| 5688 | ||
| 5689 | /// The corresponding `BackingTypeMode` depends on the item's `Tag`. | |
| 5690 | backing_int_type: Index, | |
| 5691 | ||
| 5692 | fields_len: u32, | |
| 5693 | field_name_map: MapIndex, | |
| 5694 | ||
| 5695 | const Bits = packed struct(u32) { | |
| 5696 | captures_len: enum(u31) { | |
| 5697 | reified = std.math.maxInt(u31), | |
| 5698 | _, | |
| 5699 | }, | |
| 5700 | want_layout: bool, | |
| 6174 | 5701 | }; |
| 6175 | 5702 | }; |
| 6176 | 5703 | |
| 5704 | /// For declared unions, field names are intentionally omitted because they are available in | |
| 5705 | /// `enum_tag_type`. However, reified unions do store field names, because they are needed by | |
| 5706 | /// type resolution to create or validate the enum tag type (type resolution for declared unions | |
| 5707 | /// instead fetches field names from ZIR). | |
| 5708 | /// | |
| 6177 | 5709 | /// Trailing: |
| 6178 | /// 0. captures_len: u32 // if `any_captures` | |
| 6179 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 6180 | /// 2. type_hash: PackedU64 // if `is_reified` | |
| 6181 | /// 3. field type: Index for each field; declaration order | |
| 6182 | /// 4. field align: Alignment for each field; declaration order | |
| 5710 | /// 0. type_hash: PackedU64 // if `any_captures == .reified` | |
| 5711 | /// 1. captures_len: u32 // if `any_captures == .true` | |
| 5712 | /// 2. capture: CaptureValue // if `any_captures == .true`; for each `captures_len` | |
| 5713 | /// 3. reified_field_name: NullTerminatedString // if `any_captures == .reified`; for each `fields_len` | |
| 5714 | /// 4. field_type: Index // for each `fields_len` | |
| 5715 | /// 5. field_align: Alignment // for each `fields_len` if `any_field_aligns` | |
| 6183 | 5716 | pub const TypeUnion = struct { |
| 5717 | zir_index: TrackedInst.Index, | |
| 5718 | ||
| 6184 | 5719 | name: NullTerminatedString, |
| 6185 | 5720 | name_nav: Nav.Index.Optional, |
| 6186 | flags: Flags, | |
| 5721 | namespace: NamespaceIndex, | |
| 5722 | /// The enum that provides the list of field names and values. | |
| 5723 | enum_tag_type: Index, | |
| 5724 | ||
| 6187 | 5725 | /// This could be provided through the tag type, but it is more convenient |
| 6188 | 5726 | /// to store it directly. This is also necessary for `dumpStatsFallible` to |
| 6189 | 5727 | /// work on unresolved types. |
| 6190 | 5728 | fields_len: u32, |
| 6191 | /// Only valid after .have_layout | |
| 5729 | ||
| 5730 | /// Always 0 until layout resolved. | |
| 6192 | 5731 | size: u32, |
| 6193 | /// Only valid after .have_layout | |
| 5732 | /// Always 0 until layout resolved. | |
| 6194 | 5733 | padding: u32, |
| 6195 | namespace: NamespaceIndex, | |
| 6196 | /// The enum that provides the list of field names and values. | |
| 6197 | tag_ty: Index, | |
| 6198 | zir_index: TrackedInst.Index, | |
| 5734 | ||
| 5735 | flags: Flags, | |
| 6199 | 5736 | |
| 6200 | 5737 | pub const Flags = packed struct(u32) { |
| 6201 | any_captures: bool, | |
| 6202 | runtime_tag: LoadedUnionType.RuntimeTag, | |
| 6203 | /// If false, the field alignment trailing data is omitted. | |
| 6204 | any_aligned_fields: bool, | |
| 6205 | layout: std.builtin.Type.ContainerLayout, | |
| 6206 | status: LoadedUnionType.Status, | |
| 6207 | requires_comptime: RequiresComptime, | |
| 6208 | assumed_runtime_bits: bool, | |
| 6209 | assumed_pointer_aligned: bool, | |
| 5738 | any_captures: enum(u2) { true, false, reified }, | |
| 5739 | ||
| 5740 | /// Whether `enum_tag_type` was explicitly specified with `union(E)` syntax. | |
| 5741 | /// | |
| 5742 | /// For `union(enum(E))` syntax, this is `false`, but the generated enum tag type is | |
| 5743 | /// considered to have an explicitly specified integer tag type. | |
| 5744 | enum_tag_mode: BackingTypeMode, | |
| 5745 | ||
| 5746 | /// `packed` layout is represented separately by `TypeStructPacked`. | |
| 5747 | layout: enum(u1) { auto, @"extern" }, | |
| 5748 | ||
| 5749 | any_field_aligns: bool, | |
| 5750 | tag_usage: LoadedUnionType.TagUsage, | |
| 5751 | ||
| 5752 | class: TypeClass, | |
| 5753 | has_runtime_tag: bool, | |
| 5754 | ||
| 5755 | /// Alignment of the whole union. Always `.none` until layout resolved. | |
| 6210 | 5756 | alignment: Alignment, |
| 6211 | is_reified: bool, | |
| 6212 | _: u12 = 0, | |
| 5757 | ||
| 5758 | want_layout: bool, | |
| 5759 | ||
| 5760 | _: u14 = 0, | |
| 6213 | 5761 | }; |
| 6214 | 5762 | }; |
| 6215 | 5763 | |
| 5764 | /// For declared unions, field names are intentionally omitted because they are available in | |
| 5765 | /// `enum_tag_type`. However, reified unions do store field names, because they are needed by | |
| 5766 | /// type resolution to create or validate the enum tag type (type resolution for declared unions | |
| 5767 | /// instead fetches field names from ZIR). | |
| 5768 | /// | |
| 6216 | 5769 | /// Trailing: |
| 6217 | /// 0. captures_len: u32 // if `any_captures` | |
| 6218 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 6219 | /// 2. type_hash: PackedU64 // if `is_reified` | |
| 6220 | /// 3. type: Index for each fields_len | |
| 6221 | /// 4. name: NullTerminatedString for each fields_len | |
| 6222 | /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits | |
| 6223 | pub const TypeStructPacked = struct { | |
| 5770 | /// 0. type_hash: PackedU64 // if `captures_len == .reified` | |
| 5771 | /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` | |
| 5772 | /// 2. reified_field_name: NullTerminatedString // if `captures_len == .reified`; for each `fields_len` | |
| 5773 | /// 3. field_type: Index // for each `fields_len` | |
| 5774 | pub const TypeUnionPacked = struct { | |
| 5775 | zir_index: TrackedInst.Index, | |
| 5776 | bits: Bits, | |
| 5777 | ||
| 6224 | 5778 | name: NullTerminatedString, |
| 6225 | 5779 | name_nav: Nav.Index.Optional, |
| 6226 | zir_index: TrackedInst.Index, | |
| 6227 | fields_len: u32, | |
| 6228 | 5780 | namespace: NamespaceIndex, |
| 6229 | backing_int_ty: Index, | |
| 6230 | names_map: MapIndex, | |
| 6231 | flags: Flags, | |
| 6232 | 5781 | |
| 6233 | pub const Flags = packed struct(u32) { | |
| 6234 | any_captures: bool = false, | |
| 6235 | /// Dependency loop detection when resolving field inits. | |
| 6236 | field_inits_wip: bool = false, | |
| 6237 | inits_resolved: bool = false, | |
| 6238 | is_reified: bool = false, | |
| 6239 | _: u28 = 0, | |
| 5782 | /// The corresponding `BackingTypeMode` depends on the item's `Tag`. | |
| 5783 | backing_int_type: Index, | |
| 5784 | /// Although packed unions do not semantically have a tag type, the compiler still assigns | |
| 5785 | /// them a "hypothetical" tag type. | |
| 5786 | enum_tag_type: Index, | |
| 5787 | ||
| 5788 | /// This could be provided through the tag type, but it is more convenient | |
| 5789 | /// to store it directly. This is also necessary for `dumpStatsFallible` to | |
| 5790 | /// work on unresolved types. | |
| 5791 | fields_len: u32, | |
| 5792 | ||
| 5793 | const Bits = packed struct(u32) { | |
| 5794 | captures_len: enum(u31) { | |
| 5795 | reified = std.math.maxInt(u31), | |
| 5796 | _, | |
| 5797 | }, | |
| 5798 | want_layout: bool, | |
| 6240 | 5799 | }; |
| 6241 | 5800 | }; |
| 6242 | 5801 | |
| 6243 | /// At first I thought of storing the denormalized data externally, such as... | |
| 6244 | /// | |
| 6245 | /// * runtime field order | |
| 6246 | /// * calculated field offsets | |
| 6247 | /// * size and alignment of the struct | |
| 6248 | /// | |
| 6249 | /// ...since these can be computed based on the other data here. However, | |
| 6250 | /// this data does need to be memoized, and therefore stored in memory | |
| 6251 | /// while the compiler is running, in order to avoid O(N^2) logic in many | |
| 6252 | /// places. Since the data can be stored compactly in the InternPool | |
| 6253 | /// representation, it is better for memory usage to store denormalized data | |
| 6254 | /// here, and potentially also better for performance as well. It's also simpler | |
| 6255 | /// than coming up with some other scheme for the data. | |
| 6256 | /// | |
| 6257 | 5802 | /// Trailing: |
| 6258 | /// 0. captures_len: u32 // if `any_captures` | |
| 6259 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 6260 | /// 2. type_hash: PackedU64 // if `is_reified` | |
| 6261 | /// 3. type: Index for each field in declared order | |
| 6262 | /// 4. if any_default_inits: | |
| 6263 | /// init: Index // for each field in declared order | |
| 6264 | /// 5. if any_aligned_fields: | |
| 6265 | /// align: Alignment // for each field in declared order | |
| 6266 | /// 6. if any_comptime_fields: | |
| 6267 | /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0 | |
| 6268 | /// 7. if not is_extern: | |
| 6269 | /// field_index: RuntimeOrder // for each field in runtime order | |
| 6270 | /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved | |
| 6271 | pub const TypeStruct = struct { | |
| 5803 | /// 0. owner_union: Index // if `captures_len == .generated_union_tag` | |
| 5804 | /// 1. zir_index: TrackedInst.Index // if `captures_len != .generated_union_tag` | |
| 5805 | /// 2. type_hash: PackedU64 // if `captures_len == .reified` | |
| 5806 | /// 3. capture: CaptureValue // if `captures_len` is not a named tag; for each `captures_len` | |
| 5807 | /// 4. field_value_map: MapIndex // if tag is not `.type_enum_auto` | |
| 5808 | /// 5. field_name: NullTerminatedString // for each `fields_len` | |
| 5809 | /// 6. field_value: Index // if tag is not `.type_enum_auto`; for each `fields_len` | |
| 5810 | pub const TypeEnum = struct { | |
| 5811 | bits: Bits, | |
| 5812 | ||
| 6272 | 5813 | name: NullTerminatedString, |
| 6273 | 5814 | name_nav: Nav.Index.Optional, |
| 6274 | zir_index: TrackedInst.Index, | |
| 6275 | 5815 | namespace: NamespaceIndex, |
| 5816 | ||
| 5817 | /// An integer type which is used for the numerical value of the enum. Whether this was | |
| 5818 | /// user-provided or inferred by the compiler depends on the tag. | |
| 5819 | int_tag_type: Index, | |
| 5820 | ||
| 6276 | 5821 | fields_len: u32, |
| 6277 | flags: Flags, | |
| 6278 | size: u32, | |
| 5822 | field_name_map: MapIndex, | |
| 6279 | 5823 | |
| 6280 | pub const Flags = packed struct(u32) { | |
| 6281 | any_captures: bool = false, | |
| 6282 | is_extern: bool = false, | |
| 6283 | known_non_opv: bool = false, | |
| 6284 | requires_comptime: RequiresComptime = @enumFromInt(0), | |
| 6285 | assumed_runtime_bits: bool = false, | |
| 6286 | assumed_pointer_aligned: bool = false, | |
| 6287 | any_comptime_fields: bool = false, | |
| 6288 | any_default_inits: bool = false, | |
| 6289 | any_aligned_fields: bool = false, | |
| 6290 | /// `.none` until layout_resolved | |
| 6291 | alignment: Alignment = @enumFromInt(0), | |
| 6292 | /// Dependency loop detection when resolving struct alignment. | |
| 6293 | alignment_wip: bool = false, | |
| 6294 | /// Dependency loop detection when resolving field types. | |
| 6295 | field_types_wip: bool = false, | |
| 6296 | /// Dependency loop detection when resolving struct layout. | |
| 6297 | layout_wip: bool = false, | |
| 6298 | /// Indicates whether `size`, `alignment`, runtime field order, and | |
| 6299 | /// field offets are populated. | |
| 6300 | layout_resolved: bool = false, | |
| 6301 | /// Dependency loop detection when resolving field inits. | |
| 6302 | field_inits_wip: bool = false, | |
| 6303 | /// Indicates whether `field_inits` has been resolved. | |
| 6304 | inits_resolved: bool = false, | |
| 6305 | // The types and all its fields have had their layout resolved. Even through pointer = false, | |
| 6306 | // which `layout_resolved` does not ensure. | |
| 6307 | fully_resolved: bool = false, | |
| 6308 | is_reified: bool = false, | |
| 6309 | _: u8 = 0, | |
| 5824 | const Bits = packed struct(u32) { | |
| 5825 | captures_len: enum(u31) { | |
| 5826 | reified = std.math.maxInt(u31), | |
| 5827 | generated_union_tag = std.math.maxInt(u31) - 1, | |
| 5828 | _, | |
| 5829 | }, | |
| 5830 | want_layout: bool, | |
| 6310 | 5831 | }; |
| 6311 | 5832 | }; |
| 6312 | 5833 | |
| 6313 | 5834 | /// Trailing: |
| 6314 | 5835 | /// 0. capture: CaptureValue // for each `captures_len` |
| 6315 | 5836 | pub const TypeOpaque = struct { |
| 5837 | zir_index: TrackedInst.Index, | |
| 5838 | captures_len: u32, | |
| 5839 | ||
| 6316 | 5840 | name: NullTerminatedString, |
| 6317 | 5841 | name_nav: Nav.Index.Optional, |
| 6318 | /// Contains the declarations inside this opaque. | |
| 6319 | 5842 | namespace: NamespaceIndex, |
| 6320 | /// The index of the `opaque_decl` instruction. | |
| 6321 | zir_index: TrackedInst.Index, | |
| 6322 | /// `std.math.maxInt(u32)` indicates this type is reified. | |
| 6323 | captures_len: u32, | |
| 6324 | 5843 | }; |
| 6325 | 5844 | }; |
| 6326 | 5845 | |
| 5846 | /// Differentiates between user-provided and compiler-generated backing types for packed and tagged types. | |
| 5847 | pub const BackingTypeMode = enum(u1) { | |
| 5848 | /// The backing type was explicitly provided by the user. For instance: | |
| 5849 | /// union(T) | |
| 5850 | /// enum(T) | |
| 5851 | /// packed struct(T) | |
| 5852 | /// packed union(T) | |
| 5853 | /// Type layout resolution will evaluate the user-provided expression and validate that type. | |
| 5854 | explicit, | |
| 5855 | /// No backing type was explicitly provided by the user. Type layout resolution will populate | |
| 5856 | /// an inferred/generated type. | |
| 5857 | auto, | |
| 5858 | }; | |
| 5859 | ||
| 6327 | 5860 | /// State that is mutable during semantic analysis. This data is not used for |
| 6328 | 5861 | /// equality or hashing, except for `inferred_error_set` which is considered |
| 6329 | 5862 | /// to be part of the type of the function. |
| 6330 | 5863 | pub const FuncAnalysis = packed struct(u32) { |
| 6331 | is_analyzed: bool, | |
| 5864 | want_runtime_analysis: bool, | |
| 6332 | 5865 | branch_hint: std.builtin.BranchHint, |
| 6333 | 5866 | is_noinline: bool, |
| 6334 | 5867 | has_error_trace: bool, |
| ... | ... | @@ -6399,13 +5932,9 @@ pub const SimpleType = enum(u32) { |
| 6399 | 5932 | }; |
| 6400 | 5933 | |
| 6401 | 5934 | pub const SimpleValue = enum(u32) { |
| 6402 | /// This is untyped `undefined`. | |
| 6403 | undefined = @intFromEnum(Index.undef), | |
| 6404 | 5935 | void = @intFromEnum(Index.void_value), |
| 6405 | 5936 | /// This is untyped `null`. |
| 6406 | 5937 | null = @intFromEnum(Index.null_value), |
| 6407 | /// This is the untyped empty struct/array literal: `.{}` | |
| 6408 | empty_tuple = @intFromEnum(Index.empty_tuple), | |
| 6409 | 5938 | true = @intFromEnum(Index.bool_true), |
| 6410 | 5939 | false = @intFromEnum(Index.bool_false), |
| 6411 | 5940 | @"unreachable" = @intFromEnum(Index.unreachable_value), |
| ... | ... | @@ -6536,12 +6065,17 @@ pub const Alignment = enum(u6) { |
| 6536 | 6065 | pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; |
| 6537 | 6066 | |
| 6538 | 6067 | pub fn get(slice: Slice, ip: *const InternPool) []Alignment { |
| 6539 | // TODO: implement @ptrCast between slices changing the length | |
| 6540 | 6068 | const extra = ip.getLocalShared(slice.tid).extra.acquire(); |
| 6541 | //const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]); | |
| 6542 | const bytes: []u8 = std.mem.sliceAsBytes(extra.view().items(.@"0")[slice.start..]); | |
| 6069 | const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]); | |
| 6543 | 6070 | return @ptrCast(bytes[0..slice.len]); |
| 6544 | 6071 | } |
| 6072 | ||
| 6073 | /// If `slice` is empty (`slice.len == 0`), returns `.none`. | |
| 6074 | /// Otherwise, asserts that `index < slice.len`, and returns the value at `index`. | |
| 6075 | pub fn getOrNone(slice: Slice, ip: *const InternPool, index: usize) Alignment { | |
| 6076 | if (slice.len == 0) return .none; | |
| 6077 | return slice.get(ip)[index]; | |
| 6078 | } | |
| 6545 | 6079 | }; |
| 6546 | 6080 | |
| 6547 | 6081 | pub fn toRelaxedCompareUnits(a: Alignment) u8 { |
| ... | ... | @@ -6596,55 +6130,6 @@ pub const Array = struct { |
| 6596 | 6130 | } |
| 6597 | 6131 | }; |
| 6598 | 6132 | |
| 6599 | /// Trailing: | |
| 6600 | /// 0. owner_union: Index // if `zir_index == .none` | |
| 6601 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 6602 | /// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | |
| 6603 | /// 3. field name: NullTerminatedString for each fields_len; declaration order | |
| 6604 | /// 4. tag value: Index for each fields_len; declaration order | |
| 6605 | pub const EnumExplicit = struct { | |
| 6606 | name: NullTerminatedString, | |
| 6607 | name_nav: Nav.Index.Optional, | |
| 6608 | /// `std.math.maxInt(u32)` indicates this type is reified. | |
| 6609 | captures_len: u32, | |
| 6610 | namespace: NamespaceIndex, | |
| 6611 | /// An integer type which is used for the numerical value of the enum, which | |
| 6612 | /// has been explicitly provided by the enum declaration. | |
| 6613 | int_tag_type: Index, | |
| 6614 | fields_len: u32, | |
| 6615 | /// Maps field names to declaration index. | |
| 6616 | names_map: MapIndex, | |
| 6617 | /// Maps field values to declaration index. | |
| 6618 | /// If this is `none`, it means the trailing tag values are absent because | |
| 6619 | /// they are auto-numbered. | |
| 6620 | values_map: OptionalMapIndex, | |
| 6621 | /// `none` means this is a generated tag type. | |
| 6622 | /// There will be a trailing union type for which this is a tag. | |
| 6623 | zir_index: TrackedInst.Index.Optional, | |
| 6624 | }; | |
| 6625 | ||
| 6626 | /// Trailing: | |
| 6627 | /// 0. owner_union: Index // if `zir_index == .none` | |
| 6628 | /// 1. capture: CaptureValue // for each `captures_len` | |
| 6629 | /// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) | |
| 6630 | /// 3. field name: NullTerminatedString for each fields_len; declaration order | |
| 6631 | pub const EnumAuto = struct { | |
| 6632 | name: NullTerminatedString, | |
| 6633 | name_nav: Nav.Index.Optional, | |
| 6634 | /// `std.math.maxInt(u32)` indicates this type is reified. | |
| 6635 | captures_len: u32, | |
| 6636 | namespace: NamespaceIndex, | |
| 6637 | /// An integer type which is used for the numerical value of the enum, which | |
| 6638 | /// was inferred by Zig based on the number of tags. | |
| 6639 | int_tag_type: Index, | |
| 6640 | fields_len: u32, | |
| 6641 | /// Maps field names to declaration index. | |
| 6642 | names_map: MapIndex, | |
| 6643 | /// `none` means this is a generated tag type. | |
| 6644 | /// There will be a trailing union type for which this is a tag. | |
| 6645 | zir_index: TrackedInst.Index.Optional, | |
| 6646 | }; | |
| 6647 | ||
| 6648 | 6133 | pub const PackedU64 = packed struct(u64) { |
| 6649 | 6134 | a: u32, |
| 6650 | 6135 | b: u32, |
| ... | ... | @@ -6827,11 +6312,6 @@ pub const IntSmall = struct { |
| 6827 | 6312 | value: u32, |
| 6828 | 6313 | }; |
| 6829 | 6314 | |
| 6830 | pub const IntLazy = struct { | |
| 6831 | ty: Index, | |
| 6832 | lazy_ty: Index, | |
| 6833 | }; | |
| 6834 | ||
| 6835 | 6315 | /// A f64 value, broken up into 2 u32 parts. |
| 6836 | 6316 | pub const Float64 = struct { |
| 6837 | 6317 | piece0: u32, |
| ... | ... | @@ -6994,7 +6474,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { |
| 6994 | 6474 | ip.src_hash_deps.deinit(gpa); |
| 6995 | 6475 | ip.nav_val_deps.deinit(gpa); |
| 6996 | 6476 | ip.nav_ty_deps.deinit(gpa); |
| 6997 | ip.interned_deps.deinit(gpa); | |
| 6477 | ip.func_ies_deps.deinit(gpa); | |
| 6478 | ip.type_layout_deps.deinit(gpa); | |
| 6479 | ip.struct_defaults_deps.deinit(gpa); | |
| 6998 | 6480 | ip.zon_file_deps.deinit(gpa); |
| 6999 | 6481 | ip.embed_file_deps.deinit(gpa); |
| 7000 | 6482 | ip.namespace_deps.deinit(gpa); |
| ... | ... | @@ -7130,132 +6612,118 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7130 | 6612 | .type_inferred_error_set => .{ |
| 7131 | 6613 | .inferred_error_set_type = @enumFromInt(data), |
| 7132 | 6614 | }, |
| 7133 | ||
| 7134 | .type_opaque => .{ .opaque_type = ns: { | |
| 7135 | const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data); | |
| 7136 | if (extra.data.captures_len == std.math.maxInt(u32)) { | |
| 7137 | break :ns .{ .reified = .{ | |
| 7138 | .zir_index = extra.data.zir_index, | |
| 7139 | .type_hash = 0, | |
| 7140 | } }; | |
| 7141 | } | |
| 7142 | break :ns .{ .declared = .{ | |
| 7143 | .zir_index = extra.data.zir_index, | |
| 7144 | .captures = .{ .owned = .{ | |
| 7145 | .tid = unwrapped_index.tid, | |
| 7146 | .start = extra.end, | |
| 7147 | .len = extra.data.captures_len, | |
| 7148 | } }, | |
| 7149 | } }; | |
| 7150 | } }, | |
| 6615 | .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, | |
| 6616 | .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, | |
| 7151 | 6617 | |
| 7152 | 6618 | .type_struct => .{ .struct_type = ns: { |
| 7153 | 6619 | const extra_list = unwrapped_index.getExtra(ip); |
| 7154 | const extra_items = extra_list.view().items(.@"0"); | |
| 7155 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]); | |
| 7156 | const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered)); | |
| 7157 | const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStruct).@"struct".fields.len); | |
| 7158 | if (flags.is_reified) { | |
| 7159 | assert(!flags.any_captures); | |
| 7160 | break :ns .{ .reified = .{ | |
| 7161 | .zir_index = zir_index, | |
| 7162 | .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(), | |
| 7163 | } }; | |
| 7164 | } | |
| 7165 | break :ns .{ .declared = .{ | |
| 7166 | .zir_index = zir_index, | |
| 7167 | .captures = .{ .owned = if (flags.any_captures) .{ | |
| 7168 | .tid = unwrapped_index.tid, | |
| 7169 | .start = end_extra_index + 1, | |
| 7170 | .len = extra_list.view().items(.@"0")[end_extra_index], | |
| 7171 | } else CaptureValue.Slice.empty }, | |
| 7172 | } }; | |
| 6620 | const extra = extraDataTrail(extra_list, Tag.TypeStruct, data); | |
| 6621 | break :ns switch (extra.data.flags.any_captures) { | |
| 6622 | .reified => .{ .reified = .{ | |
| 6623 | .zir_index = extra.data.zir_index, | |
| 6624 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), | |
| 6625 | } }, | |
| 6626 | .false => .{ .declared = .{ | |
| 6627 | .zir_index = extra.data.zir_index, | |
| 6628 | .captures = .{ .owned = .empty }, | |
| 6629 | } }, | |
| 6630 | .true => .{ .declared = .{ | |
| 6631 | .zir_index = extra.data.zir_index, | |
| 6632 | .captures = .{ .owned = .{ | |
| 6633 | .tid = unwrapped_index.tid, | |
| 6634 | .start = extra.end + 1, | |
| 6635 | .len = extra_list.view().items(.@"0")[extra.end], | |
| 6636 | } }, | |
| 6637 | } }, | |
| 6638 | }; | |
| 7173 | 6639 | } }, |
| 7174 | ||
| 7175 | .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = ns: { | |
| 6640 | .type_struct_packed_auto, | |
| 6641 | .type_struct_packed_explicit, | |
| 6642 | .type_struct_packed_auto_defaults, | |
| 6643 | .type_struct_packed_explicit_defaults, | |
| 6644 | => .{ .struct_type = ns: { | |
| 7176 | 6645 | const extra_list = unwrapped_index.getExtra(ip); |
| 7177 | const extra_items = extra_list.view().items(.@"0"); | |
| 7178 | const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]); | |
| 7179 | const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered)); | |
| 7180 | const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStructPacked).@"struct".fields.len); | |
| 7181 | if (flags.is_reified) { | |
| 7182 | assert(!flags.any_captures); | |
| 7183 | break :ns .{ .reified = .{ | |
| 7184 | .zir_index = zir_index, | |
| 7185 | .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(), | |
| 7186 | } }; | |
| 7187 | } | |
| 7188 | break :ns .{ .declared = .{ | |
| 7189 | .zir_index = zir_index, | |
| 7190 | .captures = .{ .owned = if (flags.any_captures) .{ | |
| 7191 | .tid = unwrapped_index.tid, | |
| 7192 | .start = end_extra_index + 1, | |
| 7193 | .len = extra_items[end_extra_index], | |
| 7194 | } else CaptureValue.Slice.empty }, | |
| 7195 | } }; | |
| 6646 | const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); | |
| 6647 | break :ns switch (extra.data.bits.captures_len) { | |
| 6648 | .reified => .{ .reified = .{ | |
| 6649 | .zir_index = extra.data.zir_index, | |
| 6650 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), | |
| 6651 | } }, | |
| 6652 | _ => |len| .{ .declared = .{ | |
| 6653 | .zir_index = extra.data.zir_index, | |
| 6654 | .captures = .{ .owned = .{ | |
| 6655 | .tid = unwrapped_index.tid, | |
| 6656 | .start = extra.end, | |
| 6657 | .len = @intFromEnum(len), | |
| 6658 | } }, | |
| 6659 | } }, | |
| 6660 | }; | |
| 7196 | 6661 | } }, |
| 7197 | .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, | |
| 7198 | 6662 | .type_union => .{ .union_type = ns: { |
| 7199 | 6663 | const extra_list = unwrapped_index.getExtra(ip); |
| 7200 | 6664 | const extra = extraDataTrail(extra_list, Tag.TypeUnion, data); |
| 7201 | if (extra.data.flags.is_reified) { | |
| 7202 | assert(!extra.data.flags.any_captures); | |
| 7203 | break :ns .{ .reified = .{ | |
| 6665 | break :ns switch (extra.data.flags.any_captures) { | |
| 6666 | .reified => .{ .reified = .{ | |
| 7204 | 6667 | .zir_index = extra.data.zir_index, |
| 7205 | 6668 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), |
| 7206 | } }; | |
| 7207 | } | |
| 7208 | break :ns .{ .declared = .{ | |
| 7209 | .zir_index = extra.data.zir_index, | |
| 7210 | .captures = .{ .owned = if (extra.data.flags.any_captures) .{ | |
| 7211 | .tid = unwrapped_index.tid, | |
| 7212 | .start = extra.end + 1, | |
| 7213 | .len = extra_list.view().items(.@"0")[extra.end], | |
| 7214 | } else CaptureValue.Slice.empty }, | |
| 7215 | } }; | |
| 6669 | } }, | |
| 6670 | .false => .{ .declared = .{ | |
| 6671 | .zir_index = extra.data.zir_index, | |
| 6672 | .captures = .{ .owned = .empty }, | |
| 6673 | } }, | |
| 6674 | .true => .{ .declared = .{ | |
| 6675 | .zir_index = extra.data.zir_index, | |
| 6676 | .captures = .{ .owned = .{ | |
| 6677 | .tid = unwrapped_index.tid, | |
| 6678 | .start = extra.end + 1, | |
| 6679 | .len = extra_list.view().items(.@"0")[extra.end], | |
| 6680 | } }, | |
| 6681 | } }, | |
| 6682 | }; | |
| 7216 | 6683 | } }, |
| 7217 | ||
| 7218 | .type_enum_auto => .{ .enum_type = ns: { | |
| 6684 | .type_union_packed_auto, .type_union_packed_explicit => .{ .union_type = ns: { | |
| 7219 | 6685 | const extra_list = unwrapped_index.getExtra(ip); |
| 7220 | const extra = extraDataTrail(extra_list, EnumAuto, data); | |
| 7221 | const zir_index = extra.data.zir_index.unwrap() orelse { | |
| 7222 | assert(extra.data.captures_len == 0); | |
| 7223 | break :ns .{ .generated_tag = .{ | |
| 7224 | .union_type = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), | |
| 7225 | } }; | |
| 7226 | }; | |
| 7227 | if (extra.data.captures_len == std.math.maxInt(u32)) { | |
| 7228 | break :ns .{ .reified = .{ | |
| 7229 | .zir_index = zir_index, | |
| 6686 | const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); | |
| 6687 | break :ns switch (extra.data.bits.captures_len) { | |
| 6688 | .reified => .{ .reified = .{ | |
| 6689 | .zir_index = extra.data.zir_index, | |
| 7230 | 6690 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), |
| 7231 | } }; | |
| 7232 | } | |
| 7233 | break :ns .{ .declared = .{ | |
| 7234 | .zir_index = zir_index, | |
| 7235 | .captures = .{ .owned = .{ | |
| 7236 | .tid = unwrapped_index.tid, | |
| 7237 | .start = extra.end, | |
| 7238 | .len = extra.data.captures_len, | |
| 7239 | 6691 | } }, |
| 7240 | } }; | |
| 6692 | _ => |len| .{ .declared = .{ | |
| 6693 | .zir_index = extra.data.zir_index, | |
| 6694 | .captures = .{ .owned = .{ | |
| 6695 | .tid = unwrapped_index.tid, | |
| 6696 | .start = extra.end, | |
| 6697 | .len = @intFromEnum(len), | |
| 6698 | } }, | |
| 6699 | } }, | |
| 6700 | }; | |
| 7241 | 6701 | } }, |
| 7242 | .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { | |
| 6702 | .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { | |
| 7243 | 6703 | const extra_list = unwrapped_index.getExtra(ip); |
| 7244 | const extra = extraDataTrail(extra_list, EnumExplicit, data); | |
| 7245 | const zir_index = extra.data.zir_index.unwrap() orelse { | |
| 7246 | assert(extra.data.captures_len == 0); | |
| 7247 | break :ns .{ .generated_tag = .{ | |
| 7248 | .union_type = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), | |
| 7249 | } }; | |
| 6704 | const extra = extraDataTrail(extra_list, Tag.TypeEnum, data); | |
| 6705 | break :ns switch (extra.data.bits.captures_len) { | |
| 6706 | .reified => .{ .reified = .{ | |
| 6707 | .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), | |
| 6708 | .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(), | |
| 6709 | } }, | |
| 6710 | .generated_union_tag => .{ .generated_union_tag = owner_union: { | |
| 6711 | break :owner_union @enumFromInt(extra_list.view().items(.@"0")[extra.end]); | |
| 6712 | } }, | |
| 6713 | _ => |len| .{ .declared = .{ | |
| 6714 | .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), | |
| 6715 | .captures = .{ .owned = .{ | |
| 6716 | .tid = unwrapped_index.tid, | |
| 6717 | .start = extra.end + 1, | |
| 6718 | .len = @intFromEnum(len), | |
| 6719 | } }, | |
| 6720 | } }, | |
| 7250 | 6721 | }; |
| 7251 | if (extra.data.captures_len == std.math.maxInt(u32)) { | |
| 7252 | break :ns .{ .reified = .{ | |
| 7253 | .zir_index = zir_index, | |
| 7254 | .type_hash = extraData(extra_list, PackedU64, extra.end).get(), | |
| 7255 | } }; | |
| 7256 | } | |
| 6722 | } }, | |
| 6723 | .type_opaque => .{ .opaque_type = ns: { | |
| 6724 | const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data); | |
| 7257 | 6725 | break :ns .{ .declared = .{ |
| 7258 | .zir_index = zir_index, | |
| 6726 | .zir_index = extra.data.zir_index, | |
| 7259 | 6727 | .captures = .{ .owned = .{ |
| 7260 | 6728 | .tid = unwrapped_index.tid, |
| 7261 | 6729 | .start = extra.end, |
| ... | ... | @@ -7263,7 +6731,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7263 | 6731 | } }, |
| 7264 | 6732 | } }; |
| 7265 | 6733 | } }, |
| 7266 | .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, | |
| 7267 | 6734 | |
| 7268 | 6735 | .undef => .{ .undef = @enumFromInt(data) }, |
| 7269 | 6736 | .opt_null => .{ .opt = .{ |
| ... | ... | @@ -7390,17 +6857,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7390 | 6857 | .storage = .{ .u64 = info.value }, |
| 7391 | 6858 | } }; |
| 7392 | 6859 | }, |
| 7393 | .int_lazy_align, .int_lazy_size => |tag| { | |
| 7394 | const info = extraData(unwrapped_index.getExtra(ip), IntLazy, data); | |
| 7395 | return .{ .int = .{ | |
| 7396 | .ty = info.ty, | |
| 7397 | .storage = switch (tag) { | |
| 7398 | .int_lazy_align => .{ .lazy_align = info.lazy_ty }, | |
| 7399 | .int_lazy_size => .{ .lazy_size = info.lazy_ty }, | |
| 7400 | else => unreachable, | |
| 7401 | }, | |
| 7402 | } }; | |
| 7403 | }, | |
| 7404 | 6860 | .float_f16 => .{ .float = .{ |
| 7405 | 6861 | .ty = .f16_type, |
| 7406 | 6862 | .storage = .{ .f16 = @bitCast(@as(u16, @intCast(data))) }, |
| ... | ... | @@ -7488,7 +6944,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7488 | 6944 | }, |
| 7489 | 6945 | .type_array_small, |
| 7490 | 6946 | .type_vector, |
| 7491 | .type_struct_packed, | |
| 6947 | .type_struct_packed_auto, | |
| 6948 | .type_struct_packed_explicit, | |
| 7492 | 6949 | => .{ .aggregate = .{ |
| 7493 | 6950 | .ty = ty, |
| 7494 | 6951 | .storage = .{ .elems = &.{} }, |
| ... | ... | @@ -7496,11 +6953,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7496 | 6953 | |
| 7497 | 6954 | // There is only one possible value precisely due to the |
| 7498 | 6955 | // fact that this values slice is fully populated! |
| 7499 | .type_struct, .type_struct_packed_inits => { | |
| 6956 | .type_struct, | |
| 6957 | .type_struct_packed_auto_defaults, | |
| 6958 | .type_struct_packed_explicit_defaults, | |
| 6959 | => { | |
| 7500 | 6960 | const info = loadStructType(ip, ty); |
| 7501 | 6961 | return .{ .aggregate = .{ |
| 7502 | 6962 | .ty = ty, |
| 7503 | .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) }, | |
| 6963 | .storage = .{ .elems = @ptrCast(info.field_defaults.get(ip)) }, | |
| 7504 | 6964 | } }; |
| 7505 | 6965 | }, |
| 7506 | 6966 | |
| ... | ... | @@ -7516,11 +6976,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7516 | 6976 | } }; |
| 7517 | 6977 | }, |
| 7518 | 6978 | |
| 7519 | .type_enum_auto, | |
| 7520 | .type_enum_explicit, | |
| 7521 | .type_union, | |
| 7522 | => .{ .empty_enum_value = ty }, | |
| 7523 | ||
| 7524 | 6979 | else => unreachable, |
| 7525 | 6980 | }; |
| 7526 | 6981 | }, |
| ... | ... | @@ -7566,6 +7021,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7566 | 7021 | }, |
| 7567 | 7022 | .enum_literal => .{ .enum_literal = @enumFromInt(data) }, |
| 7568 | 7023 | .enum_tag => .{ .enum_tag = extraData(unwrapped_index.getExtra(ip), Tag.EnumTag, data) }, |
| 7024 | .bitpack => .{ .bitpack = extraData(unwrapped_index.getExtra(ip), Key.Bitpack, data) }, | |
| 7569 | 7025 | |
| 7570 | 7026 | .memoized_call => { |
| 7571 | 7027 | const extra_list = unwrapped_index.getExtra(ip); |
| ... | ... | @@ -7634,7 +7090,6 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke |
| 7634 | 7090 | .cc = type_function.data.flags.cc.unpack(), |
| 7635 | 7091 | .is_var_args = type_function.data.flags.is_var_args, |
| 7636 | 7092 | .is_noinline = type_function.data.flags.is_noinline, |
| 7637 | .is_generic = type_function.data.flags.is_generic, | |
| 7638 | 7093 | }; |
| 7639 | 7094 | } |
| 7640 | 7095 | |
| ... | ... | @@ -7893,45 +7348,6 @@ fn getOrPutKeyEnsuringAdditionalCapacity( |
| 7893 | 7348 | .map_index = map_index, |
| 7894 | 7349 | } }; |
| 7895 | 7350 | } |
| 7896 | /// Like `getOrPutKey`, but asserts that the key already exists, and prepares to replace | |
| 7897 | /// its shard entry with a new `Index` anyway. After finalizing this, the old index remains | |
| 7898 | /// valid (in that `indexToKey` and similar queries will behave as before), but it will | |
| 7899 | /// never be returned from a lookup (`getOrPutKey` etc). | |
| 7900 | /// This is used by incremental compilation when an existing container type is outdated. In | |
| 7901 | /// this case, the type must be recreated at a new `InternPool.Index`, but the old index must | |
| 7902 | /// remain valid since now-unreferenced `AnalUnit`s may retain references to it. The old index | |
| 7903 | /// will be cleaned up when the `Zcu` undergoes garbage collection. | |
| 7904 | fn putKeyReplace( | |
| 7905 | ip: *InternPool, | |
| 7906 | io: Io, | |
| 7907 | tid: Zcu.PerThread.Id, | |
| 7908 | key: Key, | |
| 7909 | ) GetOrPutKey { | |
| 7910 | const full_hash = key.hash64(ip); | |
| 7911 | const hash: u32 = @truncate(full_hash >> 32); | |
| 7912 | const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; | |
| 7913 | shard.mutate.map.mutex.lock(io, tid); | |
| 7914 | errdefer shard.mutate.map.mutex.unlock(io); | |
| 7915 | const map = shard.shared.map; | |
| 7916 | const map_mask = map.header().mask(); | |
| 7917 | var map_index = hash; | |
| 7918 | while (true) : (map_index += 1) { | |
| 7919 | map_index &= map_mask; | |
| 7920 | const entry = &map.entries[map_index]; | |
| 7921 | const index = entry.value; | |
| 7922 | assert(index != .none); // key not present | |
| 7923 | if (entry.hash == hash and ip.indexToKey(index).eql(key, ip)) { | |
| 7924 | break; // we found the entry to replace | |
| 7925 | } | |
| 7926 | } | |
| 7927 | return .{ .new = .{ | |
| 7928 | .ip = ip, | |
| 7929 | .tid = tid, | |
| 7930 | .io = io, | |
| 7931 | .shard = shard, | |
| 7932 | .map_index = map_index, | |
| 7933 | } }; | |
| 7934 | } | |
| 7935 | 7351 | |
| 7936 | 7352 | pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { |
| 7937 | 7353 | var gop = try ip.getOrPutKey(gpa, io, tid, key); |
| ... | ... | @@ -8084,12 +7500,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8084 | 7500 | }); |
| 8085 | 7501 | }, |
| 8086 | 7502 | |
| 8087 | .struct_type => unreachable, // use getStructType() instead | |
| 8088 | .tuple_type => unreachable, // use getTupleType() instead | |
| 8089 | .union_type => unreachable, // use getUnionType() instead | |
| 8090 | .opaque_type => unreachable, // use getOpaqueType() instead | |
| 7503 | .struct_type => unreachable, // instead use: getDeclaredStructType, getReifiedStructType | |
| 7504 | .union_type => unreachable, // instead use: getDeclaredUnionType, getReifiedUnionType | |
| 7505 | .enum_type => unreachable, // instead use: getDeclaredEnumType, getReifiedEnumType, getGeneratedEnumTagType | |
| 7506 | .opaque_type => unreachable, // instead use: getDeclaredOpaqueType | |
| 8091 | 7507 | |
| 8092 | .enum_type => unreachable, // use getEnumType() instead | |
| 7508 | .tuple_type => unreachable, // use getTupleType() instead | |
| 8093 | 7509 | .func_type => unreachable, // use getFuncType() instead |
| 8094 | 7510 | .@"extern" => unreachable, // use getExtern() instead |
| 8095 | 7511 | .func => unreachable, // use getFuncInstance() or getFuncDecl() instead |
| ... | ... | @@ -8247,25 +7663,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8247 | 7663 | }); |
| 8248 | 7664 | }, |
| 8249 | 7665 | |
| 8250 | .int => |int| b: { | |
| 8251 | assert(ip.isIntegerType(int.ty)); | |
| 8252 | switch (int.storage) { | |
| 8253 | .u64, .i64, .big_int => {}, | |
| 8254 | .lazy_align, .lazy_size => |lazy_ty| { | |
| 8255 | items.appendAssumeCapacity(.{ | |
| 8256 | .tag = switch (int.storage) { | |
| 8257 | else => unreachable, | |
| 8258 | .lazy_align => .int_lazy_align, | |
| 8259 | .lazy_size => .int_lazy_size, | |
| 8260 | }, | |
| 8261 | .data = try addExtra(extra, IntLazy{ | |
| 8262 | .ty = int.ty, | |
| 8263 | .lazy_ty = lazy_ty, | |
| 8264 | }), | |
| 8265 | }); | |
| 8266 | return gop.put(); | |
| 8267 | }, | |
| 8268 | } | |
| 7666 | .int => |int| b: { | |
| 7667 | assert(ip.isIntegerType(int.ty)); | |
| 8269 | 7668 | switch (int.ty) { |
| 8270 | 7669 | .u8_type => switch (int.storage) { |
| 8271 | 7670 | .big_int => |big_int| { |
| ... | ... | @@ -8282,7 +7681,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8282 | 7681 | }); |
| 8283 | 7682 | break :b; |
| 8284 | 7683 | }, |
| 8285 | .lazy_align, .lazy_size => unreachable, | |
| 8286 | 7684 | }, |
| 8287 | 7685 | .u16_type => switch (int.storage) { |
| 8288 | 7686 | .big_int => |big_int| { |
| ... | ... | @@ -8299,7 +7697,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8299 | 7697 | }); |
| 8300 | 7698 | break :b; |
| 8301 | 7699 | }, |
| 8302 | .lazy_align, .lazy_size => unreachable, | |
| 8303 | 7700 | }, |
| 8304 | 7701 | .u32_type => switch (int.storage) { |
| 8305 | 7702 | .big_int => |big_int| { |
| ... | ... | @@ -8316,7 +7713,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8316 | 7713 | }); |
| 8317 | 7714 | break :b; |
| 8318 | 7715 | }, |
| 8319 | .lazy_align, .lazy_size => unreachable, | |
| 8320 | 7716 | }, |
| 8321 | 7717 | .i32_type => switch (int.storage) { |
| 8322 | 7718 | .big_int => |big_int| { |
| ... | ... | @@ -8334,7 +7730,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8334 | 7730 | }); |
| 8335 | 7731 | break :b; |
| 8336 | 7732 | }, |
| 8337 | .lazy_align, .lazy_size => unreachable, | |
| 8338 | 7733 | }, |
| 8339 | 7734 | .usize_type => switch (int.storage) { |
| 8340 | 7735 | .big_int => |big_int| { |
| ... | ... | @@ -8355,7 +7750,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8355 | 7750 | break :b; |
| 8356 | 7751 | } |
| 8357 | 7752 | }, |
| 8358 | .lazy_align, .lazy_size => unreachable, | |
| 8359 | 7753 | }, |
| 8360 | 7754 | .comptime_int_type => switch (int.storage) { |
| 8361 | 7755 | .big_int => |big_int| { |
| ... | ... | @@ -8390,7 +7784,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8390 | 7784 | break :b; |
| 8391 | 7785 | } |
| 8392 | 7786 | }, |
| 8393 | .lazy_align, .lazy_size => unreachable, | |
| 8394 | 7787 | }, |
| 8395 | 7788 | else => {}, |
| 8396 | 7789 | } |
| ... | ... | @@ -8427,7 +7820,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8427 | 7820 | const tag: Tag = if (big_int.positive) .int_positive else .int_negative; |
| 8428 | 7821 | try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs); |
| 8429 | 7822 | }, |
| 8430 | .lazy_align, .lazy_size => unreachable, | |
| 8431 | 7823 | } |
| 8432 | 7824 | }, |
| 8433 | 7825 | |
| ... | ... | @@ -8468,7 +7860,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8468 | 7860 | assert(ip.isEnumType(enum_tag.ty)); |
| 8469 | 7861 | switch (ip.indexToKey(enum_tag.ty)) { |
| 8470 | 7862 | .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))), |
| 8471 | .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).tag_ty), | |
| 7863 | .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).int_tag_type), | |
| 8472 | 7864 | else => unreachable, |
| 8473 | 7865 | } |
| 8474 | 7866 | items.appendAssumeCapacity(.{ |
| ... | ... | @@ -8477,11 +7869,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8477 | 7869 | }); |
| 8478 | 7870 | }, |
| 8479 | 7871 | |
| 8480 | .empty_enum_value => |enum_or_union_ty| items.appendAssumeCapacity(.{ | |
| 8481 | .tag = .only_possible_value, | |
| 8482 | .data = @intFromEnum(enum_or_union_ty), | |
| 8483 | }), | |
| 8484 | ||
| 8485 | 7872 | .float => |float| { |
| 8486 | 7873 | switch (float.ty) { |
| 8487 | 7874 | .f16_type => items.appendAssumeCapacity(.{ |
| ... | ... | @@ -8525,15 +7912,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8525 | 7912 | .aggregate => |aggregate| { |
| 8526 | 7913 | const ty_key = ip.indexToKey(aggregate.ty); |
| 8527 | 7914 | const len = ip.aggregateTypeLen(aggregate.ty); |
| 8528 | const child = switch (ty_key) { | |
| 8529 | .array_type => |array_type| array_type.child, | |
| 8530 | .vector_type => |vector_type| vector_type.child, | |
| 8531 | .tuple_type, .struct_type => .none, | |
| 8532 | else => unreachable, | |
| 8533 | }; | |
| 8534 | const sentinel = switch (ty_key) { | |
| 8535 | .array_type => |array_type| array_type.sentinel, | |
| 8536 | .vector_type, .tuple_type, .struct_type => .none, | |
| 7915 | const child: Index, const sentinel: Index = switch (ty_key) { | |
| 7916 | .array_type => |array_type| .{ array_type.child, array_type.sentinel }, | |
| 7917 | .vector_type => |vector_type| .{ vector_type.child, .none }, | |
| 7918 | .tuple_type => .{ .none, .none }, | |
| 7919 | .struct_type => child: { | |
| 7920 | assert(ip.loadStructType(aggregate.ty).layout != .@"packed"); | |
| 7921 | break :child .{ .none, .none }; | |
| 7922 | }, | |
| 8537 | 7923 | else => unreachable, |
| 8538 | 7924 | }; |
| 8539 | 7925 | const len_including_sentinel = len + @intFromBool(sentinel != .none); |
| ... | ... | @@ -8715,224 +8101,929 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 8715 | 8101 | extra.appendSliceAssumeCapacity(.{@ptrCast(aggregate.storage.elems)}); |
| 8716 | 8102 | if (sentinel != .none) extra.appendAssumeCapacity(.{@intFromEnum(sentinel)}); |
| 8717 | 8103 | }, |
| 8104 | .bitpack => |bitpack| { | |
| 8105 | switch (ip.zigTypeTag(bitpack.ty)) { | |
| 8106 | .@"struct" => assert(ip.typeOf(bitpack.backing_int_val) == ip.loadStructType(bitpack.ty).packed_backing_int_type), | |
| 8107 | .@"union" => assert(ip.typeOf(bitpack.backing_int_val) == ip.loadUnionType(bitpack.ty).packed_backing_int_type), | |
| 8108 | else => unreachable, | |
| 8109 | } | |
| 8110 | assert(!ip.isUndef(bitpack.backing_int_val)); | |
| 8111 | items.appendAssumeCapacity(.{ | |
| 8112 | .tag = .bitpack, | |
| 8113 | .data = try addExtra(extra, bitpack), | |
| 8114 | }); | |
| 8115 | }, | |
| 8718 | 8116 | |
| 8719 | 8117 | .memoized_call => |memoized_call| { |
| 8720 | 8118 | for (memoized_call.arg_values) |arg| assert(arg != .none); |
| 8721 | 8119 | try extra.ensureUnusedCapacity(@typeInfo(MemoizedCall).@"struct".fields.len + |
| 8722 | 8120 | memoized_call.arg_values.len); |
| 8723 | 8121 | items.appendAssumeCapacity(.{ |
| 8724 | .tag = .memoized_call, | |
| 8725 | .data = addExtraAssumeCapacity(extra, MemoizedCall{ | |
| 8726 | .func = memoized_call.func, | |
| 8727 | .args_len = @intCast(memoized_call.arg_values.len), | |
| 8728 | .result = memoized_call.result, | |
| 8729 | .branch_count = memoized_call.branch_count, | |
| 8730 | }), | |
| 8122 | .tag = .memoized_call, | |
| 8123 | .data = addExtraAssumeCapacity(extra, MemoizedCall{ | |
| 8124 | .func = memoized_call.func, | |
| 8125 | .args_len = @intCast(memoized_call.arg_values.len), | |
| 8126 | .result = memoized_call.result, | |
| 8127 | .branch_count = memoized_call.branch_count, | |
| 8128 | }), | |
| 8129 | }); | |
| 8130 | extra.appendSliceAssumeCapacity(.{@ptrCast(memoized_call.arg_values)}); | |
| 8131 | }, | |
| 8132 | } | |
| 8133 | return gop.put(); | |
| 8134 | } | |
| 8135 | ||
| 8136 | pub fn getDeclaredStructType( | |
| 8137 | ip: *InternPool, | |
| 8138 | gpa: Allocator, | |
| 8139 | io: Io, | |
| 8140 | tid: Zcu.PerThread.Id, | |
| 8141 | ini: struct { | |
| 8142 | zir_index: TrackedInst.Index, | |
| 8143 | captures: []const CaptureValue, | |
| 8144 | ||
| 8145 | // If the value of any of the following fields would change on an incremental update, then logic | |
| 8146 | // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) | |
| 8147 | // and refuse to map the type declaration. This causes `zir_index` to change so that a new type | |
| 8148 | // will be interned at a fresh index. | |
| 8149 | // | |
| 8150 | // In the future, it would be good to remove all of those fields from `ini`, and in fact just | |
| 8151 | // have a single function `getDeclaredContainer` which is suitable for all container types. | |
| 8152 | // However, this requires some major changes to how container types are represented in the | |
| 8153 | // InternPool, so that it is possible for their backing storage to be "reallocated" as needed | |
| 8154 | // during type resolution. | |
| 8155 | fields_len: u32, | |
| 8156 | layout: std.builtin.Type.ContainerLayout, | |
| 8157 | any_comptime_fields: bool, | |
| 8158 | any_field_defaults: bool, | |
| 8159 | any_field_aligns: bool, | |
| 8160 | packed_backing_mode: BackingTypeMode, | |
| 8161 | }, | |
| 8162 | ) Allocator.Error!WipContainerType.Result { | |
| 8163 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .struct_type = .{ .declared = .{ | |
| 8164 | .zir_index = ini.zir_index, | |
| 8165 | .captures = .{ .external = ini.captures }, | |
| 8166 | } } }); | |
| 8167 | defer gop.deinit(); | |
| 8168 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8169 | ||
| 8170 | const local = ip.getLocal(tid); | |
| 8171 | const items = local.getMutableItems(gpa, io); | |
| 8172 | const extra = local.getMutableExtra(gpa, io); | |
| 8173 | try items.ensureUnusedCapacity(1); | |
| 8174 | ||
| 8175 | const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 8176 | errdefer local.mutate.maps.len -= 1; | |
| 8177 | ||
| 8178 | const is_extern = switch (ini.layout) { | |
| 8179 | .auto => false, | |
| 8180 | .@"extern" => true, | |
| 8181 | .@"packed" => { | |
| 8182 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + | |
| 8183 | ini.captures.len + // capture | |
| 8184 | ini.fields_len + // field_name | |
| 8185 | ini.fields_len + // field_type | |
| 8186 | (if (ini.any_field_defaults) ini.fields_len else 0)); // field_default | |
| 8187 | ||
| 8188 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ | |
| 8189 | .zir_index = ini.zir_index, | |
| 8190 | .bits = .{ | |
| 8191 | .captures_len = @enumFromInt(ini.captures.len), | |
| 8192 | .want_layout = false, | |
| 8193 | }, | |
| 8194 | .name = undefined, // set by `finish` | |
| 8195 | .name_nav = undefined, // set by `finish` | |
| 8196 | .namespace = undefined, // set by `finish` | |
| 8197 | .backing_int_type = .none, | |
| 8198 | .fields_len = ini.fields_len, | |
| 8199 | .field_name_map = field_name_map, | |
| 8200 | }); | |
| 8201 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture | |
| 8202 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8203 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8204 | if (ini.any_field_defaults) { | |
| 8205 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default | |
| 8206 | } | |
| 8207 | items.appendAssumeCapacity(.{ | |
| 8208 | .tag = switch (ini.packed_backing_mode) { | |
| 8209 | .auto => if (ini.any_field_defaults) .type_struct_packed_auto_defaults else .type_struct_packed_auto, | |
| 8210 | .explicit => if (ini.any_field_defaults) .type_struct_packed_explicit_defaults else .type_struct_packed_explicit, | |
| 8211 | }, | |
| 8212 | .data = extra_index, | |
| 8213 | }); | |
| 8214 | return .{ .wip = .{ | |
| 8215 | .index = gop.put(), | |
| 8216 | .tid = tid, | |
| 8217 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, | |
| 8218 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, | |
| 8219 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, | |
| 8220 | .field_names = undefined, | |
| 8221 | .field_types = undefined, | |
| 8222 | .field_values = undefined, | |
| 8223 | .field_aligns = undefined, | |
| 8224 | .field_is_comptime_bits = undefined, | |
| 8225 | } }; | |
| 8226 | }, | |
| 8227 | }; | |
| 8228 | ||
| 8229 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len + | |
| 8230 | 1 + // captures_len | |
| 8231 | ini.captures.len + // capture | |
| 8232 | ini.fields_len + // field_name | |
| 8233 | ini.fields_len + // field_type | |
| 8234 | (if (ini.any_field_defaults) ini.fields_len else 0) + // field_default | |
| 8235 | (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0) + // field_align | |
| 8236 | (if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0) + // field_is_comptime_bits | |
| 8237 | (if (!is_extern) ini.fields_len else 0) + // field_runtime_order | |
| 8238 | ini.fields_len); // field_offset | |
| 8239 | ||
| 8240 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ | |
| 8241 | .zir_index = ini.zir_index, | |
| 8242 | .name = undefined, // set by `finish` | |
| 8243 | .name_nav = undefined, // set by `finish` | |
| 8244 | .namespace = undefined, // set by `finish` | |
| 8245 | .fields_len = ini.fields_len, | |
| 8246 | .field_name_map = field_name_map, | |
| 8247 | .size = 0, | |
| 8248 | .flags = .{ | |
| 8249 | .any_captures = if (ini.captures.len != 0) .true else .false, | |
| 8250 | .layout = if (is_extern) .@"extern" else .auto, | |
| 8251 | .any_comptime_fields = ini.any_comptime_fields, | |
| 8252 | .any_field_defaults = ini.any_field_defaults, | |
| 8253 | .any_field_aligns = ini.any_field_aligns, | |
| 8254 | .class = .no_possible_value, | |
| 8255 | .alignment = .none, | |
| 8256 | .want_layout = false, | |
| 8257 | }, | |
| 8258 | }); | |
| 8259 | if (ini.captures.len != 0) { | |
| 8260 | extra.appendAssumeCapacity(.{@intCast(ini.captures.len)}); // captures_len | |
| 8261 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture | |
| 8262 | } | |
| 8263 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8264 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8265 | if (ini.any_field_defaults) { | |
| 8266 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default | |
| 8267 | } | |
| 8268 | if (ini.any_field_aligns) { | |
| 8269 | extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align | |
| 8270 | } | |
| 8271 | if (ini.any_comptime_fields) { | |
| 8272 | extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 31) / 32); // field_is_comptime_bits | |
| 8273 | } | |
| 8274 | if (!is_extern) { | |
| 8275 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); // field_runtime_order | |
| 8276 | } | |
| 8277 | extra.appendNTimesAssumeCapacity(.{0}, ini.fields_len); // field_offset | |
| 8278 | items.appendAssumeCapacity(.{ | |
| 8279 | .tag = .type_struct, | |
| 8280 | .data = extra_index, | |
| 8281 | }); | |
| 8282 | return .{ .wip = .{ | |
| 8283 | .index = gop.put(), | |
| 8284 | .tid = tid, | |
| 8285 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, | |
| 8286 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, | |
| 8287 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, | |
| 8288 | .field_names = undefined, | |
| 8289 | .field_types = undefined, | |
| 8290 | .field_values = undefined, | |
| 8291 | .field_aligns = undefined, | |
| 8292 | .field_is_comptime_bits = undefined, | |
| 8293 | } }; | |
| 8294 | } | |
| 8295 | ||
| 8296 | pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { | |
| 8297 | zir_index: TrackedInst.Index, | |
| 8298 | type_hash: u64, | |
| 8299 | fields_len: u32, | |
| 8300 | layout: std.builtin.Type.ContainerLayout, | |
| 8301 | any_comptime_fields: bool, | |
| 8302 | any_field_defaults: bool, | |
| 8303 | any_field_aligns: bool, | |
| 8304 | /// Explicitly specified backing int type. `.none` if not packed or if backing type is inferred. | |
| 8305 | packed_backing_int_type: Index, | |
| 8306 | }) Allocator.Error!WipContainerType.Result { | |
| 8307 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .struct_type = .{ .reified = .{ | |
| 8308 | .zir_index = ini.zir_index, | |
| 8309 | .type_hash = ini.type_hash, | |
| 8310 | } } }); | |
| 8311 | defer gop.deinit(); | |
| 8312 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8313 | ||
| 8314 | const local = ip.getLocal(tid); | |
| 8315 | const items = local.getMutableItems(gpa, io); | |
| 8316 | const extra = local.getMutableExtra(gpa, io); | |
| 8317 | try items.ensureUnusedCapacity(1); | |
| 8318 | ||
| 8319 | const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 8320 | errdefer local.mutate.maps.len -= 1; | |
| 8321 | ||
| 8322 | const is_extern = switch (ini.layout) { | |
| 8323 | .auto => false, | |
| 8324 | .@"extern" => true, | |
| 8325 | .@"packed" => { | |
| 8326 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + | |
| 8327 | 2 + // type_hash | |
| 8328 | ini.fields_len + // field_name | |
| 8329 | ini.fields_len + // field_type | |
| 8330 | (if (ini.any_field_defaults) ini.fields_len else 0)); // field_default | |
| 8331 | ||
| 8332 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ | |
| 8333 | .zir_index = ini.zir_index, | |
| 8334 | .bits = .{ | |
| 8335 | .captures_len = .reified, | |
| 8336 | .want_layout = false, | |
| 8337 | }, | |
| 8338 | .name = undefined, // set by `finish` | |
| 8339 | .name_nav = undefined, // set by `finish` | |
| 8340 | .namespace = undefined, // set by `finish` | |
| 8341 | .backing_int_type = ini.packed_backing_int_type, | |
| 8342 | .fields_len = ini.fields_len, | |
| 8343 | .field_name_map = field_name_map, | |
| 8344 | }); | |
| 8345 | _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash | |
| 8346 | const field_names_start = extra.mutate.len; | |
| 8347 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8348 | const field_types_start = extra.mutate.len; | |
| 8349 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8350 | const field_defaults_start = extra.mutate.len; | |
| 8351 | if (ini.any_field_defaults) { | |
| 8352 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default | |
| 8353 | } | |
| 8354 | items.appendAssumeCapacity(.{ | |
| 8355 | .tag = switch (ini.packed_backing_int_type) { | |
| 8356 | .none => if (ini.any_field_defaults) .type_struct_packed_auto_defaults else .type_struct_packed_auto, | |
| 8357 | else => if (ini.any_field_defaults) .type_struct_packed_explicit_defaults else .type_struct_packed_explicit, | |
| 8358 | }, | |
| 8359 | .data = extra_index, | |
| 8360 | }); | |
| 8361 | return .{ .wip = .{ | |
| 8362 | .index = gop.put(), | |
| 8363 | .tid = tid, | |
| 8364 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, | |
| 8365 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, | |
| 8366 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, | |
| 8367 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | |
| 8368 | .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, | |
| 8369 | .field_values = if (ini.any_field_defaults) | |
| 8370 | .{ .tid = tid, .start = field_defaults_start, .len = ini.fields_len } | |
| 8371 | else | |
| 8372 | undefined, | |
| 8373 | .field_aligns = undefined, | |
| 8374 | .field_is_comptime_bits = undefined, | |
| 8375 | } }; | |
| 8376 | }, | |
| 8377 | }; | |
| 8378 | ||
| 8379 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len + | |
| 8380 | 2 + // type_hash | |
| 8381 | ini.fields_len + // field_name | |
| 8382 | ini.fields_len + // field_type | |
| 8383 | (if (ini.any_field_defaults) ini.fields_len else 0) + // field_default | |
| 8384 | (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0) + // field_align | |
| 8385 | (if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0) + // field_is_comptime_bits | |
| 8386 | (if (!is_extern) ini.fields_len else 0) + // field_runtime_order | |
| 8387 | ini.fields_len); // field_offset | |
| 8388 | ||
| 8389 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ | |
| 8390 | .zir_index = ini.zir_index, | |
| 8391 | .name = undefined, // set by `finish` | |
| 8392 | .name_nav = undefined, // set by `finish` | |
| 8393 | .namespace = undefined, // set by `finish` | |
| 8394 | .fields_len = ini.fields_len, | |
| 8395 | .field_name_map = field_name_map, | |
| 8396 | .size = 0, | |
| 8397 | .flags = .{ | |
| 8398 | .any_captures = .reified, | |
| 8399 | .layout = if (is_extern) .@"extern" else .auto, | |
| 8400 | .any_comptime_fields = ini.any_comptime_fields, | |
| 8401 | .any_field_defaults = ini.any_field_defaults, | |
| 8402 | .any_field_aligns = ini.any_field_aligns, | |
| 8403 | .class = .no_possible_value, | |
| 8404 | .alignment = .none, | |
| 8405 | .want_layout = false, | |
| 8406 | }, | |
| 8407 | }); | |
| 8408 | _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash | |
| 8409 | const field_names_start = extra.mutate.len; | |
| 8410 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8411 | const field_types_start = extra.mutate.len; | |
| 8412 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8413 | const field_defaults_start = extra.mutate.len; | |
| 8414 | if (ini.any_field_defaults) { | |
| 8415 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default | |
| 8416 | } | |
| 8417 | const field_aligns_start = extra.mutate.len; | |
| 8418 | if (ini.any_field_aligns) { | |
| 8419 | extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align | |
| 8420 | } | |
| 8421 | const field_is_comptime_bits_start = extra.mutate.len; | |
| 8422 | if (ini.any_comptime_fields) { | |
| 8423 | extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 31) / 32); // field_is_comptime_bits | |
| 8424 | } | |
| 8425 | if (!is_extern) { | |
| 8426 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); // field_runtime_order | |
| 8427 | } | |
| 8428 | extra.appendNTimesAssumeCapacity(.{0}, ini.fields_len); // field_offset | |
| 8429 | items.appendAssumeCapacity(.{ | |
| 8430 | .tag = .type_struct, | |
| 8431 | .data = extra_index, | |
| 8432 | }); | |
| 8433 | return .{ .wip = .{ | |
| 8434 | .index = gop.put(), | |
| 8435 | .tid = tid, | |
| 8436 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, | |
| 8437 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, | |
| 8438 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, | |
| 8439 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | |
| 8440 | .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, | |
| 8441 | .field_values = if (ini.any_field_defaults) | |
| 8442 | .{ .tid = tid, .start = field_defaults_start, .len = ini.fields_len } | |
| 8443 | else | |
| 8444 | undefined, | |
| 8445 | .field_aligns = if (ini.any_field_aligns) | |
| 8446 | .{ .tid = tid, .start = field_aligns_start, .len = ini.fields_len } | |
| 8447 | else | |
| 8448 | undefined, | |
| 8449 | .field_is_comptime_bits = if (ini.any_comptime_fields) | |
| 8450 | .{ .tid = tid, .start = field_is_comptime_bits_start, .len = (ini.fields_len + 31) / 32 } | |
| 8451 | else | |
| 8452 | undefined, | |
| 8453 | } }; | |
| 8454 | } | |
| 8455 | ||
| 8456 | pub fn getDeclaredUnionType( | |
| 8457 | ip: *InternPool, | |
| 8458 | gpa: Allocator, | |
| 8459 | io: Io, | |
| 8460 | tid: Zcu.PerThread.Id, | |
| 8461 | ini: struct { | |
| 8462 | zir_index: TrackedInst.Index, | |
| 8463 | captures: []const CaptureValue, | |
| 8464 | ||
| 8465 | // If the value of any of the following fields would change on an incremental update, then logic | |
| 8466 | // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) | |
| 8467 | // and refuse to map the type declaration. This causes `zir_index` to change so that a new type | |
| 8468 | // will be interned at a fresh index. | |
| 8469 | // | |
| 8470 | // In the future, it would be good to remove all of those fields from `ini`, and in fact just | |
| 8471 | // have a single function `getDeclaredContainer` which is suitable for all container types. | |
| 8472 | // However, this requires some major changes to how container types are represented in the | |
| 8473 | // InternPool, so that it is possible for their backing storage to be "reallocated" as needed | |
| 8474 | // during type resolution. | |
| 8475 | fields_len: u32, | |
| 8476 | layout: std.builtin.Type.ContainerLayout, | |
| 8477 | any_field_aligns: bool, | |
| 8478 | tag_usage: LoadedUnionType.TagUsage, | |
| 8479 | enum_tag_mode: BackingTypeMode, | |
| 8480 | packed_backing_mode: BackingTypeMode, | |
| 8481 | }, | |
| 8482 | ) Allocator.Error!WipContainerType.Result { | |
| 8483 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .union_type = .{ .declared = .{ | |
| 8484 | .zir_index = ini.zir_index, | |
| 8485 | .captures = .{ .external = ini.captures }, | |
| 8486 | } } }); | |
| 8487 | defer gop.deinit(); | |
| 8488 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8489 | ||
| 8490 | const local = ip.getLocal(tid); | |
| 8491 | const items = local.getMutableItems(gpa, io); | |
| 8492 | const extra = local.getMutableExtra(gpa, io); | |
| 8493 | try items.ensureUnusedCapacity(1); | |
| 8494 | ||
| 8495 | const is_extern = switch (ini.layout) { | |
| 8496 | .auto => false, | |
| 8497 | .@"extern" => true, | |
| 8498 | .@"packed" => { | |
| 8499 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnionPacked).@"struct".fields.len + | |
| 8500 | ini.captures.len + // capture | |
| 8501 | ini.fields_len); // field_type | |
| 8502 | ||
| 8503 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ | |
| 8504 | .zir_index = ini.zir_index, | |
| 8505 | .bits = .{ | |
| 8506 | .captures_len = @enumFromInt(ini.captures.len), | |
| 8507 | .want_layout = false, | |
| 8508 | }, | |
| 8509 | .name = undefined, // set by `finish` | |
| 8510 | .name_nav = undefined, // set by `finish` | |
| 8511 | .namespace = undefined, // set by `finish` | |
| 8512 | .backing_int_type = .none, | |
| 8513 | .enum_tag_type = .none, | |
| 8514 | .fields_len = ini.fields_len, | |
| 8515 | }); | |
| 8516 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture | |
| 8517 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8518 | items.appendAssumeCapacity(.{ | |
| 8519 | .tag = switch (ini.packed_backing_mode) { | |
| 8520 | .auto => .type_union_packed_auto, | |
| 8521 | .explicit => .type_union_packed_explicit, | |
| 8522 | }, | |
| 8523 | .data = extra_index, | |
| 8524 | }); | |
| 8525 | return .{ .wip = .{ | |
| 8526 | .index = gop.put(), | |
| 8527 | .tid = tid, | |
| 8528 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, | |
| 8529 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, | |
| 8530 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, | |
| 8531 | .field_names = undefined, | |
| 8532 | .field_types = undefined, | |
| 8533 | .field_values = undefined, | |
| 8534 | .field_aligns = undefined, | |
| 8535 | .field_is_comptime_bits = undefined, | |
| 8536 | } }; | |
| 8537 | }, | |
| 8538 | }; | |
| 8539 | ||
| 8540 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + | |
| 8541 | 1 + // captures_len | |
| 8542 | ini.captures.len + // capture | |
| 8543 | ini.fields_len + // field_type | |
| 8544 | (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0)); // field_align | |
| 8545 | ||
| 8546 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ | |
| 8547 | .zir_index = ini.zir_index, | |
| 8548 | .name = undefined, // set by `finish` | |
| 8549 | .name_nav = undefined, // set by `finish` | |
| 8550 | .namespace = undefined, // set by `finish` | |
| 8551 | .enum_tag_type = .none, | |
| 8552 | .fields_len = ini.fields_len, | |
| 8553 | .size = 0, | |
| 8554 | .padding = 0, | |
| 8555 | .flags = .{ | |
| 8556 | .any_captures = if (ini.captures.len != 0) .true else .false, | |
| 8557 | .enum_tag_mode = ini.enum_tag_mode, | |
| 8558 | .layout = if (is_extern) .@"extern" else .auto, | |
| 8559 | .any_field_aligns = ini.any_field_aligns, | |
| 8560 | .tag_usage = ini.tag_usage, | |
| 8561 | .class = .no_possible_value, | |
| 8562 | .has_runtime_tag = false, | |
| 8563 | .alignment = .none, | |
| 8564 | .want_layout = false, | |
| 8565 | }, | |
| 8566 | }); | |
| 8567 | if (ini.captures.len > 0) { | |
| 8568 | extra.appendAssumeCapacity(.{@intCast(ini.captures.len)}); // captures_len | |
| 8569 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture | |
| 8570 | } | |
| 8571 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8572 | if (ini.any_field_aligns) { | |
| 8573 | extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align | |
| 8574 | } | |
| 8575 | items.appendAssumeCapacity(.{ | |
| 8576 | .tag = .type_union, | |
| 8577 | .data = extra_index, | |
| 8578 | }); | |
| 8579 | return .{ .wip = .{ | |
| 8580 | .index = gop.put(), | |
| 8581 | .tid = tid, | |
| 8582 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, | |
| 8583 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, | |
| 8584 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, | |
| 8585 | .field_names = undefined, | |
| 8586 | .field_types = undefined, | |
| 8587 | .field_values = undefined, | |
| 8588 | .field_aligns = undefined, | |
| 8589 | .field_is_comptime_bits = undefined, | |
| 8590 | } }; | |
| 8591 | } | |
| 8592 | ||
| 8593 | pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { | |
| 8594 | zir_index: TrackedInst.Index, | |
| 8595 | type_hash: u64, | |
| 8596 | fields_len: u32, | |
| 8597 | layout: std.builtin.Type.ContainerLayout, | |
| 8598 | any_field_aligns: bool, | |
| 8599 | tag_usage: LoadedUnionType.TagUsage, | |
| 8600 | /// Explicitly specified enum tag type. `.none` if `tag_usage != .tagged`. | |
| 8601 | enum_tag_type: Index, | |
| 8602 | /// Explicitly specified backing int type. `.none` if not packed or if backing type is inferred. | |
| 8603 | packed_backing_int_type: Index, | |
| 8604 | }) Allocator.Error!WipContainerType.Result { | |
| 8605 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .union_type = .{ .reified = .{ | |
| 8606 | .zir_index = ini.zir_index, | |
| 8607 | .type_hash = ini.type_hash, | |
| 8608 | } } }); | |
| 8609 | defer gop.deinit(); | |
| 8610 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8611 | ||
| 8612 | const local = ip.getLocal(tid); | |
| 8613 | const items = local.getMutableItems(gpa, io); | |
| 8614 | const extra = local.getMutableExtra(gpa, io); | |
| 8615 | try items.ensureUnusedCapacity(1); | |
| 8616 | ||
| 8617 | const is_extern = switch (ini.layout) { | |
| 8618 | .auto => false, | |
| 8619 | .@"extern" => true, | |
| 8620 | .@"packed" => { | |
| 8621 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnionPacked).@"struct".fields.len + | |
| 8622 | 2 + // type_hash | |
| 8623 | ini.fields_len + // reified_field_name | |
| 8624 | ini.fields_len); // field_type | |
| 8625 | ||
| 8626 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ | |
| 8627 | .zir_index = ini.zir_index, | |
| 8628 | .bits = .{ | |
| 8629 | .captures_len = .reified, | |
| 8630 | .want_layout = false, | |
| 8631 | }, | |
| 8632 | .name = undefined, // set by `finish` | |
| 8633 | .name_nav = undefined, // set by `finish` | |
| 8634 | .namespace = undefined, // set by `finish` | |
| 8635 | .backing_int_type = ini.packed_backing_int_type, | |
| 8636 | .enum_tag_type = .none, | |
| 8637 | .fields_len = ini.fields_len, | |
| 8638 | }); | |
| 8639 | _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash | |
| 8640 | const field_names_start = extra.mutate.len; | |
| 8641 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // reified_field_name | |
| 8642 | const field_types_start = extra.mutate.len; | |
| 8643 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8644 | items.appendAssumeCapacity(.{ | |
| 8645 | .tag = switch (ini.packed_backing_int_type) { | |
| 8646 | .none => .type_union_packed_auto, | |
| 8647 | else => .type_union_packed_explicit, | |
| 8648 | }, | |
| 8649 | .data = extra_index, | |
| 8731 | 8650 | }); |
| 8732 | extra.appendSliceAssumeCapacity(.{@ptrCast(memoized_call.arg_values)}); | |
| 8651 | return .{ .wip = .{ | |
| 8652 | .index = gop.put(), | |
| 8653 | .tid = tid, | |
| 8654 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, | |
| 8655 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, | |
| 8656 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, | |
| 8657 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | |
| 8658 | .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, | |
| 8659 | .field_values = undefined, | |
| 8660 | .field_aligns = undefined, | |
| 8661 | .field_is_comptime_bits = undefined, | |
| 8662 | } }; | |
| 8663 | }, | |
| 8664 | }; | |
| 8665 | ||
| 8666 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + | |
| 8667 | 2 + // type_hash | |
| 8668 | ini.fields_len + // reified_field_name | |
| 8669 | ini.fields_len + // field_type | |
| 8670 | (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0)); // field_align | |
| 8671 | ||
| 8672 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ | |
| 8673 | .zir_index = ini.zir_index, | |
| 8674 | .name = undefined, // set by `finish` | |
| 8675 | .name_nav = undefined, // set by `finish` | |
| 8676 | .namespace = undefined, // set by `finish` | |
| 8677 | .enum_tag_type = ini.enum_tag_type, | |
| 8678 | .fields_len = ini.fields_len, | |
| 8679 | .size = 0, | |
| 8680 | .padding = 0, | |
| 8681 | .flags = .{ | |
| 8682 | .any_captures = .reified, | |
| 8683 | .enum_tag_mode = if (ini.enum_tag_type == .none) .auto else .explicit, | |
| 8684 | .layout = if (is_extern) .@"extern" else .auto, | |
| 8685 | .any_field_aligns = ini.any_field_aligns, | |
| 8686 | .tag_usage = ini.tag_usage, | |
| 8687 | .class = .no_possible_value, | |
| 8688 | .has_runtime_tag = false, | |
| 8689 | .alignment = .none, | |
| 8690 | .want_layout = false, | |
| 8733 | 8691 | }, |
| 8692 | }); | |
| 8693 | _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); | |
| 8694 | const field_names_start = extra.mutate.len; | |
| 8695 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // reified_field_name | |
| 8696 | const field_types_start = extra.mutate.len; | |
| 8697 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type | |
| 8698 | const field_aligns_start = extra.mutate.len; | |
| 8699 | if (ini.any_field_aligns) { | |
| 8700 | extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align | |
| 8734 | 8701 | } |
| 8735 | return gop.put(); | |
| 8702 | items.appendAssumeCapacity(.{ | |
| 8703 | .tag = .type_union, | |
| 8704 | .data = extra_index, | |
| 8705 | }); | |
| 8706 | return .{ .wip = .{ | |
| 8707 | .index = gop.put(), | |
| 8708 | .tid = tid, | |
| 8709 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, | |
| 8710 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, | |
| 8711 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, | |
| 8712 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | |
| 8713 | .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, | |
| 8714 | .field_values = undefined, | |
| 8715 | .field_aligns = if (ini.any_field_aligns) | |
| 8716 | .{ .tid = tid, .start = field_aligns_start, .len = ini.fields_len } | |
| 8717 | else | |
| 8718 | undefined, | |
| 8719 | .field_is_comptime_bits = undefined, | |
| 8720 | } }; | |
| 8736 | 8721 | } |
| 8737 | 8722 | |
| 8738 | pub fn getUnion( | |
| 8723 | pub fn getDeclaredEnumType( | |
| 8739 | 8724 | ip: *InternPool, |
| 8740 | 8725 | gpa: Allocator, |
| 8741 | 8726 | io: Io, |
| 8742 | 8727 | tid: Zcu.PerThread.Id, |
| 8743 | un: Key.Union, | |
| 8744 | ) Allocator.Error!Index { | |
| 8745 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); | |
| 8728 | ini: struct { | |
| 8729 | zir_index: TrackedInst.Index, | |
| 8730 | captures: []const CaptureValue, | |
| 8731 | ||
| 8732 | // If the value of any of the following fields would change on an incremental update, then logic | |
| 8733 | // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) | |
| 8734 | // and refuse to map the type declaration. This causes `zir_index` to change so that a new type | |
| 8735 | // will be interned at a fresh index. | |
| 8736 | // | |
| 8737 | // In the future, it would be good to remove all of those fields from `ini`, and in fact just | |
| 8738 | // have a single function `getDeclaredContainer` which is suitable for all container types. | |
| 8739 | // However, this requires some major changes to how container types are represented in the | |
| 8740 | // InternPool, so that it is possible for their backing storage to be "reallocated" as needed | |
| 8741 | // during type resolution. | |
| 8742 | fields_len: u32, | |
| 8743 | nonexhaustive: bool, | |
| 8744 | /// For `enum(T)` this is `.explicit`. Otherwise this is `.none`. | |
| 8745 | int_tag_mode: BackingTypeMode, | |
| 8746 | }, | |
| 8747 | ) Allocator.Error!WipContainerType.Result { | |
| 8748 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .declared = .{ | |
| 8749 | .zir_index = ini.zir_index, | |
| 8750 | .captures = .{ .external = ini.captures }, | |
| 8751 | } } }); | |
| 8746 | 8752 | defer gop.deinit(); |
| 8747 | if (gop == .existing) return gop.existing; | |
| 8753 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8754 | ||
| 8748 | 8755 | const local = ip.getLocal(tid); |
| 8749 | 8756 | const items = local.getMutableItems(gpa, io); |
| 8750 | 8757 | const extra = local.getMutableExtra(gpa, io); |
| 8751 | 8758 | try items.ensureUnusedCapacity(1); |
| 8752 | 8759 | |
| 8753 | assert(un.ty != .none); | |
| 8754 | assert(un.val != .none); | |
| 8760 | const tag: Tag, const have_values: bool = if (ini.nonexhaustive) | |
| 8761 | .{ .type_enum_nonexhaustive, true } | |
| 8762 | else if (ini.int_tag_mode == .explicit) | |
| 8763 | .{ .type_enum_explicit, true } | |
| 8764 | else | |
| 8765 | .{ .type_enum_auto, false }; | |
| 8766 | ||
| 8767 | const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 8768 | errdefer local.mutate.maps.len -= 1; | |
| 8769 | ||
| 8770 | const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined; | |
| 8771 | errdefer local.mutate.maps.len -= @intFromBool(have_values); | |
| 8772 | ||
| 8773 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + | |
| 8774 | 1 + // zir_index | |
| 8775 | ini.captures.len + // capture | |
| 8776 | @intFromBool(have_values) + // field_value_map | |
| 8777 | ini.fields_len + // field_name | |
| 8778 | (if (have_values) ini.fields_len else 0)); // field_value | |
| 8779 | ||
| 8780 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ | |
| 8781 | .bits = .{ | |
| 8782 | .captures_len = @enumFromInt(ini.captures.len), | |
| 8783 | .want_layout = false, | |
| 8784 | }, | |
| 8785 | .name = undefined, // set by `finish` | |
| 8786 | .name_nav = undefined, // set by `finish` | |
| 8787 | .namespace = undefined, // set by `finish` | |
| 8788 | .int_tag_type = .none, | |
| 8789 | .fields_len = ini.fields_len, | |
| 8790 | .field_name_map = field_name_map, | |
| 8791 | }); | |
| 8792 | extra.appendAssumeCapacity(.{@intFromEnum(ini.zir_index)}); // zir_index | |
| 8793 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture | |
| 8794 | if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); // field_value_map | |
| 8795 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8796 | if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value | |
| 8755 | 8797 | items.appendAssumeCapacity(.{ |
| 8756 | .tag = .union_value, | |
| 8757 | .data = try addExtra(extra, un), | |
| 8798 | .tag = tag, | |
| 8799 | .data = extra_index, | |
| 8758 | 8800 | }); |
| 8759 | ||
| 8760 | return gop.put(); | |
| 8801 | return .{ .wip = .{ | |
| 8802 | .index = gop.put(), | |
| 8803 | .tid = tid, | |
| 8804 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, | |
| 8805 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, | |
| 8806 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, | |
| 8807 | .field_names = undefined, | |
| 8808 | .field_types = undefined, | |
| 8809 | .field_values = undefined, | |
| 8810 | .field_aligns = undefined, | |
| 8811 | .field_is_comptime_bits = undefined, | |
| 8812 | } }; | |
| 8761 | 8813 | } |
| 8762 | 8814 | |
| 8763 | pub const UnionTypeInit = struct { | |
| 8764 | flags: packed struct { | |
| 8765 | runtime_tag: LoadedUnionType.RuntimeTag, | |
| 8766 | any_aligned_fields: bool, | |
| 8767 | layout: std.builtin.Type.ContainerLayout, | |
| 8768 | status: LoadedUnionType.Status, | |
| 8769 | requires_comptime: RequiresComptime, | |
| 8770 | assumed_runtime_bits: bool, | |
| 8771 | assumed_pointer_aligned: bool, | |
| 8772 | alignment: Alignment, | |
| 8773 | }, | |
| 8815 | pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { | |
| 8816 | zir_index: TrackedInst.Index, | |
| 8817 | type_hash: u64, | |
| 8774 | 8818 | fields_len: u32, |
| 8775 | enum_tag_ty: Index, | |
| 8776 | /// May have length 0 which leaves the values unset until later. | |
| 8777 | field_types: []const Index, | |
| 8778 | /// May have length 0 which leaves the values unset until later. | |
| 8779 | /// The logic for `any_aligned_fields` is asserted to have been done before | |
| 8780 | /// calling this function. | |
| 8781 | field_aligns: []const Alignment, | |
| 8782 | key: union(enum) { | |
| 8783 | declared: struct { | |
| 8784 | zir_index: TrackedInst.Index, | |
| 8785 | captures: []const CaptureValue, | |
| 8786 | }, | |
| 8787 | declared_owned_captures: struct { | |
| 8788 | zir_index: TrackedInst.Index, | |
| 8789 | captures: CaptureValue.Slice, | |
| 8790 | }, | |
| 8791 | reified: struct { | |
| 8792 | zir_index: TrackedInst.Index, | |
| 8793 | type_hash: u64, | |
| 8794 | }, | |
| 8795 | }, | |
| 8796 | }; | |
| 8797 | ||
| 8798 | pub fn getUnionType( | |
| 8799 | ip: *InternPool, | |
| 8800 | gpa: Allocator, | |
| 8801 | io: Io, | |
| 8802 | tid: Zcu.PerThread.Id, | |
| 8803 | ini: UnionTypeInit, | |
| 8804 | /// If it is known that there is an existing type with this key which is outdated, | |
| 8805 | /// this is passed as `true`, and the type is replaced with one at a fresh index. | |
| 8806 | replace_existing: bool, | |
| 8807 | ) Allocator.Error!WipNamespaceType.Result { | |
| 8808 | const key: Key = .{ .union_type = switch (ini.key) { | |
| 8809 | .declared => |d| .{ .declared = .{ | |
| 8810 | .zir_index = d.zir_index, | |
| 8811 | .captures = .{ .external = d.captures }, | |
| 8812 | } }, | |
| 8813 | .declared_owned_captures => |d| .{ .declared = .{ | |
| 8814 | .zir_index = d.zir_index, | |
| 8815 | .captures = .{ .owned = d.captures }, | |
| 8816 | } }, | |
| 8817 | .reified => |r| .{ .reified = .{ | |
| 8818 | .zir_index = r.zir_index, | |
| 8819 | .type_hash = r.type_hash, | |
| 8820 | } }, | |
| 8821 | } }; | |
| 8822 | var gop = if (replace_existing) | |
| 8823 | ip.putKeyReplace(io, tid, key) | |
| 8824 | else | |
| 8825 | try ip.getOrPutKey(gpa, io, tid, key); | |
| 8819 | nonexhaustive: bool, | |
| 8820 | /// Explicitly specified int tag type, or `.none` if the int tag type is inferred. | |
| 8821 | int_tag_type: Index, | |
| 8822 | }) Allocator.Error!WipContainerType.Result { | |
| 8823 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .reified = .{ | |
| 8824 | .zir_index = ini.zir_index, | |
| 8825 | .type_hash = ini.type_hash, | |
| 8826 | } } }); | |
| 8826 | 8827 | defer gop.deinit(); |
| 8827 | 8828 | if (gop == .existing) return .{ .existing = gop.existing }; |
| 8828 | 8829 | |
| 8829 | 8830 | const local = ip.getLocal(tid); |
| 8830 | 8831 | const items = local.getMutableItems(gpa, io); |
| 8831 | try items.ensureUnusedCapacity(1); | |
| 8832 | 8832 | const extra = local.getMutableExtra(gpa, io); |
| 8833 | try items.ensureUnusedCapacity(1); | |
| 8833 | 8834 | |
| 8834 | const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; | |
| 8835 | const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); | |
| 8836 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + | |
| 8837 | // TODO: fmt bug | |
| 8838 | // zig fmt: off | |
| 8839 | switch (ini.key) { | |
| 8840 | inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len, | |
| 8841 | .reified => 2, // type_hash: PackedU64 | |
| 8842 | } + | |
| 8843 | // zig fmt: on | |
| 8844 | ini.fields_len + // field types | |
| 8845 | align_elements_len); | |
| 8835 | const tag: Tag, const have_values: bool = if (ini.nonexhaustive) | |
| 8836 | .{ .type_enum_nonexhaustive, true } | |
| 8837 | else if (ini.int_tag_type != .none) | |
| 8838 | .{ .type_enum_explicit, true } | |
| 8839 | else | |
| 8840 | .{ .type_enum_auto, false }; | |
| 8846 | 8841 | |
| 8847 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ | |
| 8848 | .flags = .{ | |
| 8849 | .any_captures = switch (ini.key) { | |
| 8850 | inline .declared, .declared_owned_captures => |d| d.captures.len != 0, | |
| 8851 | .reified => false, | |
| 8852 | }, | |
| 8853 | .runtime_tag = ini.flags.runtime_tag, | |
| 8854 | .any_aligned_fields = ini.flags.any_aligned_fields, | |
| 8855 | .layout = ini.flags.layout, | |
| 8856 | .status = ini.flags.status, | |
| 8857 | .requires_comptime = ini.flags.requires_comptime, | |
| 8858 | .assumed_runtime_bits = ini.flags.assumed_runtime_bits, | |
| 8859 | .assumed_pointer_aligned = ini.flags.assumed_pointer_aligned, | |
| 8860 | .alignment = ini.flags.alignment, | |
| 8861 | .is_reified = switch (ini.key) { | |
| 8862 | .declared, .declared_owned_captures => false, | |
| 8863 | .reified => true, | |
| 8864 | }, | |
| 8842 | const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 8843 | errdefer local.mutate.maps.len -= 1; | |
| 8844 | ||
| 8845 | const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined; | |
| 8846 | errdefer local.mutate.maps.len -= @intFromBool(have_values); | |
| 8847 | ||
| 8848 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + | |
| 8849 | 1 + // zir_index | |
| 8850 | 2 + // type_hash | |
| 8851 | @intFromBool(have_values) + // field_value_map | |
| 8852 | ini.fields_len + // field_name | |
| 8853 | (if (have_values) ini.fields_len else 0)); // field_value | |
| 8854 | ||
| 8855 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ | |
| 8856 | .bits = .{ | |
| 8857 | .captures_len = .reified, | |
| 8858 | .want_layout = false, | |
| 8865 | 8859 | }, |
| 8866 | .fields_len = ini.fields_len, | |
| 8867 | .size = std.math.maxInt(u32), | |
| 8868 | .padding = std.math.maxInt(u32), | |
| 8869 | 8860 | .name = undefined, // set by `finish` |
| 8870 | 8861 | .name_nav = undefined, // set by `finish` |
| 8871 | 8862 | .namespace = undefined, // set by `finish` |
| 8872 | .tag_ty = ini.enum_tag_ty, | |
| 8873 | .zir_index = switch (ini.key) { | |
| 8874 | inline else => |x| x.zir_index, | |
| 8875 | }, | |
| 8863 | .int_tag_type = ini.int_tag_type, | |
| 8864 | .fields_len = ini.fields_len, | |
| 8865 | .field_name_map = field_name_map, | |
| 8876 | 8866 | }); |
| 8877 | ||
| 8867 | extra.appendAssumeCapacity(.{@intFromEnum(ini.zir_index)}); // zir_index | |
| 8868 | _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash | |
| 8869 | if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); // field_value_map | |
| 8870 | const field_names_start = extra.mutate.len; | |
| 8871 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8872 | const field_values_start = extra.mutate.len; | |
| 8873 | if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value | |
| 8878 | 8874 | items.appendAssumeCapacity(.{ |
| 8879 | .tag = .type_union, | |
| 8875 | .tag = tag, | |
| 8880 | 8876 | .data = extra_index, |
| 8881 | 8877 | }); |
| 8878 | return .{ .wip = .{ | |
| 8879 | .index = gop.put(), | |
| 8880 | .tid = tid, | |
| 8881 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, | |
| 8882 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, | |
| 8883 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, | |
| 8884 | .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, | |
| 8885 | .field_types = undefined, | |
| 8886 | .field_values = if (have_values) | |
| 8887 | .{ .tid = tid, .start = field_values_start, .len = ini.fields_len } | |
| 8888 | else | |
| 8889 | undefined, | |
| 8890 | .field_aligns = undefined, | |
| 8891 | .field_is_comptime_bits = undefined, | |
| 8892 | } }; | |
| 8893 | } | |
| 8894 | ||
| 8895 | pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { | |
| 8896 | /// The union type for which this enum is a generated tag. | |
| 8897 | union_type: Index, | |
| 8898 | /// For `union(enum(T))` this is `.explicit`. Otherwise this is `.none`. | |
| 8899 | int_tag_mode: BackingTypeMode, | |
| 8900 | fields_len: u32, | |
| 8901 | }) Allocator.Error!WipContainerType.Result { | |
| 8902 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .generated_union_tag = ini.union_type } }); | |
| 8903 | defer gop.deinit(); | |
| 8904 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8882 | 8905 | |
| 8883 | switch (ini.key) { | |
| 8884 | .declared => |d| if (d.captures.len != 0) { | |
| 8885 | extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); | |
| 8886 | extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); | |
| 8906 | const local = ip.getLocal(tid); | |
| 8907 | const items = local.getMutableItems(gpa, io); | |
| 8908 | const extra = local.getMutableExtra(gpa, io); | |
| 8909 | try items.ensureUnusedCapacity(1); | |
| 8910 | ||
| 8911 | const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 8912 | errdefer local.mutate.maps.len -= 1; | |
| 8913 | ||
| 8914 | const have_values = switch (ini.int_tag_mode) { | |
| 8915 | .explicit => true, | |
| 8916 | .auto => false, | |
| 8917 | }; | |
| 8918 | ||
| 8919 | const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined; | |
| 8920 | errdefer local.mutate.maps.len -= @intFromBool(have_values); | |
| 8921 | ||
| 8922 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + | |
| 8923 | 1 + // owner_union | |
| 8924 | @intFromBool(have_values) + // field_value_map | |
| 8925 | ini.fields_len + // field_name | |
| 8926 | (if (have_values) ini.fields_len else 0)); // field_value | |
| 8927 | ||
| 8928 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ | |
| 8929 | .bits = .{ | |
| 8930 | .captures_len = .generated_union_tag, | |
| 8931 | .want_layout = false, | |
| 8887 | 8932 | }, |
| 8888 | .declared_owned_captures => |d| if (d.captures.len != 0) { | |
| 8889 | extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); | |
| 8890 | extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}); | |
| 8933 | .name = undefined, // set by `finish` | |
| 8934 | .name_nav = undefined, // set by `finish` | |
| 8935 | .namespace = undefined, // set by `finish` | |
| 8936 | .int_tag_type = .none, | |
| 8937 | .fields_len = ini.fields_len, | |
| 8938 | .field_name_map = field_name_map, | |
| 8939 | }); | |
| 8940 | extra.appendAssumeCapacity(.{@intFromEnum(ini.union_type)}); // owner_union | |
| 8941 | if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); | |
| 8942 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name | |
| 8943 | if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value | |
| 8944 | items.appendAssumeCapacity(.{ | |
| 8945 | .tag = switch (ini.int_tag_mode) { | |
| 8946 | .auto => .type_enum_auto, | |
| 8947 | .explicit => .type_enum_explicit, | |
| 8891 | 8948 | }, |
| 8892 | .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), | |
| 8893 | } | |
| 8949 | .data = extra_index, | |
| 8950 | }); | |
| 8951 | return .{ .wip = .{ | |
| 8952 | .index = gop.put(), | |
| 8953 | .tid = tid, | |
| 8954 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, | |
| 8955 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, | |
| 8956 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, | |
| 8957 | .field_names = undefined, | |
| 8958 | .field_types = undefined, | |
| 8959 | .field_values = undefined, | |
| 8960 | .field_aligns = undefined, | |
| 8961 | .field_is_comptime_bits = undefined, | |
| 8962 | } }; | |
| 8963 | } | |
| 8894 | 8964 | |
| 8895 | // field types | |
| 8896 | if (ini.field_types.len > 0) { | |
| 8897 | assert(ini.field_types.len == ini.fields_len); | |
| 8898 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.field_types)}); | |
| 8899 | } else { | |
| 8900 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); | |
| 8901 | } | |
| 8965 | pub fn getDeclaredOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { | |
| 8966 | zir_index: TrackedInst.Index, | |
| 8967 | captures: []const CaptureValue, | |
| 8968 | }) Allocator.Error!WipContainerType.Result { | |
| 8969 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{ | |
| 8970 | .zir_index = ini.zir_index, | |
| 8971 | .captures = .{ .external = ini.captures }, | |
| 8972 | } } }); | |
| 8973 | defer gop.deinit(); | |
| 8974 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 8902 | 8975 | |
| 8903 | // field alignments | |
| 8904 | if (ini.flags.any_aligned_fields) { | |
| 8905 | extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len); | |
| 8906 | if (ini.field_aligns.len > 0) { | |
| 8907 | assert(ini.field_aligns.len == ini.fields_len); | |
| 8908 | @memcpy((Alignment.Slice{ | |
| 8909 | .tid = tid, | |
| 8910 | .start = @intCast(extra.mutate.len - align_elements_len), | |
| 8911 | .len = @intCast(ini.field_aligns.len), | |
| 8912 | }).get(ip), ini.field_aligns); | |
| 8913 | } | |
| 8914 | } else { | |
| 8915 | assert(ini.field_aligns.len == 0); | |
| 8916 | } | |
| 8976 | const local = ip.getLocal(tid); | |
| 8977 | const items = local.getMutableItems(gpa, io); | |
| 8978 | const extra = local.getMutableExtra(gpa, io); | |
| 8979 | try items.ensureUnusedCapacity(1); | |
| 8917 | 8980 | |
| 8981 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); | |
| 8982 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ | |
| 8983 | .zir_index = ini.zir_index, | |
| 8984 | .captures_len = @intCast(ini.captures.len), | |
| 8985 | .name = undefined, // set by `finish` | |
| 8986 | .name_nav = undefined, // set by `finish` | |
| 8987 | .namespace = undefined, // set by `finish` | |
| 8988 | }); | |
| 8989 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); | |
| 8990 | items.appendAssumeCapacity(.{ | |
| 8991 | .tag = .type_opaque, | |
| 8992 | .data = extra_index, | |
| 8993 | }); | |
| 8918 | 8994 | return .{ .wip = .{ |
| 8919 | .tid = tid, | |
| 8920 | 8995 | .index = gop.put(), |
| 8921 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, | |
| 8922 | .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, | |
| 8923 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, | |
| 8996 | .tid = tid, | |
| 8997 | .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, | |
| 8998 | .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, | |
| 8999 | .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, | |
| 9000 | .field_names = undefined, | |
| 9001 | .field_types = undefined, | |
| 9002 | .field_values = undefined, | |
| 9003 | .field_aligns = undefined, | |
| 9004 | .field_is_comptime_bits = undefined, | |
| 8924 | 9005 | } }; |
| 8925 | 9006 | } |
| 8926 | 9007 | |
| 8927 | pub const WipNamespaceType = struct { | |
| 8928 | tid: Zcu.PerThread.Id, | |
| 9008 | pub const WipContainerType = struct { | |
| 8929 | 9009 | index: Index, |
| 8930 | type_name_extra_index: u32, | |
| 8931 | namespace_extra_index: u32, | |
| 8932 | name_nav_extra_index: u32, | |
| 9010 | tid: Zcu.PerThread.Id, | |
| 9011 | type_name_index: u32, | |
| 9012 | name_nav_index: u32, | |
| 9013 | namespace_index: u32, | |
| 9014 | ||
| 9015 | // These fields are only populated when creating reified types, because reified types populate | |
| 9016 | // field information immediately, with type resolution only handling validation. This is in | |
| 9017 | // contrast to declared types, where field information is populated by the type resolution | |
| 9018 | // process evaluating ZIR expressions. | |
| 9019 | field_names: NullTerminatedString.Slice, | |
| 9020 | field_types: Index.Slice, | |
| 9021 | field_values: Index.Slice, | |
| 9022 | field_aligns: Alignment.Slice, | |
| 9023 | field_is_comptime_bits: LoadedStructType.ComptimeBits, | |
| 8933 | 9024 | |
| 8934 | 9025 | pub fn setName( |
| 8935 | wip: WipNamespaceType, | |
| 9026 | wip: WipContainerType, | |
| 8936 | 9027 | ip: *InternPool, |
| 8937 | 9028 | type_name: NullTerminatedString, |
| 8938 | 9029 | /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. |
| ... | ... | @@ -8941,257 +9032,58 @@ pub const WipNamespaceType = struct { |
| 8941 | 9032 | ) void { |
| 8942 | 9033 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); |
| 8943 | 9034 | const extra_items = extra.view().items(.@"0"); |
| 8944 | extra_items[wip.type_name_extra_index] = @intFromEnum(type_name); | |
| 8945 | extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav); | |
| 9035 | extra_items[wip.type_name_index] = @intFromEnum(type_name); | |
| 9036 | extra_items[wip.name_nav_index] = @intFromEnum(name_nav); | |
| 8946 | 9037 | } |
| 8947 | 9038 | |
| 8948 | 9039 | pub fn finish( |
| 8949 | wip: WipNamespaceType, | |
| 9040 | wip: WipContainerType, | |
| 8950 | 9041 | ip: *InternPool, |
| 8951 | 9042 | namespace: NamespaceIndex, |
| 8952 | 9043 | ) Index { |
| 8953 | 9044 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); |
| 8954 | 9045 | const extra_items = extra.view().items(.@"0"); |
| 8955 | 9046 | |
| 8956 | extra_items[wip.namespace_extra_index] = @intFromEnum(namespace); | |
| 9047 | extra_items[wip.namespace_index] = @intFromEnum(namespace); | |
| 8957 | 9048 | |
| 8958 | 9049 | return wip.index; |
| 8959 | 9050 | } |
| 8960 | 9051 | |
| 8961 | pub fn cancel(wip: WipNamespaceType, ip: *InternPool, tid: Zcu.PerThread.Id) void { | |
| 9052 | pub fn cancel(wip: WipContainerType, ip: *InternPool, tid: Zcu.PerThread.Id) void { | |
| 8962 | 9053 | ip.remove(tid, wip.index); |
| 8963 | 9054 | } |
| 8964 | 9055 | |
| 8965 | 9056 | pub const Result = union(enum) { |
| 8966 | wip: WipNamespaceType, | |
| 8967 | existing: Index, | |
| 8968 | }; | |
| 8969 | }; | |
| 8970 | ||
| 8971 | pub const StructTypeInit = struct { | |
| 8972 | layout: std.builtin.Type.ContainerLayout, | |
| 8973 | fields_len: u32, | |
| 8974 | known_non_opv: bool, | |
| 8975 | requires_comptime: RequiresComptime, | |
| 8976 | any_comptime_fields: bool, | |
| 8977 | any_default_inits: bool, | |
| 8978 | inits_resolved: bool, | |
| 8979 | any_aligned_fields: bool, | |
| 8980 | key: union(enum) { | |
| 8981 | declared: struct { | |
| 8982 | zir_index: TrackedInst.Index, | |
| 8983 | captures: []const CaptureValue, | |
| 8984 | }, | |
| 8985 | declared_owned_captures: struct { | |
| 8986 | zir_index: TrackedInst.Index, | |
| 8987 | captures: CaptureValue.Slice, | |
| 8988 | }, | |
| 8989 | reified: struct { | |
| 8990 | zir_index: TrackedInst.Index, | |
| 8991 | type_hash: u64, | |
| 8992 | }, | |
| 8993 | }, | |
| 8994 | }; | |
| 8995 | ||
| 8996 | pub fn getStructType( | |
| 8997 | ip: *InternPool, | |
| 8998 | gpa: Allocator, | |
| 8999 | io: Io, | |
| 9000 | tid: Zcu.PerThread.Id, | |
| 9001 | ini: StructTypeInit, | |
| 9002 | /// If it is known that there is an existing type with this key which is outdated, | |
| 9003 | /// this is passed as `true`, and the type is replaced with one at a fresh index. | |
| 9004 | replace_existing: bool, | |
| 9005 | ) Allocator.Error!WipNamespaceType.Result { | |
| 9006 | const key: Key = .{ .struct_type = switch (ini.key) { | |
| 9007 | .declared => |d| .{ .declared = .{ | |
| 9008 | .zir_index = d.zir_index, | |
| 9009 | .captures = .{ .external = d.captures }, | |
| 9010 | } }, | |
| 9011 | .declared_owned_captures => |d| .{ .declared = .{ | |
| 9012 | .zir_index = d.zir_index, | |
| 9013 | .captures = .{ .owned = d.captures }, | |
| 9014 | } }, | |
| 9015 | .reified => |r| .{ .reified = .{ | |
| 9016 | .zir_index = r.zir_index, | |
| 9017 | .type_hash = r.type_hash, | |
| 9018 | } }, | |
| 9019 | } }; | |
| 9020 | var gop = if (replace_existing) | |
| 9021 | ip.putKeyReplace(io, tid, key) | |
| 9022 | else | |
| 9023 | try ip.getOrPutKey(gpa, io, tid, key); | |
| 9024 | defer gop.deinit(); | |
| 9025 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 9026 | ||
| 9027 | const local = ip.getLocal(tid); | |
| 9028 | const items = local.getMutableItems(gpa, io); | |
| 9029 | const extra = local.getMutableExtra(gpa, io); | |
| 9030 | ||
| 9031 | const names_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 9032 | errdefer local.mutate.maps.len -= 1; | |
| 9033 | ||
| 9034 | const zir_index = switch (ini.key) { | |
| 9035 | inline else => |x| x.zir_index, | |
| 9036 | }; | |
| 9037 | ||
| 9038 | const is_extern = switch (ini.layout) { | |
| 9039 | .auto => false, | |
| 9040 | .@"extern" => true, | |
| 9041 | .@"packed" => { | |
| 9042 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + | |
| 9043 | // TODO: fmt bug | |
| 9044 | // zig fmt: off | |
| 9045 | switch (ini.key) { | |
| 9046 | inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len, | |
| 9047 | .reified => 2, // type_hash: PackedU64 | |
| 9048 | } + | |
| 9049 | // zig fmt: on | |
| 9050 | ini.fields_len + // types | |
| 9051 | ini.fields_len + // names | |
| 9052 | ini.fields_len); // inits | |
| 9053 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ | |
| 9054 | .name = undefined, // set by `finish` | |
| 9055 | .name_nav = undefined, // set by `finish` | |
| 9056 | .zir_index = zir_index, | |
| 9057 | .fields_len = ini.fields_len, | |
| 9058 | .namespace = undefined, // set by `finish` | |
| 9059 | .backing_int_ty = .none, | |
| 9060 | .names_map = names_map, | |
| 9061 | .flags = .{ | |
| 9062 | .any_captures = switch (ini.key) { | |
| 9063 | inline .declared, .declared_owned_captures => |d| d.captures.len != 0, | |
| 9064 | .reified => false, | |
| 9065 | }, | |
| 9066 | .field_inits_wip = false, | |
| 9067 | .inits_resolved = ini.inits_resolved, | |
| 9068 | .is_reified = switch (ini.key) { | |
| 9069 | .declared, .declared_owned_captures => false, | |
| 9070 | .reified => true, | |
| 9071 | }, | |
| 9072 | }, | |
| 9073 | }); | |
| 9074 | try items.append(.{ | |
| 9075 | .tag = if (ini.any_default_inits) .type_struct_packed_inits else .type_struct_packed, | |
| 9076 | .data = extra_index, | |
| 9077 | }); | |
| 9078 | switch (ini.key) { | |
| 9079 | .declared => |d| if (d.captures.len != 0) { | |
| 9080 | extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); | |
| 9081 | extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); | |
| 9082 | }, | |
| 9083 | .declared_owned_captures => |d| if (d.captures.len != 0) { | |
| 9084 | extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); | |
| 9085 | extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}); | |
| 9086 | }, | |
| 9087 | .reified => |r| { | |
| 9088 | _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); | |
| 9089 | }, | |
| 9090 | } | |
| 9091 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); | |
| 9092 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len); | |
| 9093 | if (ini.any_default_inits) { | |
| 9094 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); | |
| 9095 | } | |
| 9096 | return .{ .wip = .{ | |
| 9097 | .tid = tid, | |
| 9098 | .index = gop.put(), | |
| 9099 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, | |
| 9100 | .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, | |
| 9101 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, | |
| 9102 | } }; | |
| 9103 | }, | |
| 9057 | wip: WipContainerType, | |
| 9058 | existing: Index, | |
| 9104 | 9059 | }; |
| 9060 | }; | |
| 9105 | 9061 | |
| 9106 | const align_elements_len = if (ini.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; | |
| 9107 | const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); | |
| 9108 | const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0; | |
| 9062 | pub fn getUnion( | |
| 9063 | ip: *InternPool, | |
| 9064 | gpa: Allocator, | |
| 9065 | io: Io, | |
| 9066 | tid: Zcu.PerThread.Id, | |
| 9067 | un: Key.Union, | |
| 9068 | ) Allocator.Error!Index { | |
| 9069 | assert(un.ty != .none); | |
| 9070 | assert(un.val != .none); | |
| 9071 | assert(ip.loadUnionType(un.ty).layout != .@"packed"); | |
| 9109 | 9072 | |
| 9110 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len + | |
| 9111 | // TODO: fmt bug | |
| 9112 | // zig fmt: off | |
| 9113 | switch (ini.key) { | |
| 9114 | inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len, | |
| 9115 | .reified => 2, // type_hash: PackedU64 | |
| 9116 | } + | |
| 9117 | // zig fmt: on | |
| 9118 | (ini.fields_len * 5) + // types, names, inits, runtime order, offsets | |
| 9119 | align_elements_len + comptime_elements_len + | |
| 9120 | 1); // names_map | |
| 9121 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ | |
| 9122 | .name = undefined, // set by `finish` | |
| 9123 | .name_nav = undefined, // set by `finish` | |
| 9124 | .zir_index = zir_index, | |
| 9125 | .namespace = undefined, // set by `finish` | |
| 9126 | .fields_len = ini.fields_len, | |
| 9127 | .size = std.math.maxInt(u32), | |
| 9128 | .flags = .{ | |
| 9129 | .any_captures = switch (ini.key) { | |
| 9130 | inline .declared, .declared_owned_captures => |d| d.captures.len != 0, | |
| 9131 | .reified => false, | |
| 9132 | }, | |
| 9133 | .is_extern = is_extern, | |
| 9134 | .known_non_opv = ini.known_non_opv, | |
| 9135 | .requires_comptime = ini.requires_comptime, | |
| 9136 | .assumed_runtime_bits = false, | |
| 9137 | .assumed_pointer_aligned = false, | |
| 9138 | .any_comptime_fields = ini.any_comptime_fields, | |
| 9139 | .any_default_inits = ini.any_default_inits, | |
| 9140 | .any_aligned_fields = ini.any_aligned_fields, | |
| 9141 | .alignment = .none, | |
| 9142 | .alignment_wip = false, | |
| 9143 | .field_types_wip = false, | |
| 9144 | .layout_wip = false, | |
| 9145 | .layout_resolved = false, | |
| 9146 | .field_inits_wip = false, | |
| 9147 | .inits_resolved = ini.inits_resolved, | |
| 9148 | .fully_resolved = false, | |
| 9149 | .is_reified = switch (ini.key) { | |
| 9150 | .declared, .declared_owned_captures => false, | |
| 9151 | .reified => true, | |
| 9152 | }, | |
| 9153 | }, | |
| 9154 | }); | |
| 9155 | try items.append(.{ | |
| 9156 | .tag = .type_struct, | |
| 9157 | .data = extra_index, | |
| 9073 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); | |
| 9074 | defer gop.deinit(); | |
| 9075 | if (gop == .existing) return gop.existing; | |
| 9076 | const local = ip.getLocal(tid); | |
| 9077 | const items = local.getMutableItems(gpa, io); | |
| 9078 | const extra = local.getMutableExtra(gpa, io); | |
| 9079 | try items.ensureUnusedCapacity(1); | |
| 9080 | ||
| 9081 | items.appendAssumeCapacity(.{ | |
| 9082 | .tag = .union_value, | |
| 9083 | .data = try addExtra(extra, un), | |
| 9158 | 9084 | }); |
| 9159 | switch (ini.key) { | |
| 9160 | .declared => |d| if (d.captures.len != 0) { | |
| 9161 | extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); | |
| 9162 | extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); | |
| 9163 | }, | |
| 9164 | .declared_owned_captures => |d| if (d.captures.len != 0) { | |
| 9165 | extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); | |
| 9166 | extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}); | |
| 9167 | }, | |
| 9168 | .reified => |r| { | |
| 9169 | _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); | |
| 9170 | }, | |
| 9171 | } | |
| 9172 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); | |
| 9173 | extra.appendAssumeCapacity(.{@intFromEnum(names_map)}); | |
| 9174 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len); | |
| 9175 | if (ini.any_default_inits) { | |
| 9176 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); | |
| 9177 | } | |
| 9178 | if (ini.any_aligned_fields) { | |
| 9179 | extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len); | |
| 9180 | } | |
| 9181 | if (ini.any_comptime_fields) { | |
| 9182 | extra.appendNTimesAssumeCapacity(.{0}, comptime_elements_len); | |
| 9183 | } | |
| 9184 | if (ini.layout == .auto) { | |
| 9185 | extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); | |
| 9186 | } | |
| 9187 | extra.appendNTimesAssumeCapacity(.{std.math.maxInt(u32)}, ini.fields_len); | |
| 9188 | return .{ .wip = .{ | |
| 9189 | .tid = tid, | |
| 9190 | .index = gop.put(), | |
| 9191 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, | |
| 9192 | .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, | |
| 9193 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, | |
| 9194 | } }; | |
| 9085 | ||
| 9086 | return gop.put(); | |
| 9195 | 9087 | } |
| 9196 | 9088 | |
| 9197 | 9089 | pub const TupleTypeInit = struct { |
| ... | ... | @@ -9252,10 +9144,7 @@ pub const GetFuncTypeKey = struct { |
| 9252 | 9144 | /// `null` means generic. |
| 9253 | 9145 | cc: ?std.builtin.CallingConvention = .auto, |
| 9254 | 9146 | is_var_args: bool = false, |
| 9255 | is_generic: bool = false, | |
| 9256 | 9147 | is_noinline: bool = false, |
| 9257 | section_is_generic: bool = false, | |
| 9258 | addrspace_is_generic: bool = false, | |
| 9259 | 9148 | }; |
| 9260 | 9149 | |
| 9261 | 9150 | pub fn getFuncType( |
| ... | ... | @@ -9293,7 +9182,6 @@ pub fn getFuncType( |
| 9293 | 9182 | .is_var_args = key.is_var_args, |
| 9294 | 9183 | .has_comptime_bits = key.comptime_bits != 0, |
| 9295 | 9184 | .has_noalias_bits = key.noalias_bits != 0, |
| 9296 | .is_generic = key.is_generic, | |
| 9297 | 9185 | .is_noinline = key.is_noinline, |
| 9298 | 9186 | }, |
| 9299 | 9187 | }); |
| ... | ... | @@ -9427,7 +9315,7 @@ pub fn getFuncDecl( |
| 9427 | 9315 | |
| 9428 | 9316 | const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ |
| 9429 | 9317 | .analysis = .{ |
| 9430 | .is_analyzed = false, | |
| 9318 | .want_runtime_analysis = false, | |
| 9431 | 9319 | .branch_hint = .none, |
| 9432 | 9320 | .is_noinline = key.is_noinline, |
| 9433 | 9321 | .has_error_trace = false, |
| ... | ... | @@ -9480,7 +9368,6 @@ pub const GetFuncDeclIesKey = struct { |
| 9480 | 9368 | /// null means generic. |
| 9481 | 9369 | cc: ?std.builtin.CallingConvention, |
| 9482 | 9370 | is_var_args: bool, |
| 9483 | is_generic: bool, | |
| 9484 | 9371 | is_noinline: bool, |
| 9485 | 9372 | zir_body_inst: TrackedInst.Index, |
| 9486 | 9373 | lbrace_line: u32, |
| ... | ... | @@ -9538,7 +9425,7 @@ pub fn getFuncDeclIes( |
| 9538 | 9425 | |
| 9539 | 9426 | const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ |
| 9540 | 9427 | .analysis = .{ |
| 9541 | .is_analyzed = false, | |
| 9428 | .want_runtime_analysis = false, | |
| 9542 | 9429 | .branch_hint = .none, |
| 9543 | 9430 | .is_noinline = key.is_noinline, |
| 9544 | 9431 | .has_error_trace = false, |
| ... | ... | @@ -9564,7 +9451,6 @@ pub fn getFuncDeclIes( |
| 9564 | 9451 | .is_var_args = key.is_var_args, |
| 9565 | 9452 | .has_comptime_bits = key.comptime_bits != 0, |
| 9566 | 9453 | .has_noalias_bits = key.noalias_bits != 0, |
| 9567 | .is_generic = key.is_generic, | |
| 9568 | 9454 | .is_noinline = key.is_noinline, |
| 9569 | 9455 | }, |
| 9570 | 9456 | }); |
| ... | ... | @@ -9737,7 +9623,7 @@ pub fn getFuncInstance( |
| 9737 | 9623 | |
| 9738 | 9624 | const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ |
| 9739 | 9625 | .analysis = .{ |
| 9740 | .is_analyzed = false, | |
| 9626 | .want_runtime_analysis = false, | |
| 9741 | 9627 | .branch_hint = .none, |
| 9742 | 9628 | .is_noinline = arg.is_noinline, |
| 9743 | 9629 | .has_error_trace = false, |
| ... | ... | @@ -9838,7 +9724,7 @@ fn getFuncInstanceIes( |
| 9838 | 9724 | |
| 9839 | 9725 | const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ |
| 9840 | 9726 | .analysis = .{ |
| 9841 | .is_analyzed = false, | |
| 9727 | .want_runtime_analysis = false, | |
| 9842 | 9728 | .branch_hint = .none, |
| 9843 | 9729 | .is_noinline = arg.is_noinline, |
| 9844 | 9730 | .has_error_trace = false, |
| ... | ... | @@ -9864,7 +9750,6 @@ fn getFuncInstanceIes( |
| 9864 | 9750 | .is_var_args = false, |
| 9865 | 9751 | .has_comptime_bits = false, |
| 9866 | 9752 | .has_noalias_bits = arg.noalias_bits != 0, |
| 9867 | .is_generic = false, | |
| 9868 | 9753 | .is_noinline = arg.is_noinline, |
| 9869 | 9754 | }, |
| 9870 | 9755 | }); |
| ... | ... | @@ -9972,444 +9857,6 @@ fn finishFuncInstance( |
| 9972 | 9857 | ] = @intFromEnum(nav_index); |
| 9973 | 9858 | } |
| 9974 | 9859 | |
| 9975 | pub const EnumTypeInit = struct { | |
| 9976 | has_values: bool, | |
| 9977 | tag_mode: LoadedEnumType.TagMode, | |
| 9978 | fields_len: u32, | |
| 9979 | key: union(enum) { | |
| 9980 | declared: struct { | |
| 9981 | zir_index: TrackedInst.Index, | |
| 9982 | captures: []const CaptureValue, | |
| 9983 | }, | |
| 9984 | declared_owned_captures: struct { | |
| 9985 | zir_index: TrackedInst.Index, | |
| 9986 | captures: CaptureValue.Slice, | |
| 9987 | }, | |
| 9988 | reified: struct { | |
| 9989 | zir_index: TrackedInst.Index, | |
| 9990 | type_hash: u64, | |
| 9991 | }, | |
| 9992 | }, | |
| 9993 | }; | |
| 9994 | ||
| 9995 | pub const WipEnumType = struct { | |
| 9996 | tid: Zcu.PerThread.Id, | |
| 9997 | index: Index, | |
| 9998 | tag_ty_index: u32, | |
| 9999 | type_name_extra_index: u32, | |
| 10000 | namespace_extra_index: u32, | |
| 10001 | name_nav_extra_index: u32, | |
| 10002 | names_map: MapIndex, | |
| 10003 | names_start: u32, | |
| 10004 | values_map: OptionalMapIndex, | |
| 10005 | values_start: u32, | |
| 10006 | ||
| 10007 | pub fn setName( | |
| 10008 | wip: WipEnumType, | |
| 10009 | ip: *InternPool, | |
| 10010 | type_name: NullTerminatedString, | |
| 10011 | /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. | |
| 10012 | name_nav: Nav.Index.Optional, | |
| 10013 | ) void { | |
| 10014 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | |
| 10015 | const extra_items = extra.view().items(.@"0"); | |
| 10016 | extra_items[wip.type_name_extra_index] = @intFromEnum(type_name); | |
| 10017 | extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav); | |
| 10018 | } | |
| 10019 | ||
| 10020 | pub fn prepare( | |
| 10021 | wip: WipEnumType, | |
| 10022 | ip: *InternPool, | |
| 10023 | namespace: NamespaceIndex, | |
| 10024 | ) void { | |
| 10025 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | |
| 10026 | const extra_items = extra.view().items(.@"0"); | |
| 10027 | ||
| 10028 | extra_items[wip.namespace_extra_index] = @intFromEnum(namespace); | |
| 10029 | } | |
| 10030 | ||
| 10031 | pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void { | |
| 10032 | assert(ip.isIntegerType(tag_ty)); | |
| 10033 | const extra = ip.getLocalShared(wip.tid).extra.acquire(); | |
| 10034 | extra.view().items(.@"0")[wip.tag_ty_index] = @intFromEnum(tag_ty); | |
| 10035 | } | |
| 10036 | ||
| 10037 | pub const FieldConflict = struct { | |
| 10038 | kind: enum { name, value }, | |
| 10039 | prev_field_idx: u32, | |
| 10040 | }; | |
| 10041 | ||
| 10042 | /// Returns the already-existing field with the same name or value, if any. | |
| 10043 | /// If the enum is automatially numbered, `value` must be `.none`. | |
| 10044 | /// Otherwise, the type of `value` must be the integer tag type of the enum. | |
| 10045 | pub fn nextField(wip: WipEnumType, ip: *InternPool, name: NullTerminatedString, value: Index) ?FieldConflict { | |
| 10046 | const unwrapped_index = wip.index.unwrap(ip); | |
| 10047 | const extra_list = ip.getLocalShared(unwrapped_index.tid).extra.acquire(); | |
| 10048 | const extra_items = extra_list.view().items(.@"0"); | |
| 10049 | if (ip.addFieldName(extra_list, wip.names_map, wip.names_start, name)) |conflict| { | |
| 10050 | return .{ .kind = .name, .prev_field_idx = conflict }; | |
| 10051 | } | |
| 10052 | if (value == .none) { | |
| 10053 | assert(wip.values_map == .none); | |
| 10054 | return null; | |
| 10055 | } | |
| 10056 | assert(ip.typeOf(value) == @as(Index, @enumFromInt(extra_items[wip.tag_ty_index]))); | |
| 10057 | const map = wip.values_map.unwrap().?.get(ip); | |
| 10058 | const field_index = map.count(); | |
| 10059 | const indexes = extra_items[wip.values_start..][0..field_index]; | |
| 10060 | const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) }; | |
| 10061 | const gop = map.getOrPutAssumeCapacityAdapted(value, adapter); | |
| 10062 | if (gop.found_existing) { | |
| 10063 | return .{ .kind = .value, .prev_field_idx = @intCast(gop.index) }; | |
| 10064 | } | |
| 10065 | extra_items[wip.values_start + field_index] = @intFromEnum(value); | |
| 10066 | return null; | |
| 10067 | } | |
| 10068 | ||
| 10069 | pub fn cancel(wip: WipEnumType, ip: *InternPool, tid: Zcu.PerThread.Id) void { | |
| 10070 | ip.remove(tid, wip.index); | |
| 10071 | } | |
| 10072 | ||
| 10073 | pub const Result = union(enum) { | |
| 10074 | wip: WipEnumType, | |
| 10075 | existing: Index, | |
| 10076 | }; | |
| 10077 | }; | |
| 10078 | ||
| 10079 | pub fn getEnumType( | |
| 10080 | ip: *InternPool, | |
| 10081 | gpa: Allocator, | |
| 10082 | io: Io, | |
| 10083 | tid: Zcu.PerThread.Id, | |
| 10084 | ini: EnumTypeInit, | |
| 10085 | /// If it is known that there is an existing type with this key which is outdated, | |
| 10086 | /// this is passed as `true`, and the type is replaced with one at a fresh index. | |
| 10087 | replace_existing: bool, | |
| 10088 | ) Allocator.Error!WipEnumType.Result { | |
| 10089 | const key: Key = .{ .enum_type = switch (ini.key) { | |
| 10090 | .declared => |d| .{ .declared = .{ | |
| 10091 | .zir_index = d.zir_index, | |
| 10092 | .captures = .{ .external = d.captures }, | |
| 10093 | } }, | |
| 10094 | .declared_owned_captures => |d| .{ .declared = .{ | |
| 10095 | .zir_index = d.zir_index, | |
| 10096 | .captures = .{ .owned = d.captures }, | |
| 10097 | } }, | |
| 10098 | .reified => |r| .{ .reified = .{ | |
| 10099 | .zir_index = r.zir_index, | |
| 10100 | .type_hash = r.type_hash, | |
| 10101 | } }, | |
| 10102 | } }; | |
| 10103 | var gop = if (replace_existing) | |
| 10104 | ip.putKeyReplace(io, tid, key) | |
| 10105 | else | |
| 10106 | try ip.getOrPutKey(gpa, io, tid, key); | |
| 10107 | defer gop.deinit(); | |
| 10108 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 10109 | ||
| 10110 | const local = ip.getLocal(tid); | |
| 10111 | const items = local.getMutableItems(gpa, io); | |
| 10112 | try items.ensureUnusedCapacity(1); | |
| 10113 | const extra = local.getMutableExtra(gpa, io); | |
| 10114 | ||
| 10115 | const names_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 10116 | errdefer local.mutate.maps.len -= 1; | |
| 10117 | ||
| 10118 | switch (ini.tag_mode) { | |
| 10119 | .auto => { | |
| 10120 | assert(!ini.has_values); | |
| 10121 | try extra.ensureUnusedCapacity(@typeInfo(EnumAuto).@"struct".fields.len + | |
| 10122 | // TODO: fmt bug | |
| 10123 | // zig fmt: off | |
| 10124 | switch (ini.key) { | |
| 10125 | inline .declared, .declared_owned_captures => |d| d.captures.len, | |
| 10126 | .reified => 2, // type_hash: PackedU64 | |
| 10127 | } + | |
| 10128 | // zig fmt: on | |
| 10129 | ini.fields_len); // field types | |
| 10130 | ||
| 10131 | const extra_index = addExtraAssumeCapacity(extra, EnumAuto{ | |
| 10132 | .name = undefined, // set by `prepare` | |
| 10133 | .name_nav = undefined, // set by `prepare` | |
| 10134 | .captures_len = switch (ini.key) { | |
| 10135 | inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len), | |
| 10136 | .reified => std.math.maxInt(u32), | |
| 10137 | }, | |
| 10138 | .namespace = undefined, // set by `prepare` | |
| 10139 | .int_tag_type = .none, // set by `prepare` | |
| 10140 | .fields_len = ini.fields_len, | |
| 10141 | .names_map = names_map, | |
| 10142 | .zir_index = switch (ini.key) { | |
| 10143 | inline else => |x| x.zir_index, | |
| 10144 | }.toOptional(), | |
| 10145 | }); | |
| 10146 | items.appendAssumeCapacity(.{ | |
| 10147 | .tag = .type_enum_auto, | |
| 10148 | .data = extra_index, | |
| 10149 | }); | |
| 10150 | switch (ini.key) { | |
| 10151 | .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), | |
| 10152 | .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}), | |
| 10153 | .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), | |
| 10154 | } | |
| 10155 | const names_start = extra.mutate.len; | |
| 10156 | _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len); | |
| 10157 | return .{ .wip = .{ | |
| 10158 | .tid = tid, | |
| 10159 | .index = gop.put(), | |
| 10160 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, | |
| 10161 | .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?, | |
| 10162 | .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name_nav").?, | |
| 10163 | .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?, | |
| 10164 | .names_map = names_map, | |
| 10165 | .names_start = @intCast(names_start), | |
| 10166 | .values_map = .none, | |
| 10167 | .values_start = undefined, | |
| 10168 | } }; | |
| 10169 | }, | |
| 10170 | .explicit, .nonexhaustive => { | |
| 10171 | const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: { | |
| 10172 | const values_map = try ip.addMap(gpa, io, tid, ini.fields_len); | |
| 10173 | break :m values_map.toOptional(); | |
| 10174 | }; | |
| 10175 | errdefer if (ini.has_values) { | |
| 10176 | local.mutate.maps.len -= 1; | |
| 10177 | }; | |
| 10178 | ||
| 10179 | try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).@"struct".fields.len + | |
| 10180 | // TODO: fmt bug | |
| 10181 | // zig fmt: off | |
| 10182 | switch (ini.key) { | |
| 10183 | inline .declared, .declared_owned_captures => |d| d.captures.len, | |
| 10184 | .reified => 2, // type_hash: PackedU64 | |
| 10185 | } + | |
| 10186 | // zig fmt: on | |
| 10187 | ini.fields_len + // field types | |
| 10188 | ini.fields_len * @intFromBool(ini.has_values)); // field values | |
| 10189 | ||
| 10190 | const extra_index = addExtraAssumeCapacity(extra, EnumExplicit{ | |
| 10191 | .name = undefined, // set by `prepare` | |
| 10192 | .name_nav = undefined, // set by `prepare` | |
| 10193 | .captures_len = switch (ini.key) { | |
| 10194 | inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len), | |
| 10195 | .reified => std.math.maxInt(u32), | |
| 10196 | }, | |
| 10197 | .namespace = undefined, // set by `prepare` | |
| 10198 | .int_tag_type = .none, // set by `prepare` | |
| 10199 | .fields_len = ini.fields_len, | |
| 10200 | .names_map = names_map, | |
| 10201 | .values_map = values_map, | |
| 10202 | .zir_index = switch (ini.key) { | |
| 10203 | inline else => |x| x.zir_index, | |
| 10204 | }.toOptional(), | |
| 10205 | }); | |
| 10206 | items.appendAssumeCapacity(.{ | |
| 10207 | .tag = switch (ini.tag_mode) { | |
| 10208 | .auto => unreachable, | |
| 10209 | .explicit => .type_enum_explicit, | |
| 10210 | .nonexhaustive => .type_enum_nonexhaustive, | |
| 10211 | }, | |
| 10212 | .data = extra_index, | |
| 10213 | }); | |
| 10214 | switch (ini.key) { | |
| 10215 | .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), | |
| 10216 | .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}), | |
| 10217 | .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), | |
| 10218 | } | |
| 10219 | const names_start = extra.mutate.len; | |
| 10220 | _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len); | |
| 10221 | const values_start = extra.mutate.len; | |
| 10222 | if (ini.has_values) { | |
| 10223 | _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len); | |
| 10224 | } | |
| 10225 | return .{ .wip = .{ | |
| 10226 | .tid = tid, | |
| 10227 | .index = gop.put(), | |
| 10228 | .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?, | |
| 10229 | .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?, | |
| 10230 | .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name_nav").?, | |
| 10231 | .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?, | |
| 10232 | .names_map = names_map, | |
| 10233 | .names_start = @intCast(names_start), | |
| 10234 | .values_map = values_map, | |
| 10235 | .values_start = @intCast(values_start), | |
| 10236 | } }; | |
| 10237 | }, | |
| 10238 | } | |
| 10239 | } | |
| 10240 | ||
| 10241 | const GeneratedTagEnumTypeInit = struct { | |
| 10242 | name: NullTerminatedString, | |
| 10243 | owner_union_ty: Index, | |
| 10244 | tag_ty: Index, | |
| 10245 | names: []const NullTerminatedString, | |
| 10246 | values: []const Index, | |
| 10247 | tag_mode: LoadedEnumType.TagMode, | |
| 10248 | parent_namespace: NamespaceIndex, | |
| 10249 | }; | |
| 10250 | ||
| 10251 | /// Creates an enum type which was automatically-generated as the tag type of a | |
| 10252 | /// `union` with no explicit tag type. Since this is only called once per union | |
| 10253 | /// type, it asserts that no matching type yet exists. | |
| 10254 | pub fn getGeneratedTagEnumType( | |
| 10255 | ip: *InternPool, | |
| 10256 | gpa: Allocator, | |
| 10257 | io: Io, | |
| 10258 | tid: Zcu.PerThread.Id, | |
| 10259 | ini: GeneratedTagEnumTypeInit, | |
| 10260 | ) Allocator.Error!Index { | |
| 10261 | assert(ip.isUnion(ini.owner_union_ty)); | |
| 10262 | assert(ip.isIntegerType(ini.tag_ty)); | |
| 10263 | for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty); | |
| 10264 | ||
| 10265 | const local = ip.getLocal(tid); | |
| 10266 | const items = local.getMutableItems(gpa, io); | |
| 10267 | try items.ensureUnusedCapacity(1); | |
| 10268 | const extra = local.getMutableExtra(gpa, io); | |
| 10269 | ||
| 10270 | const names_map = try ip.addMap(gpa, io, tid, ini.names.len); | |
| 10271 | errdefer local.mutate.maps.len -= 1; | |
| 10272 | ip.addStringsToMap(names_map, ini.names); | |
| 10273 | ||
| 10274 | const fields_len: u32 = @intCast(ini.names.len); | |
| 10275 | ||
| 10276 | // Predict the index the enum will live at so we can construct the namespace before releasing the shard's mutex. | |
| 10277 | const enum_index = Index.Unwrapped.wrap(.{ | |
| 10278 | .tid = tid, | |
| 10279 | .index = items.mutate.len, | |
| 10280 | }, ip); | |
| 10281 | const parent_namespace = ip.namespacePtr(ini.parent_namespace); | |
| 10282 | const namespace = try ip.createNamespace(gpa, io, tid, .{ | |
| 10283 | .parent = ini.parent_namespace.toOptional(), | |
| 10284 | .owner_type = enum_index, | |
| 10285 | .file_scope = parent_namespace.file_scope, | |
| 10286 | .generation = parent_namespace.generation, | |
| 10287 | }); | |
| 10288 | errdefer ip.destroyNamespace(tid, namespace); | |
| 10289 | ||
| 10290 | const prev_extra_len = extra.mutate.len; | |
| 10291 | switch (ini.tag_mode) { | |
| 10292 | .auto => { | |
| 10293 | try extra.ensureUnusedCapacity(@typeInfo(EnumAuto).@"struct".fields.len + | |
| 10294 | 1 + // owner_union | |
| 10295 | fields_len); // field names | |
| 10296 | items.appendAssumeCapacity(.{ | |
| 10297 | .tag = .type_enum_auto, | |
| 10298 | .data = addExtraAssumeCapacity(extra, EnumAuto{ | |
| 10299 | .name = ini.name, | |
| 10300 | .name_nav = .none, | |
| 10301 | .captures_len = 0, | |
| 10302 | .namespace = namespace, | |
| 10303 | .int_tag_type = ini.tag_ty, | |
| 10304 | .fields_len = fields_len, | |
| 10305 | .names_map = names_map, | |
| 10306 | .zir_index = .none, | |
| 10307 | }), | |
| 10308 | }); | |
| 10309 | extra.appendAssumeCapacity(.{@intFromEnum(ini.owner_union_ty)}); | |
| 10310 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)}); | |
| 10311 | }, | |
| 10312 | .explicit, .nonexhaustive => { | |
| 10313 | try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).@"struct".fields.len + | |
| 10314 | 1 + // owner_union | |
| 10315 | fields_len + // field names | |
| 10316 | ini.values.len); // field values | |
| 10317 | ||
| 10318 | const values_map: OptionalMapIndex = if (ini.values.len != 0) m: { | |
| 10319 | const map = try ip.addMap(gpa, io, tid, ini.values.len); | |
| 10320 | ip.addIndexesToMap(map, ini.values); | |
| 10321 | break :m map.toOptional(); | |
| 10322 | } else .none; | |
| 10323 | // We don't clean up the values map on error! | |
| 10324 | errdefer @compileError("error path leaks values_map"); | |
| 10325 | ||
| 10326 | items.appendAssumeCapacity(.{ | |
| 10327 | .tag = switch (ini.tag_mode) { | |
| 10328 | .explicit => .type_enum_explicit, | |
| 10329 | .nonexhaustive => .type_enum_nonexhaustive, | |
| 10330 | .auto => unreachable, | |
| 10331 | }, | |
| 10332 | .data = addExtraAssumeCapacity(extra, EnumExplicit{ | |
| 10333 | .name = ini.name, | |
| 10334 | .name_nav = .none, | |
| 10335 | .captures_len = 0, | |
| 10336 | .namespace = namespace, | |
| 10337 | .int_tag_type = ini.tag_ty, | |
| 10338 | .fields_len = fields_len, | |
| 10339 | .names_map = names_map, | |
| 10340 | .values_map = values_map, | |
| 10341 | .zir_index = .none, | |
| 10342 | }), | |
| 10343 | }); | |
| 10344 | extra.appendAssumeCapacity(.{@intFromEnum(ini.owner_union_ty)}); | |
| 10345 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)}); | |
| 10346 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)}); | |
| 10347 | }, | |
| 10348 | } | |
| 10349 | errdefer extra.mutate.len = prev_extra_len; | |
| 10350 | errdefer switch (ini.tag_mode) { | |
| 10351 | .auto => {}, | |
| 10352 | .explicit, .nonexhaustive => if (ini.values.len != 0) { | |
| 10353 | local.mutate.maps.len -= 1; | |
| 10354 | }, | |
| 10355 | }; | |
| 10356 | ||
| 10357 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ | |
| 10358 | .generated_tag = .{ .union_type = ini.owner_union_ty }, | |
| 10359 | } }); | |
| 10360 | defer gop.deinit(); | |
| 10361 | assert(gop.put() == enum_index); | |
| 10362 | return enum_index; | |
| 10363 | } | |
| 10364 | ||
| 10365 | pub const OpaqueTypeInit = struct { | |
| 10366 | zir_index: TrackedInst.Index, | |
| 10367 | captures: []const CaptureValue, | |
| 10368 | }; | |
| 10369 | ||
| 10370 | pub fn getOpaqueType( | |
| 10371 | ip: *InternPool, | |
| 10372 | gpa: Allocator, | |
| 10373 | io: Io, | |
| 10374 | tid: Zcu.PerThread.Id, | |
| 10375 | ini: OpaqueTypeInit, | |
| 10376 | ) Allocator.Error!WipNamespaceType.Result { | |
| 10377 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{ | |
| 10378 | .zir_index = ini.zir_index, | |
| 10379 | .captures = .{ .external = ini.captures }, | |
| 10380 | } } }); | |
| 10381 | defer gop.deinit(); | |
| 10382 | if (gop == .existing) return .{ .existing = gop.existing }; | |
| 10383 | ||
| 10384 | const local = ip.getLocal(tid); | |
| 10385 | const items = local.getMutableItems(gpa, io); | |
| 10386 | const extra = local.getMutableExtra(gpa, io); | |
| 10387 | try items.ensureUnusedCapacity(1); | |
| 10388 | ||
| 10389 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); | |
| 10390 | const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ | |
| 10391 | .name = undefined, // set by `finish` | |
| 10392 | .name_nav = undefined, // set by `finish` | |
| 10393 | .namespace = undefined, // set by `finish` | |
| 10394 | .zir_index = ini.zir_index, | |
| 10395 | .captures_len = @intCast(ini.captures.len), | |
| 10396 | }); | |
| 10397 | items.appendAssumeCapacity(.{ | |
| 10398 | .tag = .type_opaque, | |
| 10399 | .data = extra_index, | |
| 10400 | }); | |
| 10401 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); | |
| 10402 | return .{ | |
| 10403 | .wip = .{ | |
| 10404 | .tid = tid, | |
| 10405 | .index = gop.put(), | |
| 10406 | .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, | |
| 10407 | .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, | |
| 10408 | .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, | |
| 10409 | }, | |
| 10410 | }; | |
| 10411 | } | |
| 10412 | ||
| 10413 | 9860 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { |
| 10414 | 9861 | const full_hash = key.hash64(ip); |
| 10415 | 9862 | const hash: u32 = @truncate(full_hash >> 32); |
| ... | ... | @@ -10427,28 +9874,15 @@ pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { |
| 10427 | 9874 | } |
| 10428 | 9875 | } |
| 10429 | 9876 | |
| 10430 | fn addStringsToMap( | |
| 10431 | ip: *InternPool, | |
| 10432 | map_index: MapIndex, | |
| 10433 | strings: []const NullTerminatedString, | |
| 10434 | ) void { | |
| 10435 | const map = map_index.get(ip); | |
| 10436 | const adapter: NullTerminatedString.Adapter = .{ .strings = strings }; | |
| 10437 | for (strings) |string| { | |
| 10438 | const gop = map.getOrPutAssumeCapacityAdapted(string, adapter); | |
| 10439 | assert(!gop.found_existing); | |
| 10440 | } | |
| 10441 | } | |
| 10442 | ||
| 10443 | fn addIndexesToMap( | |
| 9877 | fn addStringsToMap( | |
| 10444 | 9878 | ip: *InternPool, |
| 10445 | 9879 | map_index: MapIndex, |
| 10446 | indexes: []const Index, | |
| 9880 | strings: []const NullTerminatedString, | |
| 10447 | 9881 | ) void { |
| 10448 | 9882 | const map = map_index.get(ip); |
| 10449 | const adapter: Index.Adapter = .{ .indexes = indexes }; | |
| 10450 | for (indexes) |index| { | |
| 10451 | const gop = map.getOrPutAssumeCapacityAdapted(index, adapter); | |
| 9883 | const adapter: NullTerminatedString.Adapter = .{ .strings = strings }; | |
| 9884 | for (strings) |string| { | |
| 9885 | const gop = map.getOrPutAssumeCapacityAdapted(string, adapter); | |
| 10452 | 9886 | assert(!gop.found_existing); |
| 10453 | 9887 | } |
| 10454 | 9888 | } |
| ... | ... | @@ -10545,7 +9979,9 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { |
| 10545 | 9979 | Tag.TypePointer.PackedOffset, |
| 10546 | 9980 | Tag.TypeUnion.Flags, |
| 10547 | 9981 | Tag.TypeStruct.Flags, |
| 10548 | Tag.TypeStructPacked.Flags, | |
| 9982 | Tag.TypeStructPacked.Bits, | |
| 9983 | Tag.TypeUnionPacked.Bits, | |
| 9984 | Tag.TypeEnum.Bits, | |
| 10549 | 9985 | => @bitCast(@field(item, field.name)), |
| 10550 | 9986 | |
| 10551 | 9987 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| ... | ... | @@ -10607,8 +10043,10 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat |
| 10607 | 10043 | Tag.TypePointer.PackedOffset, |
| 10608 | 10044 | Tag.TypeUnion.Flags, |
| 10609 | 10045 | Tag.TypeStruct.Flags, |
| 10610 | Tag.TypeStructPacked.Flags, | |
| 10611 | 10046 | FuncAnalysis, |
| 10047 | Tag.TypeStructPacked.Bits, | |
| 10048 | Tag.TypeUnionPacked.Bits, | |
| 10049 | Tag.TypeEnum.Bits, | |
| 10612 | 10050 | => @bitCast(extra_item), |
| 10613 | 10051 | |
| 10614 | 10052 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| ... | ... | @@ -10786,7 +10224,7 @@ pub fn getCoerced( |
| 10786 | 10224 | .int => |int| switch (ip.indexToKey(new_ty)) { |
| 10787 | 10225 | .enum_type => return ip.get(gpa, io, tid, .{ .enum_tag = .{ |
| 10788 | 10226 | .ty = new_ty, |
| 10789 | .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).tag_ty), | |
| 10227 | .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).int_tag_type), | |
| 10790 | 10228 | } }), |
| 10791 | 10229 | .ptr_type => switch (int.storage) { |
| 10792 | 10230 | inline .u64, .i64 => |int_val| return ip.get(gpa, io, tid, .{ .ptr = .{ |
| ... | ... | @@ -10795,7 +10233,6 @@ pub fn getCoerced( |
| 10795 | 10233 | .byte_offset = @intCast(int_val), |
| 10796 | 10234 | } }), |
| 10797 | 10235 | .big_int => unreachable, // must be a usize |
| 10798 | .lazy_align, .lazy_size => {}, | |
| 10799 | 10236 | }, |
| 10800 | 10237 | else => if (ip.isIntegerType(new_ty)) |
| 10801 | 10238 | return ip.getCoercedInts(gpa, io, tid, int, new_ty), |
| ... | ... | @@ -10825,11 +10262,11 @@ pub fn getCoerced( |
| 10825 | 10262 | const index = enum_type.nameIndex(ip, enum_literal).?; |
| 10826 | 10263 | return ip.get(gpa, io, tid, .{ .enum_tag = .{ |
| 10827 | 10264 | .ty = new_ty, |
| 10828 | .int = if (enum_type.values.len != 0) | |
| 10829 | enum_type.values.get(ip)[index] | |
| 10265 | .int = if (enum_type.field_values.len != 0) | |
| 10266 | enum_type.field_values.get(ip)[index] | |
| 10830 | 10267 | else |
| 10831 | 10268 | try ip.get(gpa, io, tid, .{ .int = .{ |
| 10832 | .ty = enum_type.tag_ty, | |
| 10269 | .ty = enum_type.int_tag_type, | |
| 10833 | 10270 | .storage = .{ .u64 = index }, |
| 10834 | 10271 | } }), |
| 10835 | 10272 | } }); |
| ... | ... | @@ -11193,10 +10630,78 @@ pub fn dump(ip: *const InternPool) void { |
| 11193 | 10630 | const stderr = std.debug.lockStderr(&buffer); |
| 11194 | 10631 | defer std.debug.unlockStderr(); |
| 11195 | 10632 | const w = &stderr.file_writer.interface; |
| 10633 | dumpDependencyStatsFallible(ip, w) catch return; | |
| 11196 | 10634 | dumpStatsFallible(ip, w, std.heap.page_allocator) catch return; |
| 11197 | 10635 | dumpAllFallible(ip, w) catch return; |
| 11198 | 10636 | } |
| 11199 | 10637 | |
| 10638 | fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { | |
| 10639 | const dep_entries_len = ip.dep_entries.items.len - ip.free_dep_entries.items.len; | |
| 10640 | const src_hash_deps_len = ip.src_hash_deps.count(); | |
| 10641 | const nav_val_deps_len = ip.nav_val_deps.count(); | |
| 10642 | const nav_ty_deps_len = ip.nav_ty_deps.count(); | |
| 10643 | const func_ies_deps_len = ip.func_ies_deps.count(); | |
| 10644 | const type_layout_deps_len = ip.type_layout_deps.count(); | |
| 10645 | const struct_defaults_deps_len = ip.struct_defaults_deps.count(); | |
| 10646 | const zon_file_deps_len = ip.zon_file_deps.count(); | |
| 10647 | const embed_file_deps_len = ip.embed_file_deps.count(); | |
| 10648 | const namespace_deps_len = ip.namespace_deps.count(); | |
| 10649 | const namespace_name_deps_len = ip.namespace_name_deps.count(); | |
| 10650 | const dep_entries_size = dep_entries_len * @sizeOf(DepEntry); | |
| 10651 | const src_hash_deps_size = src_hash_deps_len * 8; | |
| 10652 | const nav_val_deps_size = nav_val_deps_len * 8; | |
| 10653 | const nav_ty_deps_size = nav_ty_deps_len * 8; | |
| 10654 | const func_ies_deps_size = func_ies_deps_len * 8; | |
| 10655 | const type_layout_deps_size = type_layout_deps_len * 8; | |
| 10656 | const struct_defaults_deps_size = struct_defaults_deps_len * 8; | |
| 10657 | const zon_file_deps_size = zon_file_deps_len * 8; | |
| 10658 | const embed_file_deps_size = embed_file_deps_len * 8; | |
| 10659 | const namespace_deps_size = namespace_deps_len * 8; | |
| 10660 | const namespace_name_deps_size = namespace_name_deps_len * (@sizeOf(NamespaceNameKey) + 4); | |
| 10661 | ||
| 10662 | try w.print( | |
| 10663 | \\InternPool dependencies: {d} bytes | |
| 10664 | \\ {d} entries: {d} bytes | |
| 10665 | \\ {d} src_hash: {d} bytes | |
| 10666 | \\ {d} nav_val: {d} bytes | |
| 10667 | \\ {d} nav_ty: {d} bytes | |
| 10668 | \\ {d} func_ies: {d} bytes | |
| 10669 | \\ {d} type_layout: {d} bytes | |
| 10670 | \\ {d} struct_defaults: {d} bytes | |
| 10671 | \\ {d} zon_file: {d} bytes | |
| 10672 | \\ {d} embed_file: {d} bytes | |
| 10673 | \\ {d} namespace: {d} bytes | |
| 10674 | \\ {d} namespace_name: {d} bytes | |
| 10675 | \\ | |
| 10676 | , .{ | |
| 10677 | dep_entries_size + src_hash_deps_size + nav_val_deps_size + nav_ty_deps_size + | |
| 10678 | func_ies_deps_size + type_layout_deps_size + struct_defaults_deps_size + zon_file_deps_size + | |
| 10679 | embed_file_deps_size + namespace_deps_size + namespace_name_deps_size, | |
| 10680 | dep_entries_len, | |
| 10681 | dep_entries_size, | |
| 10682 | src_hash_deps_len, | |
| 10683 | src_hash_deps_size, | |
| 10684 | nav_val_deps_len, | |
| 10685 | nav_val_deps_size, | |
| 10686 | nav_ty_deps_len, | |
| 10687 | nav_ty_deps_size, | |
| 10688 | func_ies_deps_len, | |
| 10689 | func_ies_deps_size, | |
| 10690 | type_layout_deps_len, | |
| 10691 | type_layout_deps_size, | |
| 10692 | struct_defaults_deps_len, | |
| 10693 | struct_defaults_deps_size, | |
| 10694 | zon_file_deps_len, | |
| 10695 | zon_file_deps_size, | |
| 10696 | embed_file_deps_len, | |
| 10697 | embed_file_deps_size, | |
| 10698 | namespace_deps_len, | |
| 10699 | namespace_deps_size, | |
| 10700 | namespace_name_deps_len, | |
| 10701 | namespace_name_deps_size, | |
| 10702 | }); | |
| 10703 | } | |
| 10704 | ||
| 11200 | 10705 | fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !void { |
| 11201 | 10706 | var items_len: usize = 0; |
| 11202 | 10707 | var extra_len: usize = 0; |
| ... | ... | @@ -11211,10 +10716,10 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 11211 | 10716 | const limbs_size = 8 * limbs_len; |
| 11212 | 10717 | |
| 11213 | 10718 | // TODO: map overhead size is not taken into account |
| 11214 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size; | |
| 10719 | const total_size = items_size + extra_size + limbs_size; | |
| 11215 | 10720 | |
| 11216 | std.debug.print( | |
| 11217 | \\InternPool size: {d} bytes | |
| 10721 | try w.print( | |
| 10722 | \\InternPool values: {d} bytes | |
| 11218 | 10723 | \\ {d} items: {d} bytes |
| 11219 | 10724 | \\ {d} extra: {d} bytes |
| 11220 | 10725 | \\ {d} limbs: {d} bytes |
| ... | ... | @@ -11235,6 +10740,8 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 11235 | 10740 | }; |
| 11236 | 10741 | var counts = std.AutoArrayHashMap(Tag, TagStats).init(arena); |
| 11237 | 10742 | for (ip.locals) |*local| { |
| 10743 | // Early check for length 0, because `view()` is invalid if capacity is 0 | |
| 10744 | if (local.mutate.items.len == 0) continue; | |
| 11238 | 10745 | const items = local.shared.items.view().slice(); |
| 11239 | 10746 | const extra_list = local.shared.extra; |
| 11240 | 10747 | const extra_items = extra_list.view().items(.@"0"); |
| ... | ... | @@ -11266,98 +10773,137 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 11266 | 10773 | break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); |
| 11267 | 10774 | }, |
| 11268 | 10775 | .type_inferred_error_set => 0, |
| 11269 | .type_enum_explicit, .type_enum_nonexhaustive => b: { | |
| 11270 | const info = extraData(extra_list, EnumExplicit, data); | |
| 11271 | var ints = @typeInfo(EnumExplicit).@"struct".fields.len; | |
| 11272 | if (info.zir_index == .none) ints += 1; | |
| 11273 | ints += if (info.captures_len != std.math.maxInt(u32)) | |
| 11274 | info.captures_len | |
| 11275 | else | |
| 11276 | @typeInfo(PackedU64).@"struct".fields.len; | |
| 11277 | ints += info.fields_len; | |
| 11278 | if (info.values_map != .none) ints += info.fields_len; | |
| 11279 | break :b @sizeOf(u32) * ints; | |
| 11280 | }, | |
| 11281 | .type_enum_auto => b: { | |
| 11282 | const info = extraData(extra_list, EnumAuto, data); | |
| 11283 | const ints = @typeInfo(EnumAuto).@"struct".fields.len + info.captures_len + info.fields_len; | |
| 11284 | break :b @sizeOf(u32) * ints; | |
| 10776 | .type_tuple => b: { | |
| 10777 | const info = extraData(extra_list, TypeTuple, data); | |
| 10778 | break :b @sizeOf(TypeTuple) + (@sizeOf(u32) * 2 * info.fields_len); | |
| 11285 | 10779 | }, |
| 11286 | .type_opaque => b: { | |
| 11287 | const info = extraData(extra_list, Tag.TypeOpaque, data); | |
| 11288 | const ints = @typeInfo(Tag.TypeOpaque).@"struct".fields.len + info.captures_len; | |
| 11289 | break :b @sizeOf(u32) * ints; | |
| 10780 | .type_function => b: { | |
| 10781 | const info = extraData(extra_list, Tag.TypeFunction, data); | |
| 10782 | break :b @sizeOf(Tag.TypeFunction) + | |
| 10783 | (@sizeOf(Index) * info.params_len) + | |
| 10784 | (@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) + | |
| 10785 | (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits)); | |
| 11290 | 10786 | }, |
| 10787 | ||
| 11291 | 10788 | .type_struct => b: { |
| 10789 | var n: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len; | |
| 11292 | 10790 | const extra = extraDataTrail(extra_list, Tag.TypeStruct, data); |
| 11293 | const info = extra.data; | |
| 11294 | var ints: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len; | |
| 11295 | if (info.flags.any_captures) { | |
| 11296 | const captures_len = extra_items[extra.end]; | |
| 11297 | ints += 1 + captures_len; | |
| 10791 | switch (extra.data.flags.any_captures) { | |
| 10792 | .reified => n += 2, // type_hash: PackedU64 | |
| 10793 | .true => { | |
| 10794 | n += 1; // captures_len: u32 | |
| 10795 | n += extra_items[extra.end]; // capture: CaptureValue | |
| 10796 | }, | |
| 10797 | .false => {}, | |
| 10798 | } | |
| 10799 | n += extra.data.fields_len; // field_name: NullTerminatedString | |
| 10800 | n += extra.data.fields_len; // field_type: Index | |
| 10801 | if (extra.data.flags.any_field_defaults) { | |
| 10802 | n += extra.data.fields_len; // field_default: Index | |
| 10803 | } | |
| 10804 | if (extra.data.flags.any_field_aligns) { | |
| 10805 | n += (extra.data.fields_len + 3) / 4; // field_align: Alignment | |
| 11298 | 10806 | } |
| 11299 | ints += info.fields_len; // types | |
| 11300 | ints += 1; // names_map | |
| 11301 | ints += info.fields_len; // names | |
| 11302 | if (info.flags.any_default_inits) | |
| 11303 | ints += info.fields_len; // inits | |
| 11304 | if (info.flags.any_aligned_fields) | |
| 11305 | ints += (info.fields_len + 3) / 4; // aligns | |
| 11306 | if (info.flags.any_comptime_fields) | |
| 11307 | ints += (info.fields_len + 31) / 32; // comptime bits | |
| 11308 | if (!info.flags.is_extern) | |
| 11309 | ints += info.fields_len; // runtime order | |
| 11310 | ints += info.fields_len; // offsets | |
| 11311 | break :b @sizeOf(u32) * ints; | |
| 10807 | if (extra.data.flags.any_comptime_fields) { | |
| 10808 | n += (extra.data.fields_len + 31) / 32; // field_is_comptime_bits: u32 | |
| 10809 | } | |
| 10810 | if (extra.data.flags.layout == .auto) { | |
| 10811 | n += extra.data.fields_len; // field_runtime_order: RuntimeOrder | |
| 10812 | } | |
| 10813 | n += extra.data.fields_len; // field_offset: u32 | |
| 10814 | break :b n * @sizeOf(u32); | |
| 11312 | 10815 | }, |
| 11313 | .type_struct_packed => b: { | |
| 10816 | .type_struct_packed_auto, .type_struct_packed_explicit => b: { | |
| 10817 | var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len; | |
| 11314 | 10818 | const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); |
| 11315 | const captures_len = if (extra.data.flags.any_captures) | |
| 11316 | extra_items[extra.end] | |
| 11317 | else | |
| 11318 | 0; | |
| 11319 | break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + | |
| 11320 | @intFromBool(extra.data.flags.any_captures) + captures_len + | |
| 11321 | extra.data.fields_len * 2); | |
| 10819 | switch (extra.data.bits.captures_len) { | |
| 10820 | .reified => n += 2, // type_hash: PackedU64 | |
| 10821 | _ => |len| n += @intFromEnum(len), // capture: CaptureValue | |
| 10822 | } | |
| 10823 | n += extra.data.fields_len; // field_name: NullTerminatedString | |
| 10824 | n += extra.data.fields_len; // field_type: Index | |
| 10825 | break :b n * @sizeOf(u32); | |
| 11322 | 10826 | }, |
| 11323 | .type_struct_packed_inits => b: { | |
| 10827 | .type_struct_packed_auto_defaults, .type_struct_packed_explicit_defaults => b: { | |
| 10828 | var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len; | |
| 11324 | 10829 | const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); |
| 11325 | const captures_len = if (extra.data.flags.any_captures) | |
| 11326 | extra_items[extra.end] | |
| 11327 | else | |
| 11328 | 0; | |
| 11329 | break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + | |
| 11330 | @intFromBool(extra.data.flags.any_captures) + captures_len + | |
| 11331 | extra.data.fields_len * 3); | |
| 11332 | }, | |
| 11333 | .type_tuple => b: { | |
| 11334 | const info = extraData(extra_list, TypeTuple, data); | |
| 11335 | break :b @sizeOf(TypeTuple) + (@sizeOf(u32) * 2 * info.fields_len); | |
| 10830 | switch (extra.data.bits.captures_len) { | |
| 10831 | .reified => n += 2, // type_hash: PackedU64 | |
| 10832 | _ => |len| n += @intFromEnum(len), // capture: CaptureValue | |
| 10833 | } | |
| 10834 | n += extra.data.fields_len; // field_name: NullTerminatedString | |
| 10835 | n += extra.data.fields_len; // field_type: Index | |
| 10836 | n += extra.data.fields_len; // field_default: Index | |
| 10837 | break :b n * @sizeOf(u32); | |
| 11336 | 10838 | }, |
| 11337 | ||
| 11338 | 10839 | .type_union => b: { |
| 10840 | var n: usize = @typeInfo(Tag.TypeUnion).@"struct".fields.len; | |
| 11339 | 10841 | const extra = extraDataTrail(extra_list, Tag.TypeUnion, data); |
| 11340 | const captures_len = if (extra.data.flags.any_captures) | |
| 11341 | extra_items[extra.end] | |
| 11342 | else | |
| 11343 | 0; | |
| 11344 | const per_field = @sizeOf(u32); // field type | |
| 11345 | // 1 byte per field for alignment, rounded up to the nearest 4 bytes | |
| 11346 | const alignments = if (extra.data.flags.any_aligned_fields) | |
| 11347 | ((extra.data.fields_len + 3) / 4) * 4 | |
| 11348 | else | |
| 11349 | 0; | |
| 11350 | break :b @sizeOf(Tag.TypeUnion) + | |
| 11351 | 4 * (@intFromBool(extra.data.flags.any_captures) + captures_len) + | |
| 11352 | (extra.data.fields_len * per_field) + alignments; | |
| 10842 | switch (extra.data.flags.any_captures) { | |
| 10843 | .reified => n += 2, // type_hash: PackedU64 | |
| 10844 | .true => { | |
| 10845 | n += 1; // captures_len: u32 | |
| 10846 | n += extra_items[extra.end]; // capture: CaptureValue | |
| 10847 | }, | |
| 10848 | .false => {}, | |
| 10849 | } | |
| 10850 | n += extra.data.fields_len; // field_type: Index | |
| 10851 | if (extra.data.flags.any_field_aligns) { | |
| 10852 | n += (extra.data.fields_len + 3) / 4; // field_align: Alignment | |
| 10853 | } | |
| 10854 | break :b n * @sizeOf(u32); | |
| 11353 | 10855 | }, |
| 11354 | ||
| 11355 | .type_function => b: { | |
| 11356 | const info = extraData(extra_list, Tag.TypeFunction, data); | |
| 11357 | break :b @sizeOf(Tag.TypeFunction) + | |
| 11358 | (@sizeOf(Index) * info.params_len) + | |
| 11359 | (@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) + | |
| 11360 | (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits)); | |
| 10856 | .type_union_packed_auto, .type_union_packed_explicit => b: { | |
| 10857 | var n: usize = @typeInfo(Tag.TypeUnionPacked).@"struct".fields.len; | |
| 10858 | const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); | |
| 10859 | switch (extra.data.bits.captures_len) { | |
| 10860 | .reified => n += 2, // type_hash: PackedU64 | |
| 10861 | _ => |len| n += @intFromEnum(len), // capture: CaptureValue | |
| 10862 | } | |
| 10863 | n += extra.data.fields_len; // field_type: Index | |
| 10864 | break :b n * @sizeOf(u32); | |
| 10865 | }, | |
| 10866 | .type_enum_auto => b: { | |
| 10867 | var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; | |
| 10868 | const extra = extraData(extra_list, Tag.TypeEnum, data); | |
| 10869 | switch (extra.bits.captures_len) { | |
| 10870 | .generated_union_tag => n += 1, // owner_union: Index | |
| 10871 | .reified => { | |
| 10872 | n += 1; // zir_index: TrackedInst.Index, | |
| 10873 | n += 2; // type_hash: PackedU64 | |
| 10874 | }, | |
| 10875 | _ => |len| { | |
| 10876 | n += 1; // zir_index: TrackedInst.Index, | |
| 10877 | n += @intFromEnum(len); // capture: CaptureValue | |
| 10878 | }, | |
| 10879 | } | |
| 10880 | n += extra.fields_len; // field_name: NullTerminatedString | |
| 10881 | break :b n * @sizeOf(u32); | |
| 10882 | }, | |
| 10883 | .type_enum_explicit, .type_enum_nonexhaustive => b: { | |
| 10884 | var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; | |
| 10885 | const extra = extraData(extra_list, Tag.TypeEnum, data); | |
| 10886 | switch (extra.bits.captures_len) { | |
| 10887 | .generated_union_tag => n += 1, // owner_union: Index | |
| 10888 | .reified => { | |
| 10889 | n += 1; // zir_index: TrackedInst.Index, | |
| 10890 | n += 2; // type_hash: PackedU64 | |
| 10891 | }, | |
| 10892 | _ => |len| { | |
| 10893 | n += 1; // zir_index: TrackedInst.Index, | |
| 10894 | n += @intFromEnum(len); // capture: CaptureValue | |
| 10895 | }, | |
| 10896 | } | |
| 10897 | n += 1; // field_value_map: MapIndex | |
| 10898 | n += extra.fields_len; // field_name: NullTerminatedString | |
| 10899 | n += extra.fields_len; // field_value: Index | |
| 10900 | break :b n * @sizeOf(u32); | |
| 10901 | }, | |
| 10902 | .type_opaque => b: { | |
| 10903 | var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; | |
| 10904 | const extra = extraData(extra_list, Tag.TypeOpaque, data); | |
| 10905 | n += extra.captures_len; // capture: CaptureValue | |
| 10906 | break :b n * @sizeOf(u32); | |
| 11361 | 10907 | }, |
| 11362 | 10908 | |
| 11363 | 10909 | .undef => 0, |
| ... | ... | @@ -11393,8 +10939,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 11393 | 10939 | break :b @sizeOf(Int) + int.limbs_len * @sizeOf(Limb); |
| 11394 | 10940 | }, |
| 11395 | 10941 | |
| 11396 | .int_lazy_align, .int_lazy_size => @sizeOf(IntLazy), | |
| 11397 | ||
| 11398 | 10942 | .error_set_error, .error_union_error => @sizeOf(Key.Error), |
| 11399 | 10943 | .error_union_payload => @sizeOf(Tag.TypeValue), |
| 11400 | 10944 | .enum_literal => 0, |
| ... | ... | @@ -11432,6 +10976,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 11432 | 10976 | .func_coerced => @sizeOf(Tag.FuncCoerced), |
| 11433 | 10977 | .only_possible_value => 0, |
| 11434 | 10978 | .union_value => @sizeOf(Key.Union), |
| 10979 | .bitpack => 2 * @sizeOf(u32), | |
| 11435 | 10980 | |
| 11436 | 10981 | .memoized_call => b: { |
| 11437 | 10982 | const info = extraData(extra_list, MemoizedCall, data); |
| ... | ... | @@ -11458,6 +11003,8 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 11458 | 11003 | |
| 11459 | 11004 | fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { |
| 11460 | 11005 | for (ip.locals, 0..) |*local, tid| { |
| 11006 | // Early check for length 0, because `view()` is invalid if capacity is 0 | |
| 11007 | if (local.mutate.items.len == 0) continue; | |
| 11461 | 11008 | const items = local.shared.items.view(); |
| 11462 | 11009 | for ( |
| 11463 | 11010 | items.items(.tag)[0..local.mutate.items.len], |
| ... | ... | @@ -11484,16 +11031,20 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { |
| 11484 | 11031 | .type_anyerror_union, |
| 11485 | 11032 | .type_error_set, |
| 11486 | 11033 | .type_inferred_error_set, |
| 11034 | .type_tuple, | |
| 11035 | .type_function, | |
| 11036 | .type_struct, | |
| 11037 | .type_struct_packed_auto, | |
| 11038 | .type_struct_packed_explicit, | |
| 11039 | .type_struct_packed_auto_defaults, | |
| 11040 | .type_struct_packed_explicit_defaults, | |
| 11041 | .type_union, | |
| 11042 | .type_union_packed_auto, | |
| 11043 | .type_union_packed_explicit, | |
| 11044 | .type_enum_auto, | |
| 11487 | 11045 | .type_enum_explicit, |
| 11488 | 11046 | .type_enum_nonexhaustive, |
| 11489 | .type_enum_auto, | |
| 11490 | 11047 | .type_opaque, |
| 11491 | .type_struct, | |
| 11492 | .type_struct_packed, | |
| 11493 | .type_struct_packed_inits, | |
| 11494 | .type_tuple, | |
| 11495 | .type_union, | |
| 11496 | .type_function, | |
| 11497 | 11048 | .undef, |
| 11498 | 11049 | .ptr_nav, |
| 11499 | 11050 | .ptr_comptime_alloc, |
| ... | ... | @@ -11517,8 +11068,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { |
| 11517 | 11068 | .int_small, |
| 11518 | 11069 | .int_positive, |
| 11519 | 11070 | .int_negative, |
| 11520 | .int_lazy_align, | |
| 11521 | .int_lazy_size, | |
| 11522 | 11071 | .error_set_error, |
| 11523 | 11072 | .error_union_error, |
| 11524 | 11073 | .error_union_payload, |
| ... | ... | @@ -11542,6 +11091,7 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { |
| 11542 | 11091 | .func_instance, |
| 11543 | 11092 | .func_coerced, |
| 11544 | 11093 | .union_value, |
| 11094 | .bitpack, | |
| 11545 | 11095 | .memoized_call, |
| 11546 | 11096 | => try w.print("{d}", .{data}), |
| 11547 | 11097 | |
| ... | ... | @@ -11581,7 +11131,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, |
| 11581 | 11131 | const info = extraData(extra_list, Tag.FuncInstance, data); |
| 11582 | 11132 | |
| 11583 | 11133 | const gop = try instances.getOrPut(arena, info.generic_owner); |
| 11584 | if (!gop.found_existing) gop.value_ptr.* = .{}; | |
| 11134 | if (!gop.found_existing) gop.value_ptr.* = .empty; | |
| 11585 | 11135 | |
| 11586 | 11136 | try gop.value_ptr.append( |
| 11587 | 11137 | arena, |
| ... | ... | @@ -11722,6 +11272,7 @@ pub fn createDeclNav( |
| 11722 | 11272 | .analysis = .{ |
| 11723 | 11273 | .namespace = namespace, |
| 11724 | 11274 | .zir_index = zir_index, |
| 11275 | .wanted = false, | |
| 11725 | 11276 | }, |
| 11726 | 11277 | .status = .unresolved, |
| 11727 | 11278 | })); |
| ... | ... | @@ -12245,16 +11796,20 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 12245 | 11796 | .type_anyerror_union, |
| 12246 | 11797 | .type_error_set, |
| 12247 | 11798 | .type_inferred_error_set, |
| 11799 | .type_tuple, | |
| 11800 | .type_function, | |
| 11801 | .type_struct, | |
| 11802 | .type_struct_packed_auto, | |
| 11803 | .type_struct_packed_explicit, | |
| 11804 | .type_struct_packed_auto_defaults, | |
| 11805 | .type_struct_packed_explicit_defaults, | |
| 11806 | .type_union, | |
| 11807 | .type_union_packed_auto, | |
| 11808 | .type_union_packed_explicit, | |
| 12248 | 11809 | .type_enum_auto, |
| 12249 | 11810 | .type_enum_explicit, |
| 12250 | 11811 | .type_enum_nonexhaustive, |
| 12251 | 11812 | .type_opaque, |
| 12252 | .type_struct, | |
| 12253 | .type_struct_packed, | |
| 12254 | .type_struct_packed_inits, | |
| 12255 | .type_tuple, | |
| 12256 | .type_union, | |
| 12257 | .type_function, | |
| 12258 | 11813 | => .type_type, |
| 12259 | 11814 | |
| 12260 | 11815 | .undef, |
| ... | ... | @@ -12278,8 +11833,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 12278 | 11833 | .opt_payload, |
| 12279 | 11834 | .error_union_payload, |
| 12280 | 11835 | .int_small, |
| 12281 | .int_lazy_align, | |
| 12282 | .int_lazy_size, | |
| 12283 | 11836 | .error_set_error, |
| 12284 | 11837 | .error_union_error, |
| 12285 | 11838 | .enum_tag, |
| ... | ... | @@ -12293,6 +11846,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 12293 | 11846 | .bytes, |
| 12294 | 11847 | .aggregate, |
| 12295 | 11848 | .repeated, |
| 11849 | .bitpack, | |
| 12296 | 11850 | => |t| { |
| 12297 | 11851 | const extra_list = unwrapped_index.getExtra(ip); |
| 12298 | 11852 | return @enumFromInt(extra_list.view().items(.@"0")[item.data + std.meta.fieldIndex(t.Payload(), "ty").?]); |
| ... | ... | @@ -12389,20 +11943,6 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index { |
| 12389 | 11943 | ]); |
| 12390 | 11944 | } |
| 12391 | 11945 | |
| 12392 | pub fn isNoReturn(ip: *const InternPool, ty: Index) bool { | |
| 12393 | switch (ty) { | |
| 12394 | .noreturn_type => return true, | |
| 12395 | else => { | |
| 12396 | const unwrapped_ty = ty.unwrap(ip); | |
| 12397 | const ty_item = unwrapped_ty.getItem(ip); | |
| 12398 | return switch (ty_item.tag) { | |
| 12399 | .type_error_set => unwrapped_ty.getExtra(ip).view().items(.@"0")[ty_item.data + std.meta.fieldIndex(Tag.ErrorSet, "names_len").?] == 0, | |
| 12400 | else => false, | |
| 12401 | }; | |
| 12402 | }, | |
| 12403 | } | |
| 12404 | } | |
| 12405 | ||
| 12406 | 11946 | pub fn isUndef(ip: *const InternPool, val: Index) bool { |
| 12407 | 11947 | return val == .undef or val.unwrap(ip).getTag(ip) == .undef; |
| 12408 | 11948 | } |
| ... | ... | @@ -12613,22 +12153,26 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12613 | 12153 | .type_inferred_error_set, |
| 12614 | 12154 | => .error_set, |
| 12615 | 12155 | |
| 12616 | .type_enum_auto, | |
| 12617 | .type_enum_explicit, | |
| 12618 | .type_enum_nonexhaustive, | |
| 12619 | => .@"enum", | |
| 12620 | ||
| 12621 | 12156 | .simple_type => unreachable, // handled via Index tag above |
| 12622 | 12157 | |
| 12623 | .type_opaque => .@"opaque", | |
| 12158 | .type_tuple => .@"struct", | |
| 12624 | 12159 | |
| 12625 | 12160 | .type_struct, |
| 12626 | .type_struct_packed, | |
| 12627 | .type_struct_packed_inits, | |
| 12628 | .type_tuple, | |
| 12161 | .type_struct_packed_auto, | |
| 12162 | .type_struct_packed_explicit, | |
| 12163 | .type_struct_packed_auto_defaults, | |
| 12164 | .type_struct_packed_explicit_defaults, | |
| 12629 | 12165 | => .@"struct", |
| 12630 | ||
| 12631 | .type_union => .@"union", | |
| 12166 | .type_union, | |
| 12167 | .type_union_packed_auto, | |
| 12168 | .type_union_packed_explicit, | |
| 12169 | => .@"union", | |
| 12170 | .type_enum_auto, | |
| 12171 | .type_enum_explicit, | |
| 12172 | .type_enum_nonexhaustive, | |
| 12173 | => .@"enum", | |
| 12174 | .type_opaque, | |
| 12175 | => .@"opaque", | |
| 12632 | 12176 | |
| 12633 | 12177 | .type_function => .@"fn", |
| 12634 | 12178 | |
| ... | ... | @@ -12658,8 +12202,6 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12658 | 12202 | .int_small, |
| 12659 | 12203 | .int_positive, |
| 12660 | 12204 | .int_negative, |
| 12661 | .int_lazy_align, | |
| 12662 | .int_lazy_size, | |
| 12663 | 12205 | .error_set_error, |
| 12664 | 12206 | .error_union_error, |
| 12665 | 12207 | .error_union_payload, |
| ... | ... | @@ -12684,6 +12226,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12684 | 12226 | .bytes, |
| 12685 | 12227 | .aggregate, |
| 12686 | 12228 | .repeated, |
| 12229 | .bitpack, | |
| 12687 | 12230 | // memoization, not types |
| 12688 | 12231 | .memoized_call, |
| 12689 | 12232 | => unreachable, |
| ... | ... | @@ -12871,22 +12414,42 @@ pub fn unwrapCoercedFunc(ip: *const InternPool, index: Index) Index { |
| 12871 | 12414 | }; |
| 12872 | 12415 | } |
| 12873 | 12416 | |
| 12874 | /// Returns the already-existing field with the same name, if any. | |
| 12417 | /// Puts `name` into `names_slice` at the next index (that being the current length of `map`). | |
| 12418 | /// Also inserts the name into `map`. If there is an existing field with this name, its index | |
| 12419 | /// is returned. Otherwise, `null` is returned. | |
| 12875 | 12420 | pub fn addFieldName( |
| 12876 | 12421 | ip: *InternPool, |
| 12877 | extra: Local.Extra, | |
| 12878 | names_map: MapIndex, | |
| 12879 | names_start: u32, | |
| 12422 | names: NullTerminatedString.Slice, | |
| 12423 | map: MapIndex, | |
| 12880 | 12424 | name: NullTerminatedString, |
| 12881 | 12425 | ) ?u32 { |
| 12882 | const extra_items = extra.view().items(.@"0"); | |
| 12883 | const map = names_map.get(ip); | |
| 12884 | const field_index = map.count(); | |
| 12885 | const strings = extra_items[names_start..][0..field_index]; | |
| 12886 | const adapter: NullTerminatedString.Adapter = .{ .strings = @ptrCast(strings) }; | |
| 12887 | const gop = map.getOrPutAssumeCapacityAdapted(name, adapter); | |
| 12426 | const m = map.get(ip); | |
| 12427 | const field_idx = m.count(); | |
| 12428 | const names_slice = names.get(ip); | |
| 12429 | names_slice[field_idx] = name; | |
| 12430 | const adapter: NullTerminatedString.Adapter = .{ .strings = names_slice[0..field_idx] }; | |
| 12431 | const gop = m.getOrPutAssumeCapacityAdapted(name, adapter); | |
| 12888 | 12432 | if (gop.found_existing) return @intCast(gop.index); |
| 12889 | extra_items[names_start + field_index] = @intFromEnum(name); | |
| 12433 | assert(gop.index == field_idx); | |
| 12434 | return null; | |
| 12435 | } | |
| 12436 | ||
| 12437 | /// Like `addFieldName`, but instead of adding a field name to a struct, union, or enum, adds a | |
| 12438 | /// field tag value for an enum. | |
| 12439 | pub fn addFieldTagValue( | |
| 12440 | ip: *InternPool, | |
| 12441 | values: Index.Slice, | |
| 12442 | map: MapIndex, | |
| 12443 | value: Index, | |
| 12444 | ) ?u32 { | |
| 12445 | const m = map.get(ip); | |
| 12446 | const field_idx = m.count(); | |
| 12447 | const values_slice = values.get(ip); | |
| 12448 | values_slice[field_idx] = value; | |
| 12449 | const adapter: Index.Adapter = .{ .indexes = values_slice[0..field_idx] }; | |
| 12450 | const gop = m.getOrPutAssumeCapacityAdapted(value, adapter); | |
| 12451 | if (gop.found_existing) return @intCast(gop.index); | |
| 12452 | assert(gop.index == field_idx); | |
| 12890 | 12453 | return null; |
| 12891 | 12454 | } |
| 12892 | 12455 | |
| ... | ... | @@ -13169,3 +12732,275 @@ const PackedCallingConvention = packed struct(u18) { |
| 13169 | 12732 | }; |
| 13170 | 12733 | } |
| 13171 | 12734 | }; |
| 12735 | ||
| 12736 | /// Asserts that `struct_type` is a non-packed struct type. | |
| 12737 | /// As well as calling this function, the caller must also populate these arrays: | |
| 12738 | /// * `field_types` | |
| 12739 | /// * `field_aligns` | |
| 12740 | /// * `field_runtime_order` | |
| 12741 | /// * `field_offsets` | |
| 12742 | pub fn resolveStructLayout( | |
| 12743 | ip: *InternPool, | |
| 12744 | io: Io, | |
| 12745 | struct_type: Index, | |
| 12746 | size: u32, | |
| 12747 | alignment: Alignment, | |
| 12748 | class: TypeClass, | |
| 12749 | ) void { | |
| 12750 | const unwrapped_index = struct_type.unwrap(ip); | |
| 12751 | ||
| 12752 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12753 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12754 | defer local.mutate.extra.mutex.unlock(io); | |
| 12755 | ||
| 12756 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 12757 | const item = unwrapped_index.getItem(ip); | |
| 12758 | assert(item.tag == .type_struct); | |
| 12759 | ||
| 12760 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "size").?] = size; | |
| 12761 | const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?]); | |
| 12762 | flags.class = class; | |
| 12763 | flags.alignment = alignment; | |
| 12764 | } | |
| 12765 | ||
| 12766 | /// Asserts that `union_type` is a non-packed union type. | |
| 12767 | /// As well as calling this function, the caller must also populate these arrays: | |
| 12768 | /// * `field_types` | |
| 12769 | /// * `field_aligns` | |
| 12770 | pub fn resolveUnionLayout( | |
| 12771 | ip: *InternPool, | |
| 12772 | io: Io, | |
| 12773 | union_type: Index, | |
| 12774 | enum_tag_type: Index, | |
| 12775 | class: TypeClass, | |
| 12776 | has_runtime_tag: bool, | |
| 12777 | size: u32, | |
| 12778 | padding: u32, | |
| 12779 | alignment: Alignment, | |
| 12780 | ) void { | |
| 12781 | const unwrapped_index = union_type.unwrap(ip); | |
| 12782 | ||
| 12783 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12784 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12785 | defer local.mutate.extra.mutex.unlock(io); | |
| 12786 | ||
| 12787 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 12788 | const item = unwrapped_index.getItem(ip); | |
| 12789 | assert(item.tag == .type_union); | |
| 12790 | ||
| 12791 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "enum_tag_type").?] = @intFromEnum(enum_tag_type); | |
| 12792 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "size").?] = size; | |
| 12793 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "padding").?] = padding; | |
| 12794 | const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").?]); | |
| 12795 | flags.class = class; | |
| 12796 | flags.has_runtime_tag = has_runtime_tag; | |
| 12797 | flags.alignment = alignment; | |
| 12798 | } | |
| 12799 | ||
| 12800 | /// Asserts that `struct_type` is a packed struct type. | |
| 12801 | pub fn resolvePackedStructLayout( | |
| 12802 | ip: *InternPool, | |
| 12803 | io: Io, | |
| 12804 | struct_type: Index, | |
| 12805 | backing_int_type: Index, | |
| 12806 | ) void { | |
| 12807 | const unwrapped_index = struct_type.unwrap(ip); | |
| 12808 | ||
| 12809 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12810 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12811 | defer local.mutate.extra.mutex.unlock(io); | |
| 12812 | ||
| 12813 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 12814 | const item = unwrapped_index.getItem(ip); | |
| 12815 | switch (item.tag) { | |
| 12816 | .type_struct_packed_auto, | |
| 12817 | .type_struct_packed_explicit, | |
| 12818 | .type_struct_packed_auto_defaults, | |
| 12819 | .type_struct_packed_explicit_defaults, | |
| 12820 | => {}, | |
| 12821 | else => unreachable, | |
| 12822 | } | |
| 12823 | ||
| 12824 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_type").?] = @intFromEnum(backing_int_type); | |
| 12825 | } | |
| 12826 | ||
| 12827 | /// Asserts that `union_type` is a packed union type. | |
| 12828 | pub fn resolvePackedUnionLayout( | |
| 12829 | ip: *InternPool, | |
| 12830 | io: Io, | |
| 12831 | union_type: Index, | |
| 12832 | enum_tag_type: Index, | |
| 12833 | backing_int_type: Index, | |
| 12834 | ) void { | |
| 12835 | const unwrapped_index = union_type.unwrap(ip); | |
| 12836 | ||
| 12837 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12838 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12839 | defer local.mutate.extra.mutex.unlock(io); | |
| 12840 | ||
| 12841 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 12842 | const item = unwrapped_index.getItem(ip); | |
| 12843 | switch (item.tag) { | |
| 12844 | .type_union_packed_auto, | |
| 12845 | .type_union_packed_explicit, | |
| 12846 | => {}, | |
| 12847 | else => unreachable, | |
| 12848 | } | |
| 12849 | ||
| 12850 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "enum_tag_type").?] = @intFromEnum(enum_tag_type); | |
| 12851 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "backing_int_type").?] = @intFromEnum(backing_int_type); | |
| 12852 | } | |
| 12853 | ||
| 12854 | /// Asserts that `enum_type` is an enum type. | |
| 12855 | pub fn resolveEnumLayout( | |
| 12856 | ip: *InternPool, | |
| 12857 | io: Io, | |
| 12858 | enum_type: Index, | |
| 12859 | int_tag_type: Index, | |
| 12860 | ) void { | |
| 12861 | const unwrapped_index = enum_type.unwrap(ip); | |
| 12862 | ||
| 12863 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12864 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12865 | defer local.mutate.extra.mutex.unlock(io); | |
| 12866 | ||
| 12867 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 12868 | const item = unwrapped_index.getItem(ip); | |
| 12869 | switch (item.tag) { | |
| 12870 | .type_enum_auto, | |
| 12871 | .type_enum_explicit, | |
| 12872 | .type_enum_nonexhaustive, | |
| 12873 | => {}, | |
| 12874 | else => unreachable, | |
| 12875 | } | |
| 12876 | ||
| 12877 | extra_items[item.data + std.meta.fieldIndex(Tag.TypeEnum, "int_tag_type").?] = @intFromEnum(int_tag_type); | |
| 12878 | } | |
| 12879 | ||
| 12880 | /// Sets the "want_layout" flag on the given struct, union, or enum type. Returns true if the flag | |
| 12881 | /// was *not* already set, meaning we have just discovered the first reference to this type's | |
| 12882 | /// layout. This flag is never reset to false, and exists purely as an optimization; for details, | |
| 12883 | /// see doc comments in `LoadedStructType`. | |
| 12884 | pub fn setWantTypeLayout(ip: *InternPool, io: Io, container_type: Index) bool { | |
| 12885 | const unwrapped_index = container_type.unwrap(ip); | |
| 12886 | ||
| 12887 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12888 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12889 | defer local.mutate.extra.mutex.unlock(io); | |
| 12890 | ||
| 12891 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 12892 | const item = unwrapped_index.getItem(ip); | |
| 12893 | switch (item.tag) { | |
| 12894 | .type_struct_packed_auto, | |
| 12895 | .type_struct_packed_explicit, | |
| 12896 | .type_struct_packed_auto_defaults, | |
| 12897 | .type_struct_packed_explicit_defaults, | |
| 12898 | => { | |
| 12899 | const bits: *Tag.TypeStructPacked.Bits = @ptrCast(&extra_items[ | |
| 12900 | item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "bits").? | |
| 12901 | ]); | |
| 12902 | if (bits.want_layout) { | |
| 12903 | return false; | |
| 12904 | } else { | |
| 12905 | bits.want_layout = true; | |
| 12906 | return true; | |
| 12907 | } | |
| 12908 | }, | |
| 12909 | ||
| 12910 | .type_struct => { | |
| 12911 | const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[ | |
| 12912 | item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").? | |
| 12913 | ]); | |
| 12914 | if (flags.want_layout) { | |
| 12915 | return false; | |
| 12916 | } else { | |
| 12917 | flags.want_layout = true; | |
| 12918 | return true; | |
| 12919 | } | |
| 12920 | }, | |
| 12921 | ||
| 12922 | .type_union_packed_auto, | |
| 12923 | .type_union_packed_explicit, | |
| 12924 | => { | |
| 12925 | const bits: *Tag.TypeUnionPacked.Bits = @ptrCast(&extra_items[ | |
| 12926 | item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "bits").? | |
| 12927 | ]); | |
| 12928 | if (bits.want_layout) { | |
| 12929 | return false; | |
| 12930 | } else { | |
| 12931 | bits.want_layout = true; | |
| 12932 | return true; | |
| 12933 | } | |
| 12934 | }, | |
| 12935 | ||
| 12936 | .type_union => { | |
| 12937 | const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[ | |
| 12938 | item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").? | |
| 12939 | ]); | |
| 12940 | if (flags.want_layout) { | |
| 12941 | return false; | |
| 12942 | } else { | |
| 12943 | flags.want_layout = true; | |
| 12944 | return true; | |
| 12945 | } | |
| 12946 | }, | |
| 12947 | ||
| 12948 | .type_enum_auto, | |
| 12949 | .type_enum_explicit, | |
| 12950 | .type_enum_nonexhaustive, | |
| 12951 | => { | |
| 12952 | const bits: *Tag.TypeEnum.Bits = @ptrCast(&extra_items[ | |
| 12953 | item.data + std.meta.fieldIndex(Tag.TypeEnum, "bits").? | |
| 12954 | ]); | |
| 12955 | if (bits.want_layout) { | |
| 12956 | return false; | |
| 12957 | } else { | |
| 12958 | bits.want_layout = true; | |
| 12959 | return true; | |
| 12960 | } | |
| 12961 | }, | |
| 12962 | ||
| 12963 | else => unreachable, | |
| 12964 | } | |
| 12965 | } | |
| 12966 | ||
| 12967 | /// Like `setWantTypeLayout`, but for runtime analysis of a function body, using the | |
| 12968 | /// `FuncAnalysis.want_runtime_analysis` flag. | |
| 12969 | pub fn setWantRuntimeFnAnalysis(ip: *InternPool, io: Io, func_index: Index) bool { | |
| 12970 | const unwrapped_index = func_index.unwrap(ip); | |
| 12971 | ||
| 12972 | const local = ip.getLocal(unwrapped_index.tid); | |
| 12973 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12974 | defer local.mutate.extra.mutex.unlock(io); | |
| 12975 | ||
| 12976 | const a = funcAnalysisPtr(ip, func_index); | |
| 12977 | if (a.want_runtime_analysis) { | |
| 12978 | return false; | |
| 12979 | } else { | |
| 12980 | a.want_runtime_analysis = true; | |
| 12981 | return true; | |
| 12982 | } | |
| 12983 | } | |
| 12984 | ||
| 12985 | /// Like `setWantTypeLayout`, but for runtime analysis of a `Nav`, using the `Nav.analysis.wanted` flag. | |
| 12986 | pub fn setWantNavAnalysis(ip: *InternPool, io: Io, nav_index: Nav.Index) bool { | |
| 12987 | const unwrapped = nav_index.unwrap(ip); | |
| 12988 | ||
| 12989 | const local = ip.getLocal(unwrapped.tid); | |
| 12990 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 12991 | defer local.mutate.extra.mutex.unlock(io); | |
| 12992 | ||
| 12993 | const navs = local.shared.navs.view(); | |
| 12994 | ||
| 12995 | if (navs.items(.analysis_namespace)[unwrapped.index] == .none) { | |
| 12996 | return false; | |
| 12997 | } | |
| 12998 | ||
| 12999 | const bits = &navs.items(.bits)[unwrapped.index]; | |
| 13000 | if (bits.want_analysis) { | |
| 13001 | return false; | |
| 13002 | } else { | |
| 13003 | bits.want_analysis = true; | |
| 13004 | return true; | |
| 13005 | } | |
| 13006 | } |
src/Package/Manifest.zig+3-3| ... | ... | @@ -66,7 +66,7 @@ pub fn parse(gpa: Allocator, ast: *const Ast, rng: std.Random, options: ParseOpt |
| 66 | 66 | .gpa = gpa, |
| 67 | 67 | .ast = ast.*, |
| 68 | 68 | .arena = arena_instance.allocator(), |
| 69 | .errors = .{}, | |
| 69 | .errors = .empty, | |
| 70 | 70 | |
| 71 | 71 | .name = undefined, |
| 72 | 72 | .id = 0, |
| ... | ... | @@ -74,10 +74,10 @@ pub fn parse(gpa: Allocator, ast: *const Ast, rng: std.Random, options: ParseOpt |
| 74 | 74 | .version_node = undefined, |
| 75 | 75 | .dependencies = .{}, |
| 76 | 76 | .dependencies_node = .none, |
| 77 | .paths = .{}, | |
| 77 | .paths = .empty, | |
| 78 | 78 | .allow_missing_paths_field = options.allow_missing_paths_field, |
| 79 | 79 | .minimum_zig_version = null, |
| 80 | .buf = .{}, | |
| 80 | .buf = .empty, | |
| 81 | 81 | }; |
| 82 | 82 | defer p.buf.deinit(gpa); |
| 83 | 83 | defer p.errors.deinit(gpa); |
src/Sema.zig+4104-7112| ... | ... | @@ -173,13 +173,20 @@ const ComptimeAlloc = struct { |
| 173 | 173 | runtime_index: RuntimeIndex, |
| 174 | 174 | }; |
| 175 | 175 | |
| 176 | /// Asserts that `ty` is not an OPV type. | |
| 176 | 177 | /// `src` may be `null` if `is_const` will be set. |
| 177 | 178 | fn newComptimeAlloc(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, alignment: Alignment) !ComptimeAllocIndex { |
| 178 | 179 | const pt = sema.pt; |
| 179 | const init_val = try sema.typeHasOnePossibleValue(ty) orelse try pt.undefValue(ty); | |
| 180 | ||
| 181 | switch (ty.classify(pt.zcu)) { | |
| 182 | .no_possible_value => unreachable, | |
| 183 | .one_possible_value => unreachable, | |
| 184 | else => {}, | |
| 185 | } | |
| 186 | ||
| 180 | 187 | const idx = sema.comptime_allocs.items.len; |
| 181 | 188 | try sema.comptime_allocs.append(sema.gpa, .{ |
| 182 | .val = .{ .interned = init_val.toIntern() }, | |
| 189 | .val = .{ .interned = (try pt.undefValue(ty)).toIntern() }, | |
| 183 | 190 | .is_const = false, |
| 184 | 191 | .src = src, |
| 185 | 192 | .alignment = alignment, |
| ... | ... | @@ -393,7 +400,7 @@ pub const Block = struct { |
| 393 | 400 | /// The name of the current "context" for naming namespace types. |
| 394 | 401 | /// The interpretation of this depends on the name strategy in ZIR, but the name |
| 395 | 402 | /// is always incorporated into the type name somehow. |
| 396 | /// See `Sema.createTypeName`. | |
| 403 | /// See `Sema.setTypeName`. | |
| 397 | 404 | type_name_ctx: InternPool.NullTerminatedString, |
| 398 | 405 | |
| 399 | 406 | /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. |
| ... | ... | @@ -409,7 +416,7 @@ pub const Block = struct { |
| 409 | 416 | return block.comptime_reason != null; |
| 410 | 417 | } |
| 411 | 418 | |
| 412 | fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc { | |
| 419 | pub fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc { | |
| 413 | 420 | return block.src(.{ .node_offset_builtin_call_arg = .{ |
| 414 | 421 | .builtin_call_node = builtin_call_node, |
| 415 | 422 | .arg_index = arg_index, |
| ... | ... | @@ -1082,7 +1089,7 @@ fn analyzeInlineBody( |
| 1082 | 1089 | // This control flow goes further up the stack. |
| 1083 | 1090 | return error.ComptimeBreak; |
| 1084 | 1091 | } |
| 1085 | return try sema.resolveInst(break_inst.data.@"break".operand); | |
| 1092 | return sema.resolveInst(break_inst.data.@"break".operand); | |
| 1086 | 1093 | } |
| 1087 | 1094 | |
| 1088 | 1095 | /// Like `analyzeInlineBody`, but if the body does not break with a value, returns |
| ... | ... | @@ -1154,7 +1161,7 @@ fn analyzeBodyInner( |
| 1154 | 1161 | }, inst }); |
| 1155 | 1162 | } |
| 1156 | 1163 | |
| 1157 | const air_inst: Air.Inst.Ref = inst: switch (tags[@intFromEnum(inst)]) { | |
| 1164 | const air_ref: Air.Inst.Ref = inst: switch (tags[@intFromEnum(inst)]) { | |
| 1158 | 1165 | // zig fmt: off |
| 1159 | 1166 | .alloc => try sema.zirAlloc(block, inst), |
| 1160 | 1167 | .alloc_inferred => try sema.zirAllocInferred(block, true), |
| ... | ... | @@ -1382,10 +1389,10 @@ fn analyzeBodyInner( |
| 1382 | 1389 | const extended = datas[@intFromEnum(inst)].extended; |
| 1383 | 1390 | break :ext switch (extended.opcode) { |
| 1384 | 1391 | // zig fmt: off |
| 1385 | .struct_decl => try sema.zirStructDecl( block, extended, inst), | |
| 1386 | .enum_decl => try sema.zirEnumDecl( block, extended, inst), | |
| 1387 | .union_decl => try sema.zirUnionDecl( block, extended, inst), | |
| 1388 | .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst), | |
| 1392 | .struct_decl => try sema.zirStructDecl( block, inst), | |
| 1393 | .enum_decl => try sema.zirEnumDecl( block, inst), | |
| 1394 | .union_decl => try sema.zirUnionDecl( block, inst), | |
| 1395 | .opaque_decl => try sema.zirOpaqueDecl( block, inst), | |
| 1389 | 1396 | .tuple_decl => try sema.zirTupleDecl( block, extended), |
| 1390 | 1397 | .this => try sema.zirThis( block, extended), |
| 1391 | 1398 | .ret_addr => try sema.zirRetAddr( block, extended), |
| ... | ... | @@ -1869,7 +1876,7 @@ fn analyzeBodyInner( |
| 1869 | 1876 | |
| 1870 | 1877 | const break_data = opt_break_data orelse break; |
| 1871 | 1878 | if (inst == break_data.block_inst) { |
| 1872 | break :blk try sema.resolveInst(break_data.operand); | |
| 1879 | break :blk sema.resolveInst(break_data.operand); | |
| 1873 | 1880 | } else { |
| 1874 | 1881 | // `comptime_break_inst` preserved from `analyzeBodyInner` above. |
| 1875 | 1882 | return error.ComptimeBreak; |
| ... | ... | @@ -1890,7 +1897,7 @@ fn analyzeBodyInner( |
| 1890 | 1897 | extra.end + then_body.len, |
| 1891 | 1898 | extra.data.else_body_len, |
| 1892 | 1899 | ); |
| 1893 | const uncasted_cond = try sema.resolveInst(extra.data.condition); | |
| 1900 | const uncasted_cond = sema.resolveInst(extra.data.condition); | |
| 1894 | 1901 | const cond = try sema.coerce(block, .bool, uncasted_cond, cond_src); |
| 1895 | 1902 | const cond_val = try sema.resolveConstDefinedValue( |
| 1896 | 1903 | block, |
| ... | ... | @@ -1916,7 +1923,7 @@ fn analyzeBodyInner( |
| 1916 | 1923 | const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node }); |
| 1917 | 1924 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 1918 | 1925 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1919 | const err_union = try sema.resolveInst(extra.data.operand); | |
| 1926 | const err_union = sema.resolveInst(extra.data.operand); | |
| 1920 | 1927 | const err_union_ty = sema.typeOf(err_union); |
| 1921 | 1928 | if (err_union_ty.zigTypeTag(zcu) != .error_union) { |
| 1922 | 1929 | return sema.failWithOwnedErrorMsg(block, msg: { |
| ... | ... | @@ -1942,7 +1949,7 @@ fn analyzeBodyInner( |
| 1942 | 1949 | const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node }); |
| 1943 | 1950 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 1944 | 1951 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1945 | const operand = try sema.resolveInst(extra.data.operand); | |
| 1952 | const operand = sema.resolveInst(extra.data.operand); | |
| 1946 | 1953 | const err_union = try sema.analyzeLoad(block, src, operand, operand_src); |
| 1947 | 1954 | const is_non_err_val = (try sema.resolveIsNonErrVal(block, operand_src, err_union)).?; |
| 1948 | 1955 | if (is_non_err_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, operand_src, null); |
| ... | ... | @@ -1971,7 +1978,7 @@ fn analyzeBodyInner( |
| 1971 | 1978 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code; |
| 1972 | 1979 | const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data; |
| 1973 | 1980 | const defer_body = sema.code.bodySlice(extra.index, extra.len); |
| 1974 | const err_code = try sema.resolveInst(inst_data.err_code); | |
| 1981 | const err_code = sema.resolveInst(inst_data.err_code); | |
| 1975 | 1982 | try map.ensureSpaceForInstructions(sema.gpa, defer_body); |
| 1976 | 1983 | map.putAssumeCapacity(extra.remapped_err_code, err_code); |
| 1977 | 1984 | if (sema.analyzeBodyInner(block, defer_body)) { |
| ... | ... | @@ -1987,18 +1994,35 @@ fn analyzeBodyInner( |
| 1987 | 1994 | break :blk .void_value; |
| 1988 | 1995 | }, |
| 1989 | 1996 | }; |
| 1990 | if (sema.isNoReturn(air_inst)) { | |
| 1991 | // We're going to assume that the body itself is noreturn, so let's ensure that now | |
| 1992 | assert(block.instructions.items.len > 0); | |
| 1993 | assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef())); | |
| 1994 | break; | |
| 1995 | } | |
| 1996 | map.putAssumeCapacity(inst, air_inst); | |
| 1997 | ||
| 1998 | const is_inferred_alloc = if (air_ref.toIndex()) |air_inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst)]) { | |
| 1999 | .inferred_alloc, .inferred_alloc_comptime => true, | |
| 2000 | else => false, | |
| 2001 | } else false; | |
| 2002 | // We must resolve the layout of a type before creating a value of that type. Therefore, | |
| 2003 | // the layout of the type of `air_ref` must already be resolved. The call to `classify` | |
| 2004 | // doubles as an assertion of this. | |
| 2005 | if (!is_inferred_alloc) switch (sema.typeOf(air_ref).classify(zcu)) { | |
| 2006 | .no_possible_value => { | |
| 2007 | // The instruction result was noreturn, which should mean that the body itself now | |
| 2008 | // ends with a noreturn instruction. Let's confirm that. | |
| 2009 | const last_inst = block.instructions.items[block.instructions.items.len - 1]; | |
| 2010 | const last_inst_ty = sema.typeOf(last_inst.toRef()); | |
| 2011 | assert(last_inst_ty.classify(zcu) == .no_possible_value); | |
| 2012 | break; | |
| 2013 | }, | |
| 2014 | .one_possible_value => assert(air_ref.toInterned() != null), // the value should be comptime-known | |
| 2015 | .partially_comptime => assert(air_ref.toInterned() != null), // the value should be comptime-known | |
| 2016 | .fully_comptime => assert(air_ref.toInterned() != null), // the value should be comptime-known | |
| 2017 | .runtime => {}, | |
| 2018 | }; | |
| 2019 | ||
| 2020 | map.putAssumeCapacity(inst, air_ref); | |
| 1997 | 2021 | i += 1; |
| 1998 | 2022 | } |
| 1999 | 2023 | } |
| 2000 | 2024 | |
| 2001 | pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { | |
| 2025 | fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { | |
| 2002 | 2026 | if (zir_ref == .none) { |
| 2003 | 2027 | return .none; |
| 2004 | 2028 | } else { |
| ... | ... | @@ -2006,7 +2030,7 @@ pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { |
| 2006 | 2030 | } |
| 2007 | 2031 | } |
| 2008 | 2032 | |
| 2009 | pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { | |
| 2033 | fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { | |
| 2010 | 2034 | assert(zir_ref != .none); |
| 2011 | 2035 | if (zir_ref.toIndex()) |i| { |
| 2012 | 2036 | return sema.inst_map.get(i).?; |
| ... | ... | @@ -2023,7 +2047,7 @@ fn resolveConstBool( |
| 2023 | 2047 | zir_ref: Zir.Inst.Ref, |
| 2024 | 2048 | reason: ComptimeReason, |
| 2025 | 2049 | ) !bool { |
| 2026 | const air_inst = try sema.resolveInst(zir_ref); | |
| 2050 | const air_inst = sema.resolveInst(zir_ref); | |
| 2027 | 2051 | const wanted_type: Type = .bool; |
| 2028 | 2052 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 2029 | 2053 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); |
| ... | ... | @@ -2039,7 +2063,7 @@ fn resolveConstString( |
| 2039 | 2063 | /// being comptime-resolved is that the block is being comptime-evaluated. |
| 2040 | 2064 | reason: ?ComptimeReason, |
| 2041 | 2065 | ) ![]u8 { |
| 2042 | const air_inst = try sema.resolveInst(zir_ref); | |
| 2066 | const air_inst = sema.resolveInst(zir_ref); | |
| 2043 | 2067 | return sema.toConstString(block, src, air_inst, reason); |
| 2044 | 2068 | } |
| 2045 | 2069 | |
| ... | ... | @@ -2066,7 +2090,7 @@ pub fn resolveConstStringIntern( |
| 2066 | 2090 | zir_ref: Zir.Inst.Ref, |
| 2067 | 2091 | reason: ComptimeReason, |
| 2068 | 2092 | ) !InternPool.NullTerminatedString { |
| 2069 | const air_inst = try sema.resolveInst(zir_ref); | |
| 2093 | const air_inst = sema.resolveInst(zir_ref); | |
| 2070 | 2094 | const wanted_type: Type = .slice_const_u8; |
| 2071 | 2095 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 2072 | 2096 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); |
| ... | ... | @@ -2074,8 +2098,8 @@ pub fn resolveConstStringIntern( |
| 2074 | 2098 | } |
| 2075 | 2099 | |
| 2076 | 2100 | fn resolveTypeOrPoison(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !?Type { |
| 2077 | const air_inst = try sema.resolveInst(zir_ref); | |
| 2078 | const ty = try sema.analyzeAsType(block, src, air_inst); | |
| 2101 | const air_inst = sema.resolveInst(zir_ref); | |
| 2102 | const ty = try sema.analyzeAsType(block, src, .type, air_inst); | |
| 2079 | 2103 | if (ty.isGenericPoison()) return null; |
| 2080 | 2104 | return ty; |
| 2081 | 2105 | } |
| ... | ... | @@ -2168,7 +2192,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi |
| 2168 | 2192 | // There are two cases here: the pointer type may already have been |
| 2169 | 2193 | // generic poison, or it may have been an anyopaque pointer. |
| 2170 | 2194 | const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 2171 | const operand_ref = try sema.resolveInst(un_node.operand); | |
| 2195 | const operand_ref = sema.resolveInst(un_node.operand); | |
| 2172 | 2196 | const operand_val = operand_ref.toInterned() orelse return .unknown; |
| 2173 | 2197 | if (operand_val == .generic_poison_type) { |
| 2174 | 2198 | // The pointer was generic poison - keep looking. |
| ... | ... | @@ -2190,15 +2214,16 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi |
| 2190 | 2214 | } |
| 2191 | 2215 | } |
| 2192 | 2216 | |
| 2193 | fn analyzeAsType( | |
| 2217 | pub fn analyzeAsType( | |
| 2194 | 2218 | sema: *Sema, |
| 2195 | 2219 | block: *Block, |
| 2196 | 2220 | src: LazySrcLoc, |
| 2221 | reason: std.zig.SimpleComptimeReason, | |
| 2197 | 2222 | air_inst: Air.Inst.Ref, |
| 2198 | 2223 | ) !Type { |
| 2199 | 2224 | const wanted_type: Type = .type; |
| 2200 | 2225 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 2201 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, .{ .simple = .type }); | |
| 2226 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, .{ .simple = reason }); | |
| 2202 | 2227 | return val.toType(); |
| 2203 | 2228 | } |
| 2204 | 2229 | |
| ... | ... | @@ -2227,7 +2252,6 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) |
| 2227 | 2252 | |
| 2228 | 2253 | // var st: StackTrace = undefined; |
| 2229 | 2254 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); |
| 2230 | try stack_trace_ty.resolveFields(pt); | |
| 2231 | 2255 | const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty)); |
| 2232 | 2256 | |
| 2233 | 2257 | // st.instruction_addresses = &addrs; |
| ... | ... | @@ -2247,14 +2271,10 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) |
| 2247 | 2271 | } |
| 2248 | 2272 | |
| 2249 | 2273 | /// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value. |
| 2250 | fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { | |
| 2274 | fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { | |
| 2251 | 2275 | const zcu = sema.pt.zcu; |
| 2252 | 2276 | assert(inst != .none); |
| 2253 | 2277 | |
| 2254 | if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| { | |
| 2255 | return opv; | |
| 2256 | } | |
| 2257 | ||
| 2258 | 2278 | if (inst.toInterned()) |ip_index| { |
| 2259 | 2279 | const val: Value = .fromInterned(ip_index); |
| 2260 | 2280 | assert(val.getVariable(zcu) == null); |
| ... | ... | @@ -2267,12 +2287,21 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { |
| 2267 | 2287 | .inferred_alloc_comptime => unreachable, // assertion failure |
| 2268 | 2288 | else => {}, |
| 2269 | 2289 | } |
| 2290 | // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so | |
| 2291 | // we must explicitly check for `std.debug.runtime_safety`. | |
| 2292 | if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { | |
| 2293 | .no_possible_value => unreachable, // values of this type do not exist | |
| 2294 | .one_possible_value => unreachable, // the value should be comptime-known | |
| 2295 | .partially_comptime => unreachable, // the value should be comptime-known | |
| 2296 | .fully_comptime => unreachable, // the value should be comptime-known | |
| 2297 | .runtime => {}, | |
| 2298 | }; | |
| 2270 | 2299 | return null; |
| 2271 | 2300 | } |
| 2272 | 2301 | } |
| 2273 | 2302 | |
| 2274 | 2303 | /// Like `resolveValue`, but emits an error if the value is not comptime-known. |
| 2275 | fn resolveConstValue( | |
| 2304 | pub fn resolveConstValue( | |
| 2276 | 2305 | sema: *Sema, |
| 2277 | 2306 | block: *Block, |
| 2278 | 2307 | src: LazySrcLoc, |
| ... | ... | @@ -2281,7 +2310,8 @@ fn resolveConstValue( |
| 2281 | 2310 | /// being comptime-resolved is that the block is being comptime-evaluated. |
| 2282 | 2311 | reason: ?ComptimeReason, |
| 2283 | 2312 | ) CompileError!Value { |
| 2284 | return try sema.resolveValue(inst) orelse { | |
| 2313 | assert(reason != null or block.isComptime()); | |
| 2314 | return sema.resolveValue(inst) orelse { | |
| 2285 | 2315 | return sema.failWithNeededComptime(block, src, reason); |
| 2286 | 2316 | }; |
| 2287 | 2317 | } |
| ... | ... | @@ -2295,13 +2325,13 @@ fn resolveDefinedValue( |
| 2295 | 2325 | ) CompileError!?Value { |
| 2296 | 2326 | const pt = sema.pt; |
| 2297 | 2327 | const zcu = pt.zcu; |
| 2298 | const val = try sema.resolveValue(air_ref) orelse return null; | |
| 2328 | const val = sema.resolveValue(air_ref) orelse return null; | |
| 2299 | 2329 | if (val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); |
| 2300 | 2330 | return val; |
| 2301 | 2331 | } |
| 2302 | 2332 | |
| 2303 | 2333 | /// Like `resolveValue`, but emits an error if the value is not comptime-known or is undefined. |
| 2304 | fn resolveConstDefinedValue( | |
| 2334 | pub fn resolveConstDefinedValue( | |
| 2305 | 2335 | sema: *Sema, |
| 2306 | 2336 | block: *Block, |
| 2307 | 2337 | src: LazySrcLoc, |
| ... | ... | @@ -2315,11 +2345,6 @@ fn resolveConstDefinedValue( |
| 2315 | 2345 | return val; |
| 2316 | 2346 | } |
| 2317 | 2347 | |
| 2318 | /// Like `resolveValue`, but recursively resolves lazy values before returning. | |
| 2319 | fn resolveValueResolveLazy(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { | |
| 2320 | return try sema.resolveLazyValue((try sema.resolveValue(inst)) orelse return null); | |
| 2321 | } | |
| 2322 | ||
| 2323 | 2348 | /// Value Tag may be `undef` or `variable`. |
| 2324 | 2349 | pub fn resolveFinalDeclValue( |
| 2325 | 2350 | sema: *Sema, |
| ... | ... | @@ -2439,13 +2464,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non |
| 2439 | 2464 | |
| 2440 | 2465 | fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { |
| 2441 | 2466 | const pt = sema.pt; |
| 2467 | const zcu = pt.zcu; | |
| 2442 | 2468 | const msg = msg: { |
| 2443 | 2469 | const msg = try sema.errMsg(src, "type '{f}' does not support array initialization syntax", .{ |
| 2444 | 2470 | ty.fmt(pt), |
| 2445 | 2471 | }); |
| 2446 | 2472 | errdefer msg.destroy(sema.gpa); |
| 2447 | if (ty.isSlice(pt.zcu)) { | |
| 2448 | try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.elemType2(pt.zcu).fmt(pt)}); | |
| 2473 | if (ty.isSlice(zcu)) { | |
| 2474 | try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.childType(zcu).fmt(pt)}); | |
| 2449 | 2475 | } |
| 2450 | 2476 | break :msg msg; |
| 2451 | 2477 | }; |
| ... | ... | @@ -2644,7 +2670,7 @@ pub fn fail( |
| 2644 | 2670 | src: LazySrcLoc, |
| 2645 | 2671 | comptime format: []const u8, |
| 2646 | 2672 | args: anytype, |
| 2647 | ) CompileError { | |
| 2673 | ) SemaError { | |
| 2648 | 2674 | const err_msg = try sema.errMsg(src, format, args); |
| 2649 | 2675 | inline for (args) |arg| { |
| 2650 | 2676 | if (@TypeOf(arg) == Type.Formatter) { |
| ... | ... | @@ -2772,7 +2798,7 @@ fn resolveAlign( |
| 2772 | 2798 | src: LazySrcLoc, |
| 2773 | 2799 | zir_ref: Zir.Inst.Ref, |
| 2774 | 2800 | ) !Alignment { |
| 2775 | const air_ref = try sema.resolveInst(zir_ref); | |
| 2801 | const air_ref = sema.resolveInst(zir_ref); | |
| 2776 | 2802 | return sema.analyzeAsAlign(block, src, air_ref); |
| 2777 | 2803 | } |
| 2778 | 2804 | |
| ... | ... | @@ -2784,7 +2810,7 @@ fn resolveInt( |
| 2784 | 2810 | dest_ty: Type, |
| 2785 | 2811 | reason: ComptimeReason, |
| 2786 | 2812 | ) !u64 { |
| 2787 | const air_ref = try sema.resolveInst(zir_ref); | |
| 2813 | const air_ref = sema.resolveInst(zir_ref); | |
| 2788 | 2814 | return sema.analyzeAsInt(block, src, air_ref, dest_ty, reason); |
| 2789 | 2815 | } |
| 2790 | 2816 | |
| ... | ... | @@ -2798,27 +2824,26 @@ fn analyzeAsInt( |
| 2798 | 2824 | ) !u64 { |
| 2799 | 2825 | const coerced = try sema.coerce(block, dest_ty, air_ref, src); |
| 2800 | 2826 | const val = try sema.resolveConstDefinedValue(block, src, coerced, reason); |
| 2801 | return try val.toUnsignedIntSema(sema.pt); | |
| 2827 | return val.toUnsignedInt(sema.pt.zcu); | |
| 2802 | 2828 | } |
| 2803 | 2829 | |
| 2804 | 2830 | fn analyzeValueAsCallconv( |
| 2805 | 2831 | sema: *Sema, |
| 2806 | 2832 | block: *Block, |
| 2807 | 2833 | src: LazySrcLoc, |
| 2808 | unresolved_val: Value, | |
| 2834 | val: Value, | |
| 2809 | 2835 | ) !std.builtin.CallingConvention { |
| 2810 | return interpretBuiltinType(sema, block, src, unresolved_val, std.builtin.CallingConvention); | |
| 2836 | return interpretBuiltinType(sema, block, src, val, std.builtin.CallingConvention); | |
| 2811 | 2837 | } |
| 2812 | 2838 | |
| 2813 | 2839 | fn interpretBuiltinType( |
| 2814 | 2840 | sema: *Sema, |
| 2815 | 2841 | block: *Block, |
| 2816 | 2842 | src: LazySrcLoc, |
| 2817 | unresolved_val: Value, | |
| 2843 | val: Value, | |
| 2818 | 2844 | comptime T: type, |
| 2819 | 2845 | ) !T { |
| 2820 | const resolved_val = try sema.resolveLazyValue(unresolved_val); | |
| 2821 | return resolved_val.interpret(T, sema.pt) catch |err| switch (err) { | |
| 2846 | return val.interpret(T, sema.pt) catch |err| switch (err) { | |
| 2822 | 2847 | error.OutOfMemory => |e| return e, |
| 2823 | 2848 | error.UndefinedValue => return sema.failWithUseOfUndef(block, src, null), |
| 2824 | 2849 | error.TypeMismatch => @panic("std.builtin is corrupt"), |
| ... | ... | @@ -2864,7 +2889,7 @@ fn zirTupleDecl( |
| 2864 | 2889 | field_ty.* = field_type.toIntern(); |
| 2865 | 2890 | field_init.* = init: { |
| 2866 | 2891 | if (zir_field_init != .none) { |
| 2867 | const uncoerced_field_init = try sema.resolveInst(zir_field_init); | |
| 2892 | const uncoerced_field_init = sema.resolveInst(zir_field_init); | |
| 2868 | 2893 | const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src); |
| 2869 | 2894 | const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value }); |
| 2870 | 2895 | if (field_init_val.canMutateComptimeVarState(zcu)) { |
| ... | ... | @@ -2913,7 +2938,13 @@ fn validateTupleFieldType( |
| 2913 | 2938 | |
| 2914 | 2939 | /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, |
| 2915 | 2940 | /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. |
| 2916 | fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { | |
| 2941 | fn getCaptures( | |
| 2942 | sema: *Sema, | |
| 2943 | block: *Block, | |
| 2944 | type_src: LazySrcLoc, | |
| 2945 | zir_captures: []const Zir.Inst.Capture, | |
| 2946 | zir_capture_names: []const Zir.NullTerminatedString, | |
| 2947 | ) ![]InternPool.CaptureValue { | |
| 2917 | 2948 | const pt = sema.pt; |
| 2918 | 2949 | const zcu = pt.zcu; |
| 2919 | 2950 | const comp = zcu.comp; |
| ... | ... | @@ -2924,41 +2955,38 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2924 | 2955 | const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type); |
| 2925 | 2956 | const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); |
| 2926 | 2957 | |
| 2927 | const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len); | |
| 2958 | const captures = try sema.arena.alloc(InternPool.CaptureValue, zir_captures.len); | |
| 2928 | 2959 | |
| 2929 | for (sema.code.extra[extra_index..][0..captures_len], sema.code.extra[extra_index + captures_len ..][0..captures_len], captures) |raw, raw_name, *capture| { | |
| 2930 | const zir_capture: Zir.Inst.Capture = @bitCast(raw); | |
| 2931 | const zir_name: Zir.NullTerminatedString = @enumFromInt(raw_name); | |
| 2960 | for (zir_captures, zir_capture_names, captures) |zir_capture, zir_name, *capture| { | |
| 2932 | 2961 | const zir_name_slice = sema.code.nullTerminatedString(zir_name); |
| 2933 | 2962 | capture.* = switch (zir_capture.unwrap()) { |
| 2934 | 2963 | .nested => |parent_idx| parent_captures.get(ip)[parent_idx], |
| 2935 | .instruction_load => |ptr_inst| InternPool.CaptureValue.wrap(capture: { | |
| 2936 | const ptr_ref = try sema.resolveInst(ptr_inst.toRef()); | |
| 2937 | const ptr_val = try sema.resolveValue(ptr_ref) orelse { | |
| 2938 | break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }; | |
| 2964 | .instruction_load => |ptr_inst| capture: { | |
| 2965 | const ptr_ref = sema.resolveInst(ptr_inst.toRef()); | |
| 2966 | const ptr_val = sema.resolveValue(ptr_ref) orelse { | |
| 2967 | break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); | |
| 2939 | 2968 | }; |
| 2940 | 2969 | // TODO: better source location |
| 2941 | const unresolved_loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse { | |
| 2942 | break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }; | |
| 2970 | const loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse { | |
| 2971 | break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); | |
| 2943 | 2972 | }; |
| 2944 | const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val); | |
| 2945 | 2973 | if (loaded_val.canMutateComptimeVarState(zcu)) { |
| 2946 | 2974 | const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); |
| 2947 | 2975 | return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val); |
| 2948 | 2976 | } |
| 2949 | break :capture .{ .@"comptime" = loaded_val.toIntern() }; | |
| 2950 | }), | |
| 2951 | .instruction => |inst| InternPool.CaptureValue.wrap(capture: { | |
| 2952 | const air_ref = try sema.resolveInst(inst.toRef()); | |
| 2953 | if (try sema.resolveValueResolveLazy(air_ref)) |val| { | |
| 2977 | break :capture .wrap(.{ .@"comptime" = loaded_val.toIntern() }); | |
| 2978 | }, | |
| 2979 | .instruction => |inst| capture: { | |
| 2980 | const air_ref = sema.resolveInst(inst.toRef()); | |
| 2981 | if (sema.resolveValue(air_ref)) |val| { | |
| 2954 | 2982 | if (val.canMutateComptimeVarState(zcu)) { |
| 2955 | 2983 | const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); |
| 2956 | 2984 | return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val); |
| 2957 | 2985 | } |
| 2958 | break :capture .{ .@"comptime" = val.toIntern() }; | |
| 2986 | break :capture .wrap(.{ .@"comptime" = val.toIntern() }); | |
| 2959 | 2987 | } |
| 2960 | break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; | |
| 2961 | }), | |
| 2988 | break :capture .wrap(.{ .runtime = sema.typeOf(air_ref).toIntern() }); | |
| 2989 | }, | |
| 2962 | 2990 | .decl_val => |str| capture: { |
| 2963 | 2991 | const decl_name = try ip.getOrPutString( |
| 2964 | 2992 | gpa, |
| ... | ... | @@ -2968,7 +2996,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2968 | 2996 | .no_embedded_nulls, |
| 2969 | 2997 | ); |
| 2970 | 2998 | const nav = try sema.lookupIdentifier(block, decl_name); |
| 2971 | break :capture InternPool.CaptureValue.wrap(.{ .nav_val = nav }); | |
| 2999 | break :capture .wrap(.{ .nav_val = nav }); | |
| 2972 | 3000 | }, |
| 2973 | 3001 | .decl_ref => |str| capture: { |
| 2974 | 3002 | const decl_name = try ip.getOrPutString( |
| ... | ... | @@ -2987,952 +3015,335 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2987 | 3015 | return captures; |
| 2988 | 3016 | } |
| 2989 | 3017 | |
| 2990 | fn zirStructDecl( | |
| 3018 | fn zirErrorSetDecl( | |
| 2991 | 3019 | sema: *Sema, |
| 2992 | block: *Block, | |
| 2993 | extended: Zir.Inst.Extended.InstData, | |
| 2994 | 3020 | inst: Zir.Inst.Index, |
| 2995 | 3021 | ) CompileError!Air.Inst.Ref { |
| 3022 | const tracy = trace(@src()); | |
| 3023 | defer tracy.end(); | |
| 3024 | ||
| 2996 | 3025 | const pt = sema.pt; |
| 2997 | 3026 | const zcu = pt.zcu; |
| 2998 | 3027 | const comp = zcu.comp; |
| 2999 | 3028 | const gpa = comp.gpa; |
| 3000 | 3029 | const io = comp.io; |
| 3001 | const ip = &zcu.intern_pool; | |
| 3002 | ||
| 3003 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 3004 | const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand); | |
| 3005 | 3030 | |
| 3006 | const tracked_inst = try block.trackZir(inst); | |
| 3007 | const src: LazySrcLoc = .{ | |
| 3008 | .base_node_inst = tracked_inst, | |
| 3009 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 3010 | }; | |
| 3031 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | |
| 3032 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); | |
| 3011 | 3033 | |
| 3012 | var extra_index = extra.end; | |
| 3034 | var names: InferredErrorSet.NameMap = .{}; | |
| 3035 | try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); | |
| 3013 | 3036 | |
| 3014 | const captures_len = if (small.has_captures_len) blk: { | |
| 3015 | const captures_len = sema.code.extra[extra_index]; | |
| 3016 | extra_index += 1; | |
| 3017 | break :blk captures_len; | |
| 3018 | } else 0; | |
| 3019 | const fields_len = if (small.has_fields_len) blk: { | |
| 3020 | const fields_len = sema.code.extra[extra_index]; | |
| 3021 | extra_index += 1; | |
| 3022 | break :blk fields_len; | |
| 3023 | } else 0; | |
| 3024 | const decls_len = if (small.has_decls_len) blk: { | |
| 3025 | const decls_len = sema.code.extra[extra_index]; | |
| 3026 | extra_index += 1; | |
| 3027 | break :blk decls_len; | |
| 3028 | } else 0; | |
| 3037 | var extra_index: u32 = @intCast(extra.end); | |
| 3038 | const extra_index_end = extra_index + extra.data.fields_len; | |
| 3039 | while (extra_index < extra_index_end) : (extra_index += 1) { | |
| 3040 | const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]); | |
| 3041 | const name = sema.code.nullTerminatedString(name_index); | |
| 3042 | const name_ip = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); | |
| 3043 | _ = try pt.getErrorValue(name_ip); | |
| 3044 | const result = names.getOrPutAssumeCapacity(name_ip); | |
| 3045 | assert(!result.found_existing); // verified in AstGen | |
| 3046 | } | |
| 3029 | 3047 | |
| 3030 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); | |
| 3031 | extra_index += captures_len * 2; | |
| 3048 | return Air.internedToRef((try pt.errorSetFromUnsortedNames(names.keys())).toIntern()); | |
| 3049 | } | |
| 3032 | 3050 | |
| 3033 | if (small.has_backing_int) { | |
| 3034 | const backing_int_body_len = sema.code.extra[extra_index]; | |
| 3035 | extra_index += 1; // backing_int_body_len | |
| 3036 | if (backing_int_body_len == 0) { | |
| 3037 | extra_index += 1; // backing_int_ref | |
| 3038 | } else { | |
| 3039 | extra_index += backing_int_body_len; // backing_int_body_inst | |
| 3040 | } | |
| 3041 | } | |
| 3042 | ||
| 3043 | const struct_init: InternPool.StructTypeInit = .{ | |
| 3044 | .layout = small.layout, | |
| 3045 | .fields_len = fields_len, | |
| 3046 | .known_non_opv = small.known_non_opv, | |
| 3047 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, | |
| 3048 | .any_comptime_fields = small.any_comptime_fields, | |
| 3049 | .any_default_inits = small.any_default_inits, | |
| 3050 | .inits_resolved = false, | |
| 3051 | .any_aligned_fields = small.any_aligned_fields, | |
| 3052 | .key = .{ .declared = .{ | |
| 3053 | .zir_index = tracked_inst, | |
| 3054 | .captures = captures, | |
| 3055 | } }, | |
| 3056 | }; | |
| 3057 | const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, struct_init, false)) { | |
| 3058 | .existing => |ty| { | |
| 3059 | const new_ty = try pt.ensureTypeUpToDate(ty); | |
| 3051 | fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3052 | const tracy = trace(@src()); | |
| 3053 | defer tracy.end(); | |
| 3060 | 3054 | |
| 3061 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | |
| 3062 | // up on e.g. changed comptime decls. | |
| 3063 | try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu)); | |
| 3055 | const pt = sema.pt; | |
| 3056 | const zcu = pt.zcu; | |
| 3064 | 3057 | |
| 3065 | try sema.declareDependency(.{ .interned = new_ty }); | |
| 3066 | try sema.addTypeReferenceEntry(src, new_ty); | |
| 3067 | return Air.internedToRef(new_ty); | |
| 3068 | }, | |
| 3069 | .wip => |wip| wip, | |
| 3070 | }; | |
| 3071 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 3058 | const src = block.nodeOffset(sema.code.instructions.items(.data)[@intFromEnum(inst)].node); | |
| 3072 | 3059 | |
| 3073 | const type_name = try sema.createTypeName( | |
| 3074 | block, | |
| 3075 | small.name_strategy, | |
| 3076 | "struct", | |
| 3077 | inst, | |
| 3078 | wip_ty.index, | |
| 3079 | ); | |
| 3080 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 3060 | if (block.isComptime() or sema.fn_ret_ty.comptimeOnly(zcu)) { | |
| 3061 | return sema.analyzeComptimeAlloc(block, src, sema.fn_ret_ty, .none); | |
| 3062 | } | |
| 3081 | 3063 | |
| 3082 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3083 | .parent = block.namespace.toOptional(), | |
| 3084 | .owner_type = wip_ty.index, | |
| 3085 | .file_scope = block.getFileScopeIndex(zcu), | |
| 3086 | .generation = zcu.generation, | |
| 3064 | const target = zcu.getTarget(); | |
| 3065 | const ptr_type = try pt.ptrType(.{ | |
| 3066 | .child = sema.fn_ret_ty.toIntern(), | |
| 3067 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, | |
| 3087 | 3068 | }); |
| 3088 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 3089 | 3069 | |
| 3090 | if (pt.zcu.comp.config.incremental) { | |
| 3091 | try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); | |
| 3070 | if (block.inlining != null) { | |
| 3071 | // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr. | |
| 3072 | // TODO when functions gain result location support, the inlining struct in | |
| 3073 | // Block should contain the return pointer, and we would pass that through here. | |
| 3074 | return block.addTy(.alloc, ptr_type); | |
| 3092 | 3075 | } |
| 3093 | 3076 | |
| 3094 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3095 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3096 | ||
| 3097 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 3098 | codegen_type: { | |
| 3099 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 3100 | if (block.ownerModule().strip) break :codegen_type; | |
| 3101 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 3102 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3103 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 3104 | } | |
| 3105 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 3106 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 3107 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 3108 | return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); | |
| 3077 | return block.addTy(.ret_ptr, ptr_type); | |
| 3109 | 3078 | } |
| 3110 | 3079 | |
| 3111 | pub fn createTypeName( | |
| 3112 | sema: *Sema, | |
| 3113 | block: *Block, | |
| 3114 | name_strategy: Zir.Inst.NameStrategy, | |
| 3115 | anon_prefix: []const u8, | |
| 3116 | inst: ?Zir.Inst.Index, | |
| 3117 | /// This is used purely to give the type a unique name in the `anon` case. | |
| 3118 | type_index: InternPool.Index, | |
| 3119 | ) CompileError!struct { | |
| 3120 | name: InternPool.NullTerminatedString, | |
| 3121 | nav: InternPool.Nav.Index.Optional, | |
| 3122 | } { | |
| 3123 | const pt = sema.pt; | |
| 3124 | const zcu = pt.zcu; | |
| 3125 | const comp = zcu.comp; | |
| 3126 | const gpa = comp.gpa; | |
| 3127 | const io = comp.io; | |
| 3128 | const ip = &zcu.intern_pool; | |
| 3129 | ||
| 3130 | switch (name_strategy) { | |
| 3131 | .anon => {}, // handled after switch | |
| 3132 | .parent => return .{ | |
| 3133 | .name = block.type_name_ctx, | |
| 3134 | .nav = sema.owner.unwrap().nav_val.toOptional(), | |
| 3135 | }, | |
| 3136 | .func => func_strat: { | |
| 3137 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail); | |
| 3138 | const zir_tags = sema.code.instructions.items(.tag); | |
| 3080 | fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3081 | const tracy = trace(@src()); | |
| 3082 | defer tracy.end(); | |
| 3139 | 3083 | |
| 3140 | var aw: std.Io.Writer.Allocating = .init(gpa); | |
| 3141 | defer aw.deinit(); | |
| 3142 | const w = &aw.writer; | |
| 3143 | w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory; | |
| 3084 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; | |
| 3085 | const operand = sema.resolveInst(inst_data.operand); | |
| 3086 | return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand, .none); | |
| 3087 | } | |
| 3144 | 3088 | |
| 3145 | var arg_i: usize = 0; | |
| 3146 | for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) { | |
| 3147 | .param, .param_comptime, .param_anytype, .param_anytype_comptime => { | |
| 3148 | const arg = sema.inst_map.get(zir_inst).?; | |
| 3149 | // If this is being called in a generic function then analyzeCall will | |
| 3150 | // have already resolved the args and this will work. | |
| 3151 | // If not then this is a struct type being returned from a non-generic | |
| 3152 | // function and the name doesn't matter since it will later | |
| 3153 | // result in a compile error. | |
| 3154 | const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat | |
| 3089 | fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3090 | const tracy = trace(@src()); | |
| 3091 | defer tracy.end(); | |
| 3155 | 3092 | |
| 3156 | if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory; | |
| 3093 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3094 | const operand = sema.resolveInst(inst_data.operand); | |
| 3095 | const src = block.nodeOffset(inst_data.src_node); | |
| 3157 | 3096 | |
| 3158 | // Limiting the depth here helps avoid type names getting too long, which | |
| 3159 | // in turn helps to avoid unreasonably long symbol names for namespaced | |
| 3160 | // symbols. Such names should ideally be human-readable, and additionally, | |
| 3161 | // some tooling may not support very long symbol names. | |
| 3162 | w.print("{f}", .{Value.fmtValueSemaFull(.{ | |
| 3163 | .val = arg_val, | |
| 3164 | .pt = pt, | |
| 3165 | .opt_sema = sema, | |
| 3166 | .depth = 1, | |
| 3167 | })}) catch return error.OutOfMemory; | |
| 3097 | return sema.ensureResultUsed(block, sema.typeOf(operand), src); | |
| 3098 | } | |
| 3168 | 3099 | |
| 3169 | arg_i += 1; | |
| 3170 | continue; | |
| 3171 | }, | |
| 3172 | else => continue, | |
| 3100 | fn ensureResultUsed( | |
| 3101 | sema: *Sema, | |
| 3102 | block: *Block, | |
| 3103 | ty: Type, | |
| 3104 | src: LazySrcLoc, | |
| 3105 | ) CompileError!void { | |
| 3106 | const pt = sema.pt; | |
| 3107 | const zcu = pt.zcu; | |
| 3108 | switch (ty.zigTypeTag(zcu)) { | |
| 3109 | .void, .noreturn => return, | |
| 3110 | .error_set => return sema.fail(block, src, "error set is ignored", .{}), | |
| 3111 | .error_union => { | |
| 3112 | const msg = msg: { | |
| 3113 | const msg = try sema.errMsg(src, "error union is ignored", .{}); | |
| 3114 | errdefer msg.destroy(sema.gpa); | |
| 3115 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); | |
| 3116 | break :msg msg; | |
| 3173 | 3117 | }; |
| 3174 | ||
| 3175 | w.writeByte(')') catch return error.OutOfMemory; | |
| 3176 | return .{ | |
| 3177 | .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls), | |
| 3178 | .nav = .none, | |
| 3118 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3119 | }, | |
| 3120 | else => { | |
| 3121 | const msg = msg: { | |
| 3122 | const msg = try sema.errMsg(src, "value of type '{f}' ignored", .{ty.fmt(pt)}); | |
| 3123 | errdefer msg.destroy(sema.gpa); | |
| 3124 | try sema.errNote(src, msg, "all non-void values must be used", .{}); | |
| 3125 | try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{}); | |
| 3126 | break :msg msg; | |
| 3179 | 3127 | }; |
| 3128 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3180 | 3129 | }, |
| 3181 | .dbg_var => { | |
| 3182 | // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. | |
| 3183 | const ref = inst.?.toRef(); | |
| 3184 | const zir_tags = sema.code.instructions.items(.tag); | |
| 3185 | const zir_data = sema.code.instructions.items(.data); | |
| 3186 | for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) { | |
| 3187 | .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { | |
| 3188 | return .{ | |
| 3189 | .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ | |
| 3190 | block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), | |
| 3191 | }, .no_embedded_nulls), | |
| 3192 | .nav = .none, | |
| 3193 | }; | |
| 3194 | }, | |
| 3195 | else => {}, | |
| 3130 | } | |
| 3131 | } | |
| 3132 | ||
| 3133 | fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3134 | const tracy = trace(@src()); | |
| 3135 | defer tracy.end(); | |
| 3136 | ||
| 3137 | const pt = sema.pt; | |
| 3138 | const zcu = pt.zcu; | |
| 3139 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3140 | const operand = sema.resolveInst(inst_data.operand); | |
| 3141 | const src = block.nodeOffset(inst_data.src_node); | |
| 3142 | const operand_ty = sema.typeOf(operand); | |
| 3143 | switch (operand_ty.zigTypeTag(zcu)) { | |
| 3144 | .error_set => return sema.fail(block, src, "error set is discarded", .{}), | |
| 3145 | .error_union => { | |
| 3146 | const msg = msg: { | |
| 3147 | const msg = try sema.errMsg(src, "error union is discarded", .{}); | |
| 3148 | errdefer msg.destroy(sema.gpa); | |
| 3149 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); | |
| 3150 | break :msg msg; | |
| 3196 | 3151 | }; |
| 3197 | // fall through to anon strat | |
| 3152 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3198 | 3153 | }, |
| 3154 | else => return, | |
| 3155 | } | |
| 3156 | } | |
| 3157 | ||
| 3158 | fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3159 | const tracy = trace(@src()); | |
| 3160 | defer tracy.end(); | |
| 3161 | ||
| 3162 | const pt = sema.pt; | |
| 3163 | const zcu = pt.zcu; | |
| 3164 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3165 | const src = block.nodeOffset(inst_data.src_node); | |
| 3166 | const operand = sema.resolveInst(inst_data.operand); | |
| 3167 | const operand_ty = sema.typeOf(operand); | |
| 3168 | const err_union_ty = if (operand_ty.zigTypeTag(zcu) == .pointer) | |
| 3169 | operand_ty.childType(zcu) | |
| 3170 | else | |
| 3171 | operand_ty; | |
| 3172 | if (err_union_ty.zigTypeTag(zcu) != .error_union) return; | |
| 3173 | const payload_ty = err_union_ty.errorUnionPayload(zcu).zigTypeTag(zcu); | |
| 3174 | if (payload_ty != .void and payload_ty != .noreturn) { | |
| 3175 | const msg = msg: { | |
| 3176 | const msg = try sema.errMsg(src, "error union payload is ignored", .{}); | |
| 3177 | errdefer msg.destroy(sema.gpa); | |
| 3178 | try sema.errNote(src, msg, "payload value can be explicitly ignored with '|_|'", .{}); | |
| 3179 | break :msg msg; | |
| 3180 | }; | |
| 3181 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3199 | 3182 | } |
| 3183 | } | |
| 3200 | 3184 | |
| 3201 | // anon strat handling | |
| 3185 | fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3186 | const tracy = trace(@src()); | |
| 3187 | defer tracy.end(); | |
| 3202 | 3188 | |
| 3203 | // It would be neat to have "struct:line:column" but this name has | |
| 3204 | // to survive incremental updates, where it may have been shifted down | |
| 3205 | // or up to a different line, but unchanged, and thus not unnecessarily | |
| 3206 | // semantically analyzed. | |
| 3207 | // TODO: that would be possible, by detecting line number changes and renaming | |
| 3208 | // types appropriately. However, `@typeName` becomes a problem then. If we remove | |
| 3209 | // that builtin from the language, we can consider this. | |
| 3189 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3190 | const src = block.nodeOffset(inst_data.src_node); | |
| 3191 | const object = sema.resolveInst(inst_data.operand); | |
| 3210 | 3192 | |
| 3211 | return .{ | |
| 3212 | .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}__{s}_{d}", .{ | |
| 3213 | block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index), | |
| 3214 | }, .no_embedded_nulls), | |
| 3215 | .nav = .none, | |
| 3216 | }; | |
| 3193 | return indexablePtrLen(sema, block, src, object); | |
| 3217 | 3194 | } |
| 3218 | 3195 | |
| 3219 | fn zirEnumDecl( | |
| 3196 | fn indexablePtrLen( | |
| 3220 | 3197 | sema: *Sema, |
| 3221 | 3198 | block: *Block, |
| 3222 | extended: Zir.Inst.Extended.InstData, | |
| 3223 | inst: Zir.Inst.Index, | |
| 3199 | src: LazySrcLoc, | |
| 3200 | object: Air.Inst.Ref, | |
| 3224 | 3201 | ) CompileError!Air.Inst.Ref { |
| 3225 | const tracy = trace(@src()); | |
| 3226 | defer tracy.end(); | |
| 3227 | ||
| 3228 | 3202 | const pt = sema.pt; |
| 3229 | 3203 | const zcu = pt.zcu; |
| 3230 | 3204 | const comp = zcu.comp; |
| 3231 | 3205 | const gpa = comp.gpa; |
| 3232 | 3206 | const io = comp.io; |
| 3233 | const ip = &zcu.intern_pool; | |
| 3234 | ||
| 3235 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); | |
| 3236 | const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); | |
| 3237 | var extra_index: usize = extra.end; | |
| 3238 | ||
| 3239 | const tracked_inst = try block.trackZir(inst); | |
| 3240 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; | |
| 3241 | ||
| 3242 | const tag_type_ref = if (small.has_tag_type) blk: { | |
| 3243 | const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | |
| 3244 | extra_index += 1; | |
| 3245 | break :blk tag_type_ref; | |
| 3246 | } else .none; | |
| 3247 | ||
| 3248 | const captures_len = if (small.has_captures_len) blk: { | |
| 3249 | const captures_len = sema.code.extra[extra_index]; | |
| 3250 | extra_index += 1; | |
| 3251 | break :blk captures_len; | |
| 3252 | } else 0; | |
| 3253 | ||
| 3254 | const body_len = if (small.has_body_len) blk: { | |
| 3255 | const body_len = sema.code.extra[extra_index]; | |
| 3256 | extra_index += 1; | |
| 3257 | break :blk body_len; | |
| 3258 | } else 0; | |
| 3259 | ||
| 3260 | const fields_len = if (small.has_fields_len) blk: { | |
| 3261 | const fields_len = sema.code.extra[extra_index]; | |
| 3262 | extra_index += 1; | |
| 3263 | break :blk fields_len; | |
| 3264 | } else 0; | |
| 3265 | ||
| 3266 | const decls_len = if (small.has_decls_len) blk: { | |
| 3267 | const decls_len = sema.code.extra[extra_index]; | |
| 3268 | extra_index += 1; | |
| 3269 | break :blk decls_len; | |
| 3270 | } else 0; | |
| 3271 | ||
| 3272 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); | |
| 3273 | extra_index += captures_len * 2; | |
| 3274 | ||
| 3275 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3276 | extra_index += decls_len; | |
| 3277 | ||
| 3278 | const body = sema.code.bodySlice(extra_index, body_len); | |
| 3279 | extra_index += body.len; | |
| 3280 | ||
| 3281 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; | |
| 3282 | const body_end = extra_index; | |
| 3283 | extra_index += bit_bags_count; | |
| 3284 | ||
| 3285 | const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| { | |
| 3286 | if (bag != 0) break true; | |
| 3287 | } else false; | |
| 3288 | ||
| 3289 | const enum_init: InternPool.EnumTypeInit = .{ | |
| 3290 | .has_values = any_values, | |
| 3291 | .tag_mode = if (small.nonexhaustive) | |
| 3292 | .nonexhaustive | |
| 3293 | else if (tag_type_ref == .none) | |
| 3294 | .auto | |
| 3295 | else | |
| 3296 | .explicit, | |
| 3297 | .fields_len = fields_len, | |
| 3298 | .key = .{ .declared = .{ | |
| 3299 | .zir_index = tracked_inst, | |
| 3300 | .captures = captures, | |
| 3301 | } }, | |
| 3302 | }; | |
| 3303 | const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, enum_init, false)) { | |
| 3304 | .existing => |ty| { | |
| 3305 | const new_ty = try pt.ensureTypeUpToDate(ty); | |
| 3306 | ||
| 3307 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | |
| 3308 | // up on e.g. changed comptime decls. | |
| 3309 | try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu)); | |
| 3310 | ||
| 3311 | try sema.declareDependency(.{ .interned = new_ty }); | |
| 3312 | try sema.addTypeReferenceEntry(src, new_ty); | |
| 3313 | ||
| 3314 | // Since this is an enum, it has to be resolved immediately. | |
| 3315 | // `ensureTypeUpToDate` has resolved the new type if necessary. | |
| 3316 | // We just need to check for resolution failures. | |
| 3317 | const ty_unit: AnalUnit = .wrap(.{ .type = new_ty }); | |
| 3318 | if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) { | |
| 3319 | return error.AnalysisFail; | |
| 3320 | } | |
| 3321 | ||
| 3322 | return Air.internedToRef(new_ty); | |
| 3323 | }, | |
| 3324 | .wip => |wip| wip, | |
| 3325 | }; | |
| 3326 | ||
| 3327 | // Once this is `true`, we will not delete the decl or type even upon failure, since we | |
| 3328 | // have finished constructing the type and are in the process of analyzing it. | |
| 3329 | var done = false; | |
| 3330 | ||
| 3331 | errdefer if (!done) wip_ty.cancel(ip, pt.tid); | |
| 3332 | ||
| 3333 | const type_name = try sema.createTypeName( | |
| 3334 | block, | |
| 3335 | small.name_strategy, | |
| 3336 | "enum", | |
| 3337 | inst, | |
| 3338 | wip_ty.index, | |
| 3339 | ); | |
| 3340 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 3341 | ||
| 3342 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3343 | .parent = block.namespace.toOptional(), | |
| 3344 | .owner_type = wip_ty.index, | |
| 3345 | .file_scope = block.getFileScopeIndex(zcu), | |
| 3346 | .generation = zcu.generation, | |
| 3347 | }); | |
| 3348 | errdefer if (!done) pt.destroyNamespace(new_namespace_index); | |
| 3349 | ||
| 3350 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3351 | ||
| 3352 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 3353 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 3354 | ||
| 3355 | // We've finished the initial construction of this type, and are about to perform analysis. | |
| 3356 | // Set the namespace appropriately, and don't destroy anything on failure. | |
| 3357 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 3358 | wip_ty.prepare(ip, new_namespace_index); | |
| 3359 | done = true; | |
| 3360 | ||
| 3361 | { | |
| 3362 | const tracked_unit = zcu.trackUnitSema(type_name.name.toSlice(ip), null); | |
| 3363 | defer tracked_unit.end(zcu); | |
| 3364 | try Sema.resolveDeclaredEnum( | |
| 3365 | pt, | |
| 3366 | wip_ty, | |
| 3367 | inst, | |
| 3368 | tracked_inst, | |
| 3369 | new_namespace_index, | |
| 3370 | type_name.name, | |
| 3371 | small, | |
| 3372 | body, | |
| 3373 | tag_type_ref, | |
| 3374 | any_values, | |
| 3375 | fields_len, | |
| 3376 | sema.code, | |
| 3377 | body_end, | |
| 3378 | ); | |
| 3379 | } | |
| 3380 | ||
| 3381 | codegen_type: { | |
| 3382 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 3383 | if (block.ownerModule().strip) break :codegen_type; | |
| 3384 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 3385 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3386 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 3387 | } | |
| 3388 | return Air.internedToRef(wip_ty.index); | |
| 3207 | const object_ty = sema.typeOf(object); | |
| 3208 | const is_pointer_to = object_ty.isSinglePointer(zcu); | |
| 3209 | const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty; | |
| 3210 | try sema.checkIndexable(block, src, indexable_ty); | |
| 3211 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); | |
| 3212 | return sema.fieldVal(block, src, object, field_name, src); | |
| 3389 | 3213 | } |
| 3390 | 3214 | |
| 3391 | fn zirUnionDecl( | |
| 3215 | fn indexablePtrLenOrNone( | |
| 3392 | 3216 | sema: *Sema, |
| 3393 | 3217 | block: *Block, |
| 3394 | extended: Zir.Inst.Extended.InstData, | |
| 3395 | inst: Zir.Inst.Index, | |
| 3218 | src: LazySrcLoc, | |
| 3219 | operand: Air.Inst.Ref, | |
| 3396 | 3220 | ) CompileError!Air.Inst.Ref { |
| 3397 | const tracy = trace(@src()); | |
| 3398 | defer tracy.end(); | |
| 3399 | ||
| 3400 | 3221 | const pt = sema.pt; |
| 3401 | 3222 | const zcu = pt.zcu; |
| 3402 | 3223 | const comp = zcu.comp; |
| 3403 | 3224 | const gpa = comp.gpa; |
| 3404 | 3225 | const io = comp.io; |
| 3405 | const ip = &zcu.intern_pool; | |
| 3406 | ||
| 3407 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | |
| 3408 | const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); | |
| 3409 | var extra_index: usize = extra.end; | |
| 3410 | ||
| 3411 | const tracked_inst = try block.trackZir(inst); | |
| 3412 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; | |
| 3413 | ||
| 3414 | extra_index += @intFromBool(small.has_tag_type); | |
| 3415 | const captures_len = if (small.has_captures_len) blk: { | |
| 3416 | const captures_len = sema.code.extra[extra_index]; | |
| 3417 | extra_index += 1; | |
| 3418 | break :blk captures_len; | |
| 3419 | } else 0; | |
| 3420 | extra_index += @intFromBool(small.has_body_len); | |
| 3421 | const fields_len = if (small.has_fields_len) blk: { | |
| 3422 | const fields_len = sema.code.extra[extra_index]; | |
| 3423 | extra_index += 1; | |
| 3424 | break :blk fields_len; | |
| 3425 | } else 0; | |
| 3426 | ||
| 3427 | const decls_len = if (small.has_decls_len) blk: { | |
| 3428 | const decls_len = sema.code.extra[extra_index]; | |
| 3429 | extra_index += 1; | |
| 3430 | break :blk decls_len; | |
| 3431 | } else 0; | |
| 3432 | ||
| 3433 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); | |
| 3434 | extra_index += captures_len * 2; | |
| 3435 | ||
| 3436 | const union_init: InternPool.UnionTypeInit = .{ | |
| 3437 | .flags = .{ | |
| 3438 | .layout = small.layout, | |
| 3439 | .status = .none, | |
| 3440 | .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) | |
| 3441 | .tagged | |
| 3442 | else if (small.layout != .auto) | |
| 3443 | .none | |
| 3444 | else switch (block.wantSafeTypes()) { | |
| 3445 | true => .safety, | |
| 3446 | false => .none, | |
| 3447 | }, | |
| 3448 | .any_aligned_fields = small.any_aligned_fields, | |
| 3449 | .requires_comptime = .unknown, | |
| 3450 | .assumed_runtime_bits = false, | |
| 3451 | .assumed_pointer_aligned = false, | |
| 3452 | .alignment = .none, | |
| 3453 | }, | |
| 3454 | .fields_len = fields_len, | |
| 3455 | .enum_tag_ty = .none, // set later | |
| 3456 | .field_types = &.{}, // set later | |
| 3457 | .field_aligns = &.{}, // set later | |
| 3458 | .key = .{ .declared = .{ | |
| 3459 | .zir_index = tracked_inst, | |
| 3460 | .captures = captures, | |
| 3461 | } }, | |
| 3462 | }; | |
| 3463 | const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, union_init, false)) { | |
| 3464 | .existing => |ty| { | |
| 3465 | const new_ty = try pt.ensureTypeUpToDate(ty); | |
| 3466 | ||
| 3467 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | |
| 3468 | // up on e.g. changed comptime decls. | |
| 3469 | try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu)); | |
| 3470 | ||
| 3471 | try sema.declareDependency(.{ .interned = new_ty }); | |
| 3472 | try sema.addTypeReferenceEntry(src, new_ty); | |
| 3473 | return Air.internedToRef(new_ty); | |
| 3474 | }, | |
| 3475 | .wip => |wip| wip, | |
| 3476 | }; | |
| 3477 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 3478 | ||
| 3479 | const type_name = try sema.createTypeName( | |
| 3480 | block, | |
| 3481 | small.name_strategy, | |
| 3482 | "union", | |
| 3483 | inst, | |
| 3484 | wip_ty.index, | |
| 3485 | ); | |
| 3486 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 3487 | ||
| 3488 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3489 | .parent = block.namespace.toOptional(), | |
| 3490 | .owner_type = wip_ty.index, | |
| 3491 | .file_scope = block.getFileScopeIndex(zcu), | |
| 3492 | .generation = zcu.generation, | |
| 3493 | }); | |
| 3494 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 3495 | ||
| 3496 | if (pt.zcu.comp.config.incremental) { | |
| 3497 | try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); | |
| 3498 | } | |
| 3499 | ||
| 3500 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3501 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3502 | ||
| 3503 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 3504 | codegen_type: { | |
| 3505 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 3506 | if (block.ownerModule().strip) break :codegen_type; | |
| 3507 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 3508 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3509 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 3226 | const operand_ty = sema.typeOf(operand); | |
| 3227 | try checkMemOperand(sema, block, src, operand_ty); | |
| 3228 | switch (operand_ty.ptrSize(zcu)) { | |
| 3229 | .many, .c => return .none, | |
| 3230 | .one, .slice => {}, | |
| 3510 | 3231 | } |
| 3511 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 3512 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 3513 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 3514 | return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); | |
| 3232 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); | |
| 3233 | return sema.fieldVal(block, src, operand, field_name, src); | |
| 3515 | 3234 | } |
| 3516 | 3235 | |
| 3517 | fn zirOpaqueDecl( | |
| 3236 | fn zirAllocExtended( | |
| 3518 | 3237 | sema: *Sema, |
| 3519 | 3238 | block: *Block, |
| 3520 | 3239 | extended: Zir.Inst.Extended.InstData, |
| 3521 | inst: Zir.Inst.Index, | |
| 3522 | 3240 | ) CompileError!Air.Inst.Ref { |
| 3523 | const tracy = trace(@src()); | |
| 3524 | defer tracy.end(); | |
| 3525 | ||
| 3526 | 3241 | const pt = sema.pt; |
| 3527 | 3242 | const zcu = pt.zcu; |
| 3528 | const comp = zcu.comp; | |
| 3529 | const gpa = comp.gpa; | |
| 3530 | const io = comp.io; | |
| 3531 | const ip = &zcu.intern_pool; | |
| 3243 | const gpa = sema.gpa; | |
| 3244 | const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); | |
| 3245 | const var_src = block.nodeOffset(extra.data.src_node); | |
| 3246 | const ty_src = block.src(.{ .node_offset_var_decl_ty = extra.data.src_node }); | |
| 3247 | const align_src = block.src(.{ .node_offset_var_decl_align = extra.data.src_node }); | |
| 3248 | const small: Zir.Inst.AllocExtended.Small = @bitCast(extended.small); | |
| 3532 | 3249 | |
| 3533 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); | |
| 3534 | const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); | |
| 3535 | 3250 | var extra_index: usize = extra.end; |
| 3536 | 3251 | |
| 3537 | const tracked_inst = try block.trackZir(inst); | |
| 3538 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; | |
| 3539 | ||
| 3540 | const captures_len = if (small.has_captures_len) blk: { | |
| 3541 | const captures_len = sema.code.extra[extra_index]; | |
| 3252 | const var_ty: Type = if (small.has_type) blk: { | |
| 3253 | const type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | |
| 3542 | 3254 | extra_index += 1; |
| 3543 | break :blk captures_len; | |
| 3544 | } else 0; | |
| 3255 | break :blk try sema.resolveType(block, ty_src, type_ref); | |
| 3256 | } else undefined; | |
| 3545 | 3257 | |
| 3546 | const decls_len = if (small.has_decls_len) blk: { | |
| 3547 | const decls_len = sema.code.extra[extra_index]; | |
| 3258 | const alignment = if (small.has_align) blk: { | |
| 3259 | const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | |
| 3548 | 3260 | extra_index += 1; |
| 3549 | break :blk decls_len; | |
| 3550 | } else 0; | |
| 3551 | ||
| 3552 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); | |
| 3553 | extra_index += captures_len * 2; | |
| 3554 | ||
| 3555 | const opaque_init: InternPool.OpaqueTypeInit = .{ | |
| 3556 | .zir_index = tracked_inst, | |
| 3557 | .captures = captures, | |
| 3558 | }; | |
| 3559 | const wip_ty = switch (try ip.getOpaqueType(gpa, io, pt.tid, opaque_init)) { | |
| 3560 | .existing => |ty| { | |
| 3561 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | |
| 3562 | // up on e.g. changed comptime decls. | |
| 3563 | try pt.ensureNamespaceUpToDate(Type.fromInterned(ty).getNamespaceIndex(zcu)); | |
| 3261 | break :blk try sema.resolveAlign(block, align_src, align_ref); | |
| 3262 | } else .none; | |
| 3564 | 3263 | |
| 3565 | try sema.declareDependency(.{ .interned = ty }); | |
| 3566 | try sema.addTypeReferenceEntry(src, ty); | |
| 3567 | return Air.internedToRef(ty); | |
| 3568 | }, | |
| 3569 | .wip => |wip| wip, | |
| 3570 | }; | |
| 3571 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 3264 | if (small.has_type) { | |
| 3265 | try sema.ensureLayoutResolved(var_ty, var_src, if (small.is_const) .constant else .variable); | |
| 3266 | if (block.isComptime() or small.is_comptime or var_ty.comptimeOnly(zcu)) { | |
| 3267 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); | |
| 3268 | } | |
| 3269 | if (!small.is_const) { | |
| 3270 | try sema.validateVarType(block, ty_src, var_ty, false); | |
| 3271 | } | |
| 3272 | const target = pt.zcu.getTarget(); | |
| 3273 | if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { | |
| 3274 | const store_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node }); | |
| 3275 | return sema.fail(block, store_src, "local variable in naked function", .{}); | |
| 3276 | } | |
| 3277 | const ptr_type = try pt.ptrType(.{ | |
| 3278 | .child = var_ty.toIntern(), | |
| 3279 | .flags = .{ | |
| 3280 | .alignment = alignment, | |
| 3281 | .address_space = target_util.defaultAddressSpace(target, .local), | |
| 3282 | }, | |
| 3283 | }); | |
| 3284 | const ptr = try block.addTy(.alloc, ptr_type); | |
| 3285 | if (small.is_const) { | |
| 3286 | const ptr_inst = ptr.toIndex().?; | |
| 3287 | try sema.maybe_comptime_allocs.put(gpa, ptr_inst, .{ .runtime_index = block.runtime_index }); | |
| 3288 | try sema.base_allocs.put(gpa, ptr_inst, ptr_inst); | |
| 3289 | } | |
| 3290 | return ptr; | |
| 3291 | } | |
| 3572 | 3292 | |
| 3573 | const type_name = try sema.createTypeName( | |
| 3574 | block, | |
| 3575 | small.name_strategy, | |
| 3576 | "opaque", | |
| 3577 | inst, | |
| 3578 | wip_ty.index, | |
| 3579 | ); | |
| 3580 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 3293 | if (block.isComptime() or small.is_comptime) { | |
| 3294 | const iac_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); | |
| 3295 | try sema.air_instructions.append(gpa, .{ | |
| 3296 | .tag = .inferred_alloc_comptime, | |
| 3297 | .data = .{ .inferred_alloc_comptime = .{ | |
| 3298 | .alignment = alignment, | |
| 3299 | .is_const = small.is_const, | |
| 3300 | .ptr = undefined, | |
| 3301 | } }, | |
| 3302 | }); | |
| 3303 | return iac_index.toRef(); | |
| 3304 | } | |
| 3581 | 3305 | |
| 3582 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 3583 | .parent = block.namespace.toOptional(), | |
| 3584 | .owner_type = wip_ty.index, | |
| 3585 | .file_scope = block.getFileScopeIndex(zcu), | |
| 3586 | .generation = zcu.generation, | |
| 3306 | const result_index = try block.addInstAsIndex(.{ | |
| 3307 | .tag = .inferred_alloc, | |
| 3308 | .data = .{ .inferred_alloc = .{ | |
| 3309 | .alignment = alignment, | |
| 3310 | .is_const = small.is_const, | |
| 3311 | } }, | |
| 3587 | 3312 | }); |
| 3588 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 3589 | ||
| 3590 | const decls = sema.code.bodySlice(extra_index, decls_len); | |
| 3591 | try pt.scanNamespace(new_namespace_index, decls); | |
| 3592 | ||
| 3593 | codegen_type: { | |
| 3594 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 3595 | if (block.ownerModule().strip) break :codegen_type; | |
| 3596 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 3597 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3598 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 3313 | try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{}); | |
| 3314 | if (small.is_const) { | |
| 3315 | try sema.maybe_comptime_allocs.put(gpa, result_index, .{ .runtime_index = block.runtime_index }); | |
| 3316 | try sema.base_allocs.put(gpa, result_index, result_index); | |
| 3599 | 3317 | } |
| 3600 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 3601 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 3602 | return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); | |
| 3318 | return result_index.toRef(); | |
| 3603 | 3319 | } |
| 3604 | 3320 | |
| 3605 | fn zirErrorSetDecl( | |
| 3606 | sema: *Sema, | |
| 3607 | inst: Zir.Inst.Index, | |
| 3608 | ) CompileError!Air.Inst.Ref { | |
| 3321 | fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3609 | 3322 | const tracy = trace(@src()); |
| 3610 | 3323 | defer tracy.end(); |
| 3611 | 3324 | |
| 3612 | const pt = sema.pt; | |
| 3613 | const zcu = pt.zcu; | |
| 3614 | const comp = zcu.comp; | |
| 3615 | const gpa = comp.gpa; | |
| 3616 | const io = comp.io; | |
| 3617 | ||
| 3618 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | |
| 3619 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); | |
| 3620 | ||
| 3621 | var names: InferredErrorSet.NameMap = .{}; | |
| 3622 | try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); | |
| 3623 | ||
| 3624 | var extra_index: u32 = @intCast(extra.end); | |
| 3625 | const extra_index_end = extra_index + extra.data.fields_len; | |
| 3626 | while (extra_index < extra_index_end) : (extra_index += 1) { | |
| 3627 | const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]); | |
| 3628 | const name = sema.code.nullTerminatedString(name_index); | |
| 3629 | const name_ip = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); | |
| 3630 | _ = try pt.getErrorValue(name_ip); | |
| 3631 | const result = names.getOrPutAssumeCapacity(name_ip); | |
| 3632 | assert(!result.found_existing); // verified in AstGen | |
| 3633 | } | |
| 3634 | ||
| 3635 | return Air.internedToRef((try pt.errorSetFromUnsortedNames(names.keys())).toIntern()); | |
| 3325 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3326 | const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); | |
| 3327 | const var_src = block.nodeOffset(inst_data.src_node); | |
| 3328 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | |
| 3329 | try sema.ensureLayoutResolved(var_ty, var_src, .variable); | |
| 3330 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); | |
| 3636 | 3331 | } |
| 3637 | 3332 | |
| 3638 | fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3639 | const tracy = trace(@src()); | |
| 3640 | defer tracy.end(); | |
| 3641 | ||
| 3333 | fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3642 | 3334 | const pt = sema.pt; |
| 3335 | const zcu = pt.zcu; | |
| 3336 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3337 | const alloc = sema.resolveInst(inst_data.operand); | |
| 3338 | const alloc_ty = sema.typeOf(alloc); | |
| 3339 | const ptr_info = alloc_ty.ptrInfo(zcu); | |
| 3340 | const elem_ty: Type = .fromInterned(ptr_info.child); | |
| 3643 | 3341 | |
| 3644 | const src = block.nodeOffset(sema.code.instructions.items(.data)[@intFromEnum(inst)].node); | |
| 3645 | ||
| 3646 | if (block.isComptime() or try sema.fn_ret_ty.comptimeOnlySema(pt)) { | |
| 3647 | try sema.fn_ret_ty.resolveFields(pt); | |
| 3648 | return sema.analyzeComptimeAlloc(block, src, sema.fn_ret_ty, .none); | |
| 3649 | } | |
| 3650 | ||
| 3651 | const target = pt.zcu.getTarget(); | |
| 3652 | const ptr_type = try pt.ptrTypeSema(.{ | |
| 3653 | .child = sema.fn_ret_ty.toIntern(), | |
| 3654 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, | |
| 3655 | }); | |
| 3656 | ||
| 3657 | if (block.inlining != null) { | |
| 3658 | // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr. | |
| 3659 | // TODO when functions gain result location support, the inlining struct in | |
| 3660 | // Block should contain the return pointer, and we would pass that through here. | |
| 3661 | return block.addTy(.alloc, ptr_type); | |
| 3662 | } | |
| 3663 | ||
| 3664 | return block.addTy(.ret_ptr, ptr_type); | |
| 3665 | } | |
| 3666 | ||
| 3667 | fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3668 | const tracy = trace(@src()); | |
| 3669 | defer tracy.end(); | |
| 3670 | ||
| 3671 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; | |
| 3672 | const operand = try sema.resolveInst(inst_data.operand); | |
| 3673 | return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand); | |
| 3674 | } | |
| 3675 | ||
| 3676 | fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3677 | const tracy = trace(@src()); | |
| 3678 | defer tracy.end(); | |
| 3679 | ||
| 3680 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3681 | const operand = try sema.resolveInst(inst_data.operand); | |
| 3682 | const src = block.nodeOffset(inst_data.src_node); | |
| 3683 | ||
| 3684 | return sema.ensureResultUsed(block, sema.typeOf(operand), src); | |
| 3685 | } | |
| 3686 | ||
| 3687 | fn ensureResultUsed( | |
| 3688 | sema: *Sema, | |
| 3689 | block: *Block, | |
| 3690 | ty: Type, | |
| 3691 | src: LazySrcLoc, | |
| 3692 | ) CompileError!void { | |
| 3693 | const pt = sema.pt; | |
| 3694 | const zcu = pt.zcu; | |
| 3695 | switch (ty.zigTypeTag(zcu)) { | |
| 3696 | .void, .noreturn => return, | |
| 3697 | .error_set => return sema.fail(block, src, "error set is ignored", .{}), | |
| 3698 | .error_union => { | |
| 3699 | const msg = msg: { | |
| 3700 | const msg = try sema.errMsg(src, "error union is ignored", .{}); | |
| 3701 | errdefer msg.destroy(sema.gpa); | |
| 3702 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); | |
| 3703 | break :msg msg; | |
| 3704 | }; | |
| 3705 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3706 | }, | |
| 3707 | else => { | |
| 3708 | const msg = msg: { | |
| 3709 | const msg = try sema.errMsg(src, "value of type '{f}' ignored", .{ty.fmt(pt)}); | |
| 3710 | errdefer msg.destroy(sema.gpa); | |
| 3711 | try sema.errNote(src, msg, "all non-void values must be used", .{}); | |
| 3712 | try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{}); | |
| 3713 | break :msg msg; | |
| 3714 | }; | |
| 3715 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3716 | }, | |
| 3717 | } | |
| 3718 | } | |
| 3719 | ||
| 3720 | fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3721 | const tracy = trace(@src()); | |
| 3722 | defer tracy.end(); | |
| 3723 | ||
| 3724 | const pt = sema.pt; | |
| 3725 | const zcu = pt.zcu; | |
| 3726 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3727 | const operand = try sema.resolveInst(inst_data.operand); | |
| 3728 | const src = block.nodeOffset(inst_data.src_node); | |
| 3729 | const operand_ty = sema.typeOf(operand); | |
| 3730 | switch (operand_ty.zigTypeTag(zcu)) { | |
| 3731 | .error_set => return sema.fail(block, src, "error set is discarded", .{}), | |
| 3732 | .error_union => { | |
| 3733 | const msg = msg: { | |
| 3734 | const msg = try sema.errMsg(src, "error union is discarded", .{}); | |
| 3735 | errdefer msg.destroy(sema.gpa); | |
| 3736 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); | |
| 3737 | break :msg msg; | |
| 3738 | }; | |
| 3739 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3740 | }, | |
| 3741 | else => return, | |
| 3742 | } | |
| 3743 | } | |
| 3744 | ||
| 3745 | fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | |
| 3746 | const tracy = trace(@src()); | |
| 3747 | defer tracy.end(); | |
| 3748 | ||
| 3749 | const pt = sema.pt; | |
| 3750 | const zcu = pt.zcu; | |
| 3751 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3752 | const src = block.nodeOffset(inst_data.src_node); | |
| 3753 | const operand = try sema.resolveInst(inst_data.operand); | |
| 3754 | const operand_ty = sema.typeOf(operand); | |
| 3755 | const err_union_ty = if (operand_ty.zigTypeTag(zcu) == .pointer) | |
| 3756 | operand_ty.childType(zcu) | |
| 3757 | else | |
| 3758 | operand_ty; | |
| 3759 | if (err_union_ty.zigTypeTag(zcu) != .error_union) return; | |
| 3760 | const payload_ty = err_union_ty.errorUnionPayload(zcu).zigTypeTag(zcu); | |
| 3761 | if (payload_ty != .void and payload_ty != .noreturn) { | |
| 3762 | const msg = msg: { | |
| 3763 | const msg = try sema.errMsg(src, "error union payload is ignored", .{}); | |
| 3764 | errdefer msg.destroy(sema.gpa); | |
| 3765 | try sema.errNote(src, msg, "payload value can be explicitly ignored with '|_|'", .{}); | |
| 3766 | break :msg msg; | |
| 3767 | }; | |
| 3768 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 3769 | } | |
| 3770 | } | |
| 3771 | ||
| 3772 | fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3773 | const tracy = trace(@src()); | |
| 3774 | defer tracy.end(); | |
| 3775 | ||
| 3776 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3777 | const src = block.nodeOffset(inst_data.src_node); | |
| 3778 | const object = try sema.resolveInst(inst_data.operand); | |
| 3779 | ||
| 3780 | return indexablePtrLen(sema, block, src, object); | |
| 3781 | } | |
| 3782 | ||
| 3783 | fn indexablePtrLen( | |
| 3784 | sema: *Sema, | |
| 3785 | block: *Block, | |
| 3786 | src: LazySrcLoc, | |
| 3787 | object: Air.Inst.Ref, | |
| 3788 | ) CompileError!Air.Inst.Ref { | |
| 3789 | const pt = sema.pt; | |
| 3790 | const zcu = pt.zcu; | |
| 3791 | const comp = zcu.comp; | |
| 3792 | const gpa = comp.gpa; | |
| 3793 | const io = comp.io; | |
| 3794 | const object_ty = sema.typeOf(object); | |
| 3795 | const is_pointer_to = object_ty.isSinglePointer(zcu); | |
| 3796 | const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty; | |
| 3797 | try sema.checkIndexable(block, src, indexable_ty); | |
| 3798 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); | |
| 3799 | return sema.fieldVal(block, src, object, field_name, src); | |
| 3800 | } | |
| 3801 | ||
| 3802 | fn indexablePtrLenOrNone( | |
| 3803 | sema: *Sema, | |
| 3804 | block: *Block, | |
| 3805 | src: LazySrcLoc, | |
| 3806 | operand: Air.Inst.Ref, | |
| 3807 | ) CompileError!Air.Inst.Ref { | |
| 3808 | const pt = sema.pt; | |
| 3809 | const zcu = pt.zcu; | |
| 3810 | const comp = zcu.comp; | |
| 3811 | const gpa = comp.gpa; | |
| 3812 | const io = comp.io; | |
| 3813 | const operand_ty = sema.typeOf(operand); | |
| 3814 | try checkMemOperand(sema, block, src, operand_ty); | |
| 3815 | switch (operand_ty.ptrSize(zcu)) { | |
| 3816 | .many, .c => return .none, | |
| 3817 | .one, .slice => {}, | |
| 3818 | } | |
| 3819 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); | |
| 3820 | return sema.fieldVal(block, src, operand, field_name, src); | |
| 3821 | } | |
| 3822 | ||
| 3823 | fn zirAllocExtended( | |
| 3824 | sema: *Sema, | |
| 3825 | block: *Block, | |
| 3826 | extended: Zir.Inst.Extended.InstData, | |
| 3827 | ) CompileError!Air.Inst.Ref { | |
| 3828 | const pt = sema.pt; | |
| 3829 | const gpa = sema.gpa; | |
| 3830 | const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); | |
| 3831 | const var_src = block.nodeOffset(extra.data.src_node); | |
| 3832 | const ty_src = block.src(.{ .node_offset_var_decl_ty = extra.data.src_node }); | |
| 3833 | const align_src = block.src(.{ .node_offset_var_decl_align = extra.data.src_node }); | |
| 3834 | const small: Zir.Inst.AllocExtended.Small = @bitCast(extended.small); | |
| 3835 | ||
| 3836 | var extra_index: usize = extra.end; | |
| 3837 | ||
| 3838 | const var_ty: Type = if (small.has_type) blk: { | |
| 3839 | const type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | |
| 3840 | extra_index += 1; | |
| 3841 | break :blk try sema.resolveType(block, ty_src, type_ref); | |
| 3842 | } else undefined; | |
| 3843 | ||
| 3844 | const alignment = if (small.has_align) blk: { | |
| 3845 | const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | |
| 3846 | extra_index += 1; | |
| 3847 | break :blk try sema.resolveAlign(block, align_src, align_ref); | |
| 3848 | } else .none; | |
| 3849 | ||
| 3850 | if (block.isComptime() or small.is_comptime) { | |
| 3851 | if (small.has_type) { | |
| 3852 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); | |
| 3853 | } else { | |
| 3854 | try sema.air_instructions.append(gpa, .{ | |
| 3855 | .tag = .inferred_alloc_comptime, | |
| 3856 | .data = .{ .inferred_alloc_comptime = .{ | |
| 3857 | .alignment = alignment, | |
| 3858 | .is_const = small.is_const, | |
| 3859 | .ptr = undefined, | |
| 3860 | } }, | |
| 3861 | }); | |
| 3862 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); | |
| 3863 | } | |
| 3864 | } | |
| 3865 | ||
| 3866 | if (small.has_type and try var_ty.comptimeOnlySema(pt)) { | |
| 3867 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); | |
| 3868 | } | |
| 3869 | ||
| 3870 | if (small.has_type) { | |
| 3871 | if (!small.is_const) { | |
| 3872 | try sema.validateVarType(block, ty_src, var_ty, false); | |
| 3873 | } | |
| 3874 | const target = pt.zcu.getTarget(); | |
| 3875 | try var_ty.resolveLayout(pt); | |
| 3876 | if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) { | |
| 3877 | const store_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node }); | |
| 3878 | return sema.fail(block, store_src, "local variable in naked function", .{}); | |
| 3879 | } | |
| 3880 | const ptr_type = try sema.pt.ptrTypeSema(.{ | |
| 3881 | .child = var_ty.toIntern(), | |
| 3882 | .flags = .{ | |
| 3883 | .alignment = alignment, | |
| 3884 | .address_space = target_util.defaultAddressSpace(target, .local), | |
| 3885 | }, | |
| 3886 | }); | |
| 3887 | const ptr = try block.addTy(.alloc, ptr_type); | |
| 3888 | if (small.is_const) { | |
| 3889 | const ptr_inst = ptr.toIndex().?; | |
| 3890 | try sema.maybe_comptime_allocs.put(gpa, ptr_inst, .{ .runtime_index = block.runtime_index }); | |
| 3891 | try sema.base_allocs.put(gpa, ptr_inst, ptr_inst); | |
| 3892 | } | |
| 3893 | return ptr; | |
| 3894 | } | |
| 3895 | ||
| 3896 | const result_index = try block.addInstAsIndex(.{ | |
| 3897 | .tag = .inferred_alloc, | |
| 3898 | .data = .{ .inferred_alloc = .{ | |
| 3899 | .alignment = alignment, | |
| 3900 | .is_const = small.is_const, | |
| 3901 | } }, | |
| 3902 | }); | |
| 3903 | try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{}); | |
| 3904 | if (small.is_const) { | |
| 3905 | try sema.maybe_comptime_allocs.put(gpa, result_index, .{ .runtime_index = block.runtime_index }); | |
| 3906 | try sema.base_allocs.put(gpa, result_index, result_index); | |
| 3907 | } | |
| 3908 | return result_index.toRef(); | |
| 3909 | } | |
| 3910 | ||
| 3911 | fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3912 | const tracy = trace(@src()); | |
| 3913 | defer tracy.end(); | |
| 3914 | ||
| 3915 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3916 | const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); | |
| 3917 | const var_src = block.nodeOffset(inst_data.src_node); | |
| 3918 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); | |
| 3919 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); | |
| 3920 | } | |
| 3921 | ||
| 3922 | fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 3923 | const pt = sema.pt; | |
| 3924 | const zcu = pt.zcu; | |
| 3925 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | |
| 3926 | const alloc = try sema.resolveInst(inst_data.operand); | |
| 3927 | const alloc_ty = sema.typeOf(alloc); | |
| 3928 | const ptr_info = alloc_ty.ptrInfo(zcu); | |
| 3929 | const elem_ty: Type = .fromInterned(ptr_info.child); | |
| 3930 | ||
| 3931 | // If the alloc was created in a comptime scope, we already created a comptime alloc for it. | |
| 3932 | // However, if the final constructed value does not reference comptime-mutable memory, we wish | |
| 3933 | // to promote it to an anon decl. | |
| 3934 | already_ct: { | |
| 3935 | const ptr_val = try sema.resolveValue(alloc) orelse break :already_ct; | |
| 3342 | // If the alloc was created in a comptime scope, we already created a comptime alloc for it. | |
| 3343 | // However, if the final constructed value does not reference comptime-mutable memory, we wish | |
| 3344 | // to promote it to an anon decl. | |
| 3345 | already_ct: { | |
| 3346 | const ptr_val = sema.resolveValue(alloc) orelse break :already_ct; | |
| 3936 | 3347 | |
| 3937 | 3348 | // If this was a comptime inferred alloc, then `storeToInferredAllocComptime` |
| 3938 | 3349 | // might have already done our job and created an anon decl ref. |
| ... | ... | @@ -3978,7 +3389,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3978 | 3389 | return sema.makePtrConst(block, Air.internedToRef(ptr_val)); |
| 3979 | 3390 | } |
| 3980 | 3391 | |
| 3981 | if (try elem_ty.comptimeOnlySema(pt)) { | |
| 3392 | if (elem_ty.comptimeOnly(zcu)) { | |
| 3982 | 3393 | // The value was initialized through RLS, so we didn't detect the runtime condition earlier. |
| 3983 | 3394 | // TODO: source location of runtime control flow |
| 3984 | 3395 | const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node }); |
| ... | ... | @@ -4001,20 +3412,23 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4001 | 3412 | const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); |
| 4002 | 3413 | const ptr_info = alloc_ty.ptrInfo(zcu); |
| 4003 | 3414 | const elem_ty: Type = .fromInterned(ptr_info.child); |
| 3415 | elem_ty.assertHasLayout(zcu); | |
| 4004 | 3416 | |
| 4005 | 3417 | const alloc_inst = alloc.toIndex() orelse return null; |
| 4006 | 3418 | const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null; |
| 4007 | 3419 | const stores = comptime_info.value.stores.items(.inst); |
| 4008 | 3420 | |
| 3421 | // If the elem type is OPV, no need to faff about with `stores`; just use the OPV. | |
| 3422 | if (try elem_ty.onePossibleValue(pt)) |opv| { | |
| 3423 | return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, opv.toIntern(), null, alloc_inst, comptime_info.value); | |
| 3424 | } | |
| 3425 | ||
| 3426 | // Since the elem type isn't OPV, there should have been at least one store. | |
| 3427 | assert(stores.len > 0); | |
| 3428 | ||
| 4009 | 3429 | // Since the entry existed in `maybe_comptime_allocs`, the allocation is comptime-known. |
| 4010 | 3430 | // We will resolve and return its value. |
| 4011 | 3431 | |
| 4012 | // We expect to have emitted at least one store, unless the elem type is OPV. | |
| 4013 | if (stores.len == 0) { | |
| 4014 | const val = (try sema.typeHasOnePossibleValue(elem_ty)).?.toIntern(); | |
| 4015 | return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, null, alloc_inst, comptime_info.value); | |
| 4016 | } | |
| 4017 | ||
| 4018 | 3432 | // In general, we want to create a comptime alloc of the correct type and |
| 4019 | 3433 | // apply the stores to that alloc in order. However, before going to all |
| 4020 | 3434 | // that effort, let's optimize for the common case of a single store. |
| ... | ... | @@ -4115,10 +3529,10 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4115 | 3529 | Air.Bin, |
| 4116 | 3530 | tmp_air.instructions.items(.data)[@intFromEnum(air_ptr)].ty_pl.payload, |
| 4117 | 3531 | ).data; |
| 4118 | const idx_val = (try sema.resolveValue(data.rhs)).?; | |
| 3532 | const idx_val = sema.resolveValue(data.rhs).?; | |
| 4119 | 3533 | break :blk .{ |
| 4120 | 3534 | data.lhs, |
| 4121 | .{ .elem = try idx_val.toUnsignedIntSema(pt) }, | |
| 3535 | .{ .elem = idx_val.toUnsignedInt(zcu) }, | |
| 4122 | 3536 | }; |
| 4123 | 3537 | }, |
| 4124 | 3538 | .bitcast => .{ |
| ... | ... | @@ -4150,7 +3564,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4150 | 3564 | // If the payload is OPV, we must use that value instead of undef. |
| 4151 | 3565 | const opt_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); |
| 4152 | 3566 | const payload_ty = opt_ty.optionalChild(zcu); |
| 4153 | const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); | |
| 3567 | const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); | |
| 4154 | 3568 | const opt_val = try pt.intern(.{ .opt = .{ |
| 4155 | 3569 | .ty = opt_ty.toIntern(), |
| 4156 | 3570 | .val = payload_val.toIntern(), |
| ... | ... | @@ -4163,7 +3577,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4163 | 3577 | // If the payload is OPV, we must use that value instead of undef. |
| 4164 | 3578 | const eu_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); |
| 4165 | 3579 | const payload_ty = eu_ty.errorUnionPayload(zcu); |
| 4166 | const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); | |
| 3580 | const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); | |
| 4167 | 3581 | const eu_val = try pt.intern(.{ .error_union = .{ |
| 4168 | 3582 | .ty = eu_ty.toIntern(), |
| 4169 | 3583 | .val = .{ .payload = payload_val.toIntern() }, |
| ... | ... | @@ -4173,18 +3587,31 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4173 | 3587 | }, |
| 4174 | 3588 | .field => |idx| ptr: { |
| 4175 | 3589 | const maybe_union_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); |
| 4176 | if (zcu.typeToUnion(maybe_union_ty)) |union_obj| { | |
| 3590 | if (zcu.typeToUnion(maybe_union_ty)) |union_obj| if (union_obj.layout == .auto) { | |
| 4177 | 3591 | // As this is a union field, we must store to the pointer now to set the tag. |
| 4178 | 3592 | // The payload value will be stored later, so undef is a sufficent payload for now. |
| 4179 | 3593 | const payload_ty: Type = .fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]); |
| 4180 | 3594 | const payload_val = try pt.undefValue(payload_ty); |
| 4181 | const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), idx); | |
| 3595 | const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), idx); | |
| 4182 | 3596 | const store_val = try pt.unionValue(maybe_union_ty, tag_val, payload_val); |
| 4183 | 3597 | try sema.storePtrVal(block, .unneeded, .fromInterned(decl_parent_ptr), store_val, maybe_union_ty); |
| 4184 | } | |
| 3598 | }; | |
| 4185 | 3599 | break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, pt)).toIntern(); |
| 4186 | 3600 | }, |
| 4187 | .elem => |idx| (try Value.fromInterned(decl_parent_ptr).ptrElem(idx, pt)).toIntern(), | |
| 3601 | .elem => |idx| ptr: { | |
| 3602 | const parent_ptr_val: Value = .fromInterned(decl_parent_ptr); | |
| 3603 | if (parent_ptr_val.typeOf(zcu).childType(zcu).zigTypeTag(zcu) == .vector) { | |
| 3604 | const elem_ptr_ty: Type = .fromInterned(new_ptr_ty); | |
| 3605 | // Vectors are a bit weird; see logic in `elemPtrVector`. | |
| 3606 | if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) { | |
| 3607 | break :ptr (try pt.getCoerced(parent_ptr_val, elem_ptr_ty)).toIntern(); | |
| 3608 | } else { | |
| 3609 | const bit_offset = idx * @divExact(elem_ptr_ty.childType(zcu).bitSize(zcu), 8); | |
| 3610 | break :ptr (try parent_ptr_val.getOffsetPtr(bit_offset, elem_ptr_ty, pt)).toIntern(); | |
| 3611 | } | |
| 3612 | } | |
| 3613 | break :ptr (try parent_ptr_val.ptrElem(idx, pt)).toIntern(); | |
| 3614 | }, | |
| 4188 | 3615 | }; |
| 4189 | 3616 | try ptr_mapping.put(air_ptr, new_ptr); |
| 4190 | 3617 | } |
| ... | ... | @@ -4207,14 +3634,14 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4207 | 3634 | const tag_val: Value = .fromInterned(store_inst.data.bin_op.rhs.toInterned().?); |
| 4208 | 3635 | const union_ty = union_ptr_val.typeOf(zcu).childType(zcu); |
| 4209 | 3636 | const field_ty = union_ty.unionFieldType(tag_val, zcu).?; |
| 4210 | if (try sema.typeHasOnePossibleValue(field_ty)) |payload_val| { | |
| 3637 | if (try field_ty.onePossibleValue(pt)) |payload_val| { | |
| 4211 | 3638 | const new_union_val = try pt.unionValue(union_ty, tag_val, payload_val); |
| 4212 | 3639 | try sema.storePtrVal(block, .unneeded, union_ptr_val, new_union_val, union_ty); |
| 4213 | 3640 | } |
| 4214 | 3641 | }, |
| 4215 | 3642 | .store, .store_safe => { |
| 4216 | 3643 | const air_ptr_inst = store_inst.data.bin_op.lhs.toIndex().?; |
| 4217 | const store_val = (try sema.resolveValue(store_inst.data.bin_op.rhs)).?; | |
| 3644 | const store_val = sema.resolveValue(store_inst.data.bin_op.rhs).?; | |
| 4218 | 3645 | const new_ptr = ptr_mapping.get(air_ptr_inst).?; |
| 4219 | 3646 | try sema.storePtrVal(block, .unneeded, .fromInterned(new_ptr), store_val, store_val.typeOf(zcu)); |
| 4220 | 3647 | }, |
| ... | ... | @@ -4289,7 +3716,7 @@ fn finishResolveComptimeKnownAllocPtr( |
| 4289 | 3716 | fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { |
| 4290 | 3717 | var ptr_info = ptr_ty.ptrInfo(sema.pt.zcu); |
| 4291 | 3718 | ptr_info.flags.is_const = true; |
| 4292 | return sema.pt.ptrTypeSema(ptr_info); | |
| 3719 | return sema.pt.ptrType(ptr_info); | |
| 4293 | 3720 | } |
| 4294 | 3721 | |
| 4295 | 3722 | fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -4297,7 +3724,7 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai |
| 4297 | 3724 | const const_ptr_ty = try sema.makePtrTyConst(alloc_ty); |
| 4298 | 3725 | |
| 4299 | 3726 | // Detect if a comptime value simply needs to have its type changed. |
| 4300 | if (try sema.resolveValue(alloc)) |val| { | |
| 3727 | if (sema.resolveValue(alloc)) |val| { | |
| 4301 | 3728 | return Air.internedToRef((try sema.pt.getCoerced(val, const_ptr_ty)).toIntern()); |
| 4302 | 3729 | } |
| 4303 | 3730 | |
| ... | ... | @@ -4326,21 +3753,23 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 4326 | 3753 | defer tracy.end(); |
| 4327 | 3754 | |
| 4328 | 3755 | const pt = sema.pt; |
| 3756 | const zcu = pt.zcu; | |
| 4329 | 3757 | |
| 4330 | 3758 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 4331 | 3759 | const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); |
| 4332 | 3760 | const var_src = block.nodeOffset(inst_data.src_node); |
| 4333 | 3761 | |
| 4334 | 3762 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 4335 | if (block.isComptime() or try var_ty.comptimeOnlySema(pt)) { | |
| 3763 | try sema.ensureLayoutResolved(var_ty, var_src, .constant); | |
| 3764 | if (block.isComptime() or var_ty.comptimeOnly(zcu)) { | |
| 4336 | 3765 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); |
| 4337 | 3766 | } |
| 4338 | if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) { | |
| 3767 | if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { | |
| 4339 | 3768 | const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); |
| 4340 | 3769 | return sema.fail(block, mut_src, "local variable in naked function", .{}); |
| 4341 | 3770 | } |
| 4342 | const target = pt.zcu.getTarget(); | |
| 4343 | const ptr_type = try pt.ptrTypeSema(.{ | |
| 3771 | const target = zcu.getTarget(); | |
| 3772 | const ptr_type = try pt.ptrType(.{ | |
| 4344 | 3773 | .child = var_ty.toIntern(), |
| 4345 | 3774 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 4346 | 3775 | }); |
| ... | ... | @@ -4356,21 +3785,24 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 4356 | 3785 | defer tracy.end(); |
| 4357 | 3786 | |
| 4358 | 3787 | const pt = sema.pt; |
| 3788 | const zcu = pt.zcu; | |
| 4359 | 3789 | |
| 4360 | 3790 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 4361 | 3791 | const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); |
| 4362 | 3792 | const var_src = block.nodeOffset(inst_data.src_node); |
| 3793 | ||
| 4363 | 3794 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 3795 | try sema.ensureLayoutResolved(var_ty, var_src, .variable); | |
| 4364 | 3796 | if (block.isComptime()) { |
| 4365 | 3797 | return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); |
| 4366 | 3798 | } |
| 4367 | if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) { | |
| 3799 | if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { | |
| 4368 | 3800 | const store_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); |
| 4369 | 3801 | return sema.fail(block, store_src, "local variable in naked function", .{}); |
| 4370 | 3802 | } |
| 4371 | 3803 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 4372 | const target = pt.zcu.getTarget(); | |
| 4373 | const ptr_type = try pt.ptrTypeSema(.{ | |
| 3804 | const target = zcu.getTarget(); | |
| 3805 | const ptr_type = try pt.ptrType(.{ | |
| 4374 | 3806 | .child = var_ty.toIntern(), |
| 4375 | 3807 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 4376 | 3808 | }); |
| ... | ... | @@ -4424,14 +3856,15 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4424 | 3856 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 4425 | 3857 | const src = block.nodeOffset(inst_data.src_node); |
| 4426 | 3858 | const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); |
| 4427 | const ptr = try sema.resolveInst(inst_data.operand); | |
| 3859 | const ptr = sema.resolveInst(inst_data.operand); | |
| 4428 | 3860 | const ptr_inst = ptr.toIndex().?; |
| 4429 | 3861 | const target = zcu.getTarget(); |
| 4430 | 3862 | |
| 4431 | 3863 | switch (sema.air_instructions.items(.tag)[@intFromEnum(ptr_inst)]) { |
| 4432 | 3864 | .inferred_alloc_comptime => { |
| 4433 | // The work was already done for us by `Sema.storeToInferredAllocComptime`. | |
| 4434 | // All we need to do is return the pointer. | |
| 3865 | // The work was already done for us by `Sema.storeToInferredAllocComptime`. Also, since | |
| 3866 | // we had a value of the exact correct type to store, the result type's layout must be | |
| 3867 | // already resolved. So all we need to do here is return the pointer. | |
| 4435 | 3868 | const iac = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc_comptime; |
| 4436 | 3869 | const resolved_ptr = iac.ptr; |
| 4437 | 3870 | |
| ... | ... | @@ -4450,7 +3883,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4450 | 3883 | }; |
| 4451 | 3884 | if (zcu.intern_pool.isFuncBody(val)) { |
| 4452 | 3885 | const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val)); |
| 4453 | if (try ty.fnHasRuntimeBitsSema(pt)) { | |
| 3886 | if (ty.fnHasRuntimeBits(zcu)) { | |
| 4454 | 3887 | const orig_fn_index = zcu.intern_pool.unwrapCoercedFunc(val); |
| 4455 | 3888 | try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index })); |
| 4456 | 3889 | try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); |
| ... | ... | @@ -4469,8 +3902,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4469 | 3902 | peer_val.* = bin_op.rhs; |
| 4470 | 3903 | } |
| 4471 | 3904 | const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none); |
| 3905 | // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too. | |
| 3906 | final_elem_ty.assertHasLayout(zcu); | |
| 4472 | 3907 | |
| 4473 | const final_ptr_ty = try pt.ptrTypeSema(.{ | |
| 3908 | const final_ptr_ty = try pt.ptrType(.{ | |
| 4474 | 3909 | .child = final_elem_ty.toIntern(), |
| 4475 | 3910 | .flags = .{ |
| 4476 | 3911 | .alignment = ia1.alignment, |
| ... | ... | @@ -4484,21 +3919,16 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4484 | 3919 | const const_ptr_ty = try sema.makePtrTyConst(final_ptr_ty); |
| 4485 | 3920 | const new_const_ptr = try pt.getCoerced(Value.fromInterned(ptr_val), const_ptr_ty); |
| 4486 | 3921 | |
| 4487 | // Unless the block is comptime, `alloc_inferred` always produces | |
| 4488 | // a runtime constant. The final inferred type needs to be | |
| 4489 | // fully resolved so it can be lowered in codegen. | |
| 4490 | try final_elem_ty.resolveFully(pt); | |
| 4491 | ||
| 4492 | 3922 | return Air.internedToRef(new_const_ptr.toIntern()); |
| 4493 | 3923 | } |
| 4494 | 3924 | |
| 4495 | if (try final_elem_ty.comptimeOnlySema(pt)) { | |
| 3925 | if (final_elem_ty.comptimeOnly(zcu)) { | |
| 4496 | 3926 | // The alloc wasn't comptime-known per the above logic, so the |
| 4497 | 3927 | // type cannot be comptime-only. |
| 4498 | 3928 | // TODO: source location of runtime control flow |
| 4499 | 3929 | return sema.fail(block, src, "value with comptime-only type '{f}' depends on runtime control flow", .{final_elem_ty.fmt(pt)}); |
| 4500 | 3930 | } |
| 4501 | if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) { | |
| 3931 | if (sema.func_is_naked and final_elem_ty.hasRuntimeBits(zcu)) { | |
| 4502 | 3932 | const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); |
| 4503 | 3933 | return sema.fail(block, mut_src, "local variable in naked function", .{}); |
| 4504 | 3934 | } |
| ... | ... | @@ -4591,7 +4021,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4591 | 4021 | |
| 4592 | 4022 | const arg_len_uncoerced = if (zir_arg_pair[1] == .none) l: { |
| 4593 | 4023 | // This argument is an indexable. |
| 4594 | const object = try sema.resolveInst(zir_arg_pair[0]); | |
| 4024 | const object = sema.resolveInst(zir_arg_pair[0]); | |
| 4595 | 4025 | const object_ty = sema.typeOf(object); |
| 4596 | 4026 | if (!object_ty.isIndexable(zcu)) { |
| 4597 | 4027 | // Instead of using checkIndexable we customize this error. |
| ... | ... | @@ -4612,8 +4042,8 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4612 | 4042 | break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), arg_src); |
| 4613 | 4043 | } else l: { |
| 4614 | 4044 | // This argument is a range. |
| 4615 | const range_start = try sema.resolveInst(zir_arg_pair[0]); | |
| 4616 | const range_end = try sema.resolveInst(zir_arg_pair[1]); | |
| 4045 | const range_start = sema.resolveInst(zir_arg_pair[0]); | |
| 4046 | const range_end = sema.resolveInst(zir_arg_pair[1]); | |
| 4617 | 4047 | if (try sema.resolveDefinedValue(block, arg_src, range_start)) |start| { |
| 4618 | 4048 | if (try sema.valuesEqual(start, .zero_usize, .usize)) break :l range_end; |
| 4619 | 4049 | } |
| ... | ... | @@ -4663,7 +4093,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4663 | 4093 | const i: u32 = @intCast(i_usize); |
| 4664 | 4094 | if (zir_arg_pair[0] == .none) continue; |
| 4665 | 4095 | if (zir_arg_pair[1] != .none) continue; |
| 4666 | const object = try sema.resolveInst(zir_arg_pair[0]); | |
| 4096 | const object = sema.resolveInst(zir_arg_pair[0]); | |
| 4667 | 4097 | const object_ty = sema.typeOf(object); |
| 4668 | 4098 | const arg_src = block.src(.{ .for_input = .{ |
| 4669 | 4099 | .for_node_offset = inst_data.src_node, |
| ... | ... | @@ -4701,9 +4131,11 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4701 | 4131 | /// or error union pointed to, initializing these pointers along the way. |
| 4702 | 4132 | /// Given a `*E!?T`, returns a (valid) `*T`. |
| 4703 | 4133 | /// May invalidate already-stored payload data. |
| 4134 | /// Asserts that the layout of the pointer child type is already resolved. | |
| 4704 | 4135 | fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcLoc) CompileError!Air.Inst.Ref { |
| 4705 | 4136 | const pt = sema.pt; |
| 4706 | 4137 | const zcu = pt.zcu; |
| 4138 | sema.typeOf(ptr).childType(zcu).assertHasLayout(zcu); | |
| 4707 | 4139 | var base_ptr = ptr; |
| 4708 | 4140 | while (true) switch (sema.typeOf(base_ptr).childType(zcu).zigTypeTag(zcu)) { |
| 4709 | 4141 | .error_union => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), |
| ... | ... | @@ -4716,8 +4148,10 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL |
| 4716 | 4148 | |
| 4717 | 4149 | fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 4718 | 4150 | const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 4719 | const ptr = try sema.resolveInst(un_node.operand); | |
| 4720 | return sema.optEuBasePtrInit(block, ptr, block.nodeOffset(un_node.src_node)); | |
| 4151 | const ptr = sema.resolveInst(un_node.operand); | |
| 4152 | const src = block.nodeOffset(un_node.src_node); | |
| 4153 | try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu), src, .init); | |
| 4154 | return sema.optEuBasePtrInit(block, ptr, src); | |
| 4721 | 4155 | } |
| 4722 | 4156 | |
| 4723 | 4157 | fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -4726,7 +4160,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 4726 | 4160 | const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 4727 | 4161 | const src = block.nodeOffset(pl_node.src_node); |
| 4728 | 4162 | const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; |
| 4729 | const uncoerced_val = try sema.resolveInst(extra.rhs); | |
| 4163 | const uncoerced_val = sema.resolveInst(extra.rhs); | |
| 4730 | 4164 | const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val; |
| 4731 | 4165 | const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu); |
| 4732 | 4166 | assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction |
| ... | ... | @@ -4812,7 +4246,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo |
| 4812 | 4246 | if (is_ref) { |
| 4813 | 4247 | var ptr_info = operand_ty.ptrInfo(zcu); |
| 4814 | 4248 | ptr_info.child = eu_ty.toIntern(); |
| 4815 | const eu_ptr_ty = try pt.ptrTypeSema(ptr_info); | |
| 4249 | const eu_ptr_ty = try pt.ptrType(ptr_info); | |
| 4816 | 4250 | return Air.internedToRef(eu_ptr_ty.toIntern()); |
| 4817 | 4251 | } else { |
| 4818 | 4252 | return Air.internedToRef(eu_ty.toIntern()); |
| ... | ... | @@ -4842,7 +4276,7 @@ fn zirValidateConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 4842 | 4276 | |
| 4843 | 4277 | const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 4844 | 4278 | const src = block.nodeOffset(un_node.src_node); |
| 4845 | const init_ref = try sema.resolveInst(un_node.operand); | |
| 4279 | const init_ref = sema.resolveInst(un_node.operand); | |
| 4846 | 4280 | if (!try sema.isComptimeKnown(init_ref)) { |
| 4847 | 4281 | return sema.failWithNeededComptime(block, src, null); |
| 4848 | 4282 | } |
| ... | ... | @@ -4935,7 +4369,6 @@ fn validateArrayInitTy( |
| 4935 | 4369 | return; |
| 4936 | 4370 | }, |
| 4937 | 4371 | .@"struct" => if (ty.isTuple(zcu)) { |
| 4938 | try ty.resolveFields(pt); | |
| 4939 | 4372 | const array_len = ty.arrayLen(zcu); |
| 4940 | 4373 | if (init_count > array_len) { |
| 4941 | 4374 | return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{ |
| ... | ... | @@ -4986,7 +4419,7 @@ fn zirValidatePtrStructInit( |
| 4986 | 4419 | const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); |
| 4987 | 4420 | const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node; |
| 4988 | 4421 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 4989 | const object_ptr = try sema.resolveInst(field_ptr_extra.lhs); | |
| 4422 | const object_ptr = sema.resolveInst(field_ptr_extra.lhs); | |
| 4990 | 4423 | const agg_ty = sema.typeOf(object_ptr).childType(zcu).optEuBaseType(zcu); |
| 4991 | 4424 | switch (agg_ty.zigTypeTag(zcu)) { |
| 4992 | 4425 | .@"struct" => return sema.validateStructInit( |
| ... | ... | @@ -5097,12 +4530,16 @@ fn validateStructInit( |
| 5097 | 4530 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 5098 | 4531 | |
| 5099 | 4532 | for (found_fields, 0..) |explicit, i_usize| { |
| 5100 | if (explicit) continue; | |
| 5101 | 4533 | const i: u32 = @intCast(i_usize); |
| 5102 | 4534 | |
| 5103 | try struct_ty.resolveStructFieldInits(pt); | |
| 5104 | const default_val = struct_ty.structFieldDefaultValue(i, zcu); | |
| 5105 | if (default_val.toIntern() == .unreachable_value) { | |
| 4535 | if (explicit) continue; | |
| 4536 | if (struct_ty.structFieldIsComptime(i, zcu)) continue; | |
| 4537 | ||
| 4538 | if (!struct_ty.isTuple(zcu)) { | |
| 4539 | try sema.ensureStructDefaultsResolved(struct_ty, init_src); | |
| 4540 | } | |
| 4541 | ||
| 4542 | const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { | |
| 5106 | 4543 | const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse { |
| 5107 | 4544 | const template = "missing tuple field with index {d}"; |
| 5108 | 4545 | if (root_msg) |msg| { |
| ... | ... | @@ -5120,13 +4557,10 @@ fn validateStructInit( |
| 5120 | 4557 | root_msg = try sema.errMsg(init_src, template, args); |
| 5121 | 4558 | } |
| 5122 | 4559 | continue; |
| 5123 | } | |
| 4560 | }; | |
| 5124 | 4561 | |
| 5125 | 4562 | const field_src = init_src; // TODO better source location |
| 5126 | const default_field_ptr = if (struct_ty.isTuple(zcu)) | |
| 5127 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true) | |
| 5128 | else | |
| 5129 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty); | |
| 4563 | const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty); | |
| 5130 | 4564 | try sema.checkKnownAllocPtr(block, struct_ptr, default_field_ptr); |
| 5131 | 4565 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, .fromValue(default_val), field_src, .store); |
| 5132 | 4566 | } |
| ... | ... | @@ -5151,7 +4585,7 @@ fn zirValidatePtrArrayInit( |
| 5151 | 4585 | const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); |
| 5152 | 4586 | const first_elem_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node; |
| 5153 | 4587 | const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data; |
| 5154 | const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr); | |
| 4588 | const array_ptr = sema.resolveInst(elem_ptr_extra.ptr); | |
| 5155 | 4589 | const array_ty = sema.typeOf(array_ptr).childType(zcu).optEuBaseType(zcu); |
| 5156 | 4590 | const array_len = array_ty.arrayLen(zcu); |
| 5157 | 4591 | |
| ... | ... | @@ -5166,11 +4600,9 @@ fn zirValidatePtrArrayInit( |
| 5166 | 4600 | var root_msg: ?*Zcu.ErrorMsg = null; |
| 5167 | 4601 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 5168 | 4602 | |
| 5169 | try array_ty.resolveStructFieldInits(pt); | |
| 5170 | 4603 | var i = instrs.len; |
| 5171 | 4604 | while (i < array_len) : (i += 1) { |
| 5172 | const default_val = array_ty.structFieldDefaultValue(i, zcu).toIntern(); | |
| 5173 | if (default_val == .unreachable_value) { | |
| 4605 | if (array_ty.structFieldDefaultValue(i, zcu) == null) { | |
| 5174 | 4606 | const template = "missing tuple field with index {d}"; |
| 5175 | 4607 | if (root_msg) |msg| { |
| 5176 | 4608 | try sema.errNote(init_src, msg, template, .{i}); |
| ... | ... | @@ -5213,7 +4645,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 5213 | 4645 | const zcu = pt.zcu; |
| 5214 | 4646 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 5215 | 4647 | const src = block.nodeOffset(inst_data.src_node); |
| 5216 | const operand = try sema.resolveInst(inst_data.operand); | |
| 4648 | const operand = sema.resolveInst(inst_data.operand); | |
| 5217 | 4649 | const operand_ty = sema.typeOf(operand); |
| 5218 | 4650 | |
| 5219 | 4651 | if (operand_ty.zigTypeTag(zcu) != .pointer) { |
| ... | ... | @@ -5224,40 +4656,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 5224 | 4656 | .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}), |
| 5225 | 4657 | } |
| 5226 | 4658 | |
| 5227 | if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) { | |
| 5228 | // No need to validate the actual pointer value, we don't need it! | |
| 5229 | return; | |
| 5230 | } | |
| 5231 | ||
| 5232 | const elem_ty = operand_ty.elemType2(zcu); | |
| 5233 | if (try sema.resolveValue(operand)) |val| { | |
| 5234 | if (val.isUndef(zcu)) { | |
| 4659 | if (sema.resolveValue(operand)) |val| { | |
| 4660 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. | |
| 4661 | if (val.isUndef(zcu) and operand_ty.childType(zcu).classify(zcu) != .one_possible_value) { | |
| 5235 | 4662 | return sema.fail(block, src, "cannot dereference undefined value", .{}); |
| 5236 | 4663 | } |
| 5237 | } else if (try elem_ty.comptimeOnlySema(pt)) { | |
| 5238 | const msg = msg: { | |
| 5239 | const msg = try sema.errMsg( | |
| 5240 | src, | |
| 5241 | "values of type '{f}' must be comptime-known, but operand value is runtime-known", | |
| 5242 | .{elem_ty.fmt(pt)}, | |
| 5243 | ); | |
| 5244 | errdefer msg.destroy(sema.gpa); | |
| 5245 | ||
| 5246 | try sema.explainWhyTypeIsComptime(msg, src, elem_ty); | |
| 5247 | break :msg msg; | |
| 5248 | }; | |
| 5249 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 5250 | 4664 | } |
| 5251 | 4665 | } |
| 5252 | 4666 | |
| 5253 | fn typeIsDestructurable(ty: Type, zcu: *const Zcu) bool { | |
| 5254 | return switch (ty.zigTypeTag(zcu)) { | |
| 5255 | .array, .vector => true, | |
| 5256 | .@"struct" => ty.isTuple(zcu), | |
| 5257 | else => false, | |
| 5258 | }; | |
| 5259 | } | |
| 5260 | ||
| 5261 | 4667 | fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 5262 | 4668 | const pt = sema.pt; |
| 5263 | 4669 | const zcu = pt.zcu; |
| ... | ... | @@ -5265,17 +4671,17 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 5265 | 4671 | const extra = sema.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; |
| 5266 | 4672 | const src = block.nodeOffset(inst_data.src_node); |
| 5267 | 4673 | const destructure_src = block.nodeOffset(extra.destructure_node); |
| 5268 | const operand = try sema.resolveInst(extra.operand); | |
| 4674 | const operand = sema.resolveInst(extra.operand); | |
| 5269 | 4675 | const operand_ty = sema.typeOf(operand); |
| 5270 | 4676 | |
| 5271 | if (!typeIsDestructurable(operand_ty, zcu)) { | |
| 4677 | if (!operand_ty.destructurable(zcu)) { | |
| 5272 | 4678 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 5273 | 4679 | const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)}); |
| 5274 | 4680 | errdefer msg.destroy(sema.gpa); |
| 5275 | 4681 | try sema.errNote(destructure_src, msg, "result destructured here", .{}); |
| 5276 | 4682 | if (operand_ty.zigTypeTag(pt.zcu) == .error_union) { |
| 5277 | 4683 | const base_op_ty = operand_ty.errorUnionPayload(zcu); |
| 5278 | if (typeIsDestructurable(base_op_ty, zcu)) | |
| 4684 | if (base_op_ty.destructurable(zcu)) | |
| 5279 | 4685 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); |
| 5280 | 4686 | } |
| 5281 | 4687 | break :msg msg; |
| ... | ... | @@ -5373,7 +4779,7 @@ fn failWithBadUnionFieldAccess( |
| 5373 | 4779 | return sema.failWithOwnedErrorMsg(block, msg); |
| 5374 | 4780 | } |
| 5375 | 4781 | |
| 5376 | fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void { | |
| 4782 | pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void { | |
| 5377 | 4783 | const zcu = sema.pt.zcu; |
| 5378 | 4784 | const src_loc = decl_ty.srcLocOrNull(zcu) orelse return; |
| 5379 | 4785 | const category = switch (decl_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -5393,8 +4799,8 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 5393 | 4799 | const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 5394 | 4800 | const src = block.nodeOffset(pl_node.src_node); |
| 5395 | 4801 | const bin = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; |
| 5396 | const ptr = try sema.resolveInst(bin.lhs); | |
| 5397 | const operand = try sema.resolveInst(bin.rhs); | |
| 4802 | const ptr = sema.resolveInst(bin.lhs); | |
| 4803 | const operand = sema.resolveInst(bin.rhs); | |
| 5398 | 4804 | const ptr_inst = ptr.toIndex().?; |
| 5399 | 4805 | const air_datas = sema.air_instructions.items(.data); |
| 5400 | 4806 | |
| ... | ... | @@ -5440,17 +4846,19 @@ fn storeToInferredAllocComptime( |
| 5440 | 4846 | const operand_ty = sema.typeOf(operand); |
| 5441 | 4847 | // There will be only one store_to_inferred_ptr because we are running at comptime. |
| 5442 | 4848 | // The alloc will turn into a Decl or a ComptimeAlloc. |
| 5443 | const operand_val = try sema.resolveValue(operand) orelse { | |
| 4849 | const operand_val = sema.resolveValue(operand) orelse { | |
| 5444 | 4850 | return sema.failWithNeededComptime(block, src, .{ .simple = .stored_to_comptime_var }); |
| 5445 | 4851 | }; |
| 5446 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 4852 | const alloc_ty = try pt.ptrType(.{ | |
| 5447 | 4853 | .child = operand_ty.toIntern(), |
| 5448 | 4854 | .flags = .{ |
| 5449 | 4855 | .alignment = iac.alignment, |
| 5450 | 4856 | .is_const = iac.is_const, |
| 5451 | 4857 | }, |
| 5452 | 4858 | }); |
| 5453 | if (iac.is_const and !operand_val.canMutateComptimeVarState(zcu)) { | |
| 4859 | if (operand_ty.classify(zcu) == .one_possible_value or | |
| 4860 | (iac.is_const and !operand_val.canMutateComptimeVarState(zcu))) | |
| 4861 | { | |
| 5454 | 4862 | iac.ptr = try pt.intern(.{ .ptr = .{ |
| 5455 | 4863 | .ty = alloc_ty.toIntern(), |
| 5456 | 4864 | .base_addr = .{ .uav = .{ |
| ... | ... | @@ -5487,8 +4895,8 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 5487 | 4895 | const inst_data = zir_datas[@intFromEnum(inst)].pl_node; |
| 5488 | 4896 | const src = block.nodeOffset(inst_data.src_node); |
| 5489 | 4897 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 5490 | const ptr = try sema.resolveInst(extra.lhs); | |
| 5491 | const operand = try sema.resolveInst(extra.rhs); | |
| 4898 | const ptr = sema.resolveInst(extra.lhs); | |
| 4899 | const operand = sema.resolveInst(extra.rhs); | |
| 5492 | 4900 | |
| 5493 | 4901 | const is_ret = if (extra.lhs.toIndex()) |ptr_index| |
| 5494 | 4902 | zir_tags[@intFromEnum(ptr_index)] == .ret_ptr |
| ... | ... | @@ -5535,11 +4943,11 @@ pub fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError! |
| 5535 | 4943 | .ty = array_ty.toIntern(), |
| 5536 | 4944 | .storage = .{ .bytes = string }, |
| 5537 | 4945 | } }); |
| 5538 | return sema.uavRef(val); | |
| 4946 | return sema.uavRef(.fromInterned(val)); | |
| 5539 | 4947 | } |
| 5540 | 4948 | |
| 5541 | fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref { | |
| 5542 | return Air.internedToRef(try sema.pt.refValue(val)); | |
| 4949 | fn uavRef(sema: *Sema, val: Value) CompileError!Air.Inst.Ref { | |
| 4950 | return .fromValue(try sema.pt.uavValue(val)); | |
| 5543 | 4951 | } |
| 5544 | 4952 | |
| 5545 | 4953 | fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5622,9 +5030,9 @@ fn zirCompileLog( |
| 5622 | 5030 | for (args, 0..) |arg_ref, i| { |
| 5623 | 5031 | if (i != 0) writer.writeAll(", ") catch return error.OutOfMemory; |
| 5624 | 5032 | |
| 5625 | const arg = try sema.resolveInst(arg_ref); | |
| 5033 | const arg = sema.resolveInst(arg_ref); | |
| 5626 | 5034 | const arg_ty = sema.typeOf(arg); |
| 5627 | if (try sema.resolveValueResolveLazy(arg)) |val| { | |
| 5035 | if (sema.resolveValue(arg)) |val| { | |
| 5628 | 5036 | writer.print("@as({f}, {f})", .{ |
| 5629 | 5037 | arg_ty.fmt(pt), val.fmtValueSema(pt, sema), |
| 5630 | 5038 | }) catch return error.OutOfMemory; |
| ... | ... | @@ -5672,7 +5080,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 5672 | 5080 | |
| 5673 | 5081 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 5674 | 5082 | const src = block.nodeOffset(inst_data.src_node); |
| 5675 | const msg_inst = try sema.resolveInst(inst_data.operand); | |
| 5083 | const msg_inst = sema.resolveInst(inst_data.operand); | |
| 5676 | 5084 | |
| 5677 | 5085 | const arg_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 5678 | 5086 | const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, arg_src); |
| ... | ... | @@ -5752,9 +5160,9 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError |
| 5752 | 5160 | var label: Block.Label = .{ |
| 5753 | 5161 | .zir_block = inst, |
| 5754 | 5162 | .merges = .{ |
| 5755 | .src_locs = .{}, | |
| 5756 | .results = .{}, | |
| 5757 | .br_list = .{}, | |
| 5163 | .src_locs = .empty, | |
| 5164 | .results = .empty, | |
| 5165 | .br_list = .empty, | |
| 5758 | 5166 | .block_inst = block_inst, |
| 5759 | 5167 | }, |
| 5760 | 5168 | }; |
| ... | ... | @@ -5826,7 +5234,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5826 | 5234 | .parent = parent_block, |
| 5827 | 5235 | .sema = sema, |
| 5828 | 5236 | .namespace = parent_block.namespace, |
| 5829 | .instructions = .{}, | |
| 5237 | .instructions = .empty, | |
| 5830 | 5238 | .inlining = parent_block.inlining, |
| 5831 | 5239 | .comptime_reason = .{ .reason = .{ |
| 5832 | 5240 | .src = src, |
| ... | ... | @@ -5927,11 +5335,10 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5927 | 5335 | pt.updateFile(new_file_index, zcu.fileByIndex(new_file_index)) catch |err| |
| 5928 | 5336 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 5929 | 5337 | |
| 5930 | try pt.ensureFileAnalyzed(new_file_index); | |
| 5931 | const ty = zcu.fileRootType(new_file_index); | |
| 5932 | try sema.declareDependency(.{ .interned = ty }); | |
| 5338 | try pt.ensureFilePopulated(new_file_index); | |
| 5339 | const ty: Type = .fromInterned(zcu.fileRootType(new_file_index)); | |
| 5933 | 5340 | try sema.addTypeReferenceEntry(src, ty); |
| 5934 | return Air.internedToRef(ty); | |
| 5341 | return .fromType(ty); | |
| 5935 | 5342 | } |
| 5936 | 5343 | |
| 5937 | 5344 | fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5962,9 +5369,9 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro |
| 5962 | 5369 | var label: Block.Label = .{ |
| 5963 | 5370 | .zir_block = inst, |
| 5964 | 5371 | .merges = .{ |
| 5965 | .src_locs = .{}, | |
| 5966 | .results = .{}, | |
| 5967 | .br_list = .{}, | |
| 5372 | .src_locs = .empty, | |
| 5373 | .results = .empty, | |
| 5374 | .br_list = .empty, | |
| 5968 | 5375 | .block_inst = block_inst, |
| 5969 | 5376 | }, |
| 5970 | 5377 | }; |
| ... | ... | @@ -5973,7 +5380,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro |
| 5973 | 5380 | .parent = parent_block, |
| 5974 | 5381 | .sema = sema, |
| 5975 | 5382 | .namespace = parent_block.namespace, |
| 5976 | .instructions = .{}, | |
| 5383 | .instructions = .empty, | |
| 5977 | 5384 | .label = &label, |
| 5978 | 5385 | .inlining = parent_block.inlining, |
| 5979 | 5386 | .comptime_reason = parent_block.comptime_reason, |
| ... | ... | @@ -6043,7 +5450,7 @@ fn resolveBlockBody( |
| 6043 | 5450 | const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break"; |
| 6044 | 5451 | const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; |
| 6045 | 5452 | if (extra.block_inst == body_inst) { |
| 6046 | return try sema.resolveInst(break_data.operand); | |
| 5453 | return sema.resolveInst(break_data.operand); | |
| 6047 | 5454 | } else { |
| 6048 | 5455 | return error.ComptimeBreak; |
| 6049 | 5456 | } |
| ... | ... | @@ -6134,7 +5541,7 @@ fn resolveAnalyzedBlock( |
| 6134 | 5541 | // Okay, we need a runtime block. If the value is comptime-known, the |
| 6135 | 5542 | // block should just return void, and we return the merge result |
| 6136 | 5543 | // directly. Otherwise, we can defer to the logic below. |
| 6137 | if (try sema.resolveValue(merges.results.items[0])) |result_val| { | |
| 5544 | if (sema.resolveValue(merges.results.items[0])) |result_val| { | |
| 6138 | 5545 | // Create a block containing all instruction from the body. |
| 6139 | 5546 | try parent_block.instructions.append(gpa, merges.block_inst); |
| 6140 | 5547 | switch (block_tag) { |
| ... | ... | @@ -6177,10 +5584,11 @@ fn resolveAnalyzedBlock( |
| 6177 | 5584 | // to emit a jump instruction to after the block when it encounters the break. |
| 6178 | 5585 | try parent_block.instructions.append(gpa, merges.block_inst); |
| 6179 | 5586 | const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items }); |
| 5587 | resolved_ty.assertHasLayout(zcu); | |
| 6180 | 5588 | // TODO add note "missing else causes void value" |
| 6181 | 5589 | |
| 6182 | 5590 | const type_src = src; // TODO: better source location |
| 6183 | if (try resolved_ty.comptimeOnlySema(pt)) { | |
| 5591 | if (resolved_ty.comptimeOnly(zcu)) { | |
| 6184 | 5592 | const msg = msg: { |
| 6185 | 5593 | const msg = try sema.errMsg(type_src, "value with comptime-only type '{f}' depends on runtime control flow", .{resolved_ty.fmt(pt)}); |
| 6186 | 5594 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -6274,10 +5682,7 @@ fn resolveAnalyzedBlock( |
| 6274 | 5682 | }); |
| 6275 | 5683 | } |
| 6276 | 5684 | |
| 6277 | if (try sema.typeHasOnePossibleValue(resolved_ty)) |block_only_value| { | |
| 6278 | return Air.internedToRef(block_only_value.toIntern()); | |
| 6279 | } | |
| 6280 | ||
| 5685 | if (try resolved_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 6281 | 5686 | return merges.block_inst.toRef(); |
| 6282 | 5687 | } |
| 6283 | 5688 | |
| ... | ... | @@ -6295,7 +5700,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 6295 | 5700 | const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 6296 | 5701 | const options_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 6297 | 5702 | |
| 6298 | const ptr = try sema.resolveInst(extra.exported); | |
| 5703 | const ptr = sema.resolveInst(extra.exported); | |
| 6299 | 5704 | const ptr_val = try sema.resolveConstDefinedValue(block, ptr_src, ptr, .{ .simple = .export_target }); |
| 6300 | 5705 | const ptr_ty = ptr_val.typeOf(zcu); |
| 6301 | 5706 | |
| ... | ... | @@ -6314,91 +5719,95 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 6314 | 5719 | } |
| 6315 | 5720 | } |
| 6316 | 5721 | |
| 5722 | const export_ty = ptr_ty.childType(zcu); | |
| 5723 | try sema.ensureLayoutResolved(export_ty, src, .@"export"); | |
| 5724 | if (!export_ty.validateExtern(.other, zcu)) { | |
| 5725 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 5726 | const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); | |
| 5727 | errdefer msg.destroy(sema.gpa); | |
| 5728 | try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); | |
| 5729 | try sema.addDeclaredHereNote(msg, export_ty); | |
| 5730 | break :msg msg; | |
| 5731 | }); | |
| 5732 | } | |
| 5733 | ||
| 6317 | 5734 | const ptr_info = ip.indexToKey(ptr_val.toIntern()).ptr; |
| 6318 | switch (ptr_info.base_addr) { | |
| 5735 | const target: Zcu.Exported = switch (ptr_info.base_addr) { | |
| 6319 | 5736 | .comptime_alloc, .int, .comptime_field => return sema.fail(block, ptr_src, "export target must be a global variable or a comptime-known constant", .{}), |
| 6320 | 5737 | .eu_payload, .opt_payload, .field, .arr_elem => return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}), |
| 6321 | .uav => |uav| { | |
| 6322 | if (ptr_info.byte_offset != 0) { | |
| 6323 | return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); | |
| 6324 | } | |
| 6325 | if (zcu.llvm_object != null and options.linkage == .internal) return; | |
| 6326 | const export_ty = Value.fromInterned(uav.val).typeOf(zcu); | |
| 6327 | if (!try sema.validateExternType(export_ty, .other)) { | |
| 6328 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 6329 | const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); | |
| 6330 | errdefer msg.destroy(sema.gpa); | |
| 6331 | try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); | |
| 6332 | try sema.addDeclaredHereNote(msg, export_ty); | |
| 6333 | break :msg msg; | |
| 6334 | }); | |
| 6335 | } | |
| 6336 | try sema.exports.append(zcu.gpa, .{ | |
| 6337 | .opts = options, | |
| 6338 | .src = src, | |
| 6339 | .exported = .{ .uav = uav.val }, | |
| 6340 | .status = .in_progress, | |
| 6341 | }); | |
| 6342 | }, | |
| 6343 | .nav => |nav| { | |
| 6344 | if (ptr_info.byte_offset != 0) { | |
| 6345 | return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); | |
| 5738 | .uav => |uav| .{ .uav = uav.val }, | |
| 5739 | .nav => |orig_nav| target: { | |
| 5740 | try sema.ensureNavResolved(block, src, orig_nav, .fully); | |
| 5741 | const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).status.fully_resolved.val)) { | |
| 5742 | .variable => |v| v.owner_nav, | |
| 5743 | .@"extern" => |e| e.owner_nav, | |
| 5744 | .func => |f| f.owner_nav, | |
| 5745 | else => orig_nav, | |
| 5746 | }; | |
| 5747 | if (ip.getNav(export_nav).getExtern(ip) != null) { | |
| 5748 | return sema.fail(block, src, "export target cannot be extern", .{}); | |
| 6346 | 5749 | } |
| 6347 | try sema.analyzeExport(block, src, options, nav); | |
| 5750 | try sema.maybeQueueFuncBodyAnalysis(block, src, export_nav); | |
| 5751 | break :target .{ .nav = export_nav }; | |
| 6348 | 5752 | }, |
| 5753 | }; | |
| 5754 | if (ptr_info.byte_offset != 0) { | |
| 5755 | return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); | |
| 6349 | 5756 | } |
| 5757 | if (zcu.llvm_object != null and options.linkage == .internal) return; | |
| 5758 | try sema.exports.append(zcu.gpa, .{ | |
| 5759 | .opts = options, | |
| 5760 | .src = src, | |
| 5761 | .exported = target, | |
| 5762 | .status = .in_progress, | |
| 5763 | }); | |
| 6350 | 5764 | } |
| 6351 | 5765 | |
| 6352 | pub fn analyzeExport( | |
| 5766 | /// Asserts that `sema.owner` is a `.nav_val` whose value is resolved. | |
| 5767 | /// | |
| 5768 | /// Exports that `Nav` by the given name with all other options set to default. | |
| 5769 | pub fn analyzeExportSelfNav( | |
| 6353 | 5770 | sema: *Sema, |
| 6354 | 5771 | block: *Block, |
| 6355 | 5772 | src: LazySrcLoc, |
| 6356 | options: Zcu.Export.Options, | |
| 6357 | orig_nav_index: InternPool.Nav.Index, | |
| 5773 | name: InternPool.NullTerminatedString, | |
| 6358 | 5774 | ) !void { |
| 6359 | 5775 | const gpa = sema.gpa; |
| 6360 | 5776 | const pt = sema.pt; |
| 6361 | 5777 | const zcu = pt.zcu; |
| 6362 | 5778 | const ip = &zcu.intern_pool; |
| 6363 | 5779 | |
| 6364 | if (zcu.llvm_object != null and options.linkage == .internal) | |
| 6365 | return; | |
| 6366 | ||
| 6367 | try sema.ensureNavResolved(block, src, orig_nav_index, .fully); | |
| 6368 | ||
| 6369 | const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) { | |
| 6370 | .variable => |v| v.owner_nav, | |
| 6371 | .@"extern" => |e| e.owner_nav, | |
| 6372 | .func => |f| f.owner_nav, | |
| 6373 | else => orig_nav_index, | |
| 6374 | }; | |
| 6375 | ||
| 6376 | const exported_nav = ip.getNav(exported_nav_index); | |
| 6377 | const export_ty: Type = .fromInterned(exported_nav.typeOf(ip)); | |
| 5780 | const orig_nav = sema.owner.unwrap().nav_val; | |
| 5781 | const export_val: Value = .fromInterned(ip.getNav(orig_nav).status.fully_resolved.val); | |
| 5782 | const export_ty = export_val.typeOf(zcu); | |
| 6378 | 5783 | |
| 6379 | if (!try sema.validateExternType(export_ty, .other)) { | |
| 5784 | if (!export_ty.validateExtern(.other, zcu)) { | |
| 6380 | 5785 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 6381 | 5786 | const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); |
| 6382 | 5787 | errdefer msg.destroy(gpa); |
| 6383 | ||
| 6384 | 5788 | try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); |
| 6385 | ||
| 6386 | 5789 | try sema.addDeclaredHereNote(msg, export_ty); |
| 6387 | 5790 | break :msg msg; |
| 6388 | 5791 | }); |
| 6389 | 5792 | } |
| 6390 | 5793 | |
| 6391 | // TODO: some backends might support re-exporting extern decls | |
| 6392 | if (exported_nav.getExtern(ip) != null) { | |
| 6393 | return sema.fail(block, src, "export target cannot be extern", .{}); | |
| 6394 | } | |
| 6395 | ||
| 6396 | try sema.maybeQueueFuncBodyAnalysis(block, src, exported_nav_index); | |
| 5794 | const export_nav = switch (ip.indexToKey(export_val.toIntern())) { | |
| 5795 | .variable => |v| v.owner_nav, | |
| 5796 | .@"extern" => |e| e.owner_nav, | |
| 5797 | .func => |f| export_nav: { | |
| 5798 | assert(export_ty.fnHasRuntimeBits(zcu)); // otherwise `validateExtern` failed above | |
| 5799 | const orig_fn_index = ip.unwrapCoercedFunc(export_val.toIntern()); | |
| 5800 | try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index })); | |
| 5801 | try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); | |
| 5802 | break :export_nav f.owner_nav; | |
| 5803 | }, | |
| 5804 | else => orig_nav, | |
| 5805 | }; | |
| 6397 | 5806 | |
| 6398 | 5807 | try sema.exports.append(gpa, .{ |
| 6399 | .opts = options, | |
| 5808 | .opts = .{ .name = name }, | |
| 6400 | 5809 | .src = src, |
| 6401 | .exported = .{ .nav = exported_nav_index }, | |
| 5810 | .exported = .{ .nav = export_nav }, | |
| 6402 | 5811 | .status = .in_progress, |
| 6403 | 5812 | }); |
| 6404 | 5813 | } |
| ... | ... | @@ -6413,7 +5822,8 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { |
| 6413 | 5822 | .@"comptime", |
| 6414 | 5823 | .nav_val, |
| 6415 | 5824 | .nav_ty, |
| 6416 | .type, | |
| 5825 | .type_layout, | |
| 5826 | .struct_defaults, | |
| 6417 | 5827 | .memoized_state, |
| 6418 | 5828 | => return, // does nothing outside a function |
| 6419 | 5829 | }; |
| ... | ... | @@ -6431,7 +5841,8 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { |
| 6431 | 5841 | .@"comptime", |
| 6432 | 5842 | .nav_val, |
| 6433 | 5843 | .nav_ty, |
| 6434 | .type, | |
| 5844 | .type_layout, | |
| 5845 | .struct_defaults, | |
| 6435 | 5846 | .memoized_state, |
| 6436 | 5847 | => return, // does nothing outside a function |
| 6437 | 5848 | }; |
| ... | ... | @@ -6457,7 +5868,7 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError |
| 6457 | 5868 | |
| 6458 | 5869 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; |
| 6459 | 5870 | const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; |
| 6460 | const operand = try sema.resolveInst(inst_data.operand); | |
| 5871 | const operand = sema.resolveInst(inst_data.operand); | |
| 6461 | 5872 | const zir_block = extra.block_inst; |
| 6462 | 5873 | |
| 6463 | 5874 | var block = start_block; |
| ... | ... | @@ -6491,7 +5902,7 @@ fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) Com |
| 6491 | 5902 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; |
| 6492 | 5903 | const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; |
| 6493 | 5904 | const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?); |
| 6494 | const uncoerced_operand = try sema.resolveInst(inst_data.operand); | |
| 5905 | const uncoerced_operand = sema.resolveInst(inst_data.operand); | |
| 6495 | 5906 | const switch_inst = extra.block_inst; |
| 6496 | 5907 | |
| 6497 | 5908 | switch (sema.code.instructions.items(.tag)[@intFromEnum(switch_inst)]) { |
| ... | ... | @@ -6500,7 +5911,7 @@ fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) Com |
| 6500 | 5911 | else => unreachable, // assertion failure |
| 6501 | 5912 | } |
| 6502 | 5913 | |
| 6503 | const operand_ty = (try sema.resolveInst(switch_inst.toRef())).toType(); | |
| 5914 | const operand_ty = (sema.resolveInst(switch_inst.toRef())).toType(); | |
| 6504 | 5915 | const operand = try sema.coerce(start_block, operand_ty, uncoerced_operand, operand_src); |
| 6505 | 5916 | try sema.validateRuntimeValue(start_block, operand_src, operand); |
| 6506 | 5917 | |
| ... | ... | @@ -6567,7 +5978,7 @@ fn zirDbgVar( |
| 6567 | 5978 | air_tag: Air.Inst.Tag, |
| 6568 | 5979 | ) CompileError!void { |
| 6569 | 5980 | const str_op = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_op; |
| 6570 | const operand = try sema.resolveInst(str_op.operand); | |
| 5981 | const operand = sema.resolveInst(str_op.operand); | |
| 6571 | 5982 | const name = str_op.getStr(sema.code); |
| 6572 | 5983 | try sema.addDbgVar(block, operand, air_tag, name); |
| 6573 | 5984 | } |
| ... | ... | @@ -6589,9 +6000,9 @@ fn addDbgVar( |
| 6589 | 6000 | .dbg_var_val, .dbg_arg_inline => operand_ty, |
| 6590 | 6001 | else => unreachable, |
| 6591 | 6002 | }; |
| 6592 | if (try val_ty.comptimeOnlySema(pt)) return; | |
| 6593 | if (!(try val_ty.hasRuntimeBitsSema(pt))) return; | |
| 6594 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 6003 | if (val_ty.comptimeOnly(zcu)) return; | |
| 6004 | if (!val_ty.hasRuntimeBits(zcu)) return; | |
| 6005 | if (sema.resolveValue(operand)) |operand_val| { | |
| 6595 | 6006 | if (operand_val.canMutateComptimeVarState(zcu)) return; |
| 6596 | 6007 | } |
| 6597 | 6008 | |
| ... | ... | @@ -6730,7 +6141,7 @@ fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedIns |
| 6730 | 6141 | const pt = sema.pt; |
| 6731 | 6142 | const zcu = pt.zcu; |
| 6732 | 6143 | const ip = &zcu.intern_pool; |
| 6733 | const func_val = try sema.resolveValue(func_inst) orelse return null; | |
| 6144 | const func_val = sema.resolveValue(func_inst) orelse return null; | |
| 6734 | 6145 | if (func_val.isUndef(zcu)) return null; |
| 6735 | 6146 | const nav = switch (ip.indexToKey(func_val.toIntern())) { |
| 6736 | 6147 | .@"extern" => |e| e.owner_nav, |
| ... | ... | @@ -6759,7 +6170,6 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref |
| 6759 | 6170 | if (!block.ownerModule().error_tracing) return .none; |
| 6760 | 6171 | |
| 6761 | 6172 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); |
| 6762 | try stack_trace_ty.resolveFields(pt); | |
| 6763 | 6173 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); |
| 6764 | 6174 | const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) { |
| 6765 | 6175 | error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"), |
| ... | ... | @@ -6803,11 +6213,10 @@ fn popErrorReturnTrace( |
| 6803 | 6213 | // the result is comptime-known to be a non-error. Either way, pop unconditionally. |
| 6804 | 6214 | |
| 6805 | 6215 | const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace); |
| 6806 | try stack_trace_ty.resolveFields(pt); | |
| 6807 | 6216 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 6808 | 6217 | const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); |
| 6809 | 6218 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); |
| 6810 | const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true); | |
| 6219 | const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty); | |
| 6811 | 6220 | try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store); |
| 6812 | 6221 | } else if (is_non_error == null) { |
| 6813 | 6222 | // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need |
| ... | ... | @@ -6829,11 +6238,10 @@ fn popErrorReturnTrace( |
| 6829 | 6238 | |
| 6830 | 6239 | // If non-error, then pop the error return trace by restoring the index. |
| 6831 | 6240 | const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace); |
| 6832 | try stack_trace_ty.resolveFields(pt); | |
| 6833 | 6241 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 6834 | 6242 | const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty); |
| 6835 | 6243 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); |
| 6836 | const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true); | |
| 6244 | const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty); | |
| 6837 | 6245 | try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store); |
| 6838 | 6246 | _ = try then_block.addBr(cond_block_inst, .void_value); |
| 6839 | 6247 | |
| ... | ... | @@ -6905,9 +6313,9 @@ fn zirCall( |
| 6905 | 6313 | const pop_error_return_trace = extra.data.flags.pop_error_return_trace; |
| 6906 | 6314 | |
| 6907 | 6315 | const callee: ResolvedFieldCallee = switch (kind) { |
| 6908 | .direct => .{ .direct = try sema.resolveInst(extra.data.callee) }, | |
| 6316 | .direct => .{ .direct = sema.resolveInst(extra.data.callee) }, | |
| 6909 | 6317 | .field => blk: { |
| 6910 | const object_ptr = try sema.resolveInst(extra.data.obj_ptr); | |
| 6318 | const object_ptr = sema.resolveInst(extra.data.obj_ptr); | |
| 6911 | 6319 | const field_name = try zcu.intern_pool.getOrPutString( |
| 6912 | 6320 | gpa, |
| 6913 | 6321 | io, |
| ... | ... | @@ -6969,7 +6377,6 @@ fn zirCall( |
| 6969 | 6377 | // need to clean-up our own trace if we were passed to a non-error-handling expression. |
| 6970 | 6378 | if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) { |
| 6971 | 6379 | const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace); |
| 6972 | try stack_trace_ty.resolveFields(pt); | |
| 6973 | 6380 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); |
| 6974 | 6381 | const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src); |
| 6975 | 6382 | |
| ... | ... | @@ -7255,7 +6662,7 @@ const CallArgsInfo = union(enum) { |
| 7255 | 6662 | return sema.failWithNeededComptime(block, cai.argSrc(block, arg_index), null); |
| 7256 | 6663 | } |
| 7257 | 6664 | |
| 7258 | if (sema.typeOf(uncoerced_arg).zigTypeTag(zcu) == .noreturn) { | |
| 6665 | if (sema.typeOf(uncoerced_arg).classify(zcu) == .no_possible_value) { | |
| 7259 | 6666 | // This terminates resolution of arguments. The caller should |
| 7260 | 6667 | // propagate this. |
| 7261 | 6668 | return uncoerced_arg; |
| ... | ... | @@ -7318,6 +6725,21 @@ fn analyzeCall( |
| 7318 | 6725 | } else func_src; |
| 7319 | 6726 | |
| 7320 | 6727 | const func_ty_info = zcu.typeToFunc(func_ty).?; |
| 6728 | ||
| 6729 | for (func_ty_info.param_types.get(ip), 0..) |param_ty_ip, param_index| { | |
| 6730 | const arg_src = args_info.argSrc(block, param_index); | |
| 6731 | try sema.ensureLayoutResolved(.fromInterned(param_ty_ip), arg_src, .init); | |
| 6732 | } | |
| 6733 | try sema.ensureLayoutResolved(.fromInterned(func_ty_info.return_type), func_ret_ty_src, .return_type); | |
| 6734 | try sema.validateResolvedFuncType( | |
| 6735 | block, | |
| 6736 | func_ty_info.cc, | |
| 6737 | func_ty_info.param_types.get(ip), | |
| 6738 | .fromInterned(func_ty_info.return_type), | |
| 6739 | func_src, | |
| 6740 | maybe_func_inst, | |
| 6741 | ); | |
| 6742 | ||
| 7321 | 6743 | if (!callConvIsCallable(func_ty_info.cc)) { |
| 7322 | 6744 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 7323 | 6745 | const msg = try sema.errMsg( |
| ... | ... | @@ -7334,6 +6756,28 @@ fn analyzeCall( |
| 7334 | 6756 | }); |
| 7335 | 6757 | } |
| 7336 | 6758 | |
| 6759 | const any_comptime_params = func_ty_info.comptime_bits != 0 or ct: { | |
| 6760 | for (func_ty_info.param_types.get(ip)) |param_ty| { | |
| 6761 | if (Type.fromInterned(param_ty).comptimeOnly(zcu)) break :ct true; | |
| 6762 | } | |
| 6763 | break :ct Type.fromInterned(func_ty_info.return_type).comptimeOnly(zcu); | |
| 6764 | }; | |
| 6765 | const any_generic_types = generic: { | |
| 6766 | for (func_ty_info.param_types.get(ip)) |param_ty| { | |
| 6767 | if (param_ty == .generic_poison_type) break :generic true; | |
| 6768 | } | |
| 6769 | const ret_ty: Type = .fromInterned(func_ty_info.return_type); | |
| 6770 | if (ret_ty.toIntern() == .generic_poison_type) { | |
| 6771 | break :generic true; | |
| 6772 | } | |
| 6773 | if (ret_ty.zigTypeTag(zcu) == .error_union and | |
| 6774 | ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) | |
| 6775 | { | |
| 6776 | break :generic true; | |
| 6777 | } | |
| 6778 | break :generic false; | |
| 6779 | }; | |
| 6780 | ||
| 7337 | 6781 | // We need this value in a few code paths. |
| 7338 | 6782 | const callee_val = try sema.resolveDefinedValue(block, call_src, callee); |
| 7339 | 6783 | // If the callee is a comptime-known *non-extern* function, `func_val` is populated. |
| ... | ... | @@ -7353,7 +6797,7 @@ fn analyzeCall( |
| 7353 | 6797 | else => unreachable, |
| 7354 | 6798 | } else .{ null, false }; |
| 7355 | 6799 | |
| 7356 | if (func_ty_info.is_generic and func_val == null) { | |
| 6800 | if ((any_generic_types or any_comptime_params) and func_val == null) { | |
| 7357 | 6801 | return sema.failWithNeededComptime(block, func_src, .{ .simple = .generic_call_target }); |
| 7358 | 6802 | } |
| 7359 | 6803 | |
| ... | ... | @@ -7369,19 +6813,18 @@ fn analyzeCall( |
| 7369 | 6813 | .src = call_src, |
| 7370 | 6814 | .r = .{ .simple = .comptime_call_modifier }, |
| 7371 | 6815 | } }; |
| 7372 | } else if (!inline_requested and try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) { | |
| 7373 | block.comptime_reason = .{ | |
| 7374 | .reason = .{ | |
| 6816 | } else if (!inline_requested) { | |
| 6817 | const ret_ty: Type = .fromInterned(func_ty_info.return_type); | |
| 6818 | if (ret_ty.comptimeOnly(zcu)) { | |
| 6819 | block.comptime_reason = .{ .reason = .{ | |
| 7375 | 6820 | .src = call_src, |
| 7376 | .r = .{ | |
| 7377 | .comptime_only_ret_ty = .{ | |
| 7378 | .ty = .fromInterned(func_ty_info.return_type), | |
| 7379 | .is_generic_inst = false, | |
| 7380 | .ret_ty_src = func_ret_ty_src, | |
| 7381 | }, | |
| 7382 | }, | |
| 7383 | }, | |
| 7384 | }; | |
| 6821 | .r = .{ .comptime_only_ret_ty = .{ | |
| 6822 | .ty = .fromInterned(func_ty_info.return_type), | |
| 6823 | .is_generic_inst = false, | |
| 6824 | .ret_ty_src = func_ret_ty_src, | |
| 6825 | } }, | |
| 6826 | } }; | |
| 6827 | } | |
| 7385 | 6828 | } |
| 7386 | 6829 | } |
| 7387 | 6830 | |
| ... | ... | @@ -7403,13 +6846,13 @@ fn analyzeCall( |
| 7403 | 6846 | // This is the `inst_map` used when evaluating generic parameters and return types. |
| 7404 | 6847 | var generic_inst_map: InstMap = .{}; |
| 7405 | 6848 | defer generic_inst_map.deinit(gpa); |
| 7406 | if (func_ty_info.is_generic) { | |
| 6849 | if (any_generic_types) { | |
| 7407 | 6850 | try generic_inst_map.ensureSpaceForInstructions(gpa, fn_zir_info.param_body); |
| 7408 | 6851 | } |
| 7409 | 6852 | |
| 7410 | 6853 | // This exists so that `generic_block` below can include a "called from here" note back to this |
| 7411 | 6854 | // call site when analyzing generic parameter/return types. |
| 7412 | var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{ | |
| 6855 | var generic_inlining: Block.Inlining = if (any_generic_types) .{ | |
| 7413 | 6856 | .call_block = block, |
| 7414 | 6857 | .call_src = call_src, |
| 7415 | 6858 | .func = func_val.?.toIntern(), |
| ... | ... | @@ -7422,18 +6865,18 @@ fn analyzeCall( |
| 7422 | 6865 | // This is the block in which we evaluate generic function components: that is, generic parameter |
| 7423 | 6866 | // types and the generic return type. This must not be used if the function is not generic. |
| 7424 | 6867 | // `comptime_reason` is set as needed. |
| 7425 | var generic_block: Block = if (func_ty_info.is_generic) .{ | |
| 6868 | var generic_block: Block = if (any_generic_types) .{ | |
| 7426 | 6869 | .parent = null, |
| 7427 | 6870 | .sema = sema, |
| 7428 | 6871 | .namespace = fn_nav.analysis.?.namespace, |
| 7429 | .instructions = .{}, | |
| 6872 | .instructions = .empty, | |
| 7430 | 6873 | .inlining = &generic_inlining, |
| 7431 | 6874 | .src_base_inst = fn_nav.analysis.?.zir_index, |
| 7432 | 6875 | .type_name_ctx = fn_nav.fqn, |
| 7433 | 6876 | } else undefined; |
| 7434 | defer if (func_ty_info.is_generic) generic_block.instructions.deinit(gpa); | |
| 6877 | defer if (any_generic_types) generic_block.instructions.deinit(gpa); | |
| 7435 | 6878 | |
| 7436 | if (func_ty_info.is_generic) { | |
| 6879 | if (any_generic_types) { | |
| 7437 | 6880 | // We certainly depend on the generic owner's signature! |
| 7438 | 6881 | try sema.declareDependency(.{ .src_hash = fn_tracked_inst }); |
| 7439 | 6882 | } |
| ... | ... | @@ -7445,7 +6888,7 @@ fn analyzeCall( |
| 7445 | 6888 | if (raw != .generic_poison_type) break :ty .fromInterned(raw); |
| 7446 | 6889 | |
| 7447 | 6890 | // We must discover the generic parameter type. |
| 7448 | assert(func_ty_info.is_generic); | |
| 6891 | assert(any_generic_types); | |
| 7449 | 6892 | const param_inst_idx = fn_zir_info.param_body[arg_idx]; |
| 7450 | 6893 | const param_inst = fn_zir.instructions.get(@intFromEnum(param_inst_idx)); |
| 7451 | 6894 | switch (param_inst.tag) { |
| ... | ... | @@ -7476,7 +6919,7 @@ fn analyzeCall( |
| 7476 | 6919 | } }; |
| 7477 | 6920 | |
| 7478 | 6921 | const ty_ref = try sema.resolveInlineBody(&generic_block, body, param_inst_idx); |
| 7479 | const param_ty = try sema.analyzeAsType(&generic_block, param_src, ty_ref); | |
| 6922 | const param_ty = try sema.analyzeAsType(&generic_block, param_src, .fn_param_types, ty_ref); | |
| 7480 | 6923 | |
| 7481 | 6924 | if (!param_ty.isValidParamType(zcu)) { |
| 7482 | 6925 | const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; |
| ... | ... | @@ -7490,15 +6933,15 @@ fn analyzeCall( |
| 7490 | 6933 | |
| 7491 | 6934 | arg.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, callee, maybe_func_inst); |
| 7492 | 6935 | const arg_ty = sema.typeOf(arg.*); |
| 7493 | if (arg_ty.zigTypeTag(zcu) == .noreturn) { | |
| 6936 | if (arg_ty.classify(zcu) == .no_possible_value) { | |
| 7494 | 6937 | return arg.*; // terminate analysis here |
| 7495 | 6938 | } |
| 7496 | 6939 | |
| 7497 | if (func_ty_info.is_generic) { | |
| 6940 | if (any_generic_types) { | |
| 7498 | 6941 | // We need to put the argument into `generic_inst_map` so that other parameters can refer to it. |
| 7499 | 6942 | const param_inst_idx = fn_zir_info.param_body[arg_idx]; |
| 7500 | 6943 | const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false; |
| 7501 | const param_is_comptime = declared_comptime or try arg_ty.comptimeOnlySema(pt); | |
| 6944 | const param_is_comptime = declared_comptime or arg_ty.comptimeOnly(zcu); | |
| 7502 | 6945 | // We allow comptime-known arguments to propagate to generic types not only for comptime |
| 7503 | 6946 | // parameters, but if the call is known to be inline. |
| 7504 | 6947 | if (param_is_comptime or early_known_inline) { |
| ... | ... | @@ -7516,6 +6959,10 @@ fn analyzeCall( |
| 7516 | 6959 | ); |
| 7517 | 6960 | } |
| 7518 | 6961 | generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, arg.*); |
| 6962 | } else if (try arg_ty.onePossibleValue(pt)) |opv| { | |
| 6963 | // The argument is comptime-known, even though this is a generic instantiation (as | |
| 6964 | // opposed to an inline call), because the parameter type is OPV. | |
| 6965 | generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, .fromValue(opv)); | |
| 7519 | 6966 | } else { |
| 7520 | 6967 | // We need a dummy instruction with this type. It doesn't actually need to be in any block, |
| 7521 | 6968 | // since it will never be referenced at runtime! |
| ... | ... | @@ -7532,7 +6979,7 @@ fn analyzeCall( |
| 7532 | 6979 | // calls (where it should be the IES of the instantiation). However, it's how we print this |
| 7533 | 6980 | // in error messages. |
| 7534 | 6981 | const resolved_ret_ty: Type = ret_ty: { |
| 7535 | if (!func_ty_info.is_generic) break :ret_ty .fromInterned(func_ty_info.return_type); | |
| 6982 | if (!any_generic_types) break :ret_ty .fromInterned(func_ty_info.return_type); | |
| 7536 | 6983 | |
| 7537 | 6984 | const maybe_poison_bare = if (fn_zir_info.inferred_error_set) maybe_poison: { |
| 7538 | 6985 | break :maybe_poison ip.errorUnionPayload(func_ty_info.return_type); |
| ... | ... | @@ -7542,7 +6989,7 @@ fn analyzeCall( |
| 7542 | 6989 | |
| 7543 | 6990 | // Evaluate the generic return type. As with generic parameters, we switch out `sema.code` and `sema.inst_map`. |
| 7544 | 6991 | |
| 7545 | assert(func_ty_info.is_generic); | |
| 6992 | assert(any_generic_types); | |
| 7546 | 6993 | |
| 7547 | 6994 | const old_code = sema.code; |
| 7548 | 6995 | const old_inst_map = sema.inst_map; |
| ... | ... | @@ -7565,7 +7012,7 @@ fn analyzeCall( |
| 7565 | 7012 | } else bare: { |
| 7566 | 7013 | assert(fn_zir_info.ret_ty_body.len != 0); |
| 7567 | 7014 | const ty_ref = try sema.resolveInlineBody(&generic_block, fn_zir_info.ret_ty_body, fn_zir_inst); |
| 7568 | break :bare try sema.analyzeAsType(&generic_block, func_ret_ty_src, ty_ref); | |
| 7015 | break :bare try sema.analyzeAsType(&generic_block, func_ret_ty_src, .fn_ret_ty, ty_ref); | |
| 7569 | 7016 | }; |
| 7570 | 7017 | assert(bare_ty.toIntern() != .generic_poison_type); |
| 7571 | 7018 | |
| ... | ... | @@ -7584,10 +7031,11 @@ fn analyzeCall( |
| 7584 | 7031 | |
| 7585 | 7032 | break :ret_ty full_ty; |
| 7586 | 7033 | }; |
| 7034 | try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src, .return_type); | |
| 7587 | 7035 | |
| 7588 | 7036 | // If we've discovered after evaluating arguments that a generic function instantiation is |
| 7589 | 7037 | // comptime-only, then we can mark the block as comptime *now*. |
| 7590 | if (!inline_requested and !block.isComptime() and try resolved_ret_ty.comptimeOnlySema(pt)) { | |
| 7038 | if (!inline_requested and !block.isComptime() and resolved_ret_ty.comptimeOnly(zcu)) { | |
| 7591 | 7039 | block.comptime_reason = .{ |
| 7592 | 7040 | .reason = .{ |
| 7593 | 7041 | .src = call_src, |
| ... | ... | @@ -7618,15 +7066,23 @@ fn analyzeCall( |
| 7618 | 7066 | }); |
| 7619 | 7067 | if (func_ty_info.cc == .auto) { |
| 7620 | 7068 | switch (sema.owner.unwrap()) { |
| 7621 | .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, | |
| 7069 | .@"comptime", | |
| 7070 | .nav_ty, | |
| 7071 | .nav_val, | |
| 7072 | .type_layout, | |
| 7073 | .struct_defaults, | |
| 7074 | .memoized_state, | |
| 7075 | => {}, | |
| 7076 | ||
| 7622 | 7077 | .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), |
| 7623 | 7078 | } |
| 7624 | 7079 | } |
| 7625 | 7080 | for (args, 0..) |arg, arg_idx| { |
| 7626 | try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg); | |
| 7081 | const arg_src = args_info.argSrc(block, arg_idx); | |
| 7082 | try sema.validateRuntimeValue(block, arg_src, arg); | |
| 7627 | 7083 | } |
| 7628 | 7084 | const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: { |
| 7629 | if (!func_ty_info.is_generic) break :func .{ callee, args }; | |
| 7085 | if (!any_generic_types and !any_comptime_params) break :func .{ callee, args }; | |
| 7630 | 7086 | |
| 7631 | 7087 | // Instantiate the generic function! |
| 7632 | 7088 | |
| ... | ... | @@ -7648,13 +7104,13 @@ fn analyzeCall( |
| 7648 | 7104 | break :c true; |
| 7649 | 7105 | } |
| 7650 | 7106 | } |
| 7651 | break :c try arg_ty.comptimeOnlySema(pt); | |
| 7107 | break :c arg_ty.comptimeOnly(zcu); | |
| 7652 | 7108 | }; |
| 7653 | 7109 | const is_noalias = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsNoalias(i) else false; |
| 7654 | 7110 | |
| 7655 | 7111 | if (is_comptime) { |
| 7656 | 7112 | // We already emitted an error if the argument isn't comptime-known. |
| 7657 | comptime_arg.* = (try sema.resolveValue(arg)).?.toIntern(); | |
| 7113 | comptime_arg.* = sema.resolveValue(arg).?.toIntern(); | |
| 7658 | 7114 | } else { |
| 7659 | 7115 | comptime_arg.* = .none; |
| 7660 | 7116 | if (is_noalias) { |
| ... | ... | @@ -7695,7 +7151,7 @@ fn analyzeCall( |
| 7695 | 7151 | }; |
| 7696 | 7152 | |
| 7697 | 7153 | ref_func: { |
| 7698 | const runtime_func_val = try sema.resolveValue(runtime_func) orelse break :ref_func; | |
| 7154 | const runtime_func_val = sema.resolveValue(runtime_func) orelse break :ref_func; | |
| 7699 | 7155 | if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func; |
| 7700 | 7156 | const orig_fn_index = ip.unwrapCoercedFunc(runtime_func_val.toIntern()); |
| 7701 | 7157 | try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = orig_fn_index })); |
| ... | ... | @@ -7714,7 +7170,7 @@ fn analyzeCall( |
| 7714 | 7170 | }; |
| 7715 | 7171 | |
| 7716 | 7172 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).@"struct".fields.len + runtime_args.len); |
| 7717 | const maybe_opv = try block.addInst(.{ | |
| 7173 | const call_ref = try block.addInst(.{ | |
| 7718 | 7174 | .tag = call_tag, |
| 7719 | 7175 | .data = .{ .pl_op = .{ |
| 7720 | 7176 | .operand = runtime_func, |
| ... | ... | @@ -7725,8 +7181,10 @@ fn analyzeCall( |
| 7725 | 7181 | }); |
| 7726 | 7182 | sema.appendRefsAssumeCapacity(runtime_args); |
| 7727 | 7183 | |
| 7184 | const actual_ret_ty = sema.typeOf(call_ref); | |
| 7185 | ||
| 7728 | 7186 | if (ensure_result_used) { |
| 7729 | try sema.ensureResultUsed(block, sema.typeOf(maybe_opv), call_src); | |
| 7187 | try sema.ensureResultUsed(block, actual_ret_ty, call_src); | |
| 7730 | 7188 | } |
| 7731 | 7189 | |
| 7732 | 7190 | if (call_tag == .call_always_tail) { |
| ... | ... | @@ -7736,29 +7194,32 @@ fn analyzeCall( |
| 7736 | 7194 | .pointer => func_or_ptr_ty.childType(zcu), |
| 7737 | 7195 | else => unreachable, |
| 7738 | 7196 | }; |
| 7739 | return sema.handleTailCall(block, call_src, runtime_func_ty, maybe_opv); | |
| 7197 | return sema.handleTailCall(block, call_src, runtime_func_ty, call_ref); | |
| 7740 | 7198 | } |
| 7741 | 7199 | |
| 7742 | if (ip.isNoReturn(resolved_ret_ty.toIntern())) { | |
| 7743 | const want_check = c: { | |
| 7744 | if (!block.wantSafety()) break :c false; | |
| 7745 | if (func_val != null) break :c false; | |
| 7746 | break :c true; | |
| 7747 | }; | |
| 7748 | if (want_check) { | |
| 7749 | try sema.safetyPanic(block, call_src, .noreturn_returned); | |
| 7750 | } else { | |
| 7751 | _ = try block.addNoOp(.unreach); | |
| 7752 | } | |
| 7753 | return .unreachable_value; | |
| 7200 | switch (actual_ret_ty.classify(zcu)) { | |
| 7201 | .no_possible_value => { | |
| 7202 | const want_check = c: { | |
| 7203 | if (!block.wantSafety()) break :c false; | |
| 7204 | if (func_val != null) break :c false; | |
| 7205 | break :c true; | |
| 7206 | }; | |
| 7207 | if (want_check) { | |
| 7208 | try sema.safetyPanic(block, call_src, .noreturn_returned); | |
| 7209 | } else { | |
| 7210 | _ = try block.addNoOp(.unreach); | |
| 7211 | } | |
| 7212 | return .unreachable_value; | |
| 7213 | }, | |
| 7214 | .one_possible_value => { | |
| 7215 | return .fromValue((try actual_ret_ty.onePossibleValue(pt)).?); | |
| 7216 | }, | |
| 7217 | .runtime => { | |
| 7218 | return call_ref; | |
| 7219 | }, | |
| 7220 | .partially_comptime => unreachable, | |
| 7221 | .fully_comptime => unreachable, | |
| 7754 | 7222 | } |
| 7755 | ||
| 7756 | const result: Air.Inst.Ref = if (try sema.typeHasOnePossibleValue(sema.typeOf(maybe_opv))) |opv| | |
| 7757 | .fromValue(opv) | |
| 7758 | else | |
| 7759 | maybe_opv; | |
| 7760 | ||
| 7761 | return result; | |
| 7762 | 7223 | } |
| 7763 | 7224 | |
| 7764 | 7225 | // This is an inline call. The function must be comptime-known. We will analyze its body directly using this `Sema`. |
| ... | ... | @@ -7836,14 +7297,14 @@ fn analyzeCall( |
| 7836 | 7297 | if (zcu.comp.config.incremental) break :m false; |
| 7837 | 7298 | if (!block.isComptime()) break :m false; |
| 7838 | 7299 | for (args) |a| { |
| 7839 | const val = (try sema.resolveValue(a)).?; | |
| 7300 | const val = sema.resolveValue(a).?; | |
| 7840 | 7301 | if (val.canMutateComptimeVarState(zcu)) break :m false; |
| 7841 | 7302 | } |
| 7842 | 7303 | break :m true; |
| 7843 | 7304 | }; |
| 7844 | 7305 | const memoized_arg_values: []const InternPool.Index = if (want_memoize) arg_vals: { |
| 7845 | 7306 | const vals = try sema.arena.alloc(InternPool.Index, args.len); |
| 7846 | for (vals, args) |*v, a| v.* = (try sema.resolveValue(a)).?.toIntern(); | |
| 7307 | for (vals, args) |*v, a| v.* = sema.resolveValue(a).?.toIntern(); | |
| 7847 | 7308 | break :arg_vals vals; |
| 7848 | 7309 | } else undefined; |
| 7849 | 7310 | if (want_memoize) memoize: { |
| ... | ... | @@ -7927,7 +7388,7 @@ fn analyzeCall( |
| 7927 | 7388 | .parent = null, |
| 7928 | 7389 | .sema = sema, |
| 7929 | 7390 | .namespace = fn_nav.analysis.?.namespace, |
| 7930 | .instructions = .{}, | |
| 7391 | .instructions = .empty, | |
| 7931 | 7392 | .inlining = &inlining, |
| 7932 | 7393 | .is_typeof = block.is_typeof, |
| 7933 | 7394 | .comptime_reason = if (block.isComptime()) .inlining_parent else null, |
| ... | ... | @@ -8000,7 +7461,11 @@ fn analyzeCall( |
| 8000 | 7461 | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, &inlining.merges, need_debug_scope); |
| 8001 | 7462 | }; |
| 8002 | 7463 | |
| 8003 | const maybe_opv: Air.Inst.Ref = if (try sema.resolveValue(result_raw)) |result_val| r: { | |
| 7464 | if (sema.typeOf(result_raw).isNoReturn(zcu)) { | |
| 7465 | return .unreachable_value; | |
| 7466 | } | |
| 7467 | ||
| 7468 | const maybe_opv: Air.Inst.Ref = if (sema.resolveValue(result_raw)) |result_val| r: { | |
| 8004 | 7469 | const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); |
| 8005 | 7470 | break :r Air.internedToRef(val_resolved); |
| 8006 | 7471 | } else r: { |
| ... | ... | @@ -8012,7 +7477,7 @@ fn analyzeCall( |
| 8012 | 7477 | }; |
| 8013 | 7478 | |
| 8014 | 7479 | if (block.isComptime()) { |
| 8015 | const result_val = (try sema.resolveValue(maybe_opv)).?; | |
| 7480 | const result_val = sema.resolveValue(maybe_opv).?; | |
| 8016 | 7481 | if (want_memoize and sema.allow_memoize and !result_val.canMutateComptimeVarState(zcu)) { |
| 8017 | 7482 | _ = try pt.intern(.{ .memoized_call = .{ |
| 8018 | 7483 | .func = func_val.?.toIntern(), |
| ... | ... | @@ -8081,15 +7546,12 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 8081 | 7546 | const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin; |
| 8082 | 7547 | const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type; |
| 8083 | 7548 | const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu); |
| 8084 | try indexable_ty.resolveFields(pt); | |
| 8085 | 7549 | assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction |
| 8086 | if (indexable_ty.zigTypeTag(zcu) == .@"struct") { | |
| 8087 | const elem_type = indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu); | |
| 8088 | return Air.internedToRef(elem_type.toIntern()); | |
| 8089 | } else { | |
| 8090 | const elem_type = indexable_ty.elemType2(zcu); | |
| 8091 | return Air.internedToRef(elem_type.toIntern()); | |
| 8092 | } | |
| 7550 | const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) { | |
| 7551 | .@"struct" => indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu), | |
| 7552 | else => indexable_ty.indexableElem(zcu), | |
| 7553 | }; | |
| 7554 | return .fromType(elem_ty); | |
| 8093 | 7555 | } |
| 8094 | 7556 | |
| 8095 | 7557 | fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -8190,7 +7652,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 8190 | 7652 | const len = try sema.resolveInt(block, len_src, extra.len, .usize, .{ .simple = .array_length }); |
| 8191 | 7653 | const elem_type = try sema.resolveType(block, elem_src, extra.elem_type); |
| 8192 | 7654 | try sema.validateArrayElemType(block, elem_type, elem_src); |
| 8193 | const uncasted_sentinel = try sema.resolveInst(extra.sentinel); | |
| 7655 | const uncasted_sentinel = sema.resolveInst(extra.sentinel); | |
| 8194 | 7656 | const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src); |
| 8195 | 7657 | const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel }); |
| 8196 | 7658 | if (sentinel_val.canMutateComptimeVarState(zcu)) { |
| ... | ... | @@ -8306,11 +7768,11 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8306 | 7768 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 8307 | 7769 | const src = block.nodeOffset(extra.node); |
| 8308 | 7770 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 8309 | const uncasted_operand = try sema.resolveInst(extra.operand); | |
| 7771 | const uncasted_operand = sema.resolveInst(extra.operand); | |
| 8310 | 7772 | const operand = try sema.coerce(block, .anyerror, uncasted_operand, operand_src); |
| 8311 | 7773 | const err_int_ty = try pt.errorIntType(); |
| 8312 | 7774 | |
| 8313 | if (try sema.resolveValue(operand)) |val| { | |
| 7775 | if (sema.resolveValue(operand)) |val| { | |
| 8314 | 7776 | if (val.isUndef(zcu)) { |
| 8315 | 7777 | return pt.undefRef(err_int_ty); |
| 8316 | 7778 | } |
| ... | ... | @@ -8350,12 +7812,12 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8350 | 7812 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 8351 | 7813 | const src = block.nodeOffset(extra.node); |
| 8352 | 7814 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 8353 | const uncasted_operand = try sema.resolveInst(extra.operand); | |
| 7815 | const uncasted_operand = sema.resolveInst(extra.operand); | |
| 8354 | 7816 | const err_int_ty = try pt.errorIntType(); |
| 8355 | 7817 | const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src); |
| 8356 | 7818 | |
| 8357 | 7819 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { |
| 8358 | const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt)); | |
| 7820 | const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(zcu)); | |
| 8359 | 7821 | if (int > len: { |
| 8360 | 7822 | const mutate = &ip.global_error_set.mutate; |
| 8361 | 7823 | mutate.map.mutex.lockUncancelable(io); |
| ... | ... | @@ -8397,8 +7859,8 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8397 | 7859 | const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); |
| 8398 | 7860 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 8399 | 7861 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 8400 | const lhs = try sema.resolveInst(extra.lhs); | |
| 8401 | const rhs = try sema.resolveInst(extra.rhs); | |
| 7862 | const lhs = sema.resolveInst(extra.lhs); | |
| 7863 | const rhs = sema.resolveInst(extra.rhs); | |
| 8402 | 7864 | if (sema.typeOf(lhs).zigTypeTag(zcu) == .bool and sema.typeOf(rhs).zigTypeTag(zcu) == .bool) { |
| 8403 | 7865 | const msg = msg: { |
| 8404 | 7866 | const msg = try sema.errMsg(lhs_src, "expected error set type, found 'bool'", .{}); |
| ... | ... | @@ -8408,8 +7870,8 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8408 | 7870 | }; |
| 8409 | 7871 | return sema.failWithOwnedErrorMsg(block, msg); |
| 8410 | 7872 | } |
| 8411 | const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); | |
| 8412 | const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); | |
| 7873 | const lhs_ty = try sema.analyzeAsType(block, lhs_src, .type, lhs); | |
| 7874 | const rhs_ty = try sema.analyzeAsType(block, rhs_src, .type, rhs); | |
| 8413 | 7875 | if (lhs_ty.zigTypeTag(zcu) != .error_set) |
| 8414 | 7876 | return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{lhs_ty.fmt(pt)}); |
| 8415 | 7877 | if (rhs_ty.zigTypeTag(zcu) != .error_set) |
| ... | ... | @@ -8420,21 +7882,21 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 8420 | 7882 | return .anyerror_type; |
| 8421 | 7883 | } |
| 8422 | 7884 | |
| 8423 | if (ip.isInferredErrorSetType(lhs_ty.toIntern())) { | |
| 8424 | switch (try sema.resolveInferredErrorSet(block, src, lhs_ty.toIntern())) { | |
| 8425 | // isAnyError might have changed from a false negative to a true | |
| 8426 | // positive after resolution. | |
| 8427 | .anyerror_type => return .anyerror_type, | |
| 8428 | else => {}, | |
| 8429 | } | |
| 7885 | switch (ip.indexToKey(lhs_ty.toIntern())) { | |
| 7886 | .inferred_error_set_type => |func_index| { | |
| 7887 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 7888 | if (ip.funcIesResolvedUnordered(func_index) == .anyerror_type) return .anyerror_type; | |
| 7889 | }, | |
| 7890 | .error_set_type => {}, | |
| 7891 | else => unreachable, | |
| 8430 | 7892 | } |
| 8431 | if (ip.isInferredErrorSetType(rhs_ty.toIntern())) { | |
| 8432 | switch (try sema.resolveInferredErrorSet(block, src, rhs_ty.toIntern())) { | |
| 8433 | // isAnyError might have changed from a false negative to a true | |
| 8434 | // positive after resolution. | |
| 8435 | .anyerror_type => return .anyerror_type, | |
| 8436 | else => {}, | |
| 8437 | } | |
| 7893 | switch (ip.indexToKey(rhs_ty.toIntern())) { | |
| 7894 | .inferred_error_set_type => |func_index| { | |
| 7895 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 7896 | if (ip.funcIesResolvedUnordered(func_index) == .anyerror_type) return .anyerror_type; | |
| 7897 | }, | |
| 7898 | .error_set_type => {}, | |
| 7899 | else => unreachable, | |
| 8438 | 7900 | } |
| 8439 | 7901 | |
| 8440 | 7902 | const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); |
| ... | ... | @@ -8533,23 +7995,22 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8533 | 7995 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8534 | 7996 | const src = block.nodeOffset(inst_data.src_node); |
| 8535 | 7997 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 8536 | const operand = try sema.resolveInst(inst_data.operand); | |
| 7998 | const operand = sema.resolveInst(inst_data.operand); | |
| 8537 | 7999 | const operand_ty = sema.typeOf(operand); |
| 8538 | 8000 | |
| 8539 | 8001 | const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(zcu)) { |
| 8540 | 8002 | .@"enum" => operand, |
| 8541 | 8003 | .@"union" => blk: { |
| 8542 | try operand_ty.resolveFields(pt); | |
| 8543 | const tag_ty = operand_ty.unionTagType(zcu) orelse { | |
| 8004 | if (operand_ty.unionTagType(zcu) == null) { | |
| 8544 | 8005 | return sema.fail( |
| 8545 | 8006 | block, |
| 8546 | 8007 | operand_src, |
| 8547 | 8008 | "untagged union '{f}' cannot be converted to integer", |
| 8548 | 8009 | .{operand_ty.fmt(pt)}, |
| 8549 | 8010 | ); |
| 8550 | }; | |
| 8011 | } | |
| 8551 | 8012 | |
| 8552 | break :blk try sema.unionToTag(block, tag_ty, operand, operand_src); | |
| 8013 | break :blk try sema.unionToTag(block, operand); | |
| 8553 | 8014 | }, |
| 8554 | 8015 | else => { |
| 8555 | 8016 | return sema.fail(block, operand_src, "expected enum or tagged union, found '{f}'", .{ |
| ... | ... | @@ -8568,17 +8029,9 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8568 | 8029 | }); |
| 8569 | 8030 | } |
| 8570 | 8031 | |
| 8571 | if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| { | |
| 8572 | return Air.internedToRef((try pt.getCoerced(opv, int_tag_ty)).toIntern()); | |
| 8573 | } | |
| 8574 | ||
| 8575 | if (try sema.resolveValue(enum_tag)) |enum_tag_val| { | |
| 8576 | if (enum_tag_val.isUndef(zcu)) { | |
| 8577 | return pt.undefRef(int_tag_ty); | |
| 8578 | } | |
| 8579 | ||
| 8580 | const val = try enum_tag_val.intFromEnum(enum_tag_ty, pt); | |
| 8581 | return Air.internedToRef(val.toIntern()); | |
| 8032 | if (sema.resolveValue(enum_tag)) |enum_tag_val| { | |
| 8033 | if (enum_tag_val.isUndef(zcu)) return pt.undefRef(int_tag_ty); | |
| 8034 | return .fromValue(enum_tag_val.intFromEnum(zcu)); | |
| 8582 | 8035 | } |
| 8583 | 8036 | |
| 8584 | 8037 | try sema.requireRuntimeBlock(block, src, operand_src); |
| ... | ... | @@ -8593,18 +8046,19 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8593 | 8046 | const src = block.nodeOffset(inst_data.src_node); |
| 8594 | 8047 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 8595 | 8048 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); |
| 8596 | const operand = try sema.resolveInst(extra.rhs); | |
| 8049 | const operand = sema.resolveInst(extra.rhs); | |
| 8597 | 8050 | const operand_ty = sema.typeOf(operand); |
| 8598 | 8051 | |
| 8599 | 8052 | if (dest_ty.zigTypeTag(zcu) != .@"enum") { |
| 8600 | 8053 | return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)}); |
| 8601 | 8054 | } |
| 8055 | try sema.ensureLayoutResolved(dest_ty, src, .init); | |
| 8602 | 8056 | _ = try sema.checkIntType(block, operand_src, operand_ty); |
| 8603 | 8057 | |
| 8604 | if (try sema.resolveValue(operand)) |int_val| { | |
| 8058 | if (sema.resolveValue(operand)) |int_val| { | |
| 8605 | 8059 | if (dest_ty.isNonexhaustiveEnum(zcu)) { |
| 8606 | 8060 | const int_tag_ty = dest_ty.intTagType(zcu); |
| 8607 | if (try sema.intFitsInType(int_val, int_tag_ty, null)) { | |
| 8061 | if (int_val.intFitsInType(int_tag_ty, null, zcu)) { | |
| 8608 | 8062 | return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern()); |
| 8609 | 8063 | } |
| 8610 | 8064 | return sema.fail(block, src, "int value '{f}' out of range of non-exhaustive enum '{f}'", .{ |
| ... | ... | @@ -8626,19 +8080,15 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8626 | 8080 | return sema.failWithNeededComptime(block, operand_src, .{ .simple = .casted_to_comptime_enum }); |
| 8627 | 8081 | } |
| 8628 | 8082 | |
| 8629 | if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| { | |
| 8083 | if (try dest_ty.onePossibleValue(pt)) |opv| { | |
| 8630 | 8084 | if (block.wantSafety()) { |
| 8631 | 8085 | // The operand is runtime-known but the result is comptime-known. In |
| 8632 | 8086 | // this case we still need a safety check. |
| 8633 | const expect_int_val = switch (zcu.intern_pool.indexToKey(opv.toIntern())) { | |
| 8634 | .enum_tag => |enum_tag| enum_tag.int, | |
| 8635 | else => unreachable, | |
| 8636 | }; | |
| 8637 | const expect_int_coerced = try pt.getCoerced(.fromInterned(expect_int_val), operand_ty); | |
| 8638 | const ok = try block.addBinOp(.cmp_eq, operand, Air.internedToRef(expect_int_coerced.toIntern())); | |
| 8087 | const expect_int = try pt.getCoerced(opv.intFromEnum(zcu), operand_ty); | |
| 8088 | const ok = try block.addBinOp(.cmp_eq, operand, .fromValue(expect_int)); | |
| 8639 | 8089 | try sema.addSafetyCheck(block, src, ok, .invalid_enum_value); |
| 8640 | 8090 | } |
| 8641 | return Air.internedToRef(opv.toIntern()); | |
| 8091 | return .fromValue(opv); | |
| 8642 | 8092 | } |
| 8643 | 8093 | |
| 8644 | 8094 | try sema.requireRuntimeBlock(block, src, operand_src); |
| ... | ... | @@ -8660,12 +8110,17 @@ fn zirOptionalPayloadPtr( |
| 8660 | 8110 | defer tracy.end(); |
| 8661 | 8111 | |
| 8662 | 8112 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8663 | const optional_ptr = try sema.resolveInst(inst_data.operand); | |
| 8113 | const optional_ptr = sema.resolveInst(inst_data.operand); | |
| 8664 | 8114 | const src = block.nodeOffset(inst_data.src_node); |
| 8665 | 8115 | |
| 8116 | const ptr_ty = sema.typeOf(optional_ptr); | |
| 8117 | assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); | |
| 8118 | try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src, .ptr_access); | |
| 8119 | ||
| 8666 | 8120 | return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); |
| 8667 | 8121 | } |
| 8668 | 8122 | |
| 8123 | /// Asserts that the layout of the pointer child type is already resolved. | |
| 8669 | 8124 | fn analyzeOptionalPayloadPtr( |
| 8670 | 8125 | sema: *Sema, |
| 8671 | 8126 | block: *Block, |
| ... | ... | @@ -8680,12 +8135,13 @@ fn analyzeOptionalPayloadPtr( |
| 8680 | 8135 | assert(optional_ptr_ty.zigTypeTag(zcu) == .pointer); |
| 8681 | 8136 | |
| 8682 | 8137 | const opt_type = optional_ptr_ty.childType(zcu); |
| 8138 | opt_type.assertHasLayout(zcu); | |
| 8683 | 8139 | if (opt_type.zigTypeTag(zcu) != .optional) { |
| 8684 | 8140 | return sema.failWithExpectedOptionalType(block, src, opt_type); |
| 8685 | 8141 | } |
| 8686 | 8142 | |
| 8687 | 8143 | const child_type = opt_type.optionalChild(zcu); |
| 8688 | const child_pointer = try pt.ptrTypeSema(.{ | |
| 8144 | const child_pointer = try pt.ptrType(.{ | |
| 8689 | 8145 | .child = child_type.toIntern(), |
| 8690 | 8146 | .flags = .{ |
| 8691 | 8147 | .is_const = optional_ptr_ty.isConstPtr(zcu), |
| ... | ... | @@ -8698,7 +8154,7 @@ fn analyzeOptionalPayloadPtr( |
| 8698 | 8154 | if (sema.isComptimeMutablePtr(ptr_val)) { |
| 8699 | 8155 | // Set the optional to non-null at comptime. |
| 8700 | 8156 | // If the payload is OPV, we must use that value instead of undef. |
| 8701 | const payload_val = try sema.typeHasOnePossibleValue(child_type) orelse try pt.undefValue(child_type); | |
| 8157 | const payload_val = try child_type.onePossibleValue(pt) orelse try pt.undefValue(child_type); | |
| 8702 | 8158 | const opt_val = try pt.intern(.{ .opt = .{ |
| 8703 | 8159 | .ty = opt_type.toIntern(), |
| 8704 | 8160 | .val = payload_val.toIntern(), |
| ... | ... | @@ -8748,33 +8204,27 @@ fn zirOptionalPayload( |
| 8748 | 8204 | const zcu = pt.zcu; |
| 8749 | 8205 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8750 | 8206 | const src = block.nodeOffset(inst_data.src_node); |
| 8751 | const operand = try sema.resolveInst(inst_data.operand); | |
| 8207 | const operand = sema.resolveInst(inst_data.operand); | |
| 8752 | 8208 | const operand_ty = sema.typeOf(operand); |
| 8753 | 8209 | const result_ty = switch (operand_ty.zigTypeTag(zcu)) { |
| 8754 | 8210 | .optional => operand_ty.optionalChild(zcu), |
| 8755 | .pointer => t: { | |
| 8756 | if (operand_ty.ptrSize(zcu) != .c) { | |
| 8757 | return sema.failWithExpectedOptionalType(block, src, operand_ty); | |
| 8758 | } | |
| 8759 | // TODO https://github.com/ziglang/zig/issues/6597 | |
| 8760 | if (true) break :t operand_ty; | |
| 8761 | const ptr_info = operand_ty.ptrInfo(zcu); | |
| 8762 | break :t try pt.ptrTypeSema(.{ | |
| 8763 | .child = ptr_info.child, | |
| 8764 | .flags = .{ | |
| 8765 | .alignment = ptr_info.flags.alignment, | |
| 8766 | .is_const = ptr_info.flags.is_const, | |
| 8767 | .is_volatile = ptr_info.flags.is_volatile, | |
| 8768 | .is_allowzero = ptr_info.flags.is_allowzero, | |
| 8769 | .address_space = ptr_info.flags.address_space, | |
| 8770 | }, | |
| 8771 | }); | |
| 8211 | // TODO: https://github.com/ziglang/zig/issues/6597 will eliminate this branch so that we only need to handle optionals. | |
| 8212 | .pointer => switch (operand_ty.ptrSize(zcu)) { | |
| 8213 | .c => operand_ty, // if `ptr` is a `[*c]T`, then `ptr.?` is also a `[*c]T` | |
| 8214 | .one, .many, .slice => return sema.failWithExpectedOptionalType(block, src, operand_ty), | |
| 8772 | 8215 | }, |
| 8773 | 8216 | else => return sema.failWithExpectedOptionalType(block, src, operand_ty), |
| 8774 | 8217 | }; |
| 8775 | 8218 | |
| 8776 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { | |
| 8777 | if (val.optionalValue(zcu)) |payload| return Air.internedToRef(payload.toIntern()); | |
| 8219 | ct: { | |
| 8220 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { | |
| 8221 | if (val.optionalValue(zcu)) |payload| return .fromValue(payload); // comptime-known payload | |
| 8222 | } else if (try sema.resolveIsNullFromType(block, src, operand_ty)) |is_null| { | |
| 8223 | if (!is_null) break :ct; // fully runtime-known | |
| 8224 | } else { | |
| 8225 | break :ct; // fully runtime-known | |
| 8226 | } | |
| 8227 | // Comptime-known to be `null`. | |
| 8778 | 8228 | if (block.isComptime()) return sema.fail(block, src, "unable to unwrap null", .{}); |
| 8779 | 8229 | if (safety_check and block.wantSafety()) { |
| 8780 | 8230 | try sema.safetyPanic(block, src, .unwrap_null); |
| ... | ... | @@ -8784,11 +8234,14 @@ fn zirOptionalPayload( |
| 8784 | 8234 | return .unreachable_value; |
| 8785 | 8235 | } |
| 8786 | 8236 | |
| 8787 | try sema.requireRuntimeBlock(block, src, null); | |
| 8788 | 8237 | if (safety_check and block.wantSafety()) { |
| 8789 | 8238 | const is_non_null = try block.addUnOp(.is_non_null, operand); |
| 8790 | 8239 | try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); |
| 8791 | 8240 | } |
| 8241 | ||
| 8242 | // If the payload is OPV, we need the safety check but have a comptime-known result. | |
| 8243 | if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 8244 | ||
| 8792 | 8245 | return block.addTyOp(.optional_payload, result_ty, operand); |
| 8793 | 8246 | } |
| 8794 | 8247 | |
| ... | ... | @@ -8805,7 +8258,7 @@ fn zirErrUnionPayload( |
| 8805 | 8258 | const zcu = pt.zcu; |
| 8806 | 8259 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8807 | 8260 | const src = block.nodeOffset(inst_data.src_node); |
| 8808 | const operand = try sema.resolveInst(inst_data.operand); | |
| 8261 | const operand = sema.resolveInst(inst_data.operand); | |
| 8809 | 8262 | const operand_src = src; |
| 8810 | 8263 | const err_union_ty = sema.typeOf(operand); |
| 8811 | 8264 | if (err_union_ty.zigTypeTag(zcu) != .error_union) { |
| ... | ... | @@ -8844,8 +8297,8 @@ fn analyzeErrUnionPayload( |
| 8844 | 8297 | try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err); |
| 8845 | 8298 | } |
| 8846 | 8299 | |
| 8847 | if (try sema.typeHasOnePossibleValue(payload_ty)) |payload_only_value| { | |
| 8848 | return Air.internedToRef(payload_only_value.toIntern()); | |
| 8300 | if (try payload_ty.onePossibleValue(pt)) |payload_opv| { | |
| 8301 | return .fromValue(payload_opv); | |
| 8849 | 8302 | } |
| 8850 | 8303 | |
| 8851 | 8304 | return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand); |
| ... | ... | @@ -8861,12 +8314,17 @@ fn zirErrUnionPayloadPtr( |
| 8861 | 8314 | defer tracy.end(); |
| 8862 | 8315 | |
| 8863 | 8316 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8864 | const operand = try sema.resolveInst(inst_data.operand); | |
| 8317 | const operand = sema.resolveInst(inst_data.operand); | |
| 8865 | 8318 | const src = block.nodeOffset(inst_data.src_node); |
| 8866 | 8319 | |
| 8320 | const ptr_ty = sema.typeOf(operand); | |
| 8321 | assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); | |
| 8322 | try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src, .ptr_access); | |
| 8323 | ||
| 8867 | 8324 | return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); |
| 8868 | 8325 | } |
| 8869 | 8326 | |
| 8327 | /// Asserts that the layout of the pointer child type is already resolved. | |
| 8870 | 8328 | fn analyzeErrUnionPayloadPtr( |
| 8871 | 8329 | sema: *Sema, |
| 8872 | 8330 | block: *Block, |
| ... | ... | @@ -8887,8 +8345,9 @@ fn analyzeErrUnionPayloadPtr( |
| 8887 | 8345 | } |
| 8888 | 8346 | |
| 8889 | 8347 | const err_union_ty = operand_ty.childType(zcu); |
| 8348 | err_union_ty.assertHasLayout(zcu); | |
| 8890 | 8349 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 8891 | const operand_pointer_ty = try pt.ptrTypeSema(.{ | |
| 8350 | const operand_pointer_ty = try pt.ptrType(.{ | |
| 8892 | 8351 | .child = payload_ty.toIntern(), |
| 8893 | 8352 | .flags = .{ |
| 8894 | 8353 | .is_const = operand_ty.isConstPtr(zcu), |
| ... | ... | @@ -8901,7 +8360,7 @@ fn analyzeErrUnionPayloadPtr( |
| 8901 | 8360 | if (sema.isComptimeMutablePtr(ptr_val)) { |
| 8902 | 8361 | // Set the error union to non-error at comptime. |
| 8903 | 8362 | // If the payload is OPV, we must use that value instead of undef. |
| 8904 | const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); | |
| 8363 | const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); | |
| 8905 | 8364 | const eu_val = try pt.intern(.{ .error_union = .{ |
| 8906 | 8365 | .ty = err_union_ty.toIntern(), |
| 8907 | 8366 | .val = .{ .payload = payload_val.toIntern() }, |
| ... | ... | @@ -8948,7 +8407,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 8948 | 8407 | |
| 8949 | 8408 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8950 | 8409 | const src = block.nodeOffset(inst_data.src_node); |
| 8951 | const operand = try sema.resolveInst(inst_data.operand); | |
| 8410 | const operand = sema.resolveInst(inst_data.operand); | |
| 8952 | 8411 | return sema.analyzeErrUnionCode(block, src, operand); |
| 8953 | 8412 | } |
| 8954 | 8413 | |
| ... | ... | @@ -8984,7 +8443,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 8984 | 8443 | |
| 8985 | 8444 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 8986 | 8445 | const src = block.nodeOffset(inst_data.src_node); |
| 8987 | const operand = try sema.resolveInst(inst_data.operand); | |
| 8446 | const operand = sema.resolveInst(inst_data.operand); | |
| 8988 | 8447 | return sema.analyzeErrUnionCodePtr(block, src, operand); |
| 8989 | 8448 | } |
| 8990 | 8449 | |
| ... | ... | @@ -9302,11 +8761,12 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: |
| 9302 | 8761 | } |
| 9303 | 8762 | } |
| 9304 | 8763 | |
| 9305 | fn checkParamTypeCommon( | |
| 8764 | fn checkParamType( | |
| 9306 | 8765 | sema: *Sema, |
| 9307 | 8766 | block: *Block, |
| 9308 | 8767 | param_idx: u32, |
| 9309 | 8768 | param_ty: Type, |
| 8769 | param_is_comptime: bool, | |
| 9310 | 8770 | param_is_noalias: bool, |
| 9311 | 8771 | param_src: LazySrcLoc, |
| 9312 | 8772 | cc: std.builtin.CallingConvention, |
| ... | ... | @@ -9321,29 +8781,22 @@ fn checkParamTypeCommon( |
| 9321 | 8781 | opaque_str, param_ty.fmt(pt), |
| 9322 | 8782 | }); |
| 9323 | 8783 | } |
| 9324 | if (!param_ty.isGenericPoison() and | |
| 9325 | !target_util.fnCallConvAllowsZigTypes(cc) and | |
| 9326 | !try sema.validateExternType(param_ty, .param_ty)) | |
| 9327 | { | |
| 9328 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 9329 | const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{ | |
| 9330 | param_ty.fmt(pt), @tagName(cc), | |
| 9331 | }); | |
| 9332 | errdefer msg.destroy(sema.gpa); | |
| 9333 | ||
| 9334 | try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty); | |
| 9335 | ||
| 9336 | try sema.addDeclaredHereNote(msg, param_ty); | |
| 9337 | break :msg msg; | |
| 9338 | }); | |
| 8784 | if (!target_util.fnCallConvAllowsZigTypes(cc)) { | |
| 8785 | if (param_is_comptime) { | |
| 8786 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{t}'", .{cc}); | |
| 8787 | } | |
| 8788 | if (param_ty.isGenericPoison()) { | |
| 8789 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{t}'", .{cc}); | |
| 8790 | } | |
| 8791 | // The `validateExtern` check happens later, in `validateResolvedFuncType`. | |
| 9339 | 8792 | } |
| 9340 | 8793 | switch (cc) { |
| 9341 | 8794 | .x86_64_interrupt, .x86_interrupt => { |
| 9342 | 8795 | const err_code_size = target.ptrBitWidth(); |
| 9343 | 8796 | switch (param_idx) { |
| 9344 | 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}), | |
| 9345 | 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }), | |
| 9346 | else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), param_idx + 1 }), | |
| 8797 | 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{t}' calling convention must be a pointer type", .{cc}), | |
| 8798 | 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{t}' calling convention must be a {d}-bit integer", .{ cc, err_code_size }), | |
| 8799 | else => return sema.fail(block, param_src, "'{t}' calling convention supports up to 2 parameters, found {d}", .{ cc, param_idx + 1 }), | |
| 9347 | 8800 | } |
| 9348 | 8801 | }, |
| 9349 | 8802 | .arc_interrupt, |
| ... | ... | @@ -9359,7 +8812,7 @@ fn checkParamTypeCommon( |
| 9359 | 8812 | .m68k_interrupt, |
| 9360 | 8813 | .msp430_interrupt, |
| 9361 | 8814 | .avr_signal, |
| 9362 | => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}), | |
| 8815 | => return sema.fail(block, param_src, "parameters are not allowed with '{t}' calling convention", .{cc}), | |
| 9363 | 8816 | else => {}, |
| 9364 | 8817 | } |
| 9365 | 8818 | if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) { |
| ... | ... | @@ -9367,7 +8820,7 @@ fn checkParamTypeCommon( |
| 9367 | 8820 | } |
| 9368 | 8821 | } |
| 9369 | 8822 | |
| 9370 | fn checkReturnTypeAndCallConvCommon( | |
| 8823 | fn checkReturnTypeAndCallConv( | |
| 9371 | 8824 | sema: *Sema, |
| 9372 | 8825 | block: *Block, |
| 9373 | 8826 | bare_ret_ty: Type, |
| ... | ... | @@ -9381,7 +8834,6 @@ fn checkReturnTypeAndCallConvCommon( |
| 9381 | 8834 | ) CompileError!void { |
| 9382 | 8835 | const pt = sema.pt; |
| 9383 | 8836 | const zcu = pt.zcu; |
| 9384 | const gpa = zcu.gpa; | |
| 9385 | 8837 | if (opt_varargs_src) |varargs_src| { |
| 9386 | 8838 | try sema.checkCallConvSupportsVarArgs(block, varargs_src, @"callconv"); |
| 9387 | 8839 | } |
| ... | ... | @@ -9395,21 +8847,14 @@ fn checkReturnTypeAndCallConvCommon( |
| 9395 | 8847 | opaque_str, ies_ret_ty_prefix, bare_ret_ty.fmt(pt), |
| 9396 | 8848 | }); |
| 9397 | 8849 | } |
| 9398 | if (!bare_ret_ty.isGenericPoison() and | |
| 9399 | !target_util.fnCallConvAllowsZigTypes(@"callconv") and | |
| 9400 | (inferred_error_set or !try sema.validateExternType(bare_ret_ty, .ret_ty))) | |
| 9401 | { | |
| 9402 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 9403 | const msg = try sema.errMsg(ret_ty_src, "return type '{s}{f}' not allowed in function with calling convention '{s}'", .{ | |
| 9404 | ies_ret_ty_prefix, bare_ret_ty.fmt(pt), @tagName(@"callconv"), | |
| 9405 | }); | |
| 9406 | errdefer msg.destroy(gpa); | |
| 9407 | if (!inferred_error_set) { | |
| 9408 | try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, bare_ret_ty, .ret_ty); | |
| 9409 | try sema.addDeclaredHereNote(msg, bare_ret_ty); | |
| 9410 | } | |
| 9411 | break :msg msg; | |
| 9412 | }); | |
| 8850 | if (!target_util.fnCallConvAllowsZigTypes(@"callconv")) { | |
| 8851 | if (inferred_error_set) { | |
| 8852 | return sema.fail(block, ret_ty_src, "return type '!{f}' not allowed in function with calling convention '{t}'", .{ bare_ret_ty.fmt(pt), @"callconv" }); | |
| 8853 | } | |
| 8854 | if (bare_ret_ty.isGenericPoison()) { | |
| 8855 | return sema.fail(block, ret_ty_src, "generic return type not allowed in function with calling convention '{t}'", .{@"callconv"}); | |
| 8856 | } | |
| 8857 | // The `validateExtern` check happens later, in `validateResolvedFuncType`. | |
| 9413 | 8858 | } |
| 9414 | 8859 | validate_incoming_stack_align: { |
| 9415 | 8860 | const a: u64 = switch (@"callconv") { |
| ... | ... | @@ -9444,7 +8889,7 @@ fn checkReturnTypeAndCallConvCommon( |
| 9444 | 8889 | else => false, |
| 9445 | 8890 | }; |
| 9446 | 8891 | if (!ret_ok) { |
| 9447 | return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(@"callconv")}); | |
| 8892 | return sema.fail(block, ret_ty_src, "function with calling convention '{t}' must return 'void' or 'noreturn'", .{@"callconv"}); | |
| 9448 | 8893 | } |
| 9449 | 8894 | }, |
| 9450 | 8895 | .@"inline" => if (is_noinline) { |
| ... | ... | @@ -9465,18 +8910,76 @@ fn checkReturnTypeAndCallConvCommon( |
| 9465 | 8910 | } |
| 9466 | 8911 | } |
| 9467 | 8912 | }; |
| 9468 | return sema.fail(block, callconv_src, "calling convention '{s}' only available on architectures {f}", .{ | |
| 9469 | @tagName(@"callconv"), | |
| 9470 | ArchListFormatter{ .archs = allowed_archs }, | |
| 8913 | return sema.fail(block, callconv_src, "calling convention '{t}' only available on architectures {f}", .{ | |
| 8914 | @"callconv", ArchListFormatter{ .archs = allowed_archs }, | |
| 9471 | 8915 | }); |
| 9472 | 8916 | }, |
| 9473 | .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{ | |
| 9474 | @tagName(@"callconv"), | |
| 9475 | @tagName(bad_backend), | |
| 8917 | .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{t}' not supported by compiler backend '{t}'", .{ | |
| 8918 | @"callconv", bad_backend, | |
| 9476 | 8919 | }), |
| 9477 | 8920 | } |
| 9478 | 8921 | } |
| 9479 | 8922 | |
| 8923 | /// To avoid forcing type layout resolution too quickly, some validation of function types cannot be | |
| 8924 | /// performed when the type is first constructed, and instead must happen when either (a) a function | |
| 8925 | /// with that type is declared, or (b) a function with that type is called. That validation is | |
| 8926 | /// handled here. | |
| 8927 | /// | |
| 8928 | /// Asserts that all parameter types and return types have their layout fully resolved. | |
| 8929 | fn validateResolvedFuncType( | |
| 8930 | sema: *Sema, | |
| 8931 | block: *Block, | |
| 8932 | @"callconv": std.builtin.CallingConvention, | |
| 8933 | param_types: []const InternPool.Index, | |
| 8934 | ret_ty: Type, | |
| 8935 | src: LazySrcLoc, | |
| 8936 | maybe_func_decl_inst: ?InternPool.TrackedInst.Index, | |
| 8937 | ) SemaError!void { | |
| 8938 | const pt = sema.pt; | |
| 8939 | const zcu = pt.zcu; | |
| 8940 | const gpa = zcu.comp.gpa; | |
| 8941 | if (!target_util.fnCallConvAllowsZigTypes(@"callconv")) { | |
| 8942 | // Check that all parameter types are extern-compatible. | |
| 8943 | for (param_types, 0..) |param_ty_ip, param_index| { | |
| 8944 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 8945 | if (!param_ty.validateExtern(.param_ty, zcu)) { | |
| 8946 | const param_src: LazySrcLoc = if (maybe_func_decl_inst) |inst| .{ | |
| 8947 | .base_node_inst = inst, | |
| 8948 | .offset = .{ .fn_proto_param = .{ | |
| 8949 | .fn_proto_node_offset = .zero, | |
| 8950 | .param_index = @intCast(param_index), | |
| 8951 | } }, | |
| 8952 | } else src; | |
| 8953 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 8954 | const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{t}'", .{ | |
| 8955 | param_ty.fmt(pt), @"callconv", | |
| 8956 | }); | |
| 8957 | errdefer msg.destroy(gpa); | |
| 8958 | try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty); | |
| 8959 | try sema.addDeclaredHereNote(msg, param_ty); | |
| 8960 | break :msg msg; | |
| 8961 | }); | |
| 8962 | } | |
| 8963 | } | |
| 8964 | // Check that the return type is extern-compatible. | |
| 8965 | if (!ret_ty.validateExtern(.ret_ty, zcu)) { | |
| 8966 | const ret_ty_src: LazySrcLoc = if (maybe_func_decl_inst) |inst| .{ | |
| 8967 | .base_node_inst = inst, | |
| 8968 | .offset = .{ .node_offset_fn_type_ret_ty = .zero }, | |
| 8969 | } else src; | |
| 8970 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 8971 | const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{t}'", .{ | |
| 8972 | ret_ty.fmt(pt), @"callconv", | |
| 8973 | }); | |
| 8974 | errdefer msg.destroy(gpa); | |
| 8975 | try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, ret_ty, .ret_ty); | |
| 8976 | try sema.addDeclaredHereNote(msg, ret_ty); | |
| 8977 | break :msg msg; | |
| 8978 | }); | |
| 8979 | } | |
| 8980 | } | |
| 8981 | } | |
| 8982 | ||
| 9480 | 8983 | fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool { |
| 9481 | 8984 | return switch (cc) { |
| 9482 | 8985 | .naked, |
| ... | ... | @@ -9569,12 +9072,9 @@ fn funcCommon( |
| 9569 | 9072 | const io = comp.io; |
| 9570 | 9073 | const ip = &zcu.intern_pool; |
| 9571 | 9074 | |
| 9075 | const src = block.nodeOffset(src_node_offset); | |
| 9572 | 9076 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); |
| 9573 | 9077 | const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); |
| 9574 | const func_src = block.nodeOffset(src_node_offset); | |
| 9575 | ||
| 9576 | const ret_ty_requires_comptime = try bare_return_type.comptimeOnlySema(pt); | |
| 9577 | var is_generic = bare_return_type.isGenericPoison() or ret_ty_requires_comptime; | |
| 9578 | 9078 | |
| 9579 | 9079 | var comptime_bits: u32 = 0; |
| 9580 | 9080 | for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { |
| ... | ... | @@ -9587,49 +9087,21 @@ fn funcCommon( |
| 9587 | 9087 | .fn_proto_node_offset = src_node_offset, |
| 9588 | 9088 | .param_index = @intCast(i), |
| 9589 | 9089 | } }); |
| 9590 | const param_ty_comptime = try param_ty.comptimeOnlySema(pt); | |
| 9591 | const param_ty_generic = param_ty.isGenericPoison(); | |
| 9592 | if (param_is_comptime or param_ty_comptime or param_ty_generic) { | |
| 9593 | is_generic = true; | |
| 9594 | } | |
| 9595 | 9090 | if (param_is_comptime) { |
| 9596 | 9091 | comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error |
| 9597 | 9092 | } |
| 9598 | if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(cc)) { | |
| 9599 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); | |
| 9600 | } | |
| 9601 | if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) { | |
| 9602 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); | |
| 9603 | } | |
| 9604 | try sema.checkParamTypeCommon( | |
| 9093 | try sema.checkParamType( | |
| 9605 | 9094 | block, |
| 9606 | 9095 | @intCast(i), |
| 9607 | 9096 | param_ty, |
| 9097 | param_is_comptime, | |
| 9608 | 9098 | is_noalias, |
| 9609 | 9099 | param_src, |
| 9610 | 9100 | cc, |
| 9611 | 9101 | ); |
| 9612 | if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) { | |
| 9613 | const msg = msg: { | |
| 9614 | const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{ | |
| 9615 | param_ty.fmt(pt), | |
| 9616 | }); | |
| 9617 | errdefer msg.destroy(sema.gpa); | |
| 9618 | ||
| 9619 | try sema.explainWhyTypeIsComptime(msg, param_src, param_ty); | |
| 9620 | ||
| 9621 | try sema.addDeclaredHereNote(msg, param_ty); | |
| 9622 | break :msg msg; | |
| 9623 | }; | |
| 9624 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 9625 | } | |
| 9626 | } | |
| 9627 | ||
| 9628 | if (var_args and is_generic) { | |
| 9629 | return sema.fail(block, func_src, "generic function cannot be variadic", .{}); | |
| 9630 | 9102 | } |
| 9631 | 9103 | |
| 9632 | try sema.checkReturnTypeAndCallConvCommon( | |
| 9104 | try sema.checkReturnTypeAndCallConv( | |
| 9633 | 9105 | block, |
| 9634 | 9106 | bare_return_type, |
| 9635 | 9107 | ret_ty_src, |
| ... | ... | @@ -9643,48 +9115,28 @@ fn funcCommon( |
| 9643 | 9115 | is_noinline, |
| 9644 | 9116 | ); |
| 9645 | 9117 | |
| 9646 | // If the return type is comptime-only but not dependent on parameters then | |
| 9647 | // all parameter types also need to be comptime. | |
| 9648 | if (has_body and ret_ty_requires_comptime and !block.isComptime()) comptime_check: { | |
| 9649 | for (block.params.items(.is_comptime)) |is_comptime| { | |
| 9650 | if (!is_comptime) break; | |
| 9651 | } else break :comptime_check; | |
| 9652 | const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else ""; | |
| 9653 | const msg = try sema.errMsg( | |
| 9654 | ret_ty_src, | |
| 9655 | "function with comptime-only return type '{s}{f}' requires all parameters to be comptime", | |
| 9656 | .{ ies_ret_ty_prefix, bare_return_type.fmt(pt) }, | |
| 9118 | const param_types = block.params.items(.ty); | |
| 9119 | ||
| 9120 | if (has_body) { | |
| 9121 | for (param_types, 0..) |param_ty_ip, param_index| { | |
| 9122 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 9123 | const param_src = block.src(.{ .fn_proto_param = .{ | |
| 9124 | .fn_proto_node_offset = src_node_offset, | |
| 9125 | .param_index = @intCast(param_index), | |
| 9126 | } }); | |
| 9127 | try sema.ensureLayoutResolved(param_ty, param_src, .parameter); | |
| 9128 | } | |
| 9129 | try sema.ensureLayoutResolved(bare_return_type, ret_ty_src, .return_type); | |
| 9130 | try sema.validateResolvedFuncType( | |
| 9131 | block, | |
| 9132 | cc, | |
| 9133 | param_types, | |
| 9134 | bare_return_type, | |
| 9135 | src, | |
| 9136 | ip.getNav(sema.owner.unwrap().nav_val).srcInst(ip), | |
| 9657 | 9137 | ); |
| 9658 | errdefer msg.destroy(sema.gpa); | |
| 9659 | try sema.explainWhyTypeIsComptime(msg, ret_ty_src, bare_return_type); | |
| 9660 | ||
| 9661 | const tags = sema.code.instructions.items(.tag); | |
| 9662 | const data = sema.code.instructions.items(.data); | |
| 9663 | const param_body = sema.code.getParamBody(func_inst); | |
| 9664 | for ( | |
| 9665 | block.params.items(.is_comptime), | |
| 9666 | block.params.items(.name), | |
| 9667 | param_body[0..block.params.len], | |
| 9668 | ) |is_comptime, name_nts, param_index| { | |
| 9669 | if (!is_comptime) { | |
| 9670 | const param_src = block.tokenOffset(switch (tags[@intFromEnum(param_index)]) { | |
| 9671 | .param => data[@intFromEnum(param_index)].pl_tok.src_tok, | |
| 9672 | .param_anytype => data[@intFromEnum(param_index)].str_tok.src_tok, | |
| 9673 | else => unreachable, | |
| 9674 | }); | |
| 9675 | const name = sema.code.nullTerminatedString(name_nts); | |
| 9676 | if (name.len != 0) { | |
| 9677 | try sema.errNote(param_src, msg, "param '{s}' is required to be comptime", .{name}); | |
| 9678 | } else { | |
| 9679 | try sema.errNote(param_src, msg, "param is required to be comptime", .{}); | |
| 9680 | } | |
| 9681 | } | |
| 9682 | } | |
| 9683 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 9684 | 9138 | } |
| 9685 | 9139 | |
| 9686 | const param_types = block.params.items(.ty); | |
| 9687 | ||
| 9688 | 9140 | if (inferred_error_set) { |
| 9689 | 9141 | assert(has_body); |
| 9690 | 9142 | return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ |
| ... | ... | @@ -9696,7 +9148,6 @@ fn funcCommon( |
| 9696 | 9148 | .bare_return_type = bare_return_type.toIntern(), |
| 9697 | 9149 | .cc = cc, |
| 9698 | 9150 | .is_var_args = var_args, |
| 9699 | .is_generic = is_generic, | |
| 9700 | 9151 | .is_noinline = is_noinline, |
| 9701 | 9152 | |
| 9702 | 9153 | .zir_body_inst = try block.trackZir(func_inst), |
| ... | ... | @@ -9714,7 +9165,6 @@ fn funcCommon( |
| 9714 | 9165 | .return_type = bare_return_type.toIntern(), |
| 9715 | 9166 | .cc = cc, |
| 9716 | 9167 | .is_var_args = var_args, |
| 9717 | .is_generic = is_generic, | |
| 9718 | 9168 | .is_noinline = is_noinline, |
| 9719 | 9169 | }); |
| 9720 | 9170 | |
| ... | ... | @@ -9756,7 +9206,7 @@ fn zirParam( |
| 9756 | 9206 | } |
| 9757 | 9207 | |
| 9758 | 9208 | const param_ty_inst = try sema.resolveInlineBody(block, body, inst); |
| 9759 | break :ty try sema.analyzeAsType(block, src, param_ty_inst); | |
| 9209 | break :ty try sema.analyzeAsType(block, src, .fn_param_types, param_ty_inst); | |
| 9760 | 9210 | }; |
| 9761 | 9211 | |
| 9762 | 9212 | try block.params.append(sema.arena, .{ |
| ... | ... | @@ -9812,7 +9262,7 @@ fn analyzeAs( |
| 9812 | 9262 | ) CompileError!Air.Inst.Ref { |
| 9813 | 9263 | const pt = sema.pt; |
| 9814 | 9264 | const zcu = pt.zcu; |
| 9815 | const operand = try sema.resolveInst(zir_operand); | |
| 9265 | const operand = sema.resolveInst(zir_operand); | |
| 9816 | 9266 | const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand; |
| 9817 | 9267 | switch (dest_ty.zigTypeTag(zcu)) { |
| 9818 | 9268 | .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)}), |
| ... | ... | @@ -9838,32 +9288,23 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 9838 | 9288 | const zcu = pt.zcu; |
| 9839 | 9289 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 9840 | 9290 | const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 9841 | const operand = try sema.resolveInst(inst_data.operand); | |
| 9291 | const operand = sema.resolveInst(inst_data.operand); | |
| 9842 | 9292 | const operand_ty = sema.typeOf(operand); |
| 9843 | 9293 | const ptr_ty = operand_ty.scalarType(zcu); |
| 9844 | 9294 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 9845 | 9295 | if (!ptr_ty.isPtrAtRuntime(zcu)) { |
| 9846 | 9296 | return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}); |
| 9847 | 9297 | } |
| 9848 | const pointee_ty = ptr_ty.childType(zcu); | |
| 9849 | if (try ptr_ty.comptimeOnlySema(pt)) { | |
| 9850 | const msg = msg: { | |
| 9851 | const msg = try sema.errMsg(ptr_src, "comptime-only type '{f}' has no pointer address", .{pointee_ty.fmt(pt)}); | |
| 9852 | errdefer msg.destroy(sema.gpa); | |
| 9853 | try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty); | |
| 9854 | break :msg msg; | |
| 9855 | }; | |
| 9856 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 9857 | } | |
| 9298 | ||
| 9858 | 9299 | const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; |
| 9859 | 9300 | const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .usize_type, .len = len }) else .usize; |
| 9860 | 9301 | |
| 9861 | if (try sema.resolveValue(operand)) |operand_val| ct: { | |
| 9302 | if (sema.resolveValue(operand)) |operand_val| ct: { | |
| 9862 | 9303 | if (!is_vector) { |
| 9863 | 9304 | if (operand_val.isUndef(zcu)) { |
| 9864 | 9305 | return .undef_usize; |
| 9865 | 9306 | } |
| 9866 | const addr = try operand_val.getUnsignedIntSema(pt) orelse { | |
| 9307 | const addr = operand_val.getUnsignedInt(zcu) orelse { | |
| 9867 | 9308 | // Wasn't an integer pointer. This is a runtime operation. |
| 9868 | 9309 | break :ct; |
| 9869 | 9310 | }; |
| ... | ... | @@ -9879,7 +9320,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 9879 | 9320 | new_elem.* = .undef_usize; |
| 9880 | 9321 | continue; |
| 9881 | 9322 | } |
| 9882 | const addr = try ptr_val.getUnsignedIntSema(pt) orelse { | |
| 9323 | const addr = ptr_val.getUnsignedInt(zcu) orelse { | |
| 9883 | 9324 | // A vector element wasn't an integer pointer. This is a runtime operation. |
| 9884 | 9325 | break :ct; |
| 9885 | 9326 | }; |
| ... | ... | @@ -9917,7 +9358,7 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 9917 | 9358 | sema.code.nullTerminatedString(extra.field_name_start), |
| 9918 | 9359 | .no_embedded_nulls, |
| 9919 | 9360 | ); |
| 9920 | const object_ptr = try sema.resolveInst(extra.lhs); | |
| 9361 | const object_ptr = sema.resolveInst(extra.lhs); | |
| 9921 | 9362 | return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); |
| 9922 | 9363 | } |
| 9923 | 9364 | |
| ... | ... | @@ -9942,7 +9383,7 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9942 | 9383 | sema.code.nullTerminatedString(extra.field_name_start), |
| 9943 | 9384 | .no_embedded_nulls, |
| 9944 | 9385 | ); |
| 9945 | const object_ptr = try sema.resolveInst(extra.lhs); | |
| 9386 | const object_ptr = sema.resolveInst(extra.lhs); | |
| 9946 | 9387 | return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); |
| 9947 | 9388 | } |
| 9948 | 9389 | |
| ... | ... | @@ -9967,7 +9408,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 9967 | 9408 | sema.code.nullTerminatedString(extra.field_name_start), |
| 9968 | 9409 | .no_embedded_nulls, |
| 9969 | 9410 | ); |
| 9970 | const object_ptr = try sema.resolveInst(extra.lhs); | |
| 9411 | const object_ptr = sema.resolveInst(extra.lhs); | |
| 9971 | 9412 | const struct_ty = sema.typeOf(object_ptr).childType(zcu); |
| 9972 | 9413 | switch (struct_ty.zigTypeTag(zcu)) { |
| 9973 | 9414 | .@"struct", .@"union" => { |
| ... | ... | @@ -9987,7 +9428,7 @@ fn zirFieldPtrNamedLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 9987 | 9428 | const src = block.nodeOffset(inst_data.src_node); |
| 9988 | 9429 | const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 9989 | 9430 | const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; |
| 9990 | const object_ptr = try sema.resolveInst(extra.lhs); | |
| 9431 | const object_ptr = sema.resolveInst(extra.lhs); | |
| 9991 | 9432 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); |
| 9992 | 9433 | return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); |
| 9993 | 9434 | } |
| ... | ... | @@ -10000,7 +9441,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 10000 | 9441 | const src = block.nodeOffset(inst_data.src_node); |
| 10001 | 9442 | const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 10002 | 9443 | const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; |
| 10003 | const object_ptr = try sema.resolveInst(extra.lhs); | |
| 9444 | const object_ptr = sema.resolveInst(extra.lhs); | |
| 10004 | 9445 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); |
| 10005 | 9446 | return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); |
| 10006 | 9447 | } |
| ... | ... | @@ -10015,7 +9456,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10015 | 9456 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10016 | 9457 | |
| 10017 | 9458 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); |
| 10018 | const operand = try sema.resolveInst(extra.rhs); | |
| 9459 | const operand = sema.resolveInst(extra.rhs); | |
| 10019 | 9460 | |
| 10020 | 9461 | return sema.intCast(block, block.nodeOffset(inst_data.src_node), dest_ty, src, operand, operand_src); |
| 10021 | 9462 | } |
| ... | ... | @@ -10044,7 +9485,7 @@ fn intCast( |
| 10044 | 9485 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src); |
| 10045 | 9486 | const is_vector = dest_ty.zigTypeTag(zcu) == .vector; |
| 10046 | 9487 | |
| 10047 | if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| { | |
| 9488 | if (try dest_ty.onePossibleValue(pt)) |opv| { | |
| 10048 | 9489 | // requirement: intCast(u0, input) iff input == 0 |
| 10049 | 9490 | if (block.wantSafety()) { |
| 10050 | 9491 | try sema.requireRuntimeBlock(block, src, operand_src); |
| ... | ... | @@ -10090,7 +9531,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10090 | 9531 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10091 | 9532 | |
| 10092 | 9533 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast"); |
| 10093 | const operand = try sema.resolveInst(extra.rhs); | |
| 9534 | const operand = sema.resolveInst(extra.rhs); | |
| 10094 | 9535 | const operand_ty = sema.typeOf(operand); |
| 10095 | 9536 | switch (dest_ty.zigTypeTag(zcu)) { |
| 10096 | 9537 | .@"anyframe", |
| ... | ... | @@ -10258,7 +9699,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10258 | 9699 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); |
| 10259 | 9700 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 10260 | 9701 | |
| 10261 | const operand = try sema.resolveInst(extra.rhs); | |
| 9702 | const operand = sema.resolveInst(extra.rhs); | |
| 10262 | 9703 | const operand_ty = sema.typeOf(operand); |
| 10263 | 9704 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 10264 | 9705 | |
| ... | ... | @@ -10287,7 +9728,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10287 | 9728 | ), |
| 10288 | 9729 | } |
| 10289 | 9730 | |
| 10290 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 9731 | if (sema.resolveValue(operand)) |operand_val| { | |
| 10291 | 9732 | if (!is_vector) { |
| 10292 | 9733 | return Air.internedToRef((try operand_val.floatCast(dest_ty, pt)).toIntern()); |
| 10293 | 9734 | } |
| ... | ... | @@ -10319,8 +9760,8 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10319 | 9760 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 10320 | 9761 | const src = block.nodeOffset(inst_data.src_node); |
| 10321 | 9762 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10322 | const array = try sema.resolveInst(extra.lhs); | |
| 10323 | const elem_index = try sema.resolveInst(extra.rhs); | |
| 9763 | const array = sema.resolveInst(extra.lhs); | |
| 9764 | const elem_index = sema.resolveInst(extra.rhs); | |
| 10324 | 9765 | return sema.elemVal(block, src, array, elem_index, src, false); |
| 10325 | 9766 | } |
| 10326 | 9767 | |
| ... | ... | @@ -10332,8 +9773,8 @@ fn zirElemPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10332 | 9773 | const src = block.nodeOffset(inst_data.src_node); |
| 10333 | 9774 | const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); |
| 10334 | 9775 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10335 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10336 | const uncoerced_elem_index = try sema.resolveInst(extra.rhs); | |
| 9776 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9777 | const uncoerced_elem_index = sema.resolveInst(extra.rhs); | |
| 10337 | 9778 | if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { |
| 10338 | 9779 | const array_ptr_ty = sema.typeOf(array_ptr); |
| 10339 | 9780 | if (try sema.pointerDeref(block, src, array_ptr_val, array_ptr_ty)) |array_val| { |
| ... | ... | @@ -10351,7 +9792,7 @@ fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10351 | 9792 | defer tracy.end(); |
| 10352 | 9793 | |
| 10353 | 9794 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; |
| 10354 | const array = try sema.resolveInst(inst_data.operand); | |
| 9795 | const array = sema.resolveInst(inst_data.operand); | |
| 10355 | 9796 | const elem_index = try sema.pt.intRef(.usize, inst_data.idx); |
| 10356 | 9797 | return sema.elemVal(block, LazySrcLoc.unneeded, array, elem_index, LazySrcLoc.unneeded, false); |
| 10357 | 9798 | } |
| ... | ... | @@ -10365,8 +9806,8 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10365 | 9806 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 10366 | 9807 | const src = block.nodeOffset(inst_data.src_node); |
| 10367 | 9808 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10368 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10369 | const elem_index = try sema.resolveInst(extra.rhs); | |
| 9809 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9810 | const elem_index = sema.resolveInst(extra.rhs); | |
| 10370 | 9811 | const indexable_ty = sema.typeOf(array_ptr); |
| 10371 | 9812 | if (indexable_ty.zigTypeTag(zcu) != .pointer) { |
| 10372 | 9813 | const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node }); |
| ... | ... | @@ -10382,6 +9823,8 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10382 | 9823 | }; |
| 10383 | 9824 | return sema.failWithOwnedErrorMsg(block, msg); |
| 10384 | 9825 | } |
| 9826 | try sema.checkIndexable(block, src, indexable_ty); | |
| 9827 | try sema.ensureLayoutResolved(indexable_ty.childType(zcu), src, .ptr_access); | |
| 10385 | 9828 | return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false, false); |
| 10386 | 9829 | } |
| 10387 | 9830 | |
| ... | ... | @@ -10393,8 +9836,8 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10393 | 9836 | const src = block.nodeOffset(inst_data.src_node); |
| 10394 | 9837 | const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); |
| 10395 | 9838 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10396 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10397 | const uncoerced_elem_index = try sema.resolveInst(extra.rhs); | |
| 9839 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9840 | const uncoerced_elem_index = sema.resolveInst(extra.rhs); | |
| 10398 | 9841 | const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src); |
| 10399 | 9842 | return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true); |
| 10400 | 9843 | } |
| ... | ... | @@ -10408,7 +9851,7 @@ fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile |
| 10408 | 9851 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 10409 | 9852 | const src = block.nodeOffset(inst_data.src_node); |
| 10410 | 9853 | const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; |
| 10411 | const array_ptr = try sema.resolveInst(extra.ptr); | |
| 9854 | const array_ptr = sema.resolveInst(extra.ptr); | |
| 10412 | 9855 | const elem_index = try pt.intRef(.usize, extra.index); |
| 10413 | 9856 | const array_ty = sema.typeOf(array_ptr).childType(zcu); |
| 10414 | 9857 | switch (array_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -10427,8 +9870,8 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10427 | 9870 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 10428 | 9871 | const src = block.nodeOffset(inst_data.src_node); |
| 10429 | 9872 | const extra = sema.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; |
| 10430 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10431 | const start = try sema.resolveInst(extra.start); | |
| 9873 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9874 | const start = sema.resolveInst(extra.start); | |
| 10432 | 9875 | const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); |
| 10433 | 9876 | const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); |
| 10434 | 9877 | const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); |
| ... | ... | @@ -10443,9 +9886,9 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 10443 | 9886 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 10444 | 9887 | const src = block.nodeOffset(inst_data.src_node); |
| 10445 | 9888 | const extra = sema.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; |
| 10446 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10447 | const start = try sema.resolveInst(extra.start); | |
| 10448 | const end = try sema.resolveInst(extra.end); | |
| 9889 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9890 | const start = sema.resolveInst(extra.start); | |
| 9891 | const end = sema.resolveInst(extra.end); | |
| 10449 | 9892 | const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); |
| 10450 | 9893 | const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); |
| 10451 | 9894 | const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); |
| ... | ... | @@ -10461,10 +9904,10 @@ fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 10461 | 9904 | const src = block.nodeOffset(inst_data.src_node); |
| 10462 | 9905 | const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); |
| 10463 | 9906 | const extra = sema.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data; |
| 10464 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10465 | const start = try sema.resolveInst(extra.start); | |
| 10466 | const end: Air.Inst.Ref = if (extra.end == .none) .none else try sema.resolveInst(extra.end); | |
| 10467 | const sentinel = try sema.resolveInst(extra.sentinel); | |
| 9907 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9908 | const start = sema.resolveInst(extra.start); | |
| 9909 | const end: Air.Inst.Ref = if (extra.end == .none) .none else sema.resolveInst(extra.end); | |
| 9910 | const sentinel = sema.resolveInst(extra.sentinel); | |
| 10468 | 9911 | const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); |
| 10469 | 9912 | const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); |
| 10470 | 9913 | const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); |
| ... | ... | @@ -10479,10 +9922,10 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10479 | 9922 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 10480 | 9923 | const src = block.nodeOffset(inst_data.src_node); |
| 10481 | 9924 | const extra = sema.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; |
| 10482 | const array_ptr = try sema.resolveInst(extra.lhs); | |
| 10483 | const start = try sema.resolveInst(extra.start); | |
| 10484 | const len = try sema.resolveInst(extra.len); | |
| 10485 | const sentinel = if (extra.sentinel == .none) .none else try sema.resolveInst(extra.sentinel); | |
| 9925 | const array_ptr = sema.resolveInst(extra.lhs); | |
| 9926 | const start = sema.resolveInst(extra.start); | |
| 9927 | const len = sema.resolveInst(extra.len); | |
| 9928 | const sentinel = if (extra.sentinel == .none) .none else sema.resolveInst(extra.sentinel); | |
| 10486 | 9929 | const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); |
| 10487 | 9930 | const start_src = block.src(.{ .node_offset_slice_start = extra.start_src_node_offset }); |
| 10488 | 9931 | const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); |
| ... | ... | @@ -10510,7 +9953,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 10510 | 9953 | // This is like the logic in `analyzeSlice`; since we've evaluated the LHS as an lvalue, we will |
| 10511 | 9954 | // have a double pointer if it was already a pointer. |
| 10512 | 9955 | |
| 10513 | const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand)); | |
| 9956 | const lhs_ptr_ty = sema.typeOf(sema.resolveInst(inst_data.operand)); | |
| 10514 | 9957 | const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) { |
| 10515 | 9958 | .pointer => lhs_ptr_ty.childType(zcu), |
| 10516 | 9959 | else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{lhs_ptr_ty.fmt(pt)}), |
| ... | ... | @@ -10557,9 +10000,9 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 10557 | 10000 | var label: Block.Label = .{ |
| 10558 | 10001 | .zir_block = inst, |
| 10559 | 10002 | .merges = .{ |
| 10560 | .src_locs = .{}, | |
| 10561 | .results = .{}, | |
| 10562 | .br_list = .{}, | |
| 10003 | .src_locs = .empty, | |
| 10004 | .results = .empty, | |
| 10005 | .br_list = .empty, | |
| 10563 | 10006 | .block_inst = block_inst, |
| 10564 | 10007 | }, |
| 10565 | 10008 | }; |
| ... | ... | @@ -10590,12 +10033,14 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 10590 | 10033 | // Lastly, we analyze the error prong(s) as a regular switch. |
| 10591 | 10034 | |
| 10592 | 10035 | const raw_switch_operand, const non_err_cond, const non_err_hint = non_err: { |
| 10593 | const eu_maybe_ptr = try sema.resolveInst(zir_switch.main_operand); | |
| 10036 | const eu_maybe_ptr = sema.resolveInst(zir_switch.main_operand); | |
| 10594 | 10037 | const err_union_ty: Type = err_union_ty: { |
| 10595 | 10038 | const raw_operand_ty = sema.typeOf(eu_maybe_ptr); |
| 10596 | 10039 | if (!non_err_case.operand_is_ref) break :err_union_ty raw_operand_ty; |
| 10597 | 10040 | try sema.checkPtrOperand(block, operand_src, raw_operand_ty); |
| 10598 | break :err_union_ty raw_operand_ty.childType(zcu); | |
| 10041 | const child_ty = raw_operand_ty.childType(zcu); | |
| 10042 | try sema.ensureLayoutResolved(child_ty, operand_src, .ptr_access); | |
| 10043 | break :err_union_ty child_ty; | |
| 10599 | 10044 | }; |
| 10600 | 10045 | if (err_union_ty.zigTypeTag(zcu) != .error_union) { |
| 10601 | 10046 | return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{ |
| ... | ... | @@ -10711,9 +10156,9 @@ fn zirSwitchBlock( |
| 10711 | 10156 | var label: Block.Label = .{ |
| 10712 | 10157 | .zir_block = inst, |
| 10713 | 10158 | .merges = .{ |
| 10714 | .src_locs = .{}, | |
| 10715 | .results = .{}, | |
| 10716 | .br_list = .{}, | |
| 10159 | .src_locs = .empty, | |
| 10160 | .results = .empty, | |
| 10161 | .br_list = .empty, | |
| 10717 | 10162 | .block_inst = block_inst, |
| 10718 | 10163 | }, |
| 10719 | 10164 | }; |
| ... | ... | @@ -10723,7 +10168,7 @@ fn zirSwitchBlock( |
| 10723 | 10168 | defer child_block.instructions.deinit(sema.gpa); |
| 10724 | 10169 | defer merges.deinit(sema.gpa); |
| 10725 | 10170 | |
| 10726 | const raw_operand = try sema.resolveInst(zir_switch.main_operand); | |
| 10171 | const raw_operand = sema.resolveInst(zir_switch.main_operand); | |
| 10727 | 10172 | const validated_switch = try sema.validateSwitchBlock(block, raw_operand, operand_is_ref, inst, &zir_switch); |
| 10728 | 10173 | const maybe_ref = try sema.analyzeSwitchBlock(block, &child_block, raw_operand, operand_is_ref, merges, inst, &zir_switch, &validated_switch); |
| 10729 | 10174 | return maybe_ref orelse { |
| ... | ... | @@ -10764,18 +10209,19 @@ fn analyzeSwitchBlock( |
| 10764 | 10209 | .{ raw_operand, .none }; |
| 10765 | 10210 | |
| 10766 | 10211 | const operand_ty = sema.typeOf(val); |
| 10767 | const maybe_operand_opv = try sema.typeHasOnePossibleValue(operand_ty); | |
| 10212 | operand_ty.assertHasLayout(zcu); | |
| 10213 | const maybe_operand_opv = try operand_ty.onePossibleValue(pt); | |
| 10768 | 10214 | const init_cond: Air.Inst.Ref, const item_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { |
| 10769 | 10215 | .@"union" => tag: { |
| 10770 | const tag_ty = operand_ty.unionTagType(zcu).?; | |
| 10771 | const tag_val = try sema.unionToTag(block, tag_ty, val, operand_src); | |
| 10772 | break :tag .{ tag_val, tag_ty }; | |
| 10216 | const tag_val = try sema.unionToTag(block, val); | |
| 10217 | break :tag .{ tag_val, sema.typeOf(tag_val) }; | |
| 10773 | 10218 | }, |
| 10774 | 10219 | else => .{ |
| 10775 | 10220 | if (maybe_operand_opv) |operand_opv| .fromValue(operand_opv) else val, |
| 10776 | 10221 | operand_ty, |
| 10777 | 10222 | }, |
| 10778 | 10223 | }; |
| 10224 | item_ty.assertHasLayout(zcu); | |
| 10779 | 10225 | |
| 10780 | 10226 | if (zir_switch.has_continue and !block.isComptime()) { |
| 10781 | 10227 | const operand_alloc: Air.Inst.Ref = if (zir_switch.any_maybe_runtime_capture and |
| ... | ... | @@ -10849,7 +10295,7 @@ fn analyzeSwitchBlock( |
| 10849 | 10295 | if (extra.block_inst != switch_inst) return error.ComptimeBreak; |
| 10850 | 10296 | // This is a `switch_continue` targeting this block. Change the operand and start over. |
| 10851 | 10297 | const new_operand_src = child_block.nodeOffset(extra.operand_src_node.unwrap().?); |
| 10852 | const new_operand_uncoerced = try sema.resolveInst(break_inst.data.@"break".operand); | |
| 10298 | const new_operand_uncoerced = sema.resolveInst(break_inst.data.@"break".operand); | |
| 10853 | 10299 | const new_operand = try sema.coerce(child_block, raw_operand_ty, new_operand_uncoerced, new_operand_src); |
| 10854 | 10300 | |
| 10855 | 10301 | try sema.emitBackwardBranch(child_block, src); |
| ... | ... | @@ -10860,7 +10306,7 @@ fn analyzeSwitchBlock( |
| 10860 | 10306 | .{ new_operand, .none }; |
| 10861 | 10307 | |
| 10862 | 10308 | const new_cond_ref = if (union_originally) |
| 10863 | try sema.unionToTag(child_block, item_ty, new_val, src) | |
| 10309 | try sema.unionToTag(child_block, new_val) | |
| 10864 | 10310 | else |
| 10865 | 10311 | new_val; |
| 10866 | 10312 | |
| ... | ... | @@ -10881,7 +10327,7 @@ fn analyzeSwitchBlock( |
| 10881 | 10327 | unreachable; |
| 10882 | 10328 | } |
| 10883 | 10329 | |
| 10884 | if (try sema.typeHasOnePossibleValue(item_ty)) |item_opv| { | |
| 10330 | if (try item_ty.onePossibleValue(pt)) |item_opv| { | |
| 10885 | 10331 | // We simplify conditions with OPV to either a `loop` or a `block` since |
| 10886 | 10332 | // we cannot switch on a value which doesn't exist at runtime. |
| 10887 | 10333 | assert(operand == .loop); // `simple` should have already been comptime-resolved above! |
| ... | ... | @@ -10912,7 +10358,7 @@ fn analyzeSwitchBlock( |
| 10912 | 10358 | assert(case.range_infos.len == 0); |
| 10913 | 10359 | for (case.item_infos, item_refs) |item_info, item_ref| { |
| 10914 | 10360 | if (item_info.bodyLen()) |body_len| extra_index += body_len; |
| 10915 | if (sema.wantSwitchProngBodyAnalysis(block, item_ref, operand_ty, false, true, prong_info.is_comptime_unreach)) { | |
| 10361 | if (sema.wantSwitchProngBodyAnalysis(item_ref, operand_ty, false, true, prong_info.is_comptime_unreach)) { | |
| 10916 | 10362 | break :skip_case; |
| 10917 | 10363 | } |
| 10918 | 10364 | } |
| ... | ... | @@ -10928,7 +10374,7 @@ fn analyzeSwitchBlock( |
| 10928 | 10374 | unreachable; // malformed validated switch |
| 10929 | 10375 | }; |
| 10930 | 10376 | |
| 10931 | const analyze_body = sema.wantSwitchProngBodyAnalysis(block, .fromValue(item_opv), operand_ty, union_originally, err_set, false); | |
| 10377 | const analyze_body = sema.wantSwitchProngBodyAnalysis(.fromValue(item_opv), operand_ty, union_originally, err_set, false); | |
| 10932 | 10378 | if (!analyze_body) return .unreachable_value; |
| 10933 | 10379 | |
| 10934 | 10380 | if (!(err_set and |
| ... | ... | @@ -10938,10 +10384,10 @@ fn analyzeSwitchBlock( |
| 10938 | 10384 | const payload_inst: Zir.Inst.Index = if (capture != .none) inst: { |
| 10939 | 10385 | const payload_inst = zir_switch.payload_capture_placeholder.unwrap() orelse switch_inst; |
| 10940 | 10386 | const payload_ref: Air.Inst.Ref = payload_ref: { |
| 10941 | const item_val: InternPool.Index = switch (operand_ty.zigTypeTag(zcu)) { | |
| 10387 | const item_val: Value = switch (operand_ty.zigTypeTag(zcu)) { | |
| 10942 | 10388 | .@"union" => item_val: { |
| 10943 | 10389 | if (maybe_operand_opv) |operand_opv| { |
| 10944 | break :item_val zcu.intern_pool.indexToKey(operand_opv.toIntern()).un.val; | |
| 10390 | break :item_val .fromInterned(zcu.intern_pool.indexToKey(operand_opv.toIntern()).un.val); | |
| 10945 | 10391 | } |
| 10946 | 10392 | assert(union_originally); // operand type must be union, otherwise it would be an OPV type here |
| 10947 | 10393 | assert(zir_switch.any_maybe_runtime_capture); // there's a payload capture |
| ... | ... | @@ -10978,10 +10424,10 @@ fn analyzeSwitchBlock( |
| 10978 | 10424 | validated_switch.else_err_ty, |
| 10979 | 10425 | ); |
| 10980 | 10426 | }, |
| 10981 | else => item_opv.toIntern(), | |
| 10427 | else => item_opv, | |
| 10982 | 10428 | }; |
| 10983 | 10429 | break :payload_ref switch (capture) { |
| 10984 | .by_val => .fromIntern(item_val), | |
| 10430 | .by_val => .fromValue(item_val), | |
| 10985 | 10431 | .by_ref => try sema.uavRef(item_val), |
| 10986 | 10432 | .none => unreachable, |
| 10987 | 10433 | }; |
| ... | ... | @@ -11186,7 +10632,7 @@ fn finishSwitchBr( |
| 11186 | 10632 | if (item_ref == .none) is_under_prong = true; |
| 11187 | 10633 | if (item_info.bodyLen()) |body_len| extra_index += body_len; |
| 11188 | 10634 | |
| 11189 | const analyze_body = sema.wantSwitchProngBodyAnalysis(block, item_ref, operand_ty, union_originally, err_set, prong_info.is_comptime_unreach); | |
| 10635 | const analyze_body = sema.wantSwitchProngBodyAnalysis(item_ref, operand_ty, union_originally, err_set, prong_info.is_comptime_unreach); | |
| 11190 | 10636 | if (analyze_body) any_analyze_body = true; |
| 11191 | 10637 | |
| 11192 | 10638 | if (prong_info.is_inline) { |
| ... | ... | @@ -11246,11 +10692,11 @@ fn finishSwitchBr( |
| 11246 | 10692 | any_analyze_body = true; // always an integer range, always needs analysis |
| 11247 | 10693 | |
| 11248 | 10694 | if (prong_info.is_inline) { |
| 11249 | var item = sema.resolveConstDefinedValue(block, .unneeded, range_ref[0], undefined) catch unreachable; | |
| 11250 | const item_last = sema.resolveConstDefinedValue(block, .unneeded, range_ref[1], undefined) catch unreachable; | |
| 10695 | var item = sema.resolveValue(range_ref[0]).?; | |
| 10696 | const item_last = sema.resolveValue(range_ref[1]).?; | |
| 11251 | 10697 | |
| 11252 | if (try item.getUnsignedIntSema(pt)) |first_int| { | |
| 11253 | if (try item_last.getUnsignedIntSema(pt)) |last_int| { | |
| 10698 | if (item.getUnsignedInt(zcu)) |first_int| { | |
| 10699 | if (item_last.getUnsignedInt(zcu)) |last_int| { | |
| 11254 | 10700 | if (std.math.cast(u32, last_int - first_int)) |range_len| { |
| 11255 | 10701 | try branch_hints.ensureUnusedCapacity(gpa, range_len); |
| 11256 | 10702 | } |
| ... | ... | @@ -11259,7 +10705,6 @@ fn finishSwitchBr( |
| 11259 | 10705 | |
| 11260 | 10706 | var prev_result_overflowed = false; |
| 11261 | 10707 | while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ |
| 11262 | // Previous validation has resolved any possible lazy values. | |
| 11263 | 10708 | const int_val: Value, const int_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { |
| 11264 | 10709 | .int => .{ item, operand_ty }, |
| 11265 | 10710 | .@"enum" => b: { |
| ... | ... | @@ -11426,7 +10871,7 @@ fn finishSwitchBr( |
| 11426 | 10871 | |
| 11427 | 10872 | const item_ref: Air.Inst.Ref = .fromValue(item_val); |
| 11428 | 10873 | |
| 11429 | const analyze_body = sema.wantSwitchProngBodyAnalysis(block, item_ref, operand_ty, union_originally, err_set, false); | |
| 10874 | const analyze_body = sema.wantSwitchProngBodyAnalysis(item_ref, operand_ty, union_originally, err_set, false); | |
| 11430 | 10875 | |
| 11431 | 10876 | if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); |
| 11432 | 10877 | emit_bb = true; |
| ... | ... | @@ -11896,72 +11341,69 @@ fn validateSwitchBlock( |
| 11896 | 11341 | try sema.inst_map.ensureSpaceForInstructions(gpa, &.{tag_capture_inst}); |
| 11897 | 11342 | } |
| 11898 | 11343 | |
| 11899 | const operand_ty: Type, const item_ty: Type = check_operand: { | |
| 11900 | const operand_ty = operand_ty: { | |
| 11901 | const raw_operand_ty = sema.typeOf(raw_operand); | |
| 11902 | if (operand_is_ref) { | |
| 11903 | try sema.checkPtrType(block, operand_src, raw_operand_ty, false); | |
| 11904 | break :operand_ty raw_operand_ty.childType(zcu); | |
| 11905 | } | |
| 11906 | break :operand_ty raw_operand_ty; | |
| 11907 | }; | |
| 11908 | ||
| 11909 | const item_ty: Type = item_ty: { | |
| 11910 | switch (operand_ty.zigTypeTag(zcu)) { | |
| 11911 | .@"enum", | |
| 11912 | .error_set, | |
| 11913 | .int, | |
| 11914 | .comptime_int, | |
| 11915 | .type, | |
| 11916 | .enum_literal, | |
| 11917 | .@"fn", | |
| 11918 | .bool, | |
| 11919 | .void, | |
| 11920 | => break :item_ty operand_ty, | |
| 11344 | const operand_ty = operand_ty: { | |
| 11345 | const raw_operand_ty = sema.typeOf(raw_operand); | |
| 11346 | if (operand_is_ref) { | |
| 11347 | try sema.checkPtrType(block, operand_src, raw_operand_ty, false); | |
| 11348 | const child_ty = raw_operand_ty.childType(zcu); | |
| 11349 | try sema.ensureLayoutResolved(child_ty, operand_src, .ptr_access); | |
| 11350 | break :operand_ty child_ty; | |
| 11351 | } | |
| 11352 | break :operand_ty raw_operand_ty; | |
| 11353 | }; | |
| 11921 | 11354 | |
| 11922 | .@"union" => { | |
| 11923 | try operand_ty.resolveFields(pt); | |
| 11924 | const enum_ty = operand_ty.unionTagType(zcu) orelse { | |
| 11925 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 11926 | const msg = try sema.errMsg(operand_src, "switch on union with no attached enum", .{}); | |
| 11927 | errdefer msg.destroy(sema.gpa); | |
| 11928 | if (operand_ty.srcLocOrNull(zcu)) |union_src| { | |
| 11929 | try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{}); | |
| 11930 | } | |
| 11931 | break :msg msg; | |
| 11932 | }); | |
| 11933 | }; | |
| 11934 | break :item_ty enum_ty; | |
| 11935 | }, | |
| 11355 | const item_ty: Type = item_ty: { | |
| 11356 | switch (operand_ty.zigTypeTag(zcu)) { | |
| 11357 | .@"enum", | |
| 11358 | .error_set, | |
| 11359 | .int, | |
| 11360 | .comptime_int, | |
| 11361 | .type, | |
| 11362 | .enum_literal, | |
| 11363 | .@"fn", | |
| 11364 | .bool, | |
| 11365 | .void, | |
| 11366 | => break :item_ty operand_ty, | |
| 11936 | 11367 | |
| 11937 | .pointer => { | |
| 11938 | if (!operand_ty.isSlice(zcu)) { | |
| 11939 | break :item_ty operand_ty; | |
| 11940 | } | |
| 11941 | }, | |
| 11368 | .@"union" => { | |
| 11369 | const enum_ty = operand_ty.unionTagType(zcu) orelse { | |
| 11370 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 11371 | const msg = try sema.errMsg(operand_src, "switch on union with no attached enum", .{}); | |
| 11372 | errdefer msg.destroy(sema.gpa); | |
| 11373 | if (operand_ty.srcLocOrNull(zcu)) |union_src| { | |
| 11374 | try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{}); | |
| 11375 | } | |
| 11376 | break :msg msg; | |
| 11377 | }); | |
| 11378 | }; | |
| 11379 | break :item_ty enum_ty; | |
| 11380 | }, | |
| 11942 | 11381 | |
| 11943 | else => {}, | |
| 11944 | } | |
| 11945 | return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); | |
| 11946 | }; | |
| 11382 | .pointer => { | |
| 11383 | if (!operand_ty.isSlice(zcu)) { | |
| 11384 | break :item_ty operand_ty; | |
| 11385 | } | |
| 11386 | }, | |
| 11947 | 11387 | |
| 11948 | if (zir_switch.has_continue and !block.isComptime()) { | |
| 11949 | if (try operand_ty.comptimeOnlySema(pt)) { | |
| 11950 | // Even if the operand is comptime-known, this `switch` is runtime. | |
| 11951 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 11952 | const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)}); | |
| 11953 | errdefer msg.destroy(gpa); | |
| 11954 | try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{}); | |
| 11955 | try sema.explainWhyTypeIsComptime(msg, operand_src, operand_ty); | |
| 11956 | break :msg msg; | |
| 11957 | }); | |
| 11958 | } | |
| 11959 | try sema.validateRuntimeValue(block, operand_src, raw_operand); | |
| 11388 | else => {}, | |
| 11960 | 11389 | } |
| 11961 | ||
| 11962 | break :check_operand .{ operand_ty, item_ty }; | |
| 11390 | return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); | |
| 11963 | 11391 | }; |
| 11964 | 11392 | |
| 11393 | if (zir_switch.has_continue and !block.isComptime()) { | |
| 11394 | if (operand_ty.comptimeOnly(zcu)) { | |
| 11395 | // Even if the operand is comptime-known, this `switch` is runtime. | |
| 11396 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 11397 | const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)}); | |
| 11398 | errdefer msg.destroy(gpa); | |
| 11399 | try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{}); | |
| 11400 | try sema.explainWhyTypeIsComptime(msg, operand_src, operand_ty); | |
| 11401 | break :msg msg; | |
| 11402 | }); | |
| 11403 | } | |
| 11404 | try sema.validateRuntimeValue(block, operand_src, raw_operand); | |
| 11405 | } | |
| 11406 | ||
| 11965 | 11407 | const has_else = zir_switch.else_case != null; |
| 11966 | 11408 | const has_under = zir_switch.has_under; |
| 11967 | 11409 | |
| ... | ... | @@ -12305,7 +11747,7 @@ fn resolveSwitchBlock( |
| 12305 | 11747 | child_block: *Block, |
| 12306 | 11748 | operand: SwitchOperand, |
| 12307 | 11749 | raw_operand_ty: Type, |
| 12308 | maybe_lazy_cond_val: Value, | |
| 11750 | cond_val: Value, | |
| 12309 | 11751 | merges: *Block.Merges, |
| 12310 | 11752 | switch_inst: Zir.Inst.Index, |
| 12311 | 11753 | zir_switch: *const Zir.UnwrappedSwitchBlock, |
| ... | ... | @@ -12325,9 +11767,6 @@ fn resolveSwitchBlock( |
| 12325 | 11767 | const err_set = item_ty.zigTypeTag(zcu) == .error_set; |
| 12326 | 11768 | |
| 12327 | 11769 | const cond_ref = operand.simple.cond; |
| 12328 | // We have to resolve lazy values to ensure that comparisons with switch | |
| 12329 | // prong items don't produce false negatives. | |
| 12330 | const cond_val = try sema.resolveLazyValue(maybe_lazy_cond_val); | |
| 12331 | 11770 | |
| 12332 | 11771 | const case_vals = validated_switch.case_vals; |
| 12333 | 11772 | var case_val_idx: usize = 0; |
| ... | ... | @@ -12365,7 +11804,7 @@ fn resolveSwitchBlock( |
| 12365 | 11804 | }; |
| 12366 | 11805 | continue; |
| 12367 | 11806 | } |
| 12368 | const item_val = sema.resolveConstDefinedValue(child_block, .unneeded, item_ref, undefined) catch unreachable; | |
| 11807 | const item_val = sema.resolveValue(item_ref).?; | |
| 12369 | 11808 | if (cond_val.eql(item_val, item_ty, zcu)) { |
| 12370 | 11809 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, prong_body, cond_ref); |
| 12371 | 11810 | if (union_originally and operand_ty.unionFieldType(item_val, zcu).?.isNoReturn(zcu)) { |
| ... | ... | @@ -12398,8 +11837,8 @@ fn resolveSwitchBlock( |
| 12398 | 11837 | } |
| 12399 | 11838 | } |
| 12400 | 11839 | for (range_refs) |range_ref| { |
| 12401 | const first_val = sema.resolveConstDefinedValue(child_block, .unneeded, range_ref[0], undefined) catch unreachable; | |
| 12402 | const last_val = sema.resolveConstDefinedValue(child_block, .unneeded, range_ref[1], undefined) catch unreachable; | |
| 11840 | const first_val = sema.resolveValue(range_ref[0]).?; | |
| 11841 | const last_val = sema.resolveValue(range_ref[1]).?; | |
| 12403 | 11842 | if ((try sema.compareAll(cond_val, .gte, first_val, item_ty)) and |
| 12404 | 11843 | (try sema.compareAll(cond_val, .lte, last_val, item_ty))) |
| 12405 | 11844 | { |
| ... | ... | @@ -12608,7 +12047,6 @@ fn resolveSwitchProng( |
| 12608 | 12047 | |
| 12609 | 12048 | fn wantSwitchProngBodyAnalysis( |
| 12610 | 12049 | sema: *Sema, |
| 12611 | block: *Block, | |
| 12612 | 12050 | item_ref: Air.Inst.Ref, |
| 12613 | 12051 | operand_ty: Type, |
| 12614 | 12052 | union_originally: bool, |
| ... | ... | @@ -12617,16 +12055,14 @@ fn wantSwitchProngBodyAnalysis( |
| 12617 | 12055 | ) bool { |
| 12618 | 12056 | const zcu = sema.pt.zcu; |
| 12619 | 12057 | if (union_originally) { |
| 12620 | const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; | |
| 12621 | const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable; | |
| 12058 | const item_val = sema.resolveValue(item_ref).?; | |
| 12622 | 12059 | const field_ty = operand_ty.unionFieldType(item_val, zcu).?; |
| 12623 | 12060 | if (field_ty.isNoReturn(zcu)) return false; |
| 12624 | 12061 | } |
| 12625 | 12062 | if (err_set and prong_is_comptime_unreach) { |
| 12626 | const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; | |
| 12627 | const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable; | |
| 12063 | const item_val = sema.resolveValue(item_ref).?; | |
| 12628 | 12064 | const err_name = item_val.getErrorName(zcu).unwrap().?; |
| 12629 | if (!Type.errorSetHasFieldIp(&zcu.intern_pool, operand_ty.toIntern(), err_name)) return false; | |
| 12065 | if (!operand_ty.errorSetHasField(err_name, zcu)) return false; | |
| 12630 | 12066 | } |
| 12631 | 12067 | return true; |
| 12632 | 12068 | } |
| ... | ... | @@ -12772,8 +12208,7 @@ fn analyzeSwitchTagCapture( |
| 12772 | 12208 | .item_refs => |refs| if (refs.len == 1) return refs[0], |
| 12773 | 12209 | .special => {}, |
| 12774 | 12210 | } |
| 12775 | const tag_ty = operand_ty.unionTagType(zcu).?; | |
| 12776 | return sema.unionToTag(case_block, tag_ty, operand_val, tag_capture_src); | |
| 12211 | return sema.unionToTag(case_block, operand_val); | |
| 12777 | 12212 | } |
| 12778 | 12213 | |
| 12779 | 12214 | fn analyzeSwitchPayloadCapture( |
| ... | ... | @@ -12800,14 +12235,14 @@ fn analyzeSwitchPayloadCapture( |
| 12800 | 12235 | const switch_node_offset = operand_src.offset.node_offset_switch_operand; |
| 12801 | 12236 | |
| 12802 | 12237 | if (kind == .inline_ref) { |
| 12803 | const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, kind.inline_ref, undefined) catch unreachable; | |
| 12238 | const item_val = sema.resolveValue(kind.inline_ref).?; | |
| 12804 | 12239 | if (operand_ty.zigTypeTag(zcu) == .@"union") { |
| 12805 | 12240 | const field_index: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, zcu).?); |
| 12806 | 12241 | const union_obj = zcu.typeToUnion(operand_ty).?; |
| 12807 | 12242 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 12808 | 12243 | if (capture_by_ref) { |
| 12809 | 12244 | const operand_ptr_info = sema.typeOf(operand_ptr).ptrInfo(zcu); |
| 12810 | const ptr_field_ty = try pt.ptrTypeSema(.{ | |
| 12245 | const ptr_field_ty = try pt.ptrType(.{ | |
| 12811 | 12246 | .child = field_ty.toIntern(), |
| 12812 | 12247 | .flags = .{ |
| 12813 | 12248 | .is_const = operand_ptr_info.flags.is_const, |
| ... | ... | @@ -12821,10 +12256,11 @@ fn analyzeSwitchPayloadCapture( |
| 12821 | 12256 | const tag_and_val = ip.indexToKey(union_val.toIntern()).un; |
| 12822 | 12257 | return .fromIntern(tag_and_val.val); |
| 12823 | 12258 | } |
| 12259 | if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 12824 | 12260 | return case_block.addStructFieldVal(operand_val, field_index, field_ty); |
| 12825 | 12261 | } |
| 12826 | 12262 | } else if (capture_by_ref) { |
| 12827 | return sema.uavRef(item_val.toIntern()); | |
| 12263 | return sema.uavRef(item_val); | |
| 12828 | 12264 | } else { |
| 12829 | 12265 | return kind.inline_ref; |
| 12830 | 12266 | } |
| ... | ... | @@ -12850,14 +12286,14 @@ fn analyzeSwitchPayloadCapture( |
| 12850 | 12286 | const case_vals = kind.item_refs; |
| 12851 | 12287 | |
| 12852 | 12288 | const union_obj = zcu.typeToUnion(operand_ty).?; |
| 12853 | const first_item_val = sema.resolveConstDefinedValue(case_block, .unneeded, case_vals[0], undefined) catch unreachable; | |
| 12289 | const first_item_val = sema.resolveValue(case_vals[0]).?; | |
| 12854 | 12290 | |
| 12855 | 12291 | const first_field_index: u32 = zcu.unionTagFieldIndex(union_obj, first_item_val).?; |
| 12856 | 12292 | const first_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[first_field_index]); |
| 12857 | 12293 | |
| 12858 | 12294 | const field_indices = try sema.arena.alloc(u32, case_vals.len); |
| 12859 | 12295 | for (case_vals, field_indices) |item, *field_idx| { |
| 12860 | const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, item, undefined) catch unreachable; | |
| 12296 | const item_val = sema.resolveValue(item).?; | |
| 12861 | 12297 | field_idx.* = zcu.unionTagFieldIndex(union_obj, item_val).?; |
| 12862 | 12298 | } |
| 12863 | 12299 | |
| ... | ... | @@ -12906,23 +12342,14 @@ fn analyzeSwitchPayloadCapture( |
| 12906 | 12342 | |
| 12907 | 12343 | // By-reference captures have some further restrictions which make them easier to emit |
| 12908 | 12344 | if (capture_by_ref) { |
| 12909 | const operand_ptr_info = sema.typeOf(operand_ptr).ptrInfo(zcu); | |
| 12345 | const operand_ptr_ty = sema.typeOf(operand_ptr); | |
| 12910 | 12346 | const capture_ptr_ty = resolve: { |
| 12911 | 12347 | // By-ref captures of hetereogeneous types are only allowed if all field |
| 12912 | 12348 | // pointer types are peer resolvable to each other. |
| 12913 | 12349 | // We need values to run PTR on, so make a bunch of undef constants. |
| 12914 | 12350 | const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len); |
| 12915 | for (field_indices, dummy_captures) |field_idx, *dummy| { | |
| 12916 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 12917 | const field_ptr_ty = try pt.ptrTypeSema(.{ | |
| 12918 | .child = field_ty.toIntern(), | |
| 12919 | .flags = .{ | |
| 12920 | .is_const = operand_ptr_info.flags.is_const, | |
| 12921 | .is_volatile = operand_ptr_info.flags.is_volatile, | |
| 12922 | .address_space = operand_ptr_info.flags.address_space, | |
| 12923 | .alignment = union_obj.fieldAlign(ip, field_idx), | |
| 12924 | }, | |
| 12925 | }); | |
| 12351 | for (field_indices, dummy_captures) |field_index, *dummy| { | |
| 12352 | const field_ptr_ty = try operand_ptr_ty.fieldPtrType(field_index, pt); | |
| 12926 | 12353 | dummy.* = try pt.undefRef(field_ptr_ty); |
| 12927 | 12354 | } |
| 12928 | 12355 | const case_srcs = try sema.arena.alloc(?LazySrcLoc, case_vals.len); |
| ... | ... | @@ -12963,6 +12390,8 @@ fn analyzeSwitchPayloadCapture( |
| 12963 | 12390 | return case_block.addStructFieldPtr(operand_ptr, first_field_index, capture_ptr_ty); |
| 12964 | 12391 | } |
| 12965 | 12392 | |
| 12393 | if (try capture_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 12394 | ||
| 12966 | 12395 | if (try sema.resolveDefinedValue(case_block, operand_src, operand_val)) |operand_val_val| { |
| 12967 | 12396 | if (operand_val_val.isUndef(zcu)) return pt.undefRef(capture_ty); |
| 12968 | 12397 | const union_val = ip.indexToKey(operand_val_val.toIntern()).un; |
| ... | ... | @@ -13119,7 +12548,7 @@ fn analyzeSwitchPayloadCapture( |
| 13119 | 12548 | try sema.air_instructions.append(sema.gpa, .{ |
| 13120 | 12549 | .tag = .get_union_tag, |
| 13121 | 12550 | .data = .{ .ty_op = .{ |
| 13122 | .ty = .fromIntern(union_obj.enum_tag_ty), | |
| 12551 | .ty = .fromIntern(union_obj.enum_tag_type), | |
| 13123 | 12552 | .operand = operand_val, |
| 13124 | 12553 | } }, |
| 13125 | 12554 | }); |
| ... | ... | @@ -13146,7 +12575,7 @@ fn analyzeSwitchPayloadCapture( |
| 13146 | 12575 | |
| 13147 | 12576 | const case_vals = kind.item_refs; |
| 13148 | 12577 | if (case_vals.len == 1) { |
| 13149 | const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, case_vals[0], undefined) catch unreachable; | |
| 12578 | const item_val = sema.resolveValue(case_vals[0]).?; | |
| 13150 | 12579 | const item_ty = try pt.singleErrorSetType(item_val.getErrorName(zcu).unwrap().?); |
| 13151 | 12580 | return sema.bitCast(case_block, item_ty, .fromValue(item_val), operand_src, null); |
| 13152 | 12581 | } |
| ... | ... | @@ -13154,7 +12583,7 @@ fn analyzeSwitchPayloadCapture( |
| 13154 | 12583 | var names: InferredErrorSet.NameMap = .{}; |
| 13155 | 12584 | try names.ensureUnusedCapacity(sema.arena, case_vals.len); |
| 13156 | 12585 | for (case_vals) |err| { |
| 13157 | const err_val = sema.resolveConstDefinedValue(case_block, .unneeded, err, undefined) catch unreachable; | |
| 12586 | const err_val = sema.resolveValue(err).?; | |
| 13158 | 12587 | names.putAssumeCapacityNoClobber(err_val.getErrorName(zcu).unwrap().?, {}); |
| 13159 | 12588 | } |
| 13160 | 12589 | const error_ty = try pt.errorSetFromUnsortedNames(names.keys()); |
| ... | ... | @@ -13249,7 +12678,7 @@ fn resolveSwitchItem( |
| 13249 | 12678 | // We allow prongs with errors which are not part of the error set |
| 13250 | 12679 | // being switched on if their prong body is `=> comptime unreachable,`. |
| 13251 | 12680 | switch (try sema.coerceInMemoryAllowedErrorSets(block, item_ty, uncoerced_ty, item_src, item_src)) { |
| 13252 | .ok => if (try sema.resolveValue(uncoerced)) |uncoerced_val| { | |
| 12681 | .ok => if (sema.resolveValue(uncoerced)) |uncoerced_val| { | |
| 13253 | 12682 | break :item_ref try sema.coerceInMemory(uncoerced_val, item_ty); |
| 13254 | 12683 | }, |
| 13255 | 12684 | .missing_error => if (prong_is_comptime_unreach) { |
| ... | ... | @@ -13261,17 +12690,8 @@ fn resolveSwitchItem( |
| 13261 | 12690 | } |
| 13262 | 12691 | break :item_ref try sema.coerce(block, item_ty, uncoerced, item_src); |
| 13263 | 12692 | }; |
| 13264 | const maybe_lazy = try sema.resolveConstDefinedValue(block, item_src, item_ref, .{ .simple = .switch_item }); | |
| 13265 | ||
| 13266 | // We have to resolve lazy values here to avoid false negatives when detecting | |
| 13267 | // duplicate items and comparing items to a comptime-known switch operand. | |
| 13268 | ||
| 13269 | const val = try sema.resolveLazyValue(maybe_lazy); | |
| 13270 | const ref: Air.Inst.Ref = if (val.toIntern() == maybe_lazy.toIntern()) | |
| 13271 | item_ref | |
| 13272 | else | |
| 13273 | .fromValue(val); | |
| 13274 | return .{ .{ .ref = ref, .val = val }, end }; | |
| 12693 | const val = try sema.resolveConstDefinedValue(block, item_src, item_ref, .{ .simple = .switch_item }); | |
| 12694 | return .{ .{ .ref = item_ref, .val = val }, end }; | |
| 13275 | 12695 | } |
| 13276 | 12696 | |
| 13277 | 12697 | fn validateSwitchItemOrRange( |
| ... | ... | @@ -13422,7 +12842,7 @@ fn maybeErrorUnwrap( |
| 13422 | 12842 | }, |
| 13423 | 12843 | .panic => { |
| 13424 | 12844 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 13425 | const msg_inst = try sema.resolveInst(inst_data.operand); | |
| 12845 | const msg_inst = sema.resolveInst(inst_data.operand); | |
| 13426 | 12846 | |
| 13427 | 12847 | const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call"); |
| 13428 | 12848 | const args: [2]Air.Inst.Ref = .{ msg_inst, .null_value }; |
| ... | ... | @@ -13445,7 +12865,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind |
| 13445 | 12865 | if (sema.code.instructions.items(.tag)[@intFromEnum(index)] != .is_non_err) return; |
| 13446 | 12866 | |
| 13447 | 12867 | const err_inst_data = sema.code.instructions.items(.data)[@intFromEnum(index)].un_node; |
| 13448 | const err_operand = try sema.resolveInst(err_inst_data.operand); | |
| 12868 | const err_operand = sema.resolveInst(err_inst_data.operand); | |
| 13449 | 12869 | const operand_ty = sema.typeOf(err_operand); |
| 13450 | 12870 | if (operand_ty.zigTypeTag(zcu) == .error_set) { |
| 13451 | 12871 | try sema.maybeErrorUnwrapComptime(block, body, err_operand); |
| ... | ... | @@ -13488,7 +12908,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13488 | 12908 | const name_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 13489 | 12909 | const ty = try sema.resolveType(block, ty_src, extra.lhs); |
| 13490 | 12910 | const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{ .simple = .field_name }); |
| 13491 | try ty.resolveFields(pt); | |
| 12911 | try sema.ensureLayoutResolved(ty, ty_src, .field_queried); | |
| 13492 | 12912 | const ip = &zcu.intern_pool; |
| 13493 | 12913 | |
| 13494 | 12914 | const has_field = hf: { |
| ... | ... | @@ -13510,7 +12930,8 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13510 | 12930 | }, |
| 13511 | 12931 | .union_type => { |
| 13512 | 12932 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 13513 | break :hf union_type.loadTagType(ip).nameIndex(ip, field_name) != null; | |
| 12933 | const enum_type = ip.loadEnumType(union_type.enum_tag_type); | |
| 12934 | break :hf enum_type.nameIndex(ip, field_name) != null; | |
| 13514 | 12935 | }, |
| 13515 | 12936 | .enum_type => { |
| 13516 | 12937 | break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null; |
| ... | ... | @@ -13568,17 +12989,18 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13568 | 12989 | const file = zcu.fileByIndex(file_index); |
| 13569 | 12990 | switch (file.getMode()) { |
| 13570 | 12991 | .zig => { |
| 13571 | try pt.ensureFileAnalyzed(file_index); | |
| 13572 | const ty = zcu.fileRootType(file_index); | |
| 13573 | try sema.declareDependency(.{ .interned = ty }); | |
| 12992 | try pt.ensureFilePopulated(file_index); | |
| 12993 | const ty: Type = .fromInterned(zcu.fileRootType(file_index)); | |
| 13574 | 12994 | try sema.addTypeReferenceEntry(operand_src, ty); |
| 13575 | return Air.internedToRef(ty); | |
| 12995 | // No need for `ensureNamespaceUpToDate`, because `Zcu.PerThread.updateFileNamespace` | |
| 12996 | // already made sure that all root file structs have up-to-date namespaces. | |
| 12997 | return .fromType(ty); | |
| 13576 | 12998 | }, |
| 13577 | 12999 | .zon => { |
| 13578 | 13000 | const res_ty: InternPool.Index = b: { |
| 13579 | 13001 | if (extra.res_ty == .none) break :b .none; |
| 13580 | const res_ty_inst = try sema.resolveInst(extra.res_ty); | |
| 13581 | const res_ty = try sema.analyzeAsType(block, operand_src, res_ty_inst); | |
| 13002 | const res_ty_inst = sema.resolveInst(extra.res_ty); | |
| 13003 | const res_ty = try sema.analyzeAsType(block, operand_src, .type, res_ty_inst); | |
| 13582 | 13004 | if (res_ty.isGenericPoison()) break :b .none; |
| 13583 | 13005 | break :b res_ty.toIntern(); |
| 13584 | 13006 | }; |
| ... | ... | @@ -13665,8 +13087,8 @@ fn zirShl( |
| 13665 | 13087 | const zcu = pt.zcu; |
| 13666 | 13088 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 13667 | 13089 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 13668 | const lhs = try sema.resolveInst(extra.lhs); | |
| 13669 | const rhs = try sema.resolveInst(extra.rhs); | |
| 13090 | const lhs = sema.resolveInst(extra.lhs); | |
| 13091 | const rhs = sema.resolveInst(extra.rhs); | |
| 13670 | 13092 | const lhs_ty = sema.typeOf(lhs); |
| 13671 | 13093 | const rhs_ty = sema.typeOf(rhs); |
| 13672 | 13094 | |
| ... | ... | @@ -13692,8 +13114,8 @@ fn zirShl( |
| 13692 | 13114 | // we already know `scalar_rhs_ty` is valid for `.shl` -- we only need to validate for `.shl_sat`. |
| 13693 | 13115 | if (air_tag == .shl_sat) _ = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); |
| 13694 | 13116 | |
| 13695 | const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs); | |
| 13696 | const maybe_rhs_val = try sema.resolveValueResolveLazy(rhs); | |
| 13117 | const maybe_lhs_val = sema.resolveValue(lhs); | |
| 13118 | const maybe_rhs_val = sema.resolveValue(rhs); | |
| 13697 | 13119 | |
| 13698 | 13120 | const runtime_src = rs: { |
| 13699 | 13121 | if (maybe_rhs_val) |rhs_val| { |
| ... | ... | @@ -13713,11 +13135,11 @@ fn zirShl( |
| 13713 | 13135 | const bits = scalar_ty.intInfo(zcu).bits; |
| 13714 | 13136 | switch (rhs_ty.zigTypeTag(zcu)) { |
| 13715 | 13137 | .int, .comptime_int => { |
| 13716 | switch (try rhs_val.orderAgainstZeroSema(pt)) { | |
| 13138 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 13717 | 13139 | .gt => { |
| 13718 | 13140 | if (air_tag != .shl_sat) { |
| 13719 | 13141 | var rhs_space: Value.BigIntSpace = undefined; |
| 13720 | const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); | |
| 13142 | const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu); | |
| 13721 | 13143 | if (rhs_bigint.orderAgainstScalar(bits) != .lt) { |
| 13722 | 13144 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); |
| 13723 | 13145 | } |
| ... | ... | @@ -13736,11 +13158,11 @@ fn zirShl( |
| 13736 | 13158 | .shl, .shl_exact => return sema.failWithUseOfUndef(block, rhs_src, elem_idx), |
| 13737 | 13159 | else => unreachable, |
| 13738 | 13160 | }; |
| 13739 | switch (try rhs_elem.orderAgainstZeroSema(pt)) { | |
| 13161 | switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) { | |
| 13740 | 13162 | .gt => { |
| 13741 | 13163 | if (air_tag != .shl_sat) { |
| 13742 | 13164 | var rhs_elem_space: Value.BigIntSpace = undefined; |
| 13743 | const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); | |
| 13165 | const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu); | |
| 13744 | 13166 | if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { |
| 13745 | 13167 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); |
| 13746 | 13168 | } |
| ... | ... | @@ -13769,7 +13191,7 @@ fn zirShl( |
| 13769 | 13191 | .shl, .shl_exact => try sema.checkAllScalarsDefined(block, lhs_src, lhs_val), |
| 13770 | 13192 | else => unreachable, |
| 13771 | 13193 | } |
| 13772 | if (try lhs_val.compareAllWithZeroSema(.eq, pt)) return lhs; | |
| 13194 | if (lhs_val.compareAllWithZero(.eq, zcu)) return lhs; | |
| 13773 | 13195 | } |
| 13774 | 13196 | } |
| 13775 | 13197 | break :rs rhs_src; |
| ... | ... | @@ -13785,13 +13207,13 @@ fn zirShl( |
| 13785 | 13207 | const rt_rhs_scalar_ty = try pt.smallestUnsignedInt(bit_count); |
| 13786 | 13208 | if (!rhs_ty.isVector(zcu)) break :rt_rhs try pt.intValue( |
| 13787 | 13209 | rt_rhs_scalar_ty, |
| 13788 | @min(try rhs_val.getUnsignedIntSema(pt) orelse bit_count, bit_count), | |
| 13210 | @min(rhs_val.getUnsignedInt(zcu) orelse bit_count, bit_count), | |
| 13789 | 13211 | ); |
| 13790 | 13212 | const rhs_len = rhs_ty.vectorLen(zcu); |
| 13791 | 13213 | const rhs_elems = try sema.arena.alloc(InternPool.Index, rhs_len); |
| 13792 | 13214 | for (rhs_elems, 0..) |*rhs_elem, i| rhs_elem.* = (try pt.intValue( |
| 13793 | 13215 | rt_rhs_scalar_ty, |
| 13794 | @min(try (try rhs_val.elemValue(pt, i)).getUnsignedIntSema(pt) orelse bit_count, bit_count), | |
| 13216 | @min((try rhs_val.elemValue(pt, i)).getUnsignedInt(zcu) orelse bit_count, bit_count), | |
| 13795 | 13217 | )).toIntern(); |
| 13796 | 13218 | break :rt_rhs try pt.aggregateValue(try pt.vectorType(.{ |
| 13797 | 13219 | .len = rhs_len, |
| ... | ... | @@ -13855,8 +13277,8 @@ fn zirShr( |
| 13855 | 13277 | const zcu = pt.zcu; |
| 13856 | 13278 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 13857 | 13279 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 13858 | const lhs = try sema.resolveInst(extra.lhs); | |
| 13859 | const rhs = try sema.resolveInst(extra.rhs); | |
| 13280 | const lhs = sema.resolveInst(extra.lhs); | |
| 13281 | const rhs = sema.resolveInst(extra.rhs); | |
| 13860 | 13282 | const lhs_ty = sema.typeOf(lhs); |
| 13861 | 13283 | const rhs_ty = sema.typeOf(rhs); |
| 13862 | 13284 | |
| ... | ... | @@ -13875,8 +13297,8 @@ fn zirShr( |
| 13875 | 13297 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 13876 | 13298 | const scalar_ty = lhs_ty.scalarType(zcu); |
| 13877 | 13299 | |
| 13878 | const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs); | |
| 13879 | const maybe_rhs_val = try sema.resolveValueResolveLazy(rhs); | |
| 13300 | const maybe_lhs_val = sema.resolveValue(lhs); | |
| 13301 | const maybe_rhs_val = sema.resolveValue(rhs); | |
| 13880 | 13302 | |
| 13881 | 13303 | const runtime_src = rs: { |
| 13882 | 13304 | if (maybe_rhs_val) |rhs_val| { |
| ... | ... | @@ -13893,10 +13315,10 @@ fn zirShr( |
| 13893 | 13315 | const bits = scalar_ty.intInfo(zcu).bits; |
| 13894 | 13316 | switch (rhs_ty.zigTypeTag(zcu)) { |
| 13895 | 13317 | .int, .comptime_int => { |
| 13896 | switch (try rhs_val.orderAgainstZeroSema(pt)) { | |
| 13318 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 13897 | 13319 | .gt => { |
| 13898 | 13320 | var rhs_space: Value.BigIntSpace = undefined; |
| 13899 | const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); | |
| 13321 | const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu); | |
| 13900 | 13322 | if (rhs_bigint.orderAgainstScalar(bits) != .lt) { |
| 13901 | 13323 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); |
| 13902 | 13324 | } |
| ... | ... | @@ -13912,10 +13334,10 @@ fn zirShr( |
| 13912 | 13334 | if (rhs_elem.isUndef(zcu)) { |
| 13913 | 13335 | return sema.failWithUseOfUndef(block, rhs_src, elem_idx); |
| 13914 | 13336 | } |
| 13915 | switch (try rhs_elem.orderAgainstZeroSema(pt)) { | |
| 13337 | switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) { | |
| 13916 | 13338 | .gt => { |
| 13917 | 13339 | var rhs_elem_space: Value.BigIntSpace = undefined; |
| 13918 | const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); | |
| 13340 | const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu); | |
| 13919 | 13341 | if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { |
| 13920 | 13342 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); |
| 13921 | 13343 | } |
| ... | ... | @@ -13936,7 +13358,7 @@ fn zirShr( |
| 13936 | 13358 | } |
| 13937 | 13359 | if (maybe_lhs_val) |lhs_val| { |
| 13938 | 13360 | try sema.checkAllScalarsDefined(block, lhs_src, lhs_val); |
| 13939 | if (try lhs_val.compareAllWithZeroSema(.eq, pt)) return lhs; | |
| 13361 | if (lhs_val.compareAllWithZero(.eq, zcu)) return lhs; | |
| 13940 | 13362 | } |
| 13941 | 13363 | } |
| 13942 | 13364 | break :rs rhs_src; |
| ... | ... | @@ -13988,8 +13410,8 @@ fn zirBitwise( |
| 13988 | 13410 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 13989 | 13411 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 13990 | 13412 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 13991 | const lhs = try sema.resolveInst(extra.lhs); | |
| 13992 | const rhs = try sema.resolveInst(extra.rhs); | |
| 13413 | const lhs = sema.resolveInst(extra.lhs); | |
| 13414 | const rhs = sema.resolveInst(extra.rhs); | |
| 13993 | 13415 | const lhs_ty = sema.typeOf(lhs); |
| 13994 | 13416 | const rhs_ty = sema.typeOf(rhs); |
| 13995 | 13417 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| ... | ... | @@ -14011,8 +13433,8 @@ fn zirBitwise( |
| 14011 | 13433 | const runtime_src = runtime: { |
| 14012 | 13434 | // TODO: ask the linker what kind of relocations are available, and |
| 14013 | 13435 | // in some cases emit a Value that means "this decl's address AND'd with this operand". |
| 14014 | if (try sema.resolveValueResolveLazy(casted_lhs)) |lhs_val| { | |
| 14015 | if (try sema.resolveValueResolveLazy(casted_rhs)) |rhs_val| { | |
| 13436 | if (sema.resolveValue(casted_lhs)) |lhs_val| { | |
| 13437 | if (sema.resolveValue(casted_rhs)) |rhs_val| { | |
| 14016 | 13438 | const result_val = switch (air_tag) { |
| 14017 | 13439 | // zig fmt: off |
| 14018 | 13440 | .bit_and => try arith.bitwiseBin(sema, resolved_type, lhs_val, rhs_val, .@"and"), |
| ... | ... | @@ -14040,7 +13462,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14040 | 13462 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 14041 | 13463 | const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); |
| 14042 | 13464 | const src = block.nodeOffset(inst_data.src_node); |
| 14043 | const operand = try sema.resolveInst(inst_data.operand); | |
| 13465 | const operand = sema.resolveInst(inst_data.operand); | |
| 14044 | 13466 | const operand_ty = sema.typeOf(operand); |
| 14045 | 13467 | const scalar_ty = operand_ty.scalarType(zcu); |
| 14046 | 13468 | const scalar_tag = scalar_ty.zigTypeTag(zcu); |
| ... | ... | @@ -14058,7 +13480,7 @@ fn analyzeBitNot( |
| 14058 | 13480 | src: LazySrcLoc, |
| 14059 | 13481 | ) CompileError!Air.Inst.Ref { |
| 14060 | 13482 | const operand_ty = sema.typeOf(operand); |
| 14061 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 13483 | if (sema.resolveValue(operand)) |operand_val| { | |
| 14062 | 13484 | const result_val = try arith.bitwiseNot(sema, operand_ty, operand_val); |
| 14063 | 13485 | return Air.internedToRef(result_val.toIntern()); |
| 14064 | 13486 | } |
| ... | ... | @@ -14106,13 +13528,13 @@ fn analyzeTupleCat( |
| 14106 | 13528 | var i: u32 = 0; |
| 14107 | 13529 | while (i < lhs_len) : (i += 1) { |
| 14108 | 13530 | types[i] = lhs_ty.fieldType(i, zcu).toIntern(); |
| 14109 | const default_val = lhs_ty.structFieldDefaultValue(i, zcu); | |
| 14110 | values[i] = default_val.toIntern(); | |
| 14111 | 13531 | const operand_src = block.src(.{ .array_cat_lhs = .{ |
| 14112 | 13532 | .array_cat_offset = src_node, |
| 14113 | 13533 | .elem_index = i, |
| 14114 | 13534 | } }); |
| 14115 | if (default_val.toIntern() == .unreachable_value) { | |
| 13535 | if (lhs_ty.structFieldDefaultValue(i, zcu)) |default_val| { | |
| 13536 | values[i] = default_val.toIntern(); | |
| 13537 | } else { | |
| 14116 | 13538 | runtime_src = operand_src; |
| 14117 | 13539 | values[i] = .none; |
| 14118 | 13540 | } |
| ... | ... | @@ -14120,13 +13542,13 @@ fn analyzeTupleCat( |
| 14120 | 13542 | i = 0; |
| 14121 | 13543 | while (i < rhs_len) : (i += 1) { |
| 14122 | 13544 | types[i + lhs_len] = rhs_ty.fieldType(i, zcu).toIntern(); |
| 14123 | const default_val = rhs_ty.structFieldDefaultValue(i, zcu); | |
| 14124 | values[i + lhs_len] = default_val.toIntern(); | |
| 14125 | 13545 | const operand_src = block.src(.{ .array_cat_rhs = .{ |
| 14126 | 13546 | .array_cat_offset = src_node, |
| 14127 | 13547 | .elem_index = i, |
| 14128 | 13548 | } }); |
| 14129 | if (default_val.toIntern() == .unreachable_value) { | |
| 13549 | if (rhs_ty.structFieldDefaultValue(i, zcu)) |default_val| { | |
| 13550 | values[i + lhs_len] = default_val.toIntern(); | |
| 13551 | } else { | |
| 14130 | 13552 | runtime_src = operand_src; |
| 14131 | 13553 | values[i + lhs_len] = .none; |
| 14132 | 13554 | } |
| ... | ... | @@ -14168,8 +13590,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14168 | 13590 | const zcu = pt.zcu; |
| 14169 | 13591 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 14170 | 13592 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 14171 | const lhs = try sema.resolveInst(extra.lhs); | |
| 14172 | const rhs = try sema.resolveInst(extra.rhs); | |
| 13593 | const lhs = sema.resolveInst(extra.lhs); | |
| 13594 | const rhs = sema.resolveInst(extra.rhs); | |
| 14173 | 13595 | const lhs_ty = sema.typeOf(lhs); |
| 14174 | 13596 | const rhs_ty = sema.typeOf(rhs); |
| 14175 | 13597 | const src = block.nodeOffset(inst_data.src_node); |
| ... | ... | @@ -14263,12 +13685,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14263 | 13685 | }; |
| 14264 | 13686 | |
| 14265 | 13687 | const runtime_src = if (switch (lhs_ty.zigTypeTag(zcu)) { |
| 14266 | .array, .@"struct" => try sema.resolveValue(lhs), | |
| 13688 | .array, .@"struct" => sema.resolveValue(lhs), | |
| 14267 | 13689 | .pointer => try sema.resolveDefinedValue(block, lhs_src, lhs), |
| 14268 | 13690 | else => unreachable, |
| 14269 | 13691 | }) |lhs_val| rs: { |
| 14270 | 13692 | if (switch (rhs_ty.zigTypeTag(zcu)) { |
| 14271 | .array, .@"struct" => try sema.resolveValue(rhs), | |
| 13693 | .array, .@"struct" => sema.resolveValue(rhs), | |
| 14272 | 13694 | .pointer => try sema.resolveDefinedValue(block, rhs_src, rhs), |
| 14273 | 13695 | else => unreachable, |
| 14274 | 13696 | }) |rhs_val| { |
| ... | ... | @@ -14290,32 +13712,30 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14290 | 13712 | var elem_i: u32 = 0; |
| 14291 | 13713 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 14292 | 13714 | const lhs_elem_i = elem_i; |
| 14293 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else Value.@"unreachable"; | |
| 14294 | const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(pt, lhs_elem_i) else elem_default_val; | |
| 14295 | const elem_val_inst = Air.internedToRef(elem_val.toIntern()); | |
| 13715 | const elem_default_val: ?Value = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else null; | |
| 13716 | const elem_val = elem_default_val orelse try lhs_sub_val.elemValue(pt, lhs_elem_i); | |
| 14296 | 13717 | const operand_src = block.src(.{ .array_cat_lhs = .{ |
| 14297 | 13718 | .array_cat_offset = inst_data.src_node, |
| 14298 | 13719 | .elem_index = elem_i, |
| 14299 | 13720 | } }); |
| 14300 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); | |
| 14301 | const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); | |
| 13721 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, .fromValue(elem_val), operand_src); | |
| 13722 | const coerced_elem_val = sema.resolveValue(coerced_elem_val_inst).?; | |
| 14302 | 13723 | element_vals[elem_i] = coerced_elem_val.toIntern(); |
| 14303 | 13724 | } |
| 14304 | 13725 | while (elem_i < result_len) : (elem_i += 1) { |
| 14305 | 13726 | const rhs_elem_i = elem_i - lhs_len; |
| 14306 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else Value.@"unreachable"; | |
| 14307 | const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(pt, rhs_elem_i) else elem_default_val; | |
| 14308 | const elem_val_inst = Air.internedToRef(elem_val.toIntern()); | |
| 13727 | const elem_default_val: ?Value = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else null; | |
| 13728 | const elem_val = elem_default_val orelse try rhs_sub_val.elemValue(pt, rhs_elem_i); | |
| 14309 | 13729 | const operand_src = block.src(.{ .array_cat_rhs = .{ |
| 14310 | 13730 | .array_cat_offset = inst_data.src_node, |
| 14311 | 13731 | .elem_index = @intCast(rhs_elem_i), |
| 14312 | 13732 | } }); |
| 14313 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); | |
| 14314 | const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); | |
| 13733 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, .fromValue(elem_val), operand_src); | |
| 13734 | const coerced_elem_val = sema.resolveValue(coerced_elem_val_inst).?; | |
| 14315 | 13735 | element_vals[elem_i] = coerced_elem_val.toIntern(); |
| 14316 | 13736 | } |
| 14317 | 13737 | return sema.addConstantMaybeRef( |
| 14318 | (try pt.aggregateValue(result_ty, element_vals)).toIntern(), | |
| 13738 | try pt.aggregateValue(result_ty, element_vals), | |
| 14319 | 13739 | ptr_addrspace != null, |
| 14320 | 13740 | ); |
| 14321 | 13741 | } else break :rs rhs_src; |
| ... | ... | @@ -14324,18 +13744,18 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14324 | 13744 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 14325 | 13745 | |
| 14326 | 13746 | if (ptr_addrspace) |ptr_as| { |
| 14327 | const constant_alloc_ty = try pt.ptrTypeSema(.{ | |
| 13747 | const constant_alloc_ty = try pt.ptrType(.{ | |
| 14328 | 13748 | .child = result_ty.toIntern(), |
| 14329 | 13749 | .flags = .{ |
| 14330 | 13750 | .address_space = ptr_as, |
| 14331 | 13751 | .is_const = true, |
| 14332 | 13752 | }, |
| 14333 | 13753 | }); |
| 14334 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 13754 | const alloc_ty = try pt.ptrType(.{ | |
| 14335 | 13755 | .child = result_ty.toIntern(), |
| 14336 | 13756 | .flags = .{ .address_space = ptr_as }, |
| 14337 | 13757 | }); |
| 14338 | const elem_ptr_ty = try pt.ptrTypeSema(.{ | |
| 13758 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 14339 | 13759 | .child = resolved_elem_ty.toIntern(), |
| 14340 | 13760 | .flags = .{ .address_space = ptr_as }, |
| 14341 | 13761 | }); |
| ... | ... | @@ -14347,7 +13767,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14347 | 13767 | if (lhs_ty.zigTypeTag(zcu) == .pointer and |
| 14348 | 13768 | rhs_ty.zigTypeTag(zcu) == .pointer) |
| 14349 | 13769 | { |
| 14350 | const slice_ty = try pt.ptrTypeSema(.{ | |
| 13770 | const slice_ty = try pt.ptrType(.{ | |
| 14351 | 13771 | .child = resolved_elem_ty.toIntern(), |
| 14352 | 13772 | .flags = .{ |
| 14353 | 13773 | .size = .slice, |
| ... | ... | @@ -14359,45 +13779,44 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14359 | 13779 | const many_alloc = try block.addBitCast(many_ty, mutable_alloc); |
| 14360 | 13780 | |
| 14361 | 13781 | // lhs_dest_slice = dest[0..lhs.len] |
| 14362 | const slice_ty_ref = Air.internedToRef(slice_ty.toIntern()); | |
| 14363 | const lhs_len_ref = try pt.intRef(.usize, lhs_len); | |
| 14364 | const lhs_dest_slice = try block.addInst(.{ | |
| 14365 | .tag = .slice, | |
| 14366 | .data = .{ .ty_pl = .{ | |
| 14367 | .ty = slice_ty_ref, | |
| 14368 | .payload = try sema.addExtra(Air.Bin{ | |
| 14369 | .lhs = many_alloc, | |
| 14370 | .rhs = lhs_len_ref, | |
| 14371 | }), | |
| 14372 | } }, | |
| 14373 | }); | |
| 14374 | ||
| 14375 | _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); | |
| 13782 | if (lhs_len > 0) { | |
| 13783 | const lhs_dest_slice = try block.addInst(.{ | |
| 13784 | .tag = .slice, | |
| 13785 | .data = .{ .ty_pl = .{ | |
| 13786 | .ty = .fromType(slice_ty), | |
| 13787 | .payload = try sema.addExtra(Air.Bin{ | |
| 13788 | .lhs = many_alloc, | |
| 13789 | .rhs = try pt.intRef(.usize, lhs_len), | |
| 13790 | }), | |
| 13791 | } }, | |
| 13792 | }); | |
| 13793 | _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); | |
| 13794 | } | |
| 14376 | 13795 | |
| 14377 | 13796 | // rhs_dest_slice = dest[lhs.len..][0..rhs.len] |
| 14378 | const rhs_len_ref = try pt.intRef(.usize, rhs_len); | |
| 14379 | const rhs_dest_offset = try block.addInst(.{ | |
| 14380 | .tag = .ptr_add, | |
| 14381 | .data = .{ .ty_pl = .{ | |
| 14382 | .ty = Air.internedToRef(many_ty.toIntern()), | |
| 14383 | .payload = try sema.addExtra(Air.Bin{ | |
| 14384 | .lhs = many_alloc, | |
| 14385 | .rhs = lhs_len_ref, | |
| 14386 | }), | |
| 14387 | } }, | |
| 14388 | }); | |
| 14389 | const rhs_dest_slice = try block.addInst(.{ | |
| 14390 | .tag = .slice, | |
| 14391 | .data = .{ .ty_pl = .{ | |
| 14392 | .ty = slice_ty_ref, | |
| 14393 | .payload = try sema.addExtra(Air.Bin{ | |
| 14394 | .lhs = rhs_dest_offset, | |
| 14395 | .rhs = rhs_len_ref, | |
| 14396 | }), | |
| 14397 | } }, | |
| 14398 | }); | |
| 14399 | ||
| 14400 | _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); | |
| 13797 | if (rhs_len > 0) { | |
| 13798 | const rhs_dest_offset = try block.addInst(.{ | |
| 13799 | .tag = .ptr_add, | |
| 13800 | .data = .{ .ty_pl = .{ | |
| 13801 | .ty = Air.internedToRef(many_ty.toIntern()), | |
| 13802 | .payload = try sema.addExtra(Air.Bin{ | |
| 13803 | .lhs = many_alloc, | |
| 13804 | .rhs = try pt.intRef(.usize, lhs_len), | |
| 13805 | }), | |
| 13806 | } }, | |
| 13807 | }); | |
| 13808 | const rhs_dest_slice = try block.addInst(.{ | |
| 13809 | .tag = .slice, | |
| 13810 | .data = .{ .ty_pl = .{ | |
| 13811 | .ty = .fromType(slice_ty), | |
| 13812 | .payload = try sema.addExtra(Air.Bin{ | |
| 13813 | .lhs = rhs_dest_offset, | |
| 13814 | .rhs = try pt.intRef(.usize, rhs_len), | |
| 13815 | }), | |
| 13816 | } }, | |
| 13817 | }); | |
| 13818 | _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); | |
| 13819 | } | |
| 14401 | 13820 | |
| 14402 | 13821 | if (res_sent_val) |sent_val| { |
| 14403 | 13822 | const elem_index = try pt.intRef(.usize, result_len); |
| ... | ... | @@ -14486,7 +13905,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 14486 | 13905 | .none => null, |
| 14487 | 13906 | else => Value.fromInterned(ptr_info.sentinel), |
| 14488 | 13907 | }, |
| 14489 | .len = try val.sliceLen(pt), | |
| 13908 | .len = val.sliceLen(zcu), | |
| 14490 | 13909 | }; |
| 14491 | 13910 | }, |
| 14492 | 13911 | .one => { |
| ... | ... | @@ -14500,8 +13919,20 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 14500 | 13919 | .@"struct" => { |
| 14501 | 13920 | if (operand_ty.isTuple(zcu) and peer_ty.isIndexable(zcu)) { |
| 14502 | 13921 | assert(!peer_ty.isTuple(zcu)); |
| 13922 | const peer_elem_ty = switch (peer_ty.zigTypeTag(zcu)) { | |
| 13923 | .pointer => switch (peer_ty.ptrSize(zcu)) { | |
| 13924 | .one => switch (peer_ty.childType(zcu).zigTypeTag(zcu)) { | |
| 13925 | .array, .vector => peer_ty.childType(zcu).childType(zcu), | |
| 13926 | .@"struct" => return null, | |
| 13927 | else => unreachable, | |
| 13928 | }, | |
| 13929 | .many, .c, .slice => peer_ty.childType(zcu), | |
| 13930 | }, | |
| 13931 | .vector, .array => peer_ty.childType(zcu), | |
| 13932 | else => unreachable, | |
| 13933 | }; | |
| 14503 | 13934 | return .{ |
| 14504 | .elem_type = peer_ty.elemType2(zcu), | |
| 13935 | .elem_type = peer_elem_ty, | |
| 14505 | 13936 | .sentinel = null, |
| 14506 | 13937 | .len = operand_ty.arrayLen(zcu), |
| 14507 | 13938 | }; |
| ... | ... | @@ -14543,12 +13974,13 @@ fn analyzeTupleMul( |
| 14543 | 13974 | var runtime_src: ?LazySrcLoc = null; |
| 14544 | 13975 | for (0..tuple_len) |i| { |
| 14545 | 13976 | types[i] = operand_ty.fieldType(i, zcu).toIntern(); |
| 14546 | values[i] = operand_ty.structFieldDefaultValue(i, zcu).toIntern(); | |
| 14547 | 13977 | const operand_src = block.src(.{ .array_cat_lhs = .{ |
| 14548 | 13978 | .array_cat_offset = src_node, |
| 14549 | 13979 | .elem_index = @intCast(i), |
| 14550 | 13980 | } }); |
| 14551 | if (values[i] == .unreachable_value) { | |
| 13981 | if (operand_ty.structFieldDefaultValue(i, zcu)) |default_val| { | |
| 13982 | values[i] = default_val.toIntern(); | |
| 13983 | } else { | |
| 14552 | 13984 | runtime_src = operand_src; |
| 14553 | 13985 | values[i] = .none; // TODO don't treat unreachable_value as special |
| 14554 | 13986 | } |
| ... | ... | @@ -14593,7 +14025,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14593 | 14025 | const zcu = pt.zcu; |
| 14594 | 14026 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 14595 | 14027 | const extra = sema.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data; |
| 14596 | const uncoerced_lhs = try sema.resolveInst(extra.lhs); | |
| 14028 | const uncoerced_lhs = sema.resolveInst(extra.lhs); | |
| 14597 | 14029 | const uncoerced_lhs_ty = sema.typeOf(uncoerced_lhs); |
| 14598 | 14030 | const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); |
| 14599 | 14031 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| ... | ... | @@ -14672,7 +14104,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14672 | 14104 | const ptr_addrspace = if (lhs_ty.zigTypeTag(zcu) == .pointer) lhs_ty.ptrAddressSpace(zcu) else null; |
| 14673 | 14105 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); |
| 14674 | 14106 | |
| 14675 | if (try sema.resolveValue(lhs)) |lhs_val| ct: { | |
| 14107 | if (sema.resolveValue(lhs)) |lhs_val| ct: { | |
| 14676 | 14108 | const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu)) |
| 14677 | 14109 | try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :ct |
| 14678 | 14110 | else if (lhs_ty.isSlice(zcu)) |
| ... | ... | @@ -14700,7 +14132,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14700 | 14132 | } |
| 14701 | 14133 | break :v try pt.aggregateValue(result_ty, element_vals); |
| 14702 | 14134 | }; |
| 14703 | return sema.addConstantMaybeRef(val.toIntern(), ptr_addrspace != null); | |
| 14135 | return sema.addConstantMaybeRef(val, ptr_addrspace != null); | |
| 14704 | 14136 | } |
| 14705 | 14137 | |
| 14706 | 14138 | try sema.requireRuntimeBlock(block, src, lhs_src); |
| ... | ... | @@ -14714,7 +14146,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14714 | 14146 | } |
| 14715 | 14147 | |
| 14716 | 14148 | if (ptr_addrspace) |ptr_as| { |
| 14717 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 14149 | const alloc_ty = try pt.ptrType(.{ | |
| 14718 | 14150 | .child = result_ty.toIntern(), |
| 14719 | 14151 | .flags = .{ |
| 14720 | 14152 | .address_space = ptr_as, |
| ... | ... | @@ -14722,7 +14154,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14722 | 14154 | }, |
| 14723 | 14155 | }); |
| 14724 | 14156 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 14725 | const elem_ptr_ty = try pt.ptrTypeSema(.{ | |
| 14157 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 14726 | 14158 | .child = lhs_info.elem_type.toIntern(), |
| 14727 | 14159 | .flags = .{ .address_space = ptr_as }, |
| 14728 | 14160 | }); |
| ... | ... | @@ -14761,7 +14193,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14761 | 14193 | const lhs_src = src; |
| 14762 | 14194 | const rhs_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); |
| 14763 | 14195 | |
| 14764 | const rhs = try sema.resolveInst(inst_data.operand); | |
| 14196 | const rhs = sema.resolveInst(inst_data.operand); | |
| 14765 | 14197 | const rhs_ty = sema.typeOf(rhs); |
| 14766 | 14198 | const rhs_scalar_ty = rhs_ty.scalarType(zcu); |
| 14767 | 14199 | |
| ... | ... | @@ -14774,7 +14206,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14774 | 14206 | |
| 14775 | 14207 | if (rhs_scalar_ty.isAnyFloat()) { |
| 14776 | 14208 | // We handle float negation here to ensure negative zero is represented in the bits. |
| 14777 | if (try sema.resolveValue(rhs)) |rhs_val| { | |
| 14209 | if (sema.resolveValue(rhs)) |rhs_val| { | |
| 14778 | 14210 | const result = try arith.negateFloat(sema, rhs_ty, rhs_val); |
| 14779 | 14211 | return Air.internedToRef(result.toIntern()); |
| 14780 | 14212 | } |
| ... | ... | @@ -14794,7 +14226,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 14794 | 14226 | const lhs_src = src; |
| 14795 | 14227 | const rhs_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); |
| 14796 | 14228 | |
| 14797 | const rhs = try sema.resolveInst(inst_data.operand); | |
| 14229 | const rhs = sema.resolveInst(inst_data.operand); | |
| 14798 | 14230 | const rhs_ty = sema.typeOf(rhs); |
| 14799 | 14231 | const rhs_scalar_ty = rhs_ty.scalarType(zcu); |
| 14800 | 14232 | |
| ... | ... | @@ -14822,8 +14254,8 @@ fn zirArithmetic( |
| 14822 | 14254 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 14823 | 14255 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 14824 | 14256 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 14825 | const lhs = try sema.resolveInst(extra.lhs); | |
| 14826 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14257 | const lhs = sema.resolveInst(extra.lhs); | |
| 14258 | const rhs = sema.resolveInst(extra.rhs); | |
| 14827 | 14259 | |
| 14828 | 14260 | return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, src, lhs_src, rhs_src, safety); |
| 14829 | 14261 | } |
| ... | ... | @@ -14836,8 +14268,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14836 | 14268 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 14837 | 14269 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 14838 | 14270 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 14839 | const lhs = try sema.resolveInst(extra.lhs); | |
| 14840 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14271 | const lhs = sema.resolveInst(extra.lhs); | |
| 14272 | const rhs = sema.resolveInst(extra.rhs); | |
| 14841 | 14273 | const lhs_ty = sema.typeOf(lhs); |
| 14842 | 14274 | const rhs_ty = sema.typeOf(rhs); |
| 14843 | 14275 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -14859,8 +14291,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 14859 | 14291 | |
| 14860 | 14292 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div); |
| 14861 | 14293 | |
| 14862 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 14863 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14294 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14295 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 14864 | 14296 | |
| 14865 | 14297 | if ((lhs_ty.zigTypeTag(zcu) == .comptime_float and rhs_ty.zigTypeTag(zcu) == .comptime_int) or |
| 14866 | 14298 | (lhs_ty.zigTypeTag(zcu) == .comptime_int and rhs_ty.zigTypeTag(zcu) == .comptime_float)) |
| ... | ... | @@ -14945,8 +14377,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14945 | 14377 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 14946 | 14378 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 14947 | 14379 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 14948 | const lhs = try sema.resolveInst(extra.lhs); | |
| 14949 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14380 | const lhs = sema.resolveInst(extra.lhs); | |
| 14381 | const rhs = sema.resolveInst(extra.rhs); | |
| 14950 | 14382 | const lhs_ty = sema.typeOf(lhs); |
| 14951 | 14383 | const rhs_ty = sema.typeOf(rhs); |
| 14952 | 14384 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -14968,8 +14400,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14968 | 14400 | |
| 14969 | 14401 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact); |
| 14970 | 14402 | |
| 14971 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 14972 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14403 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14404 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 14973 | 14405 | |
| 14974 | 14406 | // Because `@divExact` can trigger Illegal Behavior, undefined operands trigger Illegal Behavior. |
| 14975 | 14407 | |
| ... | ... | @@ -15041,8 +14473,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15041 | 14473 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 15042 | 14474 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 15043 | 14475 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15044 | const lhs = try sema.resolveInst(extra.lhs); | |
| 15045 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14476 | const lhs = sema.resolveInst(extra.lhs); | |
| 14477 | const rhs = sema.resolveInst(extra.rhs); | |
| 15046 | 14478 | const lhs_ty = sema.typeOf(lhs); |
| 15047 | 14479 | const rhs_ty = sema.typeOf(rhs); |
| 15048 | 14480 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -15064,8 +14496,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15064 | 14496 | |
| 15065 | 14497 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor); |
| 15066 | 14498 | |
| 15067 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 15068 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14499 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14500 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 15069 | 14501 | |
| 15070 | 14502 | const allow_div_zero = !is_int and |
| 15071 | 14503 | resolved_type.toIntern() != .comptime_float_type and |
| ... | ... | @@ -15106,8 +14538,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15106 | 14538 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 15107 | 14539 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 15108 | 14540 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15109 | const lhs = try sema.resolveInst(extra.lhs); | |
| 15110 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14541 | const lhs = sema.resolveInst(extra.lhs); | |
| 14542 | const rhs = sema.resolveInst(extra.rhs); | |
| 15111 | 14543 | const lhs_ty = sema.typeOf(lhs); |
| 15112 | 14544 | const rhs_ty = sema.typeOf(rhs); |
| 15113 | 14545 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -15129,8 +14561,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15129 | 14561 | |
| 15130 | 14562 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc); |
| 15131 | 14563 | |
| 15132 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 15133 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14564 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14565 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 15134 | 14566 | |
| 15135 | 14567 | const allow_div_zero = !is_int and |
| 15136 | 14568 | resolved_type.toIntern() != .comptime_float_type and |
| ... | ... | @@ -15317,8 +14749,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15317 | 14749 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 15318 | 14750 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 15319 | 14751 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15320 | const lhs = try sema.resolveInst(extra.lhs); | |
| 15321 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14752 | const lhs = sema.resolveInst(extra.lhs); | |
| 14753 | const rhs = sema.resolveInst(extra.rhs); | |
| 15322 | 14754 | const lhs_ty = sema.typeOf(lhs); |
| 15323 | 14755 | const rhs_ty = sema.typeOf(rhs); |
| 15324 | 14756 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -15341,8 +14773,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15341 | 14773 | |
| 15342 | 14774 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem); |
| 15343 | 14775 | |
| 15344 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 15345 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14776 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14777 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 15346 | 14778 | |
| 15347 | 14779 | const lhs_maybe_negative = a: { |
| 15348 | 14780 | if (lhs_scalar_ty.isUnsignedInt(zcu)) break :a false; |
| ... | ... | @@ -15418,8 +14850,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 15418 | 14850 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 15419 | 14851 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 15420 | 14852 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15421 | const lhs = try sema.resolveInst(extra.lhs); | |
| 15422 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14853 | const lhs = sema.resolveInst(extra.lhs); | |
| 14854 | const rhs = sema.resolveInst(extra.rhs); | |
| 15423 | 14855 | const lhs_ty = sema.typeOf(lhs); |
| 15424 | 14856 | const rhs_ty = sema.typeOf(rhs); |
| 15425 | 14857 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -15440,8 +14872,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 15440 | 14872 | |
| 15441 | 14873 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod); |
| 15442 | 14874 | |
| 15443 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 15444 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14875 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14876 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 15445 | 14877 | |
| 15446 | 14878 | const allow_div_zero = !is_int and |
| 15447 | 14879 | resolved_type.toIntern() != .comptime_float_type and |
| ... | ... | @@ -15482,8 +14914,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 15482 | 14914 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 15483 | 14915 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 15484 | 14916 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15485 | const lhs = try sema.resolveInst(extra.lhs); | |
| 15486 | const rhs = try sema.resolveInst(extra.rhs); | |
| 14917 | const lhs = sema.resolveInst(extra.lhs); | |
| 14918 | const rhs = sema.resolveInst(extra.rhs); | |
| 15487 | 14919 | const lhs_ty = sema.typeOf(lhs); |
| 15488 | 14920 | const rhs_ty = sema.typeOf(rhs); |
| 15489 | 14921 | const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); |
| ... | ... | @@ -15504,8 +14936,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 15504 | 14936 | |
| 15505 | 14937 | try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem); |
| 15506 | 14938 | |
| 15507 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 15508 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 14939 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 14940 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 15509 | 14941 | |
| 15510 | 14942 | const allow_div_zero = !is_int and |
| 15511 | 14943 | resolved_type.toIntern() != .comptime_float_type and |
| ... | ... | @@ -15553,8 +14985,8 @@ fn zirOverflowArithmetic( |
| 15553 | 14985 | const lhs_src = block.builtinCallArgSrc(extra.node, 0); |
| 15554 | 14986 | const rhs_src = block.builtinCallArgSrc(extra.node, 1); |
| 15555 | 14987 | |
| 15556 | const uncasted_lhs = try sema.resolveInst(extra.lhs); | |
| 15557 | const uncasted_rhs = try sema.resolveInst(extra.rhs); | |
| 14988 | const uncasted_lhs = sema.resolveInst(extra.lhs); | |
| 14989 | const uncasted_rhs = sema.resolveInst(extra.rhs); | |
| 15558 | 14990 | |
| 15559 | 14991 | const lhs_ty = sema.typeOf(uncasted_lhs); |
| 15560 | 14992 | const rhs_ty = sema.typeOf(uncasted_rhs); |
| ... | ... | @@ -15584,8 +15016,8 @@ fn zirOverflowArithmetic( |
| 15584 | 15016 | return sema.fail(block, src, "expected vector of integers or integer tag type, found '{f}'", .{dest_ty.fmt(pt)}); |
| 15585 | 15017 | } |
| 15586 | 15018 | |
| 15587 | const maybe_lhs_val = try sema.resolveValue(lhs); | |
| 15588 | const maybe_rhs_val = try sema.resolveValue(rhs); | |
| 15019 | const maybe_lhs_val = sema.resolveValue(lhs); | |
| 15020 | const maybe_rhs_val = sema.resolveValue(rhs); | |
| 15589 | 15021 | |
| 15590 | 15022 | const tuple_ty = try pt.overflowArithmeticTupleType(dest_ty); |
| 15591 | 15023 | const overflow_ty: Type = .fromInterned(ip.indexToKey(tuple_ty.toIntern()).tuple_type.types.get(ip)[1]); |
| ... | ... | @@ -15601,12 +15033,12 @@ fn zirOverflowArithmetic( |
| 15601 | 15033 | // to the result, even if it is undefined.. |
| 15602 | 15034 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 15603 | 15035 | if (maybe_lhs_val) |lhs_val| { |
| 15604 | if (!lhs_val.isUndef(zcu) and (try lhs_val.compareAllWithZeroSema(.eq, pt))) { | |
| 15036 | if (!lhs_val.isUndef(zcu) and lhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15605 | 15037 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; |
| 15606 | 15038 | } |
| 15607 | 15039 | } |
| 15608 | 15040 | if (maybe_rhs_val) |rhs_val| { |
| 15609 | if (!rhs_val.isUndef(zcu) and (try rhs_val.compareAllWithZeroSema(.eq, pt))) { | |
| 15041 | if (!rhs_val.isUndef(zcu) and rhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15610 | 15042 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; |
| 15611 | 15043 | } |
| 15612 | 15044 | } |
| ... | ... | @@ -15627,7 +15059,7 @@ fn zirOverflowArithmetic( |
| 15627 | 15059 | if (maybe_rhs_val) |rhs_val| { |
| 15628 | 15060 | if (rhs_val.isUndef(zcu)) { |
| 15629 | 15061 | break :result .{ .overflow_bit = .undef, .wrapped = .undef }; |
| 15630 | } else if (try rhs_val.compareAllWithZeroSema(.eq, pt)) { | |
| 15062 | } else if (rhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15631 | 15063 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; |
| 15632 | 15064 | } else if (maybe_lhs_val) |lhs_val| { |
| 15633 | 15065 | if (lhs_val.isUndef(zcu)) { |
| ... | ... | @@ -15642,12 +15074,12 @@ fn zirOverflowArithmetic( |
| 15642 | 15074 | .mul_with_overflow => { |
| 15643 | 15075 | // If either of the arguments is zero, the result is zero and no overflow occured. |
| 15644 | 15076 | if (maybe_lhs_val) |lhs_val| { |
| 15645 | if (!lhs_val.isUndef(zcu) and try lhs_val.compareAllWithZeroSema(.eq, pt)) { | |
| 15077 | if (!lhs_val.isUndef(zcu) and lhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15646 | 15078 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; |
| 15647 | 15079 | } |
| 15648 | 15080 | } |
| 15649 | 15081 | if (maybe_rhs_val) |rhs_val| { |
| 15650 | if (!rhs_val.isUndef(zcu) and try rhs_val.compareAllWithZeroSema(.eq, pt)) { | |
| 15082 | if (!rhs_val.isUndef(zcu) and rhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15651 | 15083 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; |
| 15652 | 15084 | } |
| 15653 | 15085 | } |
| ... | ... | @@ -15694,10 +15126,10 @@ fn zirOverflowArithmetic( |
| 15694 | 15126 | const bits = scalar_ty.intInfo(zcu).bits; |
| 15695 | 15127 | switch (rhs_ty.zigTypeTag(zcu)) { |
| 15696 | 15128 | .int, .comptime_int => { |
| 15697 | switch (try rhs_val.orderAgainstZeroSema(pt)) { | |
| 15129 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 15698 | 15130 | .gt => { |
| 15699 | 15131 | var rhs_space: Value.BigIntSpace = undefined; |
| 15700 | const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); | |
| 15132 | const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu); | |
| 15701 | 15133 | if (rhs_bigint.orderAgainstScalar(bits) != .lt) { |
| 15702 | 15134 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); |
| 15703 | 15135 | } |
| ... | ... | @@ -15711,10 +15143,10 @@ fn zirOverflowArithmetic( |
| 15711 | 15143 | for (0..rhs_ty.vectorLen(zcu)) |elem_idx| { |
| 15712 | 15144 | const rhs_elem = try rhs_val.elemValue(pt, elem_idx); |
| 15713 | 15145 | if (rhs_elem.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, elem_idx); |
| 15714 | switch (try rhs_elem.orderAgainstZeroSema(pt)) { | |
| 15146 | switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) { | |
| 15715 | 15147 | .gt => { |
| 15716 | 15148 | var rhs_elem_space: Value.BigIntSpace = undefined; |
| 15717 | const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); | |
| 15149 | const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu); | |
| 15718 | 15150 | if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { |
| 15719 | 15151 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); |
| 15720 | 15152 | } |
| ... | ... | @@ -15728,7 +15160,7 @@ fn zirOverflowArithmetic( |
| 15728 | 15160 | }, |
| 15729 | 15161 | else => unreachable, |
| 15730 | 15162 | } |
| 15731 | if (try rhs_val.compareAllWithZeroSema(.eq, pt)) { | |
| 15163 | if (rhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15732 | 15164 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; |
| 15733 | 15165 | } |
| 15734 | 15166 | } else { |
| ... | ... | @@ -15737,7 +15169,7 @@ fn zirOverflowArithmetic( |
| 15737 | 15169 | } |
| 15738 | 15170 | if (maybe_lhs_val) |lhs_val| { |
| 15739 | 15171 | try sema.checkAllScalarsDefined(block, lhs_src, lhs_val); |
| 15740 | if (try lhs_val.compareAllWithZeroSema(.eq, pt)) { | |
| 15172 | if (lhs_val.compareAllWithZero(.eq, zcu)) { | |
| 15741 | 15173 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; |
| 15742 | 15174 | } |
| 15743 | 15175 | } |
| ... | ... | @@ -15767,7 +15199,7 @@ fn zirOverflowArithmetic( |
| 15767 | 15199 | }; |
| 15768 | 15200 | |
| 15769 | 15201 | if (result.inst != .none) { |
| 15770 | if (try sema.resolveValue(result.inst)) |some| { | |
| 15202 | if (sema.resolveValue(result.inst)) |some| { | |
| 15771 | 15203 | result.wrapped = some; |
| 15772 | 15204 | result.inst = .none; |
| 15773 | 15205 | } |
| ... | ... | @@ -15817,22 +15249,45 @@ fn analyzeArithmetic( |
| 15817 | 15249 | if (zir_tag != .sub) { |
| 15818 | 15250 | return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction"); |
| 15819 | 15251 | } |
| 15820 | if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) { | |
| 15252 | ||
| 15253 | // TODO: these semantics are really weird. Pointer subtraction works in increments | |
| 15254 | // of the pointer child for indexable pointers (excluding pointers to vectors), | |
| 15255 | // which makes sense, but we also allow it for arbitrary single-item pointers, which | |
| 15256 | // leads to the weird result that subtraction of '*T' works completely differently | |
| 15257 | // depending on whether 'T' is an array. That seems dangerous and confusing, and | |
| 15258 | // requires the odd logic below. This behavior originally came from a now-removed | |
| 15259 | // function `Type.elemType2`, which was removed precisely *because* the thing it did | |
| 15260 | // wasn't really well-defined; for that reason, these semantics were probably | |
| 15261 | // largely accidental to begin with. We should change the langauge to avoid this | |
| 15262 | // confusing behavior. For instance, perhaps pointer subtraction should only work on | |
| 15263 | // indexable pointers. | |
| 15264 | const lhs_elem_ty = ty: { | |
| 15265 | const ptr_elem_ty = lhs_ty.childType(zcu); | |
| 15266 | if (lhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.zigTypeTag(zcu) == .array) break :ty ptr_elem_ty.childType(zcu); | |
| 15267 | break :ty ptr_elem_ty; | |
| 15268 | }; | |
| 15269 | const rhs_elem_ty = ty: { | |
| 15270 | const ptr_elem_ty = rhs_ty.childType(zcu); | |
| 15271 | if (rhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.zigTypeTag(zcu) == .array) break :ty ptr_elem_ty.childType(zcu); | |
| 15272 | break :ty ptr_elem_ty; | |
| 15273 | }; | |
| 15274 | if (lhs_elem_ty.toIntern() != rhs_elem_ty.toIntern()) { | |
| 15821 | 15275 | return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{ |
| 15822 | 15276 | lhs_ty.fmt(pt), rhs_ty.fmt(pt), |
| 15823 | 15277 | }); |
| 15824 | 15278 | } |
| 15825 | 15279 | |
| 15826 | const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu); | |
| 15280 | try sema.ensureLayoutResolved(lhs_elem_ty, src, .ptr_offset); | |
| 15281 | const elem_size = lhs_elem_ty.abiSize(zcu); | |
| 15827 | 15282 | if (elem_size == 0) { |
| 15828 | return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{ | |
| 15829 | lhs_ty.elemType2(zcu).fmt(pt), | |
| 15283 | return sema.fail(block, src, "pointer subtraction requires element type '{f}' to have runtime bits", .{ | |
| 15284 | lhs_elem_ty.fmt(pt), | |
| 15830 | 15285 | }); |
| 15831 | 15286 | } |
| 15832 | 15287 | |
| 15833 | 15288 | const runtime_src = runtime_src: { |
| 15834 | if (try sema.resolveValue(lhs)) |lhs_value| { | |
| 15835 | if (try sema.resolveValue(rhs)) |rhs_value| { | |
| 15289 | if (sema.resolveValue(lhs)) |lhs_value| { | |
| 15290 | if (sema.resolveValue(rhs)) |rhs_value| { | |
| 15836 | 15291 | const lhs_ptr = switch (zcu.intern_pool.indexToKey(lhs_value.toIntern())) { |
| 15837 | 15292 | .undef => return sema.failWithUseOfUndef(block, lhs_src, null), |
| 15838 | 15293 | .ptr => |ptr| ptr, |
| ... | ... | @@ -15875,12 +15330,8 @@ fn analyzeArithmetic( |
| 15875 | 15330 | else => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"), |
| 15876 | 15331 | }; |
| 15877 | 15332 | |
| 15878 | if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) { | |
| 15879 | return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{ | |
| 15880 | lhs_ty.elemType2(zcu).fmt(pt), | |
| 15881 | }); | |
| 15882 | } | |
| 15883 | return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src); | |
| 15333 | try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src, .ptr_offset); | |
| 15334 | return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, rhs_src); | |
| 15884 | 15335 | }, |
| 15885 | 15336 | } |
| 15886 | 15337 | } |
| ... | ... | @@ -15915,8 +15366,8 @@ fn analyzeArithmetic( |
| 15915 | 15366 | else => unreachable, |
| 15916 | 15367 | }; |
| 15917 | 15368 | |
| 15918 | const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); | |
| 15919 | const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); | |
| 15369 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 15370 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 15920 | 15371 | |
| 15921 | 15372 | if (maybe_lhs_val) |lhs_val| { |
| 15922 | 15373 | if (maybe_rhs_val) |rhs_val| { |
| ... | ... | @@ -15972,6 +15423,7 @@ fn analyzeArithmetic( |
| 15972 | 15423 | return block.addBinOp(air_tag, casted_lhs, casted_rhs); |
| 15973 | 15424 | } |
| 15974 | 15425 | |
| 15426 | /// Asserts that the layout of the pointer child type is already resolved. | |
| 15975 | 15427 | fn analyzePtrArithmetic( |
| 15976 | 15428 | sema: *Sema, |
| 15977 | 15429 | block: *Block, |
| ... | ... | @@ -15979,7 +15431,6 @@ fn analyzePtrArithmetic( |
| 15979 | 15431 | ptr: Air.Inst.Ref, |
| 15980 | 15432 | uncasted_offset: Air.Inst.Ref, |
| 15981 | 15433 | air_tag: Air.Inst.Tag, |
| 15982 | ptr_src: LazySrcLoc, | |
| 15983 | 15434 | offset_src: LazySrcLoc, |
| 15984 | 15435 | ) CompileError!Air.Inst.Ref { |
| 15985 | 15436 | // TODO if the operand is comptime-known to be negative, or is a negative int, |
| ... | ... | @@ -15987,81 +15438,55 @@ fn analyzePtrArithmetic( |
| 15987 | 15438 | const offset = try sema.coerce(block, .usize, uncasted_offset, offset_src); |
| 15988 | 15439 | const pt = sema.pt; |
| 15989 | 15440 | const zcu = pt.zcu; |
| 15990 | const opt_ptr_val = try sema.resolveValue(ptr); | |
| 15991 | const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset); | |
| 15992 | 15441 | const ptr_ty = sema.typeOf(ptr); |
| 15993 | 15442 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| 15994 | 15443 | assert(ptr_info.flags.size == .many or ptr_info.flags.size == .c); |
| 15995 | 15444 | |
| 15996 | if ((try sema.typeHasOnePossibleValue(.fromInterned(ptr_info.child))) != null) { | |
| 15997 | // Offset will be multiplied by zero, so result is the same as the base pointer. | |
| 15998 | return ptr; | |
| 15445 | const maybe_index: ?u64 = if (try sema.resolveDefinedValue(block, offset_src, offset)) |val| off: { | |
| 15446 | break :off val.toUnsignedInt(zcu); | |
| 15447 | } else null; | |
| 15448 | ||
| 15449 | const elem_ty: Type = .fromInterned(ptr_info.child); | |
| 15450 | elem_ty.assertHasLayout(zcu); | |
| 15451 | ||
| 15452 | switch (elem_ty.classify(zcu)) { | |
| 15453 | .no_possible_value, .one_possible_value => { | |
| 15454 | // Offset will be multiplied by zero, so result is the same as the base pointer. | |
| 15455 | return ptr; | |
| 15456 | }, | |
| 15457 | else => {}, | |
| 15999 | 15458 | } |
| 16000 | 15459 | |
| 16001 | const new_ptr_ty = t: { | |
| 16002 | // Calculate the new pointer alignment. | |
| 16003 | // This code is duplicated in `Type.elemPtrType`. | |
| 16004 | if (ptr_info.flags.alignment == .none) { | |
| 16005 | // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness. | |
| 16006 | break :t ptr_ty; | |
| 16007 | } | |
| 16008 | // If the addend is not a comptime-known value we can still count on | |
| 16009 | // it being a multiple of the type size. | |
| 16010 | const elem_size = try Type.fromInterned(ptr_info.child).abiSizeSema(pt); | |
| 16011 | const addend = if (opt_off_val) |off_val| a: { | |
| 16012 | const off_int = try sema.usizeCast(block, offset_src, try off_val.toUnsignedIntSema(pt)); | |
| 16013 | break :a elem_size * off_int; | |
| 16014 | } else elem_size; | |
| 16015 | ||
| 16016 | // The resulting pointer is aligned to the lcd between the offset (an | |
| 16017 | // arbitrary number) and the alignment factor (always a power of two, | |
| 16018 | // non zero). | |
| 16019 | const new_align: Alignment = @enumFromInt(@min( | |
| 16020 | @ctz(addend), | |
| 16021 | @intFromEnum(ptr_info.flags.alignment), | |
| 16022 | )); | |
| 16023 | assert(new_align != .none); | |
| 16024 | ||
| 16025 | break :t try pt.ptrTypeSema(.{ | |
| 16026 | .child = ptr_info.child, | |
| 16027 | .sentinel = ptr_info.sentinel, | |
| 16028 | .flags = .{ | |
| 16029 | .size = ptr_info.flags.size, | |
| 16030 | .alignment = new_align, | |
| 16031 | .is_const = ptr_info.flags.is_const, | |
| 16032 | .is_volatile = ptr_info.flags.is_volatile, | |
| 16033 | .is_allowzero = ptr_info.flags.is_allowzero, | |
| 16034 | .address_space = ptr_info.flags.address_space, | |
| 16035 | }, | |
| 16036 | }); | |
| 16037 | }; | |
| 15460 | const elem_ptr_ty = try ptr_ty.elemPtrType(maybe_index, pt); | |
| 15461 | // `elem_ptr_ty` is a single-item pointer, but we want a many-item or C pointer, and to preserve | |
| 15462 | // any input sentinel. | |
| 15463 | const new_ptr_ty = try pt.ptrType(info: { | |
| 15464 | var info = elem_ptr_ty.ptrInfo(zcu); | |
| 15465 | info.flags.size = ptr_info.flags.size; | |
| 15466 | info.sentinel = ptr_info.sentinel; | |
| 15467 | break :info info; | |
| 15468 | }); | |
| 16038 | 15469 | |
| 16039 | const runtime_src = rs: { | |
| 16040 | if (opt_ptr_val) |ptr_val| { | |
| 16041 | if (opt_off_val) |offset_val| { | |
| 16042 | if (ptr_val.isUndef(zcu)) return pt.undefRef(new_ptr_ty); | |
| 16043 | ||
| 16044 | const offset_int = try sema.usizeCast(block, offset_src, try offset_val.toUnsignedIntSema(pt)); | |
| 16045 | if (offset_int == 0) return ptr; | |
| 16046 | if (air_tag == .ptr_sub) { | |
| 16047 | const elem_size = try Type.fromInterned(ptr_info.child).abiSizeSema(pt); | |
| 16048 | const new_ptr_val = try sema.ptrSubtract(block, op_src, ptr_val, offset_int * elem_size, new_ptr_ty); | |
| 16049 | return Air.internedToRef(new_ptr_val.toIntern()); | |
| 16050 | } else { | |
| 16051 | const new_ptr_val = try pt.getCoerced(try ptr_val.ptrElem(offset_int, pt), new_ptr_ty); | |
| 16052 | return Air.internedToRef(new_ptr_val.toIntern()); | |
| 16053 | } | |
| 16054 | } else break :rs offset_src; | |
| 16055 | } else break :rs ptr_src; | |
| 16056 | }; | |
| 15470 | ct: { | |
| 15471 | const ptr_val = sema.resolveValue(ptr) orelse break :ct; | |
| 15472 | if (ptr_val.isUndef(zcu)) return pt.undefRef(new_ptr_ty); | |
| 15473 | const index = maybe_index orelse break :ct; | |
| 15474 | ||
| 15475 | if (index == 0) return ptr; | |
| 15476 | if (air_tag == .ptr_sub) { | |
| 15477 | const elem_size = elem_ty.abiSize(zcu); | |
| 15478 | return .fromValue(try sema.ptrSubtract(block, op_src, ptr_val, index * elem_size, new_ptr_ty)); | |
| 15479 | } else { | |
| 15480 | return .fromValue(try pt.getCoerced(try ptr_val.ptrElem(index, pt), new_ptr_ty)); | |
| 15481 | } | |
| 15482 | } | |
| 16057 | 15483 | |
| 16058 | try sema.requireRuntimeBlock(block, op_src, runtime_src); | |
| 16059 | 15484 | try sema.checkLogicalPtrOperation(block, op_src, ptr_ty); |
| 16060 | 15485 | |
| 16061 | 15486 | return block.addInst(.{ |
| 16062 | 15487 | .tag = air_tag, |
| 16063 | 15488 | .data = .{ .ty_pl = .{ |
| 16064 | .ty = Air.internedToRef(new_ptr_ty.toIntern()), | |
| 15489 | .ty = .fromType(new_ptr_ty), | |
| 16065 | 15490 | .payload = try sema.addExtra(Air.Bin{ |
| 16066 | 15491 | .lhs = ptr, |
| 16067 | 15492 | .rhs = offset, |
| ... | ... | @@ -16077,7 +15502,7 @@ fn zirLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.In |
| 16077 | 15502 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 16078 | 15503 | const src = block.nodeOffset(inst_data.src_node); |
| 16079 | 15504 | const ptr_src = src; // TODO better source location |
| 16080 | const ptr = try sema.resolveInst(inst_data.operand); | |
| 15505 | const ptr = sema.resolveInst(inst_data.operand); | |
| 16081 | 15506 | return sema.analyzeLoad(block, src, ptr, ptr_src); |
| 16082 | 15507 | } |
| 16083 | 15508 | |
| ... | ... | @@ -16151,7 +15576,7 @@ fn zirAsm( |
| 16151 | 15576 | const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand); |
| 16152 | 15577 | expr_ty = Air.internedToRef(out_ty.toIntern()); |
| 16153 | 15578 | } else { |
| 16154 | const inst = try sema.resolveInst(output.data.operand); | |
| 15579 | const inst = sema.resolveInst(output.data.operand); | |
| 16155 | 15580 | if (!sema.checkRuntimeValue(inst)) { |
| 16156 | 15581 | const output_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); |
| 16157 | 15582 | return sema.failWithContainsReferenceToComptimeVar(block, output_src, output_name, "assembly output", .fromInterned(inst.toInterned().?)); |
| ... | ... | @@ -16181,7 +15606,7 @@ fn zirAsm( |
| 16181 | 15606 | } }); |
| 16182 | 15607 | extra_i = input.end; |
| 16183 | 15608 | |
| 16184 | const uncasted_arg = try sema.resolveInst(input.data.operand); | |
| 15609 | const uncasted_arg = sema.resolveInst(input.data.operand); | |
| 16185 | 15610 | const name = sema.code.nullTerminatedString(input.data.name); |
| 16186 | 15611 | if (!sema.checkRuntimeValue(uncasted_arg)) { |
| 16187 | 15612 | const input_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); |
| ... | ... | @@ -16204,7 +15629,7 @@ fn zirAsm( |
| 16204 | 15629 | const clobbers = if (extra.data.clobbers == .none) empty: { |
| 16205 | 15630 | const clobbers_ty = try sema.getBuiltinType(src, .@"assembly.Clobbers"); |
| 16206 | 15631 | break :empty try sema.structInitEmpty(block, clobbers_ty, src, src); |
| 16207 | } else try sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen. | |
| 15632 | } else sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen. | |
| 16208 | 15633 | const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber }); |
| 16209 | 15634 | needed_capacity += asm_source.len / 4 + 1; |
| 16210 | 15635 | |
| ... | ... | @@ -16248,6 +15673,7 @@ fn zirAsm( |
| 16248 | 15673 | buffer[input.c.len + 1 + input.n.len] = 0; |
| 16249 | 15674 | sema.air_extra.items.len += (input.c.len + input.n.len + (2 + 3)) / 4; |
| 16250 | 15675 | } |
| 15676 | if (try expr_ty.toType().onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 16251 | 15677 | return asm_air; |
| 16252 | 15678 | } |
| 16253 | 15679 | |
| ... | ... | @@ -16269,8 +15695,8 @@ fn zirCmpEq( |
| 16269 | 15695 | const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); |
| 16270 | 15696 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 16271 | 15697 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 16272 | const lhs = try sema.resolveInst(extra.lhs); | |
| 16273 | const rhs = try sema.resolveInst(extra.rhs); | |
| 15698 | const lhs = sema.resolveInst(extra.lhs); | |
| 15699 | const rhs = sema.resolveInst(extra.rhs); | |
| 16274 | 15700 | |
| 16275 | 15701 | const lhs_ty = sema.typeOf(lhs); |
| 16276 | 15702 | const rhs_ty = sema.typeOf(rhs); |
| ... | ... | @@ -16283,10 +15709,10 @@ fn zirCmpEq( |
| 16283 | 15709 | |
| 16284 | 15710 | // comparing null with optionals |
| 16285 | 15711 | if (lhs_ty_tag == .null and (rhs_ty_tag == .optional or rhs_ty.isCPtr(zcu))) { |
| 16286 | return sema.analyzeIsNull(block, rhs, op == .neq); | |
| 15712 | return sema.analyzeIsNull(block, src, rhs, op == .neq); | |
| 16287 | 15713 | } |
| 16288 | 15714 | if (rhs_ty_tag == .null and (lhs_ty_tag == .optional or lhs_ty.isCPtr(zcu))) { |
| 16289 | return sema.analyzeIsNull(block, lhs, op == .neq); | |
| 15715 | return sema.analyzeIsNull(block, src, lhs, op == .neq); | |
| 16290 | 15716 | } |
| 16291 | 15717 | |
| 16292 | 15718 | if (lhs_ty_tag == .null or rhs_ty_tag == .null) { |
| ... | ... | @@ -16303,8 +15729,8 @@ fn zirCmpEq( |
| 16303 | 15729 | |
| 16304 | 15730 | if (lhs_ty_tag == .error_set and rhs_ty_tag == .error_set) { |
| 16305 | 15731 | const runtime_src: LazySrcLoc = src: { |
| 16306 | if (try sema.resolveValue(lhs)) |lval| { | |
| 16307 | if (try sema.resolveValue(rhs)) |rval| { | |
| 15732 | if (sema.resolveValue(lhs)) |lval| { | |
| 15733 | if (sema.resolveValue(rhs)) |rval| { | |
| 16308 | 15734 | if (lval.isUndef(zcu) or rval.isUndef(zcu)) return .undef_bool; |
| 16309 | 15735 | const lkey = zcu.intern_pool.indexToKey(lval.toIntern()); |
| 16310 | 15736 | const rkey = zcu.intern_pool.indexToKey(rval.toIntern()); |
| ... | ... | @@ -16323,8 +15749,8 @@ fn zirCmpEq( |
| 16323 | 15749 | return block.addBinOp(air_tag, lhs, rhs); |
| 16324 | 15750 | } |
| 16325 | 15751 | if (lhs_ty_tag == .type and rhs_ty_tag == .type) { |
| 16326 | const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs); | |
| 16327 | const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs); | |
| 15752 | const lhs_as_type = try sema.analyzeAsType(block, lhs_src, .type, lhs); | |
| 15753 | const rhs_as_type = try sema.analyzeAsType(block, rhs_src, .type, rhs); | |
| 16328 | 15754 | return if (lhs_as_type.eql(rhs_as_type, zcu) == (op == .eq)) .bool_true else .bool_false; |
| 16329 | 15755 | } |
| 16330 | 15756 | return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, true); |
| ... | ... | @@ -16343,7 +15769,6 @@ fn analyzeCmpUnionTag( |
| 16343 | 15769 | const pt = sema.pt; |
| 16344 | 15770 | const zcu = pt.zcu; |
| 16345 | 15771 | const union_ty = sema.typeOf(un); |
| 16346 | try union_ty.resolveFields(pt); | |
| 16347 | 15772 | const union_tag_ty = union_ty.unionTagType(zcu) orelse { |
| 16348 | 15773 | const msg = msg: { |
| 16349 | 15774 | const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); |
| ... | ... | @@ -16358,10 +15783,10 @@ fn analyzeCmpUnionTag( |
| 16358 | 15783 | const coerced_tag = try sema.coerce(block, union_tag_ty, tag, tag_src); |
| 16359 | 15784 | const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src); |
| 16360 | 15785 | |
| 16361 | if (try sema.resolveValue(coerced_tag)) |enum_val| { | |
| 15786 | if (sema.resolveValue(coerced_tag)) |enum_val| { | |
| 16362 | 15787 | if (enum_val.isUndef(zcu)) return .undef_bool; |
| 16363 | 15788 | const field_ty = union_ty.unionFieldType(enum_val, zcu).?; |
| 16364 | if (field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 15789 | if (field_ty.classify(zcu) == .no_possible_value) { | |
| 16365 | 15790 | return .bool_false; |
| 16366 | 15791 | } |
| 16367 | 15792 | } |
| ... | ... | @@ -16384,8 +15809,8 @@ fn zirCmp( |
| 16384 | 15809 | const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); |
| 16385 | 15810 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 16386 | 15811 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 16387 | const lhs = try sema.resolveInst(extra.lhs); | |
| 16388 | const rhs = try sema.resolveInst(extra.rhs); | |
| 15812 | const lhs = sema.resolveInst(extra.lhs); | |
| 15813 | const rhs = sema.resolveInst(extra.rhs); | |
| 16389 | 15814 | return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, false); |
| 16390 | 15815 | } |
| 16391 | 15816 | |
| ... | ... | @@ -16468,8 +15893,8 @@ fn cmpSelf( |
| 16468 | 15893 | const zcu = pt.zcu; |
| 16469 | 15894 | const resolved_type = sema.typeOf(casted_lhs); |
| 16470 | 15895 | |
| 16471 | const maybe_lhs_val = try sema.resolveValue(casted_lhs); | |
| 16472 | const maybe_rhs_val = try sema.resolveValue(casted_rhs); | |
| 15896 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 15897 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 16473 | 15898 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; |
| 16474 | 15899 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; |
| 16475 | 15900 | |
| ... | ... | @@ -16534,42 +15959,26 @@ fn runtimeBoolCmp( |
| 16534 | 15959 | |
| 16535 | 15960 | fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 16536 | 15961 | const pt = sema.pt; |
| 15962 | const zcu = pt.zcu; | |
| 16537 | 15963 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 16538 | 15964 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 16539 | 15965 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 16540 | switch (ty.zigTypeTag(pt.zcu)) { | |
| 16541 | .@"fn", | |
| 16542 | .noreturn, | |
| 16543 | .undefined, | |
| 16544 | .null, | |
| 16545 | .@"opaque", | |
| 16546 | => return sema.fail(block, operand_src, "no size available for type '{f}'", .{ty.fmt(pt)}), | |
| 15966 | try sema.ensureLayoutResolved(ty, operand_src, .size_of); | |
| 15967 | switch (ty.classify(zcu)) { | |
| 15968 | .no_possible_value, | |
| 15969 | => return sema.fail(block, operand_src, "no size available for uninstantiable type '{f}'", .{ty.fmt(pt)}), | |
| 16547 | 15970 | |
| 16548 | .type, | |
| 16549 | .enum_literal, | |
| 16550 | .comptime_float, | |
| 16551 | .comptime_int, | |
| 16552 | .void, | |
| 16553 | => return .zero, | |
| 15971 | .partially_comptime, | |
| 15972 | .fully_comptime, | |
| 15973 | => return sema.fail(block, operand_src, "no size available for comptime-only type '{f}'", .{ty.fmt(pt)}), | |
| 16554 | 15974 | |
| 16555 | .bool, | |
| 16556 | .int, | |
| 16557 | .float, | |
| 16558 | .pointer, | |
| 16559 | .array, | |
| 16560 | .@"struct", | |
| 16561 | .optional, | |
| 16562 | .error_union, | |
| 16563 | .error_set, | |
| 16564 | .@"enum", | |
| 16565 | .@"union", | |
| 16566 | .vector, | |
| 16567 | .frame, | |
| 16568 | .@"anyframe", | |
| 16569 | => {}, | |
| 15975 | .one_possible_value => { | |
| 15976 | assert(ty.abiSize(zcu) == 0); | |
| 15977 | return .zero; | |
| 15978 | }, | |
| 15979 | ||
| 15980 | .runtime => return .fromValue(try pt.intValue(.comptime_int, ty.abiSize(zcu))), | |
| 16570 | 15981 | } |
| 16571 | const val = try ty.abiSizeLazy(pt); | |
| 16572 | return Air.internedToRef(val.toIntern()); | |
| 16573 | 15982 | } |
| 16574 | 15983 | |
| 16575 | 15984 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -16584,12 +15993,12 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16584 | 15993 | .undefined, |
| 16585 | 15994 | .null, |
| 16586 | 15995 | .@"opaque", |
| 16587 | => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}), | |
| 16588 | ||
| 16589 | 15996 | .type, |
| 16590 | 15997 | .enum_literal, |
| 16591 | 15998 | .comptime_float, |
| 16592 | 15999 | .comptime_int, |
| 16000 | => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}), | |
| 16001 | ||
| 16593 | 16002 | .void, |
| 16594 | 16003 | => return .zero, |
| 16595 | 16004 | |
| ... | ... | @@ -16609,8 +16018,8 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16609 | 16018 | .@"anyframe", |
| 16610 | 16019 | => {}, |
| 16611 | 16020 | } |
| 16612 | const bit_size = try operand_ty.bitSizeSema(pt); | |
| 16613 | return pt.intRef(.comptime_int, bit_size); | |
| 16021 | try sema.ensureLayoutResolved(operand_ty, operand_src, .size_of); | |
| 16022 | return .fromValue(try pt.intValue(.comptime_int, operand_ty.bitSize(zcu))); | |
| 16614 | 16023 | } |
| 16615 | 16024 | |
| 16616 | 16025 | fn zirThis( |
| ... | ... | @@ -16619,34 +16028,7 @@ fn zirThis( |
| 16619 | 16028 | extended: Zir.Inst.Extended.InstData, |
| 16620 | 16029 | ) CompileError!Air.Inst.Ref { |
| 16621 | 16030 | _ = extended; |
| 16622 | const pt = sema.pt; | |
| 16623 | const zcu = pt.zcu; | |
| 16624 | const namespace = pt.zcu.namespacePtr(block.namespace); | |
| 16625 | ||
| 16626 | switch (pt.zcu.intern_pool.indexToKey(namespace.owner_type)) { | |
| 16627 | .opaque_type => { | |
| 16628 | // Opaque types are never outdated since they don't undergo type resolution, so nothing to do! | |
| 16629 | return Air.internedToRef(namespace.owner_type); | |
| 16630 | }, | |
| 16631 | .struct_type, .union_type => { | |
| 16632 | const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type); | |
| 16633 | try sema.declareDependency(.{ .interned = new_ty }); | |
| 16634 | return Air.internedToRef(new_ty); | |
| 16635 | }, | |
| 16636 | .enum_type => { | |
| 16637 | const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type); | |
| 16638 | try sema.declareDependency(.{ .interned = new_ty }); | |
| 16639 | // Since this is an enum, it has to be resolved immediately. | |
| 16640 | // `ensureTypeUpToDate` has resolved the new type if necessary. | |
| 16641 | // We just need to check for resolution failures. | |
| 16642 | const ty_unit: AnalUnit = .wrap(.{ .type = new_ty }); | |
| 16643 | if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) { | |
| 16644 | return error.AnalysisFail; | |
| 16645 | } | |
| 16646 | return Air.internedToRef(new_ty); | |
| 16647 | }, | |
| 16648 | else => unreachable, | |
| 16649 | } | |
| 16031 | return .fromIntern(sema.pt.zcu.namespacePtr(block.namespace).owner_type); | |
| 16650 | 16032 | } |
| 16651 | 16033 | |
| 16652 | 16034 | fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -16739,7 +16121,7 @@ fn zirRetAddr( |
| 16739 | 16121 | _ = sema; |
| 16740 | 16122 | _ = extended; |
| 16741 | 16123 | if (block.isComptime()) { |
| 16742 | // TODO: we could give a meaningful lazy value here. #14938 | |
| 16124 | // TODO: we could give a meaningful value here. #14938 | |
| 16743 | 16125 | return .zero_usize; |
| 16744 | 16126 | } else { |
| 16745 | 16127 | return block.addNoOp(.ret_addr); |
| ... | ... | @@ -16882,6 +16264,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16882 | 16264 | const type_info_ty = try sema.getBuiltinType(src, .Type); |
| 16883 | 16265 | const type_info_tag_ty = type_info_ty.unionTagType(zcu).?; |
| 16884 | 16266 | |
| 16267 | try sema.ensureLayoutResolved(ty, src, .type_info); | |
| 16268 | ||
| 16885 | 16269 | if (ty.typeDeclInst(zcu)) |type_decl_inst| { |
| 16886 | 16270 | try sema.declareDependency(.{ .namespace = type_decl_inst }); |
| 16887 | 16271 | } |
| ... | ... | @@ -16896,7 +16280,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16896 | 16280 | .undefined, |
| 16897 | 16281 | .null, |
| 16898 | 16282 | .enum_literal, |
| 16899 | => |type_info_tag| return unionInitFromEnumTag(sema, block, src, type_info_ty, @intFromEnum(type_info_tag), .void_value), | |
| 16283 | => |type_info_tag| return .fromValue(try pt.unionValue( | |
| 16284 | type_info_ty, | |
| 16285 | Value.uninterpret(type_info_tag, type_info_tag_ty, pt) catch |err| switch (err) { | |
| 16286 | error.TypeMismatch => @panic("std.builtin is corrupt"), | |
| 16287 | error.OutOfMemory => |e| return e, | |
| 16288 | }, | |
| 16289 | .void, | |
| 16290 | )), | |
| 16900 | 16291 | |
| 16901 | 16292 | .@"fn" => { |
| 16902 | 16293 | const fn_info_ty = try sema.getBuiltinType(src, .@"Type.Fn"); |
| ... | ... | @@ -16904,19 +16295,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16904 | 16295 | |
| 16905 | 16296 | const func_ty_info = zcu.typeToFunc(ty).?; |
| 16906 | 16297 | const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); |
| 16907 | for (param_vals, 0..) |*param_val, i| { | |
| 16908 | const param_ty = func_ty_info.param_types.get(ip)[i]; | |
| 16298 | var func_is_generic = false; | |
| 16299 | ||
| 16300 | for (param_vals, 0..) |*param_val, param_index| { | |
| 16301 | const param_ty = func_ty_info.param_types.get(ip)[param_index]; | |
| 16909 | 16302 | const is_generic = param_ty == .generic_poison_type; |
| 16303 | const is_noalias, const is_comptime = flags: { | |
| 16304 | const i = std.math.cast(u5, param_index) orelse break :flags .{ false, false }; | |
| 16305 | break :flags .{ func_ty_info.paramIsNoalias(i), func_ty_info.paramIsComptime(i) }; | |
| 16306 | }; | |
| 16307 | ||
| 16308 | if (is_generic or is_comptime or Type.fromInterned(param_ty).comptimeOnly(zcu)) { | |
| 16309 | func_is_generic = true; | |
| 16310 | } | |
| 16311 | ||
| 16910 | 16312 | const param_ty_val = try pt.intern(.{ .opt = .{ |
| 16911 | 16313 | .ty = try pt.intern(.{ .opt_type = .type_type }), |
| 16912 | 16314 | .val = if (is_generic) .none else param_ty, |
| 16913 | 16315 | } }); |
| 16914 | 16316 | |
| 16915 | const is_noalias = blk: { | |
| 16916 | const index = std.math.cast(u5, i) orelse break :blk false; | |
| 16917 | break :blk @as(u1, @truncate(func_ty_info.noalias_bits >> index)) != 0; | |
| 16918 | }; | |
| 16919 | ||
| 16920 | 16317 | const param_fields = .{ |
| 16921 | 16318 | // is_generic: bool, |
| 16922 | 16319 | Value.makeBool(is_generic).toIntern(), |
| ... | ... | @@ -16934,7 +16331,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16934 | 16331 | .child = param_info_ty.toIntern(), |
| 16935 | 16332 | }); |
| 16936 | 16333 | const new_decl_val = (try pt.aggregateValue(new_decl_ty, param_vals)).toIntern(); |
| 16937 | const slice_ty = (try pt.ptrTypeSema(.{ | |
| 16334 | const slice_ty = (try pt.ptrType(.{ | |
| 16938 | 16335 | .child = param_info_ty.toIntern(), |
| 16939 | 16336 | .flags = .{ |
| 16940 | 16337 | .size = .slice, |
| ... | ... | @@ -16956,18 +16353,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16956 | 16353 | } }); |
| 16957 | 16354 | }; |
| 16958 | 16355 | |
| 16356 | const ret_ty_is_generic = generic: { | |
| 16357 | const ret_ty: Type = .fromInterned(func_ty_info.return_type); | |
| 16358 | if (ret_ty.toIntern() == .generic_poison_type or | |
| 16359 | (ret_ty.zigTypeTag(zcu) == .error_union and | |
| 16360 | ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type)) | |
| 16361 | { | |
| 16362 | break :generic true; | |
| 16363 | } | |
| 16364 | break :generic false; | |
| 16365 | }; | |
| 16366 | if (ret_ty_is_generic or Type.fromInterned(func_ty_info.return_type).comptimeOnly(zcu)) { | |
| 16367 | func_is_generic = true; | |
| 16368 | } | |
| 16369 | ||
| 16959 | 16370 | const ret_ty_opt = try pt.intern(.{ .opt = .{ |
| 16960 | 16371 | .ty = try pt.intern(.{ .opt_type = .type_type }), |
| 16961 | .val = opt_val: { | |
| 16962 | const ret_ty: Type = .fromInterned(func_ty_info.return_type); | |
| 16963 | if (ret_ty.toIntern() == .generic_poison_type) break :opt_val .none; | |
| 16964 | if (ret_ty.zigTypeTag(zcu) == .error_union) { | |
| 16965 | if (ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) { | |
| 16966 | break :opt_val .none; | |
| 16967 | } | |
| 16968 | } | |
| 16969 | break :opt_val ret_ty.toIntern(); | |
| 16970 | }, | |
| 16372 | .val = if (ret_ty_is_generic) .none else func_ty_info.return_type, | |
| 16971 | 16373 | } }); |
| 16972 | 16374 | |
| 16973 | 16375 | const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); |
| ... | ... | @@ -16980,7 +16382,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16980 | 16382 | // calling_convention: CallingConvention, |
| 16981 | 16383 | callconv_val.toIntern(), |
| 16982 | 16384 | // is_generic: bool, |
| 16983 | Value.makeBool(func_ty_info.is_generic).toIntern(), | |
| 16385 | Value.makeBool(func_is_generic).toIntern(), | |
| 16984 | 16386 | // is_var_args: bool, |
| 16985 | 16387 | Value.makeBool(func_ty_info.is_var_args).toIntern(), |
| 16986 | 16388 | // return_type: ?type, |
| ... | ... | @@ -17015,7 +16417,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17015 | 16417 | |
| 17016 | 16418 | const field_vals = .{ |
| 17017 | 16419 | // bits: u16, |
| 17018 | (try pt.intValue(.u16, ty.bitSize(zcu))).toIntern(), | |
| 16420 | (try pt.intValue(.u16, ty.floatBits(zcu.getTarget()))).toIntern(), | |
| 17019 | 16421 | }; |
| 17020 | 16422 | return Air.internedToRef((try pt.internUnion(.{ |
| 17021 | 16423 | .ty = type_info_ty.toIntern(), |
| ... | ... | @@ -17025,10 +16427,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17025 | 16427 | }, |
| 17026 | 16428 | .pointer => { |
| 17027 | 16429 | const info = ty.ptrInfo(zcu); |
| 17028 | const alignment = if (info.flags.alignment.toByteUnits()) |alignment| | |
| 17029 | try pt.intValue(.comptime_int, alignment) | |
| 17030 | else | |
| 17031 | try Type.fromInterned(info.child).lazyAbiAlignment(pt); | |
| 16430 | const alignment_ty = try pt.optionalType(.usize_type); | |
| 16431 | const alignment_val: Value = val: { | |
| 16432 | const bytes = info.flags.alignment.toByteUnits() orelse { | |
| 16433 | break :val try pt.nullValue(alignment_ty); | |
| 16434 | }; | |
| 16435 | const int_val = try pt.intValue(.usize, bytes); | |
| 16436 | break :val .fromInterned(try pt.intern(.{ .opt = .{ | |
| 16437 | .ty = alignment_ty.toIntern(), | |
| 16438 | .val = int_val.toIntern(), | |
| 16439 | } })); | |
| 16440 | }; | |
| 17032 | 16441 | |
| 17033 | 16442 | const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); |
| 17034 | 16443 | const pointer_ty = try sema.getBuiltinType(src, .@"Type.Pointer"); |
| ... | ... | @@ -17041,8 +16450,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17041 | 16450 | Value.makeBool(info.flags.is_const).toIntern(), |
| 17042 | 16451 | // is_volatile: bool, |
| 17043 | 16452 | Value.makeBool(info.flags.is_volatile).toIntern(), |
| 17044 | // alignment: comptime_int, | |
| 17045 | alignment.toIntern(), | |
| 16453 | // alignment: ?usize, | |
| 16454 | alignment_val.toIntern(), | |
| 17046 | 16455 | // address_space: AddressSpace |
| 17047 | 16456 | (try pt.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(), |
| 17048 | 16457 | // child: type, |
| ... | ... | @@ -17159,7 +16568,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17159 | 16568 | }; |
| 17160 | 16569 | |
| 17161 | 16570 | // Build our ?[]const Error value |
| 17162 | const slice_errors_ty = try pt.ptrTypeSema(.{ | |
| 16571 | const slice_errors_ty = try pt.ptrType(.{ | |
| 17163 | 16572 | .child = error_field_ty.toIntern(), |
| 17164 | 16573 | .flags = .{ |
| 17165 | 16574 | .size = .slice, |
| ... | ... | @@ -17215,19 +16624,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17215 | 16624 | }))); |
| 17216 | 16625 | }, |
| 17217 | 16626 | .@"enum" => { |
| 17218 | const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive); | |
| 16627 | const enum_obj = ip.loadEnumType(ty.toIntern()); | |
| 16628 | const is_exhaustive: Value = .makeBool(!enum_obj.nonexhaustive); | |
| 17219 | 16629 | |
| 17220 | 16630 | const enum_field_ty = try sema.getBuiltinType(src, .@"Type.EnumField"); |
| 17221 | 16631 | |
| 17222 | const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len); | |
| 16632 | const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_obj.field_names.len); | |
| 17223 | 16633 | for (enum_field_vals, 0..) |*field_val, tag_index| { |
| 17224 | const enum_type = ip.loadEnumType(ty.toIntern()); | |
| 17225 | const value_val = if (enum_type.values.len > 0) | |
| 16634 | const value_val = if (enum_obj.field_values.len > 0) | |
| 17226 | 16635 | try ip.getCoercedInts( |
| 17227 | 16636 | gpa, |
| 17228 | 16637 | io, |
| 17229 | 16638 | pt.tid, |
| 17230 | ip.indexToKey(enum_type.values.get(ip)[tag_index]).int, | |
| 16639 | ip.indexToKey(enum_obj.field_values.get(ip)[tag_index]).int, | |
| 17231 | 16640 | .comptime_int_type, |
| 17232 | 16641 | ) |
| 17233 | 16642 | else |
| ... | ... | @@ -17235,7 +16644,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17235 | 16644 | |
| 17236 | 16645 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 17237 | 16646 | const name_val = v: { |
| 17238 | const tag_name = enum_type.names.get(ip)[tag_index]; | |
| 16647 | const tag_name = enum_obj.field_names.get(ip)[tag_index]; | |
| 17239 | 16648 | const tag_name_len = tag_name.length(ip); |
| 17240 | 16649 | const new_decl_ty = try pt.arrayType(.{ |
| 17241 | 16650 | .len = tag_name_len, |
| ... | ... | @@ -17275,7 +16684,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17275 | 16684 | .child = enum_field_ty.toIntern(), |
| 17276 | 16685 | }); |
| 17277 | 16686 | const new_decl_val = (try pt.aggregateValue(fields_array_ty, enum_field_vals)).toIntern(); |
| 17278 | const slice_ty = (try pt.ptrTypeSema(.{ | |
| 16687 | const slice_ty = (try pt.ptrType(.{ | |
| 17279 | 16688 | .child = enum_field_ty.toIntern(), |
| 17280 | 16689 | .flags = .{ |
| 17281 | 16690 | .size = .slice, |
| ... | ... | @@ -17303,7 +16712,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17303 | 16712 | |
| 17304 | 16713 | const field_values = .{ |
| 17305 | 16714 | // tag_type: type, |
| 17306 | ip.loadEnumType(ty.toIntern()).tag_ty, | |
| 16715 | ip.loadEnumType(ty.toIntern()).int_tag_type, | |
| 17307 | 16716 | // fields: []const EnumField, |
| 17308 | 16717 | fields_val, |
| 17309 | 16718 | // decls: []const Declaration, |
| ... | ... | @@ -17321,17 +16730,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17321 | 16730 | const type_union_ty = try sema.getBuiltinType(src, .@"Type.Union"); |
| 17322 | 16731 | const union_field_ty = try sema.getBuiltinType(src, .@"Type.UnionField"); |
| 17323 | 16732 | |
| 17324 | try ty.resolveLayout(pt); // Getting alignment requires type layout | |
| 17325 | const union_obj = zcu.typeToUnion(ty).?; | |
| 17326 | const tag_type = union_obj.loadTagType(ip); | |
| 17327 | const layout = union_obj.flagsUnordered(ip).layout; | |
| 16733 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 16734 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | |
| 16735 | const layout = union_obj.layout; | |
| 17328 | 16736 | |
| 17329 | const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len); | |
| 16737 | const union_field_vals = try gpa.alloc(InternPool.Index, enum_obj.field_names.len); | |
| 17330 | 16738 | defer gpa.free(union_field_vals); |
| 17331 | 16739 | |
| 17332 | 16740 | for (union_field_vals, 0..) |*field_val, field_index| { |
| 17333 | 16741 | const name_val = v: { |
| 17334 | const field_name = tag_type.names.get(ip)[field_index]; | |
| 16742 | const field_name = enum_obj.field_names.get(ip)[field_index]; | |
| 17335 | 16743 | const field_name_len = field_name.length(ip); |
| 17336 | 16744 | const new_decl_ty = try pt.arrayType(.{ |
| 17337 | 16745 | .len = field_name_len, |
| ... | ... | @@ -17356,19 +16764,31 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17356 | 16764 | } }); |
| 17357 | 16765 | }; |
| 17358 | 16766 | |
| 17359 | const alignment = switch (layout) { | |
| 17360 | .auto, .@"extern" => try ty.fieldAlignmentSema(field_index, pt), | |
| 17361 | .@"packed" => .none, | |
| 16767 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 16768 | ||
| 16769 | const alignment_ty = try pt.optionalType(.usize_type); | |
| 16770 | const alignment_val: Value = val: { | |
| 16771 | const a: Alignment = switch (layout) { | |
| 16772 | .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), | |
| 16773 | .@"packed" => .none, | |
| 16774 | }; | |
| 16775 | const bytes = a.toByteUnits() orelse { | |
| 16776 | break :val try pt.nullValue(alignment_ty); | |
| 16777 | }; | |
| 16778 | const int_val = try pt.intValue(.usize, bytes); | |
| 16779 | break :val .fromInterned(try pt.intern(.{ .opt = .{ | |
| 16780 | .ty = alignment_ty.toIntern(), | |
| 16781 | .val = int_val.toIntern(), | |
| 16782 | } })); | |
| 17362 | 16783 | }; |
| 17363 | 16784 | |
| 17364 | const field_ty = union_obj.field_types.get(ip)[field_index]; | |
| 17365 | 16785 | const union_field_fields = .{ |
| 17366 | 16786 | // name: [:0]const u8, |
| 17367 | 16787 | name_val, |
| 17368 | 16788 | // type: type, |
| 17369 | field_ty, | |
| 17370 | // alignment: comptime_int, | |
| 17371 | (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), | |
| 16789 | field_ty.toIntern(), | |
| 16790 | // alignment: ?usize, | |
| 16791 | alignment_val.toIntern(), | |
| 17372 | 16792 | }; |
| 17373 | 16793 | field_val.* = (try pt.aggregateValue(union_field_ty, &union_field_fields)).toIntern(); |
| 17374 | 16794 | } |
| ... | ... | @@ -17379,7 +16799,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17379 | 16799 | .child = union_field_ty.toIntern(), |
| 17380 | 16800 | }); |
| 17381 | 16801 | const new_decl_val = (try pt.aggregateValue(array_fields_ty, union_field_vals)).toIntern(); |
| 17382 | const slice_ty = (try pt.ptrTypeSema(.{ | |
| 16802 | const slice_ty = (try pt.ptrType(.{ | |
| 17383 | 16803 | .child = union_field_ty.toIntern(), |
| 17384 | 16804 | .flags = .{ |
| 17385 | 16805 | .size = .slice, |
| ... | ... | @@ -17431,8 +16851,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17431 | 16851 | const type_struct_ty = try sema.getBuiltinType(src, .@"Type.Struct"); |
| 17432 | 16852 | const struct_field_ty = try sema.getBuiltinType(src, .@"Type.StructField"); |
| 17433 | 16853 | |
| 17434 | try ty.resolveLayout(pt); // Getting alignment requires type layout | |
| 17435 | ||
| 17436 | 16854 | var struct_field_vals: []InternPool.Index = &.{}; |
| 17437 | 16855 | defer gpa.free(struct_field_vals); |
| 17438 | 16856 | fv: { |
| ... | ... | @@ -17468,11 +16886,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17468 | 16886 | } }); |
| 17469 | 16887 | }; |
| 17470 | 16888 | |
| 17471 | try Type.fromInterned(field_ty).resolveLayout(pt); | |
| 17472 | ||
| 17473 | 16889 | const is_comptime = field_val != .none; |
| 17474 | 16890 | const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null; |
| 17475 | 16891 | const default_val_ptr = try sema.optRefValue(opt_default_val); |
| 16892 | ||
| 17476 | 16893 | const struct_field_fields = .{ |
| 17477 | 16894 | // name: [:0]const u8, |
| 17478 | 16895 | name_val, |
| ... | ... | @@ -17482,8 +16899,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17482 | 16899 | default_val_ptr.toIntern(), |
| 17483 | 16900 | // is_comptime: bool, |
| 17484 | 16901 | Value.makeBool(is_comptime).toIntern(), |
| 17485 | // alignment: comptime_int, | |
| 17486 | (try pt.intValue(.comptime_int, Type.fromInterned(field_ty).abiAlignment(zcu).toByteUnits() orelse 0)).toIntern(), | |
| 16902 | // alignment: ?usize, | |
| 16903 | (try pt.nullValue(try pt.optionalType(.usize_type))).toIntern(), | |
| 17487 | 16904 | }; |
| 17488 | 16905 | struct_field_val.* = (try pt.aggregateValue(struct_field_ty, &struct_field_fields)).toIntern(); |
| 17489 | 16906 | } |
| ... | ... | @@ -17492,16 +16909,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17492 | 16909 | .struct_type => ip.loadStructType(ty.toIntern()), |
| 17493 | 16910 | else => unreachable, |
| 17494 | 16911 | }; |
| 16912 | try sema.ensureStructDefaultsResolved(ty, src); // can't do this sooner, since it's not allowed on tuples | |
| 17495 | 16913 | struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); |
| 17496 | 16914 | |
| 17497 | try ty.resolveStructFieldInits(pt); | |
| 17498 | ||
| 17499 | 16915 | for (struct_field_vals, 0..) |*field_val, field_index| { |
| 17500 | const field_name = struct_type.fieldName(ip, field_index); | |
| 16916 | const field_name = struct_type.field_names.get(ip)[field_index]; | |
| 17501 | 16917 | const field_name_len = field_name.length(ip); |
| 17502 | 16918 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 17503 | const field_init = struct_type.fieldInit(ip, field_index); | |
| 17504 | const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); | |
| 16919 | const field_default: InternPool.Index = if (struct_type.field_defaults.len > 0) d: { | |
| 16920 | break :d struct_type.field_defaults.get(ip)[field_index]; | |
| 16921 | } else .none; | |
| 16922 | const field_is_comptime = struct_type.field_is_comptime_bits.get(ip, field_index); | |
| 17505 | 16923 | const name_val = v: { |
| 17506 | 16924 | const new_decl_ty = try pt.arrayType(.{ |
| 17507 | 16925 | .len = field_name_len, |
| ... | ... | @@ -17526,15 +16944,23 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17526 | 16944 | } }); |
| 17527 | 16945 | }; |
| 17528 | 16946 | |
| 17529 | const opt_default_val = if (field_init == .none) null else Value.fromInterned(field_init); | |
| 16947 | const opt_default_val: ?Value = if (field_default == .none) null else .fromInterned(field_default); | |
| 17530 | 16948 | const default_val_ptr = try sema.optRefValue(opt_default_val); |
| 17531 | const alignment = switch (struct_type.layout) { | |
| 17532 | .@"packed" => .none, | |
| 17533 | else => try field_ty.structFieldAlignmentSema( | |
| 17534 | struct_type.fieldAlign(ip, field_index), | |
| 17535 | struct_type.layout, | |
| 17536 | pt, | |
| 17537 | ), | |
| 16949 | ||
| 16950 | const alignment_ty = try pt.optionalType(.usize_type); | |
| 16951 | const alignment_val: Value = val: { | |
| 16952 | const a: Alignment = switch (struct_type.layout) { | |
| 16953 | .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), | |
| 16954 | .@"packed" => .none, | |
| 16955 | }; | |
| 16956 | const bytes = a.toByteUnits() orelse { | |
| 16957 | break :val try pt.nullValue(alignment_ty); | |
| 16958 | }; | |
| 16959 | const int_val = try pt.intValue(.usize, bytes); | |
| 16960 | break :val .fromInterned(try pt.intern(.{ .opt = .{ | |
| 16961 | .ty = alignment_ty.toIntern(), | |
| 16962 | .val = int_val.toIntern(), | |
| 16963 | } })); | |
| 17538 | 16964 | }; |
| 17539 | 16965 | |
| 17540 | 16966 | const struct_field_fields = .{ |
| ... | ... | @@ -17546,8 +16972,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17546 | 16972 | default_val_ptr.toIntern(), |
| 17547 | 16973 | // is_comptime: bool, |
| 17548 | 16974 | Value.makeBool(field_is_comptime).toIntern(), |
| 17549 | // alignment: comptime_int, | |
| 17550 | (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), | |
| 16975 | // alignment: ?usize, | |
| 16976 | alignment_val.toIntern(), | |
| 17551 | 16977 | }; |
| 17552 | 16978 | field_val.* = (try pt.aggregateValue(struct_field_ty, &struct_field_fields)).toIntern(); |
| 17553 | 16979 | } |
| ... | ... | @@ -17559,7 +16985,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17559 | 16985 | .child = struct_field_ty.toIntern(), |
| 17560 | 16986 | }); |
| 17561 | 16987 | const new_decl_val = (try pt.aggregateValue(array_fields_ty, struct_field_vals)).toIntern(); |
| 17562 | const slice_ty = (try pt.ptrTypeSema(.{ | |
| 16988 | const slice_ty = (try pt.ptrType(.{ | |
| 17563 | 16989 | .child = struct_field_ty.toIntern(), |
| 17564 | 16990 | .flags = .{ |
| 17565 | 16991 | .size = .slice, |
| ... | ... | @@ -17585,9 +17011,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17585 | 17011 | |
| 17586 | 17012 | const backing_integer_val = try pt.intern(.{ .opt = .{ |
| 17587 | 17013 | .ty = (try pt.optionalType(.type_type)).toIntern(), |
| 17588 | .val = if (zcu.typeToPackedStruct(ty)) |packed_struct| val: { | |
| 17589 | assert(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)).isInt(zcu)); | |
| 17590 | break :val packed_struct.backingIntTypeUnordered(ip); | |
| 17014 | .val = if (zcu.typeToPackedStruct(ty)) |struct_obj| val: { | |
| 17015 | assert(Type.fromInterned(struct_obj.packed_backing_int_type).isInt(zcu)); | |
| 17016 | break :val struct_obj.packed_backing_int_type; | |
| 17591 | 17017 | } else .none, |
| 17592 | 17018 | } }); |
| 17593 | 17019 | |
| ... | ... | @@ -17616,7 +17042,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17616 | 17042 | .@"opaque" => { |
| 17617 | 17043 | const type_opaque_ty = try sema.getBuiltinType(src, .@"Type.Opaque"); |
| 17618 | 17044 | |
| 17619 | try ty.resolveFields(pt); | |
| 17620 | 17045 | const decls_val = try sema.typeInfoDecls(src, ty.getNamespace(zcu)); |
| 17621 | 17046 | |
| 17622 | 17047 | const field_values = .{ |
| ... | ... | @@ -17658,7 +17083,7 @@ fn typeInfoDecls( |
| 17658 | 17083 | .child = declaration_ty.toIntern(), |
| 17659 | 17084 | }); |
| 17660 | 17085 | const new_decl_val = (try pt.aggregateValue(array_decl_ty, decl_vals.items)).toIntern(); |
| 17661 | const slice_ty = (try pt.ptrTypeSema(.{ | |
| 17086 | const slice_ty = (try pt.ptrType(.{ | |
| 17662 | 17087 | .child = declaration_ty.toIntern(), |
| 17663 | 17088 | .flags = .{ |
| 17664 | 17089 | .size = .slice, |
| ... | ... | @@ -17740,7 +17165,7 @@ fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 17740 | 17165 | _ = block; |
| 17741 | 17166 | const zir_datas = sema.code.instructions.items(.data); |
| 17742 | 17167 | const inst_data = zir_datas[@intFromEnum(inst)].un_node; |
| 17743 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17168 | const operand = sema.resolveInst(inst_data.operand); | |
| 17744 | 17169 | const operand_ty = sema.typeOf(operand); |
| 17745 | 17170 | return Air.internedToRef(operand_ty.toIntern()); |
| 17746 | 17171 | } |
| ... | ... | @@ -17754,7 +17179,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 17754 | 17179 | .parent = block, |
| 17755 | 17180 | .sema = sema, |
| 17756 | 17181 | .namespace = block.namespace, |
| 17757 | .instructions = .{}, | |
| 17182 | .instructions = .empty, | |
| 17758 | 17183 | .inlining = block.inlining, |
| 17759 | 17184 | .comptime_reason = null, |
| 17760 | 17185 | .is_typeof = true, |
| ... | ... | @@ -17772,7 +17197,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 17772 | 17197 | fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 17773 | 17198 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 17774 | 17199 | const src = block.nodeOffset(inst_data.src_node); |
| 17775 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17200 | const operand = sema.resolveInst(inst_data.operand); | |
| 17776 | 17201 | const operand_ty = sema.typeOf(operand); |
| 17777 | 17202 | const res_ty = try sema.log2IntType(block, operand_ty, src); |
| 17778 | 17203 | return Air.internedToRef(res_ty.toIntern()); |
| ... | ... | @@ -17783,22 +17208,12 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi |
| 17783 | 17208 | const zcu = pt.zcu; |
| 17784 | 17209 | switch (operand.zigTypeTag(zcu)) { |
| 17785 | 17210 | .comptime_int => return .comptime_int, |
| 17786 | .int => { | |
| 17787 | const bits = operand.bitSize(zcu); | |
| 17788 | const count = if (bits == 0) | |
| 17789 | 0 | |
| 17790 | else blk: { | |
| 17791 | var count: u16 = 0; | |
| 17792 | var s = bits - 1; | |
| 17793 | while (s != 0) : (s >>= 1) { | |
| 17794 | count += 1; | |
| 17795 | } | |
| 17796 | break :blk count; | |
| 17797 | }; | |
| 17798 | return pt.intType(.unsigned, count); | |
| 17799 | }, | |
| 17211 | .int => return pt.intType(.unsigned, switch (operand.intInfo(zcu).bits) { | |
| 17212 | 0 => 0, | |
| 17213 | else => |b| std.math.log2_int_ceil(u16, b), | |
| 17214 | }), | |
| 17800 | 17215 | .vector => { |
| 17801 | const elem_ty = operand.elemType2(zcu); | |
| 17216 | const elem_ty = operand.childType(zcu); | |
| 17802 | 17217 | const log2_elem_ty = try sema.log2IntType(block, elem_ty, src); |
| 17803 | 17218 | return pt.vectorType(.{ |
| 17804 | 17219 | .len = operand.vectorLen(zcu), |
| ... | ... | @@ -17832,7 +17247,7 @@ fn zirTypeofPeer( |
| 17832 | 17247 | .parent = block, |
| 17833 | 17248 | .sema = sema, |
| 17834 | 17249 | .namespace = block.namespace, |
| 17835 | .instructions = .{}, | |
| 17250 | .instructions = .empty, | |
| 17836 | 17251 | .inlining = block.inlining, |
| 17837 | 17252 | .comptime_reason = null, |
| 17838 | 17253 | .is_typeof = true, |
| ... | ... | @@ -17852,7 +17267,7 @@ fn zirTypeofPeer( |
| 17852 | 17267 | defer sema.gpa.free(inst_list); |
| 17853 | 17268 | |
| 17854 | 17269 | for (args, 0..) |arg_ref, i| { |
| 17855 | inst_list[i] = try sema.resolveInst(arg_ref); | |
| 17270 | inst_list[i] = sema.resolveInst(arg_ref); | |
| 17856 | 17271 | } |
| 17857 | 17272 | |
| 17858 | 17273 | const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node }); |
| ... | ... | @@ -17865,7 +17280,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17865 | 17280 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 17866 | 17281 | const src = block.nodeOffset(inst_data.src_node); |
| 17867 | 17282 | const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); |
| 17868 | const uncasted_operand = try sema.resolveInst(inst_data.operand); | |
| 17283 | const uncasted_operand = sema.resolveInst(inst_data.operand); | |
| 17869 | 17284 | const uncasted_ty = sema.typeOf(uncasted_operand); |
| 17870 | 17285 | if (uncasted_ty.isVector(zcu)) { |
| 17871 | 17286 | if (uncasted_ty.scalarType(zcu).zigTypeTag(zcu) != .bool) { |
| ... | ... | @@ -17876,7 +17291,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17876 | 17291 | return analyzeBitNot(sema, block, uncasted_operand, src); |
| 17877 | 17292 | } |
| 17878 | 17293 | const operand = try sema.coerce(block, .bool, uncasted_operand, operand_src); |
| 17879 | if (try sema.resolveValue(operand)) |val| { | |
| 17294 | if (sema.resolveValue(operand)) |val| { | |
| 17880 | 17295 | return if (val.isUndef(zcu)) .undef_bool else if (val.toBool()) .bool_false else .bool_true; |
| 17881 | 17296 | } |
| 17882 | 17297 | try sema.requireRuntimeBlock(block, src, null); |
| ... | ... | @@ -17900,7 +17315,7 @@ fn zirBoolBr( |
| 17900 | 17315 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 17901 | 17316 | const extra = sema.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index); |
| 17902 | 17317 | |
| 17903 | const uncoerced_lhs = try sema.resolveInst(extra.data.lhs); | |
| 17318 | const uncoerced_lhs = sema.resolveInst(extra.data.lhs); | |
| 17904 | 17319 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 17905 | 17320 | const lhs_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 17906 | 17321 | const rhs_src = parent_block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| ... | ... | @@ -18063,9 +17478,9 @@ fn zirIsNonNull( |
| 18063 | 17478 | |
| 18064 | 17479 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18065 | 17480 | const src = block.nodeOffset(inst_data.src_node); |
| 18066 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17481 | const operand = sema.resolveInst(inst_data.operand); | |
| 18067 | 17482 | try sema.checkNullableType(block, src, sema.typeOf(operand)); |
| 18068 | return sema.analyzeIsNull(block, operand, true); | |
| 17483 | return sema.analyzeIsNull(block, src, operand, true); | |
| 18069 | 17484 | } |
| 18070 | 17485 | |
| 18071 | 17486 | fn zirIsNonNullPtr( |
| ... | ... | @@ -18080,17 +17495,23 @@ fn zirIsNonNullPtr( |
| 18080 | 17495 | const zcu = pt.zcu; |
| 18081 | 17496 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18082 | 17497 | const src = block.nodeOffset(inst_data.src_node); |
| 18083 | const ptr = try sema.resolveInst(inst_data.operand); | |
| 17498 | const ptr = sema.resolveInst(inst_data.operand); | |
| 18084 | 17499 | const ptr_ty = sema.typeOf(ptr); |
| 18085 | try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2(zcu)); | |
| 18086 | if (try sema.resolveValue(ptr)) |ptr_val| { | |
| 18087 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |loaded_val| { | |
| 18088 | return sema.analyzeIsNull(block, Air.internedToRef(loaded_val.toIntern()), true); | |
| 18089 | } | |
| 17500 | assert(ptr_ty.zigTypeTag(zcu) == .pointer); | |
| 17501 | const nullable_ty = ptr_ty.childType(zcu); | |
| 17502 | ||
| 17503 | try sema.checkNullableType(block, src, nullable_ty); | |
| 17504 | ||
| 17505 | if (try sema.resolveIsNullFromType(block, src, nullable_ty)) |is_null| { | |
| 17506 | return .fromValue(.makeBool(!is_null)); | |
| 18090 | 17507 | } |
| 18091 | if (ptr_ty.childType(zcu).isNullFromType(zcu)) |is_null| { | |
| 18092 | return if (is_null) .bool_false else .bool_true; | |
| 17508 | ||
| 17509 | if (sema.resolveValue(ptr)) |ptr_val| { | |
| 17510 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |nullable_val| { | |
| 17511 | return sema.analyzeIsNull(block, src, .fromValue(nullable_val), true); | |
| 17512 | } | |
| 18093 | 17513 | } |
| 17514 | ||
| 18094 | 17515 | return block.addUnOp(.is_non_null_ptr, ptr); |
| 18095 | 17516 | } |
| 18096 | 17517 | |
| ... | ... | @@ -18111,7 +17532,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18111 | 17532 | |
| 18112 | 17533 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18113 | 17534 | const src = block.nodeOffset(inst_data.src_node); |
| 18114 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17535 | const operand = sema.resolveInst(inst_data.operand); | |
| 18115 | 17536 | try sema.checkErrorType(block, src, sema.typeOf(operand)); |
| 18116 | 17537 | return sema.analyzeIsNonErr(block, src, operand); |
| 18117 | 17538 | } |
| ... | ... | @@ -18124,8 +17545,11 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 18124 | 17545 | const zcu = pt.zcu; |
| 18125 | 17546 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18126 | 17547 | const src = block.nodeOffset(inst_data.src_node); |
| 18127 | const ptr = try sema.resolveInst(inst_data.operand); | |
| 18128 | try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2(zcu)); | |
| 17548 | const ptr = sema.resolveInst(inst_data.operand); | |
| 17549 | const ptr_ty = sema.typeOf(ptr); | |
| 17550 | assert(ptr_ty.zigTypeTag(zcu) == .pointer); | |
| 17551 | const error_ty = ptr_ty.childType(zcu); | |
| 17552 | try sema.checkErrorType(block, src, error_ty); | |
| 18129 | 17553 | const loaded = try sema.analyzeLoad(block, src, ptr, src); |
| 18130 | 17554 | return sema.analyzeIsNonErr(block, src, loaded); |
| 18131 | 17555 | } |
| ... | ... | @@ -18136,7 +17560,7 @@ fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 18136 | 17560 | |
| 18137 | 17561 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18138 | 17562 | const src = block.nodeOffset(inst_data.src_node); |
| 18139 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17563 | const operand = sema.resolveInst(inst_data.operand); | |
| 18140 | 17564 | return sema.analyzeIsNonErr(block, src, operand); |
| 18141 | 17565 | } |
| 18142 | 17566 | |
| ... | ... | @@ -18157,7 +17581,7 @@ fn zirCondbr( |
| 18157 | 17581 | const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len); |
| 18158 | 17582 | const else_body = sema.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len); |
| 18159 | 17583 | |
| 18160 | const uncasted_cond = try sema.resolveInst(extra.data.condition); | |
| 17584 | const uncasted_cond = sema.resolveInst(extra.data.condition); | |
| 18161 | 17585 | const cond = try sema.coerce(parent_block, .bool, uncasted_cond, cond_src); |
| 18162 | 17586 | |
| 18163 | 17587 | if (try sema.resolveDefinedValue(parent_block, cond_src, cond)) |cond_val| { |
| ... | ... | @@ -18193,7 +17617,7 @@ fn zirCondbr( |
| 18193 | 17617 | if (sema.code.instructions.items(.tag)[@intFromEnum(index)] != .is_non_err) break :blk null; |
| 18194 | 17618 | |
| 18195 | 17619 | const err_inst_data = sema.code.instructions.items(.data)[@intFromEnum(index)].un_node; |
| 18196 | const err_operand = try sema.resolveInst(err_inst_data.operand); | |
| 17620 | const err_operand = sema.resolveInst(err_inst_data.operand); | |
| 18197 | 17621 | const operand_ty = sema.typeOf(err_operand); |
| 18198 | 17622 | assert(operand_ty.zigTypeTag(zcu) == .error_union); |
| 18199 | 17623 | const result_ty = operand_ty.errorUnionSet(zcu); |
| ... | ... | @@ -18241,7 +17665,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! |
| 18241 | 17665 | const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); |
| 18242 | 17666 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 18243 | 17667 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 18244 | const err_union = try sema.resolveInst(extra.data.operand); | |
| 17668 | const err_union = sema.resolveInst(extra.data.operand); | |
| 18245 | 17669 | const err_union_ty = sema.typeOf(err_union); |
| 18246 | 17670 | const pt = sema.pt; |
| 18247 | 17671 | const zcu = pt.zcu; |
| ... | ... | @@ -18294,6 +17718,11 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! |
| 18294 | 17718 | } }, |
| 18295 | 17719 | }); |
| 18296 | 17720 | sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items)); |
| 17721 | ||
| 17722 | // The payload type might still be OPV, in which case `try_inst` is just there for the runtime | |
| 17723 | // control flow and we should return a comptime-known result. | |
| 17724 | if (try err_union_ty.errorUnionPayload(zcu).onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 17725 | ||
| 18297 | 17726 | return try_inst; |
| 18298 | 17727 | } |
| 18299 | 17728 | |
| ... | ... | @@ -18303,7 +17732,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr |
| 18303 | 17732 | const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); |
| 18304 | 17733 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 18305 | 17734 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 18306 | const operand = try sema.resolveInst(extra.data.operand); | |
| 17735 | const operand = sema.resolveInst(extra.data.operand); | |
| 18307 | 17736 | const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src); |
| 18308 | 17737 | const err_union_ty = sema.typeOf(err_union); |
| 18309 | 17738 | const pt = sema.pt; |
| ... | ... | @@ -18347,7 +17776,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr |
| 18347 | 17776 | |
| 18348 | 17777 | const operand_ty = sema.typeOf(operand); |
| 18349 | 17778 | const ptr_info = operand_ty.ptrInfo(zcu); |
| 18350 | const res_ty = try pt.ptrTypeSema(.{ | |
| 17779 | const res_ty = try pt.ptrType(.{ | |
| 18351 | 17780 | .child = err_union_ty.errorUnionPayload(zcu).toIntern(), |
| 18352 | 17781 | .flags = .{ |
| 18353 | 17782 | .is_const = ptr_info.flags.is_const, |
| ... | ... | @@ -18396,9 +17825,9 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label |
| 18396 | 17825 | .label = .{ |
| 18397 | 17826 | .zir_block = dest_block, |
| 18398 | 17827 | .merges = .{ |
| 18399 | .src_locs = .{}, | |
| 18400 | .results = .{}, | |
| 18401 | .br_list = .{}, | |
| 17828 | .src_locs = .empty, | |
| 17829 | .results = .empty, | |
| 17830 | .br_list = .empty, | |
| 18402 | 17831 | .block_inst = new_block_inst, |
| 18403 | 17832 | }, |
| 18404 | 17833 | }, |
| ... | ... | @@ -18406,7 +17835,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label |
| 18406 | 17835 | .parent = block, |
| 18407 | 17836 | .sema = sema, |
| 18408 | 17837 | .namespace = block.namespace, |
| 18409 | .instructions = .{}, | |
| 17838 | .instructions = .empty, | |
| 18410 | 17839 | .label = &labeled_block.label, |
| 18411 | 17840 | .inlining = block.inlining, |
| 18412 | 17841 | .comptime_reason = block.comptime_reason, |
| ... | ... | @@ -18424,7 +17853,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label |
| 18424 | 17853 | fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, break_operand: Zir.Inst.Ref) !void { |
| 18425 | 17854 | const labeled_block = try sema.ensurePostHoc(child_block, block_inst); |
| 18426 | 17855 | |
| 18427 | const operand = try sema.resolveInst(break_operand); | |
| 17856 | const operand = sema.resolveInst(break_operand); | |
| 18428 | 17857 | const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand); |
| 18429 | 17858 | |
| 18430 | 17859 | try labeled_block.label.merges.results.append(sema.gpa, operand); |
| ... | ... | @@ -18510,9 +17939,9 @@ fn zirRetImplicit( |
| 18510 | 17939 | return; |
| 18511 | 17940 | } |
| 18512 | 17941 | |
| 18513 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17942 | const operand = sema.resolveInst(inst_data.operand); | |
| 18514 | 17943 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero }); |
| 18515 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu); | |
| 17944 | const base_tag = sema.fn_ret_ty.optEuBaseType(zcu).zigTypeTag(zcu); | |
| 18516 | 17945 | if (base_tag == .noreturn) { |
| 18517 | 17946 | const msg = msg: { |
| 18518 | 17947 | const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{ |
| ... | ... | @@ -18543,7 +17972,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi |
| 18543 | 17972 | defer tracy.end(); |
| 18544 | 17973 | |
| 18545 | 17974 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18546 | const operand = try sema.resolveInst(inst_data.operand); | |
| 17975 | const operand = sema.resolveInst(inst_data.operand); | |
| 18547 | 17976 | const src = block.nodeOffset(inst_data.src_node); |
| 18548 | 17977 | |
| 18549 | 17978 | return sema.analyzeRet(block, operand, src, block.src(.{ .node_offset_return_operand = inst_data.src_node })); |
| ... | ... | @@ -18555,7 +17984,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi |
| 18555 | 17984 | |
| 18556 | 17985 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 18557 | 17986 | const src = block.nodeOffset(inst_data.src_node); |
| 18558 | const ret_ptr = try sema.resolveInst(inst_data.operand); | |
| 17987 | const ret_ptr = sema.resolveInst(inst_data.operand); | |
| 18559 | 17988 | |
| 18560 | 17989 | if (block.isComptime() or block.inlining != null or sema.func_is_naked) { |
| 18561 | 17990 | const operand = try sema.analyzeLoad(block, src, ret_ptr, src); |
| ... | ... | @@ -18652,7 +18081,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 18652 | 18081 | if (block.isComptime() or block.is_typeof) return; |
| 18653 | 18082 | |
| 18654 | 18083 | const save_index = inst_data.operand == .none or b: { |
| 18655 | const operand = try sema.resolveInst(inst_data.operand); | |
| 18084 | const operand = sema.resolveInst(inst_data.operand); | |
| 18656 | 18085 | const operand_ty = sema.typeOf(operand); |
| 18657 | 18086 | break :b operand_ty.isError(zcu); |
| 18658 | 18087 | }; |
| ... | ... | @@ -18701,7 +18130,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_ |
| 18701 | 18130 | return; // No need to restore |
| 18702 | 18131 | }; |
| 18703 | 18132 | |
| 18704 | const operand = try sema.resolveInstAllowNone(operand_zir); | |
| 18133 | const operand = sema.resolveInstAllowNone(operand_zir); | |
| 18705 | 18134 | |
| 18706 | 18135 | if (start_block.isComptime() or start_block.is_typeof) { |
| 18707 | 18136 | const is_non_error = if (operand != .none) blk: { |
| ... | ... | @@ -18809,8 +18238,6 @@ fn analyzeRet( |
| 18809 | 18238 | return sema.failWithOwnedErrorMsg(block, msg); |
| 18810 | 18239 | } |
| 18811 | 18240 | |
| 18812 | try sema.fn_ret_ty.resolveLayout(pt); | |
| 18813 | ||
| 18814 | 18241 | try sema.validateRuntimeValue(block, operand_src, operand); |
| 18815 | 18242 | |
| 18816 | 18243 | const air_tag: Air.Inst.Tag = if (block.wantSafety()) .ret_safe else .ret; |
| ... | ... | @@ -18853,8 +18280,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18853 | 18280 | const hostsize_src = block.src(.{ .node_offset_ptr_hostsize = extra.data.src_node }); |
| 18854 | 18281 | |
| 18855 | 18282 | const elem_ty = blk: { |
| 18856 | const air_inst = try sema.resolveInst(extra.data.elem_type); | |
| 18857 | const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| { | |
| 18283 | const air_inst = sema.resolveInst(extra.data.elem_type); | |
| 18284 | const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| { | |
| 18858 | 18285 | if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) { |
| 18859 | 18286 | try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); |
| 18860 | 18287 | } |
| ... | ... | @@ -18874,7 +18301,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18874 | 18301 | const sentinel = if (inst_data.flags.has_sentinel) blk: { |
| 18875 | 18302 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 18876 | 18303 | extra_i += 1; |
| 18877 | const coerced = try sema.coerce(block, elem_ty, try sema.resolveInst(ref), sentinel_src); | |
| 18304 | const coerced = try sema.coerce(block, elem_ty, sema.resolveInst(ref), sentinel_src); | |
| 18878 | 18305 | const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel }); |
| 18879 | 18306 | try checkSentinelType(sema, block, sentinel_src, elem_ty); |
| 18880 | 18307 | if (val.canMutateComptimeVarState(zcu)) { |
| ... | ... | @@ -18887,18 +18314,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18887 | 18314 | const abi_align: Alignment = if (inst_data.flags.has_align) blk: { |
| 18888 | 18315 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 18889 | 18316 | extra_i += 1; |
| 18890 | const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src); | |
| 18317 | const coerced = try sema.coerce(block, align_ty, sema.resolveInst(ref), align_src); | |
| 18891 | 18318 | const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" }); |
| 18892 | // Check if this happens to be the lazy alignment of our element type, in | |
| 18893 | // which case we can make this 0 without resolving it. | |
| 18894 | switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 18895 | .int => |int| switch (int.storage) { | |
| 18896 | .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.toIntern()) break :blk .none, | |
| 18897 | else => {}, | |
| 18898 | }, | |
| 18899 | else => {}, | |
| 18900 | } | |
| 18901 | const align_bytes = (try val.getUnsignedIntSema(pt)).?; | |
| 18319 | const align_bytes = val.toUnsignedInt(zcu); | |
| 18902 | 18320 | break :blk try sema.validateAlign(block, align_src, align_bytes); |
| 18903 | 18321 | } else .none; |
| 18904 | 18322 | |
| ... | ... | @@ -18928,7 +18346,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18928 | 18346 | elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size, |
| 18929 | 18347 | }); |
| 18930 | 18348 | } |
| 18931 | const elem_bit_size = try elem_ty.bitSizeSema(pt); | |
| 18349 | try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .bit_ptr_child); | |
| 18350 | const elem_bit_size = elem_ty.bitSize(zcu); | |
| 18932 | 18351 | if (elem_bit_size > host_size * 8 - bit_offset) { |
| 18933 | 18352 | return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{ |
| 18934 | 18353 | elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size, |
| ... | ... | @@ -18942,31 +18361,18 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18942 | 18361 | } |
| 18943 | 18362 | } else if (inst_data.size != .one and elem_ty.zigTypeTag(zcu) == .@"opaque") { |
| 18944 | 18363 | return sema.fail(block, elem_ty_src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)}); |
| 18945 | } else if (inst_data.size == .c) { | |
| 18946 | if (!try sema.validateExternType(elem_ty, .other)) { | |
| 18947 | const msg = msg: { | |
| 18948 | const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); | |
| 18949 | errdefer msg.destroy(sema.gpa); | |
| 18950 | ||
| 18951 | try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other); | |
| 18952 | ||
| 18953 | try sema.addDeclaredHereNote(msg, elem_ty); | |
| 18954 | break :msg msg; | |
| 18955 | }; | |
| 18956 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 18957 | } | |
| 18958 | 18364 | } |
| 18959 | 18365 | |
| 18960 | if (host_size != 0 and !try sema.validatePackedType(elem_ty)) { | |
| 18961 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 18366 | if (host_size != 0) { | |
| 18367 | if (elem_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: { | |
| 18962 | 18368 | const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)}); |
| 18963 | 18369 | errdefer msg.destroy(sema.gpa); |
| 18964 | try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty); | |
| 18370 | try sema.explainWhyTypeIsUnpackable(msg, elem_ty_src, reason); | |
| 18965 | 18371 | break :msg msg; |
| 18966 | 18372 | }); |
| 18967 | 18373 | } |
| 18968 | 18374 | |
| 18969 | const ty = try pt.ptrTypeSema(.{ | |
| 18375 | const ty = try pt.ptrType(.{ | |
| 18970 | 18376 | .child = elem_ty.toIntern(), |
| 18971 | 18377 | .sentinel = sentinel, |
| 18972 | 18378 | .flags = .{ |
| ... | ... | @@ -18996,6 +18402,8 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 18996 | 18402 | const pt = sema.pt; |
| 18997 | 18403 | const zcu = pt.zcu; |
| 18998 | 18404 | |
| 18405 | try sema.ensureLayoutResolved(obj_ty, ty_src, .init); | |
| 18406 | ||
| 18999 | 18407 | switch (obj_ty.zigTypeTag(zcu)) { |
| 19000 | 18408 | .@"struct" => return sema.structInitEmpty(block, obj_ty, src, src), |
| 19001 | 18409 | .array, .vector => return sema.arrayInitEmpty(block, src, obj_ty), |
| ... | ... | @@ -19058,6 +18466,9 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is |
| 19058 | 18466 | .child = ptr_ty.childType(zcu).toIntern(), |
| 19059 | 18467 | }); |
| 19060 | 18468 | } else ty_operand; |
| 18469 | ||
| 18470 | try sema.ensureLayoutResolved(init_ty, src, .init); | |
| 18471 | ||
| 19061 | 18472 | const obj_ty = init_ty.optEuBaseType(zcu); |
| 19062 | 18473 | |
| 19063 | 18474 | const empty_ref = switch (obj_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -19069,13 +18480,13 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is |
| 19069 | 18480 | const init_ref = try sema.coerce(block, init_ty, empty_ref, src); |
| 19070 | 18481 | |
| 19071 | 18482 | if (is_byref) { |
| 19072 | const init_val = (try sema.resolveValue(init_ref)).?; | |
| 19073 | return sema.uavRef(init_val.toIntern()); | |
| 18483 | return sema.uavRef(sema.resolveValue(init_ref).?); | |
| 19074 | 18484 | } else { |
| 19075 | 18485 | return init_ref; |
| 19076 | 18486 | } |
| 19077 | 18487 | } |
| 19078 | 18488 | |
| 18489 | /// Asserts that the layout of `struct_ty` is already resolved. | |
| 19079 | 18490 | fn structInitEmpty( |
| 19080 | 18491 | sema: *Sema, |
| 19081 | 18492 | block: *Block, |
| ... | ... | @@ -19087,7 +18498,7 @@ fn structInitEmpty( |
| 19087 | 18498 | const zcu = pt.zcu; |
| 19088 | 18499 | const gpa = sema.gpa; |
| 19089 | 18500 | // This logic must be synchronized with that in `zirStructInit`. |
| 19090 | try struct_ty.resolveFields(pt); | |
| 18501 | struct_ty.assertHasLayout(zcu); | |
| 19091 | 18502 | |
| 19092 | 18503 | // The init values to use for the struct instance. |
| 19093 | 18504 | const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(zcu)); |
| ... | ... | @@ -19118,63 +18529,36 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com |
| 19118 | 18529 | |
| 19119 | 18530 | fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19120 | 18531 | const pt = sema.pt; |
| 18532 | const zcu = pt.zcu; | |
| 18533 | const ip = &zcu.intern_pool; | |
| 19121 | 18534 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 19122 | 18535 | const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 19123 | 18536 | const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 19124 | const init_src = block.builtinCallArgSrc(inst_data.src_node, 2); | |
| 18537 | const payload_src = block.builtinCallArgSrc(inst_data.src_node, 2); | |
| 19125 | 18538 | const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; |
| 19126 | 18539 | const union_ty = try sema.resolveType(block, ty_src, extra.union_type); |
| 19127 | 18540 | if (union_ty.zigTypeTag(pt.zcu) != .@"union") { |
| 19128 | 18541 | return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)}); |
| 19129 | 18542 | } |
| 18543 | union_ty.assertHasLayout(zcu); // from a previous `field_type_ref` instruction | |
| 19130 | 18544 | const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_names }); |
| 19131 | const init = try sema.resolveInst(extra.init); | |
| 19132 | return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src); | |
| 19133 | } | |
| 19134 | ||
| 19135 | fn unionInit( | |
| 19136 | sema: *Sema, | |
| 19137 | block: *Block, | |
| 19138 | uncasted_init: Air.Inst.Ref, | |
| 19139 | init_src: LazySrcLoc, | |
| 19140 | union_ty: Type, | |
| 19141 | union_ty_src: LazySrcLoc, | |
| 19142 | field_name: InternPool.NullTerminatedString, | |
| 19143 | field_src: LazySrcLoc, | |
| 19144 | ) CompileError!Air.Inst.Ref { | |
| 19145 | const pt = sema.pt; | |
| 19146 | const zcu = pt.zcu; | |
| 19147 | const ip = &zcu.intern_pool; | |
| 19148 | 18545 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); |
| 19149 | 18546 | const field_ty: Type = .fromInterned(zcu.typeToUnion(union_ty).?.field_types.get(ip)[field_index]); |
| 19150 | const init = try sema.coerce(block, field_ty, uncasted_init, init_src); | |
| 19151 | _ = union_ty_src; | |
| 19152 | return unionInitFromEnumTag(sema, block, init_src, union_ty, field_index, init); | |
| 19153 | } | |
| 19154 | 18547 | |
| 19155 | fn unionInitFromEnumTag( | |
| 19156 | sema: *Sema, | |
| 19157 | block: *Block, | |
| 19158 | init_src: LazySrcLoc, | |
| 19159 | union_ty: Type, | |
| 19160 | field_index: u32, | |
| 19161 | init: Air.Inst.Ref, | |
| 19162 | ) !Air.Inst.Ref { | |
| 19163 | const pt = sema.pt; | |
| 19164 | const zcu = pt.zcu; | |
| 18548 | const payload = try sema.coerce(block, field_ty, sema.resolveInst(extra.init), payload_src); | |
| 18549 | ||
| 18550 | if (union_ty.containerLayout(zcu) == .@"packed") { | |
| 18551 | return sema.bitCast(block, union_ty, payload, block.nodeOffset(inst_data.src_node), payload_src); | |
| 18552 | } | |
| 19165 | 18553 | |
| 19166 | if (try sema.resolveValue(init)) |init_val| { | |
| 18554 | if (sema.resolveValue(payload)) |payload_val| { | |
| 19167 | 18555 | const tag_ty = union_ty.unionTagTypeHypothetical(zcu); |
| 19168 | 18556 | const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); |
| 19169 | return Air.internedToRef((try pt.internUnion(.{ | |
| 19170 | .ty = union_ty.toIntern(), | |
| 19171 | .tag = tag_val.toIntern(), | |
| 19172 | .val = init_val.toIntern(), | |
| 19173 | }))); | |
| 18557 | return .fromValue(try pt.unionValue(union_ty, tag_val, payload_val)); | |
| 19174 | 18558 | } |
| 19175 | 18559 | |
| 19176 | try sema.requireRuntimeBlock(block, init_src, null); | |
| 19177 | return block.addUnionInit(union_ty, field_index, init); | |
| 18560 | try sema.requireRuntimeBlock(block, payload_src, null); | |
| 18561 | return block.addUnionInit(union_ty, field_index, payload); | |
| 19178 | 18562 | } |
| 19179 | 18563 | |
| 19180 | 18564 | fn zirStructInit( |
| ... | ... | @@ -19202,8 +18586,8 @@ fn zirStructInit( |
| 19202 | 18586 | // The type wasn't actually known, so treat this as an anon struct init. |
| 19203 | 18587 | return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref); |
| 19204 | 18588 | }; |
| 18589 | try sema.ensureLayoutResolved(result_ty, src, .init); | |
| 19205 | 18590 | const resolved_ty = result_ty.optEuBaseType(zcu); |
| 19206 | try resolved_ty.resolveLayout(pt); | |
| 19207 | 18591 | |
| 19208 | 18592 | if (resolved_ty.zigTypeTag(zcu) == .@"struct") { |
| 19209 | 18593 | // This logic must be synchronized with that in `zirStructInitEmpty`. |
| ... | ... | @@ -19226,7 +18610,6 @@ fn zirStructInit( |
| 19226 | 18610 | var field_i: u32 = 0; |
| 19227 | 18611 | var extra_index = extra.end; |
| 19228 | 18612 | |
| 19229 | const is_packed = resolved_ty.containerLayout(zcu) == .@"packed"; | |
| 19230 | 18613 | while (field_i < extra.data.fields_len) : (field_i += 1) { |
| 19231 | 18614 | const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index); |
| 19232 | 18615 | extra_index = item.end; |
| ... | ... | @@ -19248,19 +18631,16 @@ fn zirStructInit( |
| 19248 | 18631 | assert(field_inits[field_index] == .none); |
| 19249 | 18632 | field_assign_idxs[field_index] = field_i; |
| 19250 | 18633 | found_fields[field_index] = item.data.field_type; |
| 19251 | const uncoerced_init = try sema.resolveInst(item.data.init); | |
| 18634 | const uncoerced_init = sema.resolveInst(item.data.init); | |
| 19252 | 18635 | const field_ty = resolved_ty.fieldType(field_index, zcu); |
| 19253 | 18636 | field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src); |
| 19254 | if (!is_packed) { | |
| 19255 | try resolved_ty.resolveStructFieldInits(pt); | |
| 19256 | if (try resolved_ty.structFieldValueComptime(pt, field_index)) |default_value| { | |
| 19257 | const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { | |
| 19258 | return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); | |
| 19259 | }; | |
| 19260 | ||
| 19261 | if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) { | |
| 19262 | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); | |
| 19263 | } | |
| 18637 | if (resolved_ty.structFieldIsComptime(field_index, zcu)) { | |
| 18638 | const default_value = (try resolved_ty.structFieldValueComptime(pt, field_index)).?; | |
| 18639 | const init_val = sema.resolveValue(field_inits[field_index]) orelse { | |
| 18640 | return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); | |
| 18641 | }; | |
| 18642 | if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) { | |
| 18643 | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); | |
| 19264 | 18644 | } |
| 19265 | 18645 | } |
| 19266 | 18646 | } |
| ... | ... | @@ -19288,9 +18668,9 @@ fn zirStructInit( |
| 19288 | 18668 | const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); |
| 19289 | 18669 | const field_ty: Type = .fromInterned(zcu.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index]); |
| 19290 | 18670 | |
| 19291 | if (field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 18671 | if (field_ty.classify(zcu) == .no_possible_value) { | |
| 19292 | 18672 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 19293 | const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); | |
| 18673 | const msg = try sema.errMsg(src, "cannot initialize union field with uninstantiable type '{f}'", .{field_ty.fmt(pt)}); | |
| 19294 | 18674 | errdefer msg.destroy(sema.gpa); |
| 19295 | 18675 | |
| 19296 | 18676 | try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{f}' declared here", .{ |
| ... | ... | @@ -19301,21 +18681,31 @@ fn zirStructInit( |
| 19301 | 18681 | }); |
| 19302 | 18682 | } |
| 19303 | 18683 | |
| 19304 | const uncoerced_init_inst = try sema.resolveInst(item.data.init); | |
| 18684 | const uncoerced_init_inst = sema.resolveInst(item.data.init); | |
| 19305 | 18685 | const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src); |
| 19306 | 18686 | |
| 19307 | if (try sema.resolveValue(init_inst)) |val| { | |
| 18687 | if (resolved_ty.containerLayout(zcu) == .@"packed") { | |
| 18688 | const union_val = try sema.bitCast(block, resolved_ty, init_inst, src, field_src); | |
| 18689 | const result_val = try sema.coerce(block, result_ty, union_val, src); | |
| 18690 | if (is_ref) { | |
| 18691 | return sema.analyzeRef(block, src, result_val, .none); | |
| 18692 | } else { | |
| 18693 | return result_val; | |
| 18694 | } | |
| 18695 | } | |
| 18696 | ||
| 18697 | if (sema.resolveValue(init_inst)) |val| { | |
| 19308 | 18698 | const struct_val = Value.fromInterned(try pt.internUnion(.{ |
| 19309 | 18699 | .ty = resolved_ty.toIntern(), |
| 19310 | 18700 | .tag = tag_val.toIntern(), |
| 19311 | 18701 | .val = val.toIntern(), |
| 19312 | 18702 | })); |
| 19313 | 18703 | const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); |
| 19314 | const final_val = (try sema.resolveValue(final_val_inst)).?; | |
| 19315 | return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); | |
| 18704 | const final_val = sema.resolveValue(final_val_inst).?; | |
| 18705 | return sema.addConstantMaybeRef(final_val, is_ref); | |
| 19316 | 18706 | } |
| 19317 | 18707 | |
| 19318 | if (try resolved_ty.comptimeOnlySema(pt)) { | |
| 18708 | if (resolved_ty.comptimeOnly(zcu)) { | |
| 19319 | 18709 | return sema.failWithNeededComptime(block, field_src, .{ .comptime_only = .{ |
| 19320 | 18710 | .ty = resolved_ty, |
| 19321 | 18711 | .msg = .union_init, |
| ... | ... | @@ -19326,7 +18716,7 @@ fn zirStructInit( |
| 19326 | 18716 | |
| 19327 | 18717 | if (is_ref) { |
| 19328 | 18718 | const target = zcu.getTarget(); |
| 19329 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 18719 | const alloc_ty = try pt.ptrType(.{ | |
| 19330 | 18720 | .child = result_ty.toIntern(), |
| 19331 | 18721 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19332 | 18722 | }); |
| ... | ... | @@ -19334,10 +18724,6 @@ fn zirStructInit( |
| 19334 | 18724 | const base_ptr = try sema.optEuBasePtrInit(block, alloc, src); |
| 19335 | 18725 | const field_ptr = try sema.unionFieldPtr(block, field_src, base_ptr, field_name, field_src, resolved_ty, true); |
| 19336 | 18726 | try sema.storePtr(block, src, field_ptr, init_inst); |
| 19337 | if ((try sema.typeHasOnePossibleValue(tag_ty)) == null) { | |
| 19338 | const new_tag = Air.internedToRef(tag_val.toIntern()); | |
| 19339 | _ = try block.addBinOp(.set_union_tag, base_ptr, new_tag); | |
| 19340 | } | |
| 19341 | 18727 | return sema.makePtrConst(block, alloc); |
| 19342 | 18728 | } |
| 19343 | 18729 | |
| ... | ... | @@ -19409,20 +18795,29 @@ fn finishStructInit( |
| 19409 | 18795 | continue; |
| 19410 | 18796 | } |
| 19411 | 18797 | |
| 19412 | try struct_ty.resolveStructFieldInits(pt); | |
| 18798 | if (struct_type.field_is_comptime_bits.get(ip, i)) { | |
| 18799 | field_inits[i] = .fromIntern(struct_type.field_defaults.get(ip)[i]); | |
| 18800 | continue; | |
| 18801 | } | |
| 18802 | ||
| 18803 | try sema.ensureStructDefaultsResolved(struct_ty, init_src); | |
| 19413 | 18804 | |
| 19414 | const field_init = struct_type.fieldInit(ip, i); | |
| 19415 | if (field_init == .none) { | |
| 19416 | const field_name = struct_type.field_names.get(ip)[i]; | |
| 19417 | const template = "missing struct field: {f}"; | |
| 19418 | const args = .{field_name.fmt(ip)}; | |
| 19419 | if (root_msg) |msg| { | |
| 19420 | try sema.errNote(init_src, msg, template, args); | |
| 19421 | } else { | |
| 19422 | root_msg = try sema.errMsg(init_src, template, args); | |
| 19423 | } | |
| 18805 | const field_default: InternPool.Index = d: { | |
| 18806 | if (struct_type.field_defaults.len == 0) break :d .none; | |
| 18807 | break :d struct_type.field_defaults.get(ip)[i]; | |
| 18808 | }; | |
| 18809 | if (field_default != .none) { | |
| 18810 | field_inits[i] = .fromIntern(field_default); | |
| 18811 | continue; | |
| 18812 | } | |
| 18813 | ||
| 18814 | const field_name = struct_type.field_names.get(ip)[i]; | |
| 18815 | const template = "missing struct field: {f}"; | |
| 18816 | const args = .{field_name.fmt(ip)}; | |
| 18817 | if (root_msg) |msg| { | |
| 18818 | try sema.errNote(init_src, msg, template, args); | |
| 19424 | 18819 | } else { |
| 19425 | field_inits[i] = Air.internedToRef(field_init); | |
| 18820 | root_msg = try sema.errMsg(init_src, template, args); | |
| 19426 | 18821 | } |
| 19427 | 18822 | } |
| 19428 | 18823 | }, |
| ... | ... | @@ -19442,18 +18837,38 @@ fn finishStructInit( |
| 19442 | 18837 | } |
| 19443 | 18838 | } else null; |
| 19444 | 18839 | |
| 19445 | const runtime_index = opt_runtime_index orelse { | |
| 19446 | const elems = try sema.arena.alloc(InternPool.Index, field_inits.len); | |
| 19447 | for (elems, field_inits) |*elem, field_init| { | |
| 19448 | elem.* = (sema.resolveValue(field_init) catch unreachable).?.toIntern(); | |
| 19449 | } | |
| 19450 | const struct_val = try pt.aggregateValue(struct_ty, elems); | |
| 19451 | const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), init_src); | |
| 19452 | const final_val = (try sema.resolveValue(final_val_inst)).?; | |
| 19453 | return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); | |
| 18840 | const runtime_index = opt_runtime_index orelse switch (struct_ty.containerLayout(zcu)) { | |
| 18841 | .auto, .@"extern" => { | |
| 18842 | const elems = try sema.arena.alloc(InternPool.Index, field_inits.len); | |
| 18843 | for (elems, field_inits) |*elem, field_init| { | |
| 18844 | elem.* = sema.resolveValue(field_init).?.toIntern(); | |
| 18845 | } | |
| 18846 | const struct_val = try pt.aggregateValue(struct_ty, elems); | |
| 18847 | const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src); | |
| 18848 | return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref); | |
| 18849 | }, | |
| 18850 | .@"packed" => { | |
| 18851 | const buf = try sema.arena.alloc(u8, @intCast((struct_ty.bitSize(zcu) + 7) / 8)); | |
| 18852 | var bit_offset: u16 = 0; | |
| 18853 | for (field_inits) |field_init| { | |
| 18854 | const field_val = sema.resolveValue(field_init).?; | |
| 18855 | field_val.writeToPackedMemory(pt, buf, bit_offset) catch |err| switch (err) { | |
| 18856 | error.ReinterpretDeclRef => unreachable, // bitpack fields cannot be pointers | |
| 18857 | error.OutOfMemory => |e| return e, | |
| 18858 | }; | |
| 18859 | bit_offset += @intCast(field_val.typeOf(zcu).bitSize(zcu)); | |
| 18860 | } | |
| 18861 | assert(bit_offset == struct_ty.bitSize(zcu)); | |
| 18862 | const struct_val = Value.readFromPackedMemory(struct_ty, pt, buf, 0, sema.arena) catch |err| switch (err) { | |
| 18863 | error.IllDefinedMemoryLayout => unreachable, // bitpacks have well-defined layout | |
| 18864 | error.OutOfMemory => |e| return e, | |
| 18865 | }; | |
| 18866 | const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src); | |
| 18867 | return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref); | |
| 18868 | }, | |
| 19454 | 18869 | }; |
| 19455 | 18870 | |
| 19456 | if (try struct_ty.comptimeOnlySema(pt)) { | |
| 18871 | if (struct_ty.comptimeOnly(zcu)) { | |
| 19457 | 18872 | return sema.failWithNeededComptime(block, block.src(.{ .init_elem = .{ |
| 19458 | 18873 | .init_node_offset = init_src.offset.node_offset.x, |
| 19459 | 18874 | .elem_index = @intCast(runtime_index), |
| ... | ... | @@ -19468,9 +18883,8 @@ fn finishStructInit( |
| 19468 | 18883 | } |
| 19469 | 18884 | |
| 19470 | 18885 | if (is_ref) { |
| 19471 | try struct_ty.resolveLayout(pt); | |
| 19472 | 18886 | const target = zcu.getTarget(); |
| 19473 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 18887 | const alloc_ty = try pt.ptrType(.{ | |
| 19474 | 18888 | .child = result_ty.toIntern(), |
| 19475 | 18889 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19476 | 18890 | }); |
| ... | ... | @@ -19489,7 +18903,6 @@ fn finishStructInit( |
| 19489 | 18903 | .init_node_offset = init_src.offset.node_offset.x, |
| 19490 | 18904 | .elem_index = @intCast(runtime_index), |
| 19491 | 18905 | } })); |
| 19492 | try struct_ty.resolveStructFieldInits(pt); | |
| 19493 | 18906 | const struct_val = try block.addAggregateInit(struct_ty, field_inits); |
| 19494 | 18907 | return sema.coerce(block, result_ty, struct_val, init_src); |
| 19495 | 18908 | } |
| ... | ... | @@ -19558,7 +18971,7 @@ fn structInitAnon( |
| 19558 | 18971 | |
| 19559 | 18972 | field_name.* = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); |
| 19560 | 18973 | |
| 19561 | const init = try sema.resolveInst(item.data.init); | |
| 18974 | const init = sema.resolveInst(item.data.init); | |
| 19562 | 18975 | field_ty.* = sema.typeOf(init).toIntern(); |
| 19563 | 18976 | if (Type.fromInterned(field_ty.*).zigTypeTag(zcu) == .@"opaque") { |
| 19564 | 18977 | const msg = msg: { |
| ... | ... | @@ -19574,7 +18987,7 @@ fn structInitAnon( |
| 19574 | 18987 | }; |
| 19575 | 18988 | return sema.failWithOwnedErrorMsg(block, msg); |
| 19576 | 18989 | } |
| 19577 | if (try sema.resolveValue(init)) |init_val| { | |
| 18990 | if (sema.resolveValue(init)) |init_val| { | |
| 19578 | 18991 | field_val.* = init_val.toIntern(); |
| 19579 | 18992 | any_values = true; |
| 19580 | 18993 | } else { |
| ... | ... | @@ -19585,12 +18998,11 @@ fn structInitAnon( |
| 19585 | 18998 | break :rs runtime_index; |
| 19586 | 18999 | }; |
| 19587 | 19000 | |
| 19588 | // We treat anonymous struct types as reified types, because there are similarities: | |
| 19589 | // * They use a form of structural equivalence, which we can easily model using a custom hash | |
| 19590 | // * They do not have captures | |
| 19591 | // * They immediately have their fields resolved | |
| 19592 | // In general, other code should treat anon struct types and reified struct types identically, | |
| 19593 | // so there's no point having a separate `InternPool.NamespaceType` field for them. | |
| 19001 | // We treat anonymous struct types as reified types, because there are similarities: they have | |
| 19002 | // no captures, and instead use a form of structural equivalence which we can easy represent by | |
| 19003 | // hashing the field names/types/values. They also perform layout resolution immediately. These | |
| 19004 | // similarities mean that other code should actually treat anon struct types and reified struct | |
| 19005 | // types identically anyway, so sharing the representation makes everything simpler. | |
| 19594 | 19006 | const type_hash: u64 = hash: { |
| 19595 | 19007 | var hasher = std.hash.Wyhash.init(0); |
| 19596 | 19008 | hasher.update(std.mem.sliceAsBytes(types)); |
| ... | ... | @@ -19599,35 +19011,33 @@ fn structInitAnon( |
| 19599 | 19011 | break :hash hasher.final(); |
| 19600 | 19012 | }; |
| 19601 | 19013 | const tracked_inst = try block.trackZir(inst); |
| 19602 | const struct_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ | |
| 19603 | .layout = .auto, | |
| 19014 | const struct_ty: Type = switch (try ip.getReifiedStructType(gpa, io, pt.tid, .{ | |
| 19015 | .zir_index = tracked_inst, | |
| 19016 | .type_hash = type_hash, | |
| 19604 | 19017 | .fields_len = extra_data.fields_len, |
| 19605 | .known_non_opv = false, | |
| 19606 | .requires_comptime = .unknown, | |
| 19018 | .layout = .auto, | |
| 19607 | 19019 | .any_comptime_fields = any_values, |
| 19608 | .any_default_inits = any_values, | |
| 19609 | .inits_resolved = true, | |
| 19610 | .any_aligned_fields = false, | |
| 19611 | .key = .{ .reified = .{ | |
| 19612 | .zir_index = tracked_inst, | |
| 19613 | .type_hash = type_hash, | |
| 19614 | } }, | |
| 19615 | }, false)) { | |
| 19020 | .any_field_defaults = any_values, | |
| 19021 | .any_field_aligns = false, | |
| 19022 | .packed_backing_int_type = .none, | |
| 19023 | })) { | |
| 19024 | .existing => |ty| .fromInterned(ty), | |
| 19616 | 19025 | .wip => |wip| ty: { |
| 19617 | 19026 | errdefer wip.cancel(ip, pt.tid); |
| 19618 | const type_name = try sema.createTypeName(block, .anon, "struct", inst, wip.index); | |
| 19619 | wip.setName(ip, type_name.name, type_name.nav); | |
| 19620 | ||
| 19621 | const struct_type = ip.loadStructType(wip.index); | |
| 19027 | try sema.setTypeName(block, &wip, .anon, "struct", inst); | |
| 19622 | 19028 | |
| 19623 | for (names, values, 0..) |name, init_val, field_idx| { | |
| 19624 | assert(struct_type.addFieldName(ip, name) == null); | |
| 19625 | if (init_val != .none) struct_type.setFieldComptime(ip, field_idx); | |
| 19626 | } | |
| 19627 | ||
| 19628 | @memcpy(struct_type.field_types.get(ip), types); | |
| 19029 | // Reified structs have field information populated immediately. | |
| 19030 | @memcpy(wip.field_names.get(ip), names); | |
| 19031 | @memcpy(wip.field_types.get(ip), types); | |
| 19629 | 19032 | if (any_values) { |
| 19630 | @memcpy(struct_type.field_inits.get(ip), values); | |
| 19033 | @memcpy(wip.field_values.get(ip), values); | |
| 19034 | @memset(wip.field_is_comptime_bits.getAll(ip), 0); | |
| 19035 | for (values, 0..) |val, field_index| { | |
| 19036 | if (val == .none) continue; | |
| 19037 | const bit_bag_index = field_index / 32; | |
| 19038 | const mask = @as(u32, 1) << @intCast(field_index % 32); | |
| 19039 | wip.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; | |
| 19040 | } | |
| 19631 | 19041 | } |
| 19632 | 19042 | |
| 19633 | 19043 | const new_namespace_index = try pt.createNamespace(.{ |
| ... | ... | @@ -19636,30 +19046,24 @@ fn structInitAnon( |
| 19636 | 19046 | .file_scope = block.getFileScopeIndex(zcu), |
| 19637 | 19047 | .generation = zcu.generation, |
| 19638 | 19048 | }); |
| 19639 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index }); | |
| 19640 | codegen_type: { | |
| 19641 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 19642 | if (block.ownerModule().strip) break :codegen_type; | |
| 19643 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 19644 | try zcu.comp.queueJob(.{ .link_type = wip.index }); | |
| 19645 | } | |
| 19049 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 19646 | 19050 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); |
| 19647 | break :ty wip.finish(ip, new_namespace_index); | |
| 19051 | break :ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 19648 | 19052 | }, |
| 19649 | .existing => |ty| ty, | |
| 19650 | 19053 | }; |
| 19651 | try sema.declareDependency(.{ .interned = struct_ty }); | |
| 19652 | 19054 | try sema.addTypeReferenceEntry(src, struct_ty); |
| 19055 | // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. | |
| 19056 | try sema.ensureLayoutResolved(struct_ty, src, .init); | |
| 19653 | 19057 | |
| 19654 | 19058 | _ = opt_runtime_index orelse { |
| 19655 | const struct_val = try pt.aggregateValue(.fromInterned(struct_ty), values); | |
| 19656 | return sema.addConstantMaybeRef(struct_val.toIntern(), is_ref); | |
| 19059 | const struct_val = try pt.aggregateValue(struct_ty, values); | |
| 19060 | return sema.addConstantMaybeRef(struct_val, is_ref); | |
| 19657 | 19061 | }; |
| 19658 | 19062 | |
| 19659 | 19063 | if (is_ref) { |
| 19660 | 19064 | const target = zcu.getTarget(); |
| 19661 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 19662 | .child = struct_ty, | |
| 19065 | const alloc_ty = try pt.ptrType(.{ | |
| 19066 | .child = struct_ty.toIntern(), | |
| 19663 | 19067 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19664 | 19068 | }); |
| 19665 | 19069 | const alloc = try block.addTy(.alloc, alloc_ty); |
| ... | ... | @@ -19672,12 +19076,12 @@ fn structInitAnon( |
| 19672 | 19076 | }; |
| 19673 | 19077 | extra_index = item.end; |
| 19674 | 19078 | |
| 19675 | const field_ptr_ty = try pt.ptrTypeSema(.{ | |
| 19079 | const field_ptr_ty = try pt.ptrType(.{ | |
| 19676 | 19080 | .child = field_ty, |
| 19677 | 19081 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19678 | 19082 | }); |
| 19679 | 19083 | if (values[i] == .none) { |
| 19680 | const init = try sema.resolveInst(item.data.init); | |
| 19084 | const init = sema.resolveInst(item.data.init); | |
| 19681 | 19085 | const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); |
| 19682 | 19086 | _ = try block.addBinOp(.store, field_ptr, init); |
| 19683 | 19087 | } |
| ... | ... | @@ -19694,10 +19098,10 @@ fn structInitAnon( |
| 19694 | 19098 | .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index), |
| 19695 | 19099 | }; |
| 19696 | 19100 | extra_index = item.end; |
| 19697 | element_refs[i] = try sema.resolveInst(item.data.init); | |
| 19101 | element_refs[i] = sema.resolveInst(item.data.init); | |
| 19698 | 19102 | } |
| 19699 | 19103 | |
| 19700 | return block.addAggregateInit(.fromInterned(struct_ty), element_refs); | |
| 19104 | return block.addAggregateInit(struct_ty, element_refs); | |
| 19701 | 19105 | } |
| 19702 | 19106 | |
| 19703 | 19107 | fn zirArrayInit( |
| ... | ... | @@ -19737,17 +19141,16 @@ fn zirArrayInit( |
| 19737 | 19141 | } }); |
| 19738 | 19142 | // Less inits than needed. |
| 19739 | 19143 | if (i + 2 > args.len) if (is_tuple) { |
| 19740 | const default_val = array_ty.structFieldDefaultValue(i, zcu).toIntern(); | |
| 19741 | if (default_val == .unreachable_value) { | |
| 19144 | const default_val = array_ty.structFieldDefaultValue(i, zcu) orelse { | |
| 19742 | 19145 | const template = "missing tuple field with index {d}"; |
| 19743 | 19146 | if (root_msg) |msg| { |
| 19744 | 19147 | try sema.errNote(src, msg, template, .{i}); |
| 19745 | 19148 | } else { |
| 19746 | 19149 | root_msg = try sema.errMsg(src, template, .{i}); |
| 19747 | 19150 | } |
| 19748 | } else { | |
| 19749 | dest.* = Air.internedToRef(default_val); | |
| 19750 | } | |
| 19151 | continue; | |
| 19152 | }; | |
| 19153 | dest.* = .fromValue(default_val); | |
| 19751 | 19154 | continue; |
| 19752 | 19155 | } else { |
| 19753 | 19156 | dest.* = Air.internedToRef(sentinel_val.?.toIntern()); |
| ... | ... | @@ -19755,15 +19158,13 @@ fn zirArrayInit( |
| 19755 | 19158 | }; |
| 19756 | 19159 | |
| 19757 | 19160 | const arg = args[i + 1]; |
| 19758 | const resolved_arg = try sema.resolveInst(arg); | |
| 19161 | const resolved_arg = sema.resolveInst(arg); | |
| 19759 | 19162 | const elem_ty = if (is_tuple) |
| 19760 | 19163 | array_ty.fieldType(i, zcu) |
| 19761 | 19164 | else |
| 19762 | array_ty.elemType2(zcu); | |
| 19165 | array_ty.childType(zcu); | |
| 19763 | 19166 | dest.* = try sema.coerce(block, elem_ty, resolved_arg, elem_src); |
| 19764 | 19167 | if (is_tuple) { |
| 19765 | if (array_ty.structFieldIsComptime(i, zcu)) | |
| 19766 | try array_ty.resolveStructFieldInits(pt); | |
| 19767 | 19168 | if (try array_ty.structFieldValueComptime(pt, i)) |field_val| { |
| 19768 | 19169 | const init_val = try sema.resolveConstValue(block, elem_src, dest.*, .{ .simple = .stored_to_comptime_field }); |
| 19769 | 19170 | if (!field_val.eql(init_val, elem_ty, zcu)) { |
| ... | ... | @@ -19788,17 +19189,17 @@ fn zirArrayInit( |
| 19788 | 19189 | const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len); |
| 19789 | 19190 | for (elem_vals, resolved_args) |*val, arg| { |
| 19790 | 19191 | // We checked that all args are comptime above. |
| 19791 | val.* = (sema.resolveValue(arg) catch unreachable).?.toIntern(); | |
| 19192 | val.* = sema.resolveValue(arg).?.toIntern(); | |
| 19792 | 19193 | } |
| 19793 | 19194 | const arr_val = try pt.aggregateValue(array_ty, elem_vals); |
| 19794 | 19195 | const result_ref = try sema.coerce(block, result_ty, Air.internedToRef(arr_val.toIntern()), src); |
| 19795 | const result_val = (try sema.resolveValue(result_ref)).?; | |
| 19796 | return sema.addConstantMaybeRef(result_val.toIntern(), is_ref); | |
| 19196 | const result_val = (sema.resolveValue(result_ref)).?; | |
| 19197 | return sema.addConstantMaybeRef(result_val, is_ref); | |
| 19797 | 19198 | }; |
| 19798 | 19199 | |
| 19799 | 19200 | if (is_ref) { |
| 19800 | 19201 | const target = zcu.getTarget(); |
| 19801 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 19202 | const alloc_ty = try pt.ptrType(.{ | |
| 19802 | 19203 | .child = result_ty.toIntern(), |
| 19803 | 19204 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19804 | 19205 | }); |
| ... | ... | @@ -19807,7 +19208,7 @@ fn zirArrayInit( |
| 19807 | 19208 | |
| 19808 | 19209 | if (is_tuple) { |
| 19809 | 19210 | for (resolved_args, 0..) |arg, i| { |
| 19810 | const elem_ptr_ty = try pt.ptrTypeSema(.{ | |
| 19211 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 19811 | 19212 | .child = array_ty.fieldType(i, zcu).toIntern(), |
| 19812 | 19213 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19813 | 19214 | }); |
| ... | ... | @@ -19820,8 +19221,8 @@ fn zirArrayInit( |
| 19820 | 19221 | return sema.makePtrConst(block, alloc); |
| 19821 | 19222 | } |
| 19822 | 19223 | |
| 19823 | const elem_ptr_ty = try pt.ptrTypeSema(.{ | |
| 19824 | .child = array_ty.elemType2(zcu).toIntern(), | |
| 19224 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 19225 | .child = array_ty.childType(zcu).toIntern(), | |
| 19825 | 19226 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19826 | 19227 | }); |
| 19827 | 19228 | const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern()); |
| ... | ... | @@ -19875,7 +19276,7 @@ fn arrayInitAnon( |
| 19875 | 19276 | .init_node_offset = src.offset.node_offset.x, |
| 19876 | 19277 | .elem_index = @intCast(i), |
| 19877 | 19278 | } }); |
| 19878 | const elem = try sema.resolveInst(operand); | |
| 19279 | const elem = sema.resolveInst(operand); | |
| 19879 | 19280 | types[i] = sema.typeOf(elem).toIntern(); |
| 19880 | 19281 | if (Type.fromInterned(types[i]).zigTypeTag(zcu) == .@"opaque") { |
| 19881 | 19282 | const msg = msg: { |
| ... | ... | @@ -19887,7 +19288,7 @@ fn arrayInitAnon( |
| 19887 | 19288 | }; |
| 19888 | 19289 | return sema.failWithOwnedErrorMsg(block, msg); |
| 19889 | 19290 | } |
| 19890 | if (try sema.resolveValue(elem)) |val| { | |
| 19291 | if (sema.resolveValue(elem)) |val| { | |
| 19891 | 19292 | values[i] = val.toIntern(); |
| 19892 | 19293 | any_comptime = true; |
| 19893 | 19294 | } else { |
| ... | ... | @@ -19917,7 +19318,7 @@ fn arrayInitAnon( |
| 19917 | 19318 | |
| 19918 | 19319 | const runtime_src = opt_runtime_src orelse { |
| 19919 | 19320 | const tuple_val = try pt.aggregateValue(tuple_ty, values); |
| 19920 | return sema.addConstantMaybeRef(tuple_val.toIntern(), is_ref); | |
| 19321 | return sema.addConstantMaybeRef(tuple_val, is_ref); | |
| 19921 | 19322 | }; |
| 19922 | 19323 | |
| 19923 | 19324 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| ... | ... | @@ -19927,25 +19328,25 @@ fn arrayInitAnon( |
| 19927 | 19328 | .init_node_offset = src.offset.node_offset.x, |
| 19928 | 19329 | .elem_index = @intCast(i), |
| 19929 | 19330 | } }); |
| 19930 | try sema.validateRuntimeValue(block, operand_src, try sema.resolveInst(operand)); | |
| 19331 | try sema.validateRuntimeValue(block, operand_src, sema.resolveInst(operand)); | |
| 19931 | 19332 | } |
| 19932 | 19333 | |
| 19933 | 19334 | if (is_ref) { |
| 19934 | 19335 | const target = sema.pt.zcu.getTarget(); |
| 19935 | const alloc_ty = try pt.ptrTypeSema(.{ | |
| 19336 | const alloc_ty = try pt.ptrType(.{ | |
| 19936 | 19337 | .child = tuple_ty.toIntern(), |
| 19937 | 19338 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19938 | 19339 | }); |
| 19939 | 19340 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 19940 | 19341 | for (operands, 0..) |operand, i_usize| { |
| 19941 | 19342 | const i: u32 = @intCast(i_usize); |
| 19942 | const field_ptr_ty = try pt.ptrTypeSema(.{ | |
| 19343 | const field_ptr_ty = try pt.ptrType(.{ | |
| 19943 | 19344 | .child = types[i], |
| 19944 | 19345 | .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, |
| 19945 | 19346 | }); |
| 19946 | 19347 | if (values[i] == .none) { |
| 19947 | 19348 | const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); |
| 19948 | _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand)); | |
| 19349 | _ = try block.addBinOp(.store, field_ptr, sema.resolveInst(operand)); | |
| 19949 | 19350 | } |
| 19950 | 19351 | } |
| 19951 | 19352 | |
| ... | ... | @@ -19954,14 +19355,14 @@ fn arrayInitAnon( |
| 19954 | 19355 | |
| 19955 | 19356 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, operands.len); |
| 19956 | 19357 | for (operands, 0..) |operand, i| { |
| 19957 | element_refs[i] = try sema.resolveInst(operand); | |
| 19358 | element_refs[i] = sema.resolveInst(operand); | |
| 19958 | 19359 | } |
| 19959 | 19360 | |
| 19960 | 19361 | return block.addAggregateInit(tuple_ty, element_refs); |
| 19961 | 19362 | } |
| 19962 | 19363 | |
| 19963 | fn addConstantMaybeRef(sema: *Sema, val: InternPool.Index, is_ref: bool) !Air.Inst.Ref { | |
| 19964 | return if (is_ref) sema.uavRef(val) else Air.internedToRef(val); | |
| 19364 | fn addConstantMaybeRef(sema: *Sema, val: Value, is_ref: bool) !Air.Inst.Ref { | |
| 19365 | return if (is_ref) sema.uavRef(val) else .fromValue(val); | |
| 19965 | 19366 | } |
| 19966 | 19367 | |
| 19967 | 19368 | fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -19971,6 +19372,7 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 19971 | 19372 | const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 19972 | 19373 | const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); |
| 19973 | 19374 | const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .field_name }); |
| 19375 | try sema.ensureLayoutResolved(aggregate_ty, ty_src, .field_queried); | |
| 19974 | 19376 | return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src); |
| 19975 | 19377 | } |
| 19976 | 19378 | |
| ... | ... | @@ -19990,9 +19392,11 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 19990 | 19392 | const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu); |
| 19991 | 19393 | const zir_field_name = sema.code.nullTerminatedString(extra.name_start); |
| 19992 | 19394 | const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls); |
| 19395 | try sema.ensureLayoutResolved(aggregate_ty, ty_src, .init); | |
| 19993 | 19396 | return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); |
| 19994 | 19397 | } |
| 19995 | 19398 | |
| 19399 | /// Asserts that the layout of `aggregate_ty` is resolved. | |
| 19996 | 19400 | fn fieldType( |
| 19997 | 19401 | sema: *Sema, |
| 19998 | 19402 | block: *Block, |
| ... | ... | @@ -20004,9 +19408,9 @@ fn fieldType( |
| 20004 | 19408 | const pt = sema.pt; |
| 20005 | 19409 | const zcu = pt.zcu; |
| 20006 | 19410 | const ip = &zcu.intern_pool; |
| 19411 | aggregate_ty.assertHasLayout(zcu); | |
| 20007 | 19412 | var cur_ty = aggregate_ty; |
| 20008 | 19413 | while (true) { |
| 20009 | try cur_ty.resolveFields(pt); | |
| 20010 | 19414 | switch (cur_ty.zigTypeTag(zcu)) { |
| 20011 | 19415 | .@"struct" => switch (ip.indexToKey(cur_ty.toIntern())) { |
| 20012 | 19416 | .tuple_type => |tuple| { |
| ... | ... | @@ -20024,10 +19428,11 @@ fn fieldType( |
| 20024 | 19428 | }, |
| 20025 | 19429 | .@"union" => { |
| 20026 | 19430 | const union_obj = zcu.typeToUnion(cur_ty).?; |
| 20027 | const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse | |
| 19431 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | |
| 19432 | const field_index = enum_obj.nameIndex(ip, field_name) orelse | |
| 20028 | 19433 | return sema.failWithBadUnionFieldAccess(block, cur_ty, union_obj, field_src, field_name); |
| 20029 | 19434 | const field_ty = union_obj.field_types.get(ip)[field_index]; |
| 20030 | return Air.internedToRef(field_ty); | |
| 19435 | return .fromIntern(field_ty); | |
| 20031 | 19436 | }, |
| 20032 | 19437 | .optional => { |
| 20033 | 19438 | // Struct/array init through optional requires the child type to not be a pointer. |
| ... | ... | @@ -20056,7 +19461,6 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 20056 | 19461 | const zcu = pt.zcu; |
| 20057 | 19462 | const ip = &zcu.intern_pool; |
| 20058 | 19463 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); |
| 20059 | try stack_trace_ty.resolveFields(pt); | |
| 20060 | 19464 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 20061 | 19465 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); |
| 20062 | 19466 | |
| ... | ... | @@ -20064,7 +19468,14 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 20064 | 19468 | .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) { |
| 20065 | 19469 | return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); |
| 20066 | 19470 | }, |
| 20067 | .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, | |
| 19471 | ||
| 19472 | .@"comptime", | |
| 19473 | .nav_ty, | |
| 19474 | .nav_val, | |
| 19475 | .type_layout, | |
| 19476 | .struct_defaults, | |
| 19477 | .memoized_state, | |
| 19478 | => {}, | |
| 20068 | 19479 | } |
| 20069 | 19480 | return Air.internedToRef(try pt.intern(.{ .opt = .{ |
| 20070 | 19481 | .ty = opt_ptr_stack_trace_ty.toIntern(), |
| ... | ... | @@ -20083,15 +19494,16 @@ fn zirFrame( |
| 20083 | 19494 | } |
| 20084 | 19495 | |
| 20085 | 19496 | fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20086 | const zcu = sema.pt.zcu; | |
| 19497 | const pt = sema.pt; | |
| 19498 | const zcu = pt.zcu; | |
| 20087 | 19499 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20088 | 19500 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20089 | 19501 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 19502 | try sema.ensureLayoutResolved(ty, operand_src, .align_of); | |
| 20090 | 19503 | if (ty.isNoReturn(zcu)) { |
| 20091 | return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)}); | |
| 19504 | return sema.fail(block, operand_src, "no align available for uninstantiable type '{f}'", .{ty.fmt(sema.pt)}); | |
| 20092 | 19505 | } |
| 20093 | const val = try ty.lazyAbiAlignment(sema.pt); | |
| 20094 | return Air.internedToRef(val.toIntern()); | |
| 19506 | return .fromValue(try pt.intValue(.comptime_int, ty.abiAlignment(zcu).toByteUnits().?)); | |
| 20095 | 19507 | } |
| 20096 | 19508 | |
| 20097 | 19509 | fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -20099,7 +19511,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20099 | 19511 | const zcu = pt.zcu; |
| 20100 | 19512 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20101 | 19513 | const src = block.nodeOffset(inst_data.src_node); |
| 20102 | const operand = try sema.resolveInst(inst_data.operand); | |
| 19514 | const operand = sema.resolveInst(inst_data.operand); | |
| 20103 | 19515 | const operand_ty = sema.typeOf(operand); |
| 20104 | 19516 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 20105 | 19517 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| ... | ... | @@ -20108,7 +19520,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20108 | 19520 | } |
| 20109 | 19521 | const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; |
| 20110 | 19522 | const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1; |
| 20111 | if (try sema.resolveValue(operand)) |val| { | |
| 19523 | if (sema.resolveValue(operand)) |val| { | |
| 20112 | 19524 | if (!is_vector) { |
| 20113 | 19525 | return if (val.isUndef(zcu)) .undef_u1 else if (val.toBool()) .one_u1 else .zero_u1; |
| 20114 | 19526 | } |
| ... | ... | @@ -20131,7 +19543,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20131 | 19543 | fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20132 | 19544 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20133 | 19545 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20134 | const uncoerced_operand = try sema.resolveInst(inst_data.operand); | |
| 19546 | const uncoerced_operand = sema.resolveInst(inst_data.operand); | |
| 20135 | 19547 | const operand = try sema.coerce(block, .anyerror, uncoerced_operand, operand_src); |
| 20136 | 19548 | |
| 20137 | 19549 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { |
| ... | ... | @@ -20152,7 +19564,7 @@ fn zirAbs( |
| 20152 | 19564 | const pt = sema.pt; |
| 20153 | 19565 | const zcu = pt.zcu; |
| 20154 | 19566 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20155 | const operand = try sema.resolveInst(inst_data.operand); | |
| 19567 | const operand = sema.resolveInst(inst_data.operand); | |
| 20156 | 19568 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20157 | 19569 | const operand_ty = sema.typeOf(operand); |
| 20158 | 19570 | const scalar_ty = operand_ty.scalarType(zcu); |
| ... | ... | @@ -20183,7 +19595,7 @@ fn maybeConstantUnaryMath( |
| 20183 | 19595 | const pt = sema.pt; |
| 20184 | 19596 | const zcu = pt.zcu; |
| 20185 | 19597 | switch (result_ty.zigTypeTag(zcu)) { |
| 20186 | .vector => if (try sema.resolveValue(operand)) |val| { | |
| 19598 | .vector => if (sema.resolveValue(operand)) |val| { | |
| 20187 | 19599 | const scalar_ty = result_ty.scalarType(zcu); |
| 20188 | 19600 | const vec_len = result_ty.vectorLen(zcu); |
| 20189 | 19601 | if (val.isUndef(zcu)) |
| ... | ... | @@ -20196,7 +19608,7 @@ fn maybeConstantUnaryMath( |
| 20196 | 19608 | } |
| 20197 | 19609 | return Air.internedToRef((try pt.aggregateValue(result_ty, elems)).toIntern()); |
| 20198 | 19610 | }, |
| 20199 | else => if (try sema.resolveValue(operand)) |operand_val| { | |
| 19611 | else => if (sema.resolveValue(operand)) |operand_val| { | |
| 20200 | 19612 | if (operand_val.isUndef(zcu)) |
| 20201 | 19613 | return try pt.undefRef(result_ty); |
| 20202 | 19614 | const result_val = try eval(operand_val, result_ty, sema.arena, pt); |
| ... | ... | @@ -20219,7 +19631,7 @@ fn zirUnaryMath( |
| 20219 | 19631 | const pt = sema.pt; |
| 20220 | 19632 | const zcu = pt.zcu; |
| 20221 | 19633 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20222 | const operand = try sema.resolveInst(inst_data.operand); | |
| 19634 | const operand = sema.resolveInst(inst_data.operand); | |
| 20223 | 19635 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20224 | 19636 | const operand_ty = sema.typeOf(operand); |
| 20225 | 19637 | const scalar_ty = operand_ty.scalarType(zcu); |
| ... | ... | @@ -20244,12 +19656,11 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 20244 | 19656 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20245 | 19657 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20246 | 19658 | const src = block.nodeOffset(inst_data.src_node); |
| 20247 | const operand = try sema.resolveInst(inst_data.operand); | |
| 19659 | const operand = sema.resolveInst(inst_data.operand); | |
| 20248 | 19660 | const operand_ty = sema.typeOf(operand); |
| 20249 | 19661 | const pt = sema.pt; |
| 20250 | 19662 | const zcu = pt.zcu; |
| 20251 | 19663 | const ip = &zcu.intern_pool; |
| 20252 | try operand_ty.resolveLayout(pt); | |
| 20253 | 19664 | const enum_ty = switch (operand_ty.zigTypeTag(zcu)) { |
| 20254 | 19665 | .enum_literal => { |
| 20255 | 19666 | const val = (try sema.resolveDefinedValue(block, operand_src, operand)).?; |
| ... | ... | @@ -20332,17 +19743,17 @@ fn zirReifySliceArgTy( |
| 20332 | 19743 | // zig fmt: on |
| 20333 | 19744 | }; |
| 20334 | 19745 | |
| 20335 | const operand_ty = try pt.ptrTypeSema(.{ | |
| 19746 | const operand_ty = try pt.ptrType(.{ | |
| 20336 | 19747 | .child = in_scalar_ty.toIntern(), |
| 20337 | 19748 | .flags = .{ .size = .slice, .is_const = true }, |
| 20338 | 19749 | }); |
| 20339 | 19750 | |
| 20340 | const operand_uncoerced = try sema.resolveInst(extra.operand); | |
| 19751 | const operand_uncoerced = sema.resolveInst(extra.operand); | |
| 20341 | 19752 | const operand_coerced = try sema.coerce(block, operand_ty, operand_uncoerced, src); |
| 20342 | 19753 | const operand_val = try sema.resolveConstDefinedValue(block, src, operand_coerced, .{ .simple = comptime_reason }); |
| 20343 | 19754 | const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len); |
| 20344 | 19755 | if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); |
| 20345 | const len = try len_val.toUnsignedIntSema(pt); | |
| 19756 | const len = len_val.toUnsignedInt(zcu); | |
| 20346 | 19757 | |
| 20347 | 19758 | return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{ |
| 20348 | 19759 | .len = len, |
| ... | ... | @@ -20365,12 +19776,12 @@ fn zirReifyEnumValueSliceTy( |
| 20365 | 19776 | |
| 20366 | 19777 | const int_tag_ty = try sema.resolveType(block, int_tag_ty_src, extra.lhs); |
| 20367 | 19778 | |
| 20368 | const operand_uncoerced = try sema.resolveInst(extra.rhs); | |
| 19779 | const operand_uncoerced = sema.resolveInst(extra.rhs); | |
| 20369 | 19780 | const operand_coerced = try sema.coerce(block, .slice_const_slice_const_u8, operand_uncoerced, field_names_src); |
| 20370 | 19781 | const operand_val = try sema.resolveConstDefinedValue(block, field_names_src, operand_coerced, .{ .simple = .enum_field_names }); |
| 20371 | 19782 | const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len); |
| 20372 | 19783 | if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, field_names_src, null); |
| 20373 | const len = try len_val.toUnsignedIntSema(pt); | |
| 19784 | const len = len_val.toUnsignedInt(zcu); | |
| 20374 | 19785 | |
| 20375 | 19786 | return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{ |
| 20376 | 19787 | .len = len, |
| ... | ... | @@ -20410,7 +19821,7 @@ fn zirReifyTuple( |
| 20410 | 19821 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 20411 | 19822 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 20412 | 19823 | |
| 20413 | const types_uncoerced = try sema.resolveInst(extra.operand); | |
| 19824 | const types_uncoerced = sema.resolveInst(extra.operand); | |
| 20414 | 19825 | const types_coerced = try sema.coerce(block, .slice_const_type, types_uncoerced, operand_src); |
| 20415 | 19826 | const types_slice_val = try sema.resolveConstDefinedValue(block, operand_src, types_coerced, .{ .simple = .tuple_field_types }); |
| 20416 | 19827 | const types_array_val = try sema.derefSliceAsArray(block, operand_src, types_slice_val, .{ .simple = .tuple_field_types }); |
| ... | ... | @@ -20422,6 +19833,7 @@ fn zirReifyTuple( |
| 20422 | 19833 | if (field_ty_val.isUndef(zcu)) { |
| 20423 | 19834 | return sema.failWithUseOfUndef(block, operand_src, null); |
| 20424 | 19835 | } |
| 19836 | try sema.validateTupleFieldType(block, field_ty_val.toType(), operand_src); | |
| 20425 | 19837 | field_ty.* = field_ty_val.toIntern(); |
| 20426 | 19838 | } |
| 20427 | 19839 | |
| ... | ... | @@ -20456,12 +19868,12 @@ fn zirReifyPointer( |
| 20456 | 19868 | const size_ty = try sema.getBuiltinType(size_src, .@"Type.Pointer.Size"); |
| 20457 | 19869 | const attrs_ty = try sema.getBuiltinType(attrs_src, .@"Type.Pointer.Attributes"); |
| 20458 | 19870 | |
| 20459 | const size_uncoerced = try sema.resolveInst(extra.size); | |
| 19871 | const size_uncoerced = sema.resolveInst(extra.size); | |
| 20460 | 19872 | const size_coerced = try sema.coerce(block, size_ty, size_uncoerced, size_src); |
| 20461 | 19873 | const size_val = try sema.resolveConstDefinedValue(block, size_src, size_coerced, .{ .simple = .pointer_size }); |
| 20462 | 19874 | const size = try sema.interpretBuiltinType(block, size_src, size_val, std.builtin.Type.Pointer.Size); |
| 20463 | 19875 | |
| 20464 | const attrs_uncoerced = try sema.resolveInst(extra.attrs); | |
| 19876 | const attrs_uncoerced = sema.resolveInst(extra.attrs); | |
| 20465 | 19877 | const attrs_coerced = try sema.coerce(block, attrs_ty, attrs_uncoerced, attrs_src); |
| 20466 | 19878 | const attrs_val = try sema.resolveConstDefinedValue(block, attrs_src, attrs_coerced, .{ .simple = .pointer_attrs }); |
| 20467 | 19879 | const attrs = try sema.interpretBuiltinType(block, attrs_src, attrs_val, std.builtin.Type.Pointer.Attributes); |
| ... | ... | @@ -20489,18 +19901,8 @@ fn zirReifyPointer( |
| 20489 | 19901 | else => {}, |
| 20490 | 19902 | } |
| 20491 | 19903 | |
| 20492 | if (size == .c and !try sema.validateExternType(elem_ty, .other)) { | |
| 20493 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 20494 | const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); | |
| 20495 | errdefer msg.destroy(gpa); | |
| 20496 | try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other); | |
| 20497 | try sema.addDeclaredHereNote(msg, elem_ty); | |
| 20498 | break :msg msg; | |
| 20499 | }); | |
| 20500 | } | |
| 20501 | ||
| 20502 | 19904 | const sentinel_ty = try pt.optionalType(elem_ty.toIntern()); |
| 20503 | const sentinel_uncoerced = try sema.resolveInst(extra.sentinel); | |
| 19905 | const sentinel_uncoerced = sema.resolveInst(extra.sentinel); | |
| 20504 | 19906 | const sentinel_coerced = try sema.coerce(block, sentinel_ty, sentinel_uncoerced, sentinel_src); |
| 20505 | 19907 | const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel_coerced, .{ .simple = .pointer_sentinel }); |
| 20506 | 19908 | const opt_sentinel = sentinel_val.optionalValue(zcu); |
| ... | ... | @@ -20516,7 +19918,7 @@ fn zirReifyPointer( |
| 20516 | 19918 | } |
| 20517 | 19919 | } |
| 20518 | 19920 | |
| 20519 | return .fromType(try pt.ptrTypeSema(.{ | |
| 19921 | return .fromType(try pt.ptrType(.{ | |
| 20520 | 19922 | .child = elem_ty.toIntern(), |
| 20521 | 19923 | .sentinel = if (opt_sentinel) |s| s.toIntern() else .none, |
| 20522 | 19924 | .flags = .{ |
| ... | ... | @@ -20554,7 +19956,7 @@ fn zirReifyFn( |
| 20554 | 19956 | const single_param_attrs_ty = try sema.getBuiltinType(param_attrs_src, .@"Type.Fn.Param.Attributes"); |
| 20555 | 19957 | const fn_attrs_ty = try sema.getBuiltinType(fn_attrs_src, .@"Type.Fn.Attributes"); |
| 20556 | 19958 | |
| 20557 | const param_types_uncoerced = try sema.resolveInst(extra.param_types); | |
| 19959 | const param_types_uncoerced = sema.resolveInst(extra.param_types); | |
| 20558 | 19960 | const param_types_coerced = try sema.coerce(block, .slice_const_type, param_types_uncoerced, param_types_src); |
| 20559 | 19961 | const param_types_slice = try sema.resolveConstDefinedValue(block, param_types_src, param_types_coerced, .{ .simple = .fn_param_types }); |
| 20560 | 19962 | const param_types_arr = try sema.derefSliceAsArray(block, param_types_src, param_types_slice, .{ .simple = .fn_param_types }); |
| ... | ... | @@ -20565,14 +19967,14 @@ fn zirReifyFn( |
| 20565 | 19967 | .len = params_len, |
| 20566 | 19968 | .child = single_param_attrs_ty.toIntern(), |
| 20567 | 19969 | })); |
| 20568 | const param_attrs_uncoerced = try sema.resolveInst(extra.param_attrs); | |
| 19970 | const param_attrs_uncoerced = sema.resolveInst(extra.param_attrs); | |
| 20569 | 19971 | const param_attrs_coerced = try sema.coerce(block, param_attrs_ty, param_attrs_uncoerced, param_attrs_src); |
| 20570 | 19972 | const param_attrs_slice = try sema.resolveConstDefinedValue(block, param_attrs_src, param_attrs_coerced, .{ .simple = .fn_param_attrs }); |
| 20571 | 19973 | const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs }); |
| 20572 | 19974 | |
| 20573 | 19975 | const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty); |
| 20574 | 19976 | |
| 20575 | const fn_attrs_uncoerced = try sema.resolveInst(extra.fn_attrs); | |
| 19977 | const fn_attrs_uncoerced = sema.resolveInst(extra.fn_attrs); | |
| 20576 | 19978 | const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src); |
| 20577 | 19979 | const fn_attrs_val = try sema.resolveConstDefinedValue(block, fn_attrs_src, fn_attrs_coerced, .{ .simple = .fn_attrs }); |
| 20578 | 19980 | const fn_attrs = try sema.interpretBuiltinType(block, fn_attrs_src, fn_attrs_val, std.builtin.Type.Fn.Attributes); |
| ... | ... | @@ -20587,17 +19989,15 @@ fn zirReifyFn( |
| 20587 | 19989 | try param_attrs_arr.elemValue(pt, param_idx), |
| 20588 | 19990 | std.builtin.Type.Fn.Param.Attributes, |
| 20589 | 19991 | ); |
| 20590 | try sema.checkParamTypeCommon( | |
| 19992 | try sema.checkParamType( | |
| 20591 | 19993 | block, |
| 20592 | 19994 | @intCast(param_idx), |
| 20593 | 19995 | param_ty, |
| 19996 | false, | |
| 20594 | 19997 | param_attrs.@"noalias", |
| 20595 | 19998 | param_types_src, |
| 20596 | 19999 | fn_attrs.@"callconv", |
| 20597 | 20000 | ); |
| 20598 | if (try param_ty.comptimeOnlySema(pt)) { | |
| 20599 | return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)}); | |
| 20600 | } | |
| 20601 | 20001 | if (param_attrs.@"noalias") { |
| 20602 | 20002 | if (param_idx > 31) { |
| 20603 | 20003 | return sema.fail(block, param_attrs_src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}); |
| ... | ... | @@ -20611,7 +20011,7 @@ fn zirReifyFn( |
| 20611 | 20011 | try sema.checkCallConvSupportsVarArgs(block, fn_attrs_src, fn_attrs.@"callconv"); |
| 20612 | 20012 | } |
| 20613 | 20013 | |
| 20614 | try sema.checkReturnTypeAndCallConvCommon( | |
| 20014 | try sema.checkReturnTypeAndCallConv( | |
| 20615 | 20015 | block, |
| 20616 | 20016 | ret_ty, |
| 20617 | 20017 | ret_ty_src, |
| ... | ... | @@ -20621,9 +20021,6 @@ fn zirReifyFn( |
| 20621 | 20021 | false, |
| 20622 | 20022 | false, |
| 20623 | 20023 | ); |
| 20624 | if (try ret_ty.comptimeOnlySema(pt)) { | |
| 20625 | return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)}); | |
| 20626 | } | |
| 20627 | 20024 | |
| 20628 | 20025 | return .fromIntern(try ip.getFuncType(gpa, io, pt.tid, .{ |
| 20629 | 20026 | .param_types = param_types_ip, |
| ... | ... | @@ -20632,7 +20029,6 @@ fn zirReifyFn( |
| 20632 | 20029 | .return_type = ret_ty.toIntern(), |
| 20633 | 20030 | .cc = fn_attrs.@"callconv", |
| 20634 | 20031 | .is_var_args = fn_attrs.varargs, |
| 20635 | .is_generic = false, | |
| 20636 | 20032 | .is_noinline = false, |
| 20637 | 20033 | })); |
| 20638 | 20034 | } |
| ... | ... | @@ -20653,6 +20049,7 @@ fn zirReifyStruct( |
| 20653 | 20049 | const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); |
| 20654 | 20050 | const extra = sema.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data; |
| 20655 | 20051 | const tracked_inst = try block.trackZir(inst); |
| 20052 | ||
| 20656 | 20053 | const src: LazySrcLoc = .{ |
| 20657 | 20054 | .base_node_inst = tracked_inst, |
| 20658 | 20055 | .offset = .nodeOffset(.zero), |
| ... | ... | @@ -20697,16 +20094,16 @@ fn zirReifyStruct( |
| 20697 | 20094 | const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout"); |
| 20698 | 20095 | const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.StructField.Attributes"); |
| 20699 | 20096 | |
| 20700 | const layout_uncoerced = try sema.resolveInst(extra.layout); | |
| 20097 | const layout_uncoerced = sema.resolveInst(extra.layout); | |
| 20701 | 20098 | const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src); |
| 20702 | 20099 | const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .struct_layout }); |
| 20703 | 20100 | const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout); |
| 20704 | 20101 | |
| 20705 | const backing_int_ty_uncoerced = try sema.resolveInst(extra.backing_ty); | |
| 20102 | const backing_int_ty_uncoerced = sema.resolveInst(extra.backing_ty); | |
| 20706 | 20103 | const backing_int_ty_coerced = try sema.coerce(block, .optional_type, backing_int_ty_uncoerced, backing_ty_src); |
| 20707 | const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .type }); | |
| 20104 | const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .packed_struct_backing_int_type }); | |
| 20708 | 20105 | |
| 20709 | const field_names_uncoerced = try sema.resolveInst(extra.field_names); | |
| 20106 | const field_names_uncoerced = sema.resolveInst(extra.field_names); | |
| 20710 | 20107 | const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); |
| 20711 | 20108 | const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .struct_field_names }); |
| 20712 | 20109 | const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .struct_field_names }); |
| ... | ... | @@ -20722,12 +20119,12 @@ fn zirReifyStruct( |
| 20722 | 20119 | .child = single_field_attrs_ty.toIntern(), |
| 20723 | 20120 | })); |
| 20724 | 20121 | |
| 20725 | const field_types_uncoerced = try sema.resolveInst(extra.field_types); | |
| 20122 | const field_types_uncoerced = sema.resolveInst(extra.field_types); | |
| 20726 | 20123 | const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src); |
| 20727 | 20124 | const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .struct_field_types }); |
| 20728 | 20125 | const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .struct_field_types }); |
| 20729 | 20126 | |
| 20730 | const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs); | |
| 20127 | const field_attrs_uncoerced = sema.resolveInst(extra.field_attrs); | |
| 20731 | 20128 | const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src); |
| 20732 | 20129 | const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .struct_field_attrs }); |
| 20733 | 20130 | const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .struct_field_attrs }); |
| ... | ... | @@ -20744,19 +20141,30 @@ fn zirReifyStruct( |
| 20744 | 20141 | return sema.failWithUseOfUndef(block, backing_ty_src, null); |
| 20745 | 20142 | } |
| 20746 | 20143 | |
| 20747 | // The validation work here is non-trivial, and it's possible the type already exists. | |
| 20748 | // So in this first pass, let's just construct a hash to optimize for this case. If the | |
| 20749 | // inputs turn out to be invalid, we can cancel the WIP type later. | |
| 20144 | // Most validation of this type happens during type resolution. We basically need to do the work | |
| 20145 | // which AstGen would normally do. An exception is checking for duplicate field names, which is | |
| 20146 | // handled by type resolution---it just simplifies some logic a little. | |
| 20147 | ||
| 20148 | // As well as validation, we're going to gather some information about the fields, and construct | |
| 20149 | // a hash representing the inputs for deduplication purposes. | |
| 20750 | 20150 | |
| 20751 | 20151 | var any_comptime_fields = false; |
| 20752 | var any_default_inits = false; | |
| 20753 | var any_aligned_fields = false; | |
| 20152 | var any_field_defaults = false; | |
| 20153 | var any_field_aligns = false; | |
| 20754 | 20154 | |
| 20755 | // For deduplication purposes, we must create a hash including all details of this type. | |
| 20756 | 20155 | // TODO: use a longer hash! |
| 20757 | 20156 | var hasher = std.hash.Wyhash.init(0); |
| 20758 | 20157 | std.hash.autoHash(&hasher, layout); |
| 20759 | 20158 | std.hash.autoHash(&hasher, backing_int_ty_val); |
| 20159 | ||
| 20160 | const backing_int_ty: ?Type = if (backing_int_ty_val.optionalValue(zcu)) |backing| ty: { | |
| 20161 | switch (layout) { | |
| 20162 | .auto, .@"extern" => return sema.fail(block, backing_ty_src, "non-packed struct does not support backing integer type", .{}), | |
| 20163 | .@"packed" => {}, | |
| 20164 | } | |
| 20165 | break :ty backing.toType(); | |
| 20166 | } else null; | |
| 20167 | ||
| 20760 | 20168 | // The field *type* array has already been deduplicated for us thanks to the InternPool! |
| 20761 | 20169 | std.hash.autoHash(&hasher, field_types_arr); |
| 20762 | 20170 | // However, for field names and attributes, we need to actually iterate the individual fields, |
| ... | ... | @@ -20791,207 +20199,119 @@ fn zirReifyStruct( |
| 20791 | 20199 | field_attrs_src, |
| 20792 | 20200 | .{ .simple = .struct_field_default_value }, |
| 20793 | 20201 | ); |
| 20794 | // Resolve the value so that lazy values do not create distinct types. | |
| 20795 | break :d (try sema.resolveLazyValue(deref_val)).toIntern(); | |
| 20202 | if (deref_val.canMutateComptimeVarState(zcu)) { | |
| 20203 | return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val); | |
| 20204 | } | |
| 20205 | any_field_defaults = true; | |
| 20206 | break :d deref_val.toIntern(); | |
| 20796 | 20207 | }; |
| 20797 | 20208 | |
| 20209 | if (field_attr_comptime.toBool()) { | |
| 20210 | if (field_default == .none) { | |
| 20211 | return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{}); | |
| 20212 | } | |
| 20213 | if (layout != .auto) { | |
| 20214 | return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout}); | |
| 20215 | } | |
| 20216 | any_comptime_fields = true; | |
| 20217 | } | |
| 20218 | ||
| 20219 | if (field_attr_align.optionalValue(zcu)) |align_val| { | |
| 20220 | if (layout == .@"packed") { | |
| 20221 | return sema.fail(block, field_attrs_src, "packed struct fields cannot be aligned", .{}); | |
| 20222 | } | |
| 20223 | // Trigger a compile error if the alignment is invalid. | |
| 20224 | _ = try sema.validateAlign(block, field_attrs_src, align_val.toUnsignedInt(zcu)); | |
| 20225 | any_field_aligns = true; | |
| 20226 | } | |
| 20227 | ||
| 20798 | 20228 | std.hash.autoHash(&hasher, .{ |
| 20799 | 20229 | field_name, |
| 20800 | 20230 | field_attr_comptime, |
| 20801 | 20231 | field_attr_align, |
| 20802 | 20232 | field_default, |
| 20803 | 20233 | }); |
| 20804 | ||
| 20805 | if (field_attr_comptime.toBool()) any_comptime_fields = true; | |
| 20806 | if (field_attr_align.optionalValue(zcu)) |_| any_aligned_fields = true; | |
| 20807 | if (field_default != .none) any_default_inits = true; | |
| 20808 | } | |
| 20809 | ||
| 20810 | // Some basic validation to avoid a bogus `getStructType` call... | |
| 20811 | const backing_int_ty: ?Type = if (backing_int_ty_val.optionalValue(zcu)) |backing| ty: { | |
| 20812 | switch (layout) { | |
| 20813 | .auto, .@"extern" => return sema.fail(block, backing_ty_src, "non-packed struct does not support backing integer type", .{}), | |
| 20814 | .@"packed" => {}, | |
| 20815 | } | |
| 20816 | break :ty backing.toType(); | |
| 20817 | } else null; | |
| 20818 | if (any_aligned_fields and layout == .@"packed") { | |
| 20819 | return sema.fail(block, field_attrs_src, "packed struct fields cannot be aligned", .{}); | |
| 20820 | } | |
| 20821 | if (any_comptime_fields and layout != .auto) { | |
| 20822 | return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout}); | |
| 20823 | 20234 | } |
| 20824 | 20235 | |
| 20825 | const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ | |
| 20826 | .layout = layout, | |
| 20236 | switch (try ip.getReifiedStructType(gpa, io, pt.tid, .{ | |
| 20237 | .zir_index = tracked_inst, | |
| 20238 | .type_hash = hasher.final(), | |
| 20827 | 20239 | .fields_len = @intCast(fields_len), |
| 20828 | .known_non_opv = false, | |
| 20829 | .requires_comptime = .unknown, | |
| 20240 | .layout = layout, | |
| 20830 | 20241 | .any_comptime_fields = any_comptime_fields, |
| 20831 | .any_default_inits = any_default_inits, | |
| 20832 | .any_aligned_fields = any_aligned_fields, | |
| 20833 | .inits_resolved = true, | |
| 20834 | .key = .{ .reified = .{ | |
| 20835 | .zir_index = tracked_inst, | |
| 20836 | .type_hash = hasher.final(), | |
| 20837 | } }, | |
| 20838 | }, false)) { | |
| 20839 | .wip => |wip| wip, | |
| 20242 | .any_field_defaults = any_field_defaults, | |
| 20243 | .any_field_aligns = any_field_aligns, | |
| 20244 | .packed_backing_int_type = if (backing_int_ty) |ty| ty.toIntern() else .none, | |
| 20245 | })) { | |
| 20840 | 20246 | .existing => |ty| { |
| 20841 | try sema.declareDependency(.{ .interned = ty }); | |
| 20842 | try sema.addTypeReferenceEntry(src, ty); | |
| 20843 | return Air.internedToRef(ty); | |
| 20247 | try sema.addTypeReferenceEntry(src, .fromInterned(ty)); | |
| 20248 | // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. | |
| 20249 | return .fromIntern(ty); | |
| 20844 | 20250 | }, |
| 20845 | }; | |
| 20846 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 20847 | ||
| 20848 | const type_name = try sema.createTypeName( | |
| 20849 | block, | |
| 20850 | name_strategy, | |
| 20851 | "struct", | |
| 20852 | inst, | |
| 20853 | wip_ty.index, | |
| 20854 | ); | |
| 20855 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 20856 | ||
| 20857 | const wip_struct_type = ip.loadStructType(wip_ty.index); | |
| 20858 | ||
| 20859 | for (0..fields_len) |field_idx| { | |
| 20860 | const field_name_val = try field_names_arr.elemValue(pt, field_idx); | |
| 20861 | const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx); | |
| 20862 | ||
| 20863 | const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); | |
| 20864 | ||
| 20865 | // Don't pass a reason; first loop acts as a check that this is valid. | |
| 20866 | const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); | |
| 20867 | if (wip_struct_type.addFieldName(ip, field_name)) |prev_index| { | |
| 20868 | _ = prev_index; // TODO: better source location | |
| 20869 | return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); | |
| 20870 | } | |
| 20871 | ||
| 20872 | const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( | |
| 20873 | std.builtin.Type.StructField.Attributes, | |
| 20874 | "comptime", | |
| 20875 | ).?); | |
| 20876 | const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( | |
| 20877 | std.builtin.Type.StructField.Attributes, | |
| 20878 | "align", | |
| 20879 | ).?); | |
| 20880 | const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( | |
| 20881 | std.builtin.Type.StructField.Attributes, | |
| 20882 | "default_value_ptr", | |
| 20883 | ).?); | |
| 20884 | ||
| 20885 | if (field_attr_align.optionalValue(zcu)) |field_align_val| { | |
| 20886 | assert(layout != .@"packed"); | |
| 20887 | const bytes = try field_align_val.toUnsignedIntSema(pt); | |
| 20888 | const a = try sema.validateAlign(block, field_attrs_src, bytes); | |
| 20889 | wip_struct_type.field_aligns.get(ip)[field_idx] = a; | |
| 20890 | } else if (any_aligned_fields) { | |
| 20891 | assert(layout != .@"packed"); | |
| 20892 | wip_struct_type.field_aligns.get(ip)[field_idx] = .none; | |
| 20893 | } | |
| 20251 | .wip => |wip| { | |
| 20252 | errdefer wip.cancel(ip, pt.tid); | |
| 20253 | try sema.setTypeName(block, &wip, name_strategy, "struct", inst); | |
| 20254 | for (0..fields_len) |field_idx| { | |
| 20255 | const field_name_val = try field_names_arr.elemValue(pt, field_idx); | |
| 20256 | const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx); | |
| 20257 | ||
| 20258 | // No source location or reason; first loop checked this is valid. | |
| 20259 | const field_name = try sema.sliceToIpString(block, .unneeded, field_name_val, undefined); | |
| 20260 | wip.field_names.get(ip)[field_idx] = field_name; | |
| 20261 | ||
| 20262 | const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); | |
| 20263 | wip.field_types.get(ip)[field_idx] = field_ty.toIntern(); | |
| 20264 | ||
| 20265 | const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( | |
| 20266 | std.builtin.Type.StructField.Attributes, | |
| 20267 | "comptime", | |
| 20268 | ).?); | |
| 20269 | const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( | |
| 20270 | std.builtin.Type.StructField.Attributes, | |
| 20271 | "align", | |
| 20272 | ).?); | |
| 20273 | const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( | |
| 20274 | std.builtin.Type.StructField.Attributes, | |
| 20275 | "default_value_ptr", | |
| 20276 | ).?); | |
| 20277 | ||
| 20278 | if (field_attr_comptime.toBool()) { | |
| 20279 | const bit_bag_index = field_idx / 32; | |
| 20280 | const mask = @as(u32, 1) << @intCast(field_idx % 32); | |
| 20281 | wip.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; | |
| 20282 | } | |
| 20894 | 20283 | |
| 20895 | const field_default: InternPool.Index = d: { | |
| 20896 | const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none; | |
| 20897 | assert(any_default_inits); | |
| 20898 | const ptr_ty = try pt.singleConstPtrType(field_ty); | |
| 20899 | // The first loop checked that this is comptime-dereferencable. | |
| 20900 | const deref_val = (try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty)).?; | |
| 20901 | // ...but we've not checked this yet! | |
| 20902 | if (deref_val.canMutateComptimeVarState(zcu)) { | |
| 20903 | return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val); | |
| 20904 | } | |
| 20905 | break :d (try sema.resolveLazyValue(deref_val)).toIntern(); | |
| 20906 | }; | |
| 20284 | if (field_attr_default_value_ptr.optionalValue(zcu)) |ptr_val| { | |
| 20285 | const ptr_ty = try pt.singleConstPtrType(field_ty); | |
| 20286 | // No source location; first loop checked this is valid. | |
| 20287 | const deref_val = (try sema.pointerDeref(block, .unneeded, ptr_val, ptr_ty)).?; | |
| 20288 | wip.field_values.get(ip)[field_idx] = deref_val.toIntern(); | |
| 20289 | } else if (any_field_defaults) { | |
| 20290 | wip.field_values.get(ip)[field_idx] = .none; | |
| 20291 | } | |
| 20907 | 20292 | |
| 20908 | if (field_attr_comptime.toBool()) { | |
| 20909 | assert(layout == .auto); | |
| 20910 | if (field_default == .none) { | |
| 20911 | return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{}); | |
| 20293 | if (field_attr_align.optionalValue(zcu)) |field_align_val| { | |
| 20294 | const bytes = field_align_val.toUnsignedInt(zcu); | |
| 20295 | // No source location; first loop checked this is valid. | |
| 20296 | const a = try sema.validateAlign(block, .unneeded, bytes); | |
| 20297 | wip.field_aligns.get(ip)[field_idx] = a; | |
| 20298 | } else if (any_field_aligns) { | |
| 20299 | wip.field_aligns.get(ip)[field_idx] = .none; | |
| 20300 | } | |
| 20912 | 20301 | } |
| 20913 | wip_struct_type.setFieldComptime(ip, field_idx); | |
| 20914 | } | |
| 20915 | ||
| 20916 | wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern(); | |
| 20917 | if (field_default != .none) { | |
| 20918 | wip_struct_type.field_inits.get(ip)[field_idx] = field_default; | |
| 20919 | } | |
| 20920 | ||
| 20921 | switch (field_ty.zigTypeTag(zcu)) { | |
| 20922 | .@"opaque" => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 20923 | const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | |
| 20924 | errdefer msg.destroy(gpa); | |
| 20925 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 20926 | break :msg msg; | |
| 20927 | }), | |
| 20928 | .noreturn => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 20929 | const msg = try sema.errMsg(field_types_src, "struct fields cannot be 'noreturn'", .{}); | |
| 20930 | errdefer msg.destroy(gpa); | |
| 20931 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 20932 | break :msg msg; | |
| 20933 | }), | |
| 20934 | else => {}, | |
| 20935 | } | |
| 20936 | ||
| 20937 | switch (layout) { | |
| 20938 | .auto => {}, | |
| 20939 | .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) { | |
| 20940 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 20941 | const msg = try sema.errMsg(field_types_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 20942 | errdefer msg.destroy(gpa); | |
| 20943 | try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .struct_field); | |
| 20944 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 20945 | break :msg msg; | |
| 20946 | }); | |
| 20947 | }, | |
| 20948 | .@"packed" => if (!try sema.validatePackedType(field_ty)) { | |
| 20949 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 20950 | const msg = try sema.errMsg(field_types_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 20951 | errdefer msg.destroy(gpa); | |
| 20952 | try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty); | |
| 20953 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 20954 | break :msg msg; | |
| 20955 | }); | |
| 20956 | }, | |
| 20957 | } | |
| 20958 | } | |
| 20959 | ||
| 20960 | if (layout == .@"packed") { | |
| 20961 | var fields_bit_sum: u64 = 0; | |
| 20962 | for (0..wip_struct_type.field_types.len) |field_idx| { | |
| 20963 | const field_ty: Type = .fromInterned(wip_struct_type.field_types.get(ip)[field_idx]); | |
| 20964 | try field_ty.resolveLayout(pt); | |
| 20965 | fields_bit_sum += field_ty.bitSize(zcu); | |
| 20966 | } | |
| 20967 | if (backing_int_ty) |ty| { | |
| 20968 | try sema.checkBackingIntType(block, src, ty, fields_bit_sum); | |
| 20969 | wip_struct_type.setBackingIntType(ip, io, ty.toIntern()); | |
| 20970 | } else { | |
| 20971 | const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); | |
| 20972 | wip_struct_type.setBackingIntType(ip, io, ty.toIntern()); | |
| 20973 | } | |
| 20974 | } | |
| 20975 | ||
| 20976 | const new_namespace_index = try pt.createNamespace(.{ | |
| 20977 | .parent = block.namespace.toOptional(), | |
| 20978 | .owner_type = wip_ty.index, | |
| 20979 | .file_scope = block.getFileScopeIndex(zcu), | |
| 20980 | .generation = zcu.generation, | |
| 20981 | }); | |
| 20982 | 20302 | |
| 20983 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 20984 | codegen_type: { | |
| 20985 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 20986 | if (block.ownerModule().strip) break :codegen_type; | |
| 20987 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 20988 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 20989 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 20303 | const new_namespace_index = try pt.createNamespace(.{ | |
| 20304 | .parent = block.namespace.toOptional(), | |
| 20305 | .owner_type = wip.index, | |
| 20306 | .file_scope = block.getFileScopeIndex(zcu), | |
| 20307 | .generation = zcu.generation, | |
| 20308 | }); | |
| 20309 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 20310 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 20311 | try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); | |
| 20312 | return .fromIntern(wip.finish(ip, new_namespace_index)); | |
| 20313 | }, | |
| 20990 | 20314 | } |
| 20991 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 20992 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 20993 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 20994 | return .fromIntern(wip_ty.finish(ip, new_namespace_index)); | |
| 20995 | 20315 | } |
| 20996 | 20316 | |
| 20997 | 20317 | fn zirReifyUnion( |
| ... | ... | @@ -21054,16 +20374,19 @@ fn zirReifyUnion( |
| 21054 | 20374 | const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout"); |
| 21055 | 20375 | const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.UnionField.Attributes"); |
| 21056 | 20376 | |
| 21057 | const layout_uncoerced = try sema.resolveInst(extra.layout); | |
| 20377 | const layout_uncoerced = sema.resolveInst(extra.layout); | |
| 21058 | 20378 | const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src); |
| 21059 | 20379 | const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .union_layout }); |
| 21060 | 20380 | const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout); |
| 21061 | 20381 | |
| 21062 | const arg_ty_uncoerced = try sema.resolveInst(extra.arg_ty); | |
| 20382 | const arg_ty_uncoerced = sema.resolveInst(extra.arg_ty); | |
| 21063 | 20383 | const arg_ty_coerced = try sema.coerce(block, .optional_type, arg_ty_uncoerced, arg_ty_src); |
| 21064 | const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, .{ .simple = .type }); | |
| 20384 | const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, switch (layout) { | |
| 20385 | .@"packed" => .{ .simple = .packed_union_backing_int_type }, | |
| 20386 | .auto, .@"extern" => .{ .simple = .union_enum_tag_type }, | |
| 20387 | }); | |
| 21065 | 20388 | |
| 21066 | const field_names_uncoerced = try sema.resolveInst(extra.field_names); | |
| 20389 | const field_names_uncoerced = sema.resolveInst(extra.field_names); | |
| 21067 | 20390 | const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); |
| 21068 | 20391 | const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .union_field_names }); |
| 21069 | 20392 | const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .union_field_names }); |
| ... | ... | @@ -21079,12 +20402,12 @@ fn zirReifyUnion( |
| 21079 | 20402 | .child = single_field_attrs_ty.toIntern(), |
| 21080 | 20403 | })); |
| 21081 | 20404 | |
| 21082 | const field_types_uncoerced = try sema.resolveInst(extra.field_types); | |
| 20405 | const field_types_uncoerced = sema.resolveInst(extra.field_types); | |
| 21083 | 20406 | const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src); |
| 21084 | 20407 | const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .union_field_types }); |
| 21085 | 20408 | const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .union_field_types }); |
| 21086 | 20409 | |
| 21087 | const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs); | |
| 20410 | const field_attrs_uncoerced = sema.resolveInst(extra.field_attrs); | |
| 21088 | 20411 | const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src); |
| 21089 | 20412 | const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .union_field_attrs }); |
| 21090 | 20413 | const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .union_field_attrs }); |
| ... | ... | @@ -21101,17 +20424,29 @@ fn zirReifyUnion( |
| 21101 | 20424 | return sema.failWithUseOfUndef(block, arg_ty_src, null); |
| 21102 | 20425 | } |
| 21103 | 20426 | |
| 21104 | // The validation work here is non-trivial, and it's possible the type already exists. | |
| 21105 | // So in this first pass, let's just construct a hash to optimize for this case. If the | |
| 21106 | // inputs turn out to be invalid, we can cancel the WIP type later. | |
| 20427 | // Most validation of this type happens during type resolution. We basically need to do the work | |
| 20428 | // which AstGen would normally do. An exception is checking for duplicate field names, which is | |
| 20429 | // handled by type resolution---it just simplifies some logic a little. | |
| 20430 | ||
| 20431 | // As well as validation, we're going to gather some information about the fields, and construct | |
| 20432 | // a hash representing the inputs for deduplication purposes. | |
| 21107 | 20433 | |
| 21108 | var any_aligned_fields = false; | |
| 20434 | var any_field_aligns = false; | |
| 21109 | 20435 | |
| 21110 | // For deduplication purposes, we must create a hash including all details of this type. | |
| 21111 | 20436 | // TODO: use a longer hash! |
| 21112 | 20437 | var hasher = std.hash.Wyhash.init(0); |
| 21113 | 20438 | std.hash.autoHash(&hasher, layout); |
| 21114 | 20439 | std.hash.autoHash(&hasher, arg_ty_val); |
| 20440 | ||
| 20441 | const explicit_tag_ty: ?Type, const explicit_packed_backing_type: ?Type = ty: { | |
| 20442 | const arg_ty = arg_ty_val.optionalValue(zcu) orelse break :ty .{ null, null }; | |
| 20443 | switch (layout) { | |
| 20444 | .@"extern" => return sema.fail(block, arg_ty_src, "extern union does not support enum tag type", .{}), | |
| 20445 | .@"packed" => break :ty .{ null, arg_ty.toType() }, | |
| 20446 | .auto => break :ty .{ arg_ty.toType(), null }, | |
| 20447 | } | |
| 20448 | }; | |
| 20449 | ||
| 21115 | 20450 | // `field_types_arr` and `field_attrs_arr` are already deduplicated by the InternPool! |
| 21116 | 20451 | std.hash.autoHash(&hasher, field_types_arr); |
| 21117 | 20452 | std.hash.autoHash(&hasher, field_attrs_arr); |
| ... | ... | @@ -21128,203 +20463,76 @@ fn zirReifyUnion( |
| 21128 | 20463 | try field_attrs_arr.elemValue(pt, field_idx), |
| 21129 | 20464 | std.builtin.Type.UnionField.Attributes, |
| 21130 | 20465 | ); |
| 21131 | if (field_attrs.@"align" != null) { | |
| 21132 | any_aligned_fields = true; | |
| 21133 | } | |
| 21134 | } | |
| 21135 | ||
| 21136 | // Some basic validation to avoid a bogus `getUnionType` call... | |
| 21137 | const explicit_tag_ty: ?Type = if (arg_ty_val.optionalValue(zcu)) |arg_ty| ty: { | |
| 21138 | switch (layout) { | |
| 21139 | .@"extern", .@"packed" => return sema.fail(block, arg_ty_src, "{t} union does not support enum tag type", .{layout}), | |
| 21140 | .auto => {}, | |
| 20466 | if (field_attrs.@"align") |bytes| { | |
| 20467 | if (layout == .@"packed") { | |
| 20468 | return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); | |
| 20469 | } | |
| 20470 | // Trigger a compile error if the alignment is invalid. | |
| 20471 | _ = try sema.validateAlign(block, field_attrs_src, bytes); | |
| 20472 | any_field_aligns = true; | |
| 21141 | 20473 | } |
| 21142 | break :ty arg_ty.toType(); | |
| 21143 | } else null; | |
| 21144 | if (any_aligned_fields and layout == .@"packed") { | |
| 21145 | return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); | |
| 21146 | 20474 | } |
| 21147 | 20475 | |
| 21148 | const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ | |
| 21149 | .flags = .{ | |
| 21150 | .layout = layout, | |
| 21151 | .status = .none, | |
| 21152 | .runtime_tag = rt: { | |
| 21153 | if (explicit_tag_ty != null) break :rt .tagged; | |
| 21154 | if (layout == .auto and block.wantSafeTypes()) break :rt .safety; | |
| 21155 | break :rt .none; | |
| 21156 | }, | |
| 21157 | .any_aligned_fields = any_aligned_fields, | |
| 21158 | .requires_comptime = .unknown, | |
| 21159 | .assumed_runtime_bits = false, | |
| 21160 | .assumed_pointer_aligned = false, | |
| 21161 | .alignment = .none, | |
| 21162 | }, | |
| 20476 | switch (try ip.getReifiedUnionType(gpa, io, pt.tid, .{ | |
| 20477 | .zir_index = tracked_inst, | |
| 20478 | .type_hash = hasher.final(), | |
| 21163 | 20479 | .fields_len = @intCast(fields_len), |
| 21164 | .enum_tag_ty = .none, // set later because not yet validated | |
| 21165 | .field_types = &.{}, // set later | |
| 21166 | .field_aligns = &.{}, // set later | |
| 21167 | .key = .{ .reified = .{ | |
| 21168 | .zir_index = tracked_inst, | |
| 21169 | .type_hash = hasher.final(), | |
| 21170 | } }, | |
| 21171 | }, false)) { | |
| 21172 | .wip => |wip| wip, | |
| 20480 | .layout = layout, | |
| 20481 | .any_field_aligns = any_field_aligns, | |
| 20482 | .tag_usage = tag: { | |
| 20483 | if (explicit_tag_ty != null) break :tag .tagged; | |
| 20484 | if (layout == .auto and block.wantSafeTypes()) break :tag .safety; | |
| 20485 | break :tag .none; | |
| 20486 | }, | |
| 20487 | .enum_tag_type = if (explicit_tag_ty) |ty| ty.toIntern() else .none, | |
| 20488 | .packed_backing_int_type = if (explicit_packed_backing_type) |ty| ty.toIntern() else .none, | |
| 20489 | })) { | |
| 21173 | 20490 | .existing => |ty| { |
| 21174 | try sema.declareDependency(.{ .interned = ty }); | |
| 21175 | try sema.addTypeReferenceEntry(src, ty); | |
| 21176 | return Air.internedToRef(ty); | |
| 20491 | try sema.addTypeReferenceEntry(src, .fromInterned(ty)); | |
| 20492 | // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. | |
| 20493 | return .fromIntern(ty); | |
| 21177 | 20494 | }, |
| 21178 | }; | |
| 21179 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 21180 | ||
| 21181 | const type_name = try sema.createTypeName( | |
| 21182 | block, | |
| 21183 | name_strategy, | |
| 21184 | "union", | |
| 21185 | inst, | |
| 21186 | wip_ty.index, | |
| 21187 | ); | |
| 21188 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 21189 | ||
| 21190 | const loaded_union = ip.loadUnionType(wip_ty.index); | |
| 21191 | ||
| 21192 | const enum_tag_ty, const has_explicit_tag = if (explicit_tag_ty) |enum_tag_ty| tag: { | |
| 21193 | if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") { | |
| 21194 | return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{}); | |
| 21195 | } | |
| 20495 | .wip => |wip| { | |
| 20496 | errdefer wip.cancel(ip, pt.tid); | |
| 20497 | try sema.setTypeName(block, &wip, name_strategy, "union", inst); | |
| 21196 | 20498 | |
| 21197 | const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu); | |
| 20499 | for (0..fields_len) |field_idx| { | |
| 20500 | const field_name_val = try field_names_arr.elemValue(pt, field_idx); | |
| 20501 | // No source location or reason; first loop checked this is valid. | |
| 20502 | const field_name = try sema.sliceToIpString(block, .unneeded, field_name_val, undefined); | |
| 20503 | wip.field_names.get(ip)[field_idx] = field_name; | |
| 21198 | 20504 | |
| 21199 | for (0..fields_len) |field_idx| { | |
| 21200 | const field_name_val = try field_names_arr.elemValue(pt, field_idx); | |
| 21201 | // Don't pass a reason; first loop acts as a check that this is valid. | |
| 21202 | const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); | |
| 20505 | const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); | |
| 20506 | wip.field_types.get(ip)[field_idx] = field_ty.toIntern(); | |
| 21203 | 20507 | |
| 21204 | if (field_idx >= tag_ty_fields_len) { | |
| 21205 | return sema.fail(block, field_names_src, "no field named '{f}' in enum '{f}'", .{ | |
| 21206 | field_name.fmt(ip), enum_tag_ty.fmt(pt), | |
| 21207 | }); | |
| 20508 | // No source location; first loop checked this is valid. | |
| 20509 | const field_attrs = try sema.interpretBuiltinType( | |
| 20510 | block, | |
| 20511 | .unneeded, | |
| 20512 | try field_attrs_arr.elemValue(pt, field_idx), | |
| 20513 | std.builtin.Type.UnionField.Attributes, | |
| 20514 | ); | |
| 20515 | if (field_attrs.@"align") |bytes| { | |
| 20516 | // No source location; first loop checked this is valid. | |
| 20517 | const a = try sema.validateAlign(block, .unneeded, bytes); | |
| 20518 | wip.field_aligns.get(ip)[field_idx] = a; | |
| 20519 | } else if (any_field_aligns) { | |
| 20520 | wip.field_aligns.get(ip)[field_idx] = .none; | |
| 20521 | } | |
| 21208 | 20522 | } |
| 21209 | 20523 | |
| 21210 | const enum_field_name = enum_tag_ty.enumFieldName(field_idx, zcu); | |
| 21211 | if (enum_field_name != field_name) { | |
| 21212 | return sema.fail(block, field_names_src, "union field name '{f}' does not match enum field name '{f}'", .{ | |
| 21213 | field_name.fmt(ip), enum_field_name.fmt(ip), | |
| 21214 | }); | |
| 21215 | } | |
| 21216 | } | |
| 21217 | if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 21218 | const msg = try sema.errMsg(field_names_src, "{d} enum fields missing in union", .{ | |
| 21219 | tag_ty_fields_len - fields_len, | |
| 20524 | const new_namespace_index = try pt.createNamespace(.{ | |
| 20525 | .parent = block.namespace.toOptional(), | |
| 20526 | .owner_type = wip.index, | |
| 20527 | .file_scope = block.getFileScopeIndex(zcu), | |
| 20528 | .generation = zcu.generation, | |
| 21220 | 20529 | }); |
| 21221 | errdefer msg.destroy(gpa); | |
| 21222 | for (fields_len..tag_ty_fields_len) |enum_field_idx| { | |
| 21223 | try sema.addFieldErrNote(enum_tag_ty, enum_field_idx, msg, "field '{f}' missing, declared here", .{ | |
| 21224 | enum_tag_ty.enumFieldName(enum_field_idx, zcu).fmt(ip), | |
| 21225 | }); | |
| 21226 | } | |
| 21227 | try sema.addDeclaredHereNote(msg, enum_tag_ty); | |
| 21228 | break :msg msg; | |
| 21229 | }); | |
| 21230 | break :tag .{ enum_tag_ty.toIntern(), true }; | |
| 21231 | } else tag: { | |
| 21232 | // We must track field names and set up the tag type ourselves. | |
| 21233 | var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; | |
| 21234 | try field_names.ensureTotalCapacity(sema.arena, fields_len); | |
| 21235 | ||
| 21236 | for (0..fields_len) |field_idx| { | |
| 21237 | const field_name_val = try field_names_arr.elemValue(pt, field_idx); | |
| 21238 | // Don't pass a reason; first loop acts as a check that this is valid. | |
| 21239 | const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); | |
| 21240 | const gop = field_names.getOrPutAssumeCapacity(field_name); | |
| 21241 | if (gop.found_existing) { | |
| 21242 | // TODO: better source location | |
| 21243 | return sema.fail(block, field_names_src, "duplicate union field {f}", .{field_name.fmt(ip)}); | |
| 21244 | } | |
| 21245 | } | |
| 21246 | const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name); | |
| 21247 | break :tag .{ enum_tag_ty, false }; | |
| 21248 | }; | |
| 21249 | errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error | |
| 21250 | ||
| 21251 | for (0..fields_len) |field_idx| { | |
| 21252 | const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); | |
| 21253 | const field_attrs = try sema.interpretBuiltinType( | |
| 21254 | block, | |
| 21255 | field_attrs_src, | |
| 21256 | try field_attrs_arr.elemValue(pt, field_idx), | |
| 21257 | std.builtin.Type.UnionField.Attributes, | |
| 21258 | ); | |
| 21259 | ||
| 21260 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 21261 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 21262 | const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | |
| 21263 | errdefer msg.destroy(gpa); | |
| 21264 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 21265 | break :msg msg; | |
| 21266 | }); | |
| 21267 | } | |
| 21268 | ||
| 21269 | switch (layout) { | |
| 21270 | .auto => {}, | |
| 21271 | .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) { | |
| 21272 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 21273 | const msg = try sema.errMsg(field_types_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 21274 | errdefer msg.destroy(gpa); | |
| 21275 | ||
| 21276 | try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .union_field); | |
| 21277 | ||
| 21278 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 21279 | break :msg msg; | |
| 21280 | }); | |
| 21281 | }, | |
| 21282 | .@"packed" => if (!try sema.validatePackedType(field_ty)) { | |
| 21283 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 21284 | const msg = try sema.errMsg(field_types_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 21285 | errdefer msg.destroy(gpa); | |
| 21286 | ||
| 21287 | try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty); | |
| 21288 | ||
| 21289 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 21290 | break :msg msg; | |
| 21291 | }); | |
| 21292 | }, | |
| 21293 | } | |
| 21294 | ||
| 21295 | loaded_union.field_types.get(ip)[field_idx] = field_ty.toIntern(); | |
| 21296 | if (field_attrs.@"align") |bytes| { | |
| 21297 | assert(layout != .@"packed"); | |
| 21298 | const a = try sema.validateAlign(block, field_attrs_src, bytes); | |
| 21299 | loaded_union.field_aligns.get(ip)[field_idx] = a; | |
| 21300 | } else if (any_aligned_fields) { | |
| 21301 | assert(layout != .@"packed"); | |
| 21302 | loaded_union.field_aligns.get(ip)[field_idx] = .none; | |
| 21303 | } | |
| 21304 | } | |
| 21305 | ||
| 21306 | loaded_union.setTagType(ip, io, enum_tag_ty); | |
| 21307 | loaded_union.setStatus(ip, io, .have_field_types); | |
| 21308 | ||
| 21309 | const new_namespace_index = try pt.createNamespace(.{ | |
| 21310 | .parent = block.namespace.toOptional(), | |
| 21311 | .owner_type = wip_ty.index, | |
| 21312 | .file_scope = block.getFileScopeIndex(zcu), | |
| 21313 | .generation = zcu.generation, | |
| 21314 | }); | |
| 21315 | ||
| 21316 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 21317 | codegen_type: { | |
| 21318 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 21319 | if (block.ownerModule().strip) break :codegen_type; | |
| 21320 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 21321 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 21322 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 20530 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 20531 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 20532 | try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); | |
| 20533 | return .fromIntern(wip.finish(ip, new_namespace_index)); | |
| 20534 | }, | |
| 21323 | 20535 | } |
| 21324 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 21325 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 21326 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 21327 | return .fromIntern(wip_ty.finish(ip, new_namespace_index)); | |
| 21328 | 20536 | } |
| 21329 | 20537 | |
| 21330 | 20538 | fn zirReifyEnum( |
| ... | ... | @@ -21379,12 +20587,12 @@ fn zirReifyEnum( |
| 21379 | 20587 | |
| 21380 | 20588 | const enum_mode_ty = try sema.getBuiltinType(mode_src, .@"Type.Enum.Mode"); |
| 21381 | 20589 | |
| 21382 | const tag_ty = try sema.resolveType(block, tag_ty_src, extra.tag_ty); | |
| 21383 | if (tag_ty.zigTypeTag(zcu) != .int) { | |
| 21384 | return sema.fail(block, tag_ty_src, "tag type must be an integer type", .{}); | |
| 21385 | } | |
| 20590 | const tag_ty_uncoerced = sema.resolveInst(extra.tag_ty); | |
| 20591 | const tag_ty_coerced = try sema.coerce(block, .type, tag_ty_uncoerced, tag_ty_src); | |
| 20592 | const tag_ty_val = try sema.resolveConstDefinedValue(block, tag_ty_src, tag_ty_coerced, .{ .simple = .enum_int_tag_type }); | |
| 20593 | const tag_ty = tag_ty_val.toType(); | |
| 21386 | 20594 | |
| 21387 | const mode_uncoerced = try sema.resolveInst(extra.mode); | |
| 20595 | const mode_uncoerced = sema.resolveInst(extra.mode); | |
| 21388 | 20596 | const mode_coerced = try sema.coerce(block, enum_mode_ty, mode_uncoerced, mode_src); |
| 21389 | 20597 | const mode_val = try sema.resolveConstDefinedValue(block, mode_src, mode_coerced, .{ .simple = .type }); |
| 21390 | 20598 | const nonexhaustive = switch (try sema.interpretBuiltinType(block, mode_src, mode_val, std.builtin.Type.Enum.Mode)) { |
| ... | ... | @@ -21392,7 +20600,7 @@ fn zirReifyEnum( |
| 21392 | 20600 | .nonexhaustive => true, |
| 21393 | 20601 | }; |
| 21394 | 20602 | |
| 21395 | const field_names_uncoerced = try sema.resolveInst(extra.field_names); | |
| 20603 | const field_names_uncoerced = sema.resolveInst(extra.field_names); | |
| 21396 | 20604 | const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); |
| 21397 | 20605 | const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .enum_field_names }); |
| 21398 | 20606 | const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .enum_field_names }); |
| ... | ... | @@ -21404,7 +20612,7 @@ fn zirReifyEnum( |
| 21404 | 20612 | .child = tag_ty.toIntern(), |
| 21405 | 20613 | })); |
| 21406 | 20614 | |
| 21407 | const field_values_uncoerced = try sema.resolveInst(extra.field_values); | |
| 20615 | const field_values_uncoerced = sema.resolveInst(extra.field_values); | |
| 21408 | 20616 | const field_values_coerced = try sema.coerce(block, field_values_ty, field_values_uncoerced, field_values_src); |
| 21409 | 20617 | const field_values_slice = try sema.resolveConstDefinedValue(block, field_values_src, field_values_coerced, .{ .simple = .enum_field_values }); |
| 21410 | 20618 | const field_values_arr = try sema.derefSliceAsArray(block, field_values_src, field_values_slice, .{ .simple = .enum_field_values }); |
| ... | ... | @@ -21415,11 +20623,13 @@ fn zirReifyEnum( |
| 21415 | 20623 | } |
| 21416 | 20624 | // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us. |
| 21417 | 20625 | |
| 21418 | // The validation work here is non-trivial, and it's possible the type already exists. | |
| 21419 | // So in this first pass, let's just construct a hash to optimize for this case. If the | |
| 21420 | // inputs turn out to be invalid, we can cancel the WIP type later. | |
| 20626 | // Most validation of this type happens during type resolution. We basically need to do the work | |
| 20627 | // which AstGen would normally do. An exception is checking for duplicate field names, which is | |
| 20628 | // handled by type resolution---it just simplifies some logic a little. | |
| 20629 | ||
| 20630 | // As well as validation, we're going to gather some information about the fields, and construct | |
| 20631 | // a hash representing the inputs for deduplication purposes. | |
| 21421 | 20632 | |
| 21422 | // For deduplication purposes, we must create a hash including all details of this type. | |
| 21423 | 20633 | // TODO: use a longer hash! |
| 21424 | 20634 | var hasher = std.hash.Wyhash.init(0); |
| 21425 | 20635 | std.hash.autoHash(&hasher, tag_ty.toIntern()); |
| ... | ... | @@ -21435,87 +20645,46 @@ fn zirReifyEnum( |
| 21435 | 20645 | std.hash.autoHash(&hasher, field_name); |
| 21436 | 20646 | } |
| 21437 | 20647 | |
| 21438 | const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ | |
| 21439 | .has_values = true, | |
| 21440 | .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit, | |
| 20648 | switch (try ip.getReifiedEnumType(gpa, io, pt.tid, .{ | |
| 20649 | .zir_index = tracked_inst, | |
| 20650 | .type_hash = hasher.final(), | |
| 21441 | 20651 | .fields_len = @intCast(fields_len), |
| 21442 | .key = .{ .reified = .{ | |
| 21443 | .zir_index = tracked_inst, | |
| 21444 | .type_hash = hasher.final(), | |
| 21445 | } }, | |
| 21446 | }, false)) { | |
| 21447 | .wip => |wip| wip, | |
| 20652 | .nonexhaustive = nonexhaustive, | |
| 20653 | .int_tag_type = tag_ty.toIntern(), | |
| 20654 | })) { | |
| 21448 | 20655 | .existing => |ty| { |
| 21449 | try sema.declareDependency(.{ .interned = ty }); | |
| 21450 | try sema.addTypeReferenceEntry(src, ty); | |
| 20656 | try sema.addTypeReferenceEntry(src, .fromInterned(ty)); | |
| 20657 | // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. | |
| 21451 | 20658 | return .fromIntern(ty); |
| 21452 | 20659 | }, |
| 21453 | }; | |
| 21454 | var done = false; | |
| 21455 | errdefer if (!done) wip_ty.cancel(ip, pt.tid); | |
| 21456 | ||
| 21457 | const type_name = try sema.createTypeName( | |
| 21458 | block, | |
| 21459 | name_strategy, | |
| 21460 | "enum", | |
| 21461 | inst, | |
| 21462 | wip_ty.index, | |
| 21463 | ); | |
| 21464 | wip_ty.setName(ip, type_name.name, type_name.nav); | |
| 21465 | ||
| 21466 | const new_namespace_index = try pt.createNamespace(.{ | |
| 21467 | .parent = block.namespace.toOptional(), | |
| 21468 | .owner_type = wip_ty.index, | |
| 21469 | .file_scope = block.getFileScopeIndex(zcu), | |
| 21470 | .generation = zcu.generation, | |
| 21471 | }); | |
| 20660 | .wip => |wip| { | |
| 20661 | errdefer wip.cancel(ip, pt.tid); | |
| 21472 | 20662 | |
| 21473 | try sema.declareDependency(.{ .interned = wip_ty.index }); | |
| 21474 | try sema.addTypeReferenceEntry(src, wip_ty.index); | |
| 21475 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 21476 | wip_ty.prepare(ip, new_namespace_index); | |
| 21477 | wip_ty.setTagTy(ip, tag_ty.toIntern()); | |
| 21478 | done = true; | |
| 20663 | try sema.setTypeName(block, &wip, name_strategy, "enum", inst); | |
| 21479 | 20664 | |
| 21480 | for (0..fields_len) |field_idx| { | |
| 21481 | const field_name_val = try field_names_arr.elemValue(pt, field_idx); | |
| 21482 | // Don't pass a reason; first loop acts as a check that this is valid. | |
| 21483 | const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); | |
| 20665 | // Populate field names and values. Duplicate checking will be handled by type resolution. | |
| 20666 | for (0..fields_len) |field_index| { | |
| 20667 | const field_name_val = try field_names_arr.elemValue(pt, field_index); | |
| 20668 | // No source location or reason; first loop checked this is valid. | |
| 20669 | const field_name = try sema.sliceToIpString(block, .unneeded, field_name_val, undefined); | |
| 20670 | wip.field_names.get(ip)[field_index] = field_name; | |
| 21484 | 20671 | |
| 21485 | const field_val = try field_values_arr.elemValue(pt, field_idx); | |
| 20672 | const field_val = try field_values_arr.elemValue(pt, field_index); | |
| 20673 | wip.field_values.get(ip)[field_index] = field_val.toIntern(); | |
| 20674 | } | |
| 21486 | 20675 | |
| 21487 | if (wip_ty.nextField(ip, field_name, field_val.toIntern())) |conflict| { | |
| 21488 | return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) { | |
| 21489 | .name => msg: { | |
| 21490 | const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}'", .{field_name.fmt(ip)}); | |
| 21491 | errdefer msg.destroy(gpa); | |
| 21492 | _ = conflict.prev_field_idx; // TODO: this note is incorrect | |
| 21493 | try sema.errNote(field_names_src, msg, "other field here", .{}); | |
| 21494 | break :msg msg; | |
| 21495 | }, | |
| 21496 | .value => msg: { | |
| 21497 | const msg = try sema.errMsg(field_values_src, "enum tag value {f} already taken", .{field_val.fmtValueSema(pt, sema)}); | |
| 21498 | errdefer msg.destroy(gpa); | |
| 21499 | _ = conflict.prev_field_idx; // TODO: this note is incorrect | |
| 21500 | try sema.errNote(field_values_src, msg, "other enum tag value here", .{}); | |
| 21501 | break :msg msg; | |
| 21502 | }, | |
| 20676 | const new_namespace_index = try pt.createNamespace(.{ | |
| 20677 | .parent = block.namespace.toOptional(), | |
| 20678 | .owner_type = wip.index, | |
| 20679 | .file_scope = block.getFileScopeIndex(zcu), | |
| 20680 | .generation = zcu.generation, | |
| 21503 | 20681 | }); |
| 21504 | } | |
| 21505 | } | |
| 21506 | ||
| 21507 | if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) { | |
| 21508 | return sema.fail(block, src, "non-exhaustive enum specified every value", .{}); | |
| 21509 | } | |
| 21510 | ||
| 21511 | codegen_type: { | |
| 21512 | if (zcu.comp.config.use_llvm) break :codegen_type; | |
| 21513 | if (block.ownerModule().strip) break :codegen_type; | |
| 21514 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 21515 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 21516 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 20682 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 20683 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 20684 | try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); | |
| 20685 | return .fromIntern(wip.finish(ip, new_namespace_index)); | |
| 20686 | }, | |
| 21517 | 20687 | } |
| 21518 | return Air.internedToRef(wip_ty.index); | |
| 21519 | 20688 | } |
| 21520 | 20689 | |
| 21521 | 20690 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -21523,7 +20692,7 @@ fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.In |
| 21523 | 20692 | const va_list_ty = try sema.getBuiltinType(src, .VaList); |
| 21524 | 20693 | const va_list_ptr = try pt.singleMutPtrType(va_list_ty); |
| 21525 | 20694 | |
| 21526 | const inst = try sema.resolveInst(zir_ref); | |
| 20695 | const inst = sema.resolveInst(zir_ref); | |
| 21527 | 20696 | return sema.coerce(block, va_list_ptr, inst, src); |
| 21528 | 20697 | } |
| 21529 | 20698 | |
| ... | ... | @@ -21535,8 +20704,8 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 21535 | 20704 | |
| 21536 | 20705 | const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.lhs); |
| 21537 | 20706 | const arg_ty = try sema.resolveType(block, ty_src, extra.rhs); |
| 21538 | ||
| 21539 | if (!try sema.validateExternType(arg_ty, .param_ty)) { | |
| 20707 | try sema.ensureLayoutResolved(arg_ty, ty_src, .parameter); | |
| 20708 | if (!arg_ty.validateExtern(.param_ty, sema.pt.zcu)) { | |
| 21540 | 20709 | const msg = msg: { |
| 21541 | 20710 | const msg = try sema.errMsg(ty_src, "cannot get '{f}' from variadic argument", .{arg_ty.fmt(sema.pt)}); |
| 21542 | 20711 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -21573,7 +20742,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 21573 | 20742 | const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand); |
| 21574 | 20743 | |
| 21575 | 20744 | try sema.requireRuntimeBlock(block, src, null); |
| 21576 | return block.addUnOp(.c_va_end, va_list_ref); | |
| 20745 | _ = try block.addUnOp(.c_va_end, va_list_ref); | |
| 20746 | return .void_value; | |
| 21577 | 20747 | } |
| 21578 | 20748 | |
| 21579 | 20749 | fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -21618,7 +20788,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21618 | 20788 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 21619 | 20789 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 21620 | 20790 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat"); |
| 21621 | const operand = try sema.resolveInst(extra.rhs); | |
| 20791 | const operand = sema.resolveInst(extra.rhs); | |
| 21622 | 20792 | const operand_ty = sema.typeOf(operand); |
| 21623 | 20793 | |
| 21624 | 20794 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| ... | ... | @@ -21630,7 +20800,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21630 | 20800 | _ = try sema.checkIntType(block, src, dest_scalar_ty); |
| 21631 | 20801 | try sema.checkFloatType(block, operand_src, operand_scalar_ty); |
| 21632 | 20802 | |
| 21633 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 20803 | if (sema.resolveValue(operand)) |operand_val| { | |
| 21634 | 20804 | const result_val = try sema.intFromFloat(block, operand_src, operand_val, operand_ty, dest_ty, .truncate); |
| 21635 | 20805 | return Air.internedToRef(result_val.toIntern()); |
| 21636 | 20806 | } else if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) { |
| ... | ... | @@ -21671,7 +20841,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21671 | 20841 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 21672 | 20842 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 21673 | 20843 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt"); |
| 21674 | const operand = try sema.resolveInst(extra.rhs); | |
| 20844 | const operand = sema.resolveInst(extra.rhs); | |
| 21675 | 20845 | const operand_ty = sema.typeOf(operand); |
| 21676 | 20846 | |
| 21677 | 20847 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| ... | ... | @@ -21682,9 +20852,21 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21682 | 20852 | try sema.checkFloatType(block, src, dest_scalar_ty); |
| 21683 | 20853 | _ = try sema.checkIntType(block, operand_src, operand_scalar_ty); |
| 21684 | 20854 | |
| 21685 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 21686 | const result_val = try operand_val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, pt, .sema); | |
| 21687 | return Air.internedToRef(result_val.toIntern()); | |
| 20855 | if (sema.resolveValue(operand)) |operand_val| { | |
| 20856 | if (operand_val.isUndef(zcu)) return .fromValue(try pt.undefValue(dest_ty)); | |
| 20857 | if (dest_ty.zigTypeTag(zcu) != .vector) { | |
| 20858 | return .fromValue(try pt.floatValue(dest_ty, operand_val.toFloat(f128, zcu))); | |
| 20859 | } | |
| 20860 | const dest_elems = try sema.arena.alloc(InternPool.Index, dest_ty.vectorLen(zcu)); | |
| 20861 | for (dest_elems, 0..) |*out_elem, elem_idx| { | |
| 20862 | const orig_elem = try operand_val.elemValue(pt, elem_idx); | |
| 20863 | const casted_elem = if (orig_elem.isUndef(zcu)) | |
| 20864 | try pt.undefValue(dest_scalar_ty) | |
| 20865 | else | |
| 20866 | try pt.floatValue(dest_scalar_ty, orig_elem.toFloat(f128, zcu)); | |
| 20867 | out_elem.* = casted_elem.toIntern(); | |
| 20868 | } | |
| 20869 | return .fromValue(try pt.aggregateValue(dest_ty, dest_elems)); | |
| 21688 | 20870 | } else if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_float) { |
| 21689 | 20871 | return sema.failWithNeededComptime(block, operand_src, .{ .simple = .casted_to_comptime_float }); |
| 21690 | 20872 | } |
| ... | ... | @@ -21702,7 +20884,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21702 | 20884 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 21703 | 20885 | |
| 21704 | 20886 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 21705 | const operand_res = try sema.resolveInst(extra.rhs); | |
| 20887 | const operand_res = sema.resolveInst(extra.rhs); | |
| 21706 | 20888 | |
| 21707 | 20889 | const uncoerced_operand_ty = sema.typeOf(operand_res); |
| 21708 | 20890 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt"); |
| ... | ... | @@ -21719,8 +20901,10 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21719 | 20901 | const ptr_ty = dest_ty.scalarType(zcu); |
| 21720 | 20902 | try sema.checkPtrType(block, src, ptr_ty, true); |
| 21721 | 20903 | |
| 21722 | const elem_ty = ptr_ty.elemType2(zcu); | |
| 21723 | const ptr_align = try ptr_ty.ptrAlignmentSema(pt); | |
| 20904 | const elem_ty = ptr_ty.nullablePtrElem(zcu); | |
| 20905 | ||
| 20906 | try sema.ensureLayoutResolved(elem_ty, src, .align_check); | |
| 20907 | const ptr_align = ptr_ty.ptrAlignment(zcu); | |
| 21724 | 20908 | |
| 21725 | 20909 | if (ptr_ty.isSlice(zcu)) { |
| 21726 | 20910 | const msg = msg: { |
| ... | ... | @@ -21746,18 +20930,9 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 21746 | 20930 | } |
| 21747 | 20931 | return Air.internedToRef((try pt.aggregateValue(dest_ty, new_elems)).toIntern()); |
| 21748 | 20932 | } |
| 21749 | if (try ptr_ty.comptimeOnlySema(pt)) { | |
| 21750 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 21751 | const msg = try sema.errMsg(src, "pointer to comptime-only type '{f}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)}); | |
| 21752 | errdefer msg.destroy(sema.gpa); | |
| 21753 | ||
| 21754 | try sema.explainWhyTypeIsComptime(msg, src, ptr_ty); | |
| 21755 | break :msg msg; | |
| 21756 | }); | |
| 21757 | } | |
| 21758 | 20933 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 21759 | 20934 | try sema.checkLogicalPtrOperation(block, src, ptr_ty); |
| 21760 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { | |
| 20935 | if (block.wantSafety()) { | |
| 21761 | 20936 | if (!ptr_ty.isAllowzeroPtr(zcu)) { |
| 21762 | 20937 | const is_non_zero = if (is_vector) all_non_zero: { |
| 21763 | 20938 | const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); |
| ... | ... | @@ -21804,7 +20979,7 @@ fn ptrFromIntVal( |
| 21804 | 20979 | } |
| 21805 | 20980 | return sema.failWithUseOfUndef(block, operand_src, vec_idx); |
| 21806 | 20981 | } |
| 21807 | const addr = try operand_val.toUnsignedIntSema(pt); | |
| 20982 | const addr = operand_val.toUnsignedInt(zcu); | |
| 21808 | 20983 | if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0) |
| 21809 | 20984 | return sema.fail(block, operand_src, "pointer type '{f}' does not allow address zero", .{ptr_ty.fmt(pt)}); |
| 21810 | 20985 | if (addr != 0 and ptr_align != .none) { |
| ... | ... | @@ -21836,7 +21011,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 21836 | 21011 | const src = block.nodeOffset(extra.node); |
| 21837 | 21012 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 21838 | 21013 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt, "@errorCast"); |
| 21839 | const operand = try sema.resolveInst(extra.rhs); | |
| 21014 | const operand = sema.resolveInst(extra.rhs); | |
| 21840 | 21015 | const operand_ty = sema.typeOf(operand); |
| 21841 | 21016 | |
| 21842 | 21017 | const dest_tag = dest_ty.zigTypeTag(zcu); |
| ... | ... | @@ -21877,34 +21052,62 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 21877 | 21052 | else => unreachable, |
| 21878 | 21053 | }; |
| 21879 | 21054 | |
| 21880 | const disjoint = disjoint: { | |
| 21881 | // Try avoiding resolving inferred error sets if we can | |
| 21882 | if (!dest_err_ty.isAnyError(zcu) and dest_err_ty.errorSetIsEmpty(zcu)) break :disjoint true; | |
| 21883 | if (!operand_err_ty.isAnyError(zcu) and operand_err_ty.errorSetIsEmpty(zcu)) break :disjoint true; | |
| 21884 | if (dest_err_ty.isAnyError(zcu)) break :disjoint false; | |
| 21885 | if (operand_err_ty.isAnyError(zcu)) break :disjoint false; | |
| 21886 | const dest_err_names = dest_err_ty.errorSetNames(zcu); | |
| 21887 | for (0..dest_err_names.len) |dest_err_index| { | |
| 21888 | if (Type.errorSetHasFieldIp(ip, operand_err_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) | |
| 21889 | break :disjoint false; | |
| 21890 | } | |
| 21891 | ||
| 21892 | if (!ip.isInferredErrorSetType(dest_err_ty.toIntern()) and | |
| 21893 | !ip.isInferredErrorSetType(operand_err_ty.toIntern())) | |
| 21894 | { | |
| 21895 | break :disjoint true; | |
| 21896 | } | |
| 21897 | ||
| 21898 | _ = try sema.resolveInferredErrorSetTy(block, src, dest_err_ty.toIntern()); | |
| 21899 | _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_err_ty.toIntern()); | |
| 21900 | for (0..dest_err_names.len) |dest_err_index| { | |
| 21901 | if (Type.errorSetHasFieldIp(ip, operand_err_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) | |
| 21902 | break :disjoint false; | |
| 21903 | } | |
| 21055 | switch (ip.indexToKey(operand_err_ty.toIntern())) { | |
| 21056 | .inferred_error_set_type => |func| try sema.ensureFuncIesResolved(block, src, func), | |
| 21057 | else => {}, | |
| 21058 | } | |
| 21904 | 21059 | |
| 21905 | break :disjoint true; | |
| 21060 | const result: enum { | |
| 21061 | /// The operand and destination error sets are disjoint, i.e. have no errors in common. | |
| 21062 | disjoint, | |
| 21063 | /// The destination error set is a superset of the operand error set, so the operation is | |
| 21064 | /// effectively equivalent to a coercion. | |
| 21065 | superset, | |
| 21066 | /// The operand and destination error sets have *some* errors in common, but the destination | |
| 21067 | /// is not a superset of the operand, so a safety check may be needed. | |
| 21068 | overlap, | |
| 21069 | } = if (operand_err_ty.errorSetIsEmpty(zcu)) res: { | |
| 21070 | break :res .disjoint; | |
| 21071 | } else check: switch (dest_err_ty.toIntern()) { | |
| 21072 | .anyerror_type => .superset, | |
| 21073 | .adhoc_inferred_error_set_type => { | |
| 21074 | // `@errorCast` to this function's own error set. | |
| 21075 | try sema.fn_ret_ty_ies.?.addErrorSet(operand_err_ty, ip, sema.arena); | |
| 21076 | break :check .superset; | |
| 21077 | }, | |
| 21078 | else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { | |
| 21079 | .inferred_error_set_type => |func_index| { | |
| 21080 | if (sema.fn_ret_ty_ies) |dst_ies| { | |
| 21081 | if (dst_ies.func == func_index) { | |
| 21082 | // `@errorCast` to this function's own error set. | |
| 21083 | try sema.fn_ret_ty_ies.?.addErrorSet(operand_err_ty, ip, sema.arena); | |
| 21084 | break :check .superset; | |
| 21085 | } | |
| 21086 | } | |
| 21087 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 21088 | continue :check ip.funcIesResolvedUnordered(func_index); | |
| 21089 | }, | |
| 21090 | .error_set_type => |dest| { | |
| 21091 | if (dest.names.len == 0) break :check .disjoint; // dest is 'error{}' | |
| 21092 | if (operand_err_ty.isAnyError(zcu)) break :check .overlap; // anyerror -> error{...} (non-empty) | |
| 21093 | var dest_has_all = true; | |
| 21094 | var dest_has_any = false; | |
| 21095 | for (operand_err_ty.errorSetNames(zcu).get(ip)) |operand_err_name| { | |
| 21096 | if (dest.nameIndex(ip, operand_err_name) != null) { | |
| 21097 | dest_has_any = true; | |
| 21098 | } else { | |
| 21099 | dest_has_all = false; | |
| 21100 | } | |
| 21101 | } | |
| 21102 | if (!dest_has_any) break :check .disjoint; | |
| 21103 | if (dest_has_all) break :check .superset; | |
| 21104 | break :check .overlap; | |
| 21105 | }, | |
| 21106 | else => unreachable, | |
| 21107 | }, | |
| 21906 | 21108 | }; |
| 21907 | if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) { | |
| 21109 | ||
| 21110 | if (result == .disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) { | |
| 21908 | 21111 | return sema.fail(block, src, "error sets '{f}' and '{f}' have no common errors", .{ |
| 21909 | 21112 | operand_err_ty.fmt(pt), dest_err_ty.fmt(pt), |
| 21910 | 21113 | }); |
| ... | ... | @@ -21912,25 +21115,30 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 21912 | 21115 | |
| 21913 | 21116 | // operand must be defined since it can be an invalid error value |
| 21914 | 21117 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| { |
| 21915 | const err_name: InternPool.NullTerminatedString = switch (operand_tag) { | |
| 21916 | .error_set => ip.indexToKey(operand_val.toIntern()).err.name, | |
| 21917 | .error_union => switch (ip.indexToKey(operand_val.toIntern()).error_union.val) { | |
| 21118 | const err_name: InternPool.NullTerminatedString = switch (ip.indexToKey(operand_val.toIntern())) { | |
| 21119 | .err => |err| err.name, | |
| 21120 | .error_union => |eu| switch (eu.val) { | |
| 21918 | 21121 | .err_name => |name| name, |
| 21919 | 21122 | .payload => |payload_val| { |
| 21920 | 21123 | assert(dest_tag == .error_union); // should be guaranteed from the type checks above |
| 21921 | return sema.coerce(block, dest_ty, Air.internedToRef(payload_val), operand_src); | |
| 21124 | const dest_payload_ty = dest_ty.errorUnionPayload(zcu); | |
| 21125 | const coerced_payload = try sema.coerce(block, dest_payload_ty, .fromIntern(payload_val), operand_src); | |
| 21126 | return sema.wrapErrorUnionPayload(block, dest_ty, coerced_payload, operand_src) catch |err| switch (err) { | |
| 21127 | error.NotCoercible => unreachable, | |
| 21128 | else => |e| return e, | |
| 21129 | }; | |
| 21922 | 21130 | }, |
| 21923 | 21131 | }, |
| 21924 | 21132 | else => unreachable, |
| 21925 | 21133 | }; |
| 21926 | 21134 | |
| 21927 | if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) { | |
| 21135 | if (result != .superset and !dest_err_ty.errorSetHasField(err_name, zcu)) { | |
| 21928 | 21136 | return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{ |
| 21929 | 21137 | err_name.fmt(ip), dest_err_ty.fmt(pt), |
| 21930 | 21138 | }); |
| 21931 | 21139 | } |
| 21932 | 21140 | |
| 21933 | return Air.internedToRef(try pt.intern(switch (dest_tag) { | |
| 21141 | return .fromIntern(try pt.intern(switch (dest_tag) { | |
| 21934 | 21142 | .error_set => .{ .err = .{ |
| 21935 | 21143 | .ty = dest_ty.toIntern(), |
| 21936 | 21144 | .name = err_name, |
| ... | ... | @@ -21944,21 +21152,17 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 21944 | 21152 | } |
| 21945 | 21153 | |
| 21946 | 21154 | const err_int_ty = try pt.errorIntType(); |
| 21947 | if (block.wantSafety() and !dest_err_ty.isAnyError(zcu) and | |
| 21948 | dest_err_ty.toIntern() != .adhoc_inferred_error_set_type and | |
| 21949 | zcu.backendSupportsFeature(.error_set_has_value)) | |
| 21950 | { | |
| 21155 | if (block.wantSafety() and result != .superset and zcu.backendSupportsFeature(.error_set_has_value)) { | |
| 21951 | 21156 | const err_code_inst = switch (operand_tag) { |
| 21952 | 21157 | .error_set => operand, |
| 21953 | 21158 | .error_union => try block.addTyOp(.unwrap_errunion_err, operand_err_ty, operand), |
| 21954 | 21159 | else => unreachable, |
| 21955 | 21160 | }; |
| 21956 | 21161 | const err_int_inst = try block.addBitCast(err_int_ty, err_code_inst); |
| 21957 | ||
| 21958 | 21162 | if (dest_tag == .error_union) { |
| 21959 | 21163 | const zero_err = try pt.intRef(err_int_ty, 0); |
| 21960 | 21164 | const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err); |
| 21961 | if (disjoint) { | |
| 21165 | if (result == .disjoint) { | |
| 21962 | 21166 | // Error must be zero. |
| 21963 | 21167 | try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code); |
| 21964 | 21168 | } else { |
| ... | ... | @@ -21987,7 +21191,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa |
| 21987 | 21191 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 21988 | 21192 | const src = block.nodeOffset(extra.node); |
| 21989 | 21193 | const operand_src = block.src(.{ .node_offset_ptrcast_operand = extra.node }); |
| 21990 | const operand = try sema.resolveInst(extra.rhs); | |
| 21194 | const operand = sema.resolveInst(extra.rhs); | |
| 21991 | 21195 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName()); |
| 21992 | 21196 | return sema.ptrCastFull( |
| 21993 | 21197 | block, |
| ... | ... | @@ -22006,7 +21210,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 22006 | 21210 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22007 | 21211 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 22008 | 21212 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrCast"); |
| 22009 | const operand = try sema.resolveInst(extra.rhs); | |
| 21213 | const operand = sema.resolveInst(extra.rhs); | |
| 22010 | 21214 | |
| 22011 | 21215 | return sema.ptrCastFull( |
| 22012 | 21216 | block, |
| ... | ... | @@ -22043,8 +21247,8 @@ fn ptrCastFull( |
| 22043 | 21247 | const src_info = operand_ty.ptrInfo(zcu); |
| 22044 | 21248 | const dest_info = dest_ty.ptrInfo(zcu); |
| 22045 | 21249 | |
| 22046 | try Type.fromInterned(src_info.child).resolveLayout(pt); | |
| 22047 | try Type.fromInterned(dest_info.child).resolveLayout(pt); | |
| 21250 | try sema.ensureLayoutResolved(.fromInterned(src_info.child), operand_src, .align_check); | |
| 21251 | try sema.ensureLayoutResolved(.fromInterned(dest_info.child), src, .align_check); | |
| 22048 | 21252 | |
| 22049 | 21253 | const DestSliceLen = union(enum) { |
| 22050 | 21254 | undef, |
| ... | ... | @@ -22072,16 +21276,16 @@ fn ptrCastFull( |
| 22072 | 21276 | }; |
| 22073 | 21277 | }, |
| 22074 | 21278 | .slice => src: { |
| 22075 | const operand_val = try sema.resolveValue(operand) orelse break :src .{ .fromInterned(src_info.child), null }; | |
| 21279 | const operand_val = sema.resolveValue(operand) orelse break :src .{ .fromInterned(src_info.child), null }; | |
| 22076 | 21280 | if (operand_val.isUndef(zcu)) break :len .undef; |
| 22077 | 21281 | const slice_val = switch (operand_ty.zigTypeTag(zcu)) { |
| 22078 | 21282 | .optional => operand_val.optionalValue(zcu) orelse break :len .undef, |
| 22079 | 21283 | .pointer => operand_val, |
| 22080 | 21284 | else => unreachable, |
| 22081 | 21285 | }; |
| 22082 | const slice_len_resolved = try sema.resolveLazyValue(.fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern()))); | |
| 22083 | if (slice_len_resolved.isUndef(zcu)) break :len .undef; | |
| 22084 | break :src .{ .fromInterned(src_info.child), slice_len_resolved.toUnsignedInt(zcu) }; | |
| 21286 | const slice_len: Value = .fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern())); | |
| 21287 | if (slice_len.isUndef(zcu)) break :len .undef; | |
| 21288 | break :src .{ .fromInterned(src_info.child), slice_len.toUnsignedInt(zcu) }; | |
| 22085 | 21289 | }, |
| 22086 | 21290 | .many, .c => { |
| 22087 | 21291 | return sema.fail(block, src, "cannot infer length of slice from {s}", .{pointerSizeString(src_info.flags.size)}); |
| ... | ... | @@ -22369,7 +21573,7 @@ fn ptrCastFull( |
| 22369 | 21573 | |
| 22370 | 21574 | ct: { |
| 22371 | 21575 | if (flags.addrspace_cast) break :ct; // cannot `@addrSpaceCast` at comptime |
| 22372 | const operand_val = try sema.resolveValue(operand) orelse break :ct; | |
| 21576 | const operand_val = sema.resolveValue(operand) orelse break :ct; | |
| 22373 | 21577 | |
| 22374 | 21578 | if (operand_val.isUndef(zcu)) { |
| 22375 | 21579 | if (!dest_ty.ptrAllowsZero(zcu)) { |
| ... | ... | @@ -22395,7 +21599,7 @@ fn ptrCastFull( |
| 22395 | 21599 | }; |
| 22396 | 21600 | |
| 22397 | 21601 | if (dest_align.compare(.gt, src_align)) { |
| 22398 | if (try ptr_val.getUnsignedIntSema(pt)) |addr| { | |
| 21602 | if (ptr_val.getUnsignedInt(zcu)) |addr| { | |
| 22399 | 21603 | const masked_addr = if (Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu)) |mask| |
| 22400 | 21604 | addr & mask |
| 22401 | 21605 | else |
| ... | ... | @@ -22464,7 +21668,7 @@ fn ptrCastFull( |
| 22464 | 21668 | // Now, do an addrspace cast if necessary! |
| 22465 | 21669 | if (!flags.addrspace_cast) break :ptr pre_addrspace_cast; |
| 22466 | 21670 | |
| 22467 | const intermediate_ptr_ty = try pt.ptrTypeSema(info: { | |
| 21671 | const intermediate_ptr_ty = try pt.ptrType(info: { | |
| 22468 | 21672 | var info = src_info; |
| 22469 | 21673 | info.flags.address_space = dest_info.flags.address_space; |
| 22470 | 21674 | break :info info; |
| ... | ... | @@ -22629,7 +21833,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 22629 | 21833 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 22630 | 21834 | const src = block.nodeOffset(extra.node); |
| 22631 | 21835 | const operand_src = block.src(.{ .node_offset_ptrcast_operand = extra.node }); |
| 22632 | const operand = try sema.resolveInst(extra.operand); | |
| 21836 | const operand = sema.resolveInst(extra.operand); | |
| 22633 | 21837 | const operand_ty = sema.typeOf(operand); |
| 22634 | 21838 | try sema.checkPtrOperand(block, operand_src, operand_ty); |
| 22635 | 21839 | |
| ... | ... | @@ -22638,14 +21842,14 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 22638 | 21842 | if (flags.volatile_cast) ptr_info.flags.is_volatile = false; |
| 22639 | 21843 | |
| 22640 | 21844 | const dest_ty = blk: { |
| 22641 | const dest_ty = try pt.ptrTypeSema(ptr_info); | |
| 21845 | const dest_ty = try pt.ptrType(ptr_info); | |
| 22642 | 21846 | if (operand_ty.zigTypeTag(zcu) == .optional) { |
| 22643 | 21847 | break :blk try pt.optionalType(dest_ty.toIntern()); |
| 22644 | 21848 | } |
| 22645 | 21849 | break :blk dest_ty; |
| 22646 | 21850 | }; |
| 22647 | 21851 | |
| 22648 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 21852 | if (sema.resolveValue(operand)) |operand_val| { | |
| 22649 | 21853 | return Air.internedToRef((try pt.getCoerced(operand_val, dest_ty)).toIntern()); |
| 22650 | 21854 | } |
| 22651 | 21855 | |
| ... | ... | @@ -22664,7 +21868,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22664 | 21868 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 22665 | 21869 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate"); |
| 22666 | 21870 | const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src); |
| 22667 | const operand = try sema.resolveInst(extra.rhs); | |
| 21871 | const operand = sema.resolveInst(extra.rhs); | |
| 22668 | 21872 | const operand_ty = sema.typeOf(operand); |
| 22669 | 21873 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); |
| 22670 | 21874 | |
| ... | ... | @@ -22678,48 +21882,24 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22678 | 21882 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 22679 | 21883 | } |
| 22680 | 21884 | |
| 22681 | const dest_info = dest_scalar_ty.intInfo(zcu); | |
| 21885 | if (try dest_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 22682 | 21886 | |
| 22683 | if (try sema.typeHasOnePossibleValue(dest_ty)) |val| { | |
| 22684 | return Air.internedToRef(val.toIntern()); | |
| 22685 | } | |
| 21887 | const dest_info = dest_scalar_ty.intInfo(zcu); | |
| 22686 | 21888 | |
| 22687 | 21889 | if (operand_scalar_ty.zigTypeTag(zcu) != .comptime_int) { |
| 22688 | 21890 | const operand_info = operand_ty.intInfo(zcu); |
| 22689 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { | |
| 22690 | return Air.internedToRef(val.toIntern()); | |
| 22691 | } | |
| 22692 | 21891 | |
| 22693 | 21892 | if (operand_info.signedness != dest_info.signedness) { |
| 22694 | 21893 | return sema.fail(block, operand_src, "expected {s} integer type, found '{f}'", .{ |
| 22695 | 21894 | @tagName(dest_info.signedness), operand_ty.fmt(pt), |
| 22696 | 21895 | }); |
| 22697 | 21896 | } |
| 22698 | switch (std.math.order(dest_info.bits, operand_info.bits)) { | |
| 22699 | .gt => { | |
| 22700 | const msg = msg: { | |
| 22701 | const msg = try sema.errMsg( | |
| 22702 | src, | |
| 22703 | "destination type '{f}' has more bits than source type '{f}'", | |
| 22704 | .{ dest_ty.fmt(pt), operand_ty.fmt(pt) }, | |
| 22705 | ); | |
| 22706 | errdefer msg.destroy(sema.gpa); | |
| 22707 | try sema.errNote(src, msg, "destination type has {d} bits", .{ | |
| 22708 | dest_info.bits, | |
| 22709 | }); | |
| 22710 | try sema.errNote(operand_src, msg, "operand type has {d} bits", .{ | |
| 22711 | operand_info.bits, | |
| 22712 | }); | |
| 22713 | break :msg msg; | |
| 22714 | }; | |
| 22715 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 22716 | }, | |
| 22717 | .eq => return operand, | |
| 22718 | .lt => {}, | |
| 21897 | if (dest_info.bits >= operand_info.bits) { | |
| 21898 | return sema.coerce(block, dest_ty, operand, operand_src); | |
| 22719 | 21899 | } |
| 22720 | 21900 | } |
| 22721 | 21901 | |
| 22722 | if (try sema.resolveValueResolveLazy(operand)) |val| { | |
| 21902 | if (sema.resolveValue(operand)) |val| { | |
| 22723 | 21903 | const result_val = try arith.truncate(sema, val, operand_ty, dest_ty, dest_info.signedness, dest_info.bits); |
| 22724 | 21904 | return Air.internedToRef(result_val.toIntern()); |
| 22725 | 21905 | } |
| ... | ... | @@ -22740,15 +21920,11 @@ fn zirBitCount( |
| 22740 | 21920 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 22741 | 21921 | const src = block.nodeOffset(inst_data.src_node); |
| 22742 | 21922 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22743 | const operand = try sema.resolveInst(inst_data.operand); | |
| 21923 | const operand = sema.resolveInst(inst_data.operand); | |
| 22744 | 21924 | const operand_ty = sema.typeOf(operand); |
| 22745 | 21925 | _ = try sema.checkIntOrVector(block, operand, operand_src); |
| 22746 | 21926 | const bits = operand_ty.intInfo(zcu).bits; |
| 22747 | 21927 | |
| 22748 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { | |
| 22749 | return Air.internedToRef(val.toIntern()); | |
| 22750 | } | |
| 22751 | ||
| 22752 | 21928 | const result_scalar_ty = try pt.smallestUnsignedInt(bits); |
| 22753 | 21929 | switch (operand_ty.zigTypeTag(zcu)) { |
| 22754 | 21930 | .vector => { |
| ... | ... | @@ -22757,7 +21933,7 @@ fn zirBitCount( |
| 22757 | 21933 | .len = vec_len, |
| 22758 | 21934 | .child = result_scalar_ty.toIntern(), |
| 22759 | 21935 | }); |
| 22760 | if (try sema.resolveValue(operand)) |val| { | |
| 21936 | if (sema.resolveValue(operand)) |val| { | |
| 22761 | 21937 | if (val.isUndef(zcu)) return pt.undefRef(result_ty); |
| 22762 | 21938 | |
| 22763 | 21939 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| ... | ... | @@ -22774,7 +21950,7 @@ fn zirBitCount( |
| 22774 | 21950 | } |
| 22775 | 21951 | }, |
| 22776 | 21952 | .int => { |
| 22777 | if (try sema.resolveValueResolveLazy(operand)) |val| { | |
| 21953 | if (sema.resolveValue(operand)) |val| { | |
| 22778 | 21954 | if (val.isUndef(zcu)) return pt.undefRef(result_scalar_ty); |
| 22779 | 21955 | return pt.intRef(result_scalar_ty, comptimeOp(val, operand_ty, zcu)); |
| 22780 | 21956 | } else { |
| ... | ... | @@ -22791,7 +21967,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22791 | 21967 | const zcu = pt.zcu; |
| 22792 | 21968 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 22793 | 21969 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22794 | const operand = try sema.resolveInst(inst_data.operand); | |
| 21970 | const operand = sema.resolveInst(inst_data.operand); | |
| 22795 | 21971 | const operand_ty = sema.typeOf(operand); |
| 22796 | 21972 | const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); |
| 22797 | 21973 | const bits = scalar_ty.intInfo(zcu).bits; |
| ... | ... | @@ -22803,10 +21979,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22803 | 21979 | .{ scalar_ty.fmt(pt), bits }, |
| 22804 | 21980 | ); |
| 22805 | 21981 | } |
| 22806 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { | |
| 22807 | return .fromValue(val); | |
| 22808 | } | |
| 22809 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 21982 | if (sema.resolveValue(operand)) |operand_val| { | |
| 22810 | 21983 | return .fromValue(try arith.byteSwap(sema, operand_val, operand_ty)); |
| 22811 | 21984 | } |
| 22812 | 21985 | return block.addTyOp(.byte_swap, operand_ty, operand); |
| ... | ... | @@ -22815,14 +21988,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 22815 | 21988 | fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 22816 | 21989 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 22817 | 21990 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 22818 | const operand = try sema.resolveInst(inst_data.operand); | |
| 21991 | const operand = sema.resolveInst(inst_data.operand); | |
| 22819 | 21992 | const operand_ty = sema.typeOf(operand); |
| 22820 | 21993 | _ = try sema.checkIntOrVector(block, operand, operand_src); |
| 22821 | 21994 | |
| 22822 | if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { | |
| 22823 | return .fromValue(val); | |
| 22824 | } | |
| 22825 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 21995 | if (sema.resolveValue(operand)) |operand_val| { | |
| 22826 | 21996 | return .fromValue(try arith.bitReverse(sema, operand_val, operand_ty)); |
| 22827 | 21997 | } |
| 22828 | 21998 | return block.addTyOp(.bit_reverse, operand_ty, operand); |
| ... | ... | @@ -22849,10 +22019,11 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 22849 | 22019 | const ty = try sema.resolveType(block, ty_src, extra.lhs); |
| 22850 | 22020 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name }); |
| 22851 | 22021 | |
| 22022 | try sema.ensureLayoutResolved(ty, ty_src, .field_queried); | |
| 22023 | ||
| 22852 | 22024 | const pt = sema.pt; |
| 22853 | 22025 | const zcu = pt.zcu; |
| 22854 | 22026 | const ip = &zcu.intern_pool; |
| 22855 | try ty.resolveLayout(pt); | |
| 22856 | 22027 | switch (ty.zigTypeTag(zcu)) { |
| 22857 | 22028 | .@"struct" => {}, |
| 22858 | 22029 | else => return sema.fail(block, ty_src, "expected struct type, found '{f}'", .{ty.fmt(pt)}), |
| ... | ... | @@ -23090,7 +22261,7 @@ fn checkAtomicPtrOperand( |
| 23090 | 22261 | ) CompileError!Air.Inst.Ref { |
| 23091 | 22262 | const pt = sema.pt; |
| 23092 | 22263 | const zcu = pt.zcu; |
| 23093 | try elem_ty.resolveLayout(pt); | |
| 22264 | try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .ptr_access); | |
| 23094 | 22265 | var diag: Zcu.AtomicPtrAlignmentDiagnostics = .{}; |
| 23095 | 22266 | const alignment = zcu.atomicPtrAlignment(elem_ty, &diag) catch |err| switch (err) { |
| 23096 | 22267 | error.OutOfMemory => return error.OutOfMemory, |
| ... | ... | @@ -23126,7 +22297,7 @@ fn checkAtomicPtrOperand( |
| 23126 | 22297 | const ptr_data = switch (ptr_ty.zigTypeTag(zcu)) { |
| 23127 | 22298 | .pointer => ptr_ty.ptrInfo(zcu), |
| 23128 | 22299 | else => { |
| 23129 | const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data); | |
| 22300 | const wanted_ptr_ty = try pt.ptrType(wanted_ptr_data); | |
| 23130 | 22301 | _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src); |
| 23131 | 22302 | unreachable; |
| 23132 | 22303 | }, |
| ... | ... | @@ -23136,7 +22307,7 @@ fn checkAtomicPtrOperand( |
| 23136 | 22307 | wanted_ptr_data.flags.is_allowzero = ptr_data.flags.is_allowzero; |
| 23137 | 22308 | wanted_ptr_data.flags.is_volatile = ptr_data.flags.is_volatile; |
| 23138 | 22309 | |
| 23139 | const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data); | |
| 22310 | const wanted_ptr_ty = try pt.ptrType(wanted_ptr_data); | |
| 23140 | 22311 | const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src); |
| 23141 | 22312 | |
| 23142 | 22313 | return casted_ptr; |
| ... | ... | @@ -23245,8 +22416,8 @@ fn checkSimdBinOp( |
| 23245 | 22416 | .len = vec_len, |
| 23246 | 22417 | .lhs = lhs, |
| 23247 | 22418 | .rhs = rhs, |
| 23248 | .lhs_val = try sema.resolveValue(lhs), | |
| 23249 | .rhs_val = try sema.resolveValue(rhs), | |
| 22419 | .lhs_val = sema.resolveValue(lhs), | |
| 22420 | .rhs_val = sema.resolveValue(rhs), | |
| 23250 | 22421 | .result_ty = result_ty, |
| 23251 | 22422 | .scalar_ty = result_ty.scalarType(zcu), |
| 23252 | 22423 | }; |
| ... | ... | @@ -23338,7 +22509,7 @@ fn resolveExportOptions( |
| 23338 | 22509 | const ip = &zcu.intern_pool; |
| 23339 | 22510 | |
| 23340 | 22511 | const export_options_ty = try sema.getBuiltinType(src, .ExportOptions); |
| 23341 | const air_ref = try sema.resolveInst(zir_ref); | |
| 22512 | const air_ref = sema.resolveInst(zir_ref); | |
| 23342 | 22513 | const options = try sema.coerce(block, export_options_ty, air_ref, src); |
| 23343 | 22514 | |
| 23344 | 22515 | const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| ... | ... | @@ -23391,7 +22562,7 @@ fn resolveBuiltinEnum( |
| 23391 | 22562 | reason: ComptimeReason, |
| 23392 | 22563 | ) CompileError!@field(std.builtin, @tagName(name)) { |
| 23393 | 22564 | const ty = try sema.getBuiltinType(src, name); |
| 23394 | const air_ref = try sema.resolveInst(zir_ref); | |
| 22565 | const air_ref = sema.resolveInst(zir_ref); | |
| 23395 | 22566 | const coerced = try sema.coerce(block, ty, air_ref, src); |
| 23396 | 22567 | const val = try sema.resolveConstDefinedValue(block, src, coerced, reason); |
| 23397 | 22568 | return sema.interpretBuiltinType(block, src, val, @field(std.builtin, @tagName(name))); |
| ... | ... | @@ -23438,7 +22609,7 @@ fn zirCmpxchg( |
| 23438 | 22609 | const success_order_src = block.builtinCallArgSrc(extra.node, 4); |
| 23439 | 22610 | const failure_order_src = block.builtinCallArgSrc(extra.node, 5); |
| 23440 | 22611 | // zig fmt: on |
| 23441 | const expected_value = try sema.resolveInst(extra.expected_value); | |
| 22612 | const expected_value = sema.resolveInst(extra.expected_value); | |
| 23442 | 22613 | const elem_ty = sema.typeOf(expected_value); |
| 23443 | 22614 | if (elem_ty.zigTypeTag(zcu) == .float) { |
| 23444 | 22615 | return sema.fail( |
| ... | ... | @@ -23448,9 +22619,9 @@ fn zirCmpxchg( |
| 23448 | 22619 | .{elem_ty.fmt(pt)}, |
| 23449 | 22620 | ); |
| 23450 | 22621 | } |
| 23451 | const uncasted_ptr = try sema.resolveInst(extra.ptr); | |
| 22622 | const uncasted_ptr = sema.resolveInst(extra.ptr); | |
| 23452 | 22623 | const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); |
| 23453 | const new_value = try sema.coerce(block, elem_ty, try sema.resolveInst(extra.new_value), new_value_src); | |
| 22624 | const new_value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.new_value), new_value_src); | |
| 23454 | 22625 | const success_order = try sema.resolveAtomicOrder(block, success_order_src, extra.success_order, .{ .simple = .atomic_order }); |
| 23455 | 22626 | const failure_order = try sema.resolveAtomicOrder(block, failure_order_src, extra.failure_order, .{ .simple = .atomic_order }); |
| 23456 | 22627 | |
| ... | ... | @@ -23470,16 +22641,13 @@ fn zirCmpxchg( |
| 23470 | 22641 | const result_ty = try pt.optionalType(elem_ty.toIntern()); |
| 23471 | 22642 | |
| 23472 | 22643 | // special case zero bit types |
| 23473 | if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) { | |
| 23474 | return Air.internedToRef((try pt.intern(.{ .opt = .{ | |
| 23475 | .ty = result_ty.toIntern(), | |
| 23476 | .val = .none, | |
| 23477 | } }))); | |
| 22644 | if (elem_ty.classify(zcu) == .one_possible_value) { | |
| 22645 | return .fromValue(try pt.nullValue(result_ty)); | |
| 23478 | 22646 | } |
| 23479 | 22647 | |
| 23480 | 22648 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { |
| 23481 | if (try sema.resolveValue(expected_value)) |expected_val| { | |
| 23482 | if (try sema.resolveValue(new_value)) |new_val| { | |
| 22649 | if (sema.resolveValue(expected_value)) |expected_val| { | |
| 22650 | if (sema.resolveValue(new_value)) |new_val| { | |
| 23483 | 22651 | if (expected_val.isUndef(zcu) or new_val.isUndef(zcu)) { |
| 23484 | 22652 | // TODO: this should probably cause the memory stored at the pointer |
| 23485 | 22653 | // to become undef as well |
| ... | ... | @@ -23531,22 +22699,18 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 23531 | 22699 | else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(pt)}), |
| 23532 | 22700 | } |
| 23533 | 22701 | |
| 23534 | const operand = try sema.resolveInst(extra.rhs); | |
| 22702 | const operand = sema.resolveInst(extra.rhs); | |
| 23535 | 22703 | const scalar_ty = dest_ty.childType(zcu); |
| 23536 | 22704 | const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src); |
| 23537 | 22705 | |
| 23538 | 22706 | const len = try sema.usizeCast(block, src, dest_ty.arrayLen(zcu)); |
| 23539 | 22707 | |
| 23540 | if (try sema.typeHasOnePossibleValue(dest_ty)) |val| { | |
| 23541 | return Air.internedToRef(val.toIntern()); | |
| 23542 | } | |
| 23543 | ||
| 23544 | // We also need this case because `[0:s]T` is not OPV. | |
| 22708 | // If the length is 0, the result is comptime-known even if the operand isn't. | |
| 23545 | 22709 | if (len == 0) return .fromValue(try pt.aggregateValue(dest_ty, &.{})); |
| 23546 | 22710 | |
| 23547 | 22711 | const maybe_sentinel = dest_ty.sentinel(zcu); |
| 23548 | 22712 | |
| 23549 | if (try sema.resolveValue(scalar)) |scalar_val| { | |
| 22713 | if (sema.resolveValue(scalar)) |scalar_val| { | |
| 23550 | 22714 | full: { |
| 23551 | 22715 | if (dest_ty.zigTypeTag(zcu) == .vector) break :full; |
| 23552 | 22716 | const sentinel = maybe_sentinel orelse break :full; |
| ... | ... | @@ -23581,7 +22745,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 23581 | 22745 | const op_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 23582 | 22746 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 23583 | 22747 | const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, .ReduceOp, .{ .simple = .operand_reduce_operation }); |
| 23584 | const operand = try sema.resolveInst(extra.rhs); | |
| 22748 | const operand = sema.resolveInst(extra.rhs); | |
| 23585 | 22749 | const operand_ty = sema.typeOf(operand); |
| 23586 | 22750 | const pt = sema.pt; |
| 23587 | 22751 | const zcu = pt.zcu; |
| ... | ... | @@ -23615,7 +22779,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 23615 | 22779 | return sema.fail(block, operand_src, "@reduce operation requires a vector with nonzero length", .{}); |
| 23616 | 22780 | } |
| 23617 | 22781 | |
| 23618 | if (try sema.resolveValue(operand)) |operand_val| { | |
| 22782 | if (sema.resolveValue(operand)) |operand_val| { | |
| 23619 | 22783 | if (operand_val.isUndef(zcu)) return pt.undefRef(scalar_ty); |
| 23620 | 22784 | |
| 23621 | 22785 | var accum: Value = try operand_val.elemValue(pt, 0); |
| ... | ... | @@ -23651,9 +22815,9 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 23651 | 22815 | |
| 23652 | 22816 | const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); |
| 23653 | 22817 | try sema.checkVectorElemType(block, elem_ty_src, elem_ty); |
| 23654 | const a = try sema.resolveInst(extra.a); | |
| 23655 | const b = try sema.resolveInst(extra.b); | |
| 23656 | var mask = try sema.resolveInst(extra.mask); | |
| 22818 | const a = sema.resolveInst(extra.a); | |
| 22819 | const b = sema.resolveInst(extra.b); | |
| 22820 | var mask = sema.resolveInst(extra.mask); | |
| 23657 | 22821 | var mask_ty = sema.typeOf(mask); |
| 23658 | 22822 | |
| 23659 | 22823 | const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) { |
| ... | ... | @@ -23733,7 +22897,7 @@ fn analyzeShuffle( |
| 23733 | 22897 | continue; |
| 23734 | 22898 | } |
| 23735 | 22899 | // Safe because mask elements are `i32` and we already checked for undef: |
| 23736 | const raw = (try sema.resolveLazyValue(mask_val)).toSignedInt(zcu); | |
| 22900 | const raw = mask_val.toSignedInt(zcu); | |
| 23737 | 22901 | if (raw >= 0) { |
| 23738 | 22902 | const idx: u32 = @intCast(raw); |
| 23739 | 22903 | a_used = true; |
| ... | ... | @@ -23760,8 +22924,8 @@ fn analyzeShuffle( |
| 23760 | 22924 | } |
| 23761 | 22925 | } |
| 23762 | 22926 | |
| 23763 | const maybe_a_val = try sema.resolveValue(a_coerced); | |
| 23764 | const maybe_b_val = try sema.resolveValue(b_coerced); | |
| 22927 | const maybe_a_val = sema.resolveValue(a_coerced); | |
| 22928 | const maybe_b_val = sema.resolveValue(b_coerced); | |
| 23765 | 22929 | |
| 23766 | 22930 | const a_rt = a_used and maybe_a_val == null; |
| 23767 | 22931 | const b_rt = b_used and maybe_b_val == null; |
| ... | ... | @@ -23849,7 +23013,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 23849 | 23013 | |
| 23850 | 23014 | const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); |
| 23851 | 23015 | try sema.checkVectorElemType(block, elem_ty_src, elem_ty); |
| 23852 | const pred_uncoerced = try sema.resolveInst(extra.pred); | |
| 23016 | const pred_uncoerced = sema.resolveInst(extra.pred); | |
| 23853 | 23017 | const pred_ty = sema.typeOf(pred_uncoerced); |
| 23854 | 23018 | |
| 23855 | 23019 | const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -23868,12 +23032,12 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 23868 | 23032 | .len = vec_len, |
| 23869 | 23033 | .child = elem_ty.toIntern(), |
| 23870 | 23034 | }); |
| 23871 | const a = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.a), a_src); | |
| 23872 | const b = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.b), b_src); | |
| 23035 | const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src); | |
| 23036 | const b = try sema.coerce(block, vec_ty, sema.resolveInst(extra.b), b_src); | |
| 23873 | 23037 | |
| 23874 | const maybe_pred = try sema.resolveValue(pred); | |
| 23875 | const maybe_a = try sema.resolveValue(a); | |
| 23876 | const maybe_b = try sema.resolveValue(b); | |
| 23038 | const maybe_pred = sema.resolveValue(pred); | |
| 23039 | const maybe_a = sema.resolveValue(a); | |
| 23040 | const maybe_b = sema.resolveValue(b); | |
| 23877 | 23041 | |
| 23878 | 23042 | const runtime_src = if (maybe_pred) |pred_val| rs: { |
| 23879 | 23043 | if (pred_val.isUndef(zcu)) return pt.undefRef(vec_ty); |
| ... | ... | @@ -23934,10 +23098,12 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 23934 | 23098 | const order_src = block.builtinCallArgSrc(inst_data.src_node, 2); |
| 23935 | 23099 | // zig fmt: on |
| 23936 | 23100 | const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); |
| 23937 | const uncasted_ptr = try sema.resolveInst(extra.ptr); | |
| 23101 | const uncasted_ptr = sema.resolveInst(extra.ptr); | |
| 23938 | 23102 | const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true); |
| 23939 | 23103 | const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); |
| 23940 | 23104 | |
| 23105 | try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .ptr_access); | |
| 23106 | ||
| 23941 | 23107 | switch (order) { |
| 23942 | 23108 | .release, .acq_rel => { |
| 23943 | 23109 | return sema.fail( |
| ... | ... | @@ -23950,9 +23116,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 23950 | 23116 | else => {}, |
| 23951 | 23117 | } |
| 23952 | 23118 | |
| 23953 | if (try sema.typeHasOnePossibleValue(elem_ty)) |val| { | |
| 23954 | return Air.internedToRef(val.toIntern()); | |
| 23955 | } | |
| 23119 | if (try elem_ty.onePossibleValue(sema.pt)) |opv| return .fromValue(opv); | |
| 23956 | 23120 | |
| 23957 | 23121 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 23958 | 23122 | if (try sema.pointerDeref(block, ptr_src, ptr_val, sema.typeOf(ptr))) |elem_val| { |
| ... | ... | @@ -23983,9 +23147,9 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 23983 | 23147 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 3); |
| 23984 | 23148 | const order_src = block.builtinCallArgSrc(inst_data.src_node, 4); |
| 23985 | 23149 | // zig fmt: on |
| 23986 | const operand = try sema.resolveInst(extra.operand); | |
| 23150 | const operand = sema.resolveInst(extra.operand); | |
| 23987 | 23151 | const elem_ty = sema.typeOf(operand); |
| 23988 | const uncasted_ptr = try sema.resolveInst(extra.ptr); | |
| 23152 | const uncasted_ptr = sema.resolveInst(extra.ptr); | |
| 23989 | 23153 | const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); |
| 23990 | 23154 | const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation); |
| 23991 | 23155 | |
| ... | ... | @@ -24009,12 +23173,10 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 24009 | 23173 | } |
| 24010 | 23174 | |
| 24011 | 23175 | // special case zero bit types |
| 24012 | if (try sema.typeHasOnePossibleValue(elem_ty)) |val| { | |
| 24013 | return Air.internedToRef(val.toIntern()); | |
| 24014 | } | |
| 23176 | if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 24015 | 23177 | |
| 24016 | 23178 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { |
| 24017 | const maybe_operand_val = try sema.resolveValue(operand); | |
| 23179 | const maybe_operand_val = sema.resolveValue(operand); | |
| 24018 | 23180 | const operand_val = maybe_operand_val orelse { |
| 24019 | 23181 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); |
| 24020 | 23182 | break :rs operand_src; |
| ... | ... | @@ -24065,9 +23227,9 @@ fn zirAtomicStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 24065 | 23227 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 2); |
| 24066 | 23228 | const order_src = block.builtinCallArgSrc(inst_data.src_node, 3); |
| 24067 | 23229 | // zig fmt: on |
| 24068 | const operand = try sema.resolveInst(extra.operand); | |
| 23230 | const operand = sema.resolveInst(extra.operand); | |
| 24069 | 23231 | const elem_ty = sema.typeOf(operand); |
| 24070 | const uncasted_ptr = try sema.resolveInst(extra.ptr); | |
| 23232 | const uncasted_ptr = sema.resolveInst(extra.ptr); | |
| 24071 | 23233 | const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); |
| 24072 | 23234 | const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); |
| 24073 | 23235 | |
| ... | ... | @@ -24098,14 +23260,14 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 24098 | 23260 | const mulend2_src = block.builtinCallArgSrc(inst_data.src_node, 2); |
| 24099 | 23261 | const addend_src = block.builtinCallArgSrc(inst_data.src_node, 3); |
| 24100 | 23262 | |
| 24101 | const addend = try sema.resolveInst(extra.addend); | |
| 23263 | const addend = sema.resolveInst(extra.addend); | |
| 24102 | 23264 | const ty = sema.typeOf(addend); |
| 24103 | const mulend1 = try sema.coerce(block, ty, try sema.resolveInst(extra.mulend1), mulend1_src); | |
| 24104 | const mulend2 = try sema.coerce(block, ty, try sema.resolveInst(extra.mulend2), mulend2_src); | |
| 23265 | const mulend1 = try sema.coerce(block, ty, sema.resolveInst(extra.mulend1), mulend1_src); | |
| 23266 | const mulend2 = try sema.coerce(block, ty, sema.resolveInst(extra.mulend2), mulend2_src); | |
| 24105 | 23267 | |
| 24106 | const maybe_mulend1 = try sema.resolveValue(mulend1); | |
| 24107 | const maybe_mulend2 = try sema.resolveValue(mulend2); | |
| 24108 | const maybe_addend = try sema.resolveValue(addend); | |
| 23268 | const maybe_mulend1 = sema.resolveValue(mulend1); | |
| 23269 | const maybe_mulend2 = sema.resolveValue(mulend2); | |
| 23270 | const maybe_addend = sema.resolveValue(addend); | |
| 24109 | 23271 | const pt = sema.pt; |
| 24110 | 23272 | const zcu = pt.zcu; |
| 24111 | 23273 | |
| ... | ... | @@ -24167,10 +23329,10 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 24167 | 23329 | const call_src = block.nodeOffset(inst_data.src_node); |
| 24168 | 23330 | |
| 24169 | 23331 | const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; |
| 24170 | const func = try sema.resolveInst(extra.callee); | |
| 23332 | const func = sema.resolveInst(extra.callee); | |
| 24171 | 23333 | |
| 24172 | 23334 | const modifier_ty = try sema.getBuiltinType(call_src, .CallModifier); |
| 24173 | const air_ref = try sema.resolveInst(extra.modifier); | |
| 23335 | const air_ref = sema.resolveInst(extra.modifier); | |
| 24174 | 23336 | const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src); |
| 24175 | 23337 | const modifier_val = try sema.resolveConstDefinedValue(block, modifier_src, modifier_ref, .{ .simple = .call_modifier }); |
| 24176 | 23338 | var modifier = try sema.interpretBuiltinType(block, modifier_src, modifier_val, std.builtin.CallModifier); |
| ... | ... | @@ -24208,7 +23370,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 24208 | 23370 | }, |
| 24209 | 23371 | } |
| 24210 | 23372 | |
| 24211 | const args = try sema.resolveInst(extra.args); | |
| 23373 | const args = sema.resolveInst(extra.args); | |
| 24212 | 23374 | |
| 24213 | 23375 | const args_ty = sema.typeOf(args); |
| 24214 | 23376 | if (!args_ty.isTuple(zcu)) { |
| ... | ... | @@ -24253,18 +23415,23 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins |
| 24253 | 23415 | const field_name_src = block.builtinCallArgSrc(extra.src_node, 0); |
| 24254 | 23416 | const field_ptr_src = block.builtinCallArgSrc(extra.src_node, 1); |
| 24255 | 23417 | |
| 24256 | const parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr"); | |
| 24257 | try sema.checkPtrType(block, inst_src, parent_ptr_ty, true); | |
| 23418 | const maybe_opt_parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr"); | |
| 23419 | try sema.checkPtrType(block, inst_src, maybe_opt_parent_ptr_ty, true); | |
| 23420 | const parent_ptr_ty = switch (maybe_opt_parent_ptr_ty.zigTypeTag(zcu)) { | |
| 23421 | .optional => maybe_opt_parent_ptr_ty.optionalChild(zcu), | |
| 23422 | .pointer => maybe_opt_parent_ptr_ty, | |
| 23423 | else => unreachable, | |
| 23424 | }; | |
| 24258 | 23425 | const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); |
| 24259 | 23426 | if (parent_ptr_info.flags.size != .one) { |
| 24260 | 23427 | return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)}); |
| 24261 | 23428 | } |
| 24262 | 23429 | const parent_ty: Type = .fromInterned(parent_ptr_info.child); |
| 23430 | try sema.ensureLayoutResolved(parent_ty, inst_src, .field_used); | |
| 24263 | 23431 | switch (parent_ty.zigTypeTag(zcu)) { |
| 24264 | 23432 | .@"struct", .@"union" => {}, |
| 24265 | 23433 | else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}), |
| 24266 | 23434 | } |
| 24267 | try parent_ty.resolveLayout(pt); | |
| 24268 | 23435 | |
| 24269 | 23436 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); |
| 24270 | 23437 | const field_index = switch (parent_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -24285,144 +23452,77 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins |
| 24285 | 23452 | return sema.fail(block, field_name_src, "cannot get @fieldParentPtr of a comptime field", .{}); |
| 24286 | 23453 | } |
| 24287 | 23454 | |
| 24288 | const field_ptr = try sema.resolveInst(extra.field_ptr); | |
| 23455 | const field_ptr = sema.resolveInst(extra.field_ptr); | |
| 24289 | 23456 | const field_ptr_ty = sema.typeOf(field_ptr); |
| 24290 | 23457 | try sema.checkPtrOperand(block, field_ptr_src, field_ptr_ty); |
| 24291 | const field_ptr_info = field_ptr_ty.ptrInfo(zcu); | |
| 24292 | ||
| 24293 | var actual_parent_ptr_info: InternPool.Key.PtrType = .{ | |
| 24294 | .child = parent_ty.toIntern(), | |
| 24295 | .flags = .{ | |
| 24296 | .alignment = try parent_ptr_ty.ptrAlignmentSema(pt), | |
| 24297 | .is_const = field_ptr_info.flags.is_const, | |
| 24298 | .is_volatile = field_ptr_info.flags.is_volatile, | |
| 24299 | .is_allowzero = field_ptr_info.flags.is_allowzero, | |
| 24300 | .address_space = field_ptr_info.flags.address_space, | |
| 24301 | }, | |
| 24302 | .packed_offset = parent_ptr_info.packed_offset, | |
| 24303 | }; | |
| 24304 | const field_ty = parent_ty.fieldType(field_index, zcu); | |
| 24305 | var actual_field_ptr_info: InternPool.Key.PtrType = .{ | |
| 24306 | .child = field_ty.toIntern(), | |
| 24307 | .flags = .{ | |
| 24308 | .alignment = try field_ptr_ty.ptrAlignmentSema(pt), | |
| 24309 | .is_const = field_ptr_info.flags.is_const, | |
| 24310 | .is_volatile = field_ptr_info.flags.is_volatile, | |
| 24311 | .is_allowzero = field_ptr_info.flags.is_allowzero, | |
| 24312 | .address_space = field_ptr_info.flags.address_space, | |
| 24313 | }, | |
| 24314 | .packed_offset = field_ptr_info.packed_offset, | |
| 24315 | }; | |
| 24316 | switch (parent_ty.containerLayout(zcu)) { | |
| 24317 | .auto => { | |
| 24318 | actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict( | |
| 24319 | if (zcu.typeToStruct(parent_ty)) |struct_obj| | |
| 24320 | try field_ty.structFieldAlignmentSema( | |
| 24321 | struct_obj.fieldAlign(ip, field_index), | |
| 24322 | struct_obj.layout, | |
| 24323 | pt, | |
| 24324 | ) | |
| 24325 | else if (zcu.typeToUnion(parent_ty)) |union_obj| | |
| 24326 | try field_ty.unionFieldAlignmentSema( | |
| 24327 | union_obj.fieldAlign(ip, field_index), | |
| 24328 | union_obj.flagsUnordered(ip).layout, | |
| 24329 | pt, | |
| 24330 | ) | |
| 24331 | else | |
| 24332 | actual_field_ptr_info.flags.alignment, | |
| 24333 | ); | |
| 24334 | ||
| 24335 | actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; | |
| 24336 | actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; | |
| 24337 | }, | |
| 24338 | .@"extern" => { | |
| 24339 | const field_offset = parent_ty.structFieldOffset(field_index, zcu); | |
| 24340 | actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (field_offset > 0) | |
| 24341 | Alignment.fromLog2Units(@ctz(field_offset)) | |
| 24342 | else | |
| 24343 | actual_field_ptr_info.flags.alignment); | |
| 24344 | 23458 | |
| 24345 | actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; | |
| 24346 | actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; | |
| 24347 | }, | |
| 24348 | .@"packed" => { | |
| 24349 | const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) + | |
| 24350 | (if (zcu.typeToStruct(parent_ty)) |struct_obj| zcu.structPackedFieldBitOffset(struct_obj, field_index) else 0) - | |
| 24351 | actual_field_ptr_info.packed_offset.bit_offset), 8) catch | |
| 24352 | return sema.fail(block, inst_src, "pointer bit-offset mismatch", .{}); | |
| 24353 | actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (byte_offset > 0) | |
| 24354 | Alignment.fromLog2Units(@ctz(byte_offset)) | |
| 24355 | else | |
| 24356 | actual_field_ptr_info.flags.alignment); | |
| 24357 | }, | |
| 24358 | } | |
| 23459 | const hypothetical_field_ptr_ty = try parent_ptr_ty.fieldPtrType(field_index, pt); | |
| 23460 | const casted_field_ptr = try sema.ptrCastFull( | |
| 23461 | block, | |
| 23462 | flags, | |
| 23463 | inst_src, | |
| 23464 | field_ptr, | |
| 23465 | field_ptr_src, | |
| 23466 | hypothetical_field_ptr_ty, | |
| 23467 | "@fieldParentPtr", | |
| 23468 | ); | |
| 24359 | 23469 | |
| 24360 | const actual_field_ptr_ty = try pt.ptrTypeSema(actual_field_ptr_info); | |
| 24361 | const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src); | |
| 24362 | const actual_parent_ptr_ty = try pt.ptrTypeSema(actual_parent_ptr_info); | |
| 23470 | const unaligned_parent_ptr_ty = try pt.ptrType(info: { | |
| 23471 | var info = parent_ptr_info; | |
| 23472 | info.flags.alignment = hypothetical_field_ptr_ty.ptrAlignment(zcu); | |
| 23473 | break :info info; | |
| 23474 | }); | |
| 24363 | 23475 | |
| 24364 | const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: { | |
| 24365 | switch (parent_ty.zigTypeTag(zcu)) { | |
| 24366 | .@"struct" => switch (parent_ty.containerLayout(zcu)) { | |
| 24367 | .auto => {}, | |
| 24368 | .@"extern" => { | |
| 24369 | const byte_offset = parent_ty.structFieldOffset(field_index, zcu); | |
| 24370 | const parent_ptr_val = try sema.ptrSubtract(block, field_ptr_src, field_ptr_val, byte_offset, actual_parent_ptr_ty); | |
| 24371 | break :result Air.internedToRef(parent_ptr_val.toIntern()); | |
| 24372 | }, | |
| 24373 | .@"packed" => { | |
| 24374 | // Logic lifted from type computation above - I'm just assuming it's correct. | |
| 24375 | // `catch unreachable` since error case handled above. | |
| 24376 | const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) + | |
| 24377 | zcu.structPackedFieldBitOffset(zcu.typeToStruct(parent_ty).?, field_index) - | |
| 24378 | actual_field_ptr_info.packed_offset.bit_offset), 8) catch unreachable; | |
| 24379 | const parent_ptr_val = try sema.ptrSubtract(block, field_ptr_src, field_ptr_val, byte_offset, actual_parent_ptr_ty); | |
| 24380 | break :result Air.internedToRef(parent_ptr_val.toIntern()); | |
| 24381 | }, | |
| 24382 | }, | |
| 24383 | .@"union" => switch (parent_ty.containerLayout(zcu)) { | |
| 24384 | .auto => {}, | |
| 24385 | .@"extern", .@"packed" => { | |
| 24386 | // For an extern or packed union, just coerce the pointer. | |
| 24387 | const parent_ptr_val = try pt.getCoerced(field_ptr_val, actual_parent_ptr_ty); | |
| 24388 | break :result Air.internedToRef(parent_ptr_val.toIntern()); | |
| 24389 | }, | |
| 24390 | }, | |
| 23476 | const unaligned_parent_ptr: Air.Inst.Ref = if (try sema.resolveDefinedValue( | |
| 23477 | block, | |
| 23478 | field_ptr_src, | |
| 23479 | casted_field_ptr, | |
| 23480 | )) |field_ptr_val| switch (parent_ty.containerLayout(zcu)) { | |
| 23481 | .@"packed" => .fromValue(try pt.getCoerced(field_ptr_val, unaligned_parent_ptr_ty)), | |
| 23482 | .@"extern" => switch (parent_ty.zigTypeTag(zcu)) { | |
| 23483 | .@"struct" => .fromValue(try sema.ptrSubtract( | |
| 23484 | block, | |
| 23485 | field_ptr_src, | |
| 23486 | field_ptr_val, | |
| 23487 | parent_ty.structFieldOffset(field_index, zcu), | |
| 23488 | unaligned_parent_ptr_ty, | |
| 23489 | )), | |
| 23490 | .@"union" => .fromValue(try pt.getCoerced(field_ptr_val, unaligned_parent_ptr_ty)), | |
| 24391 | 23491 | else => unreachable, |
| 24392 | } | |
| 24393 | ||
| 24394 | const opt_field: ?InternPool.Key.Ptr.BaseAddr.BaseIndex = opt_field: { | |
| 24395 | const ptr = switch (ip.indexToKey(field_ptr_val.toIntern())) { | |
| 24396 | .ptr => |ptr| ptr, | |
| 24397 | else => break :opt_field null, | |
| 24398 | }; | |
| 24399 | if (ptr.byte_offset != 0) break :opt_field null; | |
| 24400 | break :opt_field switch (ptr.base_addr) { | |
| 24401 | .field => |field| field, | |
| 24402 | else => null, | |
| 23492 | }, | |
| 23493 | .auto => result: { | |
| 23494 | const opt_field: ?InternPool.Key.Ptr.BaseAddr.BaseIndex = opt_field: { | |
| 23495 | const ptr = switch (ip.indexToKey(field_ptr_val.toIntern())) { | |
| 23496 | .ptr => |ptr| ptr, | |
| 23497 | else => break :opt_field null, | |
| 23498 | }; | |
| 23499 | if (ptr.byte_offset != 0) break :opt_field null; | |
| 23500 | break :opt_field switch (ptr.base_addr) { | |
| 23501 | .field => |field| field, | |
| 23502 | else => null, | |
| 23503 | }; | |
| 24403 | 23504 | }; |
| 24404 | }; | |
| 24405 | 23505 | |
| 24406 | const field = opt_field orelse { | |
| 24407 | return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); | |
| 24408 | }; | |
| 23506 | const field = opt_field orelse { | |
| 23507 | return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); | |
| 23508 | }; | |
| 24409 | 23509 | |
| 24410 | if (Value.fromInterned(field.base).typeOf(zcu).childType(zcu).toIntern() != parent_ty.toIntern()) { | |
| 24411 | return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); | |
| 24412 | } | |
| 23510 | if (Value.fromInterned(field.base).typeOf(zcu).childType(zcu).toIntern() != parent_ty.toIntern()) { | |
| 23511 | return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); | |
| 23512 | } | |
| 24413 | 23513 | |
| 24414 | if (field.index != field_index) { | |
| 24415 | return sema.fail(block, inst_src, "field '{f}' has index '{d}' but pointer value is index '{d}' of struct '{f}'", .{ | |
| 24416 | field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt), | |
| 24417 | }); | |
| 24418 | } | |
| 24419 | break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src); | |
| 23514 | if (field.index != field_index) { | |
| 23515 | return sema.fail(block, inst_src, "field '{f}' has index '{d}' but pointer value is index '{d}' of struct '{f}'", .{ | |
| 23516 | field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt), | |
| 23517 | }); | |
| 23518 | } | |
| 23519 | break :result .fromValue(try pt.getCoerced(.fromInterned(field.base), unaligned_parent_ptr_ty)); | |
| 23520 | }, | |
| 24420 | 23521 | } else result: { |
| 24421 | try sema.requireRuntimeBlock(block, inst_src, field_ptr_src); | |
| 24422 | 23522 | break :result try block.addInst(.{ |
| 24423 | 23523 | .tag = .field_parent_ptr, |
| 24424 | 23524 | .data = .{ .ty_pl = .{ |
| 24425 | .ty = Air.internedToRef(actual_parent_ptr_ty.toIntern()), | |
| 23525 | .ty = .fromType(unaligned_parent_ptr_ty), | |
| 24426 | 23526 | .payload = try block.sema.addExtra(Air.FieldParentPtr{ |
| 24427 | 23527 | .field_ptr = casted_field_ptr, |
| 24428 | 23528 | .field_index = @intCast(field_index), |
| ... | ... | @@ -24430,14 +23530,61 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins |
| 24430 | 23530 | } }, |
| 24431 | 23531 | }); |
| 24432 | 23532 | }; |
| 24433 | return sema.ptrCastFull(block, flags, inst_src, result, inst_src, parent_ptr_ty, "@fieldParentPtr"); | |
| 23533 | ||
| 23534 | // There's one more error condition: if the hypothetical field pointer type has a lower | |
| 23535 | // alignment than the parent pointer type, then we need an `@alignCast`. Note that the earlier | |
| 23536 | // `ptrCastFull` may *also* have "used" the `@alignCast`; that would be a case where the field | |
| 23537 | // is naturally less aligned than the rest of the struct, *and* the field pointer is itself | |
| 23538 | // underaligned compared to the field alignment. For example, `struct { a: u32, b: u16 }` with | |
| 23539 | // a field pointer of type `*align(1) u16`. | |
| 23540 | switch (hypothetical_field_ptr_ty.ptrAlignment(zcu).order(parent_ptr_ty.ptrAlignment(zcu))) { | |
| 23541 | .gt => unreachable, // getting a field pointer can never increase alignment | |
| 23542 | .eq => return sema.coerce(block, maybe_opt_parent_ptr_ty, unaligned_parent_ptr, inst_src), | |
| 23543 | .lt => if (flags.align_cast) { | |
| 23544 | // Go through `ptrCastFull` for the safety check. | |
| 23545 | return sema.ptrCastFull( | |
| 23546 | block, | |
| 23547 | flags, | |
| 23548 | inst_src, | |
| 23549 | unaligned_parent_ptr, | |
| 23550 | inst_src, | |
| 23551 | maybe_opt_parent_ptr_ty, | |
| 23552 | "@fieldParentPtr", | |
| 23553 | ); | |
| 23554 | } else return sema.failWithOwnedErrorMsg(block, msg: { | |
| 23555 | const msg = try sema.errMsg(inst_src, "@fieldParentPtr increases pointer alignment", .{}); | |
| 23556 | errdefer msg.destroy(sema.gpa); | |
| 23557 | try sema.errNote(inst_src, msg, "parent pointer type '{f}' has alignment '{d}'", .{ | |
| 23558 | parent_ptr_ty.fmt(pt), | |
| 23559 | parent_ptr_ty.abiAlignment(zcu), | |
| 23560 | }); | |
| 23561 | if (parent_ty.isTuple(zcu)) { | |
| 23562 | try sema.errNote(field_ptr_src, msg, "tuple field '{d}' limits alignment to '{d}'", .{ | |
| 23563 | field_index, | |
| 23564 | field_ptr_ty.ptrAlignment(zcu), | |
| 23565 | }); | |
| 23566 | } else { | |
| 23567 | try sema.errNote(parent_ty.srcLoc(zcu), msg, "{t} field '{f}' limits alignment to '{d}'", .{ | |
| 23568 | parent_ty.zigTypeTag(zcu), | |
| 23569 | switch (parent_ty.zigTypeTag(zcu)) { | |
| 23570 | .@"struct" => parent_ty.structFieldName(field_index, zcu).unwrap().?.fmt(ip), | |
| 23571 | .@"union" => parent_ty.unionTagTypeHypothetical(zcu).enumFieldName(field_index, zcu).fmt(ip), | |
| 23572 | else => unreachable, | |
| 23573 | }, | |
| 23574 | field_ptr_ty.ptrAlignment(zcu), | |
| 23575 | }); | |
| 23576 | } | |
| 23577 | try sema.errNote(inst_src, msg, "use @alignCast to assert pointer alignment", .{}); | |
| 23578 | break :msg msg; | |
| 23579 | }), | |
| 23580 | } | |
| 24434 | 23581 | } |
| 24435 | 23582 | |
| 24436 | 23583 | fn ptrSubtract(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, byte_subtract: u64, new_ty: Type) !Value { |
| 24437 | 23584 | const pt = sema.pt; |
| 24438 | 23585 | const zcu = pt.zcu; |
| 24439 | 23586 | if (byte_subtract == 0) return pt.getCoerced(ptr_val, new_ty); |
| 24440 | var ptr = switch (zcu.intern_pool.indexToKey(ptr_val.toIntern())) { | |
| 23587 | const ptr = switch (zcu.intern_pool.indexToKey(ptr_val.toIntern())) { | |
| 24441 | 23588 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 24442 | 23589 | .ptr => |ptr| ptr, |
| 24443 | 23590 | else => unreachable, |
| ... | ... | @@ -24450,9 +23597,11 @@ fn ptrSubtract(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, byte |
| 24450 | 23597 | break :msg msg; |
| 24451 | 23598 | }); |
| 24452 | 23599 | } |
| 24453 | ptr.byte_offset -= byte_subtract; | |
| 24454 | ptr.ty = new_ty.toIntern(); | |
| 24455 | return Value.fromInterned(try pt.intern(.{ .ptr = ptr })); | |
| 23600 | return Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 23601 | .ty = new_ty.toIntern(), | |
| 23602 | .base_addr = ptr.base_addr, | |
| 23603 | .byte_offset = ptr.byte_offset - byte_subtract, | |
| 23604 | } })); | |
| 24456 | 23605 | } |
| 24457 | 23606 | |
| 24458 | 23607 | fn zirMinMax( |
| ... | ... | @@ -24466,8 +23615,8 @@ fn zirMinMax( |
| 24466 | 23615 | const src = block.nodeOffset(inst_data.src_node); |
| 24467 | 23616 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 24468 | 23617 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 24469 | const lhs = try sema.resolveInst(extra.lhs); | |
| 24470 | const rhs = try sema.resolveInst(extra.rhs); | |
| 23618 | const lhs = sema.resolveInst(extra.lhs); | |
| 23619 | const rhs = sema.resolveInst(extra.rhs); | |
| 24471 | 23620 | return sema.analyzeMinMax(block, src, air_tag, &.{ lhs, rhs }, &.{ lhs_src, rhs_src }); |
| 24472 | 23621 | } |
| 24473 | 23622 | |
| ... | ... | @@ -24487,7 +23636,7 @@ fn zirMinMaxMulti( |
| 24487 | 23636 | |
| 24488 | 23637 | for (operands, air_refs, operand_srcs, 0..) |zir_ref, *air_ref, *op_src, i| { |
| 24489 | 23638 | op_src.* = block.builtinCallArgSrc(src_node, @intCast(i)); |
| 24490 | air_ref.* = try sema.resolveInst(zir_ref); | |
| 23639 | air_ref.* = sema.resolveInst(zir_ref); | |
| 24491 | 23640 | } |
| 24492 | 23641 | |
| 24493 | 23642 | return sema.analyzeMinMax(block, src, air_tag, air_refs, operand_srcs); |
| ... | ... | @@ -24590,7 +23739,7 @@ fn analyzeMinMax( |
| 24590 | 23739 | const operand_scalar_ty = sema.typeOf(operand).scalarType(zcu); |
| 24591 | 23740 | const want_strat: TypeStrat = switch (operand_scalar_ty.zigTypeTag(zcu)) { |
| 24592 | 23741 | .comptime_int => s: { |
| 24593 | const val = (try sema.resolveValueResolveLazy(operand)).?; | |
| 23742 | const val = sema.resolveValue(operand).?; | |
| 24594 | 23743 | if (val.isUndef(zcu)) break :s .none; |
| 24595 | 23744 | break :s .{ .int = .{ |
| 24596 | 23745 | .all_comptime_int = true, |
| ... | ... | @@ -24609,7 +23758,7 @@ fn analyzeMinMax( |
| 24609 | 23758 | // (replaced with just the simple calls to `Type.minInt`/`Type.maxInt`) so that we only |
| 24610 | 23759 | // use the input *types* to determine the result type. |
| 24611 | 23760 | const min: Value, const max: Value = bounds: { |
| 24612 | if (try sema.resolveValueResolveLazy(operand)) |operand_val| { | |
| 23761 | if (sema.resolveValue(operand)) |operand_val| { | |
| 24613 | 23762 | if (vector_len) |len| { |
| 24614 | 23763 | var min = try operand_val.elemValue(pt, 0); |
| 24615 | 23764 | var max = min; |
| ... | ... | @@ -24696,6 +23845,9 @@ fn analyzeMinMax( |
| 24696 | 23845 | .child = intermediate_scalar_ty.toIntern(), |
| 24697 | 23846 | }) else intermediate_scalar_ty; |
| 24698 | 23847 | |
| 23848 | // We might have refined all the way down to an OPV type---check now. | |
| 23849 | if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 23850 | ||
| 24699 | 23851 | // This value, if not `null`, will have type `intermediate_ty`. |
| 24700 | 23852 | const comptime_part: ?Value = ct: { |
| 24701 | 23853 | // Contains the comptime-known scalar result values. |
| ... | ... | @@ -24712,7 +23864,7 @@ fn analyzeMinMax( |
| 24712 | 23864 | var opt_runtime_src: ?LazySrcLoc = null; |
| 24713 | 23865 | |
| 24714 | 23866 | for (operands, operand_srcs) |operand, operand_src| { |
| 24715 | const operand_val = try sema.resolveValueResolveLazy(operand) orelse { | |
| 23867 | const operand_val = sema.resolveValue(operand) orelse { | |
| 24716 | 23868 | if (opt_runtime_src == null) opt_runtime_src = operand_src; |
| 24717 | 23869 | continue; |
| 24718 | 23870 | }; |
| ... | ... | @@ -24819,7 +23971,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A |
| 24819 | 23971 | // Already an array pointer. |
| 24820 | 23972 | return ptr; |
| 24821 | 23973 | } |
| 24822 | const new_ty = try pt.ptrTypeSema(.{ | |
| 23974 | const new_ty = try pt.ptrType(.{ | |
| 24823 | 23975 | .child = (try pt.arrayType(.{ |
| 24824 | 23976 | .len = len, |
| 24825 | 23977 | .sentinel = info.sentinel, |
| ... | ... | @@ -24852,8 +24004,8 @@ fn zirMemcpy( |
| 24852 | 24004 | const src = block.nodeOffset(inst_data.src_node); |
| 24853 | 24005 | const dest_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 24854 | 24006 | const src_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 24855 | const dest_ptr = try sema.resolveInst(extra.lhs); | |
| 24856 | const src_ptr = try sema.resolveInst(extra.rhs); | |
| 24007 | const dest_ptr = sema.resolveInst(extra.lhs); | |
| 24008 | const src_ptr = sema.resolveInst(extra.rhs); | |
| 24857 | 24009 | const dest_ty = sema.typeOf(dest_ptr); |
| 24858 | 24010 | const src_ty = sema.typeOf(src_ptr); |
| 24859 | 24011 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); |
| ... | ... | @@ -24880,8 +24032,11 @@ fn zirMemcpy( |
| 24880 | 24032 | return sema.failWithOwnedErrorMsg(block, msg); |
| 24881 | 24033 | } |
| 24882 | 24034 | |
| 24883 | const dest_elem_ty = dest_ty.indexablePtrElem(zcu); | |
| 24884 | const src_elem_ty = src_ty.indexablePtrElem(zcu); | |
| 24035 | const dest_elem_ty = dest_ty.indexableElem(zcu); | |
| 24036 | const src_elem_ty = src_ty.indexableElem(zcu); | |
| 24037 | ||
| 24038 | try sema.ensureLayoutResolved(dest_elem_ty, dest_src, .ptr_access); | |
| 24039 | try sema.ensureLayoutResolved(src_elem_ty, src_src, .ptr_access); | |
| 24885 | 24040 | |
| 24886 | 24041 | const imc = try sema.coerceInMemoryAllowed( |
| 24887 | 24042 | block, |
| ... | ... | @@ -24946,13 +24101,13 @@ fn zirMemcpy( |
| 24946 | 24101 | } |
| 24947 | 24102 | |
| 24948 | 24103 | zero_bit: { |
| 24949 | const src_comptime = try src_elem_ty.comptimeOnlySema(pt); | |
| 24950 | const dest_comptime = try dest_elem_ty.comptimeOnlySema(pt); | |
| 24104 | const src_comptime = src_elem_ty.comptimeOnly(zcu); | |
| 24105 | const dest_comptime = dest_elem_ty.comptimeOnly(zcu); | |
| 24951 | 24106 | assert(src_comptime == dest_comptime); // IMC |
| 24952 | 24107 | if (src_comptime) break :zero_bit; |
| 24953 | 24108 | |
| 24954 | const src_has_bits = try src_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt); | |
| 24955 | const dest_has_bits = try dest_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt); | |
| 24109 | const src_has_bits = src_elem_ty.hasRuntimeBits(zcu); | |
| 24110 | const dest_has_bits = dest_elem_ty.hasRuntimeBits(zcu); | |
| 24956 | 24111 | assert(src_has_bits == dest_has_bits); // IMC |
| 24957 | 24112 | if (src_has_bits) break :zero_bit; |
| 24958 | 24113 | |
| ... | ... | @@ -24968,7 +24123,7 @@ fn zirMemcpy( |
| 24968 | 24123 | const raw_dest_ptr = if (dest_ty.isSlice(zcu)) dest_ptr_val.slicePtr(zcu) else dest_ptr_val; |
| 24969 | 24124 | const raw_src_ptr = if (src_ty.isSlice(zcu)) src_ptr_val.slicePtr(zcu) else src_ptr_val; |
| 24970 | 24125 | |
| 24971 | const len_u64 = try len_val.?.toUnsignedIntSema(pt); | |
| 24126 | const len_u64 = len_val.?.toUnsignedInt(zcu); | |
| 24972 | 24127 | |
| 24973 | 24128 | if (check_aliasing) { |
| 24974 | 24129 | if (Value.doPointersOverlap( |
| ... | ... | @@ -25018,7 +24173,7 @@ fn zirMemcpy( |
| 25018 | 24173 | var new_dest_ptr = dest_ptr; |
| 25019 | 24174 | var new_src_ptr = src_ptr; |
| 25020 | 24175 | if (len_val) |val| { |
| 25021 | const len = try val.toUnsignedIntSema(pt); | |
| 24176 | const len = val.toUnsignedInt(zcu); | |
| 25022 | 24177 | if (len == 0) { |
| 25023 | 24178 | // This AIR instruction guarantees length > 0 if it is comptime-known. |
| 25024 | 24179 | return; |
| ... | ... | @@ -25036,7 +24191,7 @@ fn zirMemcpy( |
| 25036 | 24191 | } |
| 25037 | 24192 | } else if (dest_len == .none and len_val == null) { |
| 25038 | 24193 | // Change the dest to a slice, since its type must have the length. |
| 25039 | const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); | |
| 24194 | const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr, .none); | |
| 25040 | 24195 | new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, LazySrcLoc.unneeded, dest_src, dest_src, dest_src, false); |
| 25041 | 24196 | const new_src_ptr_ty = sema.typeOf(new_src_ptr); |
| 25042 | 24197 | if (new_src_ptr_ty.isSlice(zcu)) { |
| ... | ... | @@ -25067,7 +24222,7 @@ fn zirMemcpy( |
| 25067 | 24222 | assert(dest_manyptr_ty_key.flags.size == .one); |
| 25068 | 24223 | dest_manyptr_ty_key.child = dest_elem_ty.toIntern(); |
| 25069 | 24224 | dest_manyptr_ty_key.flags.size = .many; |
| 25070 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(dest_manyptr_ty_key), new_dest_ptr, dest_src); | |
| 24225 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src); | |
| 25071 | 24226 | } else new_dest_ptr; |
| 25072 | 24227 | |
| 25073 | 24228 | const new_src_ptr_ty = sema.typeOf(new_src_ptr); |
| ... | ... | @@ -25078,13 +24233,13 @@ fn zirMemcpy( |
| 25078 | 24233 | assert(src_manyptr_ty_key.flags.size == .one); |
| 25079 | 24234 | src_manyptr_ty_key.child = src_elem_ty.toIntern(); |
| 25080 | 24235 | src_manyptr_ty_key.flags.size = .many; |
| 25081 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(src_manyptr_ty_key), new_src_ptr, src_src); | |
| 24236 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(src_manyptr_ty_key), new_src_ptr, src_src); | |
| 25082 | 24237 | } else new_src_ptr; |
| 25083 | 24238 | |
| 25084 | 24239 | // ok1: dest >= src + len |
| 25085 | 24240 | // ok2: src >= dest + len |
| 25086 | const src_plus_len = try sema.analyzePtrArithmetic(block, src, raw_src_ptr, len, .ptr_add, src_src, src); | |
| 25087 | const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src); | |
| 24241 | const src_plus_len = try sema.analyzePtrArithmetic(block, src, raw_src_ptr, len, .ptr_add, src); | |
| 24242 | const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, src); | |
| 25088 | 24243 | const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len); |
| 25089 | 24244 | const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len); |
| 25090 | 24245 | const ok = try block.addBinOp(.bool_or, ok1, ok2); |
| ... | ... | @@ -25113,8 +24268,8 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25113 | 24268 | const src = block.nodeOffset(inst_data.src_node); |
| 25114 | 24269 | const dest_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 25115 | 24270 | const value_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 25116 | const dest_ptr = try sema.resolveInst(extra.lhs); | |
| 25117 | const uncoerced_elem = try sema.resolveInst(extra.rhs); | |
| 24271 | const dest_ptr = sema.resolveInst(extra.lhs); | |
| 24272 | const uncoerced_elem = sema.resolveInst(extra.rhs); | |
| 25118 | 24273 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 25119 | 24274 | try checkMemOperand(sema, block, dest_src, dest_ptr_ty); |
| 25120 | 24275 | |
| ... | ... | @@ -25145,10 +24300,17 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25145 | 24300 | |
| 25146 | 24301 | const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); |
| 25147 | 24302 | |
| 24303 | const comptime_only_elem = switch (dest_elem_ty.classify(zcu)) { | |
| 24304 | .no_possible_value => unreachable, // `elem` is a value of this type | |
| 24305 | .one_possible_value => return, // no work to do | |
| 24306 | .runtime => false, | |
| 24307 | .partially_comptime, .fully_comptime => true, | |
| 24308 | }; | |
| 24309 | ||
| 25148 | 24310 | const runtime_src = rs: { |
| 25149 | 24311 | const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src); |
| 25150 | 24312 | const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; |
| 25151 | const len_u64 = try len_val.toUnsignedIntSema(pt); | |
| 24313 | const len_u64 = len_val.toUnsignedInt(zcu); | |
| 25152 | 24314 | const len = try sema.usizeCast(block, dest_src, len_u64); |
| 25153 | 24315 | if (len == 0) { |
| 25154 | 24316 | // This AIR instruction guarantees length > 0 if it is comptime-known. |
| ... | ... | @@ -25157,7 +24319,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25157 | 24319 | |
| 25158 | 24320 | const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src; |
| 25159 | 24321 | if (!sema.isComptimeMutablePtr(ptr_val)) break :rs dest_src; |
| 25160 | const elem_val = try sema.resolveValue(elem) orelse break :rs value_src; | |
| 24322 | const elem_val = sema.resolveValue(elem) orelse break :rs value_src; | |
| 25161 | 24323 | const array_ty = try pt.arrayType(.{ |
| 25162 | 24324 | .child = dest_elem_ty.toIntern(), |
| 25163 | 24325 | .len = len_u64, |
| ... | ... | @@ -25174,6 +24336,15 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25174 | 24336 | return sema.storePtrVal(block, src, array_ptr_val, array_val, array_ty); |
| 25175 | 24337 | }; |
| 25176 | 24338 | |
| 24339 | if (comptime_only_elem) { | |
| 24340 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 24341 | const msg = try sema.errMsg(src, "cannot store comptime-only element '{f}' at runtime", .{dest_elem_ty.fmt(pt)}); | |
| 24342 | errdefer msg.destroy(sema.gpa); | |
| 24343 | try sema.errNote(dest_src, msg, "operation is runtime due to destination pointer", .{}); | |
| 24344 | break :msg msg; | |
| 24345 | }); | |
| 24346 | } | |
| 24347 | ||
| 25177 | 24348 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 25178 | 24349 | try sema.validateRuntimeValue(block, dest_src, dest_ptr); |
| 25179 | 24350 | try sema.validateRuntimeValue(block, value_src, elem); |
| ... | ... | @@ -25227,7 +24398,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 25227 | 24398 | const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| 25228 | 24399 | extra_index += 1; |
| 25229 | 24400 | const cc_ty = try sema.getBuiltinType(cc_src, .CallingConvention); |
| 25230 | const uncoerced_cc = try sema.resolveInst(cc_ref); | |
| 24401 | const uncoerced_cc = sema.resolveInst(cc_ref); | |
| 25231 | 24402 | const coerced_cc = try sema.coerce(block, cc_ty, uncoerced_cc, cc_src); |
| 25232 | 24403 | const cc_val = try sema.resolveConstDefinedValue(block, cc_src, coerced_cc, .{ .simple = .@"callconv" }); |
| 25233 | 24404 | break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val); |
| ... | ... | @@ -25344,7 +24515,7 @@ fn zirCDefine( |
| 25344 | 24515 | const val_src = block.builtinCallArgSrc(extra.node, 1); |
| 25345 | 24516 | |
| 25346 | 24517 | const name = try sema.resolveConstString(block, name_src, extra.lhs, .{ .simple = .operand_cDefine_macro_name }); |
| 25347 | const rhs = try sema.resolveInst(extra.rhs); | |
| 24518 | const rhs = sema.resolveInst(extra.rhs); | |
| 25348 | 24519 | if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) { |
| 25349 | 24520 | const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value }); |
| 25350 | 24521 | try block.c_import_buf.?.print("#define {s} {s}\n", .{ name, value }); |
| ... | ... | @@ -25393,7 +24564,7 @@ fn zirWasmMemoryGrow( |
| 25393 | 24564 | } |
| 25394 | 24565 | |
| 25395 | 24566 | const index: u32 = @intCast(try sema.resolveInt(block, index_src, extra.lhs, .u32, .{ .simple = .wasm_memory_index })); |
| 25396 | const delta = try sema.coerce(block, .usize, try sema.resolveInst(extra.rhs), delta_src); | |
| 24567 | const delta = try sema.coerce(block, .usize, sema.resolveInst(extra.rhs), delta_src); | |
| 25397 | 24568 | |
| 25398 | 24569 | try sema.requireRuntimeBlock(block, builtin_src, null); |
| 25399 | 24570 | return block.addInst(.{ |
| ... | ... | @@ -25419,7 +24590,7 @@ fn resolvePrefetchOptions( |
| 25419 | 24590 | const ip = &zcu.intern_pool; |
| 25420 | 24591 | |
| 25421 | 24592 | const options_ty = try sema.getBuiltinType(src, .PrefetchOptions); |
| 25422 | const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); | |
| 24593 | const options = try sema.coerce(block, options_ty, sema.resolveInst(zir_ref), src); | |
| 25423 | 24594 | |
| 25424 | 24595 | const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25425 | 24596 | const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| ... | ... | @@ -25436,7 +24607,7 @@ fn resolvePrefetchOptions( |
| 25436 | 24607 | |
| 25437 | 24608 | return std.builtin.PrefetchOptions{ |
| 25438 | 24609 | .rw = try sema.interpretBuiltinType(block, rw_src, rw_val, std.builtin.PrefetchOptions.Rw), |
| 25439 | .locality = @intCast(try locality_val.toUnsignedIntSema(pt)), | |
| 24610 | .locality = @intCast(locality_val.toUnsignedInt(zcu)), | |
| 25440 | 24611 | .cache = try sema.interpretBuiltinType(block, cache_src, cache_val, std.builtin.PrefetchOptions.Cache), |
| 25441 | 24612 | }; |
| 25442 | 24613 | } |
| ... | ... | @@ -25449,7 +24620,7 @@ fn zirPrefetch( |
| 25449 | 24620 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 25450 | 24621 | const ptr_src = block.builtinCallArgSrc(extra.node, 0); |
| 25451 | 24622 | const opts_src = block.builtinCallArgSrc(extra.node, 1); |
| 25452 | const ptr = try sema.resolveInst(extra.lhs); | |
| 24623 | const ptr = sema.resolveInst(extra.lhs); | |
| 25453 | 24624 | try sema.checkPtrOperand(block, ptr_src, sema.typeOf(ptr)); |
| 25454 | 24625 | |
| 25455 | 24626 | const options = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs); |
| ... | ... | @@ -25491,7 +24662,7 @@ fn resolveExternOptions( |
| 25491 | 24662 | const io = comp.io; |
| 25492 | 24663 | const ip = &zcu.intern_pool; |
| 25493 | 24664 | |
| 25494 | const options_inst = try sema.resolveInst(zir_ref); | |
| 24665 | const options_inst = sema.resolveInst(zir_ref); | |
| 25495 | 24666 | const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions); |
| 25496 | 24667 | const options = try sema.coerce(block, extern_options_ty, options_inst, src); |
| 25497 | 24668 | |
| ... | ... | @@ -25574,18 +24745,32 @@ fn zirBuiltinExtern( |
| 25574 | 24745 | const ty_src = block.builtinCallArgSrc(extra.node, 0); |
| 25575 | 24746 | const options_src = block.builtinCallArgSrc(extra.node, 1); |
| 25576 | 24747 | |
| 25577 | var ty = try sema.resolveType(block, ty_src, extra.lhs); | |
| 25578 | if (!ty.isPtrAtRuntime(zcu)) { | |
| 24748 | const ptr_ty = try sema.resolveType(block, ty_src, extra.lhs); | |
| 24749 | if (!ptr_ty.isPtrAtRuntime(zcu)) { | |
| 25579 | 24750 | return sema.fail(block, ty_src, "expected (optional) pointer", .{}); |
| 25580 | 24751 | } |
| 25581 | if (!try sema.validateExternType(ty, .other)) { | |
| 25582 | const msg = msg: { | |
| 25583 | const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)}); | |
| 24752 | ||
| 24753 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 24754 | ||
| 24755 | const elem_ty: Type = .fromInterned(ptr_info.child); | |
| 24756 | try sema.ensureLayoutResolved(elem_ty, src, .@"extern"); | |
| 24757 | ||
| 24758 | if (!elem_ty.validateExtern(.other, zcu)) { | |
| 24759 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 24760 | const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ptr_ty.fmt(pt)}); | |
| 25584 | 24761 | errdefer msg.destroy(sema.gpa); |
| 25585 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other); | |
| 24762 | try sema.errNote(ty_src, msg, "pointer element type '{f}' is not extern compatible", .{elem_ty.fmt(pt)}); | |
| 24763 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, elem_ty, .other); | |
| 25586 | 24764 | break :msg msg; |
| 25587 | }; | |
| 25588 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 24765 | }); | |
| 24766 | } | |
| 24767 | if (elem_ty.zigTypeTag(zcu) == .@"fn" and !ptr_info.flags.is_const) { | |
| 24768 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 24769 | const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ptr_ty.fmt(pt)}); | |
| 24770 | errdefer msg.destroy(sema.gpa); | |
| 24771 | try sema.errNote(ty_src, msg, "pointer to extern function must be 'const'", .{}); | |
| 24772 | break :msg msg; | |
| 24773 | }); | |
| 25589 | 24774 | } |
| 25590 | 24775 | |
| 25591 | 24776 | const options = try sema.resolveExternOptions(block, options_src, extra.rhs); |
| ... | ... | @@ -25603,14 +24788,9 @@ fn zirBuiltinExtern( |
| 25603 | 24788 | |
| 25604 | 24789 | // TODO: error for threadlocal functions, non-const functions, etc |
| 25605 | 24790 | |
| 25606 | if (options.linkage == .weak and !ty.ptrAllowsZero(zcu)) { | |
| 25607 | ty = try pt.optionalType(ty.toIntern()); | |
| 25608 | } | |
| 25609 | const ptr_info = ty.ptrInfo(zcu); | |
| 25610 | ||
| 25611 | 24791 | const extern_val = try pt.getExtern(.{ |
| 25612 | 24792 | .name = options.name, |
| 25613 | .ty = ptr_info.child, | |
| 24793 | .ty = elem_ty.toIntern(), | |
| 25614 | 24794 | .lib_name = options.library_name, |
| 25615 | 24795 | .linkage = options.linkage, |
| 25616 | 24796 | .visibility = options.visibility, |
| ... | ... | @@ -25626,7 +24806,7 @@ fn zirBuiltinExtern( |
| 25626 | 24806 | // So, for now, just use our containing `declaration`. |
| 25627 | 24807 | .zir_index = switch (sema.owner.unwrap()) { |
| 25628 | 24808 | .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index, |
| 25629 | .type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?, | |
| 24809 | .type_layout, .struct_defaults => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, | |
| 25630 | 24810 | .memoized_state => unreachable, |
| 25631 | 24811 | .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index, |
| 25632 | 24812 | .func => |func| zir_index: { |
| ... | ... | @@ -25641,13 +24821,17 @@ fn zirBuiltinExtern( |
| 25641 | 24821 | .source = .builtin, |
| 25642 | 24822 | }); |
| 25643 | 24823 | |
| 24824 | // For a weak symbol where the given type is not nullable, make the pointer optional. | |
| 24825 | const result_ptr_ty: Type = if (options.linkage == .weak and !ptr_ty.ptrAllowsZero(zcu)) ty: { | |
| 24826 | break :ty try pt.optionalType(ptr_ty.toIntern()); | |
| 24827 | } else ptr_ty; | |
| 24828 | ||
| 25644 | 24829 | const uncasted_ptr = try sema.analyzeNavRef(block, src, ip.indexToKey(extern_val).@"extern".owner_nav); |
| 25645 | // We want to cast to `ty`, but that isn't necessarily an allowed coercion. | |
| 25646 | if (try sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| { | |
| 25647 | const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, ty); | |
| 24830 | if (sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| { | |
| 24831 | const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, result_ptr_ty); | |
| 25648 | 24832 | return Air.internedToRef(casted_ptr_val.toIntern()); |
| 25649 | 24833 | } else { |
| 25650 | return block.addBitCast(ty, uncasted_ptr); | |
| 24834 | return block.addBitCast(result_ptr_ty, uncasted_ptr); | |
| 25651 | 24835 | } |
| 25652 | 24836 | } |
| 25653 | 24837 | |
| ... | ... | @@ -25732,6 +24916,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 25732 | 24916 | // Values are handled here. |
| 25733 | 24917 | .calling_convention_c => { |
| 25734 | 24918 | const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); |
| 24919 | // Cannot use `Value.uninterpret` because `c` is a *declaration* whose value depends on the target. | |
| 25735 | 24920 | return try sema.namespaceLookupVal( |
| 25736 | 24921 | block, |
| 25737 | 24922 | src, |
| ... | ... | @@ -25740,17 +24925,15 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 25740 | 24925 | ) orelse @panic("std.builtin is corrupt"); |
| 25741 | 24926 | }, |
| 25742 | 24927 | .calling_convention_inline => { |
| 25743 | comptime assert(@typeInfo(std.builtin.CallingConvention.Tag).@"enum".tag_type == u8); | |
| 25744 | 24928 | const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); |
| 25745 | const callconv_tag_ty = callconv_ty.unionTagType(zcu) orelse @panic("std.builtin is corrupt"); | |
| 25746 | const inline_tag_val = try pt.enumValue( | |
| 25747 | callconv_tag_ty, | |
| 25748 | (try pt.intValue( | |
| 25749 | .u8, | |
| 25750 | @intFromEnum(std.builtin.CallingConvention.@"inline"), | |
| 25751 | )).toIntern(), | |
| 25752 | ); | |
| 25753 | return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src); | |
| 24929 | return .fromValue(Value.uninterpret( | |
| 24930 | @as(std.builtin.CallingConvention, .@"inline"), | |
| 24931 | callconv_ty, | |
| 24932 | pt, | |
| 24933 | ) catch |err| switch (err) { | |
| 24934 | error.TypeMismatch => @panic("std.builtin is corrupt"), | |
| 24935 | error.OutOfMemory => |e| return e, | |
| 24936 | }); | |
| 25754 | 24937 | }, |
| 25755 | 24938 | }; |
| 25756 | 24939 | return .fromType(try sema.getBuiltinType(src, builtin_type)); |
| ... | ... | @@ -25760,7 +24943,7 @@ fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) Co |
| 25760 | 24943 | const pt = sema.pt; |
| 25761 | 24944 | const zcu = pt.zcu; |
| 25762 | 24945 | |
| 25763 | const lhs = try sema.resolveInst(@enumFromInt(extended.operand)); | |
| 24946 | const lhs = sema.resolveInst(@enumFromInt(extended.operand)); | |
| 25764 | 24947 | const lhs_ty = sema.typeOf(lhs); |
| 25765 | 24948 | |
| 25766 | 24949 | const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small); |
| ... | ... | @@ -25785,7 +24968,7 @@ fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) Co |
| 25785 | 24968 | |
| 25786 | 24969 | fn zirBranchHint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 25787 | 24970 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 25788 | const uncoerced_hint = try sema.resolveInst(extra.operand); | |
| 24971 | const uncoerced_hint = sema.resolveInst(extra.operand); | |
| 25789 | 24972 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 25790 | 24973 | |
| 25791 | 24974 | const hint_ty = try sema.getBuiltinType(operand_src, .BranchHint); |
| ... | ... | @@ -25839,7 +25022,8 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: |
| 25839 | 25022 | } |
| 25840 | 25023 | } |
| 25841 | 25024 | |
| 25842 | /// Emit a compile error if type cannot be used for a runtime variable. | |
| 25025 | /// Emit a compile error if `var_ty` cannot be used for a runtime variable. | |
| 25026 | /// Asserts that the layout of `var_ty` is already resolved. | |
| 25843 | 25027 | pub fn validateVarType( |
| 25844 | 25028 | sema: *Sema, |
| 25845 | 25029 | block: *Block, |
| ... | ... | @@ -25849,8 +25033,9 @@ pub fn validateVarType( |
| 25849 | 25033 | ) CompileError!void { |
| 25850 | 25034 | const pt = sema.pt; |
| 25851 | 25035 | const zcu = pt.zcu; |
| 25036 | var_ty.assertHasLayout(zcu); | |
| 25852 | 25037 | if (is_extern) { |
| 25853 | if (!try sema.validateExternType(var_ty, .other)) { | |
| 25038 | if (!var_ty.validateExtern(.other, zcu)) { | |
| 25854 | 25039 | const msg = msg: { |
| 25855 | 25040 | const msg = try sema.errMsg(src, "extern variable cannot have type '{f}'", .{var_ty.fmt(pt)}); |
| 25856 | 25041 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -25870,7 +25055,7 @@ pub fn validateVarType( |
| 25870 | 25055 | } |
| 25871 | 25056 | } |
| 25872 | 25057 | |
| 25873 | if (!try var_ty.comptimeOnlySema(pt)) return; | |
| 25058 | if (!var_ty.comptimeOnly(zcu)) return; | |
| 25874 | 25059 | |
| 25875 | 25060 | const msg = msg: { |
| 25876 | 25061 | const msg = try sema.errMsg(src, "variable of type '{f}' must be const or comptime", .{var_ty.fmt(pt)}); |
| ... | ... | @@ -25886,49 +25071,28 @@ pub fn validateVarType( |
| 25886 | 25071 | return sema.failWithOwnedErrorMsg(block, msg); |
| 25887 | 25072 | } |
| 25888 | 25073 | |
| 25889 | const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void); | |
| 25890 | ||
| 25891 | 25074 | fn explainWhyTypeIsComptime( |
| 25892 | 25075 | sema: *Sema, |
| 25893 | 25076 | msg: *Zcu.ErrorMsg, |
| 25894 | src_loc: LazySrcLoc, | |
| 25895 | ty: Type, | |
| 25896 | ) CompileError!void { | |
| 25897 | var type_set = TypeSet{}; | |
| 25898 | defer type_set.deinit(sema.gpa); | |
| 25899 | ||
| 25900 | try ty.resolveFully(sema.pt); | |
| 25901 | return sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty, &type_set); | |
| 25902 | } | |
| 25903 | ||
| 25904 | fn explainWhyTypeIsComptimeInner( | |
| 25905 | sema: *Sema, | |
| 25906 | msg: *Zcu.ErrorMsg, | |
| 25907 | src_loc: LazySrcLoc, | |
| 25077 | src: LazySrcLoc, | |
| 25908 | 25078 | ty: Type, |
| 25909 | type_set: *TypeSet, | |
| 25910 | 25079 | ) CompileError!void { |
| 25911 | 25080 | const pt = sema.pt; |
| 25912 | 25081 | const zcu = pt.zcu; |
| 25913 | 25082 | const ip = &zcu.intern_pool; |
| 25083 | assert(ty.comptimeOnly(zcu)); | |
| 25914 | 25084 | switch (ty.zigTypeTag(zcu)) { |
| 25915 | 25085 | .bool, |
| 25916 | 25086 | .int, |
| 25917 | 25087 | .float, |
| 25918 | 25088 | .error_set, |
| 25919 | .@"enum", | |
| 25920 | 25089 | .frame, |
| 25921 | 25090 | .@"anyframe", |
| 25922 | 25091 | .void, |
| 25923 | => return, | |
| 25924 | ||
| 25925 | .@"fn" => { | |
| 25926 | try sema.errNote(src_loc, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)}); | |
| 25927 | }, | |
| 25928 | ||
| 25929 | .type => { | |
| 25930 | try sema.errNote(src_loc, msg, "types are not available at runtime", .{}); | |
| 25931 | }, | |
| 25092 | .@"enum", | |
| 25093 | .@"opaque", | |
| 25094 | .pointer, | |
| 25095 | => unreachable, // not comptime-only | |
| 25932 | 25096 | |
| 25933 | 25097 | .comptime_float, |
| 25934 | 25098 | .comptime_int, |
| ... | ... | @@ -25936,99 +25100,65 @@ fn explainWhyTypeIsComptimeInner( |
| 25936 | 25100 | .noreturn, |
| 25937 | 25101 | .undefined, |
| 25938 | 25102 | .null, |
| 25939 | => return, | |
| 25940 | ||
| 25941 | .@"opaque" => { | |
| 25942 | try sema.errNote(src_loc, msg, "opaque type '{f}' has undefined size", .{ty.fmt(pt)}); | |
| 25943 | }, | |
| 25944 | ||
| 25945 | .array, .vector => { | |
| 25946 | try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(zcu), type_set); | |
| 25947 | }, | |
| 25948 | .pointer => { | |
| 25949 | const elem_ty = ty.elemType2(zcu); | |
| 25950 | if (elem_ty.zigTypeTag(zcu) == .@"fn") { | |
| 25951 | const fn_info = zcu.typeToFunc(elem_ty).?; | |
| 25952 | if (fn_info.is_generic) { | |
| 25953 | try sema.errNote(src_loc, msg, "function is generic", .{}); | |
| 25954 | } | |
| 25955 | switch (fn_info.cc) { | |
| 25956 | .@"inline" => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}), | |
| 25957 | else => {}, | |
| 25958 | } | |
| 25959 | if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) { | |
| 25960 | try sema.errNote(src_loc, msg, "function has a comptime-only return type", .{}); | |
| 25961 | } | |
| 25962 | return; | |
| 25963 | } | |
| 25964 | try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(zcu), type_set); | |
| 25965 | }, | |
| 25966 | ||
| 25967 | .optional => { | |
| 25968 | try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(zcu), type_set); | |
| 25969 | }, | |
| 25970 | .error_union => { | |
| 25971 | try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(zcu), type_set); | |
| 25972 | }, | |
| 25103 | => return, // no explanation needed | |
| 25973 | 25104 | |
| 25974 | .@"struct" => { | |
| 25975 | if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return; | |
| 25105 | .array, .vector => try sema.explainWhyTypeIsComptime(msg, src, ty.childType(zcu)), | |
| 25106 | .optional => try sema.explainWhyTypeIsComptime(msg, src, ty.optionalChild(zcu)), | |
| 25107 | .error_union => try sema.explainWhyTypeIsComptime(msg, src, ty.errorUnionPayload(zcu)), | |
| 25976 | 25108 | |
| 25977 | if (zcu.typeToStruct(ty)) |struct_type| { | |
| 25978 | for (0..struct_type.field_types.len) |i| { | |
| 25979 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 25980 | const field_src: LazySrcLoc = .{ | |
| 25981 | .base_node_inst = struct_type.zir_index, | |
| 25982 | .offset = .{ .container_field_type = @intCast(i) }, | |
| 25983 | }; | |
| 25109 | .@"fn" => try sema.errNote(src, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)}), | |
| 25110 | .type => try sema.errNote(src, msg, "types are not available at runtime", .{}), | |
| 25984 | 25111 | |
| 25985 | if (try field_ty.comptimeOnlySema(pt)) { | |
| 25986 | try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{}); | |
| 25987 | try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set); | |
| 25988 | } | |
| 25989 | } | |
| 25112 | .@"struct" => if (zcu.typeToStruct(ty)) |struct_type| { | |
| 25113 | ty.assertHasLayout(zcu); | |
| 25114 | for (0..struct_type.field_types.len) |i| { | |
| 25115 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 25116 | if (!field_ty.comptimeOnly(zcu)) continue; | |
| 25117 | const field_src: LazySrcLoc = .{ | |
| 25118 | .base_node_inst = struct_type.zir_index, | |
| 25119 | .offset = .{ .container_field_type = @intCast(i) }, | |
| 25120 | }; | |
| 25121 | try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{}); | |
| 25122 | return sema.explainWhyTypeIsComptime(msg, field_src, field_ty); | |
| 25123 | } | |
| 25124 | unreachable; | |
| 25125 | } else { | |
| 25126 | const tuple = ip.indexToKey(ty.toIntern()).tuple_type; | |
| 25127 | for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty_ip, field_val_ip| { | |
| 25128 | if (field_val_ip != .none) continue; | |
| 25129 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 25130 | if (!field_ty.comptimeOnly(zcu)) continue; | |
| 25131 | try sema.errNote(src, msg, "tuple requires comptime because of field of type '{f}'", .{field_ty.fmt(pt)}); | |
| 25132 | return sema.explainWhyTypeIsComptime(msg, src, field_ty); | |
| 25990 | 25133 | } |
| 25991 | // TODO tuples | |
| 25134 | unreachable; | |
| 25992 | 25135 | }, |
| 25993 | 25136 | |
| 25994 | 25137 | .@"union" => { |
| 25995 | if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return; | |
| 25996 | ||
| 25997 | if (zcu.typeToUnion(ty)) |union_obj| { | |
| 25998 | for (0..union_obj.field_types.len) |i| { | |
| 25999 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]); | |
| 26000 | const field_src: LazySrcLoc = .{ | |
| 26001 | .base_node_inst = union_obj.zir_index, | |
| 26002 | .offset = .{ .container_field_type = @intCast(i) }, | |
| 26003 | }; | |
| 26004 | ||
| 26005 | if (try field_ty.comptimeOnlySema(pt)) { | |
| 26006 | try sema.errNote(field_src, msg, "union requires comptime because of this field", .{}); | |
| 26007 | try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set); | |
| 26008 | } | |
| 26009 | } | |
| 25138 | const union_obj = zcu.typeToUnion(ty).?; | |
| 25139 | for (0..union_obj.field_types.len) |i| { | |
| 25140 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]); | |
| 25141 | if (!field_ty.comptimeOnly(zcu)) continue; | |
| 25142 | const field_src: LazySrcLoc = .{ | |
| 25143 | .base_node_inst = union_obj.zir_index, | |
| 25144 | .offset = .{ .container_field_type = @intCast(i) }, | |
| 25145 | }; | |
| 25146 | try sema.errNote(field_src, msg, "union requires comptime because of this field", .{}); | |
| 25147 | return sema.explainWhyTypeIsComptime(msg, field_src, field_ty); | |
| 26010 | 25148 | } |
| 25149 | unreachable; | |
| 26011 | 25150 | }, |
| 26012 | 25151 | } |
| 26013 | 25152 | } |
| 26014 | 25153 | |
| 26015 | const ExternPosition = enum { | |
| 26016 | ret_ty, | |
| 26017 | param_ty, | |
| 26018 | union_field, | |
| 26019 | struct_field, | |
| 26020 | element, | |
| 26021 | other, | |
| 26022 | }; | |
| 26023 | ||
| 26024 | /// Returns true if `ty` is allowed in extern types. | |
| 26025 | /// Does *NOT* require `ty` to be resolved in any way. | |
| 26026 | /// Calls `resolveLayout` for packed containers. | |
| 26027 | fn validateExternType( | |
| 25154 | /// Keep in sync with `Type.validateExtern`. | |
| 25155 | pub fn explainWhyTypeIsNotExtern( | |
| 26028 | 25156 | sema: *Sema, |
| 25157 | msg: *Zcu.ErrorMsg, | |
| 25158 | src_loc: LazySrcLoc, | |
| 26029 | 25159 | ty: Type, |
| 26030 | position: ExternPosition, | |
| 26031 | ) !bool { | |
| 25160 | position: Type.ExternPosition, | |
| 25161 | ) SemaError!void { | |
| 26032 | 25162 | const pt = sema.pt; |
| 26033 | 25163 | const zcu = pt.zcu; |
| 26034 | 25164 | switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -26041,217 +25171,122 @@ fn validateExternType( |
| 26041 | 25171 | .error_union, |
| 26042 | 25172 | .error_set, |
| 26043 | 25173 | .frame, |
| 26044 | => return false, | |
| 26045 | .void => return position == .union_field or position == .ret_ty or position == .struct_field or position == .element, | |
| 26046 | .noreturn => return position == .ret_ty, | |
| 26047 | .@"opaque", | |
| 26048 | .bool, | |
| 26049 | .float, | |
| 26050 | .@"anyframe", | |
| 26051 | => return true, | |
| 26052 | .pointer => { | |
| 26053 | if (ty.childType(zcu).zigTypeTag(zcu) == .@"fn") { | |
| 26054 | return ty.isConstPtr(zcu) and try sema.validateExternType(ty.childType(zcu), .other); | |
| 26055 | } | |
| 26056 | return !(ty.isSlice(zcu) or try ty.comptimeOnlySema(pt)); | |
| 26057 | }, | |
| 26058 | .int => switch (ty.intInfo(zcu).bits) { | |
| 26059 | 0, 8, 16, 32, 64, 128 => return true, | |
| 26060 | else => return false, | |
| 26061 | }, | |
| 26062 | .@"fn" => { | |
| 26063 | if (position != .other) return false; | |
| 26064 | // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. | |
| 26065 | // The goal is to experiment with more integrated CPU/GPU code. | |
| 26066 | if (ty.fnCallingConvention(zcu) == .nvptx_kernel) { | |
| 26067 | return true; | |
| 26068 | } | |
| 26069 | return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu)); | |
| 26070 | }, | |
| 26071 | .@"enum" => { | |
| 26072 | return sema.validateExternType(ty.intTagType(zcu), position); | |
| 26073 | }, | |
| 26074 | .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { | |
| 26075 | .@"extern" => return true, | |
| 26076 | .@"packed" => { | |
| 26077 | const bit_size = try ty.bitSizeSema(pt); | |
| 26078 | switch (bit_size) { | |
| 26079 | 0, 8, 16, 32, 64, 128 => return true, | |
| 26080 | else => return false, | |
| 26081 | } | |
| 26082 | }, | |
| 26083 | .auto => return !(try ty.hasRuntimeBitsSema(pt)), | |
| 26084 | }, | |
| 26085 | .array => { | |
| 26086 | if (position == .ret_ty or position == .param_ty) return false; | |
| 26087 | return sema.validateExternType(ty.elemType2(zcu), .element); | |
| 26088 | }, | |
| 26089 | .vector => return sema.validateExternType(ty.elemType2(zcu), .element), | |
| 26090 | .optional => return ty.isPtrLikeOptional(zcu), | |
| 26091 | } | |
| 26092 | } | |
| 25174 | => return, | |
| 25175 | ||
| 25176 | .void => try sema.errNote(src_loc, msg, "'void' is a zero bit type", .{}), | |
| 25177 | .noreturn => try sema.errNote(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), | |
| 26093 | 25178 | |
| 26094 | fn explainWhyTypeIsNotExtern( | |
| 26095 | sema: *Sema, | |
| 26096 | msg: *Zcu.ErrorMsg, | |
| 26097 | src_loc: LazySrcLoc, | |
| 26098 | ty: Type, | |
| 26099 | position: ExternPosition, | |
| 26100 | ) CompileError!void { | |
| 26101 | const pt = sema.pt; | |
| 26102 | const zcu = pt.zcu; | |
| 26103 | switch (ty.zigTypeTag(zcu)) { | |
| 26104 | 25179 | .@"opaque", |
| 26105 | 25180 | .bool, |
| 26106 | 25181 | .float, |
| 26107 | 25182 | .@"anyframe", |
| 26108 | => return, | |
| 26109 | ||
| 26110 | .type, | |
| 26111 | .comptime_float, | |
| 26112 | .comptime_int, | |
| 26113 | .enum_literal, | |
| 26114 | .undefined, | |
| 26115 | .null, | |
| 26116 | .error_union, | |
| 26117 | .error_set, | |
| 26118 | .frame, | |
| 26119 | => return, | |
| 25183 | => unreachable, // these *are* allowed | |
| 26120 | 25184 | |
| 26121 | .pointer => { | |
| 26122 | if (ty.isSlice(zcu)) { | |
| 26123 | try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); | |
| 25185 | .pointer => if (ty.isSlice(zcu)) { | |
| 25186 | try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); | |
| 25187 | } else { | |
| 25188 | assert(ty.childType(zcu).zigTypeTag(zcu) == .@"fn"); | |
| 25189 | if (!ty.isConstPtr(zcu)) { | |
| 25190 | try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); | |
| 26124 | 25191 | } else { |
| 26125 | const pointee_ty = ty.childType(zcu); | |
| 26126 | if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") { | |
| 26127 | try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); | |
| 26128 | } else if (try ty.comptimeOnlySema(pt)) { | |
| 26129 | try sema.errNote(src_loc, msg, "pointer to comptime-only type '{f}'", .{pointee_ty.fmt(pt)}); | |
| 26130 | try sema.explainWhyTypeIsComptime(msg, src_loc, ty); | |
| 26131 | } | |
| 26132 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other); | |
| 25192 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .other); | |
| 26133 | 25193 | } |
| 26134 | 25194 | }, |
| 26135 | .void => try sema.errNote(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), | |
| 26136 | .noreturn => try sema.errNote(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), | |
| 26137 | 25195 | .int => if (!std.math.isPowerOfTwo(ty.intInfo(zcu).bits)) { |
| 26138 | 25196 | try sema.errNote(src_loc, msg, "only integers with 0 or power of two bits are extern compatible", .{}); |
| 26139 | 25197 | } else { |
| 26140 | 25198 | try sema.errNote(src_loc, msg, "only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible", .{}); |
| 26141 | 25199 | }, |
| 26142 | .@"fn" => { | |
| 26143 | if (position != .other) { | |
| 26144 | try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); | |
| 26145 | try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); | |
| 26146 | return; | |
| 26147 | } | |
| 26148 | switch (ty.fnCallingConvention(zcu)) { | |
| 26149 | .auto => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}), | |
| 26150 | .async => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}), | |
| 26151 | .@"inline" => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}), | |
| 26152 | else => return, | |
| 26153 | } | |
| 25200 | .@"fn" => if (position != .other) { | |
| 25201 | try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); | |
| 25202 | try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); | |
| 25203 | } else switch (ty.fnCallingConvention(zcu)) { | |
| 25204 | .auto => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}), | |
| 25205 | else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}), | |
| 26154 | 25206 | }, |
| 26155 | 25207 | .@"enum" => { |
| 26156 | const tag_ty = ty.intTagType(zcu); | |
| 26157 | try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); | |
| 26158 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); | |
| 25208 | const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); | |
| 25209 | switch (enum_obj.int_tag_mode) { | |
| 25210 | .auto => { | |
| 25211 | try sema.errNote(ty.srcLoc(zcu), msg, "integer tag type of enum is inferred", .{}); | |
| 25212 | try sema.errNote(ty.srcLoc(zcu), msg, "consider explicitly specifying the integer tag type", .{}); | |
| 25213 | }, | |
| 25214 | .explicit => { | |
| 25215 | const tag_ty: Type = .fromInterned(enum_obj.int_tag_type); | |
| 25216 | try sema.errNote(ty.srcLoc(zcu), msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); | |
| 25217 | try sema.explainWhyTypeIsNotExtern(msg, ty.srcLoc(zcu), tag_ty, position); | |
| 25218 | }, | |
| 25219 | } | |
| 26159 | 25220 | }, |
| 26160 | .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}), | |
| 26161 | .@"union" => try sema.errNote(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}), | |
| 26162 | .array => { | |
| 26163 | if (position == .ret_ty) { | |
| 26164 | return sema.errNote(src_loc, msg, "arrays are not allowed as a return type", .{}); | |
| 26165 | } else if (position == .param_ty) { | |
| 26166 | return sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}); | |
| 25221 | .@"struct" => { | |
| 25222 | const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); | |
| 25223 | switch (struct_obj.layout) { | |
| 25224 | .auto => try sema.errNote(src_loc, msg, "struct with automatic layout has no guaranteed in-memory representation", .{}), | |
| 25225 | .@"extern" => unreachable, | |
| 25226 | .@"packed" => switch (struct_obj.packed_backing_mode) { | |
| 25227 | .auto => try sema.errNote(src_loc, msg, "inferred backing integer of packed struct has unspecified signedness", .{}), | |
| 25228 | .explicit => { | |
| 25229 | const backing_int_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); | |
| 25230 | try sema.errNote(src_loc, msg, "packed struct backing integer type '{f}' is not extern compatible", .{backing_int_ty.fmt(pt)}); | |
| 25231 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, backing_int_ty, position); | |
| 25232 | }, | |
| 25233 | }, | |
| 26167 | 25234 | } |
| 26168 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(zcu), .element); | |
| 26169 | 25235 | }, |
| 26170 | .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(zcu), .element), | |
| 26171 | .optional => try sema.errNote(src_loc, msg, "only pointer like optionals are extern compatible", .{}), | |
| 26172 | } | |
| 26173 | } | |
| 26174 | ||
| 26175 | /// Returns true if `ty` is allowed in packed types. | |
| 26176 | /// Does not require `ty` to be resolved in any way, but may resolve whether it is comptime-only. | |
| 26177 | fn validatePackedType(sema: *Sema, ty: Type) !bool { | |
| 26178 | const pt = sema.pt; | |
| 26179 | const zcu = pt.zcu; | |
| 26180 | return switch (ty.zigTypeTag(zcu)) { | |
| 26181 | .type, | |
| 26182 | .comptime_float, | |
| 26183 | .comptime_int, | |
| 26184 | .enum_literal, | |
| 26185 | .undefined, | |
| 26186 | .null, | |
| 26187 | .error_union, | |
| 26188 | .error_set, | |
| 26189 | .frame, | |
| 26190 | .noreturn, | |
| 26191 | .@"opaque", | |
| 26192 | .@"anyframe", | |
| 26193 | .@"fn", | |
| 26194 | .array, | |
| 26195 | => false, | |
| 26196 | .optional => return ty.isPtrLikeOptional(zcu), | |
| 26197 | .void, | |
| 26198 | .bool, | |
| 26199 | .float, | |
| 26200 | .int, | |
| 26201 | .vector, | |
| 26202 | => true, | |
| 26203 | .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).tag_mode) { | |
| 26204 | .auto => false, | |
| 26205 | .explicit, .nonexhaustive => true, | |
| 25236 | .@"union" => { | |
| 25237 | const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); | |
| 25238 | switch (union_obj.layout) { | |
| 25239 | .auto => try sema.errNote(src_loc, msg, "union with automatic layout has no guaranteed in-memory representation", .{}), | |
| 25240 | .@"extern" => unreachable, | |
| 25241 | .@"packed" => switch (union_obj.packed_backing_mode) { | |
| 25242 | .auto => try sema.errNote(src_loc, msg, "inferred backing integer of packed union has unspecified signedness", .{}), | |
| 25243 | .explicit => { | |
| 25244 | const backing_int_ty: Type = .fromInterned(union_obj.packed_backing_int_type); | |
| 25245 | try sema.errNote(src_loc, msg, "packed union backing integer type '{f}' is not extern compatible", .{backing_int_ty.fmt(pt)}); | |
| 25246 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, backing_int_ty, position); | |
| 25247 | }, | |
| 25248 | }, | |
| 25249 | } | |
| 26206 | 25250 | }, |
| 26207 | .pointer => !ty.isSlice(zcu) and !try ty.comptimeOnlySema(pt), | |
| 26208 | .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", | |
| 26209 | }; | |
| 25251 | .array => switch (position) { | |
| 25252 | .ret_ty => try sema.errNote(src_loc, msg, "arrays are not allowed as a return type", .{}), | |
| 25253 | .param_ty => try sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}), | |
| 25254 | else => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element), | |
| 25255 | }, | |
| 25256 | .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element), | |
| 25257 | .optional => try sema.errNote(src_loc, msg, "non-pointer optionals have no guaranteed in-memory representation", .{}), | |
| 25258 | } | |
| 26210 | 25259 | } |
| 26211 | 25260 | |
| 26212 | fn explainWhyTypeIsNotPacked( | |
| 25261 | pub fn explainWhyTypeIsUnpackable( | |
| 26213 | 25262 | sema: *Sema, |
| 26214 | 25263 | msg: *Zcu.ErrorMsg, |
| 26215 | src_loc: LazySrcLoc, | |
| 26216 | ty: Type, | |
| 25264 | src: LazySrcLoc, | |
| 25265 | reason: Type.UnpackableReason, | |
| 26217 | 25266 | ) CompileError!void { |
| 26218 | 25267 | const pt = sema.pt; |
| 26219 | 25268 | const zcu = pt.zcu; |
| 26220 | switch (ty.zigTypeTag(zcu)) { | |
| 26221 | .void, | |
| 26222 | .bool, | |
| 26223 | .float, | |
| 26224 | .int, | |
| 26225 | .vector, | |
| 26226 | .@"enum", | |
| 26227 | => return, | |
| 26228 | .type, | |
| 26229 | .comptime_float, | |
| 26230 | .comptime_int, | |
| 26231 | .enum_literal, | |
| 26232 | .undefined, | |
| 26233 | .null, | |
| 26234 | .frame, | |
| 26235 | .noreturn, | |
| 26236 | .@"opaque", | |
| 26237 | .error_union, | |
| 26238 | .error_set, | |
| 26239 | .@"anyframe", | |
| 26240 | .optional, | |
| 26241 | .array, | |
| 26242 | => try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}), | |
| 26243 | .pointer => if (ty.isSlice(zcu)) { | |
| 26244 | try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); | |
| 26245 | } else { | |
| 26246 | try sema.errNote(src_loc, msg, "comptime-only pointer has no guaranteed in-memory representation", .{}); | |
| 26247 | try sema.explainWhyTypeIsComptime(msg, src_loc, ty); | |
| 25269 | switch (reason) { | |
| 25270 | .comptime_only => try sema.errNote(src, msg, "comptime-only types have no bit-packed representation", .{}), | |
| 25271 | .pointer => { | |
| 25272 | try sema.errNote(src, msg, "pointers cannot be directly bitpacked", .{}); | |
| 25273 | try sema.errNote(src, msg, "consider using 'usize' and '@intFromPtr'", .{}); | |
| 26248 | 25274 | }, |
| 26249 | .@"fn" => { | |
| 26250 | try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); | |
| 26251 | try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); | |
| 25275 | .enum_inferred_int_tag => |enum_ty| { | |
| 25276 | const enum_src = enum_ty.srcLoc(zcu); | |
| 25277 | try sema.errNote(enum_src, msg, "integer tag type of enum is inferred", .{}); | |
| 25278 | try sema.errNote(enum_src, msg, "consider explicitly specifying the integer tag type", .{}); | |
| 25279 | }, | |
| 25280 | .non_packed_struct => |struct_ty| { | |
| 25281 | try sema.errNote(src, msg, "non-packed structs do not have a bit-packed representation", .{}); | |
| 25282 | try sema.addDeclaredHereNote(msg, struct_ty); | |
| 25283 | }, | |
| 25284 | .non_packed_union => |union_ty| { | |
| 25285 | try sema.errNote(src, msg, "non-packed unions do not have a bit-packed representation", .{}); | |
| 25286 | try sema.addDeclaredHereNote(msg, union_ty); | |
| 26252 | 25287 | }, |
| 26253 | .@"struct" => try sema.errNote(src_loc, msg, "only packed structs layout are allowed in packed types", .{}), | |
| 26254 | .@"union" => try sema.errNote(src_loc, msg, "only packed unions layout are allowed in packed types", .{}), | |
| 25288 | .slice => try sema.errNote(src, msg, "slices do not have a bit-packed representation", .{}), | |
| 25289 | .other => try sema.errNote(src, msg, "type does not have a bit-packed representation", .{}), | |
| 26255 | 25290 | } |
| 26256 | 25291 | } |
| 26257 | 25292 | |
| ... | ... | @@ -26277,7 +25312,14 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In |
| 26277 | 25312 | try sema.ensureMemoizedStateResolved(src, .panic); |
| 26278 | 25313 | const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); |
| 26279 | 25314 | switch (sema.owner.unwrap()) { |
| 26280 | .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, | |
| 25315 | .@"comptime", | |
| 25316 | .nav_ty, | |
| 25317 | .nav_val, | |
| 25318 | .type_layout, | |
| 25319 | .struct_defaults, | |
| 25320 | .memoized_state, | |
| 25321 | => {}, | |
| 25322 | ||
| 26281 | 25323 | .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true), |
| 26282 | 25324 | } |
| 26283 | 25325 | return panic_fn_index; |
| ... | ... | @@ -26297,7 +25339,7 @@ fn addSafetyCheck( |
| 26297 | 25339 | .parent = parent_block, |
| 26298 | 25340 | .sema = sema, |
| 26299 | 25341 | .namespace = parent_block.namespace, |
| 26300 | .instructions = .{}, | |
| 25342 | .instructions = .empty, | |
| 26301 | 25343 | .inlining = parent_block.inlining, |
| 26302 | 25344 | .comptime_reason = null, |
| 26303 | 25345 | .src_base_inst = parent_block.src_base_inst, |
| ... | ... | @@ -26391,7 +25433,7 @@ fn addSafetyCheckUnwrapError( |
| 26391 | 25433 | .parent = parent_block, |
| 26392 | 25434 | .sema = sema, |
| 26393 | 25435 | .namespace = parent_block.namespace, |
| 26394 | .instructions = .{}, | |
| 25436 | .instructions = .empty, | |
| 26395 | 25437 | .inlining = parent_block.inlining, |
| 26396 | 25438 | .comptime_reason = null, |
| 26397 | 25439 | .src_base_inst = parent_block.src_base_inst, |
| ... | ... | @@ -26458,21 +25500,39 @@ fn addSafetyCheckSentinelMismatch( |
| 26458 | 25500 | const expected_sentinel = Air.internedToRef(expected_sentinel_val.toIntern()); |
| 26459 | 25501 | |
| 26460 | 25502 | const ptr_ty = sema.typeOf(ptr); |
| 26461 | const actual_sentinel = if (ptr_ty.isSlice(zcu)) | |
| 26462 | try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index) | |
| 26463 | else blk: { | |
| 26464 | const elem_ptr_ty = try ptr_ty.elemPtrType(null, pt); | |
| 26465 | const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty); | |
| 26466 | break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr); | |
| 26467 | }; | |
| 26468 | ||
| 26469 | const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: { | |
| 26470 | const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq); | |
| 26471 | break :ok try parent_block.addReduce(eql, .And); | |
| 26472 | } else ok: { | |
| 26473 | assert(sentinel_ty.isSelfComparable(zcu, true)); | |
| 26474 | break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); | |
| 25503 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 25504 | const actual_sentinel: Air.Inst.Ref = switch (ptr_ty.ptrSize(zcu)) { | |
| 25505 | .slice => try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index), | |
| 25506 | .one => s: { | |
| 25507 | const array_ty: Type = .fromInterned(ptr_info.child); | |
| 25508 | assert(array_ty.zigTypeTag(zcu) == .array); | |
| 25509 | assert(array_ty.childType(zcu).toIntern() == sentinel_ty.toIntern()); | |
| 25510 | const many_ptr_ty = try pt.ptrType(.{ | |
| 25511 | .child = sentinel_ty.toIntern(), | |
| 25512 | .flags = .{ | |
| 25513 | .size = .many, | |
| 25514 | .is_const = ptr_info.flags.is_const, | |
| 25515 | .is_volatile = ptr_info.flags.is_volatile, | |
| 25516 | .is_allowzero = ptr_info.flags.is_allowzero, | |
| 25517 | .alignment = switch (ptr_info.flags.alignment) { | |
| 25518 | .none => .none, | |
| 25519 | else => |ptr_align| .minStrict(ptr_align, sentinel_ty.abiAlignment(zcu)), | |
| 25520 | }, | |
| 25521 | .address_space = ptr_info.flags.address_space, | |
| 25522 | }, | |
| 25523 | }); | |
| 25524 | const many_ptr = try parent_block.addBitCast(many_ptr_ty, ptr); | |
| 25525 | break :s try parent_block.addBinOp(.ptr_elem_val, many_ptr, sentinel_index); | |
| 25526 | }, | |
| 25527 | .many => unreachable, | |
| 25528 | .c => unreachable, | |
| 26475 | 25529 | }; |
| 25530 | assert(sema.typeOf(actual_sentinel).toIntern() == sentinel_ty.toIntern()); | |
| 25531 | assert(sentinel_ty.isSelfComparable(zcu, true)); | |
| 25532 | const ok: Air.Inst.Ref = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: { | |
| 25533 | const elementwise = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq); | |
| 25534 | break :ok try parent_block.addReduce(elementwise, .And); | |
| 25535 | } else try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); | |
| 26476 | 25536 | |
| 26477 | 25537 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{ |
| 26478 | 25538 | expected_sentinel, actual_sentinel, |
| ... | ... | @@ -26496,7 +25556,7 @@ fn addSafetyCheckCall( |
| 26496 | 25556 | .parent = parent_block, |
| 26497 | 25557 | .sema = sema, |
| 26498 | 25558 | .namespace = parent_block.namespace, |
| 26499 | .instructions = .{}, | |
| 25559 | .instructions = .empty, | |
| 26500 | 25560 | .inlining = parent_block.inlining, |
| 26501 | 25561 | .comptime_reason = null, |
| 26502 | 25562 | .src_base_inst = parent_block.src_base_inst, |
| ... | ... | @@ -26554,8 +25614,10 @@ fn fieldPtrLoad( |
| 26554 | 25614 | const pt = sema.pt; |
| 26555 | 25615 | const zcu = pt.zcu; |
| 26556 | 25616 | const object_ptr_ty = sema.typeOf(object_ptr); |
| 25617 | assert(object_ptr_ty.zigTypeTag(zcu) == .pointer); | |
| 26557 | 25618 | const pointee_ty = object_ptr_ty.childType(zcu); |
| 26558 | if (try typeHasOnePossibleValue(sema, pointee_ty)) |opv| { | |
| 25619 | try sema.ensureLayoutResolved(pointee_ty, src, .ptr_access); | |
| 25620 | if (try pointee_ty.onePossibleValue(pt)) |opv| { | |
| 26559 | 25621 | const object: Air.Inst.Ref = .fromValue(opv); |
| 26560 | 25622 | return fieldVal(sema, block, src, object, field_name, field_name_src); |
| 26561 | 25623 | } |
| ... | ... | @@ -26603,7 +25665,7 @@ fn fieldVal( |
| 26603 | 25665 | return Air.internedToRef((try pt.intValue(.usize, inner_ty.arrayLen(zcu))).toIntern()); |
| 26604 | 25666 | } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { |
| 26605 | 25667 | const ptr_info = object_ty.ptrInfo(zcu); |
| 26606 | const result_ty = try pt.ptrTypeSema(.{ | |
| 25668 | const result_ty = try pt.ptrType(.{ | |
| 26607 | 25669 | .child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(), |
| 26608 | 25670 | .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none, |
| 26609 | 25671 | .flags = .{ |
| ... | ... | @@ -26663,37 +25725,34 @@ fn fieldVal( |
| 26663 | 25725 | |
| 26664 | 25726 | switch (child_type.zigTypeTag(zcu)) { |
| 26665 | 25727 | .error_set => { |
| 26666 | switch (ip.indexToKey(child_type.toIntern())) { | |
| 26667 | .error_set_type => |error_set_type| blk: { | |
| 26668 | if (error_set_type.nameIndex(ip, field_name) != null) break :blk; | |
| 25728 | const err_set_ty: Type = err_set: switch (ip.indexToKey(child_type.toIntern())) { | |
| 25729 | .inferred_error_set_type => |func_index| { | |
| 25730 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 25731 | const resolved_ies = ip.funcIesResolvedUnordered(func_index); | |
| 25732 | continue :err_set ip.indexToKey(resolved_ies); | |
| 25733 | }, | |
| 25734 | .error_set_type => |err_set| if (err_set.nameIndex(ip, field_name) == null) { | |
| 26669 | 25735 | return sema.fail(block, src, "no error named '{f}' in '{f}'", .{ |
| 26670 | 25736 | field_name.fmt(ip), child_type.fmt(pt), |
| 26671 | 25737 | }); |
| 26672 | }, | |
| 26673 | .inferred_error_set_type => { | |
| 26674 | return sema.fail(block, src, "TODO handle inferred error sets here", .{}); | |
| 26675 | }, | |
| 25738 | } else child_type, | |
| 26676 | 25739 | .simple_type => |t| { |
| 26677 | 25740 | assert(t == .anyerror); |
| 26678 | 25741 | _ = try pt.getErrorValue(field_name); |
| 25742 | break :err_set try pt.singleErrorSetType(field_name); | |
| 26679 | 25743 | }, |
| 26680 | 25744 | else => unreachable, |
| 26681 | } | |
| 26682 | ||
| 26683 | const error_set_type = if (!child_type.isAnyError(zcu)) | |
| 26684 | child_type | |
| 26685 | else | |
| 26686 | try pt.singleErrorSetType(field_name); | |
| 26687 | return Air.internedToRef((try pt.intern(.{ .err = .{ | |
| 26688 | .ty = error_set_type.toIntern(), | |
| 25745 | }; | |
| 25746 | return .fromIntern(try pt.intern(.{ .err = .{ | |
| 25747 | .ty = err_set_ty.toIntern(), | |
| 26689 | 25748 | .name = field_name, |
| 26690 | } }))); | |
| 25749 | } })); | |
| 26691 | 25750 | }, |
| 26692 | 25751 | .@"union" => { |
| 26693 | 25752 | if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { |
| 26694 | 25753 | return inst; |
| 26695 | 25754 | } |
| 26696 | try child_type.resolveFields(pt); | |
| 25755 | try sema.ensureLayoutResolved(child_type, src, .field_used); | |
| 26697 | 25756 | if (child_type.unionTagType(zcu)) |enum_ty| { |
| 26698 | 25757 | if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index_usize| { |
| 26699 | 25758 | const field_index: u32 = @intCast(field_index_usize); |
| ... | ... | @@ -26706,6 +25765,7 @@ fn fieldVal( |
| 26706 | 25765 | if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { |
| 26707 | 25766 | return inst; |
| 26708 | 25767 | } |
| 25768 | try sema.ensureLayoutResolved(child_type, src, .field_used); | |
| 26709 | 25769 | const field_index_usize = child_type.enumFieldIndex(field_name, zcu) orelse |
| 26710 | 25770 | return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); |
| 26711 | 25771 | const field_index: u32 = @intCast(field_index_usize); |
| ... | ... | @@ -26731,13 +25791,15 @@ fn fieldVal( |
| 26731 | 25791 | }, |
| 26732 | 25792 | .@"struct" => if (is_pointer_to) { |
| 26733 | 25793 | // Avoid loading the entire struct by fetching a pointer and loading that |
| 26734 | const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); | |
| 25794 | try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); | |
| 25795 | const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty); | |
| 26735 | 25796 | return sema.analyzeLoad(block, src, field_ptr, object_src); |
| 26736 | 25797 | } else { |
| 26737 | 25798 | return sema.structFieldVal(block, object, field_name, field_name_src, inner_ty); |
| 26738 | 25799 | }, |
| 26739 | 25800 | .@"union" => if (is_pointer_to) { |
| 26740 | 25801 | // Avoid loading the entire union by fetching a pointer and loading that |
| 25802 | try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); | |
| 26741 | 25803 | const field_ptr = try sema.unionFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); |
| 26742 | 25804 | return sema.analyzeLoad(block, src, field_ptr, object_src); |
| 26743 | 25805 | } else { |
| ... | ... | @@ -26784,10 +25846,10 @@ fn fieldPtr( |
| 26784 | 25846 | .array => { |
| 26785 | 25847 | if (field_name.eqlSlice("len", ip)) { |
| 26786 | 25848 | const int_val = try pt.intValue(.usize, inner_ty.arrayLen(zcu)); |
| 26787 | return uavRef(sema, int_val.toIntern()); | |
| 25849 | return uavRef(sema, int_val); | |
| 26788 | 25850 | } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { |
| 26789 | 25851 | const ptr_info = object_ty.ptrInfo(zcu); |
| 26790 | const new_ptr_ty = try pt.ptrTypeSema(.{ | |
| 25852 | const new_ptr_ty = try pt.ptrType(.{ | |
| 26791 | 25853 | .child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(), |
| 26792 | 25854 | .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none, |
| 26793 | 25855 | .flags = .{ |
| ... | ... | @@ -26802,10 +25864,11 @@ fn fieldPtr( |
| 26802 | 25864 | .packed_offset = ptr_info.packed_offset, |
| 26803 | 25865 | }); |
| 26804 | 25866 | const ptr_ptr_info = object_ptr_ty.ptrInfo(zcu); |
| 26805 | const result_ty = try pt.ptrTypeSema(.{ | |
| 25867 | const result_ty = try pt.ptrType(.{ | |
| 26806 | 25868 | .child = new_ptr_ty.toIntern(), |
| 26807 | 25869 | .sentinel = if (object_ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none, |
| 26808 | 25870 | .flags = .{ |
| 25871 | .size = .one, | |
| 26809 | 25872 | .alignment = ptr_ptr_info.flags.alignment, |
| 26810 | 25873 | .is_const = ptr_ptr_info.flags.is_const, |
| 26811 | 25874 | .is_volatile = ptr_ptr_info.flags.is_volatile, |
| ... | ... | @@ -26836,7 +25899,7 @@ fn fieldPtr( |
| 26836 | 25899 | if (field_name.eqlSlice("ptr", ip)) { |
| 26837 | 25900 | const slice_ptr_ty = inner_ty.slicePtrFieldType(zcu); |
| 26838 | 25901 | |
| 26839 | const result_ty = try pt.ptrTypeSema(.{ | |
| 25902 | const result_ty = try pt.ptrType(.{ | |
| 26840 | 25903 | .child = slice_ptr_ty.toIntern(), |
| 26841 | 25904 | .flags = .{ |
| 26842 | 25905 | .is_const = !attr_ptr_ty.ptrIsMutable(zcu), |
| ... | ... | @@ -26854,7 +25917,7 @@ fn fieldPtr( |
| 26854 | 25917 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 26855 | 25918 | return field_ptr; |
| 26856 | 25919 | } else if (field_name.eqlSlice("len", ip)) { |
| 26857 | const result_ty = try pt.ptrTypeSema(.{ | |
| 25920 | const result_ty = try pt.ptrType(.{ | |
| 26858 | 25921 | .child = .usize_type, |
| 26859 | 25922 | .flags = .{ |
| 26860 | 25923 | .is_const = !attr_ptr_ty.ptrIsMutable(zcu), |
| ... | ... | @@ -26881,7 +25944,6 @@ fn fieldPtr( |
| 26881 | 25944 | } |
| 26882 | 25945 | }, |
| 26883 | 25946 | .type => { |
| 26884 | _ = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, object_ptr, undefined); | |
| 26885 | 25947 | const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src); |
| 26886 | 25948 | const inner = if (is_pointer_to) |
| 26887 | 25949 | try sema.analyzeLoad(block, src, result, object_ptr_src) |
| ... | ... | @@ -26893,44 +25955,39 @@ fn fieldPtr( |
| 26893 | 25955 | |
| 26894 | 25956 | switch (child_type.zigTypeTag(zcu)) { |
| 26895 | 25957 | .error_set => { |
| 26896 | switch (ip.indexToKey(child_type.toIntern())) { | |
| 26897 | .error_set_type => |error_set_type| blk: { | |
| 26898 | if (error_set_type.nameIndex(ip, field_name) != null) { | |
| 26899 | break :blk; | |
| 26900 | } | |
| 25958 | const err_set_ty: Type = err_set: switch (ip.indexToKey(child_type.toIntern())) { | |
| 25959 | .inferred_error_set_type => |func_index| { | |
| 25960 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 25961 | const resolved_ies = ip.funcIesResolvedUnordered(func_index); | |
| 25962 | continue :err_set ip.indexToKey(resolved_ies); | |
| 25963 | }, | |
| 25964 | .error_set_type => |err_set| if (err_set.nameIndex(ip, field_name) == null) { | |
| 26901 | 25965 | return sema.fail(block, src, "no error named '{f}' in '{f}'", .{ |
| 26902 | 25966 | field_name.fmt(ip), child_type.fmt(pt), |
| 26903 | 25967 | }); |
| 26904 | }, | |
| 26905 | .inferred_error_set_type => { | |
| 26906 | return sema.fail(block, src, "TODO handle inferred error sets here", .{}); | |
| 26907 | }, | |
| 25968 | } else child_type, | |
| 26908 | 25969 | .simple_type => |t| { |
| 26909 | 25970 | assert(t == .anyerror); |
| 26910 | 25971 | _ = try pt.getErrorValue(field_name); |
| 25972 | break :err_set try pt.singleErrorSetType(field_name); | |
| 26911 | 25973 | }, |
| 26912 | 25974 | else => unreachable, |
| 26913 | } | |
| 26914 | ||
| 26915 | const error_set_type = if (!child_type.isAnyError(zcu)) | |
| 26916 | child_type | |
| 26917 | else | |
| 26918 | try pt.singleErrorSetType(field_name); | |
| 26919 | return uavRef(sema, try pt.intern(.{ .err = .{ | |
| 26920 | .ty = error_set_type.toIntern(), | |
| 25975 | }; | |
| 25976 | return uavRef(sema, .fromInterned(try pt.intern(.{ .err = .{ | |
| 25977 | .ty = err_set_ty.toIntern(), | |
| 26921 | 25978 | .name = field_name, |
| 26922 | } })); | |
| 25979 | } }))); | |
| 26923 | 25980 | }, |
| 26924 | 25981 | .@"union" => { |
| 26925 | 25982 | if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { |
| 26926 | 25983 | return inst; |
| 26927 | 25984 | } |
| 26928 | try child_type.resolveFields(pt); | |
| 25985 | try sema.ensureLayoutResolved(child_type, src, .field_used); | |
| 26929 | 25986 | if (child_type.unionTagType(zcu)) |enum_ty| { |
| 26930 | 25987 | if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| { |
| 26931 | 25988 | const field_index_u32: u32 = @intCast(field_index); |
| 26932 | 25989 | const idx_val = try pt.enumValueFieldIndex(enum_ty, field_index_u32); |
| 26933 | return uavRef(sema, idx_val.toIntern()); | |
| 25990 | return uavRef(sema, idx_val); | |
| 26934 | 25991 | } |
| 26935 | 25992 | } |
| 26936 | 25993 | return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); |
| ... | ... | @@ -26939,12 +25996,13 @@ fn fieldPtr( |
| 26939 | 25996 | if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { |
| 26940 | 25997 | return inst; |
| 26941 | 25998 | } |
| 25999 | try sema.ensureLayoutResolved(child_type, src, .field_used); | |
| 26942 | 26000 | const field_index = child_type.enumFieldIndex(field_name, zcu) orelse { |
| 26943 | 26001 | return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); |
| 26944 | 26002 | }; |
| 26945 | 26003 | const field_index_u32: u32 = @intCast(field_index); |
| 26946 | 26004 | const idx_val = try pt.enumValueFieldIndex(child_type, field_index_u32); |
| 26947 | return uavRef(sema, idx_val.toIntern()); | |
| 26005 | return uavRef(sema, idx_val); | |
| 26948 | 26006 | }, |
| 26949 | 26007 | .@"struct", .@"opaque" => { |
| 26950 | 26008 | if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { |
| ... | ... | @@ -26960,7 +26018,8 @@ fn fieldPtr( |
| 26960 | 26018 | try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) |
| 26961 | 26019 | else |
| 26962 | 26020 | object_ptr; |
| 26963 | const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); | |
| 26021 | try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); | |
| 26022 | const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty); | |
| 26964 | 26023 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 26965 | 26024 | return field_ptr; |
| 26966 | 26025 | }, |
| ... | ... | @@ -26969,6 +26028,7 @@ fn fieldPtr( |
| 26969 | 26028 | try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) |
| 26970 | 26029 | else |
| 26971 | 26030 | object_ptr; |
| 26031 | try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); | |
| 26972 | 26032 | const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); |
| 26973 | 26033 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 26974 | 26034 | return field_ptr; |
| ... | ... | @@ -27012,6 +26072,7 @@ fn fieldCallBind( |
| 27012 | 26072 | // Optionally dereference a second pointer to get the concrete type. |
| 27013 | 26073 | const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one; |
| 27014 | 26074 | const concrete_ty = if (is_double_ptr) inner_ty.childType(zcu) else inner_ty; |
| 26075 | try sema.ensureLayoutResolved(concrete_ty, src, .ptr_access); | |
| 27015 | 26076 | const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; |
| 27016 | 26077 | const object_ptr = if (is_double_ptr) |
| 27017 | 26078 | try sema.analyzeLoad(block, src, raw_ptr, src) |
| ... | ... | @@ -27021,10 +26082,8 @@ fn fieldCallBind( |
| 27021 | 26082 | find_field: { |
| 27022 | 26083 | switch (concrete_ty.zigTypeTag(zcu)) { |
| 27023 | 26084 | .@"struct" => { |
| 27024 | try concrete_ty.resolveFields(pt); | |
| 27025 | 26085 | if (zcu.typeToStruct(concrete_ty)) |struct_type| { |
| 27026 | const field_index = struct_type.nameIndex(ip, field_name) orelse | |
| 27027 | break :find_field; | |
| 26086 | const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field; | |
| 27028 | 26087 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 27029 | 26088 | |
| 27030 | 26089 | return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr); |
| ... | ... | @@ -27047,9 +26106,9 @@ fn fieldCallBind( |
| 27047 | 26106 | } |
| 27048 | 26107 | }, |
| 27049 | 26108 | .@"union" => { |
| 27050 | try concrete_ty.resolveFields(pt); | |
| 27051 | 26109 | const union_obj = zcu.typeToUnion(concrete_ty).?; |
| 27052 | _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field; | |
| 26110 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | |
| 26111 | if (enum_obj.nameIndex(ip, field_name) == null) break :find_field; | |
| 27053 | 26112 | const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false); |
| 27054 | 26113 | return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) }; |
| 27055 | 26114 | }, |
| ... | ... | @@ -27163,7 +26222,7 @@ fn finishFieldCallBind( |
| 27163 | 26222 | ) CompileError!ResolvedFieldCallee { |
| 27164 | 26223 | const pt = sema.pt; |
| 27165 | 26224 | const zcu = pt.zcu; |
| 27166 | const ptr_field_ty = try pt.ptrTypeSema(.{ | |
| 26225 | const ptr_field_ty = try pt.ptrType(.{ | |
| 27167 | 26226 | .child = field_ty.toIntern(), |
| 27168 | 26227 | .flags = .{ |
| 27169 | 26228 | .is_const = !ptr_ty.ptrIsMutable(zcu), |
| ... | ... | @@ -27174,7 +26233,6 @@ fn finishFieldCallBind( |
| 27174 | 26233 | const container_ty = ptr_ty.childType(zcu); |
| 27175 | 26234 | if (container_ty.zigTypeTag(zcu) == .@"struct") { |
| 27176 | 26235 | if (container_ty.structFieldIsComptime(field_index, zcu)) { |
| 27177 | try container_ty.resolveStructFieldInits(pt); | |
| 27178 | 26236 | const default_val = (try container_ty.structFieldValueComptime(pt, field_index)).?; |
| 27179 | 26237 | return .{ .direct = Air.internedToRef(default_val.toIntern()) }; |
| 27180 | 26238 | } |
| ... | ... | @@ -27239,6 +26297,7 @@ fn namespaceLookupVal( |
| 27239 | 26297 | return try sema.analyzeNavVal(block, src, nav); |
| 27240 | 26298 | } |
| 27241 | 26299 | |
| 26300 | /// Asserts that the layout of `struct_ty` is already resolved. | |
| 27242 | 26301 | fn structFieldPtr( |
| 27243 | 26302 | sema: *Sema, |
| 27244 | 26303 | block: *Block, |
| ... | ... | @@ -27247,33 +26306,33 @@ fn structFieldPtr( |
| 27247 | 26306 | field_name: InternPool.NullTerminatedString, |
| 27248 | 26307 | field_name_src: LazySrcLoc, |
| 27249 | 26308 | struct_ty: Type, |
| 27250 | initializing: bool, | |
| 27251 | 26309 | ) CompileError!Air.Inst.Ref { |
| 27252 | 26310 | const pt = sema.pt; |
| 27253 | 26311 | const zcu = pt.zcu; |
| 27254 | 26312 | const ip = &zcu.intern_pool; |
| 27255 | assert(struct_ty.zigTypeTag(zcu) == .@"struct"); | |
| 27256 | 26313 | |
| 27257 | try struct_ty.resolveFields(pt); | |
| 27258 | try struct_ty.resolveLayout(pt); | |
| 26314 | assert(struct_ty.zigTypeTag(zcu) == .@"struct"); | |
| 26315 | struct_ty.assertHasLayout(zcu); | |
| 27259 | 26316 | |
| 27260 | if (struct_ty.isTuple(zcu)) { | |
| 26317 | const field_index: u32 = if (struct_ty.isTuple(zcu)) field_index: { | |
| 27261 | 26318 | if (field_name.eqlSlice("len", ip)) { |
| 27262 | 26319 | const len_inst = try pt.intRef(.usize, struct_ty.structFieldCount(zcu)); |
| 27263 | return sema.analyzeRef(block, src, len_inst); | |
| 26320 | return sema.analyzeRef(block, src, len_inst, .none); | |
| 27264 | 26321 | } |
| 27265 | const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); | |
| 27266 | return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing); | |
| 27267 | } | |
| 27268 | ||
| 27269 | const struct_type = zcu.typeToStruct(struct_ty).?; | |
| 27270 | ||
| 27271 | const field_index = struct_type.nameIndex(ip, field_name) orelse | |
| 27272 | return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); | |
| 26322 | break :field_index try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); | |
| 26323 | } else field_index: { | |
| 26324 | const struct_type = zcu.typeToStruct(struct_ty).?; | |
| 26325 | break :field_index struct_type.nameIndex(ip, field_name) orelse { | |
| 26326 | return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); | |
| 26327 | }; | |
| 26328 | }; | |
| 27273 | 26329 | |
| 27274 | 26330 | return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_ty); |
| 27275 | 26331 | } |
| 27276 | 26332 | |
| 26333 | /// Supports both structs and unions. | |
| 26334 | /// | |
| 26335 | /// Asserts that the layout of `struct_ty` is already resolved. | |
| 27277 | 26336 | fn structFieldPtrByIndex( |
| 27278 | 26337 | sema: *Sema, |
| 27279 | 26338 | block: *Block, |
| ... | ... | @@ -27284,79 +26343,24 @@ fn structFieldPtrByIndex( |
| 27284 | 26343 | ) CompileError!Air.Inst.Ref { |
| 27285 | 26344 | const pt = sema.pt; |
| 27286 | 26345 | const zcu = pt.zcu; |
| 27287 | const ip = &zcu.intern_pool; | |
| 27288 | ||
| 27289 | const struct_type = zcu.typeToStruct(struct_ty).?; | |
| 27290 | const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); | |
| 27291 | 26346 | |
| 27292 | // Comptime fields are handled later | |
| 27293 | if (!field_is_comptime) { | |
| 27294 | if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { | |
| 27295 | const val = try struct_ptr_val.ptrField(field_index, pt); | |
| 27296 | return Air.internedToRef(val.toIntern()); | |
| 27297 | } | |
| 27298 | } | |
| 27299 | ||
| 27300 | const field_ty = struct_type.field_types.get(ip)[field_index]; | |
| 26347 | struct_ty.assertHasLayout(zcu); | |
| 27301 | 26348 | const struct_ptr_ty = sema.typeOf(struct_ptr); |
| 27302 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); | |
| 27303 | ||
| 27304 | var ptr_ty_data: InternPool.Key.PtrType = .{ | |
| 27305 | .child = field_ty, | |
| 27306 | .flags = .{ | |
| 27307 | .is_const = struct_ptr_ty_info.flags.is_const, | |
| 27308 | .is_volatile = struct_ptr_ty_info.flags.is_volatile, | |
| 27309 | .address_space = struct_ptr_ty_info.flags.address_space, | |
| 27310 | }, | |
| 27311 | }; | |
| 27312 | 26349 | |
| 27313 | const parent_align = if (struct_ptr_ty_info.flags.alignment != .none) | |
| 27314 | struct_ptr_ty_info.flags.alignment | |
| 27315 | else | |
| 27316 | try Type.fromInterned(struct_ptr_ty_info.child).abiAlignmentSema(pt); | |
| 27317 | ||
| 27318 | if (struct_type.layout == .@"packed") { | |
| 27319 | assert(!field_is_comptime); | |
| 27320 | const packed_offset = struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt); | |
| 27321 | ptr_ty_data.flags.alignment = parent_align; | |
| 27322 | ptr_ty_data.packed_offset = packed_offset; | |
| 27323 | } else if (struct_type.layout == .@"extern") { | |
| 27324 | assert(!field_is_comptime); | |
| 27325 | // For extern structs, field alignment might be bigger than type's | |
| 27326 | // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the | |
| 27327 | // second field is aligned as u32. | |
| 27328 | const field_offset = struct_ty.structFieldOffset(field_index, zcu); | |
| 27329 | ptr_ty_data.flags.alignment = if (parent_align == .none) | |
| 27330 | .none | |
| 27331 | else | |
| 27332 | @enumFromInt(@min(@intFromEnum(parent_align), @ctz(field_offset))); | |
| 26350 | if (struct_ty.structFieldIsComptime(field_index, zcu)) { | |
| 26351 | const field_ptr_ty = try struct_ptr_ty.fieldPtrType(field_index, pt); | |
| 26352 | return .fromIntern(try pt.intern(.{ .ptr = .{ | |
| 26353 | .ty = field_ptr_ty.toIntern(), | |
| 26354 | .base_addr = .{ .comptime_field = struct_ty.structFieldDefaultValue(field_index, zcu).?.toIntern() }, | |
| 26355 | .byte_offset = 0, | |
| 26356 | } })); | |
| 26357 | } else if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { | |
| 26358 | return .fromValue(try struct_ptr_val.ptrField(field_index, pt)); | |
| 27333 | 26359 | } else { |
| 27334 | // Our alignment is capped at the field alignment. | |
| 27335 | const field_align = try Type.fromInterned(field_ty).structFieldAlignmentSema( | |
| 27336 | struct_type.fieldAlign(ip, field_index), | |
| 27337 | struct_type.layout, | |
| 27338 | pt, | |
| 27339 | ); | |
| 27340 | ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none) | |
| 27341 | field_align | |
| 27342 | else | |
| 27343 | field_align.min(parent_align); | |
| 26360 | const field_ptr_ty = try struct_ptr_ty.fieldPtrType(field_index, pt); | |
| 26361 | return block.addStructFieldPtr(struct_ptr, field_index, field_ptr_ty); | |
| 27344 | 26362 | } |
| 27345 | ||
| 27346 | const ptr_field_ty = try pt.ptrTypeSema(ptr_ty_data); | |
| 27347 | ||
| 27348 | if (field_is_comptime) { | |
| 27349 | try struct_ty.resolveStructFieldInits(pt); | |
| 27350 | const val = try pt.intern(.{ .ptr = .{ | |
| 27351 | .ty = ptr_field_ty.toIntern(), | |
| 27352 | .base_addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] }, | |
| 27353 | .byte_offset = 0, | |
| 27354 | } }); | |
| 27355 | return Air.internedToRef(val); | |
| 27356 | } | |
| 27357 | ||
| 27358 | return block.addStructFieldPtr(struct_ptr, field_index, ptr_field_ty); | |
| 27359 | } | |
| 26363 | } | |
| 27360 | 26364 | |
| 27361 | 26365 | fn structFieldVal( |
| 27362 | 26366 | sema: *Sema, |
| ... | ... | @@ -27370,8 +26374,8 @@ fn structFieldVal( |
| 27370 | 26374 | const zcu = pt.zcu; |
| 27371 | 26375 | const ip = &zcu.intern_pool; |
| 27372 | 26376 | assert(struct_ty.zigTypeTag(zcu) == .@"struct"); |
| 27373 | ||
| 27374 | try struct_ty.resolveFields(pt); | |
| 26377 | assert(sema.typeOf(struct_byval).toIntern() == struct_ty.toIntern()); | |
| 26378 | struct_ty.assertHasLayout(zcu); | |
| 27375 | 26379 | |
| 27376 | 26380 | switch (ip.indexToKey(struct_ty.toIntern())) { |
| 27377 | 26381 | .struct_type => { |
| ... | ... | @@ -27379,24 +26383,19 @@ fn structFieldVal( |
| 27379 | 26383 | |
| 27380 | 26384 | const field_index = struct_type.nameIndex(ip, field_name) orelse |
| 27381 | 26385 | return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); |
| 27382 | if (struct_type.fieldIsComptime(ip, field_index)) { | |
| 27383 | try struct_ty.resolveStructFieldInits(pt); | |
| 27384 | return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); | |
| 26386 | if (struct_type.field_is_comptime_bits.get(ip, field_index)) { | |
| 26387 | return .fromIntern(struct_type.field_defaults.get(ip)[field_index]); | |
| 27385 | 26388 | } |
| 27386 | 26389 | |
| 27387 | 26390 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 27388 | if (try sema.typeHasOnePossibleValue(field_ty)) |field_val| | |
| 27389 | return Air.internedToRef(field_val.toIntern()); | |
| 26391 | if (try field_ty.onePossibleValue(pt)) |field_val| | |
| 26392 | return .fromValue(field_val); | |
| 27390 | 26393 | |
| 27391 | if (try sema.resolveValue(struct_byval)) |struct_val| { | |
| 26394 | if (sema.resolveValue(struct_byval)) |struct_val| { | |
| 27392 | 26395 | if (struct_val.isUndef(zcu)) return pt.undefRef(field_ty); |
| 27393 | if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { | |
| 27394 | return Air.internedToRef(opv.toIntern()); | |
| 27395 | } | |
| 27396 | return Air.internedToRef((try struct_val.fieldValue(pt, field_index)).toIntern()); | |
| 26396 | return .fromValue(try struct_val.fieldValue(pt, field_index)); | |
| 27397 | 26397 | } |
| 27398 | 26398 | |
| 27399 | try field_ty.resolveLayout(pt); | |
| 27400 | 26399 | return block.addStructFieldVal(struct_byval, field_index, field_ty); |
| 27401 | 26400 | }, |
| 27402 | 26401 | .tuple_type => { |
| ... | ... | @@ -27457,16 +26456,13 @@ fn tupleFieldValByIndex( |
| 27457 | 26456 | const zcu = pt.zcu; |
| 27458 | 26457 | const field_ty = tuple_ty.fieldType(field_index, zcu); |
| 27459 | 26458 | |
| 27460 | if (tuple_ty.structFieldIsComptime(field_index, zcu)) | |
| 27461 | try tuple_ty.resolveStructFieldInits(pt); | |
| 27462 | 26459 | if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_value| { |
| 27463 | 26460 | return Air.internedToRef(default_value.toIntern()); |
| 27464 | 26461 | } |
| 27465 | 26462 | |
| 27466 | if (try sema.resolveValue(tuple_byval)) |tuple_val| { | |
| 27467 | if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { | |
| 27468 | return Air.internedToRef(opv.toIntern()); | |
| 27469 | } | |
| 26463 | if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 26464 | ||
| 26465 | if (sema.resolveValue(tuple_byval)) |tuple_val| { | |
| 27470 | 26466 | return switch (zcu.intern_pool.indexToKey(tuple_val.toIntern())) { |
| 27471 | 26467 | .undef => pt.undefRef(field_ty), |
| 27472 | 26468 | .aggregate => |aggregate| Air.internedToRef(switch (aggregate.storage) { |
| ... | ... | @@ -27478,10 +26474,10 @@ fn tupleFieldValByIndex( |
| 27478 | 26474 | }; |
| 27479 | 26475 | } |
| 27480 | 26476 | |
| 27481 | try field_ty.resolveLayout(pt); | |
| 27482 | 26477 | return block.addStructFieldVal(tuple_byval, field_index, field_ty); |
| 27483 | 26478 | } |
| 27484 | 26479 | |
| 26480 | /// Asserts that the layout of `union_ty` is already resolved. | |
| 27485 | 26481 | fn unionFieldPtr( |
| 27486 | 26482 | sema: *Sema, |
| 27487 | 26483 | block: *Block, |
| ... | ... | @@ -27497,35 +26493,17 @@ fn unionFieldPtr( |
| 27497 | 26493 | const ip = &zcu.intern_pool; |
| 27498 | 26494 | |
| 27499 | 26495 | assert(union_ty.zigTypeTag(zcu) == .@"union"); |
| 26496 | union_ty.assertHasLayout(zcu); | |
| 27500 | 26497 | |
| 27501 | const union_ptr_ty = sema.typeOf(union_ptr); | |
| 27502 | const union_ptr_info = union_ptr_ty.ptrInfo(zcu); | |
| 27503 | try union_ty.resolveFields(pt); | |
| 27504 | 26498 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 26499 | const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); | |
| 26500 | ||
| 27505 | 26501 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 27506 | 26502 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 27507 | const ptr_field_ty = try pt.ptrTypeSema(.{ | |
| 27508 | .child = field_ty.toIntern(), | |
| 27509 | .flags = .{ | |
| 27510 | .is_const = union_ptr_info.flags.is_const, | |
| 27511 | .is_volatile = union_ptr_info.flags.is_volatile, | |
| 27512 | .address_space = union_ptr_info.flags.address_space, | |
| 27513 | .alignment = if (union_obj.flagsUnordered(ip).layout == .auto) blk: { | |
| 27514 | const union_align = if (union_ptr_info.flags.alignment != .none) | |
| 27515 | union_ptr_info.flags.alignment | |
| 27516 | else | |
| 27517 | try union_ty.abiAlignmentSema(pt); | |
| 27518 | const field_align = try union_ty.fieldAlignmentSema(field_index, pt); | |
| 27519 | break :blk union_align.min(field_align); | |
| 27520 | } else union_ptr_info.flags.alignment, | |
| 27521 | }, | |
| 27522 | .packed_offset = union_ptr_info.packed_offset, | |
| 27523 | }); | |
| 27524 | const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?); | |
| 27525 | 26503 | |
| 27526 | if (initializing and field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 26504 | if (initializing and field_ty.classify(zcu) == .no_possible_value) { | |
| 27527 | 26505 | const msg = msg: { |
| 27528 | const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); | |
| 26506 | const msg = try sema.errMsg(src, "cannot initialize union field with uninstantiable type '{f}'", .{field_ty.fmt(pt)}); | |
| 27529 | 26507 | errdefer msg.destroy(sema.gpa); |
| 27530 | 26508 | |
| 27531 | 26509 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ |
| ... | ... | @@ -27538,30 +26516,24 @@ fn unionFieldPtr( |
| 27538 | 26516 | } |
| 27539 | 26517 | |
| 27540 | 26518 | if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: { |
| 27541 | switch (union_obj.flagsUnordered(ip).layout) { | |
| 26519 | switch (union_obj.layout) { | |
| 27542 | 26520 | .auto => if (initializing) { |
| 27543 | 26521 | if (!sema.isComptimeMutablePtr(union_ptr_val)) { |
| 27544 | 26522 | // The initialization is a runtime operation. |
| 27545 | 26523 | break :ct; |
| 27546 | 26524 | } |
| 27547 | 26525 | // Store to the union to initialize the tag. |
| 27548 | const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 27549 | const payload_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 27550 | const new_union_val = try pt.unionValue(union_ty, field_tag, try pt.undefValue(payload_ty)); | |
| 26526 | const field_tag = try pt.enumValueFieldIndex(tag_ty, field_index); | |
| 26527 | const payload_val = try field_ty.onePossibleValue(pt) orelse try pt.undefValue(field_ty); | |
| 26528 | const new_union_val = try pt.unionValue(union_ty, field_tag, payload_val); | |
| 27551 | 26529 | try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty); |
| 27552 | 26530 | } else { |
| 27553 | const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse | |
| 27554 | break :ct; | |
| 27555 | if (union_val.isUndef(zcu)) { | |
| 27556 | return sema.failWithUseOfUndef(block, src, null); | |
| 27557 | } | |
| 27558 | const un = ip.indexToKey(union_val.toIntern()).un; | |
| 27559 | const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 27560 | const tag_matches = un.tag == field_tag.toIntern(); | |
| 27561 | if (!tag_matches) { | |
| 26531 | const union_val = try sema.pointerDeref(block, src, union_ptr_val, union_ptr_val.typeOf(zcu)) orelse break :ct; | |
| 26532 | if (union_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); | |
| 26533 | const active_index = tag_ty.enumTagFieldIndex(union_val.unionTag(zcu).?, zcu).?; | |
| 26534 | if (active_index != field_index) { | |
| 27562 | 26535 | const msg = msg: { |
| 27563 | const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; | |
| 27564 | const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu); | |
| 26536 | const active_field_name = tag_ty.enumFieldName(active_index, zcu); | |
| 27565 | 26537 | const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ |
| 27566 | 26538 | field_name.fmt(ip), |
| 27567 | 26539 | active_field_name.fmt(ip), |
| ... | ... | @@ -27575,34 +26547,34 @@ fn unionFieldPtr( |
| 27575 | 26547 | }, |
| 27576 | 26548 | .@"packed", .@"extern" => {}, |
| 27577 | 26549 | } |
| 27578 | const field_ptr_val = try union_ptr_val.ptrField(field_index, pt); | |
| 27579 | return Air.internedToRef(field_ptr_val.toIntern()); | |
| 26550 | return .fromValue(try union_ptr_val.ptrField(field_index, pt)); | |
| 27580 | 26551 | } |
| 27581 | 26552 | |
| 27582 | 26553 | // If the union has a tag, we must either set or or safety check it depending on `initializing`. |
| 27583 | 26554 | tag: { |
| 27584 | 26555 | if (union_ty.containerLayout(zcu) != .auto) break :tag; |
| 27585 | const tag_ty: Type = .fromInterned(union_obj.enum_tag_ty); | |
| 27586 | if (try sema.typeHasOnePossibleValue(tag_ty) != null) break :tag; | |
| 26556 | if (tag_ty.classify(zcu) == .one_possible_value) break :tag; | |
| 27587 | 26557 | // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but |
| 27588 | 26558 | // only emit a safety check if it's available at runtime (i.e. it's safety-tagged). |
| 27589 | const want_tag = try pt.enumValueFieldIndex(tag_ty, enum_field_index); | |
| 26559 | const want_tag = try pt.enumValueFieldIndex(tag_ty, field_index); | |
| 27590 | 26560 | if (initializing) { |
| 27591 | 26561 | const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, .fromValue(want_tag)); |
| 27592 | 26562 | try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store |
| 27593 | } else if (block.wantSafety() and union_obj.hasTag(ip)) { | |
| 27594 | // The tag exists at runtime (safety tag), so emit a safety check. | |
| 26563 | } else if (block.wantSafety() and union_obj.has_runtime_tag) { | |
| 26564 | // The tag exists at runtime (actual or safety tag), so emit a safety check. | |
| 27595 | 26565 | // TODO would it be better if get_union_tag supported pointers to unions? |
| 27596 | 26566 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); |
| 27597 | 26567 | const active_tag = try block.addTyOp(.get_union_tag, tag_ty, union_val); |
| 27598 | 26568 | try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, .fromValue(want_tag)); |
| 27599 | 26569 | } |
| 27600 | 26570 | } |
| 27601 | if (field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 26571 | if (field_ty.classify(zcu) == .no_possible_value) { | |
| 27602 | 26572 | _ = try block.addNoOp(.unreach); |
| 27603 | 26573 | return .unreachable_value; |
| 27604 | 26574 | } |
| 27605 | return block.addStructFieldPtr(union_ptr, field_index, ptr_field_ty); | |
| 26575 | ||
| 26576 | const field_ptr_ty = try sema.typeOf(union_ptr).fieldPtrType(field_index, pt); | |
| 26577 | return block.addStructFieldPtr(union_ptr, field_index, field_ptr_ty); | |
| 27606 | 26578 | } |
| 27607 | 26579 | |
| 27608 | 26580 | fn unionFieldVal( |
| ... | ... | @@ -27618,71 +26590,57 @@ fn unionFieldVal( |
| 27618 | 26590 | const zcu = pt.zcu; |
| 27619 | 26591 | const ip = &zcu.intern_pool; |
| 27620 | 26592 | assert(union_ty.zigTypeTag(zcu) == .@"union"); |
| 26593 | assert(sema.typeOf(union_byval).toIntern() == union_ty.toIntern()); | |
| 26594 | union_ty.assertHasLayout(zcu); | |
| 27621 | 26595 | |
| 27622 | try union_ty.resolveFields(pt); | |
| 27623 | 26596 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 27624 | 26597 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 27625 | 26598 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 27626 | const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?); | |
| 26599 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); | |
| 27627 | 26600 | |
| 27628 | if (try sema.resolveValue(union_byval)) |union_val| { | |
| 26601 | if (sema.resolveValue(union_byval)) |union_val| { | |
| 27629 | 26602 | if (union_val.isUndef(zcu)) return pt.undefRef(field_ty); |
| 27630 | ||
| 27631 | const un = ip.indexToKey(union_val.toIntern()).un; | |
| 27632 | const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 27633 | const tag_matches = un.tag == field_tag.toIntern(); | |
| 27634 | switch (union_obj.flagsUnordered(ip).layout) { | |
| 26603 | switch (union_obj.layout) { | |
| 27635 | 26604 | .auto => { |
| 27636 | if (tag_matches) { | |
| 27637 | return Air.internedToRef(un.val); | |
| 27638 | } else { | |
| 27639 | const msg = msg: { | |
| 27640 | const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; | |
| 27641 | const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu); | |
| 27642 | const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ | |
| 27643 | field_name.fmt(ip), active_field_name.fmt(ip), | |
| 27644 | }); | |
| 27645 | errdefer msg.destroy(sema.gpa); | |
| 27646 | try sema.addDeclaredHereNote(msg, union_ty); | |
| 27647 | break :msg msg; | |
| 27648 | }; | |
| 27649 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 27650 | } | |
| 26605 | const active_tag_val = union_val.unionTag(zcu).?; | |
| 26606 | const active_index = enum_tag_ty.enumTagFieldIndex(active_tag_val, zcu).?; | |
| 26607 | if (active_index == field_index) return .fromValue(union_val.unionPayload(zcu)); | |
| 26608 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 26609 | const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ | |
| 26610 | field_name.fmt(ip), enum_tag_ty.enumFieldName(active_index, zcu).fmt(ip), | |
| 26611 | }); | |
| 26612 | errdefer msg.destroy(zcu.comp.gpa); | |
| 26613 | try sema.addDeclaredHereNote(msg, union_ty); | |
| 26614 | break :msg msg; | |
| 26615 | }); | |
| 27651 | 26616 | }, |
| 27652 | .@"extern" => if (tag_matches) { | |
| 27653 | // Fast path - no need to use bitcast logic. | |
| 27654 | return Air.internedToRef(un.val); | |
| 27655 | } else if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| { | |
| 27656 | return Air.internedToRef(field_val.toIntern()); | |
| 26617 | .@"extern" => if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| { | |
| 26618 | return .fromValue(field_val); | |
| 26619 | } else { | |
| 26620 | // Runtime-known due to a pointer-to-integer conversion. | |
| 27657 | 26621 | }, |
| 27658 | .@"packed" => if (tag_matches) { | |
| 27659 | // Fast path - no need to use bitcast logic. | |
| 27660 | return Air.internedToRef(un.val); | |
| 27661 | } else if (try sema.bitCastVal(union_val, field_ty, 0, try union_ty.bitSizeSema(pt), 0)) |field_val| { | |
| 27662 | return Air.internedToRef(field_val.toIntern()); | |
| 26622 | .@"packed" => { | |
| 26623 | const field_val = try sema.bitCastVal(union_val, field_ty, 0, union_ty.bitSize(zcu), 0) orelse { | |
| 26624 | unreachable; // `null` is only possible if the input value contains a pointer, which a packed union cannot. | |
| 26625 | }; | |
| 26626 | return .fromValue(field_val); | |
| 27663 | 26627 | }, |
| 27664 | 26628 | } |
| 27665 | 26629 | } |
| 27666 | 26630 | |
| 27667 | if (union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and | |
| 27668 | union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1) | |
| 27669 | { | |
| 27670 | const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 27671 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); | |
| 27672 | const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_ty), union_byval); | |
| 27673 | try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag); | |
| 26631 | if (union_obj.layout == .auto and block.wantSafety() and union_obj.has_runtime_tag) { | |
| 26632 | const wanted_tag_val = try pt.enumValueFieldIndex(enum_tag_ty, field_index); | |
| 26633 | const active_tag = try block.addTyOp(.get_union_tag, enum_tag_ty, union_byval); | |
| 26634 | try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, .fromValue(wanted_tag_val)); | |
| 27674 | 26635 | } |
| 27675 | 26636 | |
| 27676 | if (field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 26637 | if (field_ty.classify(zcu) == .no_possible_value) { | |
| 27677 | 26638 | _ = try block.addNoOp(.unreach); |
| 27678 | 26639 | return .unreachable_value; |
| 27679 | 26640 | } |
| 27680 | 26641 | |
| 27681 | if (try sema.typeHasOnePossibleValue(field_ty)) |field_only_value| { | |
| 27682 | return Air.internedToRef(field_only_value.toIntern()); | |
| 27683 | } | |
| 26642 | if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 27684 | 26643 | |
| 27685 | try field_ty.resolveLayout(pt); | |
| 27686 | 26644 | return block.addStructFieldVal(union_byval, field_index, field_ty); |
| 27687 | 26645 | } |
| 27688 | 26646 | |
| ... | ... | @@ -27706,17 +26664,15 @@ fn elemPtr( |
| 27706 | 26664 | else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}), |
| 27707 | 26665 | }; |
| 27708 | 26666 | try sema.checkIndexable(block, src, indexable_ty); |
| 26667 | try sema.ensureLayoutResolved(indexable_ty, src, .ptr_access); | |
| 27709 | 26668 | |
| 27710 | 26669 | const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) { |
| 27711 | .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), | |
| 27712 | .@"struct" => blk: { | |
| 27713 | // Tuple field access. | |
| 27714 | const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); | |
| 27715 | const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 27716 | break :blk try sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init); | |
| 27717 | }, | |
| 26670 | .vector => try sema.elemPtrVector(block, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init), | |
| 26671 | .array => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), | |
| 26672 | .@"struct" => try sema.tupleElemPtr(block, src, indexable_ptr, elem_index, elem_index_src), | |
| 27718 | 26673 | else => { |
| 27719 | 26674 | const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src); |
| 26675 | try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu), src, .ptr_access); | |
| 27720 | 26676 | return elemPtrOneLayerOnly(sema, block, src, indexable, elem_index, elem_index_src, init, oob_safety); |
| 27721 | 26677 | }, |
| 27722 | 26678 | }; |
| ... | ... | @@ -27725,7 +26681,7 @@ fn elemPtr( |
| 27725 | 26681 | return elem_ptr; |
| 27726 | 26682 | } |
| 27727 | 26683 | |
| 27728 | /// Asserts that the type of indexable is pointer. | |
| 26684 | /// Asserts that `indexable` is an indexable pointer whose child type has its layout already resolved. | |
| 27729 | 26685 | fn elemPtrOneLayerOnly( |
| 27730 | 26686 | sema: *Sema, |
| 27731 | 26687 | block: *Block, |
| ... | ... | @@ -27741,28 +26697,31 @@ fn elemPtrOneLayerOnly( |
| 27741 | 26697 | const pt = sema.pt; |
| 27742 | 26698 | const zcu = pt.zcu; |
| 27743 | 26699 | |
| 27744 | try sema.checkIndexable(block, src, indexable_ty); | |
| 26700 | assert(indexable_ty.isIndexable(zcu)); | |
| 26701 | assert(indexable_ty.zigTypeTag(zcu) == .pointer); | |
| 26702 | const child_ty = indexable_ty.childType(zcu); | |
| 26703 | child_ty.assertHasLayout(zcu); | |
| 27745 | 26704 | |
| 27746 | 26705 | switch (indexable_ty.ptrSize(zcu)) { |
| 27747 | 26706 | .slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), |
| 27748 | 26707 | .many, .c => { |
| 27749 | 26708 | const maybe_ptr_val = try sema.resolveDefinedValue(block, indexable_src, indexable); |
| 27750 | 26709 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 26710 | const maybe_index: ?u64 = if (maybe_index_val) |val| val.toUnsignedInt(zcu) else null; | |
| 27751 | 26711 | ct: { |
| 27752 | 26712 | const ptr_val = maybe_ptr_val orelse break :ct; |
| 27753 | const index_val = maybe_index_val orelse break :ct; | |
| 27754 | const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 27755 | const elem_ptr = try ptr_val.ptrElem(index, pt); | |
| 27756 | return Air.internedToRef(elem_ptr.toIntern()); | |
| 26713 | const index: usize = @intCast(maybe_index orelse break :ct); | |
| 26714 | return .fromValue(try ptr_val.ptrElem(index, pt)); | |
| 27757 | 26715 | } |
| 27758 | 26716 | |
| 27759 | 26717 | try sema.checkLogicalPtrOperation(block, src, indexable_ty); |
| 27760 | const result_ty = try indexable_ty.elemPtrType(null, pt); | |
| 26718 | ||
| 26719 | const result_ty = try indexable_ty.elemPtrType(maybe_index, pt); | |
| 27761 | 26720 | |
| 27762 | 26721 | try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src); |
| 27763 | 26722 | try sema.validateRuntimeValue(block, indexable_src, indexable); |
| 27764 | 26723 | |
| 27765 | if (!try result_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) { | |
| 26724 | if (child_ty.abiSize(zcu) == 0) { | |
| 27766 | 26725 | // zero-bit child type; just bitcast the pointer |
| 27767 | 26726 | return block.addBitCast(result_ty, indexable); |
| 27768 | 26727 | } |
| ... | ... | @@ -27770,15 +26729,10 @@ fn elemPtrOneLayerOnly( |
| 27770 | 26729 | return block.addPtrElemPtr(indexable, elem_index, result_ty); |
| 27771 | 26730 | }, |
| 27772 | 26731 | .one => { |
| 27773 | const child_ty = indexable_ty.childType(zcu); | |
| 27774 | 26732 | const elem_ptr = switch (child_ty.zigTypeTag(zcu)) { |
| 27775 | .array, .vector => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety), | |
| 27776 | .@"struct" => blk: { | |
| 27777 | assert(child_ty.isTuple(zcu)); | |
| 27778 | const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); | |
| 27779 | const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 27780 | break :blk try sema.tupleFieldPtr(block, indexable_src, indexable, elem_index_src, index, false); | |
| 27781 | }, | |
| 26733 | .vector => try sema.elemPtrVector(block, indexable_src, indexable, elem_index_src, elem_index, init), | |
| 26734 | .array => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety), | |
| 26735 | .@"struct" => try sema.tupleElemPtr(block, indexable_src, indexable, elem_index, elem_index_src), | |
| 27782 | 26736 | else => unreachable, // Guaranteed by checkIndexable |
| 27783 | 26737 | }; |
| 27784 | 26738 | try sema.checkKnownAllocPtr(block, indexable, elem_ptr); |
| ... | ... | @@ -27808,45 +26762,51 @@ fn elemVal( |
| 27808 | 26762 | const elem_index = try sema.coerce(block, .usize, elem_index_uncasted, elem_index_src); |
| 27809 | 26763 | |
| 27810 | 26764 | switch (indexable_ty.zigTypeTag(zcu)) { |
| 27811 | .pointer => switch (indexable_ty.ptrSize(zcu)) { | |
| 27812 | .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), | |
| 27813 | .many, .c => { | |
| 27814 | const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable); | |
| 27815 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | |
| 27816 | const elem_ty = indexable_ty.elemType2(zcu); | |
| 27817 | ||
| 27818 | ct: { | |
| 27819 | const indexable_val = maybe_indexable_val orelse break :ct; | |
| 27820 | const index_val = maybe_index_val orelse break :ct; | |
| 27821 | const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 27822 | const many_ptr_ty = try pt.manyConstPtrType(elem_ty); | |
| 27823 | const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty); | |
| 27824 | const elem_ptr_ty = try pt.singleConstPtrType(elem_ty); | |
| 27825 | const elem_ptr_val = try many_ptr_val.ptrElem(index, pt); | |
| 27826 | const elem_val = try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty) orelse break :ct; | |
| 27827 | return Air.internedToRef((try pt.getCoerced(elem_val, elem_ty)).toIntern()); | |
| 27828 | } | |
| 26765 | .pointer => { | |
| 26766 | const child_ty = indexable_ty.childType(zcu); | |
| 26767 | try sema.ensureLayoutResolved(child_ty, src, .ptr_access); | |
| 26768 | switch (indexable_ty.ptrSize(zcu)) { | |
| 26769 | .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), | |
| 26770 | .many, .c => { | |
| 26771 | const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable); | |
| 26772 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | |
| 26773 | ||
| 26774 | ct: { | |
| 26775 | const indexable_val = maybe_indexable_val orelse break :ct; | |
| 26776 | const index_val = maybe_index_val orelse break :ct; | |
| 26777 | const index: usize = @intCast(index_val.toUnsignedInt(zcu)); | |
| 26778 | const many_ptr_ty = try pt.manyConstPtrType(child_ty); | |
| 26779 | const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty); | |
| 26780 | const elem_ptr_val = try many_ptr_val.ptrElem(index, pt); | |
| 26781 | return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), indexable_src); | |
| 26782 | } | |
| 27829 | 26783 | |
| 27830 | if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| { | |
| 27831 | return Air.internedToRef(elem_only_value.toIntern()); | |
| 27832 | } | |
| 26784 | try sema.validateRuntimeElemAccess(block, elem_index_src, child_ty, indexable_ty, src); | |
| 26785 | switch (child_ty.classify(zcu)) { | |
| 26786 | .runtime => {}, | |
| 26787 | .one_possible_value => return .fromValue((try child_ty.onePossibleValue(pt)).?), | |
| 26788 | .no_possible_value => switch (child_ty.zigTypeTag(zcu)) { | |
| 26789 | .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{child_ty.fmt(pt)}), | |
| 26790 | else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{child_ty.fmt(pt)}), | |
| 26791 | }, | |
| 26792 | .partially_comptime, .fully_comptime => unreachable, // caught by `validateRuntimeElemAccess` | |
| 26793 | } | |
| 27833 | 26794 | |
| 27834 | try sema.checkLogicalPtrOperation(block, src, indexable_ty); | |
| 27835 | return block.addBinOp(.ptr_elem_val, indexable, elem_index); | |
| 27836 | }, | |
| 27837 | .one => { | |
| 27838 | arr_sent: { | |
| 27839 | const inner_ty = indexable_ty.childType(zcu); | |
| 27840 | if (inner_ty.zigTypeTag(zcu) != .array) break :arr_sent; | |
| 27841 | const sentinel = inner_ty.sentinel(zcu) orelse break :arr_sent; | |
| 27842 | const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent; | |
| 27843 | const index = try sema.usizeCast(block, src, try index_val.toUnsignedIntSema(pt)); | |
| 27844 | if (index != inner_ty.arrayLen(zcu)) break :arr_sent; | |
| 27845 | return Air.internedToRef(sentinel.toIntern()); | |
| 27846 | } | |
| 27847 | const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety); | |
| 27848 | return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); | |
| 27849 | }, | |
| 26795 | return block.addBinOp(.ptr_elem_val, indexable, elem_index); | |
| 26796 | }, | |
| 26797 | .one => { | |
| 26798 | arr_sent: { | |
| 26799 | if (child_ty.zigTypeTag(zcu) != .array) break :arr_sent; | |
| 26800 | const sentinel = child_ty.sentinel(zcu) orelse break :arr_sent; | |
| 26801 | const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent; | |
| 26802 | const index = try sema.usizeCast(block, src, index_val.toUnsignedInt(zcu)); | |
| 26803 | if (index != child_ty.arrayLen(zcu)) break :arr_sent; | |
| 26804 | return .fromValue(sentinel); | |
| 26805 | } | |
| 26806 | const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety); | |
| 26807 | return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); | |
| 26808 | }, | |
| 26809 | } | |
| 27850 | 26810 | }, |
| 27851 | 26811 | .array => return sema.elemValArray(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), |
| 27852 | 26812 | .vector => { |
| ... | ... | @@ -27856,7 +26816,7 @@ fn elemVal( |
| 27856 | 26816 | .@"struct" => { |
| 27857 | 26817 | // Tuple field access. |
| 27858 | 26818 | const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); |
| 27859 | const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 26819 | const index: u32 = @intCast(index_val.toUnsignedInt(zcu)); | |
| 27860 | 26820 | return sema.tupleField(block, indexable_src, indexable, elem_index_src, index); |
| 27861 | 26821 | }, |
| 27862 | 26822 | else => unreachable, |
| ... | ... | @@ -27864,6 +26824,7 @@ fn elemVal( |
| 27864 | 26824 | } |
| 27865 | 26825 | |
| 27866 | 26826 | /// Called when the index or indexable is runtime known. |
| 26827 | /// Asserts that the layout of `elem_ty` is already resolved. | |
| 27867 | 26828 | fn validateRuntimeElemAccess( |
| 27868 | 26829 | sema: *Sema, |
| 27869 | 26830 | block: *Block, |
| ... | ... | @@ -27875,16 +26836,16 @@ fn validateRuntimeElemAccess( |
| 27875 | 26836 | const pt = sema.pt; |
| 27876 | 26837 | const zcu = pt.zcu; |
| 27877 | 26838 | |
| 27878 | if (try elem_ty.comptimeOnlySema(sema.pt)) { | |
| 26839 | if (elem_ty.comptimeOnly(zcu)) { | |
| 27879 | 26840 | const msg = msg: { |
| 27880 | 26841 | const msg = try sema.errMsg( |
| 27881 | 26842 | elem_index_src, |
| 27882 | 26843 | "values of type '{f}' must be comptime-known, but index value is runtime-known", |
| 27883 | .{parent_ty.fmt(sema.pt)}, | |
| 26844 | .{elem_ty.fmt(sema.pt)}, | |
| 27884 | 26845 | ); |
| 27885 | 26846 | errdefer msg.destroy(sema.gpa); |
| 27886 | 26847 | |
| 27887 | try sema.explainWhyTypeIsComptime(msg, parent_src, parent_ty); | |
| 26848 | try sema.explainWhyTypeIsComptime(msg, parent_src, elem_ty); | |
| 27888 | 26849 | |
| 27889 | 26850 | break :msg msg; |
| 27890 | 26851 | }; |
| ... | ... | @@ -27900,71 +26861,38 @@ fn validateRuntimeElemAccess( |
| 27900 | 26861 | } |
| 27901 | 26862 | } |
| 27902 | 26863 | |
| 27903 | fn tupleFieldPtr( | |
| 26864 | /// Validates `elem_index`, and returns a pointer to that field using `structFieldPtrByIndex`. | |
| 26865 | /// | |
| 26866 | /// Asserts that the type of `tuple_ptr` is a single-item pointer whose child type is a tuple. | |
| 26867 | fn tupleElemPtr( | |
| 27904 | 26868 | sema: *Sema, |
| 27905 | 26869 | block: *Block, |
| 27906 | tuple_ptr_src: LazySrcLoc, | |
| 26870 | src: LazySrcLoc, | |
| 27907 | 26871 | tuple_ptr: Air.Inst.Ref, |
| 27908 | field_index_src: LazySrcLoc, | |
| 27909 | field_index: u32, | |
| 27910 | init: bool, | |
| 26872 | elem_index: Air.Inst.Ref, | |
| 26873 | elem_index_src: LazySrcLoc, | |
| 27911 | 26874 | ) CompileError!Air.Inst.Ref { |
| 27912 | 26875 | const pt = sema.pt; |
| 27913 | 26876 | const zcu = pt.zcu; |
| 27914 | 26877 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 27915 | const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu); | |
| 27916 | const tuple_ty: Type = .fromInterned(tuple_ptr_info.child); | |
| 27917 | try tuple_ty.resolveFields(pt); | |
| 27918 | const field_count = tuple_ty.structFieldCount(zcu); | |
| 26878 | assert(tuple_ptr_ty.isSinglePointer(zcu)); | |
| 26879 | const tuple_ty = tuple_ptr_ty.childType(zcu); | |
| 26880 | assert(tuple_ty.isTuple(zcu)); | |
| 27919 | 26881 | |
| 26882 | const field_count = tuple_ty.structFieldCount(zcu); | |
| 27920 | 26883 | if (field_count == 0) { |
| 27921 | return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); | |
| 26884 | return sema.fail(block, src, "indexing into empty tuple is not allowed", .{}); | |
| 27922 | 26885 | } |
| 27923 | 26886 | |
| 27924 | if (field_index >= field_count) { | |
| 27925 | return sema.fail(block, field_index_src, "index {d} outside tuple of length {d}", .{ | |
| 27926 | field_index, field_count, | |
| 26887 | const elem_index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); | |
| 26888 | const index = elem_index_val.getUnsignedInt(zcu); | |
| 26889 | if (index == null or index.? >= field_count) { | |
| 26890 | return sema.fail(block, elem_index_src, "index '{f}' out of bounds of tuple '{f}'", .{ | |
| 26891 | elem_index_val.fmtValueSema(pt, sema), tuple_ty.fmt(pt), | |
| 27927 | 26892 | }); |
| 27928 | 26893 | } |
| 27929 | 26894 | |
| 27930 | const field_ty = tuple_ty.fieldType(field_index, zcu); | |
| 27931 | const ptr_field_ty = try pt.ptrTypeSema(.{ | |
| 27932 | .child = field_ty.toIntern(), | |
| 27933 | .flags = .{ | |
| 27934 | .is_const = tuple_ptr_info.flags.is_const, | |
| 27935 | .is_volatile = tuple_ptr_info.flags.is_volatile, | |
| 27936 | .address_space = tuple_ptr_info.flags.address_space, | |
| 27937 | .alignment = a: { | |
| 27938 | if (tuple_ptr_info.flags.alignment == .none) break :a .none; | |
| 27939 | // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned. | |
| 27940 | const tuple_align = tuple_ptr_info.flags.alignment; | |
| 27941 | const field_align = try field_ty.abiAlignmentSema(pt); | |
| 27942 | break :a tuple_align.min(field_align); | |
| 27943 | }, | |
| 27944 | }, | |
| 27945 | }); | |
| 27946 | ||
| 27947 | if (tuple_ty.structFieldIsComptime(field_index, zcu)) | |
| 27948 | try tuple_ty.resolveStructFieldInits(pt); | |
| 27949 | ||
| 27950 | if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_val| { | |
| 27951 | return Air.internedToRef((try pt.intern(.{ .ptr = .{ | |
| 27952 | .ty = ptr_field_ty.toIntern(), | |
| 27953 | .base_addr = .{ .comptime_field = default_val.toIntern() }, | |
| 27954 | .byte_offset = 0, | |
| 27955 | } }))); | |
| 27956 | } | |
| 27957 | ||
| 27958 | if (try sema.resolveValue(tuple_ptr)) |tuple_ptr_val| { | |
| 27959 | const field_ptr_val = try tuple_ptr_val.ptrField(field_index, pt); | |
| 27960 | return Air.internedToRef(field_ptr_val.toIntern()); | |
| 27961 | } | |
| 27962 | ||
| 27963 | if (!init) { | |
| 27964 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_ptr_src); | |
| 27965 | } | |
| 27966 | ||
| 27967 | return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty); | |
| 26895 | return sema.structFieldPtrByIndex(block, src, tuple_ptr, @intCast(index.?), tuple_ty); | |
| 27968 | 26896 | } |
| 27969 | 26897 | |
| 27970 | 26898 | fn tupleField( |
| ... | ... | @@ -27978,7 +26906,6 @@ fn tupleField( |
| 27978 | 26906 | const pt = sema.pt; |
| 27979 | 26907 | const zcu = pt.zcu; |
| 27980 | 26908 | const tuple_ty = sema.typeOf(tuple); |
| 27981 | try tuple_ty.resolveFields(pt); | |
| 27982 | 26909 | const field_count = tuple_ty.structFieldCount(zcu); |
| 27983 | 26910 | |
| 27984 | 26911 | if (field_count == 0) { |
| ... | ... | @@ -27993,20 +26920,17 @@ fn tupleField( |
| 27993 | 26920 | |
| 27994 | 26921 | const field_ty = tuple_ty.fieldType(field_index, zcu); |
| 27995 | 26922 | |
| 27996 | if (tuple_ty.structFieldIsComptime(field_index, zcu)) | |
| 27997 | try tuple_ty.resolveStructFieldInits(pt); | |
| 27998 | 26923 | if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_value| { |
| 27999 | 26924 | return Air.internedToRef(default_value.toIntern()); // comptime field |
| 28000 | 26925 | } |
| 28001 | 26926 | |
| 28002 | if (try sema.resolveValue(tuple)) |tuple_val| { | |
| 26927 | if (sema.resolveValue(tuple)) |tuple_val| { | |
| 28003 | 26928 | if (tuple_val.isUndef(zcu)) return pt.undefRef(field_ty); |
| 28004 | 26929 | return Air.internedToRef((try tuple_val.fieldValue(pt, field_index)).toIntern()); |
| 28005 | 26930 | } |
| 28006 | 26931 | |
| 28007 | 26932 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); |
| 28008 | 26933 | |
| 28009 | try field_ty.resolveLayout(pt); | |
| 28010 | 26934 | return block.addStructFieldVal(tuple, field_index, field_ty); |
| 28011 | 26935 | } |
| 28012 | 26936 | |
| ... | ... | @@ -28032,12 +26956,12 @@ fn elemValArray( |
| 28032 | 26956 | return sema.fail(block, array_src, "indexing into empty array is not allowed", .{}); |
| 28033 | 26957 | } |
| 28034 | 26958 | |
| 28035 | const maybe_undef_array_val = try sema.resolveValue(array); | |
| 26959 | const maybe_undef_array_val = sema.resolveValue(array); | |
| 28036 | 26960 | // index must be defined since it can access out of bounds |
| 28037 | 26961 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 28038 | 26962 | |
| 28039 | 26963 | if (maybe_index_val) |index_val| { |
| 28040 | const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 26964 | const index: usize = @intCast(index_val.toUnsignedInt(zcu)); | |
| 28041 | 26965 | if (array_sent) |s| { |
| 28042 | 26966 | if (index == array_len) { |
| 28043 | 26967 | return Air.internedToRef(s.toIntern()); |
| ... | ... | @@ -28053,10 +26977,11 @@ fn elemValArray( |
| 28053 | 26977 | return pt.undefRef(elem_ty); |
| 28054 | 26978 | } |
| 28055 | 26979 | if (maybe_index_val) |index_val| { |
| 28056 | const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 28057 | const elem_val = try array_val.elemValue(pt, index); | |
| 28058 | return Air.internedToRef(elem_val.toIntern()); | |
| 26980 | const index: usize = @intCast(index_val.toUnsignedInt(zcu)); | |
| 26981 | return .fromValue(try array_val.elemValue(pt, index)); | |
| 28059 | 26982 | } |
| 26983 | // Since the array is comptime-known, it might be OPV, in which case the index is irrelevant. | |
| 26984 | if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 28060 | 26985 | } |
| 28061 | 26986 | |
| 28062 | 26987 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src); |
| ... | ... | @@ -28071,12 +26996,105 @@ fn elemValArray( |
| 28071 | 26996 | } |
| 28072 | 26997 | } |
| 28073 | 26998 | |
| 28074 | if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_val| | |
| 28075 | return Air.internedToRef(elem_val.toIntern()); | |
| 28076 | ||
| 28077 | 26999 | return block.addBinOp(.array_elem_val, array, elem_index); |
| 28078 | 27000 | } |
| 28079 | 27001 | |
| 27002 | fn elemPtrVector( | |
| 27003 | sema: *Sema, | |
| 27004 | block: *Block, | |
| 27005 | vector_ptr_src: LazySrcLoc, | |
| 27006 | vector_ptr: Air.Inst.Ref, | |
| 27007 | elem_index_src: LazySrcLoc, | |
| 27008 | elem_index: Air.Inst.Ref, | |
| 27009 | init: bool, | |
| 27010 | ) CompileError!Air.Inst.Ref { | |
| 27011 | const pt = sema.pt; | |
| 27012 | const zcu = pt.zcu; | |
| 27013 | const vector_ptr_ty = sema.typeOf(vector_ptr); | |
| 27014 | const vector_ty = vector_ptr_ty.childType(zcu); | |
| 27015 | assert(vector_ty.zigTypeTag(zcu) == .vector); | |
| 27016 | const vector_len = vector_ty.vectorLen(zcu); | |
| 27017 | ||
| 27018 | if (vector_len == 0) { | |
| 27019 | return sema.fail(block, vector_ptr_src, "cannot index into empty vector", .{}); | |
| 27020 | } | |
| 27021 | ||
| 27022 | const maybe_vector_ptr_val = sema.resolveValue(vector_ptr); | |
| 27023 | // The index must not be undefined since it can be out of bounds. | |
| 27024 | const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse { | |
| 27025 | return sema.fail(block, elem_index_src, "vector index not comptime known", .{}); | |
| 27026 | }; | |
| 27027 | const index = index_val.toUnsignedInt(zcu); | |
| 27028 | if (index >= vector_len) { | |
| 27029 | return sema.fail(block, elem_index_src, "index {d} outside vector of length {d}", .{ index, vector_len }); | |
| 27030 | } | |
| 27031 | ||
| 27032 | const elem_ty = vector_ty.childType(zcu); | |
| 27033 | const elem_bits = elem_ty.bitSize(zcu); | |
| 27034 | // Exiting this block means the operation is a runtime one. | |
| 27035 | const elem_ptr_ty: Type = if (elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits)) elem_ptr_ty: { | |
| 27036 | // Use a packed pointer (i.e. vector_index != 0) | |
| 27037 | const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu); | |
| 27038 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 27039 | .child = elem_ty.toIntern(), | |
| 27040 | .flags = .{ | |
| 27041 | .size = .one, | |
| 27042 | .alignment = vector_ptr_info.flags.alignment, | |
| 27043 | .is_const = vector_ptr_info.flags.is_const, | |
| 27044 | .is_volatile = vector_ptr_info.flags.is_volatile, | |
| 27045 | .is_allowzero = vector_ptr_info.flags.is_allowzero, | |
| 27046 | .address_space = vector_ptr_info.flags.address_space, | |
| 27047 | .vector_index = @enumFromInt(index), | |
| 27048 | }, | |
| 27049 | .packed_offset = .{ | |
| 27050 | .host_size = @intCast(vector_len), | |
| 27051 | .bit_offset = 0, | |
| 27052 | }, | |
| 27053 | }); | |
| 27054 | if (maybe_vector_ptr_val) |ptr_val| { | |
| 27055 | if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty); | |
| 27056 | return .fromValue(try pt.getCoerced(ptr_val, elem_ptr_ty)); | |
| 27057 | } | |
| 27058 | break :elem_ptr_ty elem_ptr_ty; | |
| 27059 | } else elem_ptr_ty: { | |
| 27060 | // Use a normal pointer (i.e. vector_index == 0) | |
| 27061 | const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu); | |
| 27062 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 27063 | .child = elem_ty.toIntern(), | |
| 27064 | .flags = .{ | |
| 27065 | .size = .one, | |
| 27066 | // TODO: this logic was ported from old code, but it's bogus. This entire block will | |
| 27067 | // go away when https://github.com/ziglang/zig/issues/24061 is implemented anyway. | |
| 27068 | .alignment = switch (vector_ptr_info.flags.alignment) { | |
| 27069 | .none => .none, | |
| 27070 | else => |vec_align| switch (index * elem_ty.abiSize(zcu)) { | |
| 27071 | 0 => vec_align, | |
| 27072 | else => |byte_offset| .minStrict(vec_align, .fromLog2Units(@ctz(byte_offset))), | |
| 27073 | }, | |
| 27074 | }, | |
| 27075 | .is_const = vector_ptr_info.flags.is_const, | |
| 27076 | .is_volatile = vector_ptr_info.flags.is_volatile, | |
| 27077 | .is_allowzero = vector_ptr_info.flags.is_allowzero, | |
| 27078 | .address_space = vector_ptr_info.flags.address_space, | |
| 27079 | }, | |
| 27080 | }); | |
| 27081 | if (maybe_vector_ptr_val) |ptr_val| { | |
| 27082 | if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty); | |
| 27083 | const bit_offset = index * @divExact(elem_ty.bitSize(zcu), 8); | |
| 27084 | return .fromValue(try ptr_val.getOffsetPtr(bit_offset, elem_ptr_ty, pt)); | |
| 27085 | } | |
| 27086 | break :elem_ptr_ty elem_ptr_ty; | |
| 27087 | }; | |
| 27088 | ||
| 27089 | if (!init) { | |
| 27090 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, vector_ty, vector_ptr_src); | |
| 27091 | try sema.validateRuntimeValue(block, vector_ptr_src, vector_ptr); | |
| 27092 | } | |
| 27093 | ||
| 27094 | return block.addPtrElemPtr(vector_ptr, elem_index, elem_ptr_ty); | |
| 27095 | } | |
| 27096 | ||
| 27097 | /// Asserts that the layout of the array is already resolved. | |
| 28080 | 27098 | fn elemPtrArray( |
| 28081 | 27099 | sema: *Sema, |
| 28082 | 27100 | block: *Block, |
| ... | ... | @@ -28091,19 +27109,21 @@ fn elemPtrArray( |
| 28091 | 27109 | const pt = sema.pt; |
| 28092 | 27110 | const zcu = pt.zcu; |
| 28093 | 27111 | const array_ptr_ty = sema.typeOf(array_ptr); |
| 27112 | assert(array_ptr_ty.ptrSize(zcu) == .one); | |
| 28094 | 27113 | const array_ty = array_ptr_ty.childType(zcu); |
| 27114 | assert(array_ty.zigTypeTag(zcu) == .array); | |
| 28095 | 27115 | const array_sent = array_ty.sentinel(zcu) != null; |
| 28096 | 27116 | const array_len = array_ty.arrayLen(zcu); |
| 28097 | 27117 | const array_len_s = array_len + @intFromBool(array_sent); |
| 28098 | 27118 | |
| 28099 | 27119 | if (array_len_s == 0) { |
| 28100 | return sema.fail(block, array_ptr_src, "indexing into empty array is not allowed", .{}); | |
| 27120 | return sema.fail(block, array_ptr_src, "cannot index into empty array", .{}); | |
| 28101 | 27121 | } |
| 28102 | 27122 | |
| 28103 | const maybe_undef_array_ptr_val = try sema.resolveValue(array_ptr); | |
| 27123 | const maybe_undef_array_ptr_val = sema.resolveValue(array_ptr); | |
| 28104 | 27124 | // The index must not be undefined since it can be out of bounds. |
| 28105 | const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { | |
| 28106 | const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(pt)); | |
| 27125 | const maybe_index: ?u64 = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { | |
| 27126 | const index = index_val.toUnsignedInt(zcu); | |
| 28107 | 27127 | if (index >= array_len_s) { |
| 28108 | 27128 | const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else ""; |
| 28109 | 27129 | return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label }); |
| ... | ... | @@ -28111,37 +27131,39 @@ fn elemPtrArray( |
| 28111 | 27131 | break :o index; |
| 28112 | 27132 | } else null; |
| 28113 | 27133 | |
| 28114 | if (offset == null and array_ty.zigTypeTag(zcu) == .vector) { | |
| 28115 | return sema.fail(block, elem_index_src, "vector index not comptime known", .{}); | |
| 28116 | } | |
| 28117 | ||
| 28118 | const elem_ptr_ty = try array_ptr_ty.elemPtrType(offset, pt); | |
| 27134 | array_ty.assertHasLayout(zcu); | |
| 27135 | const elem_ptr_ty = try array_ptr_ty.elemPtrType(maybe_index, pt); | |
| 28119 | 27136 | |
| 28120 | 27137 | if (maybe_undef_array_ptr_val) |array_ptr_val| { |
| 28121 | 27138 | if (array_ptr_val.isUndef(zcu)) { |
| 28122 | 27139 | return pt.undefRef(elem_ptr_ty); |
| 28123 | 27140 | } |
| 28124 | if (offset) |index| { | |
| 28125 | const elem_ptr = try array_ptr_val.ptrElem(index, pt); | |
| 28126 | return Air.internedToRef(elem_ptr.toIntern()); | |
| 27141 | if (maybe_index) |index| { | |
| 27142 | return .fromValue(try array_ptr_val.ptrElem(index, pt)); | |
| 28127 | 27143 | } |
| 28128 | 27144 | } |
| 28129 | 27145 | |
| 28130 | 27146 | if (!init) { |
| 28131 | try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(zcu), array_ty, array_ptr_src); | |
| 27147 | try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.childType(zcu), array_ty, array_ptr_src); | |
| 28132 | 27148 | try sema.validateRuntimeValue(block, array_ptr_src, array_ptr); |
| 28133 | 27149 | } |
| 28134 | 27150 | |
| 28135 | 27151 | // Runtime check is only needed if unable to comptime check. |
| 28136 | if (oob_safety and block.wantSafety() and offset == null) { | |
| 27152 | if (oob_safety and block.wantSafety() and maybe_index == null) { | |
| 28137 | 27153 | const len_inst = try pt.intRef(.usize, array_len); |
| 28138 | 27154 | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; |
| 28139 | 27155 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| 28140 | 27156 | } |
| 28141 | 27157 | |
| 27158 | if (array_ty.childType(zcu).abiSize(zcu) == 0) { | |
| 27159 | // zero-bit child type; just bitcast the pointer | |
| 27160 | return block.addBitCast(elem_ptr_ty, array_ptr); | |
| 27161 | } | |
| 27162 | ||
| 28142 | 27163 | return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty); |
| 28143 | 27164 | } |
| 28144 | 27165 | |
| 27166 | /// Asserts that the layout of the slice element type is already resolved. | |
| 28145 | 27167 | fn elemValSlice( |
| 28146 | 27168 | sema: *Sema, |
| 28147 | 27169 | block: *Block, |
| ... | ... | @@ -28155,9 +27177,11 @@ fn elemValSlice( |
| 28155 | 27177 | const pt = sema.pt; |
| 28156 | 27178 | const zcu = pt.zcu; |
| 28157 | 27179 | const slice_ty = sema.typeOf(slice); |
| 27180 | assert(slice_ty.isSlice(zcu)); | |
| 28158 | 27181 | const slice_sent = slice_ty.sentinel(zcu) != null; |
| 28159 | const elem_ty = slice_ty.elemType2(zcu); | |
| 28160 | var runtime_src = slice_src; | |
| 27182 | const elem_ty = slice_ty.childType(zcu); | |
| 27183 | ||
| 27184 | elem_ty.assertHasLayout(zcu); | |
| 28161 | 27185 | |
| 28162 | 27186 | // slice must be defined since it can dereferenced as null |
| 28163 | 27187 | const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice); |
| ... | ... | @@ -28165,37 +27189,30 @@ fn elemValSlice( |
| 28165 | 27189 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 28166 | 27190 | |
| 28167 | 27191 | if (maybe_slice_val) |slice_val| { |
| 28168 | runtime_src = elem_index_src; | |
| 28169 | const slice_len = try slice_val.sliceLen(pt); | |
| 27192 | const slice_len = slice_val.sliceLen(zcu); | |
| 28170 | 27193 | const slice_len_s = slice_len + @intFromBool(slice_sent); |
| 28171 | 27194 | if (slice_len_s == 0) { |
| 28172 | 27195 | return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); |
| 28173 | 27196 | } |
| 28174 | 27197 | if (maybe_index_val) |index_val| { |
| 28175 | const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); | |
| 27198 | const index: usize = @intCast(index_val.toUnsignedInt(zcu)); | |
| 28176 | 27199 | if (index >= slice_len_s) { |
| 28177 | 27200 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 28178 | 27201 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| 28179 | 27202 | } |
| 28180 | const elem_ptr_ty = try slice_ty.elemPtrType(index, pt); | |
| 28181 | 27203 | const elem_ptr_val = try slice_val.ptrElem(index, pt); |
| 28182 | if (try sema.pointerDeref(block, slice_src, elem_ptr_val, elem_ptr_ty)) |elem_val| { | |
| 28183 | return Air.internedToRef(elem_val.toIntern()); | |
| 28184 | } | |
| 28185 | runtime_src = slice_src; | |
| 27204 | return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), slice_src); | |
| 28186 | 27205 | } |
| 28187 | 27206 | } |
| 28188 | 27207 | |
| 28189 | if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| { | |
| 28190 | return Air.internedToRef(elem_only_value.toIntern()); | |
| 28191 | } | |
| 27208 | if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 28192 | 27209 | |
| 28193 | 27210 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src); |
| 28194 | 27211 | try sema.validateRuntimeValue(block, slice_src, slice); |
| 28195 | 27212 | |
| 28196 | 27213 | if (oob_safety and block.wantSafety()) { |
| 28197 | 27214 | const len_inst = if (maybe_slice_val) |slice_val| |
| 28198 | try pt.intRef(.usize, try slice_val.sliceLen(pt)) | |
| 27215 | try pt.intRef(.usize, slice_val.sliceLen(zcu)) | |
| 28199 | 27216 | else |
| 28200 | 27217 | try block.addTyOp(.slice_len, .usize, slice); |
| 28201 | 27218 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| ... | ... | @@ -28204,6 +27221,7 @@ fn elemValSlice( |
| 28204 | 27221 | return block.addBinOp(.slice_elem_val, slice, elem_index); |
| 28205 | 27222 | } |
| 28206 | 27223 | |
| 27224 | /// Asserts that the layout of the slice element type is already resolved. | |
| 28207 | 27225 | fn elemPtrSlice( |
| 28208 | 27226 | sema: *Sema, |
| 28209 | 27227 | block: *Block, |
| ... | ... | @@ -28217,33 +27235,35 @@ fn elemPtrSlice( |
| 28217 | 27235 | const pt = sema.pt; |
| 28218 | 27236 | const zcu = pt.zcu; |
| 28219 | 27237 | const slice_ty = sema.typeOf(slice); |
| 27238 | assert(slice_ty.isSlice(zcu)); | |
| 28220 | 27239 | const slice_sent = slice_ty.sentinel(zcu) != null; |
| 27240 | const elem_ty = slice_ty.childType(zcu); | |
| 27241 | elem_ty.assertHasLayout(zcu); | |
| 28221 | 27242 | |
| 28222 | const maybe_undef_slice_val = try sema.resolveValue(slice); | |
| 27243 | const maybe_undef_slice_val = sema.resolveValue(slice); | |
| 28223 | 27244 | // The index must not be undefined since it can be out of bounds. |
| 28224 | const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { | |
| 28225 | const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(pt)); | |
| 28226 | break :o index; | |
| 27245 | const offset: ?u64 = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { | |
| 27246 | break :o index_val.toUnsignedInt(zcu); | |
| 28227 | 27247 | } else null; |
| 28228 | 27248 | |
| 28229 | 27249 | const elem_ptr_ty = try slice_ty.elemPtrType(offset, pt); |
| 27250 | assert(elem_ptr_ty.childType(zcu).toIntern() == elem_ty.toIntern()); | |
| 28230 | 27251 | |
| 28231 | 27252 | if (maybe_undef_slice_val) |slice_val| { |
| 28232 | 27253 | if (slice_val.isUndef(zcu)) { |
| 28233 | 27254 | return pt.undefRef(elem_ptr_ty); |
| 28234 | 27255 | } |
| 28235 | const slice_len = try slice_val.sliceLen(pt); | |
| 27256 | const slice_len = slice_val.sliceLen(zcu); | |
| 28236 | 27257 | const slice_len_s = slice_len + @intFromBool(slice_sent); |
| 28237 | 27258 | if (slice_len_s == 0) { |
| 28238 | return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); | |
| 27259 | return sema.fail(block, slice_src, "cannot index into empty slice", .{}); | |
| 28239 | 27260 | } |
| 28240 | 27261 | if (offset) |index| { |
| 28241 | 27262 | if (index >= slice_len_s) { |
| 28242 | 27263 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 28243 | 27264 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| 28244 | 27265 | } |
| 28245 | const elem_ptr_val = try slice_val.ptrElem(index, pt); | |
| 28246 | return Air.internedToRef(elem_ptr_val.toIntern()); | |
| 27266 | return .fromValue(try slice_val.ptrElem(index, pt)); | |
| 28247 | 27267 | } |
| 28248 | 27268 | } |
| 28249 | 27269 | |
| ... | ... | @@ -28254,13 +27274,13 @@ fn elemPtrSlice( |
| 28254 | 27274 | const len_inst = len: { |
| 28255 | 27275 | if (maybe_undef_slice_val) |slice_val| |
| 28256 | 27276 | if (!slice_val.isUndef(zcu)) |
| 28257 | break :len try pt.intRef(.usize, try slice_val.sliceLen(pt)); | |
| 27277 | break :len try pt.intRef(.usize, slice_val.sliceLen(zcu)); | |
| 28258 | 27278 | break :len try block.addTyOp(.slice_len, .usize, slice); |
| 28259 | 27279 | }; |
| 28260 | 27280 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 28261 | 27281 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| 28262 | 27282 | } |
| 28263 | if (!try slice_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) { | |
| 27283 | if (elem_ty.abiSize(zcu) == 0) { | |
| 28264 | 27284 | // zero-bit child type; just extract the pointer and bitcast it |
| 28265 | 27285 | const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice); |
| 28266 | 27286 | return block.addBitCast(elem_ptr_ty, slice_ptr); |
| ... | ... | @@ -28331,15 +27351,17 @@ fn coerceExtra( |
| 28331 | 27351 | if (dest_ty.isGenericPoison()) return inst; |
| 28332 | 27352 | |
| 28333 | 27353 | const dest_ty_src = inst_src; // TODO better source location |
| 28334 | try dest_ty.resolveFields(pt); | |
| 28335 | 27354 | const inst_ty = sema.typeOf(inst); |
| 28336 | try inst_ty.resolveFields(pt); | |
| 28337 | 27355 | const target = zcu.getTarget(); |
| 27356 | ||
| 27357 | inst_ty.assertHasLayout(zcu); | |
| 27358 | try sema.ensureLayoutResolved(dest_ty, inst_src, .coerce); | |
| 27359 | ||
| 28338 | 27360 | // If the types are the same, we can return the operand. |
| 28339 | 27361 | if (dest_ty.eql(inst_ty, zcu)) |
| 28340 | 27362 | return inst; |
| 28341 | 27363 | |
| 28342 | const maybe_inst_val = try sema.resolveValue(inst); | |
| 27364 | const maybe_inst_val = sema.resolveValue(inst); | |
| 28343 | 27365 | |
| 28344 | 27366 | var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); |
| 28345 | 27367 | if (in_memory_result == .ok) { |
| ... | ... | @@ -28357,7 +27379,7 @@ fn coerceExtra( |
| 28357 | 27379 | if (maybe_inst_val) |val| { |
| 28358 | 27380 | // undefined sets the optional bit also to undefined. |
| 28359 | 27381 | if (val.toIntern() == .undef) { |
| 28360 | return pt.undefRef(dest_ty); | |
| 27382 | return .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)); | |
| 28361 | 27383 | } |
| 28362 | 27384 | |
| 28363 | 27385 | // null to ?T |
| ... | ... | @@ -28372,11 +27394,11 @@ fn coerceExtra( |
| 28372 | 27394 | // cast from ?*T and ?[*]T to ?*anyopaque |
| 28373 | 27395 | // but don't do it if the source type is a double pointer |
| 28374 | 27396 | if (dest_ty.isPtrLikeOptional(zcu) and |
| 28375 | dest_ty.elemType2(zcu).toIntern() == .anyopaque_type and | |
| 27397 | dest_ty.nullablePtrElem(zcu).toIntern() == .anyopaque_type and | |
| 28376 | 27398 | inst_ty.isPtrAtRuntime(zcu)) |
| 28377 | 27399 | anyopaque_check: { |
| 28378 | 27400 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional; |
| 28379 | const elem_ty = inst_ty.elemType2(zcu); | |
| 27401 | const elem_ty = inst_ty.nullablePtrElem(zcu); | |
| 28380 | 27402 | if (elem_ty.zigTypeTag(zcu) == .pointer or elem_ty.isPtrLikeOptional(zcu)) { |
| 28381 | 27403 | in_memory_result = .{ .double_ptr_to_anyopaque = .{ |
| 28382 | 27404 | .actual = inst_ty, |
| ... | ... | @@ -28409,7 +27431,7 @@ fn coerceExtra( |
| 28409 | 27431 | |
| 28410 | 27432 | // Function body to function pointer. |
| 28411 | 27433 | if (inst_ty.zigTypeTag(zcu) == .@"fn") { |
| 28412 | const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); | |
| 27434 | const fn_val = sema.resolveValue(inst).?; | |
| 28413 | 27435 | const fn_nav = switch (zcu.intern_pool.indexToKey(fn_val.toIntern())) { |
| 28414 | 27436 | .func => |f| f.owner_nav, |
| 28415 | 27437 | .@"extern" => |e| e.owner_nav, |
| ... | ... | @@ -28430,7 +27452,7 @@ fn coerceExtra( |
| 28430 | 27452 | const array_elem_ty = array_ty.childType(zcu); |
| 28431 | 27453 | if (array_ty.arrayLen(zcu) != 1) break :single_item; |
| 28432 | 27454 | const dest_is_mut = !dest_info.flags.is_const; |
| 28433 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { | |
| 27455 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { | |
| 28434 | 27456 | .ok => {}, |
| 28435 | 27457 | else => break :single_item, |
| 28436 | 27458 | } |
| ... | ... | @@ -28448,7 +27470,7 @@ fn coerceExtra( |
| 28448 | 27470 | const dest_is_mut = !dest_info.flags.is_const; |
| 28449 | 27471 | |
| 28450 | 27472 | const dst_elem_type: Type = .fromInterned(dest_info.child); |
| 28451 | const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val); | |
| 27473 | const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, null); | |
| 28452 | 27474 | switch (elem_res) { |
| 28453 | 27475 | .ok => {}, |
| 28454 | 27476 | else => { |
| ... | ... | @@ -28509,7 +27531,7 @@ fn coerceExtra( |
| 28509 | 27531 | const src_elem_ty = inst_ty.childType(zcu); |
| 28510 | 27532 | const dest_is_mut = !dest_info.flags.is_const; |
| 28511 | 27533 | const dst_elem_type: Type = .fromInterned(dest_info.child); |
| 28512 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { | |
| 27534 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { | |
| 28513 | 27535 | .ok => {}, |
| 28514 | 27536 | else => break :src_c_ptr, |
| 28515 | 27537 | } |
| ... | ... | @@ -28520,7 +27542,7 @@ fn coerceExtra( |
| 28520 | 27542 | // but don't do it if the source type is a double pointer |
| 28521 | 27543 | if (dest_info.child == .anyopaque_type and inst_ty.zigTypeTag(zcu) == .pointer) to_anyopaque: { |
| 28522 | 27544 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; |
| 28523 | const elem_ty = inst_ty.elemType2(zcu); | |
| 27545 | const elem_ty = inst_ty.childType(zcu); | |
| 28524 | 27546 | if (elem_ty.zigTypeTag(zcu) == .pointer or elem_ty.isPtrLikeOptional(zcu)) { |
| 28525 | 27547 | in_memory_result = .{ .double_ptr_to_anyopaque = .{ |
| 28526 | 27548 | .actual = inst_ty, |
| ... | ... | @@ -28580,7 +27602,7 @@ fn coerceExtra( |
| 28580 | 27602 | target, |
| 28581 | 27603 | dest_ty_src, |
| 28582 | 27604 | inst_src, |
| 28583 | maybe_inst_val, | |
| 27605 | null, | |
| 28584 | 27606 | )) { |
| 28585 | 27607 | .ok => {}, |
| 28586 | 27608 | else => break :p, |
| ... | ... | @@ -28616,16 +27638,14 @@ fn coerceExtra( |
| 28616 | 27638 | // empty tuple to zero-length slice |
| 28617 | 27639 | // note that this allows coercing to a mutable slice. |
| 28618 | 27640 | if (inst_child_ty.structFieldCount(zcu) == 0) { |
| 28619 | const align_val = try dest_ty.ptrAlignmentSema(pt); | |
| 28620 | return Air.internedToRef(try pt.intern(.{ .slice = .{ | |
| 28621 | .ty = dest_ty.toIntern(), | |
| 28622 | .ptr = try pt.intern(.{ .ptr = .{ | |
| 28623 | .ty = dest_ty.slicePtrFieldType(zcu).toIntern(), | |
| 28624 | .base_addr = .int, | |
| 28625 | .byte_offset = align_val.toByteUnits().?, | |
| 28626 | } }), | |
| 28627 | .len = .zero_usize, | |
| 28628 | } })); | |
| 27641 | const empty_array_ty = try pt.arrayType(.{ | |
| 27642 | .len = 0, | |
| 27643 | .child = dest_info.child, | |
| 27644 | .sentinel = dest_info.sentinel, | |
| 27645 | }); | |
| 27646 | const empty_array_val = try pt.aggregateValue(empty_array_ty, &.{}); | |
| 27647 | const empty_array_ptr = try sema.uavRef(empty_array_val); | |
| 27648 | return sema.coerceArrayPtrToSlice(block, dest_ty, empty_array_ptr, inst_src); | |
| 28629 | 27649 | } |
| 28630 | 27650 | |
| 28631 | 27651 | // pointer to tuple to slice |
| ... | ... | @@ -28653,7 +27673,7 @@ fn coerceExtra( |
| 28653 | 27673 | target, |
| 28654 | 27674 | dest_ty_src, |
| 28655 | 27675 | inst_src, |
| 28656 | maybe_inst_val, | |
| 27676 | null, | |
| 28657 | 27677 | )) { |
| 28658 | 27678 | .ok => {}, |
| 28659 | 27679 | else => break :p, |
| ... | ... | @@ -28684,12 +27704,12 @@ fn coerceExtra( |
| 28684 | 27704 | .int, .comptime_int => { |
| 28685 | 27705 | if (maybe_inst_val) |val| { |
| 28686 | 27706 | // comptime-known integer to other number |
| 28687 | if (!(try sema.intFitsInType(val, dest_ty, null))) { | |
| 27707 | if (!val.intFitsInType(dest_ty, null, zcu)) { | |
| 28688 | 27708 | if (!opts.report_err) return error.NotCoercible; |
| 28689 | 27709 | return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) }); |
| 28690 | 27710 | } |
| 28691 | 27711 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 28692 | .undef => try pt.undefRef(dest_ty), | |
| 27712 | .undef => .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)), | |
| 28693 | 27713 | .int => |int| Air.internedToRef( |
| 28694 | 27714 | try zcu.intern_pool.getCoercedInts(gpa, io, pt.tid, int, dest_ty.toIntern()), |
| 28695 | 27715 | ), |
| ... | ... | @@ -28717,7 +27737,7 @@ fn coerceExtra( |
| 28717 | 27737 | }, |
| 28718 | 27738 | .float, .comptime_float => switch (inst_ty.zigTypeTag(zcu)) { |
| 28719 | 27739 | .comptime_float => { |
| 28720 | const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); | |
| 27740 | const val = sema.resolveValue(inst).?; | |
| 28721 | 27741 | const result_val = try val.floatCast(dest_ty, pt); |
| 28722 | 27742 | return Air.internedToRef(result_val.toIntern()); |
| 28723 | 27743 | }, |
| ... | ... | @@ -28768,28 +27788,26 @@ fn coerceExtra( |
| 28768 | 27788 | } |
| 28769 | 27789 | break :int; |
| 28770 | 27790 | }; |
| 28771 | const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema); | |
| 28772 | const fits: bool = switch (ip.indexToKey(result_val.toIntern())) { | |
| 28773 | else => unreachable, | |
| 28774 | .undef => true, | |
| 28775 | .float => |float| fits: { | |
| 28776 | var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; | |
| 28777 | const operand_big_int = val.toBigInt(&buffer, zcu); | |
| 28778 | switch (float.storage) { | |
| 28779 | inline else => |x| { | |
| 28780 | if (!std.math.isFinite(x)) break :fits false; | |
| 28781 | var result_big_int: std.math.big.int.Mutable = .{ | |
| 28782 | .limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)), | |
| 28783 | .len = undefined, | |
| 28784 | .positive = undefined, | |
| 28785 | }; | |
| 28786 | switch (result_big_int.setFloat(x, .nearest_even)) { | |
| 28787 | .inexact => break :fits false, | |
| 28788 | .exact => {}, | |
| 28789 | } | |
| 28790 | break :fits result_big_int.toConst().eql(operand_big_int); | |
| 28791 | }, | |
| 27791 | if (val.isUndef(zcu)) { | |
| 27792 | return .fromValue(try pt.undefValue(dest_ty)); | |
| 27793 | } | |
| 27794 | const result_val = try pt.floatValue(dest_ty, val.toFloat(f128, zcu)); | |
| 27795 | const float = ip.indexToKey(result_val.toIntern()).float; | |
| 27796 | var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; | |
| 27797 | const operand_big_int = val.toBigInt(&buffer, zcu); | |
| 27798 | const fits = switch (float.storage) { | |
| 27799 | inline else => |x| fits: { | |
| 27800 | if (!std.math.isFinite(x)) break :fits false; | |
| 27801 | var result_big_int: std.math.big.int.Mutable = .{ | |
| 27802 | .limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)), | |
| 27803 | .len = undefined, | |
| 27804 | .positive = undefined, | |
| 27805 | }; | |
| 27806 | switch (result_big_int.setFloat(x, .nearest_even)) { | |
| 27807 | .inexact => break :fits false, | |
| 27808 | .exact => {}, | |
| 28792 | 27809 | } |
| 27810 | break :fits result_big_int.toConst().eql(operand_big_int); | |
| 28793 | 27811 | }, |
| 28794 | 27812 | }; |
| 28795 | 27813 | if (!fits) return sema.fail( |
| ... | ... | @@ -28805,7 +27823,7 @@ fn coerceExtra( |
| 28805 | 27823 | .@"enum" => switch (inst_ty.zigTypeTag(zcu)) { |
| 28806 | 27824 | .enum_literal => { |
| 28807 | 27825 | // enum literal to enum |
| 28808 | const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); | |
| 27826 | const val = sema.resolveValue(inst).?; | |
| 28809 | 27827 | const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; |
| 28810 | 27828 | const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { |
| 28811 | 27829 | return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{ |
| ... | ... | @@ -28814,33 +27832,36 @@ fn coerceExtra( |
| 28814 | 27832 | }; |
| 28815 | 27833 | return Air.internedToRef((try pt.enumValueFieldIndex(dest_ty, @intCast(field_index))).toIntern()); |
| 28816 | 27834 | }, |
| 28817 | .@"union" => blk: { | |
| 27835 | .@"union" => if (inst_ty.unionTagType(zcu)) |enum_tag_ty| { | |
| 28818 | 27836 | // union to its own tag type |
| 28819 | const union_tag_ty = inst_ty.unionTagType(zcu) orelse break :blk; | |
| 28820 | if (union_tag_ty.eql(dest_ty, zcu)) { | |
| 28821 | return sema.unionToTag(block, dest_ty, inst, inst_src); | |
| 27837 | if (enum_tag_ty.toIntern() == dest_ty.toIntern()) { | |
| 27838 | return sema.unionToTag(block, inst); | |
| 28822 | 27839 | } |
| 28823 | 27840 | }, |
| 28824 | 27841 | else => {}, |
| 28825 | 27842 | }, |
| 28826 | 27843 | .error_union => switch (inst_ty.zigTypeTag(zcu)) { |
| 28827 | .error_set => { | |
| 28828 | // E to E!T | |
| 28829 | return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src); | |
| 27844 | // E to E!T | |
| 27845 | .error_set => if (sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src)) |res| { | |
| 27846 | return res; | |
| 27847 | } else |err| switch (err) { | |
| 27848 | error.NotCoercible => if (in_memory_result == .no_match) { | |
| 27849 | // Try to give more useful notes | |
| 27850 | const err_set_type = dest_ty.errorUnionSet(zcu); | |
| 27851 | in_memory_result = try sema.coerceInMemoryAllowed(block, err_set_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); | |
| 27852 | }, | |
| 27853 | else => |e| return e, | |
| 28830 | 27854 | }, |
| 28831 | else => eu: { | |
| 28832 | // T to E!T | |
| 28833 | return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src) catch |err| switch (err) { | |
| 28834 | error.NotCoercible => { | |
| 28835 | if (in_memory_result == .no_match) { | |
| 28836 | const payload_type = dest_ty.errorUnionPayload(zcu); | |
| 28837 | // Try to give more useful notes | |
| 28838 | in_memory_result = try sema.coerceInMemoryAllowed(block, payload_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); | |
| 28839 | } | |
| 28840 | break :eu; | |
| 28841 | }, | |
| 28842 | else => |e| return e, | |
| 28843 | }; | |
| 27855 | // T to E!T | |
| 27856 | else => if (sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src)) |res| { | |
| 27857 | return res; | |
| 27858 | } else |err| switch (err) { | |
| 27859 | error.NotCoercible => if (in_memory_result == .no_match) { | |
| 27860 | // Try to give more useful notes | |
| 27861 | const payload_type = dest_ty.errorUnionPayload(zcu); | |
| 27862 | in_memory_result = try sema.coerceInMemoryAllowed(block, payload_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); | |
| 27863 | }, | |
| 27864 | else => |e| return e, | |
| 28844 | 27865 | }, |
| 28845 | 27866 | }, |
| 28846 | 27867 | .@"union" => switch (inst_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -28858,7 +27879,7 @@ fn coerceExtra( |
| 28858 | 27879 | target, |
| 28859 | 27880 | dest_ty_src, |
| 28860 | 27881 | inst_src, |
| 28861 | maybe_inst_val, | |
| 27882 | null, | |
| 28862 | 27883 | )) { |
| 28863 | 27884 | break :array_to_array; |
| 28864 | 27885 | } |
| ... | ... | @@ -28900,18 +27921,16 @@ fn coerceExtra( |
| 28900 | 27921 | else => {}, |
| 28901 | 27922 | } |
| 28902 | 27923 | |
| 28903 | const can_coerce_to = switch (dest_ty.zigTypeTag(zcu)) { | |
| 28904 | .noreturn, .@"opaque" => false, | |
| 28905 | else => true, | |
| 27924 | const dest_is_npv = switch (dest_ty.classify(zcu)) { | |
| 27925 | .no_possible_value => true, | |
| 27926 | .one_possible_value => if (inst == .undef) { | |
| 27927 | return .fromValue((try dest_ty.onePossibleValue(pt)).?); | |
| 27928 | } else false, | |
| 27929 | .runtime, .fully_comptime, .partially_comptime => if (inst == .undef) { | |
| 27930 | return .fromValue(try pt.undefValue(dest_ty)); | |
| 27931 | } else false, | |
| 28906 | 27932 | }; |
| 28907 | 27933 | |
| 28908 | if (can_coerce_to) { | |
| 28909 | // undefined to anything. We do this after the big switch above so that | |
| 28910 | // special logic has a chance to run first, such as `*[N]T` to `[]T` which | |
| 28911 | // should initialize the length field of the slice. | |
| 28912 | if (maybe_inst_val) |val| if (val.toIntern() == .undef) return pt.undefRef(dest_ty); | |
| 28913 | } | |
| 28914 | ||
| 28915 | 27934 | if (!opts.report_err) return error.NotCoercible; |
| 28916 | 27935 | |
| 28917 | 27936 | if (opts.is_ret and dest_ty.zigTypeTag(zcu) == .noreturn) { |
| ... | ... | @@ -28933,13 +27952,13 @@ fn coerceExtra( |
| 28933 | 27952 | const msg = try sema.typeMismatchErrMsg(inst_src, dest_ty, inst_ty); |
| 28934 | 27953 | errdefer msg.destroy(sema.gpa); |
| 28935 | 27954 | |
| 28936 | if (!can_coerce_to) { | |
| 28937 | try sema.errNote(inst_src, msg, "cannot coerce to '{f}'", .{dest_ty.fmt(pt)}); | |
| 27955 | if (dest_is_npv) { | |
| 27956 | try sema.errNote(inst_src, msg, "cannot coerce to uninstantiable type '{f}'", .{dest_ty.fmt(pt)}); | |
| 28938 | 27957 | } |
| 28939 | 27958 | |
| 28940 | 27959 | // E!T to T |
| 28941 | 27960 | if (inst_ty.zigTypeTag(zcu) == .error_union and |
| 28942 | (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok) | |
| 27961 | (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, null)) == .ok) | |
| 28943 | 27962 | { |
| 28944 | 27963 | try sema.errNote(inst_src, msg, "cannot convert error union to payload type", .{}); |
| 28945 | 27964 | try sema.errNote(inst_src, msg, "consider using 'try', 'catch', or 'if'", .{}); |
| ... | ... | @@ -28947,7 +27966,7 @@ fn coerceExtra( |
| 28947 | 27966 | |
| 28948 | 27967 | // ?T to T |
| 28949 | 27968 | if (inst_ty.zigTypeTag(zcu) == .optional and |
| 28950 | (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok) | |
| 27969 | (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, null)) == .ok) | |
| 28951 | 27970 | { |
| 28952 | 27971 | try sema.errNote(inst_src, msg, "cannot convert optional to payload type", .{}); |
| 28953 | 27972 | try sema.errNote(inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); |
| ... | ... | @@ -29394,6 +28413,10 @@ pub fn coerceInMemoryAllowed( |
| 29394 | 28413 | const pt = sema.pt; |
| 29395 | 28414 | const zcu = pt.zcu; |
| 29396 | 28415 | |
| 28416 | if (src_val) |val| { | |
| 28417 | assert(val.typeOf(zcu).toIntern() == src_ty.toIntern()); | |
| 28418 | } | |
| 28419 | ||
| 29397 | 28420 | if (dest_ty.eql(src_ty, zcu)) |
| 29398 | 28421 | return .ok; |
| 29399 | 28422 | |
| ... | ... | @@ -29428,7 +28451,7 @@ pub fn coerceInMemoryAllowed( |
| 29428 | 28451 | // Comptime int to regular int. |
| 29429 | 28452 | if (dest_tag == .int and src_tag == .comptime_int) { |
| 29430 | 28453 | if (src_val) |val| { |
| 29431 | if (!(try sema.intFitsInType(val, dest_ty, null))) { | |
| 28454 | if (!val.intFitsInType(dest_ty, null, zcu)) { | |
| 29432 | 28455 | return .{ .comptime_int_not_coercible = .{ .wanted = dest_ty, .actual = val } }; |
| 29433 | 28456 | } |
| 29434 | 28457 | } |
| ... | ... | @@ -29444,17 +28467,13 @@ pub fn coerceInMemoryAllowed( |
| 29444 | 28467 | } |
| 29445 | 28468 | |
| 29446 | 28469 | // Pointers / Pointer-like Optionals |
| 29447 | const maybe_dest_ptr_ty = try sema.typePtrOrOptionalPtrTy(dest_ty); | |
| 29448 | const maybe_src_ptr_ty = try sema.typePtrOrOptionalPtrTy(src_ty); | |
| 29449 | if (maybe_dest_ptr_ty) |dest_ptr_ty| { | |
| 29450 | if (maybe_src_ptr_ty) |src_ptr_ty| { | |
| 29451 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target, dest_src, src_src); | |
| 29452 | } | |
| 28470 | if (dest_ty.isPtrAtRuntime(zcu) and src_ty.isPtrAtRuntime(zcu)) { | |
| 28471 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); | |
| 29453 | 28472 | } |
| 29454 | 28473 | |
| 29455 | 28474 | // Slices |
| 29456 | 28475 | if (dest_ty.isSlice(zcu) and src_ty.isSlice(zcu)) { |
| 29457 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); | |
| 28476 | return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); | |
| 29458 | 28477 | } |
| 29459 | 28478 | |
| 29460 | 28479 | // Functions |
| ... | ... | @@ -29554,7 +28573,8 @@ pub fn coerceInMemoryAllowed( |
| 29554 | 28573 | |
| 29555 | 28574 | // Optionals |
| 29556 | 28575 | if (dest_tag == .optional and src_tag == .optional) { |
| 29557 | if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) { | |
| 28576 | if (dest_ty.isPtrAtRuntime(zcu) or src_ty.isPtrAtRuntime(zcu)) { | |
| 28577 | // Only one is, because we already handled when both are. | |
| 29558 | 28578 | return .{ .optional_shape = .{ |
| 29559 | 28579 | .actual = src_ty, |
| 29560 | 28580 | .wanted = dest_ty, |
| ... | ... | @@ -29581,7 +28601,6 @@ pub fn coerceInMemoryAllowed( |
| 29581 | 28601 | const field_count = dest_ty.structFieldCount(zcu); |
| 29582 | 28602 | for (0..field_count) |field_idx| { |
| 29583 | 28603 | if (dest_ty.structFieldIsComptime(field_idx, zcu) != src_ty.structFieldIsComptime(field_idx, zcu)) break :tuple; |
| 29584 | if (dest_ty.fieldAlignment(field_idx, zcu) != src_ty.fieldAlignment(field_idx, zcu)) break :tuple; | |
| 29585 | 28604 | const dest_field_ty = dest_ty.fieldType(field_idx, zcu); |
| 29586 | 28605 | const src_field_ty = src_ty.fieldType(field_idx, zcu); |
| 29587 | 28606 | const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src, null); |
| ... | ... | @@ -29609,89 +28628,62 @@ fn coerceInMemoryAllowedErrorSets( |
| 29609 | 28628 | const gpa = sema.gpa; |
| 29610 | 28629 | const ip = &zcu.intern_pool; |
| 29611 | 28630 | |
| 29612 | // Coercion to `anyerror`. Note that this check can return false negatives | |
| 29613 | // in case the error sets did not get resolved. | |
| 29614 | if (dest_ty.isAnyError(zcu)) { | |
| 29615 | return .ok; | |
| 29616 | } | |
| 29617 | ||
| 29618 | if (dest_ty.toIntern() == .adhoc_inferred_error_set_type) { | |
| 29619 | // We are trying to coerce an error set to the current function's | |
| 29620 | // inferred error set. | |
| 29621 | const dst_ies = sema.fn_ret_ty_ies.?; | |
| 29622 | try dst_ies.addErrorSet(src_ty, ip, sema.arena); | |
| 29623 | return .ok; | |
| 29624 | } | |
| 29625 | ||
| 29626 | if (ip.isInferredErrorSetType(dest_ty.toIntern())) { | |
| 29627 | const dst_ies_func_index = ip.iesFuncIndex(dest_ty.toIntern()); | |
| 29628 | if (sema.fn_ret_ty_ies) |dst_ies| { | |
| 29629 | if (dst_ies.func == dst_ies_func_index) { | |
| 29630 | // We are trying to coerce an error set to the current function's | |
| 29631 | // inferred error set. | |
| 29632 | try dst_ies.addErrorSet(src_ty, ip, sema.arena); | |
| 29633 | return .ok; | |
| 29634 | } | |
| 29635 | } | |
| 29636 | switch (try sema.resolveInferredErrorSet(block, dest_src, dest_ty.toIntern())) { | |
| 29637 | // isAnyError might have changed from a false negative to a true | |
| 29638 | // positive after resolution. | |
| 29639 | .anyerror_type => return .ok, | |
| 29640 | else => {}, | |
| 29641 | } | |
| 29642 | } | |
| 29643 | ||
| 29644 | var missing_error_buf = std.array_list.Managed(InternPool.NullTerminatedString).init(gpa); | |
| 29645 | defer missing_error_buf.deinit(); | |
| 29646 | ||
| 29647 | switch (src_ty.toIntern()) { | |
| 29648 | .anyerror_type => switch (ip.indexToKey(dest_ty.toIntern())) { | |
| 29649 | .simple_type => unreachable, // filtered out above | |
| 29650 | .error_set_type, .inferred_error_set_type => return .from_anyerror, | |
| 29651 | else => unreachable, | |
| 28631 | const dest_set: InternPool.Key.ErrorSetType = err_set: switch (dest_ty.toIntern()) { | |
| 28632 | .anyerror_type => return .ok, | |
| 28633 | .adhoc_inferred_error_set_type => { | |
| 28634 | // We are trying to coerce an error set to the current function's | |
| 28635 | // inferred error set. | |
| 28636 | const dst_ies = sema.fn_ret_ty_ies.?; | |
| 28637 | try dst_ies.addErrorSet(src_ty, ip, sema.arena); | |
| 28638 | return .ok; | |
| 29652 | 28639 | }, |
| 29653 | ||
| 29654 | else => switch (ip.indexToKey(src_ty.toIntern())) { | |
| 29655 | .inferred_error_set_type => { | |
| 29656 | const resolved_src_ty = try sema.resolveInferredErrorSet(block, src_src, src_ty.toIntern()); | |
| 29657 | // src anyerror status might have changed after the resolution. | |
| 29658 | if (resolved_src_ty == .anyerror_type) { | |
| 29659 | // dest_ty.isAnyError(zcu) == true is already checked for at this point. | |
| 29660 | return .from_anyerror; | |
| 29661 | } | |
| 29662 | ||
| 29663 | for (ip.indexToKey(resolved_src_ty).error_set_type.names.get(ip)) |key| { | |
| 29664 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) { | |
| 29665 | try missing_error_buf.append(key); | |
| 28640 | else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { | |
| 28641 | .inferred_error_set_type => |func_index| { | |
| 28642 | if (sema.fn_ret_ty_ies) |dst_ies| { | |
| 28643 | if (dst_ies.func == func_index) { | |
| 28644 | // We are trying to coerce an error set to the current function's | |
| 28645 | // inferred error set. | |
| 28646 | try dst_ies.addErrorSet(src_ty, ip, sema.arena); | |
| 28647 | return .ok; | |
| 29666 | 28648 | } |
| 29667 | 28649 | } |
| 29668 | ||
| 29669 | if (missing_error_buf.items.len != 0) { | |
| 29670 | return InMemoryCoercionResult{ | |
| 29671 | .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items), | |
| 29672 | }; | |
| 29673 | } | |
| 29674 | ||
| 29675 | return .ok; | |
| 28650 | try sema.ensureFuncIesResolved(block, dest_src, func_index); | |
| 28651 | continue :err_set ip.funcIesResolvedUnordered(func_index); | |
| 29676 | 28652 | }, |
| 29677 | .error_set_type => |error_set_type| { | |
| 29678 | for (error_set_type.names.get(ip)) |name| { | |
| 29679 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) { | |
| 29680 | try missing_error_buf.append(name); | |
| 29681 | } | |
| 29682 | } | |
| 29683 | ||
| 29684 | if (missing_error_buf.items.len != 0) { | |
| 29685 | return InMemoryCoercionResult{ | |
| 29686 | .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items), | |
| 29687 | }; | |
| 29688 | } | |
| 28653 | .error_set_type => |err_set| err_set, | |
| 28654 | else => unreachable, | |
| 28655 | }, | |
| 28656 | }; | |
| 29689 | 28657 | |
| 29690 | return .ok; | |
| 28658 | const src_names: InternPool.NullTerminatedString.Slice = err_set: switch (src_ty.toIntern()) { | |
| 28659 | .anyerror_type => return .from_anyerror, | |
| 28660 | else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { | |
| 28661 | .inferred_error_set_type => |func_index| { | |
| 28662 | try sema.ensureFuncIesResolved(block, src_src, func_index); | |
| 28663 | continue :err_set ip.funcIesResolvedUnordered(func_index); | |
| 29691 | 28664 | }, |
| 28665 | .error_set_type => |err_set| err_set.names, | |
| 29692 | 28666 | else => unreachable, |
| 29693 | 28667 | }, |
| 28668 | }; | |
| 28669 | ||
| 28670 | var missing_error_buf: std.ArrayList(InternPool.NullTerminatedString) = .empty; | |
| 28671 | defer missing_error_buf.deinit(gpa); | |
| 28672 | ||
| 28673 | for (src_names.get(ip)) |name| { | |
| 28674 | if (dest_set.nameIndex(ip, name) == null) { | |
| 28675 | try missing_error_buf.append(gpa, name); | |
| 28676 | } | |
| 28677 | } | |
| 28678 | ||
| 28679 | if (missing_error_buf.items.len != 0) { | |
| 28680 | return .{ .missing_error = try sema.arena.dupe( | |
| 28681 | InternPool.NullTerminatedString, | |
| 28682 | missing_error_buf.items, | |
| 28683 | ) }; | |
| 29694 | 28684 | } |
| 28685 | ||
| 28686 | return .ok; | |
| 29695 | 28687 | } |
| 29696 | 28688 | |
| 29697 | 28689 | fn coerceInMemoryAllowedFns( |
| ... | ... | @@ -29714,11 +28706,7 @@ fn coerceInMemoryAllowedFns( |
| 29714 | 28706 | |
| 29715 | 28707 | { |
| 29716 | 28708 | if (dest_info.is_var_args != src_info.is_var_args) { |
| 29717 | return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; | |
| 29718 | } | |
| 29719 | ||
| 29720 | if (dest_info.is_generic != src_info.is_generic) { | |
| 29721 | return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic }; | |
| 28709 | return .{ .fn_var_args = dest_info.is_var_args }; | |
| 29722 | 28710 | } |
| 29723 | 28711 | |
| 29724 | 28712 | const callconv_ok = callconvCoerceAllowed(target, src_info.cc, dest_info.cc) and |
| ... | ... | @@ -29731,6 +28719,12 @@ fn coerceInMemoryAllowedFns( |
| 29731 | 28719 | } }; |
| 29732 | 28720 | } |
| 29733 | 28721 | |
| 28722 | try sema.ensureLayoutResolved(src_ty, src_src, .coerce); | |
| 28723 | try sema.ensureLayoutResolved(dest_ty, dest_src, .coerce); | |
| 28724 | const src_is_runtime = src_ty.fnHasRuntimeBits(zcu); | |
| 28725 | const dest_is_runtime = dest_ty.fnHasRuntimeBits(zcu); | |
| 28726 | if (src_is_runtime != dest_is_runtime) return .{ .fn_generic = !dest_is_runtime }; | |
| 28727 | ||
| 29734 | 28728 | if (!switch (src_info.return_type) { |
| 29735 | 28729 | .generic_poison_type => true, |
| 29736 | 28730 | .noreturn_type => !dest_is_mut, |
| ... | ... | @@ -29780,7 +28774,7 @@ fn coerceInMemoryAllowedFns( |
| 29780 | 28774 | const src_is_comptime = src_info.paramIsComptime(@intCast(param_i)); |
| 29781 | 28775 | const dest_is_comptime = dest_info.paramIsComptime(@intCast(param_i)); |
| 29782 | 28776 | if (src_is_comptime == dest_is_comptime) break :comptime_param; |
| 29783 | if (!dest_is_mut and src_is_comptime and !dest_is_comptime and try dest_param_ty.comptimeOnlySema(pt)) { | |
| 28777 | if (!dest_is_mut and src_is_comptime and !dest_is_comptime and dest_param_ty.comptimeOnly(zcu)) { | |
| 29784 | 28778 | // A parameter which is marked `comptime` can drop that annotation if the type is comptime-only. |
| 29785 | 28779 | // The function remains generic, and the parameter is going to be comptime-resolved either way, |
| 29786 | 28780 | // so this just affects whether or not the argument is comptime-evaluated at the call site. |
| ... | ... | @@ -29861,8 +28855,6 @@ fn coerceInMemoryAllowedPtrs( |
| 29861 | 28855 | block: *Block, |
| 29862 | 28856 | dest_ty: Type, |
| 29863 | 28857 | src_ty: Type, |
| 29864 | dest_ptr_ty: Type, | |
| 29865 | src_ptr_ty: Type, | |
| 29866 | 28858 | /// If set, the coercion must be valid in both directions. |
| 29867 | 28859 | dest_is_mut: bool, |
| 29868 | 28860 | target: *const std.Target, |
| ... | ... | @@ -29875,8 +28867,8 @@ fn coerceInMemoryAllowedPtrs( |
| 29875 | 28867 | const gpa = comp.gpa; |
| 29876 | 28868 | const io = comp.io; |
| 29877 | 28869 | |
| 29878 | const dest_info = dest_ptr_ty.ptrInfo(zcu); | |
| 29879 | const src_info = src_ptr_ty.ptrInfo(zcu); | |
| 28870 | const dest_info = dest_ty.ptrInfo(zcu); | |
| 28871 | const src_info = src_ty.ptrInfo(zcu); | |
| 29880 | 28872 | |
| 29881 | 28873 | const ok_ptr_size = src_info.flags.size == dest_info.flags.size or |
| 29882 | 28874 | src_info.flags.size == .c or dest_info.flags.size == .c; |
| ... | ... | @@ -30008,16 +29000,14 @@ fn coerceInMemoryAllowedPtrs( |
| 30008 | 29000 | if (src_info.flags.alignment != .none or dest_info.flags.alignment != .none or |
| 30009 | 29001 | dest_info.child != src_info.child) |
| 30010 | 29002 | { |
| 30011 | const src_align = if (src_info.flags.alignment != .none) | |
| 30012 | src_info.flags.alignment | |
| 30013 | else | |
| 30014 | try Type.fromInterned(src_info.child).abiAlignmentSema(pt); | |
| 30015 | ||
| 30016 | const dest_align = if (dest_info.flags.alignment != .none) | |
| 30017 | dest_info.flags.alignment | |
| 30018 | else | |
| 30019 | try Type.fromInterned(dest_info.child).abiAlignmentSema(pt); | |
| 30020 | ||
| 29003 | const src_align = if (src_info.flags.alignment == .none) a: { | |
| 29004 | try sema.ensureLayoutResolved(src_child, src_src, .align_check); | |
| 29005 | break :a src_child.abiAlignment(zcu); | |
| 29006 | } else src_info.flags.alignment; | |
| 29007 | const dest_align = if (dest_info.flags.alignment == .none) a: { | |
| 29008 | try sema.ensureLayoutResolved(dest_child, dest_src, .align_check); | |
| 29009 | break :a dest_child.abiAlignment(zcu); | |
| 29010 | } else dest_info.flags.alignment; | |
| 30021 | 29011 | if (dest_align.compare(if (dest_is_mut) .neq else .gt, src_align)) { |
| 30022 | 29012 | return InMemoryCoercionResult{ .ptr_alignment = .{ |
| 30023 | 29013 | .actual = src_align, |
| ... | ... | @@ -30049,7 +29039,7 @@ fn coerceVarArgParam( |
| 30049 | 29039 | .{}, |
| 30050 | 29040 | ), |
| 30051 | 29041 | .@"fn" => fn_ptr: { |
| 30052 | const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); | |
| 29042 | const fn_val = sema.resolveValue(inst).?; | |
| 30053 | 29043 | const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav; |
| 30054 | 29044 | break :fn_ptr try sema.analyzeNavRef(block, inst_src, fn_nav); |
| 30055 | 29045 | }, |
| ... | ... | @@ -30066,7 +29056,7 @@ fn coerceVarArgParam( |
| 30066 | 29056 | } |
| 30067 | 29057 | }, |
| 30068 | 29058 | else => if (uncasted_ty.isAbiInt(zcu)) int: { |
| 30069 | if (!try sema.validateExternType(uncasted_ty, .param_ty)) break :int inst; | |
| 29059 | if (!uncasted_ty.validateExtern(.param_ty, zcu)) break :int inst; | |
| 30070 | 29060 | const target = zcu.getTarget(); |
| 30071 | 29061 | const uncasted_info = uncasted_ty.intInfo(zcu); |
| 30072 | 29062 | if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { |
| ... | ... | @@ -30095,7 +29085,7 @@ fn coerceVarArgParam( |
| 30095 | 29085 | }; |
| 30096 | 29086 | |
| 30097 | 29087 | const coerced_ty = sema.typeOf(coerced); |
| 30098 | if (!try sema.validateExternType(coerced_ty, .param_ty)) { | |
| 29088 | if (!coerced_ty.validateExtern(.param_ty, zcu)) { | |
| 30099 | 29089 | const msg = msg: { |
| 30100 | 29090 | const msg = try sema.errMsg(inst_src, "cannot pass '{f}' to variadic function", .{coerced_ty.fmt(pt)}); |
| 30101 | 29091 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -30140,38 +29130,20 @@ fn storePtr2( |
| 30140 | 29130 | |
| 30141 | 29131 | const elem_ty = ptr_ty.childType(zcu); |
| 30142 | 29132 | |
| 30143 | // To generate better code for tuples, we detect a tuple operand here, and | |
| 30144 | // analyze field loads and stores directly. This avoids an extra allocation + memcpy | |
| 30145 | // which would occur if we used `coerce`. | |
| 30146 | // However, we avoid this mechanism if the destination element type is a tuple, | |
| 30147 | // because the regular store will be better for this case. | |
| 30148 | // If the destination type is a struct we don't want this mechanism to trigger, because | |
| 30149 | // this code does not handle tuple-to-struct coercion which requires dealing with missing | |
| 30150 | // fields. | |
| 30151 | const operand_ty = sema.typeOf(uncasted_operand); | |
| 30152 | if (operand_ty.isTuple(zcu) and elem_ty.zigTypeTag(zcu) == .array) { | |
| 30153 | const field_count = operand_ty.structFieldCount(zcu); | |
| 30154 | var i: u32 = 0; | |
| 30155 | while (i < field_count) : (i += 1) { | |
| 30156 | const elem_src = operand_src; // TODO better source location | |
| 30157 | const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i); | |
| 30158 | const elem_index = try pt.intRef(.usize, i); | |
| 30159 | const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false, true); | |
| 30160 | try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store); | |
| 30161 | } | |
| 30162 | return; | |
| 30163 | } | |
| 30164 | ||
| 30165 | // TODO do the same thing for anon structs as for tuples above. | |
| 30166 | // However, beware of the need to handle missing/extra fields. | |
| 30167 | ||
| 30168 | 29133 | const is_ret = air_tag == .ret_ptr; |
| 30169 | 29134 | |
| 30170 | 29135 | const operand = sema.coerceExtra(block, elem_ty, uncasted_operand, operand_src, .{ .is_ret = is_ret }) catch |err| switch (err) { |
| 30171 | 29136 | error.NotCoercible => unreachable, |
| 30172 | 29137 | else => |e| return e, |
| 30173 | 29138 | }; |
| 30174 | const maybe_operand_val = try sema.resolveValue(operand); | |
| 29139 | const maybe_operand_val = sema.resolveValue(operand); | |
| 29140 | ||
| 29141 | const comptime_only = switch (elem_ty.classify(zcu)) { | |
| 29142 | .no_possible_value => unreachable, // the coercion should have failed | |
| 29143 | .one_possible_value => return, // no actual store operation is necessary | |
| 29144 | .runtime => false, | |
| 29145 | .partially_comptime, .fully_comptime => true, | |
| 29146 | }; | |
| 30175 | 29147 | |
| 30176 | 29148 | const runtime_src = rs: { |
| 30177 | 29149 | const ptr_val = try sema.resolveDefinedValue(block, ptr_src, ptr) orelse break :rs ptr_src; |
| ... | ... | @@ -30180,22 +29152,13 @@ fn storePtr2( |
| 30180 | 29152 | return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); |
| 30181 | 29153 | }; |
| 30182 | 29154 | |
| 30183 | // We're performing the store at runtime; as such, we need to make sure the pointee type | |
| 30184 | // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer. | |
| 30185 | if (try elem_ty.comptimeOnlySema(pt)) { | |
| 30186 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 30187 | const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)}); | |
| 30188 | errdefer msg.destroy(sema.gpa); | |
| 30189 | try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{}); | |
| 30190 | break :msg msg; | |
| 30191 | }); | |
| 30192 | } | |
| 30193 | ||
| 30194 | // We do this after the possible comptime store above, for the case of field_ptr stores | |
| 30195 | // to unions because we want the comptime tag to be set, even if the field type is void. | |
| 30196 | if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) { | |
| 30197 | return; | |
| 30198 | } | |
| 29155 | // We're performing the store at runtime, so the pointee type must not be comptime-only. | |
| 29156 | if (comptime_only) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 29157 | const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)}); | |
| 29158 | errdefer msg.destroy(sema.gpa); | |
| 29159 | try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{}); | |
| 29160 | break :msg msg; | |
| 29161 | }); | |
| 30199 | 29162 | |
| 30200 | 29163 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 30201 | 29164 | |
| ... | ... | @@ -30223,7 +29186,7 @@ fn checkComptimeKnownStore(sema: *Sema, block: *Block, store_inst_ref: Air.Inst. |
| 30223 | 29186 | const maybe_base_alloc = sema.base_allocs.get(ptr) orelse break :known; |
| 30224 | 29187 | const maybe_comptime_alloc = sema.maybe_comptime_allocs.getPtr(maybe_base_alloc) orelse break :known; |
| 30225 | 29188 | |
| 30226 | if ((try sema.resolveValue(operand)) != null and | |
| 29189 | if (sema.resolveValue(operand) != null and | |
| 30227 | 29190 | block.runtime_index == maybe_comptime_alloc.runtime_index) |
| 30228 | 29191 | { |
| 30229 | 29192 | try maybe_comptime_alloc.stores.append(sema.arena, .{ |
| ... | ... | @@ -30272,7 +29235,7 @@ fn checkKnownAllocPtr(sema: *Sema, block: *Block, base_ptr: Air.Inst.Ref, new_pt |
| 30272 | 29235 | |
| 30273 | 29236 | // If the index value is runtime-known, this pointer is also runtime-known, so |
| 30274 | 29237 | // we must in turn make the alloc value runtime-known. |
| 30275 | if (null == try sema.resolveValue(index_ref)) { | |
| 29238 | if (null == sema.resolveValue(index_ref)) { | |
| 30276 | 29239 | try sema.markMaybeComptimeAllocRuntime(block, alloc_inst); |
| 30277 | 29240 | } |
| 30278 | 29241 | }, |
| ... | ... | @@ -30361,10 +29324,10 @@ fn bitCast( |
| 30361 | 29324 | ) CompileError!Air.Inst.Ref { |
| 30362 | 29325 | const pt = sema.pt; |
| 30363 | 29326 | const zcu = pt.zcu; |
| 30364 | try dest_ty.resolveLayout(pt); | |
| 30365 | ||
| 30366 | 29327 | const old_ty = sema.typeOf(inst); |
| 30367 | try old_ty.resolveLayout(pt); | |
| 29328 | ||
| 29329 | old_ty.assertHasLayout(zcu); | |
| 29330 | try sema.ensureLayoutResolved(dest_ty, inst_src, .init); | |
| 30368 | 29331 | |
| 30369 | 29332 | const dest_bits = dest_ty.bitSize(zcu); |
| 30370 | 29333 | const old_bits = old_ty.bitSize(zcu); |
| ... | ... | @@ -30378,7 +29341,7 @@ fn bitCast( |
| 30378 | 29341 | }); |
| 30379 | 29342 | } |
| 30380 | 29343 | |
| 30381 | if (try sema.resolveValue(inst)) |val| { | |
| 29344 | if (sema.resolveValue(inst)) |val| { | |
| 30382 | 29345 | if (val.isUndef(zcu)) |
| 30383 | 29346 | return pt.undefRef(dest_ty); |
| 30384 | 29347 | if (old_ty.zigTypeTag(zcu) == .error_set and dest_ty.zigTypeTag(zcu) == .error_set) { |
| ... | ... | @@ -30404,7 +29367,7 @@ fn coerceArrayPtrToSlice( |
| 30404 | 29367 | ) CompileError!Air.Inst.Ref { |
| 30405 | 29368 | const pt = sema.pt; |
| 30406 | 29369 | const zcu = pt.zcu; |
| 30407 | if (try sema.resolveValue(inst)) |val| { | |
| 29370 | if (sema.resolveValue(inst)) |val| { | |
| 30408 | 29371 | const ptr_array_ty = sema.typeOf(inst); |
| 30409 | 29372 | const array_ty = ptr_array_ty.childType(zcu); |
| 30410 | 29373 | const slice_ptr_ty = dest_ty.slicePtrFieldType(zcu); |
| ... | ... | @@ -30499,7 +29462,7 @@ fn coerceCompatiblePtrs( |
| 30499 | 29462 | const pt = sema.pt; |
| 30500 | 29463 | const zcu = pt.zcu; |
| 30501 | 29464 | const inst_ty = sema.typeOf(inst); |
| 30502 | if (try sema.resolveValue(inst)) |val| { | |
| 29465 | if (sema.resolveValue(inst)) |val| { | |
| 30503 | 29466 | if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) { |
| 30504 | 29467 | return sema.fail(block, inst_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)}); |
| 30505 | 29468 | } |
| ... | ... | @@ -30510,9 +29473,7 @@ fn coerceCompatiblePtrs( |
| 30510 | 29473 | } |
| 30511 | 29474 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 30512 | 29475 | const inst_allows_zero = inst_ty.zigTypeTag(zcu) != .pointer or inst_ty.ptrAllowsZero(zcu); |
| 30513 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu) and | |
| 30514 | (try dest_ty.elemType2(zcu).hasRuntimeBitsSema(pt) or dest_ty.elemType2(zcu).zigTypeTag(zcu) == .@"fn")) | |
| 30515 | { | |
| 29476 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu)) { | |
| 30516 | 29477 | try sema.checkLogicalPtrOperation(block, inst_src, inst_ty); |
| 30517 | 29478 | const actual_ptr = if (inst_ty.isSlice(zcu)) |
| 30518 | 29479 | try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty) |
| ... | ... | @@ -30532,6 +29493,7 @@ fn coerceCompatiblePtrs( |
| 30532 | 29493 | return new_ptr; |
| 30533 | 29494 | } |
| 30534 | 29495 | |
| 29496 | /// Asserts that the layout of `union_ty` is already resolved. | |
| 30535 | 29497 | fn coerceEnumToUnion( |
| 30536 | 29498 | sema: *Sema, |
| 30537 | 29499 | block: *Block, |
| ... | ... | @@ -30545,18 +29507,21 @@ fn coerceEnumToUnion( |
| 30545 | 29507 | const ip = &zcu.intern_pool; |
| 30546 | 29508 | const inst_ty = sema.typeOf(inst); |
| 30547 | 29509 | |
| 30548 | const tag_ty = union_ty.unionTagType(zcu) orelse { | |
| 30549 | const msg = msg: { | |
| 30550 | const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty); | |
| 30551 | errdefer msg.destroy(sema.gpa); | |
| 30552 | try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{}); | |
| 30553 | try sema.addDeclaredHereNote(msg, union_ty); | |
| 30554 | break :msg msg; | |
| 30555 | }; | |
| 30556 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 30557 | }; | |
| 29510 | union_ty.assertHasLayout(zcu); | |
| 29511 | ||
| 29512 | const union_obj = zcu.typeToUnion(union_ty).?; | |
| 29513 | const enum_ty: Type = .fromInterned(union_obj.enum_tag_type); | |
| 29514 | const enum_obj = ip.loadEnumType(enum_ty.toIntern()); | |
| 29515 | ||
| 29516 | if (union_obj.tag_usage != .tagged) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 29517 | const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty); | |
| 29518 | errdefer msg.destroy(sema.gpa); | |
| 29519 | try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{}); | |
| 29520 | try sema.addDeclaredHereNote(msg, union_ty); | |
| 29521 | break :msg msg; | |
| 29522 | }); | |
| 30558 | 29523 | |
| 30559 | const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); | |
| 29524 | const enum_tag = try sema.coerce(block, enum_ty, inst, inst_src); | |
| 30560 | 29525 | if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { |
| 30561 | 29526 | const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse { |
| 30562 | 29527 | return sema.fail(block, inst_src, "union '{f}' has no tag with value '{f}'", .{ |
| ... | ... | @@ -30564,101 +29529,88 @@ fn coerceEnumToUnion( |
| 30564 | 29529 | }); |
| 30565 | 29530 | }; |
| 30566 | 29531 | |
| 30567 | const union_obj = zcu.typeToUnion(union_ty).?; | |
| 29532 | const field_name = enum_obj.field_names.get(ip)[field_index]; | |
| 30568 | 29533 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 30569 | try field_ty.resolveFields(pt); | |
| 30570 | if (field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 30571 | const msg = msg: { | |
| 30572 | const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{}); | |
| 29534 | switch (field_ty.classify(zcu)) { | |
| 29535 | .one_possible_value => return .fromValue(try pt.unionValue( | |
| 29536 | union_ty, | |
| 29537 | val, | |
| 29538 | (try field_ty.onePossibleValue(pt)).?, | |
| 29539 | )), | |
| 29540 | ||
| 29541 | .no_possible_value => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 29542 | const msg = try sema.errMsg(inst_src, "cannot initialize union field with uninstantiable type '{f}'", .{field_ty.fmt(pt)}); | |
| 30573 | 29543 | errdefer msg.destroy(sema.gpa); |
| 30574 | ||
| 30575 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | |
| 30576 | 29544 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ |
| 30577 | 29545 | field_name.fmt(ip), |
| 30578 | 29546 | }); |
| 30579 | 29547 | try sema.addDeclaredHereNote(msg, union_ty); |
| 30580 | 29548 | break :msg msg; |
| 30581 | }; | |
| 30582 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 30583 | } | |
| 30584 | const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse { | |
| 30585 | const msg = msg: { | |
| 30586 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | |
| 29549 | }), | |
| 29550 | ||
| 29551 | else => return sema.failWithOwnedErrorMsg(block, msg: { | |
| 30587 | 29552 | const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{ |
| 30588 | 29553 | inst_ty.fmt(pt), union_ty.fmt(pt), |
| 30589 | 29554 | field_ty.fmt(pt), field_name.fmt(ip), |
| 30590 | 29555 | }); |
| 30591 | 29556 | errdefer msg.destroy(sema.gpa); |
| 30592 | 29557 | |
| 30593 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ | |
| 30594 | field_name.fmt(ip), | |
| 30595 | }); | |
| 29558 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{field_name.fmt(ip)}); | |
| 30596 | 29559 | try sema.addDeclaredHereNote(msg, union_ty); |
| 30597 | 29560 | break :msg msg; |
| 30598 | }; | |
| 30599 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 30600 | }; | |
| 30601 | ||
| 30602 | return Air.internedToRef((try pt.unionValue(union_ty, val, opv)).toIntern()); | |
| 29561 | }), | |
| 29562 | } | |
| 30603 | 29563 | } |
| 30604 | 29564 | |
| 30605 | 29565 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 30606 | 29566 | |
| 30607 | if (tag_ty.isNonexhaustiveEnum(zcu)) { | |
| 29567 | if (enum_ty.isNonexhaustiveEnum(zcu)) { | |
| 30608 | 29568 | const msg = msg: { |
| 30609 | 29569 | const msg = try sema.errMsg(inst_src, "runtime coercion to union '{f}' from non-exhaustive enum", .{ |
| 30610 | 29570 | union_ty.fmt(pt), |
| 30611 | 29571 | }); |
| 30612 | 29572 | errdefer msg.destroy(sema.gpa); |
| 30613 | try sema.addDeclaredHereNote(msg, tag_ty); | |
| 29573 | try sema.addDeclaredHereNote(msg, enum_ty); | |
| 30614 | 29574 | break :msg msg; |
| 30615 | 29575 | }; |
| 30616 | 29576 | return sema.failWithOwnedErrorMsg(block, msg); |
| 30617 | 29577 | } |
| 30618 | 29578 | |
| 30619 | const union_obj = zcu.typeToUnion(union_ty).?; | |
| 30620 | { | |
| 30621 | var msg: ?*Zcu.ErrorMsg = null; | |
| 30622 | errdefer if (msg) |some| some.destroy(sema.gpa); | |
| 30623 | ||
| 30624 | for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| { | |
| 30625 | if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) { | |
| 30626 | const err_msg = msg orelse try sema.errMsg( | |
| 30627 | inst_src, | |
| 30628 | "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field", | |
| 30629 | .{ tag_ty.fmt(pt), union_ty.fmt(pt) }, | |
| 30630 | ); | |
| 30631 | msg = err_msg; | |
| 30632 | ||
| 30633 | try sema.addFieldErrNote(union_ty, field_index, err_msg, "'noreturn' field here", .{}); | |
| 30634 | } | |
| 30635 | } | |
| 30636 | if (msg) |some| { | |
| 30637 | msg = null; | |
| 30638 | try sema.addDeclaredHereNote(some, union_ty); | |
| 30639 | return sema.failWithOwnedErrorMsg(block, some); | |
| 29579 | for (union_obj.field_types.get(ip)) |field_ty_ip| { | |
| 29580 | if (Type.fromInterned(field_ty_ip).classify(zcu) != .one_possible_value) break; | |
| 29581 | } else { | |
| 29582 | // All fields are OPV, so the coercion is okay. | |
| 29583 | if (try union_ty.onePossibleValue(pt)) |opv| { | |
| 29584 | // The tag had redundant bits, but we've omitted the tag from the union's runtime layout, so the union is OPV and hence runtime-known. | |
| 29585 | return .fromValue(opv); | |
| 29586 | } else { | |
| 29587 | // The union layout is just the tag, so we can bitcast the enum straight to the union. | |
| 29588 | return block.addBitCast(union_ty, enum_tag); | |
| 30640 | 29589 | } |
| 30641 | 29590 | } |
| 30642 | 29591 | |
| 30643 | // If the union has all fields 0 bits, the union value is just the enum value. | |
| 30644 | if (union_ty.unionHasAllZeroBitFieldTypes(zcu)) { | |
| 30645 | return block.addBitCast(union_ty, enum_tag); | |
| 30646 | } | |
| 29592 | // The coercion is invalid because one or more fields is not OPV. | |
| 30647 | 29593 | |
| 30648 | 29594 | const msg = msg: { |
| 30649 | 29595 | const msg = try sema.errMsg( |
| 30650 | 29596 | inst_src, |
| 30651 | 29597 | "runtime coercion from enum '{f}' to union '{f}' which has non-void fields", |
| 30652 | .{ tag_ty.fmt(pt), union_ty.fmt(pt) }, | |
| 29598 | .{ enum_ty.fmt(pt), union_ty.fmt(pt) }, | |
| 30653 | 29599 | ); |
| 30654 | 29600 | errdefer msg.destroy(sema.gpa); |
| 30655 | 29601 | |
| 30656 | 29602 | for (0..union_obj.field_types.len) |field_index| { |
| 30657 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | |
| 29603 | const field_name = enum_obj.field_names.get(ip)[field_index]; | |
| 30658 | 29604 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 30659 | if (!(try field_ty.hasRuntimeBitsSema(pt))) continue; | |
| 30660 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{ | |
| 29605 | const ty_description: []const u8 = switch (field_ty.classify(zcu)) { | |
| 29606 | .one_possible_value => continue, | |
| 29607 | .no_possible_value => "uninstantiable type", | |
| 29608 | else => "type", | |
| 29609 | }; | |
| 29610 | if (field_ty.classify(zcu) == .one_possible_value) continue; | |
| 29611 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has {s} '{f}'", .{ | |
| 30661 | 29612 | field_name.fmt(ip), |
| 29613 | ty_description, | |
| 30662 | 29614 | field_ty.fmt(pt), |
| 30663 | 29615 | }); |
| 30664 | 29616 | } |
| ... | ... | @@ -30685,7 +29637,7 @@ fn coerceArrayLike( |
| 30685 | 29637 | // try coercion of the whole array |
| 30686 | 29638 | const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, null); |
| 30687 | 29639 | if (in_memory_result == .ok) { |
| 30688 | if (try sema.resolveValue(inst)) |inst_val| { | |
| 29640 | if (sema.resolveValue(inst)) |inst_val| { | |
| 30689 | 29641 | // These types share the same comptime value representation. |
| 30690 | 29642 | return sema.coerceInMemory(inst_val, dest_ty); |
| 30691 | 29643 | } |
| ... | ... | @@ -30708,7 +29660,7 @@ fn coerceArrayLike( |
| 30708 | 29660 | } |
| 30709 | 29661 | |
| 30710 | 29662 | const dest_elem_ty = dest_ty.childType(zcu); |
| 30711 | if (dest_ty.isVector(zcu) and inst_ty.isVector(zcu) and (try sema.resolveValue(inst)) == null) { | |
| 29663 | if (dest_ty.isVector(zcu) and inst_ty.isVector(zcu) and sema.resolveValue(inst) == null) { | |
| 30712 | 29664 | const inst_elem_ty = inst_ty.childType(zcu); |
| 30713 | 29665 | switch (dest_elem_ty.zigTypeTag(zcu)) { |
| 30714 | 29666 | .int => if (inst_elem_ty.isInt(zcu)) { |
| ... | ... | @@ -30748,7 +29700,7 @@ fn coerceArrayLike( |
| 30748 | 29700 | const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src); |
| 30749 | 29701 | ref.* = coerced; |
| 30750 | 29702 | if (runtime_src == null) { |
| 30751 | if (try sema.resolveValue(coerced)) |elem_val| { | |
| 29703 | if (sema.resolveValue(coerced)) |elem_val| { | |
| 30752 | 29704 | val.* = elem_val.toIntern(); |
| 30753 | 29705 | } else { |
| 30754 | 29706 | runtime_src = elem_src; |
| ... | ... | @@ -30809,7 +29761,7 @@ fn coerceTupleToArray( |
| 30809 | 29761 | const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src); |
| 30810 | 29762 | ref.* = coerced; |
| 30811 | 29763 | if (runtime_src == null) { |
| 30812 | if (try sema.resolveValue(coerced)) |elem_val| { | |
| 29764 | if (sema.resolveValue(coerced)) |elem_val| { | |
| 30813 | 29765 | val.* = elem_val.toIntern(); |
| 30814 | 29766 | } else { |
| 30815 | 29767 | runtime_src = elem_src; |
| ... | ... | @@ -30845,10 +29797,7 @@ fn coerceTupleToSlicePtrs( |
| 30845 | 29797 | .child = slice_info.child, |
| 30846 | 29798 | }); |
| 30847 | 29799 | const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src); |
| 30848 | if (slice_info.flags.alignment != .none) { | |
| 30849 | return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{}); | |
| 30850 | } | |
| 30851 | const ptr_array = try sema.analyzeRef(block, slice_ty_src, array_inst); | |
| 29800 | const ptr_array = try sema.analyzeRef(block, slice_ty_src, array_inst, slice_info.flags.alignment); | |
| 30852 | 29801 | return sema.coerceArrayPtrToSlice(block, slice_ty, ptr_array, slice_ty_src); |
| 30853 | 29802 | } |
| 30854 | 29803 | |
| ... | ... | @@ -30867,10 +29816,7 @@ fn coerceTupleToArrayPtrs( |
| 30867 | 29816 | const ptr_info = ptr_array_ty.ptrInfo(zcu); |
| 30868 | 29817 | const array_ty: Type = .fromInterned(ptr_info.child); |
| 30869 | 29818 | const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src); |
| 30870 | if (ptr_info.flags.alignment != .none) { | |
| 30871 | return sema.fail(block, array_ty_src, "TODO: override the alignment of the array decl we create here", .{}); | |
| 30872 | } | |
| 30873 | const ptr_array = try sema.analyzeRef(block, array_ty_src, array_inst); | |
| 29819 | const ptr_array = try sema.analyzeRef(block, array_ty_src, array_inst, ptr_info.flags.alignment); | |
| 30874 | 29820 | return ptr_array; |
| 30875 | 29821 | } |
| 30876 | 29822 | |
| ... | ... | @@ -30904,24 +29850,21 @@ fn coerceTupleToTuple( |
| 30904 | 29850 | const field_i: u32 = @intCast(field_index_usize); |
| 30905 | 29851 | const field_src = inst_src; // TODO better source location |
| 30906 | 29852 | |
| 30907 | const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) { | |
| 30908 | .tuple_type => |tuple_type| tuple_type.types.get(ip)[field_index_usize], | |
| 30909 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize], | |
| 30910 | else => unreachable, | |
| 30911 | }; | |
| 30912 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | |
| 30913 | .tuple_type => |tuple_type| tuple_type.values.get(ip)[field_index_usize], | |
| 30914 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize), | |
| 30915 | else => unreachable, | |
| 30916 | }; | |
| 30917 | ||
| 30918 | 29853 | const field_index: u32 = @intCast(field_index_usize); |
| 30919 | 29854 | |
| 29855 | const field_ty, const default_val = field: { | |
| 29856 | const tuple_type = ip.indexToKey(tuple_ty.toIntern()).tuple_type; | |
| 29857 | break :field .{ | |
| 29858 | tuple_type.types.get(ip)[field_index], | |
| 29859 | tuple_type.values.get(ip)[field_index], | |
| 29860 | }; | |
| 29861 | }; | |
| 29862 | ||
| 30920 | 29863 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 30921 | 29864 | const coerced = try sema.coerce(block, .fromInterned(field_ty), elem_ref, field_src); |
| 30922 | 29865 | field_refs[field_index] = coerced; |
| 30923 | 29866 | if (default_val != .none) { |
| 30924 | const init_val = (try sema.resolveValue(coerced)) orelse { | |
| 29867 | const init_val = sema.resolveValue(coerced) orelse { | |
| 30925 | 29868 | return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); |
| 30926 | 29869 | }; |
| 30927 | 29870 | |
| ... | ... | @@ -30930,7 +29873,7 @@ fn coerceTupleToTuple( |
| 30930 | 29873 | } |
| 30931 | 29874 | } |
| 30932 | 29875 | if (runtime_src == null) { |
| 30933 | if (try sema.resolveValue(coerced)) |field_val| { | |
| 29876 | if (sema.resolveValue(coerced)) |field_val| { | |
| 30934 | 29877 | field_vals[field_index] = field_val.toIntern(); |
| 30935 | 29878 | } else { |
| 30936 | 29879 | runtime_src = field_src; |
| ... | ... | @@ -30946,11 +29889,7 @@ fn coerceTupleToTuple( |
| 30946 | 29889 | const i: u32 = @intCast(i_usize); |
| 30947 | 29890 | if (field_ref.* != .none) continue; |
| 30948 | 29891 | |
| 30949 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | |
| 30950 | .tuple_type => |tuple_type| tuple_type.values.get(ip)[i], | |
| 30951 | .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i), | |
| 30952 | else => unreachable, | |
| 30953 | }; | |
| 29892 | const default_val = ip.indexToKey(tuple_ty.toIntern()).tuple_type.values.get(ip)[i]; | |
| 30954 | 29893 | |
| 30955 | 29894 | const field_src = inst_src; // TODO better source location |
| 30956 | 29895 | if (default_val == .none) { |
| ... | ... | @@ -30993,7 +29932,7 @@ fn analyzeNavVal( |
| 30993 | 29932 | return sema.analyzeLoad(block, src, ref, src); |
| 30994 | 29933 | } |
| 30995 | 29934 | |
| 30996 | fn addReferenceEntry( | |
| 29935 | pub fn addReferenceEntry( | |
| 30997 | 29936 | sema: *Sema, |
| 30998 | 29937 | opt_block: ?*Block, |
| 30999 | 29938 | src: LazySrcLoc, |
| ... | ... | @@ -31005,7 +29944,6 @@ fn addReferenceEntry( |
| 31005 | 29944 | .func => |f| assert(ip.unwrapCoercedFunc(f) == f), // for `.{ .func = f }`, `f` must be uncoerced |
| 31006 | 29945 | else => {}, |
| 31007 | 29946 | } |
| 31008 | if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; | |
| 31009 | 29947 | const gop = try sema.references.getOrPut(sema.gpa, referenced_unit); |
| 31010 | 29948 | if (gop.found_existing) return; |
| 31011 | 29949 | try zcu.addUnitReference(sema.owner, referenced_unit, src, inline_frame: { |
| ... | ... | @@ -31019,13 +29957,12 @@ fn addReferenceEntry( |
| 31019 | 29957 | pub fn addTypeReferenceEntry( |
| 31020 | 29958 | sema: *Sema, |
| 31021 | 29959 | src: LazySrcLoc, |
| 31022 | referenced_type: InternPool.Index, | |
| 29960 | referenced_type: Type, | |
| 31023 | 29961 | ) !void { |
| 31024 | 29962 | const zcu = sema.pt.zcu; |
| 31025 | if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; | |
| 31026 | const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type); | |
| 29963 | const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type.toIntern()); | |
| 31027 | 29964 | if (gop.found_existing) return; |
| 31028 | try zcu.addTypeReference(sema.owner, referenced_type, src); | |
| 29965 | try zcu.addTypeReference(sema.owner, referenced_type.toIntern(), src); | |
| 31029 | 29966 | } |
| 31030 | 29967 | |
| 31031 | 29968 | fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.MemoizedStateStage) SemaError!void { |
| ... | ... | @@ -31035,10 +29972,11 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M |
| 31035 | 29972 | try sema.addReferenceEntry(null, src, unit); |
| 31036 | 29973 | try sema.declareDependency(.{ .memoized_state = stage }); |
| 31037 | 29974 | |
| 29975 | const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; | |
| 31038 | 29976 | if (pt.zcu.analysis_in_progress.contains(unit)) { |
| 31039 | return sema.failWithOwnedErrorMsg(null, try sema.errMsg(src, "dependency loop detected", .{})); | |
| 29977 | return sema.failWithDependencyLoop(unit, &reason); | |
| 31040 | 29978 | } |
| 31041 | try pt.ensureMemoizedStateUpToDate(stage); | |
| 29979 | try pt.ensureMemoizedStateUpToDate(stage, &reason); | |
| 31042 | 29980 | } |
| 31043 | 29981 | |
| 31044 | 29982 | pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void { |
| ... | ... | @@ -31052,11 +29990,6 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: |
| 31052 | 29990 | return; |
| 31053 | 29991 | } |
| 31054 | 29992 | |
| 31055 | try sema.declareDependency(switch (kind) { | |
| 31056 | .type => .{ .nav_ty = nav_index }, | |
| 31057 | .fully => .{ .nav_val = nav_index }, | |
| 31058 | }); | |
| 31059 | ||
| 31060 | 29993 | // Note that even if `nav.status == .resolved`, we must still trigger `ensureNavValUpToDate` |
| 31061 | 29994 | // to make sure the value is up-to-date on incremental updates. |
| 31062 | 29995 | |
| ... | ... | @@ -31065,32 +29998,37 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: |
| 31065 | 29998 | .fully => .{ .nav_val = nav_index }, |
| 31066 | 29999 | }); |
| 31067 | 30000 | try sema.addReferenceEntry(block, src, anal_unit); |
| 30001 | try sema.declareDependency(switch (kind) { | |
| 30002 | .type => .{ .nav_ty = nav_index }, | |
| 30003 | .fully => .{ .nav_val = nav_index }, | |
| 30004 | }); | |
| 30005 | ||
| 30006 | const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; | |
| 31068 | 30007 | |
| 31069 | 30008 | if (zcu.analysis_in_progress.contains(anal_unit)) { |
| 31070 | return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{ | |
| 31071 | .base_node_inst = nav.analysis.?.zir_index, | |
| 31072 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 31073 | }, "dependency loop detected", .{})); | |
| 30009 | return sema.failWithDependencyLoop(anal_unit, &reason); | |
| 31074 | 30010 | } |
| 31075 | 30011 | |
| 31076 | 30012 | switch (kind) { |
| 31077 | 30013 | .type => { |
| 31078 | 30014 | try zcu.ensureNavValAnalysisQueued(nav_index); |
| 31079 | return pt.ensureNavTypeUpToDate(nav_index); | |
| 30015 | return pt.ensureNavTypeUpToDate(nav_index, &reason); | |
| 31080 | 30016 | }, |
| 31081 | .fully => return pt.ensureNavValUpToDate(nav_index), | |
| 30017 | .fully => return pt.ensureNavValUpToDate(nav_index, &reason), | |
| 31082 | 30018 | } |
| 31083 | 30019 | } |
| 31084 | 30020 | |
| 31085 | 30021 | fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { |
| 31086 | 30022 | const pt = sema.pt; |
| 31087 | 30023 | const ptr_anyopaque_ty = try pt.singleConstPtrType(.anyopaque); |
| 31088 | return Value.fromInterned(try pt.intern(.{ .opt = .{ | |
| 31089 | .ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(), | |
| 31090 | .val = if (opt_val) |val| (try pt.getCoerced( | |
| 31091 | Value.fromInterned(try pt.refValue(val.toIntern())), | |
| 31092 | ptr_anyopaque_ty, | |
| 31093 | )).toIntern() else .none, | |
| 30024 | const opt_ptr_anyopaque_ty = try pt.optionalType(ptr_anyopaque_ty.toIntern()); | |
| 30025 | return .fromInterned(try pt.intern(.{ .opt = .{ | |
| 30026 | .ty = opt_ptr_anyopaque_ty.toIntern(), | |
| 30027 | .val = payload: { | |
| 30028 | const val = opt_val orelse break :payload .none; | |
| 30029 | const ptr_val = try pt.getCoerced(try pt.uavValue(val), ptr_anyopaque_ty); | |
| 30030 | break :payload ptr_val.toIntern(); | |
| 30031 | }, | |
| 31094 | 30032 | } })); |
| 31095 | 30033 | } |
| 31096 | 30034 | |
| ... | ... | @@ -31143,7 +30081,7 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 31143 | 30081 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, |
| 31144 | 30082 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const }, |
| 31145 | 30083 | }; |
| 31146 | const ptr_ty = try pt.ptrTypeSema(.{ | |
| 30084 | const ptr_ty = try pt.ptrType(.{ | |
| 31147 | 30085 | .child = ty, |
| 31148 | 30086 | .flags = .{ |
| 31149 | 30087 | .alignment = alignment, |
| ... | ... | @@ -31185,7 +30123,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i |
| 31185 | 30123 | try sema.ensureNavResolved(block, src, nav_index, .type); |
| 31186 | 30124 | const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip)); |
| 31187 | 30125 | if (nav_ty.zigTypeTag(zcu) != .@"fn") return; |
| 31188 | if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return; | |
| 30126 | if (!nav_ty.fnHasRuntimeBits(zcu)) return; | |
| 31189 | 30127 | |
| 31190 | 30128 | try sema.ensureNavResolved(block, src, nav_index, .fully); |
| 31191 | 30129 | const nav_val = zcu.navValue(nav_index); |
| ... | ... | @@ -31201,34 +30139,48 @@ fn analyzeRef( |
| 31201 | 30139 | block: *Block, |
| 31202 | 30140 | src: LazySrcLoc, |
| 31203 | 30141 | operand: Air.Inst.Ref, |
| 30142 | alignment: Alignment, | |
| 31204 | 30143 | ) CompileError!Air.Inst.Ref { |
| 31205 | 30144 | const pt = sema.pt; |
| 31206 | 30145 | const zcu = pt.zcu; |
| 31207 | 30146 | const operand_ty = sema.typeOf(operand); |
| 31208 | 30147 | |
| 31209 | if (try sema.resolveValue(operand)) |val| { | |
| 30148 | const address_space = target_util.defaultAddressSpace(zcu.getTarget(), .local); | |
| 30149 | const ptr_type = try pt.ptrType(.{ | |
| 30150 | .child = operand_ty.toIntern(), | |
| 30151 | .flags = .{ | |
| 30152 | .alignment = alignment, | |
| 30153 | .is_const = true, | |
| 30154 | .address_space = address_space, | |
| 30155 | }, | |
| 30156 | }); | |
| 30157 | ||
| 30158 | if (sema.resolveValue(operand)) |val| { | |
| 31210 | 30159 | switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 31211 | 30160 | .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav), |
| 31212 | 30161 | .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav), |
| 31213 | else => return uavRef(sema, val.toIntern()), | |
| 30162 | else => return .fromIntern(try pt.intern(.{ .ptr = .{ | |
| 30163 | .ty = ptr_type.toIntern(), | |
| 30164 | .base_addr = .{ .uav = .{ | |
| 30165 | .val = val.toIntern(), | |
| 30166 | .orig_ty = ptr_type.toIntern(), | |
| 30167 | } }, | |
| 30168 | .byte_offset = 0, | |
| 30169 | } })), | |
| 31214 | 30170 | } |
| 31215 | 30171 | } |
| 31216 | 30172 | |
| 31217 | 30173 | // No `requireRuntimeBlock`; it's okay to `ref` to a runtime value in a comptime context, |
| 31218 | 30174 | // it's just that we can only use the *type* of the result, since the value is runtime-known. |
| 31219 | 30175 | |
| 31220 | const address_space = target_util.defaultAddressSpace(zcu.getTarget(), .local); | |
| 31221 | const ptr_type = try pt.ptrTypeSema(.{ | |
| 30176 | const mut_ptr_type = try pt.ptrType(.{ | |
| 31222 | 30177 | .child = operand_ty.toIntern(), |
| 31223 | 30178 | .flags = .{ |
| 31224 | .is_const = true, | |
| 30179 | .alignment = alignment, | |
| 30180 | .is_const = false, | |
| 31225 | 30181 | .address_space = address_space, |
| 31226 | 30182 | }, |
| 31227 | 30183 | }); |
| 31228 | const mut_ptr_type = try pt.ptrTypeSema(.{ | |
| 31229 | .child = operand_ty.toIntern(), | |
| 31230 | .flags = .{ .address_space = address_space }, | |
| 31231 | }); | |
| 31232 | 30184 | const alloc = try block.addTy(.alloc, mut_ptr_type); |
| 31233 | 30185 | |
| 31234 | 30186 | // In a comptime context, the store would fail, since the operand is runtime-known. But that's |
| ... | ... | @@ -31257,13 +30209,18 @@ fn analyzeLoad( |
| 31257 | 30209 | .pointer => ptr_ty.childType(zcu), |
| 31258 | 30210 | else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}), |
| 31259 | 30211 | }; |
| 31260 | if (elem_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 31261 | return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}); | |
| 31262 | } | |
| 31263 | 30212 | |
| 31264 | if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| { | |
| 31265 | return Air.internedToRef(opv.toIntern()); | |
| 31266 | } | |
| 30213 | try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); | |
| 30214 | ||
| 30215 | const comptime_only = switch (elem_ty.classify(zcu)) { | |
| 30216 | .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) { | |
| 30217 | .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}), | |
| 30218 | else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)}), | |
| 30219 | }, | |
| 30220 | .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?), | |
| 30221 | .runtime => false, | |
| 30222 | .partially_comptime, .fully_comptime => true, | |
| 30223 | }; | |
| 31267 | 30224 | |
| 31268 | 30225 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 31269 | 30226 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { |
| ... | ... | @@ -31271,6 +30228,13 @@ fn analyzeLoad( |
| 31271 | 30228 | } |
| 31272 | 30229 | } |
| 31273 | 30230 | |
| 30231 | if (comptime_only) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 30232 | const msg = try sema.errMsg(src, "cannot load comptime-only type '{f}'", .{elem_ty.fmt(pt)}); | |
| 30233 | errdefer msg.destroy(zcu.gpa); | |
| 30234 | try sema.errNote(ptr_src, msg, "pointer of type '{f}' is runtime-known", .{ptr_ty.fmt(pt)}); | |
| 30235 | break :msg msg; | |
| 30236 | }); | |
| 30237 | ||
| 31274 | 30238 | return block.addTyOp(.load, elem_ty, ptr); |
| 31275 | 30239 | } |
| 31276 | 30240 | |
| ... | ... | @@ -31284,7 +30248,7 @@ fn analyzeSlicePtr( |
| 31284 | 30248 | const pt = sema.pt; |
| 31285 | 30249 | const zcu = pt.zcu; |
| 31286 | 30250 | const result_ty = slice_ty.slicePtrFieldType(zcu); |
| 31287 | if (try sema.resolveValue(slice)) |val| { | |
| 30251 | if (sema.resolveValue(slice)) |val| { | |
| 31288 | 30252 | if (val.isUndef(zcu)) return pt.undefRef(result_ty); |
| 31289 | 30253 | return Air.internedToRef(val.slicePtr(zcu).toIntern()); |
| 31290 | 30254 | } |
| ... | ... | @@ -31304,7 +30268,7 @@ fn analyzeOptionalSlicePtr( |
| 31304 | 30268 | const slice_ty = opt_slice_ty.optionalChild(zcu); |
| 31305 | 30269 | const result_ty = slice_ty.slicePtrFieldType(zcu); |
| 31306 | 30270 | |
| 31307 | if (try sema.resolveValue(opt_slice)) |opt_val| { | |
| 30271 | if (sema.resolveValue(opt_slice)) |opt_val| { | |
| 31308 | 30272 | if (opt_val.isUndef(zcu)) return pt.undefRef(result_ty); |
| 31309 | 30273 | const slice_ptr: InternPool.Index = if (opt_val.optionalValue(zcu)) |val| |
| 31310 | 30274 | val.slicePtr(zcu).toIntern() |
| ... | ... | @@ -31328,11 +30292,11 @@ fn analyzeSliceLen( |
| 31328 | 30292 | ) CompileError!Air.Inst.Ref { |
| 31329 | 30293 | const pt = sema.pt; |
| 31330 | 30294 | const zcu = pt.zcu; |
| 31331 | if (try sema.resolveValue(slice_inst)) |slice_val| { | |
| 30295 | if (sema.resolveValue(slice_inst)) |slice_val| { | |
| 31332 | 30296 | if (slice_val.isUndef(zcu)) { |
| 31333 | 30297 | return .undef_usize; |
| 31334 | 30298 | } |
| 31335 | return pt.intRef(.usize, try slice_val.sliceLen(pt)); | |
| 30299 | return pt.intRef(.usize, slice_val.sliceLen(zcu)); | |
| 31336 | 30300 | } |
| 31337 | 30301 | try sema.requireRuntimeBlock(block, src, null); |
| 31338 | 30302 | return block.addTyOp(.slice_len, .usize, slice_inst); |
| ... | ... | @@ -31341,25 +30305,25 @@ fn analyzeSliceLen( |
| 31341 | 30305 | fn analyzeIsNull( |
| 31342 | 30306 | sema: *Sema, |
| 31343 | 30307 | block: *Block, |
| 30308 | src: LazySrcLoc, | |
| 31344 | 30309 | operand: Air.Inst.Ref, |
| 31345 | 30310 | invert_logic: bool, |
| 31346 | 30311 | ) CompileError!Air.Inst.Ref { |
| 31347 | 30312 | const pt = sema.pt; |
| 31348 | 30313 | const zcu = pt.zcu; |
| 31349 | const result_ty: Type = .bool; | |
| 31350 | if (try sema.resolveValue(operand)) |opt_val| { | |
| 30314 | ||
| 30315 | if (try sema.resolveIsNullFromType(block, src, sema.typeOf(operand))) |is_null| { | |
| 30316 | return .fromValue(.makeBool(is_null != invert_logic)); // XOR | |
| 30317 | } | |
| 30318 | ||
| 30319 | if (sema.resolveValue(operand)) |opt_val| { | |
| 31351 | 30320 | if (opt_val.isUndef(zcu)) { |
| 31352 | return pt.undefRef(result_ty); | |
| 30321 | return pt.undefRef(.bool); | |
| 31353 | 30322 | } |
| 31354 | 30323 | const is_null = opt_val.isNull(zcu); |
| 31355 | const bool_value = if (invert_logic) !is_null else is_null; | |
| 31356 | return if (bool_value) .bool_true else .bool_false; | |
| 30324 | return .fromValue(.makeBool(is_null != invert_logic)); // XOR | |
| 31357 | 30325 | } |
| 31358 | 30326 | |
| 31359 | if (sema.typeOf(operand).isNullFromType(zcu)) |is_null| { | |
| 31360 | const result = is_null != invert_logic; | |
| 31361 | return if (result) .bool_true else .bool_false; | |
| 31362 | } | |
| 31363 | 30327 | const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null; |
| 31364 | 30328 | return block.addUnOp(air_tag, operand); |
| 31365 | 30329 | } |
| ... | ... | @@ -31381,7 +30345,7 @@ fn resolvePtrIsNonErrVal( |
| 31381 | 30345 | } |
| 31382 | 30346 | assert(child_ty.zigTypeTag(zcu) == .error_union); |
| 31383 | 30347 | |
| 31384 | if (try sema.resolveValue(operand)) |eu_ptr_val| { | |
| 30348 | if (sema.resolveValue(operand)) |eu_ptr_val| { | |
| 31385 | 30349 | if (eu_ptr_val.isUndef(zcu)) return .undef_bool; |
| 31386 | 30350 | if (try sema.pointerDeref(block, src, eu_ptr_val, ptr_ty)) |err_union| { |
| 31387 | 30351 | if (err_union.isUndef(zcu)) return .undef_bool; |
| ... | ... | @@ -31404,7 +30368,7 @@ fn resolveIsNonErrVal( |
| 31404 | 30368 | } |
| 31405 | 30369 | assert(sema.typeOf(operand).zigTypeTag(zcu) == .error_union); |
| 31406 | 30370 | |
| 31407 | if (try sema.resolveValue(operand)) |err_union| { | |
| 30371 | if (sema.resolveValue(operand)) |err_union| { | |
| 31408 | 30372 | if (err_union.isUndef(zcu)) return .undef_bool; |
| 31409 | 30373 | return .makeBool(err_union.getErrorName(zcu) == .none); |
| 31410 | 30374 | } |
| ... | ... | @@ -31412,6 +30376,35 @@ fn resolveIsNonErrVal( |
| 31412 | 30376 | return null; |
| 31413 | 30377 | } |
| 31414 | 30378 | |
| 30379 | fn resolveIsNullFromType( | |
| 30380 | sema: *Sema, | |
| 30381 | block: *Block, | |
| 30382 | src: LazySrcLoc, | |
| 30383 | ty: Type, | |
| 30384 | ) CompileError!?bool { | |
| 30385 | const zcu = sema.pt.zcu; | |
| 30386 | return switch (ty.zigTypeTag(zcu)) { | |
| 30387 | else => false, | |
| 30388 | .null => true, | |
| 30389 | .pointer => switch (ty.ptrSize(zcu)) { | |
| 30390 | .c => null, | |
| 30391 | else => false, | |
| 30392 | }, | |
| 30393 | .optional => { | |
| 30394 | const payload_ty = ty.optionalChild(zcu); | |
| 30395 | if (payload_ty.classify(zcu) == .no_possible_value) { | |
| 30396 | return true; // e.g. `?noreturn` | |
| 30397 | } | |
| 30398 | if (payload_ty.zigTypeTag(zcu) == .error_set and | |
| 30399 | try sema.resolveErrSetIsEmpty(block, src, payload_ty)) | |
| 30400 | { | |
| 30401 | return true; // e.g. `?error{}` | |
| 30402 | } | |
| 30403 | return null; | |
| 30404 | }, | |
| 30405 | }; | |
| 30406 | } | |
| 30407 | ||
| 31415 | 30408 | fn resolveIsNonErrFromType( |
| 31416 | 30409 | sema: *Sema, |
| 31417 | 30410 | block: *Block, |
| ... | ... | @@ -31420,89 +30413,71 @@ fn resolveIsNonErrFromType( |
| 31420 | 30413 | ) CompileError!?Value { |
| 31421 | 30414 | const pt = sema.pt; |
| 31422 | 30415 | const zcu = pt.zcu; |
| 31423 | const ip = &zcu.intern_pool; | |
| 31424 | 30416 | const ot = operand_ty.zigTypeTag(zcu); |
| 31425 | 30417 | if (ot != .error_set and ot != .error_union) return .true; |
| 31426 | 30418 | if (ot == .error_set) return .false; |
| 31427 | 30419 | assert(ot == .error_union); |
| 31428 | 30420 | |
| 31429 | 30421 | const payload_ty = operand_ty.errorUnionPayload(zcu); |
| 31430 | if (payload_ty.zigTypeTag(zcu) == .noreturn) { | |
| 30422 | if (payload_ty.classify(zcu) == .no_possible_value) { | |
| 31431 | 30423 | return .false; |
| 31432 | 30424 | } |
| 30425 | if (try sema.resolveErrSetIsEmpty(block, src, operand_ty.errorUnionSet(zcu))) { | |
| 30426 | return .true; | |
| 30427 | } | |
| 30428 | return null; | |
| 30429 | } | |
| 31433 | 30430 | |
| 31434 | // exception if the error union error set is known to be empty, | |
| 31435 | // we allow the comparison but always make it comptime-known. | |
| 31436 | const set_ty = ip.errorUnionSet(operand_ty.toIntern()); | |
| 31437 | switch (set_ty) { | |
| 31438 | .anyerror_type => {}, | |
| 31439 | .adhoc_inferred_error_set_type => if (sema.fn_ret_ty_ies) |ies| blk: { | |
| 31440 | // If the error set is empty, we must return a comptime true or false. | |
| 31441 | // However we want to avoid unnecessarily resolving an inferred error set | |
| 31442 | // in case it is already non-empty. | |
| 31443 | switch (ies.resolved) { | |
| 31444 | .anyerror_type => break :blk, | |
| 31445 | .none => {}, | |
| 31446 | else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk, | |
| 31447 | } | |
| 31448 | ||
| 31449 | if (ies.errors.count() != 0) return null; | |
| 31450 | switch (ies.resolved) { | |
| 31451 | .anyerror_type => return null, | |
| 31452 | .none => {}, | |
| 31453 | else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) { | |
| 31454 | 0 => return .true, | |
| 31455 | else => return null, | |
| 31456 | }, | |
| 31457 | } | |
| 31458 | // We do not have a comptime answer because this inferred error | |
| 31459 | // set is not resolved, and an instruction later in this function | |
| 31460 | // body may or may not cause an error to be added to this set. | |
| 31461 | return null; | |
| 31462 | }, | |
| 31463 | else => switch (ip.indexToKey(set_ty)) { | |
| 31464 | .error_set_type => |error_set_type| { | |
| 31465 | if (error_set_type.names.len == 0) return .true; | |
| 31466 | }, | |
| 31467 | .inferred_error_set_type => |func_index| blk: { | |
| 31468 | // If the error set is empty, we must return a comptime true or false. | |
| 31469 | // However we want to avoid unnecessarily resolving an inferred error set | |
| 31470 | // in case it is already non-empty. | |
| 31471 | try zcu.maybeUnresolveIes(func_index); | |
| 31472 | switch (ip.funcIesResolvedUnordered(func_index)) { | |
| 31473 | .anyerror_type => break :blk, | |
| 31474 | .none => {}, | |
| 31475 | else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk, | |
| 31476 | } | |
| 30431 | /// Returns `true` iff the error set type `orig_err_set_ty` contains no errors. | |
| 30432 | /// | |
| 30433 | /// This is used to give comptime answers for whether `error{}!T` is an error or a payload, as well | |
| 30434 | /// as whether `?error{}` is null. The type `error{}` cannot be NPV, as it has runtime bits, but the | |
| 30435 | /// only value of that type which can exist is `undefined`; semantically it has no "legal" value. | |
| 30436 | /// TODO: this runs into some unsolved language design questions about such types. Performing a | |
| 30437 | /// coercion from `@as(E, undefined)` to `E!T` needs to semantically result in an `undefined` error | |
| 30438 | /// union if our implementation is to be legal, and likewise for coercing `@as(E, undefined)` to | |
| 30439 | /// `?E` (for an error set `E`) because our implementation uses the zero error value at runtime to | |
| 30440 | /// represent `null`. The unsolved problem is the exact rules for `undefined` propagation through | |
| 30441 | /// these types: for instance, what if `@as(u32, undfined)` is coerced to `?u32`? What about error | |
| 30442 | /// union *payloads*, i.e. `@as(u32, undefined)` to `E!u32`? That one is analagous to the optional | |
| 30443 | /// example in some ways, but right now I believe there is code which relies on that coercion giving | |
| 30444 | /// a well-defined error union with an `undefined` payload. | |
| 30445 | /// Relevant issues/discussions: | |
| 30446 | /// * https://github.com/ziglang/zig/issues/1831 | |
| 30447 | /// * https://github.com/ziglang/zig/issues/6762 | |
| 30448 | /// * https://github.com/ziglang/zig/issues/1831#issuecomment-722129239 | |
| 30449 | fn resolveErrSetIsEmpty( | |
| 30450 | sema: *Sema, | |
| 30451 | block: *Block, | |
| 30452 | src: LazySrcLoc, | |
| 30453 | orig_err_set_ty: Type, | |
| 30454 | ) CompileError!bool { | |
| 30455 | const ip = &sema.pt.zcu.intern_pool; | |
| 30456 | err_set: switch (orig_err_set_ty.toIntern()) { | |
| 30457 | .anyerror_type => return false, | |
| 30458 | .adhoc_inferred_error_set_type => { | |
| 30459 | // This is *our* error set; that is, we're currently analyzing the function | |
| 30460 | // which owns it. Trying to resolve it now would cause a dependency loop. | |
| 30461 | // Instead, accept that we don't know. | |
| 30462 | return false; | |
| 30463 | }, | |
| 30464 | else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { | |
| 30465 | .error_set_type => |es| return es.names.len == 0, | |
| 30466 | .inferred_error_set_type => |func_index| { | |
| 31477 | 30467 | if (sema.fn_ret_ty_ies) |ies| { |
| 31478 | 30468 | if (ies.func == func_index) { |
| 31479 | // Try to avoid resolving inferred error set if possible. | |
| 31480 | if (ies.errors.count() != 0) return null; | |
| 31481 | switch (ies.resolved) { | |
| 31482 | .anyerror_type => return null, | |
| 31483 | .none => {}, | |
| 31484 | else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) { | |
| 31485 | 0 => return .true, | |
| 31486 | else => return null, | |
| 31487 | }, | |
| 31488 | } | |
| 31489 | // We do not have a comptime answer because this inferred error | |
| 31490 | // set is not resolved, and an instruction later in this function | |
| 31491 | // body may or may not cause an error to be added to this set. | |
| 31492 | return null; | |
| 30469 | // This is *our* error set; that is, we're currently analyzing the function | |
| 30470 | // which owns it. Trying to resolve it now would cause a dependency loop. | |
| 30471 | // Instead, accept that we don't know. | |
| 30472 | return false; | |
| 31493 | 30473 | } |
| 31494 | 30474 | } |
| 31495 | const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty); | |
| 31496 | if (resolved_ty == .anyerror_type) | |
| 31497 | break :blk; | |
| 31498 | if (ip.indexToKey(resolved_ty).error_set_type.names.len == 0) | |
| 31499 | return .true; | |
| 30475 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 30476 | continue :err_set ip.funcIesResolvedUnordered(func_index); | |
| 31500 | 30477 | }, |
| 31501 | 30478 | else => unreachable, |
| 31502 | 30479 | }, |
| 31503 | 30480 | } |
| 31504 | ||
| 31505 | return null; | |
| 31506 | 30481 | } |
| 31507 | 30482 | |
| 31508 | 30483 | fn analyzeIsNonErr( |
| ... | ... | @@ -31682,6 +30657,8 @@ fn analyzeSlice( |
| 31682 | 30657 | else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}), |
| 31683 | 30658 | } |
| 31684 | 30659 | |
| 30660 | try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); | |
| 30661 | ||
| 31685 | 30662 | const ptr = if (slice_ty.isSlice(zcu)) |
| 31686 | 30663 | try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty) |
| 31687 | 30664 | else if (array_ty.zigTypeTag(zcu) == .array) ptr: { |
| ... | ... | @@ -31690,11 +30667,11 @@ fn analyzeSlice( |
| 31690 | 30667 | assert(manyptr_ty_key.flags.size == .one); |
| 31691 | 30668 | manyptr_ty_key.child = elem_ty.toIntern(); |
| 31692 | 30669 | manyptr_ty_key.flags.size = .many; |
| 31693 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(manyptr_ty_key), ptr_or_slice, ptr_src); | |
| 30670 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src); | |
| 31694 | 30671 | } else ptr_or_slice; |
| 31695 | 30672 | |
| 31696 | 30673 | const start = try sema.coerce(block, .usize, uncasted_start, start_src); |
| 31697 | const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); | |
| 30674 | const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, start_src); | |
| 31698 | 30675 | const new_ptr_ty = sema.typeOf(new_ptr); |
| 31699 | 30676 | |
| 31700 | 30677 | // true if and only if the end index of the slice, implicitly or explicitly, equals |
| ... | ... | @@ -31754,12 +30731,12 @@ fn analyzeSlice( |
| 31754 | 30731 | break :end try sema.coerce(block, .usize, uncasted_end, end_src); |
| 31755 | 30732 | } else try sema.coerce(block, .usize, uncasted_end_opt, end_src); |
| 31756 | 30733 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| 31757 | if (try sema.resolveValue(ptr_or_slice)) |slice_val| { | |
| 30734 | if (sema.resolveValue(ptr_or_slice)) |slice_val| { | |
| 31758 | 30735 | if (slice_val.isUndef(zcu)) { |
| 31759 | 30736 | return sema.fail(block, src, "slice of undefined", .{}); |
| 31760 | 30737 | } |
| 31761 | 30738 | const has_sentinel = slice_ty.sentinel(zcu) != null; |
| 31762 | const slice_len = try slice_val.sliceLen(pt); | |
| 30739 | const slice_len = slice_val.sliceLen(zcu); | |
| 31763 | 30740 | const len_plus_sent = slice_len + @intFromBool(has_sentinel); |
| 31764 | 30741 | const slice_len_val_with_sentinel = try pt.intValue(.usize, len_plus_sent); |
| 31765 | 30742 | if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, .usize))) { |
| ... | ... | @@ -31774,7 +30751,7 @@ fn analyzeSlice( |
| 31774 | 30751 | "end index {f} out of bounds for slice of length {d}{s}", |
| 31775 | 30752 | .{ |
| 31776 | 30753 | end_val.fmtValueSema(pt, sema), |
| 31777 | try slice_val.sliceLen(pt), | |
| 30754 | slice_val.sliceLen(zcu), | |
| 31778 | 30755 | sentinel_label, |
| 31779 | 30756 | }, |
| 31780 | 30757 | ); |
| ... | ... | @@ -31832,7 +30809,7 @@ fn analyzeSlice( |
| 31832 | 30809 | break :msg msg; |
| 31833 | 30810 | }); |
| 31834 | 30811 | } |
| 31835 | return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); | |
| 30812 | return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, start_src); | |
| 31836 | 30813 | }; |
| 31837 | 30814 | |
| 31838 | 30815 | const sentinel = s: { |
| ... | ... | @@ -31876,7 +30853,7 @@ fn analyzeSlice( |
| 31876 | 30853 | ); |
| 31877 | 30854 | } |
| 31878 | 30855 | checked_start_lte_end = true; |
| 31879 | if (try sema.resolveValue(new_ptr)) |ptr_val| sentinel_check: { | |
| 30856 | if (sema.resolveValue(new_ptr)) |ptr_val| sentinel_check: { | |
| 31880 | 30857 | const expected_sentinel = sentinel orelse break :sentinel_check; |
| 31881 | 30858 | const start_int = start_val.toUnsignedInt(zcu); |
| 31882 | 30859 | const end_int = end_val.toUnsignedInt(zcu); |
| ... | ... | @@ -31943,9 +30920,9 @@ fn analyzeSlice( |
| 31943 | 30920 | const new_allowzero = new_ptr_ty_info.flags.is_allowzero and sema.typeOf(ptr).ptrSize(zcu) != .c; |
| 31944 | 30921 | |
| 31945 | 30922 | if (opt_new_len_val) |new_len_val| { |
| 31946 | const new_len_int = try new_len_val.toUnsignedIntSema(pt); | |
| 30923 | const new_len_int = new_len_val.toUnsignedInt(zcu); | |
| 31947 | 30924 | |
| 31948 | const return_ty = try pt.ptrTypeSema(.{ | |
| 30925 | const return_ty = try pt.ptrType(.{ | |
| 31949 | 30926 | .child = (try pt.arrayType(.{ |
| 31950 | 30927 | .len = new_len_int, |
| 31951 | 30928 | .sentinel = if (sentinel) |s| s.toIntern() else .none, |
| ... | ... | @@ -31960,13 +30937,13 @@ fn analyzeSlice( |
| 31960 | 30937 | }, |
| 31961 | 30938 | }); |
| 31962 | 30939 | |
| 31963 | const opt_new_ptr_val = try sema.resolveValue(new_ptr); | |
| 30940 | const opt_new_ptr_val = sema.resolveValue(new_ptr); | |
| 31964 | 30941 | const new_ptr_val = opt_new_ptr_val orelse { |
| 31965 | 30942 | const result = try block.addBitCast(return_ty, new_ptr); |
| 31966 | 30943 | if (block.wantSafety()) { |
| 31967 | 30944 | // requirement: slicing C ptr is non-null |
| 31968 | 30945 | if (ptr_ptr_child_ty.isCPtr(zcu)) { |
| 31969 | const is_non_null = try sema.analyzeIsNull(block, ptr, true); | |
| 30946 | const is_non_null = try block.addUnOp(.is_non_null, ptr); | |
| 31970 | 30947 | try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); |
| 31971 | 30948 | } |
| 31972 | 30949 | |
| ... | ... | @@ -32009,7 +30986,7 @@ fn analyzeSlice( |
| 32009 | 30986 | return sema.fail(block, src, "non-zero length slice of undefined pointer", .{}); |
| 32010 | 30987 | } |
| 32011 | 30988 | |
| 32012 | const return_ty = try pt.ptrTypeSema(.{ | |
| 30989 | const return_ty = try pt.ptrType(.{ | |
| 32013 | 30990 | .child = elem_ty.toIntern(), |
| 32014 | 30991 | .sentinel = if (sentinel) |s| s.toIntern() else .none, |
| 32015 | 30992 | .flags = .{ |
| ... | ... | @@ -32026,7 +31003,7 @@ fn analyzeSlice( |
| 32026 | 31003 | if (block.wantSafety()) { |
| 32027 | 31004 | // requirement: slicing C ptr is non-null |
| 32028 | 31005 | if (ptr_ptr_child_ty.isCPtr(zcu)) { |
| 32029 | const is_non_null = try sema.analyzeIsNull(block, ptr, true); | |
| 31006 | const is_non_null = try block.addUnOp(.is_non_null, ptr); | |
| 32030 | 31007 | try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); |
| 32031 | 31008 | } |
| 32032 | 31009 | |
| ... | ... | @@ -32037,7 +31014,7 @@ fn analyzeSlice( |
| 32037 | 31014 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { |
| 32038 | 31015 | // we don't need to add one for sentinels because the |
| 32039 | 31016 | // underlying value data includes the sentinel |
| 32040 | break :blk try pt.intRef(.usize, try slice_val.sliceLen(pt)); | |
| 31017 | break :blk try pt.intRef(.usize, slice_val.sliceLen(zcu)); | |
| 32041 | 31018 | } |
| 32042 | 31019 | |
| 32043 | 31020 | const slice_len_inst = try block.addTyOp(.slice_len, .usize, ptr_or_slice); |
| ... | ... | @@ -32107,8 +31084,8 @@ fn cmpNumeric( |
| 32107 | 31084 | else |
| 32108 | 31085 | uncasted_rhs; |
| 32109 | 31086 | |
| 32110 | const maybe_lhs_val = try sema.resolveValue(lhs); | |
| 32111 | const maybe_rhs_val = try sema.resolveValue(rhs); | |
| 31087 | const maybe_lhs_val = sema.resolveValue(lhs); | |
| 31088 | const maybe_rhs_val = sema.resolveValue(rhs); | |
| 32112 | 31089 | |
| 32113 | 31090 | // If the LHS is const, check if there is a guaranteed result which does not depend on ths RHS value. |
| 32114 | 31091 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -32158,16 +31135,10 @@ fn cmpNumeric( |
| 32158 | 31135 | |
| 32159 | 31136 | const runtime_src: LazySrcLoc = if (maybe_lhs_val) |lhs_val| rs: { |
| 32160 | 31137 | if (maybe_rhs_val) |rhs_val| { |
| 32161 | const res = try Value.compareHeteroSema(lhs_val, op, rhs_val, pt); | |
| 32162 | return if (res) .bool_true else .bool_false; | |
| 31138 | return .fromValue(.makeBool(Value.compareHetero(lhs_val, op, rhs_val, zcu))); | |
| 32163 | 31139 | } else break :rs rhs_src; |
| 32164 | 31140 | } else lhs_src; |
| 32165 | 31141 | |
| 32166 | // TODO handle comparisons against lazy zero values | |
| 32167 | // Some values can be compared against zero without being runtime-known or without forcing | |
| 32168 | // a full resolution of their value, for example `@sizeOf(@Frame(function))` is known to | |
| 32169 | // always be nonzero, and we benefit from not forcing the full evaluation and stack frame layout | |
| 32170 | // of this function if we don't need to. | |
| 32171 | 31142 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 32172 | 31143 | |
| 32173 | 31144 | // For floats, emit a float comparison instruction. |
| ... | ... | @@ -32207,11 +31178,11 @@ fn cmpNumeric( |
| 32207 | 31178 | // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, |
| 32208 | 31179 | // add/subtract 1. |
| 32209 | 31180 | const lhs_is_signed = if (maybe_lhs_val) |lhs_val| |
| 32210 | !(try lhs_val.compareAllWithZeroSema(.gte, pt)) | |
| 31181 | !lhs_val.compareAllWithZero(.gte, zcu) | |
| 32211 | 31182 | else |
| 32212 | 31183 | (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(zcu)); |
| 32213 | 31184 | const rhs_is_signed = if (maybe_rhs_val) |rhs_val| |
| 32214 | !(try rhs_val.compareAllWithZeroSema(.gte, pt)) | |
| 31185 | !rhs_val.compareAllWithZero(.gte, zcu) | |
| 32215 | 31186 | else |
| 32216 | 31187 | (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(zcu)); |
| 32217 | 31188 | const dest_int_is_signed = lhs_is_signed or rhs_is_signed; |
| ... | ... | @@ -32219,10 +31190,9 @@ fn cmpNumeric( |
| 32219 | 31190 | var dest_float_type: ?Type = null; |
| 32220 | 31191 | |
| 32221 | 31192 | var lhs_bits: usize = undefined; |
| 32222 | if (maybe_lhs_val) |unresolved_lhs_val| { | |
| 32223 | const lhs_val = try sema.resolveLazyValue(unresolved_lhs_val); | |
| 31193 | if (maybe_lhs_val) |lhs_val| { | |
| 32224 | 31194 | if (!rhs_is_signed) { |
| 32225 | switch (lhs_val.orderAgainstZero(zcu)) { | |
| 31195 | switch (Value.order(lhs_val, .zero_comptime_int, zcu)) { | |
| 32226 | 31196 | .gt => {}, |
| 32227 | 31197 | .eq => switch (op) { // LHS = 0, RHS is unsigned |
| 32228 | 31198 | .lte => return .bool_true, |
| ... | ... | @@ -32263,10 +31233,9 @@ fn cmpNumeric( |
| 32263 | 31233 | } |
| 32264 | 31234 | |
| 32265 | 31235 | var rhs_bits: usize = undefined; |
| 32266 | if (maybe_rhs_val) |unresolved_rhs_val| { | |
| 32267 | const rhs_val = try sema.resolveLazyValue(unresolved_rhs_val); | |
| 31236 | if (maybe_rhs_val) |rhs_val| { | |
| 32268 | 31237 | if (!lhs_is_signed) { |
| 32269 | switch (rhs_val.orderAgainstZero(zcu)) { | |
| 31238 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 32270 | 31239 | .gt => {}, |
| 32271 | 31240 | .eq => switch (op) { // RHS = 0, LHS is unsigned |
| 32272 | 31241 | .gte => return .bool_true, |
| ... | ... | @@ -32328,7 +31297,7 @@ fn compareIntsOnlyPossibleResult( |
| 32328 | 31297 | lhs_val: Value, |
| 32329 | 31298 | op: std.math.CompareOperator, |
| 32330 | 31299 | rhs_ty: Type, |
| 32331 | ) SemaError!?bool { | |
| 31300 | ) Allocator.Error!?bool { | |
| 32332 | 31301 | const pt = sema.pt; |
| 32333 | 31302 | const zcu = pt.zcu; |
| 32334 | 31303 | |
| ... | ... | @@ -32337,11 +31306,11 @@ fn compareIntsOnlyPossibleResult( |
| 32337 | 31306 | |
| 32338 | 31307 | if (min_rhs.toIntern() == max_rhs.toIntern()) { |
| 32339 | 31308 | // RHS is effectively comptime-known. |
| 32340 | return try Value.compareHeteroSema(lhs_val, op, min_rhs, pt); | |
| 31309 | return Value.compareHetero(lhs_val, op, min_rhs, zcu); | |
| 32341 | 31310 | } |
| 32342 | 31311 | |
| 32343 | const against_min = try lhs_val.orderAdvanced(min_rhs, .sema, zcu, pt.tid); | |
| 32344 | const against_max = try lhs_val.orderAdvanced(max_rhs, .sema, zcu, pt.tid); | |
| 31312 | const against_min = lhs_val.order(min_rhs, zcu); | |
| 31313 | const against_max = lhs_val.order(max_rhs, zcu); | |
| 32345 | 31314 | |
| 32346 | 31315 | switch (op) { |
| 32347 | 31316 | .eq => { |
| ... | ... | @@ -32401,8 +31370,8 @@ fn cmpVector( |
| 32401 | 31370 | .child = .bool_type, |
| 32402 | 31371 | }); |
| 32403 | 31372 | |
| 32404 | const maybe_lhs_val = try sema.resolveValue(casted_lhs); | |
| 32405 | const maybe_rhs_val = try sema.resolveValue(casted_rhs); | |
| 31373 | const maybe_lhs_val = sema.resolveValue(casted_lhs); | |
| 31374 | const maybe_rhs_val = sema.resolveValue(casted_rhs); | |
| 32406 | 31375 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(result_ty); |
| 32407 | 31376 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(result_ty); |
| 32408 | 31377 | |
| ... | ... | @@ -32424,7 +31393,7 @@ fn wrapOptional( |
| 32424 | 31393 | inst: Air.Inst.Ref, |
| 32425 | 31394 | inst_src: LazySrcLoc, |
| 32426 | 31395 | ) !Air.Inst.Ref { |
| 32427 | if (try sema.resolveValue(inst)) |val| { | |
| 31396 | if (sema.resolveValue(inst)) |val| { | |
| 32428 | 31397 | return Air.internedToRef((try sema.pt.intern(.{ .opt = .{ |
| 32429 | 31398 | .ty = dest_ty.toIntern(), |
| 32430 | 31399 | .val = val.toIntern(), |
| ... | ... | @@ -32446,7 +31415,7 @@ fn wrapErrorUnionPayload( |
| 32446 | 31415 | const zcu = pt.zcu; |
| 32447 | 31416 | const dest_payload_ty = dest_ty.errorUnionPayload(zcu); |
| 32448 | 31417 | const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false }); |
| 32449 | if (try sema.resolveValue(coerced)) |val| { | |
| 31418 | if (sema.resolveValue(coerced)) |val| { | |
| 32450 | 31419 | return Air.internedToRef((try pt.intern(.{ .error_union = .{ |
| 32451 | 31420 | .ty = dest_ty.toIntern(), |
| 32452 | 31421 | .val = .{ .payload = val.toIntern() }, |
| ... | ... | @@ -32466,80 +31435,40 @@ fn wrapErrorUnionSet( |
| 32466 | 31435 | const pt = sema.pt; |
| 32467 | 31436 | const zcu = pt.zcu; |
| 32468 | 31437 | const ip = &zcu.intern_pool; |
| 32469 | const inst_ty = sema.typeOf(inst); | |
| 32470 | 31438 | const dest_err_set_ty = dest_ty.errorUnionSet(zcu); |
| 32471 | if (try sema.resolveValue(inst)) |val| { | |
| 32472 | const expected_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name; | |
| 32473 | switch (dest_err_set_ty.toIntern()) { | |
| 32474 | .anyerror_type => {}, | |
| 32475 | .adhoc_inferred_error_set_type => ok: { | |
| 32476 | const ies = sema.fn_ret_ty_ies.?; | |
| 32477 | switch (ies.resolved) { | |
| 32478 | .anyerror_type => break :ok, | |
| 32479 | .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { | |
| 32480 | break :ok; | |
| 32481 | }, | |
| 32482 | else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { | |
| 32483 | break :ok; | |
| 32484 | }, | |
| 32485 | } | |
| 32486 | return sema.failWithTypeMismatch(block, inst_src, dest_err_set_ty, inst_ty); | |
| 32487 | }, | |
| 32488 | else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) { | |
| 32489 | .error_set_type => |error_set_type| ok: { | |
| 32490 | if (error_set_type.nameIndex(ip, expected_name) != null) break :ok; | |
| 32491 | return sema.failWithTypeMismatch(block, inst_src, dest_err_set_ty, inst_ty); | |
| 32492 | }, | |
| 32493 | .inferred_error_set_type => |func_index| ok: { | |
| 32494 | // We carefully do this in an order that avoids unnecessarily | |
| 32495 | // resolving the destination error set type. | |
| 32496 | try zcu.maybeUnresolveIes(func_index); | |
| 32497 | switch (ip.funcIesResolvedUnordered(func_index)) { | |
| 32498 | .anyerror_type => break :ok, | |
| 32499 | .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { | |
| 32500 | break :ok; | |
| 32501 | }, | |
| 32502 | else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { | |
| 32503 | break :ok; | |
| 32504 | }, | |
| 32505 | } | |
| 32506 | ||
| 32507 | return sema.failWithTypeMismatch(block, inst_src, dest_err_set_ty, inst_ty); | |
| 32508 | }, | |
| 32509 | else => unreachable, | |
| 32510 | }, | |
| 32511 | } | |
| 32512 | return Air.internedToRef((try pt.intern(.{ .error_union = .{ | |
| 31439 | const coerced = try sema.coerceExtra(block, dest_err_set_ty, inst, inst_src, .{ .report_err = false }); | |
| 31440 | if (try sema.resolveDefinedValue(block, inst_src, coerced)) |error_val| { | |
| 31441 | return .fromIntern(try pt.intern(.{ .error_union = .{ | |
| 32513 | 31442 | .ty = dest_ty.toIntern(), |
| 32514 | .val = .{ .err_name = expected_name }, | |
| 32515 | } }))); | |
| 31443 | .val = .{ .err_name = ip.indexToKey(error_val.toIntern()).err.name }, | |
| 31444 | } })); | |
| 31445 | } else { | |
| 31446 | return block.addTyOp(.wrap_errunion_err, dest_ty, coerced); | |
| 32516 | 31447 | } |
| 32517 | ||
| 32518 | try sema.requireRuntimeBlock(block, inst_src, null); | |
| 32519 | const coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src); | |
| 32520 | return block.addTyOp(.wrap_errunion_err, dest_ty, coerced); | |
| 32521 | 31448 | } |
| 32522 | 31449 | |
| 32523 | fn unionToTag( | |
| 32524 | sema: *Sema, | |
| 32525 | block: *Block, | |
| 32526 | enum_ty: Type, | |
| 32527 | un: Air.Inst.Ref, | |
| 32528 | un_src: LazySrcLoc, | |
| 32529 | ) !Air.Inst.Ref { | |
| 31450 | /// Returns the enum tag value for the active tag of a tagged union value. | |
| 31451 | /// | |
| 31452 | /// Asserts that the type of `un` is a tagged union type. | |
| 31453 | fn unionToTag(sema: *Sema, block: *Block, un: Air.Inst.Ref) !Air.Inst.Ref { | |
| 32530 | 31454 | const pt = sema.pt; |
| 32531 | 31455 | const zcu = pt.zcu; |
| 32532 | if ((try sema.typeHasOnePossibleValue(enum_ty))) |opv| { | |
| 32533 | return Air.internedToRef(opv.toIntern()); | |
| 31456 | const ip = &zcu.intern_pool; | |
| 31457 | const union_obj = ip.loadUnionType(sema.typeOf(un).toIntern()); | |
| 31458 | assert(union_obj.tag_usage == .tagged); | |
| 31459 | if (sema.resolveValue(un)) |un_val| { | |
| 31460 | return .fromValue(un_val.unionTag(zcu).?); | |
| 32534 | 31461 | } |
| 32535 | if (try sema.resolveValue(un)) |un_val| { | |
| 32536 | const tag_val = un_val.unionTag(zcu).?; | |
| 32537 | if (tag_val.isUndef(zcu)) | |
| 32538 | return try pt.undefRef(enum_ty); | |
| 32539 | return Air.internedToRef(tag_val.toIntern()); | |
| 31462 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); | |
| 31463 | if (!union_obj.has_runtime_tag) { | |
| 31464 | // This means that only one field is possible. | |
| 31465 | const field_index = for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { | |
| 31466 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 31467 | if (field_ty.classify(zcu) != .no_possible_value) break field_index; | |
| 31468 | } else unreachable; | |
| 31469 | return .fromValue(try pt.enumValueFieldIndex(enum_tag_ty, @intCast(field_index))); | |
| 32540 | 31470 | } |
| 32541 | try sema.requireRuntimeBlock(block, un_src, null); | |
| 32542 | return block.addTyOp(.get_union_tag, enum_ty, un); | |
| 31471 | return block.addTyOp(.get_union_tag, enum_tag_ty, un); | |
| 32543 | 31472 | } |
| 32544 | 31473 | |
| 32545 | 31474 | const PeerResolveStrategy = enum { |
| ... | ... | @@ -32879,7 +31808,7 @@ fn resolvePeerTypes( |
| 32879 | 31808 | |
| 32880 | 31809 | for (instructions, peer_tys, peer_vals) |inst, *ty, *val| { |
| 32881 | 31810 | ty.* = sema.typeOf(inst); |
| 32882 | val.* = try sema.resolveValue(inst); | |
| 31811 | val.* = sema.resolveValue(inst); | |
| 32883 | 31812 | } |
| 32884 | 31813 | |
| 32885 | 31814 | switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals)) { |
| ... | ... | @@ -33240,18 +32169,24 @@ fn resolvePeerTypesInner( |
| 33240 | 32169 | ptr_info.sentinel = .none; |
| 33241 | 32170 | } |
| 33242 | 32171 | |
| 33243 | // Note that the align can be always non-zero; Zcu.ptrType will canonicalize it | |
| 33244 | ptr_info.flags.alignment = InternPool.Alignment.min( | |
| 33245 | if (ptr_info.flags.alignment != .none) | |
| 33246 | ptr_info.flags.alignment | |
| 33247 | else | |
| 33248 | Type.fromInterned(ptr_info.child).abiAlignment(zcu), | |
| 33249 | ||
| 33250 | if (peer_info.flags.alignment != .none) | |
| 33251 | peer_info.flags.alignment | |
| 33252 | else | |
| 33253 | Type.fromInterned(peer_info.child).abiAlignment(zcu), | |
| 33254 | ); | |
| 32172 | ptr_info.flags.alignment = a: { | |
| 32173 | // If both alignments are implicit, the result alignment is implicit. | |
| 32174 | // e.g. '[*c]u32' + '[*c]c_uint' -> '[*c]u32' | |
| 32175 | if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) { | |
| 32176 | break :a .none; | |
| 32177 | } | |
| 32178 | // Otherwise (if either alignment is explicit), the result alignment is explicit. | |
| 32179 | // e.g. '[*c]u32' + '[*c]align(4) c_uint' -> '[*c]align(4) u32' | |
| 32180 | const cur_align = switch (ptr_info.flags.alignment) { | |
| 32181 | .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu), | |
| 32182 | else => ptr_info.flags.alignment, | |
| 32183 | }; | |
| 32184 | const new_align = switch (peer_info.flags.alignment) { | |
| 32185 | .none => Type.fromInterned(peer_info.child).abiAlignment(zcu), | |
| 32186 | else => peer_info.flags.alignment, | |
| 32187 | }; | |
| 32188 | break :a .minStrict(cur_align, new_align); | |
| 32189 | }; | |
| 33255 | 32190 | if (ptr_info.flags.address_space != peer_info.flags.address_space) { |
| 33256 | 32191 | return .{ .conflict = .{ |
| 33257 | 32192 | .peer_idx_a = first_idx, |
| ... | ... | @@ -33273,7 +32208,7 @@ fn resolvePeerTypesInner( |
| 33273 | 32208 | |
| 33274 | 32209 | opt_ptr_info = ptr_info; |
| 33275 | 32210 | } |
| 33276 | return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) }; | |
| 32211 | return .{ .success = try pt.ptrType(opt_ptr_info.?) }; | |
| 33277 | 32212 | }, |
| 33278 | 32213 | |
| 33279 | 32214 | .ptr => { |
| ... | ... | @@ -33281,7 +32216,6 @@ fn resolvePeerTypesInner( |
| 33281 | 32216 | // if there were no actual slices. Else, we want the slice index to report a conflict. |
| 33282 | 32217 | var opt_slice_idx: ?usize = null; |
| 33283 | 32218 | |
| 33284 | var any_abi_aligned = false; | |
| 33285 | 32219 | var opt_ptr_info: ?InternPool.Key.PtrType = null; |
| 33286 | 32220 | var first_idx: usize = undefined; |
| 33287 | 32221 | var other_idx: usize = undefined; // We sometimes need a second peer index to report a generic error |
| ... | ... | @@ -33325,15 +32259,24 @@ fn resolvePeerTypesInner( |
| 33325 | 32259 | .peer_idx_b = i, |
| 33326 | 32260 | } }; |
| 33327 | 32261 | |
| 33328 | // Note that the align can be always non-zero; Type.ptr will canonicalize it | |
| 33329 | if (peer_info.flags.alignment == .none) { | |
| 33330 | any_abi_aligned = true; | |
| 33331 | } else if (ptr_info.flags.alignment == .none) { | |
| 33332 | any_abi_aligned = true; | |
| 33333 | ptr_info.flags.alignment = peer_info.flags.alignment; | |
| 33334 | } else { | |
| 33335 | ptr_info.flags.alignment = ptr_info.flags.alignment.minStrict(peer_info.flags.alignment); | |
| 33336 | } | |
| 32262 | ptr_info.flags.alignment = a: { | |
| 32263 | // If both alignments are implicit, the result alignment is implicit. | |
| 32264 | // e.g. '*u32' + '*c_uint' -> '*u32' | |
| 32265 | if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) { | |
| 32266 | break :a .none; | |
| 32267 | } | |
| 32268 | // Otherwise (if either alignment is explicit), the result alignment is explicit. | |
| 32269 | // e.g. '*u32' + '*align(4) c_uint' -> '*align(4) u32' | |
| 32270 | const cur_align = switch (ptr_info.flags.alignment) { | |
| 32271 | .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu), | |
| 32272 | else => ptr_info.flags.alignment, | |
| 32273 | }; | |
| 32274 | const new_align = switch (peer_info.flags.alignment) { | |
| 32275 | .none => Type.fromInterned(peer_info.child).abiAlignment(zcu), | |
| 32276 | else => peer_info.flags.alignment, | |
| 32277 | }; | |
| 32278 | break :a .minStrict(cur_align, new_align); | |
| 32279 | }; | |
| 33337 | 32280 | |
| 33338 | 32281 | if (ptr_info.flags.address_space != peer_info.flags.address_space) { |
| 33339 | 32282 | return generic_err; |
| ... | ... | @@ -33582,13 +32525,7 @@ fn resolvePeerTypesInner( |
| 33582 | 32525 | }, |
| 33583 | 32526 | } |
| 33584 | 32527 | |
| 33585 | if (any_abi_aligned and opt_ptr_info.?.flags.alignment != .none) { | |
| 33586 | opt_ptr_info.?.flags.alignment = opt_ptr_info.?.flags.alignment.minStrict( | |
| 33587 | try Type.fromInterned(pointee).abiAlignmentSema(pt), | |
| 33588 | ); | |
| 33589 | } | |
| 33590 | ||
| 33591 | return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) }; | |
| 32528 | return .{ .success = try pt.ptrType(opt_ptr_info.?) }; | |
| 33592 | 32529 | }, |
| 33593 | 32530 | |
| 33594 | 32531 | .func => { |
| ... | ... | @@ -33731,7 +32668,7 @@ fn resolvePeerTypesInner( |
| 33731 | 32668 | .peer_idx_b = i, |
| 33732 | 32669 | } }; |
| 33733 | 32670 | any_comptime_known = true; |
| 33734 | ptr_opt_val.* = try sema.resolveLazyValue(opt_val.?); | |
| 32671 | ptr_opt_val.* = opt_val.?; | |
| 33735 | 32672 | continue; |
| 33736 | 32673 | }, |
| 33737 | 32674 | .int => {}, |
| ... | ... | @@ -33924,7 +32861,6 @@ fn resolvePeerTypesInner( |
| 33924 | 32861 | var comptime_val: ?Value = null; |
| 33925 | 32862 | for (peer_tys) |opt_ty| { |
| 33926 | 32863 | const struct_ty = opt_ty orelse continue; |
| 33927 | try struct_ty.resolveStructFieldInits(pt); | |
| 33928 | 32864 | |
| 33929 | 32865 | const uncoerced_field_val = try struct_ty.structFieldValueComptime(pt, field_index) orelse { |
| 33930 | 32866 | comptime_val = null; |
| ... | ... | @@ -33939,2242 +32875,274 @@ fn resolvePeerTypesInner( |
| 33939 | 32875 | }, |
| 33940 | 32876 | else => |e| return e, |
| 33941 | 32877 | }; |
| 33942 | const coerced_val = (try sema.resolveValue(coerced_inst)) orelse continue; | |
| 32878 | const coerced_val = sema.resolveValue(coerced_inst) orelse continue; | |
| 33943 | 32879 | const existing = comptime_val orelse { |
| 33944 | 32880 | comptime_val = coerced_val; |
| 33945 | continue; | |
| 33946 | }; | |
| 33947 | if (!coerced_val.eql(existing, .fromInterned(field_ty.*), zcu)) { | |
| 33948 | comptime_val = null; | |
| 33949 | break; | |
| 33950 | } | |
| 33951 | } | |
| 33952 | ||
| 33953 | field_val.* = if (comptime_val) |v| v.toIntern() else .none; | |
| 33954 | } | |
| 33955 | ||
| 33956 | const final_ty = try ip.getTupleType(gpa, io, pt.tid, .{ | |
| 33957 | .types = field_types, | |
| 33958 | .values = field_vals, | |
| 33959 | }); | |
| 33960 | ||
| 33961 | return .{ .success = .fromInterned(final_ty) }; | |
| 33962 | }, | |
| 33963 | ||
| 33964 | .exact => { | |
| 33965 | var expect_ty: ?Type = null; | |
| 33966 | var first_idx: usize = undefined; | |
| 33967 | for (peer_tys, 0..) |opt_ty, i| { | |
| 33968 | const ty = opt_ty orelse continue; | |
| 33969 | if (expect_ty) |expect| { | |
| 33970 | if (!ty.eql(expect, zcu)) return .{ .conflict = .{ | |
| 33971 | .peer_idx_a = first_idx, | |
| 33972 | .peer_idx_b = i, | |
| 33973 | } }; | |
| 33974 | } else { | |
| 33975 | expect_ty = ty; | |
| 33976 | first_idx = i; | |
| 33977 | } | |
| 33978 | } | |
| 33979 | return .{ .success = expect_ty.? }; | |
| 33980 | }, | |
| 33981 | } | |
| 33982 | } | |
| 33983 | ||
| 33984 | fn maybeMergeErrorSets(sema: *Sema, block: *Block, src: LazySrcLoc, e0: Type, e1: Type) !Type { | |
| 33985 | // e0 -> e1 | |
| 33986 | if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, e1, e0, src, src)) { | |
| 33987 | return e1; | |
| 33988 | } | |
| 33989 | ||
| 33990 | // e1 -> e0 | |
| 33991 | if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, e0, e1, src, src)) { | |
| 33992 | return e0; | |
| 33993 | } | |
| 33994 | ||
| 33995 | return sema.errorSetMerge(e0, e1); | |
| 33996 | } | |
| 33997 | ||
| 33998 | fn resolvePairInMemoryCoercible(sema: *Sema, block: *Block, src: LazySrcLoc, ty_a: Type, ty_b: Type) !?Type { | |
| 33999 | const target = sema.pt.zcu.getTarget(); | |
| 34000 | ||
| 34001 | // ty_b -> ty_a | |
| 34002 | if (.ok == try sema.coerceInMemoryAllowed(block, ty_a, ty_b, false, target, src, src, null)) { | |
| 34003 | return ty_a; | |
| 34004 | } | |
| 34005 | ||
| 34006 | // ty_a -> ty_b | |
| 34007 | if (.ok == try sema.coerceInMemoryAllowed(block, ty_b, ty_a, false, target, src, src, null)) { | |
| 34008 | return ty_b; | |
| 34009 | } | |
| 34010 | ||
| 34011 | return null; | |
| 34012 | } | |
| 34013 | ||
| 34014 | const ArrayLike = struct { | |
| 34015 | len: u64, | |
| 34016 | /// `noreturn` indicates that this type is `struct{}` so can coerce to anything | |
| 34017 | elem_ty: Type, | |
| 34018 | }; | |
| 34019 | fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { | |
| 34020 | const pt = sema.pt; | |
| 34021 | const zcu = pt.zcu; | |
| 34022 | return switch (ty.zigTypeTag(zcu)) { | |
| 34023 | .array => .{ | |
| 34024 | .len = ty.arrayLen(zcu), | |
| 34025 | .elem_ty = ty.childType(zcu), | |
| 34026 | }, | |
| 34027 | .@"struct" => { | |
| 34028 | const field_count = ty.structFieldCount(zcu); | |
| 34029 | if (field_count == 0) return .{ | |
| 34030 | .len = 0, | |
| 34031 | .elem_ty = .noreturn, | |
| 34032 | }; | |
| 34033 | if (!ty.isTuple(zcu)) return null; | |
| 34034 | const elem_ty = ty.fieldType(0, zcu); | |
| 34035 | for (1..field_count) |i| { | |
| 34036 | if (!ty.fieldType(i, zcu).eql(elem_ty, zcu)) { | |
| 34037 | return null; | |
| 34038 | } | |
| 34039 | } | |
| 34040 | return .{ | |
| 34041 | .len = field_count, | |
| 34042 | .elem_ty = elem_ty, | |
| 34043 | }; | |
| 34044 | }, | |
| 34045 | else => null, | |
| 34046 | }; | |
| 34047 | } | |
| 34048 | ||
| 34049 | pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void { | |
| 34050 | const pt = sema.pt; | |
| 34051 | const zcu = pt.zcu; | |
| 34052 | const ip = &zcu.intern_pool; | |
| 34053 | ||
| 34054 | if (sema.fn_ret_ty_ies) |ies| { | |
| 34055 | try sema.resolveInferredErrorSetPtr(block, src, ies); | |
| 34056 | assert(ies.resolved != .none); | |
| 34057 | ip.funcIesResolved(sema.func_index).* = ies.resolved; | |
| 34058 | } | |
| 34059 | } | |
| 34060 | ||
| 34061 | pub fn resolveFnTypes(sema: *Sema, fn_ty: Type, src: LazySrcLoc) CompileError!void { | |
| 34062 | const pt = sema.pt; | |
| 34063 | const zcu = pt.zcu; | |
| 34064 | const ip = &zcu.intern_pool; | |
| 34065 | const fn_ty_info = zcu.typeToFunc(fn_ty).?; | |
| 34066 | ||
| 34067 | try Type.fromInterned(fn_ty_info.return_type).resolveFully(pt); | |
| 34068 | ||
| 34069 | if (zcu.comp.config.any_error_tracing and | |
| 34070 | Type.fromInterned(fn_ty_info.return_type).isError(zcu)) | |
| 34071 | { | |
| 34072 | // Ensure the type exists so that backends can assume that. | |
| 34073 | _ = try sema.getBuiltinType(src, .StackTrace); | |
| 34074 | } | |
| 34075 | ||
| 34076 | for (0..fn_ty_info.param_types.len) |i| { | |
| 34077 | try Type.fromInterned(fn_ty_info.param_types.get(ip)[i]).resolveFully(pt); | |
| 34078 | } | |
| 34079 | } | |
| 34080 | ||
| 34081 | fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { | |
| 34082 | return val.resolveLazy(sema.arena, sema.pt); | |
| 34083 | } | |
| 34084 | ||
| 34085 | /// Resolve a struct's alignment only without triggering resolution of its layout. | |
| 34086 | /// Asserts that the alignment is not yet resolved and the layout is non-packed. | |
| 34087 | pub fn resolveStructAlignment( | |
| 34088 | sema: *Sema, | |
| 34089 | ty: InternPool.Index, | |
| 34090 | struct_type: InternPool.LoadedStructType, | |
| 34091 | ) SemaError!void { | |
| 34092 | const pt = sema.pt; | |
| 34093 | const zcu = pt.zcu; | |
| 34094 | const io = zcu.comp.io; | |
| 34095 | const ip = &zcu.intern_pool; | |
| 34096 | const target = zcu.getTarget(); | |
| 34097 | ||
| 34098 | assert(sema.owner.unwrap().type == ty); | |
| 34099 | ||
| 34100 | assert(struct_type.layout != .@"packed"); | |
| 34101 | assert(struct_type.flagsUnordered(ip).alignment == .none); | |
| 34102 | ||
| 34103 | const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); | |
| 34104 | ||
| 34105 | // We'll guess "pointer-aligned", if the struct has an | |
| 34106 | // underaligned pointer field then some allocations | |
| 34107 | // might require explicit alignment. | |
| 34108 | if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; | |
| 34109 | ||
| 34110 | try sema.resolveStructFieldTypes(ty, struct_type); | |
| 34111 | ||
| 34112 | // We'll guess "pointer-aligned", if the struct has an | |
| 34113 | // underaligned pointer field then some allocations | |
| 34114 | // might require explicit alignment. | |
| 34115 | if (struct_type.assumePointerAlignedIfWip(ip, io, ptr_align)) return; | |
| 34116 | defer struct_type.clearAlignmentWip(ip, io); | |
| 34117 | ||
| 34118 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. | |
| 34119 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. | |
| 34120 | ||
| 34121 | var alignment: Alignment = .@"1"; | |
| 34122 | ||
| 34123 | for (0..struct_type.field_types.len) |i| { | |
| 34124 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34125 | if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) | |
| 34126 | continue; | |
| 34127 | const field_align = try field_ty.structFieldAlignmentSema( | |
| 34128 | struct_type.fieldAlign(ip, i), | |
| 34129 | struct_type.layout, | |
| 34130 | pt, | |
| 34131 | ); | |
| 34132 | alignment = alignment.maxStrict(field_align); | |
| 34133 | } | |
| 34134 | ||
| 34135 | struct_type.setAlignment(ip, io, alignment); | |
| 34136 | } | |
| 34137 | ||
| 34138 | pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { | |
| 34139 | const pt = sema.pt; | |
| 34140 | const zcu = pt.zcu; | |
| 34141 | const ip = &zcu.intern_pool; | |
| 34142 | const io = zcu.comp.io; | |
| 34143 | const struct_type = zcu.typeToStruct(ty) orelse return; | |
| 34144 | ||
| 34145 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34146 | ||
| 34147 | if (struct_type.haveLayout(ip)) | |
| 34148 | return; | |
| 34149 | ||
| 34150 | try sema.resolveStructFieldTypes(ty.toIntern(), struct_type); | |
| 34151 | ||
| 34152 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. | |
| 34153 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. | |
| 34154 | ||
| 34155 | if (struct_type.layout == .@"packed") { | |
| 34156 | sema.backingIntType(struct_type) catch |err| switch (err) { | |
| 34157 | error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, | |
| 34158 | error.ComptimeBreak, error.ComptimeReturn => unreachable, | |
| 34159 | }; | |
| 34160 | return; | |
| 34161 | } | |
| 34162 | ||
| 34163 | if (struct_type.setLayoutWip(ip, io)) { | |
| 34164 | const msg = try sema.errMsg( | |
| 34165 | ty.srcLoc(zcu), | |
| 34166 | "struct '{f}' depends on itself", | |
| 34167 | .{ty.fmt(pt)}, | |
| 34168 | ); | |
| 34169 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34170 | } | |
| 34171 | defer struct_type.clearLayoutWip(ip, io); | |
| 34172 | ||
| 34173 | const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); | |
| 34174 | const sizes = try sema.arena.alloc(u64, struct_type.field_types.len); | |
| 34175 | ||
| 34176 | var big_align: Alignment = .@"1"; | |
| 34177 | ||
| 34178 | for (aligns, sizes, 0..) |*field_align, *field_size, i| { | |
| 34179 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34180 | if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) { | |
| 34181 | struct_type.offsets.get(ip)[i] = 0; | |
| 34182 | field_size.* = 0; | |
| 34183 | field_align.* = .none; | |
| 34184 | continue; | |
| 34185 | } | |
| 34186 | ||
| 34187 | field_size.* = field_ty.abiSizeSema(pt) catch |err| switch (err) { | |
| 34188 | error.AnalysisFail => { | |
| 34189 | const msg = sema.err orelse return err; | |
| 34190 | try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{}); | |
| 34191 | return err; | |
| 34192 | }, | |
| 34193 | else => return err, | |
| 34194 | }; | |
| 34195 | field_align.* = try field_ty.structFieldAlignmentSema( | |
| 34196 | struct_type.fieldAlign(ip, i), | |
| 34197 | struct_type.layout, | |
| 34198 | pt, | |
| 34199 | ); | |
| 34200 | big_align = big_align.maxStrict(field_align.*); | |
| 34201 | } | |
| 34202 | ||
| 34203 | if (struct_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) { | |
| 34204 | const msg = try sema.errMsg( | |
| 34205 | ty.srcLoc(zcu), | |
| 34206 | "struct layout depends on it having runtime bits", | |
| 34207 | .{}, | |
| 34208 | ); | |
| 34209 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34210 | } | |
| 34211 | ||
| 34212 | if (struct_type.flagsUnordered(ip).assumed_pointer_aligned and | |
| 34213 | big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(zcu.getTarget().ptrBitWidth(), 8)))) | |
| 34214 | { | |
| 34215 | const msg = try sema.errMsg( | |
| 34216 | ty.srcLoc(zcu), | |
| 34217 | "struct layout depends on being pointer aligned", | |
| 34218 | .{}, | |
| 34219 | ); | |
| 34220 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34221 | } | |
| 34222 | ||
| 34223 | if (struct_type.hasReorderedFields()) { | |
| 34224 | const runtime_order = struct_type.runtime_order.get(ip); | |
| 34225 | ||
| 34226 | for (runtime_order, 0..) |*ro, i| { | |
| 34227 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34228 | if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) { | |
| 34229 | ro.* = .omitted; | |
| 34230 | } else { | |
| 34231 | ro.* = @enumFromInt(i); | |
| 34232 | } | |
| 34233 | } | |
| 34234 | ||
| 34235 | const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder; | |
| 34236 | ||
| 34237 | const AlignSortContext = struct { | |
| 34238 | aligns: []const Alignment, | |
| 34239 | ||
| 34240 | fn lessThan(ctx: @This(), a: RuntimeOrder, b: RuntimeOrder) bool { | |
| 34241 | if (a == .omitted) return false; | |
| 34242 | if (b == .omitted) return true; | |
| 34243 | const a_align = ctx.aligns[@intFromEnum(a)]; | |
| 34244 | const b_align = ctx.aligns[@intFromEnum(b)]; | |
| 34245 | return a_align.compare(.gt, b_align); | |
| 34246 | } | |
| 34247 | }; | |
| 34248 | if (!zcu.backendSupportsFeature(.field_reordering)) { | |
| 34249 | // TODO: we should probably also reorder tuple fields? This is a bit weird because it'll involve | |
| 34250 | // mutating the `InternPool` for a non-container type. | |
| 34251 | // | |
| 34252 | // TODO: implement field reordering support in all the backends! | |
| 34253 | // | |
| 34254 | // This logic does not reorder fields; it only moves the omitted ones to the end | |
| 34255 | // so that logic elsewhere does not need to special-case here. | |
| 34256 | var i: usize = 0; | |
| 34257 | var off: usize = 0; | |
| 34258 | while (i + off < runtime_order.len) { | |
| 34259 | if (runtime_order[i + off] == .omitted) { | |
| 34260 | off += 1; | |
| 34261 | continue; | |
| 34262 | } | |
| 34263 | runtime_order[i] = runtime_order[i + off]; | |
| 34264 | i += 1; | |
| 34265 | } | |
| 34266 | @memset(runtime_order[i..], .omitted); | |
| 34267 | } else { | |
| 34268 | mem.sortUnstable(RuntimeOrder, runtime_order, AlignSortContext{ | |
| 34269 | .aligns = aligns, | |
| 34270 | }, AlignSortContext.lessThan); | |
| 34271 | } | |
| 34272 | } | |
| 34273 | ||
| 34274 | // Calculate size, alignment, and field offsets. | |
| 34275 | const offsets = struct_type.offsets.get(ip); | |
| 34276 | var it = struct_type.iterateRuntimeOrder(ip); | |
| 34277 | var offset: u64 = 0; | |
| 34278 | while (it.next()) |i| { | |
| 34279 | offsets[i] = @intCast(aligns[i].forward(offset)); | |
| 34280 | offset = offsets[i] + sizes[i]; | |
| 34281 | } | |
| 34282 | const size = std.math.cast(u32, big_align.forward(offset)) orelse { | |
| 34283 | const msg = try sema.errMsg( | |
| 34284 | ty.srcLoc(zcu), | |
| 34285 | "struct layout requires size {d}, this compiler implementation supports up to {d}", | |
| 34286 | .{ big_align.forward(offset), std.math.maxInt(u32) }, | |
| 34287 | ); | |
| 34288 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34289 | }; | |
| 34290 | struct_type.setLayoutResolved(ip, io, size, big_align); | |
| 34291 | _ = try ty.comptimeOnlySema(pt); | |
| 34292 | } | |
| 34293 | ||
| 34294 | fn backingIntType( | |
| 34295 | sema: *Sema, | |
| 34296 | struct_type: InternPool.LoadedStructType, | |
| 34297 | ) CompileError!void { | |
| 34298 | const pt = sema.pt; | |
| 34299 | const zcu = pt.zcu; | |
| 34300 | const comp = zcu.comp; | |
| 34301 | const gpa = comp.gpa; | |
| 34302 | const io = comp.io; | |
| 34303 | const ip = &zcu.intern_pool; | |
| 34304 | ||
| 34305 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | |
| 34306 | defer analysis_arena.deinit(); | |
| 34307 | ||
| 34308 | var block: Block = .{ | |
| 34309 | .parent = null, | |
| 34310 | .sema = sema, | |
| 34311 | .namespace = struct_type.namespace, | |
| 34312 | .instructions = .{}, | |
| 34313 | .inlining = null, | |
| 34314 | .comptime_reason = null, // set below if needed | |
| 34315 | .src_base_inst = struct_type.zir_index, | |
| 34316 | .type_name_ctx = struct_type.name, | |
| 34317 | }; | |
| 34318 | defer assert(block.instructions.items.len == 0); | |
| 34319 | ||
| 34320 | const fields_bit_sum = blk: { | |
| 34321 | var accumulator: u64 = 0; | |
| 34322 | for (0..struct_type.field_types.len) |i| { | |
| 34323 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34324 | accumulator += try field_ty.bitSizeSema(pt); | |
| 34325 | } | |
| 34326 | break :blk accumulator; | |
| 34327 | }; | |
| 34328 | ||
| 34329 | const zir = zcu.namespacePtr(struct_type.namespace).fileScope(zcu).zir.?; | |
| 34330 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 34331 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | |
| 34332 | assert(extended.opcode == .struct_decl); | |
| 34333 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 34334 | ||
| 34335 | if (small.has_backing_int) { | |
| 34336 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; | |
| 34337 | const captures_len = if (small.has_captures_len) blk: { | |
| 34338 | const captures_len = zir.extra[extra_index]; | |
| 34339 | extra_index += 1; | |
| 34340 | break :blk captures_len; | |
| 34341 | } else 0; | |
| 34342 | extra_index += @intFromBool(small.has_fields_len); | |
| 34343 | extra_index += @intFromBool(small.has_decls_len); | |
| 34344 | ||
| 34345 | extra_index += captures_len * 2; | |
| 34346 | ||
| 34347 | const backing_int_body_len = zir.extra[extra_index]; | |
| 34348 | extra_index += 1; | |
| 34349 | ||
| 34350 | const backing_int_src: LazySrcLoc = .{ | |
| 34351 | .base_node_inst = struct_type.zir_index, | |
| 34352 | .offset = .{ .node_offset_container_tag = .zero }, | |
| 34353 | }; | |
| 34354 | block.comptime_reason = .{ .reason = .{ | |
| 34355 | .src = backing_int_src, | |
| 34356 | .r = .{ .simple = .type }, | |
| 34357 | } }; | |
| 34358 | const backing_int_ty = blk: { | |
| 34359 | if (backing_int_body_len == 0) { | |
| 34360 | const backing_int_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 34361 | break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref); | |
| 34362 | } else { | |
| 34363 | const body = zir.bodySlice(extra_index, backing_int_body_len); | |
| 34364 | const ty_ref = try sema.resolveInlineBody(&block, body, zir_index); | |
| 34365 | break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref); | |
| 34366 | } | |
| 34367 | }; | |
| 34368 | ||
| 34369 | try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum); | |
| 34370 | struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern()); | |
| 34371 | } else { | |
| 34372 | if (fields_bit_sum > std.math.maxInt(u16)) { | |
| 34373 | return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | |
| 34374 | } | |
| 34375 | const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); | |
| 34376 | struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern()); | |
| 34377 | } | |
| 34378 | ||
| 34379 | try sema.flushExports(); | |
| 34380 | } | |
| 34381 | ||
| 34382 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { | |
| 34383 | const pt = sema.pt; | |
| 34384 | const zcu = pt.zcu; | |
| 34385 | ||
| 34386 | if (!backing_int_ty.isInt(zcu)) { | |
| 34387 | return sema.fail(block, src, "expected backing integer type, found '{f}'", .{backing_int_ty.fmt(pt)}); | |
| 34388 | } | |
| 34389 | if (backing_int_ty.bitSize(zcu) != fields_bit_sum) { | |
| 34390 | return sema.fail( | |
| 34391 | block, | |
| 34392 | src, | |
| 34393 | "backing integer type '{f}' has bit size {d} but the struct fields have a total bit size of {d}", | |
| 34394 | .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum }, | |
| 34395 | ); | |
| 34396 | } | |
| 34397 | } | |
| 34398 | ||
| 34399 | fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | |
| 34400 | const pt = sema.pt; | |
| 34401 | if (!ty.isIndexable(pt.zcu)) { | |
| 34402 | const msg = msg: { | |
| 34403 | const msg = try sema.errMsg(src, "type '{f}' does not support indexing", .{ty.fmt(pt)}); | |
| 34404 | errdefer msg.destroy(sema.gpa); | |
| 34405 | try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{}); | |
| 34406 | break :msg msg; | |
| 34407 | }; | |
| 34408 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 34409 | } | |
| 34410 | } | |
| 34411 | ||
| 34412 | fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | |
| 34413 | const pt = sema.pt; | |
| 34414 | const zcu = pt.zcu; | |
| 34415 | if (ty.zigTypeTag(zcu) == .pointer) { | |
| 34416 | switch (ty.ptrSize(zcu)) { | |
| 34417 | .slice, .many, .c => return, | |
| 34418 | .one => { | |
| 34419 | const elem_ty = ty.childType(zcu); | |
| 34420 | if (elem_ty.zigTypeTag(zcu) == .array) return; | |
| 34421 | // TODO https://github.com/ziglang/zig/issues/15479 | |
| 34422 | // if (elem_ty.isTuple()) return; | |
| 34423 | }, | |
| 34424 | } | |
| 34425 | } | |
| 34426 | const msg = msg: { | |
| 34427 | const msg = try sema.errMsg(src, "type '{f}' is not an indexable pointer", .{ty.fmt(pt)}); | |
| 34428 | errdefer msg.destroy(sema.gpa); | |
| 34429 | try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); | |
| 34430 | break :msg msg; | |
| 34431 | }; | |
| 34432 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 34433 | } | |
| 34434 | ||
| 34435 | /// Resolve a unions's alignment only without triggering resolution of its layout. | |
| 34436 | /// Asserts that the alignment is not yet resolved. | |
| 34437 | pub fn resolveUnionAlignment( | |
| 34438 | sema: *Sema, | |
| 34439 | ty: Type, | |
| 34440 | union_type: InternPool.LoadedUnionType, | |
| 34441 | ) SemaError!void { | |
| 34442 | const pt = sema.pt; | |
| 34443 | const zcu = pt.zcu; | |
| 34444 | const io = zcu.comp.io; | |
| 34445 | const ip = &zcu.intern_pool; | |
| 34446 | const target = zcu.getTarget(); | |
| 34447 | ||
| 34448 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34449 | ||
| 34450 | assert(!union_type.haveLayout(ip)); | |
| 34451 | ||
| 34452 | const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); | |
| 34453 | ||
| 34454 | // We'll guess "pointer-aligned", if the union has an | |
| 34455 | // underaligned pointer field then some allocations | |
| 34456 | // might require explicit alignment. | |
| 34457 | if (union_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; | |
| 34458 | ||
| 34459 | try sema.resolveUnionFieldTypes(ty, union_type); | |
| 34460 | ||
| 34461 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. | |
| 34462 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. | |
| 34463 | ||
| 34464 | var max_align: Alignment = .@"1"; | |
| 34465 | for (0..union_type.field_types.len) |field_index| { | |
| 34466 | const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 34467 | if (!(try field_ty.hasRuntimeBitsSema(pt))) continue; | |
| 34468 | ||
| 34469 | const explicit_align = union_type.fieldAlign(ip, field_index); | |
| 34470 | const field_align = if (explicit_align != .none) | |
| 34471 | explicit_align | |
| 34472 | else | |
| 34473 | try field_ty.abiAlignmentSema(sema.pt); | |
| 34474 | ||
| 34475 | max_align = max_align.max(field_align); | |
| 34476 | } | |
| 34477 | ||
| 34478 | union_type.setAlignment(ip, io, max_align); | |
| 34479 | } | |
| 34480 | ||
| 34481 | /// This logic must be kept in sync with `Type.getUnionLayout`. | |
| 34482 | pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { | |
| 34483 | const pt = sema.pt; | |
| 34484 | const io = pt.zcu.comp.io; | |
| 34485 | const ip = &pt.zcu.intern_pool; | |
| 34486 | ||
| 34487 | try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index)); | |
| 34488 | ||
| 34489 | // Load again, since the tag type might have changed due to resolution. | |
| 34490 | const union_type = ip.loadUnionType(ty.ip_index); | |
| 34491 | ||
| 34492 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34493 | ||
| 34494 | const old_flags = union_type.flagsUnordered(ip); | |
| 34495 | switch (old_flags.status) { | |
| 34496 | .none, .have_field_types => {}, | |
| 34497 | .field_types_wip, .layout_wip => { | |
| 34498 | const msg = try sema.errMsg( | |
| 34499 | ty.srcLoc(pt.zcu), | |
| 34500 | "union '{f}' depends on itself", | |
| 34501 | .{ty.fmt(pt)}, | |
| 34502 | ); | |
| 34503 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34504 | }, | |
| 34505 | .have_layout, .fully_resolved_wip, .fully_resolved => return, | |
| 34506 | } | |
| 34507 | ||
| 34508 | errdefer union_type.setStatusIfLayoutWip(ip, io, old_flags.status); | |
| 34509 | ||
| 34510 | union_type.setStatus(ip, io, .layout_wip); | |
| 34511 | ||
| 34512 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. | |
| 34513 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. | |
| 34514 | ||
| 34515 | var max_size: u64 = 0; | |
| 34516 | var max_align: Alignment = .@"1"; | |
| 34517 | for (0..union_type.field_types.len) |field_index| { | |
| 34518 | const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 34519 | if (field_ty.isNoReturn(pt.zcu)) continue; | |
| 34520 | ||
| 34521 | // We need to call `hasRuntimeBits` before calling `abiSize` to prevent reachable `unreachable`s, | |
| 34522 | // but `hasRuntimeBits` only resolves field types and so may infinite recurse on a layout wip type, | |
| 34523 | // so we must resolve the layout manually first, instead of waiting for `abiSize` to do it for us. | |
| 34524 | // This is arguably just hacking around bugs in both `abiSize` for not allowing arbitrary types to | |
| 34525 | // be queried, enabling failures to be handled with the emission of a compile error, and also in | |
| 34526 | // `hasRuntimeBits` for ever being able to infinite recurse in the first place. | |
| 34527 | try field_ty.resolveLayout(pt); | |
| 34528 | ||
| 34529 | if (try field_ty.hasRuntimeBitsSema(pt)) { | |
| 34530 | max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) { | |
| 34531 | error.AnalysisFail => { | |
| 34532 | const msg = sema.err orelse return err; | |
| 34533 | try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{}); | |
| 34534 | return err; | |
| 34535 | }, | |
| 34536 | else => return err, | |
| 34537 | }); | |
| 34538 | } | |
| 34539 | ||
| 34540 | const explicit_align = union_type.fieldAlign(ip, field_index); | |
| 34541 | const field_align = if (explicit_align != .none) | |
| 34542 | explicit_align | |
| 34543 | else | |
| 34544 | try field_ty.abiAlignmentSema(pt); | |
| 34545 | max_align = max_align.max(field_align); | |
| 34546 | } | |
| 34547 | ||
| 34548 | const has_runtime_tag = union_type.flagsUnordered(ip).runtime_tag.hasTag() and | |
| 34549 | try Type.fromInterned(union_type.enum_tag_ty).hasRuntimeBitsSema(pt); | |
| 34550 | const size, const alignment, const padding = if (has_runtime_tag) layout: { | |
| 34551 | const enum_tag_type: Type = .fromInterned(union_type.enum_tag_ty); | |
| 34552 | const tag_align = try enum_tag_type.abiAlignmentSema(pt); | |
| 34553 | const tag_size = try enum_tag_type.abiSizeSema(pt); | |
| 34554 | ||
| 34555 | // Put the tag before or after the payload depending on which one's | |
| 34556 | // alignment is greater. | |
| 34557 | var size: u64 = 0; | |
| 34558 | var padding: u32 = 0; | |
| 34559 | if (tag_align.order(max_align).compare(.gte)) { | |
| 34560 | // {Tag, Payload} | |
| 34561 | size += tag_size; | |
| 34562 | size = max_align.forward(size); | |
| 34563 | size += max_size; | |
| 34564 | const prev_size = size; | |
| 34565 | size = tag_align.forward(size); | |
| 34566 | padding = @intCast(size - prev_size); | |
| 34567 | } else { | |
| 34568 | // {Payload, Tag} | |
| 34569 | size += max_size; | |
| 34570 | size = switch (pt.zcu.getTarget().ofmt) { | |
| 34571 | .c => max_align, | |
| 34572 | else => tag_align, | |
| 34573 | }.forward(size); | |
| 34574 | size += tag_size; | |
| 34575 | const prev_size = size; | |
| 34576 | size = max_align.forward(size); | |
| 34577 | padding = @intCast(size - prev_size); | |
| 34578 | } | |
| 34579 | ||
| 34580 | break :layout .{ size, max_align.max(tag_align), padding }; | |
| 34581 | } else .{ max_align.forward(max_size), max_align, 0 }; | |
| 34582 | ||
| 34583 | const casted_size = std.math.cast(u32, size) orelse { | |
| 34584 | const msg = try sema.errMsg( | |
| 34585 | ty.srcLoc(pt.zcu), | |
| 34586 | "union layout requires size {d}, this compiler implementation supports up to {d}", | |
| 34587 | .{ size, std.math.maxInt(u32) }, | |
| 34588 | ); | |
| 34589 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34590 | }; | |
| 34591 | union_type.setHaveLayout(ip, io, casted_size, padding, alignment); | |
| 34592 | ||
| 34593 | if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) { | |
| 34594 | const msg = try sema.errMsg( | |
| 34595 | ty.srcLoc(pt.zcu), | |
| 34596 | "union layout depends on it having runtime bits", | |
| 34597 | .{}, | |
| 34598 | ); | |
| 34599 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34600 | } | |
| 34601 | ||
| 34602 | if (union_type.flagsUnordered(ip).assumed_pointer_aligned and | |
| 34603 | alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(pt.zcu.getTarget().ptrBitWidth(), 8)))) | |
| 34604 | { | |
| 34605 | const msg = try sema.errMsg( | |
| 34606 | ty.srcLoc(pt.zcu), | |
| 34607 | "union layout depends on being pointer aligned", | |
| 34608 | .{}, | |
| 34609 | ); | |
| 34610 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34611 | } | |
| 34612 | _ = try ty.comptimeOnlySema(pt); | |
| 34613 | } | |
| 34614 | ||
| 34615 | /// Returns `error.AnalysisFail` if any of the types (recursively) failed to | |
| 34616 | /// be resolved. | |
| 34617 | pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void { | |
| 34618 | try sema.resolveStructLayout(ty); | |
| 34619 | try sema.resolveStructFieldInits(ty); | |
| 34620 | ||
| 34621 | const pt = sema.pt; | |
| 34622 | const zcu = pt.zcu; | |
| 34623 | const io = zcu.comp.io; | |
| 34624 | const ip = &zcu.intern_pool; | |
| 34625 | const struct_type = zcu.typeToStruct(ty).?; | |
| 34626 | ||
| 34627 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34628 | ||
| 34629 | if (struct_type.setFullyResolved(ip, io)) return; | |
| 34630 | errdefer struct_type.clearFullyResolved(ip, io); | |
| 34631 | ||
| 34632 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. | |
| 34633 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. | |
| 34634 | ||
| 34635 | // After we have resolve struct layout we have to go over the fields again to | |
| 34636 | // make sure pointer fields get their child types resolved as well. | |
| 34637 | // See also similar code for unions. | |
| 34638 | ||
| 34639 | for (0..struct_type.field_types.len) |i| { | |
| 34640 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34641 | try field_ty.resolveFully(pt); | |
| 34642 | } | |
| 34643 | } | |
| 34644 | ||
| 34645 | pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { | |
| 34646 | try sema.resolveUnionLayout(ty); | |
| 34647 | ||
| 34648 | const pt = sema.pt; | |
| 34649 | const zcu = pt.zcu; | |
| 34650 | const io = zcu.comp.io; | |
| 34651 | const ip = &zcu.intern_pool; | |
| 34652 | const union_obj = zcu.typeToUnion(ty).?; | |
| 34653 | ||
| 34654 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34655 | ||
| 34656 | switch (union_obj.flagsUnordered(ip).status) { | |
| 34657 | .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {}, | |
| 34658 | .fully_resolved_wip, .fully_resolved => return, | |
| 34659 | } | |
| 34660 | ||
| 34661 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. | |
| 34662 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. | |
| 34663 | ||
| 34664 | { | |
| 34665 | // After we have resolve union layout we have to go over the fields again to | |
| 34666 | // make sure pointer fields get their child types resolved as well. | |
| 34667 | // See also similar code for structs. | |
| 34668 | const prev_status = union_obj.flagsUnordered(ip).status; | |
| 34669 | errdefer union_obj.setStatus(ip, io, prev_status); | |
| 34670 | ||
| 34671 | union_obj.setStatus(ip, io, .fully_resolved_wip); | |
| 34672 | for (0..union_obj.field_types.len) |field_index| { | |
| 34673 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 34674 | try field_ty.resolveFully(pt); | |
| 34675 | } | |
| 34676 | union_obj.setStatus(ip, io, .fully_resolved); | |
| 34677 | } | |
| 34678 | ||
| 34679 | // And let's not forget comptime-only status. | |
| 34680 | _ = try ty.comptimeOnlySema(pt); | |
| 34681 | } | |
| 34682 | ||
| 34683 | pub fn resolveStructFieldTypes( | |
| 34684 | sema: *Sema, | |
| 34685 | ty: InternPool.Index, | |
| 34686 | struct_type: InternPool.LoadedStructType, | |
| 34687 | ) SemaError!void { | |
| 34688 | const pt = sema.pt; | |
| 34689 | const zcu = pt.zcu; | |
| 34690 | const io = zcu.comp.io; | |
| 34691 | const ip = &zcu.intern_pool; | |
| 34692 | ||
| 34693 | assert(sema.owner.unwrap().type == ty); | |
| 34694 | ||
| 34695 | if (struct_type.haveFieldTypes(ip)) return; | |
| 34696 | ||
| 34697 | if (struct_type.setFieldTypesWip(ip, io)) { | |
| 34698 | const msg = try sema.errMsg( | |
| 34699 | Type.fromInterned(ty).srcLoc(zcu), | |
| 34700 | "struct '{f}' depends on itself", | |
| 34701 | .{Type.fromInterned(ty).fmt(pt)}, | |
| 34702 | ); | |
| 34703 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34704 | } | |
| 34705 | defer struct_type.clearFieldTypesWip(ip, io); | |
| 34706 | ||
| 34707 | // can't happen earlier than this because we only want the progress node if not already resolved | |
| 34708 | const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); | |
| 34709 | defer tracked_unit.end(zcu); | |
| 34710 | ||
| 34711 | sema.structFields(struct_type) catch |err| switch (err) { | |
| 34712 | error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, | |
| 34713 | error.ComptimeBreak, error.ComptimeReturn => unreachable, | |
| 34714 | }; | |
| 34715 | } | |
| 34716 | ||
| 34717 | pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { | |
| 34718 | const pt = sema.pt; | |
| 34719 | const zcu = pt.zcu; | |
| 34720 | const io = zcu.comp.io; | |
| 34721 | const ip = &zcu.intern_pool; | |
| 34722 | const struct_type = zcu.typeToStruct(ty) orelse return; | |
| 34723 | ||
| 34724 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34725 | ||
| 34726 | // Inits can start as resolved | |
| 34727 | if (struct_type.haveFieldInits(ip)) return; | |
| 34728 | ||
| 34729 | try sema.resolveStructLayout(ty); | |
| 34730 | ||
| 34731 | if (struct_type.setInitsWip(ip, io)) { | |
| 34732 | const msg = try sema.errMsg( | |
| 34733 | ty.srcLoc(zcu), | |
| 34734 | "struct '{f}' depends on itself", | |
| 34735 | .{ty.fmt(pt)}, | |
| 34736 | ); | |
| 34737 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34738 | } | |
| 34739 | defer struct_type.clearInitsWip(ip, io); | |
| 34740 | ||
| 34741 | // can't happen earlier than this because we only want the progress node if not already resolved | |
| 34742 | const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); | |
| 34743 | defer tracked_unit.end(zcu); | |
| 34744 | ||
| 34745 | sema.structFieldInits(struct_type) catch |err| switch (err) { | |
| 34746 | error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, | |
| 34747 | error.ComptimeBreak, error.ComptimeReturn => unreachable, | |
| 34748 | }; | |
| 34749 | struct_type.setHaveFieldInits(ip, io); | |
| 34750 | } | |
| 34751 | ||
| 34752 | pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void { | |
| 34753 | const pt = sema.pt; | |
| 34754 | const zcu = pt.zcu; | |
| 34755 | const io = zcu.comp.io; | |
| 34756 | const ip = &zcu.intern_pool; | |
| 34757 | ||
| 34758 | assert(sema.owner.unwrap().type == ty.toIntern()); | |
| 34759 | ||
| 34760 | switch (union_type.flagsUnordered(ip).status) { | |
| 34761 | .none => {}, | |
| 34762 | .field_types_wip => { | |
| 34763 | const msg = try sema.errMsg(ty.srcLoc(zcu), "union '{f}' depends on itself", .{ty.fmt(pt)}); | |
| 34764 | return sema.failWithOwnedErrorMsg(null, msg); | |
| 34765 | }, | |
| 34766 | .have_field_types, | |
| 34767 | .have_layout, | |
| 34768 | .layout_wip, | |
| 34769 | .fully_resolved_wip, | |
| 34770 | .fully_resolved, | |
| 34771 | => return, | |
| 34772 | } | |
| 34773 | ||
| 34774 | // can't happen earlier than this because we only want the progress node if not already resolved | |
| 34775 | const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null); | |
| 34776 | defer tracked_unit.end(zcu); | |
| 34777 | ||
| 34778 | union_type.setStatus(ip, io, .field_types_wip); | |
| 34779 | errdefer union_type.setStatus(ip, io, .none); | |
| 34780 | sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) { | |
| 34781 | error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, | |
| 34782 | error.ComptimeBreak, error.ComptimeReturn => unreachable, | |
| 34783 | }; | |
| 34784 | union_type.setStatus(ip, io, .have_field_types); | |
| 34785 | } | |
| 34786 | ||
| 34787 | /// Returns a normal error set corresponding to the fully populated inferred | |
| 34788 | /// error set. | |
| 34789 | fn resolveInferredErrorSet( | |
| 34790 | sema: *Sema, | |
| 34791 | block: *Block, | |
| 34792 | src: LazySrcLoc, | |
| 34793 | ies_index: InternPool.Index, | |
| 34794 | ) CompileError!InternPool.Index { | |
| 34795 | const pt = sema.pt; | |
| 34796 | const zcu = pt.zcu; | |
| 34797 | const ip = &zcu.intern_pool; | |
| 34798 | const func_index = ip.iesFuncIndex(ies_index); | |
| 34799 | const func = zcu.funcInfo(func_index); | |
| 34800 | ||
| 34801 | try sema.declareDependency(.{ .interned = func_index }); // resolved IES | |
| 34802 | ||
| 34803 | try zcu.maybeUnresolveIes(func_index); | |
| 34804 | const resolved_ty = func.resolvedErrorSetUnordered(ip); | |
| 34805 | if (resolved_ty != .none) return resolved_ty; | |
| 34806 | ||
| 34807 | if (zcu.analysis_in_progress.contains(.wrap(.{ .func = func_index }))) { | |
| 34808 | return sema.fail(block, src, "unable to resolve inferred error set", .{}); | |
| 34809 | } | |
| 34810 | ||
| 34811 | // In order to ensure that all dependencies are properly added to the set, | |
| 34812 | // we need to ensure the function body is analyzed of the inferred error | |
| 34813 | // set. However, in the case of comptime/inline function calls with | |
| 34814 | // inferred error sets, each call gets an adhoc InferredErrorSet object, which | |
| 34815 | // has no corresponding function body. | |
| 34816 | const ies_func_info = zcu.typeToFunc(.fromInterned(func.ty)).?; | |
| 34817 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, | |
| 34818 | // because inline function does not create a new declaration, and the ies has been filled with analyzeCall, | |
| 34819 | // so here we can simply skip this case. | |
| 34820 | if (ies_func_info.return_type == .generic_poison_type) { | |
| 34821 | assert(ies_func_info.cc == .@"inline"); | |
| 34822 | } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { | |
| 34823 | if (ies_func_info.is_generic) { | |
| 34824 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 34825 | const msg = try sema.errMsg(src, "unable to resolve inferred error set of generic function", .{}); | |
| 34826 | errdefer msg.destroy(sema.gpa); | |
| 34827 | try sema.errNote(zcu.navSrcLoc(func.owner_nav), msg, "generic function declared here", .{}); | |
| 34828 | break :msg msg; | |
| 34829 | }); | |
| 34830 | } | |
| 34831 | // In this case we are dealing with the actual InferredErrorSet object that | |
| 34832 | // corresponds to the function, not one created to track an inline/comptime call. | |
| 34833 | const orig_func_index = ip.unwrapCoercedFunc(func_index); | |
| 34834 | try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_func_index })); | |
| 34835 | try pt.ensureFuncBodyUpToDate(orig_func_index); | |
| 34836 | } | |
| 34837 | ||
| 34838 | // This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody` | |
| 34839 | // which calls `resolveInferredErrorSetPtr`. | |
| 34840 | const final_resolved_ty = func.resolvedErrorSetUnordered(ip); | |
| 34841 | assert(final_resolved_ty != .none); | |
| 34842 | return final_resolved_ty; | |
| 34843 | } | |
| 34844 | ||
| 34845 | pub fn resolveInferredErrorSetPtr( | |
| 34846 | sema: *Sema, | |
| 34847 | block: *Block, | |
| 34848 | src: LazySrcLoc, | |
| 34849 | ies: *InferredErrorSet, | |
| 34850 | ) CompileError!void { | |
| 34851 | const pt = sema.pt; | |
| 34852 | const ip = &pt.zcu.intern_pool; | |
| 34853 | ||
| 34854 | if (ies.resolved != .none) return; | |
| 34855 | ||
| 34856 | const ies_index = ip.errorUnionSet(sema.fn_ret_ty.toIntern()); | |
| 34857 | ||
| 34858 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | |
| 34859 | if (ies_index == other_ies_index) continue; | |
| 34860 | switch (try sema.resolveInferredErrorSet(block, src, other_ies_index)) { | |
| 34861 | .anyerror_type => { | |
| 34862 | ies.resolved = .anyerror_type; | |
| 34863 | return; | |
| 34864 | }, | |
| 34865 | else => |error_set_ty_index| { | |
| 34866 | const names = ip.indexToKey(error_set_ty_index).error_set_type.names; | |
| 34867 | for (names.get(ip)) |name| { | |
| 34868 | try ies.errors.put(sema.arena, name, {}); | |
| 34869 | } | |
| 34870 | }, | |
| 34871 | } | |
| 34872 | } | |
| 34873 | ||
| 34874 | const resolved_error_set_ty = try pt.errorSetFromUnsortedNames(ies.errors.keys()); | |
| 34875 | ies.resolved = resolved_error_set_ty.toIntern(); | |
| 34876 | } | |
| 34877 | ||
| 34878 | fn resolveAdHocInferredErrorSet( | |
| 34879 | sema: *Sema, | |
| 34880 | block: *Block, | |
| 34881 | src: LazySrcLoc, | |
| 34882 | value: InternPool.Index, | |
| 34883 | ) CompileError!InternPool.Index { | |
| 34884 | const pt = sema.pt; | |
| 34885 | const zcu = pt.zcu; | |
| 34886 | const comp = zcu.comp; | |
| 34887 | const gpa = comp.gpa; | |
| 34888 | const io = comp.io; | |
| 34889 | const ip = &zcu.intern_pool; | |
| 34890 | ||
| 34891 | const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value)); | |
| 34892 | if (new_ty == .none) return value; | |
| 34893 | return ip.getCoerced(gpa, io, pt.tid, value, new_ty); | |
| 34894 | } | |
| 34895 | ||
| 34896 | fn resolveAdHocInferredErrorSetTy( | |
| 34897 | sema: *Sema, | |
| 34898 | block: *Block, | |
| 34899 | src: LazySrcLoc, | |
| 34900 | ty: InternPool.Index, | |
| 34901 | ) CompileError!InternPool.Index { | |
| 34902 | const ies = sema.fn_ret_ty_ies orelse return .none; | |
| 34903 | const pt = sema.pt; | |
| 34904 | const zcu = pt.zcu; | |
| 34905 | const ip = &zcu.intern_pool; | |
| 34906 | const error_union_info = switch (ip.indexToKey(ty)) { | |
| 34907 | .error_union_type => |x| x, | |
| 34908 | else => return .none, | |
| 34909 | }; | |
| 34910 | if (error_union_info.error_set_type != .adhoc_inferred_error_set_type) | |
| 34911 | return .none; | |
| 34912 | ||
| 34913 | try sema.resolveInferredErrorSetPtr(block, src, ies); | |
| 34914 | const new_ty = try pt.intern(.{ .error_union_type = .{ | |
| 34915 | .error_set_type = ies.resolved, | |
| 34916 | .payload_type = error_union_info.payload_type, | |
| 34917 | } }); | |
| 34918 | return new_ty; | |
| 34919 | } | |
| 34920 | ||
| 34921 | fn resolveInferredErrorSetTy( | |
| 34922 | sema: *Sema, | |
| 34923 | block: *Block, | |
| 34924 | src: LazySrcLoc, | |
| 34925 | ty: InternPool.Index, | |
| 34926 | ) CompileError!InternPool.Index { | |
| 34927 | const pt = sema.pt; | |
| 34928 | const zcu = pt.zcu; | |
| 34929 | const ip = &zcu.intern_pool; | |
| 34930 | if (ty == .anyerror_type) return ty; | |
| 34931 | switch (ip.indexToKey(ty)) { | |
| 34932 | .error_set_type => return ty, | |
| 34933 | .inferred_error_set_type => return sema.resolveInferredErrorSet(block, src, ty), | |
| 34934 | else => unreachable, | |
| 34935 | } | |
| 34936 | } | |
| 34937 | ||
| 34938 | fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | |
| 34939 | /// fields_len | |
| 34940 | usize, | |
| 34941 | Zir.Inst.StructDecl.Small, | |
| 34942 | /// extra_index | |
| 34943 | usize, | |
| 34944 | } { | |
| 34945 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | |
| 34946 | assert(extended.opcode == .struct_decl); | |
| 34947 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 34948 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; | |
| 34949 | ||
| 34950 | const captures_len = if (small.has_captures_len) blk: { | |
| 34951 | const captures_len = zir.extra[extra_index]; | |
| 34952 | extra_index += 1; | |
| 34953 | break :blk captures_len; | |
| 34954 | } else 0; | |
| 34955 | ||
| 34956 | const fields_len = if (small.has_fields_len) blk: { | |
| 34957 | const fields_len = zir.extra[extra_index]; | |
| 34958 | extra_index += 1; | |
| 34959 | break :blk fields_len; | |
| 34960 | } else 0; | |
| 34961 | ||
| 34962 | const decls_len = if (small.has_decls_len) decls_len: { | |
| 34963 | const decls_len = zir.extra[extra_index]; | |
| 34964 | extra_index += 1; | |
| 34965 | break :decls_len decls_len; | |
| 34966 | } else 0; | |
| 34967 | ||
| 34968 | extra_index += captures_len * 2; | |
| 34969 | ||
| 34970 | // The backing integer cannot be handled until `resolveStructLayout()`. | |
| 34971 | if (small.has_backing_int) { | |
| 34972 | const backing_int_body_len = zir.extra[extra_index]; | |
| 34973 | extra_index += 1; // backing_int_body_len | |
| 34974 | if (backing_int_body_len == 0) { | |
| 34975 | extra_index += 1; // backing_int_ref | |
| 34976 | } else { | |
| 34977 | extra_index += backing_int_body_len; // backing_int_body_inst | |
| 34978 | } | |
| 34979 | } | |
| 34980 | ||
| 34981 | // Skip over decls. | |
| 34982 | extra_index += decls_len; | |
| 34983 | ||
| 34984 | return .{ fields_len, small, extra_index }; | |
| 34985 | } | |
| 34986 | ||
| 34987 | fn structFields( | |
| 34988 | sema: *Sema, | |
| 34989 | struct_type: InternPool.LoadedStructType, | |
| 34990 | ) CompileError!void { | |
| 34991 | const pt = sema.pt; | |
| 34992 | const zcu = pt.zcu; | |
| 34993 | const comp = zcu.comp; | |
| 34994 | const gpa = comp.gpa; | |
| 34995 | const io = comp.io; | |
| 34996 | const ip = &zcu.intern_pool; | |
| 34997 | ||
| 34998 | const namespace_index = struct_type.namespace; | |
| 34999 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; | |
| 35000 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 35001 | ||
| 35002 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); | |
| 35003 | ||
| 35004 | if (fields_len == 0) switch (struct_type.layout) { | |
| 35005 | .@"packed" => { | |
| 35006 | try sema.backingIntType(struct_type); | |
| 35007 | return; | |
| 35008 | }, | |
| 35009 | .auto, .@"extern" => { | |
| 35010 | struct_type.setLayoutResolved(ip, io, 0, .none); | |
| 35011 | return; | |
| 35012 | }, | |
| 35013 | }; | |
| 35014 | ||
| 35015 | var block_scope: Block = .{ | |
| 35016 | .parent = null, | |
| 35017 | .sema = sema, | |
| 35018 | .namespace = namespace_index, | |
| 35019 | .instructions = .{}, | |
| 35020 | .inlining = null, | |
| 35021 | .comptime_reason = .{ .reason = .{ | |
| 35022 | .src = .{ | |
| 35023 | .base_node_inst = struct_type.zir_index, | |
| 35024 | .offset = .nodeOffset(.zero), | |
| 35025 | }, | |
| 35026 | .r = .{ .simple = .type }, | |
| 35027 | } }, | |
| 35028 | .src_base_inst = struct_type.zir_index, | |
| 35029 | .type_name_ctx = struct_type.name, | |
| 35030 | }; | |
| 35031 | defer assert(block_scope.instructions.items.len == 0); | |
| 35032 | ||
| 35033 | const Field = struct { | |
| 35034 | type_body_len: u32 = 0, | |
| 35035 | align_body_len: u32 = 0, | |
| 35036 | init_body_len: u32 = 0, | |
| 35037 | type_ref: Zir.Inst.Ref = .none, | |
| 35038 | }; | |
| 35039 | const fields = try sema.arena.alloc(Field, fields_len); | |
| 35040 | ||
| 35041 | var any_inits = false; | |
| 35042 | var any_aligned = false; | |
| 35043 | ||
| 35044 | { | |
| 35045 | const bits_per_field = 4; | |
| 35046 | const fields_per_u32 = 32 / bits_per_field; | |
| 35047 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 35048 | const flags_index = extra_index; | |
| 35049 | var bit_bag_index: usize = flags_index; | |
| 35050 | extra_index += bit_bags_count; | |
| 35051 | var cur_bit_bag: u32 = undefined; | |
| 35052 | var field_i: u32 = 0; | |
| 35053 | while (field_i < fields_len) : (field_i += 1) { | |
| 35054 | if (field_i % fields_per_u32 == 0) { | |
| 35055 | cur_bit_bag = zir.extra[bit_bag_index]; | |
| 35056 | bit_bag_index += 1; | |
| 35057 | } | |
| 35058 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35059 | cur_bit_bag >>= 1; | |
| 35060 | const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35061 | cur_bit_bag >>= 1; | |
| 35062 | const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35063 | cur_bit_bag >>= 1; | |
| 35064 | const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35065 | cur_bit_bag >>= 1; | |
| 35066 | ||
| 35067 | if (is_comptime) struct_type.setFieldComptime(ip, field_i); | |
| 35068 | ||
| 35069 | const field_name_zir: [:0]const u8 = zir.nullTerminatedString(@enumFromInt(zir.extra[extra_index])); | |
| 35070 | extra_index += 1; // field_name | |
| 35071 | ||
| 35072 | fields[field_i] = .{}; | |
| 35073 | ||
| 35074 | if (has_type_body) { | |
| 35075 | fields[field_i].type_body_len = zir.extra[extra_index]; | |
| 35076 | } else { | |
| 35077 | fields[field_i].type_ref = @enumFromInt(zir.extra[extra_index]); | |
| 35078 | } | |
| 35079 | extra_index += 1; | |
| 35080 | ||
| 35081 | // This string needs to outlive the ZIR code. | |
| 35082 | const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); | |
| 35083 | assert(struct_type.addFieldName(ip, field_name) == null); | |
| 35084 | ||
| 35085 | if (has_align) { | |
| 35086 | fields[field_i].align_body_len = zir.extra[extra_index]; | |
| 35087 | extra_index += 1; | |
| 35088 | any_aligned = true; | |
| 35089 | } | |
| 35090 | if (has_init) { | |
| 35091 | fields[field_i].init_body_len = zir.extra[extra_index]; | |
| 35092 | extra_index += 1; | |
| 35093 | any_inits = true; | |
| 35094 | } | |
| 35095 | } | |
| 35096 | } | |
| 35097 | ||
| 35098 | // Next we do only types and alignments, saving the inits for a second pass, | |
| 35099 | // so that init values may depend on type layout. | |
| 35100 | ||
| 35101 | for (fields, 0..) |zir_field, field_i| { | |
| 35102 | const ty_src: LazySrcLoc = .{ | |
| 35103 | .base_node_inst = struct_type.zir_index, | |
| 35104 | .offset = .{ .container_field_type = @intCast(field_i) }, | |
| 35105 | }; | |
| 35106 | const field_ty: Type = ty: { | |
| 35107 | if (zir_field.type_ref != .none) { | |
| 35108 | break :ty try sema.resolveType(&block_scope, ty_src, zir_field.type_ref); | |
| 35109 | } | |
| 35110 | assert(zir_field.type_body_len != 0); | |
| 35111 | const body = zir.bodySlice(extra_index, zir_field.type_body_len); | |
| 35112 | extra_index += body.len; | |
| 35113 | const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index); | |
| 35114 | break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref); | |
| 35115 | }; | |
| 35116 | ||
| 35117 | struct_type.field_types.get(ip)[field_i] = field_ty.toIntern(); | |
| 35118 | ||
| 35119 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 35120 | const msg = msg: { | |
| 35121 | const msg = try sema.errMsg(ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | |
| 35122 | errdefer msg.destroy(sema.gpa); | |
| 35123 | ||
| 35124 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35125 | break :msg msg; | |
| 35126 | }; | |
| 35127 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35128 | } | |
| 35129 | if (field_ty.zigTypeTag(zcu) == .noreturn) { | |
| 35130 | const msg = msg: { | |
| 35131 | const msg = try sema.errMsg(ty_src, "struct fields cannot be 'noreturn'", .{}); | |
| 35132 | errdefer msg.destroy(sema.gpa); | |
| 35133 | ||
| 35134 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35135 | break :msg msg; | |
| 35136 | }; | |
| 35137 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35138 | } | |
| 35139 | switch (struct_type.layout) { | |
| 35140 | .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) { | |
| 35141 | const msg = msg: { | |
| 35142 | const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 35143 | errdefer msg.destroy(sema.gpa); | |
| 35144 | ||
| 35145 | try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field); | |
| 35146 | ||
| 35147 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35148 | break :msg msg; | |
| 35149 | }; | |
| 35150 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35151 | }, | |
| 35152 | .@"packed" => if (!try sema.validatePackedType(field_ty)) { | |
| 35153 | const msg = msg: { | |
| 35154 | const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 35155 | errdefer msg.destroy(sema.gpa); | |
| 35156 | ||
| 35157 | try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty); | |
| 35158 | ||
| 35159 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35160 | break :msg msg; | |
| 35161 | }; | |
| 35162 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35163 | }, | |
| 35164 | else => {}, | |
| 35165 | } | |
| 35166 | ||
| 35167 | if (zir_field.align_body_len > 0) { | |
| 35168 | const body = zir.bodySlice(extra_index, zir_field.align_body_len); | |
| 35169 | extra_index += body.len; | |
| 35170 | const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index); | |
| 35171 | const align_src: LazySrcLoc = .{ | |
| 35172 | .base_node_inst = struct_type.zir_index, | |
| 35173 | .offset = .{ .container_field_align = @intCast(field_i) }, | |
| 35174 | }; | |
| 35175 | const field_align = try sema.analyzeAsAlign(&block_scope, align_src, align_ref); | |
| 35176 | struct_type.field_aligns.get(ip)[field_i] = field_align; | |
| 35177 | } | |
| 35178 | ||
| 35179 | extra_index += zir_field.init_body_len; | |
| 35180 | } | |
| 35181 | ||
| 35182 | struct_type.clearFieldTypesWip(ip, io); | |
| 35183 | if (!any_inits) struct_type.setHaveFieldInits(ip, io); | |
| 35184 | ||
| 35185 | try sema.flushExports(); | |
| 35186 | } | |
| 35187 | ||
| 35188 | // This logic must be kept in sync with `structFields` | |
| 35189 | fn structFieldInits( | |
| 35190 | sema: *Sema, | |
| 35191 | struct_type: InternPool.LoadedStructType, | |
| 35192 | ) CompileError!void { | |
| 35193 | const pt = sema.pt; | |
| 35194 | const zcu = pt.zcu; | |
| 35195 | const ip = &zcu.intern_pool; | |
| 35196 | ||
| 35197 | assert(!struct_type.haveFieldInits(ip)); | |
| 35198 | ||
| 35199 | const namespace_index = struct_type.namespace; | |
| 35200 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; | |
| 35201 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 35202 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); | |
| 35203 | ||
| 35204 | var block_scope: Block = .{ | |
| 35205 | .parent = null, | |
| 35206 | .sema = sema, | |
| 35207 | .namespace = namespace_index, | |
| 35208 | .instructions = .{}, | |
| 35209 | .inlining = null, | |
| 35210 | .comptime_reason = undefined, // set when `block_scope` is used | |
| 35211 | .src_base_inst = struct_type.zir_index, | |
| 35212 | .type_name_ctx = struct_type.name, | |
| 35213 | }; | |
| 35214 | defer assert(block_scope.instructions.items.len == 0); | |
| 35215 | ||
| 35216 | const Field = struct { | |
| 35217 | type_body_len: u32 = 0, | |
| 35218 | align_body_len: u32 = 0, | |
| 35219 | init_body_len: u32 = 0, | |
| 35220 | }; | |
| 35221 | const fields = try sema.arena.alloc(Field, fields_len); | |
| 35222 | ||
| 35223 | var any_inits = false; | |
| 35224 | ||
| 35225 | { | |
| 35226 | const bits_per_field = 4; | |
| 35227 | const fields_per_u32 = 32 / bits_per_field; | |
| 35228 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 35229 | const flags_index = extra_index; | |
| 35230 | var bit_bag_index: usize = flags_index; | |
| 35231 | extra_index += bit_bags_count; | |
| 35232 | var cur_bit_bag: u32 = undefined; | |
| 35233 | var field_i: u32 = 0; | |
| 35234 | while (field_i < fields_len) : (field_i += 1) { | |
| 35235 | if (field_i % fields_per_u32 == 0) { | |
| 35236 | cur_bit_bag = zir.extra[bit_bag_index]; | |
| 35237 | bit_bag_index += 1; | |
| 35238 | } | |
| 35239 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35240 | cur_bit_bag >>= 1; | |
| 35241 | const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35242 | cur_bit_bag >>= 2; | |
| 35243 | const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35244 | cur_bit_bag >>= 1; | |
| 35245 | ||
| 35246 | extra_index += 1; // field_name | |
| 35247 | ||
| 35248 | fields[field_i] = .{}; | |
| 35249 | ||
| 35250 | if (has_type_body) fields[field_i].type_body_len = zir.extra[extra_index]; | |
| 35251 | extra_index += 1; | |
| 35252 | ||
| 35253 | if (has_align) { | |
| 35254 | fields[field_i].align_body_len = zir.extra[extra_index]; | |
| 35255 | extra_index += 1; | |
| 35256 | } | |
| 35257 | if (has_init) { | |
| 35258 | fields[field_i].init_body_len = zir.extra[extra_index]; | |
| 35259 | extra_index += 1; | |
| 35260 | any_inits = true; | |
| 35261 | } | |
| 35262 | } | |
| 35263 | } | |
| 35264 | ||
| 35265 | if (any_inits) { | |
| 35266 | for (fields, 0..) |zir_field, field_i| { | |
| 35267 | extra_index += zir_field.type_body_len; | |
| 35268 | extra_index += zir_field.align_body_len; | |
| 35269 | const body = zir.bodySlice(extra_index, zir_field.init_body_len); | |
| 35270 | extra_index += zir_field.init_body_len; | |
| 35271 | ||
| 35272 | if (body.len == 0) continue; | |
| 35273 | ||
| 35274 | // Pre-populate the type mapping the body expects to be there. | |
| 35275 | // In init bodies, the zir index of the struct itself is used | |
| 35276 | // to refer to the current field type. | |
| 35277 | ||
| 35278 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_i]); | |
| 35279 | const type_ref = Air.internedToRef(field_ty.toIntern()); | |
| 35280 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index}); | |
| 35281 | sema.inst_map.putAssumeCapacity(zir_index, type_ref); | |
| 35282 | ||
| 35283 | const init_src: LazySrcLoc = .{ | |
| 35284 | .base_node_inst = struct_type.zir_index, | |
| 35285 | .offset = .{ .container_field_value = @intCast(field_i) }, | |
| 35286 | }; | |
| 35287 | ||
| 35288 | block_scope.comptime_reason = .{ .reason = .{ | |
| 35289 | .src = init_src, | |
| 35290 | .r = .{ .simple = .struct_field_default_value }, | |
| 35291 | } }; | |
| 35292 | const init = try sema.resolveInlineBody(&block_scope, body, zir_index); | |
| 35293 | const coerced = try sema.coerce(&block_scope, field_ty, init, init_src); | |
| 35294 | const default_val = try sema.resolveConstValue(&block_scope, init_src, coerced, null); | |
| 35295 | ||
| 35296 | if (default_val.canMutateComptimeVarState(zcu)) { | |
| 35297 | return sema.failWithContainsReferenceToComptimeVar( | |
| 35298 | &block_scope, | |
| 35299 | init_src, | |
| 35300 | struct_type.fieldName(ip, field_i), | |
| 35301 | "field default value", | |
| 35302 | default_val, | |
| 35303 | ); | |
| 35304 | } | |
| 35305 | struct_type.field_inits.get(ip)[field_i] = default_val.toIntern(); | |
| 35306 | } | |
| 35307 | } | |
| 35308 | ||
| 35309 | try sema.flushExports(); | |
| 35310 | } | |
| 35311 | ||
| 35312 | fn unionFields( | |
| 35313 | sema: *Sema, | |
| 35314 | union_ty: InternPool.Index, | |
| 35315 | union_type: InternPool.LoadedUnionType, | |
| 35316 | ) CompileError!void { | |
| 35317 | const tracy = trace(@src()); | |
| 35318 | defer tracy.end(); | |
| 35319 | ||
| 35320 | const pt = sema.pt; | |
| 35321 | const zcu = pt.zcu; | |
| 35322 | const comp = zcu.comp; | |
| 35323 | const gpa = comp.gpa; | |
| 35324 | const io = comp.io; | |
| 35325 | const ip = &zcu.intern_pool; | |
| 35326 | ||
| 35327 | const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?; | |
| 35328 | const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 35329 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | |
| 35330 | assert(extended.opcode == .union_decl); | |
| 35331 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | |
| 35332 | const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); | |
| 35333 | var extra_index: usize = extra.end; | |
| 35334 | ||
| 35335 | const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: { | |
| 35336 | const ty_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 35337 | extra_index += 1; | |
| 35338 | break :blk ty_ref; | |
| 35339 | } else .none; | |
| 35340 | ||
| 35341 | const captures_len = if (small.has_captures_len) blk: { | |
| 35342 | const captures_len = zir.extra[extra_index]; | |
| 35343 | extra_index += 1; | |
| 35344 | break :blk captures_len; | |
| 35345 | } else 0; | |
| 35346 | ||
| 35347 | const body_len = if (small.has_body_len) blk: { | |
| 35348 | const body_len = zir.extra[extra_index]; | |
| 35349 | extra_index += 1; | |
| 35350 | break :blk body_len; | |
| 35351 | } else 0; | |
| 35352 | ||
| 35353 | const fields_len = if (small.has_fields_len) blk: { | |
| 35354 | const fields_len = zir.extra[extra_index]; | |
| 35355 | extra_index += 1; | |
| 35356 | break :blk fields_len; | |
| 35357 | } else 0; | |
| 35358 | ||
| 35359 | const decls_len = if (small.has_decls_len) decls_len: { | |
| 35360 | const decls_len = zir.extra[extra_index]; | |
| 35361 | extra_index += 1; | |
| 35362 | break :decls_len decls_len; | |
| 35363 | } else 0; | |
| 35364 | ||
| 35365 | // Skip over captures and decls. | |
| 35366 | extra_index += captures_len * 2 + decls_len; | |
| 35367 | ||
| 35368 | const body = zir.bodySlice(extra_index, body_len); | |
| 35369 | extra_index += body.len; | |
| 35370 | ||
| 35371 | const src: LazySrcLoc = .{ | |
| 35372 | .base_node_inst = union_type.zir_index, | |
| 35373 | .offset = .nodeOffset(.zero), | |
| 35374 | }; | |
| 35375 | ||
| 35376 | var block_scope: Block = .{ | |
| 35377 | .parent = null, | |
| 35378 | .sema = sema, | |
| 35379 | .namespace = union_type.namespace, | |
| 35380 | .instructions = .{}, | |
| 35381 | .inlining = null, | |
| 35382 | .comptime_reason = .{ .reason = .{ | |
| 35383 | .src = src, | |
| 35384 | .r = .{ .simple = .type }, | |
| 35385 | } }, | |
| 35386 | .src_base_inst = union_type.zir_index, | |
| 35387 | .type_name_ctx = union_type.name, | |
| 35388 | }; | |
| 35389 | defer assert(block_scope.instructions.items.len == 0); | |
| 35390 | ||
| 35391 | if (body.len != 0) { | |
| 35392 | _ = try sema.analyzeInlineBody(&block_scope, body, zir_index); | |
| 35393 | } | |
| 35394 | ||
| 35395 | var int_tag_ty: Type = undefined; | |
| 35396 | var enum_field_names: []InternPool.NullTerminatedString = &.{}; | |
| 35397 | var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty; | |
| 35398 | var explicit_tags_seen: []bool = &.{}; | |
| 35399 | if (tag_type_ref != .none) { | |
| 35400 | const tag_ty_src: LazySrcLoc = .{ | |
| 35401 | .base_node_inst = union_type.zir_index, | |
| 35402 | .offset = .{ .node_offset_container_tag = .zero }, | |
| 35403 | }; | |
| 35404 | const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref); | |
| 35405 | if (small.auto_enum_tag) { | |
| 35406 | // The provided type is an integer type and we must construct the enum tag type here. | |
| 35407 | int_tag_ty = provided_ty; | |
| 35408 | if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) { | |
| 35409 | return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{f}'", .{int_tag_ty.fmt(pt)}); | |
| 35410 | } | |
| 35411 | ||
| 35412 | if (fields_len > 0) { | |
| 35413 | const field_count_val = try pt.intValue(.comptime_int, fields_len - 1); | |
| 35414 | if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { | |
| 35415 | const msg = msg: { | |
| 35416 | const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{}); | |
| 35417 | errdefer msg.destroy(sema.gpa); | |
| 35418 | try sema.errNote(tag_ty_src, msg, "type '{f}' cannot fit values in range 0...{d}", .{ | |
| 35419 | int_tag_ty.fmt(pt), | |
| 35420 | fields_len - 1, | |
| 35421 | }); | |
| 35422 | break :msg msg; | |
| 35423 | }; | |
| 35424 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35425 | } | |
| 35426 | enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len); | |
| 35427 | try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len); | |
| 35428 | } | |
| 35429 | } else { | |
| 35430 | // The provided type is the enum tag type. | |
| 35431 | const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) { | |
| 35432 | .enum_type => ip.loadEnumType(provided_ty.toIntern()), | |
| 35433 | else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}), | |
| 35434 | }; | |
| 35435 | union_type.setTagType(ip, io, provided_ty.toIntern()); | |
| 35436 | // The fields of the union must match the enum exactly. | |
| 35437 | // A flag per field is used to check for missing and extraneous fields. | |
| 35438 | explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len); | |
| 35439 | @memset(explicit_tags_seen, false); | |
| 35440 | } | |
| 35441 | } else { | |
| 35442 | // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis | |
| 35443 | // purposes, we still auto-generate an enum tag type the same way. That the union is | |
| 35444 | // untagged is represented by the Type tag (union vs union_tagged). | |
| 35445 | enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len); | |
| 35446 | } | |
| 35447 | ||
| 35448 | var field_types: std.ArrayList(InternPool.Index) = .empty; | |
| 35449 | var field_aligns: std.ArrayList(InternPool.Alignment) = .empty; | |
| 35450 | ||
| 35451 | try field_types.ensureTotalCapacityPrecise(sema.arena, fields_len); | |
| 35452 | if (small.any_aligned_fields) | |
| 35453 | try field_aligns.ensureTotalCapacityPrecise(sema.arena, fields_len); | |
| 35454 | ||
| 35455 | var max_bits: u64 = 0; | |
| 35456 | var min_bits: u64 = std.math.maxInt(u64); | |
| 35457 | var max_bits_src: LazySrcLoc = undefined; | |
| 35458 | var min_bits_src: LazySrcLoc = undefined; | |
| 35459 | var max_bits_ty: Type = undefined; | |
| 35460 | var min_bits_ty: Type = undefined; | |
| 35461 | const bits_per_field = 4; | |
| 35462 | const fields_per_u32 = 32 / bits_per_field; | |
| 35463 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 35464 | var bit_bag_index: usize = extra_index; | |
| 35465 | extra_index += bit_bags_count; | |
| 35466 | var cur_bit_bag: u32 = undefined; | |
| 35467 | var field_i: u32 = 0; | |
| 35468 | var last_tag_val: ?Value = null; | |
| 35469 | const layout = union_type.flagsUnordered(ip).layout; | |
| 35470 | while (field_i < fields_len) : (field_i += 1) { | |
| 35471 | if (field_i % fields_per_u32 == 0) { | |
| 35472 | cur_bit_bag = zir.extra[bit_bag_index]; | |
| 35473 | bit_bag_index += 1; | |
| 35474 | } | |
| 35475 | const has_type = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35476 | cur_bit_bag >>= 1; | |
| 35477 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35478 | cur_bit_bag >>= 1; | |
| 35479 | const has_tag = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35480 | cur_bit_bag >>= 1; | |
| 35481 | const unused = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 35482 | cur_bit_bag >>= 1; | |
| 35483 | _ = unused; | |
| 35484 | ||
| 35485 | const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]); | |
| 35486 | const field_name_zir = zir.nullTerminatedString(field_name_index); | |
| 35487 | extra_index += 1; | |
| 35488 | ||
| 35489 | const field_type_ref: Zir.Inst.Ref = if (has_type) blk: { | |
| 35490 | const field_type_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 35491 | extra_index += 1; | |
| 35492 | break :blk field_type_ref; | |
| 35493 | } else .none; | |
| 32881 | continue; | |
| 32882 | }; | |
| 32883 | if (!coerced_val.eql(existing, .fromInterned(field_ty.*), zcu)) { | |
| 32884 | comptime_val = null; | |
| 32885 | break; | |
| 32886 | } | |
| 32887 | } | |
| 35494 | 32888 | |
| 35495 | const align_ref: Zir.Inst.Ref = if (has_align) blk: { | |
| 35496 | const align_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 35497 | extra_index += 1; | |
| 35498 | break :blk align_ref; | |
| 35499 | } else .none; | |
| 32889 | field_val.* = if (comptime_val) |v| v.toIntern() else .none; | |
| 32890 | } | |
| 35500 | 32891 | |
| 35501 | const tag_ref: Air.Inst.Ref = if (has_tag) blk: { | |
| 35502 | const tag_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 35503 | extra_index += 1; | |
| 35504 | break :blk try sema.resolveInst(tag_ref); | |
| 35505 | } else .none; | |
| 32892 | const final_ty = try ip.getTupleType(gpa, io, pt.tid, .{ | |
| 32893 | .types = field_types, | |
| 32894 | .values = field_vals, | |
| 32895 | }); | |
| 35506 | 32896 | |
| 35507 | const name_src: LazySrcLoc = .{ | |
| 35508 | .base_node_inst = union_type.zir_index, | |
| 35509 | .offset = .{ .container_field_name = field_i }, | |
| 35510 | }; | |
| 35511 | const value_src: LazySrcLoc = .{ | |
| 35512 | .base_node_inst = union_type.zir_index, | |
| 35513 | .offset = .{ .container_field_value = field_i }, | |
| 35514 | }; | |
| 35515 | const align_src: LazySrcLoc = .{ | |
| 35516 | .base_node_inst = union_type.zir_index, | |
| 35517 | .offset = .{ .container_field_align = field_i }, | |
| 35518 | }; | |
| 35519 | const type_src: LazySrcLoc = .{ | |
| 35520 | .base_node_inst = union_type.zir_index, | |
| 35521 | .offset = .{ .container_field_type = field_i }, | |
| 35522 | }; | |
| 32897 | return .{ .success = .fromInterned(final_ty) }; | |
| 32898 | }, | |
| 35523 | 32899 | |
| 35524 | if (enum_field_vals.capacity() > 0) { | |
| 35525 | const enum_tag_val = if (tag_ref != .none) blk: { | |
| 35526 | const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, value_src); | |
| 35527 | const val = try sema.resolveConstDefinedValue(&block_scope, value_src, coerced, .{ .simple = .enum_field_tag_value }); | |
| 35528 | last_tag_val = val; | |
| 35529 | ||
| 35530 | break :blk val; | |
| 35531 | } else blk: { | |
| 35532 | if (last_tag_val) |last_tag| { | |
| 35533 | const result = try arith.incrementDefinedInt(sema, int_tag_ty, last_tag); | |
| 35534 | if (result.overflow) return sema.fail( | |
| 35535 | &block_scope, | |
| 35536 | value_src, | |
| 35537 | "enumeration value '{f}' too large for type '{f}'", | |
| 35538 | .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) }, | |
| 35539 | ); | |
| 35540 | last_tag_val = result.val; | |
| 32900 | .exact => { | |
| 32901 | var expect_ty: ?Type = null; | |
| 32902 | var first_idx: usize = undefined; | |
| 32903 | for (peer_tys, 0..) |opt_ty, i| { | |
| 32904 | const ty = opt_ty orelse continue; | |
| 32905 | if (expect_ty) |expect| { | |
| 32906 | if (!ty.eql(expect, zcu)) return .{ .conflict = .{ | |
| 32907 | .peer_idx_a = first_idx, | |
| 32908 | .peer_idx_b = i, | |
| 32909 | } }; | |
| 35541 | 32910 | } else { |
| 35542 | last_tag_val = try pt.intValue(int_tag_ty, 0); | |
| 32911 | expect_ty = ty; | |
| 32912 | first_idx = i; | |
| 35543 | 32913 | } |
| 35544 | break :blk last_tag_val.?; | |
| 35545 | }; | |
| 35546 | const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern()); | |
| 35547 | if (gop.found_existing) { | |
| 35548 | const other_value_src: LazySrcLoc = .{ | |
| 35549 | .base_node_inst = union_type.zir_index, | |
| 35550 | .offset = .{ .container_field_value = @intCast(gop.index) }, | |
| 35551 | }; | |
| 35552 | const msg = msg: { | |
| 35553 | const msg = try sema.errMsg( | |
| 35554 | value_src, | |
| 35555 | "enum tag value {f} already taken", | |
| 35556 | .{enum_tag_val.fmtValueSema(pt, sema)}, | |
| 35557 | ); | |
| 35558 | errdefer msg.destroy(gpa); | |
| 35559 | try sema.errNote(other_value_src, msg, "other occurrence here", .{}); | |
| 35560 | break :msg msg; | |
| 35561 | }; | |
| 35562 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35563 | 32914 | } |
| 35564 | } | |
| 35565 | ||
| 35566 | // This string needs to outlive the ZIR code. | |
| 35567 | const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); | |
| 35568 | if (enum_field_names.len != 0) { | |
| 35569 | enum_field_names[field_i] = field_name; | |
| 35570 | } | |
| 35571 | ||
| 35572 | const field_ty: Type = if (!has_type) | |
| 35573 | .void | |
| 35574 | else if (field_type_ref == .none) | |
| 35575 | .noreturn | |
| 35576 | else | |
| 35577 | try sema.resolveType(&block_scope, type_src, field_type_ref); | |
| 35578 | ||
| 35579 | if (explicit_tags_seen.len > 0) { | |
| 35580 | const tag_ty = union_type.tagTypeUnordered(ip); | |
| 35581 | const tag_info = ip.loadEnumType(tag_ty); | |
| 35582 | const enum_index = tag_info.nameIndex(ip, field_name) orelse { | |
| 35583 | return sema.fail(&block_scope, name_src, "no field named '{f}' in enum '{f}'", .{ | |
| 35584 | field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt), | |
| 35585 | }); | |
| 35586 | }; | |
| 32915 | return .{ .success = expect_ty.? }; | |
| 32916 | }, | |
| 32917 | } | |
| 32918 | } | |
| 35587 | 32919 | |
| 35588 | // No check for duplicate because the check already happened in order | |
| 35589 | // to create the enum type in the first place. | |
| 35590 | assert(!explicit_tags_seen[enum_index]); | |
| 35591 | explicit_tags_seen[enum_index] = true; | |
| 32920 | fn maybeMergeErrorSets(sema: *Sema, block: *Block, src: LazySrcLoc, e0: Type, e1: Type) !Type { | |
| 32921 | // e0 -> e1 | |
| 32922 | if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, e1, e0, src, src)) { | |
| 32923 | return e1; | |
| 32924 | } | |
| 35592 | 32925 | |
| 35593 | // Enforce the enum fields and the union fields being in the same order. | |
| 35594 | if (enum_index != field_i) { | |
| 35595 | const msg = msg: { | |
| 35596 | const enum_field_src: LazySrcLoc = .{ | |
| 35597 | .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?, | |
| 35598 | .offset = .{ .container_field_name = enum_index }, | |
| 35599 | }; | |
| 35600 | const msg = try sema.errMsg(name_src, "union field '{f}' ordered differently than corresponding enum field", .{ | |
| 35601 | field_name.fmt(ip), | |
| 35602 | }); | |
| 35603 | errdefer msg.destroy(sema.gpa); | |
| 35604 | try sema.errNote(enum_field_src, msg, "enum field here", .{}); | |
| 35605 | break :msg msg; | |
| 35606 | }; | |
| 35607 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35608 | } | |
| 35609 | } | |
| 32926 | // e1 -> e0 | |
| 32927 | if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, e0, e1, src, src)) { | |
| 32928 | return e0; | |
| 32929 | } | |
| 35610 | 32930 | |
| 35611 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 35612 | const msg = msg: { | |
| 35613 | const msg = try sema.errMsg(type_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | |
| 35614 | errdefer msg.destroy(sema.gpa); | |
| 32931 | return sema.errorSetMerge(e0, e1); | |
| 32932 | } | |
| 35615 | 32933 | |
| 35616 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35617 | break :msg msg; | |
| 35618 | }; | |
| 35619 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35620 | } | |
| 35621 | switch (layout) { | |
| 35622 | .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) { | |
| 35623 | const msg = msg: { | |
| 35624 | const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 35625 | errdefer msg.destroy(sema.gpa); | |
| 32934 | fn resolvePairInMemoryCoercible(sema: *Sema, block: *Block, src: LazySrcLoc, ty_a: Type, ty_b: Type) !?Type { | |
| 32935 | const target = sema.pt.zcu.getTarget(); | |
| 35626 | 32936 | |
| 35627 | try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field); | |
| 32937 | // ty_b -> ty_a | |
| 32938 | if (.ok == try sema.coerceInMemoryAllowed(block, ty_a, ty_b, false, target, src, src, null)) { | |
| 32939 | return ty_a; | |
| 32940 | } | |
| 35628 | 32941 | |
| 35629 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35630 | break :msg msg; | |
| 35631 | }; | |
| 35632 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35633 | }, | |
| 35634 | .@"packed" => { | |
| 35635 | if (!try sema.validatePackedType(field_ty)) { | |
| 35636 | const msg = msg: { | |
| 35637 | const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 35638 | errdefer msg.destroy(sema.gpa); | |
| 32942 | // ty_a -> ty_b | |
| 32943 | if (.ok == try sema.coerceInMemoryAllowed(block, ty_b, ty_a, false, target, src, src, null)) { | |
| 32944 | return ty_b; | |
| 32945 | } | |
| 35639 | 32946 | |
| 35640 | try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty); | |
| 32947 | return null; | |
| 32948 | } | |
| 35641 | 32949 | |
| 35642 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 35643 | break :msg msg; | |
| 35644 | }; | |
| 35645 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 35646 | } | |
| 35647 | const field_bits = try field_ty.bitSizeSema(pt); | |
| 35648 | if (field_bits >= max_bits) { | |
| 35649 | max_bits = field_bits; | |
| 35650 | max_bits_src = type_src; | |
| 35651 | max_bits_ty = field_ty; | |
| 35652 | } | |
| 35653 | if (field_bits <= min_bits) { | |
| 35654 | min_bits = field_bits; | |
| 35655 | min_bits_src = type_src; | |
| 35656 | min_bits_ty = field_ty; | |
| 32950 | const ArrayLike = struct { | |
| 32951 | len: u64, | |
| 32952 | /// `noreturn` indicates that this type is `struct{}` so can coerce to anything | |
| 32953 | elem_ty: Type, | |
| 32954 | }; | |
| 32955 | fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { | |
| 32956 | const pt = sema.pt; | |
| 32957 | const zcu = pt.zcu; | |
| 32958 | return switch (ty.zigTypeTag(zcu)) { | |
| 32959 | .array => .{ | |
| 32960 | .len = ty.arrayLen(zcu), | |
| 32961 | .elem_ty = ty.childType(zcu), | |
| 32962 | }, | |
| 32963 | .@"struct" => { | |
| 32964 | if (!ty.isTuple(zcu)) return null; | |
| 32965 | const field_count = ty.structFieldCount(zcu); | |
| 32966 | if (field_count == 0) return .{ | |
| 32967 | .len = 0, | |
| 32968 | .elem_ty = .noreturn, | |
| 32969 | }; | |
| 32970 | const elem_ty = ty.fieldType(0, zcu); | |
| 32971 | for (1..field_count) |i| { | |
| 32972 | if (!ty.fieldType(i, zcu).eql(elem_ty, zcu)) { | |
| 32973 | return null; | |
| 35657 | 32974 | } |
| 35658 | }, | |
| 35659 | .auto => {}, | |
| 35660 | } | |
| 35661 | ||
| 35662 | field_types.appendAssumeCapacity(field_ty.toIntern()); | |
| 35663 | ||
| 35664 | if (small.any_aligned_fields) { | |
| 35665 | field_aligns.appendAssumeCapacity(if (align_ref != .none) | |
| 35666 | try sema.resolveAlign(&block_scope, align_src, align_ref) | |
| 35667 | else | |
| 35668 | .none); | |
| 35669 | } else { | |
| 35670 | assert(align_ref == .none); | |
| 35671 | } | |
| 35672 | } | |
| 35673 | ||
| 35674 | union_type.setFieldTypes(ip, field_types.items); | |
| 35675 | union_type.setFieldAligns(ip, field_aligns.items); | |
| 32975 | } | |
| 32976 | return .{ | |
| 32977 | .len = field_count, | |
| 32978 | .elem_ty = elem_ty, | |
| 32979 | }; | |
| 32980 | }, | |
| 32981 | else => null, | |
| 32982 | }; | |
| 32983 | } | |
| 35676 | 32984 | |
| 35677 | if (layout == .@"packed" and fields_len != 0 and min_bits != max_bits) { | |
| 32985 | fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | |
| 32986 | const pt = sema.pt; | |
| 32987 | if (!ty.isIndexable(pt.zcu)) { | |
| 35678 | 32988 | const msg = msg: { |
| 35679 | const msg = try sema.errMsg(src, "packed union has fields with mismatching bit sizes", .{}); | |
| 32989 | const msg = try sema.errMsg(src, "type '{f}' does not support indexing", .{ty.fmt(pt)}); | |
| 35680 | 32990 | errdefer msg.destroy(sema.gpa); |
| 35681 | try sema.errNote(min_bits_src, msg, "{d} bits here", .{min_bits}); | |
| 35682 | try sema.addDeclaredHereNote(msg, min_bits_ty); | |
| 35683 | try sema.errNote(max_bits_src, msg, "{d} bits here", .{max_bits}); | |
| 35684 | try sema.addDeclaredHereNote(msg, max_bits_ty); | |
| 32991 | try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{}); | |
| 35685 | 32992 | break :msg msg; |
| 35686 | 32993 | }; |
| 35687 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 32994 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 35688 | 32995 | } |
| 32996 | } | |
| 35689 | 32997 | |
| 35690 | if (explicit_tags_seen.len > 0) { | |
| 35691 | const tag_ty = union_type.tagTypeUnordered(ip); | |
| 35692 | const tag_info = ip.loadEnumType(tag_ty); | |
| 35693 | if (tag_info.names.len > fields_len) { | |
| 35694 | const msg = msg: { | |
| 35695 | const msg = try sema.errMsg(src, "enum field(s) missing in union", .{}); | |
| 35696 | errdefer msg.destroy(sema.gpa); | |
| 35697 | ||
| 35698 | for (tag_info.names.get(ip), 0..) |field_name, field_index| { | |
| 35699 | if (explicit_tags_seen[field_index]) continue; | |
| 35700 | try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{f}' missing, declared here", .{ | |
| 35701 | field_name.fmt(ip), | |
| 35702 | }); | |
| 35703 | } | |
| 35704 | try sema.addDeclaredHereNote(msg, .fromInterned(tag_ty)); | |
| 35705 | break :msg msg; | |
| 35706 | }; | |
| 35707 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 32998 | fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | |
| 32999 | const pt = sema.pt; | |
| 33000 | const zcu = pt.zcu; | |
| 33001 | if (ty.zigTypeTag(zcu) == .pointer) { | |
| 33002 | switch (ty.ptrSize(zcu)) { | |
| 33003 | .slice, .many, .c => return, | |
| 33004 | .one => { | |
| 33005 | const elem_ty = ty.childType(zcu); | |
| 33006 | if (elem_ty.zigTypeTag(zcu) == .array) return; | |
| 33007 | // TODO https://github.com/ziglang/zig/issues/15479 | |
| 33008 | // if (elem_ty.isTuple()) return; | |
| 33009 | }, | |
| 35708 | 33010 | } |
| 35709 | } else if (enum_field_vals.count() > 0) { | |
| 35710 | const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name); | |
| 35711 | union_type.setTagType(ip, io, enum_ty); | |
| 35712 | } else { | |
| 35713 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name); | |
| 35714 | union_type.setTagType(ip, io, enum_ty); | |
| 35715 | 33011 | } |
| 35716 | ||
| 35717 | try sema.flushExports(); | |
| 33012 | const msg = msg: { | |
| 33013 | const msg = try sema.errMsg(src, "type '{f}' is not an indexable pointer", .{ty.fmt(pt)}); | |
| 33014 | errdefer msg.destroy(sema.gpa); | |
| 33015 | try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); | |
| 33016 | break :msg msg; | |
| 33017 | }; | |
| 33018 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 35718 | 33019 | } |
| 35719 | 33020 | |
| 35720 | fn generateUnionTagTypeNumbered( | |
| 33021 | /// Resolves the inferred error set of the given function, so that the corresponding concrete error | |
| 33022 | /// set is available by calling `InternPool.funcIesResolvedUnordered` on `func_index`. | |
| 33023 | /// | |
| 33024 | /// Asserts that `func_index` is a function. Also asserts that it is not a coerced function, because | |
| 33025 | /// coerced functions do not own inferred error sets. | |
| 33026 | fn ensureFuncIesResolved( | |
| 35721 | 33027 | sema: *Sema, |
| 35722 | 33028 | block: *Block, |
| 35723 | enum_field_names: []const InternPool.NullTerminatedString, | |
| 35724 | enum_field_vals: []const InternPool.Index, | |
| 35725 | union_type: InternPool.Index, | |
| 35726 | union_name: InternPool.NullTerminatedString, | |
| 35727 | ) !InternPool.Index { | |
| 33029 | src: LazySrcLoc, | |
| 33030 | func_index: InternPool.Index, | |
| 33031 | ) CompileError!void { | |
| 35728 | 33032 | const pt = sema.pt; |
| 35729 | 33033 | const zcu = pt.zcu; |
| 35730 | const comp = zcu.comp; | |
| 35731 | const gpa = comp.gpa; | |
| 35732 | const io = comp.io; | |
| 35733 | 33034 | const ip = &zcu.intern_pool; |
| 35734 | 33035 | |
| 35735 | const name = try ip.getOrPutStringFmt( | |
| 35736 | gpa, | |
| 35737 | io, | |
| 35738 | pt.tid, | |
| 35739 | "@typeInfo({f}).@\"union\".tag_type.?", | |
| 35740 | .{union_name.fmt(ip)}, | |
| 35741 | .no_embedded_nulls, | |
| 35742 | ); | |
| 35743 | ||
| 35744 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ | |
| 35745 | .name = name, | |
| 35746 | .owner_union_ty = union_type, | |
| 35747 | .tag_ty = if (enum_field_vals.len == 0) | |
| 35748 | (try pt.intType(.unsigned, 0)).toIntern() | |
| 35749 | else | |
| 35750 | ip.typeOf(enum_field_vals[0]), | |
| 35751 | .names = enum_field_names, | |
| 35752 | .values = enum_field_vals, | |
| 35753 | .tag_mode = .explicit, | |
| 35754 | .parent_namespace = block.namespace, | |
| 35755 | }); | |
| 35756 | ||
| 35757 | return enum_ty; | |
| 35758 | } | |
| 33036 | assert(ip.unwrapCoercedFunc(func_index) == func_index); | |
| 35759 | 33037 | |
| 35760 | fn generateUnionTagTypeSimple( | |
| 35761 | sema: *Sema, | |
| 35762 | block: *Block, | |
| 35763 | enum_field_names: []const InternPool.NullTerminatedString, | |
| 35764 | union_type: InternPool.Index, | |
| 35765 | union_name: InternPool.NullTerminatedString, | |
| 35766 | ) !InternPool.Index { | |
| 35767 | const pt = sema.pt; | |
| 35768 | const zcu = pt.zcu; | |
| 35769 | const comp = zcu.comp; | |
| 35770 | const gpa = comp.gpa; | |
| 35771 | const io = comp.io; | |
| 35772 | const ip = &zcu.intern_pool; | |
| 33038 | try sema.declareDependency(.{ .func_ies = func_index }); | |
| 33039 | try sema.addReferenceEntry(block, src, .wrap(.{ .func = func_index })); | |
| 35773 | 33040 | |
| 35774 | const name = try ip.getOrPutStringFmt( | |
| 35775 | gpa, | |
| 35776 | io, | |
| 35777 | pt.tid, | |
| 35778 | "@typeInfo({f}).@\"union\".tag_type.?", | |
| 35779 | .{union_name.fmt(ip)}, | |
| 35780 | .no_embedded_nulls, | |
| 35781 | ); | |
| 33041 | const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; | |
| 35782 | 33042 | |
| 35783 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ | |
| 35784 | .name = name, | |
| 35785 | .owner_union_ty = union_type, | |
| 35786 | .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(), | |
| 35787 | .names = enum_field_names, | |
| 35788 | .values = &.{}, | |
| 35789 | .tag_mode = .auto, | |
| 35790 | .parent_namespace = block.namespace, | |
| 35791 | }); | |
| 33043 | if (zcu.analysis_in_progress.contains(.wrap(.{ .func = func_index }))) { | |
| 33044 | return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason); | |
| 33045 | } | |
| 35792 | 33046 | |
| 35793 | return enum_ty; | |
| 33047 | try pt.ensureFuncBodyUpToDate(func_index, &reason); | |
| 35794 | 33048 | } |
| 35795 | 33049 | |
| 35796 | /// There is another implementation of this in `Type.onePossibleValue`. This one | |
| 35797 | /// in `Sema` is for calling during semantic analysis, and performs field resolution | |
| 35798 | /// to get the answer. The one in `Type` is for calling during codegen and asserts | |
| 35799 | /// that the types are already resolved. | |
| 35800 | /// TODO assert the return value matches `ty.onePossibleValue` | |
| 35801 | pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | |
| 33050 | pub fn resolveInferredErrorSetPtr( | |
| 33051 | sema: *Sema, | |
| 33052 | block: *Block, | |
| 33053 | src: LazySrcLoc, | |
| 33054 | ies: *InferredErrorSet, | |
| 33055 | ) CompileError!void { | |
| 35802 | 33056 | const pt = sema.pt; |
| 35803 | const zcu = pt.zcu; | |
| 35804 | const comp = zcu.comp; | |
| 35805 | const gpa = comp.gpa; | |
| 35806 | const io = comp.io; | |
| 35807 | const ip = &zcu.intern_pool; | |
| 35808 | ||
| 35809 | return switch (ty.toIntern()) { | |
| 35810 | .u0_type, | |
| 35811 | .i0_type, | |
| 35812 | => try pt.intValue(ty, 0), | |
| 35813 | .u1_type, | |
| 35814 | .u8_type, | |
| 35815 | .i8_type, | |
| 35816 | .u16_type, | |
| 35817 | .i16_type, | |
| 35818 | .u29_type, | |
| 35819 | .u32_type, | |
| 35820 | .i32_type, | |
| 35821 | .u64_type, | |
| 35822 | .i64_type, | |
| 35823 | .u80_type, | |
| 35824 | .u128_type, | |
| 35825 | .i128_type, | |
| 35826 | .u256_type, | |
| 35827 | .usize_type, | |
| 35828 | .isize_type, | |
| 35829 | .c_char_type, | |
| 35830 | .c_short_type, | |
| 35831 | .c_ushort_type, | |
| 35832 | .c_int_type, | |
| 35833 | .c_uint_type, | |
| 35834 | .c_long_type, | |
| 35835 | .c_ulong_type, | |
| 35836 | .c_longlong_type, | |
| 35837 | .c_ulonglong_type, | |
| 35838 | .c_longdouble_type, | |
| 35839 | .f16_type, | |
| 35840 | .f32_type, | |
| 35841 | .f64_type, | |
| 35842 | .f80_type, | |
| 35843 | .f128_type, | |
| 35844 | .anyopaque_type, | |
| 35845 | .bool_type, | |
| 35846 | .type_type, | |
| 35847 | .anyerror_type, | |
| 35848 | .adhoc_inferred_error_set_type, | |
| 35849 | .comptime_int_type, | |
| 35850 | .comptime_float_type, | |
| 35851 | .enum_literal_type, | |
| 35852 | .ptr_usize_type, | |
| 35853 | .ptr_const_comptime_int_type, | |
| 35854 | .manyptr_u8_type, | |
| 35855 | .manyptr_const_u8_type, | |
| 35856 | .manyptr_const_u8_sentinel_0_type, | |
| 35857 | .manyptr_const_slice_const_u8_type, | |
| 35858 | .slice_const_u8_type, | |
| 35859 | .slice_const_u8_sentinel_0_type, | |
| 35860 | .slice_const_slice_const_u8_type, | |
| 35861 | .optional_type_type, | |
| 35862 | .manyptr_const_type_type, | |
| 35863 | .slice_const_type_type, | |
| 35864 | .vector_8_i8_type, | |
| 35865 | .vector_16_i8_type, | |
| 35866 | .vector_32_i8_type, | |
| 35867 | .vector_64_i8_type, | |
| 35868 | .vector_1_u8_type, | |
| 35869 | .vector_2_u8_type, | |
| 35870 | .vector_4_u8_type, | |
| 35871 | .vector_8_u8_type, | |
| 35872 | .vector_16_u8_type, | |
| 35873 | .vector_32_u8_type, | |
| 35874 | .vector_64_u8_type, | |
| 35875 | .vector_2_i16_type, | |
| 35876 | .vector_4_i16_type, | |
| 35877 | .vector_8_i16_type, | |
| 35878 | .vector_16_i16_type, | |
| 35879 | .vector_32_i16_type, | |
| 35880 | .vector_4_u16_type, | |
| 35881 | .vector_8_u16_type, | |
| 35882 | .vector_16_u16_type, | |
| 35883 | .vector_32_u16_type, | |
| 35884 | .vector_2_i32_type, | |
| 35885 | .vector_4_i32_type, | |
| 35886 | .vector_8_i32_type, | |
| 35887 | .vector_16_i32_type, | |
| 35888 | .vector_4_u32_type, | |
| 35889 | .vector_8_u32_type, | |
| 35890 | .vector_16_u32_type, | |
| 35891 | .vector_2_i64_type, | |
| 35892 | .vector_4_i64_type, | |
| 35893 | .vector_8_i64_type, | |
| 35894 | .vector_2_u64_type, | |
| 35895 | .vector_4_u64_type, | |
| 35896 | .vector_8_u64_type, | |
| 35897 | .vector_1_u128_type, | |
| 35898 | .vector_2_u128_type, | |
| 35899 | .vector_1_u256_type, | |
| 35900 | .vector_4_f16_type, | |
| 35901 | .vector_8_f16_type, | |
| 35902 | .vector_16_f16_type, | |
| 35903 | .vector_32_f16_type, | |
| 35904 | .vector_2_f32_type, | |
| 35905 | .vector_4_f32_type, | |
| 35906 | .vector_8_f32_type, | |
| 35907 | .vector_16_f32_type, | |
| 35908 | .vector_2_f64_type, | |
| 35909 | .vector_4_f64_type, | |
| 35910 | .vector_8_f64_type, | |
| 35911 | .anyerror_void_error_union_type, | |
| 35912 | => null, | |
| 35913 | .void_type => Value.void, | |
| 35914 | .noreturn_type => Value.@"unreachable", | |
| 35915 | .anyframe_type => unreachable, | |
| 35916 | .null_type => Value.null, | |
| 35917 | .undefined_type => Value.undef, | |
| 35918 | .optional_noreturn_type => try pt.nullValue(ty), | |
| 35919 | .generic_poison_type => unreachable, | |
| 35920 | .empty_tuple_type => Value.empty_tuple, | |
| 35921 | // values, not types | |
| 35922 | .undef, | |
| 35923 | .undef_bool, | |
| 35924 | .undef_usize, | |
| 35925 | .undef_u1, | |
| 35926 | .zero, | |
| 35927 | .zero_usize, | |
| 35928 | .zero_u1, | |
| 35929 | .zero_u8, | |
| 35930 | .one, | |
| 35931 | .one_usize, | |
| 35932 | .one_u1, | |
| 35933 | .one_u8, | |
| 35934 | .four_u8, | |
| 35935 | .negative_one, | |
| 35936 | .void_value, | |
| 35937 | .unreachable_value, | |
| 35938 | .null_value, | |
| 35939 | .bool_true, | |
| 35940 | .bool_false, | |
| 35941 | .empty_tuple, | |
| 35942 | // invalid | |
| 35943 | .none, | |
| 35944 | => unreachable, | |
| 35945 | ||
| 35946 | _ => switch (ty.toIntern().unwrap(ip).getTag(ip)) { | |
| 35947 | .removed => unreachable, | |
| 35948 | ||
| 35949 | .type_int_signed, // i0 handled above | |
| 35950 | .type_int_unsigned, // u0 handled above | |
| 35951 | .type_pointer, | |
| 35952 | .type_slice, | |
| 35953 | .type_anyframe, | |
| 35954 | .type_error_union, | |
| 35955 | .type_anyerror_union, | |
| 35956 | .type_error_set, | |
| 35957 | .type_inferred_error_set, | |
| 35958 | .type_opaque, | |
| 35959 | .type_function, | |
| 35960 | => null, | |
| 35961 | ||
| 35962 | .simple_type, // handled above | |
| 35963 | // values, not types | |
| 35964 | .undef, | |
| 35965 | .simple_value, | |
| 35966 | .ptr_nav, | |
| 35967 | .ptr_uav, | |
| 35968 | .ptr_uav_aligned, | |
| 35969 | .ptr_comptime_alloc, | |
| 35970 | .ptr_comptime_field, | |
| 35971 | .ptr_int, | |
| 35972 | .ptr_eu_payload, | |
| 35973 | .ptr_opt_payload, | |
| 35974 | .ptr_elem, | |
| 35975 | .ptr_field, | |
| 35976 | .ptr_slice, | |
| 35977 | .opt_payload, | |
| 35978 | .opt_null, | |
| 35979 | .int_u8, | |
| 35980 | .int_u16, | |
| 35981 | .int_u32, | |
| 35982 | .int_i32, | |
| 35983 | .int_usize, | |
| 35984 | .int_comptime_int_u32, | |
| 35985 | .int_comptime_int_i32, | |
| 35986 | .int_small, | |
| 35987 | .int_positive, | |
| 35988 | .int_negative, | |
| 35989 | .int_lazy_align, | |
| 35990 | .int_lazy_size, | |
| 35991 | .error_set_error, | |
| 35992 | .error_union_error, | |
| 35993 | .error_union_payload, | |
| 35994 | .enum_literal, | |
| 35995 | .enum_tag, | |
| 35996 | .float_f16, | |
| 35997 | .float_f32, | |
| 35998 | .float_f64, | |
| 35999 | .float_f80, | |
| 36000 | .float_f128, | |
| 36001 | .float_c_longdouble_f80, | |
| 36002 | .float_c_longdouble_f128, | |
| 36003 | .float_comptime_float, | |
| 36004 | .variable, | |
| 36005 | .threadlocal_variable, | |
| 36006 | .@"extern", | |
| 36007 | .func_decl, | |
| 36008 | .func_instance, | |
| 36009 | .func_coerced, | |
| 36010 | .only_possible_value, | |
| 36011 | .union_value, | |
| 36012 | .bytes, | |
| 36013 | .aggregate, | |
| 36014 | .repeated, | |
| 36015 | // memoized value, not types | |
| 36016 | .memoized_call, | |
| 36017 | => unreachable, | |
| 36018 | ||
| 36019 | .type_array_big, | |
| 36020 | .type_array_small, | |
| 36021 | .type_vector, | |
| 36022 | .type_enum_auto, | |
| 36023 | .type_enum_explicit, | |
| 36024 | .type_enum_nonexhaustive, | |
| 36025 | .type_struct, | |
| 36026 | .type_struct_packed, | |
| 36027 | .type_struct_packed_inits, | |
| 36028 | .type_tuple, | |
| 36029 | .type_union, | |
| 36030 | => switch (ip.indexToKey(ty.toIntern())) { | |
| 36031 | inline .array_type, .vector_type => |seq_type, seq_tag| { | |
| 36032 | const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; | |
| 36033 | if (seq_type.len + @intFromBool(has_sentinel) == 0) return try pt.aggregateValue(ty, &.{}); | |
| 36034 | if (try sema.typeHasOnePossibleValue(.fromInterned(seq_type.child))) |opv| { | |
| 36035 | return try pt.aggregateSplatValue(ty, opv); | |
| 36036 | } | |
| 36037 | return null; | |
| 36038 | }, | |
| 36039 | ||
| 36040 | .struct_type => { | |
| 36041 | // Resolving the layout first helps to avoid loops. | |
| 36042 | // If the type has a coherent layout, we can recurse through fields safely. | |
| 36043 | try ty.resolveLayout(pt); | |
| 36044 | ||
| 36045 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 36046 | ||
| 36047 | if (struct_type.field_types.len == 0) { | |
| 36048 | // In this case the struct has no fields at all and | |
| 36049 | // therefore has one possible value. | |
| 36050 | return try pt.aggregateValue(ty, &.{}); | |
| 36051 | } | |
| 36052 | ||
| 36053 | const field_vals = try sema.arena.alloc( | |
| 36054 | InternPool.Index, | |
| 36055 | struct_type.field_types.len, | |
| 36056 | ); | |
| 36057 | for (field_vals, 0..) |*field_val, i| { | |
| 36058 | if (struct_type.fieldIsComptime(ip, i)) { | |
| 36059 | try ty.resolveStructFieldInits(pt); | |
| 36060 | field_val.* = struct_type.field_inits.get(ip)[i]; | |
| 36061 | continue; | |
| 36062 | } | |
| 36063 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 36064 | if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| { | |
| 36065 | field_val.* = field_opv.toIntern(); | |
| 36066 | } else return null; | |
| 36067 | } | |
| 36068 | ||
| 36069 | // In this case the struct has no runtime-known fields and | |
| 36070 | // therefore has one possible value. | |
| 36071 | return try pt.aggregateValue(ty, field_vals); | |
| 36072 | }, | |
| 36073 | ||
| 36074 | .tuple_type => |tuple| { | |
| 36075 | try ty.resolveLayout(pt); | |
| 36076 | ||
| 36077 | if (tuple.types.len == 0) { | |
| 36078 | return try pt.aggregateValue(ty, &.{}); | |
| 36079 | } | |
| 33057 | const ip = &pt.zcu.intern_pool; | |
| 36080 | 33058 | |
| 36081 | const field_vals = try sema.arena.alloc( | |
| 36082 | InternPool.Index, | |
| 36083 | tuple.types.len, | |
| 36084 | ); | |
| 36085 | for ( | |
| 36086 | field_vals, | |
| 36087 | tuple.types.get(ip), | |
| 36088 | tuple.values.get(ip), | |
| 36089 | ) |*field_val, field_ty, field_comptime_val| { | |
| 36090 | if (field_comptime_val != .none) { | |
| 36091 | field_val.* = field_comptime_val; | |
| 36092 | continue; | |
| 36093 | } | |
| 36094 | if (try sema.typeHasOnePossibleValue(.fromInterned(field_ty))) |opv| { | |
| 36095 | field_val.* = opv.toIntern(); | |
| 36096 | } else return null; | |
| 36097 | } | |
| 33059 | if (ies.resolved != .none) return; | |
| 36098 | 33060 | |
| 36099 | return try pt.aggregateValue(ty, field_vals); | |
| 36100 | }, | |
| 33061 | const ies_index = ip.errorUnionSet(sema.fn_ret_ty.toIntern()); | |
| 36101 | 33062 | |
| 36102 | .union_type => { | |
| 36103 | // Resolving the layout first helps to avoid loops. | |
| 36104 | // If the type has a coherent layout, we can recurse through fields safely. | |
| 36105 | try ty.resolveLayout(pt); | |
| 36106 | ||
| 36107 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 36108 | const tag_val = (try sema.typeHasOnePossibleValue(.fromInterned(union_obj.tagTypeUnordered(ip)))) orelse | |
| 36109 | return null; | |
| 36110 | if (union_obj.field_types.len == 0) { | |
| 36111 | const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); | |
| 36112 | return Value.fromInterned(only); | |
| 36113 | } | |
| 36114 | const only_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[0]); | |
| 36115 | const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse | |
| 36116 | return null; | |
| 36117 | const only = try pt.internUnion(.{ | |
| 36118 | .ty = ty.toIntern(), | |
| 36119 | .tag = tag_val.toIntern(), | |
| 36120 | .val = val_val.toIntern(), | |
| 36121 | }); | |
| 36122 | return Value.fromInterned(only); | |
| 36123 | }, | |
| 33063 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | |
| 33064 | if (ies_index == other_ies_index) continue; | |
| 33065 | const other_func_index = ip.iesFuncIndex(other_ies_index); | |
| 33066 | try sema.ensureFuncIesResolved(block, src, other_func_index); | |
| 33067 | switch (ip.funcIesResolvedUnordered(other_func_index)) { | |
| 33068 | .anyerror_type => { | |
| 33069 | ies.resolved = .anyerror_type; | |
| 33070 | return; | |
| 33071 | }, | |
| 33072 | else => |error_set_ty_index| { | |
| 33073 | const names = ip.indexToKey(error_set_ty_index).error_set_type.names; | |
| 33074 | for (names.get(ip)) |name| { | |
| 33075 | try ies.errors.put(sema.arena, name, {}); | |
| 33076 | } | |
| 33077 | }, | |
| 33078 | } | |
| 33079 | } | |
| 36124 | 33080 | |
| 36125 | .enum_type => { | |
| 36126 | const enum_type = ip.loadEnumType(ty.toIntern()); | |
| 36127 | switch (enum_type.tag_mode) { | |
| 36128 | .nonexhaustive => { | |
| 36129 | if (enum_type.tag_ty == .comptime_int_type) return null; | |
| 33081 | const resolved_error_set_ty = try pt.errorSetFromUnsortedNames(ies.errors.keys()); | |
| 33082 | ies.resolved = resolved_error_set_ty.toIntern(); | |
| 33083 | } | |
| 36130 | 33084 | |
| 36131 | if (try sema.typeHasOnePossibleValue(.fromInterned(enum_type.tag_ty))) |int_opv| { | |
| 36132 | const only = try pt.intern(.{ .enum_tag = .{ | |
| 36133 | .ty = ty.toIntern(), | |
| 36134 | .int = int_opv.toIntern(), | |
| 36135 | } }); | |
| 36136 | return Value.fromInterned(only); | |
| 36137 | } | |
| 33085 | fn resolveAdHocInferredErrorSet( | |
| 33086 | sema: *Sema, | |
| 33087 | block: *Block, | |
| 33088 | src: LazySrcLoc, | |
| 33089 | value: InternPool.Index, | |
| 33090 | ) CompileError!InternPool.Index { | |
| 33091 | const pt = sema.pt; | |
| 33092 | const zcu = pt.zcu; | |
| 33093 | const comp = zcu.comp; | |
| 33094 | const gpa = comp.gpa; | |
| 33095 | const io = comp.io; | |
| 33096 | const ip = &zcu.intern_pool; | |
| 36138 | 33097 | |
| 36139 | return null; | |
| 36140 | }, | |
| 36141 | .auto, .explicit => { | |
| 36142 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; | |
| 36143 | ||
| 36144 | return Value.fromInterned(switch (enum_type.names.len) { | |
| 36145 | 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }), | |
| 36146 | 1 => try pt.intern(.{ .enum_tag = .{ | |
| 36147 | .ty = ty.toIntern(), | |
| 36148 | .int = if (enum_type.values.len == 0) | |
| 36149 | (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() | |
| 36150 | else | |
| 36151 | try ip.getCoercedInts( | |
| 36152 | gpa, | |
| 36153 | io, | |
| 36154 | pt.tid, | |
| 36155 | ip.indexToKey(enum_type.values.get(ip)[0]).int, | |
| 36156 | enum_type.tag_ty, | |
| 36157 | ), | |
| 36158 | } }), | |
| 36159 | else => return null, | |
| 36160 | }); | |
| 36161 | }, | |
| 36162 | } | |
| 36163 | }, | |
| 33098 | const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value)); | |
| 33099 | if (new_ty == .none) return value; | |
| 33100 | return ip.getCoerced(gpa, io, pt.tid, value, new_ty); | |
| 33101 | } | |
| 36164 | 33102 | |
| 36165 | else => unreachable, | |
| 36166 | }, | |
| 33103 | fn resolveAdHocInferredErrorSetTy( | |
| 33104 | sema: *Sema, | |
| 33105 | block: *Block, | |
| 33106 | src: LazySrcLoc, | |
| 33107 | ty: InternPool.Index, | |
| 33108 | ) CompileError!InternPool.Index { | |
| 33109 | const ies = sema.fn_ret_ty_ies orelse return .none; | |
| 33110 | const pt = sema.pt; | |
| 33111 | const zcu = pt.zcu; | |
| 33112 | const ip = &zcu.intern_pool; | |
| 33113 | const error_union_info = switch (ip.indexToKey(ty)) { | |
| 33114 | .error_union_type => |x| x, | |
| 33115 | else => return .none, | |
| 33116 | }; | |
| 33117 | if (error_union_info.error_set_type != .adhoc_inferred_error_set_type) | |
| 33118 | return .none; | |
| 36167 | 33119 | |
| 36168 | .type_optional => { | |
| 36169 | const payload_ip = ip.indexToKey(ty.toIntern()).opt_type; | |
| 36170 | // Although ?noreturn is handled above, the element type | |
| 36171 | // can be effectively noreturn for example via an empty | |
| 36172 | // enum or error set. | |
| 36173 | if (ip.isNoReturn(payload_ip)) return try pt.nullValue(ty); | |
| 36174 | return null; | |
| 36175 | }, | |
| 33120 | try sema.resolveInferredErrorSetPtr(block, src, ies); | |
| 33121 | const new_ty = try pt.intern(.{ .error_union_type = .{ | |
| 33122 | .error_set_type = ies.resolved, | |
| 33123 | .payload_type = error_union_info.payload_type, | |
| 33124 | } }); | |
| 33125 | return new_ty; | |
| 33126 | } | |
| 33127 | ||
| 33128 | fn resolveInferredErrorSetTy( | |
| 33129 | sema: *Sema, | |
| 33130 | block: *Block, | |
| 33131 | src: LazySrcLoc, | |
| 33132 | ty: InternPool.Index, | |
| 33133 | ) CompileError!InternPool.Index { | |
| 33134 | const pt = sema.pt; | |
| 33135 | const zcu = pt.zcu; | |
| 33136 | const ip = &zcu.intern_pool; | |
| 33137 | if (ty == .anyerror_type) return ty; | |
| 33138 | switch (ip.indexToKey(ty)) { | |
| 33139 | .error_set_type => return ty, | |
| 33140 | .inferred_error_set_type => |func_index| { | |
| 33141 | try sema.ensureFuncIesResolved(block, src, func_index); | |
| 33142 | return ip.funcIesResolvedUnordered(func_index); | |
| 36176 | 33143 | }, |
| 36177 | }; | |
| 33144 | else => unreachable, | |
| 33145 | } | |
| 36178 | 33146 | } |
| 36179 | 33147 | |
| 36180 | 33148 | /// Returns the type of the AIR instruction. |
| ... | ... | @@ -36232,9 +33200,10 @@ fn isComptimeKnown( |
| 36232 | 33200 | sema: *Sema, |
| 36233 | 33201 | inst: Air.Inst.Ref, |
| 36234 | 33202 | ) !bool { |
| 36235 | return (try sema.resolveValue(inst)) != null; | |
| 33203 | return sema.resolveValue(inst) != null; | |
| 36236 | 33204 | } |
| 36237 | 33205 | |
| 33206 | /// Asserts that the layout of `var_type` has already been resolved. | |
| 36238 | 33207 | fn analyzeComptimeAlloc( |
| 36239 | 33208 | sema: *Sema, |
| 36240 | 33209 | block: *Block, |
| ... | ... | @@ -36245,10 +33214,9 @@ fn analyzeComptimeAlloc( |
| 36245 | 33214 | const pt = sema.pt; |
| 36246 | 33215 | const zcu = pt.zcu; |
| 36247 | 33216 | |
| 36248 | // Needed to make an anon decl with type `var_type` (the `finish()` call below). | |
| 36249 | _ = try sema.typeHasOnePossibleValue(var_type); | |
| 33217 | var_type.assertHasLayout(zcu); | |
| 36250 | 33218 | |
| 36251 | const ptr_type = try pt.ptrTypeSema(.{ | |
| 33219 | const ptr_type = try pt.ptrType(.{ | |
| 36252 | 33220 | .child = var_type.toIntern(), |
| 36253 | 33221 | .flags = .{ |
| 36254 | 33222 | .alignment = alignment, |
| ... | ... | @@ -36256,13 +33224,23 @@ fn analyzeComptimeAlloc( |
| 36256 | 33224 | }, |
| 36257 | 33225 | }); |
| 36258 | 33226 | |
| 36259 | const alloc = try sema.newComptimeAlloc(block, src, var_type, alignment); | |
| 36260 | ||
| 36261 | return Air.internedToRef((try pt.intern(.{ .ptr = .{ | |
| 36262 | .ty = ptr_type.toIntern(), | |
| 36263 | .base_addr = .{ .comptime_alloc = alloc }, | |
| 36264 | .byte_offset = 0, | |
| 36265 | } }))); | |
| 33227 | if (try var_type.onePossibleValue(pt)) |opv| { | |
| 33228 | return .fromIntern(try pt.intern(.{ .ptr = .{ | |
| 33229 | .ty = ptr_type.toIntern(), | |
| 33230 | .base_addr = .{ .uav = .{ | |
| 33231 | .val = opv.toIntern(), | |
| 33232 | .orig_ty = ptr_type.toIntern(), | |
| 33233 | } }, | |
| 33234 | .byte_offset = 0, | |
| 33235 | } })); | |
| 33236 | } else { | |
| 33237 | const alloc = try sema.newComptimeAlloc(block, src, var_type, alignment); | |
| 33238 | return .fromIntern(try pt.intern(.{ .ptr = .{ | |
| 33239 | .ty = ptr_type.toIntern(), | |
| 33240 | .base_addr = .{ .comptime_alloc = alloc }, | |
| 33241 | .byte_offset = 0, | |
| 33242 | } })); | |
| 33243 | } | |
| 36266 | 33244 | } |
| 36267 | 33245 | |
| 36268 | 33246 | fn resolveAddressSpace( |
| ... | ... | @@ -36272,7 +33250,7 @@ fn resolveAddressSpace( |
| 36272 | 33250 | zir_ref: Zir.Inst.Ref, |
| 36273 | 33251 | ctx: std.Target.AddressSpaceContext, |
| 36274 | 33252 | ) !std.builtin.AddressSpace { |
| 36275 | const air_ref = try sema.resolveInst(zir_ref); | |
| 33253 | const air_ref = sema.resolveInst(zir_ref); | |
| 36276 | 33254 | return sema.analyzeAsAddressSpace(block, src, air_ref, ctx); |
| 36277 | 33255 | } |
| 36278 | 33256 | |
| ... | ... | @@ -36363,40 +33341,7 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError |
| 36363 | 33341 | return std.math.cast(usize, int) orelse return sema.fail(block, src, "expression produces integer value '{d}' which is too big for this compiler implementation to handle", .{int}); |
| 36364 | 33342 | } |
| 36365 | 33343 | |
| 36366 | /// For pointer-like optionals, it returns the pointer type. For pointers, | |
| 36367 | /// the type is returned unmodified. | |
| 36368 | /// This can return `error.AnalysisFail` because it sometimes requires resolving whether | |
| 36369 | /// a type has zero bits, which can cause a "foo depends on itself" compile error. | |
| 36370 | /// This logic must be kept in sync with `Type.isPtrLikeOptional`. | |
| 36371 | fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type { | |
| 36372 | const pt = sema.pt; | |
| 36373 | const zcu = pt.zcu; | |
| 36374 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 36375 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | |
| 36376 | .one, .many, .c => ty, | |
| 36377 | .slice => null, | |
| 36378 | }, | |
| 36379 | .opt_type => |opt_child| switch (zcu.intern_pool.indexToKey(opt_child)) { | |
| 36380 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | |
| 36381 | .slice, .c => null, | |
| 36382 | .many, .one => { | |
| 36383 | if (ptr_type.flags.is_allowzero) return null; | |
| 36384 | ||
| 36385 | // optionals of zero sized types behave like bools, not pointers | |
| 36386 | const payload_ty: Type = .fromInterned(opt_child); | |
| 36387 | if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) { | |
| 36388 | return null; | |
| 36389 | } | |
| 36390 | ||
| 36391 | return payload_ty; | |
| 36392 | }, | |
| 36393 | }, | |
| 36394 | else => null, | |
| 36395 | }, | |
| 36396 | else => null, | |
| 36397 | }; | |
| 36398 | } | |
| 36399 | ||
| 33344 | /// Asserts that the layout of `union_ty` is already resolved. | |
| 36400 | 33345 | fn unionFieldIndex( |
| 36401 | 33346 | sema: *Sema, |
| 36402 | 33347 | block: *Block, |
| ... | ... | @@ -36407,13 +33352,14 @@ fn unionFieldIndex( |
| 36407 | 33352 | const pt = sema.pt; |
| 36408 | 33353 | const zcu = pt.zcu; |
| 36409 | 33354 | const ip = &zcu.intern_pool; |
| 36410 | try union_ty.resolveFields(pt); | |
| 36411 | 33355 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 36412 | const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse | |
| 33356 | const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); | |
| 33357 | const field_index = enum_obj.nameIndex(ip, field_name) orelse | |
| 36413 | 33358 | return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name); |
| 36414 | 33359 | return @intCast(field_index); |
| 36415 | 33360 | } |
| 36416 | 33361 | |
| 33362 | /// Asserts that the layout of `struct_ty` is already resolved. | |
| 36417 | 33363 | fn structFieldIndex( |
| 36418 | 33364 | sema: *Sema, |
| 36419 | 33365 | block: *Block, |
| ... | ... | @@ -36424,7 +33370,6 @@ fn structFieldIndex( |
| 36424 | 33370 | const pt = sema.pt; |
| 36425 | 33371 | const zcu = pt.zcu; |
| 36426 | 33372 | const ip = &zcu.intern_pool; |
| 36427 | try struct_ty.resolveFields(pt); | |
| 36428 | 33373 | const struct_type = zcu.typeToStruct(struct_ty).?; |
| 36429 | 33374 | return struct_type.nameIndex(ip, field_name) orelse |
| 36430 | 33375 | return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_src, field_name); |
| ... | ... | @@ -36509,102 +33454,25 @@ fn intFromFloatScalar( |
| 36509 | 33454 | return pt.getCoerced(cti_result, int_ty); |
| 36510 | 33455 | } |
| 36511 | 33456 | |
| 36512 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. | |
| 36513 | /// Vectors are also accepted. Vector results are reduced with AND. | |
| 36514 | /// | |
| 36515 | /// If provided, `vector_index` reports the first element that failed the range check. | |
| 36516 | fn intFitsInType( | |
| 36517 | sema: *Sema, | |
| 36518 | val: Value, | |
| 36519 | ty: Type, | |
| 36520 | vector_index: ?*usize, | |
| 36521 | ) CompileError!bool { | |
| 36522 | const pt = sema.pt; | |
| 36523 | const zcu = pt.zcu; | |
| 36524 | if (ty.toIntern() == .comptime_int_type) return true; | |
| 36525 | const info = ty.intInfo(zcu); | |
| 36526 | switch (val.toIntern()) { | |
| 36527 | .zero_usize, .zero_u8 => return true, | |
| 36528 | else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 36529 | .undef => return true, | |
| 36530 | .variable, .@"extern", .func, .ptr => { | |
| 36531 | const target = zcu.getTarget(); | |
| 36532 | const ptr_bits = target.ptrBitWidth(); | |
| 36533 | return switch (info.signedness) { | |
| 36534 | .signed => info.bits > ptr_bits, | |
| 36535 | .unsigned => info.bits >= ptr_bits, | |
| 36536 | }; | |
| 36537 | }, | |
| 36538 | .int => |int| switch (int.storage) { | |
| 36539 | .u64, .i64, .big_int => { | |
| 36540 | var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; | |
| 36541 | const big_int = int.storage.toBigInt(&buffer); | |
| 36542 | return big_int.fitsInTwosComp(info.signedness, info.bits); | |
| 36543 | }, | |
| 36544 | .lazy_align => |lazy_ty| { | |
| 36545 | const max_needed_bits = @as(u16, 16) + @intFromBool(info.signedness == .signed); | |
| 36546 | // If it is u16 or bigger we know the alignment fits without resolving it. | |
| 36547 | if (info.bits >= max_needed_bits) return true; | |
| 36548 | const x = try Type.fromInterned(lazy_ty).abiAlignmentSema(pt); | |
| 36549 | if (x == .none) return true; | |
| 36550 | const actual_needed_bits = @as(usize, x.toLog2Units()) + 1 + @intFromBool(info.signedness == .signed); | |
| 36551 | return info.bits >= actual_needed_bits; | |
| 36552 | }, | |
| 36553 | .lazy_size => |lazy_ty| { | |
| 36554 | const max_needed_bits = @as(u16, 64) + @intFromBool(info.signedness == .signed); | |
| 36555 | // If it is u64 or bigger we know the size fits without resolving it. | |
| 36556 | if (info.bits >= max_needed_bits) return true; | |
| 36557 | const x = try Type.fromInterned(lazy_ty).abiSizeSema(pt); | |
| 36558 | if (x == 0) return true; | |
| 36559 | const actual_needed_bits = std.math.log2(x) + 1 + @intFromBool(info.signedness == .signed); | |
| 36560 | return info.bits >= actual_needed_bits; | |
| 36561 | }, | |
| 36562 | }, | |
| 36563 | .aggregate => |aggregate| { | |
| 36564 | assert(ty.zigTypeTag(zcu) == .vector); | |
| 36565 | return switch (aggregate.storage) { | |
| 36566 | .bytes => |bytes| for (bytes.toSlice(ty.vectorLen(zcu), &zcu.intern_pool), 0..) |byte, i| { | |
| 36567 | if (byte == 0) continue; | |
| 36568 | const actual_needed_bits = std.math.log2(byte) + 1 + @intFromBool(info.signedness == .signed); | |
| 36569 | if (info.bits >= actual_needed_bits) continue; | |
| 36570 | if (vector_index) |vi| vi.* = i; | |
| 36571 | break false; | |
| 36572 | } else true, | |
| 36573 | .elems, .repeated_elem => for (switch (aggregate.storage) { | |
| 36574 | .bytes => unreachable, | |
| 36575 | .elems => |elems| elems, | |
| 36576 | .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem), | |
| 36577 | }, 0..) |elem, i| { | |
| 36578 | if (try sema.intFitsInType(Value.fromInterned(elem), ty.scalarType(zcu), null)) continue; | |
| 36579 | if (vector_index) |vi| vi.* = i; | |
| 36580 | break false; | |
| 36581 | } else true, | |
| 36582 | }; | |
| 36583 | }, | |
| 36584 | else => unreachable, | |
| 36585 | }, | |
| 36586 | } | |
| 36587 | } | |
| 36588 | ||
| 36589 | 33457 | fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool { |
| 36590 | 33458 | const pt = sema.pt; |
| 36591 | if (!(try int_val.compareAllWithZeroSema(.gte, pt))) return false; | |
| 33459 | if (!int_val.compareAllWithZero(.gte, pt.zcu)) return false; | |
| 36592 | 33460 | const end_val = try pt.intValue(tag_ty, end); |
| 36593 | 33461 | if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false; |
| 36594 | 33462 | return true; |
| 36595 | 33463 | } |
| 36596 | 33464 | |
| 36597 | /// Asserts the type is an enum. | |
| 33465 | /// Asserts the type is an exhaustive enum. | |
| 36598 | 33466 | fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { |
| 36599 | 33467 | const pt = sema.pt; |
| 36600 | 33468 | const zcu = pt.zcu; |
| 36601 | 33469 | const enum_type = zcu.intern_pool.loadEnumType(ty.toIntern()); |
| 36602 | assert(enum_type.tag_mode != .nonexhaustive); | |
| 33470 | assert(!enum_type.nonexhaustive); | |
| 36603 | 33471 | // The `tagValueIndex` function call below relies on the type being the integer tag type. |
| 36604 | 33472 | // `getCoerced` assumes the value will fit the new type. |
| 36605 | if (!(try sema.intFitsInType(int, .fromInterned(enum_type.tag_ty), null))) return false; | |
| 36606 | const int_coerced = try pt.getCoerced(int, .fromInterned(enum_type.tag_ty)); | |
| 36607 | ||
| 33473 | const int_tag_ty: Type = .fromInterned(enum_type.int_tag_type); | |
| 33474 | if (!int.intFitsInType(int_tag_ty, null, zcu)) return false; | |
| 33475 | const int_coerced = try pt.getCoerced(int, int_tag_ty); | |
| 36608 | 33476 | return enum_type.tagValueIndex(&zcu.intern_pool, int_coerced.toIntern()) != null; |
| 36609 | 33477 | } |
| 36610 | 33478 | |
| ... | ... | @@ -36644,17 +33512,19 @@ fn compareScalar( |
| 36644 | 33512 | ty: Type, |
| 36645 | 33513 | ) CompileError!bool { |
| 36646 | 33514 | const pt = sema.pt; |
| 33515 | const zcu = pt.zcu; | |
| 33516 | ||
| 36647 | 33517 | const coerced_lhs = try pt.getCoerced(lhs, ty); |
| 36648 | 33518 | const coerced_rhs = try pt.getCoerced(rhs, ty); |
| 36649 | 33519 | |
| 36650 | 33520 | // Equality comparisons of signed zero and NaN need to use floating point semantics |
| 36651 | if (coerced_lhs.isFloat(pt.zcu) or coerced_rhs.isFloat(pt.zcu)) | |
| 36652 | return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt); | |
| 33521 | if (coerced_lhs.isFloat(zcu) or coerced_rhs.isFloat(zcu)) | |
| 33522 | return Value.compareHetero(coerced_lhs, op, coerced_rhs, zcu); | |
| 36653 | 33523 | |
| 36654 | 33524 | switch (op) { |
| 36655 | .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty), | |
| 36656 | .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)), | |
| 36657 | else => return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt), | |
| 33525 | .eq => return Value.eql(coerced_lhs, coerced_rhs, ty, zcu), | |
| 33526 | .neq => return !Value.eql(coerced_lhs, coerced_rhs, ty, zcu), | |
| 33527 | else => return Value.compareHetero(coerced_lhs, op, coerced_rhs, zcu), | |
| 36658 | 33528 | } |
| 36659 | 33529 | } |
| 36660 | 33530 | |
| ... | ... | @@ -36716,25 +33586,6 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { |
| 36716 | 33586 | return pt.errorSetFromUnsortedNames(names.keys()); |
| 36717 | 33587 | } |
| 36718 | 33588 | |
| 36719 | /// Avoids crashing the compiler when asking if inferred allocations are noreturn. | |
| 36720 | fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool { | |
| 36721 | if (ref == .unreachable_value) return true; | |
| 36722 | if (ref.toIndex()) |inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(inst)]) { | |
| 36723 | .inferred_alloc, .inferred_alloc_comptime => return false, | |
| 36724 | else => {}, | |
| 36725 | }; | |
| 36726 | return sema.typeOf(ref).isNoReturn(sema.pt.zcu); | |
| 36727 | } | |
| 36728 | ||
| 36729 | /// Avoids crashing the compiler when asking if inferred allocations are known to be a certain zig type. | |
| 36730 | fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool { | |
| 36731 | if (ref.toIndex()) |inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(inst)]) { | |
| 36732 | .inferred_alloc, .inferred_alloc_comptime => return false, | |
| 36733 | else => {}, | |
| 36734 | }; | |
| 36735 | return sema.typeOf(ref).zigTypeTag(sema.pt.zcu) == tag; | |
| 36736 | } | |
| 36737 | ||
| 36738 | 33589 | pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { |
| 36739 | 33590 | const pt = sema.pt; |
| 36740 | 33591 | if (!pt.zcu.comp.config.incremental) return; |
| ... | ... | @@ -36742,23 +33593,6 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { |
| 36742 | 33593 | const gop = try sema.dependencies.getOrPut(sema.gpa, dependee); |
| 36743 | 33594 | if (gop.found_existing) return; |
| 36744 | 33595 | |
| 36745 | // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields | |
| 36746 | // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would | |
| 36747 | // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve | |
| 36748 | // the loop. | |
| 36749 | // Note that this also disallows a `nav_val` | |
| 36750 | switch (sema.owner.unwrap()) { | |
| 36751 | .nav_val => |this_nav| switch (dependee) { | |
| 36752 | .nav_val => |other_nav| if (this_nav == other_nav) return, | |
| 36753 | else => {}, | |
| 36754 | }, | |
| 36755 | .nav_ty => |this_nav| switch (dependee) { | |
| 36756 | .nav_ty => |other_nav| if (this_nav == other_nav) return, | |
| 36757 | else => {}, | |
| 36758 | }, | |
| 36759 | else => {}, | |
| 36760 | } | |
| 36761 | ||
| 36762 | 33596 | try pt.addDependency(sema.owner, dependee); |
| 36763 | 33597 | } |
| 36764 | 33598 | |
| ... | ... | @@ -36799,7 +33633,7 @@ fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Ai |
| 36799 | 33633 | }); |
| 36800 | 33634 | } |
| 36801 | 33635 | |
| 36802 | fn failWithContainsReferenceToComptimeVar(sema: *Sema, block: *Block, src: LazySrcLoc, value_name: InternPool.NullTerminatedString, kind_of_value: []const u8, val: ?Value) CompileError { | |
| 33636 | pub fn failWithContainsReferenceToComptimeVar(sema: *Sema, block: *Block, src: LazySrcLoc, value_name: InternPool.NullTerminatedString, kind_of_value: []const u8, val: ?Value) CompileError { | |
| 36803 | 33637 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 36804 | 33638 | const msg = try sema.errMsg(src, "{s} contains reference to comptime var", .{kind_of_value}); |
| 36805 | 33639 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -36867,11 +33701,7 @@ fn notePathToComptimeAllocPtr( |
| 36867 | 33701 | else => {}, // there will be another stage |
| 36868 | 33702 | } |
| 36869 | 33703 | |
| 36870 | const derivation = comptime_ptr.pointerDerivationAdvanced(arena, pt, false, sema) catch |err| switch (err) { | |
| 36871 | error.OutOfMemory => |e| return e, | |
| 36872 | error.Canceled => @panic("TODO"), // pls don't be cancelable mlugg | |
| 36873 | error.AnalysisFail => unreachable, | |
| 36874 | }; | |
| 33704 | const derivation = try comptime_ptr.pointerDerivation(arena, pt, sema); | |
| 36875 | 33705 | |
| 36876 | 33706 | var second_path_aw: std.Io.Writer.Allocating = .init(arena); |
| 36877 | 33707 | defer second_path_aw.deinit(); |
| ... | ... | @@ -36983,7 +33813,6 @@ fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool { |
| 36983 | 33813 | const zcu = pt.zcu; |
| 36984 | 33814 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 36985 | 33815 | .undef => true, |
| 36986 | .simple_value => |v| v == .undefined, | |
| 36987 | 33816 | .slice => { |
| 36988 | 33817 | // If the slice contents are runtime-known, reification will fail later on with a |
| 36989 | 33818 | // specific error message. |
| ... | ... | @@ -37058,12 +33887,12 @@ fn maybeDerefSliceAsArray( |
| 37058 | 33887 | else => unreachable, |
| 37059 | 33888 | }; |
| 37060 | 33889 | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); |
| 37061 | const len = try Value.fromInterned(slice.len).toUnsignedIntSema(pt); | |
| 33890 | const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); | |
| 37062 | 33891 | const array_ty = try pt.arrayType(.{ |
| 37063 | 33892 | .child = elem_ty.toIntern(), |
| 37064 | 33893 | .len = len, |
| 37065 | 33894 | }); |
| 37066 | const ptr_ty = try pt.ptrTypeSema(p: { | |
| 33895 | const ptr_ty = try pt.ptrType(p: { | |
| 37067 | 33896 | var p = Type.fromInterned(slice.ty).ptrInfo(zcu); |
| 37068 | 33897 | p.flags.size = .one; |
| 37069 | 33898 | p.child = array_ty.toIntern(); |
| ... | ... | @@ -37097,19 +33926,9 @@ pub fn flushExports(sema: *Sema) !void { |
| 37097 | 33926 | const zcu = sema.pt.zcu; |
| 37098 | 33927 | const gpa = zcu.gpa; |
| 37099 | 33928 | |
| 37100 | // There may be existing exports. For instance, a struct may export | |
| 37101 | // things during both field type resolution and field default resolution. | |
| 37102 | // | |
| 37103 | // So, pick up and delete any existing exports. This strategy performs | |
| 37104 | // redundant work, but that's okay, because this case is exceedingly rare. | |
| 37105 | if (zcu.single_exports.get(sema.owner)) |export_idx| { | |
| 37106 | try sema.exports.append(gpa, export_idx.ptr(zcu).*); | |
| 37107 | } else if (zcu.multi_exports.get(sema.owner)) |info| { | |
| 37108 | try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]); | |
| 37109 | } | |
| 37110 | zcu.deleteUnitExports(sema.owner); | |
| 33929 | assert(!zcu.single_exports.contains(sema.owner)); | |
| 33930 | assert(!zcu.multi_exports.contains(sema.owner)); | |
| 37111 | 33931 | |
| 37112 | // `sema.exports` is completed; store the data into the `Zcu`. | |
| 37113 | 33932 | if (sema.exports.items.len == 1) { |
| 37114 | 33933 | try zcu.single_exports.ensureUnusedCapacity(gpa, 1); |
| 37115 | 33934 | const export_idx: Zcu.Export.Index = zcu.free_exports.pop() orelse idx: { |
| ... | ... | @@ -37129,238 +33948,6 @@ pub fn flushExports(sema: *Sema) !void { |
| 37129 | 33948 | } |
| 37130 | 33949 | } |
| 37131 | 33950 | |
| 37132 | /// Called as soon as a `declared` enum type is created. | |
| 37133 | /// Resolves the tag type and field inits. | |
| 37134 | /// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this. | |
| 37135 | pub fn resolveDeclaredEnum( | |
| 37136 | pt: Zcu.PerThread, | |
| 37137 | wip_ty: InternPool.WipEnumType, | |
| 37138 | inst: Zir.Inst.Index, | |
| 37139 | tracked_inst: InternPool.TrackedInst.Index, | |
| 37140 | namespace: InternPool.NamespaceIndex, | |
| 37141 | type_name: InternPool.NullTerminatedString, | |
| 37142 | small: Zir.Inst.EnumDecl.Small, | |
| 37143 | body: []const Zir.Inst.Index, | |
| 37144 | tag_type_ref: Zir.Inst.Ref, | |
| 37145 | any_values: bool, | |
| 37146 | fields_len: u32, | |
| 37147 | zir: Zir, | |
| 37148 | body_end: usize, | |
| 37149 | ) Zcu.SemaError!void { | |
| 37150 | const zcu = pt.zcu; | |
| 37151 | const gpa = zcu.gpa; | |
| 37152 | ||
| 37153 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; | |
| 37154 | ||
| 37155 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 37156 | defer arena.deinit(); | |
| 37157 | ||
| 37158 | var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); | |
| 37159 | defer comptime_err_ret_trace.deinit(); | |
| 37160 | ||
| 37161 | var sema: Sema = .{ | |
| 37162 | .pt = pt, | |
| 37163 | .gpa = gpa, | |
| 37164 | .arena = arena.allocator(), | |
| 37165 | .code = zir, | |
| 37166 | .owner = .wrap(.{ .type = wip_ty.index }), | |
| 37167 | .func_index = .none, | |
| 37168 | .func_is_naked = false, | |
| 37169 | .fn_ret_ty = .void, | |
| 37170 | .fn_ret_ty_ies = null, | |
| 37171 | .comptime_err_ret_trace = &comptime_err_ret_trace, | |
| 37172 | }; | |
| 37173 | defer sema.deinit(); | |
| 37174 | ||
| 37175 | if (zcu.comp.debugIncremental()) { | |
| 37176 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, sema.owner); | |
| 37177 | info.last_update_gen = zcu.generation; | |
| 37178 | } | |
| 37179 | ||
| 37180 | try sema.declareDependency(.{ .src_hash = tracked_inst }); | |
| 37181 | ||
| 37182 | var block: Block = .{ | |
| 37183 | .parent = null, | |
| 37184 | .sema = &sema, | |
| 37185 | .namespace = namespace, | |
| 37186 | .instructions = .{}, | |
| 37187 | .inlining = null, | |
| 37188 | .comptime_reason = .{ .reason = .{ | |
| 37189 | .src = src, | |
| 37190 | .r = .{ .simple = .enum_field_values }, | |
| 37191 | } }, | |
| 37192 | .src_base_inst = tracked_inst, | |
| 37193 | .type_name_ctx = type_name, | |
| 37194 | }; | |
| 37195 | defer block.instructions.deinit(gpa); | |
| 37196 | ||
| 37197 | sema.resolveDeclaredEnumInner( | |
| 37198 | &block, | |
| 37199 | wip_ty, | |
| 37200 | inst, | |
| 37201 | tracked_inst, | |
| 37202 | src, | |
| 37203 | small, | |
| 37204 | body, | |
| 37205 | tag_type_ref, | |
| 37206 | any_values, | |
| 37207 | fields_len, | |
| 37208 | zir, | |
| 37209 | body_end, | |
| 37210 | ) catch |err| switch (err) { | |
| 37211 | error.ComptimeBreak => unreachable, | |
| 37212 | error.ComptimeReturn => unreachable, | |
| 37213 | error.OutOfMemory, error.Canceled => |e| return e, | |
| 37214 | error.AnalysisFail => { | |
| 37215 | if (!zcu.failed_analysis.contains(sema.owner)) { | |
| 37216 | try zcu.transitive_failed_analysis.put(gpa, sema.owner, {}); | |
| 37217 | } | |
| 37218 | return error.AnalysisFail; | |
| 37219 | }, | |
| 37220 | }; | |
| 37221 | } | |
| 37222 | ||
| 37223 | fn resolveDeclaredEnumInner( | |
| 37224 | sema: *Sema, | |
| 37225 | block: *Block, | |
| 37226 | wip_ty: InternPool.WipEnumType, | |
| 37227 | inst: Zir.Inst.Index, | |
| 37228 | tracked_inst: InternPool.TrackedInst.Index, | |
| 37229 | src: LazySrcLoc, | |
| 37230 | small: Zir.Inst.EnumDecl.Small, | |
| 37231 | body: []const Zir.Inst.Index, | |
| 37232 | tag_type_ref: Zir.Inst.Ref, | |
| 37233 | any_values: bool, | |
| 37234 | fields_len: u32, | |
| 37235 | zir: Zir, | |
| 37236 | body_end: usize, | |
| 37237 | ) Zcu.CompileError!void { | |
| 37238 | const pt = sema.pt; | |
| 37239 | const zcu = pt.zcu; | |
| 37240 | const comp = zcu.comp; | |
| 37241 | const gpa = comp.gpa; | |
| 37242 | const io = comp.io; | |
| 37243 | const ip = &zcu.intern_pool; | |
| 37244 | ||
| 37245 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; | |
| 37246 | ||
| 37247 | const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } }; | |
| 37248 | ||
| 37249 | const int_tag_ty = ty: { | |
| 37250 | if (body.len != 0) { | |
| 37251 | _ = try sema.analyzeInlineBody(block, body, inst); | |
| 37252 | } | |
| 37253 | ||
| 37254 | if (tag_type_ref != .none) { | |
| 37255 | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); | |
| 37256 | if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) { | |
| 37257 | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{f}'", .{ty.fmt(pt)}); | |
| 37258 | } | |
| 37259 | break :ty ty; | |
| 37260 | } else if (fields_len == 0) { | |
| 37261 | break :ty try pt.intType(.unsigned, 0); | |
| 37262 | } else { | |
| 37263 | const bits = std.math.log2_int_ceil(usize, fields_len); | |
| 37264 | break :ty try pt.intType(.unsigned, bits); | |
| 37265 | } | |
| 37266 | }; | |
| 37267 | ||
| 37268 | wip_ty.setTagTy(ip, int_tag_ty.toIntern()); | |
| 37269 | ||
| 37270 | var extra_index = body_end + bit_bags_count; | |
| 37271 | var bit_bag_index: usize = body_end; | |
| 37272 | var cur_bit_bag: u32 = undefined; | |
| 37273 | var last_tag_val: ?Value = null; | |
| 37274 | for (0..fields_len) |field_i_usize| { | |
| 37275 | const field_i: u32 = @intCast(field_i_usize); | |
| 37276 | if (field_i % 32 == 0) { | |
| 37277 | cur_bit_bag = zir.extra[bit_bag_index]; | |
| 37278 | bit_bag_index += 1; | |
| 37279 | } | |
| 37280 | const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 37281 | cur_bit_bag >>= 1; | |
| 37282 | ||
| 37283 | const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]); | |
| 37284 | const field_name_zir = zir.nullTerminatedString(field_name_index); | |
| 37285 | extra_index += 1; // field name | |
| 37286 | ||
| 37287 | const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); | |
| 37288 | ||
| 37289 | const value_src: LazySrcLoc = .{ | |
| 37290 | .base_node_inst = tracked_inst, | |
| 37291 | .offset = .{ .container_field_value = field_i }, | |
| 37292 | }; | |
| 37293 | ||
| 37294 | const tag_overflow = if (has_tag_value) overflow: { | |
| 37295 | const tag_val_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 37296 | extra_index += 1; | |
| 37297 | const tag_inst = try sema.resolveInst(tag_val_ref); | |
| 37298 | last_tag_val = try sema.resolveConstDefinedValue(block, .{ | |
| 37299 | .base_node_inst = tracked_inst, | |
| 37300 | .offset = .{ .container_field_name = field_i }, | |
| 37301 | }, tag_inst, .{ .simple = .enum_field_tag_value }); | |
| 37302 | if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; | |
| 37303 | last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty); | |
| 37304 | if (wip_ty.nextField(ip, field_name, last_tag_val.?.toIntern())) |conflict| { | |
| 37305 | assert(conflict.kind == .value); // AstGen validated names are unique | |
| 37306 | const other_field_src: LazySrcLoc = .{ | |
| 37307 | .base_node_inst = tracked_inst, | |
| 37308 | .offset = .{ .container_field_value = conflict.prev_field_idx }, | |
| 37309 | }; | |
| 37310 | const msg = msg: { | |
| 37311 | const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)}); | |
| 37312 | errdefer msg.destroy(gpa); | |
| 37313 | try sema.errNote(other_field_src, msg, "other occurrence here", .{}); | |
| 37314 | break :msg msg; | |
| 37315 | }; | |
| 37316 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 37317 | } | |
| 37318 | break :overflow false; | |
| 37319 | } else if (any_values) overflow: { | |
| 37320 | if (last_tag_val) |last_tag| { | |
| 37321 | const result = try arith.incrementDefinedInt(sema, int_tag_ty, last_tag); | |
| 37322 | last_tag_val = result.val; | |
| 37323 | if (result.overflow) break :overflow true; | |
| 37324 | } else { | |
| 37325 | last_tag_val = try pt.intValue(int_tag_ty, 0); | |
| 37326 | } | |
| 37327 | if (wip_ty.nextField(ip, field_name, last_tag_val.?.toIntern())) |conflict| { | |
| 37328 | assert(conflict.kind == .value); // AstGen validated names are unique | |
| 37329 | const other_field_src: LazySrcLoc = .{ | |
| 37330 | .base_node_inst = tracked_inst, | |
| 37331 | .offset = .{ .container_field_value = conflict.prev_field_idx }, | |
| 37332 | }; | |
| 37333 | const msg = msg: { | |
| 37334 | const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)}); | |
| 37335 | errdefer msg.destroy(gpa); | |
| 37336 | try sema.errNote(other_field_src, msg, "other occurrence here", .{}); | |
| 37337 | break :msg msg; | |
| 37338 | }; | |
| 37339 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 37340 | } | |
| 37341 | break :overflow false; | |
| 37342 | } else overflow: { | |
| 37343 | assert(wip_ty.nextField(ip, field_name, .none) == null); | |
| 37344 | last_tag_val = try pt.intValue(.comptime_int, field_i); | |
| 37345 | if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true; | |
| 37346 | last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty); | |
| 37347 | break :overflow false; | |
| 37348 | }; | |
| 37349 | ||
| 37350 | if (tag_overflow) { | |
| 37351 | const msg = try sema.errMsg(value_src, "enumeration value '{f}' too large for type '{f}'", .{ | |
| 37352 | last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt), | |
| 37353 | }); | |
| 37354 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 37355 | } | |
| 37356 | } | |
| 37357 | if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { | |
| 37358 | if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) { | |
| 37359 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); | |
| 37360 | } | |
| 37361 | } | |
| 37362 | } | |
| 37363 | ||
| 37364 | 33951 | pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; |
| 37365 | 33952 | pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; |
| 37366 | 33953 | |
| ... | ... | @@ -37369,6 +33956,10 @@ const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadR |
| 37369 | 33956 | const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr; |
| 37370 | 33957 | const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult; |
| 37371 | 33958 | |
| 33959 | pub const type_resolution = @import("Sema/type_resolution.zig"); | |
| 33960 | pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved; | |
| 33961 | pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved; | |
| 33962 | ||
| 37372 | 33963 | pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type { |
| 37373 | 33964 | assert(decl.kind() == .type); |
| 37374 | 33965 | try sema.ensureMemoizedStateResolved(src, decl.stage()); |
| ... | ... | @@ -37448,62 +34039,95 @@ pub fn resolveNavPtrModifiers( |
| 37448 | 34039 | }; |
| 37449 | 34040 | } |
| 37450 | 34041 | |
| 37451 | pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool { | |
| 37452 | const pt = sema.pt; | |
| 37453 | const zcu = pt.zcu; | |
| 37454 | const comp = zcu.comp; | |
| 37455 | const gpa = comp.gpa; | |
| 37456 | const io = comp.io; | |
| 37457 | const ip = &zcu.intern_pool; | |
| 34042 | pub fn analyzeMemoizedState(sema: *Sema, stage: InternPool.MemoizedStateStage) CompileError!bool { | |
| 34043 | const pt = sema.pt; | |
| 34044 | const zcu = pt.zcu; | |
| 34045 | const comp = zcu.comp; | |
| 34046 | const gpa = comp.gpa; | |
| 34047 | const io = comp.io; | |
| 34048 | const ip = &zcu.intern_pool; | |
| 34049 | ||
| 34050 | // This `Block` acts kind of like it's evaluating a `comptime` declaration in the root source | |
| 34051 | // file of the standard library. In particular, its namespace is the root std namespace. | |
| 34052 | var block: Block = block: { | |
| 34053 | // Get the main struct type of the root source file of `std`. No need for a reference entry | |
| 34054 | // because `std` is always an analysis root. | |
| 34055 | const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; | |
| 34056 | try pt.ensureFilePopulated(std_file_index); | |
| 34057 | const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); | |
| 34058 | break :block .{ | |
| 34059 | .parent = null, | |
| 34060 | .sema = sema, | |
| 34061 | .namespace = std_type.getNamespaceIndex(zcu), | |
| 34062 | .instructions = .empty, | |
| 34063 | .inlining = null, | |
| 34064 | .comptime_reason = null, | |
| 34065 | .src_base_inst = std_type.typeDeclInst(zcu).?, | |
| 34066 | .type_name_ctx = .empty, | |
| 34067 | }; | |
| 34068 | }; | |
| 34069 | defer block.instructions.deinit(gpa); | |
| 34070 | ||
| 34071 | const std_builtin_ty: Type = ty: { | |
| 34072 | const std_src = block.nodeOffset(.zero); | |
| 34073 | const decl_name = try ip.getOrPutString(gpa, io, pt.tid, "builtin", .no_embedded_nulls); | |
| 34074 | const nav = try sema.namespaceLookup(&block, std_src, block.namespace, decl_name) orelse { | |
| 34075 | return sema.fail(&block, std_src, "'std' missing 'builtin'", .{}); | |
| 34076 | }; | |
| 34077 | const uncoerced_val = try sema.analyzeNavVal(&block, std_src, nav); | |
| 34078 | const decl_src: LazySrcLoc = .{ | |
| 34079 | .base_node_inst = ip.getNav(nav).srcInst(ip), | |
| 34080 | .offset = .nodeOffset(.zero), | |
| 34081 | }; | |
| 34082 | break :ty try sema.analyzeAsType(&block, decl_src, .std_builtin_decl, uncoerced_val); | |
| 34083 | }; | |
| 37458 | 34084 | |
| 37459 | 34085 | var any_changed = false; |
| 37460 | 34086 | |
| 37461 | 34087 | inline for (comptime std.enums.values(Zcu.BuiltinDecl)) |builtin_decl| { |
| 37462 | 34088 | if (stage == comptime builtin_decl.stage()) { |
| 37463 | const parent_ns: Zcu.Namespace.Index, const parent_name: []const u8, const name: []const u8 = switch (comptime builtin_decl.access()) { | |
| 37464 | .direct => |name| .{ builtin_namespace, "std.builtin", name }, | |
| 34089 | const parent_ns_ty: Type, const parent_name: []const u8, const name: []const u8 = switch (comptime builtin_decl.access()) { | |
| 34090 | .direct => |name| .{ std_builtin_ty, "std.builtin", name }, | |
| 37465 | 34091 | .nested => |nested| access: { |
| 37466 | const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(nested[0])); | |
| 37467 | const parent_ns = parent_ty.getNamespace(zcu).unwrap() orelse { | |
| 37468 | return sema.fail(block, simple_src, "std.builtin.{s} is not a container type", .{@tagName(nested[0])}); | |
| 37469 | }; | |
| 37470 | break :access .{ parent_ns, "std.builtin." ++ @tagName(nested[0]), nested[1] }; | |
| 34092 | const parent_decl, const name = nested; | |
| 34093 | const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(parent_decl)); | |
| 34094 | break :access .{ parent_ty, "std.builtin." ++ @tagName(parent_decl), name }; | |
| 37471 | 34095 | }, |
| 37472 | 34096 | }; |
| 37473 | 34097 | |
| 34098 | const parent_ns = parent_ns_ty.getNamespace(zcu).unwrap() orelse { | |
| 34099 | return sema.fail(&block, block.nodeOffset(.zero), "'{s}' is not a container type", .{parent_name}); | |
| 34100 | }; | |
| 34101 | const parent_ty_src = parent_ns_ty.srcLoc(zcu); | |
| 37474 | 34102 | const name_nts = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); |
| 37475 | const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse | |
| 37476 | return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name }); | |
| 34103 | const nav = try sema.namespaceLookup(&block, parent_ty_src, parent_ns, name_nts) orelse { | |
| 34104 | return sema.fail(&block, parent_ty_src, "'{s}' missing '{s}'", .{ parent_name, name }); | |
| 34105 | }; | |
| 34106 | const uncoerced_val = try sema.analyzeNavVal(&block, parent_ty_src, nav); | |
| 37477 | 34107 | |
| 37478 | const src: LazySrcLoc = .{ | |
| 34108 | const decl_src: LazySrcLoc = .{ | |
| 37479 | 34109 | .base_node_inst = ip.getNav(nav).srcInst(ip), |
| 37480 | 34110 | .offset = .nodeOffset(.zero), |
| 37481 | 34111 | }; |
| 37482 | 34112 | |
| 37483 | const result = try sema.analyzeNavVal(block, src, nav); | |
| 37484 | ||
| 37485 | const uncoerced_val = try sema.resolveConstDefinedValue(block, src, result, null); | |
| 37486 | const maybe_lazy_val: Value = switch (builtin_decl.kind()) { | |
| 37487 | .type => if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .type) { | |
| 37488 | return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); | |
| 37489 | } else val: { | |
| 37490 | try uncoerced_val.toType().resolveFully(pt); | |
| 37491 | break :val uncoerced_val; | |
| 34113 | const val: Value = switch (builtin_decl.kind()) { | |
| 34114 | .type => val: { | |
| 34115 | const ty = try sema.analyzeAsType(&block, decl_src, .std_builtin_decl, uncoerced_val); | |
| 34116 | try sema.ensureLayoutResolved(ty, decl_src, .builtin_type); | |
| 34117 | break :val ty.toValue(); | |
| 37492 | 34118 | }, |
| 37493 | 34119 | .func => val: { |
| 37494 | 34120 | const func_ty = try sema.getExpectedBuiltinFnType(builtin_decl); |
| 37495 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); | |
| 37496 | break :val .fromInterned(coerced.toInterned().?); | |
| 34121 | const coerced = try sema.coerce(&block, func_ty, uncoerced_val, decl_src); | |
| 34122 | break :val try sema.resolveConstDefinedValue(&block, decl_src, coerced, .{ .simple = .std_builtin_decl }); | |
| 37497 | 34123 | }, |
| 37498 | 34124 | .string => val: { |
| 37499 | const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src); | |
| 37500 | break :val .fromInterned(coerced.toInterned().?); | |
| 34125 | const coerced = try sema.coerce(&block, .slice_const_u8, uncoerced_val, decl_src); | |
| 34126 | break :val try sema.resolveConstDefinedValue(&block, decl_src, coerced, .{ .simple = .std_builtin_decl }); | |
| 37501 | 34127 | }, |
| 37502 | 34128 | }; |
| 37503 | const val = try sema.resolveLazyValue(maybe_lazy_val); | |
| 37504 | 34129 | |
| 37505 | const prev = zcu.builtin_decl_values.get(builtin_decl); | |
| 37506 | if (val.toIntern() != prev) { | |
| 34130 | if (zcu.builtin_decl_values.get(builtin_decl) != val.toIntern()) { | |
| 37507 | 34131 | zcu.builtin_decl_values.set(builtin_decl, val.toIntern()); |
| 37508 | 34132 | any_changed = true; |
| 37509 | 34133 | } |
| ... | ... | @@ -37539,7 +34163,6 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ |
| 37539 | 34163 | => try pt.funcType(.{ |
| 37540 | 34164 | .param_types = &.{ .generic_poison_type, .generic_poison_type }, |
| 37541 | 34165 | .return_type = .noreturn_type, |
| 37542 | .is_generic = true, | |
| 37543 | 34166 | }), |
| 37544 | 34167 | |
| 37545 | 34168 | // `fn (anyerror) noreturn` |
| ... | ... | @@ -37590,3 +34213,372 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ |
| 37590 | 34213 | else => unreachable, |
| 37591 | 34214 | }; |
| 37592 | 34215 | } |
| 34216 | ||
| 34217 | pub fn setTypeName( | |
| 34218 | sema: *Sema, | |
| 34219 | block: *Block, | |
| 34220 | wip: *const InternPool.WipContainerType, | |
| 34221 | name_strategy: Zir.Inst.NameStrategy, | |
| 34222 | anon_prefix: []const u8, | |
| 34223 | inst: Zir.Inst.Index, | |
| 34224 | ) CompileError!void { | |
| 34225 | const pt = sema.pt; | |
| 34226 | const zcu = pt.zcu; | |
| 34227 | const comp = zcu.comp; | |
| 34228 | const gpa = comp.gpa; | |
| 34229 | const io = comp.io; | |
| 34230 | const ip = &zcu.intern_pool; | |
| 34231 | ||
| 34232 | strat: switch (name_strategy) { | |
| 34233 | .anon => { | |
| 34234 | // It would be neat to have "struct:line:column" but this name has | |
| 34235 | // to survive incremental updates, where it may have been shifted down | |
| 34236 | // or up to a different line, but unchanged, and thus not unnecessarily | |
| 34237 | // semantically analyzed. | |
| 34238 | // TODO: that would be possible, by detecting line number changes and renaming | |
| 34239 | // types appropriately. However, `@typeName` becomes a problem then. If we remove | |
| 34240 | // that builtin from the language, we can consider this. | |
| 34241 | wip.setName(ip, try ip.getOrPutStringFmt( | |
| 34242 | gpa, | |
| 34243 | io, | |
| 34244 | pt.tid, | |
| 34245 | "{f}__{s}_{d}", | |
| 34246 | .{ block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(wip.index) }, | |
| 34247 | .no_embedded_nulls, | |
| 34248 | ), .none); | |
| 34249 | }, | |
| 34250 | .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()), | |
| 34251 | .func => { | |
| 34252 | const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail); | |
| 34253 | const zir_tags = sema.code.instructions.items(.tag); | |
| 34254 | ||
| 34255 | var aw: std.Io.Writer.Allocating = .init(gpa); | |
| 34256 | defer aw.deinit(); | |
| 34257 | const w = &aw.writer; | |
| 34258 | w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory; | |
| 34259 | ||
| 34260 | var arg_i: usize = 0; | |
| 34261 | for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) { | |
| 34262 | .param, .param_comptime, .param_anytype, .param_anytype_comptime => { | |
| 34263 | const arg = sema.inst_map.get(zir_inst).?; | |
| 34264 | // If this is being called in a generic function then analyzeCall will | |
| 34265 | // have already resolved the args and this will work. | |
| 34266 | // If not then this is a struct type being returned from a non-generic | |
| 34267 | // function and the name doesn't matter since it will later | |
| 34268 | // result in a compile error. | |
| 34269 | const arg_val = sema.resolveValue(arg) orelse { | |
| 34270 | continue :strat .anon; | |
| 34271 | }; | |
| 34272 | ||
| 34273 | if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory; | |
| 34274 | ||
| 34275 | // Limiting the depth here helps avoid type names getting too long, which | |
| 34276 | // in turn helps to avoid unreasonably long symbol names for namespaced | |
| 34277 | // symbols. Such names should ideally be human-readable, and additionally, | |
| 34278 | // some tooling may not support very long symbol names. | |
| 34279 | w.print("{f}", .{Value.fmtValueSemaFull(.{ | |
| 34280 | .val = arg_val, | |
| 34281 | .pt = pt, | |
| 34282 | .opt_sema = sema, | |
| 34283 | .depth = 1, | |
| 34284 | })}) catch return error.OutOfMemory; | |
| 34285 | ||
| 34286 | arg_i += 1; | |
| 34287 | continue; | |
| 34288 | }, | |
| 34289 | else => continue, | |
| 34290 | }; | |
| 34291 | ||
| 34292 | w.writeByte(')') catch return error.OutOfMemory; | |
| 34293 | const name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls); | |
| 34294 | wip.setName(ip, name, .none); | |
| 34295 | }, | |
| 34296 | .dbg_var => { | |
| 34297 | // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. | |
| 34298 | const ref = inst.toRef(); | |
| 34299 | const zir_tags = sema.code.instructions.items(.tag); | |
| 34300 | const zir_data = sema.code.instructions.items(.data); | |
| 34301 | const var_name = for (@intFromEnum(inst)..zir_tags.len) |i| switch (zir_tags[i]) { | |
| 34302 | .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { | |
| 34303 | break zir_data[i].str_op.getStr(sema.code); | |
| 34304 | }, | |
| 34305 | else => {}, | |
| 34306 | } else { | |
| 34307 | continue :strat .anon; | |
| 34308 | }; | |
| 34309 | const name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ | |
| 34310 | block.type_name_ctx.fmt(ip), var_name, | |
| 34311 | }, .no_embedded_nulls); | |
| 34312 | wip.setName(ip, name, .none); | |
| 34313 | }, | |
| 34314 | } | |
| 34315 | } | |
| 34316 | ||
| 34317 | fn zirStructDecl( | |
| 34318 | sema: *Sema, | |
| 34319 | block: *Block, | |
| 34320 | inst: Zir.Inst.Index, | |
| 34321 | ) CompileError!Air.Inst.Ref { | |
| 34322 | const pt = sema.pt; | |
| 34323 | const zcu = pt.zcu; | |
| 34324 | const comp = zcu.comp; | |
| 34325 | const gpa = comp.gpa; | |
| 34326 | const io = comp.io; | |
| 34327 | const ip = &zcu.intern_pool; | |
| 34328 | ||
| 34329 | const tracked_inst = try block.trackZir(inst); | |
| 34330 | ||
| 34331 | const src: LazySrcLoc = .{ | |
| 34332 | .base_node_inst = tracked_inst, | |
| 34333 | .offset = .nodeOffset(.zero), | |
| 34334 | }; | |
| 34335 | ||
| 34336 | const struct_decl = sema.code.getStructDecl(inst); | |
| 34337 | ||
| 34338 | const captures = try sema.getCaptures(block, src, struct_decl.captures, struct_decl.capture_names); | |
| 34339 | ||
| 34340 | const ty: Type = switch (try ip.getDeclaredStructType(gpa, io, pt.tid, .{ | |
| 34341 | .zir_index = tracked_inst, | |
| 34342 | .captures = captures, | |
| 34343 | .fields_len = @intCast(struct_decl.field_names.len), | |
| 34344 | .layout = struct_decl.layout, | |
| 34345 | .any_comptime_fields = struct_decl.field_comptime_bits != null, | |
| 34346 | .any_field_defaults = struct_decl.field_default_body_lens != null, | |
| 34347 | .any_field_aligns = struct_decl.field_align_body_lens != null, | |
| 34348 | .packed_backing_mode = if (struct_decl.backing_int_type_body != null) .explicit else .auto, | |
| 34349 | })) { | |
| 34350 | .existing => |ty| .fromInterned(ty), | |
| 34351 | .wip => |wip| ty: { | |
| 34352 | errdefer wip.cancel(ip, pt.tid); | |
| 34353 | try sema.setTypeName(block, &wip, struct_decl.name_strategy, "struct", inst); | |
| 34354 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 34355 | .parent = block.namespace.toOptional(), | |
| 34356 | .owner_type = wip.index, | |
| 34357 | .file_scope = block.getFileScopeIndex(zcu), | |
| 34358 | .generation = zcu.generation, | |
| 34359 | }); | |
| 34360 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 34361 | try pt.scanNamespace(new_namespace_index, struct_decl.decls); | |
| 34362 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 34363 | break :ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 34364 | }, | |
| 34365 | }; | |
| 34366 | ||
| 34367 | try sema.addTypeReferenceEntry(src, ty); | |
| 34368 | try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); | |
| 34369 | ||
| 34370 | return .fromType(ty); | |
| 34371 | } | |
| 34372 | fn zirUnionDecl( | |
| 34373 | sema: *Sema, | |
| 34374 | block: *Block, | |
| 34375 | inst: Zir.Inst.Index, | |
| 34376 | ) CompileError!Air.Inst.Ref { | |
| 34377 | const pt = sema.pt; | |
| 34378 | const zcu = pt.zcu; | |
| 34379 | const comp = zcu.comp; | |
| 34380 | const gpa = comp.gpa; | |
| 34381 | const io = comp.io; | |
| 34382 | const ip = &zcu.intern_pool; | |
| 34383 | ||
| 34384 | const tracked_inst = try block.trackZir(inst); | |
| 34385 | ||
| 34386 | const src: LazySrcLoc = .{ | |
| 34387 | .base_node_inst = tracked_inst, | |
| 34388 | .offset = .nodeOffset(.zero), | |
| 34389 | }; | |
| 34390 | ||
| 34391 | const union_decl = sema.code.getUnionDecl(inst); | |
| 34392 | ||
| 34393 | const captures = try sema.getCaptures(block, src, union_decl.captures, union_decl.capture_names); | |
| 34394 | ||
| 34395 | const ty: Type = switch (try ip.getDeclaredUnionType(gpa, io, pt.tid, .{ | |
| 34396 | .zir_index = tracked_inst, | |
| 34397 | .captures = captures, | |
| 34398 | .fields_len = @intCast(union_decl.field_names.len), | |
| 34399 | .layout = union_decl.kind.layout(), | |
| 34400 | .any_field_aligns = union_decl.field_align_body_lens != null, | |
| 34401 | .tag_usage = switch (union_decl.kind) { | |
| 34402 | .auto => if (block.wantSafeTypes()) .safety else .none, | |
| 34403 | ||
| 34404 | .tagged_explicit, | |
| 34405 | .tagged_enum, | |
| 34406 | .tagged_enum_explicit, | |
| 34407 | => .tagged, | |
| 34408 | ||
| 34409 | .@"extern", | |
| 34410 | .@"packed", | |
| 34411 | .packed_explicit, | |
| 34412 | => .none, | |
| 34413 | }, | |
| 34414 | .enum_tag_mode = switch (union_decl.kind) { | |
| 34415 | .tagged_explicit => .explicit, | |
| 34416 | else => .auto, | |
| 34417 | }, | |
| 34418 | .packed_backing_mode = switch (union_decl.kind) { | |
| 34419 | .packed_explicit => .explicit, | |
| 34420 | else => .auto, | |
| 34421 | }, | |
| 34422 | })) { | |
| 34423 | .existing => |ty| .fromInterned(ty), | |
| 34424 | .wip => |wip| ty: { | |
| 34425 | errdefer wip.cancel(ip, pt.tid); | |
| 34426 | try sema.setTypeName(block, &wip, union_decl.name_strategy, "union", inst); | |
| 34427 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 34428 | .parent = block.namespace.toOptional(), | |
| 34429 | .owner_type = wip.index, | |
| 34430 | .file_scope = block.getFileScopeIndex(zcu), | |
| 34431 | .generation = zcu.generation, | |
| 34432 | }); | |
| 34433 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 34434 | try pt.scanNamespace(new_namespace_index, union_decl.decls); | |
| 34435 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 34436 | break :ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 34437 | }, | |
| 34438 | }; | |
| 34439 | ||
| 34440 | try sema.addTypeReferenceEntry(src, ty); | |
| 34441 | try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); | |
| 34442 | ||
| 34443 | return .fromType(ty); | |
| 34444 | } | |
| 34445 | fn zirEnumDecl( | |
| 34446 | sema: *Sema, | |
| 34447 | block: *Block, | |
| 34448 | inst: Zir.Inst.Index, | |
| 34449 | ) CompileError!Air.Inst.Ref { | |
| 34450 | const pt = sema.pt; | |
| 34451 | const zcu = pt.zcu; | |
| 34452 | const comp = zcu.comp; | |
| 34453 | const gpa = comp.gpa; | |
| 34454 | const io = comp.io; | |
| 34455 | const ip = &zcu.intern_pool; | |
| 34456 | ||
| 34457 | const tracked_inst = try block.trackZir(inst); | |
| 34458 | ||
| 34459 | const src: LazySrcLoc = .{ | |
| 34460 | .base_node_inst = tracked_inst, | |
| 34461 | .offset = .nodeOffset(.zero), | |
| 34462 | }; | |
| 34463 | ||
| 34464 | const enum_decl = sema.code.getEnumDecl(inst); | |
| 34465 | ||
| 34466 | const captures = try sema.getCaptures(block, src, enum_decl.captures, enum_decl.capture_names); | |
| 34467 | ||
| 34468 | const ty: Type = switch (try ip.getDeclaredEnumType(gpa, io, pt.tid, .{ | |
| 34469 | .zir_index = tracked_inst, | |
| 34470 | .captures = captures, | |
| 34471 | .fields_len = @intCast(enum_decl.field_names.len), | |
| 34472 | .nonexhaustive = enum_decl.nonexhaustive, | |
| 34473 | .int_tag_mode = if (enum_decl.tag_type_body != null) .explicit else .auto, | |
| 34474 | })) { | |
| 34475 | .existing => |ty| .fromInterned(ty), | |
| 34476 | .wip => |wip| ty: { | |
| 34477 | errdefer wip.cancel(ip, pt.tid); | |
| 34478 | try sema.setTypeName(block, &wip, enum_decl.name_strategy, "enum", inst); | |
| 34479 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 34480 | .parent = block.namespace.toOptional(), | |
| 34481 | .owner_type = wip.index, | |
| 34482 | .file_scope = block.getFileScopeIndex(zcu), | |
| 34483 | .generation = zcu.generation, | |
| 34484 | }); | |
| 34485 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 34486 | try pt.scanNamespace(new_namespace_index, enum_decl.decls); | |
| 34487 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 34488 | break :ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 34489 | }, | |
| 34490 | }; | |
| 34491 | ||
| 34492 | try sema.addTypeReferenceEntry(src, ty); | |
| 34493 | try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); | |
| 34494 | ||
| 34495 | return .fromType(ty); | |
| 34496 | } | |
| 34497 | fn zirOpaqueDecl( | |
| 34498 | sema: *Sema, | |
| 34499 | block: *Block, | |
| 34500 | inst: Zir.Inst.Index, | |
| 34501 | ) CompileError!Air.Inst.Ref { | |
| 34502 | const pt = sema.pt; | |
| 34503 | const zcu = pt.zcu; | |
| 34504 | const comp = zcu.comp; | |
| 34505 | const gpa = comp.gpa; | |
| 34506 | const io = comp.io; | |
| 34507 | const ip = &zcu.intern_pool; | |
| 34508 | ||
| 34509 | const tracked_inst = try block.trackZir(inst); | |
| 34510 | ||
| 34511 | const src: LazySrcLoc = .{ | |
| 34512 | .base_node_inst = tracked_inst, | |
| 34513 | .offset = .nodeOffset(.zero), | |
| 34514 | }; | |
| 34515 | ||
| 34516 | const opaque_decl = sema.code.getOpaqueDecl(inst); | |
| 34517 | ||
| 34518 | const captures = try sema.getCaptures(block, src, opaque_decl.captures, opaque_decl.capture_names); | |
| 34519 | ||
| 34520 | const ty: Type = switch (try ip.getDeclaredOpaqueType(gpa, io, pt.tid, .{ | |
| 34521 | .zir_index = tracked_inst, | |
| 34522 | .captures = captures, | |
| 34523 | })) { | |
| 34524 | .existing => |ty| .fromInterned(ty), | |
| 34525 | .wip => |wip| ty: { | |
| 34526 | errdefer wip.cancel(ip, pt.tid); | |
| 34527 | try sema.setTypeName(block, &wip, opaque_decl.name_strategy, "opaque", inst); | |
| 34528 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 34529 | .parent = block.namespace.toOptional(), | |
| 34530 | .owner_type = wip.index, | |
| 34531 | .file_scope = block.getFileScopeIndex(zcu), | |
| 34532 | .generation = zcu.generation, | |
| 34533 | }); | |
| 34534 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 34535 | try pt.scanNamespace(new_namespace_index, opaque_decl.decls); | |
| 34536 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 34537 | break :ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 34538 | }, | |
| 34539 | }; | |
| 34540 | ||
| 34541 | try sema.addTypeReferenceEntry(src, ty); | |
| 34542 | try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); | |
| 34543 | ||
| 34544 | return .fromType(ty); | |
| 34545 | } | |
| 34546 | ||
| 34547 | /// Registers an error indicating a dependency loop: we have introduced a dependency on `want` (with | |
| 34548 | /// reason `want_reason`) but have learnt that `want` is already in `zcu.analysis_in_progress`. | |
| 34549 | pub fn failWithDependencyLoop( | |
| 34550 | sema: *Sema, | |
| 34551 | want: AnalUnit, | |
| 34552 | want_reason: *const Zcu.DependencyReason, | |
| 34553 | ) SemaError { | |
| 34554 | const pt = sema.pt; | |
| 34555 | const zcu = pt.zcu; | |
| 34556 | const gpa = zcu.comp.gpa; | |
| 34557 | ||
| 34558 | const in_progress_len = zcu.analysis_in_progress.count(); | |
| 34559 | var index = zcu.analysis_in_progress.getIndex(want).? + 1; | |
| 34560 | ||
| 34561 | try zcu.dependency_loops.ensureUnusedCapacity(gpa, 1); | |
| 34562 | try zcu.dependency_loop_nodes.ensureUnusedCapacity(gpa, in_progress_len - index + 1); | |
| 34563 | ||
| 34564 | zcu.dependency_loops.putAssumeCapacityNoClobber(want, {}); | |
| 34565 | ||
| 34566 | while (index <= in_progress_len) : (index += 1) { | |
| 34567 | const parent_unit = zcu.analysis_in_progress.keys()[index - 1]; | |
| 34568 | const unit, const reason = if (index == in_progress_len) .{ | |
| 34569 | want, | |
| 34570 | want_reason, | |
| 34571 | } else .{ | |
| 34572 | zcu.analysis_in_progress.keys()[index], | |
| 34573 | zcu.analysis_in_progress.values()[index], | |
| 34574 | }; | |
| 34575 | ||
| 34576 | zcu.dependency_loop_nodes.putAssumeCapacityNoClobber(parent_unit, .{ | |
| 34577 | .unit = unit, | |
| 34578 | .reason = reason.?.*, | |
| 34579 | }); | |
| 34580 | } | |
| 34581 | ||
| 34582 | // A dependency loop error will be reported. Mark us all as transitive failures. | |
| 34583 | return error.AnalysisFail; | |
| 34584 | } |
src/Sema/LowerZon.zig+61-71| ... | ... | @@ -129,84 +129,73 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter |
| 129 | 129 | for (0..init.names.len) |i| { |
| 130 | 130 | elems[i] = try self.lowerExprAnonResTy(init.vals.at(@intCast(i))); |
| 131 | 131 | } |
| 132 | const struct_ty = switch (try ip.getStructType( | |
| 133 | gpa, | |
| 134 | io, | |
| 135 | pt.tid, | |
| 136 | .{ | |
| 137 | .layout = .auto, | |
| 138 | .fields_len = @intCast(init.names.len), | |
| 139 | .known_non_opv = false, | |
| 140 | .requires_comptime = .no, | |
| 141 | .any_comptime_fields = true, | |
| 142 | .any_default_inits = true, | |
| 143 | .inits_resolved = true, | |
| 144 | .any_aligned_fields = false, | |
| 145 | .key = .{ .reified = .{ | |
| 146 | .zir_index = self.base_node_inst, | |
| 147 | .type_hash = hash: { | |
| 148 | var hasher: std.hash.Wyhash = .init(0); | |
| 149 | hasher.update(std.mem.asBytes(&node)); | |
| 150 | hasher.update(std.mem.sliceAsBytes(elems)); | |
| 151 | hasher.update(std.mem.sliceAsBytes(init.names)); | |
| 152 | break :hash hasher.final(); | |
| 153 | }, | |
| 154 | } }, | |
| 132 | const struct_ty: Type = switch (try ip.getReifiedStructType(gpa, io, pt.tid, .{ | |
| 133 | .zir_index = self.base_node_inst, | |
| 134 | .type_hash = hash: { | |
| 135 | var hasher: std.hash.Wyhash = .init(0); | |
| 136 | hasher.update(std.mem.asBytes(&node)); | |
| 137 | hasher.update(std.mem.sliceAsBytes(elems)); | |
| 138 | hasher.update(std.mem.sliceAsBytes(init.names)); | |
| 139 | break :hash hasher.final(); | |
| 155 | 140 | }, |
| 156 | false, | |
| 157 | )) { | |
| 141 | .fields_len = @intCast(init.names.len), | |
| 142 | .layout = .auto, | |
| 143 | .any_comptime_fields = true, | |
| 144 | .any_field_defaults = true, | |
| 145 | .any_field_aligns = false, | |
| 146 | .packed_backing_int_type = .none, | |
| 147 | })) { | |
| 148 | .existing => |ty| .fromInterned(ty), | |
| 158 | 149 | .wip => |wip| ty: { |
| 159 | 150 | errdefer wip.cancel(ip, pt.tid); |
| 160 | const type_name = try self.sema.createTypeName( | |
| 161 | self.block, | |
| 162 | .anon, | |
| 163 | "struct", | |
| 164 | self.base_node_inst.resolve(ip), | |
| 165 | wip.index, | |
| 166 | ); | |
| 167 | wip.setName(ip, type_name.name, type_name.nav); | |
| 168 | ||
| 169 | const struct_type = ip.loadStructType(wip.index); | |
| 170 | ||
| 171 | for (init.names, 0..) |name, field_idx| { | |
| 172 | const name_interned = try ip.getOrPutString( | |
| 151 | const block = self.block; | |
| 152 | const zcu = pt.zcu; | |
| 153 | try self.sema.setTypeName(block, &wip, .anon, "struct", self.base_node_inst.resolve(ip).?); | |
| 154 | ||
| 155 | // Reified structs have field information populated immediately. | |
| 156 | @memcpy(wip.field_values.get(ip), elems); | |
| 157 | if (init.names.len > 0) { | |
| 158 | // All fields are comptime, but unused bits remain zeroed. | |
| 159 | const unused_bits = switch (init.names.len % 32) { | |
| 160 | 0 => 0, | |
| 161 | else => |n| 32 - n, | |
| 162 | }; | |
| 163 | const comptime_bits = wip.field_is_comptime_bits.getAll(ip); | |
| 164 | @memset(comptime_bits[0 .. comptime_bits.len - 1], std.math.maxInt(u32)); | |
| 165 | comptime_bits[comptime_bits.len - 1] = @as(u32, std.math.maxInt(u32)) >> @intCast(unused_bits); | |
| 166 | } | |
| 167 | for ( | |
| 168 | init.names, | |
| 169 | wip.field_names.get(ip), | |
| 170 | wip.field_types.get(ip), | |
| 171 | wip.field_values.get(ip), | |
| 172 | ) |zoir_name, *field_name, *field_ty, field_val| { | |
| 173 | field_name.* = try ip.getOrPutString( | |
| 173 | 174 | gpa, |
| 174 | 175 | io, |
| 175 | 176 | pt.tid, |
| 176 | name.get(self.file.zoir.?), | |
| 177 | zoir_name.get(self.file.zoir.?), | |
| 177 | 178 | .no_embedded_nulls, |
| 178 | 179 | ); |
| 179 | assert(struct_type.addFieldName(ip, name_interned) == null); | |
| 180 | struct_type.setFieldComptime(ip, field_idx); | |
| 181 | } | |
| 182 | ||
| 183 | @memcpy(struct_type.field_inits.get(ip), elems); | |
| 184 | const types = struct_type.field_types.get(ip); | |
| 185 | for (0..init.names.len) |i| { | |
| 186 | types[i] = Value.fromInterned(elems[i]).typeOf(pt.zcu).toIntern(); | |
| 180 | field_ty.* = ip.typeOf(field_val); | |
| 187 | 181 | } |
| 188 | 182 | |
| 189 | 183 | const new_namespace_index = try pt.createNamespace(.{ |
| 190 | .parent = self.block.namespace.toOptional(), | |
| 184 | .parent = block.namespace.toOptional(), | |
| 191 | 185 | .owner_type = wip.index, |
| 192 | .file_scope = self.block.getFileScopeIndex(pt.zcu), | |
| 193 | .generation = pt.zcu.generation, | |
| 186 | .file_scope = block.getFileScopeIndex(zcu), | |
| 187 | .generation = zcu.generation, | |
| 194 | 188 | }); |
| 195 | try pt.zcu.comp.queueJob(.{ .resolve_type_fully = wip.index }); | |
| 196 | codegen_type: { | |
| 197 | if (pt.zcu.comp.config.use_llvm) break :codegen_type; | |
| 198 | if (self.block.ownerModule().strip) break :codegen_type; | |
| 199 | pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 200 | try pt.zcu.comp.queueJob(.{ .link_type = wip.index }); | |
| 201 | } | |
| 202 | break :ty wip.finish(ip, new_namespace_index); | |
| 189 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 190 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 191 | break :ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 203 | 192 | }, |
| 204 | .existing => |ty| ty, | |
| 205 | 193 | }; |
| 206 | try self.sema.declareDependency(.{ .interned = struct_ty }); | |
| 207 | 194 | try self.sema.addTypeReferenceEntry(self.nodeSrc(node), struct_ty); |
| 195 | // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. | |
| 196 | try self.sema.ensureLayoutResolved(struct_ty, self.nodeSrc(node), .init); | |
| 208 | 197 | |
| 209 | return (try pt.aggregateValue(.fromInterned(struct_ty), elems)).toIntern(); | |
| 198 | return (try pt.aggregateValue(struct_ty, elems)).toIntern(); | |
| 210 | 199 | }, |
| 211 | 200 | } |
| 212 | 201 | } |
| ... | ... | @@ -299,7 +288,7 @@ fn checkTypeInner( |
| 299 | 288 | } else { |
| 300 | 289 | const gop = try visited.getOrPut(sema.arena, ty.toIntern()); |
| 301 | 290 | if (gop.found_existing) return; |
| 302 | try ty.resolveFields(pt); | |
| 291 | try sema.ensureLayoutResolved(ty, self.import_loc, .init); | |
| 303 | 292 | const struct_info = zcu.typeToStruct(ty).?; |
| 304 | 293 | for (struct_info.field_types.get(ip)) |field_type| { |
| 305 | 294 | try self.checkTypeInner(.fromInterned(field_type), null, visited); |
| ... | ... | @@ -308,7 +297,7 @@ fn checkTypeInner( |
| 308 | 297 | .@"union" => { |
| 309 | 298 | const gop = try visited.getOrPut(sema.arena, ty.toIntern()); |
| 310 | 299 | if (gop.found_existing) return; |
| 311 | try ty.resolveFields(pt); | |
| 300 | try sema.ensureLayoutResolved(ty, self.import_loc, .init); | |
| 312 | 301 | const union_info = zcu.typeToUnion(ty).?; |
| 313 | 302 | for (union_info.field_types.get(ip)) |field_type| { |
| 314 | 303 | if (field_type != .void_type) { |
| ... | ... | @@ -645,6 +634,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I |
| 645 | 634 | const gpa = comp.gpa; |
| 646 | 635 | const io = comp.io; |
| 647 | 636 | const ip = &pt.zcu.intern_pool; |
| 637 | try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); | |
| 648 | 638 | switch (node.get(self.file.zoir.?)) { |
| 649 | 639 | .enum_literal => |field_name| { |
| 650 | 640 | const field_name_interned = try ip.getOrPutString( |
| ... | ... | @@ -767,8 +757,8 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 767 | 757 | const io = comp.io; |
| 768 | 758 | const ip = &pt.zcu.intern_pool; |
| 769 | 759 | |
| 770 | try res_ty.resolveFields(self.sema.pt); | |
| 771 | try res_ty.resolveStructFieldInits(self.sema.pt); | |
| 760 | try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); | |
| 761 | try self.sema.ensureStructDefaultsResolved(res_ty, self.import_loc); | |
| 772 | 762 | const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; |
| 773 | 763 | |
| 774 | 764 | const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { |
| ... | ... | @@ -779,7 +769,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 779 | 769 | |
| 780 | 770 | const field_values = try self.sema.arena.alloc(InternPool.Index, struct_info.field_names.len); |
| 781 | 771 | |
| 782 | const field_defaults = struct_info.field_inits.get(ip); | |
| 772 | const field_defaults = struct_info.field_defaults.get(ip); | |
| 783 | 773 | if (field_defaults.len > 0) { |
| 784 | 774 | @memcpy(field_values, field_defaults); |
| 785 | 775 | } else { |
| ... | ... | @@ -803,7 +793,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 803 | 793 | const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]); |
| 804 | 794 | field_values[name_index] = try self.lowerExprKnownResTy(field_node, field_type); |
| 805 | 795 | |
| 806 | if (struct_info.comptime_bits.getBit(ip, name_index)) { | |
| 796 | if (struct_info.field_is_comptime_bits.get(ip, name_index)) { | |
| 807 | 797 | const val = ip.indexToKey(field_values[name_index]); |
| 808 | 798 | const default = ip.indexToKey(field_defaults[name_index]); |
| 809 | 799 | if (!val.eql(default, ip)) { |
| ... | ... | @@ -918,9 +908,9 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 918 | 908 | const gpa = comp.gpa; |
| 919 | 909 | const io = comp.io; |
| 920 | 910 | const ip = &pt.zcu.intern_pool; |
| 921 | try res_ty.resolveFields(self.sema.pt); | |
| 922 | const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?; | |
| 923 | const enum_tag_info = union_info.loadTagType(ip); | |
| 911 | try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); | |
| 912 | const union_info = pt.zcu.typeToUnion(res_ty).?; | |
| 913 | const enum_tag_info = ip.loadEnumType(union_info.enum_tag_type); | |
| 924 | 914 | |
| 925 | 915 | const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) { |
| 926 | 916 | .enum_literal => |name| b: { |
| ... | ... | @@ -956,7 +946,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 956 | 946 | const name_index = enum_tag_info.nameIndex(ip, field_name) orelse { |
| 957 | 947 | return error.WrongType; |
| 958 | 948 | }; |
| 959 | const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_ty), name_index); | |
| 949 | const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_type), name_index); | |
| 960 | 950 | const field_type: Type = .fromInterned(union_info.field_types.get(ip)[name_index]); |
| 961 | 951 | const val = if (maybe_field_node) |field_node| b: { |
| 962 | 952 | if (field_type.toIntern() == .void_type) { |
src/Sema/arith.zig+23-19| ... | ... | @@ -20,6 +20,9 @@ pub fn incrementDefinedInt( |
| 20 | 20 | const zcu = pt.zcu; |
| 21 | 21 | assert(prev_val.typeOf(zcu).toIntern() == ty.toIntern()); |
| 22 | 22 | assert(!prev_val.isUndef(zcu)); |
| 23 | if (ty.intInfo(zcu).bits == 0) { | |
| 24 | return .{ .overflow = true, .val = try comptimeIntAdd(sema, prev_val, .one_comptime_int) }; | |
| 25 | } | |
| 23 | 26 | const res = try intAdd(sema, prev_val, try pt.intValue(ty, 1), ty); |
| 24 | 27 | return .{ .overflow = res.overflow, .val = res.val }; |
| 25 | 28 | } |
| ... | ... | @@ -1053,7 +1056,7 @@ fn shlScalar( |
| 1053 | 1056 | if (rhs_val.isUndef(zcu)) return rhs_val; |
| 1054 | 1057 | }, |
| 1055 | 1058 | } |
| 1056 | switch (try rhs_val.orderAgainstZeroSema(pt)) { | |
| 1059 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 1057 | 1060 | .gt => {}, |
| 1058 | 1061 | .eq => return lhs_val, |
| 1059 | 1062 | .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx), |
| ... | ... | @@ -1090,7 +1093,7 @@ fn shlWithOverflowScalar( |
| 1090 | 1093 | if (lhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, lhs_src, vec_idx); |
| 1091 | 1094 | if (rhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, vec_idx); |
| 1092 | 1095 | |
| 1093 | switch (try rhs_val.orderAgainstZeroSema(pt)) { | |
| 1096 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 1094 | 1097 | .gt => {}, |
| 1095 | 1098 | .eq => return .{ .overflow_bit = .zero_u1, .wrapped_result = lhs_val }, |
| 1096 | 1099 | .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx), |
| ... | ... | @@ -1169,7 +1172,7 @@ fn shrScalar( |
| 1169 | 1172 | if (lhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, lhs_src, vec_idx); |
| 1170 | 1173 | if (rhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, vec_idx); |
| 1171 | 1174 | |
| 1172 | switch (try rhs_val.orderAgainstZeroSema(pt)) { | |
| 1175 | switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { | |
| 1173 | 1176 | .gt => {}, |
| 1174 | 1177 | .eq => return lhs_val, |
| 1175 | 1178 | .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx), |
| ... | ... | @@ -1430,8 +1433,8 @@ fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value |
| 1430 | 1433 | const info = ty.intInfo(zcu); |
| 1431 | 1434 | var lhs_space: Value.BigIntSpace = undefined; |
| 1432 | 1435 | var rhs_space: Value.BigIntSpace = undefined; |
| 1433 | const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); | |
| 1434 | const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt); | |
| 1436 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | |
| 1437 | const rhs_bigint = rhs.toBigInt(&rhs_space, zcu); | |
| 1435 | 1438 | const limbs = try sema.arena.alloc( |
| 1436 | 1439 | std.math.big.Limb, |
| 1437 | 1440 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | ... | @@ -1512,8 +1515,8 @@ fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value |
| 1512 | 1515 | const info = ty.intInfo(zcu); |
| 1513 | 1516 | var lhs_space: Value.BigIntSpace = undefined; |
| 1514 | 1517 | var rhs_space: Value.BigIntSpace = undefined; |
| 1515 | const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); | |
| 1516 | const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt); | |
| 1518 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | |
| 1519 | const rhs_bigint = rhs.toBigInt(&rhs_space, zcu); | |
| 1517 | 1520 | const limbs = try sema.arena.alloc( |
| 1518 | 1521 | std.math.big.Limb, |
| 1519 | 1522 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| ... | ... | @@ -1597,8 +1600,8 @@ fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value |
| 1597 | 1600 | const info = ty.intInfo(zcu); |
| 1598 | 1601 | var lhs_space: Value.BigIntSpace = undefined; |
| 1599 | 1602 | var rhs_space: Value.BigIntSpace = undefined; |
| 1600 | const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); | |
| 1601 | const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt); | |
| 1603 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | |
| 1604 | const rhs_bigint = rhs.toBigInt(&rhs_space, zcu); | |
| 1602 | 1605 | const limbs = try sema.arena.alloc( |
| 1603 | 1606 | std.math.big.Limb, |
| 1604 | 1607 | lhs_bigint.limbs.len + rhs_bigint.limbs.len, |
| ... | ... | @@ -1840,7 +1843,7 @@ fn intShl( |
| 1840 | 1843 | var lhs_space: Value.BigIntSpace = undefined; |
| 1841 | 1844 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); |
| 1842 | 1845 | |
| 1843 | const shift_amt: usize = @intCast(try rhs.toUnsignedIntSema(pt)); | |
| 1846 | const shift_amt: usize = @intCast(rhs.toUnsignedInt(zcu)); | |
| 1844 | 1847 | if (shift_amt >= info.bits) { |
| 1845 | 1848 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx); |
| 1846 | 1849 | } |
| ... | ... | @@ -1862,7 +1865,7 @@ fn intShlSat( |
| 1862 | 1865 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); |
| 1863 | 1866 | |
| 1864 | 1867 | const shift_amt: usize = amt: { |
| 1865 | if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| { | |
| 1868 | if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| { | |
| 1866 | 1869 | if (std.math.cast(usize, shift_amt_u64)) |shift_amt| break :amt shift_amt; |
| 1867 | 1870 | } |
| 1868 | 1871 | // We only support ints with up to 2^16 - 1 bits, so this |
| ... | ... | @@ -1895,9 +1898,9 @@ fn intShlWithOverflow( |
| 1895 | 1898 | const info = lhs_ty.intInfo(zcu); |
| 1896 | 1899 | |
| 1897 | 1900 | var lhs_space: Value.BigIntSpace = undefined; |
| 1898 | const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); | |
| 1901 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | |
| 1899 | 1902 | |
| 1900 | const shift_amt: usize = @intCast(try rhs.toUnsignedIntSema(pt)); | |
| 1903 | const shift_amt: usize = @intCast(rhs.toUnsignedInt(zcu)); | |
| 1901 | 1904 | if (shift_amt >= info.bits) { |
| 1902 | 1905 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx); |
| 1903 | 1906 | } |
| ... | ... | @@ -1924,9 +1927,10 @@ fn comptimeIntShl( |
| 1924 | 1927 | vec_idx: ?usize, |
| 1925 | 1928 | ) !Value { |
| 1926 | 1929 | const pt = sema.pt; |
| 1930 | const zcu = pt.zcu; | |
| 1927 | 1931 | var lhs_space: Value.BigIntSpace = undefined; |
| 1928 | const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); | |
| 1929 | if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| { | |
| 1932 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | |
| 1933 | if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| { | |
| 1930 | 1934 | if (std.math.cast(usize, shift_amt_u64)) |shift_amt| { |
| 1931 | 1935 | const result_bigint = try intShlInner(sema, lhs_bigint, shift_amt); |
| 1932 | 1936 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); |
| ... | ... | @@ -1963,15 +1967,15 @@ fn intShr( |
| 1963 | 1967 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); |
| 1964 | 1968 | |
| 1965 | 1969 | const shift_amt: usize = if (rhs_ty.toIntern() == .comptime_int_type) amt: { |
| 1966 | if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| { | |
| 1970 | if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| { | |
| 1967 | 1971 | if (std.math.cast(usize, shift_amt_u64)) |shift_amt| break :amt shift_amt; |
| 1968 | 1972 | } |
| 1969 | if (try rhs.compareAllWithZeroSema(.lt, pt)) { | |
| 1973 | if (rhs.compareAllWithZero(.lt, zcu)) { | |
| 1970 | 1974 | return sema.failWithNegativeShiftAmount(block, rhs_src, rhs, vec_idx); |
| 1971 | 1975 | } else { |
| 1972 | 1976 | return sema.failWithUnsupportedComptimeShiftAmount(block, rhs_src, vec_idx); |
| 1973 | 1977 | } |
| 1974 | } else @intCast(try rhs.toUnsignedIntSema(pt)); | |
| 1978 | } else @intCast(rhs.toUnsignedInt(zcu)); | |
| 1975 | 1979 | |
| 1976 | 1980 | if (lhs_ty.toIntern() != .comptime_int_type and shift_amt >= lhs_ty.intInfo(zcu).bits) { |
| 1977 | 1981 | return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx); |
| ... | ... | @@ -2006,7 +2010,7 @@ fn intBitReverse(sema: *Sema, val: Value, ty: Type) !Value { |
| 2006 | 2010 | const info = ty.intInfo(zcu); |
| 2007 | 2011 | |
| 2008 | 2012 | var val_space: Value.BigIntSpace = undefined; |
| 2009 | const val_bigint = try val.toBigIntSema(&val_space, pt); | |
| 2013 | const val_bigint = val.toBigInt(&val_space, zcu); | |
| 2010 | 2014 | |
| 2011 | 2015 | const limbs = try sema.arena.alloc( |
| 2012 | 2016 | std.math.big.Limb, |
src/Sema/bitcast.zig+94-90| ... | ... | @@ -79,8 +79,8 @@ fn bitCastInner( |
| 79 | 79 | |
| 80 | 80 | const val_ty = val.typeOf(zcu); |
| 81 | 81 | |
| 82 | try val_ty.resolveLayout(pt); | |
| 83 | try dest_ty.resolveLayout(pt); | |
| 82 | val_ty.assertHasLayout(zcu); | |
| 83 | dest_ty.assertHasLayout(zcu); | |
| 84 | 84 | |
| 85 | 85 | assert(val_ty.hasWellDefinedLayout(zcu)); |
| 86 | 86 | |
| ... | ... | @@ -138,8 +138,8 @@ fn bitCastSpliceInner( |
| 138 | 138 | const val_ty = val.typeOf(zcu); |
| 139 | 139 | const splice_val_ty = splice_val.typeOf(zcu); |
| 140 | 140 | |
| 141 | try val_ty.resolveLayout(pt); | |
| 142 | try splice_val_ty.resolveLayout(pt); | |
| 141 | val_ty.assertHasLayout(zcu); | |
| 142 | splice_val_ty.assertHasLayout(zcu); | |
| 143 | 143 | |
| 144 | 144 | const splice_bits = splice_val_ty.bitSize(zcu); |
| 145 | 145 | |
| ... | ... | @@ -267,12 +267,13 @@ const UnpackValueBits = struct { |
| 267 | 267 | .int, |
| 268 | 268 | .enum_tag, |
| 269 | 269 | .simple_value, |
| 270 | .empty_enum_value, | |
| 271 | 270 | .float, |
| 272 | 271 | .ptr, |
| 273 | 272 | .opt, |
| 274 | 273 | => try unpack.primitive(val), |
| 275 | 274 | |
| 275 | .bitpack => |bitpack| try unpack.primitive(.fromInterned(bitpack.backing_int_val)), | |
| 276 | ||
| 276 | 277 | .aggregate => switch (ty.zigTypeTag(zcu)) { |
| 277 | 278 | .vector => { |
| 278 | 279 | const len: usize = @intCast(ty.arrayLen(zcu)); |
| ... | ... | @@ -443,7 +444,7 @@ const UnpackValueBits = struct { |
| 443 | 444 | // This @intCast is okay because no primitive can exceed the size of a u16. |
| 444 | 445 | const int_ty = try unpack.pt.intType(.unsigned, @intCast(bit_count)); |
| 445 | 446 | const buf = try unpack.arena.alloc(u8, @intCast((val_bits + 7) / 8)); |
| 446 | try val.writeToPackedMemory(ty, unpack.pt, buf, 0); | |
| 447 | try val.writeToPackedMemory(unpack.pt, buf, 0); | |
| 447 | 448 | const sub_val = try Value.readFromPackedMemory(int_ty, unpack.pt, buf, @intCast(bit_offset), unpack.arena); |
| 448 | 449 | try unpack.primitive(sub_val); |
| 449 | 450 | }, |
| ... | ... | @@ -451,7 +452,6 @@ const UnpackValueBits = struct { |
| 451 | 452 | // The only values here with runtime bits are `true` and `false. |
| 452 | 453 | // These are both 1 bit, so will never need truncating. |
| 453 | 454 | .simple_value => unreachable, |
| 454 | .empty_enum_value => unreachable, // zero-bit | |
| 455 | 455 | else => unreachable, // zero-bit or not primitives |
| 456 | 456 | } |
| 457 | 457 | } |
| ... | ... | @@ -565,102 +565,103 @@ const PackValueBits = struct { |
| 565 | 565 | return pt.aggregateValue(ty, elems); |
| 566 | 566 | }, |
| 567 | 567 | .@"packed" => { |
| 568 | // All fields are in order with no padding. | |
| 569 | // This is identical between LE and BE targets. | |
| 570 | const elems = try arena.alloc(InternPool.Index, ty.structFieldCount(zcu)); | |
| 571 | for (elems, 0..) |*elem, i| { | |
| 572 | const field_ty = ty.fieldType(i, zcu); | |
| 573 | elem.* = (try pack.get(field_ty)).toIntern(); | |
| 574 | } | |
| 575 | return pt.aggregateValue(ty, elems); | |
| 568 | const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu)); | |
| 569 | return pt.bitpackValue(ty, backing_int_val); | |
| 576 | 570 | }, |
| 577 | 571 | }, |
| 578 | .@"union" => { | |
| 579 | // We will attempt to read as the backing representation. If this emits | |
| 580 | // `error.ReinterpretDeclRef`, we will try each union field, preferring larger ones. | |
| 581 | // We will also attempt smaller fields when we get `undefined`, as if some bits are | |
| 582 | // defined we want to include them. | |
| 583 | // TODO: this is very very bad. We need a more sophisticated union representation. | |
| 584 | ||
| 585 | const prev_unpacked = pack.unpacked; | |
| 586 | const prev_bit_offset = pack.bit_offset; | |
| 587 | ||
| 588 | const backing_ty = try ty.unionBackingType(pt); | |
| 589 | ||
| 590 | backing: { | |
| 591 | const backing_val = pack.get(backing_ty) catch |err| switch (err) { | |
| 592 | error.ReinterpretDeclRef => { | |
| 572 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 573 | .auto => unreachable, // ill-defined layout | |
| 574 | .@"extern" => { | |
| 575 | // We will attempt to read as the backing representation. If this emits | |
| 576 | // `error.ReinterpretDeclRef`, we will try each union field, preferring larger ones. | |
| 577 | // We will also attempt smaller fields when we get `undefined`, as if some bits are | |
| 578 | // defined we want to include them. | |
| 579 | // TODO: this is very very bad. We need a more sophisticated union representation. | |
| 580 | ||
| 581 | const prev_unpacked = pack.unpacked; | |
| 582 | const prev_bit_offset = pack.bit_offset; | |
| 583 | ||
| 584 | const backing_ty = try ty.externUnionBackingType(pt); | |
| 585 | ||
| 586 | backing: { | |
| 587 | const backing_val = pack.get(backing_ty) catch |err| switch (err) { | |
| 588 | error.ReinterpretDeclRef => { | |
| 589 | pack.unpacked = prev_unpacked; | |
| 590 | pack.bit_offset = prev_bit_offset; | |
| 591 | break :backing; | |
| 592 | }, | |
| 593 | else => |e| return e, | |
| 594 | }; | |
| 595 | if (backing_val.isUndef(zcu)) { | |
| 593 | 596 | pack.unpacked = prev_unpacked; |
| 594 | 597 | pack.bit_offset = prev_bit_offset; |
| 595 | 598 | break :backing; |
| 596 | }, | |
| 597 | else => |e| return e, | |
| 598 | }; | |
| 599 | if (backing_val.isUndef(zcu)) { | |
| 600 | pack.unpacked = prev_unpacked; | |
| 601 | pack.bit_offset = prev_bit_offset; | |
| 602 | break :backing; | |
| 599 | } | |
| 600 | return Value.fromInterned(try pt.internUnion(.{ | |
| 601 | .ty = ty.toIntern(), | |
| 602 | .tag = .none, | |
| 603 | .val = backing_val.toIntern(), | |
| 604 | })); | |
| 603 | 605 | } |
| 604 | return Value.fromInterned(try pt.internUnion(.{ | |
| 605 | .ty = ty.toIntern(), | |
| 606 | .tag = .none, | |
| 607 | .val = backing_val.toIntern(), | |
| 608 | })); | |
| 609 | } | |
| 610 | 606 | |
| 611 | const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu)); | |
| 612 | for (field_order, 0..) |*f, i| f.* = @intCast(i); | |
| 613 | // Sort `field_order` to put the fields with the largest bit sizes first. | |
| 614 | const SizeSortCtx = struct { | |
| 615 | zcu: *Zcu, | |
| 616 | field_types: []const InternPool.Index, | |
| 617 | fn lessThan(ctx: @This(), a_idx: u32, b_idx: u32) bool { | |
| 618 | const a_ty = Type.fromInterned(ctx.field_types[a_idx]); | |
| 619 | const b_ty = Type.fromInterned(ctx.field_types[b_idx]); | |
| 620 | return a_ty.bitSize(ctx.zcu) > b_ty.bitSize(ctx.zcu); | |
| 621 | } | |
| 622 | }; | |
| 623 | std.mem.sortUnstable(u32, field_order, SizeSortCtx{ | |
| 624 | .zcu = zcu, | |
| 625 | .field_types = zcu.typeToUnion(ty).?.field_types.get(ip), | |
| 626 | }, SizeSortCtx.lessThan); | |
| 627 | ||
| 628 | const padding_after = endian == .little or ty.containerLayout(zcu) == .@"packed"; | |
| 629 | ||
| 630 | for (field_order) |field_idx| { | |
| 631 | const field_ty = Type.fromInterned(zcu.typeToUnion(ty).?.field_types.get(ip)[field_idx]); | |
| 632 | const pad_bits = ty.bitSize(zcu) - field_ty.bitSize(zcu); | |
| 633 | if (!padding_after) try pack.padding(pad_bits); | |
| 634 | const field_val = pack.get(field_ty) catch |err| switch (err) { | |
| 635 | error.ReinterpretDeclRef => { | |
| 607 | const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu)); | |
| 608 | for (field_order, 0..) |*f, i| f.* = @intCast(i); | |
| 609 | // Sort `field_order` to put the fields with the largest bit sizes first. | |
| 610 | const SizeSortCtx = struct { | |
| 611 | zcu: *Zcu, | |
| 612 | field_types: []const InternPool.Index, | |
| 613 | fn lessThan(ctx: @This(), a_idx: u32, b_idx: u32) bool { | |
| 614 | const a_ty = Type.fromInterned(ctx.field_types[a_idx]); | |
| 615 | const b_ty = Type.fromInterned(ctx.field_types[b_idx]); | |
| 616 | return a_ty.bitSize(ctx.zcu) > b_ty.bitSize(ctx.zcu); | |
| 617 | } | |
| 618 | }; | |
| 619 | std.mem.sortUnstable(u32, field_order, SizeSortCtx{ | |
| 620 | .zcu = zcu, | |
| 621 | .field_types = zcu.typeToUnion(ty).?.field_types.get(ip), | |
| 622 | }, SizeSortCtx.lessThan); | |
| 623 | ||
| 624 | const padding_after = endian == .little or ty.containerLayout(zcu) == .@"packed"; | |
| 625 | ||
| 626 | for (field_order) |field_idx| { | |
| 627 | const field_ty = Type.fromInterned(zcu.typeToUnion(ty).?.field_types.get(ip)[field_idx]); | |
| 628 | const pad_bits = ty.bitSize(zcu) - field_ty.bitSize(zcu); | |
| 629 | if (!padding_after) try pack.padding(pad_bits); | |
| 630 | const field_val = pack.get(field_ty) catch |err| switch (err) { | |
| 631 | error.ReinterpretDeclRef => { | |
| 632 | pack.unpacked = prev_unpacked; | |
| 633 | pack.bit_offset = prev_bit_offset; | |
| 634 | continue; | |
| 635 | }, | |
| 636 | else => |e| return e, | |
| 637 | }; | |
| 638 | if (padding_after) try pack.padding(pad_bits); | |
| 639 | if (field_val.isUndef(zcu)) { | |
| 636 | 640 | pack.unpacked = prev_unpacked; |
| 637 | 641 | pack.bit_offset = prev_bit_offset; |
| 638 | 642 | continue; |
| 639 | }, | |
| 640 | else => |e| return e, | |
| 641 | }; | |
| 642 | if (padding_after) try pack.padding(pad_bits); | |
| 643 | if (field_val.isUndef(zcu)) { | |
| 644 | pack.unpacked = prev_unpacked; | |
| 645 | pack.bit_offset = prev_bit_offset; | |
| 646 | continue; | |
| 643 | } | |
| 644 | const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx); | |
| 645 | return Value.fromInterned(try pt.internUnion(.{ | |
| 646 | .ty = ty.toIntern(), | |
| 647 | .tag = tag_val.toIntern(), | |
| 648 | .val = field_val.toIntern(), | |
| 649 | })); | |
| 647 | 650 | } |
| 648 | const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx); | |
| 651 | ||
| 652 | // No field could represent the value. Just do whatever happens when we try to read | |
| 653 | // the backing type - either `undefined` or `error.ReinterpretDeclRef`. | |
| 654 | const backing_val = try pack.get(backing_ty); | |
| 649 | 655 | return Value.fromInterned(try pt.internUnion(.{ |
| 650 | 656 | .ty = ty.toIntern(), |
| 651 | .tag = tag_val.toIntern(), | |
| 652 | .val = field_val.toIntern(), | |
| 657 | .tag = .none, | |
| 658 | .val = backing_val.toIntern(), | |
| 653 | 659 | })); |
| 654 | } | |
| 655 | ||
| 656 | // No field could represent the value. Just do whatever happens when we try to read | |
| 657 | // the backing type - either `undefined` or `error.ReinterpretDeclRef`. | |
| 658 | const backing_val = try pack.get(backing_ty); | |
| 659 | return Value.fromInterned(try pt.internUnion(.{ | |
| 660 | .ty = ty.toIntern(), | |
| 661 | .tag = .none, | |
| 662 | .val = backing_val.toIntern(), | |
| 663 | })); | |
| 660 | }, | |
| 661 | .@"packed" => { | |
| 662 | const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu)); | |
| 663 | return pt.bitpackValue(ty, backing_int_val); | |
| 664 | }, | |
| 664 | 665 | }, |
| 665 | 666 | else => return pack.primitive(ty), |
| 666 | 667 | } |
| ... | ... | @@ -673,6 +674,9 @@ const PackValueBits = struct { |
| 673 | 674 | fn primitive(pack: *PackValueBits, want_ty: Type) BitCastError!Value { |
| 674 | 675 | const pt = pack.pt; |
| 675 | 676 | const zcu = pt.zcu; |
| 677 | ||
| 678 | if (try want_ty.onePossibleValue(pt)) |opv| return opv; | |
| 679 | ||
| 676 | 680 | const vals, const bit_offset = pack.prepareBits(want_ty.bitSize(zcu)); |
| 677 | 681 | |
| 678 | 682 | for (vals) |val| { |
| ... | ... | @@ -719,7 +723,7 @@ const PackValueBits = struct { |
| 719 | 723 | const val = Value.fromInterned(ip_val); |
| 720 | 724 | const ty = val.typeOf(zcu); |
| 721 | 725 | if (!val.isUndef(zcu)) { |
| 722 | try val.writeToPackedMemory(ty, pt, buf, cur_bit_off); | |
| 726 | try val.writeToPackedMemory(pt, buf, cur_bit_off); | |
| 723 | 727 | } |
| 724 | 728 | cur_bit_off += @intCast(ty.bitSize(zcu)); |
| 725 | 729 | } |
src/Sema/comptime_ptr_access.zig+19-19| ... | ... | @@ -67,7 +67,7 @@ pub fn storeComptimePtr( |
| 67 | 67 | |
| 68 | 68 | { |
| 69 | 69 | const store_ty: Type = .fromInterned(ptr_info.child); |
| 70 | if (!try store_ty.comptimeOnlySema(pt) and !try store_ty.hasRuntimeBitsIgnoreComptimeSema(pt)) { | |
| 70 | if (!store_ty.comptimeOnly(zcu) and !store_ty.hasRuntimeBits(zcu)) { | |
| 71 | 71 | // zero-bit store; nothing to do |
| 72 | 72 | return .success; |
| 73 | 73 | } |
| ... | ... | @@ -354,8 +354,8 @@ fn loadComptimePtrInner( |
| 354 | 354 | const load_one_ty, const load_count = load_ty.arrayBase(zcu); |
| 355 | 355 | |
| 356 | 356 | const extra_base_index: u64 = if (ptr.byte_offset == 0) 0 else idx: { |
| 357 | if (try load_one_ty.comptimeOnlySema(pt)) break :restructure_array; | |
| 358 | const elem_len = try load_one_ty.abiSizeSema(pt); | |
| 357 | if (load_one_ty.comptimeOnly(zcu)) break :restructure_array; | |
| 358 | const elem_len = load_one_ty.abiSize(zcu); | |
| 359 | 359 | if (ptr.byte_offset % elem_len != 0) break :restructure_array; |
| 360 | 360 | break :idx @divExact(ptr.byte_offset, elem_len); |
| 361 | 361 | }; |
| ... | ... | @@ -401,12 +401,12 @@ fn loadComptimePtrInner( |
| 401 | 401 | var cur_offset = ptr.byte_offset; |
| 402 | 402 | |
| 403 | 403 | if (load_ty.zigTypeTag(zcu) == .array and array_offset > 0) { |
| 404 | cur_offset += try load_ty.childType(zcu).abiSizeSema(pt) * array_offset; | |
| 404 | cur_offset += load_ty.childType(zcu).abiSize(zcu) * array_offset; | |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else try load_ty.abiSizeSema(pt); | |
| 407 | const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else load_ty.abiSize(zcu); | |
| 408 | 408 | |
| 409 | if (cur_offset + need_bytes > try cur_val.typeOf(zcu).abiSizeSema(pt)) { | |
| 409 | if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) { | |
| 410 | 410 | return .{ .out_of_bounds = cur_val.typeOf(zcu) }; |
| 411 | 411 | } |
| 412 | 412 | |
| ... | ... | @@ -441,7 +441,7 @@ fn loadComptimePtrInner( |
| 441 | 441 | .optional => break, // this can only be a pointer-like optional so is terminal |
| 442 | 442 | .array => { |
| 443 | 443 | const elem_ty = cur_ty.childType(zcu); |
| 444 | const elem_size = try elem_ty.abiSizeSema(pt); | |
| 444 | const elem_size = elem_ty.abiSize(zcu); | |
| 445 | 445 | const elem_idx = cur_offset / elem_size; |
| 446 | 446 | const next_elem_off = elem_size * (elem_idx + 1); |
| 447 | 447 | if (cur_offset + need_bytes <= next_elem_off) { |
| ... | ... | @@ -457,7 +457,7 @@ fn loadComptimePtrInner( |
| 457 | 457 | .@"packed" => break, // let the bitcast logic handle this |
| 458 | 458 | .@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| { |
| 459 | 459 | const start_off = cur_ty.structFieldOffset(field_idx, zcu); |
| 460 | const end_off = start_off + try cur_ty.fieldType(field_idx, zcu).abiSizeSema(pt); | |
| 460 | const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu); | |
| 461 | 461 | if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { |
| 462 | 462 | cur_val = try cur_val.getElem(sema.pt, field_idx); |
| 463 | 463 | cur_offset -= start_off; |
| ... | ... | @@ -484,7 +484,7 @@ fn loadComptimePtrInner( |
| 484 | 484 | }; |
| 485 | 485 | // The payload always has offset 0. If it's big enough |
| 486 | 486 | // to represent the whole load type, we can use it. |
| 487 | if (try payload.typeOf(zcu).abiSizeSema(pt) >= need_bytes) { | |
| 487 | if (payload.typeOf(zcu).abiSize(zcu) >= need_bytes) { | |
| 488 | 488 | cur_val = payload; |
| 489 | 489 | } else { |
| 490 | 490 | break; |
| ... | ... | @@ -753,8 +753,8 @@ fn prepareComptimePtrStore( |
| 753 | 753 | |
| 754 | 754 | const store_one_ty, const store_count = store_ty.arrayBase(zcu); |
| 755 | 755 | const extra_base_index: u64 = if (ptr.byte_offset == 0) 0 else idx: { |
| 756 | if (try store_one_ty.comptimeOnlySema(pt)) break :restructure_array; | |
| 757 | const elem_len = try store_one_ty.abiSizeSema(pt); | |
| 756 | if (store_one_ty.comptimeOnly(zcu)) break :restructure_array; | |
| 757 | const elem_len = store_one_ty.abiSize(zcu); | |
| 758 | 758 | if (ptr.byte_offset % elem_len != 0) break :restructure_array; |
| 759 | 759 | break :idx @divExact(ptr.byte_offset, elem_len); |
| 760 | 760 | }; |
| ... | ... | @@ -807,11 +807,11 @@ fn prepareComptimePtrStore( |
| 807 | 807 | var cur_val: *MutableValue, var cur_offset: u64 = switch (base_strat) { |
| 808 | 808 | .direct => |direct| .{ direct.val, 0 }, |
| 809 | 809 | // It's okay to do `abiSize` - the comptime-only case will be caught below. |
| 810 | .index => |index| .{ index.val, index.elem_index * try index.val.typeOf(zcu).childType(zcu).abiSizeSema(pt) }, | |
| 810 | .index => |index| .{ index.val, index.elem_index * index.val.typeOf(zcu).childType(zcu).abiSize(zcu) }, | |
| 811 | 811 | .flat_index => |flat_index| .{ |
| 812 | 812 | flat_index.val, |
| 813 | 813 | // It's okay to do `abiSize` - the comptime-only case will be caught below. |
| 814 | flat_index.flat_elem_index * try flat_index.val.typeOf(zcu).arrayBase(zcu)[0].abiSizeSema(pt), | |
| 814 | flat_index.flat_elem_index * flat_index.val.typeOf(zcu).arrayBase(zcu)[0].abiSize(zcu), | |
| 815 | 815 | }, |
| 816 | 816 | .reinterpret => |r| .{ r.val, r.byte_offset }, |
| 817 | 817 | else => unreachable, |
| ... | ... | @@ -823,12 +823,12 @@ fn prepareComptimePtrStore( |
| 823 | 823 | } |
| 824 | 824 | |
| 825 | 825 | if (store_ty.zigTypeTag(zcu) == .array and array_offset > 0) { |
| 826 | cur_offset += try store_ty.childType(zcu).abiSizeSema(pt) * array_offset; | |
| 826 | cur_offset += store_ty.childType(zcu).abiSize(zcu) * array_offset; | |
| 827 | 827 | } |
| 828 | 828 | |
| 829 | const need_bytes = try store_ty.abiSizeSema(pt); | |
| 829 | const need_bytes = store_ty.abiSize(zcu); | |
| 830 | 830 | |
| 831 | if (cur_offset + need_bytes > try cur_val.typeOf(zcu).abiSizeSema(pt)) { | |
| 831 | if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) { | |
| 832 | 832 | return .{ .out_of_bounds = cur_val.typeOf(zcu) }; |
| 833 | 833 | } |
| 834 | 834 | |
| ... | ... | @@ -863,7 +863,7 @@ fn prepareComptimePtrStore( |
| 863 | 863 | .optional => break, // this can only be a pointer-like optional so is terminal |
| 864 | 864 | .array => { |
| 865 | 865 | const elem_ty = cur_ty.childType(zcu); |
| 866 | const elem_size = try elem_ty.abiSizeSema(pt); | |
| 866 | const elem_size = elem_ty.abiSize(zcu); | |
| 867 | 867 | const elem_idx = cur_offset / elem_size; |
| 868 | 868 | const next_elem_off = elem_size * (elem_idx + 1); |
| 869 | 869 | if (cur_offset + need_bytes <= next_elem_off) { |
| ... | ... | @@ -879,7 +879,7 @@ fn prepareComptimePtrStore( |
| 879 | 879 | .@"packed" => break, // let the bitcast logic handle this |
| 880 | 880 | .@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| { |
| 881 | 881 | const start_off = cur_ty.structFieldOffset(field_idx, zcu); |
| 882 | const end_off = start_off + try cur_ty.fieldType(field_idx, zcu).abiSizeSema(pt); | |
| 882 | const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu); | |
| 883 | 883 | if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { |
| 884 | 884 | cur_val = try cur_val.elem(pt, sema.arena, field_idx); |
| 885 | 885 | cur_offset -= start_off; |
| ... | ... | @@ -902,7 +902,7 @@ fn prepareComptimePtrStore( |
| 902 | 902 | }; |
| 903 | 903 | // The payload always has offset 0. If it's big enough |
| 904 | 904 | // to represent the whole load type, we can use it. |
| 905 | if (try payload.typeOf(zcu).abiSizeSema(pt) >= need_bytes) { | |
| 905 | if (payload.typeOf(zcu).abiSize(zcu) >= need_bytes) { | |
| 906 | 906 | cur_val = payload; |
| 907 | 907 | } else { |
| 908 | 908 | break; |
src/Sema/type_resolution.zig created+1398| ... | ... | @@ -0,0 +1,1398 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | ||
| 5 | const Sema = @import("../Sema.zig"); | |
| 6 | const Block = Sema.Block; | |
| 7 | const Type = @import("../Type.zig"); | |
| 8 | const Value = @import("../Value.zig"); | |
| 9 | const Zcu = @import("../Zcu.zig"); | |
| 10 | const CompileError = Zcu.CompileError; | |
| 11 | const SemaError = Zcu.SemaError; | |
| 12 | const LazySrcLoc = Zcu.LazySrcLoc; | |
| 13 | const InternPool = @import("../InternPool.zig"); | |
| 14 | const Alignment = InternPool.Alignment; | |
| 15 | const arith = @import("arith.zig"); | |
| 16 | ||
| 17 | pub const LayoutResolveReason = enum { | |
| 18 | variable, | |
| 19 | constant, | |
| 20 | parameter, | |
| 21 | return_type, | |
| 22 | field, | |
| 23 | backing_enum, | |
| 24 | init, | |
| 25 | coerce, | |
| 26 | ptr_access, | |
| 27 | ptr_offset, | |
| 28 | field_used, | |
| 29 | field_queried, | |
| 30 | size_of, | |
| 31 | align_of, | |
| 32 | type_info, | |
| 33 | align_check, | |
| 34 | bit_ptr_child, | |
| 35 | @"export", | |
| 36 | @"extern", | |
| 37 | builtin_type, | |
| 38 | ||
| 39 | /// Written after string: "while resolving type 'T' " | |
| 40 | /// e.g. "while resolving type 'MyStruct' for variable declared here" | |
| 41 | pub fn msg(r: LayoutResolveReason) []const u8 { | |
| 42 | return switch (r) { | |
| 43 | // zig fmt: off | |
| 44 | .variable => "for variable declared here", | |
| 45 | .constant => "for constant declared here", | |
| 46 | .parameter => "for function parameter declared here", | |
| 47 | .return_type => "for function return type declared here", | |
| 48 | .field => "for field declared here", | |
| 49 | .backing_enum => "for backing enum type declared here", | |
| 50 | .init => "for initialization performed here", | |
| 51 | .coerce => "for coercion performed here", | |
| 52 | .ptr_access => "for pointer access here", | |
| 53 | .ptr_offset => "for pointer offset here", | |
| 54 | .field_used => "for field usage here", | |
| 55 | .field_queried => "for field query here", | |
| 56 | .size_of => "for size query here", | |
| 57 | .align_of => "for alignment query here", | |
| 58 | .type_info => "for type information query here", | |
| 59 | .align_check => "for alignment check here", | |
| 60 | .bit_ptr_child => "for bit size check here", | |
| 61 | .@"export" => "for export here", | |
| 62 | .@"extern" => "for extern declaration here", | |
| 63 | .builtin_type => "from 'std.builtin'", | |
| 64 | // zig fmt: on | |
| 65 | }; | |
| 66 | } | |
| 67 | }; | |
| 68 | ||
| 69 | /// Ensures that `ty` has known layout, including alignment, size, and (where relevant) field offsets. | |
| 70 | /// `ty` may be any type; its layout is resolved *recursively* if necessary. | |
| 71 | /// Adds incremental dependencies tracking any required type resolution. | |
| 72 | pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc, reason: LayoutResolveReason) SemaError!void { | |
| 73 | return ensureLayoutResolvedInner(sema, ty, ty, &.{ | |
| 74 | .src = src, | |
| 75 | .type_layout_reason = reason, | |
| 76 | }); | |
| 77 | } | |
| 78 | fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *const Zcu.DependencyReason) SemaError!void { | |
| 79 | const pt = sema.pt; | |
| 80 | const zcu = pt.zcu; | |
| 81 | const ip = &zcu.intern_pool; | |
| 82 | switch (ip.indexToKey(ty.toIntern())) { | |
| 83 | .int_type, | |
| 84 | .ptr_type, | |
| 85 | .anyframe_type, | |
| 86 | .simple_type, | |
| 87 | .opaque_type, | |
| 88 | .error_set_type, | |
| 89 | .inferred_error_set_type, | |
| 90 | => {}, | |
| 91 | ||
| 92 | .func_type => |func_type| { | |
| 93 | for (func_type.param_types.get(ip)) |param_ty| { | |
| 94 | try ensureLayoutResolvedInner(sema, .fromInterned(param_ty), orig_ty, reason); | |
| 95 | } | |
| 96 | try ensureLayoutResolvedInner(sema, .fromInterned(func_type.return_type), orig_ty, reason); | |
| 97 | }, | |
| 98 | ||
| 99 | .array_type => |arr| return ensureLayoutResolvedInner(sema, .fromInterned(arr.child), orig_ty, reason), | |
| 100 | .vector_type => |vec| return ensureLayoutResolvedInner(sema, .fromInterned(vec.child), orig_ty, reason), | |
| 101 | .opt_type => |child| return ensureLayoutResolvedInner(sema, .fromInterned(child), orig_ty, reason), | |
| 102 | .error_union_type => |eu| return ensureLayoutResolvedInner(sema, .fromInterned(eu.payload_type), orig_ty, reason), | |
| 103 | .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { | |
| 104 | try ensureLayoutResolvedInner(sema, .fromInterned(field_ty), orig_ty, reason); | |
| 105 | }, | |
| 106 | .struct_type, .union_type, .enum_type => { | |
| 107 | try sema.declareDependency(.{ .type_layout = ty.toIntern() }); | |
| 108 | try sema.addReferenceEntry(null, reason.src, .wrap(.{ .type_layout = ty.toIntern() })); | |
| 109 | if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) { | |
| 110 | return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason); | |
| 111 | } | |
| 112 | try pt.ensureTypeLayoutUpToDate(ty, reason); | |
| 113 | }, | |
| 114 | ||
| 115 | // values, not types | |
| 116 | .undef, | |
| 117 | .simple_value, | |
| 118 | .variable, | |
| 119 | .@"extern", | |
| 120 | .func, | |
| 121 | .int, | |
| 122 | .err, | |
| 123 | .error_union, | |
| 124 | .enum_literal, | |
| 125 | .enum_tag, | |
| 126 | .float, | |
| 127 | .ptr, | |
| 128 | .slice, | |
| 129 | .opt, | |
| 130 | .aggregate, | |
| 131 | .un, | |
| 132 | .bitpack, | |
| 133 | // memoization, not types | |
| 134 | .memoized_call, | |
| 135 | => unreachable, | |
| 136 | } | |
| 137 | } | |
| 138 | ||
| 139 | /// Asserts that `ty` is a non-tuple `struct` type, and ensures that its fields' default values | |
| 140 | /// are resolved. Adds incremental dependencies tracking the required type resolution. | |
| 141 | /// | |
| 142 | /// It is not necessary to call this function to query the values of comptime fields: those values | |
| 143 | /// are available from type *layout* resolution, see `ensureLayoutResolved`. | |
| 144 | /// | |
| 145 | /// Asserts that the *layout* of `ty` has already been resolved---see `ensureLayoutResolved`. | |
| 146 | pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void { | |
| 147 | const pt = sema.pt; | |
| 148 | const zcu = pt.zcu; | |
| 149 | const ip = &zcu.intern_pool; | |
| 150 | ||
| 151 | assert(ip.indexToKey(ty.toIntern()) == .struct_type); | |
| 152 | ty.assertHasLayout(zcu); | |
| 153 | ||
| 154 | try sema.declareDependency(.{ .struct_defaults = ty.toIntern() }); | |
| 155 | try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() })); | |
| 156 | ||
| 157 | const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; | |
| 158 | ||
| 159 | if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) { | |
| 160 | return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason); | |
| 161 | } | |
| 162 | ||
| 163 | try pt.ensureStructDefaultsUpToDate(ty, &reason); | |
| 164 | } | |
| 165 | ||
| 166 | /// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type. | |
| 167 | /// This function *does* register the `src_hash` dependency on the struct. | |
| 168 | pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { | |
| 169 | const pt = sema.pt; | |
| 170 | const zcu = pt.zcu; | |
| 171 | const comp = zcu.comp; | |
| 172 | const io = comp.io; | |
| 173 | const gpa = comp.gpa; | |
| 174 | const ip = &zcu.intern_pool; | |
| 175 | ||
| 176 | assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); | |
| 177 | ||
| 178 | const struct_obj = ip.loadStructType(struct_ty.toIntern()); | |
| 179 | assert(struct_obj.want_layout); | |
| 180 | const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 181 | ||
| 182 | var block: Block = .{ | |
| 183 | .parent = null, | |
| 184 | .sema = sema, | |
| 185 | .namespace = struct_obj.namespace, | |
| 186 | .instructions = .empty, | |
| 187 | .inlining = null, | |
| 188 | .comptime_reason = undefined, // always set before using `block` | |
| 189 | .src_base_inst = struct_obj.zir_index, | |
| 190 | .type_name_ctx = struct_obj.name, | |
| 191 | }; | |
| 192 | defer block.instructions.deinit(gpa); | |
| 193 | ||
| 194 | // There may be old field names in here from a previous update. | |
| 195 | struct_obj.field_name_map.get(ip).clearRetainingCapacity(); | |
| 196 | ||
| 197 | if (struct_obj.is_reified) { | |
| 198 | // The field names are populated, but we haven't checked for duplicates (nor populated the map) yet. | |
| 199 | for (0..struct_obj.field_names.len) |field_index| { | |
| 200 | const name = struct_obj.field_names.get(ip)[field_index]; | |
| 201 | if (ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name)) |prev_field_index| { | |
| 202 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 203 | const src = block.builtinCallArgSrc(.zero, 2); | |
| 204 | const msg = try sema.errMsg(src, "duplicate struct field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); | |
| 205 | errdefer msg.destroy(gpa); | |
| 206 | try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); | |
| 207 | break :msg msg; | |
| 208 | }); | |
| 209 | } | |
| 210 | } | |
| 211 | } else { | |
| 212 | // Declared structs do not yet have field information populated: | |
| 213 | // * field names | |
| 214 | // * field comptime-ness | |
| 215 | // * field types | |
| 216 | // * field aligns | |
| 217 | // It's our job to populate these now. | |
| 218 | try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); | |
| 219 | ||
| 220 | // Likewise, comptime bits may be set. We clear them all first because it avoids needing | |
| 221 | // "unset bit with AND" logic below (instead we only need the "set bit with OR" case). | |
| 222 | @memset(struct_obj.field_is_comptime_bits.getAll(ip), 0); | |
| 223 | ||
| 224 | const zir_struct = sema.code.getStructDecl(zir_index); | |
| 225 | var field_it = zir_struct.iterateFields(); | |
| 226 | var any_comptime_fields = false; | |
| 227 | while (field_it.next()) |zir_field| { | |
| 228 | { | |
| 229 | const name_slice = sema.code.nullTerminatedString(zir_field.name); | |
| 230 | const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); | |
| 231 | assert(ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name) == null); // AstGen validated this for us | |
| 232 | } | |
| 233 | ||
| 234 | if (zir_field.is_comptime) { | |
| 235 | const bit_bag_index = zir_field.idx / 32; | |
| 236 | const mask = @as(u32, 1) << @intCast(zir_field.idx % 32); | |
| 237 | struct_obj.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; | |
| 238 | any_comptime_fields = true; | |
| 239 | } | |
| 240 | ||
| 241 | { | |
| 242 | const field_ty_src = block.src(.{ .container_field_type = zir_field.idx }); | |
| 243 | const field_ty: Type = field_ty: { | |
| 244 | block.comptime_reason = .{ .reason = .{ | |
| 245 | .src = field_ty_src, | |
| 246 | .r = .{ .simple = .struct_field_types }, | |
| 247 | } }; | |
| 248 | const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); | |
| 249 | break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref); | |
| 250 | }; | |
| 251 | struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); | |
| 252 | } | |
| 253 | ||
| 254 | if (struct_obj.field_aligns.len == 0) { | |
| 255 | assert(zir_field.align_body == null); | |
| 256 | } else { | |
| 257 | const field_align_src = block.src(.{ .container_field_align = zir_field.idx }); | |
| 258 | const field_align: Alignment = a: { | |
| 259 | block.comptime_reason = .{ .reason = .{ | |
| 260 | .src = field_align_src, | |
| 261 | .r = .{ .simple = .struct_field_attrs }, | |
| 262 | } }; | |
| 263 | const align_body = zir_field.align_body orelse break :a .none; | |
| 264 | const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); | |
| 265 | break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); | |
| 266 | }; | |
| 267 | struct_obj.field_aligns.get(ip)[zir_field.idx] = field_align; | |
| 268 | } | |
| 269 | } | |
| 270 | ||
| 271 | // We also resolve the default values of any `comptime` fields now. This is not necessary in | |
| 272 | // the case of a reified struct because the the default values were already poulated and | |
| 273 | // validated by `Sema.zirReifyStruct`. | |
| 274 | if (any_comptime_fields) { | |
| 275 | try resolveStructDefaultsInner(sema, &block, &struct_obj, .comptime_fields); | |
| 276 | } | |
| 277 | } | |
| 278 | ||
| 279 | if (struct_obj.layout == .@"packed") { | |
| 280 | return resolvePackedStructLayout(sema, &block, struct_ty, &struct_obj); | |
| 281 | } | |
| 282 | ||
| 283 | // Resolve the layout of all fields, and check their types are allowed. | |
| 284 | for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { | |
| 285 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 286 | assert(!field_ty.isGenericPoison()); | |
| 287 | const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); | |
| 288 | try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); | |
| 289 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 290 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 291 | const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); | |
| 292 | errdefer msg.destroy(gpa); | |
| 293 | try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); | |
| 294 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 295 | break :msg msg; | |
| 296 | }); | |
| 297 | } | |
| 298 | if (struct_obj.layout == .@"extern" and !field_ty.validateExtern(.struct_field, zcu)) { | |
| 299 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 300 | const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 301 | errdefer msg.destroy(gpa); | |
| 302 | try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .struct_field); | |
| 303 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 304 | break :msg msg; | |
| 305 | }); | |
| 306 | } | |
| 307 | } | |
| 308 | ||
| 309 | // Fields are okay. Now we need to resolve the struct's overall layout (size, field offsets, etc). | |
| 310 | ||
| 311 | var any_comptime_fields = false; | |
| 312 | var struct_align: Alignment = .@"1"; | |
| 313 | var has_no_possible_value = false; | |
| 314 | var has_runtime_state = false; | |
| 315 | var has_comptime_state = false; | |
| 316 | // Unlike `struct_obj.field_aligns`, these are not `.none`. | |
| 317 | const resolved_field_aligns = try sema.arena.alloc(Alignment, struct_obj.field_names.len); | |
| 318 | for (resolved_field_aligns, 0..) |*align_out, field_idx| { | |
| 319 | const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]); | |
| 320 | const field_align: Alignment = a: { | |
| 321 | if (struct_obj.field_aligns.len != 0) { | |
| 322 | const a = struct_obj.field_aligns.get(ip)[field_idx]; | |
| 323 | if (a != .none) break :a a; | |
| 324 | } | |
| 325 | break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); | |
| 326 | }; | |
| 327 | align_out.* = field_align; | |
| 328 | if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) { | |
| 329 | assert(struct_obj.layout == .auto); // comptime fields not allowed in extern or packed structs | |
| 330 | struct_obj.field_runtime_order.get(ip)[field_idx] = .omitted; // comptime fields are not in the runtime order | |
| 331 | any_comptime_fields = true; | |
| 332 | continue; // `comptime` fields do not contribute to the struct layout | |
| 333 | } | |
| 334 | struct_align = struct_align.maxStrict(field_align); | |
| 335 | if (struct_obj.layout == .auto) { | |
| 336 | struct_obj.field_runtime_order.get(ip)[field_idx] = @enumFromInt(field_idx); | |
| 337 | } | |
| 338 | switch (field_ty.classify(zcu)) { | |
| 339 | .one_possible_value => {}, | |
| 340 | .no_possible_value => has_no_possible_value = true, | |
| 341 | .runtime => has_runtime_state = true, | |
| 342 | .fully_comptime => has_comptime_state = true, | |
| 343 | .partially_comptime => { | |
| 344 | has_runtime_state = true; | |
| 345 | has_comptime_state = true; | |
| 346 | }, | |
| 347 | } | |
| 348 | } | |
| 349 | const class: Type.Class = class: { | |
| 350 | if (has_no_possible_value) break :class .no_possible_value; | |
| 351 | if (has_comptime_state) { | |
| 352 | break :class if (has_runtime_state) .partially_comptime else .fully_comptime; | |
| 353 | } else { | |
| 354 | break :class if (has_runtime_state) .runtime else .one_possible_value; | |
| 355 | } | |
| 356 | }; | |
| 357 | ||
| 358 | switch (struct_obj.layout) { | |
| 359 | .auto => {}, | |
| 360 | .@"extern" => assert(class != .no_possible_value), // field types are all extern, so are not NPV | |
| 361 | .@"packed" => unreachable, | |
| 362 | } | |
| 363 | ||
| 364 | if (struct_obj.layout == .auto) { | |
| 365 | const runtime_order = struct_obj.field_runtime_order.get(ip); | |
| 366 | // This logic does not reorder fields; it only moves the omitted ones to the end so that logic | |
| 367 | // elsewhere does not need to special-case. TODO: support field reordering in all the backends! | |
| 368 | if (!zcu.backendSupportsFeature(.field_reordering)) { | |
| 369 | var i: usize = 0; | |
| 370 | var off: usize = 0; | |
| 371 | while (i + off < runtime_order.len) { | |
| 372 | if (runtime_order[i + off] == .omitted) { | |
| 373 | off += 1; | |
| 374 | } else { | |
| 375 | runtime_order[i] = runtime_order[i + off]; | |
| 376 | i += 1; | |
| 377 | } | |
| 378 | } | |
| 379 | } else { | |
| 380 | // Sort by descending alignment to minimize padding. | |
| 381 | const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder; | |
| 382 | const AlignSortCtx = struct { | |
| 383 | aligns: []const Alignment, | |
| 384 | fn lessThan(ctx: @This(), a: RuntimeOrder, b: RuntimeOrder) bool { | |
| 385 | assert(a != .unresolved); | |
| 386 | assert(b != .unresolved); | |
| 387 | if (a == .omitted) return false; | |
| 388 | if (b == .omitted) return true; | |
| 389 | const a_align = ctx.aligns[@intFromEnum(a)]; | |
| 390 | const b_align = ctx.aligns[@intFromEnum(b)]; | |
| 391 | return a_align.compare(.gt, b_align); | |
| 392 | } | |
| 393 | }; | |
| 394 | mem.sortUnstable( | |
| 395 | RuntimeOrder, | |
| 396 | runtime_order, | |
| 397 | @as(AlignSortCtx, .{ .aligns = resolved_field_aligns }), | |
| 398 | AlignSortCtx.lessThan, | |
| 399 | ); | |
| 400 | } | |
| 401 | } | |
| 402 | ||
| 403 | var runtime_order_it = struct_obj.iterateRuntimeOrder(ip); | |
| 404 | var cur_offset: u64 = 0; | |
| 405 | while (runtime_order_it.next()) |field_idx| { | |
| 406 | const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]); | |
| 407 | const offset = resolved_field_aligns[field_idx].forward(cur_offset); | |
| 408 | struct_obj.field_offsets.get(ip)[field_idx] = @truncate(offset); // truncate because the overflow is handled below | |
| 409 | cur_offset = offset + field_ty.abiSize(zcu); | |
| 410 | } | |
| 411 | const struct_size: u32 = switch (class) { | |
| 412 | .no_possible_value => 0, | |
| 413 | else => std.math.cast(u32, struct_align.forward(cur_offset)) orelse return sema.fail( | |
| 414 | &block, | |
| 415 | struct_ty.srcLoc(zcu), | |
| 416 | "struct layout requires size {d}, this compiler implementation supports up to {d}", | |
| 417 | .{ struct_align.forward(cur_offset), std.math.maxInt(u32) }, | |
| 418 | ), | |
| 419 | }; | |
| 420 | ip.resolveStructLayout( | |
| 421 | io, | |
| 422 | struct_ty.toIntern(), | |
| 423 | struct_size, | |
| 424 | struct_align, | |
| 425 | class, | |
| 426 | ); | |
| 427 | } | |
| 428 | ||
| 429 | /// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type. | |
| 430 | /// This function *does* register the `src_hash` dependency on the struct. | |
| 431 | fn resolvePackedStructLayout( | |
| 432 | sema: *Sema, | |
| 433 | block: *Block, | |
| 434 | struct_ty: Type, | |
| 435 | struct_obj: *const InternPool.LoadedStructType, | |
| 436 | ) CompileError!void { | |
| 437 | const pt = sema.pt; | |
| 438 | const zcu = pt.zcu; | |
| 439 | const comp = zcu.comp; | |
| 440 | const io = comp.io; | |
| 441 | const gpa = comp.gpa; | |
| 442 | const ip = &zcu.intern_pool; | |
| 443 | ||
| 444 | // Resolve the layout of all fields, and check their types are allowed. | |
| 445 | // Also count the number of bits while we're at it. | |
| 446 | var field_bits: u64 = 0; | |
| 447 | for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { | |
| 448 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 449 | assert(!field_ty.isGenericPoison()); | |
| 450 | const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); | |
| 451 | try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); | |
| 452 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 453 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 454 | const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); | |
| 455 | errdefer msg.destroy(gpa); | |
| 456 | try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); | |
| 457 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 458 | break :msg msg; | |
| 459 | }); | |
| 460 | } | |
| 461 | if (field_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: { | |
| 462 | const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 463 | errdefer msg.destroy(gpa); | |
| 464 | try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason); | |
| 465 | break :msg msg; | |
| 466 | }); | |
| 467 | switch (field_ty.classify(zcu)) { | |
| 468 | .one_possible_value, .runtime => {}, | |
| 469 | .no_possible_value => unreachable, // packable types are not NPV | |
| 470 | .partially_comptime => unreachable, // packable types are not comptime-only | |
| 471 | .fully_comptime => unreachable, // packable types are not comptime-only | |
| 472 | } | |
| 473 | field_bits += field_ty.bitSize(zcu); | |
| 474 | } | |
| 475 | ||
| 476 | const explicit_backing_int_ty: ?Type = if (struct_obj.is_reified) ty: { | |
| 477 | break :ty switch (struct_obj.packed_backing_mode) { | |
| 478 | .explicit => .fromInterned(struct_obj.packed_backing_int_type), | |
| 479 | .auto => null, | |
| 480 | }; | |
| 481 | } else ty: { | |
| 482 | const zir_index = struct_obj.zir_index.resolve(ip).?; | |
| 483 | const zir_struct = sema.code.getStructDecl(zir_index); | |
| 484 | const backing_int_type_body = zir_struct.backing_int_type_body orelse { | |
| 485 | break :ty null; // inferred backing type | |
| 486 | }; | |
| 487 | // Explicitly specified, so evaluate the backing int type expression. | |
| 488 | const backing_int_type_src = block.src(.container_arg); | |
| 489 | block.comptime_reason = .{ .reason = .{ | |
| 490 | .src = backing_int_type_src, | |
| 491 | .r = .{ .simple = .packed_struct_backing_int_type }, | |
| 492 | } }; | |
| 493 | const type_ref = try sema.resolveInlineBody(block, backing_int_type_body, zir_index); | |
| 494 | break :ty try sema.analyzeAsType(block, backing_int_type_src, .packed_struct_backing_int_type, type_ref); | |
| 495 | }; | |
| 496 | ||
| 497 | // Finally, either validate or infer the backing int type. | |
| 498 | const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: { | |
| 499 | if (backing_ty.zigTypeTag(zcu) != .int) return sema.fail( | |
| 500 | block, | |
| 501 | block.src(.container_arg), | |
| 502 | "expected backing integer type, found '{f}'", | |
| 503 | .{backing_ty.fmt(pt)}, | |
| 504 | ); | |
| 505 | if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 506 | const src = struct_ty.srcLoc(zcu); | |
| 507 | const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{}); | |
| 508 | errdefer msg.destroy(gpa); | |
| 509 | try sema.errNote( | |
| 510 | block.src(.container_arg), | |
| 511 | msg, | |
| 512 | "backing integer '{f}' has bit width '{d}'", | |
| 513 | .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }, | |
| 514 | ); | |
| 515 | try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); | |
| 516 | break :msg msg; | |
| 517 | }); | |
| 518 | break :ty backing_ty; | |
| 519 | } else ty: { | |
| 520 | // We need to generate the inferred tag. | |
| 521 | const backing_int_bits = std.math.cast(u16, field_bits) orelse return sema.fail( | |
| 522 | block, | |
| 523 | struct_ty.srcLoc(zcu), | |
| 524 | "packed struct bit width '{d}' exceeds maximum bit width of 65535", | |
| 525 | .{field_bits}, | |
| 526 | ); | |
| 527 | break :ty try pt.intType(.unsigned, backing_int_bits); | |
| 528 | }; | |
| 529 | ip.resolvePackedStructLayout( | |
| 530 | io, | |
| 531 | struct_ty.toIntern(), | |
| 532 | backing_int_ty.toIntern(), | |
| 533 | ); | |
| 534 | } | |
| 535 | ||
| 536 | /// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type. | |
| 537 | /// | |
| 538 | /// Also asserts that the layout of `struct_ty` has *already* been resolved (though it is okay for | |
| 539 | /// that resolution to have failed). This requirement exists to ensure better error messages in the | |
| 540 | /// event of a dependency loop. | |
| 541 | /// | |
| 542 | /// This function *does* register the `src_hash` dependency on the struct. | |
| 543 | pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { | |
| 544 | const pt = sema.pt; | |
| 545 | const zcu = pt.zcu; | |
| 546 | const comp = zcu.comp; | |
| 547 | const gpa = comp.gpa; | |
| 548 | const ip = &zcu.intern_pool; | |
| 549 | ||
| 550 | assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); | |
| 551 | ||
| 552 | // We always depend on the layout of `struct_ty`. However, we don't actually need to resolve it | |
| 553 | // now, because the caller has done so for us. Just mark the dependency so that the incremental | |
| 554 | // compilation handling understands the dependency graph. | |
| 555 | try sema.declareDependency(.{ .type_layout = struct_ty.toIntern() }); | |
| 556 | struct_ty.assertHasLayout(zcu); | |
| 557 | const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() }); | |
| 558 | if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) { | |
| 559 | return error.AnalysisFail; | |
| 560 | } | |
| 561 | ||
| 562 | const struct_obj = ip.loadStructType(struct_ty.toIntern()); | |
| 563 | assert(struct_obj.want_layout); | |
| 564 | ||
| 565 | if (struct_obj.is_reified) { | |
| 566 | // `Sema.zirReifyStruct` has already populated the default field values *and* (by loading | |
| 567 | // the default values from pointers) validated their types, so we have nothing to do. | |
| 568 | return; | |
| 569 | } | |
| 570 | ||
| 571 | try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); | |
| 572 | ||
| 573 | if (struct_obj.field_defaults.len == 0) { | |
| 574 | // The struct has no default field values, so the slice has been omitted. | |
| 575 | return; | |
| 576 | } | |
| 577 | ||
| 578 | var block: Block = .{ | |
| 579 | .parent = null, | |
| 580 | .sema = sema, | |
| 581 | .namespace = struct_obj.namespace, | |
| 582 | .instructions = .empty, | |
| 583 | .inlining = null, | |
| 584 | .comptime_reason = undefined, // always set before using `block` | |
| 585 | .src_base_inst = struct_obj.zir_index, | |
| 586 | .type_name_ctx = struct_obj.name, | |
| 587 | }; | |
| 588 | defer block.instructions.deinit(gpa); | |
| 589 | ||
| 590 | return resolveStructDefaultsInner(sema, &block, &struct_obj, .normal_fields); | |
| 591 | } | |
| 592 | ||
| 593 | /// Asserts that the struct is not reified, and that `struct_obj.field_defaults.len` is non-zero. | |
| 594 | fn resolveStructDefaultsInner( | |
| 595 | sema: *Sema, | |
| 596 | block: *Block, | |
| 597 | struct_obj: *const InternPool.LoadedStructType, | |
| 598 | mode: enum { comptime_fields, normal_fields }, | |
| 599 | ) CompileError!void { | |
| 600 | const pt = sema.pt; | |
| 601 | const zcu = pt.zcu; | |
| 602 | const comp = zcu.comp; | |
| 603 | const gpa = comp.gpa; | |
| 604 | const ip = &zcu.intern_pool; | |
| 605 | ||
| 606 | assert(struct_obj.field_defaults.len > 0); | |
| 607 | ||
| 608 | // We'll need to map the struct decl instruction to provide result types | |
| 609 | const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 610 | try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); | |
| 611 | ||
| 612 | const field_types = struct_obj.field_types.get(ip); | |
| 613 | ||
| 614 | const zir_struct = sema.code.getStructDecl(zir_index); | |
| 615 | var field_it = zir_struct.iterateFields(); | |
| 616 | while (field_it.next()) |zir_field| { | |
| 617 | switch (mode) { | |
| 618 | .comptime_fields => if (!zir_field.is_comptime) continue, | |
| 619 | .normal_fields => if (zir_field.is_comptime) continue, | |
| 620 | } | |
| 621 | ||
| 622 | const default_val_src = block.src(.{ .container_field_value = zir_field.idx }); | |
| 623 | block.comptime_reason = .{ .reason = .{ | |
| 624 | .src = default_val_src, | |
| 625 | .r = .{ .simple = .struct_field_default_value }, | |
| 626 | } }; | |
| 627 | const default_body = zir_field.default_body orelse { | |
| 628 | struct_obj.field_defaults.get(ip)[zir_field.idx] = .none; | |
| 629 | continue; | |
| 630 | }; | |
| 631 | const field_ty: Type = .fromInterned(field_types[zir_field.idx]); | |
| 632 | const uncoerced = ref: { | |
| 633 | // Provide the result type | |
| 634 | sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern())); | |
| 635 | defer assert(sema.inst_map.remove(zir_index)); | |
| 636 | break :ref try sema.resolveInlineBody(block, default_body, zir_index); | |
| 637 | }; | |
| 638 | const coerced = try sema.coerce(block, field_ty, uncoerced, default_val_src); | |
| 639 | const default_val = try sema.resolveConstValue(block, default_val_src, coerced, null); | |
| 640 | if (default_val.canMutateComptimeVarState(zcu)) { | |
| 641 | const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; | |
| 642 | return sema.failWithContainsReferenceToComptimeVar(block, default_val_src, field_name, "field default value", default_val); | |
| 643 | } | |
| 644 | struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern(); | |
| 645 | } | |
| 646 | } | |
| 647 | ||
| 648 | /// This logic must be kept in sync with `Type.getUnionLayout`. | |
| 649 | pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { | |
| 650 | const pt = sema.pt; | |
| 651 | const zcu = pt.zcu; | |
| 652 | const comp = zcu.comp; | |
| 653 | const io = comp.io; | |
| 654 | const gpa = comp.gpa; | |
| 655 | const ip = &zcu.intern_pool; | |
| 656 | ||
| 657 | assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); | |
| 658 | ||
| 659 | const union_obj = ip.loadUnionType(union_ty.toIntern()); | |
| 660 | assert(union_obj.want_layout); | |
| 661 | const zir_index = union_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; | |
| 662 | ||
| 663 | var block: Block = .{ | |
| 664 | .parent = null, | |
| 665 | .sema = sema, | |
| 666 | .namespace = union_obj.namespace, | |
| 667 | .instructions = .empty, | |
| 668 | .inlining = null, | |
| 669 | .comptime_reason = undefined, // always set before using `block` | |
| 670 | .src_base_inst = union_obj.zir_index, | |
| 671 | .type_name_ctx = union_obj.name, | |
| 672 | }; | |
| 673 | defer block.instructions.deinit(gpa); | |
| 674 | ||
| 675 | const enum_tag_ty: Type = switch (union_obj.enum_tag_mode) { | |
| 676 | .explicit => validated_tag_ty: { | |
| 677 | // If the union is reified, its enum tag type is already populated. If the union is | |
| 678 | // declared, we need to evaluate the enum tag type expression (the `E` in `union(E)`). | |
| 679 | const tag_ty: Type = switch (union_obj.is_reified) { | |
| 680 | true => .fromInterned(union_obj.enum_tag_type), | |
| 681 | false => tag_ty: { | |
| 682 | const zir_union = sema.code.getUnionDecl(zir_index); | |
| 683 | assert(zir_union.kind == .tagged_explicit); // `Zcu.mapOldZirToNew` guarantees that the ZIR mapping preserves `kind` | |
| 684 | const tag_type_body = zir_union.arg_type_body.?; | |
| 685 | const tag_type_src = block.src(.container_arg); | |
| 686 | block.comptime_reason = .{ .reason = .{ | |
| 687 | .src = tag_type_src, | |
| 688 | .r = .{ .simple = .union_enum_tag_type }, | |
| 689 | } }; | |
| 690 | const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); | |
| 691 | break :tag_ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref); | |
| 692 | }, | |
| 693 | }; | |
| 694 | // Because the type is explicitly specified, we need to validate it. | |
| 695 | if (tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail( | |
| 696 | &block, | |
| 697 | block.src(.container_arg), | |
| 698 | "expected enum tag type, found '{f}'", | |
| 699 | .{tag_ty.fmt(pt)}, | |
| 700 | ); | |
| 701 | break :validated_tag_ty tag_ty; | |
| 702 | }, | |
| 703 | // If no tag type was specified, we generate one keyed on this union type. | |
| 704 | .auto => switch (try ip.getGeneratedEnumTagType(gpa, io, pt.tid, .{ | |
| 705 | .union_type = union_ty.toIntern(), | |
| 706 | // The int tag for this enum is usually inferred---the exception is `union(enum(T))`. | |
| 707 | .int_tag_mode = switch (union_obj.is_reified) { | |
| 708 | true => .auto, | |
| 709 | false => switch (sema.code.getUnionDecl(zir_index).kind) { | |
| 710 | .tagged_enum_explicit => .explicit, | |
| 711 | else => .auto, | |
| 712 | }, | |
| 713 | }, | |
| 714 | .fields_len = @intCast(union_obj.field_types.len), | |
| 715 | })) { | |
| 716 | .existing => |tag_ty| .fromInterned(tag_ty), | |
| 717 | .wip => |wip| tag_ty: { | |
| 718 | errdefer wip.cancel(ip, pt.tid); | |
| 719 | _ = wip.setName(ip, try ip.getOrPutStringFmt( | |
| 720 | gpa, | |
| 721 | io, | |
| 722 | pt.tid, | |
| 723 | "@typeInfo({f}).@\"union\".tag_type.?", | |
| 724 | .{union_obj.name.fmt(ip)}, | |
| 725 | .no_embedded_nulls, | |
| 726 | ), .none); | |
| 727 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 728 | .parent = union_obj.namespace.toOptional(), | |
| 729 | .owner_type = wip.index, | |
| 730 | .file_scope = zcu.namespacePtr(union_obj.namespace).file_scope, | |
| 731 | .generation = zcu.generation, | |
| 732 | }); | |
| 733 | if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 734 | break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index)); | |
| 735 | }, | |
| 736 | }, | |
| 737 | }; | |
| 738 | ||
| 739 | try sema.ensureLayoutResolved(enum_tag_ty, block.src(.container_arg), .backing_enum); | |
| 740 | const enum_obj = ip.loadEnumType(enum_tag_ty.toIntern()); | |
| 741 | ||
| 742 | if (union_obj.is_reified) { | |
| 743 | // We have field names in `union_obj.reified_field_names`, but we haven't | |
| 744 | // checked them against the backing type yet. | |
| 745 | const union_field_names = union_obj.reified_field_names.get(ip); | |
| 746 | match_fields: { | |
| 747 | // We can efficiently *check* if the fields match... | |
| 748 | if (union_field_names.len == enum_obj.field_names.len) { | |
| 749 | for (union_field_names, enum_obj.field_names.get(ip)) |union_field_name, enum_field_name| { | |
| 750 | if (!std.mem.eql(u8, union_field_name.toSlice(ip), enum_field_name.toSlice(ip))) break; | |
| 751 | } else { | |
| 752 | break :match_fields; | |
| 753 | } | |
| 754 | } | |
| 755 | // ...but if they don't, reporting a nice error is a little more involved. If some field | |
| 756 | // is present in the enum but not the union, or vice versa, we will report that instead | |
| 757 | // of a generic "field order mismatch" error. Of course, this error is impossible for a | |
| 758 | // generated tag type, because we populated that from the union ZIR! | |
| 759 | assert(enum_obj.owner_union != union_ty.toIntern()); | |
| 760 | return failUnionFieldMismatch(sema, &block, union_field_names, enum_tag_ty, &enum_obj); | |
| 761 | } | |
| 762 | } else { | |
| 763 | // Declared unions do not have field types or aligns populated yet. | |
| 764 | // We also need to check the field names match the backing enum. | |
| 765 | try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); | |
| 766 | const zir_union = sema.code.getUnionDecl(zir_index); | |
| 767 | ||
| 768 | // We'll first check the field names against the backing enum, and only analyze the types | |
| 769 | // once we know the fields match one-to-one. | |
| 770 | match_fields: { | |
| 771 | // We can efficiently *check* if the fields match... | |
| 772 | if (zir_union.field_names.len == enum_obj.field_names.len) { | |
| 773 | for (zir_union.field_names, enum_obj.field_names.get(ip)) |union_field_name_zir, enum_field_name| { | |
| 774 | const union_field_name_slice = sema.code.nullTerminatedString(union_field_name_zir); | |
| 775 | if (!std.mem.eql(u8, union_field_name_slice, enum_field_name.toSlice(ip))) break; | |
| 776 | } else { | |
| 777 | break :match_fields; | |
| 778 | } | |
| 779 | } | |
| 780 | // ...but if they don't, reporting a nice error is a little more involved. If some field | |
| 781 | // is present in the enum but not the union, or vice versa, we will report that instead | |
| 782 | // of a generic "field order mismatch" error. Of course, this error is impossible for a | |
| 783 | // generated tag type, because we populated that from the union ZIR! | |
| 784 | assert(enum_obj.owner_union != union_ty.toIntern()); | |
| 785 | const union_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, zir_union.field_names.len); | |
| 786 | for (zir_union.field_names, union_field_names) |name_zir, *name| { | |
| 787 | name.* = try ip.getOrPutString(gpa, io, pt.tid, sema.code.nullTerminatedString(name_zir), .no_embedded_nulls); | |
| 788 | } | |
| 789 | return failUnionFieldMismatch(sema, &block, union_field_names, enum_tag_ty, &enum_obj); | |
| 790 | } | |
| 791 | ||
| 792 | // Field names okay; populate types and aligns. | |
| 793 | var field_it = zir_union.iterateFields(); | |
| 794 | while (field_it.next()) |zir_field| { | |
| 795 | const field_ty_src = block.src(.{ .container_field_type = zir_field.idx }); | |
| 796 | const field_ty: Type = field_ty: { | |
| 797 | block.comptime_reason = .{ .reason = .{ | |
| 798 | .src = field_ty_src, | |
| 799 | .r = .{ .simple = .union_field_types }, | |
| 800 | } }; | |
| 801 | const type_body = zir_field.type_body orelse break :field_ty .void; | |
| 802 | const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index); | |
| 803 | break :field_ty try sema.analyzeAsType(&block, field_ty_src, .union_field_types, type_ref); | |
| 804 | }; | |
| 805 | union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); | |
| 806 | ||
| 807 | const field_align_src = block.src(.{ .container_field_align = zir_field.idx }); | |
| 808 | const explicit_field_align: Alignment = a: { | |
| 809 | block.comptime_reason = .{ .reason = .{ | |
| 810 | .src = field_align_src, | |
| 811 | .r = .{ .simple = .union_field_attrs }, | |
| 812 | } }; | |
| 813 | const align_body = zir_field.align_body orelse break :a .none; | |
| 814 | const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); | |
| 815 | break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); | |
| 816 | }; | |
| 817 | if (union_obj.field_aligns.len != 0) { | |
| 818 | union_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align; | |
| 819 | } else { | |
| 820 | assert(explicit_field_align == .none); | |
| 821 | } | |
| 822 | } | |
| 823 | } | |
| 824 | ||
| 825 | if (union_obj.layout == .@"packed") { | |
| 826 | return resolvePackedUnionLayout(sema, &block, union_ty, &union_obj, enum_tag_ty); | |
| 827 | } | |
| 828 | ||
| 829 | // Resolve the layout of all fields, and check their types are allowed. | |
| 830 | for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { | |
| 831 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 832 | assert(!field_ty.isGenericPoison()); | |
| 833 | const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); | |
| 834 | try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); | |
| 835 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 836 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 837 | const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); | |
| 838 | errdefer msg.destroy(gpa); | |
| 839 | try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); | |
| 840 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 841 | break :msg msg; | |
| 842 | }); | |
| 843 | } | |
| 844 | if (union_obj.layout == .@"extern" and !field_ty.validateExtern(.union_field, zcu)) { | |
| 845 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 846 | const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 847 | errdefer msg.destroy(gpa); | |
| 848 | try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .union_field); | |
| 849 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 850 | break :msg msg; | |
| 851 | }); | |
| 852 | } | |
| 853 | } | |
| 854 | ||
| 855 | // Fields are okay. Now we need to resolve the union's overall layout (size, alignment, etc). | |
| 856 | var payload_align: Alignment = .@"1"; | |
| 857 | var payload_size: u64 = 0; | |
| 858 | var possible_tags: u32 = 0; | |
| 859 | var payload_has_comptime_state = false; | |
| 860 | for (0..union_obj.field_types.len) |field_idx| { | |
| 861 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 862 | const field_align: Alignment = a: { | |
| 863 | if (union_obj.field_aligns.len != 0) { | |
| 864 | const a = union_obj.field_aligns.get(ip)[field_idx]; | |
| 865 | if (a != .none) break :a a; | |
| 866 | } | |
| 867 | break :a field_ty.abiAlignment(zcu); | |
| 868 | }; | |
| 869 | payload_align = payload_align.maxStrict(field_align); | |
| 870 | payload_size = @max(payload_size, field_ty.abiSize(zcu)); | |
| 871 | ||
| 872 | switch (field_ty.classify(zcu)) { | |
| 873 | .no_possible_value => {}, // uninstantiable field has no effect | |
| 874 | .one_possible_value, .runtime => { | |
| 875 | possible_tags += 1; | |
| 876 | }, | |
| 877 | .partially_comptime, .fully_comptime => { | |
| 878 | possible_tags += 1; | |
| 879 | payload_has_comptime_state = true; | |
| 880 | }, | |
| 881 | } | |
| 882 | } | |
| 883 | ||
| 884 | // Uninstantiable `extern union`s don't make sense; disallow them. | |
| 885 | if (possible_tags == 0 and union_obj.layout != .auto) { | |
| 886 | // Field types are all extern, so not NPV; thus zero possible tags means no tags at all. | |
| 887 | assert(union_obj.field_types.len == 0); | |
| 888 | return sema.fail(&block, union_ty.srcLoc(zcu), "extern union has no fields", .{}); | |
| 889 | } | |
| 890 | ||
| 891 | // We only need a runtime tag if there are multiple possible active fields *and* the union is | |
| 892 | // not going to be comptime-only. Even if there are still runtime bits in the payload, the tag | |
| 893 | // does not require runtime bits in a comptime-only union, because it is impossible to get a | |
| 894 | // pointer to a union's tag. | |
| 895 | const has_runtime_tag = switch (possible_tags) { | |
| 896 | 0, 1 => false, | |
| 897 | else => union_obj.tag_usage != .none and !payload_has_comptime_state, | |
| 898 | }; | |
| 899 | ||
| 900 | const class: Type.Class = class: { | |
| 901 | if (possible_tags == 0) { | |
| 902 | break :class .no_possible_value; | |
| 903 | } | |
| 904 | if (payload_has_comptime_state) { | |
| 905 | break :class if (payload_size > 0) .partially_comptime else .fully_comptime; | |
| 906 | } | |
| 907 | const have_runtime_bits = has_runtime_tag or payload_size > 0; | |
| 908 | break :class if (have_runtime_bits) .runtime else .one_possible_value; | |
| 909 | }; | |
| 910 | ||
| 911 | const size: u64, const padding: u64, const alignment: Alignment = layout: { | |
| 912 | if (!has_runtime_tag) { | |
| 913 | break :layout .{ payload_align.forward(payload_size), 0, payload_align }; | |
| 914 | } | |
| 915 | const tag_align = enum_tag_ty.abiAlignment(zcu); | |
| 916 | const tag_size = enum_tag_ty.abiSize(zcu); | |
| 917 | // The layout will either be (tag, payload, padding) or (payload, tag, padding) depending on | |
| 918 | // which has larger alignment. So the overall size is just the tag and payload sizes, added, | |
| 919 | // and padded to the larger alignment. | |
| 920 | const alignment = tag_align.maxStrict(payload_align); | |
| 921 | const unpadded_size = tag_size + payload_size; | |
| 922 | const size = alignment.forward(unpadded_size); | |
| 923 | break :layout .{ size, size - unpadded_size, alignment }; | |
| 924 | }; | |
| 925 | ||
| 926 | if (class == .no_possible_value or class == .one_possible_value) { | |
| 927 | assert(size == 0); | |
| 928 | assert(padding == 0); | |
| 929 | } | |
| 930 | ||
| 931 | const casted_size = std.math.cast(u32, size) orelse return sema.fail( | |
| 932 | &block, | |
| 933 | union_ty.srcLoc(zcu), | |
| 934 | "union layout requires size {d}, this compiler implementation supports up to {d}", | |
| 935 | .{ size, std.math.maxInt(u32) }, | |
| 936 | ); | |
| 937 | ip.resolveUnionLayout( | |
| 938 | io, | |
| 939 | union_ty.toIntern(), | |
| 940 | enum_tag_ty.toIntern(), | |
| 941 | class, | |
| 942 | has_runtime_tag, | |
| 943 | casted_size, | |
| 944 | @intCast(padding), // okay because padding is no greater than size | |
| 945 | alignment, | |
| 946 | ); | |
| 947 | } | |
| 948 | fn failUnionFieldMismatch(sema: *Sema, block: *Block, union_field_names: []const InternPool.NullTerminatedString, enum_tag_ty: Type, enum_obj: *const InternPool.LoadedEnumType) CompileError { | |
| 949 | const pt = sema.pt; | |
| 950 | const zcu = pt.zcu; | |
| 951 | const comp = zcu.comp; | |
| 952 | const gpa = comp.gpa; | |
| 953 | const ip = &zcu.intern_pool; | |
| 954 | const enum_to_union_map = try sema.arena.alloc(?u32, enum_obj.field_names.len); | |
| 955 | @memset(enum_to_union_map, null); | |
| 956 | for (union_field_names, 0..) |field_name, union_field_index| { | |
| 957 | if (enum_obj.nameIndex(ip, field_name)) |enum_field_index| { | |
| 958 | enum_to_union_map[enum_field_index] = @intCast(union_field_index); | |
| 959 | continue; | |
| 960 | } | |
| 961 | const union_field_src = block.src(.{ .container_field_name = @intCast(union_field_index) }); | |
| 962 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 963 | const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name.fmt(ip), enum_tag_ty.fmt(pt) }); | |
| 964 | errdefer msg.destroy(gpa); | |
| 965 | try sema.addDeclaredHereNote(msg, enum_tag_ty); | |
| 966 | break :msg msg; | |
| 967 | }); | |
| 968 | } | |
| 969 | for (enum_to_union_map, 0..) |union_field_index, enum_field_index| { | |
| 970 | if (union_field_index != null) continue; | |
| 971 | const field_name_ip = enum_obj.field_names.get(ip)[enum_field_index]; | |
| 972 | const enum_field_src: LazySrcLoc = .{ | |
| 973 | .base_node_inst = enum_tag_ty.typeDeclInstAllowGeneratedTag(zcu).?, | |
| 974 | .offset = .{ .container_field_name = @intCast(enum_field_index) }, | |
| 975 | }; | |
| 976 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 977 | const msg = try sema.errMsg(block.nodeOffset(.zero), "enum field '{f}' missing from union", .{field_name_ip.fmt(ip)}); | |
| 978 | errdefer msg.destroy(gpa); | |
| 979 | try sema.errNote(enum_field_src, msg, "enum field here", .{}); | |
| 980 | break :msg msg; | |
| 981 | }); | |
| 982 | } | |
| 983 | // The only problem is the field ordering. | |
| 984 | for (enum_to_union_map, 0..) |union_field_index, enum_field_index| { | |
| 985 | if (union_field_index.? == enum_field_index) continue; | |
| 986 | const field_name = enum_obj.field_names.get(ip)[enum_field_index]; | |
| 987 | const union_field_src = block.src(.{ .container_field_name = union_field_index.? }); | |
| 988 | const enum_field_src: LazySrcLoc = .{ | |
| 989 | .base_node_inst = enum_tag_ty.typeDeclInstAllowGeneratedTag(zcu).?, | |
| 990 | .offset = .{ .container_field_name = @intCast(enum_field_index) }, | |
| 991 | }; | |
| 992 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 993 | const msg = try sema.errMsg(block.nodeOffset(.zero), "union field order does not match tag enum field order", .{}); | |
| 994 | errdefer msg.destroy(gpa); | |
| 995 | try sema.errNote(union_field_src, msg, "union field '{f}' is index {d}", .{ field_name.fmt(ip), union_field_index.? }); | |
| 996 | try sema.errNote(enum_field_src, msg, "enum field '{f}' is index {d}", .{ field_name.fmt(ip), enum_field_index }); | |
| 997 | break :msg msg; | |
| 998 | }); | |
| 999 | } | |
| 1000 | unreachable; // we already determined that *something* is wrong | |
| 1001 | } | |
| 1002 | fn resolvePackedUnionLayout( | |
| 1003 | sema: *Sema, | |
| 1004 | block: *Block, | |
| 1005 | union_ty: Type, | |
| 1006 | union_obj: *const InternPool.LoadedUnionType, | |
| 1007 | enum_tag_ty: Type, | |
| 1008 | ) CompileError!void { | |
| 1009 | const pt = sema.pt; | |
| 1010 | const zcu = pt.zcu; | |
| 1011 | const comp = zcu.comp; | |
| 1012 | const io = comp.io; | |
| 1013 | const gpa = comp.gpa; | |
| 1014 | const ip = &zcu.intern_pool; | |
| 1015 | ||
| 1016 | // Uninstantiable `packed union`s don't make sense; disallow them. | |
| 1017 | if (union_obj.field_types.len == 0) { | |
| 1018 | return sema.fail(block, union_ty.srcLoc(zcu), "packed union has no fields", .{}); | |
| 1019 | } | |
| 1020 | ||
| 1021 | // Resolve the layout of all fields, and check their types are allowed. | |
| 1022 | for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { | |
| 1023 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 1024 | assert(!field_ty.isGenericPoison()); | |
| 1025 | const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); | |
| 1026 | try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); | |
| 1027 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { | |
| 1028 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 1029 | const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); | |
| 1030 | errdefer msg.destroy(gpa); | |
| 1031 | try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); | |
| 1032 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 1033 | break :msg msg; | |
| 1034 | }); | |
| 1035 | } | |
| 1036 | if (field_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: { | |
| 1037 | const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); | |
| 1038 | errdefer msg.destroy(gpa); | |
| 1039 | try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason); | |
| 1040 | break :msg msg; | |
| 1041 | }); | |
| 1042 | assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only | |
| 1043 | } | |
| 1044 | ||
| 1045 | const explicit_backing_int_ty: ?Type = if (union_obj.is_reified) ty: { | |
| 1046 | switch (union_obj.packed_backing_mode) { | |
| 1047 | .explicit => break :ty .fromInterned(union_obj.packed_backing_int_type), | |
| 1048 | .auto => break :ty null, | |
| 1049 | } | |
| 1050 | } else ty: { | |
| 1051 | const zir_index = union_obj.zir_index.resolve(ip).?; | |
| 1052 | const zir_union = sema.code.getUnionDecl(zir_index); | |
| 1053 | const backing_int_type_body = zir_union.arg_type_body orelse { | |
| 1054 | break :ty null; // inferred backing type | |
| 1055 | }; | |
| 1056 | // Explicitly specified, so evaluate the backing int type expression. | |
| 1057 | const backing_int_type_src = block.src(.container_arg); | |
| 1058 | block.comptime_reason = .{ .reason = .{ | |
| 1059 | .src = backing_int_type_src, | |
| 1060 | .r = .{ .simple = .packed_union_backing_int_type }, | |
| 1061 | } }; | |
| 1062 | const type_ref = try sema.resolveInlineBody(block, backing_int_type_body, zir_index); | |
| 1063 | break :ty try sema.analyzeAsType(block, backing_int_type_src, .packed_union_backing_int_type, type_ref); | |
| 1064 | }; | |
| 1065 | ||
| 1066 | // Finally, either validate or infer the backing int type. | |
| 1067 | const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: { | |
| 1068 | if (backing_ty.zigTypeTag(zcu) != .int) return sema.fail( | |
| 1069 | block, | |
| 1070 | block.src(.container_arg), | |
| 1071 | "expected backing integer type, found '{f}'", | |
| 1072 | .{backing_ty.fmt(pt)}, | |
| 1073 | ); | |
| 1074 | const backing_int_bits = backing_ty.intInfo(zcu).bits; | |
| 1075 | for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| { | |
| 1076 | const field_type: Type = .fromInterned(field_type_ip); | |
| 1077 | const field_bits = field_type.bitSize(zcu); | |
| 1078 | if (field_bits != backing_int_bits) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 1079 | const field_ty_src = block.src(.{ .container_field_type = @intCast(field_idx) }); | |
| 1080 | const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{}); | |
| 1081 | errdefer msg.destroy(gpa); | |
| 1082 | try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); | |
| 1083 | try sema.errNote( | |
| 1084 | block.src(.container_arg), | |
| 1085 | msg, | |
| 1086 | "backing integer '{f}' has bit width '{d}'", | |
| 1087 | .{ backing_ty.fmt(pt), backing_int_bits }, | |
| 1088 | ); | |
| 1089 | try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); | |
| 1090 | break :msg msg; | |
| 1091 | }); | |
| 1092 | } | |
| 1093 | break :ty backing_ty; | |
| 1094 | } else ty: { | |
| 1095 | const field_types = union_obj.field_types.get(ip); | |
| 1096 | const first_field_type: Type = .fromInterned(field_types[0]); | |
| 1097 | const first_field_bits = first_field_type.bitSize(zcu); | |
| 1098 | for (field_types[1..], 1..) |field_type_ip, field_idx| { | |
| 1099 | const field_type: Type = .fromInterned(field_type_ip); | |
| 1100 | const field_bits = field_type.bitSize(zcu); | |
| 1101 | if (field_bits != first_field_bits) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 1102 | const first_field_ty_src = block.src(.{ .container_field_type = 0 }); | |
| 1103 | const field_ty_src = block.src(.{ .container_field_type = @intCast(field_idx) }); | |
| 1104 | const msg = try sema.errMsg(field_ty_src, "field bit width does not match earlier field", .{}); | |
| 1105 | errdefer msg.destroy(gpa); | |
| 1106 | try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); | |
| 1107 | try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(pt), first_field_bits }); | |
| 1108 | try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); | |
| 1109 | break :msg msg; | |
| 1110 | }); | |
| 1111 | } | |
| 1112 | const backing_int_bits = std.math.cast(u16, first_field_bits) orelse return sema.fail( | |
| 1113 | block, | |
| 1114 | union_ty.srcLoc(zcu), | |
| 1115 | "packed union bit width '{d}' exceeds maximum bit width of 65535", | |
| 1116 | .{first_field_bits}, | |
| 1117 | ); | |
| 1118 | break :ty try pt.intType(.unsigned, backing_int_bits); | |
| 1119 | }; | |
| 1120 | ip.resolvePackedUnionLayout( | |
| 1121 | io, | |
| 1122 | union_ty.toIntern(), | |
| 1123 | enum_tag_ty.toIntern(), | |
| 1124 | backing_int_ty.toIntern(), | |
| 1125 | ); | |
| 1126 | } | |
| 1127 | ||
| 1128 | pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { | |
| 1129 | const pt = sema.pt; | |
| 1130 | const zcu = pt.zcu; | |
| 1131 | const comp = zcu.comp; | |
| 1132 | const io = comp.io; | |
| 1133 | const gpa = comp.gpa; | |
| 1134 | const ip = &zcu.intern_pool; | |
| 1135 | ||
| 1136 | assert(sema.owner.unwrap().type_layout == enum_ty.toIntern()); | |
| 1137 | ||
| 1138 | const enum_obj = ip.loadEnumType(enum_ty.toIntern()); | |
| 1139 | assert(enum_obj.want_layout); | |
| 1140 | ||
| 1141 | const maybe_parent_union_obj: ?InternPool.LoadedUnionType = un: { | |
| 1142 | if (enum_obj.owner_union == .none) break :un null; | |
| 1143 | break :un ip.loadUnionType(enum_obj.owner_union); | |
| 1144 | }; | |
| 1145 | ||
| 1146 | const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index; | |
| 1147 | const zir_index = tracked_inst.resolve(ip) orelse return error.AnalysisFail; | |
| 1148 | ||
| 1149 | var block: Block = .{ | |
| 1150 | .parent = null, | |
| 1151 | .sema = sema, | |
| 1152 | .namespace = enum_obj.namespace, | |
| 1153 | .instructions = .empty, | |
| 1154 | .inlining = null, | |
| 1155 | .comptime_reason = undefined, // always set before using `block` | |
| 1156 | .src_base_inst = tracked_inst, | |
| 1157 | .type_name_ctx = enum_obj.name, | |
| 1158 | }; | |
| 1159 | defer block.instructions.deinit(gpa); | |
| 1160 | ||
| 1161 | // There may be old field names in the map from a previous update. | |
| 1162 | enum_obj.field_name_map.get(ip).clearRetainingCapacity(); | |
| 1163 | ||
| 1164 | if (maybe_parent_union_obj) |*union_obj| { | |
| 1165 | if (union_obj.is_reified) { | |
| 1166 | // In the case of reification, the union stores the field names, just for us to copy. | |
| 1167 | @memcpy(enum_obj.field_names.get(ip), union_obj.reified_field_names.get(ip)); | |
| 1168 | // The list of field names is now populated, but we haven't checked for duplicates yet, | |
| 1169 | // nor have we populated the hash map. | |
| 1170 | for (0..enum_obj.field_names.len) |field_index| { | |
| 1171 | const name = enum_obj.field_names.get(ip)[field_index]; | |
| 1172 | if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| { | |
| 1173 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 1174 | const src = block.builtinCallArgSrc(.zero, 2); | |
| 1175 | const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); | |
| 1176 | errdefer msg.destroy(gpa); | |
| 1177 | try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); | |
| 1178 | break :msg msg; | |
| 1179 | }); | |
| 1180 | } | |
| 1181 | } | |
| 1182 | } else { | |
| 1183 | // Generated tag enums for declared unions do not yet have field names populated. It is | |
| 1184 | // our job to populate them now. | |
| 1185 | try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); | |
| 1186 | const zir_union = sema.code.getUnionDecl(zir_index); | |
| 1187 | for (zir_union.field_names) |zir_field_name| { | |
| 1188 | const name_slice = sema.code.nullTerminatedString(zir_field_name); | |
| 1189 | const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); | |
| 1190 | assert(ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name) == null); // AstGen validated this for us | |
| 1191 | } | |
| 1192 | } | |
| 1193 | } else { | |
| 1194 | if (enum_obj.is_reified) { | |
| 1195 | // The field names are populated, but we haven't checked for duplicates (nor populated the map) yet. | |
| 1196 | for (0..enum_obj.field_names.len) |field_index| { | |
| 1197 | const name = enum_obj.field_names.get(ip)[field_index]; | |
| 1198 | if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| { | |
| 1199 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 1200 | const src = block.builtinCallArgSrc(.zero, 2); | |
| 1201 | const msg = try sema.errMsg(src, "duplicate enum field '{f}' at index '{d}'", .{ name.fmt(ip), field_index }); | |
| 1202 | errdefer msg.destroy(gpa); | |
| 1203 | try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); | |
| 1204 | break :msg msg; | |
| 1205 | }); | |
| 1206 | } | |
| 1207 | } | |
| 1208 | } else { | |
| 1209 | // Declared enums do not yet have field names populated. It is our job to populate them now. | |
| 1210 | try sema.declareDependency(.{ .src_hash = enum_obj.zir_index.unwrap().? }); | |
| 1211 | const zir_enum = sema.code.getEnumDecl(zir_index); | |
| 1212 | for (zir_enum.field_names) |zir_field_name| { | |
| 1213 | const name_slice = sema.code.nullTerminatedString(zir_field_name); | |
| 1214 | const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); | |
| 1215 | assert(ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name) == null); // AstGen validated this for us | |
| 1216 | } | |
| 1217 | } | |
| 1218 | } | |
| 1219 | ||
| 1220 | // Field names populated; now deal with the backing integer type. If explicitly provided, | |
| 1221 | // validate it; otherwise, infer it. | |
| 1222 | ||
| 1223 | const explicit_int_tag_ty: ?Type = if (enum_obj.is_reified) ty: { | |
| 1224 | break :ty switch (enum_obj.int_tag_mode) { | |
| 1225 | .explicit => .fromInterned(enum_obj.int_tag_type), | |
| 1226 | .auto => null, | |
| 1227 | }; | |
| 1228 | } else if (maybe_parent_union_obj) |*union_obj| ty: { | |
| 1229 | if (union_obj.is_reified) { | |
| 1230 | // Reification has no equivalent of 'union(enum(T))'. | |
| 1231 | break :ty null; | |
| 1232 | } | |
| 1233 | const zir_union = sema.code.getUnionDecl(zir_index); | |
| 1234 | if (zir_union.kind != .tagged_enum_explicit) { | |
| 1235 | break :ty null; // int tag type will be inferred | |
| 1236 | } | |
| 1237 | // Explicitly specified, so evaluate the int tag type expression. | |
| 1238 | const tag_type_body = zir_union.arg_type_body.?; | |
| 1239 | const tag_type_src = block.src(.container_arg); | |
| 1240 | block.comptime_reason = .{ .reason = .{ | |
| 1241 | .src = tag_type_src, | |
| 1242 | .r = .{ .simple = .enum_int_tag_type }, | |
| 1243 | } }; | |
| 1244 | const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); | |
| 1245 | break :ty try sema.analyzeAsType(&block, tag_type_src, .enum_int_tag_type, type_ref); | |
| 1246 | } else ty: { | |
| 1247 | const zir_enum = sema.code.getEnumDecl(zir_index); | |
| 1248 | const tag_type_body = zir_enum.tag_type_body orelse { | |
| 1249 | break :ty null; // int tag type will be inferred | |
| 1250 | }; | |
| 1251 | // Explicitly specified, so evaluate the int tag type expression. | |
| 1252 | const tag_type_src = block.src(.container_arg); | |
| 1253 | block.comptime_reason = .{ .reason = .{ | |
| 1254 | .src = tag_type_src, | |
| 1255 | .r = .{ .simple = .enum_int_tag_type }, | |
| 1256 | } }; | |
| 1257 | const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); | |
| 1258 | break :ty try sema.analyzeAsType(&block, tag_type_src, .enum_int_tag_type, type_ref); | |
| 1259 | }; | |
| 1260 | const int_tag_ty: Type = if (explicit_int_tag_ty) |int_tag_ty| ty: { | |
| 1261 | if (int_tag_ty.zigTypeTag(zcu) != .int) return sema.fail( | |
| 1262 | &block, | |
| 1263 | block.src(.container_arg), | |
| 1264 | "expected integer tag type, found '{f}'", | |
| 1265 | .{int_tag_ty.fmt(pt)}, | |
| 1266 | ); | |
| 1267 | break :ty int_tag_ty; | |
| 1268 | } else ty: { | |
| 1269 | // Infer the int tag type from the field count | |
| 1270 | const bits = Type.smallestUnsignedBits(enum_obj.field_names.len -| 1); | |
| 1271 | break :ty try pt.intType(.unsigned, bits); | |
| 1272 | }; | |
| 1273 | ||
| 1274 | ip.resolveEnumLayout(io, enum_ty.toIntern(), int_tag_ty.toIntern()); | |
| 1275 | ||
| 1276 | // Finally, deal with field values. For declared types we need to analyze the expressions, while | |
| 1277 | // reified types already have them populated; but either way, we need to populate the hash map | |
| 1278 | // (and validate the values along the way). | |
| 1279 | ||
| 1280 | // We'll populate this map. | |
| 1281 | const field_value_map = enum_obj.field_value_map.unwrap() orelse { | |
| 1282 | // The enum is auto-numbered with an inferred tag type. We know that the tag type generated | |
| 1283 | // earlier is sufficient for the number of fields, so we have nothing more to do. | |
| 1284 | assert(enum_obj.int_tag_mode == .auto); | |
| 1285 | return; | |
| 1286 | }; | |
| 1287 | ||
| 1288 | // There may be old field values in here from a previous update. | |
| 1289 | field_value_map.get(ip).clearRetainingCapacity(); | |
| 1290 | ||
| 1291 | // Map the enum (or union) decl instruction to provide the tag type as the result type | |
| 1292 | try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); | |
| 1293 | sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(int_tag_ty.toIntern())); | |
| 1294 | defer assert(sema.inst_map.remove(zir_index)); | |
| 1295 | ||
| 1296 | // First, populate any explicitly provided values. This is the part that actually depends on | |
| 1297 | // the ZIR, and hence depends on whether this is a declared or generated enum. If any explicit | |
| 1298 | // value is straight-up invalid, we'll emit an error here. | |
| 1299 | if (maybe_parent_union_obj) |union_obj| { | |
| 1300 | if (union_obj.is_reified) { | |
| 1301 | // Generated tag type for reified union; values already populated. | |
| 1302 | } else { | |
| 1303 | // Generated tag type for declared union; evaluate the expressions given in the union declaration. | |
| 1304 | const zir_union = sema.code.getUnionDecl(zir_index); | |
| 1305 | var field_it = zir_union.iterateFields(); | |
| 1306 | while (field_it.next()) |zir_field| { | |
| 1307 | const field_val_src = block.src(.{ .container_field_value = zir_field.idx }); | |
| 1308 | block.comptime_reason = .{ .reason = .{ | |
| 1309 | .src = field_val_src, | |
| 1310 | .r = .{ .simple = .enum_field_values }, | |
| 1311 | } }; | |
| 1312 | const value_body = zir_field.value_body orelse { | |
| 1313 | enum_obj.field_values.get(ip)[zir_field.idx] = .none; | |
| 1314 | continue; | |
| 1315 | }; | |
| 1316 | const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index); | |
| 1317 | const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src); | |
| 1318 | const val = try sema.resolveConstValue(&block, field_val_src, coerced, null); | |
| 1319 | enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern(); | |
| 1320 | } | |
| 1321 | } | |
| 1322 | } else if (enum_obj.is_reified) { | |
| 1323 | // Reified enum; values already populated. | |
| 1324 | } else { | |
| 1325 | // Declared enum; evaluate the expressions given in the enum declaration. | |
| 1326 | const zir_enum = sema.code.getEnumDecl(zir_index); | |
| 1327 | var field_it = zir_enum.iterateFields(); | |
| 1328 | while (field_it.next()) |zir_field| { | |
| 1329 | const field_val_src = block.src(.{ .container_field_value = zir_field.idx }); | |
| 1330 | block.comptime_reason = .{ .reason = .{ | |
| 1331 | .src = field_val_src, | |
| 1332 | .r = .{ .simple = .enum_field_values }, | |
| 1333 | } }; | |
| 1334 | const value_body = zir_field.value_body orelse { | |
| 1335 | enum_obj.field_values.get(ip)[zir_field.idx] = .none; | |
| 1336 | continue; | |
| 1337 | }; | |
| 1338 | const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index); | |
| 1339 | const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src); | |
| 1340 | const val = try sema.resolveConstDefinedValue(&block, field_val_src, coerced, null); | |
| 1341 | enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern(); | |
| 1342 | } | |
| 1343 | } | |
| 1344 | ||
| 1345 | // Explicit values are set. Now we'll go through the whole array and figure out the final | |
| 1346 | // field values. This is also where we'll detect duplicates. | |
| 1347 | ||
| 1348 | for (0..enum_obj.field_names.len) |field_idx| { | |
| 1349 | const field_val_src = block.src(.{ .container_field_value = @intCast(field_idx) }); | |
| 1350 | // If the field value was not specified, compute the implicit value. | |
| 1351 | const field_val = val: { | |
| 1352 | const explicit_val = enum_obj.field_values.get(ip)[field_idx]; | |
| 1353 | if (explicit_val != .none) { | |
| 1354 | assert(ip.typeOf(explicit_val) == int_tag_ty.toIntern()); | |
| 1355 | break :val explicit_val; | |
| 1356 | } | |
| 1357 | if (field_idx == 0) { | |
| 1358 | // Implicit value is 0, which is valid for every integer type. | |
| 1359 | const val = (try pt.intValue(int_tag_ty, 0)).toIntern(); | |
| 1360 | enum_obj.field_values.get(ip)[field_idx] = val; | |
| 1361 | break :val val; | |
| 1362 | } | |
| 1363 | // Implicit non-initial value: take the previous field value and add one. | |
| 1364 | const prev_field_val: Value = .fromInterned(enum_obj.field_values.get(ip)[field_idx - 1]); | |
| 1365 | const result = try arith.incrementDefinedInt(sema, int_tag_ty, prev_field_val); | |
| 1366 | if (result.overflow) return sema.fail( | |
| 1367 | &block, | |
| 1368 | field_val_src, | |
| 1369 | "enum tag value '{f}' too large for type '{f}'", | |
| 1370 | .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) }, | |
| 1371 | ); | |
| 1372 | const val = result.val.toIntern(); | |
| 1373 | enum_obj.field_values.get(ip)[field_idx] = val; | |
| 1374 | break :val val; | |
| 1375 | }; | |
| 1376 | if (ip.addFieldTagValue(enum_obj.field_values, field_value_map, field_val)) |prev_field_index| { | |
| 1377 | return sema.failWithOwnedErrorMsg(&block, msg: { | |
| 1378 | const prev_field_val_src = block.src(.{ .container_field_value = prev_field_index }); | |
| 1379 | const msg = try sema.errMsg(field_val_src, "enum tag value '{f}' for field '{f}' already taken", .{ | |
| 1380 | Value.fromInterned(field_val).fmtValueSema(pt, sema), | |
| 1381 | enum_obj.field_names.get(ip)[field_idx].fmt(ip), | |
| 1382 | }); | |
| 1383 | errdefer msg.destroy(gpa); | |
| 1384 | try sema.errNote(prev_field_val_src, msg, "previous occurrence in field '{f}'", .{ | |
| 1385 | enum_obj.field_names.get(ip)[prev_field_index].fmt(ip), | |
| 1386 | }); | |
| 1387 | break :msg msg; | |
| 1388 | }); | |
| 1389 | } | |
| 1390 | } | |
| 1391 | ||
| 1392 | if (enum_obj.nonexhaustive) { | |
| 1393 | const fields_len = enum_obj.field_names.len; | |
| 1394 | if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) { | |
| 1395 | return sema.fail(&block, block.nodeOffset(.zero), "non-exhaustive enum specifies every value", .{}); | |
| 1396 | } | |
| 1397 | } | |
| 1398 | } |
src/Type.zig+1641-2419| ... | ... | @@ -12,12 +12,10 @@ const Target = std.Target; |
| 12 | 12 | const Zcu = @import("Zcu.zig"); |
| 13 | 13 | const log = std.log.scoped(.Type); |
| 14 | 14 | const target_util = @import("target.zig"); |
| 15 | const Sema = @import("Sema.zig"); | |
| 16 | 15 | const InternPool = @import("InternPool.zig"); |
| 17 | 16 | const Alignment = InternPool.Alignment; |
| 18 | 17 | const Zir = std.zig.Zir; |
| 19 | 18 | const Type = @This(); |
| 20 | const SemaError = Zcu.SemaError; | |
| 21 | 19 | |
| 22 | 20 | ip_index: InternPool.Index, |
| 23 | 21 | |
| ... | ... | @@ -25,14 +23,288 @@ pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId { |
| 25 | 23 | return zcu.intern_pool.zigTypeTag(ty.toIntern()); |
| 26 | 24 | } |
| 27 | 25 | |
| 28 | pub fn baseZigTypeTag(self: Type, mod: *Zcu) std.builtin.TypeId { | |
| 29 | return switch (self.zigTypeTag(mod)) { | |
| 30 | .error_union => self.errorUnionPayload(mod).baseZigTypeTag(mod), | |
| 31 | .optional => { | |
| 32 | return self.optionalChild(mod).baseZigTypeTag(mod); | |
| 26 | /// Every type is a member of exactly one "class" which determines: | |
| 27 | /// * whether values of the type can exist at all | |
| 28 | /// * whether values of the type can be runtime-knwon | |
| 29 | /// * whether the type is considered comptime-only | |
| 30 | /// * whether the type has runtime bits (nonzero ABI size) | |
| 31 | pub const Class = enum(u3) { | |
| 32 | /// Values of this type cannot exist because the type semantically has no values. Attempting to | |
| 33 | /// create a value of this type (such as by coercing `undefined`) always emits a compile error. | |
| 34 | /// | |
| 35 | /// Not comptime-only. No runtime bits, i.e. ABI size is 0. | |
| 36 | /// | |
| 37 | /// Exhaustive list of no-possible-value ("NPV") types: | |
| 38 | /// * `noreturn` | |
| 39 | /// * `anyopaque`, and any `opaque` type | |
| 40 | /// * `[n]T` where `n` is non-zero and `T` is NPV | |
| 41 | /// * Any tuple where at least one non-`comptime` field has an NPV type | |
| 42 | /// * Any enum whose backing type is `noreturn` | |
| 43 | /// * Any struct where at least one non-`comptime` field has an NPV type | |
| 44 | /// * Any union where every field has an NPV type (including unions with no fields) | |
| 45 | /// * If the union would typically have a runtime tag, even if that tag would have runtime | |
| 46 | /// bits, the union type is still NPV; the runtime tag is effectively omitted. | |
| 47 | no_possible_value, | |
| 48 | ||
| 49 | /// Values of this type are always comptime-known because there is only one value inhabiting the | |
| 50 | /// type. This matches the colloquial understanding of a "zero-bit type". | |
| 51 | /// | |
| 52 | /// Not comptime-only (although always comptime-known). No runtime bits, i.e. ABI size is 0. | |
| 53 | /// | |
| 54 | /// Exhaustive list of one-possible-value ("OPV") types: | |
| 55 | /// * `void` | |
| 56 | /// * `u0`, `i0` | |
| 57 | /// * `[0]T` for any `T` | |
| 58 | /// * `[n]T` where `T` is OPV | |
| 59 | /// * `[n:s]T` where `T` is OPV | |
| 60 | /// * `@Vector(0, T)` for any `T` | |
| 61 | /// * `@Vector(n, T)` where `T` is OPV | |
| 62 | /// * Any tuple where every non-`comptime` field has an OPV type (including tuples with no fields) | |
| 63 | /// * Any enum whose backing type is OPV | |
| 64 | /// * Any struct where every non-`comptime` field has an OPV type (including structs with no fields) | |
| 65 | /// * Any union with no runtime tag where all fields have OPV | |
| 66 | /// * Any union where one field has an OPV type, and either: | |
| 67 | /// * All other fields have NPV types (in this case, if there would be a runtime tag, it is omitted) | |
| 68 | /// * All other fields have NPV or OPV types, and the union has no runtime tag | |
| 69 | one_possible_value, | |
| 70 | ||
| 71 | /// The type holds state (so it is neither NPV nor OPV), but contains no comptime-only state, so | |
| 72 | /// values may be runtime-known. | |
| 73 | /// | |
| 74 | /// Not comptime-only. Has runtime bits, i.e. ABI size is non-zero. | |
| 75 | /// | |
| 76 | /// Most types which are typically used in Zig inhabit this class. For instance, all pointer | |
| 77 | /// types, all integer types other than `u0` and `i0`, and most user-defined aggregates fall | |
| 78 | /// into this category. | |
| 79 | runtime, | |
| 80 | ||
| 81 | /// The type holds state (so it is neither NPV nor OPV). Some, but not all, of the contained | |
| 82 | /// state is comptime-only. | |
| 83 | /// | |
| 84 | /// Comptime-only. Has runtime bits, i.e. ABI size is non-zero. | |
| 85 | /// | |
| 86 | /// Partially-comptime types arise from aggregates (`struct`s, `union`s, or tuples) which have | |
| 87 | /// some fields with fully-comptime types (such as `comptime_int`) and some fields with runtime | |
| 88 | /// types (such as `u8`). Because the user may acquire pointers to these fields, pointers to the | |
| 89 | /// embedded runtime state must be valid, so backends are required to lower the runtime state | |
| 90 | /// within the type. | |
| 91 | /// | |
| 92 | /// Note that logically-runtime state which cannot be directly referenced by the user (such as | |
| 93 | /// the enum tag of a tagged union type, or the "populated" bit of an optional type) does not | |
| 94 | /// cause a type to be partially-comptime. | |
| 95 | partially_comptime, | |
| 96 | ||
| 97 | /// The type contains exclusively comptime-only state. | |
| 98 | /// | |
| 99 | /// Comptime-only. No runtime bits, i.e. ABI size is 0. | |
| 100 | /// | |
| 101 | /// Fully-comptime types arise from a handful of primitive fully-comptime types: | |
| 102 | /// * `type` | |
| 103 | /// * `comptime_int` | |
| 104 | /// * `comptime_float` | |
| 105 | /// * `@EnumLiteral()` | |
| 106 | /// * `@TypeOf(null)` | |
| 107 | /// * `@TypeOf(undefined)` | |
| 108 | /// | |
| 109 | /// Then, aggregates containing fully-comptime types may themselves be either fully-comptime or | |
| 110 | /// partially-comptime; see the doc comment on `.partially_comptime` for details. | |
| 111 | fully_comptime, | |
| 112 | }; | |
| 113 | ||
| 114 | /// Returns the `Class` for the type `ty`. Asserts that the layout of `ty` is resolved. | |
| 115 | pub fn classify(start_ty: Type, zcu: *const Zcu) Class { | |
| 116 | const ip = &zcu.intern_pool; | |
| 117 | ||
| 118 | // We avoid recursion in most cases to make us more optimizer-friendly because this can be a | |
| 119 | // very hot code path. The only case where recursion is necessary is tuples, so that case is | |
| 120 | // outlined into a separate function; see `classifyTuple`. | |
| 121 | ||
| 122 | var extra_states: enum { none, one, many } = .none; | |
| 123 | ||
| 124 | var cur_ty = start_ty; | |
| 125 | const base: Class = while (true) break switch (ip.indexToKey(cur_ty.toIntern())) { | |
| 126 | .simple_type => |t| switch (t) { | |
| 127 | .f16, | |
| 128 | .f32, | |
| 129 | .f64, | |
| 130 | .f80, | |
| 131 | .f128, | |
| 132 | .usize, | |
| 133 | .isize, | |
| 134 | .c_char, | |
| 135 | .c_short, | |
| 136 | .c_ushort, | |
| 137 | .c_int, | |
| 138 | .c_uint, | |
| 139 | .c_long, | |
| 140 | .c_ulong, | |
| 141 | .c_longlong, | |
| 142 | .c_ulonglong, | |
| 143 | .c_longdouble, | |
| 144 | .bool, | |
| 145 | .anyerror, | |
| 146 | .adhoc_inferred_error_set, | |
| 147 | => .runtime, | |
| 148 | ||
| 149 | .anyopaque => .no_possible_value, | |
| 150 | ||
| 151 | .type, | |
| 152 | .comptime_int, | |
| 153 | .comptime_float, | |
| 154 | .enum_literal, | |
| 155 | .null, | |
| 156 | .undefined, | |
| 157 | => .fully_comptime, | |
| 158 | ||
| 159 | .void => .one_possible_value, | |
| 160 | .noreturn => .no_possible_value, | |
| 161 | ||
| 162 | .generic_poison => unreachable, | |
| 163 | }, | |
| 164 | ||
| 165 | .error_set_type, | |
| 166 | .inferred_error_set_type, | |
| 167 | .ptr_type, | |
| 168 | .anyframe_type, | |
| 169 | => .runtime, | |
| 170 | ||
| 171 | .func_type => .fully_comptime, | |
| 172 | ||
| 173 | .opaque_type => .no_possible_value, | |
| 174 | ||
| 175 | .error_union_type => |eu| { | |
| 176 | extra_states = .many; | |
| 177 | cur_ty = .fromInterned(eu.payload_type); | |
| 178 | continue; | |
| 179 | }, | |
| 180 | ||
| 181 | .int_type => |int| switch (int.bits) { | |
| 182 | 0 => .one_possible_value, | |
| 183 | else => .runtime, | |
| 184 | }, | |
| 185 | .array_type => |arr| { | |
| 186 | if (arr.len == 0 and arr.sentinel == .none) break .one_possible_value; | |
| 187 | cur_ty = .fromInterned(arr.child); | |
| 188 | continue; | |
| 189 | }, | |
| 190 | .vector_type => |vec| { | |
| 191 | if (vec.len == 0) break .one_possible_value; | |
| 192 | cur_ty = .fromInterned(vec.child); | |
| 193 | continue; | |
| 194 | }, | |
| 195 | .opt_type => |child_ty_ip| { | |
| 196 | extra_states = switch (extra_states) { | |
| 197 | .none => .one, | |
| 198 | .one, .many => .many, | |
| 199 | }; | |
| 200 | cur_ty = .fromInterned(child_ty_ip); | |
| 201 | continue; | |
| 202 | }, | |
| 203 | .tuple_type => |tuple| { | |
| 204 | @branchHint(.unlikely); | |
| 205 | break classifyTuple(tuple.types.get(ip), tuple.values.get(ip), zcu); | |
| 206 | }, | |
| 207 | .struct_type => { | |
| 208 | const struct_obj = ip.loadStructType(cur_ty.toIntern()); | |
| 209 | switch (struct_obj.layout) { | |
| 210 | .auto, .@"extern" => { | |
| 211 | zcu.assertUpToDate(.wrap(.{ .type_layout = cur_ty.toIntern() })); | |
| 212 | break struct_obj.class; | |
| 213 | }, | |
| 214 | .@"packed" => { | |
| 215 | cur_ty = .fromInterned(struct_obj.packed_backing_int_type); | |
| 216 | continue; | |
| 217 | }, | |
| 218 | } | |
| 219 | }, | |
| 220 | .union_type => { | |
| 221 | const union_obj = ip.loadUnionType(cur_ty.toIntern()); | |
| 222 | switch (union_obj.layout) { | |
| 223 | .auto, .@"extern" => { | |
| 224 | zcu.assertUpToDate(.wrap(.{ .type_layout = cur_ty.toIntern() })); | |
| 225 | break union_obj.class; | |
| 226 | }, | |
| 227 | .@"packed" => { | |
| 228 | cur_ty = .fromInterned(union_obj.packed_backing_int_type); | |
| 229 | continue; | |
| 230 | }, | |
| 231 | } | |
| 232 | }, | |
| 233 | .enum_type => { | |
| 234 | zcu.assertUpToDate(.wrap(.{ .type_layout = cur_ty.toIntern() })); | |
| 235 | cur_ty = .fromInterned(ip.loadEnumType(cur_ty.toIntern()).int_tag_type); | |
| 236 | continue; | |
| 33 | 237 | }, |
| 34 | else => |t| t, | |
| 238 | ||
| 239 | // values, not types | |
| 240 | .undef, | |
| 241 | .simple_value, | |
| 242 | .variable, | |
| 243 | .@"extern", | |
| 244 | .func, | |
| 245 | .int, | |
| 246 | .err, | |
| 247 | .error_union, | |
| 248 | .enum_literal, | |
| 249 | .enum_tag, | |
| 250 | .float, | |
| 251 | .ptr, | |
| 252 | .slice, | |
| 253 | .opt, | |
| 254 | .aggregate, | |
| 255 | .un, | |
| 256 | .bitpack, | |
| 257 | // memoization, not types | |
| 258 | .memoized_call, | |
| 259 | => unreachable, | |
| 35 | 260 | }; |
| 261 | ||
| 262 | return switch (base) { | |
| 263 | .runtime => .runtime, // extra states are irrelevant, we already have many! | |
| 264 | .partially_comptime => .partially_comptime, // likewise | |
| 265 | .fully_comptime => { | |
| 266 | // We do not need to change to `.partially_comptime` here because the extra states do | |
| 267 | // not necessarily require runtime bits. This is because Zig does not provide a way to | |
| 268 | // take the address of the "is null" bit of an optional or the error set "inside" of an | |
| 269 | // error union. | |
| 270 | return .fully_comptime; | |
| 271 | }, | |
| 272 | ||
| 273 | .no_possible_value => switch (extra_states) { | |
| 274 | .none => .no_possible_value, | |
| 275 | .one => .one_possible_value, | |
| 276 | .many => .runtime, | |
| 277 | }, | |
| 278 | ||
| 279 | .one_possible_value => switch (extra_states) { | |
| 280 | .none => .one_possible_value, | |
| 281 | .one, .many => .runtime, | |
| 282 | }, | |
| 283 | }; | |
| 284 | } | |
| 285 | /// This is a separate function to `classify` to avoid recursion in the main `classify` function, | |
| 286 | /// which can encourage the optimizer to e.g. inline `classify` where it would be beneficial. | |
| 287 | fn classifyTuple(types: []const InternPool.Index, values: []const InternPool.Index, zcu: *const Zcu) Class { | |
| 288 | var has_runtime_state = false; | |
| 289 | var has_comptime_state = false; | |
| 290 | for (types, values) |field_ty, field_comptime_val| { | |
| 291 | if (field_comptime_val != .none) continue; | |
| 292 | switch (Type.fromInterned(field_ty).classify(zcu)) { | |
| 293 | .no_possible_value => return .no_possible_value, | |
| 294 | .one_possible_value => {}, | |
| 295 | .runtime => has_runtime_state = true, | |
| 296 | .fully_comptime => has_comptime_state = true, | |
| 297 | .partially_comptime => { | |
| 298 | has_runtime_state = true; | |
| 299 | has_comptime_state = true; | |
| 300 | }, | |
| 301 | } | |
| 302 | } | |
| 303 | if (has_comptime_state) { | |
| 304 | return if (has_runtime_state) .partially_comptime else .fully_comptime; | |
| 305 | } else { | |
| 306 | return if (has_runtime_state) .runtime else .one_possible_value; | |
| 307 | } | |
| 36 | 308 | } |
| 37 | 309 | |
| 38 | 310 | /// Asserts the type is resolved. |
| ... | ... | @@ -44,7 +316,7 @@ pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool { |
| 44 | 316 | .comptime_int, |
| 45 | 317 | => true, |
| 46 | 318 | |
| 47 | .vector => ty.elemType2(zcu).isSelfComparable(zcu, is_equality_cmp), | |
| 319 | .vector => ty.childType(zcu).isSelfComparable(zcu, is_equality_cmp), | |
| 48 | 320 | |
| 49 | 321 | .bool, |
| 50 | 322 | .type, |
| ... | ... | @@ -121,11 +393,7 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool { |
| 121 | 393 | return a.toIntern() == b.toIntern(); |
| 122 | 394 | } |
| 123 | 395 | |
| 124 | pub fn format(ty: Type, writer: *std.Io.Writer) !void { | |
| 125 | _ = ty; | |
| 126 | _ = writer; | |
| 127 | @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); | |
| 128 | } | |
| 396 | pub const format = @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); | |
| 129 | 397 | |
| 130 | 398 | pub const Formatter = std.fmt.Alt(Format, Format.default); |
| 131 | 399 | |
| ... | ... | @@ -416,13 +684,13 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari |
| 416 | 684 | .error_union, |
| 417 | 685 | .enum_literal, |
| 418 | 686 | .enum_tag, |
| 419 | .empty_enum_value, | |
| 420 | 687 | .float, |
| 421 | 688 | .ptr, |
| 422 | 689 | .slice, |
| 423 | 690 | .opt, |
| 424 | 691 | .aggregate, |
| 425 | 692 | .un, |
| 693 | .bitpack, | |
| 426 | 694 | // memoization, not types |
| 427 | 695 | .memoized_call, |
| 428 | 696 | => unreachable, |
| ... | ... | @@ -440,247 +708,41 @@ pub fn toIntern(ty: Type) InternPool.Index { |
| 440 | 708 | } |
| 441 | 709 | |
| 442 | 710 | pub fn toValue(self: Type) Value { |
| 443 | return Value.fromInterned(self.toIntern()); | |
| 711 | return .fromInterned(self.toIntern()); | |
| 444 | 712 | } |
| 445 | 713 | |
| 446 | const RuntimeBitsError = SemaError || error{NeedLazy}; | |
| 447 | ||
| 714 | /// Returns `true` if and only if the type takes up space in memory at runtime. This is also exactly | |
| 715 | /// whether or not the backend/linker needs to be sent values of this type to emit to the binary. | |
| 716 | /// | |
| 717 | /// Types without runtime bits have an ABI size of 0; all other types have a non-zero ABI size. All | |
| 718 | /// types, regardless of whether they have runtime bits, have a non-zero ABI alignment. | |
| 719 | /// | |
| 720 | /// Comptime-only types may still have runtime bits. For instance, `struct { a: u32, b: type }` is a | |
| 721 | /// comptime-only type, but it nonetheless has runtime bits and a runtime memory layout (where the | |
| 722 | /// field `b: type` is omitted). This is because a user may take a pointer to the field `a`, which | |
| 723 | /// must then be valid to use at runtime. | |
| 724 | /// | |
| 725 | /// This function is a trivial wrapper around `classify`: | |
| 726 | /// | |
| 727 | /// * Types with one possible value, such as `void`, or no possible value, such as `noreturn`, do | |
| 728 | /// not have runtime bits and have an ABI size of 0 because they simply contain no state. | |
| 729 | /// | |
| 730 | /// * Types which are fully comptime, such as `type` and `comptime_int`, do not have runtime bits | |
| 731 | /// because they contain only comptime state. (This compiler implementation also currently makes | |
| 732 | /// types like `struct { x: comptime_int }` fully comptime, but that could change in the future if | |
| 733 | /// we start inserting hidden safety fields into them.) | |
| 734 | /// | |
| 735 | /// * All other types contain some runtime state, so have runtime bits and a non-zero ABI size. | |
| 448 | 736 | pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { |
| 449 | return hasRuntimeBitsInner(ty, false, .eager, zcu, {}) catch unreachable; | |
| 450 | } | |
| 451 | ||
| 452 | pub fn hasRuntimeBitsSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { | |
| 453 | return hasRuntimeBitsInner(ty, false, .sema, pt.zcu, pt.tid) catch |err| switch (err) { | |
| 454 | error.NeedLazy => unreachable, // this would require a resolve strat of lazy | |
| 455 | else => |e| return e, | |
| 456 | }; | |
| 457 | } | |
| 458 | ||
| 459 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type, zcu: *const Zcu) bool { | |
| 460 | return hasRuntimeBitsInner(ty, true, .eager, zcu, {}) catch unreachable; | |
| 461 | } | |
| 462 | ||
| 463 | pub fn hasRuntimeBitsIgnoreComptimeSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { | |
| 464 | return hasRuntimeBitsInner(ty, true, .sema, pt.zcu, pt.tid) catch |err| switch (err) { | |
| 465 | error.NeedLazy => unreachable, // this would require a resolve strat of lazy | |
| 466 | else => |e| return e, | |
| 467 | }; | |
| 468 | } | |
| 469 | ||
| 470 | /// true if and only if the type takes up space in memory at runtime. | |
| 471 | /// There are two reasons a type will return false: | |
| 472 | /// * the type is a comptime-only type. For example, the type `type` itself. | |
| 473 | /// - note, however, that a struct can have mixed fields and only the non-comptime-only | |
| 474 | /// fields will count towards the ABI size. For example, `struct {T: type, x: i32}` | |
| 475 | /// hasRuntimeBits()=true and abiSize()=4 | |
| 476 | /// * the type has only one possible value, making its ABI size 0. | |
| 477 | /// - an enum with an explicit tag type has the ABI size of the integer tag type, | |
| 478 | /// making it one-possible-value only if the integer tag type has 0 bits. | |
| 479 | /// When `ignore_comptime_only` is true, then types that are comptime-only | |
| 480 | /// may return false positives. | |
| 481 | pub fn hasRuntimeBitsInner( | |
| 482 | ty: Type, | |
| 483 | ignore_comptime_only: bool, | |
| 484 | comptime strat: ResolveStratLazy, | |
| 485 | zcu: strat.ZcuPtr(), | |
| 486 | tid: strat.Tid(), | |
| 487 | ) RuntimeBitsError!bool { | |
| 488 | const ip = &zcu.intern_pool; | |
| 489 | const io = zcu.comp.io; | |
| 490 | return switch (ty.toIntern()) { | |
| 491 | .empty_tuple_type => false, | |
| 492 | else => switch (ip.indexToKey(ty.toIntern())) { | |
| 493 | .int_type => |int_type| int_type.bits != 0, | |
| 494 | .ptr_type => { | |
| 495 | // Pointers to zero-bit types still have a runtime address; however, pointers | |
| 496 | // to comptime-only types do not, with the exception of function pointers. | |
| 497 | if (ignore_comptime_only) return true; | |
| 498 | return switch (strat) { | |
| 499 | .sema => { | |
| 500 | const pt = strat.pt(zcu, tid); | |
| 501 | return !try ty.comptimeOnlySema(pt); | |
| 502 | }, | |
| 503 | .eager => !ty.comptimeOnly(zcu), | |
| 504 | .lazy => error.NeedLazy, | |
| 505 | }; | |
| 506 | }, | |
| 507 | .anyframe_type => true, | |
| 508 | .array_type => |array_type| return array_type.lenIncludingSentinel() > 0 and | |
| 509 | try Type.fromInterned(array_type.child).hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid), | |
| 510 | .vector_type => |vector_type| return vector_type.len > 0 and | |
| 511 | try Type.fromInterned(vector_type.child).hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid), | |
| 512 | .opt_type => |child| { | |
| 513 | const child_ty = Type.fromInterned(child); | |
| 514 | if (child_ty.isNoReturn(zcu)) { | |
| 515 | // Then the optional is comptime-known to be null. | |
| 516 | return false; | |
| 517 | } | |
| 518 | if (ignore_comptime_only) return true; | |
| 519 | return switch (strat) { | |
| 520 | .sema => !try child_ty.comptimeOnlyInner(.sema, zcu, tid), | |
| 521 | .eager => !child_ty.comptimeOnly(zcu), | |
| 522 | .lazy => error.NeedLazy, | |
| 523 | }; | |
| 524 | }, | |
| 525 | .error_union_type, | |
| 526 | .error_set_type, | |
| 527 | .inferred_error_set_type, | |
| 528 | => true, | |
| 529 | ||
| 530 | // These are function *bodies*, not pointers. | |
| 531 | // They return false here because they are comptime-only types. | |
| 532 | // Special exceptions have to be made when emitting functions due to | |
| 533 | // this returning false. | |
| 534 | .func_type => false, | |
| 535 | ||
| 536 | .simple_type => |t| switch (t) { | |
| 537 | .f16, | |
| 538 | .f32, | |
| 539 | .f64, | |
| 540 | .f80, | |
| 541 | .f128, | |
| 542 | .usize, | |
| 543 | .isize, | |
| 544 | .c_char, | |
| 545 | .c_short, | |
| 546 | .c_ushort, | |
| 547 | .c_int, | |
| 548 | .c_uint, | |
| 549 | .c_long, | |
| 550 | .c_ulong, | |
| 551 | .c_longlong, | |
| 552 | .c_ulonglong, | |
| 553 | .c_longdouble, | |
| 554 | .bool, | |
| 555 | .anyerror, | |
| 556 | .adhoc_inferred_error_set, | |
| 557 | .anyopaque, | |
| 558 | => true, | |
| 559 | ||
| 560 | // These are false because they are comptime-only types. | |
| 561 | .void, | |
| 562 | .type, | |
| 563 | .comptime_int, | |
| 564 | .comptime_float, | |
| 565 | .noreturn, | |
| 566 | .null, | |
| 567 | .undefined, | |
| 568 | .enum_literal, | |
| 569 | => false, | |
| 570 | ||
| 571 | .generic_poison => unreachable, | |
| 572 | }, | |
| 573 | .struct_type => { | |
| 574 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 575 | if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) { | |
| 576 | // In this case, we guess that hasRuntimeBits() for this type is true, | |
| 577 | // and then later if our guess was incorrect, we emit a compile error. | |
| 578 | return true; | |
| 579 | } | |
| 580 | switch (strat) { | |
| 581 | .sema => try ty.resolveFields(strat.pt(zcu, tid)), | |
| 582 | .eager => assert(struct_type.haveFieldTypes(ip)), | |
| 583 | .lazy => if (!struct_type.haveFieldTypes(ip)) return error.NeedLazy, | |
| 584 | } | |
| 585 | for (0..struct_type.field_types.len) |i| { | |
| 586 | if (struct_type.comptime_bits.getBit(ip, i)) continue; | |
| 587 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 588 | if (try field_ty.hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid)) | |
| 589 | return true; | |
| 590 | } else { | |
| 591 | return false; | |
| 592 | } | |
| 593 | }, | |
| 594 | .tuple_type => |tuple| { | |
| 595 | for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { | |
| 596 | if (val != .none) continue; // comptime field | |
| 597 | if (try Type.fromInterned(field_ty).hasRuntimeBitsInner( | |
| 598 | ignore_comptime_only, | |
| 599 | strat, | |
| 600 | zcu, | |
| 601 | tid, | |
| 602 | )) return true; | |
| 603 | } | |
| 604 | return false; | |
| 605 | }, | |
| 606 | ||
| 607 | .union_type => { | |
| 608 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 609 | const union_flags = union_type.flagsUnordered(ip); | |
| 610 | switch (union_flags.runtime_tag) { | |
| 611 | .none => if (strat != .eager) { | |
| 612 | // In this case, we guess that hasRuntimeBits() for this type is true, | |
| 613 | // and then later if our guess was incorrect, we emit a compile error. | |
| 614 | if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) return true; | |
| 615 | }, | |
| 616 | .safety, .tagged => {}, | |
| 617 | } | |
| 618 | switch (strat) { | |
| 619 | .sema => try ty.resolveFields(strat.pt(zcu, tid)), | |
| 620 | .eager => assert(union_flags.status.haveFieldTypes()), | |
| 621 | .lazy => if (!union_flags.status.haveFieldTypes()) | |
| 622 | return error.NeedLazy, | |
| 623 | } | |
| 624 | switch (union_flags.runtime_tag) { | |
| 625 | .none => {}, | |
| 626 | .safety, .tagged => { | |
| 627 | const tag_ty = union_type.tagTypeUnordered(ip); | |
| 628 | assert(tag_ty != .none); // tag_ty should have been resolved above | |
| 629 | if (try Type.fromInterned(tag_ty).hasRuntimeBitsInner( | |
| 630 | ignore_comptime_only, | |
| 631 | strat, | |
| 632 | zcu, | |
| 633 | tid, | |
| 634 | )) { | |
| 635 | return true; | |
| 636 | } | |
| 637 | }, | |
| 638 | } | |
| 639 | for (0..union_type.field_types.len) |field_index| { | |
| 640 | const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 641 | if (try field_ty.hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid)) | |
| 642 | return true; | |
| 643 | } else { | |
| 644 | return false; | |
| 645 | } | |
| 646 | }, | |
| 647 | ||
| 648 | .opaque_type => true, | |
| 649 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsInner( | |
| 650 | ignore_comptime_only, | |
| 651 | strat, | |
| 652 | zcu, | |
| 653 | tid, | |
| 654 | ), | |
| 655 | ||
| 656 | // values, not types | |
| 657 | .undef, | |
| 658 | .simple_value, | |
| 659 | .variable, | |
| 660 | .@"extern", | |
| 661 | .func, | |
| 662 | .int, | |
| 663 | .err, | |
| 664 | .error_union, | |
| 665 | .enum_literal, | |
| 666 | .enum_tag, | |
| 667 | .empty_enum_value, | |
| 668 | .float, | |
| 669 | .ptr, | |
| 670 | .slice, | |
| 671 | .opt, | |
| 672 | .aggregate, | |
| 673 | .un, | |
| 674 | // memoization, not types | |
| 675 | .memoized_call, | |
| 676 | => unreachable, | |
| 677 | }, | |
| 737 | return switch (ty.classify(zcu)) { | |
| 738 | .no_possible_value, .one_possible_value, .fully_comptime => false, | |
| 739 | .runtime, .partially_comptime => true, | |
| 678 | 740 | }; |
| 679 | 741 | } |
| 680 | 742 | |
| 681 | /// true if and only if the type has a well-defined memory layout | |
| 682 | /// readFrom/writeToMemory are supported only for types with a well- | |
| 683 | /// defined memory layout | |
| 743 | /// Returns `true` iff the memory layout of `ty` is defined by the Zig language specification. | |
| 744 | /// | |
| 745 | /// Does not require `ty` to be resolved. | |
| 684 | 746 | pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { |
| 685 | 747 | const ip = &zcu.intern_pool; |
| 686 | 748 | return switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -737,17 +799,17 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { |
| 737 | 799 | .generic_poison, |
| 738 | 800 | => false, |
| 739 | 801 | }, |
| 740 | .struct_type => ip.loadStructType(ty.toIntern()).layout != .auto, | |
| 741 | .union_type => { | |
| 742 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 743 | return switch (union_type.flagsUnordered(ip).runtime_tag) { | |
| 744 | .none, .safety => union_type.flagsUnordered(ip).layout != .auto, | |
| 745 | .tagged => false, | |
| 746 | }; | |
| 802 | .struct_type => switch (ip.loadStructType(ty.toIntern()).layout) { | |
| 803 | .auto => false, | |
| 804 | .@"extern", .@"packed" => true, | |
| 805 | }, | |
| 806 | .union_type => switch (ip.loadUnionType(ty.toIntern()).layout) { | |
| 807 | .auto => false, | |
| 808 | .@"extern", .@"packed" => true, | |
| 747 | 809 | }, |
| 748 | .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) { | |
| 810 | .enum_type => switch (ip.loadEnumType(ty.toIntern()).int_tag_mode) { | |
| 811 | .explicit => true, | |
| 749 | 812 | .auto => false, |
| 750 | .explicit, .nonexhaustive => true, | |
| 751 | 813 | }, |
| 752 | 814 | |
| 753 | 815 | // values, not types |
| ... | ... | @@ -761,86 +823,88 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { |
| 761 | 823 | .error_union, |
| 762 | 824 | .enum_literal, |
| 763 | 825 | .enum_tag, |
| 764 | .empty_enum_value, | |
| 765 | 826 | .float, |
| 766 | 827 | .ptr, |
| 767 | 828 | .slice, |
| 768 | 829 | .opt, |
| 769 | 830 | .aggregate, |
| 770 | 831 | .un, |
| 832 | .bitpack, | |
| 771 | 833 | // memoization, not types |
| 772 | 834 | .memoized_call, |
| 773 | 835 | => unreachable, |
| 774 | 836 | }; |
| 775 | 837 | } |
| 776 | 838 | |
| 777 | pub fn fnHasRuntimeBits(ty: Type, zcu: *Zcu) bool { | |
| 778 | return ty.fnHasRuntimeBitsInner(.normal, zcu, {}) catch unreachable; | |
| 779 | } | |
| 780 | ||
| 781 | pub fn fnHasRuntimeBitsSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { | |
| 782 | return try ty.fnHasRuntimeBitsInner(.sema, pt.zcu, pt.tid); | |
| 783 | } | |
| 784 | ||
| 785 | 839 | /// Determines whether a function type has runtime bits, i.e. whether a |
| 786 | 840 | /// function with this type can exist at runtime. |
| 787 | 841 | /// Asserts that `ty` is a function type. |
| 788 | pub fn fnHasRuntimeBitsInner( | |
| 789 | ty: Type, | |
| 790 | comptime strat: ResolveStrat, | |
| 791 | zcu: strat.ZcuPtr(), | |
| 792 | tid: strat.Tid(), | |
| 793 | ) SemaError!bool { | |
| 794 | const fn_info = zcu.typeToFunc(ty).?; | |
| 795 | if (fn_info.is_generic) return false; | |
| 796 | if (fn_info.is_var_args) return true; | |
| 842 | pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *const Zcu) bool { | |
| 843 | assertHasLayout(fn_ty, zcu); | |
| 844 | const fn_info = zcu.typeToFunc(fn_ty).?; | |
| 845 | if (fn_info.comptime_bits != 0) return false; | |
| 846 | for (fn_info.param_types.get(&zcu.intern_pool)) |param_ty| { | |
| 847 | if (param_ty == .generic_poison_type) return false; | |
| 848 | switch (Type.fromInterned(param_ty).classify(zcu)) { | |
| 849 | .fully_comptime, | |
| 850 | .partially_comptime, | |
| 851 | .no_possible_value, | |
| 852 | => return false, | |
| 853 | ||
| 854 | .one_possible_value, | |
| 855 | .runtime, | |
| 856 | => {}, | |
| 857 | } | |
| 858 | } | |
| 859 | const ret_ty: Type = .fromInterned(fn_info.return_type); | |
| 860 | if (ret_ty.toIntern() == .generic_poison_type) { | |
| 861 | return false; | |
| 862 | } | |
| 863 | if (ret_ty.zigTypeTag(zcu) == .error_union and | |
| 864 | ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) | |
| 865 | { | |
| 866 | return false; | |
| 867 | } | |
| 868 | switch (ret_ty.classify(zcu)) { | |
| 869 | .fully_comptime, | |
| 870 | .partially_comptime, | |
| 871 | => return false, | |
| 872 | ||
| 873 | .no_possible_value, | |
| 874 | .one_possible_value, | |
| 875 | .runtime, | |
| 876 | => {}, | |
| 877 | } | |
| 797 | 878 | if (fn_info.cc == .@"inline") return false; |
| 798 | return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid); | |
| 879 | return true; | |
| 799 | 880 | } |
| 800 | 881 | |
| 801 | pub fn isFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { | |
| 882 | /// Like `hasRuntimeBits`, but also returns `true` for runtime functions. | |
| 883 | pub fn isRuntimeFnOrHasRuntimeBits(ty: Type, zcu: *const Zcu) bool { | |
| 802 | 884 | switch (ty.zigTypeTag(zcu)) { |
| 803 | 885 | .@"fn" => return ty.fnHasRuntimeBits(zcu), |
| 804 | 886 | else => return ty.hasRuntimeBits(zcu), |
| 805 | 887 | } |
| 806 | 888 | } |
| 807 | 889 | |
| 808 | /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive. | |
| 809 | pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, zcu: *Zcu) bool { | |
| 810 | return switch (ty.zigTypeTag(zcu)) { | |
| 811 | .@"fn" => true, | |
| 812 | else => return ty.hasRuntimeBitsIgnoreComptime(zcu), | |
| 813 | }; | |
| 814 | } | |
| 815 | ||
| 890 | /// Returns whether `ty` is NPV, meaning it is "like `noreturn`" in a sense. See doc comments on | |
| 891 | /// `Class` for more details. | |
| 892 | /// | |
| 893 | /// Exactly equivalent to `ty.classify(zcu) == .no_possible_value`. | |
| 816 | 894 | pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool { |
| 817 | return zcu.intern_pool.isNoReturn(ty.toIntern()); | |
| 895 | return ty.classify(zcu) == .no_possible_value; | |
| 818 | 896 | } |
| 819 | 897 | |
| 820 | 898 | /// Never returns `none`. Asserts that all necessary type resolution is already done. |
| 821 | pub fn ptrAlignment(ty: Type, zcu: *Zcu) Alignment { | |
| 822 | return ptrAlignmentInner(ty, .normal, zcu, {}) catch unreachable; | |
| 823 | } | |
| 824 | ||
| 825 | pub fn ptrAlignmentSema(ty: Type, pt: Zcu.PerThread) SemaError!Alignment { | |
| 826 | return try ty.ptrAlignmentInner(.sema, pt.zcu, pt.tid); | |
| 827 | } | |
| 828 | ||
| 829 | pub fn ptrAlignmentInner( | |
| 830 | ty: Type, | |
| 831 | comptime strat: ResolveStrat, | |
| 832 | zcu: strat.ZcuPtr(), | |
| 833 | tid: strat.Tid(), | |
| 834 | ) !Alignment { | |
| 835 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 836 | .ptr_type => |ptr_type| { | |
| 837 | if (ptr_type.flags.alignment != .none) return ptr_type.flags.alignment; | |
| 838 | const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(strat.toLazy(), zcu, tid); | |
| 839 | return res.scalar; | |
| 840 | }, | |
| 841 | .opt_type => |child| Type.fromInterned(child).ptrAlignmentInner(strat, zcu, tid), | |
| 899 | pub fn ptrAlignment(ptr_ty: Type, zcu: *Zcu) Alignment { | |
| 900 | const ip = &zcu.intern_pool; | |
| 901 | const ptr_key: InternPool.Key.PtrType = switch (ip.indexToKey(ptr_ty.toIntern())) { | |
| 902 | .ptr_type => |key| key, | |
| 903 | .opt_type => |child| ip.indexToKey(child).ptr_type, | |
| 842 | 904 | else => unreachable, |
| 843 | 905 | }; |
| 906 | if (ptr_key.flags.alignment != .none) return ptr_key.flags.alignment; | |
| 907 | return Type.fromInterned(ptr_key.child).abiAlignment(zcu); | |
| 844 | 908 | } |
| 845 | 909 | |
| 846 | 910 | pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace { |
| ... | ... | @@ -851,861 +915,364 @@ pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace { |
| 851 | 915 | }; |
| 852 | 916 | } |
| 853 | 917 | |
| 854 | /// May capture a reference to `ty`. | |
| 855 | /// Returned value has type `comptime_int`. | |
| 856 | pub fn lazyAbiAlignment(ty: Type, pt: Zcu.PerThread) !Value { | |
| 857 | switch (try ty.abiAlignmentInner(.lazy, pt.zcu, pt.tid)) { | |
| 858 | .val => |val| return val, | |
| 859 | .scalar => |x| return pt.intValue(Type.comptime_int, x.toByteUnits() orelse 0), | |
| 860 | } | |
| 861 | } | |
| 862 | ||
| 863 | pub const AbiAlignmentInner = union(enum) { | |
| 864 | scalar: Alignment, | |
| 865 | val: Value, | |
| 866 | }; | |
| 867 | ||
| 868 | pub const ResolveStratLazy = enum { | |
| 869 | /// Return a `lazy_size` or `lazy_align` value if necessary. | |
| 870 | /// This value can be resolved later using `Value.resolveLazy`. | |
| 871 | lazy, | |
| 872 | /// Return a scalar result, expecting all necessary type resolution to be completed. | |
| 873 | /// Backends should typically use this, since they must not perform type resolution. | |
| 874 | eager, | |
| 875 | /// Return a scalar result, performing type resolution as necessary. | |
| 876 | /// This should typically be used from semantic analysis. | |
| 877 | sema, | |
| 878 | ||
| 879 | pub fn Tid(strat: ResolveStratLazy) type { | |
| 880 | return switch (strat) { | |
| 881 | .lazy, .sema => Zcu.PerThread.Id, | |
| 882 | .eager => void, | |
| 883 | }; | |
| 884 | } | |
| 885 | ||
| 886 | pub fn ZcuPtr(strat: ResolveStratLazy) type { | |
| 887 | return switch (strat) { | |
| 888 | .eager => *const Zcu, | |
| 889 | .sema, .lazy => *Zcu, | |
| 890 | }; | |
| 891 | } | |
| 892 | ||
| 893 | pub fn pt( | |
| 894 | comptime strat: ResolveStratLazy, | |
| 895 | zcu: strat.ZcuPtr(), | |
| 896 | tid: strat.Tid(), | |
| 897 | ) switch (strat) { | |
| 898 | .lazy, .sema => Zcu.PerThread, | |
| 899 | .eager => void, | |
| 900 | } { | |
| 901 | return switch (strat) { | |
| 902 | .lazy, .sema => .{ .tid = tid, .zcu = zcu }, | |
| 903 | else => {}, | |
| 904 | }; | |
| 905 | } | |
| 906 | }; | |
| 907 | ||
| 908 | /// The chosen strategy can be easily optimized away in release builds. | |
| 909 | /// However, in debug builds, it helps to avoid accidentally resolving types in backends. | |
| 910 | pub const ResolveStrat = enum { | |
| 911 | /// Assert that all necessary resolution is completed. | |
| 912 | /// Backends should typically use this, since they must not perform type resolution. | |
| 913 | normal, | |
| 914 | /// Perform type resolution as necessary using `Zcu`. | |
| 915 | /// This should typically be used from semantic analysis. | |
| 916 | sema, | |
| 917 | ||
| 918 | pub fn Tid(strat: ResolveStrat) type { | |
| 919 | return switch (strat) { | |
| 920 | .sema => Zcu.PerThread.Id, | |
| 921 | .normal => void, | |
| 922 | }; | |
| 923 | } | |
| 924 | ||
| 925 | pub fn ZcuPtr(strat: ResolveStrat) type { | |
| 926 | return switch (strat) { | |
| 927 | .normal => *const Zcu, | |
| 928 | .sema => *Zcu, | |
| 929 | }; | |
| 930 | } | |
| 931 | ||
| 932 | pub fn pt(comptime strat: ResolveStrat, zcu: strat.ZcuPtr(), tid: strat.Tid()) switch (strat) { | |
| 933 | .sema => Zcu.PerThread, | |
| 934 | .normal => void, | |
| 935 | } { | |
| 936 | return switch (strat) { | |
| 937 | .sema => .{ .tid = tid, .zcu = zcu }, | |
| 938 | .normal => {}, | |
| 939 | }; | |
| 940 | } | |
| 941 | ||
| 942 | pub inline fn toLazy(strat: ResolveStrat) ResolveStratLazy { | |
| 943 | return switch (strat) { | |
| 944 | .normal => .eager, | |
| 945 | .sema => .sema, | |
| 946 | }; | |
| 947 | } | |
| 948 | }; | |
| 949 | ||
| 950 | /// Never returns `none`. Asserts that all necessary type resolution is already done. | |
| 918 | /// Never returns `.none`. Asserts that the layout of `ty` is resolved. | |
| 919 | /// | |
| 920 | /// Unlike ABI size, a type's ABI alignment is not affected by its `Class`. In other words, any | |
| 921 | /// alignment is possible regardless of the result of `ty.classify(zcu)`. | |
| 951 | 922 | pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { |
| 952 | return (ty.abiAlignmentInner(.eager, zcu, {}) catch unreachable).scalar; | |
| 953 | } | |
| 954 | ||
| 955 | pub fn abiAlignmentSema(ty: Type, pt: Zcu.PerThread) SemaError!Alignment { | |
| 956 | return (try ty.abiAlignmentInner(.sema, pt.zcu, pt.tid)).scalar; | |
| 957 | } | |
| 958 | ||
| 959 | /// If you pass `eager` you will get back `scalar` and assert the type is resolved. | |
| 960 | /// In this case there will be no error, guaranteed. | |
| 961 | /// If you pass `lazy` you may get back `scalar` or `val`. | |
| 962 | /// If `val` is returned, a reference to `ty` has been captured. | |
| 963 | /// If you pass `sema` you will get back `scalar` and resolve the type if | |
| 964 | /// necessary, possibly returning a CompileError. | |
| 965 | pub fn abiAlignmentInner( | |
| 966 | ty: Type, | |
| 967 | comptime strat: ResolveStratLazy, | |
| 968 | zcu: strat.ZcuPtr(), | |
| 969 | tid: strat.Tid(), | |
| 970 | ) SemaError!AbiAlignmentInner { | |
| 971 | const pt = strat.pt(zcu, tid); | |
| 972 | const target = zcu.getTarget(); | |
| 973 | 923 | const ip = &zcu.intern_pool; |
| 924 | const target = zcu.getTarget(); | |
| 925 | assertHasLayout(ty, zcu); | |
| 926 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 927 | .int_type => |int_type| { | |
| 928 | if (int_type.bits == 0) return .@"1"; | |
| 929 | return .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)); | |
| 930 | }, | |
| 931 | .ptr_type, .anyframe_type => ptrAbiAlignment(target), | |
| 932 | .array_type => |array_type| Type.fromInterned(array_type.child).abiAlignment(zcu), | |
| 933 | .vector_type => |vector_type| { | |
| 934 | if (vector_type.len == 0) return .@"1"; | |
| 935 | switch (zcu.comp.getZigBackend()) { | |
| 936 | else => { | |
| 937 | const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)); | |
| 938 | if (elem_bits == 0) return .@"1"; | |
| 939 | const bytes = ((elem_bits * vector_type.len) + 7) / 8; | |
| 940 | return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); | |
| 941 | }, | |
| 942 | .stage2_c => return Type.fromInterned(vector_type.child).abiAlignment(zcu), | |
| 943 | .stage2_x86_64 => { | |
| 944 | if (vector_type.child == .bool_type) { | |
| 945 | if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64"; | |
| 946 | if (vector_type.len > 128 and target.cpu.has(.x86, .avx)) return .@"32"; | |
| 947 | if (vector_type.len > 64) return .@"16"; | |
| 948 | const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable; | |
| 949 | return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); | |
| 950 | } | |
| 951 | const elem_bytes: u32 = @intCast(Type.fromInterned(vector_type.child).abiSize(zcu)); | |
| 952 | if (elem_bytes == 0) return .@"1"; | |
| 953 | const bytes = elem_bytes * vector_type.len; | |
| 954 | if (bytes > 32 and target.cpu.has(.x86, .avx512f)) return .@"64"; | |
| 955 | if (bytes > 16 and target.cpu.has(.x86, .avx)) return .@"32"; | |
| 956 | return .@"16"; | |
| 957 | }, | |
| 958 | } | |
| 959 | }, | |
| 974 | 960 | |
| 975 | switch (ty.toIntern()) { | |
| 976 | .empty_tuple_type => return .{ .scalar = .@"1" }, | |
| 977 | else => switch (ip.indexToKey(ty.toIntern())) { | |
| 978 | .int_type => |int_type| { | |
| 979 | if (int_type.bits == 0) return .{ .scalar = .@"1" }; | |
| 980 | return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)) }; | |
| 981 | }, | |
| 982 | .ptr_type, .anyframe_type => { | |
| 983 | return .{ .scalar = ptrAbiAlignment(target) }; | |
| 984 | }, | |
| 985 | .array_type => |array_type| { | |
| 986 | return Type.fromInterned(array_type.child).abiAlignmentInner(strat, zcu, tid); | |
| 987 | }, | |
| 988 | .vector_type => |vector_type| { | |
| 989 | if (vector_type.len == 0) return .{ .scalar = .@"1" }; | |
| 990 | switch (zcu.comp.getZigBackend()) { | |
| 991 | else => { | |
| 992 | // This is fine because the child type of a vector always has a bit-size known | |
| 993 | // without needing any type resolution. | |
| 994 | const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)); | |
| 995 | if (elem_bits == 0) return .{ .scalar = .@"1" }; | |
| 996 | const bytes = ((elem_bits * vector_type.len) + 7) / 8; | |
| 997 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | |
| 998 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; | |
| 999 | }, | |
| 1000 | .stage2_c => { | |
| 1001 | return Type.fromInterned(vector_type.child).abiAlignmentInner(strat, zcu, tid); | |
| 1002 | }, | |
| 1003 | .stage2_x86_64 => { | |
| 1004 | if (vector_type.child == .bool_type) { | |
| 1005 | if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .{ .scalar = .@"64" }; | |
| 1006 | if (vector_type.len > 128 and target.cpu.has(.x86, .avx)) return .{ .scalar = .@"32" }; | |
| 1007 | if (vector_type.len > 64) return .{ .scalar = .@"16" }; | |
| 1008 | const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable; | |
| 1009 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | |
| 1010 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; | |
| 1011 | } | |
| 1012 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar); | |
| 1013 | if (elem_bytes == 0) return .{ .scalar = .@"1" }; | |
| 1014 | const bytes = elem_bytes * vector_type.len; | |
| 1015 | if (bytes > 32 and target.cpu.has(.x86, .avx512f)) return .{ .scalar = .@"64" }; | |
| 1016 | if (bytes > 16 and target.cpu.has(.x86, .avx)) return .{ .scalar = .@"32" }; | |
| 1017 | return .{ .scalar = .@"16" }; | |
| 1018 | }, | |
| 1019 | } | |
| 1020 | }, | |
| 961 | .opt_type => |child| Type.fromInterned(child).abiAlignment(zcu), | |
| 962 | .error_union_type => |eu| Alignment.maxStrict( | |
| 963 | Type.fromInterned(eu.payload_type).abiAlignment(zcu), | |
| 964 | errorAbiAlignment(zcu), | |
| 965 | ), | |
| 1021 | 966 | |
| 1022 | .opt_type => return ty.abiAlignmentInnerOptional(strat, zcu, tid), | |
| 1023 | .error_union_type => |info| return ty.abiAlignmentInnerErrorUnion( | |
| 1024 | strat, | |
| 1025 | zcu, | |
| 1026 | tid, | |
| 1027 | Type.fromInterned(info.payload_type), | |
| 1028 | ), | |
| 967 | .error_set_type, .inferred_error_set_type => errorAbiAlignment(zcu), | |
| 1029 | 968 | |
| 1030 | .error_set_type, .inferred_error_set_type => { | |
| 1031 | const bits = zcu.errorSetBits(); | |
| 1032 | if (bits == 0) return .{ .scalar = .@"1" }; | |
| 1033 | return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) }; | |
| 1034 | }, | |
| 969 | .func_type => target_util.minFunctionAlignment(target), | |
| 1035 | 970 | |
| 1036 | // represents machine code; not a pointer | |
| 1037 | .func_type => return .{ .scalar = target_util.minFunctionAlignment(target) }, | |
| 1038 | ||
| 1039 | .simple_type => |t| switch (t) { | |
| 1040 | .bool, | |
| 1041 | .anyopaque, | |
| 1042 | => return .{ .scalar = .@"1" }, | |
| 1043 | ||
| 1044 | .usize, | |
| 1045 | .isize, | |
| 1046 | => return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())) }, | |
| 1047 | ||
| 1048 | .c_char => return .{ .scalar = cTypeAlign(target, .char) }, | |
| 1049 | .c_short => return .{ .scalar = cTypeAlign(target, .short) }, | |
| 1050 | .c_ushort => return .{ .scalar = cTypeAlign(target, .ushort) }, | |
| 1051 | .c_int => return .{ .scalar = cTypeAlign(target, .int) }, | |
| 1052 | .c_uint => return .{ .scalar = cTypeAlign(target, .uint) }, | |
| 1053 | .c_long => return .{ .scalar = cTypeAlign(target, .long) }, | |
| 1054 | .c_ulong => return .{ .scalar = cTypeAlign(target, .ulong) }, | |
| 1055 | .c_longlong => return .{ .scalar = cTypeAlign(target, .longlong) }, | |
| 1056 | .c_ulonglong => return .{ .scalar = cTypeAlign(target, .ulonglong) }, | |
| 1057 | .c_longdouble => return .{ .scalar = cTypeAlign(target, .longdouble) }, | |
| 1058 | ||
| 1059 | .f16 => return .{ .scalar = .@"2" }, | |
| 1060 | .f32 => return .{ .scalar = cTypeAlign(target, .float) }, | |
| 1061 | .f64 => switch (target.cTypeBitSize(.double)) { | |
| 1062 | 64 => return .{ .scalar = cTypeAlign(target, .double) }, | |
| 1063 | else => return .{ .scalar = .@"8" }, | |
| 1064 | }, | |
| 1065 | .f80 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1066 | 80 => return .{ .scalar = cTypeAlign(target, .longdouble) }, | |
| 1067 | else => return .{ .scalar = Type.u80.abiAlignment(zcu) }, | |
| 1068 | }, | |
| 1069 | .f128 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1070 | 128 => return .{ .scalar = cTypeAlign(target, .longdouble) }, | |
| 1071 | else => return .{ .scalar = .@"16" }, | |
| 1072 | }, | |
| 1073 | ||
| 1074 | .anyerror, .adhoc_inferred_error_set => { | |
| 1075 | const bits = zcu.errorSetBits(); | |
| 1076 | if (bits == 0) return .{ .scalar = .@"1" }; | |
| 1077 | return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) }; | |
| 1078 | }, | |
| 1079 | ||
| 1080 | .void, | |
| 1081 | .type, | |
| 1082 | .comptime_int, | |
| 1083 | .comptime_float, | |
| 1084 | .null, | |
| 1085 | .undefined, | |
| 1086 | .enum_literal, | |
| 1087 | => return .{ .scalar = .@"1" }, | |
| 1088 | ||
| 1089 | .noreturn => unreachable, | |
| 1090 | .generic_poison => unreachable, | |
| 1091 | }, | |
| 1092 | .struct_type => { | |
| 1093 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 1094 | if (struct_type.layout == .@"packed") { | |
| 1095 | switch (strat) { | |
| 1096 | .sema => try ty.resolveLayout(pt), | |
| 1097 | .lazy => if (struct_type.backingIntTypeUnordered(ip) == .none) return .{ | |
| 1098 | .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1099 | .ty = .comptime_int_type, | |
| 1100 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1101 | } })), | |
| 1102 | }, | |
| 1103 | .eager => {}, | |
| 1104 | } | |
| 1105 | return .{ .scalar = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)).abiAlignment(zcu) }; | |
| 1106 | } | |
| 1107 | ||
| 1108 | if (struct_type.flagsUnordered(ip).alignment == .none) switch (strat) { | |
| 1109 | .eager => unreachable, // struct alignment not resolved | |
| 1110 | .sema => try ty.resolveStructAlignment(pt), | |
| 1111 | .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1112 | .ty = .comptime_int_type, | |
| 1113 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1114 | } })) }, | |
| 1115 | }; | |
| 1116 | ||
| 1117 | return .{ .scalar = struct_type.flagsUnordered(ip).alignment }; | |
| 1118 | }, | |
| 1119 | .tuple_type => |tuple| { | |
| 1120 | var big_align: Alignment = .@"1"; | |
| 1121 | for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { | |
| 1122 | if (val != .none) continue; // comptime field | |
| 1123 | switch (try Type.fromInterned(field_ty).abiAlignmentInner(strat, zcu, tid)) { | |
| 1124 | .scalar => |field_align| big_align = big_align.max(field_align), | |
| 1125 | .val => switch (strat) { | |
| 1126 | .eager => unreachable, // field type alignment not resolved | |
| 1127 | .sema => unreachable, // passed to abiAlignmentInner above | |
| 1128 | .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1129 | .ty = .comptime_int_type, | |
| 1130 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1131 | } })) }, | |
| 1132 | }, | |
| 1133 | } | |
| 1134 | } | |
| 1135 | return .{ .scalar = big_align }; | |
| 971 | .simple_type => |t| switch (t) { | |
| 972 | .bool, | |
| 973 | .void, | |
| 974 | .noreturn, | |
| 975 | .anyopaque, | |
| 976 | .type, | |
| 977 | .comptime_int, | |
| 978 | .comptime_float, | |
| 979 | .null, | |
| 980 | .undefined, | |
| 981 | .enum_literal, | |
| 982 | => .@"1", | |
| 983 | ||
| 984 | .anyerror, .adhoc_inferred_error_set => errorAbiAlignment(zcu), | |
| 985 | .usize, .isize => .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 986 | ||
| 987 | .c_char => cTypeAlign(target, .char), | |
| 988 | .c_short => cTypeAlign(target, .short), | |
| 989 | .c_ushort => cTypeAlign(target, .ushort), | |
| 990 | .c_int => cTypeAlign(target, .int), | |
| 991 | .c_uint => cTypeAlign(target, .uint), | |
| 992 | .c_long => cTypeAlign(target, .long), | |
| 993 | .c_ulong => cTypeAlign(target, .ulong), | |
| 994 | .c_longlong => cTypeAlign(target, .longlong), | |
| 995 | .c_ulonglong => cTypeAlign(target, .ulonglong), | |
| 996 | .c_longdouble => cTypeAlign(target, .longdouble), | |
| 997 | ||
| 998 | .f16 => .@"2", | |
| 999 | .f32 => cTypeAlign(target, .float), | |
| 1000 | .f64 => switch (target.cTypeBitSize(.double)) { | |
| 1001 | 64 => cTypeAlign(target, .double), | |
| 1002 | else => .@"8", | |
| 1136 | 1003 | }, |
| 1137 | .union_type => { | |
| 1138 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 1139 | ||
| 1140 | if (union_type.flagsUnordered(ip).alignment == .none) switch (strat) { | |
| 1141 | .eager => unreachable, // union layout not resolved | |
| 1142 | .sema => try ty.resolveUnionAlignment(pt), | |
| 1143 | .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1144 | .ty = .comptime_int_type, | |
| 1145 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1146 | } })) }, | |
| 1147 | }; | |
| 1148 | ||
| 1149 | return .{ .scalar = union_type.flagsUnordered(ip).alignment }; | |
| 1004 | .f80 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1005 | 80 => cTypeAlign(target, .longdouble), | |
| 1006 | else => Type.u80.abiAlignment(zcu), | |
| 1150 | 1007 | }, |
| 1151 | .opaque_type => return .{ .scalar = .@"1" }, | |
| 1152 | .enum_type => return .{ | |
| 1153 | .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(zcu), | |
| 1008 | .f128 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1009 | 128 => cTypeAlign(target, .longdouble), | |
| 1010 | else => .@"16", | |
| 1154 | 1011 | }, |
| 1155 | 1012 | |
| 1156 | // values, not types | |
| 1157 | .undef, | |
| 1158 | .simple_value, | |
| 1159 | .variable, | |
| 1160 | .@"extern", | |
| 1161 | .func, | |
| 1162 | .int, | |
| 1163 | .err, | |
| 1164 | .error_union, | |
| 1165 | .enum_literal, | |
| 1166 | .enum_tag, | |
| 1167 | .empty_enum_value, | |
| 1168 | .float, | |
| 1169 | .ptr, | |
| 1170 | .slice, | |
| 1171 | .opt, | |
| 1172 | .aggregate, | |
| 1173 | .un, | |
| 1174 | // memoization, not types | |
| 1175 | .memoized_call, | |
| 1176 | => unreachable, | |
| 1013 | .generic_poison => unreachable, | |
| 1177 | 1014 | }, |
| 1178 | } | |
| 1179 | } | |
| 1180 | ||
| 1181 | fn abiAlignmentInnerErrorUnion( | |
| 1182 | ty: Type, | |
| 1183 | comptime strat: ResolveStratLazy, | |
| 1184 | zcu: strat.ZcuPtr(), | |
| 1185 | tid: strat.Tid(), | |
| 1186 | payload_ty: Type, | |
| 1187 | ) SemaError!AbiAlignmentInner { | |
| 1188 | // This code needs to be kept in sync with the equivalent switch prong | |
| 1189 | // in abiSizeInner. | |
| 1190 | const code_align = Type.anyerror.abiAlignment(zcu); | |
| 1191 | switch (strat) { | |
| 1192 | .eager, .sema => { | |
| 1193 | if (!(payload_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { | |
| 1194 | error.NeedLazy => if (strat == .lazy) { | |
| 1195 | const pt = strat.pt(zcu, tid); | |
| 1196 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1197 | .ty = .comptime_int_type, | |
| 1198 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1199 | } })) }; | |
| 1200 | } else unreachable, | |
| 1201 | else => |e| return e, | |
| 1202 | })) { | |
| 1203 | return .{ .scalar = code_align }; | |
| 1204 | } | |
| 1205 | return .{ .scalar = code_align.max( | |
| 1206 | (try payload_ty.abiAlignmentInner(strat, zcu, tid)).scalar, | |
| 1207 | ) }; | |
| 1208 | }, | |
| 1209 | .lazy => { | |
| 1210 | const pt = strat.pt(zcu, tid); | |
| 1211 | switch (try payload_ty.abiAlignmentInner(strat, zcu, tid)) { | |
| 1212 | .scalar => |payload_align| return .{ .scalar = code_align.max(payload_align) }, | |
| 1213 | .val => {}, | |
| 1015 | .tuple_type => |tuple| { | |
| 1016 | var big_align: Alignment = .@"1"; | |
| 1017 | for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { | |
| 1018 | if (val != .none) continue; // comptime field | |
| 1019 | const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); | |
| 1020 | big_align = big_align.maxStrict(field_align); | |
| 1214 | 1021 | } |
| 1215 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1216 | .ty = .comptime_int_type, | |
| 1217 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1218 | } })) }; | |
| 1022 | return big_align; | |
| 1219 | 1023 | }, |
| 1220 | } | |
| 1221 | } | |
| 1222 | ||
| 1223 | fn abiAlignmentInnerOptional( | |
| 1224 | ty: Type, | |
| 1225 | comptime strat: ResolveStratLazy, | |
| 1226 | zcu: strat.ZcuPtr(), | |
| 1227 | tid: strat.Tid(), | |
| 1228 | ) SemaError!AbiAlignmentInner { | |
| 1229 | const pt = strat.pt(zcu, tid); | |
| 1230 | const target = zcu.getTarget(); | |
| 1231 | const child_type = ty.optionalChild(zcu); | |
| 1232 | ||
| 1233 | switch (child_type.zigTypeTag(zcu)) { | |
| 1234 | .pointer => return .{ .scalar = ptrAbiAlignment(target) }, | |
| 1235 | .error_set => return Type.anyerror.abiAlignmentInner(strat, zcu, tid), | |
| 1236 | .noreturn => return .{ .scalar = .@"1" }, | |
| 1237 | else => {}, | |
| 1238 | } | |
| 1239 | ||
| 1240 | switch (strat) { | |
| 1241 | .eager, .sema => { | |
| 1242 | if (!(child_type.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { | |
| 1243 | error.NeedLazy => if (strat == .lazy) { | |
| 1244 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1245 | .ty = .comptime_int_type, | |
| 1246 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1247 | } })) }; | |
| 1248 | } else unreachable, | |
| 1249 | else => |e| return e, | |
| 1250 | })) { | |
| 1251 | return .{ .scalar = .@"1" }; | |
| 1024 | .struct_type => { | |
| 1025 | const struct_obj = ip.loadStructType(ty.toIntern()); | |
| 1026 | switch (struct_obj.layout) { | |
| 1027 | .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiAlignment(zcu), | |
| 1028 | .auto, .@"extern" => { | |
| 1029 | assert(struct_obj.alignment != .none); | |
| 1030 | return struct_obj.alignment; | |
| 1031 | }, | |
| 1252 | 1032 | } |
| 1253 | return child_type.abiAlignmentInner(strat, zcu, tid); | |
| 1254 | 1033 | }, |
| 1255 | .lazy => switch (try child_type.abiAlignmentInner(strat, zcu, tid)) { | |
| 1256 | .scalar => |x| return .{ .scalar = x.max(.@"1") }, | |
| 1257 | .val => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1258 | .ty = .comptime_int_type, | |
| 1259 | .storage = .{ .lazy_align = ty.toIntern() }, | |
| 1260 | } })) }, | |
| 1034 | .union_type => { | |
| 1035 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 1036 | switch (union_obj.layout) { | |
| 1037 | .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiAlignment(zcu), | |
| 1038 | .auto, .@"extern" => { | |
| 1039 | assert(union_obj.alignment != .none); | |
| 1040 | return union_obj.alignment; | |
| 1041 | }, | |
| 1042 | } | |
| 1261 | 1043 | }, |
| 1262 | } | |
| 1263 | } | |
| 1264 | ||
| 1265 | const AbiSizeInner = union(enum) { | |
| 1266 | scalar: u64, | |
| 1267 | val: Value, | |
| 1268 | }; | |
| 1269 | ||
| 1270 | /// Asserts the type has the ABI size already resolved. | |
| 1271 | /// Types that return false for hasRuntimeBits() return 0. | |
| 1272 | pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { | |
| 1273 | return (abiSizeInner(ty, .eager, zcu, {}) catch unreachable).scalar; | |
| 1274 | } | |
| 1044 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiAlignment(zcu), | |
| 1045 | .opaque_type => .@"1", | |
| 1275 | 1046 | |
| 1276 | /// May capture a reference to `ty`. | |
| 1277 | pub fn abiSizeLazy(ty: Type, pt: Zcu.PerThread) !Value { | |
| 1278 | switch (try ty.abiSizeInner(.lazy, pt.zcu, pt.tid)) { | |
| 1279 | .val => |val| return val, | |
| 1280 | .scalar => |x| return pt.intValue(Type.comptime_int, x), | |
| 1281 | } | |
| 1282 | } | |
| 1283 | ||
| 1284 | pub fn abiSizeSema(ty: Type, pt: Zcu.PerThread) SemaError!u64 { | |
| 1285 | return (try abiSizeInner(ty, .sema, pt.zcu, pt.tid)).scalar; | |
| 1047 | // values, not types | |
| 1048 | .undef, | |
| 1049 | .simple_value, | |
| 1050 | .variable, | |
| 1051 | .@"extern", | |
| 1052 | .func, | |
| 1053 | .int, | |
| 1054 | .err, | |
| 1055 | .error_union, | |
| 1056 | .enum_literal, | |
| 1057 | .enum_tag, | |
| 1058 | .float, | |
| 1059 | .ptr, | |
| 1060 | .slice, | |
| 1061 | .opt, | |
| 1062 | .aggregate, | |
| 1063 | .un, | |
| 1064 | .bitpack, | |
| 1065 | // memoization, not types | |
| 1066 | .memoized_call, | |
| 1067 | => unreachable, | |
| 1068 | }; | |
| 1286 | 1069 | } |
| 1287 | 1070 | |
| 1288 | /// If you pass `eager` you will get back `scalar` and assert the type is resolved. | |
| 1289 | /// In this case there will be no error, guaranteed. | |
| 1290 | /// If you pass `lazy` you may get back `scalar` or `val`. | |
| 1291 | /// If `val` is returned, a reference to `ty` has been captured. | |
| 1292 | /// If you pass `sema` you will get back `scalar` and resolve the type if | |
| 1293 | /// necessary, possibly returning a CompileError. | |
| 1294 | pub fn abiSizeInner( | |
| 1295 | ty: Type, | |
| 1296 | comptime strat: ResolveStratLazy, | |
| 1297 | zcu: strat.ZcuPtr(), | |
| 1298 | tid: strat.Tid(), | |
| 1299 | ) SemaError!AbiSizeInner { | |
| 1300 | const target = zcu.getTarget(); | |
| 1071 | /// Asserts that `ty` is not an opaque type, and that the layout of `ty` is resolved. | |
| 1072 | /// | |
| 1073 | /// If the type is NPV, OPV, or fully-comptime (see `Class`), the return value of this function is | |
| 1074 | /// guaranteed to be zero. Otherwise (if the type is runtime or partially-comptime) the return value | |
| 1075 | /// is guaranteed to be non-zero. | |
| 1076 | pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { | |
| 1301 | 1077 | const ip = &zcu.intern_pool; |
| 1302 | ||
| 1303 | switch (ty.toIntern()) { | |
| 1304 | .empty_tuple_type => return .{ .scalar = 0 }, | |
| 1305 | ||
| 1306 | else => switch (ip.indexToKey(ty.toIntern())) { | |
| 1307 | .int_type => |int_type| { | |
| 1308 | if (int_type.bits == 0) return .{ .scalar = 0 }; | |
| 1309 | return .{ .scalar = std.zig.target.intByteSize(target, int_type.bits) }; | |
| 1310 | }, | |
| 1311 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | |
| 1312 | .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, | |
| 1313 | else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | |
| 1314 | }, | |
| 1315 | .anyframe_type => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | |
| 1316 | ||
| 1317 | .array_type => |array_type| { | |
| 1318 | const len = array_type.lenIncludingSentinel(); | |
| 1319 | if (len == 0) return .{ .scalar = 0 }; | |
| 1320 | switch (try Type.fromInterned(array_type.child).abiSizeInner(strat, zcu, tid)) { | |
| 1321 | .scalar => |elem_size| return .{ .scalar = len * elem_size }, | |
| 1322 | .val => switch (strat) { | |
| 1323 | .sema, .eager => unreachable, | |
| 1324 | .lazy => { | |
| 1325 | const pt = strat.pt(zcu, tid); | |
| 1326 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1327 | .ty = .comptime_int_type, | |
| 1328 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1329 | } })) }; | |
| 1330 | }, | |
| 1331 | }, | |
| 1332 | } | |
| 1333 | }, | |
| 1334 | .vector_type => |vector_type| { | |
| 1335 | const sub_strat: ResolveStrat = switch (strat) { | |
| 1336 | .sema => .sema, | |
| 1337 | .eager => .normal, | |
| 1338 | .lazy => { | |
| 1339 | const pt = strat.pt(zcu, tid); | |
| 1340 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1341 | .ty = .comptime_int_type, | |
| 1342 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1343 | } })) }; | |
| 1344 | }, | |
| 1345 | }; | |
| 1346 | const alignment = (try ty.abiAlignmentInner(strat, zcu, tid)).scalar; | |
| 1347 | const total_bytes = switch (zcu.comp.getZigBackend()) { | |
| 1348 | else => total_bytes: { | |
| 1349 | const elem_bits = try Type.fromInterned(vector_type.child).bitSizeInner(sub_strat, zcu, tid); | |
| 1350 | const total_bits = elem_bits * vector_type.len; | |
| 1351 | break :total_bytes (total_bits + 7) / 8; | |
| 1352 | }, | |
| 1353 | .stage2_c => total_bytes: { | |
| 1354 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar); | |
| 1355 | break :total_bytes elem_bytes * vector_type.len; | |
| 1356 | }, | |
| 1357 | .stage2_x86_64 => total_bytes: { | |
| 1358 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; | |
| 1359 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar); | |
| 1360 | break :total_bytes elem_bytes * vector_type.len; | |
| 1361 | }, | |
| 1362 | }; | |
| 1363 | return .{ .scalar = alignment.forward(total_bytes) }; | |
| 1364 | }, | |
| 1365 | ||
| 1366 | .opt_type => return ty.abiSizeInnerOptional(strat, zcu, tid), | |
| 1367 | ||
| 1368 | .error_set_type, .inferred_error_set_type => { | |
| 1369 | const bits = zcu.errorSetBits(); | |
| 1370 | if (bits == 0) return .{ .scalar = 0 }; | |
| 1371 | return .{ .scalar = std.zig.target.intByteSize(target, bits) }; | |
| 1372 | }, | |
| 1373 | ||
| 1374 | .error_union_type => |error_union_type| { | |
| 1375 | const payload_ty = Type.fromInterned(error_union_type.payload_type); | |
| 1376 | // This code needs to be kept in sync with the equivalent switch prong | |
| 1377 | // in abiAlignmentInner. | |
| 1378 | const code_size = Type.anyerror.abiSize(zcu); | |
| 1379 | if (!(payload_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { | |
| 1380 | error.NeedLazy => if (strat == .lazy) { | |
| 1381 | const pt = strat.pt(zcu, tid); | |
| 1382 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1383 | .ty = .comptime_int_type, | |
| 1384 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1385 | } })) }; | |
| 1386 | } else unreachable, | |
| 1387 | else => |e| return e, | |
| 1388 | })) { | |
| 1389 | // Same as anyerror. | |
| 1390 | return .{ .scalar = code_size }; | |
| 1391 | } | |
| 1392 | const code_align = Type.anyerror.abiAlignment(zcu); | |
| 1393 | const payload_align = (try payload_ty.abiAlignmentInner(strat, zcu, tid)).scalar; | |
| 1394 | const payload_size = switch (try payload_ty.abiSizeInner(strat, zcu, tid)) { | |
| 1395 | .scalar => |elem_size| elem_size, | |
| 1396 | .val => switch (strat) { | |
| 1397 | .sema => unreachable, | |
| 1398 | .eager => unreachable, | |
| 1399 | .lazy => { | |
| 1400 | const pt = strat.pt(zcu, tid); | |
| 1401 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1402 | .ty = .comptime_int_type, | |
| 1403 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1404 | } })) }; | |
| 1405 | }, | |
| 1406 | }, | |
| 1407 | }; | |
| 1408 | ||
| 1409 | var size: u64 = 0; | |
| 1410 | if (code_align.compare(.gt, payload_align)) { | |
| 1411 | size += code_size; | |
| 1412 | size = payload_align.forward(size); | |
| 1413 | size += payload_size; | |
| 1414 | size = code_align.forward(size); | |
| 1415 | } else { | |
| 1416 | size += payload_size; | |
| 1417 | size = code_align.forward(size); | |
| 1418 | size += code_size; | |
| 1419 | size = payload_align.forward(size); | |
| 1420 | } | |
| 1421 | return .{ .scalar = size }; | |
| 1422 | }, | |
| 1423 | .func_type => unreachable, // represents machine code; not a pointer | |
| 1424 | .simple_type => |t| switch (t) { | |
| 1425 | .bool => return .{ .scalar = 1 }, | |
| 1426 | ||
| 1427 | .f16 => return .{ .scalar = 2 }, | |
| 1428 | .f32 => return .{ .scalar = 4 }, | |
| 1429 | .f64 => return .{ .scalar = 8 }, | |
| 1430 | .f128 => return .{ .scalar = 16 }, | |
| 1431 | .f80 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1432 | 80 => return .{ .scalar = target.cTypeByteSize(.longdouble) }, | |
| 1433 | else => return .{ .scalar = Type.u80.abiSize(zcu) }, | |
| 1434 | }, | |
| 1435 | ||
| 1436 | .usize, | |
| 1437 | .isize, | |
| 1438 | => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | |
| 1439 | ||
| 1440 | .c_char => return .{ .scalar = target.cTypeByteSize(.char) }, | |
| 1441 | .c_short => return .{ .scalar = target.cTypeByteSize(.short) }, | |
| 1442 | .c_ushort => return .{ .scalar = target.cTypeByteSize(.ushort) }, | |
| 1443 | .c_int => return .{ .scalar = target.cTypeByteSize(.int) }, | |
| 1444 | .c_uint => return .{ .scalar = target.cTypeByteSize(.uint) }, | |
| 1445 | .c_long => return .{ .scalar = target.cTypeByteSize(.long) }, | |
| 1446 | .c_ulong => return .{ .scalar = target.cTypeByteSize(.ulong) }, | |
| 1447 | .c_longlong => return .{ .scalar = target.cTypeByteSize(.longlong) }, | |
| 1448 | .c_ulonglong => return .{ .scalar = target.cTypeByteSize(.ulonglong) }, | |
| 1449 | .c_longdouble => return .{ .scalar = target.cTypeByteSize(.longdouble) }, | |
| 1450 | ||
| 1451 | .anyopaque, | |
| 1452 | .void, | |
| 1453 | .type, | |
| 1454 | .comptime_int, | |
| 1455 | .comptime_float, | |
| 1456 | .null, | |
| 1457 | .undefined, | |
| 1458 | .enum_literal, | |
| 1459 | => return .{ .scalar = 0 }, | |
| 1460 | ||
| 1461 | .anyerror, .adhoc_inferred_error_set => { | |
| 1462 | const bits = zcu.errorSetBits(); | |
| 1463 | if (bits == 0) return .{ .scalar = 0 }; | |
| 1464 | return .{ .scalar = std.zig.target.intByteSize(target, bits) }; | |
| 1078 | const target = zcu.getTarget(); | |
| 1079 | assertHasLayout(ty, zcu); | |
| 1080 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 1081 | .int_type => |int_type| std.zig.target.intByteSize(target, int_type.bits), | |
| 1082 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | |
| 1083 | .slice => ptrAbiSize(target) * 2, | |
| 1084 | .one, .many, .c => ptrAbiSize(target), | |
| 1085 | }, | |
| 1086 | .anyframe_type => ptrAbiSize(target), | |
| 1087 | .array_type => |arr| arr.lenIncludingSentinel() * Type.fromInterned(arr.child).abiSize(zcu), | |
| 1088 | .vector_type => |vec| { | |
| 1089 | const elem_ty: Type = .fromInterned(vec.child); | |
| 1090 | const bytes = switch (zcu.comp.getZigBackend()) { | |
| 1091 | else => std.math.divCeil(u64, vec.len * elem_ty.bitSize(zcu), 8) catch unreachable, | |
| 1092 | .stage2_c => vec.len * elem_ty.abiSize(zcu), | |
| 1093 | .stage2_x86_64 => switch (elem_ty.toIntern()) { | |
| 1094 | .bool_type => std.math.divCeil(u64, vec.len, 8) catch unreachable, | |
| 1095 | else => vec.len * elem_ty.abiSize(zcu), | |
| 1465 | 1096 | }, |
| 1466 | ||
| 1467 | .noreturn => unreachable, | |
| 1468 | .generic_poison => unreachable, | |
| 1469 | }, | |
| 1470 | .struct_type => { | |
| 1471 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 1472 | switch (strat) { | |
| 1473 | .sema => try ty.resolveLayout(strat.pt(zcu, tid)), | |
| 1474 | .lazy => { | |
| 1475 | const pt = strat.pt(zcu, tid); | |
| 1476 | switch (struct_type.layout) { | |
| 1477 | .@"packed" => { | |
| 1478 | if (struct_type.backingIntTypeUnordered(ip) == .none) return .{ | |
| 1479 | .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1480 | .ty = .comptime_int_type, | |
| 1481 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1482 | } })), | |
| 1483 | }; | |
| 1484 | }, | |
| 1485 | .auto, .@"extern" => { | |
| 1486 | if (!struct_type.haveLayout(ip)) return .{ | |
| 1487 | .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1488 | .ty = .comptime_int_type, | |
| 1489 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1490 | } })), | |
| 1491 | }; | |
| 1492 | }, | |
| 1493 | } | |
| 1494 | }, | |
| 1495 | .eager => {}, | |
| 1496 | } | |
| 1497 | switch (struct_type.layout) { | |
| 1498 | .@"packed" => return .{ | |
| 1499 | .scalar = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)).abiSize(zcu), | |
| 1500 | }, | |
| 1501 | .auto, .@"extern" => { | |
| 1502 | assert(struct_type.haveLayout(ip)); | |
| 1503 | return .{ .scalar = struct_type.sizeUnordered(ip) }; | |
| 1504 | }, | |
| 1505 | } | |
| 1506 | }, | |
| 1507 | .tuple_type => |tuple| { | |
| 1508 | switch (strat) { | |
| 1509 | .sema => try ty.resolveLayout(strat.pt(zcu, tid)), | |
| 1510 | .lazy, .eager => {}, | |
| 1511 | } | |
| 1512 | const field_count = tuple.types.len; | |
| 1513 | if (field_count == 0) { | |
| 1514 | return .{ .scalar = 0 }; | |
| 1515 | } | |
| 1516 | return .{ .scalar = ty.structFieldOffset(field_count, zcu) }; | |
| 1517 | }, | |
| 1518 | ||
| 1519 | .union_type => { | |
| 1520 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 1521 | switch (strat) { | |
| 1522 | .sema => try ty.resolveLayout(strat.pt(zcu, tid)), | |
| 1523 | .lazy => { | |
| 1524 | const pt = strat.pt(zcu, tid); | |
| 1525 | if (!union_type.flagsUnordered(ip).status.haveLayout()) return .{ | |
| 1526 | .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1527 | .ty = .comptime_int_type, | |
| 1528 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1529 | } })), | |
| 1530 | }; | |
| 1531 | }, | |
| 1532 | .eager => {}, | |
| 1533 | } | |
| 1534 | ||
| 1535 | assert(union_type.haveLayout(ip)); | |
| 1536 | return .{ .scalar = union_type.sizeUnordered(ip) }; | |
| 1097 | }; | |
| 1098 | return ty.abiAlignment(zcu).forward(bytes); | |
| 1099 | }, | |
| 1100 | .opt_type => |child_ty_ip| { | |
| 1101 | const child_ty: Type = .fromInterned(child_ty_ip); | |
| 1102 | if (child_ty.classify(zcu) == .no_possible_value) return 0; | |
| 1103 | if (ty.optionalReprIsPayload(zcu)) return child_ty.abiSize(zcu); | |
| 1104 | // Optional types are represented as a struct with the child type as the first | |
| 1105 | // field and a boolean as the second. Since the child type's abi alignment is | |
| 1106 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | |
| 1107 | // to the child type's ABI alignment. | |
| 1108 | return child_ty.abiSize(zcu) + child_ty.abiAlignment(zcu).toByteUnits().?; | |
| 1109 | }, | |
| 1110 | .error_set_type, .inferred_error_set_type => errorAbiSize(zcu), | |
| 1111 | .error_union_type => |error_union| { | |
| 1112 | const payload_ty: Type = .fromInterned(error_union.payload_type); | |
| 1113 | switch (payload_ty.classify(zcu)) { | |
| 1114 | // Zig has no way to take the address of the error set "in" an error union (giving | |
| 1115 | // implementations more freedom in terms of data layout), so if the payload type is | |
| 1116 | // fully comptime, we don't need to dedicate runtime bits to the error set. | |
| 1117 | .fully_comptime => return 0, | |
| 1118 | else => {}, | |
| 1119 | } | |
| 1120 | // The layout will either be (code, payload, padding) or (payload, code, padding) | |
| 1121 | // depending on which has larger alignment. So the overall size is just the code | |
| 1122 | // and payload sizes added and padded to the larger alignment. | |
| 1123 | const big_align: Alignment = .maxStrict(errorAbiAlignment(zcu), payload_ty.abiAlignment(zcu)); | |
| 1124 | return big_align.forward(errorAbiSize(zcu) + payload_ty.abiSize(zcu)); | |
| 1125 | }, | |
| 1126 | .func_type => 0, | |
| 1127 | .simple_type => |t| switch (t) { | |
| 1128 | .void, | |
| 1129 | .noreturn, | |
| 1130 | .type, | |
| 1131 | .comptime_int, | |
| 1132 | .comptime_float, | |
| 1133 | .null, | |
| 1134 | .undefined, | |
| 1135 | .enum_literal, | |
| 1136 | => 0, | |
| 1137 | ||
| 1138 | .bool => 1, | |
| 1139 | .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu), | |
| 1140 | .usize, .isize => ptrAbiSize(target), | |
| 1141 | ||
| 1142 | .c_char => target.cTypeByteSize(.char), | |
| 1143 | .c_short => target.cTypeByteSize(.short), | |
| 1144 | .c_ushort => target.cTypeByteSize(.ushort), | |
| 1145 | .c_int => target.cTypeByteSize(.int), | |
| 1146 | .c_uint => target.cTypeByteSize(.uint), | |
| 1147 | .c_long => target.cTypeByteSize(.long), | |
| 1148 | .c_ulong => target.cTypeByteSize(.ulong), | |
| 1149 | .c_longlong => target.cTypeByteSize(.longlong), | |
| 1150 | .c_ulonglong => target.cTypeByteSize(.ulonglong), | |
| 1151 | .c_longdouble => target.cTypeByteSize(.longdouble), | |
| 1152 | ||
| 1153 | .f16 => 2, | |
| 1154 | .f32 => 4, | |
| 1155 | .f64 => 8, | |
| 1156 | .f80 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1157 | 80 => target.cTypeByteSize(.longdouble), | |
| 1158 | else => Type.u80.abiSize(zcu), | |
| 1537 | 1159 | }, |
| 1538 | .opaque_type => unreachable, // no size available | |
| 1539 | .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(zcu) }, | |
| 1160 | .f128 => 16, | |
| 1540 | 1161 | |
| 1541 | // values, not types | |
| 1542 | .undef, | |
| 1543 | .simple_value, | |
| 1544 | .variable, | |
| 1545 | .@"extern", | |
| 1546 | .func, | |
| 1547 | .int, | |
| 1548 | .err, | |
| 1549 | .error_union, | |
| 1550 | .enum_literal, | |
| 1551 | .enum_tag, | |
| 1552 | .empty_enum_value, | |
| 1553 | .float, | |
| 1554 | .ptr, | |
| 1555 | .slice, | |
| 1556 | .opt, | |
| 1557 | .aggregate, | |
| 1558 | .un, | |
| 1559 | // memoization, not types | |
| 1560 | .memoized_call, | |
| 1561 | => unreachable, | |
| 1162 | .anyopaque => unreachable, | |
| 1163 | .generic_poison => unreachable, | |
| 1562 | 1164 | }, |
| 1563 | } | |
| 1564 | } | |
| 1565 | ||
| 1566 | fn abiSizeInnerOptional( | |
| 1567 | ty: Type, | |
| 1568 | comptime strat: ResolveStratLazy, | |
| 1569 | zcu: strat.ZcuPtr(), | |
| 1570 | tid: strat.Tid(), | |
| 1571 | ) SemaError!AbiSizeInner { | |
| 1572 | const child_ty = ty.optionalChild(zcu); | |
| 1573 | ||
| 1574 | if (child_ty.isNoReturn(zcu)) { | |
| 1575 | return .{ .scalar = 0 }; | |
| 1576 | } | |
| 1577 | ||
| 1578 | if (!(child_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { | |
| 1579 | error.NeedLazy => if (strat == .lazy) { | |
| 1580 | const pt = strat.pt(zcu, tid); | |
| 1581 | return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ | |
| 1582 | .ty = .comptime_int_type, | |
| 1583 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1584 | } })) }; | |
| 1585 | } else unreachable, | |
| 1586 | else => |e| return e, | |
| 1587 | })) return .{ .scalar = 1 }; | |
| 1588 | ||
| 1589 | if (ty.optionalReprIsPayload(zcu)) { | |
| 1590 | return child_ty.abiSizeInner(strat, zcu, tid); | |
| 1591 | } | |
| 1592 | ||
| 1593 | const payload_size = switch (try child_ty.abiSizeInner(strat, zcu, tid)) { | |
| 1594 | .scalar => |elem_size| elem_size, | |
| 1595 | .val => switch (strat) { | |
| 1596 | .sema => unreachable, | |
| 1597 | .eager => unreachable, | |
| 1598 | .lazy => return .{ .val = Value.fromInterned(try strat.pt(zcu, tid).intern(.{ .int = .{ | |
| 1599 | .ty = .comptime_int_type, | |
| 1600 | .storage = .{ .lazy_size = ty.toIntern() }, | |
| 1601 | } })) }, | |
| 1165 | .tuple_type => |tuple| switch (ty.classify(zcu)) { | |
| 1166 | // `structFieldOffset` is bogus on NPV tuples, because there may be some fields with | |
| 1167 | // non-zero size. | |
| 1168 | .no_possible_value => 0, | |
| 1169 | else => ty.structFieldOffset(tuple.types.len, zcu), | |
| 1602 | 1170 | }, |
| 1603 | }; | |
| 1171 | .struct_type => { | |
| 1172 | const struct_obj = ip.loadStructType(ty.toIntern()); | |
| 1173 | switch (struct_obj.layout) { | |
| 1174 | .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiSize(zcu), | |
| 1175 | .auto, .@"extern" => return struct_obj.size, | |
| 1176 | } | |
| 1177 | }, | |
| 1178 | .union_type => { | |
| 1179 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 1180 | switch (union_obj.layout) { | |
| 1181 | .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiSize(zcu), | |
| 1182 | .auto, .@"extern" => return union_obj.size, | |
| 1183 | } | |
| 1184 | }, | |
| 1185 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiSize(zcu), | |
| 1186 | .opaque_type => unreachable, | |
| 1604 | 1187 | |
| 1605 | // Optional types are represented as a struct with the child type as the first | |
| 1606 | // field and a boolean as the second. Since the child type's abi alignment is | |
| 1607 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | |
| 1608 | // to the child type's ABI alignment. | |
| 1609 | return .{ | |
| 1610 | .scalar = (child_ty.abiAlignment(zcu).toByteUnits() orelse 0) + payload_size, | |
| 1188 | // values, not types | |
| 1189 | .undef, | |
| 1190 | .simple_value, | |
| 1191 | .variable, | |
| 1192 | .@"extern", | |
| 1193 | .func, | |
| 1194 | .int, | |
| 1195 | .err, | |
| 1196 | .error_union, | |
| 1197 | .enum_literal, | |
| 1198 | .enum_tag, | |
| 1199 | .float, | |
| 1200 | .ptr, | |
| 1201 | .slice, | |
| 1202 | .opt, | |
| 1203 | .aggregate, | |
| 1204 | .un, | |
| 1205 | .bitpack, | |
| 1206 | // memoization, not types | |
| 1207 | .memoized_call, | |
| 1208 | => unreachable, | |
| 1611 | 1209 | }; |
| 1612 | 1210 | } |
| 1613 | 1211 | |
| 1614 | 1212 | pub fn ptrAbiAlignment(target: *const Target) Alignment { |
| 1615 | return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); | |
| 1213 | return .fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); | |
| 1616 | 1214 | } |
| 1617 | ||
| 1618 | pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { | |
| 1619 | return bitSizeInner(ty, .normal, zcu, {}) catch unreachable; | |
| 1215 | pub fn ptrAbiSize(target: *const Target) u64 { | |
| 1216 | return @divExact(target.ptrBitWidth(), 8); | |
| 1620 | 1217 | } |
| 1621 | ||
| 1622 | pub fn bitSizeSema(ty: Type, pt: Zcu.PerThread) SemaError!u64 { | |
| 1623 | return bitSizeInner(ty, .sema, pt.zcu, pt.tid); | |
| 1218 | pub fn errorAbiAlignment(zcu: *const Zcu) Alignment { | |
| 1219 | return .fromNonzeroByteUnits(std.zig.target.intAlignment(zcu.getTarget(), zcu.errorSetBits())); | |
| 1220 | } | |
| 1221 | pub fn errorAbiSize(zcu: *const Zcu) u64 { | |
| 1222 | return std.zig.target.intByteSize(zcu.getTarget(), zcu.errorSetBits()); | |
| 1624 | 1223 | } |
| 1625 | 1224 | |
| 1626 | pub fn bitSizeInner( | |
| 1627 | ty: Type, | |
| 1628 | comptime strat: ResolveStrat, | |
| 1629 | zcu: strat.ZcuPtr(), | |
| 1630 | tid: strat.Tid(), | |
| 1631 | ) SemaError!u64 { | |
| 1225 | /// Asserts that `ty` is not an opaque or comptime-only type. | |
| 1226 | /// Once #19755 is implemented, this query will only work on types with a defined bit-level representation. | |
| 1227 | pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { | |
| 1632 | 1228 | const target = zcu.getTarget(); |
| 1633 | 1229 | const ip = &zcu.intern_pool; |
| 1634 | ||
| 1635 | const strat_lazy: ResolveStratLazy = strat.toLazy(); | |
| 1636 | ||
| 1637 | switch (ip.indexToKey(ty.toIntern())) { | |
| 1638 | .int_type => |int_type| return int_type.bits, | |
| 1230 | assertHasLayout(ty, zcu); | |
| 1231 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 1232 | .int_type => |int_type| int_type.bits, | |
| 1639 | 1233 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 1640 | .slice => return target.ptrBitWidth() * 2, | |
| 1641 | else => return target.ptrBitWidth(), | |
| 1234 | .slice => target.ptrBitWidth() * 2, | |
| 1235 | else => target.ptrBitWidth(), | |
| 1642 | 1236 | }, |
| 1643 | .anyframe_type => return target.ptrBitWidth(), | |
| 1644 | ||
| 1237 | .anyframe_type => target.ptrBitWidth(), | |
| 1645 | 1238 | .array_type => |array_type| { |
| 1646 | const len = array_type.lenIncludingSentinel(); | |
| 1647 | if (len == 0) return 0; | |
| 1648 | 1239 | const elem_ty: Type = .fromInterned(array_type.child); |
| 1649 | switch (zcu.comp.getZigBackend()) { | |
| 1650 | else => { | |
| 1651 | const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar; | |
| 1652 | if (elem_size == 0) return 0; | |
| 1653 | const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid); | |
| 1654 | return (len - 1) * 8 * elem_size + elem_bit_size; | |
| 1655 | }, | |
| 1656 | .stage2_x86_64 => { | |
| 1657 | const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid); | |
| 1658 | return elem_bit_size * len; | |
| 1240 | const len = array_type.lenIncludingSentinel(); | |
| 1241 | return switch (zcu.comp.getZigBackend()) { | |
| 1242 | .stage2_x86_64 => len * elem_ty.bitSize(zcu), | |
| 1243 | // this case will be removed under #19755 | |
| 1244 | else => switch (len) { | |
| 1245 | 0 => 0, | |
| 1246 | else => (len - 1) * 8 * elem_ty.abiSize(zcu) + elem_ty.bitSize(zcu), | |
| 1659 | 1247 | }, |
| 1660 | } | |
| 1661 | }, | |
| 1662 | .vector_type => |vector_type| { | |
| 1663 | const child_ty: Type = .fromInterned(vector_type.child); | |
| 1664 | const elem_bit_size = try child_ty.bitSizeInner(strat, zcu, tid); | |
| 1665 | return elem_bit_size * vector_type.len; | |
| 1666 | }, | |
| 1667 | .opt_type => { | |
| 1668 | // Optionals and error unions are not packed so their bitsize | |
| 1669 | // includes padding bits. | |
| 1670 | return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; | |
| 1248 | }; | |
| 1671 | 1249 | }, |
| 1250 | .vector_type => |vec| vec.len * Type.fromInterned(vec.child).bitSize(zcu), | |
| 1251 | .error_set_type, .inferred_error_set_type => zcu.errorSetBits(), | |
| 1252 | .func_type => unreachable, | |
| 1672 | 1253 | |
| 1673 | .error_set_type, .inferred_error_set_type => return zcu.errorSetBits(), | |
| 1674 | ||
| 1675 | .error_union_type => { | |
| 1676 | // Optionals and error unions are not packed so their bitsize | |
| 1677 | // includes padding bits. | |
| 1678 | return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; | |
| 1679 | }, | |
| 1680 | .func_type => unreachable, // represents machine code; not a pointer | |
| 1681 | 1254 | .simple_type => |t| switch (t) { |
| 1682 | .f16 => return 16, | |
| 1683 | .f32 => return 32, | |
| 1684 | .f64 => return 64, | |
| 1685 | .f80 => return 80, | |
| 1686 | .f128 => return 128, | |
| 1687 | ||
| 1688 | .usize, | |
| 1689 | .isize, | |
| 1690 | => return target.ptrBitWidth(), | |
| 1691 | ||
| 1692 | .c_char => return target.cTypeBitSize(.char), | |
| 1693 | .c_short => return target.cTypeBitSize(.short), | |
| 1694 | .c_ushort => return target.cTypeBitSize(.ushort), | |
| 1695 | .c_int => return target.cTypeBitSize(.int), | |
| 1696 | .c_uint => return target.cTypeBitSize(.uint), | |
| 1697 | .c_long => return target.cTypeBitSize(.long), | |
| 1698 | .c_ulong => return target.cTypeBitSize(.ulong), | |
| 1699 | .c_longlong => return target.cTypeBitSize(.longlong), | |
| 1700 | .c_ulonglong => return target.cTypeBitSize(.ulonglong), | |
| 1701 | .c_longdouble => return target.cTypeBitSize(.longdouble), | |
| 1702 | ||
| 1703 | .bool => return 1, | |
| 1704 | .void => return 0, | |
| 1705 | ||
| 1706 | .anyerror, | |
| 1707 | .adhoc_inferred_error_set, | |
| 1708 | => return zcu.errorSetBits(), | |
| 1255 | .void => 0, | |
| 1256 | .bool => 1, | |
| 1257 | .anyerror, .adhoc_inferred_error_set => zcu.errorSetBits(), | |
| 1258 | .usize, .isize => target.ptrBitWidth(), | |
| 1259 | ||
| 1260 | .c_char => target.cTypeBitSize(.char), | |
| 1261 | .c_short => target.cTypeBitSize(.short), | |
| 1262 | .c_ushort => target.cTypeBitSize(.ushort), | |
| 1263 | .c_int => target.cTypeBitSize(.int), | |
| 1264 | .c_uint => target.cTypeBitSize(.uint), | |
| 1265 | .c_long => target.cTypeBitSize(.long), | |
| 1266 | .c_ulong => target.cTypeBitSize(.ulong), | |
| 1267 | .c_longlong => target.cTypeBitSize(.longlong), | |
| 1268 | .c_ulonglong => target.cTypeBitSize(.ulonglong), | |
| 1269 | .c_longdouble => target.cTypeBitSize(.longdouble), | |
| 1270 | ||
| 1271 | .f16 => 16, | |
| 1272 | .f32 => 32, | |
| 1273 | .f64 => 64, | |
| 1274 | .f80 => 80, | |
| 1275 | .f128 => 128, | |
| 1709 | 1276 | |
| 1710 | 1277 | .anyopaque => unreachable, |
| 1711 | 1278 | .type => unreachable, |
| ... | ... | @@ -1717,49 +1284,30 @@ pub fn bitSizeInner( |
| 1717 | 1284 | .enum_literal => unreachable, |
| 1718 | 1285 | .generic_poison => unreachable, |
| 1719 | 1286 | }, |
| 1287 | ||
| 1720 | 1288 | .struct_type => { |
| 1721 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 1722 | const is_packed = struct_type.layout == .@"packed"; | |
| 1723 | if (strat == .sema) { | |
| 1724 | const pt = strat.pt(zcu, tid); | |
| 1725 | try ty.resolveFields(pt); | |
| 1726 | if (is_packed) try ty.resolveLayout(pt); | |
| 1727 | } | |
| 1728 | if (is_packed) { | |
| 1729 | return try Type.fromInterned(struct_type.backingIntTypeUnordered(ip)) | |
| 1730 | .bitSizeInner(strat, zcu, tid); | |
| 1289 | const struct_obj = ip.loadStructType(ty.toIntern()); | |
| 1290 | switch (struct_obj.layout) { | |
| 1291 | .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).bitSize(zcu), | |
| 1292 | .auto, .@"extern" => return struct_obj.size * 8, // will be `unreachable` under #19755 | |
| 1731 | 1293 | } |
| 1732 | return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; | |
| 1733 | 1294 | }, |
| 1734 | ||
| 1735 | .tuple_type => { | |
| 1736 | return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; | |
| 1737 | }, | |
| 1738 | ||
| 1739 | 1295 | .union_type => { |
| 1740 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 1741 | const is_packed = ty.containerLayout(zcu) == .@"packed"; | |
| 1742 | if (strat == .sema) { | |
| 1743 | const pt = strat.pt(zcu, tid); | |
| 1744 | try ty.resolveFields(pt); | |
| 1745 | if (is_packed) try ty.resolveLayout(pt); | |
| 1746 | } | |
| 1747 | if (!is_packed) { | |
| 1748 | return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; | |
| 1296 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 1297 | switch (union_obj.layout) { | |
| 1298 | .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).bitSize(zcu), | |
| 1299 | .auto, .@"extern" => return union_obj.size * 8, // will be `unreachable` under #19755 | |
| 1749 | 1300 | } |
| 1750 | assert(union_type.flagsUnordered(ip).status.haveFieldTypes()); | |
| 1301 | }, | |
| 1302 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).bitSize(zcu), | |
| 1751 | 1303 | |
| 1752 | var size: u64 = 0; | |
| 1753 | for (0..union_type.field_types.len) |field_index| { | |
| 1754 | const field_ty = union_type.field_types.get(ip)[field_index]; | |
| 1755 | size = @max(size, try Type.fromInterned(field_ty).bitSizeInner(strat, zcu, tid)); | |
| 1756 | } | |
| 1304 | // will be `unreachable` under #19755 | |
| 1305 | .opt_type, | |
| 1306 | .error_union_type, | |
| 1307 | .tuple_type, | |
| 1308 | => ty.abiSize(zcu) * 8, | |
| 1757 | 1309 | |
| 1758 | return size; | |
| 1759 | }, | |
| 1760 | 1310 | .opaque_type => unreachable, |
| 1761 | .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty) | |
| 1762 | .bitSizeInner(strat, zcu, tid), | |
| 1763 | 1311 | |
| 1764 | 1312 | // values, not types |
| 1765 | 1313 | .undef, |
| ... | ... | @@ -1772,33 +1320,16 @@ pub fn bitSizeInner( |
| 1772 | 1320 | .error_union, |
| 1773 | 1321 | .enum_literal, |
| 1774 | 1322 | .enum_tag, |
| 1775 | .empty_enum_value, | |
| 1776 | 1323 | .float, |
| 1777 | 1324 | .ptr, |
| 1778 | .slice, | |
| 1779 | .opt, | |
| 1780 | .aggregate, | |
| 1781 | .un, | |
| 1782 | // memoization, not types | |
| 1783 | .memoized_call, | |
| 1784 | => unreachable, | |
| 1785 | } | |
| 1786 | } | |
| 1787 | ||
| 1788 | /// Returns true if the type's layout is already resolved and it is safe | |
| 1789 | /// to use `abiSize`, `abiAlignment` and `bitSize` on it. | |
| 1790 | pub fn layoutIsResolved(ty: Type, zcu: *const Zcu) bool { | |
| 1791 | const ip = &zcu.intern_pool; | |
| 1792 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 1793 | .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip), | |
| 1794 | .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip), | |
| 1795 | .array_type => |array_type| { | |
| 1796 | if (array_type.lenIncludingSentinel() == 0) return true; | |
| 1797 | return Type.fromInterned(array_type.child).layoutIsResolved(zcu); | |
| 1798 | }, | |
| 1799 | .opt_type => |child| Type.fromInterned(child).layoutIsResolved(zcu), | |
| 1800 | .error_union_type => |k| Type.fromInterned(k.payload_type).layoutIsResolved(zcu), | |
| 1801 | else => true, | |
| 1325 | .slice, | |
| 1326 | .opt, | |
| 1327 | .aggregate, | |
| 1328 | .un, | |
| 1329 | .bitpack, | |
| 1330 | // memoization, not types | |
| 1331 | .memoized_call, | |
| 1332 | => unreachable, | |
| 1802 | 1333 | }; |
| 1803 | 1334 | } |
| 1804 | 1335 | |
| ... | ... | @@ -1841,7 +1372,7 @@ pub fn isSliceAtRuntime(ty: Type, zcu: *const Zcu) bool { |
| 1841 | 1372 | } |
| 1842 | 1373 | |
| 1843 | 1374 | pub fn slicePtrFieldType(ty: Type, zcu: *const Zcu) Type { |
| 1844 | return Type.fromInterned(zcu.intern_pool.slicePtrType(ty.toIntern())); | |
| 1375 | return .fromInterned(zcu.intern_pool.slicePtrType(ty.toIntern())); | |
| 1845 | 1376 | } |
| 1846 | 1377 | |
| 1847 | 1378 | pub fn isConstPtr(ty: Type, zcu: *const Zcu) bool { |
| ... | ... | @@ -1897,10 +1428,7 @@ pub fn isPtrAtRuntime(ty: Type, zcu: *const Zcu) bool { |
| 1897 | 1428 | /// For pointer-like optionals, returns true, otherwise returns the allowzero property |
| 1898 | 1429 | /// of pointers. |
| 1899 | 1430 | pub fn ptrAllowsZero(ty: Type, zcu: *const Zcu) bool { |
| 1900 | if (ty.isPtrLikeOptional(zcu)) { | |
| 1901 | return true; | |
| 1902 | } | |
| 1903 | return ty.ptrInfo(zcu).flags.is_allowzero; | |
| 1431 | return ty.isPtrLikeOptional(zcu) or ty.ptrInfo(zcu).flags.is_allowzero; | |
| 1904 | 1432 | } |
| 1905 | 1433 | |
| 1906 | 1434 | /// See also `isPtrLikeOptional`. |
| ... | ... | @@ -1918,7 +1446,6 @@ pub fn optionalReprIsPayload(ty: Type, zcu: *const Zcu) bool { |
| 1918 | 1446 | |
| 1919 | 1447 | /// Returns true if the type is optional and would be lowered to a single pointer |
| 1920 | 1448 | /// address value, using 0 for null. Note that this returns true for C pointers. |
| 1921 | /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`. | |
| 1922 | 1449 | pub fn isPtrLikeOptional(ty: Type, zcu: *const Zcu) bool { |
| 1923 | 1450 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { |
| 1924 | 1451 | .ptr_type => |ptr_type| ptr_type.flags.size == .c, |
| ... | ... | @@ -1947,52 +1474,54 @@ pub fn childTypeIp(ty: Type, ip: *const InternPool) Type { |
| 1947 | 1474 | return Type.fromInterned(ip.childType(ty.toIntern())); |
| 1948 | 1475 | } |
| 1949 | 1476 | |
| 1950 | /// For `*[N]T`, returns `T`. | |
| 1951 | /// For `?*T`, returns `T`. | |
| 1952 | /// For `?*[N]T`, returns `T`. | |
| 1953 | /// For `?[*]T`, returns `T`. | |
| 1954 | /// For `*T`, returns `T`. | |
| 1955 | /// For `[*]T`, returns `T`. | |
| 1956 | /// For `[N]T`, returns `T`. | |
| 1957 | /// For `[]T`, returns `T`. | |
| 1958 | /// For `anyframe->T`, returns `T`. | |
| 1959 | pub fn elemType2(ty: Type, zcu: *const Zcu) Type { | |
| 1960 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 1961 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | |
| 1962 | .one => Type.fromInterned(ptr_type.child).shallowElemType(zcu), | |
| 1963 | .many, .c, .slice => Type.fromInterned(ptr_type.child), | |
| 1964 | }, | |
| 1965 | .anyframe_type => |child| { | |
| 1966 | assert(child != .none); | |
| 1967 | return Type.fromInterned(child); | |
| 1477 | /// Similar to `childType`, but for pointer-like (or slice-like) optionals, gets the child type | |
| 1478 | /// of the *pointer* type. Asserts that `ty` is either a pointer or a pointer-like optional. | |
| 1479 | /// | |
| 1480 | /// Essentially, unwraps any one of the following into `T`: | |
| 1481 | /// ``` | |
| 1482 | /// *T ?*T *allowzero T | |
| 1483 | /// [*]T ?[*]T [*]allowzero T | |
| 1484 | /// []T ?[]T []allowzero T | |
| 1485 | /// [*c]T | |
| 1486 | /// ``` | |
| 1487 | /// This is primarily useful in Sema to implement operations which can act on optional pointers. | |
| 1488 | pub fn nullablePtrElem(ty: Type, zcu: *const Zcu) Type { | |
| 1489 | switch (ty.zigTypeTag(zcu)) { | |
| 1490 | .pointer => return ty.childType(zcu), | |
| 1491 | .optional => { | |
| 1492 | const ptr_ty = ty.childType(zcu); | |
| 1493 | const ptr_info = zcu.intern_pool.indexToKey(ptr_ty.toIntern()).ptr_type; | |
| 1494 | assert(ptr_info.flags.size != .c); | |
| 1495 | assert(!ptr_info.flags.is_allowzero); | |
| 1496 | return .fromInterned(ptr_info.child); | |
| 1968 | 1497 | }, |
| 1969 | .vector_type => |vector_type| Type.fromInterned(vector_type.child), | |
| 1970 | .array_type => |array_type| Type.fromInterned(array_type.child), | |
| 1971 | .opt_type => |child| Type.fromInterned(zcu.intern_pool.childType(child)), | |
| 1972 | 1498 | else => unreachable, |
| 1973 | }; | |
| 1974 | } | |
| 1975 | ||
| 1976 | /// Given that `ty` is an indexable pointer, returns its element type. Specifically: | |
| 1977 | /// * for `*[n]T`, returns `T` | |
| 1978 | /// * for `[]T`, returns `T` | |
| 1979 | /// * for `[*]T`, returns `T` | |
| 1980 | /// * for `[*c]T`, returns `T` | |
| 1981 | pub fn indexablePtrElem(ty: Type, zcu: *const Zcu) Type { | |
| 1982 | const ip = &zcu.intern_pool; | |
| 1983 | const ptr_type = ip.indexToKey(ty.toIntern()).ptr_type; | |
| 1984 | switch (ptr_type.flags.size) { | |
| 1985 | .many, .slice, .c => return .fromInterned(ptr_type.child), | |
| 1986 | .one => {}, | |
| 1987 | 1499 | } |
| 1988 | const array_type = ip.indexToKey(ptr_type.child).array_type; | |
| 1989 | return .fromInterned(array_type.child); | |
| 1990 | 1500 | } |
| 1991 | 1501 | |
| 1992 | fn shallowElemType(child_ty: Type, zcu: *const Zcu) Type { | |
| 1993 | return switch (child_ty.zigTypeTag(zcu)) { | |
| 1994 | .array, .vector => child_ty.childType(zcu), | |
| 1995 | else => child_ty, | |
| 1502 | /// Asserts that `ty` is an indexable type, and returns its element type. Tuples (and pointers to | |
| 1503 | /// tuples) are not supported because they do not have a single element type. | |
| 1504 | /// | |
| 1505 | /// Returns `T` for each of the following types: | |
| 1506 | /// * `[n]T` | |
| 1507 | /// * `@Vector(n, T)` | |
| 1508 | /// * `*[n]T` | |
| 1509 | /// * `*@Vector(n, T)` | |
| 1510 | /// * `[]T` | |
| 1511 | /// * `[*]T` | |
| 1512 | /// * `[*c]T` | |
| 1513 | pub fn indexableElem(ty: Type, zcu: *const Zcu) Type { | |
| 1514 | const ip = &zcu.intern_pool; | |
| 1515 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 1516 | inline .array_type, .vector_type => |arr| .fromInterned(arr.child), | |
| 1517 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { | |
| 1518 | .many, .slice, .c => .fromInterned(ptr_type.child), | |
| 1519 | .one => switch (ip.indexToKey(ptr_type.child)) { | |
| 1520 | inline .array_type, .vector_type => |arr| .fromInterned(arr.child), | |
| 1521 | else => unreachable, | |
| 1522 | }, | |
| 1523 | }, | |
| 1524 | else => unreachable, | |
| 1996 | 1525 | }; |
| 1997 | 1526 | } |
| 1998 | 1527 | |
| ... | ... | @@ -2004,61 +1533,54 @@ pub fn scalarType(ty: Type, zcu: *const Zcu) Type { |
| 2004 | 1533 | }; |
| 2005 | 1534 | } |
| 2006 | 1535 | |
| 2007 | /// Asserts that the type is an optional. | |
| 2008 | /// Note that for C pointers this returns the type unmodified. | |
| 1536 | /// Asserts that the type is an optional, or a C pointer. | |
| 1537 | /// For C pointers this returns the type unmodified. | |
| 2009 | 1538 | pub fn optionalChild(ty: Type, zcu: *const Zcu) Type { |
| 2010 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 2011 | .opt_type => |child| Type.fromInterned(child), | |
| 2012 | .ptr_type => |ptr_type| b: { | |
| 1539 | switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 1540 | .opt_type => |child| return .fromInterned(child), | |
| 1541 | .ptr_type => |ptr_type| { | |
| 2013 | 1542 | assert(ptr_type.flags.size == .c); |
| 2014 | break :b ty; | |
| 1543 | return ty; | |
| 2015 | 1544 | }, |
| 2016 | 1545 | else => unreachable, |
| 2017 | }; | |
| 1546 | } | |
| 2018 | 1547 | } |
| 2019 | 1548 | |
| 2020 | /// Returns the tag type of a union, if the type is a union and it has a tag type. | |
| 2021 | /// Otherwise, returns `null`. | |
| 1549 | /// If `ty` is a tagged union, returns its tag type. Otherwise, returns `null`. | |
| 2022 | 1550 | pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type { |
| 1551 | assertHasLayout(ty, zcu); | |
| 2023 | 1552 | const ip = &zcu.intern_pool; |
| 2024 | 1553 | switch (ip.indexToKey(ty.toIntern())) { |
| 2025 | 1554 | .union_type => {}, |
| 2026 | 1555 | else => return null, |
| 2027 | 1556 | } |
| 2028 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 2029 | const union_flags = union_type.flagsUnordered(ip); | |
| 2030 | switch (union_flags.runtime_tag) { | |
| 2031 | .tagged => { | |
| 2032 | assert(union_flags.status.haveFieldTypes()); | |
| 2033 | return Type.fromInterned(union_type.enum_tag_ty); | |
| 2034 | }, | |
| 2035 | else => return null, | |
| 2036 | } | |
| 1557 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 1558 | return switch (union_obj.tag_usage) { | |
| 1559 | .tagged => .fromInterned(union_obj.enum_tag_type), | |
| 1560 | .none, .safety => null, | |
| 1561 | }; | |
| 2037 | 1562 | } |
| 2038 | 1563 | |
| 2039 | /// Same as `unionTagType` but includes safety tag. | |
| 2040 | /// Codegen should use this version. | |
| 2041 | pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type { | |
| 2042 | const ip = &zcu.intern_pool; | |
| 2043 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 2044 | .union_type => { | |
| 2045 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 2046 | if (!union_type.hasTag(ip)) return null; | |
| 2047 | assert(union_type.haveFieldTypes(ip)); | |
| 2048 | return Type.fromInterned(union_type.enum_tag_ty); | |
| 2049 | }, | |
| 2050 | else => null, | |
| 2051 | }; | |
| 1564 | /// If the given union type contains a tag (including a safety tag) in its runtime layout, returns | |
| 1565 | /// its enum tag type. Otherwise, returns null. Asserts that `ty` is a union type. | |
| 1566 | /// | |
| 1567 | /// In general, codegen logic should call this function instead of `unionTagType`. | |
| 1568 | pub fn unionTagTypeRuntime(ty: Type, zcu: *const Zcu) ?Type { | |
| 1569 | assertHasLayout(ty, zcu); | |
| 1570 | const union_type = zcu.intern_pool.loadUnionType(ty.toIntern()); | |
| 1571 | if (!union_type.has_runtime_tag) return null; | |
| 1572 | return .fromInterned(union_type.enum_tag_type); | |
| 2052 | 1573 | } |
| 2053 | 1574 | |
| 2054 | /// Asserts the type is a union; returns the tag type, even if the tag will | |
| 2055 | /// not be stored at runtime. | |
| 1575 | /// Asserts that `ty` is a union type, and returns its tag type, even if the tag will not be stored at runtime. | |
| 2056 | 1576 | pub fn unionTagTypeHypothetical(ty: Type, zcu: *const Zcu) Type { |
| 2057 | const union_obj = zcu.typeToUnion(ty).?; | |
| 2058 | return Type.fromInterned(union_obj.enum_tag_ty); | |
| 1577 | assertHasLayout(ty, zcu); | |
| 1578 | const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); | |
| 1579 | return .fromInterned(union_obj.enum_tag_type); | |
| 2059 | 1580 | } |
| 2060 | 1581 | |
| 2061 | 1582 | pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type { |
| 1583 | assertHasLayout(ty, zcu); | |
| 2062 | 1584 | const ip = &zcu.intern_pool; |
| 2063 | 1585 | const union_obj = zcu.typeToUnion(ty).?; |
| 2064 | 1586 | const union_fields = union_obj.field_types.get(ip); |
| ... | ... | @@ -2067,17 +1589,20 @@ pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type { |
| 2067 | 1589 | } |
| 2068 | 1590 | |
| 2069 | 1591 | pub fn unionFieldTypeByIndex(ty: Type, index: usize, zcu: *const Zcu) Type { |
| 1592 | assertHasLayout(ty, zcu); | |
| 2070 | 1593 | const ip = &zcu.intern_pool; |
| 2071 | 1594 | const union_obj = zcu.typeToUnion(ty).?; |
| 2072 | 1595 | return Type.fromInterned(union_obj.field_types.get(ip)[index]); |
| 2073 | 1596 | } |
| 2074 | 1597 | |
| 2075 | 1598 | pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { |
| 1599 | assertHasLayout(ty, zcu); | |
| 2076 | 1600 | const union_obj = zcu.typeToUnion(ty).?; |
| 2077 | 1601 | return zcu.unionTagFieldIndex(union_obj, enum_tag); |
| 2078 | 1602 | } |
| 2079 | 1603 | |
| 2080 | 1604 | pub fn unionHasAllZeroBitFieldTypes(ty: Type, zcu: *Zcu) bool { |
| 1605 | assertHasLayout(ty, zcu); | |
| 2081 | 1606 | const ip = &zcu.intern_pool; |
| 2082 | 1607 | const union_obj = zcu.typeToUnion(ty).?; |
| 2083 | 1608 | for (union_obj.field_types.get(ip)) |field_ty| { |
| ... | ... | @@ -2087,17 +1612,21 @@ pub fn unionHasAllZeroBitFieldTypes(ty: Type, zcu: *Zcu) bool { |
| 2087 | 1612 | } |
| 2088 | 1613 | |
| 2089 | 1614 | /// Returns the type used for backing storage of this union during comptime operations. |
| 2090 | /// Asserts the type is either an extern or packed union. | |
| 2091 | pub fn unionBackingType(ty: Type, pt: Zcu.PerThread) !Type { | |
| 1615 | /// Asserts the type is an extern union. | |
| 1616 | pub fn externUnionBackingType(ty: Type, pt: Zcu.PerThread) !Type { | |
| 2092 | 1617 | const zcu = pt.zcu; |
| 2093 | return switch (ty.containerLayout(zcu)) { | |
| 2094 | .@"extern" => try pt.arrayType(.{ .len = ty.abiSize(zcu), .child = .u8_type }), | |
| 2095 | .@"packed" => try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))), | |
| 1618 | assertHasLayout(ty, zcu); | |
| 1619 | const loaded_union = zcu.intern_pool.loadUnionType(ty.toIntern()); | |
| 1620 | switch (loaded_union.layout) { | |
| 1621 | .@"extern" => return pt.arrayType(.{ .len = ty.abiSize(zcu), .child = .u8_type }), | |
| 1622 | .@"packed" => unreachable, | |
| 2096 | 1623 | .auto => unreachable, |
| 2097 | }; | |
| 1624 | } | |
| 2098 | 1625 | } |
| 2099 | 1626 | |
| 1627 | /// Asserts that `ty` is a non-packed union type. | |
| 2100 | 1628 | pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { |
| 1629 | assertHasLayout(ty, zcu); | |
| 2101 | 1630 | const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); |
| 2102 | 1631 | return Type.getUnionLayout(union_obj, zcu); |
| 2103 | 1632 | } |
| ... | ... | @@ -2105,9 +1634,18 @@ pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { |
| 2105 | 1634 | pub fn containerLayout(ty: Type, zcu: *const Zcu) std.builtin.Type.ContainerLayout { |
| 2106 | 1635 | const ip = &zcu.intern_pool; |
| 2107 | 1636 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2108 | .struct_type => ip.loadStructType(ty.toIntern()).layout, | |
| 2109 | 1637 | .tuple_type => .auto, |
| 2110 | .union_type => ip.loadUnionType(ty.toIntern()).flagsUnordered(ip).layout, | |
| 1638 | .struct_type => ip.loadStructType(ty.toIntern()).layout, | |
| 1639 | .union_type => ip.loadUnionType(ty.toIntern()).layout, | |
| 1640 | else => unreachable, | |
| 1641 | }; | |
| 1642 | } | |
| 1643 | ||
| 1644 | pub fn bitpackBackingInt(ty: Type, zcu: *const Zcu) Type { | |
| 1645 | const ip = &zcu.intern_pool; | |
| 1646 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 1647 | .struct_type => .fromInterned(ip.loadStructType(ty.toIntern()).packed_backing_int_type), | |
| 1648 | .union_type => .fromInterned(ip.loadUnionType(ty.toIntern()).packed_backing_int_type), | |
| 2111 | 1649 | else => unreachable, |
| 2112 | 1650 | }; |
| 2113 | 1651 | } |
| ... | ... | @@ -2123,6 +1661,11 @@ pub fn errorUnionSet(ty: Type, zcu: *const Zcu) Type { |
| 2123 | 1661 | } |
| 2124 | 1662 | |
| 2125 | 1663 | /// Returns false for unresolved inferred error sets. |
| 1664 | /// | |
| 1665 | /// TODO: this function will behave incorrectly under incremental compilation, because in that case | |
| 1666 | /// it may see an outdated resolved error set. This function must be either deleted, or its contract | |
| 1667 | /// changed to require the caller to resolve the error set beforehand. If you must introduce new | |
| 1668 | /// call sites, please make sure the error set in question is definitely resolved first! | |
| 2126 | 1669 | pub fn errorSetIsEmpty(ty: Type, zcu: *const Zcu) bool { |
| 2127 | 1670 | const ip = &zcu.intern_pool; |
| 2128 | 1671 | return switch (ty.toIntern()) { |
| ... | ... | @@ -2141,6 +1684,11 @@ pub fn errorSetIsEmpty(ty: Type, zcu: *const Zcu) bool { |
| 2141 | 1684 | /// Returns true if it is an error set that includes anyerror, false otherwise. |
| 2142 | 1685 | /// Note that the result may be a false negative if the type did not get error set |
| 2143 | 1686 | /// resolution prior to this call. |
| 1687 | /// | |
| 1688 | /// TODO: this function will behave incorrectly under incremental compilation, because in that case | |
| 1689 | /// it may see an outdated resolved error set. This function must be either deleted, or its contract | |
| 1690 | /// changed to require the caller to resolve the error set beforehand. If you must introduce new | |
| 1691 | /// call sites, please make sure the error set in question is definitely resolved first! | |
| 2144 | 1692 | pub fn isAnyError(ty: Type, zcu: *const Zcu) bool { |
| 2145 | 1693 | const ip = &zcu.intern_pool; |
| 2146 | 1694 | return switch (ty.toIntern()) { |
| ... | ... | @@ -2163,46 +1711,25 @@ pub fn isError(ty: Type, zcu: *const Zcu) bool { |
| 2163 | 1711 | /// Returns whether ty, which must be an error set, includes an error `name`. |
| 2164 | 1712 | /// Might return a false negative if `ty` is an inferred error set and not fully |
| 2165 | 1713 | /// resolved yet. |
| 2166 | pub fn errorSetHasFieldIp( | |
| 2167 | ip: *const InternPool, | |
| 2168 | ty: InternPool.Index, | |
| 1714 | /// | |
| 1715 | /// TODO: this function will behave incorrectly under incremental compilation, because in that case | |
| 1716 | /// it may see an outdated resolved error set. This function must be either deleted, or its contract | |
| 1717 | /// changed to require the caller to resolve the error set beforehand. If you must introduce new | |
| 1718 | /// call sites, please make sure the error set in question is definitely resolved first! | |
| 1719 | pub fn errorSetHasField( | |
| 1720 | ty: Type, | |
| 2169 | 1721 | name: InternPool.NullTerminatedString, |
| 1722 | zcu: *const Zcu, | |
| 2170 | 1723 | ) bool { |
| 2171 | return switch (ty) { | |
| 2172 | .anyerror_type => true, | |
| 2173 | else => switch (ip.indexToKey(ty)) { | |
| 2174 | .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null, | |
| 2175 | .inferred_error_set_type => |i| switch (ip.funcIesResolvedUnordered(i)) { | |
| 2176 | .anyerror_type => true, | |
| 2177 | .none => false, | |
| 2178 | else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null, | |
| 2179 | }, | |
| 2180 | else => unreachable, | |
| 2181 | }, | |
| 2182 | }; | |
| 2183 | } | |
| 2184 | ||
| 2185 | /// Returns whether ty, which must be an error set, includes an error `name`. | |
| 2186 | /// Might return a false negative if `ty` is an inferred error set and not fully | |
| 2187 | /// resolved yet. | |
| 2188 | pub fn errorSetHasField(ty: Type, name: []const u8, zcu: *const Zcu) bool { | |
| 2189 | 1724 | const ip = &zcu.intern_pool; |
| 2190 | 1725 | return switch (ty.toIntern()) { |
| 2191 | 1726 | .anyerror_type => true, |
| 2192 | 1727 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 2193 | .error_set_type => |error_set_type| { | |
| 2194 | // If the string is not interned, then the field certainly is not present. | |
| 2195 | const field_name_interned = ip.getString(name).unwrap() orelse return false; | |
| 2196 | return error_set_type.nameIndex(ip, field_name_interned) != null; | |
| 2197 | }, | |
| 1728 | .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null, | |
| 2198 | 1729 | .inferred_error_set_type => |i| switch (ip.funcIesResolvedUnordered(i)) { |
| 2199 | 1730 | .anyerror_type => true, |
| 2200 | 1731 | .none => false, |
| 2201 | else => |t| { | |
| 2202 | // If the string is not interned, then the field certainly is not present. | |
| 2203 | const field_name_interned = ip.getString(name).unwrap() orelse return false; | |
| 2204 | return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null; | |
| 2205 | }, | |
| 1732 | else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null, | |
| 2206 | 1733 | }, |
| 2207 | 1734 | else => unreachable, |
| 2208 | 1735 | }, |
| ... | ... | @@ -2275,12 +1802,12 @@ pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool { |
| 2275 | 1802 | }; |
| 2276 | 1803 | } |
| 2277 | 1804 | |
| 2278 | /// Returns true for integers, enums, error sets, and packed structs. | |
| 1805 | /// Returns true for integers, enums, error sets, and packed structs/unions. | |
| 2279 | 1806 | /// If this function returns true, then intInfo() can be called on the type. |
| 2280 | 1807 | pub fn isAbiInt(ty: Type, zcu: *const Zcu) bool { |
| 2281 | 1808 | return switch (ty.zigTypeTag(zcu)) { |
| 2282 | 1809 | .int, .@"enum", .error_set => true, |
| 2283 | .@"struct" => ty.containerLayout(zcu) == .@"packed", | |
| 1810 | .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", | |
| 2284 | 1811 | else => false, |
| 2285 | 1812 | }; |
| 2286 | 1813 | } |
| ... | ... | @@ -2308,8 +1835,17 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { |
| 2308 | 1835 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) }, |
| 2309 | 1836 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 2310 | 1837 | .int_type => |int_type| return int_type, |
| 2311 | .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)), | |
| 2312 | .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), | |
| 1838 | .struct_type => { | |
| 1839 | const struct_obj = ip.loadStructType(ty.toIntern()); | |
| 1840 | assert(struct_obj.layout == .@"packed"); | |
| 1841 | ty = .fromInterned(struct_obj.packed_backing_int_type); | |
| 1842 | }, | |
| 1843 | .union_type => { | |
| 1844 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 1845 | assert(union_obj.layout == .@"packed"); | |
| 1846 | ty = .fromInterned(union_obj.packed_backing_int_type); | |
| 1847 | }, | |
| 1848 | .enum_type => ty = .fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type), | |
| 2313 | 1849 | .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child), |
| 2314 | 1850 | |
| 2315 | 1851 | .error_set_type, .inferred_error_set_type => { |
| ... | ... | @@ -2327,7 +1863,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { |
| 2327 | 1863 | .func_type => unreachable, |
| 2328 | 1864 | .simple_type => unreachable, // handled via Index enum tag above |
| 2329 | 1865 | |
| 2330 | .union_type => unreachable, | |
| 2331 | 1866 | .opaque_type => unreachable, |
| 2332 | 1867 | |
| 2333 | 1868 | // values, not types |
| ... | ... | @@ -2341,13 +1876,13 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { |
| 2341 | 1876 | .error_union, |
| 2342 | 1877 | .enum_literal, |
| 2343 | 1878 | .enum_tag, |
| 2344 | .empty_enum_value, | |
| 2345 | 1879 | .float, |
| 2346 | 1880 | .ptr, |
| 2347 | 1881 | .slice, |
| 2348 | 1882 | .opt, |
| 2349 | 1883 | .aggregate, |
| 2350 | 1884 | .un, |
| 1885 | .bitpack, | |
| 2351 | 1886 | // memoization, not types |
| 2352 | 1887 | .memoized_call, |
| 2353 | 1888 | => unreachable, |
| ... | ... | @@ -2355,25 +1890,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { |
| 2355 | 1890 | }; |
| 2356 | 1891 | } |
| 2357 | 1892 | |
| 2358 | pub fn isNamedInt(ty: Type) bool { | |
| 2359 | return switch (ty.toIntern()) { | |
| 2360 | .usize_type, | |
| 2361 | .isize_type, | |
| 2362 | .c_char_type, | |
| 2363 | .c_short_type, | |
| 2364 | .c_ushort_type, | |
| 2365 | .c_int_type, | |
| 2366 | .c_uint_type, | |
| 2367 | .c_long_type, | |
| 2368 | .c_ulong_type, | |
| 2369 | .c_longlong_type, | |
| 2370 | .c_ulonglong_type, | |
| 2371 | => true, | |
| 2372 | ||
| 2373 | else => false, | |
| 2374 | }; | |
| 2375 | } | |
| 2376 | ||
| 2377 | 1893 | /// Returns `false` for `comptime_float`. |
| 2378 | 1894 | pub fn isRuntimeFloat(ty: Type) bool { |
| 2379 | 1895 | return switch (ty.toIntern()) { |
| ... | ... | @@ -2488,429 +2004,181 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool { |
| 2488 | 2004 | }; |
| 2489 | 2005 | } |
| 2490 | 2006 | |
| 2491 | /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which | |
| 2492 | /// resolves field types rather than asserting they are already resolved. | |
| 2493 | pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { | |
| 2007 | /// If the type's classification is `Class.one_possible_value` (see `classify`), returns the only | |
| 2008 | /// possible value for the type. Otherwise, returns `null`. | |
| 2009 | pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value { | |
| 2494 | 2010 | const zcu = pt.zcu; |
| 2495 | 2011 | const comp = zcu.comp; |
| 2496 | 2012 | const gpa = comp.gpa; |
| 2497 | const io = comp.io; | |
| 2498 | 2013 | const ip = &zcu.intern_pool; |
| 2499 | var ty = starting_type; | |
| 2500 | while (true) switch (ty.toIntern()) { | |
| 2501 | .empty_tuple_type => return Value.empty_tuple, | |
| 2502 | ||
| 2503 | else => switch (ip.indexToKey(ty.toIntern())) { | |
| 2504 | .int_type => |int_type| { | |
| 2505 | if (int_type.bits == 0) { | |
| 2506 | return try pt.intValue(ty, 0); | |
| 2507 | } else { | |
| 2508 | return null; | |
| 2509 | } | |
| 2510 | }, | |
| 2511 | ||
| 2512 | .ptr_type, | |
| 2513 | .error_union_type, | |
| 2514 | .func_type, | |
| 2515 | .anyframe_type, | |
| 2516 | .error_set_type, | |
| 2517 | .inferred_error_set_type, | |
| 2518 | => return null, | |
| 2519 | ||
| 2520 | inline .array_type, .vector_type => |seq_type, seq_tag| { | |
| 2521 | const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; | |
| 2522 | if (seq_type.len + @intFromBool(has_sentinel) == 0) { | |
| 2523 | return try pt.aggregateValue(ty, &.{}); | |
| 2524 | } | |
| 2525 | if (try Type.fromInterned(seq_type.child).onePossibleValue(pt)) |opv| { | |
| 2526 | return try pt.aggregateSplatValue(ty, opv); | |
| 2527 | } | |
| 2528 | return null; | |
| 2529 | }, | |
| 2530 | .opt_type => |child| { | |
| 2531 | if (child == .noreturn_type) { | |
| 2532 | return try pt.nullValue(ty); | |
| 2533 | } else { | |
| 2534 | return null; | |
| 2535 | } | |
| 2536 | }, | |
| 2537 | ||
| 2538 | .simple_type => |t| switch (t) { | |
| 2539 | .f16, | |
| 2540 | .f32, | |
| 2541 | .f64, | |
| 2542 | .f80, | |
| 2543 | .f128, | |
| 2544 | .usize, | |
| 2545 | .isize, | |
| 2546 | .c_char, | |
| 2547 | .c_short, | |
| 2548 | .c_ushort, | |
| 2549 | .c_int, | |
| 2550 | .c_uint, | |
| 2551 | .c_long, | |
| 2552 | .c_ulong, | |
| 2553 | .c_longlong, | |
| 2554 | .c_ulonglong, | |
| 2555 | .c_longdouble, | |
| 2556 | .anyopaque, | |
| 2557 | .bool, | |
| 2558 | .type, | |
| 2559 | .anyerror, | |
| 2560 | .comptime_int, | |
| 2561 | .comptime_float, | |
| 2562 | .enum_literal, | |
| 2563 | .adhoc_inferred_error_set, | |
| 2564 | => return null, | |
| 2565 | ||
| 2566 | .void => return Value.void, | |
| 2567 | .noreturn => return Value.@"unreachable", | |
| 2568 | .null => return Value.null, | |
| 2569 | .undefined => return Value.undef, | |
| 2570 | ||
| 2571 | .generic_poison => unreachable, | |
| 2572 | }, | |
| 2573 | .struct_type => { | |
| 2574 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 2575 | assert(struct_type.haveFieldTypes(ip)); | |
| 2576 | if (struct_type.knownNonOpv(ip)) | |
| 2577 | return null; | |
| 2578 | const field_vals = try zcu.gpa.alloc(InternPool.Index, struct_type.field_types.len); | |
| 2579 | defer zcu.gpa.free(field_vals); | |
| 2580 | for (field_vals, 0..) |*field_val, i_usize| { | |
| 2581 | const i: u32 = @intCast(i_usize); | |
| 2582 | if (struct_type.fieldIsComptime(ip, i)) { | |
| 2583 | assert(struct_type.haveFieldInits(ip)); | |
| 2584 | field_val.* = struct_type.field_inits.get(ip)[i]; | |
| 2585 | continue; | |
| 2586 | } | |
| 2587 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 2588 | if (try field_ty.onePossibleValue(pt)) |field_opv| { | |
| 2589 | field_val.* = field_opv.toIntern(); | |
| 2590 | } else return null; | |
| 2591 | } | |
| 2592 | ||
| 2593 | // In this case the struct has no runtime-known fields and | |
| 2594 | // therefore has one possible value. | |
| 2595 | return try pt.aggregateValue(ty, field_vals); | |
| 2596 | }, | |
| 2597 | ||
| 2598 | .tuple_type => |tuple| { | |
| 2599 | if (tuple.types.len == 0) { | |
| 2600 | return try pt.aggregateValue(ty, &.{}); | |
| 2601 | } | |
| 2602 | ||
| 2603 | const field_vals = try zcu.gpa.alloc( | |
| 2604 | InternPool.Index, | |
| 2605 | tuple.types.len, | |
| 2606 | ); | |
| 2607 | defer zcu.gpa.free(field_vals); | |
| 2608 | for ( | |
| 2609 | field_vals, | |
| 2610 | tuple.types.get(ip), | |
| 2611 | tuple.values.get(ip), | |
| 2612 | ) |*field_val, field_ty, field_comptime_val| { | |
| 2613 | if (field_comptime_val != .none) { | |
| 2614 | field_val.* = field_comptime_val; | |
| 2615 | continue; | |
| 2616 | } | |
| 2617 | if (try Type.fromInterned(field_ty).onePossibleValue(pt)) |opv| { | |
| 2618 | field_val.* = opv.toIntern(); | |
| 2619 | } else return null; | |
| 2620 | } | |
| 2621 | ||
| 2622 | return try pt.aggregateValue(ty, field_vals); | |
| 2623 | }, | |
| 2624 | ||
| 2625 | .union_type => { | |
| 2626 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 2627 | const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(pt)) orelse | |
| 2628 | return null; | |
| 2629 | if (union_obj.field_types.len == 0) { | |
| 2630 | const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); | |
| 2631 | return Value.fromInterned(only); | |
| 2632 | } | |
| 2633 | const only_field_ty = union_obj.field_types.get(ip)[0]; | |
| 2634 | const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse | |
| 2635 | return null; | |
| 2636 | const only = try pt.internUnion(.{ | |
| 2637 | .ty = ty.toIntern(), | |
| 2638 | .tag = tag_val.toIntern(), | |
| 2639 | .val = val_val.toIntern(), | |
| 2640 | }); | |
| 2641 | return Value.fromInterned(only); | |
| 2642 | }, | |
| 2643 | .opaque_type => return null, | |
| 2644 | .enum_type => { | |
| 2645 | const enum_type = ip.loadEnumType(ty.toIntern()); | |
| 2646 | switch (enum_type.tag_mode) { | |
| 2647 | .nonexhaustive => { | |
| 2648 | if (enum_type.tag_ty == .comptime_int_type) return null; | |
| 2649 | ||
| 2650 | if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(pt)) |int_opv| { | |
| 2651 | const only = try pt.intern(.{ .enum_tag = .{ | |
| 2652 | .ty = ty.toIntern(), | |
| 2653 | .int = int_opv.toIntern(), | |
| 2654 | } }); | |
| 2655 | return Value.fromInterned(only); | |
| 2656 | } | |
| 2657 | ||
| 2658 | return null; | |
| 2659 | }, | |
| 2660 | .auto, .explicit => { | |
| 2661 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; | |
| 2662 | ||
| 2663 | return Value.fromInterned(switch (enum_type.names.len) { | |
| 2664 | 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }), | |
| 2665 | 1 => try pt.intern(.{ .enum_tag = .{ | |
| 2666 | .ty = ty.toIntern(), | |
| 2667 | .int = if (enum_type.values.len == 0) | |
| 2668 | (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() | |
| 2669 | else | |
| 2670 | try ip.getCoercedInts( | |
| 2671 | gpa, | |
| 2672 | io, | |
| 2673 | pt.tid, | |
| 2674 | ip.indexToKey(enum_type.values.get(ip)[0]).int, | |
| 2675 | enum_type.tag_ty, | |
| 2676 | ), | |
| 2677 | } }), | |
| 2678 | else => return null, | |
| 2679 | }); | |
| 2680 | }, | |
| 2681 | } | |
| 2682 | }, | |
| 2014 | assertHasLayout(ty, zcu); | |
| 2015 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 2016 | .ptr_type, | |
| 2017 | .error_union_type, | |
| 2018 | .func_type, | |
| 2019 | .anyframe_type, | |
| 2020 | .error_set_type, | |
| 2021 | .inferred_error_set_type, | |
| 2022 | .opaque_type, | |
| 2023 | => null, | |
| 2683 | 2024 | |
| 2684 | // values, not types | |
| 2685 | .undef, | |
| 2686 | .simple_value, | |
| 2687 | .variable, | |
| 2688 | .@"extern", | |
| 2689 | .func, | |
| 2690 | .int, | |
| 2691 | .err, | |
| 2692 | .error_union, | |
| 2025 | .simple_type => |t| switch (t) { | |
| 2026 | .f16, | |
| 2027 | .f32, | |
| 2028 | .f64, | |
| 2029 | .f80, | |
| 2030 | .f128, | |
| 2031 | .usize, | |
| 2032 | .isize, | |
| 2033 | .c_char, | |
| 2034 | .c_short, | |
| 2035 | .c_ushort, | |
| 2036 | .c_int, | |
| 2037 | .c_uint, | |
| 2038 | .c_long, | |
| 2039 | .c_ulong, | |
| 2040 | .c_longlong, | |
| 2041 | .c_ulonglong, | |
| 2042 | .c_longdouble, | |
| 2043 | .anyopaque, | |
| 2044 | .bool, | |
| 2045 | .type, | |
| 2046 | .anyerror, | |
| 2047 | .comptime_int, | |
| 2048 | .comptime_float, | |
| 2693 | 2049 | .enum_literal, |
| 2694 | .enum_tag, | |
| 2695 | .empty_enum_value, | |
| 2696 | .float, | |
| 2697 | .ptr, | |
| 2698 | .slice, | |
| 2699 | .opt, | |
| 2700 | .aggregate, | |
| 2701 | .un, | |
| 2702 | // memoization, not types | |
| 2703 | .memoized_call, | |
| 2704 | => unreachable, | |
| 2705 | }, | |
| 2706 | }; | |
| 2707 | } | |
| 2708 | ||
| 2709 | /// During semantic analysis, instead call `ty.comptimeOnlySema` which | |
| 2710 | /// resolves field types rather than asserting they are already resolved. | |
| 2711 | pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { | |
| 2712 | return ty.comptimeOnlyInner(.normal, zcu, {}) catch unreachable; | |
| 2713 | } | |
| 2714 | ||
| 2715 | pub fn comptimeOnlySema(ty: Type, pt: Zcu.PerThread) SemaError!bool { | |
| 2716 | return try ty.comptimeOnlyInner(.sema, pt.zcu, pt.tid); | |
| 2717 | } | |
| 2718 | ||
| 2719 | /// `generic_poison` will return false. | |
| 2720 | /// May return false negatives when structs and unions are having their field types resolved. | |
| 2721 | pub fn comptimeOnlyInner( | |
| 2722 | ty: Type, | |
| 2723 | comptime strat: ResolveStrat, | |
| 2724 | zcu: strat.ZcuPtr(), | |
| 2725 | tid: strat.Tid(), | |
| 2726 | ) SemaError!bool { | |
| 2727 | const ip = &zcu.intern_pool; | |
| 2728 | const io = zcu.comp.io; | |
| 2729 | return switch (ty.toIntern()) { | |
| 2730 | .empty_tuple_type => false, | |
| 2050 | .adhoc_inferred_error_set, | |
| 2051 | .null, | |
| 2052 | .undefined, | |
| 2053 | .noreturn, | |
| 2054 | => null, | |
| 2731 | 2055 | |
| 2732 | else => switch (ip.indexToKey(ty.toIntern())) { | |
| 2733 | .int_type => false, | |
| 2734 | .ptr_type => |ptr_type| { | |
| 2735 | const child_ty = Type.fromInterned(ptr_type.child); | |
| 2736 | switch (child_ty.zigTypeTag(zcu)) { | |
| 2737 | .@"fn" => return !try child_ty.fnHasRuntimeBitsInner(strat, zcu, tid), | |
| 2738 | .@"opaque" => return false, | |
| 2739 | else => return child_ty.comptimeOnlyInner(strat, zcu, tid), | |
| 2740 | } | |
| 2741 | }, | |
| 2742 | .anyframe_type => |child| { | |
| 2743 | if (child == .none) return false; | |
| 2744 | return Type.fromInterned(child).comptimeOnlyInner(strat, zcu, tid); | |
| 2745 | }, | |
| 2746 | .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnlyInner(strat, zcu, tid), | |
| 2747 | .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnlyInner(strat, zcu, tid), | |
| 2748 | .opt_type => |child| return Type.fromInterned(child).comptimeOnlyInner(strat, zcu, tid), | |
| 2749 | .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnlyInner(strat, zcu, tid), | |
| 2056 | .void => .void, | |
| 2750 | 2057 | |
| 2751 | .error_set_type, | |
| 2752 | .inferred_error_set_type, | |
| 2753 | => false, | |
| 2058 | .generic_poison => unreachable, | |
| 2059 | }, | |
| 2754 | 2060 | |
| 2755 | // These are function bodies, not function pointers. | |
| 2756 | .func_type => true, | |
| 2757 | ||
| 2758 | .simple_type => |t| switch (t) { | |
| 2759 | .f16, | |
| 2760 | .f32, | |
| 2761 | .f64, | |
| 2762 | .f80, | |
| 2763 | .f128, | |
| 2764 | .usize, | |
| 2765 | .isize, | |
| 2766 | .c_char, | |
| 2767 | .c_short, | |
| 2768 | .c_ushort, | |
| 2769 | .c_int, | |
| 2770 | .c_uint, | |
| 2771 | .c_long, | |
| 2772 | .c_ulong, | |
| 2773 | .c_longlong, | |
| 2774 | .c_ulonglong, | |
| 2775 | .c_longdouble, | |
| 2776 | .anyopaque, | |
| 2777 | .bool, | |
| 2778 | .void, | |
| 2779 | .anyerror, | |
| 2780 | .adhoc_inferred_error_set, | |
| 2781 | .noreturn, | |
| 2782 | .generic_poison, | |
| 2783 | => false, | |
| 2784 | ||
| 2785 | .type, | |
| 2786 | .comptime_int, | |
| 2787 | .comptime_float, | |
| 2788 | .null, | |
| 2789 | .undefined, | |
| 2790 | .enum_literal, | |
| 2791 | => true, | |
| 2792 | }, | |
| 2793 | .struct_type => { | |
| 2794 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 2795 | // packed structs cannot be comptime-only because they have a well-defined | |
| 2796 | // memory layout and every field has a well-defined bit pattern. | |
| 2797 | if (struct_type.layout == .@"packed") | |
| 2798 | return false; | |
| 2799 | ||
| 2800 | return switch (strat) { | |
| 2801 | .normal => switch (struct_type.requiresComptime(ip)) { | |
| 2802 | .wip => unreachable, | |
| 2803 | .no => false, | |
| 2804 | .yes => true, | |
| 2805 | .unknown => unreachable, | |
| 2806 | }, | |
| 2807 | .sema => switch (struct_type.setRequiresComptimeWip(ip, io)) { | |
| 2808 | .no, .wip => false, | |
| 2809 | .yes => true, | |
| 2810 | .unknown => { | |
| 2811 | if (struct_type.flagsUnordered(ip).field_types_wip) { | |
| 2812 | struct_type.setRequiresComptime(ip, io, .unknown); | |
| 2813 | return false; | |
| 2814 | } | |
| 2815 | ||
| 2816 | errdefer struct_type.setRequiresComptime(ip, io, .unknown); | |
| 2817 | ||
| 2818 | const pt = strat.pt(zcu, tid); | |
| 2819 | try ty.resolveFields(pt); | |
| 2820 | ||
| 2821 | for (0..struct_type.field_types.len) |i_usize| { | |
| 2822 | const i: u32 = @intCast(i_usize); | |
| 2823 | if (struct_type.fieldIsComptime(ip, i)) continue; | |
| 2824 | const field_ty = struct_type.field_types.get(ip)[i]; | |
| 2825 | if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) { | |
| 2826 | // Note that this does not cause the layout to | |
| 2827 | // be considered resolved. Comptime-only types | |
| 2828 | // still maintain a layout of their | |
| 2829 | // runtime-known fields. | |
| 2830 | struct_type.setRequiresComptime(ip, io, .yes); | |
| 2831 | return true; | |
| 2832 | } | |
| 2833 | } | |
| 2834 | ||
| 2835 | struct_type.setRequiresComptime(ip, io, .no); | |
| 2836 | return false; | |
| 2837 | }, | |
| 2838 | }, | |
| 2839 | }; | |
| 2840 | }, | |
| 2061 | .int_type => |int_type| switch (int_type.bits) { | |
| 2062 | 0 => try pt.intValue(ty, 0), | |
| 2063 | else => null, | |
| 2064 | }, | |
| 2841 | 2065 | |
| 2842 | .tuple_type => |tuple| { | |
| 2843 | for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { | |
| 2844 | const have_comptime_val = val != .none; | |
| 2845 | if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) return true; | |
| 2066 | inline .array_type, .vector_type => |seq_type, seq_tag| { | |
| 2067 | const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; | |
| 2068 | if (seq_type.len + @intFromBool(has_sentinel) == 0) { | |
| 2069 | return try pt.aggregateValue(ty, &.{}); | |
| 2070 | } | |
| 2071 | if (try Type.fromInterned(seq_type.child).onePossibleValue(pt)) |opv| { | |
| 2072 | return try pt.aggregateSplatValue(ty, opv); | |
| 2073 | } | |
| 2074 | return null; | |
| 2075 | }, | |
| 2076 | .opt_type => |child| switch (Type.fromInterned(child).classify(zcu)) { | |
| 2077 | .no_possible_value => try pt.nullValue(ty), | |
| 2078 | else => null, | |
| 2079 | }, | |
| 2080 | .tuple_type => |tuple| { | |
| 2081 | // Check *whether* the OPV exists first, because constructing it is a little more expensive. | |
| 2082 | if (ty.classify(zcu) != .one_possible_value) return null; | |
| 2083 | const field_vals = try zcu.gpa.dupe(InternPool.Index, tuple.values.get(ip)); | |
| 2084 | defer zcu.gpa.free(field_vals); | |
| 2085 | for (field_vals, tuple.types.get(ip)) |*field_val, field_ty_ip| { | |
| 2086 | if (field_val.* != .none) continue; // comptime field value | |
| 2087 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 2088 | field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern(); | |
| 2089 | } | |
| 2090 | return try pt.aggregateValue(ty, field_vals); | |
| 2091 | }, | |
| 2092 | .struct_type => { | |
| 2093 | const struct_obj = ip.loadStructType(ty.toIntern()); | |
| 2094 | switch (struct_obj.layout) { | |
| 2095 | .auto, .@"extern" => {}, | |
| 2096 | .@"packed" => { | |
| 2097 | const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); | |
| 2098 | const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; | |
| 2099 | return try pt.bitpackValue(ty, backing_val); | |
| 2100 | }, | |
| 2101 | } | |
| 2102 | // Type resolution already figured out whether there is an OPV, but if there is, it's | |
| 2103 | // our job to compute it. | |
| 2104 | if (struct_obj.class != .one_possible_value) return null; | |
| 2105 | const field_vals = try gpa.alloc(InternPool.Index, struct_obj.field_types.len); | |
| 2106 | defer gpa.free(field_vals); | |
| 2107 | for (field_vals, 0..) |*field_val, i_usize| { | |
| 2108 | const i: u32 = @intCast(i_usize); | |
| 2109 | if (struct_obj.field_is_comptime_bits.get(ip, i)) { | |
| 2110 | field_val.* = struct_obj.field_defaults.get(ip)[i]; | |
| 2111 | assert(field_val.* != .none); | |
| 2112 | continue; | |
| 2846 | 2113 | } |
| 2847 | return false; | |
| 2848 | }, | |
| 2849 | ||
| 2850 | .union_type => { | |
| 2851 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 2852 | return switch (strat) { | |
| 2853 | .normal => switch (union_type.requiresComptime(ip)) { | |
| 2854 | .wip => unreachable, | |
| 2855 | .no => false, | |
| 2856 | .yes => true, | |
| 2857 | .unknown => unreachable, | |
| 2858 | }, | |
| 2859 | .sema => switch (union_type.setRequiresComptimeWip(ip, io)) { | |
| 2860 | .no, .wip => return false, | |
| 2861 | .yes => return true, | |
| 2862 | .unknown => { | |
| 2863 | if (union_type.flagsUnordered(ip).status == .field_types_wip) { | |
| 2864 | union_type.setRequiresComptime(ip, io, .unknown); | |
| 2865 | return false; | |
| 2866 | } | |
| 2867 | ||
| 2868 | errdefer union_type.setRequiresComptime(ip, io, .unknown); | |
| 2869 | ||
| 2870 | const pt = strat.pt(zcu, tid); | |
| 2871 | try ty.resolveFields(pt); | |
| 2872 | ||
| 2873 | for (0..union_type.field_types.len) |field_idx| { | |
| 2874 | const field_ty = union_type.field_types.get(ip)[field_idx]; | |
| 2875 | if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) { | |
| 2876 | union_type.setRequiresComptime(ip, io, .yes); | |
| 2877 | return true; | |
| 2878 | } | |
| 2879 | } | |
| 2880 | ||
| 2881 | union_type.setRequiresComptime(ip, io, .no); | |
| 2882 | return false; | |
| 2883 | }, | |
| 2884 | }, | |
| 2885 | }; | |
| 2886 | }, | |
| 2887 | ||
| 2888 | .opaque_type => false, | |
| 2889 | ||
| 2890 | .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyInner(strat, zcu, tid), | |
| 2891 | ||
| 2892 | // values, not types | |
| 2893 | .undef, | |
| 2894 | .simple_value, | |
| 2895 | .variable, | |
| 2896 | .@"extern", | |
| 2897 | .func, | |
| 2898 | .int, | |
| 2899 | .err, | |
| 2900 | .error_union, | |
| 2901 | .enum_literal, | |
| 2902 | .enum_tag, | |
| 2903 | .empty_enum_value, | |
| 2904 | .float, | |
| 2905 | .ptr, | |
| 2906 | .slice, | |
| 2907 | .opt, | |
| 2908 | .aggregate, | |
| 2909 | .un, | |
| 2910 | // memoization, not types | |
| 2911 | .memoized_call, | |
| 2912 | => unreachable, | |
| 2114 | const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[i]); | |
| 2115 | field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern(); | |
| 2116 | } | |
| 2117 | return try pt.aggregateValue(ty, field_vals); | |
| 2913 | 2118 | }, |
| 2119 | .union_type => { | |
| 2120 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 2121 | if (union_obj.layout == .@"packed") { | |
| 2122 | const backing_ty: Type = .fromInterned(union_obj.packed_backing_int_type); | |
| 2123 | const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; | |
| 2124 | return try pt.bitpackValue(ty, backing_val); | |
| 2125 | } | |
| 2126 | // Type resolution already figured out whether there is an OPV, but if there is, it's | |
| 2127 | // our job to compute it. | |
| 2128 | if (union_obj.class != .one_possible_value) return null; | |
| 2129 | // The OPV comes from exactly one field whose type is OPV, while all others are NPV. | |
| 2130 | for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { | |
| 2131 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 2132 | switch (field_ty.classify(zcu)) { | |
| 2133 | .no_possible_value => continue, | |
| 2134 | .one_possible_value => {}, | |
| 2135 | else => unreachable, | |
| 2136 | } | |
| 2137 | // This field is the one! | |
| 2138 | const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); | |
| 2139 | const tag_val = try pt.enumValueFieldIndex(enum_tag_ty, @intCast(field_index)); | |
| 2140 | const payload_val = (try field_ty.onePossibleValue(pt)).?; | |
| 2141 | return try pt.unionValue(ty, tag_val, payload_val); | |
| 2142 | } else unreachable; | |
| 2143 | }, | |
| 2144 | .enum_type => if (try ty.intTagType(zcu).onePossibleValue(pt)) |int_tag_opv| { | |
| 2145 | return .fromInterned(try pt.intern(.{ .enum_tag = .{ | |
| 2146 | .ty = ty.toIntern(), | |
| 2147 | .int = int_tag_opv.toIntern(), | |
| 2148 | } })); | |
| 2149 | } else null, | |
| 2150 | ||
| 2151 | // values, not types | |
| 2152 | .undef, | |
| 2153 | .simple_value, | |
| 2154 | .variable, | |
| 2155 | .@"extern", | |
| 2156 | .func, | |
| 2157 | .int, | |
| 2158 | .err, | |
| 2159 | .error_union, | |
| 2160 | .enum_literal, | |
| 2161 | .enum_tag, | |
| 2162 | .float, | |
| 2163 | .ptr, | |
| 2164 | .slice, | |
| 2165 | .opt, | |
| 2166 | .aggregate, | |
| 2167 | .un, | |
| 2168 | .bitpack, | |
| 2169 | // memoization, not types | |
| 2170 | .memoized_call, | |
| 2171 | => unreachable, | |
| 2172 | }; | |
| 2173 | } | |
| 2174 | ||
| 2175 | /// Asserts that `ty` has its layout resolved. `generic_poison` will return `false`. | |
| 2176 | pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { | |
| 2177 | if (ty.toIntern() == .generic_poison_type) return false; | |
| 2178 | if (ty.zigTypeTag(zcu) == .error_union and ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) return false; | |
| 2179 | return switch (ty.classify(zcu)) { | |
| 2180 | .no_possible_value, .one_possible_value, .runtime => false, | |
| 2181 | .partially_comptime, .fully_comptime => true, | |
| 2914 | 2182 | }; |
| 2915 | 2183 | } |
| 2916 | 2184 | |
| ... | ... | @@ -3056,20 +2324,18 @@ pub fn maxIntScalar(ty: Type, pt: Zcu.PerThread, dest_ty: Type) !Value { |
| 3056 | 2324 | /// Asserts the type is an enum or a union. |
| 3057 | 2325 | pub fn intTagType(ty: Type, zcu: *const Zcu) Type { |
| 3058 | 2326 | const ip = &zcu.intern_pool; |
| 3059 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3060 | .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(zcu), | |
| 3061 | .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), | |
| 2327 | const enum_ty: Type = switch (ip.indexToKey(ty.toIntern())) { | |
| 2328 | .union_type => .fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_type), | |
| 2329 | .enum_type => ty, | |
| 3062 | 2330 | else => unreachable, |
| 3063 | 2331 | }; |
| 2332 | return .fromInterned(ip.loadEnumType(enum_ty.toIntern()).int_tag_type); | |
| 3064 | 2333 | } |
| 3065 | 2334 | |
| 3066 | 2335 | pub fn isNonexhaustiveEnum(ty: Type, zcu: *const Zcu) bool { |
| 3067 | 2336 | const ip = &zcu.intern_pool; |
| 3068 | 2337 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3069 | .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) { | |
| 3070 | .nonexhaustive => true, | |
| 3071 | .auto, .explicit => false, | |
| 3072 | }, | |
| 2338 | .enum_type => ip.loadEnumType(ty.toIntern()).nonexhaustive, | |
| 3073 | 2339 | else => false, |
| 3074 | 2340 | }; |
| 3075 | 2341 | } |
| ... | ... | @@ -3090,28 +2356,33 @@ pub fn errorSetNames(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString. |
| 3090 | 2356 | } |
| 3091 | 2357 | |
| 3092 | 2358 | pub fn enumFields(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString.Slice { |
| 3093 | return zcu.intern_pool.loadEnumType(ty.toIntern()).names; | |
| 2359 | assertHasLayout(ty, zcu); | |
| 2360 | return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names; | |
| 3094 | 2361 | } |
| 3095 | 2362 | |
| 3096 | 2363 | pub fn enumFieldCount(ty: Type, zcu: *const Zcu) usize { |
| 3097 | return zcu.intern_pool.loadEnumType(ty.toIntern()).names.len; | |
| 2364 | assertHasLayout(ty, zcu); | |
| 2365 | return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names.len; | |
| 3098 | 2366 | } |
| 3099 | 2367 | |
| 3100 | 2368 | pub fn enumFieldName(ty: Type, field_index: usize, zcu: *const Zcu) InternPool.NullTerminatedString { |
| 2369 | assertHasLayout(ty, zcu); | |
| 3101 | 2370 | const ip = &zcu.intern_pool; |
| 3102 | return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index]; | |
| 2371 | return ip.loadEnumType(ty.toIntern()).field_names.get(ip)[field_index]; | |
| 3103 | 2372 | } |
| 3104 | 2373 | |
| 3105 | 2374 | pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, zcu: *const Zcu) ?u32 { |
| 2375 | assertHasLayout(ty, zcu); | |
| 3106 | 2376 | const ip = &zcu.intern_pool; |
| 3107 | 2377 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 3108 | 2378 | return enum_type.nameIndex(ip, field_name); |
| 3109 | 2379 | } |
| 3110 | 2380 | |
| 3111 | /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or | |
| 3112 | /// an integer which represents the enum value. Returns the field index in | |
| 2381 | /// Asserts `ty` is an enum. `enum_tag` can either be the actual enum tag value | |
| 2382 | /// or an integer which represents the enum value. Returns the field index in | |
| 3113 | 2383 | /// declaration order, or `null` if `enum_tag` does not match any field. |
| 3114 | 2384 | pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { |
| 2385 | assertHasLayout(ty, zcu); | |
| 3115 | 2386 | const ip = &zcu.intern_pool; |
| 3116 | 2387 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 3117 | 2388 | const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) { |
| ... | ... | @@ -3119,200 +2390,116 @@ pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { |
| 3119 | 2390 | .enum_tag => |info| info.int, |
| 3120 | 2391 | else => unreachable, |
| 3121 | 2392 | }; |
| 3122 | assert(ip.typeOf(int_tag) == enum_type.tag_ty); | |
| 2393 | assert(ip.typeOf(int_tag) == enum_type.int_tag_type); | |
| 3123 | 2394 | return enum_type.tagValueIndex(ip, int_tag); |
| 3124 | 2395 | } |
| 3125 | 2396 | |
| 3126 | 2397 | /// Returns none in the case of a tuple which uses the integer index as the field name. |
| 3127 | 2398 | pub fn structFieldName(ty: Type, index: usize, zcu: *const Zcu) InternPool.OptionalNullTerminatedString { |
| 3128 | 2399 | const ip = &zcu.intern_pool; |
| 3129 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3130 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index).toOptional(), | |
| 3131 | .tuple_type => .none, | |
| 2400 | switch (ip.indexToKey(ty.toIntern())) { | |
| 2401 | .struct_type => { | |
| 2402 | assertHasLayout(ty, zcu); | |
| 2403 | return ip.loadStructType(ty.toIntern()).field_names.get(ip)[index].toOptional(); | |
| 2404 | }, | |
| 2405 | .tuple_type => return .none, | |
| 3132 | 2406 | else => unreachable, |
| 3133 | }; | |
| 2407 | } | |
| 3134 | 2408 | } |
| 3135 | 2409 | |
| 3136 | 2410 | pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 { |
| 3137 | 2411 | const ip = &zcu.intern_pool; |
| 3138 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3139 | .struct_type => ip.loadStructType(ty.toIntern()).field_types.len, | |
| 3140 | .tuple_type => |tuple| tuple.types.len, | |
| 2412 | switch (ip.indexToKey(ty.toIntern())) { | |
| 2413 | .struct_type => { | |
| 2414 | assertHasLayout(ty, zcu); | |
| 2415 | return ip.loadStructType(ty.toIntern()).field_types.len; | |
| 2416 | }, | |
| 2417 | .tuple_type => |tuple| return tuple.types.len, | |
| 3141 | 2418 | else => unreachable, |
| 3142 | }; | |
| 2419 | } | |
| 3143 | 2420 | } |
| 3144 | 2421 | |
| 3145 | /// Returns the field type. Supports structs and unions. | |
| 2422 | /// Returns the field type. Supports tuples, structs, and unions. | |
| 3146 | 2423 | pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type { |
| 3147 | 2424 | const ip = &zcu.intern_pool; |
| 3148 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3149 | .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]), | |
| 3150 | .union_type => { | |
| 3151 | const union_obj = ip.loadUnionType(ty.toIntern()); | |
| 3152 | return Type.fromInterned(union_obj.field_types.get(ip)[index]); | |
| 2425 | const types = switch (ip.indexToKey(ty.toIntern())) { | |
| 2426 | .struct_type => types: { | |
| 2427 | assertHasLayout(ty, zcu); | |
| 2428 | break :types ip.loadStructType(ty.toIntern()).field_types; | |
| 3153 | 2429 | }, |
| 3154 | .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]), | |
| 2430 | .union_type => types: { | |
| 2431 | assertHasLayout(ty, zcu); | |
| 2432 | break :types ip.loadUnionType(ty.toIntern()).field_types; | |
| 2433 | }, | |
| 2434 | .tuple_type => |tuple| tuple.types, | |
| 3155 | 2435 | else => unreachable, |
| 3156 | 2436 | }; |
| 2437 | return .fromInterned(types.get(ip)[index]); | |
| 3157 | 2438 | } |
| 3158 | 2439 | |
| 3159 | pub fn fieldAlignment(ty: Type, index: usize, zcu: *Zcu) Alignment { | |
| 3160 | return ty.fieldAlignmentInner(index, .normal, zcu, {}) catch unreachable; | |
| 3161 | } | |
| 3162 | ||
| 3163 | pub fn fieldAlignmentSema(ty: Type, index: usize, pt: Zcu.PerThread) SemaError!Alignment { | |
| 3164 | return try ty.fieldAlignmentInner(index, .sema, pt.zcu, pt.tid); | |
| 3165 | } | |
| 3166 | ||
| 3167 | /// Returns the field alignment. Supports structs and unions. | |
| 3168 | /// If `strat` is `.sema`, may perform type resolution. | |
| 3169 | /// Asserts the layout is not packed. | |
| 2440 | /// If an alignment was explicitly specified for the given field of the struct or union type `ty`, | |
| 2441 | /// returns that. Otherwise, returns `.none`. This function also supports tuples, for which it | |
| 2442 | /// always returns `.none`. | |
| 3170 | 2443 | /// |
| 3171 | /// Provide the struct field as the `ty`. | |
| 3172 | pub fn fieldAlignmentInner( | |
| 3173 | ty: Type, | |
| 3174 | index: usize, | |
| 3175 | comptime strat: ResolveStrat, | |
| 3176 | zcu: strat.ZcuPtr(), | |
| 3177 | tid: strat.Tid(), | |
| 3178 | ) SemaError!Alignment { | |
| 2444 | /// Asserts that the layout of `ty` is resolved, unless `ty` is a tuple. | |
| 2445 | pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment { | |
| 3179 | 2446 | const ip = &zcu.intern_pool; |
| 3180 | switch (ip.indexToKey(ty.toIntern())) { | |
| 2447 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 2448 | .tuple_type => .none, | |
| 3181 | 2449 | .struct_type => { |
| 3182 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 3183 | assert(struct_type.layout != .@"packed"); | |
| 3184 | const explicit_align = struct_type.fieldAlign(ip, index); | |
| 3185 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]); | |
| 3186 | return field_ty.structFieldAlignmentInner(explicit_align, struct_type.layout, strat, zcu, tid); | |
| 3187 | }, | |
| 3188 | .tuple_type => |tuple| { | |
| 3189 | return (try Type.fromInterned(tuple.types.get(ip)[index]).abiAlignmentInner( | |
| 3190 | strat.toLazy(), | |
| 3191 | zcu, | |
| 3192 | tid, | |
| 3193 | )).scalar; | |
| 2450 | assertHasLayout(ty, zcu); | |
| 2451 | const struct_obj = ip.loadStructType(ty.toIntern()); | |
| 2452 | assert(struct_obj.layout != .@"packed"); | |
| 2453 | if (struct_obj.field_aligns.len == 0) return .none; | |
| 2454 | return struct_obj.field_aligns.get(ip)[index]; | |
| 3194 | 2455 | }, |
| 3195 | 2456 | .union_type => { |
| 2457 | assertHasLayout(ty, zcu); | |
| 3196 | 2458 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 3197 | const layout = union_obj.flagsUnordered(ip).layout; | |
| 3198 | assert(layout != .@"packed"); | |
| 3199 | const explicit_align = union_obj.fieldAlign(ip, index); | |
| 3200 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[index]); | |
| 3201 | return field_ty.unionFieldAlignmentInner(explicit_align, layout, strat, zcu, tid); | |
| 2459 | assert(union_obj.layout != .@"packed"); | |
| 2460 | if (union_obj.field_aligns.len == 0) return .none; | |
| 2461 | return union_obj.field_aligns.get(ip)[index]; | |
| 3202 | 2462 | }, |
| 3203 | 2463 | else => unreachable, |
| 3204 | } | |
| 2464 | }; | |
| 3205 | 2465 | } |
| 3206 | 2466 | |
| 3207 | /// Returns the alignment of a non-packed struct field. Assert the layout is not packed. | |
| 2467 | /// Returns the alignment a struct field of type `field_ty` will be given if no alignment is | |
| 2468 | /// explicitly specified. However, in an `extern struct`, a higher alignment may be available due | |
| 2469 | /// to the struct's full layout (i.e. a field might coincidentally be more aligned). | |
| 3208 | 2470 | /// |
| 3209 | /// Asserts that all resolution needed was done. | |
| 3210 | pub fn structFieldAlignment( | |
| 2471 | /// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`. | |
| 2472 | pub fn defaultStructFieldAlignment( | |
| 3211 | 2473 | field_ty: Type, |
| 3212 | explicit_alignment: InternPool.Alignment, | |
| 3213 | 2474 | layout: std.builtin.Type.ContainerLayout, |
| 3214 | zcu: *Zcu, | |
| 2475 | zcu: *const Zcu, | |
| 3215 | 2476 | ) Alignment { |
| 3216 | return field_ty.structFieldAlignmentInner( | |
| 3217 | explicit_alignment, | |
| 3218 | layout, | |
| 3219 | .normal, | |
| 3220 | zcu, | |
| 3221 | {}, | |
| 3222 | ) catch unreachable; | |
| 3223 | } | |
| 3224 | ||
| 3225 | /// Returns the alignment of a non-packed struct field. Assert the layout is not packed. | |
| 3226 | /// May do type resolution when needed. | |
| 3227 | /// Asserts that all resolution needed was done. | |
| 3228 | pub fn structFieldAlignmentSema( | |
| 3229 | field_ty: Type, | |
| 3230 | explicit_alignment: InternPool.Alignment, | |
| 3231 | layout: std.builtin.Type.ContainerLayout, | |
| 3232 | pt: Zcu.PerThread, | |
| 3233 | ) SemaError!Alignment { | |
| 3234 | return try field_ty.structFieldAlignmentInner( | |
| 3235 | explicit_alignment, | |
| 3236 | layout, | |
| 3237 | .sema, | |
| 3238 | pt.zcu, | |
| 3239 | pt.tid, | |
| 3240 | ); | |
| 3241 | } | |
| 3242 | ||
| 3243 | /// Returns the alignment of a non-packed struct field. Asserts the layout is not packed. | |
| 3244 | /// If `strat` is `.sema`, may perform type resolution. | |
| 3245 | pub fn structFieldAlignmentInner( | |
| 3246 | field_ty: Type, | |
| 3247 | explicit_alignment: Alignment, | |
| 3248 | layout: std.builtin.Type.ContainerLayout, | |
| 3249 | comptime strat: Type.ResolveStrat, | |
| 3250 | zcu: strat.ZcuPtr(), | |
| 3251 | tid: strat.Tid(), | |
| 3252 | ) SemaError!Alignment { | |
| 3253 | assert(layout != .@"packed"); | |
| 3254 | if (explicit_alignment != .none) return explicit_alignment; | |
| 3255 | const ty_abi_align = (try field_ty.abiAlignmentInner( | |
| 3256 | strat.toLazy(), | |
| 3257 | zcu, | |
| 3258 | tid, | |
| 3259 | )).scalar; | |
| 3260 | switch (layout) { | |
| 2477 | const overalign_big_int = switch (layout) { | |
| 3261 | 2478 | .@"packed" => unreachable, |
| 3262 | .auto => if (zcu.getTarget().ofmt != .c) return ty_abi_align, | |
| 3263 | .@"extern" => {}, | |
| 3264 | } | |
| 3265 | // extern | |
| 3266 | if (field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) { | |
| 3267 | return ty_abi_align.maxStrict(.@"16"); | |
| 2479 | .auto => zcu.getTarget().ofmt == .c, | |
| 2480 | .@"extern" => true, | |
| 2481 | }; | |
| 2482 | const abi_align = field_ty.abiAlignment(zcu); | |
| 2483 | assert(abi_align != .none); | |
| 2484 | if (overalign_big_int and field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) { | |
| 2485 | return abi_align.maxStrict(.@"16"); | |
| 3268 | 2486 | } |
| 3269 | return ty_abi_align; | |
| 3270 | } | |
| 3271 | ||
| 3272 | pub fn unionFieldAlignmentSema( | |
| 3273 | field_ty: Type, | |
| 3274 | explicit_alignment: Alignment, | |
| 3275 | layout: std.builtin.Type.ContainerLayout, | |
| 3276 | pt: Zcu.PerThread, | |
| 3277 | ) SemaError!Alignment { | |
| 3278 | return field_ty.unionFieldAlignmentInner( | |
| 3279 | explicit_alignment, | |
| 3280 | layout, | |
| 3281 | .sema, | |
| 3282 | pt.zcu, | |
| 3283 | pt.tid, | |
| 3284 | ); | |
| 3285 | } | |
| 3286 | ||
| 3287 | pub fn unionFieldAlignmentInner( | |
| 3288 | field_ty: Type, | |
| 3289 | explicit_alignment: Alignment, | |
| 3290 | layout: std.builtin.Type.ContainerLayout, | |
| 3291 | comptime strat: Type.ResolveStrat, | |
| 3292 | zcu: strat.ZcuPtr(), | |
| 3293 | tid: strat.Tid(), | |
| 3294 | ) SemaError!Alignment { | |
| 3295 | assert(layout != .@"packed"); | |
| 3296 | if (explicit_alignment != .none) return explicit_alignment; | |
| 3297 | if (field_ty.isNoReturn(zcu)) return .none; | |
| 3298 | return (try field_ty.abiAlignmentInner(strat.toLazy(), zcu, tid)).scalar; | |
| 2487 | return abi_align; | |
| 3299 | 2488 | } |
| 3300 | 2489 | |
| 3301 | pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) Value { | |
| 2490 | pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value { | |
| 3302 | 2491 | const ip = &zcu.intern_pool; |
| 3303 | 2492 | switch (ip.indexToKey(ty.toIntern())) { |
| 3304 | 2493 | .struct_type => { |
| 3305 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 3306 | const val = struct_type.fieldInit(ip, index); | |
| 3307 | // TODO: avoid using `unreachable` to indicate this. | |
| 3308 | if (val == .none) return Value.@"unreachable"; | |
| 3309 | return Value.fromInterned(val); | |
| 2494 | const field_defaults = ip.loadStructType(ty.toIntern()).field_defaults.get(ip); | |
| 2495 | if (field_defaults.len == 0) return null; | |
| 2496 | if (field_defaults[index] == .none) return null; | |
| 2497 | return .fromInterned(field_defaults[index]); | |
| 3310 | 2498 | }, |
| 3311 | 2499 | .tuple_type => |tuple| { |
| 3312 | 2500 | const val = tuple.values.get(ip)[index]; |
| 3313 | // TODO: avoid using `unreachable` to indicate this. | |
| 3314 | if (val == .none) return Value.@"unreachable"; | |
| 3315 | return Value.fromInterned(val); | |
| 2501 | if (val == .none) return null; | |
| 2502 | return .fromInterned(val); | |
| 3316 | 2503 | }, |
| 3317 | 2504 | else => unreachable, |
| 3318 | 2505 | } |
| ... | ... | @@ -3324,9 +2511,8 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val |
| 3324 | 2511 | switch (ip.indexToKey(ty.toIntern())) { |
| 3325 | 2512 | .struct_type => { |
| 3326 | 2513 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 3327 | if (struct_type.fieldIsComptime(ip, index)) { | |
| 3328 | assert(struct_type.haveFieldInits(ip)); | |
| 3329 | return Value.fromInterned(struct_type.field_inits.get(ip)[index]); | |
| 2514 | if (struct_type.field_is_comptime_bits.get(ip, index)) { | |
| 2515 | return .fromInterned(struct_type.field_defaults.get(ip)[index]); | |
| 3330 | 2516 | } else { |
| 3331 | 2517 | return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(pt); |
| 3332 | 2518 | } |
| ... | ... | @@ -3336,7 +2522,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val |
| 3336 | 2522 | if (val == .none) { |
| 3337 | 2523 | return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(pt); |
| 3338 | 2524 | } else { |
| 3339 | return Value.fromInterned(val); | |
| 2525 | return .fromInterned(val); | |
| 3340 | 2526 | } |
| 3341 | 2527 | }, |
| 3342 | 2528 | else => unreachable, |
| ... | ... | @@ -3345,11 +2531,14 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val |
| 3345 | 2531 | |
| 3346 | 2532 | pub fn structFieldIsComptime(ty: Type, index: usize, zcu: *const Zcu) bool { |
| 3347 | 2533 | const ip = &zcu.intern_pool; |
| 3348 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3349 | .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index), | |
| 3350 | .tuple_type => |tuple| tuple.values.get(ip)[index] != .none, | |
| 2534 | switch (ip.indexToKey(ty.toIntern())) { | |
| 2535 | .struct_type => { | |
| 2536 | assertHasLayout(ty, zcu); | |
| 2537 | return ip.loadStructType(ty.toIntern()).field_is_comptime_bits.get(ip, index); | |
| 2538 | }, | |
| 2539 | .tuple_type => |tuple| return tuple.values.get(ip)[index] != .none, | |
| 3351 | 2540 | else => unreachable, |
| 3352 | }; | |
| 2541 | } | |
| 3353 | 2542 | } |
| 3354 | 2543 | |
| 3355 | 2544 | pub const FieldOffset = struct { |
| ... | ... | @@ -3357,15 +2546,15 @@ pub const FieldOffset = struct { |
| 3357 | 2546 | offset: u64, |
| 3358 | 2547 | }; |
| 3359 | 2548 | |
| 3360 | /// Supports structs and unions. | |
| 2549 | /// Supports structs, tuples, and unions. | |
| 3361 | 2550 | pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { |
| 2551 | assertHasLayout(ty, zcu); | |
| 3362 | 2552 | const ip = &zcu.intern_pool; |
| 3363 | 2553 | switch (ip.indexToKey(ty.toIntern())) { |
| 3364 | 2554 | .struct_type => { |
| 3365 | 2555 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 3366 | assert(struct_type.haveLayout(ip)); | |
| 3367 | 2556 | assert(struct_type.layout != .@"packed"); |
| 3368 | return struct_type.offsets.get(ip)[index]; | |
| 2557 | return struct_type.field_offsets.get(ip)[index]; | |
| 3369 | 2558 | }, |
| 3370 | 2559 | |
| 3371 | 2560 | .tuple_type => |tuple| { |
| ... | ... | @@ -3375,7 +2564,7 @@ pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { |
| 3375 | 2564 | for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { |
| 3376 | 2565 | if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) { |
| 3377 | 2566 | // comptime field |
| 3378 | if (i == index) return offset; | |
| 2567 | if (i == index) return 0; | |
| 3379 | 2568 | continue; |
| 3380 | 2569 | } |
| 3381 | 2570 | |
| ... | ... | @@ -3391,8 +2580,7 @@ pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { |
| 3391 | 2580 | |
| 3392 | 2581 | .union_type => { |
| 3393 | 2582 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 3394 | if (!union_type.hasTag(ip)) | |
| 3395 | return 0; | |
| 2583 | if (!union_type.has_runtime_tag) return 0; | |
| 3396 | 2584 | const layout = Type.getUnionLayout(union_type, zcu); |
| 3397 | 2585 | if (layout.tag_align.compare(.gte, layout.payload_align)) { |
| 3398 | 2586 | // {Tag, Payload} |
| ... | ... | @@ -3414,7 +2602,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc { |
| 3414 | 2602 | .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) { |
| 3415 | 2603 | .declared => |d| d.zir_index, |
| 3416 | 2604 | .reified => |r| r.zir_index, |
| 3417 | .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, | |
| 2605 | .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index, | |
| 3418 | 2606 | }, |
| 3419 | 2607 | else => return null, |
| 3420 | 2608 | }, |
| ... | ... | @@ -3438,8 +2626,8 @@ pub fn isTuple(ty: Type, zcu: *const Zcu) bool { |
| 3438 | 2626 | }; |
| 3439 | 2627 | } |
| 3440 | 2628 | |
| 3441 | /// Traverses optional child types and error union payloads until the type | |
| 3442 | /// is not a pointer. For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`. | |
| 2629 | /// Traverses optional child types and error union payloads until the type is neither of those. | |
| 2630 | /// For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`. | |
| 3443 | 2631 | pub fn optEuBaseType(ty: Type, zcu: *const Zcu) Type { |
| 3444 | 2632 | var cur = ty; |
| 3445 | 2633 | while (true) switch (cur.zigTypeTag(zcu)) { |
| ... | ... | @@ -3485,439 +2673,81 @@ pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.Trac |
| 3485 | 2673 | const ip = &zcu.intern_pool; |
| 3486 | 2674 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3487 | 2675 | .struct_type => ip.loadStructType(ty.toIntern()).zir_index, |
| 3488 | .union_type => ip.loadUnionType(ty.toIntern()).zir_index, | |
| 3489 | .enum_type => |e| switch (e) { | |
| 3490 | .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?, | |
| 3491 | .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, | |
| 3492 | }, | |
| 3493 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index, | |
| 3494 | else => null, | |
| 3495 | }; | |
| 3496 | } | |
| 3497 | ||
| 3498 | pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { | |
| 3499 | // Note that changes to ZIR instruction tracking only need to update this code | |
| 3500 | // if a newly-tracked instruction can be a type's owner `zir_index`. | |
| 3501 | comptime assert(Zir.inst_tracking_version == 0); | |
| 3502 | ||
| 3503 | const ip = &zcu.intern_pool; | |
| 3504 | const tracked = switch (ip.indexToKey(ty.toIntern())) { | |
| 3505 | .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) { | |
| 3506 | .declared => |d| d.zir_index, | |
| 3507 | .reified => |r| r.zir_index, | |
| 3508 | .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, | |
| 3509 | }, | |
| 3510 | else => return null, | |
| 3511 | }; | |
| 3512 | const info = tracked.resolveFull(&zcu.intern_pool) orelse return null; | |
| 3513 | const file = zcu.fileByIndex(info.file); | |
| 3514 | const zir = switch (file.getMode()) { | |
| 3515 | .zig => file.zir.?, | |
| 3516 | .zon => return 0, | |
| 3517 | }; | |
| 3518 | const inst = zir.instructions.get(@intFromEnum(info.inst)); | |
| 3519 | return switch (inst.tag) { | |
| 3520 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line, | |
| 3521 | .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_line, | |
| 3522 | .extended => switch (inst.data.extended.opcode) { | |
| 3523 | .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line, | |
| 3524 | .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line, | |
| 3525 | .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line, | |
| 3526 | .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line, | |
| 3527 | .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line, | |
| 3528 | .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line, | |
| 3529 | .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line, | |
| 3530 | else => unreachable, | |
| 3531 | }, | |
| 3532 | else => unreachable, | |
| 3533 | }; | |
| 3534 | } | |
| 3535 | ||
| 3536 | /// Given a namespace type, returns its list of captured values. | |
| 3537 | pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice { | |
| 3538 | const ip = &zcu.intern_pool; | |
| 3539 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 3540 | .struct_type => ip.loadStructType(ty.toIntern()).captures, | |
| 3541 | .union_type => ip.loadUnionType(ty.toIntern()).captures, | |
| 3542 | .enum_type => ip.loadEnumType(ty.toIntern()).captures, | |
| 3543 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures, | |
| 3544 | else => unreachable, | |
| 3545 | }; | |
| 3546 | } | |
| 3547 | ||
| 3548 | pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } { | |
| 3549 | var cur_ty: Type = ty; | |
| 3550 | var cur_len: u64 = 1; | |
| 3551 | while (cur_ty.zigTypeTag(zcu) == .array) { | |
| 3552 | cur_len *= cur_ty.arrayLenIncludingSentinel(zcu); | |
| 3553 | cur_ty = cur_ty.childType(zcu); | |
| 3554 | } | |
| 3555 | return .{ cur_ty, cur_len }; | |
| 3556 | } | |
| 3557 | ||
| 3558 | /// Returns a bit-pointer with the same value and a new packed offset. | |
| 3559 | pub fn packedStructFieldPtrInfo( | |
| 3560 | struct_ty: Type, | |
| 3561 | parent_ptr_ty: Type, | |
| 3562 | field_idx: u32, | |
| 3563 | pt: Zcu.PerThread, | |
| 3564 | ) InternPool.Key.PtrType.PackedOffset { | |
| 3565 | comptime assert(Type.packed_struct_layout_version == 2); | |
| 3566 | ||
| 3567 | const zcu = pt.zcu; | |
| 3568 | const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); | |
| 3569 | ||
| 3570 | var bit_offset: u16 = 0; | |
| 3571 | var running_bits: u16 = 0; | |
| 3572 | for (0..struct_ty.structFieldCount(zcu)) |i| { | |
| 3573 | const f_ty = struct_ty.fieldType(i, zcu); | |
| 3574 | if (i == field_idx) { | |
| 3575 | bit_offset = running_bits; | |
| 3576 | } | |
| 3577 | running_bits += @intCast(f_ty.bitSize(zcu)); | |
| 3578 | } | |
| 3579 | ||
| 3580 | const res_host_size: u16, const res_bit_offset: u16 = if (parent_ptr_info.packed_offset.host_size != 0) .{ | |
| 3581 | parent_ptr_info.packed_offset.host_size, | |
| 3582 | parent_ptr_info.packed_offset.bit_offset + bit_offset, | |
| 3583 | } else .{ | |
| 3584 | switch (zcu.comp.getZigBackend()) { | |
| 3585 | else => (running_bits + 7) / 8, | |
| 3586 | .stage2_x86_64, .stage2_c => @intCast(struct_ty.abiSize(zcu)), | |
| 3587 | }, | |
| 3588 | bit_offset, | |
| 3589 | }; | |
| 3590 | ||
| 3591 | return .{ | |
| 3592 | .host_size = res_host_size, | |
| 3593 | .bit_offset = res_bit_offset, | |
| 3594 | }; | |
| 3595 | } | |
| 3596 | ||
| 3597 | pub fn resolveLayout(ty: Type, pt: Zcu.PerThread) SemaError!void { | |
| 3598 | const zcu = pt.zcu; | |
| 3599 | const ip = &zcu.intern_pool; | |
| 3600 | switch (ty.zigTypeTag(zcu)) { | |
| 3601 | .@"struct" => switch (ip.indexToKey(ty.toIntern())) { | |
| 3602 | .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| { | |
| 3603 | const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]); | |
| 3604 | try field_ty.resolveLayout(pt); | |
| 3605 | }, | |
| 3606 | .struct_type => return ty.resolveStructInner(pt, .layout), | |
| 3607 | else => unreachable, | |
| 3608 | }, | |
| 3609 | .@"union" => return ty.resolveUnionInner(pt, .layout), | |
| 3610 | .array => { | |
| 3611 | if (ty.arrayLenIncludingSentinel(zcu) == 0) return; | |
| 3612 | const elem_ty = ty.childType(zcu); | |
| 3613 | return elem_ty.resolveLayout(pt); | |
| 3614 | }, | |
| 3615 | .optional => { | |
| 3616 | const payload_ty = ty.optionalChild(zcu); | |
| 3617 | return payload_ty.resolveLayout(pt); | |
| 3618 | }, | |
| 3619 | .error_union => { | |
| 3620 | const payload_ty = ty.errorUnionPayload(zcu); | |
| 3621 | return payload_ty.resolveLayout(pt); | |
| 3622 | }, | |
| 3623 | .@"fn" => { | |
| 3624 | const info = zcu.typeToFunc(ty).?; | |
| 3625 | if (info.is_generic) { | |
| 3626 | // Resolving of generic function types is deferred to when | |
| 3627 | // the function is instantiated. | |
| 3628 | return; | |
| 3629 | } | |
| 3630 | for (0..info.param_types.len) |i| { | |
| 3631 | const param_ty = info.param_types.get(ip)[i]; | |
| 3632 | try Type.fromInterned(param_ty).resolveLayout(pt); | |
| 3633 | } | |
| 3634 | try Type.fromInterned(info.return_type).resolveLayout(pt); | |
| 3635 | }, | |
| 3636 | else => {}, | |
| 3637 | } | |
| 3638 | } | |
| 3639 | ||
| 3640 | pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void { | |
| 3641 | const ip = &pt.zcu.intern_pool; | |
| 3642 | const ty_ip = ty.toIntern(); | |
| 3643 | ||
| 3644 | switch (ty_ip) { | |
| 3645 | .none => unreachable, | |
| 3646 | ||
| 3647 | .u0_type, | |
| 3648 | .i0_type, | |
| 3649 | .u1_type, | |
| 3650 | .u8_type, | |
| 3651 | .i8_type, | |
| 3652 | .u16_type, | |
| 3653 | .i16_type, | |
| 3654 | .u29_type, | |
| 3655 | .u32_type, | |
| 3656 | .i32_type, | |
| 3657 | .u64_type, | |
| 3658 | .i64_type, | |
| 3659 | .u80_type, | |
| 3660 | .u128_type, | |
| 3661 | .i128_type, | |
| 3662 | .usize_type, | |
| 3663 | .isize_type, | |
| 3664 | .c_char_type, | |
| 3665 | .c_short_type, | |
| 3666 | .c_ushort_type, | |
| 3667 | .c_int_type, | |
| 3668 | .c_uint_type, | |
| 3669 | .c_long_type, | |
| 3670 | .c_ulong_type, | |
| 3671 | .c_longlong_type, | |
| 3672 | .c_ulonglong_type, | |
| 3673 | .c_longdouble_type, | |
| 3674 | .f16_type, | |
| 3675 | .f32_type, | |
| 3676 | .f64_type, | |
| 3677 | .f80_type, | |
| 3678 | .f128_type, | |
| 3679 | .anyopaque_type, | |
| 3680 | .bool_type, | |
| 3681 | .void_type, | |
| 3682 | .type_type, | |
| 3683 | .anyerror_type, | |
| 3684 | .adhoc_inferred_error_set_type, | |
| 3685 | .comptime_int_type, | |
| 3686 | .comptime_float_type, | |
| 3687 | .noreturn_type, | |
| 3688 | .anyframe_type, | |
| 3689 | .null_type, | |
| 3690 | .undefined_type, | |
| 3691 | .enum_literal_type, | |
| 3692 | .ptr_usize_type, | |
| 3693 | .ptr_const_comptime_int_type, | |
| 3694 | .manyptr_u8_type, | |
| 3695 | .manyptr_const_u8_type, | |
| 3696 | .manyptr_const_u8_sentinel_0_type, | |
| 3697 | .slice_const_u8_type, | |
| 3698 | .slice_const_u8_sentinel_0_type, | |
| 3699 | .optional_noreturn_type, | |
| 3700 | .anyerror_void_error_union_type, | |
| 3701 | .generic_poison_type, | |
| 3702 | .empty_tuple_type, | |
| 3703 | => {}, | |
| 3704 | ||
| 3705 | .undef => unreachable, | |
| 3706 | .zero => unreachable, | |
| 3707 | .zero_usize => unreachable, | |
| 3708 | .zero_u1 => unreachable, | |
| 3709 | .zero_u8 => unreachable, | |
| 3710 | .one => unreachable, | |
| 3711 | .one_usize => unreachable, | |
| 3712 | .one_u1 => unreachable, | |
| 3713 | .one_u8 => unreachable, | |
| 3714 | .four_u8 => unreachable, | |
| 3715 | .negative_one => unreachable, | |
| 3716 | .void_value => unreachable, | |
| 3717 | .unreachable_value => unreachable, | |
| 3718 | .null_value => unreachable, | |
| 3719 | .bool_true => unreachable, | |
| 3720 | .bool_false => unreachable, | |
| 3721 | .empty_tuple => unreachable, | |
| 3722 | ||
| 3723 | else => switch (ty_ip.unwrap(ip).getTag(ip)) { | |
| 3724 | .type_struct, | |
| 3725 | .type_struct_packed, | |
| 3726 | .type_struct_packed_inits, | |
| 3727 | => return ty.resolveStructInner(pt, .fields), | |
| 3728 | ||
| 3729 | .type_union => return ty.resolveUnionInner(pt, .fields), | |
| 3730 | ||
| 3731 | else => {}, | |
| 3732 | }, | |
| 3733 | } | |
| 3734 | } | |
| 3735 | ||
| 3736 | pub fn resolveFully(ty: Type, pt: Zcu.PerThread) SemaError!void { | |
| 3737 | const zcu = pt.zcu; | |
| 3738 | const ip = &zcu.intern_pool; | |
| 3739 | ||
| 3740 | switch (ty.zigTypeTag(zcu)) { | |
| 3741 | .type, | |
| 3742 | .void, | |
| 3743 | .bool, | |
| 3744 | .noreturn, | |
| 3745 | .int, | |
| 3746 | .float, | |
| 3747 | .comptime_float, | |
| 3748 | .comptime_int, | |
| 3749 | .undefined, | |
| 3750 | .null, | |
| 3751 | .error_set, | |
| 3752 | .@"enum", | |
| 3753 | .@"opaque", | |
| 3754 | .frame, | |
| 3755 | .@"anyframe", | |
| 3756 | .vector, | |
| 3757 | .enum_literal, | |
| 3758 | => {}, | |
| 3759 | ||
| 3760 | .pointer => return ty.childType(zcu).resolveFully(pt), | |
| 3761 | .array => return ty.childType(zcu).resolveFully(pt), | |
| 3762 | .optional => return ty.optionalChild(zcu).resolveFully(pt), | |
| 3763 | .error_union => return ty.errorUnionPayload(zcu).resolveFully(pt), | |
| 3764 | .@"fn" => { | |
| 3765 | const info = zcu.typeToFunc(ty).?; | |
| 3766 | if (info.is_generic) return; | |
| 3767 | for (0..info.param_types.len) |i| { | |
| 3768 | const param_ty = info.param_types.get(ip)[i]; | |
| 3769 | try Type.fromInterned(param_ty).resolveFully(pt); | |
| 3770 | } | |
| 3771 | try Type.fromInterned(info.return_type).resolveFully(pt); | |
| 3772 | }, | |
| 3773 | ||
| 3774 | .@"struct" => switch (ip.indexToKey(ty.toIntern())) { | |
| 3775 | .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| { | |
| 3776 | const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]); | |
| 3777 | try field_ty.resolveFully(pt); | |
| 3778 | }, | |
| 3779 | .struct_type => return ty.resolveStructInner(pt, .full), | |
| 3780 | else => unreachable, | |
| 3781 | }, | |
| 3782 | .@"union" => return ty.resolveUnionInner(pt, .full), | |
| 3783 | } | |
| 3784 | } | |
| 3785 | ||
| 3786 | pub fn resolveStructFieldInits(ty: Type, pt: Zcu.PerThread) SemaError!void { | |
| 3787 | // TODO: stop calling this for tuples! | |
| 3788 | _ = pt.zcu.typeToStruct(ty) orelse return; | |
| 3789 | return ty.resolveStructInner(pt, .inits); | |
| 3790 | } | |
| 3791 | ||
| 3792 | pub fn resolveStructAlignment(ty: Type, pt: Zcu.PerThread) SemaError!void { | |
| 3793 | return ty.resolveStructInner(pt, .alignment); | |
| 3794 | } | |
| 3795 | ||
| 3796 | pub fn resolveUnionAlignment(ty: Type, pt: Zcu.PerThread) SemaError!void { | |
| 3797 | return ty.resolveUnionInner(pt, .alignment); | |
| 3798 | } | |
| 3799 | ||
| 3800 | /// `ty` must be a struct. | |
| 3801 | fn resolveStructInner( | |
| 3802 | ty: Type, | |
| 3803 | pt: Zcu.PerThread, | |
| 3804 | resolution: enum { fields, inits, alignment, layout, full }, | |
| 3805 | ) SemaError!void { | |
| 3806 | const zcu = pt.zcu; | |
| 3807 | const gpa = zcu.gpa; | |
| 3808 | ||
| 3809 | const struct_obj = zcu.typeToStruct(ty).?; | |
| 3810 | const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() }); | |
| 3811 | ||
| 3812 | if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) { | |
| 3813 | return error.AnalysisFail; | |
| 3814 | } | |
| 3815 | ||
| 3816 | if (zcu.comp.debugIncremental()) { | |
| 3817 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner); | |
| 3818 | info.last_update_gen = zcu.generation; | |
| 3819 | } | |
| 3820 | ||
| 3821 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | |
| 3822 | defer analysis_arena.deinit(); | |
| 2676 | .union_type => ip.loadUnionType(ty.toIntern()).zir_index, | |
| 2677 | .enum_type => |e| switch (e) { | |
| 2678 | .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?, | |
| 2679 | .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index, | |
| 2680 | }, | |
| 2681 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index, | |
| 2682 | else => null, | |
| 2683 | }; | |
| 2684 | } | |
| 3823 | 2685 | |
| 3824 | var comptime_err_ret_trace = std.array_list.Managed(Zcu.LazySrcLoc).init(gpa); | |
| 3825 | defer comptime_err_ret_trace.deinit(); | |
| 2686 | pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { | |
| 2687 | // Note that changes to ZIR instruction tracking only need to update this code | |
| 2688 | // if a newly-tracked instruction can be a type's owner `zir_index`. | |
| 2689 | comptime assert(Zir.inst_tracking_version == 0); | |
| 3826 | 2690 | |
| 3827 | const zir = zcu.namespacePtr(struct_obj.namespace).fileScope(zcu).zir.?; | |
| 3828 | var sema: Sema = .{ | |
| 3829 | .pt = pt, | |
| 3830 | .gpa = gpa, | |
| 3831 | .arena = analysis_arena.allocator(), | |
| 3832 | .code = zir, | |
| 3833 | .owner = owner, | |
| 3834 | .func_index = .none, | |
| 3835 | .func_is_naked = false, | |
| 3836 | .fn_ret_ty = Type.void, | |
| 3837 | .fn_ret_ty_ies = null, | |
| 3838 | .comptime_err_ret_trace = &comptime_err_ret_trace, | |
| 2691 | const ip = &zcu.intern_pool; | |
| 2692 | const tracked = switch (ip.indexToKey(ty.toIntern())) { | |
| 2693 | .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) { | |
| 2694 | .declared => |d| d.zir_index, | |
| 2695 | .reified => |r| r.zir_index, | |
| 2696 | .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index, | |
| 2697 | }, | |
| 2698 | else => return null, | |
| 3839 | 2699 | }; |
| 3840 | defer sema.deinit(); | |
| 3841 | ||
| 3842 | (switch (resolution) { | |
| 3843 | .fields => sema.resolveStructFieldTypes(ty.toIntern(), struct_obj), | |
| 3844 | .inits => sema.resolveStructFieldInits(ty), | |
| 3845 | .alignment => sema.resolveStructAlignment(ty.toIntern(), struct_obj), | |
| 3846 | .layout => sema.resolveStructLayout(ty), | |
| 3847 | .full => sema.resolveStructFully(ty), | |
| 3848 | }) catch |err| switch (err) { | |
| 3849 | error.AnalysisFail => { | |
| 3850 | if (!zcu.failed_analysis.contains(owner)) { | |
| 3851 | try zcu.transitive_failed_analysis.put(gpa, owner, {}); | |
| 3852 | } | |
| 3853 | return error.AnalysisFail; | |
| 2700 | const info = tracked.resolveFull(&zcu.intern_pool) orelse return null; | |
| 2701 | const file = zcu.fileByIndex(info.file); | |
| 2702 | const zir = switch (file.getMode()) { | |
| 2703 | .zig => file.zir.?, | |
| 2704 | .zon => return 0, | |
| 2705 | }; | |
| 2706 | const inst = zir.instructions.get(@intFromEnum(info.inst)); | |
| 2707 | return switch (inst.tag) { | |
| 2708 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line, | |
| 2709 | .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_line, | |
| 2710 | .extended => switch (inst.data.extended.opcode) { | |
| 2711 | .struct_decl => zir.getStructDecl(info.inst).src_line, | |
| 2712 | .union_decl => zir.getUnionDecl(info.inst).src_line, | |
| 2713 | .enum_decl => zir.getEnumDecl(info.inst).src_line, | |
| 2714 | .opaque_decl => zir.getOpaqueDecl(info.inst).src_line, | |
| 2715 | .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line, | |
| 2716 | .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line, | |
| 2717 | .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line, | |
| 2718 | else => unreachable, | |
| 3854 | 2719 | }, |
| 3855 | error.OutOfMemory, error.Canceled => |e| return e, | |
| 2720 | else => unreachable, | |
| 3856 | 2721 | }; |
| 3857 | 2722 | } |
| 3858 | 2723 | |
| 3859 | /// `ty` must be a union. | |
| 3860 | fn resolveUnionInner( | |
| 3861 | ty: Type, | |
| 3862 | pt: Zcu.PerThread, | |
| 3863 | resolution: enum { fields, alignment, layout, full }, | |
| 3864 | ) SemaError!void { | |
| 3865 | const zcu = pt.zcu; | |
| 3866 | const gpa = zcu.gpa; | |
| 3867 | ||
| 3868 | const union_obj = zcu.typeToUnion(ty).?; | |
| 3869 | const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() }); | |
| 3870 | ||
| 3871 | if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) { | |
| 3872 | return error.AnalysisFail; | |
| 3873 | } | |
| 2724 | /// Given a namespace type, returns its list of captured values. | |
| 2725 | pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice { | |
| 2726 | const ip = &zcu.intern_pool; | |
| 2727 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 2728 | .struct_type => ip.loadStructType(ty.toIntern()).captures, | |
| 2729 | .union_type => ip.loadUnionType(ty.toIntern()).captures, | |
| 2730 | .enum_type => ip.loadEnumType(ty.toIntern()).captures, | |
| 2731 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures, | |
| 2732 | else => unreachable, | |
| 2733 | }; | |
| 2734 | } | |
| 3874 | 2735 | |
| 3875 | if (zcu.comp.debugIncremental()) { | |
| 3876 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner); | |
| 3877 | info.last_update_gen = zcu.generation; | |
| 2736 | pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } { | |
| 2737 | var cur_ty: Type = ty; | |
| 2738 | var cur_len: u64 = 1; | |
| 2739 | while (cur_ty.zigTypeTag(zcu) == .array) { | |
| 2740 | cur_len *= cur_ty.arrayLenIncludingSentinel(zcu); | |
| 2741 | cur_ty = cur_ty.childType(zcu); | |
| 3878 | 2742 | } |
| 3879 | ||
| 3880 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | |
| 3881 | defer analysis_arena.deinit(); | |
| 3882 | ||
| 3883 | var comptime_err_ret_trace = std.array_list.Managed(Zcu.LazySrcLoc).init(gpa); | |
| 3884 | defer comptime_err_ret_trace.deinit(); | |
| 3885 | ||
| 3886 | const zir = zcu.namespacePtr(union_obj.namespace).fileScope(zcu).zir.?; | |
| 3887 | var sema: Sema = .{ | |
| 3888 | .pt = pt, | |
| 3889 | .gpa = gpa, | |
| 3890 | .arena = analysis_arena.allocator(), | |
| 3891 | .code = zir, | |
| 3892 | .owner = owner, | |
| 3893 | .func_index = .none, | |
| 3894 | .func_is_naked = false, | |
| 3895 | .fn_ret_ty = Type.void, | |
| 3896 | .fn_ret_ty_ies = null, | |
| 3897 | .comptime_err_ret_trace = &comptime_err_ret_trace, | |
| 3898 | }; | |
| 3899 | defer sema.deinit(); | |
| 3900 | ||
| 3901 | (switch (resolution) { | |
| 3902 | .fields => sema.resolveUnionFieldTypes(ty, union_obj), | |
| 3903 | .alignment => sema.resolveUnionAlignment(ty, union_obj), | |
| 3904 | .layout => sema.resolveUnionLayout(ty), | |
| 3905 | .full => sema.resolveUnionFully(ty), | |
| 3906 | }) catch |err| switch (err) { | |
| 3907 | error.AnalysisFail => { | |
| 3908 | if (!zcu.failed_analysis.contains(owner)) { | |
| 3909 | try zcu.transitive_failed_analysis.put(gpa, owner, {}); | |
| 3910 | } | |
| 3911 | return error.AnalysisFail; | |
| 3912 | }, | |
| 3913 | error.OutOfMemory => |e| return e, | |
| 3914 | error.Canceled => |e| return e, | |
| 3915 | }; | |
| 2743 | return .{ cur_ty, cur_len }; | |
| 3916 | 2744 | } |
| 3917 | 2745 | |
| 2746 | /// Asserts that `loaded_union.layout` is not `.@"packed"`. | |
| 3918 | 2747 | pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout { |
| 2748 | assert(loaded_union.layout != .@"packed"); | |
| 2749 | ||
| 3919 | 2750 | const ip = &zcu.intern_pool; |
| 3920 | assert(loaded_union.haveLayout(ip)); | |
| 3921 | 2751 | var most_aligned_field: u32 = 0; |
| 3922 | 2752 | var most_aligned_field_align: InternPool.Alignment = .@"1"; |
| 3923 | 2753 | var most_aligned_field_size: u64 = 0; |
| ... | ... | @@ -3928,11 +2758,14 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) |
| 3928 | 2758 | const field_ty: Type = .fromInterned(field_ty_ip_index); |
| 3929 | 2759 | if (field_ty.isNoReturn(zcu)) continue; |
| 3930 | 2760 | |
| 3931 | const explicit_align = loaded_union.fieldAlign(ip, field_index); | |
| 3932 | const field_align = if (explicit_align != .none) | |
| 3933 | explicit_align | |
| 3934 | else | |
| 3935 | field_ty.abiAlignment(zcu); | |
| 2761 | const field_align: InternPool.Alignment = a: { | |
| 2762 | const explicit_aligns = loaded_union.field_aligns.get(ip); | |
| 2763 | if (explicit_aligns.len > 0) { | |
| 2764 | const a = explicit_aligns[field_index]; | |
| 2765 | if (a != .none) break :a a; | |
| 2766 | } | |
| 2767 | break :a field_ty.abiAlignment(zcu); | |
| 2768 | }; | |
| 3936 | 2769 | if (field_ty.hasRuntimeBits(zcu)) { |
| 3937 | 2770 | const field_size = field_ty.abiSize(zcu); |
| 3938 | 2771 | if (field_size > payload_size) { |
| ... | ... | @@ -3947,8 +2780,9 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) |
| 3947 | 2780 | } |
| 3948 | 2781 | payload_align = payload_align.max(field_align); |
| 3949 | 2782 | } |
| 3950 | const have_tag = loaded_union.flagsUnordered(ip).runtime_tag.hasTag(); | |
| 3951 | if (!have_tag or !Type.fromInterned(loaded_union.enum_tag_ty).hasRuntimeBits(zcu)) { | |
| 2783 | if (!loaded_union.has_runtime_tag or | |
| 2784 | !Type.fromInterned(loaded_union.enum_tag_type).hasRuntimeBits(zcu)) | |
| 2785 | { | |
| 3952 | 2786 | return .{ |
| 3953 | 2787 | .abi_size = payload_align.forward(payload_size), |
| 3954 | 2788 | .abi_align = payload_align, |
| ... | ... | @@ -3963,10 +2797,10 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) |
| 3963 | 2797 | }; |
| 3964 | 2798 | } |
| 3965 | 2799 | |
| 3966 | const tag_size = Type.fromInterned(loaded_union.enum_tag_ty).abiSize(zcu); | |
| 3967 | const tag_align = Type.fromInterned(loaded_union.enum_tag_ty).abiAlignment(zcu).max(.@"1"); | |
| 2800 | const tag_size = Type.fromInterned(loaded_union.enum_tag_type).abiSize(zcu); | |
| 2801 | const tag_align = Type.fromInterned(loaded_union.enum_tag_type).abiAlignment(zcu).max(.@"1"); | |
| 3968 | 2802 | return .{ |
| 3969 | .abi_size = loaded_union.sizeUnordered(ip), | |
| 2803 | .abi_size = loaded_union.size, | |
| 3970 | 2804 | .abi_align = tag_align.max(payload_align), |
| 3971 | 2805 | .most_aligned_field = most_aligned_field, |
| 3972 | 2806 | .most_aligned_field_size = most_aligned_field_size, |
| ... | ... | @@ -3975,85 +2809,229 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) |
| 3975 | 2809 | .payload_align = payload_align, |
| 3976 | 2810 | .tag_align = tag_align, |
| 3977 | 2811 | .tag_size = tag_size, |
| 3978 | .padding = loaded_union.paddingUnordered(ip), | |
| 2812 | .padding = loaded_union.padding, | |
| 3979 | 2813 | }; |
| 3980 | 2814 | } |
| 3981 | 2815 | |
| 3982 | /// Returns the type of a pointer to an element. | |
| 3983 | /// Asserts that the type is a pointer, and that the element type is indexable. | |
| 3984 | /// If the element index is comptime-known, it must be passed in `offset`. | |
| 3985 | /// For *@Vector(n, T), return *align(a:b:h:v) T | |
| 3986 | /// For *[N]T, return *T | |
| 3987 | /// For [*]T, returns *T | |
| 3988 | /// For []T, returns *T | |
| 3989 | /// Handles const-ness and address spaces in particular. | |
| 3990 | /// This code is duplicated in `Sema.analyzePtrArithmetic`. | |
| 3991 | /// May perform type resolution and return a transitive `error.AnalysisFail`. | |
| 3992 | pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type { | |
| 2816 | /// Asserts that `ptr_ty` is either a many-item pointer, a slice, a C pointer, or a single pointer | |
| 2817 | /// to array (in other words, a pointer which is indexed by pointer arithmetic), and returns the | |
| 2818 | /// type of the element pointer at the given index. | |
| 2819 | /// | |
| 2820 | /// Asserts that the layout of the pointer element type is resolved. | |
| 2821 | /// | |
| 2822 | /// If `index` is `null`, the index is an arbitrary runtime-known value. | |
| 2823 | pub fn elemPtrType(ptr_ty: Type, index: ?u64, pt: Zcu.PerThread) Allocator.Error!Type { | |
| 3993 | 2824 | const zcu = pt.zcu; |
| 3994 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 3995 | const elem_ty = ptr_ty.elemType2(zcu); | |
| 3996 | const is_allowzero = ptr_info.flags.is_allowzero and (offset orelse 0) == 0; | |
| 3997 | const parent_ty = ptr_ty.childType(zcu); | |
| 3998 | ||
| 3999 | const VI = InternPool.Key.PtrType.VectorIndex; | |
| 4000 | ||
| 4001 | const vector_info: struct { | |
| 4002 | host_size: u16 = 0, | |
| 4003 | alignment: Alignment = .none, | |
| 4004 | vector_index: VI = .none, | |
| 4005 | } = if (parent_ty.isVector(zcu) and ptr_info.flags.size == .one) blk: { | |
| 4006 | const elem_bits = elem_ty.bitSize(zcu); | |
| 4007 | if (elem_bits == 0) break :blk .{}; | |
| 4008 | const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits); | |
| 4009 | if (!is_packed) break :blk .{}; | |
| 4010 | ||
| 4011 | break :blk .{ | |
| 4012 | .host_size = @intCast(parent_ty.arrayLen(zcu)), | |
| 4013 | .alignment = parent_ty.abiAlignment(zcu), | |
| 4014 | .vector_index = @enumFromInt(offset.?), | |
| 4015 | }; | |
| 4016 | } else .{}; | |
| 4017 | ||
| 4018 | const alignment: Alignment = a: { | |
| 4019 | // Calculate the new pointer alignment. | |
| 4020 | if (ptr_info.flags.alignment == .none) { | |
| 4021 | // In case of an ABI-aligned pointer, any pointer arithmetic | |
| 4022 | // maintains the same ABI-alignedness. | |
| 4023 | break :a vector_info.alignment; | |
| 4024 | } | |
| 4025 | // If the addend is not a comptime-known value we can still count on | |
| 4026 | // it being a multiple of the type size. | |
| 4027 | const elem_size = (try elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar; | |
| 4028 | const addend = if (offset) |off| elem_size * off else elem_size; | |
| 4029 | ||
| 4030 | // The resulting pointer is aligned to the lcd between the offset (an | |
| 4031 | // arbitrary number) and the alignment factor (always a power of two, | |
| 4032 | // non zero). | |
| 4033 | const new_align: Alignment = @enumFromInt(@min( | |
| 4034 | @ctz(addend), | |
| 4035 | ptr_info.flags.alignment.toLog2Units(), | |
| 4036 | )); | |
| 4037 | assert(new_align != .none); | |
| 4038 | break :a new_align; | |
| 2825 | const ip = &zcu.intern_pool; | |
| 2826 | const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type; | |
| 2827 | const elem_ty: Type = switch (ptr_info.flags.size) { | |
| 2828 | .slice, .many, .c => .fromInterned(ptr_info.child), | |
| 2829 | .one => switch (ip.indexToKey(ptr_info.child)) { | |
| 2830 | .array_type => |array_type| .fromInterned(array_type.child), | |
| 2831 | else => unreachable, | |
| 2832 | }, | |
| 2833 | }; | |
| 2834 | elem_ty.assertHasLayout(zcu); | |
| 2835 | const elem_align: Alignment = switch (elem_ty.classify(zcu)) { | |
| 2836 | .no_possible_value, | |
| 2837 | .one_possible_value, | |
| 2838 | => ptr_info.flags.alignment, | |
| 2839 | ||
| 2840 | .partially_comptime, | |
| 2841 | .fully_comptime, | |
| 2842 | => switch (ptr_info.flags.alignment) { | |
| 2843 | .none => .none, | |
| 2844 | else => |array_align| .minStrict(array_align, elem_ty.abiAlignment(zcu)), | |
| 2845 | }, | |
| 2846 | ||
| 2847 | .runtime => switch (ptr_info.flags.alignment) { | |
| 2848 | .none => .none, | |
| 2849 | else => |array_align| elem_align: { | |
| 2850 | // If the index is runtime-known, use 1 as it gives the minimum possible alignment. | |
| 2851 | const effective_index = index orelse 1; | |
| 2852 | if (effective_index == 0) break :elem_align array_align; | |
| 2853 | const byte_offset = effective_index * elem_ty.abiSize(zcu); | |
| 2854 | break :elem_align .minStrict(array_align, .fromLog2Units(@ctz(byte_offset))); | |
| 2855 | }, | |
| 2856 | }, | |
| 4039 | 2857 | }; |
| 4040 | return pt.ptrTypeSema(.{ | |
| 2858 | return pt.ptrType(.{ | |
| 4041 | 2859 | .child = elem_ty.toIntern(), |
| 4042 | 2860 | .flags = .{ |
| 4043 | .alignment = alignment, | |
| 2861 | .size = .one, | |
| 4044 | 2862 | .is_const = ptr_info.flags.is_const, |
| 4045 | 2863 | .is_volatile = ptr_info.flags.is_volatile, |
| 4046 | .is_allowzero = is_allowzero, | |
| 2864 | .is_allowzero = ptr_info.flags.is_allowzero and (index == null or index == 0), | |
| 4047 | 2865 | .address_space = ptr_info.flags.address_space, |
| 4048 | .vector_index = vector_info.vector_index, | |
| 4049 | }, | |
| 4050 | .packed_offset = .{ | |
| 4051 | .host_size = vector_info.host_size, | |
| 4052 | .bit_offset = 0, | |
| 2866 | .alignment = elem_align, | |
| 4053 | 2867 | }, |
| 4054 | 2868 | }); |
| 4055 | 2869 | } |
| 4056 | 2870 | |
| 2871 | /// Asserts that `ptr_ty` is a pointer (single-item or C) to a struct, union, tuple, or slice, and | |
| 2872 | /// returns the type of a pointer to the field at `field_index`. | |
| 2873 | /// | |
| 2874 | /// Asserts that the layout of the pointer child type is resolved. | |
| 2875 | /// | |
| 2876 | /// For slices, `Value.slice_ptr_index` and `Value.slice_len_index` are used for the field index. | |
| 2877 | pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator.Error!Type { | |
| 2878 | const zcu = pt.zcu; | |
| 2879 | const ip = &zcu.intern_pool; | |
| 2880 | const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type; | |
| 2881 | assert(ptr_info.flags.size == .one or ptr_info.flags.size == .c); | |
| 2882 | const aggregate_ty: Type = .fromInterned(ptr_info.child); | |
| 2883 | aggregate_ty.assertHasLayout(zcu); | |
| 2884 | // We only exit this `switch` for default-layout aggregates, where the field pointer alignment | |
| 2885 | // is a simple minimum of the aggregate pointer alignment and the field alignment. | |
| 2886 | // `field_align` is `.none` if there is no explicit alignment annotation. | |
| 2887 | const field_ty: Type, const field_align: Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { | |
| 2888 | .@"struct" => switch (aggregate_ty.containerLayout(zcu)) { | |
| 2889 | .auto => field: { | |
| 2890 | if (aggregate_ty.isTuple(zcu)) { | |
| 2891 | break :field .{ aggregate_ty.fieldType(field_index, zcu), .none }; | |
| 2892 | } | |
| 2893 | const struct_obj = ip.loadStructType(aggregate_ty.toIntern()); | |
| 2894 | break :field .{ | |
| 2895 | .fromInterned(struct_obj.field_types.get(ip)[field_index]), | |
| 2896 | struct_obj.field_aligns.getOrNone(ip, field_index), | |
| 2897 | }; | |
| 2898 | }, | |
| 2899 | .@"extern" => { | |
| 2900 | // Field alignment is determined based on the actual field offset. For instance, in | |
| 2901 | // `extern struct { x: u32, y: u16 }`, the `y` field is 4-byte aligned. | |
| 2902 | const field_ty = aggregate_ty.fieldType(field_index, zcu); | |
| 2903 | const field_offset = aggregate_ty.structFieldOffset(field_index, zcu); | |
| 2904 | const parent_align = switch (ptr_info.flags.alignment) { | |
| 2905 | .none => aggregate_ty.abiAlignment(zcu), | |
| 2906 | else => |a| a, | |
| 2907 | }; | |
| 2908 | const actual_field_align = switch (field_offset) { | |
| 2909 | 0 => parent_align, | |
| 2910 | else => parent_align.minStrict(.fromLog2Units(@ctz(field_offset))), | |
| 2911 | }; | |
| 2912 | const field_ptr_align: Alignment = a: { | |
| 2913 | if (ptr_info.flags.alignment == .none and | |
| 2914 | aggregate_ty.explicitFieldAlignment(field_index, zcu) == .none and | |
| 2915 | actual_field_align == field_ty.abiAlignment(zcu)) | |
| 2916 | { | |
| 2917 | // There's no user-specified 'align' in sight, and the alignment from the | |
| 2918 | // field offset matches the field type's natural alignment, so just use a | |
| 2919 | // default-aligned pointer. | |
| 2920 | break :a .none; | |
| 2921 | } | |
| 2922 | break :a actual_field_align; | |
| 2923 | }; | |
| 2924 | var field_ptr_info = ptr_info; | |
| 2925 | field_ptr_info.child = field_ty.toIntern(); | |
| 2926 | field_ptr_info.flags.alignment = field_ptr_align; | |
| 2927 | return pt.ptrType(field_ptr_info); | |
| 2928 | }, | |
| 2929 | .@"packed" => { | |
| 2930 | var field_ptr_info = ptr_info; | |
| 2931 | if (field_ptr_info.flags.alignment == .none) { | |
| 2932 | field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu); | |
| 2933 | } | |
| 2934 | field_ptr_info.packed_offset = packed_offset: { | |
| 2935 | comptime assert(Type.packed_struct_layout_version == 2); | |
| 2936 | const bit_offset = zcu.structPackedFieldBitOffset( | |
| 2937 | ip.loadStructType(aggregate_ty.toIntern()), | |
| 2938 | field_index, | |
| 2939 | ); | |
| 2940 | break :packed_offset if (ptr_info.packed_offset.host_size != 0) .{ | |
| 2941 | .host_size = ptr_info.packed_offset.host_size, | |
| 2942 | .bit_offset = ptr_info.packed_offset.bit_offset + bit_offset, | |
| 2943 | } else .{ | |
| 2944 | .host_size = switch (zcu.comp.getZigBackend()) { | |
| 2945 | else => @intCast((aggregate_ty.bitSize(zcu) + 7) / 8), | |
| 2946 | .stage2_x86_64, .stage2_c => @intCast(aggregate_ty.abiSize(zcu)), | |
| 2947 | }, | |
| 2948 | .bit_offset = ptr_info.packed_offset.bit_offset + bit_offset, | |
| 2949 | }; | |
| 2950 | }; | |
| 2951 | field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern(); | |
| 2952 | return pt.ptrType(field_ptr_info); | |
| 2953 | }, | |
| 2954 | }, | |
| 2955 | .@"union" => switch (aggregate_ty.containerLayout(zcu)) { | |
| 2956 | .auto => field: { | |
| 2957 | const union_obj = ip.loadUnionType(aggregate_ty.toIntern()); | |
| 2958 | break :field .{ | |
| 2959 | .fromInterned(union_obj.field_types.get(ip)[field_index]), | |
| 2960 | union_obj.field_aligns.getOrNone(ip, field_index), | |
| 2961 | }; | |
| 2962 | }, | |
| 2963 | .@"extern" => { | |
| 2964 | // The alignment always matches that of the union pointer. If the union pointer is | |
| 2965 | // default aligned (`.none`), we may need to explicitly align the result pointer. | |
| 2966 | const field_ty = aggregate_ty.fieldType(field_index, zcu); | |
| 2967 | var field_ptr_info = ptr_info; | |
| 2968 | field_ptr_info.child = field_ty.toIntern(); | |
| 2969 | if (field_ptr_info.flags.alignment == .none and | |
| 2970 | Alignment.compareStrict(field_ty.abiAlignment(zcu), .neq, aggregate_ty.abiAlignment(zcu))) | |
| 2971 | { | |
| 2972 | field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu); | |
| 2973 | } | |
| 2974 | return pt.ptrType(field_ptr_info); | |
| 2975 | }, | |
| 2976 | .@"packed" => { | |
| 2977 | const field_ty = aggregate_ty.fieldType(field_index, zcu); | |
| 2978 | var field_ptr_info = ptr_info; | |
| 2979 | if (field_ptr_info.flags.alignment == .none) { | |
| 2980 | const resolved_align = aggregate_ty.abiAlignment(zcu); | |
| 2981 | if (field_ty.abiAlignment(zcu) != resolved_align) { | |
| 2982 | field_ptr_info.flags.alignment = resolved_align; | |
| 2983 | } | |
| 2984 | } | |
| 2985 | field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern(); | |
| 2986 | return pt.ptrType(field_ptr_info); | |
| 2987 | }, | |
| 2988 | }, | |
| 2989 | .pointer => field: { | |
| 2990 | assert(aggregate_ty.isSlice(zcu)); | |
| 2991 | break :field switch (field_index) { | |
| 2992 | Value.slice_ptr_index => .{ aggregate_ty.slicePtrFieldType(zcu), .none }, | |
| 2993 | Value.slice_len_index => .{ .usize, .none }, | |
| 2994 | else => unreachable, | |
| 2995 | }; | |
| 2996 | }, | |
| 2997 | else => unreachable, | |
| 2998 | }; | |
| 2999 | const field_ptr_align: Alignment = a: { | |
| 3000 | if (aggregate_ty.zigTypeTag(zcu) == .@"struct" and aggregate_ty.structFieldIsComptime(field_index, zcu)) { | |
| 3001 | // For `comptime` fields, just use exactly what was specified, or ABI alignment if nothing was specified. | |
| 3002 | break :a field_align; | |
| 3003 | } | |
| 3004 | const actual_field_align = switch (field_align) { | |
| 3005 | .none => switch (ip.indexToKey(aggregate_ty.toIntern())) { | |
| 3006 | .tuple_type, .union_type => field_ty.abiAlignment(zcu), | |
| 3007 | .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu), | |
| 3008 | .ptr_type => Type.usize.abiAlignment(zcu), | |
| 3009 | else => unreachable, | |
| 3010 | }, | |
| 3011 | else => |a| a, | |
| 3012 | }; | |
| 3013 | const actual_aggregate_align = switch (ptr_info.flags.alignment) { | |
| 3014 | .none => aggregate_ty.abiAlignment(zcu), | |
| 3015 | else => |a| a, | |
| 3016 | }; | |
| 3017 | if (actual_aggregate_align.compareStrict(.lt, actual_field_align)) { | |
| 3018 | // Underaligned aggregate; use that alignment. | |
| 3019 | assert(ptr_info.flags.alignment != .none); | |
| 3020 | break :a actual_aggregate_align; | |
| 3021 | } | |
| 3022 | if (field_align == .none and actual_field_align == field_ty.abiAlignment(zcu)) { | |
| 3023 | // No explicit annotation on the field (nor an unusual default), and the aggregate | |
| 3024 | // alignment is irrelevant to us, so return an un-annotated pointer. | |
| 3025 | break :a .none; | |
| 3026 | } | |
| 3027 | break :a actual_field_align; | |
| 3028 | }; | |
| 3029 | var field_ptr_info = ptr_info; | |
| 3030 | field_ptr_info.flags.alignment = field_ptr_align; | |
| 3031 | field_ptr_info.child = field_ty.toIntern(); | |
| 3032 | return pt.ptrType(field_ptr_info); | |
| 3033 | } | |
| 3034 | ||
| 4057 | 3035 | pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTerminatedString { |
| 4058 | 3036 | return switch (ip.indexToKey(ty.toIntern())) { |
| 4059 | 3037 | .struct_type => ip.loadStructType(ty.toIntern()).name, |
| ... | ... | @@ -4064,14 +3042,257 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina |
| 4064 | 3042 | }; |
| 4065 | 3043 | } |
| 4066 | 3044 | |
| 4067 | /// Returns `true` if a value of this type is always `null`. | |
| 4068 | /// Returns `false` if a value of this type is neve `null`. | |
| 4069 | /// Returns `null` otherwise. | |
| 4070 | pub fn isNullFromType(ty: Type, zcu: *const Zcu) ?bool { | |
| 4071 | if (ty.zigTypeTag(zcu) != .optional and !ty.isCPtr(zcu)) return false; | |
| 4072 | const child = ty.optionalChild(zcu); | |
| 4073 | if (child.zigTypeTag(zcu) == .noreturn) return true; // `?noreturn` is always null | |
| 4074 | return null; | |
| 3045 | pub fn destructurable(ty: Type, zcu: *const Zcu) bool { | |
| 3046 | return switch (ty.zigTypeTag(zcu)) { | |
| 3047 | .array, .vector => true, | |
| 3048 | .@"struct" => ty.isTuple(zcu), | |
| 3049 | else => false, | |
| 3050 | }; | |
| 3051 | } | |
| 3052 | ||
| 3053 | pub const UnpackableReason = union(enum) { | |
| 3054 | comptime_only, | |
| 3055 | pointer, | |
| 3056 | enum_inferred_int_tag: Type, | |
| 3057 | non_packed_struct: Type, | |
| 3058 | non_packed_union: Type, | |
| 3059 | slice, | |
| 3060 | other, | |
| 3061 | }; | |
| 3062 | ||
| 3063 | /// Returns `null` iff `ty` is allowed in packed types. | |
| 3064 | pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason { | |
| 3065 | return switch (ty.zigTypeTag(zcu)) { | |
| 3066 | .void, | |
| 3067 | .bool, | |
| 3068 | .float, | |
| 3069 | .int, | |
| 3070 | => null, | |
| 3071 | ||
| 3072 | .type, | |
| 3073 | .comptime_float, | |
| 3074 | .comptime_int, | |
| 3075 | .enum_literal, | |
| 3076 | .undefined, | |
| 3077 | .null, | |
| 3078 | => .comptime_only, | |
| 3079 | ||
| 3080 | .noreturn, | |
| 3081 | .@"opaque", | |
| 3082 | .error_union, | |
| 3083 | .error_set, | |
| 3084 | .frame, | |
| 3085 | .@"anyframe", | |
| 3086 | .@"fn", | |
| 3087 | .array, | |
| 3088 | .vector, | |
| 3089 | => .other, | |
| 3090 | ||
| 3091 | .optional => if (ty.isPtrLikeOptional(zcu)) | |
| 3092 | .pointer | |
| 3093 | else | |
| 3094 | .other, | |
| 3095 | ||
| 3096 | .pointer => switch (ty.ptrSize(zcu)) { | |
| 3097 | .slice => .slice, | |
| 3098 | .one, .many, .c => .pointer, | |
| 3099 | }, | |
| 3100 | ||
| 3101 | .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_mode) { | |
| 3102 | .explicit => null, | |
| 3103 | .auto => .{ .enum_inferred_int_tag = ty }, | |
| 3104 | }, | |
| 3105 | ||
| 3106 | .@"struct" => switch (ty.containerLayout(zcu)) { | |
| 3107 | .@"packed" => null, | |
| 3108 | .auto, .@"extern" => .{ .non_packed_struct = ty }, | |
| 3109 | }, | |
| 3110 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 3111 | .@"packed" => null, | |
| 3112 | .auto, .@"extern" => .{ .non_packed_union = ty }, | |
| 3113 | }, | |
| 3114 | }; | |
| 3115 | } | |
| 3116 | ||
| 3117 | pub const ExternPosition = enum { | |
| 3118 | ret_ty, | |
| 3119 | param_ty, | |
| 3120 | union_field, | |
| 3121 | struct_field, | |
| 3122 | element, | |
| 3123 | other, | |
| 3124 | }; | |
| 3125 | ||
| 3126 | /// Returns true if `ty` is allowed in extern types. | |
| 3127 | /// Asserts that `ty` is fully resolved. | |
| 3128 | /// Keep in sync with `Sema.explainWhyTypeIsNotExtern`. | |
| 3129 | pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool { | |
| 3130 | ty.assertHasLayout(zcu); | |
| 3131 | return switch (ty.zigTypeTag(zcu)) { | |
| 3132 | .type, | |
| 3133 | .comptime_float, | |
| 3134 | .comptime_int, | |
| 3135 | .enum_literal, | |
| 3136 | .undefined, | |
| 3137 | .null, | |
| 3138 | .error_union, | |
| 3139 | .error_set, | |
| 3140 | .frame, | |
| 3141 | => false, | |
| 3142 | ||
| 3143 | .void => switch (position) { | |
| 3144 | .ret_ty, | |
| 3145 | .union_field, | |
| 3146 | .struct_field, | |
| 3147 | .element, | |
| 3148 | => true, | |
| 3149 | .param_ty, | |
| 3150 | .other, | |
| 3151 | => false, | |
| 3152 | }, | |
| 3153 | ||
| 3154 | .noreturn => position == .ret_ty, | |
| 3155 | ||
| 3156 | .@"opaque", | |
| 3157 | .bool, | |
| 3158 | .float, | |
| 3159 | .@"anyframe", | |
| 3160 | => true, | |
| 3161 | ||
| 3162 | .pointer => { | |
| 3163 | if (ty.isSlice(zcu)) return false; | |
| 3164 | const child_ty = ty.childType(zcu); | |
| 3165 | if (child_ty.zigTypeTag(zcu) == .@"fn") { | |
| 3166 | return ty.isConstPtr(zcu) and validateExternCallconv(child_ty.fnCallingConvention(zcu)); | |
| 3167 | } | |
| 3168 | return true; | |
| 3169 | }, | |
| 3170 | .int => switch (ty.intInfo(zcu).bits) { | |
| 3171 | 0, 8, 16, 32, 64, 128 => true, | |
| 3172 | else => false, | |
| 3173 | }, | |
| 3174 | .@"fn" => { | |
| 3175 | if (position != .other) return false; | |
| 3176 | return validateExternCallconv(ty.fnCallingConvention(zcu)); | |
| 3177 | }, | |
| 3178 | .@"enum" => { | |
| 3179 | const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); | |
| 3180 | return switch (enum_obj.int_tag_mode) { | |
| 3181 | .auto => false, | |
| 3182 | .explicit => Type.fromInterned(enum_obj.int_tag_type).validateExtern(position, zcu), | |
| 3183 | }; | |
| 3184 | }, | |
| 3185 | .@"struct" => { | |
| 3186 | const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); | |
| 3187 | return switch (struct_obj.layout) { | |
| 3188 | .auto => false, | |
| 3189 | .@"extern" => true, | |
| 3190 | .@"packed" => switch (struct_obj.packed_backing_mode) { | |
| 3191 | .auto => false, | |
| 3192 | .explicit => Type.fromInterned(struct_obj.packed_backing_int_type).validateExtern(position, zcu), | |
| 3193 | }, | |
| 3194 | }; | |
| 3195 | }, | |
| 3196 | .@"union" => { | |
| 3197 | const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); | |
| 3198 | return switch (union_obj.layout) { | |
| 3199 | .auto => false, | |
| 3200 | .@"extern" => true, | |
| 3201 | .@"packed" => switch (union_obj.packed_backing_mode) { | |
| 3202 | .auto => false, | |
| 3203 | .explicit => Type.fromInterned(union_obj.packed_backing_int_type).validateExtern(position, zcu), | |
| 3204 | }, | |
| 3205 | }; | |
| 3206 | }, | |
| 3207 | .array => switch (position) { | |
| 3208 | .ret_ty, | |
| 3209 | .param_ty, | |
| 3210 | => false, | |
| 3211 | ||
| 3212 | .union_field, | |
| 3213 | .struct_field, | |
| 3214 | .element, | |
| 3215 | .other, | |
| 3216 | => ty.childType(zcu).validateExtern(.element, zcu), | |
| 3217 | }, | |
| 3218 | .vector => ty.childType(zcu).validateExtern(.element, zcu), | |
| 3219 | .optional => ty.isPtrLikeOptional(zcu), | |
| 3220 | }; | |
| 3221 | } | |
| 3222 | fn validateExternCallconv(cc: std.builtin.CallingConvention) bool { | |
| 3223 | return switch (cc) { | |
| 3224 | // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. | |
| 3225 | // The goal is to experiment with more integrated CPU/GPU code. | |
| 3226 | .nvptx_kernel => true, | |
| 3227 | else => !target_util.fnCallConvAllowsZigTypes(cc), | |
| 3228 | }; | |
| 3229 | } | |
| 3230 | ||
| 3231 | /// Asserts that `ty` has resolved layout. | |
| 3232 | pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { | |
| 3233 | if (!std.debug.runtime_safety) { | |
| 3234 | // This early exit isn't necessary (`Zcu.assertUpToDate` checks `std.debug.runtime_safety` | |
| 3235 | // itself), but LLVM has been observed to fail at optimizing away this safety check, which | |
| 3236 | // has a major performance impact on ReleaseFast compiler builds. | |
| 3237 | return; | |
| 3238 | } | |
| 3239 | switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 3240 | .int_type, | |
| 3241 | .ptr_type, | |
| 3242 | .anyframe_type, | |
| 3243 | .simple_type, | |
| 3244 | .opaque_type, | |
| 3245 | .error_set_type, | |
| 3246 | .inferred_error_set_type, | |
| 3247 | => {}, | |
| 3248 | .func_type => |func_type| { | |
| 3249 | for (func_type.param_types.get(&zcu.intern_pool)) |param_ty| { | |
| 3250 | assertHasLayout(.fromInterned(param_ty), zcu); | |
| 3251 | } | |
| 3252 | assertHasLayout(.fromInterned(func_type.return_type), zcu); | |
| 3253 | }, | |
| 3254 | .array_type => |arr| assertHasLayout(.fromInterned(arr.child), zcu), | |
| 3255 | .vector_type => |vec| assertHasLayout(.fromInterned(vec.child), zcu), | |
| 3256 | .opt_type => |child| assertHasLayout(.fromInterned(child), zcu), | |
| 3257 | .error_union_type => |eu| assertHasLayout(.fromInterned(eu.payload_type), zcu), | |
| 3258 | .tuple_type => |tuple| for (tuple.types.get(&zcu.intern_pool)) |field_ty| { | |
| 3259 | assertHasLayout(.fromInterned(field_ty), zcu); | |
| 3260 | }, | |
| 3261 | .struct_type => { | |
| 3262 | assert(zcu.intern_pool.loadStructType(ty.toIntern()).want_layout); | |
| 3263 | zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); | |
| 3264 | }, | |
| 3265 | .union_type => { | |
| 3266 | assert(zcu.intern_pool.loadUnionType(ty.toIntern()).want_layout); | |
| 3267 | zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); | |
| 3268 | }, | |
| 3269 | .enum_type => { | |
| 3270 | assert(zcu.intern_pool.loadEnumType(ty.toIntern()).want_layout); | |
| 3271 | zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); | |
| 3272 | }, | |
| 3273 | ||
| 3274 | // values, not types | |
| 3275 | .simple_value, | |
| 3276 | .variable, | |
| 3277 | .@"extern", | |
| 3278 | .func, | |
| 3279 | .int, | |
| 3280 | .err, | |
| 3281 | .error_union, | |
| 3282 | .enum_literal, | |
| 3283 | .enum_tag, | |
| 3284 | .float, | |
| 3285 | .ptr, | |
| 3286 | .slice, | |
| 3287 | .opt, | |
| 3288 | .aggregate, | |
| 3289 | .un, | |
| 3290 | .bitpack, | |
| 3291 | .undef, | |
| 3292 | // memoization, not types | |
| 3293 | .memoized_call, | |
| 3294 | => unreachable, | |
| 3295 | } | |
| 4075 | 3296 | } |
| 4076 | 3297 | |
| 4077 | 3298 | /// Recursively walks the type and marks for each subtype how many times it has been seen |
| ... | ... | @@ -4138,13 +3359,13 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn |
| 4138 | 3359 | .error_union, |
| 4139 | 3360 | .enum_literal, |
| 4140 | 3361 | .enum_tag, |
| 4141 | .empty_enum_value, | |
| 4142 | 3362 | .float, |
| 4143 | 3363 | .ptr, |
| 4144 | 3364 | .slice, |
| 4145 | 3365 | .opt, |
| 4146 | 3366 | .aggregate, |
| 4147 | 3367 | .un, |
| 3368 | .bitpack, | |
| 4148 | 3369 | // memoization, not types |
| 4149 | 3370 | .memoized_call, |
| 4150 | 3371 | => unreachable, |
| ... | ... | @@ -4243,6 +3464,7 @@ pub const Comparison = struct { |
| 4243 | 3464 | }; |
| 4244 | 3465 | }; |
| 4245 | 3466 | |
| 3467 | pub const @"u0": Type = .{ .ip_index = .u0_type }; | |
| 4246 | 3468 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 4247 | 3469 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 4248 | 3470 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |
src/Value.zig+295-897| ... | ... | @@ -146,80 +146,23 @@ pub fn toType(self: Value) Type { |
| 146 | 146 | return Type.fromInterned(self.toIntern()); |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | pub fn intFromEnum(val: Value, ty: Type, pt: Zcu.PerThread) Allocator.Error!Value { | |
| 150 | const ip = &pt.zcu.intern_pool; | |
| 151 | const enum_ty = ip.typeOf(val.toIntern()); | |
| 152 | return switch (ip.indexToKey(enum_ty)) { | |
| 153 | // Assume it is already an integer and return it directly. | |
| 154 | .simple_type, .int_type => val, | |
| 155 | .enum_literal => |enum_literal| { | |
| 156 | const field_index = ty.enumFieldIndex(enum_literal, pt.zcu).?; | |
| 157 | switch (ip.indexToKey(ty.toIntern())) { | |
| 158 | // Assume it is already an integer and return it directly. | |
| 159 | .simple_type, .int_type => return val, | |
| 160 | .enum_type => { | |
| 161 | const enum_type = ip.loadEnumType(ty.toIntern()); | |
| 162 | if (enum_type.values.len != 0) { | |
| 163 | return Value.fromInterned(enum_type.values.get(ip)[field_index]); | |
| 164 | } else { | |
| 165 | // Field index and integer values are the same. | |
| 166 | return pt.intValue(Type.fromInterned(enum_type.tag_ty), field_index); | |
| 167 | } | |
| 168 | }, | |
| 169 | else => unreachable, | |
| 170 | } | |
| 171 | }, | |
| 172 | .enum_type => try pt.getCoerced(val, Type.fromInterned(ip.loadEnumType(enum_ty).tag_ty)), | |
| 173 | else => unreachable, | |
| 174 | }; | |
| 149 | pub fn intFromEnum(val: Value, zcu: *const Zcu) Value { | |
| 150 | return .fromInterned(zcu.intern_pool.indexToKey(val.toIntern()).enum_tag.int); | |
| 175 | 151 | } |
| 176 | 152 | |
| 177 | pub const ResolveStrat = Type.ResolveStrat; | |
| 178 | ||
| 179 | /// Asserts the value is an integer. | |
| 180 | pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *Zcu) BigIntConst { | |
| 181 | return val.toBigIntAdvanced(space, .normal, zcu, {}) catch unreachable; | |
| 182 | } | |
| 183 | ||
| 184 | pub fn toBigIntSema(val: Value, space: *BigIntSpace, pt: Zcu.PerThread) !BigIntConst { | |
| 185 | return try val.toBigIntAdvanced(space, .sema, pt.zcu, pt.tid); | |
| 186 | } | |
| 187 | ||
| 188 | /// Asserts the value is an integer. | |
| 189 | pub fn toBigIntAdvanced( | |
| 190 | val: Value, | |
| 191 | space: *BigIntSpace, | |
| 192 | comptime strat: ResolveStrat, | |
| 193 | zcu: *Zcu, | |
| 194 | tid: strat.Tid(), | |
| 195 | ) Zcu.SemaError!BigIntConst { | |
| 153 | /// Asserts that `val` is an integer. | |
| 154 | pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *const Zcu) BigIntConst { | |
| 155 | if (val.getUnsignedInt(zcu)) |x| { | |
| 156 | return BigIntMutable.init(&space.limbs, x).toConst(); | |
| 157 | } | |
| 196 | 158 | const ip = &zcu.intern_pool; |
| 197 | return switch (val.toIntern()) { | |
| 198 | .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(), | |
| 199 | .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(), | |
| 200 | .null_value => BigIntMutable.init(&space.limbs, 0).toConst(), | |
| 201 | else => switch (ip.indexToKey(val.toIntern())) { | |
| 202 | .int => |int| switch (int.storage) { | |
| 203 | .u64, .i64, .big_int => int.storage.toBigInt(space), | |
| 204 | .lazy_align, .lazy_size => |ty| { | |
| 205 | if (strat == .sema) try Type.fromInterned(ty).resolveLayout(strat.pt(zcu, tid)); | |
| 206 | const x = switch (int.storage) { | |
| 207 | else => unreachable, | |
| 208 | .lazy_align => Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0, | |
| 209 | .lazy_size => Type.fromInterned(ty).abiSize(zcu), | |
| 210 | }; | |
| 211 | return BigIntMutable.init(&space.limbs, x).toConst(); | |
| 212 | }, | |
| 213 | }, | |
| 214 | .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).toBigIntAdvanced(space, strat, zcu, tid), | |
| 215 | .opt, .ptr => BigIntMutable.init( | |
| 216 | &space.limbs, | |
| 217 | (try val.getUnsignedIntInner(strat, zcu, tid)).?, | |
| 218 | ).toConst(), | |
| 219 | .err => |err| BigIntMutable.init(&space.limbs, ip.getErrorValueIfExists(err.name).?).toConst(), | |
| 220 | else => unreachable, | |
| 221 | }, | |
| 159 | const int_key = switch (ip.indexToKey(val.toIntern())) { | |
| 160 | .enum_tag => |enum_tag| ip.indexToKey(enum_tag.int).int, | |
| 161 | .bitpack => |bitpack| ip.indexToKey(bitpack.backing_int_val).int, | |
| 162 | .int => |int| int, | |
| 163 | else => unreachable, | |
| 222 | 164 | }; |
| 165 | return int_key.storage.toBigInt(space); | |
| 223 | 166 | } |
| 224 | 167 | |
| 225 | 168 | pub fn isFuncBody(val: Value, zcu: *Zcu) bool { |
| ... | ... | @@ -240,31 +183,17 @@ pub fn getVariable(val: Value, mod: *Zcu) ?InternPool.Key.Variable { |
| 240 | 183 | }; |
| 241 | 184 | } |
| 242 | 185 | |
| 243 | /// If the value fits in a u64, return it, otherwise null. | |
| 244 | /// Asserts not undefined. | |
| 245 | pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 { | |
| 246 | return getUnsignedIntInner(val, .normal, zcu, {}) catch unreachable; | |
| 247 | } | |
| 248 | ||
| 249 | /// Asserts the value is an integer and it fits in a u64 | |
| 186 | /// Asserts the value is a (defined) integer and it fits in a u64. | |
| 250 | 187 | pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 { |
| 251 | 188 | return getUnsignedInt(val, zcu).?; |
| 252 | 189 | } |
| 253 | 190 | |
| 254 | pub fn getUnsignedIntSema(val: Value, pt: Zcu.PerThread) !?u64 { | |
| 255 | return try val.getUnsignedIntInner(.sema, pt.zcu, pt.tid); | |
| 256 | } | |
| 257 | ||
| 258 | 191 | /// If the value fits in a u64, return it, otherwise null. |
| 259 | 192 | /// Asserts not undefined. |
| 260 | pub fn getUnsignedIntInner( | |
| 261 | val: Value, | |
| 262 | comptime strat: ResolveStrat, | |
| 263 | zcu: strat.ZcuPtr(), | |
| 264 | tid: strat.Tid(), | |
| 265 | ) !?u64 { | |
| 193 | pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 { | |
| 266 | 194 | return switch (val.toIntern()) { |
| 267 | 195 | .undef => unreachable, |
| 196 | .null_value => 0, | |
| 268 | 197 | .bool_false => 0, |
| 269 | 198 | .bool_true => 1, |
| 270 | 199 | else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| ... | ... | @@ -273,37 +202,28 @@ pub fn getUnsignedIntInner( |
| 273 | 202 | .big_int => |big_int| big_int.toInt(u64) catch null, |
| 274 | 203 | .u64 => |x| x, |
| 275 | 204 | .i64 => |x| std.math.cast(u64, x), |
| 276 | .lazy_align => |ty| (try Type.fromInterned(ty).abiAlignmentInner(strat.toLazy(), zcu, tid)).scalar.toByteUnits() orelse 0, | |
| 277 | .lazy_size => |ty| (try Type.fromInterned(ty).abiSizeInner(strat.toLazy(), zcu, tid)).scalar, | |
| 278 | 205 | }, |
| 279 | 206 | .ptr => |ptr| switch (ptr.base_addr) { |
| 280 | 207 | .int => ptr.byte_offset, |
| 281 | 208 | .field => |field| { |
| 282 | const base_addr = (try Value.fromInterned(field.base).getUnsignedIntInner(strat, zcu, tid)) orelse return null; | |
| 209 | const base_addr = Value.fromInterned(field.base).getUnsignedInt(zcu) orelse return null; | |
| 283 | 210 | const struct_ty = Value.fromInterned(field.base).typeOf(zcu).childType(zcu); |
| 284 | if (strat == .sema) { | |
| 285 | const pt = strat.pt(zcu, tid); | |
| 286 | try struct_ty.resolveLayout(pt); | |
| 287 | } | |
| 288 | 211 | return base_addr + struct_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset; |
| 289 | 212 | }, |
| 290 | 213 | else => null, |
| 291 | 214 | }, |
| 292 | 215 | .opt => |opt| switch (opt.val) { |
| 293 | 216 | .none => 0, |
| 294 | else => |payload| Value.fromInterned(payload).getUnsignedIntInner(strat, zcu, tid), | |
| 217 | else => |payload| Value.fromInterned(payload).getUnsignedInt(zcu), | |
| 295 | 218 | }, |
| 296 | .enum_tag => |enum_tag| return Value.fromInterned(enum_tag.int).getUnsignedIntInner(strat, zcu, tid), | |
| 219 | .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).getUnsignedInt(zcu), | |
| 220 | .bitpack => |bitpack| Value.fromInterned(bitpack.backing_int_val).getUnsignedInt(zcu), | |
| 221 | .err => |err| zcu.intern_pool.getErrorValueIfExists(err.name).?, | |
| 297 | 222 | else => null, |
| 298 | 223 | }, |
| 299 | 224 | }; |
| 300 | 225 | } |
| 301 | 226 | |
| 302 | /// Asserts the value is an integer and it fits in a u64 | |
| 303 | pub fn toUnsignedIntSema(val: Value, pt: Zcu.PerThread) !u64 { | |
| 304 | return (try getUnsignedIntInner(val, .sema, pt.zcu, pt.tid)).?; | |
| 305 | } | |
| 306 | ||
| 307 | 227 | /// Asserts the value is an integer and it fits in a i64 |
| 308 | 228 | pub fn toSignedInt(val: Value, zcu: *const Zcu) i64 { |
| 309 | 229 | return switch (val.toIntern()) { |
| ... | ... | @@ -314,8 +234,6 @@ pub fn toSignedInt(val: Value, zcu: *const Zcu) i64 { |
| 314 | 234 | .big_int => |big_int| big_int.toInt(i64) catch unreachable, |
| 315 | 235 | .i64 => |x| x, |
| 316 | 236 | .u64 => |x| @intCast(x), |
| 317 | .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0), | |
| 318 | .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(zcu)), | |
| 319 | 237 | }, |
| 320 | 238 | else => unreachable, |
| 321 | 239 | }, |
| ... | ... | @@ -393,7 +311,7 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ |
| 393 | 311 | // We use byte_count instead of abi_size here, so that any padding bytes |
| 394 | 312 | // follow the data bytes, on both big- and little-endian systems. |
| 395 | 313 | const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8; |
| 396 | return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); | |
| 314 | return writeToPackedMemory(val, pt, buffer[0..byte_count], 0); | |
| 397 | 315 | }, |
| 398 | 316 | .@"struct" => { |
| 399 | 317 | const struct_type = zcu.typeToStruct(ty) orelse return error.IllDefinedMemoryLayout; |
| ... | ... | @@ -412,8 +330,8 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ |
| 412 | 330 | try writeToMemory(field_val, pt, buffer[off..]); |
| 413 | 331 | }, |
| 414 | 332 | .@"packed" => { |
| 415 | const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8; | |
| 416 | return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); | |
| 333 | const int_index = ip.indexToKey(val.toIntern()).bitpack.backing_int_val; | |
| 334 | return Value.fromInterned(int_index).writeToMemory(pt, buffer); | |
| 417 | 335 | }, |
| 418 | 336 | } |
| 419 | 337 | }, |
| ... | ... | @@ -428,15 +346,14 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ |
| 428 | 346 | const byte_count: usize = @intCast(field_type.abiSize(zcu)); |
| 429 | 347 | return writeToMemory(field_val, pt, buffer[0..byte_count]); |
| 430 | 348 | } else { |
| 431 | const backing_ty = try ty.unionBackingType(pt); | |
| 349 | const backing_ty = try ty.externUnionBackingType(pt); | |
| 432 | 350 | const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); |
| 433 | return writeToMemory(val.unionValue(zcu), pt, buffer[0..byte_count]); | |
| 351 | return writeToMemory(val.unionPayload(zcu), pt, buffer[0..byte_count]); | |
| 434 | 352 | } |
| 435 | 353 | }, |
| 436 | 354 | .@"packed" => { |
| 437 | const backing_ty = try ty.unionBackingType(pt); | |
| 438 | const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); | |
| 439 | return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); | |
| 355 | const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val); | |
| 356 | return writeToMemory(int_val, pt, buffer); | |
| 440 | 357 | }, |
| 441 | 358 | }, |
| 442 | 359 | .optional => { |
| ... | ... | @@ -458,7 +375,6 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ |
| 458 | 375 | /// big-endian packed memory layouts start at the end of the buffer. |
| 459 | 376 | pub fn writeToPackedMemory( |
| 460 | 377 | val: Value, |
| 461 | ty: Type, | |
| 462 | 378 | pt: Zcu.PerThread, |
| 463 | 379 | buffer: []u8, |
| 464 | 380 | bit_offset: usize, |
| ... | ... | @@ -467,6 +383,7 @@ pub fn writeToPackedMemory( |
| 467 | 383 | const ip = &zcu.intern_pool; |
| 468 | 384 | const target = zcu.getTarget(); |
| 469 | 385 | const endian = target.cpu.arch.endian(); |
| 386 | const ty = val.typeOf(zcu); | |
| 470 | 387 | if (val.isUndef(zcu)) { |
| 471 | 388 | const bit_size: usize = @intCast(ty.bitSize(zcu)); |
| 472 | 389 | if (bit_size != 0) { |
| ... | ... | @@ -487,22 +404,22 @@ pub fn writeToPackedMemory( |
| 487 | 404 | buffer[byte_index] &= ~(@as(u8, 1) << @as(u3, @intCast(bit_offset % 8))); |
| 488 | 405 | } |
| 489 | 406 | }, |
| 490 | .int, .@"enum" => { | |
| 491 | if (buffer.len == 0) return; | |
| 407 | .@"enum" => { | |
| 408 | const int_val = val.intFromEnum(zcu); | |
| 409 | return int_val.writeToPackedMemory(pt, buffer, bit_offset); | |
| 410 | }, | |
| 411 | .pointer => { | |
| 412 | assert(!ty.isSlice(zcu)); // No well defined layout. | |
| 413 | if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef; | |
| 414 | const addr = val.toUnsignedInt(zcu); | |
| 415 | std.mem.writeVarPackedInt(buffer, bit_offset, zcu.getTarget().ptrBitWidth(), addr, endian); | |
| 416 | }, | |
| 417 | .int => { | |
| 492 | 418 | const bits = ty.intInfo(zcu).bits; |
| 493 | if (bits == 0) return; | |
| 494 | ||
| 495 | switch (ip.indexToKey((try val.intFromEnum(ty, pt)).toIntern()).int.storage) { | |
| 419 | if (bits == 0 or buffer.len == 0) return; | |
| 420 | switch (ip.indexToKey(val.toIntern()).int.storage) { | |
| 496 | 421 | inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), |
| 497 | 422 | .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), |
| 498 | .lazy_align => |lazy_align| { | |
| 499 | const num = Type.fromInterned(lazy_align).abiAlignment(zcu).toByteUnits() orelse 0; | |
| 500 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); | |
| 501 | }, | |
| 502 | .lazy_size => |lazy_size| { | |
| 503 | const num = Type.fromInterned(lazy_size).abiSize(zcu); | |
| 504 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); | |
| 505 | }, | |
| 506 | 423 | } |
| 507 | 424 | }, |
| 508 | 425 | .float => switch (ty.floatBits(target)) { |
| ... | ... | @@ -524,58 +441,21 @@ pub fn writeToPackedMemory( |
| 524 | 441 | // On big-endian systems, LLVM reverses the element order of vectors by default |
| 525 | 442 | const tgt_elem_i = if (endian == .big) len - elem_i - 1 else elem_i; |
| 526 | 443 | const elem_val = try val.elemValue(pt, tgt_elem_i); |
| 527 | try elem_val.writeToPackedMemory(elem_ty, pt, buffer, bit_offset + bits); | |
| 444 | try elem_val.writeToPackedMemory(pt, buffer, bit_offset + bits); | |
| 528 | 445 | bits += elem_bit_size; |
| 529 | 446 | } |
| 530 | 447 | }, |
| 531 | .@"struct" => { | |
| 532 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 533 | // Sema is supposed to have emitted a compile error already in the case of Auto, | |
| 534 | // and Extern is handled in non-packed writeToMemory. | |
| 535 | assert(struct_type.layout == .@"packed"); | |
| 536 | var bits: u16 = 0; | |
| 537 | for (0..struct_type.field_types.len) |i| { | |
| 538 | const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 539 | .bytes => unreachable, | |
| 540 | .elems => |elems| elems[i], | |
| 541 | .repeated_elem => |elem| elem, | |
| 542 | }); | |
| 543 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 544 | const field_bits: u16 = @intCast(field_ty.bitSize(zcu)); | |
| 545 | try field_val.writeToPackedMemory(field_ty, pt, buffer, bit_offset + bits); | |
| 546 | bits += field_bits; | |
| 547 | } | |
| 548 | }, | |
| 549 | .@"union" => { | |
| 550 | const union_obj = zcu.typeToUnion(ty).?; | |
| 551 | switch (union_obj.flagsUnordered(ip).layout) { | |
| 552 | .auto, .@"extern" => unreachable, // Handled in non-packed writeToMemory | |
| 553 | .@"packed" => { | |
| 554 | if (val.unionTag(zcu)) |union_tag| { | |
| 555 | const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?; | |
| 556 | const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 557 | const field_val = try val.fieldValue(pt, field_index); | |
| 558 | return field_val.writeToPackedMemory(field_type, pt, buffer, bit_offset); | |
| 559 | } else { | |
| 560 | const backing_ty = try ty.unionBackingType(pt); | |
| 561 | return val.unionValue(zcu).writeToPackedMemory(backing_ty, pt, buffer, bit_offset); | |
| 562 | } | |
| 563 | }, | |
| 564 | } | |
| 565 | }, | |
| 566 | .pointer => { | |
| 567 | assert(!ty.isSlice(zcu)); // No well defined layout. | |
| 568 | if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef; | |
| 569 | return val.writeToPackedMemory(Type.usize, pt, buffer, bit_offset); | |
| 448 | .@"struct", .@"union" => { | |
| 449 | assert(ty.containerLayout(zcu) == .@"packed"); | |
| 450 | const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val); | |
| 451 | return int_val.writeToPackedMemory(pt, buffer, bit_offset); | |
| 570 | 452 | }, |
| 571 | 453 | .optional => { |
| 572 | 454 | assert(ty.isPtrLikeOptional(zcu)); |
| 573 | const child = ty.optionalChild(zcu); | |
| 574 | const opt_val = val.optionalValue(zcu); | |
| 575 | if (opt_val) |some| { | |
| 576 | return some.writeToPackedMemory(child, pt, buffer, bit_offset); | |
| 455 | if (val.optionalValue(zcu)) |ptr_val| { | |
| 456 | return ptr_val.writeToPackedMemory(pt, buffer, bit_offset); | |
| 577 | 457 | } else { |
| 578 | return writeToPackedMemory(try pt.intValue(Type.usize, 0), Type.usize, pt, buffer, bit_offset); | |
| 458 | return Value.zero_usize.writeToPackedMemory(pt, buffer, bit_offset); | |
| 579 | 459 | } |
| 580 | 460 | }, |
| 581 | 461 | else => @panic("TODO implement writeToPackedMemory for more types"), |
| ... | ... | @@ -625,13 +505,12 @@ pub fn readFromPackedMemory( |
| 625 | 505 | pt: Zcu.PerThread, |
| 626 | 506 | buffer: []const u8, |
| 627 | 507 | bit_offset: usize, |
| 628 | arena: Allocator, | |
| 508 | gpa: Allocator, | |
| 629 | 509 | ) error{ |
| 630 | 510 | IllDefinedMemoryLayout, |
| 631 | 511 | OutOfMemory, |
| 632 | 512 | }!Value { |
| 633 | 513 | const zcu = pt.zcu; |
| 634 | const ip = &zcu.intern_pool; | |
| 635 | 514 | const target = zcu.getTarget(); |
| 636 | 515 | const endian = target.cpu.arch.endian(); |
| 637 | 516 | switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -665,7 +544,8 @@ pub fn readFromPackedMemory( |
| 665 | 544 | const abi_size: usize = @intCast(ty.abiSize(zcu)); |
| 666 | 545 | const Limb = std.math.big.Limb; |
| 667 | 546 | const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb); |
| 668 | const limbs_buffer = try arena.alloc(Limb, limb_count); | |
| 547 | const limbs_buffer = try gpa.alloc(Limb, limb_count); | |
| 548 | defer gpa.free(limbs_buffer); | |
| 669 | 549 | |
| 670 | 550 | var bigint = BigIntMutable.init(limbs_buffer, 0); |
| 671 | 551 | bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness); |
| ... | ... | @@ -673,7 +553,7 @@ pub fn readFromPackedMemory( |
| 673 | 553 | }, |
| 674 | 554 | .@"enum" => { |
| 675 | 555 | const int_ty = ty.intTagType(zcu); |
| 676 | const int_val = try Value.readFromPackedMemory(int_ty, pt, buffer, bit_offset, arena); | |
| 556 | const int_val = try Value.readFromPackedMemory(int_ty, pt, buffer, bit_offset, gpa); | |
| 677 | 557 | return pt.getCoerced(int_val, ty); |
| 678 | 558 | }, |
| 679 | 559 | .float => return Value.fromInterned(try pt.intern(.{ .float = .{ |
| ... | ... | @@ -689,64 +569,35 @@ pub fn readFromPackedMemory( |
| 689 | 569 | } })), |
| 690 | 570 | .vector => { |
| 691 | 571 | const elem_ty = ty.childType(zcu); |
| 692 | const elems = try arena.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu))); | |
| 572 | const elems = try gpa.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu))); | |
| 573 | defer gpa.free(elems); | |
| 693 | 574 | |
| 694 | 575 | var bits: u16 = 0; |
| 695 | 576 | const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu)); |
| 696 | 577 | for (elems, 0..) |_, i| { |
| 697 | 578 | // On big-endian systems, LLVM reverses the element order of vectors by default |
| 698 | 579 | const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i; |
| 699 | elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, pt, buffer, bit_offset + bits, arena)).toIntern(); | |
| 580 | elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, pt, buffer, bit_offset + bits, gpa)).toIntern(); | |
| 700 | 581 | bits += elem_bit_size; |
| 701 | 582 | } |
| 702 | 583 | return pt.aggregateValue(ty, elems); |
| 703 | 584 | }, |
| 704 | .@"struct" => { | |
| 705 | // Sema is supposed to have emitted a compile error already for Auto layout structs, | |
| 706 | // and Extern is handled by non-packed readFromMemory. | |
| 707 | const struct_type = zcu.typeToPackedStruct(ty).?; | |
| 708 | var bits: u16 = 0; | |
| 709 | const field_vals = try arena.alloc(InternPool.Index, struct_type.field_types.len); | |
| 710 | for (field_vals, 0..) |*field_val, i| { | |
| 711 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 712 | const field_bits: u16 = @intCast(field_ty.bitSize(zcu)); | |
| 713 | field_val.* = (try readFromPackedMemory(field_ty, pt, buffer, bit_offset + bits, arena)).toIntern(); | |
| 714 | bits += field_bits; | |
| 715 | } | |
| 716 | return pt.aggregateValue(ty, field_vals); | |
| 717 | }, | |
| 718 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 719 | .auto, .@"extern" => unreachable, // Handled by non-packed readFromMemory | |
| 720 | .@"packed" => { | |
| 721 | const backing_ty = try ty.unionBackingType(pt); | |
| 722 | const val = (try readFromPackedMemory(backing_ty, pt, buffer, bit_offset, arena)).toIntern(); | |
| 723 | return Value.fromInterned(try pt.internUnion(.{ | |
| 724 | .ty = ty.toIntern(), | |
| 725 | .tag = .none, | |
| 726 | .val = val, | |
| 727 | })); | |
| 728 | }, | |
| 585 | .@"struct", .@"union" => { | |
| 586 | assert(ty.containerLayout(zcu) == .@"packed"); | |
| 587 | const int_val: Value = try .readFromPackedMemory(ty.bitpackBackingInt(zcu), pt, buffer, bit_offset, gpa); | |
| 588 | return pt.bitpackValue(ty, int_val); | |
| 729 | 589 | }, |
| 730 | 590 | .pointer => { |
| 731 | 591 | assert(!ty.isSlice(zcu)); // No well defined layout. |
| 732 | const int_val = try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena); | |
| 733 | return Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 734 | .ty = ty.toIntern(), | |
| 735 | .base_addr = .int, | |
| 736 | .byte_offset = int_val.toUnsignedInt(zcu), | |
| 737 | } })); | |
| 592 | const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, gpa)).toUnsignedInt(zcu); | |
| 593 | return pt.ptrIntValue(ty, addr); | |
| 738 | 594 | }, |
| 739 | 595 | .optional => { |
| 740 | 596 | assert(ty.isPtrLikeOptional(zcu)); |
| 741 | const child_ty = ty.optionalChild(zcu); | |
| 742 | const child_val = try readFromPackedMemory(child_ty, pt, buffer, bit_offset, arena); | |
| 743 | return Value.fromInterned(try pt.intern(.{ .opt = .{ | |
| 597 | const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, gpa)).toUnsignedInt(zcu); | |
| 598 | return .fromInterned(try pt.intern(.{ .opt = .{ | |
| 744 | 599 | .ty = ty.toIntern(), |
| 745 | .val = switch (child_val.orderAgainstZero(zcu)) { | |
| 746 | .lt => unreachable, | |
| 747 | .eq => .none, | |
| 748 | .gt => child_val.toIntern(), | |
| 749 | }, | |
| 600 | .val = if (addr == 0) .none else (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(), | |
| 750 | 601 | } })); |
| 751 | 602 | }, |
| 752 | 603 | else => @panic("TODO implement readFromPackedMemory for more types"), |
| ... | ... | @@ -764,8 +615,6 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T { |
| 764 | 615 | } |
| 765 | 616 | return @floatFromInt(x); |
| 766 | 617 | }, |
| 767 | .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0), | |
| 768 | .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(zcu)), | |
| 769 | 618 | }, |
| 770 | 619 | .float => |float| switch (float.storage) { |
| 771 | 620 | inline else => |x| @floatCast(x), |
| ... | ... | @@ -819,110 +668,8 @@ pub fn floatCast(val: Value, dest_ty: Type, pt: Zcu.PerThread) !Value { |
| 819 | 668 | } })); |
| 820 | 669 | } |
| 821 | 670 | |
| 822 | pub fn orderAgainstZero(lhs: Value, zcu: *Zcu) std.math.Order { | |
| 823 | return orderAgainstZeroInner(lhs, .normal, zcu, {}) catch unreachable; | |
| 824 | } | |
| 825 | ||
| 826 | pub fn orderAgainstZeroSema(lhs: Value, pt: Zcu.PerThread) !std.math.Order { | |
| 827 | return try orderAgainstZeroInner(lhs, .sema, pt.zcu, pt.tid); | |
| 828 | } | |
| 829 | ||
| 830 | pub fn orderAgainstZeroInner( | |
| 831 | lhs: Value, | |
| 832 | comptime strat: ResolveStrat, | |
| 833 | zcu: *Zcu, | |
| 834 | tid: strat.Tid(), | |
| 835 | ) Zcu.SemaError!std.math.Order { | |
| 836 | return switch (lhs.toIntern()) { | |
| 837 | .bool_false => .eq, | |
| 838 | .bool_true => .gt, | |
| 839 | else => switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { | |
| 840 | .ptr => |ptr| if (ptr.byte_offset > 0) .gt else switch (ptr.base_addr) { | |
| 841 | .nav, .comptime_alloc, .comptime_field => .gt, | |
| 842 | .int => .eq, | |
| 843 | else => unreachable, | |
| 844 | }, | |
| 845 | .int => |int| switch (int.storage) { | |
| 846 | .big_int => |big_int| big_int.orderAgainstScalar(0), | |
| 847 | inline .u64, .i64 => |x| std.math.order(x, 0), | |
| 848 | .lazy_align => .gt, // alignment is never 0 | |
| 849 | .lazy_size => |ty| return if (Type.fromInterned(ty).hasRuntimeBitsInner( | |
| 850 | false, | |
| 851 | strat.toLazy(), | |
| 852 | zcu, | |
| 853 | tid, | |
| 854 | ) catch |err| switch (err) { | |
| 855 | error.NeedLazy => unreachable, | |
| 856 | else => |e| return e, | |
| 857 | }) .gt else .eq, | |
| 858 | }, | |
| 859 | .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).orderAgainstZeroInner(strat, zcu, tid), | |
| 860 | .float => |float| switch (float.storage) { | |
| 861 | inline else => |x| std.math.order(x, 0), | |
| 862 | }, | |
| 863 | .err => .gt, // error values cannot be 0 | |
| 864 | else => unreachable, | |
| 865 | }, | |
| 866 | }; | |
| 867 | } | |
| 868 | ||
| 869 | /// Asserts the value is comparable. | |
| 870 | pub fn order(lhs: Value, rhs: Value, zcu: *Zcu) std.math.Order { | |
| 871 | return orderAdvanced(lhs, rhs, .normal, zcu, {}) catch unreachable; | |
| 872 | } | |
| 873 | ||
| 874 | /// Asserts the value is comparable. | |
| 875 | pub fn orderAdvanced( | |
| 876 | lhs: Value, | |
| 877 | rhs: Value, | |
| 878 | comptime strat: ResolveStrat, | |
| 879 | zcu: *Zcu, | |
| 880 | tid: strat.Tid(), | |
| 881 | ) !std.math.Order { | |
| 882 | const lhs_against_zero = try lhs.orderAgainstZeroInner(strat, zcu, tid); | |
| 883 | const rhs_against_zero = try rhs.orderAgainstZeroInner(strat, zcu, tid); | |
| 884 | switch (lhs_against_zero) { | |
| 885 | .lt => if (rhs_against_zero != .lt) return .lt, | |
| 886 | .eq => return rhs_against_zero.invert(), | |
| 887 | .gt => {}, | |
| 888 | } | |
| 889 | switch (rhs_against_zero) { | |
| 890 | .lt => if (lhs_against_zero != .lt) return .gt, | |
| 891 | .eq => return lhs_against_zero, | |
| 892 | .gt => {}, | |
| 893 | } | |
| 894 | ||
| 895 | if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) { | |
| 896 | const lhs_f128 = lhs.toFloat(f128, zcu); | |
| 897 | const rhs_f128 = rhs.toFloat(f128, zcu); | |
| 898 | return std.math.order(lhs_f128, rhs_f128); | |
| 899 | } | |
| 900 | ||
| 901 | var lhs_bigint_space: BigIntSpace = undefined; | |
| 902 | var rhs_bigint_space: BigIntSpace = undefined; | |
| 903 | const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, strat, zcu, tid); | |
| 904 | const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, strat, zcu, tid); | |
| 905 | return lhs_bigint.order(rhs_bigint); | |
| 906 | } | |
| 907 | ||
| 908 | /// Asserts the value is comparable. Does not take a type parameter because it supports | |
| 909 | /// comparisons between heterogeneous types. | |
| 910 | pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: *Zcu) bool { | |
| 911 | return compareHeteroAdvanced(lhs, op, rhs, .normal, zcu, {}) catch unreachable; | |
| 912 | } | |
| 913 | ||
| 914 | pub fn compareHeteroSema(lhs: Value, op: std.math.CompareOperator, rhs: Value, pt: Zcu.PerThread) !bool { | |
| 915 | return try compareHeteroAdvanced(lhs, op, rhs, .sema, pt.zcu, pt.tid); | |
| 916 | } | |
| 917 | ||
| 918 | pub fn compareHeteroAdvanced( | |
| 919 | lhs: Value, | |
| 920 | op: std.math.CompareOperator, | |
| 921 | rhs: Value, | |
| 922 | comptime strat: ResolveStrat, | |
| 923 | zcu: *Zcu, | |
| 924 | tid: strat.Tid(), | |
| 925 | ) !bool { | |
| 671 | /// Asserts the value is comparable. Supports comparisons between heterogeneous types. | |
| 672 | pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: *const Zcu) bool { | |
| 926 | 673 | if (lhs.pointerNav(zcu)) |lhs_nav| { |
| 927 | 674 | if (rhs.pointerNav(zcu)) |rhs_nav| { |
| 928 | 675 | switch (op) { |
| ... | ... | @@ -944,9 +691,21 @@ pub fn compareHeteroAdvanced( |
| 944 | 691 | else => {}, |
| 945 | 692 | } |
| 946 | 693 | } |
| 947 | ||
| 948 | 694 | if (lhs.isNan(zcu) or rhs.isNan(zcu)) return op == .neq; |
| 949 | return (try orderAdvanced(lhs, rhs, strat, zcu, tid)).compare(op); | |
| 695 | return order(lhs, rhs, zcu).compare(op); | |
| 696 | } | |
| 697 | ||
| 698 | pub fn order(lhs: Value, rhs: Value, zcu: *const Zcu) std.math.Order { | |
| 699 | if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) { | |
| 700 | const lhs_f128 = lhs.toFloat(f128, zcu); | |
| 701 | const rhs_f128 = rhs.toFloat(f128, zcu); | |
| 702 | return std.math.order(lhs_f128, rhs_f128); | |
| 703 | } | |
| 704 | var lhs_bigint_space: BigIntSpace = undefined; | |
| 705 | var rhs_bigint_space: BigIntSpace = undefined; | |
| 706 | const lhs_bigint = lhs.toBigInt(&lhs_bigint_space, zcu); | |
| 707 | const rhs_bigint = rhs.toBigInt(&rhs_bigint_space, zcu); | |
| 708 | return lhs_bigint.order(rhs_bigint); | |
| 950 | 709 | } |
| 951 | 710 | |
| 952 | 711 | /// Asserts the values are comparable. Both operands have type `ty`. |
| ... | ... | @@ -988,55 +747,30 @@ pub fn compareScalar( |
| 988 | 747 | /// |
| 989 | 748 | /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)` |
| 990 | 749 | pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, zcu: *Zcu) bool { |
| 991 | return compareAllWithZeroAdvancedExtra(lhs, op, .normal, zcu, {}) catch unreachable; | |
| 992 | } | |
| 993 | ||
| 994 | pub fn compareAllWithZeroSema( | |
| 995 | lhs: Value, | |
| 996 | op: std.math.CompareOperator, | |
| 997 | pt: Zcu.PerThread, | |
| 998 | ) Zcu.CompileError!bool { | |
| 999 | return compareAllWithZeroAdvancedExtra(lhs, op, .sema, pt.zcu, pt.tid); | |
| 1000 | } | |
| 1001 | ||
| 1002 | pub fn compareAllWithZeroAdvancedExtra( | |
| 1003 | lhs: Value, | |
| 1004 | op: std.math.CompareOperator, | |
| 1005 | comptime strat: ResolveStrat, | |
| 1006 | zcu: *Zcu, | |
| 1007 | tid: strat.Tid(), | |
| 1008 | ) Zcu.CompileError!bool { | |
| 1009 | if (lhs.isInf(zcu)) { | |
| 1010 | switch (op) { | |
| 1011 | .neq => return true, | |
| 1012 | .eq => return false, | |
| 1013 | .gt, .gte => return !lhs.isNegativeInf(zcu), | |
| 1014 | .lt, .lte => return lhs.isNegativeInf(zcu), | |
| 1015 | } | |
| 1016 | } | |
| 1017 | ||
| 1018 | switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { | |
| 750 | return switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { | |
| 1019 | 751 | .float => |float| switch (float.storage) { |
| 1020 | inline else => |x| if (std.math.isNan(x)) return op == .neq, | |
| 752 | inline else => |x| std.math.compare(x, op, 0), | |
| 1021 | 753 | }, |
| 1022 | .aggregate => |aggregate| return switch (aggregate.storage) { | |
| 1023 | .bytes => |bytes| for (bytes.toSlice(lhs.typeOf(zcu).arrayLenIncludingSentinel(zcu), &zcu.intern_pool)) |byte| { | |
| 1024 | if (!std.math.order(byte, 0).compare(op)) break false; | |
| 754 | .aggregate => |aggregate| switch (aggregate.storage) { | |
| 755 | .bytes => |bytes| for (bytes.toSlice( | |
| 756 | lhs.typeOf(zcu).arrayLenIncludingSentinel(zcu), | |
| 757 | &zcu.intern_pool, | |
| 758 | )) |byte| { | |
| 759 | if (!std.math.compare(byte, op, 0)) break false; | |
| 1025 | 760 | } else true, |
| 1026 | 761 | .elems => |elems| for (elems) |elem| { |
| 1027 | if (!try Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, strat, zcu, tid)) break false; | |
| 762 | if (!Value.fromInterned(elem).compareAllWithZero(op, zcu)) break false; | |
| 1028 | 763 | } else true, |
| 1029 | .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, strat, zcu, tid), | |
| 764 | .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZero(op, zcu), | |
| 1030 | 765 | }, |
| 1031 | .undef => return false, | |
| 1032 | else => {}, | |
| 1033 | } | |
| 1034 | return (try orderAgainstZeroInner(lhs, strat, zcu, tid)).compare(op); | |
| 766 | .undef => false, | |
| 767 | else => order(lhs, .zero_comptime_int, zcu).compare(op), | |
| 768 | }; | |
| 1035 | 769 | } |
| 1036 | 770 | |
| 1037 | 771 | pub fn eql(a: Value, b: Value, ty: Type, zcu: *Zcu) bool { |
| 1038 | assert(zcu.intern_pool.typeOf(a.toIntern()) == ty.toIntern()); | |
| 1039 | assert(zcu.intern_pool.typeOf(b.toIntern()) == ty.toIntern()); | |
| 772 | assert(a.typeOf(zcu).toIntern() == ty.toIntern()); | |
| 773 | assert(b.typeOf(zcu).toIntern() == ty.toIntern()); | |
| 1040 | 774 | return a.toIntern() == b.toIntern(); |
| 1041 | 775 | } |
| 1042 | 776 | |
| ... | ... | @@ -1071,7 +805,7 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool { |
| 1071 | 805 | /// Gets the `Nav` referenced by this pointer. If the pointer does not point |
| 1072 | 806 | /// to a `Nav`, or if it points to some part of one (like a field or element), |
| 1073 | 807 | /// returns null. |
| 1074 | pub fn pointerNav(val: Value, zcu: *Zcu) ?InternPool.Nav.Index { | |
| 808 | pub fn pointerNav(val: Value, zcu: *const Zcu) ?InternPool.Nav.Index { | |
| 1075 | 809 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 1076 | 810 | // TODO: these 3 cases are weird; these aren't pointer values! |
| 1077 | 811 | .variable => |v| v.owner_nav, |
| ... | ... | @@ -1088,16 +822,13 @@ pub fn pointerNav(val: Value, zcu: *Zcu) ?InternPool.Nav.Index { |
| 1088 | 822 | pub const slice_ptr_index = 0; |
| 1089 | 823 | pub const slice_len_index = 1; |
| 1090 | 824 | |
| 825 | pub fn sliceLen(val: Value, zcu: *Zcu) u64 { | |
| 826 | return Value.fromInterned(zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedInt(zcu); | |
| 827 | } | |
| 1091 | 828 | pub fn slicePtr(val: Value, zcu: *Zcu) Value { |
| 1092 | 829 | return Value.fromInterned(zcu.intern_pool.slicePtr(val.toIntern())); |
| 1093 | 830 | } |
| 1094 | 831 | |
| 1095 | /// Gets the `len` field of a slice value as a `u64`. | |
| 1096 | /// Resolves the length using `Sema` if necessary. | |
| 1097 | pub fn sliceLen(val: Value, pt: Zcu.PerThread) !u64 { | |
| 1098 | return Value.fromInterned(pt.zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedIntSema(pt); | |
| 1099 | } | |
| 1100 | ||
| 1101 | 832 | /// Asserts the value is an aggregate, and returns the element value at the given index. |
| 1102 | 833 | pub fn elemValue(val: Value, pt: Zcu.PerThread, index: usize) Allocator.Error!Value { |
| 1103 | 834 | const zcu = pt.zcu; |
| ... | ... | @@ -1123,62 +854,6 @@ pub fn elemValue(val: Value, pt: Zcu.PerThread, index: usize) Allocator.Error!Va |
| 1123 | 854 | } |
| 1124 | 855 | } |
| 1125 | 856 | |
| 1126 | pub fn isLazyAlign(val: Value, zcu: *Zcu) bool { | |
| 1127 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 1128 | .int => |int| int.storage == .lazy_align, | |
| 1129 | else => false, | |
| 1130 | }; | |
| 1131 | } | |
| 1132 | ||
| 1133 | pub fn isLazySize(val: Value, zcu: *Zcu) bool { | |
| 1134 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 1135 | .int => |int| int.storage == .lazy_size, | |
| 1136 | else => false, | |
| 1137 | }; | |
| 1138 | } | |
| 1139 | ||
| 1140 | // Asserts that the provided start/end are in-bounds. | |
| 1141 | pub fn sliceArray( | |
| 1142 | val: Value, | |
| 1143 | sema: *Sema, | |
| 1144 | start: usize, | |
| 1145 | end: usize, | |
| 1146 | ) error{OutOfMemory}!Value { | |
| 1147 | const pt = sema.pt; | |
| 1148 | const ip = &pt.zcu.intern_pool; | |
| 1149 | const io = pt.zcu.comp.io; | |
| 1150 | return Value.fromInterned(try pt.intern(.{ | |
| 1151 | .aggregate = .{ | |
| 1152 | .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) { | |
| 1153 | .array_type => |array_type| try pt.arrayType(.{ | |
| 1154 | .len = @intCast(end - start), | |
| 1155 | .child = array_type.child, | |
| 1156 | .sentinel = if (end == array_type.len) array_type.sentinel else .none, | |
| 1157 | }), | |
| 1158 | .vector_type => |vector_type| try pt.vectorType(.{ | |
| 1159 | .len = @intCast(end - start), | |
| 1160 | .child = vector_type.child, | |
| 1161 | }), | |
| 1162 | else => unreachable, | |
| 1163 | }.toIntern(), | |
| 1164 | .storage = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 1165 | .bytes => |bytes| storage: { | |
| 1166 | try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1); | |
| 1167 | break :storage .{ .bytes = try ip.getOrPutString( | |
| 1168 | sema.gpa, | |
| 1169 | io, | |
| 1170 | bytes.toSlice(end, ip)[start..], | |
| 1171 | .maybe_embedded_nulls, | |
| 1172 | ) }; | |
| 1173 | }, | |
| 1174 | // TODO: write something like getCoercedInts to avoid needing to dupe | |
| 1175 | .elems => |elems| .{ .elems = try sema.arena.dupe(InternPool.Index, elems[start..end]) }, | |
| 1176 | .repeated_elem => |elem| .{ .repeated_elem = elem }, | |
| 1177 | }, | |
| 1178 | }, | |
| 1179 | })); | |
| 1180 | } | |
| 1181 | ||
| 1182 | 857 | pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { |
| 1183 | 858 | const zcu = pt.zcu; |
| 1184 | 859 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| ... | ... | @@ -1193,8 +868,44 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { |
| 1193 | 868 | .elems => |elems| elems[index], |
| 1194 | 869 | .repeated_elem => |elem| elem, |
| 1195 | 870 | }), |
| 1196 | // TODO assert the tag is correct | |
| 1197 | .un => |un| Value.fromInterned(un.val), | |
| 871 | .un => |un| { | |
| 872 | switch (Type.fromInterned(un.ty).containerLayout(zcu)) { | |
| 873 | .auto, .@"extern" => {}, // TODO assert the tag is correct | |
| 874 | .@"packed" => unreachable, | |
| 875 | } | |
| 876 | return .fromInterned(un.val); | |
| 877 | }, | |
| 878 | .bitpack => |bitpack| { | |
| 879 | const ty: Type = .fromInterned(bitpack.ty); | |
| 880 | assert(ty.containerLayout(zcu) == .@"packed"); | |
| 881 | const int_val: Value = .fromInterned(bitpack.backing_int_val); | |
| 882 | assert(!int_val.isUndef(zcu)); | |
| 883 | const field_ty = ty.fieldType(index, zcu); | |
| 884 | const field_bit_offset: u16 = switch (ty.zigTypeTag(zcu)) { | |
| 885 | .@"union" => 0, | |
| 886 | .@"struct" => off: { | |
| 887 | var off: u16 = 0; | |
| 888 | for (0..index) |preceding_field_index| { | |
| 889 | off += @intCast(ty.fieldType(preceding_field_index, zcu).bitSize(zcu)); | |
| 890 | } | |
| 891 | break :off off; | |
| 892 | }, | |
| 893 | else => unreachable, | |
| 894 | }; | |
| 895 | // Avoid hitting gpa for accesses to small packed structs | |
| 896 | var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa); | |
| 897 | const sfba = sfba_state.get(); | |
| 898 | const buf = try sfba.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8)); | |
| 899 | defer sfba.free(buf); | |
| 900 | int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) { | |
| 901 | error.ReinterpretDeclRef => unreachable, // it's an integer | |
| 902 | error.OutOfMemory => |e| return e, | |
| 903 | }; | |
| 904 | return Value.readFromPackedMemory(field_ty, pt, buf, field_bit_offset, sfba) catch |err| switch (err) { | |
| 905 | error.IllDefinedMemoryLayout => unreachable, // it's a bitpack | |
| 906 | error.OutOfMemory => |e| return e, | |
| 907 | }; | |
| 908 | }, | |
| 1198 | 909 | else => unreachable, |
| 1199 | 910 | }; |
| 1200 | 911 | } |
| ... | ... | @@ -1207,7 +918,7 @@ pub fn unionTag(val: Value, zcu: *Zcu) ?Value { |
| 1207 | 918 | }; |
| 1208 | 919 | } |
| 1209 | 920 | |
| 1210 | pub fn unionValue(val: Value, zcu: *Zcu) Value { | |
| 921 | pub fn unionPayload(val: Value, zcu: *Zcu) Value { | |
| 1211 | 922 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 1212 | 923 | .un => |un| Value.fromInterned(un.val), |
| 1213 | 924 | else => unreachable, |
| ... | ... | @@ -1334,63 +1045,6 @@ pub fn isFloat(self: Value, zcu: *const Zcu) bool { |
| 1334 | 1045 | }; |
| 1335 | 1046 | } |
| 1336 | 1047 | |
| 1337 | pub fn floatFromInt(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, zcu: *Zcu) !Value { | |
| 1338 | return floatFromIntAdvanced(val, arena, int_ty, float_ty, zcu, .normal) catch |err| switch (err) { | |
| 1339 | error.OutOfMemory => return error.OutOfMemory, | |
| 1340 | else => unreachable, | |
| 1341 | }; | |
| 1342 | } | |
| 1343 | ||
| 1344 | pub fn floatFromIntAdvanced( | |
| 1345 | val: Value, | |
| 1346 | arena: Allocator, | |
| 1347 | int_ty: Type, | |
| 1348 | float_ty: Type, | |
| 1349 | pt: Zcu.PerThread, | |
| 1350 | comptime strat: ResolveStrat, | |
| 1351 | ) !Value { | |
| 1352 | const zcu = pt.zcu; | |
| 1353 | if (int_ty.zigTypeTag(zcu) == .vector) { | |
| 1354 | const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(zcu)); | |
| 1355 | const scalar_ty = float_ty.scalarType(zcu); | |
| 1356 | for (result_data, 0..) |*scalar, i| { | |
| 1357 | const elem_val = try val.elemValue(pt, i); | |
| 1358 | scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, pt, strat)).toIntern(); | |
| 1359 | } | |
| 1360 | return pt.aggregateValue(float_ty, result_data); | |
| 1361 | } | |
| 1362 | return floatFromIntScalar(val, float_ty, pt, strat); | |
| 1363 | } | |
| 1364 | ||
| 1365 | pub fn floatFromIntScalar(val: Value, float_ty: Type, pt: Zcu.PerThread, comptime strat: ResolveStrat) !Value { | |
| 1366 | return switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 1367 | .undef => try pt.undefValue(float_ty), | |
| 1368 | .int => |int| switch (int.storage) { | |
| 1369 | .big_int => |big_int| pt.floatValue(float_ty, big_int.toFloat(f128, .nearest_even)[0]), | |
| 1370 | inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, pt), | |
| 1371 | .lazy_align => |ty| floatFromIntInner((try Type.fromInterned(ty).abiAlignmentInner(strat.toLazy(), pt.zcu, pt.tid)).scalar.toByteUnits() orelse 0, float_ty, pt), | |
| 1372 | .lazy_size => |ty| floatFromIntInner((try Type.fromInterned(ty).abiSizeInner(strat.toLazy(), pt.zcu, pt.tid)).scalar, float_ty, pt), | |
| 1373 | }, | |
| 1374 | else => unreachable, | |
| 1375 | }; | |
| 1376 | } | |
| 1377 | ||
| 1378 | fn floatFromIntInner(x: anytype, dest_ty: Type, pt: Zcu.PerThread) !Value { | |
| 1379 | const target = pt.zcu.getTarget(); | |
| 1380 | const storage: InternPool.Key.Float.Storage = switch (dest_ty.floatBits(target)) { | |
| 1381 | 16 => .{ .f16 = @floatFromInt(x) }, | |
| 1382 | 32 => .{ .f32 = @floatFromInt(x) }, | |
| 1383 | 64 => .{ .f64 = @floatFromInt(x) }, | |
| 1384 | 80 => .{ .f80 = @floatFromInt(x) }, | |
| 1385 | 128 => .{ .f128 = @floatFromInt(x) }, | |
| 1386 | else => unreachable, | |
| 1387 | }; | |
| 1388 | return Value.fromInterned(try pt.intern(.{ .float = .{ | |
| 1389 | .ty = dest_ty.toIntern(), | |
| 1390 | .storage = storage, | |
| 1391 | } })); | |
| 1392 | } | |
| 1393 | ||
| 1394 | 1048 | fn calcLimbLenFloat(scalar: anytype) usize { |
| 1395 | 1049 | if (scalar == 0) { |
| 1396 | 1050 | return 1; |
| ... | ... | @@ -1410,11 +1064,11 @@ pub fn numberMax(lhs: Value, rhs: Value, zcu: *Zcu) Value { |
| 1410 | 1064 | if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return undef; |
| 1411 | 1065 | if (lhs.isNan(zcu)) return rhs; |
| 1412 | 1066 | if (rhs.isNan(zcu)) return lhs; |
| 1413 | ||
| 1414 | return switch (order(lhs, rhs, zcu)) { | |
| 1415 | .lt => rhs, | |
| 1416 | .gt, .eq => lhs, | |
| 1417 | }; | |
| 1067 | if (compareHetero(lhs, .gt, rhs, zcu)) { | |
| 1068 | return lhs; | |
| 1069 | } else { | |
| 1070 | return rhs; | |
| 1071 | } | |
| 1418 | 1072 | } |
| 1419 | 1073 | |
| 1420 | 1074 | /// Supports both floats and ints; handles undefined. |
| ... | ... | @@ -1422,11 +1076,11 @@ pub fn numberMin(lhs: Value, rhs: Value, zcu: *Zcu) Value { |
| 1422 | 1076 | if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return undef; |
| 1423 | 1077 | if (lhs.isNan(zcu)) return rhs; |
| 1424 | 1078 | if (rhs.isNan(zcu)) return lhs; |
| 1425 | ||
| 1426 | return switch (order(lhs, rhs, zcu)) { | |
| 1427 | .lt => lhs, | |
| 1428 | .gt, .eq => rhs, | |
| 1429 | }; | |
| 1079 | if (compareHetero(lhs, .lt, rhs, zcu)) { | |
| 1080 | return lhs; | |
| 1081 | } else { | |
| 1082 | return rhs; | |
| 1083 | } | |
| 1430 | 1084 | } |
| 1431 | 1085 | |
| 1432 | 1086 | /// Returns true if the value is a floating point type and is NaN. Returns false otherwise. |
| ... | ... | @@ -2033,8 +1687,6 @@ pub fn makeBool(x: bool) Value { |
| 2033 | 1687 | /// `parent_ptr` must be a single-pointer or C pointer to some optional. |
| 2034 | 1688 | /// |
| 2035 | 1689 | /// Returns a pointer to the payload of the optional. |
| 2036 | /// | |
| 2037 | /// May perform type resolution. | |
| 2038 | 1690 | pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2039 | 1691 | const zcu = pt.zcu; |
| 2040 | 1692 | const parent_ptr_ty = parent_ptr.typeOf(zcu); |
| ... | ... | @@ -2044,7 +1696,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2044 | 1696 | assert(ptr_size == .one or ptr_size == .c); |
| 2045 | 1697 | assert(opt_ty.zigTypeTag(zcu) == .optional); |
| 2046 | 1698 | |
| 2047 | const result_ty = try pt.ptrTypeSema(info: { | |
| 1699 | const result_ty = try pt.ptrType(info: { | |
| 2048 | 1700 | var new = parent_ptr_ty.ptrInfo(zcu); |
| 2049 | 1701 | // We can correctly preserve alignment `.none`, since an optional has the same |
| 2050 | 1702 | // natural alignment as its child type. |
| ... | ... | @@ -2060,7 +1712,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2060 | 1712 | } |
| 2061 | 1713 | |
| 2062 | 1714 | const base_ptr = try parent_ptr.canonicalizeBasePtr(.one, opt_ty, pt); |
| 2063 | return Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 1715 | return .fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2064 | 1716 | .ty = result_ty.toIntern(), |
| 2065 | 1717 | .base_addr = .{ .opt_payload = base_ptr.toIntern() }, |
| 2066 | 1718 | .byte_offset = 0, |
| ... | ... | @@ -2069,7 +1721,6 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2069 | 1721 | |
| 2070 | 1722 | /// `parent_ptr` must be a single-pointer to some error union. |
| 2071 | 1723 | /// Returns a pointer to the payload of the error union. |
| 2072 | /// May perform type resolution. | |
| 2073 | 1724 | pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2074 | 1725 | const zcu = pt.zcu; |
| 2075 | 1726 | const parent_ptr_ty = parent_ptr.typeOf(zcu); |
| ... | ... | @@ -2078,7 +1729,7 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2078 | 1729 | assert(parent_ptr_ty.ptrSize(zcu) == .one); |
| 2079 | 1730 | assert(eu_ty.zigTypeTag(zcu) == .error_union); |
| 2080 | 1731 | |
| 2081 | const result_ty = try pt.ptrTypeSema(info: { | |
| 1732 | const result_ty = try pt.ptrType(info: { | |
| 2082 | 1733 | var new = parent_ptr_ty.ptrInfo(zcu); |
| 2083 | 1734 | // We can correctly preserve alignment `.none`, since an error union has a |
| 2084 | 1735 | // natural alignment greater than or equal to that of its payload type. |
| ... | ... | @@ -2089,147 +1740,57 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { |
| 2089 | 1740 | if (parent_ptr.isUndef(zcu)) return pt.undefValue(result_ty); |
| 2090 | 1741 | |
| 2091 | 1742 | const base_ptr = try parent_ptr.canonicalizeBasePtr(.one, eu_ty, pt); |
| 2092 | return Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 1743 | return .fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2093 | 1744 | .ty = result_ty.toIntern(), |
| 2094 | 1745 | .base_addr = .{ .eu_payload = base_ptr.toIntern() }, |
| 2095 | 1746 | .byte_offset = 0, |
| 2096 | 1747 | } })); |
| 2097 | 1748 | } |
| 2098 | 1749 | |
| 2099 | /// `parent_ptr` must be a single-pointer or c pointer to a struct, union, or slice. | |
| 1750 | /// `parent_ptr` must be a single-item pointer or C pointer to a struct, union, or slice. | |
| 2100 | 1751 | /// |
| 2101 | 1752 | /// Returns a pointer to the aggregate field at the specified index. |
| 2102 | 1753 | /// |
| 2103 | 1754 | /// For slices, uses `slice_ptr_index` and `slice_len_index`. |
| 2104 | 1755 | /// |
| 2105 | /// May perform type resolution. | |
| 1756 | /// Asserts that the layout of the aggregate type is resolved. | |
| 2106 | 1757 | pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { |
| 2107 | 1758 | const zcu = pt.zcu; |
| 2108 | 1759 | const parent_ptr_ty = parent_ptr.typeOf(zcu); |
| 2109 | 1760 | const aggregate_ty = parent_ptr_ty.childType(zcu); |
| 1761 | aggregate_ty.assertHasLayout(zcu); | |
| 2110 | 1762 | |
| 2111 | 1763 | const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); |
| 2112 | 1764 | assert(parent_ptr_info.flags.size == .one or parent_ptr_info.flags.size == .c); |
| 2113 | 1765 | |
| 2114 | // Exiting this `switch` indicates that the `field` pointer representation should be used. | |
| 2115 | // `field_align` may be `.none` to represent the natural alignment of `field_ty`, but is not necessarily. | |
| 2116 | const field_ty: Type, const field_align: InternPool.Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { | |
| 2117 | .@"struct" => field: { | |
| 2118 | const field_ty = aggregate_ty.fieldType(field_idx, zcu); | |
| 2119 | switch (aggregate_ty.containerLayout(zcu)) { | |
| 2120 | .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) }, | |
| 2121 | .@"extern" => { | |
| 2122 | // Well-defined layout, so just offset the pointer appropriately. | |
| 2123 | try aggregate_ty.resolveLayout(pt); | |
| 2124 | const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu); | |
| 2125 | const field_align = a: { | |
| 2126 | const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: { | |
| 2127 | break :pa try aggregate_ty.abiAlignmentSema(pt); | |
| 2128 | } else parent_ptr_info.flags.alignment; | |
| 2129 | break :a InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(byte_off))); | |
| 2130 | }; | |
| 2131 | const result_ty = try pt.ptrTypeSema(info: { | |
| 2132 | var new = parent_ptr_info; | |
| 2133 | new.child = field_ty.toIntern(); | |
| 2134 | new.flags.alignment = field_align; | |
| 2135 | break :info new; | |
| 2136 | }); | |
| 2137 | return parent_ptr.getOffsetPtr(byte_off, result_ty, pt); | |
| 2138 | }, | |
| 2139 | .@"packed" => { | |
| 2140 | const packed_offset = aggregate_ty.packedStructFieldPtrInfo(parent_ptr_ty, field_idx, pt); | |
| 2141 | const result_ty = try pt.ptrType(info: { | |
| 2142 | var new = parent_ptr_info; | |
| 2143 | new.packed_offset = packed_offset; | |
| 2144 | new.child = field_ty.toIntern(); | |
| 2145 | if (new.flags.alignment == .none) { | |
| 2146 | new.flags.alignment = try aggregate_ty.abiAlignmentSema(pt); | |
| 2147 | } | |
| 2148 | break :info new; | |
| 2149 | }); | |
| 2150 | return pt.getCoerced(parent_ptr, result_ty); | |
| 2151 | }, | |
| 2152 | } | |
| 2153 | }, | |
| 2154 | .@"union" => field: { | |
| 2155 | const union_obj = zcu.typeToUnion(aggregate_ty).?; | |
| 2156 | const field_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[field_idx]); | |
| 2157 | switch (aggregate_ty.containerLayout(zcu)) { | |
| 2158 | .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) }, | |
| 2159 | .@"extern" => { | |
| 2160 | // Point to the same address. | |
| 2161 | const result_ty = try pt.ptrTypeSema(info: { | |
| 2162 | var new = parent_ptr_info; | |
| 2163 | new.child = field_ty.toIntern(); | |
| 2164 | break :info new; | |
| 2165 | }); | |
| 2166 | return pt.getCoerced(parent_ptr, result_ty); | |
| 2167 | }, | |
| 2168 | .@"packed" => { | |
| 2169 | // If the field has an ABI size matching its bit size, then we can continue to use a | |
| 2170 | // non-bit pointer if the parent pointer is also a non-bit pointer. | |
| 2171 | if (parent_ptr_info.packed_offset.host_size == 0 and (try field_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar * 8 == try field_ty.bitSizeSema(pt)) { | |
| 2172 | // We must offset the pointer on big-endian targets, since the bits of packed memory don't align nicely. | |
| 2173 | const byte_offset = switch (zcu.getTarget().cpu.arch.endian()) { | |
| 2174 | .little => 0, | |
| 2175 | .big => (try aggregate_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar - (try field_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar, | |
| 2176 | }; | |
| 2177 | const result_ty = try pt.ptrTypeSema(info: { | |
| 2178 | var new = parent_ptr_info; | |
| 2179 | new.child = field_ty.toIntern(); | |
| 2180 | new.flags.alignment = InternPool.Alignment.fromLog2Units( | |
| 2181 | @ctz(byte_offset | (try parent_ptr_ty.ptrAlignmentSema(pt)).toByteUnits().?), | |
| 2182 | ); | |
| 2183 | break :info new; | |
| 2184 | }); | |
| 2185 | return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt); | |
| 2186 | } else { | |
| 2187 | // The result must be a bit-pointer if it is not already. | |
| 2188 | const result_ty = try pt.ptrTypeSema(info: { | |
| 2189 | var new = parent_ptr_info; | |
| 2190 | new.child = field_ty.toIntern(); | |
| 2191 | if (new.packed_offset.host_size == 0) { | |
| 2192 | new.packed_offset.host_size = @intCast(((try aggregate_ty.bitSizeSema(pt)) + 7) / 8); | |
| 2193 | assert(new.packed_offset.bit_offset == 0); | |
| 2194 | } | |
| 2195 | break :info new; | |
| 2196 | }); | |
| 2197 | return pt.getCoerced(parent_ptr, result_ty); | |
| 2198 | } | |
| 2199 | }, | |
| 2200 | } | |
| 1766 | const field_ptr_ty = try parent_ptr_ty.fieldPtrType(field_idx, pt); | |
| 1767 | ||
| 1768 | switch (aggregate_ty.zigTypeTag(zcu)) { | |
| 1769 | .pointer => assert(aggregate_ty.isSlice(zcu)), | |
| 1770 | .@"struct" => switch (aggregate_ty.containerLayout(zcu)) { | |
| 1771 | .auto => {}, | |
| 1772 | .@"extern" => return parent_ptr.getOffsetPtr( | |
| 1773 | aggregate_ty.structFieldOffset(field_idx, zcu), | |
| 1774 | field_ptr_ty, | |
| 1775 | pt, | |
| 1776 | ), | |
| 1777 | .@"packed" => return pt.getCoerced(parent_ptr, field_ptr_ty), | |
| 2201 | 1778 | }, |
| 2202 | .pointer => field_ty: { | |
| 2203 | assert(aggregate_ty.isSlice(zcu)); | |
| 2204 | break :field_ty switch (field_idx) { | |
| 2205 | Value.slice_ptr_index => .{ aggregate_ty.slicePtrFieldType(zcu), Type.usize.abiAlignment(zcu) }, | |
| 2206 | Value.slice_len_index => .{ Type.usize, Type.usize.abiAlignment(zcu) }, | |
| 2207 | else => unreachable, | |
| 2208 | }; | |
| 1779 | .@"union" => switch (aggregate_ty.containerLayout(zcu)) { | |
| 1780 | .auto => {}, | |
| 1781 | .@"packed", .@"extern" => return pt.getCoerced(parent_ptr, field_ptr_ty), | |
| 2209 | 1782 | }, |
| 2210 | 1783 | else => unreachable, |
| 2211 | }; | |
| 1784 | } | |
| 2212 | 1785 | |
| 2213 | const new_align: InternPool.Alignment = if (parent_ptr_info.flags.alignment != .none) a: { | |
| 2214 | const ty_align = (try field_ty.abiAlignmentInner(.sema, zcu, pt.tid)).scalar; | |
| 2215 | const true_field_align = if (field_align == .none) ty_align else field_align; | |
| 2216 | const new_align = true_field_align.min(parent_ptr_info.flags.alignment); | |
| 2217 | if (new_align == ty_align) break :a .none; | |
| 2218 | break :a new_align; | |
| 2219 | } else field_align; | |
| 2220 | ||
| 2221 | const result_ty = try pt.ptrTypeSema(info: { | |
| 2222 | var new = parent_ptr_info; | |
| 2223 | new.child = field_ty.toIntern(); | |
| 2224 | new.flags.alignment = new_align; | |
| 2225 | break :info new; | |
| 2226 | }); | |
| 1786 | // If we get here, we need to use the `.field` comptime pointer representation, because the | |
| 1787 | // aggregate does not have a well-defined layout. | |
| 2227 | 1788 | |
| 2228 | if (parent_ptr.isUndef(zcu)) return pt.undefValue(result_ty); | |
| 1789 | if (parent_ptr.isUndef(zcu)) return pt.undefValue(field_ptr_ty); | |
| 2229 | 1790 | |
| 2230 | 1791 | const base_ptr = try parent_ptr.canonicalizeBasePtr(.one, aggregate_ty, pt); |
| 2231 | return Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2232 | .ty = result_ty.toIntern(), | |
| 1792 | return .fromInterned(try pt.intern(.{ .ptr = .{ | |
| 1793 | .ty = field_ptr_ty.toIntern(), | |
| 2233 | 1794 | .base_addr = .{ .field = .{ |
| 2234 | 1795 | .base = base_ptr.toIntern(), |
| 2235 | 1796 | .index = field_idx, |
| ... | ... | @@ -2238,9 +1799,9 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { |
| 2238 | 1799 | } })); |
| 2239 | 1800 | } |
| 2240 | 1801 | |
| 2241 | /// `orig_parent_ptr` must be either a single-pointer to an array or vector, or a many-pointer or C-pointer or slice. | |
| 1802 | /// `orig_parent_ptr` must be either a single-pointer to an array, a slice, a many-item pointer, or a C pointer. | |
| 2242 | 1803 | /// Returns a pointer to the element at the specified index. |
| 2243 | /// May perform type resolution. | |
| 1804 | /// Asserts that the layout of the pointer element type is resolved. | |
| 2244 | 1805 | pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value { |
| 2245 | 1806 | const zcu = pt.zcu; |
| 2246 | 1807 | const parent_ptr = switch (orig_parent_ptr.typeOf(zcu).ptrSize(zcu)) { |
| ... | ... | @@ -2249,79 +1810,50 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value |
| 2249 | 1810 | }; |
| 2250 | 1811 | |
| 2251 | 1812 | const parent_ptr_ty = parent_ptr.typeOf(zcu); |
| 2252 | const elem_ty = parent_ptr_ty.childType(zcu); | |
| 2253 | const result_ty = try parent_ptr_ty.elemPtrType(@intCast(field_idx), pt); | |
| 1813 | const result_ty = try parent_ptr_ty.elemPtrType(field_idx, pt); | |
| 1814 | const elem_ty = result_ty.childType(zcu); | |
| 1815 | elem_ty.assertHasLayout(zcu); | |
| 2254 | 1816 | |
| 2255 | 1817 | if (parent_ptr.isUndef(zcu)) return pt.undefValue(result_ty); |
| 2256 | 1818 | |
| 2257 | if (result_ty.ptrInfo(zcu).packed_offset.host_size != 0) { | |
| 2258 | // Since we have a bit-pointer, the pointer address should be unchanged. | |
| 2259 | assert(elem_ty.zigTypeTag(zcu) == .vector); | |
| 2260 | return pt.getCoerced(parent_ptr, result_ty); | |
| 1819 | if (!elem_ty.comptimeOnly(zcu)) { | |
| 1820 | const byte_offset = field_idx * elem_ty.abiSize(zcu); | |
| 1821 | return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt); | |
| 2261 | 1822 | } |
| 2262 | 1823 | |
| 2263 | const PtrStrat = union(enum) { | |
| 2264 | offset: u64, | |
| 2265 | elem_ptr: Type, // many-ptr elem ty | |
| 2266 | }; | |
| 2267 | ||
| 2268 | const strat: PtrStrat = switch (parent_ptr_ty.ptrSize(zcu)) { | |
| 2269 | .one => switch (elem_ty.zigTypeTag(zcu)) { | |
| 2270 | .vector => .{ .offset = field_idx * @divExact(try elem_ty.childType(zcu).bitSizeSema(pt), 8) }, | |
| 2271 | .array => strat: { | |
| 2272 | const arr_elem_ty = elem_ty.childType(zcu); | |
| 2273 | if (try arr_elem_ty.comptimeOnlySema(pt)) { | |
| 2274 | break :strat .{ .elem_ptr = arr_elem_ty }; | |
| 2275 | } | |
| 2276 | break :strat .{ .offset = field_idx * (try arr_elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar }; | |
| 2277 | }, | |
| 2278 | else => unreachable, | |
| 2279 | }, | |
| 1824 | // Comptime-only element type. | |
| 2280 | 1825 | |
| 2281 | .many, .c => if (try elem_ty.comptimeOnlySema(pt)) | |
| 2282 | .{ .elem_ptr = elem_ty } | |
| 2283 | else | |
| 2284 | .{ .offset = field_idx * (try elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar }, | |
| 2285 | ||
| 2286 | .slice => unreachable, | |
| 2287 | }; | |
| 1826 | if (field_idx == 0) { | |
| 1827 | return pt.getCoerced(parent_ptr, result_ty); | |
| 1828 | } | |
| 2288 | 1829 | |
| 2289 | switch (strat) { | |
| 2290 | .offset => |byte_offset| { | |
| 2291 | return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt); | |
| 2292 | }, | |
| 2293 | .elem_ptr => |manyptr_elem_ty| if (field_idx == 0) { | |
| 2294 | return pt.getCoerced(parent_ptr, result_ty); | |
| 2295 | } else { | |
| 2296 | const arr_base_ty, const arr_base_len = manyptr_elem_ty.arrayBase(zcu); | |
| 2297 | const base_idx = arr_base_len * field_idx; | |
| 2298 | const parent_info = zcu.intern_pool.indexToKey(parent_ptr.toIntern()).ptr; | |
| 2299 | switch (parent_info.base_addr) { | |
| 2300 | .arr_elem => |arr_elem| { | |
| 2301 | if (Value.fromInterned(arr_elem.base).typeOf(zcu).childType(zcu).toIntern() == arr_base_ty.toIntern()) { | |
| 2302 | // We already have a pointer to an element of an array of this type. | |
| 2303 | // Just modify the index. | |
| 2304 | return Value.fromInterned(try pt.intern(.{ .ptr = ptr: { | |
| 2305 | var new = parent_info; | |
| 2306 | new.base_addr.arr_elem.index += base_idx; | |
| 2307 | new.ty = result_ty.toIntern(); | |
| 2308 | break :ptr new; | |
| 2309 | } })); | |
| 2310 | } | |
| 2311 | }, | |
| 2312 | else => {}, | |
| 1830 | const arr_base_ty, const arr_base_len = elem_ty.arrayBase(zcu); | |
| 1831 | const base_idx = arr_base_len * field_idx; | |
| 1832 | const parent_info = zcu.intern_pool.indexToKey(parent_ptr.toIntern()).ptr; | |
| 1833 | switch (parent_info.base_addr) { | |
| 1834 | .arr_elem => |arr_elem| { | |
| 1835 | if (Value.fromInterned(arr_elem.base).typeOf(zcu).childType(zcu).toIntern() == arr_base_ty.toIntern()) { | |
| 1836 | // We already have a pointer to an element of an array of this type. | |
| 1837 | // Just modify the index. | |
| 1838 | return .fromInterned(try pt.intern(.{ .ptr = ptr: { | |
| 1839 | var new = parent_info; | |
| 1840 | new.base_addr.arr_elem.index += base_idx; | |
| 1841 | new.ty = result_ty.toIntern(); | |
| 1842 | break :ptr new; | |
| 1843 | } })); | |
| 2313 | 1844 | } |
| 2314 | const base_ptr = try parent_ptr.canonicalizeBasePtr(.many, arr_base_ty, pt); | |
| 2315 | return Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2316 | .ty = result_ty.toIntern(), | |
| 2317 | .base_addr = .{ .arr_elem = .{ | |
| 2318 | .base = base_ptr.toIntern(), | |
| 2319 | .index = base_idx, | |
| 2320 | } }, | |
| 2321 | .byte_offset = 0, | |
| 2322 | } })); | |
| 2323 | 1845 | }, |
| 1846 | else => {}, | |
| 2324 | 1847 | } |
| 1848 | const base_ptr = try parent_ptr.canonicalizeBasePtr(.many, arr_base_ty, pt); | |
| 1849 | return .fromInterned(try pt.intern(.{ .ptr = .{ | |
| 1850 | .ty = result_ty.toIntern(), | |
| 1851 | .base_addr = .{ .arr_elem = .{ | |
| 1852 | .base = base_ptr.toIntern(), | |
| 1853 | .index = base_idx, | |
| 1854 | } }, | |
| 1855 | .byte_offset = 0, | |
| 1856 | } })); | |
| 2325 | 1857 | } |
| 2326 | 1858 | |
| 2327 | 1859 | fn canonicalizeBasePtr(base_ptr: Value, want_size: std.builtin.Type.Pointer.Size, want_child: Type, pt: Zcu.PerThread) !Value { |
| ... | ... | @@ -2417,19 +1949,11 @@ pub const PointerDeriveStep = union(enum) { |
| 2417 | 1949 | } |
| 2418 | 1950 | }; |
| 2419 | 1951 | |
| 2420 | pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread) Allocator.Error!PointerDeriveStep { | |
| 2421 | return ptr_val.pointerDerivationAdvanced(arena, pt, false, null) catch |err| switch (err) { | |
| 2422 | error.OutOfMemory => |e| return e, | |
| 2423 | error.Canceled => @panic("TODO"), // pls remove from error set mlugg | |
| 2424 | error.AnalysisFail => unreachable, | |
| 2425 | }; | |
| 2426 | } | |
| 2427 | ||
| 2428 | 1952 | /// Given a pointer value, get the sequence of steps to derive it, ideally by taking |
| 2429 | 1953 | /// only field and element pointers with no casts. This can be used by codegen backends |
| 2430 | 1954 | /// which prefer field/elem accesses when lowering constant pointer values. |
| 2431 | 1955 | /// It is also used by the Value printing logic for pointers. |
| 2432 | pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, comptime resolve_types: bool, opt_sema: ?*Sema) !PointerDeriveStep { | |
| 1956 | pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, opt_sema: ?*Sema) Allocator.Error!PointerDeriveStep { | |
| 2433 | 1957 | const zcu = pt.zcu; |
| 2434 | 1958 | const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr; |
| 2435 | 1959 | const base_derive: PointerDeriveStep = switch (ptr.base_addr) { |
| ... | ... | @@ -2454,7 +1978,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2454 | 1978 | .comptime_alloc => |idx| base: { |
| 2455 | 1979 | const sema = opt_sema.?; |
| 2456 | 1980 | const alloc = sema.getComptimeAlloc(idx); |
| 2457 | const val = try alloc.val.intern(pt, sema.arena); | |
| 1981 | const val = try alloc.val.intern(pt, arena); | |
| 2458 | 1982 | const ty = val.typeOf(zcu); |
| 2459 | 1983 | break :base .{ .comptime_alloc_ptr = .{ |
| 2460 | 1984 | .idx = idx, |
| ... | ... | @@ -2472,7 +1996,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2472 | 1996 | const base_ptr = Value.fromInterned(eu_ptr); |
| 2473 | 1997 | const base_ptr_ty = base_ptr.typeOf(zcu); |
| 2474 | 1998 | const parent_step = try arena.create(PointerDeriveStep); |
| 2475 | parent_step.* = try pointerDerivationAdvanced(Value.fromInterned(eu_ptr), arena, pt, resolve_types, opt_sema); | |
| 1999 | parent_step.* = try pointerDerivation(.fromInterned(eu_ptr), arena, pt, opt_sema); | |
| 2476 | 2000 | break :base .{ .eu_payload_ptr = .{ |
| 2477 | 2001 | .parent = parent_step, |
| 2478 | 2002 | .result_ptr_ty = try pt.adjustPtrTypeChild(base_ptr_ty, base_ptr_ty.childType(zcu).errorUnionPayload(zcu)), |
| ... | ... | @@ -2482,7 +2006,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2482 | 2006 | const base_ptr = Value.fromInterned(opt_ptr); |
| 2483 | 2007 | const base_ptr_ty = base_ptr.typeOf(zcu); |
| 2484 | 2008 | const parent_step = try arena.create(PointerDeriveStep); |
| 2485 | parent_step.* = try pointerDerivationAdvanced(Value.fromInterned(opt_ptr), arena, pt, resolve_types, opt_sema); | |
| 2009 | parent_step.* = try pointerDerivation(.fromInterned(opt_ptr), arena, pt, opt_sema); | |
| 2486 | 2010 | break :base .{ .opt_payload_ptr = .{ |
| 2487 | 2011 | .parent = parent_step, |
| 2488 | 2012 | .result_ptr_ty = try pt.adjustPtrTypeChild(base_ptr_ty, base_ptr_ty.childType(zcu).optionalChild(zcu)), |
| ... | ... | @@ -2490,59 +2014,32 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2490 | 2014 | }, |
| 2491 | 2015 | .field => |field| base: { |
| 2492 | 2016 | const base_ptr = Value.fromInterned(field.base); |
| 2493 | const base_ptr_ty = base_ptr.typeOf(zcu); | |
| 2494 | const agg_ty = base_ptr_ty.childType(zcu); | |
| 2495 | const field_ty, const field_align = switch (agg_ty.zigTypeTag(zcu)) { | |
| 2496 | .@"struct" => .{ agg_ty.fieldType(@intCast(field.index), zcu), try agg_ty.fieldAlignmentInner( | |
| 2497 | @intCast(field.index), | |
| 2498 | if (resolve_types) .sema else .normal, | |
| 2499 | pt.zcu, | |
| 2500 | if (resolve_types) pt.tid else {}, | |
| 2501 | ) }, | |
| 2502 | .@"union" => .{ agg_ty.unionFieldTypeByIndex(@intCast(field.index), zcu), try agg_ty.fieldAlignmentInner( | |
| 2503 | @intCast(field.index), | |
| 2504 | if (resolve_types) .sema else .normal, | |
| 2505 | pt.zcu, | |
| 2506 | if (resolve_types) pt.tid else {}, | |
| 2507 | ) }, | |
| 2508 | .pointer => .{ switch (field.index) { | |
| 2509 | Value.slice_ptr_index => agg_ty.slicePtrFieldType(zcu), | |
| 2510 | Value.slice_len_index => Type.usize, | |
| 2511 | else => unreachable, | |
| 2512 | }, Type.usize.abiAlignment(zcu) }, | |
| 2513 | else => unreachable, | |
| 2514 | }; | |
| 2515 | const base_align = base_ptr_ty.ptrAlignment(zcu); | |
| 2516 | const result_align = field_align.minStrict(base_align); | |
| 2517 | const result_ty = try pt.ptrType(.{ | |
| 2518 | .child = field_ty.toIntern(), | |
| 2519 | .flags = flags: { | |
| 2520 | var flags = base_ptr_ty.ptrInfo(zcu).flags; | |
| 2521 | if (result_align == field_ty.abiAlignment(zcu)) { | |
| 2522 | flags.alignment = .none; | |
| 2523 | } else { | |
| 2524 | flags.alignment = result_align; | |
| 2525 | } | |
| 2526 | break :flags flags; | |
| 2527 | }, | |
| 2017 | const base_ptr_ty = try pt.ptrType(info: { | |
| 2018 | var info = base_ptr.typeOf(zcu).ptrInfo(zcu); | |
| 2019 | info.flags.size = .one; | |
| 2020 | break :info info; | |
| 2528 | 2021 | }); |
| 2529 | 2022 | const parent_step = try arena.create(PointerDeriveStep); |
| 2530 | parent_step.* = try pointerDerivationAdvanced(base_ptr, arena, pt, resolve_types, opt_sema); | |
| 2023 | parent_step.* = try pointerDerivation(base_ptr, arena, pt, opt_sema); | |
| 2531 | 2024 | break :base .{ .field_ptr = .{ |
| 2532 | 2025 | .parent = parent_step, |
| 2533 | 2026 | .field_idx = @intCast(field.index), |
| 2534 | .result_ptr_ty = result_ty, | |
| 2027 | .result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field.index), pt), | |
| 2535 | 2028 | } }; |
| 2536 | 2029 | }, |
| 2537 | 2030 | .arr_elem => |arr_elem| base: { |
| 2538 | 2031 | const parent_step = try arena.create(PointerDeriveStep); |
| 2539 | parent_step.* = try pointerDerivationAdvanced(Value.fromInterned(arr_elem.base), arena, pt, resolve_types, opt_sema); | |
| 2032 | parent_step.* = try pointerDerivation(.fromInterned(arr_elem.base), arena, pt, opt_sema); | |
| 2540 | 2033 | const parent_ptr_info = (try parent_step.ptrType(pt)).ptrInfo(zcu); |
| 2541 | 2034 | const result_ptr_ty = try pt.ptrType(.{ |
| 2542 | 2035 | .child = parent_ptr_info.child, |
| 2543 | 2036 | .flags = flags: { |
| 2544 | 2037 | var flags = parent_ptr_info.flags; |
| 2545 | 2038 | flags.size = .one; |
| 2039 | if (flags.alignment != .none) flags.alignment = .minStrict( | |
| 2040 | flags.alignment, | |
| 2041 | Type.fromInterned(parent_ptr_info.child).abiAlignment(zcu), | |
| 2042 | ); | |
| 2546 | 2043 | break :flags flags; |
| 2547 | 2044 | }, |
| 2548 | 2045 | }); |
| ... | ... | @@ -2560,7 +2057,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2560 | 2057 | |
| 2561 | 2058 | const ptr_ty_info = Type.fromInterned(ptr.ty).ptrInfo(zcu); |
| 2562 | 2059 | const need_child: Type = .fromInterned(ptr_ty_info.child); |
| 2563 | if (need_child.comptimeOnly(zcu)) { | |
| 2060 | if (need_child.comptimeOnly(zcu) or need_child.zigTypeTag(zcu) == .@"opaque") { | |
| 2564 | 2061 | // No refinement can happen - this pointer is presumably invalid. |
| 2565 | 2062 | // Just offset it. |
| 2566 | 2063 | const parent = try arena.create(PointerDeriveStep); |
| ... | ... | @@ -2662,27 +2159,17 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2662 | 2159 | const start_off = cur_ty.structFieldOffset(field_idx, zcu); |
| 2663 | 2160 | const end_off = start_off + field_ty.abiSize(zcu); |
| 2664 | 2161 | if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { |
| 2665 | const old_ptr_ty = try cur_derive.ptrType(pt); | |
| 2666 | const parent_align = old_ptr_ty.ptrAlignment(zcu); | |
| 2667 | const field_align = InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(start_off))); | |
| 2162 | const base_ptr_ty = try pt.ptrType(info: { | |
| 2163 | var info = (try cur_derive.ptrType(pt)).ptrInfo(zcu); | |
| 2164 | info.flags.size = .one; | |
| 2165 | break :info info; | |
| 2166 | }); | |
| 2668 | 2167 | const parent = try arena.create(PointerDeriveStep); |
| 2669 | 2168 | parent.* = cur_derive; |
| 2670 | const new_ptr_ty = try pt.ptrType(.{ | |
| 2671 | .child = field_ty.toIntern(), | |
| 2672 | .flags = flags: { | |
| 2673 | var flags = old_ptr_ty.ptrInfo(zcu).flags; | |
| 2674 | if (field_align == field_ty.abiAlignment(zcu)) { | |
| 2675 | flags.alignment = .none; | |
| 2676 | } else { | |
| 2677 | flags.alignment = field_align; | |
| 2678 | } | |
| 2679 | break :flags flags; | |
| 2680 | }, | |
| 2681 | }); | |
| 2682 | 2169 | cur_derive = .{ .field_ptr = .{ |
| 2683 | 2170 | .parent = parent, |
| 2684 | 2171 | .field_idx = @intCast(field_idx), |
| 2685 | .result_ptr_ty = new_ptr_ty, | |
| 2172 | .result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field_idx), pt), | |
| 2686 | 2173 | } }; |
| 2687 | 2174 | cur_offset -= start_off; |
| 2688 | 2175 | break; |
| ... | ... | @@ -2720,148 +2207,6 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh |
| 2720 | 2207 | } }; |
| 2721 | 2208 | } |
| 2722 | 2209 | |
| 2723 | pub fn resolveLazy( | |
| 2724 | val: Value, | |
| 2725 | arena: Allocator, | |
| 2726 | pt: Zcu.PerThread, | |
| 2727 | ) Zcu.SemaError!Value { | |
| 2728 | switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 2729 | .int => |int| switch (int.storage) { | |
| 2730 | .u64, .i64, .big_int => return val, | |
| 2731 | .lazy_align, .lazy_size => return pt.intValue( | |
| 2732 | Type.fromInterned(int.ty), | |
| 2733 | try val.toUnsignedIntSema(pt), | |
| 2734 | ), | |
| 2735 | }, | |
| 2736 | .slice => |slice| { | |
| 2737 | const ptr = try Value.fromInterned(slice.ptr).resolveLazy(arena, pt); | |
| 2738 | const len = try Value.fromInterned(slice.len).resolveLazy(arena, pt); | |
| 2739 | if (ptr.toIntern() == slice.ptr and len.toIntern() == slice.len) return val; | |
| 2740 | return Value.fromInterned(try pt.intern(.{ .slice = .{ | |
| 2741 | .ty = slice.ty, | |
| 2742 | .ptr = ptr.toIntern(), | |
| 2743 | .len = len.toIntern(), | |
| 2744 | } })); | |
| 2745 | }, | |
| 2746 | .ptr => |ptr| { | |
| 2747 | switch (ptr.base_addr) { | |
| 2748 | .nav, .comptime_alloc, .uav, .int => return val, | |
| 2749 | .comptime_field => |field_val| { | |
| 2750 | const resolved_field_val = (try Value.fromInterned(field_val).resolveLazy(arena, pt)).toIntern(); | |
| 2751 | return if (resolved_field_val == field_val) | |
| 2752 | val | |
| 2753 | else | |
| 2754 | Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2755 | .ty = ptr.ty, | |
| 2756 | .base_addr = .{ .comptime_field = resolved_field_val }, | |
| 2757 | .byte_offset = ptr.byte_offset, | |
| 2758 | } })); | |
| 2759 | }, | |
| 2760 | .eu_payload, .opt_payload => |base| { | |
| 2761 | const resolved_base = (try Value.fromInterned(base).resolveLazy(arena, pt)).toIntern(); | |
| 2762 | return if (resolved_base == base) | |
| 2763 | val | |
| 2764 | else | |
| 2765 | Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2766 | .ty = ptr.ty, | |
| 2767 | .base_addr = switch (ptr.base_addr) { | |
| 2768 | .eu_payload => .{ .eu_payload = resolved_base }, | |
| 2769 | .opt_payload => .{ .opt_payload = resolved_base }, | |
| 2770 | else => unreachable, | |
| 2771 | }, | |
| 2772 | .byte_offset = ptr.byte_offset, | |
| 2773 | } })); | |
| 2774 | }, | |
| 2775 | .arr_elem, .field => |base_index| { | |
| 2776 | const resolved_base = (try Value.fromInterned(base_index.base).resolveLazy(arena, pt)).toIntern(); | |
| 2777 | return if (resolved_base == base_index.base) | |
| 2778 | val | |
| 2779 | else | |
| 2780 | Value.fromInterned(try pt.intern(.{ .ptr = .{ | |
| 2781 | .ty = ptr.ty, | |
| 2782 | .base_addr = switch (ptr.base_addr) { | |
| 2783 | .arr_elem => .{ .arr_elem = .{ | |
| 2784 | .base = resolved_base, | |
| 2785 | .index = base_index.index, | |
| 2786 | } }, | |
| 2787 | .field => .{ .field = .{ | |
| 2788 | .base = resolved_base, | |
| 2789 | .index = base_index.index, | |
| 2790 | } }, | |
| 2791 | else => unreachable, | |
| 2792 | }, | |
| 2793 | .byte_offset = ptr.byte_offset, | |
| 2794 | } })); | |
| 2795 | }, | |
| 2796 | } | |
| 2797 | }, | |
| 2798 | .aggregate => |aggregate| switch (aggregate.storage) { | |
| 2799 | .bytes => return val, | |
| 2800 | .elems => |elems| { | |
| 2801 | var resolved_elems: []InternPool.Index = &.{}; | |
| 2802 | for (elems, 0..) |elem, i| { | |
| 2803 | const resolved_elem = (try Value.fromInterned(elem).resolveLazy(arena, pt)).toIntern(); | |
| 2804 | if (resolved_elems.len == 0 and resolved_elem != elem) { | |
| 2805 | resolved_elems = try arena.alloc(InternPool.Index, elems.len); | |
| 2806 | @memcpy(resolved_elems[0..i], elems[0..i]); | |
| 2807 | } | |
| 2808 | if (resolved_elems.len > 0) resolved_elems[i] = resolved_elem; | |
| 2809 | } | |
| 2810 | return if (resolved_elems.len == 0) | |
| 2811 | val | |
| 2812 | else | |
| 2813 | pt.aggregateValue(.fromInterned(aggregate.ty), resolved_elems); | |
| 2814 | }, | |
| 2815 | .repeated_elem => |elem| { | |
| 2816 | const resolved_elem = try Value.fromInterned(elem).resolveLazy(arena, pt); | |
| 2817 | return if (resolved_elem.toIntern() == elem) | |
| 2818 | val | |
| 2819 | else | |
| 2820 | pt.aggregateSplatValue(.fromInterned(aggregate.ty), resolved_elem); | |
| 2821 | }, | |
| 2822 | }, | |
| 2823 | .un => |un| { | |
| 2824 | const resolved_tag = if (un.tag == .none) | |
| 2825 | .none | |
| 2826 | else | |
| 2827 | (try Value.fromInterned(un.tag).resolveLazy(arena, pt)).toIntern(); | |
| 2828 | const resolved_val = (try Value.fromInterned(un.val).resolveLazy(arena, pt)).toIntern(); | |
| 2829 | return if (resolved_tag == un.tag and resolved_val == un.val) | |
| 2830 | val | |
| 2831 | else | |
| 2832 | Value.fromInterned(try pt.internUnion(.{ | |
| 2833 | .ty = un.ty, | |
| 2834 | .tag = resolved_tag, | |
| 2835 | .val = resolved_val, | |
| 2836 | })); | |
| 2837 | }, | |
| 2838 | .error_union => |eu| switch (eu.val) { | |
| 2839 | .err_name => return val, | |
| 2840 | .payload => |payload| { | |
| 2841 | const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt); | |
| 2842 | if (resolved_payload.toIntern() == payload) return val; | |
| 2843 | return .fromInterned(try pt.intern(.{ .error_union = .{ | |
| 2844 | .ty = eu.ty, | |
| 2845 | .val = .{ .payload = resolved_payload.toIntern() }, | |
| 2846 | } })); | |
| 2847 | }, | |
| 2848 | }, | |
| 2849 | .opt => |opt| switch (opt.val) { | |
| 2850 | .none => return val, | |
| 2851 | else => |payload| { | |
| 2852 | const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt); | |
| 2853 | if (resolved_payload.toIntern() == payload) return val; | |
| 2854 | return .fromInterned(try pt.intern(.{ .opt = .{ | |
| 2855 | .ty = opt.ty, | |
| 2856 | .val = resolved_payload.toIntern(), | |
| 2857 | } })); | |
| 2858 | }, | |
| 2859 | }, | |
| 2860 | ||
| 2861 | else => return val, | |
| 2862 | } | |
| 2863 | } | |
| 2864 | ||
| 2865 | 2210 | const InterpretMode = enum { |
| 2866 | 2211 | /// In this mode, types are assumed to match what the compiler was built with in terms of field |
| 2867 | 2212 | /// order, field types, etc. This improves compiler performance. However, it means that certain |
| ... | ... | @@ -2878,7 +2223,6 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio |
| 2878 | 2223 | |
| 2879 | 2224 | /// Given a `Value` representing a comptime-known value of type `T`, unwrap it into an actual `T` known to the compiler. |
| 2880 | 2225 | /// This is useful for accessing `std.builtin` structures received from comptime logic. |
| 2881 | /// `val` must be fully resolved. | |
| 2882 | 2226 | pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T { |
| 2883 | 2227 | const zcu = pt.zcu; |
| 2884 | 2228 | const io = zcu.comp.io; |
| ... | ... | @@ -2917,7 +2261,6 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe |
| 2917 | 2261 | }, |
| 2918 | 2262 | |
| 2919 | 2263 | .int => switch (ip.indexToKey(val.toIntern()).int.storage) { |
| 2920 | .lazy_align, .lazy_size => unreachable, // `val` is fully resolved | |
| 2921 | 2264 | inline .u64, .i64 => |x| std.math.cast(T, x) orelse return error.TypeMismatch, |
| 2922 | 2265 | .big_int => |big| big.toInt(T) catch return error.TypeMismatch, |
| 2923 | 2266 | }, |
| ... | ... | @@ -2949,7 +2292,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe |
| 2949 | 2292 | inline else => |tag_comptime| @unionInit( |
| 2950 | 2293 | T, |
| 2951 | 2294 | @tagName(tag_comptime), |
| 2952 | try val.unionValue(zcu).interpret(@FieldType(T, @tagName(tag_comptime)), pt), | |
| 2295 | try val.unionPayload(zcu).interpret(@FieldType(T, @tagName(tag_comptime)), pt), | |
| 2953 | 2296 | ), |
| 2954 | 2297 | }; |
| 2955 | 2298 | }, |
| ... | ... | @@ -3076,7 +2419,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory |
| 3076 | 2419 | } |
| 3077 | 2420 | for (field_vals, 0..) |*field_val, field_idx| { |
| 3078 | 2421 | if (field_val.* == .none) { |
| 3079 | const default_init = struct_obj.field_inits.get(ip)[field_idx]; | |
| 2422 | const default_init = struct_obj.field_defaults.get(ip)[field_idx]; | |
| 3080 | 2423 | if (default_init == .none) return error.TypeMismatch; |
| 3081 | 2424 | field_val.* = default_init; |
| 3082 | 2425 | } |
| ... | ... | @@ -3092,8 +2435,8 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory |
| 3092 | 2435 | pub fn doPointersOverlap(ptr_val_a: Value, ptr_val_b: Value, elem_count: u64, zcu: *const Zcu) bool { |
| 3093 | 2436 | const ip = &zcu.intern_pool; |
| 3094 | 2437 | |
| 3095 | const a_elem_ty = ptr_val_a.typeOf(zcu).indexablePtrElem(zcu); | |
| 3096 | const b_elem_ty = ptr_val_b.typeOf(zcu).indexablePtrElem(zcu); | |
| 2438 | const a_elem_ty = ptr_val_a.typeOf(zcu).indexableElem(zcu); | |
| 2439 | const b_elem_ty = ptr_val_b.typeOf(zcu).indexableElem(zcu); | |
| 3097 | 2440 | |
| 3098 | 2441 | const a_ptr = ip.indexToKey(ptr_val_a.toIntern()).ptr; |
| 3099 | 2442 | const b_ptr = ip.indexToKey(ptr_val_b.toIntern()).ptr; |
| ... | ... | @@ -3179,3 +2522,58 @@ pub fn eqlScalarNum(lhs: Value, rhs: Value, zcu: *Zcu) bool { |
| 3179 | 2522 | const rhs_bigint = rhs.toBigInt(&rhs_bigint_space, zcu); |
| 3180 | 2523 | return lhs_bigint.eql(rhs_bigint); |
| 3181 | 2524 | } |
| 2525 | ||
| 2526 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. | |
| 2527 | /// Vectors are also accepted. Vector results are reduced with AND. | |
| 2528 | /// | |
| 2529 | /// If provided, `vector_index` reports the first element that failed the range check. | |
| 2530 | pub fn intFitsInType( | |
| 2531 | val: Value, | |
| 2532 | ty: Type, | |
| 2533 | vector_index: ?*usize, | |
| 2534 | zcu: *const Zcu, | |
| 2535 | ) bool { | |
| 2536 | if (ty.toIntern() == .comptime_int_type) return true; | |
| 2537 | const info = ty.intInfo(zcu); | |
| 2538 | switch (val.toIntern()) { | |
| 2539 | .zero_usize, .zero_u8 => return true, | |
| 2540 | else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { | |
| 2541 | .undef => return true, | |
| 2542 | .variable, .@"extern", .func, .ptr => { | |
| 2543 | const target = zcu.getTarget(); | |
| 2544 | const ptr_bits = target.ptrBitWidth(); | |
| 2545 | return switch (info.signedness) { | |
| 2546 | .signed => info.bits > ptr_bits, | |
| 2547 | .unsigned => info.bits >= ptr_bits, | |
| 2548 | }; | |
| 2549 | }, | |
| 2550 | .int => |int| { | |
| 2551 | var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; | |
| 2552 | const big_int = int.storage.toBigInt(&buffer); | |
| 2553 | return big_int.fitsInTwosComp(info.signedness, info.bits); | |
| 2554 | }, | |
| 2555 | .aggregate => |aggregate| { | |
| 2556 | assert(ty.zigTypeTag(zcu) == .vector); | |
| 2557 | return switch (aggregate.storage) { | |
| 2558 | .bytes => |bytes| for (bytes.toSlice(ty.vectorLen(zcu), &zcu.intern_pool), 0..) |byte, i| { | |
| 2559 | if (byte == 0) continue; | |
| 2560 | const actual_needed_bits = std.math.log2(byte) + 1 + @intFromBool(info.signedness == .signed); | |
| 2561 | if (info.bits >= actual_needed_bits) continue; | |
| 2562 | if (vector_index) |vi| vi.* = i; | |
| 2563 | break false; | |
| 2564 | } else true, | |
| 2565 | .elems, .repeated_elem => for (switch (aggregate.storage) { | |
| 2566 | .bytes => unreachable, | |
| 2567 | .elems => |elems| elems, | |
| 2568 | .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem), | |
| 2569 | }, 0..) |elem, i| { | |
| 2570 | if (Value.fromInterned(elem).intFitsInType(ty.scalarType(zcu), null, zcu)) continue; | |
| 2571 | if (vector_index) |vi| vi.* = i; | |
| 2572 | break false; | |
| 2573 | } else true, | |
| 2574 | }; | |
| 2575 | }, | |
| 2576 | else => unreachable, | |
| 2577 | }, | |
| 2578 | } | |
| 2579 | } |
src/Zcu.zig+778-370| ... | ... | @@ -14,6 +14,8 @@ const mem = std.mem; |
| 14 | 14 | const Allocator = std.mem.Allocator; |
| 15 | 15 | const assert = std.debug.assert; |
| 16 | 16 | const log = std.log.scoped(.zcu); |
| 17 | const deps_log = std.log.scoped(.zcu_deps); | |
| 18 | const refs_log = std.log.scoped(.zcu_refs); | |
| 17 | 19 | const BigIntConst = std.math.big.int.Const; |
| 18 | 20 | const BigIntMutable = std.math.big.int.Mutable; |
| 19 | 21 | const Target = std.Target; |
| ... | ... | @@ -117,7 +119,7 @@ module_roots: std.AutoArrayHashMapUnmanaged(*Package.Module, File.Index.Optional |
| 117 | 119 | /// |
| 118 | 120 | /// Always accessed through `ImportTableAdapter`, where keys are fully resolved |
| 119 | 121 | /// file paths in order to ensure files are properly deduplicated. This table owns |
| 120 | /// the keys and values. | |
| 122 | /// the keysand values. | |
| 121 | 123 | /// |
| 122 | 124 | /// Protected by Compilation's mutex. |
| 123 | 125 | /// |
| ... | ... | @@ -175,7 +177,9 @@ embed_table: std.ArrayHashMapUnmanaged( |
| 175 | 177 | /// is not yet implemented. |
| 176 | 178 | intern_pool: InternPool = .empty, |
| 177 | 179 | |
| 178 | analysis_in_progress: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, | |
| 180 | /// Value explains why this `AnalUnit` is being analyzed. It is `null` for the topmost analysis | |
| 181 | /// (index 0), and non-`null` for all others. | |
| 182 | analysis_in_progress: std.AutoArrayHashMapUnmanaged(AnalUnit, ?*const DependencyReason) = .empty, | |
| 179 | 183 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. |
| 180 | 184 | failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, *ErrorMsg) = .empty, |
| 181 | 185 | /// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed. |
| ... | ... | @@ -187,6 +191,19 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp |
| 187 | 191 | /// codegen and linking run on a separate thread. |
| 188 | 192 | failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty, |
| 189 | 193 | failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty, |
| 194 | ||
| 195 | /// Key is an `AnalUnit` which is in `dependency_loop_nodes`. For each dependency loop, exactly one | |
| 196 | /// unit in the loop is in this map, though the choice is arbitrary and not necessarily reproducible | |
| 197 | /// between compilations. So, instead of (for instance) defining where the dependency loop "starts", | |
| 198 | /// this map simply exists to allow easily iterating all dependency loops exactly once. | |
| 199 | dependency_loops: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, | |
| 200 | /// Key is an `AnalUnit`, value is the `AnalUnit` which the key references and why it does so. | |
| 201 | /// All units in here form loops. To iterate loops, see `dependency_loops`. | |
| 202 | dependency_loop_nodes: std.AutoArrayHashMapUnmanaged(AnalUnit, struct { | |
| 203 | unit: AnalUnit, | |
| 204 | reason: DependencyReason, | |
| 205 | }) = .empty, | |
| 206 | ||
| 190 | 207 | /// Keep track of `@compileLog`s per `AnalUnit`. |
| 191 | 208 | /// We track the source location of the first `@compileLog` call, and all logged lines as a linked list. |
| 192 | 209 | /// The list is singly linked, but we do track its tail for fast appends (optimizing many logs in one unit). |
| ... | ... | @@ -247,6 +264,10 @@ cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = . |
| 247 | 264 | /// Maximum amount of distinct error values, set by --error-limit |
| 248 | 265 | error_limit: ErrorInt, |
| 249 | 266 | |
| 267 | /// In safe builds, `Type.assertHasLayout` may be called cross-thread, so this lock | |
| 268 | /// guards accesses to `outdated` and `potentially_outdated`. In unsafe builds, the | |
| 269 | /// lock is not needed and is compiled out. | |
| 270 | outdated_lock: if (std.debug.runtime_safety) std.Io.RwLock else void = if (std.debug.runtime_safety) .init, | |
| 250 | 271 | /// Value is the number of PO dependencies of this AnalUnit. |
| 251 | 272 | /// This value will decrease as we perform semantic analysis to learn what is outdated. |
| 252 | 273 | /// If any of these PO deps is outdated, this value will be moved to `outdated`. |
| ... | ... | @@ -254,19 +275,22 @@ potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, |
| 254 | 275 | /// Value is the number of PO dependencies of this AnalUnit. |
| 255 | 276 | /// Once this value drops to 0, the AnalUnit is a candidate for re-analysis. |
| 256 | 277 | outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, |
| 257 | /// This contains all `AnalUnit`s in `outdated` whose PO dependency count is 0. | |
| 278 | /// This is the set of all `AnalUnit`s in `outdated` whose PO dependency count is 0. | |
| 258 | 279 | /// Such `AnalUnit`s are ready for immediate re-analysis. |
| 259 | 280 | /// See `findOutdatedToAnalyze` for details. |
| 260 | outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, | |
| 281 | outdated_ready: struct { | |
| 282 | /// These are separate from other units because it allows `findOutdatedToAnalyze` to prioritize | |
| 283 | /// functions, which is useful because it means they will be sent to codegen more quickly. | |
| 284 | funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 285 | /// Does not contain `.func` units. | |
| 286 | other: std.AutoArrayHashMapUnmanaged(AnalUnit, void), | |
| 287 | } = .{ .funcs = .empty, .other = .empty }, | |
| 261 | 288 | /// This contains a list of AnalUnit whose analysis or codegen failed, but the |
| 262 | 289 | /// failure was something like running out of disk space, and trying again may |
| 263 | 290 | /// succeed. On the next update, we will flush this list, marking all members of |
| 264 | 291 | /// it as outdated. |
| 265 | 292 | retryable_failures: std.ArrayList(AnalUnit) = .empty, |
| 266 | 293 | |
| 267 | func_body_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty, | |
| 268 | nav_val_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty, | |
| 269 | ||
| 270 | 294 | /// These are the modules which we initially queue for analysis in `Compilation.update`. |
| 271 | 295 | /// `resolveReferences` will use these as the root of its reachability traversal. |
| 272 | 296 | analysis_roots_buffer: [5]*Package.Module, |
| ... | ... | @@ -322,6 +346,12 @@ codegen_task_pool: CodegenTaskPool, |
| 322 | 346 | |
| 323 | 347 | generation: u32 = 0, |
| 324 | 348 | |
| 349 | pub const DependencyReason = struct { | |
| 350 | src: LazySrcLoc, | |
| 351 | /// Only populated if this is for a `.type_layout` unit. | |
| 352 | type_layout_reason: Sema.type_resolution.LayoutResolveReason, | |
| 353 | }; | |
| 354 | ||
| 325 | 355 | pub const IncrementalDebugState = struct { |
| 326 | 356 | /// All container types in the ZCU, even dead ones. |
| 327 | 357 | /// Value is the generation the type was created on. |
| ... | ... | @@ -1220,6 +1250,15 @@ pub const ErrorMsg = struct { |
| 1220 | 1250 | notes: []ErrorMsg = &.{}, |
| 1221 | 1251 | reference_trace_root: AnalUnit.Optional = .none, |
| 1222 | 1252 | |
| 1253 | pub fn order(lhs: *const ErrorMsg, rhs: *const ErrorMsg, zcu: *Zcu) std.math.Order { | |
| 1254 | return lhs.src_loc.order(rhs.src_loc, zcu).differ() orelse | |
| 1255 | std.mem.order(u8, lhs.msg, rhs.msg).differ() orelse | |
| 1256 | std.math.order(lhs.notes.len, rhs.notes.len).differ() orelse | |
| 1257 | for (lhs.notes, rhs.notes) |*lhs_note, *rhs_note| { | |
| 1258 | if (order(lhs_note, rhs_note, zcu).differ()) |o| break o; | |
| 1259 | } else .eq; | |
| 1260 | } | |
| 1261 | ||
| 1223 | 1262 | pub fn create( |
| 1224 | 1263 | gpa: Allocator, |
| 1225 | 1264 | src_loc: LazySrcLoc, |
| ... | ... | @@ -1910,40 +1949,6 @@ pub const SrcLoc = struct { |
| 1910 | 1949 | const full = tree.fullPtrType(parent_node).?; |
| 1911 | 1950 | return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?); |
| 1912 | 1951 | }, |
| 1913 | .node_offset_container_tag => |node_off| { | |
| 1914 | const tree = try src_loc.file_scope.getTree(zcu); | |
| 1915 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1916 | ||
| 1917 | switch (tree.nodeTag(parent_node)) { | |
| 1918 | .container_decl_arg, .container_decl_arg_trailing => { | |
| 1919 | const full = tree.containerDeclArg(parent_node); | |
| 1920 | const arg_node = full.ast.arg.unwrap().?; | |
| 1921 | return tree.nodeToSpan(arg_node); | |
| 1922 | }, | |
| 1923 | .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { | |
| 1924 | const full = tree.taggedUnionEnumTag(parent_node); | |
| 1925 | const arg_node = full.ast.arg.unwrap().?; | |
| 1926 | ||
| 1927 | return tree.tokensToSpan( | |
| 1928 | tree.firstToken(arg_node) - 2, | |
| 1929 | tree.lastToken(arg_node) + 1, | |
| 1930 | tree.nodeMainToken(arg_node), | |
| 1931 | ); | |
| 1932 | }, | |
| 1933 | else => unreachable, | |
| 1934 | } | |
| 1935 | }, | |
| 1936 | .node_offset_field_default => |node_off| { | |
| 1937 | const tree = try src_loc.file_scope.getTree(zcu); | |
| 1938 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1939 | ||
| 1940 | const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) { | |
| 1941 | .container_field => tree.containerField(parent_node), | |
| 1942 | .container_field_init => tree.containerFieldInit(parent_node), | |
| 1943 | else => unreachable, | |
| 1944 | }; | |
| 1945 | return tree.nodeToSpan(full.ast.value_expr.unwrap().?); | |
| 1946 | }, | |
| 1947 | 1952 | .node_offset_init_ty => |node_off| { |
| 1948 | 1953 | const tree = try src_loc.file_scope.getTree(zcu); |
| 1949 | 1954 | const parent_node = node_off.toAbsolute(src_loc.base_node); |
| ... | ... | @@ -2019,6 +2024,20 @@ pub const SrcLoc = struct { |
| 2019 | 2024 | } |
| 2020 | 2025 | return tree.nodeToSpan(node); |
| 2021 | 2026 | }, |
| 2027 | .container_arg => { | |
| 2028 | const tree = try src_loc.file_scope.getTree(zcu); | |
| 2029 | const node = src_loc.base_node; | |
| 2030 | var buf: [2]Ast.Node.Index = undefined; | |
| 2031 | if (tree.fullContainerDecl(&buf, node)) |container_decl| { | |
| 2032 | const arg_node = container_decl.ast.arg.unwrap() orelse return tree.nodeToSpan(node); | |
| 2033 | return tree.nodeToSpan(arg_node); | |
| 2034 | } else if (tree.builtinCallParams(&buf, node)) |args| { | |
| 2035 | // Builtin calls (`@Enum` etc) should use the first argument. | |
| 2036 | return tree.nodeToSpan(if (args.len > 0) args[0] else node); | |
| 2037 | } else { | |
| 2038 | return tree.nodeToSpan(node); | |
| 2039 | } | |
| 2040 | }, | |
| 2022 | 2041 | .container_field_name, |
| 2023 | 2042 | .container_field_value, |
| 2024 | 2043 | .container_field_type, |
| ... | ... | @@ -2027,8 +2046,38 @@ pub const SrcLoc = struct { |
| 2027 | 2046 | const tree = try src_loc.file_scope.getTree(zcu); |
| 2028 | 2047 | const node = src_loc.base_node; |
| 2029 | 2048 | var buf: [2]Ast.Node.Index = undefined; |
| 2030 | const container_decl = tree.fullContainerDecl(&buf, node) orelse | |
| 2049 | const container_decl = tree.fullContainerDecl(&buf, node) orelse { | |
| 2050 | // This could be a reification builtin. These are the args we care about: | |
| 2051 | // * `@Enum(_, _, names, values)` | |
| 2052 | // * `@Struct(_, _, names, types, values_and_aligns)` | |
| 2053 | // * `@Union(_, _, names, types, aligns)` | |
| 2054 | if (tree.builtinCallParams(&buf, node)) |args| { | |
| 2055 | const builtin_name = tree.tokenSlice(tree.firstToken(node)); | |
| 2056 | const arg_index: ?u3 = if (std.mem.eql(u8, builtin_name, "@Enum")) switch (src_loc.lazy) { | |
| 2057 | .container_field_name => 2, | |
| 2058 | .container_field_value => 3, | |
| 2059 | .container_field_type => null, | |
| 2060 | .container_field_align => null, | |
| 2061 | else => unreachable, | |
| 2062 | } else if (std.mem.eql(u8, builtin_name, "@Struct")) switch (src_loc.lazy) { | |
| 2063 | .container_field_name => 2, | |
| 2064 | .container_field_value => 4, | |
| 2065 | .container_field_type => 3, | |
| 2066 | .container_field_align => 4, | |
| 2067 | else => unreachable, | |
| 2068 | } else if (std.mem.eql(u8, builtin_name, "@Union")) switch (src_loc.lazy) { | |
| 2069 | .container_field_name => 2, | |
| 2070 | .container_field_value => 4, | |
| 2071 | .container_field_type => 3, | |
| 2072 | .container_field_align => null, | |
| 2073 | else => unreachable, | |
| 2074 | } else null; | |
| 2075 | if (arg_index) |i| { | |
| 2076 | if (args.len >= i) return tree.nodeToSpan(args[i]); | |
| 2077 | } | |
| 2078 | } | |
| 2031 | 2079 | return tree.nodeToSpan(node); |
| 2080 | }; | |
| 2032 | 2081 | |
| 2033 | 2082 | var cur_field_idx: usize = 0; |
| 2034 | 2083 | for (container_decl.ast.members) |member_node| { |
| ... | ... | @@ -2260,7 +2309,11 @@ pub const SrcLoc = struct { |
| 2260 | 2309 | var param_it = full.iterate(tree); |
| 2261 | 2310 | for (0..param_idx) |_| assert(param_it.next() != null); |
| 2262 | 2311 | const param = param_it.next().?; |
| 2263 | return tree.nodeToSpan(param.type_expr.?); | |
| 2312 | if (param.anytype_ellipsis3) |tok| { | |
| 2313 | return tree.tokenToSpan(tok); | |
| 2314 | } else { | |
| 2315 | return tree.nodeToSpan(param.type_expr.?); | |
| 2316 | } | |
| 2264 | 2317 | }, |
| 2265 | 2318 | } |
| 2266 | 2319 | } |
| ... | ... | @@ -2482,10 +2535,6 @@ pub const LazySrcLoc = struct { |
| 2482 | 2535 | node_offset_ptr_bitoffset: Ast.Node.Offset, |
| 2483 | 2536 | /// The source location points to the host size of a pointer. |
| 2484 | 2537 | node_offset_ptr_hostsize: Ast.Node.Offset, |
| 2485 | /// The source location points to the tag type of an union or an enum. | |
| 2486 | node_offset_container_tag: Ast.Node.Offset, | |
| 2487 | /// The source location points to the default value of a field. | |
| 2488 | node_offset_field_default: Ast.Node.Offset, | |
| 2489 | 2538 | /// The source location points to the type of an array or struct initializer. |
| 2490 | 2539 | node_offset_init_ty: Ast.Node.Offset, |
| 2491 | 2540 | /// The source location points to the LHS of an assignment (or assign-op, e.g. `+=`). |
| ... | ... | @@ -2530,6 +2579,11 @@ pub const LazySrcLoc = struct { |
| 2530 | 2579 | fn_proto_param_type: FnProtoParam, |
| 2531 | 2580 | array_cat_lhs: ArrayCat, |
| 2532 | 2581 | array_cat_rhs: ArrayCat, |
| 2582 | /// The source location points to the backing or tag type expression of | |
| 2583 | /// the container type declaration at the base node. | |
| 2584 | /// | |
| 2585 | /// For 'union(enum(T))', this points to 'T', not 'enum(T)'. | |
| 2586 | container_arg, | |
| 2533 | 2587 | /// The source location points to the name of the field at the given index |
| 2534 | 2588 | /// of the container type declaration at the base node. |
| 2535 | 2589 | container_field_name: u32, |
| ... | ... | @@ -2685,10 +2739,10 @@ pub const LazySrcLoc = struct { |
| 2685 | 2739 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_node, |
| 2686 | 2740 | .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_node, |
| 2687 | 2741 | .extended => switch (inst.data.extended.opcode) { |
| 2688 | .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_node, | |
| 2689 | .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node, | |
| 2690 | .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node, | |
| 2691 | .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node, | |
| 2742 | .struct_decl => zir.getStructDecl(zir_inst).src_node, | |
| 2743 | .union_decl => zir.getUnionDecl(zir_inst).src_node, | |
| 2744 | .enum_decl => zir.getEnumDecl(zir_inst).src_node, | |
| 2745 | .opaque_decl => zir.getOpaqueDecl(zir_inst).src_node, | |
| 2692 | 2746 | .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node, |
| 2693 | 2747 | .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node, |
| 2694 | 2748 | .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node, |
| ... | ... | @@ -2715,36 +2769,34 @@ pub const LazySrcLoc = struct { |
| 2715 | 2769 | }; |
| 2716 | 2770 | } |
| 2717 | 2771 | |
| 2718 | /// Used to sort error messages, so that they're printed in a consistent order. | |
| 2719 | /// If an error is returned, a file could not be read in order to resolve a source location. | |
| 2720 | /// In that case, `bad_file_out` is populated, and sorting is impossible. | |
| 2721 | pub fn lessThan(lhs_lazy: LazySrcLoc, rhs_lazy: LazySrcLoc, zcu: *Zcu, bad_file_out: **Zcu.File) File.GetSourceError!bool { | |
| 2722 | const lhs_src = lhs_lazy.upgradeOrLost(zcu) orelse { | |
| 2772 | pub fn order(lhs: LazySrcLoc, rhs: LazySrcLoc, zcu: *Zcu) std.math.Order { | |
| 2773 | const lhs_resolved = lhs.upgradeOrLost(zcu) orelse { | |
| 2723 | 2774 | // LHS source location lost, so should never be referenced. Just sort it to the end. |
| 2724 | return false; | |
| 2775 | return .gt; | |
| 2725 | 2776 | }; |
| 2726 | const rhs_src = rhs_lazy.upgradeOrLost(zcu) orelse { | |
| 2777 | const rhs_resolved = rhs.upgradeOrLost(zcu) orelse { | |
| 2727 | 2778 | // RHS source location lost, so should never be referenced. Just sort it to the end. |
| 2728 | return true; | |
| 2779 | return .lt; | |
| 2729 | 2780 | }; |
| 2730 | if (lhs_src.file_scope != rhs_src.file_scope) { | |
| 2731 | const lhs_path = lhs_src.file_scope.path; | |
| 2732 | const rhs_path = rhs_src.file_scope.path; | |
| 2733 | if (lhs_path.root != rhs_path.root) { | |
| 2734 | return @intFromEnum(lhs_path.root) < @intFromEnum(rhs_path.root); | |
| 2735 | } | |
| 2736 | return std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).compare(.lt); | |
| 2781 | if (lhs_resolved.file_scope != rhs_resolved.file_scope) { | |
| 2782 | const lhs_path = lhs_resolved.file_scope.path; | |
| 2783 | const rhs_path = rhs_resolved.file_scope.path; | |
| 2784 | return std.math.order(@intFromEnum(lhs_path.root), @intFromEnum(rhs_path.root)).differ() orelse | |
| 2785 | std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).differ().?; | |
| 2737 | 2786 | } |
| 2738 | ||
| 2739 | const lhs_span = lhs_src.span(zcu) catch |err| { | |
| 2740 | bad_file_out.* = lhs_src.file_scope; | |
| 2741 | return err; | |
| 2787 | const prev_prot = zcu.comp.io.swapCancelProtection(.blocked); | |
| 2788 | defer _ = zcu.comp.io.swapCancelProtection(prev_prot); | |
| 2789 | const lhs_span = lhs_resolved.span(zcu) catch |err| { | |
| 2790 | assert(err != error.Canceled); // we're protected | |
| 2791 | // Failed to read LHS, so we'll get a transient error. Just sort it to the end. | |
| 2792 | return .gt; | |
| 2742 | 2793 | }; |
| 2743 | const rhs_span = rhs_src.span(zcu) catch |err| { | |
| 2744 | bad_file_out.* = rhs_src.file_scope; | |
| 2745 | return err; | |
| 2794 | const rhs_span = rhs_resolved.span(zcu) catch |err| { | |
| 2795 | assert(err != error.Canceled); // we're protected | |
| 2796 | // Failed to read RHS, so we'll get a transient error. Just sort it to the end. | |
| 2797 | return .lt; | |
| 2746 | 2798 | }; |
| 2747 | return lhs_span.main < rhs_span.main; | |
| 2799 | return std.math.order(lhs_span.main, rhs_span.main); | |
| 2748 | 2800 | } |
| 2749 | 2801 | }; |
| 2750 | 2802 | |
| ... | ... | @@ -2800,6 +2852,8 @@ pub fn deinit(zcu: *Zcu) void { |
| 2800 | 2852 | zcu.analysis_in_progress.deinit(gpa); |
| 2801 | 2853 | zcu.failed_analysis.deinit(gpa); |
| 2802 | 2854 | zcu.transitive_failed_analysis.deinit(gpa); |
| 2855 | zcu.dependency_loops.deinit(gpa); | |
| 2856 | zcu.dependency_loop_nodes.deinit(gpa); | |
| 2803 | 2857 | zcu.failed_codegen.deinit(gpa); |
| 2804 | 2858 | zcu.failed_types.deinit(gpa); |
| 2805 | 2859 | |
| ... | ... | @@ -2830,12 +2884,10 @@ pub fn deinit(zcu: *Zcu) void { |
| 2830 | 2884 | |
| 2831 | 2885 | zcu.potentially_outdated.deinit(gpa); |
| 2832 | 2886 | zcu.outdated.deinit(gpa); |
| 2833 | zcu.outdated_ready.deinit(gpa); | |
| 2887 | zcu.outdated_ready.funcs.deinit(gpa); | |
| 2888 | zcu.outdated_ready.other.deinit(gpa); | |
| 2834 | 2889 | zcu.retryable_failures.deinit(gpa); |
| 2835 | 2890 | |
| 2836 | zcu.func_body_analysis_queued.deinit(gpa); | |
| 2837 | zcu.nav_val_analysis_queued.deinit(gpa); | |
| 2838 | ||
| 2839 | 2891 | zcu.test_functions.deinit(gpa); |
| 2840 | 2892 | |
| 2841 | 2893 | for (zcu.global_assembly.values()) |s| { |
| ... | ... | @@ -3063,18 +3115,24 @@ pub fn markDependeeOutdated( |
| 3063 | 3115 | marked_po: enum { not_marked_po, marked_po }, |
| 3064 | 3116 | dependee: InternPool.Dependee, |
| 3065 | 3117 | ) !void { |
| 3066 | log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3118 | const gpa = zcu.comp.gpa; | |
| 3119 | deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3067 | 3120 | var it = zcu.intern_pool.dependencyIterator(dependee); |
| 3121 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | |
| 3122 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | |
| 3068 | 3123 | while (it.next()) |depender| { |
| 3069 | 3124 | if (zcu.outdated.getPtr(depender)) |po_dep_count| { |
| 3070 | 3125 | switch (marked_po) { |
| 3071 | 3126 | .not_marked_po => {}, |
| 3072 | 3127 | .marked_po => { |
| 3073 | 3128 | po_dep_count.* -= 1; |
| 3074 | log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); | |
| 3129 | deps_log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); | |
| 3075 | 3130 | if (po_dep_count.* == 0) { |
| 3076 | log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3077 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | |
| 3131 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3132 | switch (depender.unwrap()) { | |
| 3133 | .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), | |
| 3134 | else => try zcu.outdated_ready.other.put(gpa, depender, {}), | |
| 3135 | } | |
| 3078 | 3136 | } |
| 3079 | 3137 | }, |
| 3080 | 3138 | } |
| ... | ... | @@ -3090,14 +3148,17 @@ pub fn markDependeeOutdated( |
| 3090 | 3148 | }, |
| 3091 | 3149 | }; |
| 3092 | 3150 | try zcu.outdated.putNoClobber( |
| 3093 | zcu.gpa, | |
| 3151 | gpa, | |
| 3094 | 3152 | depender, |
| 3095 | 3153 | new_po_dep_count, |
| 3096 | 3154 | ); |
| 3097 | log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); | |
| 3155 | deps_log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); | |
| 3098 | 3156 | if (new_po_dep_count == 0) { |
| 3099 | log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3100 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | |
| 3157 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3158 | switch (depender.unwrap()) { | |
| 3159 | .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), | |
| 3160 | else => try zcu.outdated_ready.other.put(gpa, depender, {}), | |
| 3161 | } | |
| 3101 | 3162 | } |
| 3102 | 3163 | // If this is a Decl and was not previously PO, we must recursively |
| 3103 | 3164 | // mark dependencies on its tyval as PO. |
| ... | ... | @@ -3109,17 +3170,27 @@ pub fn markDependeeOutdated( |
| 3109 | 3170 | } |
| 3110 | 3171 | |
| 3111 | 3172 | pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3112 | log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3173 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | |
| 3174 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | |
| 3175 | return markPoDependeeUpToDateInner(zcu, dependee); | |
| 3176 | } | |
| 3177 | /// Assumes that `zcu.outdated_lock` is already held exclusively. | |
| 3178 | fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { | |
| 3179 | const gpa = zcu.comp.gpa; | |
| 3180 | deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3113 | 3181 | var it = zcu.intern_pool.dependencyIterator(dependee); |
| 3114 | 3182 | while (it.next()) |depender| { |
| 3115 | 3183 | if (zcu.outdated.getPtr(depender)) |po_dep_count| { |
| 3116 | 3184 | // This depender is already outdated, but it now has one |
| 3117 | 3185 | // less PO dependency! |
| 3118 | 3186 | po_dep_count.* -= 1; |
| 3119 | log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); | |
| 3187 | deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); | |
| 3120 | 3188 | if (po_dep_count.* == 0) { |
| 3121 | log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3122 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | |
| 3189 | deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); | |
| 3190 | switch (depender.unwrap()) { | |
| 3191 | .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), | |
| 3192 | else => try zcu.outdated_ready.other.put(gpa, depender, {}), | |
| 3193 | } | |
| 3123 | 3194 | } |
| 3124 | 3195 | continue; |
| 3125 | 3196 | } |
| ... | ... | @@ -3132,11 +3203,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3132 | 3203 | }; |
| 3133 | 3204 | if (ptr.* > 1) { |
| 3134 | 3205 | ptr.* -= 1; |
| 3135 | log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* }); | |
| 3206 | deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* }); | |
| 3136 | 3207 | continue; |
| 3137 | 3208 | } |
| 3138 | 3209 | |
| 3139 | log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) }); | |
| 3210 | deps_log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) }); | |
| 3140 | 3211 | |
| 3141 | 3212 | // This dependency is no longer PO, i.e. is known to be up-to-date. |
| 3142 | 3213 | assert(zcu.potentially_outdated.swapRemove(depender)); |
| ... | ... | @@ -3144,139 +3215,120 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3144 | 3215 | // as no longer PO. |
| 3145 | 3216 | switch (depender.unwrap()) { |
| 3146 | 3217 | .@"comptime" => {}, |
| 3147 | .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }), | |
| 3148 | .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }), | |
| 3149 | .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }), | |
| 3150 | .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }), | |
| 3151 | .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }), | |
| 3218 | .nav_val => |nav| try zcu.markPoDependeeUpToDateInner(.{ .nav_val = nav }), | |
| 3219 | .nav_ty => |nav| try zcu.markPoDependeeUpToDateInner(.{ .nav_ty = nav }), | |
| 3220 | .type_layout => |ty| try zcu.markPoDependeeUpToDateInner(.{ .type_layout = ty }), | |
| 3221 | .struct_defaults => |ty| try zcu.markPoDependeeUpToDateInner(.{ .struct_defaults = ty }), | |
| 3222 | .func => |func| try zcu.markPoDependeeUpToDateInner(.{ .func_ies = func }), | |
| 3223 | .memoized_state => |stage| try zcu.markPoDependeeUpToDateInner(.{ .memoized_state = stage }), | |
| 3152 | 3224 | } |
| 3153 | 3225 | } |
| 3154 | 3226 | } |
| 3155 | 3227 | |
| 3156 | 3228 | /// Given a AnalUnit which is newly outdated or PO, mark all AnalUnits which may |
| 3157 | 3229 | /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. |
| 3158 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { | |
| 3230 | /// | |
| 3231 | /// Assumes that `zcu.outdated_lock` is already held exclusively. | |
| 3232 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) Allocator.Error!void { | |
| 3233 | const gpa = zcu.comp.gpa; | |
| 3159 | 3234 | const ip = &zcu.intern_pool; |
| 3160 | 3235 | const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) { |
| 3161 | 3236 | .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies |
| 3162 | 3237 | .nav_val => |nav| .{ .nav_val = nav }, |
| 3163 | 3238 | .nav_ty => |nav| .{ .nav_ty = nav }, |
| 3164 | .type => |ty| .{ .interned = ty }, | |
| 3165 | .func => |func_index| .{ .interned = func_index }, // IES | |
| 3239 | .type_layout => |ty| .{ .type_layout = ty }, | |
| 3240 | .struct_defaults => |ty| .{ .struct_defaults = ty }, | |
| 3241 | .func => |func_index| .{ .func_ies = func_index }, | |
| 3166 | 3242 | .memoized_state => |stage| .{ .memoized_state = stage }, |
| 3167 | 3243 | }; |
| 3168 | log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3244 | deps_log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); | |
| 3169 | 3245 | var it = ip.dependencyIterator(dependee); |
| 3170 | 3246 | while (it.next()) |po| { |
| 3171 | 3247 | if (zcu.outdated.getPtr(po)) |po_dep_count| { |
| 3172 | // This dependency is already outdated, but it now has one more PO | |
| 3173 | // dependency. | |
| 3248 | // This dependency is already outdated, but it now has one more PO dependency. | |
| 3174 | 3249 | if (po_dep_count.* == 0) { |
| 3175 | _ = zcu.outdated_ready.swapRemove(po); | |
| 3250 | switch (po.unwrap()) { | |
| 3251 | .func => |func| _ = zcu.outdated_ready.funcs.swapRemove(func), | |
| 3252 | else => _ = zcu.outdated_ready.other.swapRemove(po), | |
| 3253 | } | |
| 3176 | 3254 | } |
| 3177 | 3255 | po_dep_count.* += 1; |
| 3178 | log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); | |
| 3256 | deps_log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); | |
| 3179 | 3257 | continue; |
| 3180 | 3258 | } |
| 3181 | 3259 | if (zcu.potentially_outdated.getPtr(po)) |n| { |
| 3182 | 3260 | // There is now one more PO dependency. |
| 3183 | 3261 | n.* += 1; |
| 3184 | log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); | |
| 3262 | deps_log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); | |
| 3185 | 3263 | continue; |
| 3186 | 3264 | } |
| 3187 | try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1); | |
| 3188 | log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); | |
| 3265 | try zcu.potentially_outdated.putNoClobber(gpa, po, 1); | |
| 3266 | deps_log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); | |
| 3189 | 3267 | // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO. |
| 3190 | 3268 | try zcu.markTransitiveDependersPotentiallyOutdated(po); |
| 3191 | 3269 | } |
| 3192 | 3270 | } |
| 3193 | 3271 | |
| 3272 | /// Selects an outdated `AnalUnit` to analyze next. Called from the main semantic analysis loop when | |
| 3273 | /// there is no work immediately queued. The unit is chosen such that it is unlikely to require any | |
| 3274 | /// recursive analysis (all of its previously-marked dependencies are already up-to-date), because | |
| 3275 | /// recursive analysis can cause over-analysis on incremental updates. | |
| 3194 | 3276 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 3195 | if (!zcu.comp.config.incremental) return null; | |
| 3196 | ||
| 3197 | if (zcu.outdated.count() == 0) { | |
| 3198 | // Any units in `potentially_outdated` must just be stuck in loops with one another: none of those | |
| 3199 | // units have had any outdated dependencies so far, and all of their remaining PO deps are triggered | |
| 3200 | // by other units in `potentially_outdated`. So, we can safety assume those units up-to-date. | |
| 3201 | zcu.potentially_outdated.clearRetainingCapacity(); | |
| 3202 | log.debug("findOutdatedToAnalyze: no outdated depender", .{}); | |
| 3203 | return null; | |
| 3277 | // We prioritize functions, because the sooner they get analyzed, the sooner they can be send to | |
| 3278 | // the codegen backend and linker, which are usually running in parallel (so this can increase | |
| 3279 | // parallelism). | |
| 3280 | // TODO: perhaps we should also experiment with *avoiding* functions if the codegen/link queue | |
| 3281 | // is backed up (for instance due to a very large function). That could help minimize blocking | |
| 3282 | // on the main thread in `CodegenTaskPool.start` waiting for the linker to catch up. | |
| 3283 | if (zcu.outdated_ready.funcs.count() > 0) { | |
| 3284 | const unit: AnalUnit = .wrap(.{ .func = zcu.outdated_ready.funcs.keys()[0] }); | |
| 3285 | log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); | |
| 3286 | return unit; | |
| 3204 | 3287 | } |
| 3205 | 3288 | |
| 3206 | // Our goal is to find an outdated AnalUnit which itself has no outdated or | |
| 3207 | // PO dependencies. Most of the time, such an AnalUnit will exist - we track | |
| 3208 | // them in the `outdated_ready` set for efficiency. However, this is not | |
| 3209 | // necessarily the case, since the Decl dependency graph may contain loops | |
| 3210 | // via mutually recursive definitions: | |
| 3211 | // pub const A = struct { b: *B }; | |
| 3212 | // pub const B = struct { b: *A }; | |
| 3213 | // In this case, we must defer to more complex logic below. | |
| 3214 | ||
| 3215 | if (zcu.outdated_ready.count() > 0) { | |
| 3216 | const unit = zcu.outdated_ready.keys()[0]; | |
| 3217 | log.debug("findOutdatedToAnalyze: trivial {f}", .{zcu.fmtAnalUnit(unit)}); | |
| 3289 | if (zcu.outdated_ready.other.count() > 0) { | |
| 3290 | const unit = zcu.outdated_ready.other.keys()[0]; | |
| 3291 | log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); | |
| 3218 | 3292 | return unit; |
| 3219 | 3293 | } |
| 3220 | 3294 | |
| 3221 | // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some | |
| 3222 | // AnalUnit with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of | |
| 3223 | // A or B. We should definitely not select a function, since a function can't be responsible for the | |
| 3224 | // loop (IES dependencies can't have loops). We should also, of course, not select a `comptime` | |
| 3225 | // declaration, since you can't depend on those! | |
| 3226 | ||
| 3227 | // The choice of this unit could have a big impact on how much total analysis we perform, since | |
| 3228 | // if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit | |
| 3229 | // may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a unit | |
| 3230 | // which the most things depend on - the idea is that this will resolve a lot of loops (but this | |
| 3231 | // is only a heuristic). | |
| 3232 | ||
| 3233 | log.debug("findOutdatedToAnalyze: no trivial ready, using heuristic; {d} outdated, {d} PO", .{ | |
| 3234 | zcu.outdated.count(), | |
| 3235 | zcu.potentially_outdated.count(), | |
| 3236 | }); | |
| 3237 | ||
| 3238 | const ip = &zcu.intern_pool; | |
| 3295 | // Usually, getting here means that everything is up-to-date, so there is no more work to do. We | |
| 3296 | // will see that `zcu.outdated` and `zcu.potentially_outdated` are both empty. | |
| 3297 | // | |
| 3298 | // However, if a previous update had a dependency loop compile error, there is a cycle in the | |
| 3299 | // dependency graph (which is usually acyclic), which can cause a scenario where no unit appears | |
| 3300 | // to be ready, because they're all waiting for the next in the loop to be up-to-date. In that | |
| 3301 | // case, we usually have to just bite the bullet and analyze one of them. An exception is if | |
| 3302 | // `zcu.outdated` is empty but `zcu.potentially_outdated` is non-empty: in that case, the only | |
| 3303 | // possible situation is a cycle where everything is actually up-to-date, so we can clear out | |
| 3304 | // `zcu.potentially_outdated` and we are done. | |
| 3239 | 3305 | |
| 3240 | var chosen_unit: ?AnalUnit = null; | |
| 3241 | var chosen_unit_dependers: u32 = undefined; | |
| 3242 | ||
| 3243 | inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| { | |
| 3244 | for (outdated_units) |unit| { | |
| 3245 | var n: u32 = 0; | |
| 3246 | var it = ip.dependencyIterator(switch (unit.unwrap()) { | |
| 3247 | .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice | |
| 3248 | .@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice | |
| 3249 | .type => |ty| .{ .interned = ty }, | |
| 3250 | .nav_val => |nav| .{ .nav_val = nav }, | |
| 3251 | .nav_ty => |nav| .{ .nav_ty = nav }, | |
| 3252 | .memoized_state => { | |
| 3253 | // If we've hit a loop and some `.memoized_state` is outdated, we should make that choice eagerly. | |
| 3254 | // In general, it's good to resolve this early on, since -- for instance -- almost every function | |
| 3255 | // references the panic handler. | |
| 3256 | return unit; | |
| 3257 | }, | |
| 3258 | }); | |
| 3259 | while (it.next()) |_| n += 1; | |
| 3306 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | |
| 3307 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | |
| 3260 | 3308 | |
| 3261 | if (chosen_unit == null or n > chosen_unit_dependers) { | |
| 3262 | chosen_unit = unit; | |
| 3263 | chosen_unit_dependers = n; | |
| 3264 | } | |
| 3265 | } | |
| 3309 | if (zcu.outdated.count() == 0) { | |
| 3310 | // Everything is up-to-date. There could be lingering entries in `zcu.potentially_outdated` | |
| 3311 | // from a dependency loop on a previous update. | |
| 3312 | zcu.potentially_outdated.clearRetainingCapacity(); | |
| 3313 | log.debug("findOutdatedToAnalyze: all up-to-date", .{}); | |
| 3314 | return null; | |
| 3266 | 3315 | } |
| 3267 | 3316 | |
| 3268 | log.debug("findOutdatedToAnalyze: heuristic returned '{f}' ({d} dependers)", .{ | |
| 3269 | zcu.fmtAnalUnit(chosen_unit.?), | |
| 3270 | chosen_unit_dependers, | |
| 3317 | const unit = zcu.outdated.keys()[0]; | |
| 3318 | log.debug("findOutdatedToAnalyze: dependency loop affecting {d} units, selected {f}", .{ | |
| 3319 | zcu.outdated.count(), | |
| 3320 | zcu.fmtAnalUnit(unit), | |
| 3271 | 3321 | }); |
| 3272 | ||
| 3273 | return chosen_unit.?; | |
| 3322 | return unit; | |
| 3274 | 3323 | } |
| 3275 | 3324 | |
| 3276 | 3325 | /// During an incremental update, before semantic analysis, call this to flush all values from |
| 3277 | 3326 | /// `retryable_failures` and mark them as outdated so they get re-analyzed. |
| 3278 | 3327 | pub fn flushRetryableFailures(zcu: *Zcu) !void { |
| 3279 | const gpa = zcu.gpa; | |
| 3328 | const comp = zcu.comp; | |
| 3329 | const gpa = comp.gpa; | |
| 3330 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(comp.io); | |
| 3331 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(comp.io); | |
| 3280 | 3332 | for (zcu.retryable_failures.items) |depender| { |
| 3281 | 3333 | if (zcu.outdated.contains(depender)) continue; |
| 3282 | 3334 | if (zcu.potentially_outdated.fetchSwapRemove(depender)) |kv| { |
| ... | ... | @@ -3350,12 +3402,59 @@ pub fn mapOldZirToNew( |
| 3350 | 3402 | } |
| 3351 | 3403 | |
| 3352 | 3404 | while (match_stack.pop()) |match_item| { |
| 3353 | // First, a check: if the number of captures of this type has changed, we can't map it, because | |
| 3354 | // we wouldn't know how to correlate type information with the last update. | |
| 3355 | // Synchronizes with logic in `Zcu.PerThread.recreateStructType` etc. | |
| 3356 | if (old_zir.typeCapturesLen(match_item.old_inst) != new_zir.typeCapturesLen(match_item.new_inst)) { | |
| 3357 | // Don't map this type or anything within it. | |
| 3358 | continue; | |
| 3405 | // There are some properties of type declarations which cannot change across incremental | |
| 3406 | // updates. If they have, we need to ignore this mapping. These properties are essentially | |
| 3407 | // everything passed into `InternPool.getDeclaredStructType` (likewise for unions, enums, | |
| 3408 | // and opaques). | |
| 3409 | const old_tag = old_zir.instructions.items(.data)[@intFromEnum(match_item.old_inst)].extended.opcode; | |
| 3410 | const new_tag = new_zir.instructions.items(.data)[@intFromEnum(match_item.new_inst)].extended.opcode; | |
| 3411 | if (old_tag != new_tag) continue; | |
| 3412 | switch (old_tag) { | |
| 3413 | .struct_decl => { | |
| 3414 | const old = old_zir.getStructDecl(match_item.old_inst); | |
| 3415 | const new = new_zir.getStructDecl(match_item.new_inst); | |
| 3416 | if (old.captures.len != new.captures.len) continue; | |
| 3417 | if (old.field_names.len != new.field_names.len) continue; | |
| 3418 | if (old.layout != new.layout) continue; | |
| 3419 | const old_any_field_aligns = old.field_align_body_lens != null; | |
| 3420 | const old_any_field_defaults = old.field_default_body_lens != null; | |
| 3421 | const old_any_comptime_fields = old.field_comptime_bits != null; | |
| 3422 | const old_explicit_backing_int = old.backing_int_type_body != null; | |
| 3423 | const new_any_field_aligns = new.field_align_body_lens != null; | |
| 3424 | const new_any_field_defaults = new.field_default_body_lens != null; | |
| 3425 | const new_any_comptime_fields = new.field_comptime_bits != null; | |
| 3426 | const new_explicit_backing_int = new.backing_int_type_body != null; | |
| 3427 | if (old_any_field_aligns != new_any_field_aligns) continue; | |
| 3428 | if (old_any_field_defaults != new_any_field_defaults) continue; | |
| 3429 | if (old_any_comptime_fields != new_any_comptime_fields) continue; | |
| 3430 | if (old_explicit_backing_int != new_explicit_backing_int) continue; | |
| 3431 | }, | |
| 3432 | .union_decl => { | |
| 3433 | const old = old_zir.getUnionDecl(match_item.old_inst); | |
| 3434 | const new = new_zir.getUnionDecl(match_item.new_inst); | |
| 3435 | if (old.captures.len != new.captures.len) continue; | |
| 3436 | if (old.field_names.len != new.field_names.len) continue; | |
| 3437 | if (old.kind != new.kind) continue; | |
| 3438 | const old_any_field_aligns = old.field_align_body_lens != null; | |
| 3439 | const new_any_field_aligns = new.field_align_body_lens != null; | |
| 3440 | if (old_any_field_aligns != new_any_field_aligns) continue; | |
| 3441 | }, | |
| 3442 | .enum_decl => { | |
| 3443 | const old = old_zir.getEnumDecl(match_item.old_inst); | |
| 3444 | const new = new_zir.getEnumDecl(match_item.new_inst); | |
| 3445 | if (old.captures.len != new.captures.len) continue; | |
| 3446 | if (old.field_names.len != new.field_names.len) continue; | |
| 3447 | if (old.nonexhaustive != new.nonexhaustive) continue; | |
| 3448 | const old_explicit_tag_type = old.tag_type_body != null; | |
| 3449 | const new_explicit_tag_type = new.tag_type_body != null; | |
| 3450 | if (old_explicit_tag_type != new_explicit_tag_type) continue; | |
| 3451 | }, | |
| 3452 | .opaque_decl => { | |
| 3453 | const old = old_zir.getOpaqueDecl(match_item.old_inst); | |
| 3454 | const new = new_zir.getOpaqueDecl(match_item.new_inst); | |
| 3455 | if (old.captures.len != new.captures.len) continue; | |
| 3456 | }, | |
| 3457 | else => unreachable, | |
| 3359 | 3458 | } |
| 3360 | 3459 | |
| 3361 | 3460 | // Match the namespace declaration itself |
| ... | ... | @@ -3377,25 +3476,21 @@ pub fn mapOldZirToNew( |
| 3377 | 3476 | var comptime_decls: std.ArrayList(Zir.Inst.Index) = .empty; |
| 3378 | 3477 | defer comptime_decls.deinit(gpa); |
| 3379 | 3478 | |
| 3380 | { | |
| 3381 | var old_decl_it = old_zir.declIterator(match_item.old_inst); | |
| 3382 | while (old_decl_it.next()) |old_decl_inst| { | |
| 3383 | const old_decl = old_zir.getDeclaration(old_decl_inst); | |
| 3384 | switch (old_decl.kind) { | |
| 3385 | .@"comptime" => try comptime_decls.append(gpa, old_decl_inst), | |
| 3386 | .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst), | |
| 3387 | .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), | |
| 3388 | .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), | |
| 3389 | .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), | |
| 3390 | } | |
| 3479 | for (old_zir.typeDecls(match_item.old_inst)) |old_decl_inst| { | |
| 3480 | const old_decl = old_zir.getDeclaration(old_decl_inst); | |
| 3481 | switch (old_decl.kind) { | |
| 3482 | .@"comptime" => try comptime_decls.append(gpa, old_decl_inst), | |
| 3483 | .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst), | |
| 3484 | .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), | |
| 3485 | .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), | |
| 3486 | .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), | |
| 3391 | 3487 | } |
| 3392 | 3488 | } |
| 3393 | 3489 | |
| 3394 | 3490 | var unnamed_test_idx: u32 = 0; |
| 3395 | 3491 | var comptime_decl_idx: u32 = 0; |
| 3396 | 3492 | |
| 3397 | var new_decl_it = new_zir.declIterator(match_item.new_inst); | |
| 3398 | while (new_decl_it.next()) |new_decl_inst| { | |
| 3493 | for (new_zir.typeDecls(match_item.new_inst)) |new_decl_inst| { | |
| 3399 | 3494 | const new_decl = new_zir.getDeclaration(new_decl_inst); |
| 3400 | 3495 | // Attempt to match this to a declaration in the old ZIR: |
| 3401 | 3496 | // * For named declarations (`const`/`var`/`fn`), we match based on name. |
| ... | ... | @@ -3474,47 +3569,93 @@ pub fn mapOldZirToNew( |
| 3474 | 3569 | /// The caller is responsible for ensuring the function decl itself is already |
| 3475 | 3570 | /// analyzed, and for ensuring it can exist at runtime (see |
| 3476 | 3571 | /// `Type.fnHasRuntimeBitsSema`). This function does *not* guarantee that the body |
| 3477 | /// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`. | |
| 3478 | pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !void { | |
| 3572 | /// will be analyzed when it returns: for that, see `PerThread.ensureFuncBodyUpToDate`. | |
| 3573 | pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { | |
| 3574 | const comp = zcu.comp; | |
| 3575 | const gpa = comp.gpa; | |
| 3576 | const io = comp.io; | |
| 3479 | 3577 | const ip = &zcu.intern_pool; |
| 3578 | assert(func == ip.unwrapCoercedFunc(func)); // analyze the body of the original function, not a coerced one | |
| 3579 | if (ip.setWantRuntimeFnAnalysis(io, func)) { | |
| 3580 | // This is the first reference to this function, so we must ensure it will be analyzed. | |
| 3581 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | |
| 3582 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | |
| 3583 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | |
| 3584 | try zcu.outdated_ready.funcs.ensureUnusedCapacity(gpa, 1); | |
| 3585 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .func = func }), 0); | |
| 3586 | zcu.outdated_ready.funcs.putAssumeCapacityNoClobber(func, {}); | |
| 3587 | } | |
| 3588 | } | |
| 3480 | 3589 | |
| 3481 | const func = zcu.funcInfo(func_index); | |
| 3482 | ||
| 3483 | assert(func.ty == func.uncoerced_ty); // analyze the body of the original function, not a coerced one | |
| 3590 | pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { | |
| 3591 | const comp = zcu.comp; | |
| 3592 | const gpa = comp.gpa; | |
| 3593 | const io = comp.io; | |
| 3594 | const ip = &zcu.intern_pool; | |
| 3595 | if (ip.setWantNavAnalysis(io, nav)) { | |
| 3596 | // This is the first reference to this function, so we must ensure it will be analyzed. | |
| 3597 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | |
| 3598 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | |
| 3599 | try zcu.outdated.ensureUnusedCapacity(gpa, 2); | |
| 3600 | try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 2); | |
| 3601 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), 0); | |
| 3602 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), 0); | |
| 3603 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); | |
| 3604 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); | |
| 3605 | } | |
| 3606 | } | |
| 3484 | 3607 | |
| 3485 | if (zcu.func_body_analysis_queued.contains(func_index)) return; | |
| 3608 | /// Called when an `InternPool.ComptimeUnit` is first created to mark it as outdated so that it will | |
| 3609 | /// be semantically analyzed. | |
| 3610 | pub fn queueComptimeUnitAnalysis(zcu: *Zcu, cu: InternPool.ComptimeUnit.Id) Allocator.Error!void { | |
| 3611 | const comp = zcu.comp; | |
| 3612 | const gpa = comp.gpa; | |
| 3613 | const io = comp.io; | |
| 3614 | const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); | |
| 3615 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); | |
| 3616 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); | |
| 3617 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | |
| 3618 | try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 1); | |
| 3619 | zcu.outdated.putAssumeCapacityNoClobber(unit, 0); | |
| 3620 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(unit, {}); | |
| 3621 | } | |
| 3486 | 3622 | |
| 3487 | if (func.analysisUnordered(ip).is_analyzed) { | |
| 3488 | if (!zcu.outdated.contains(.wrap(.{ .func = func_index })) and | |
| 3489 | !zcu.potentially_outdated.contains(.wrap(.{ .func = func_index }))) | |
| 3490 | { | |
| 3491 | // This function has been analyzed before and is definitely up-to-date. | |
| 3492 | return; | |
| 3623 | /// If `unit` was marked as outdated or porentially outdated, clears that status and returns `true`. | |
| 3624 | /// Otherwise, returns `false`. | |
| 3625 | pub fn clearOutdatedState(zcu: *Zcu, unit: AnalUnit) bool { | |
| 3626 | const io = zcu.comp.io; | |
| 3627 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); | |
| 3628 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); | |
| 3629 | if (zcu.outdated.fetchSwapRemove(unit)) |kv| { | |
| 3630 | const was_ready = switch (unit.unwrap()) { | |
| 3631 | .func => |func| zcu.outdated_ready.funcs.swapRemove(func), | |
| 3632 | else => zcu.outdated_ready.other.swapRemove(unit), | |
| 3633 | }; | |
| 3634 | if (kv.value == 0) { | |
| 3635 | assert(was_ready); | |
| 3636 | } else { | |
| 3637 | assert(!was_ready); | |
| 3493 | 3638 | } |
| 3639 | return true; | |
| 3640 | } else if (zcu.potentially_outdated.swapRemove(unit)) { | |
| 3641 | return true; | |
| 3642 | } else { | |
| 3643 | return false; | |
| 3494 | 3644 | } |
| 3495 | ||
| 3496 | try zcu.func_body_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1); | |
| 3497 | try zcu.comp.queueJob(.{ .analyze_func = func_index }); | |
| 3498 | zcu.func_body_analysis_queued.putAssumeCapacityNoClobber(func_index, {}); | |
| 3499 | 3645 | } |
| 3500 | 3646 | |
| 3501 | pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void { | |
| 3502 | const ip = &zcu.intern_pool; | |
| 3647 | /// This function takes a `*const Zcu` and `@constCast`s it so that it can be called from functions | |
| 3648 | /// in `Type` which otherwise do not modify the `Zcu`. | |
| 3649 | pub fn assertUpToDate(zcu: *const Zcu, unit: AnalUnit) void { | |
| 3650 | if (!std.debug.runtime_safety) return; | |
| 3503 | 3651 | |
| 3504 | if (zcu.nav_val_analysis_queued.contains(nav_id)) return; | |
| 3652 | const io = zcu.comp.io; | |
| 3505 | 3653 | |
| 3506 | if (ip.getNav(nav_id).status == .fully_resolved) { | |
| 3507 | if (!zcu.outdated.contains(.wrap(.{ .nav_val = nav_id })) and | |
| 3508 | !zcu.potentially_outdated.contains(.wrap(.{ .nav_val = nav_id }))) | |
| 3509 | { | |
| 3510 | // This `Nav` has been analyzed before and is definitely up-to-date. | |
| 3511 | return; | |
| 3512 | } | |
| 3513 | } | |
| 3654 | @constCast(zcu).outdated_lock.lockSharedUncancelable(io); | |
| 3655 | defer @constCast(zcu).outdated_lock.unlockShared(io); | |
| 3514 | 3656 | |
| 3515 | try zcu.nav_val_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1); | |
| 3516 | try zcu.comp.queueJob(.{ .analyze_comptime_unit = .wrap(.{ .nav_val = nav_id }) }); | |
| 3517 | zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {}); | |
| 3657 | assert(!zcu.outdated.contains(unit)); | |
| 3658 | assert(!zcu.potentially_outdated.contains(unit)); | |
| 3518 | 3659 | } |
| 3519 | 3660 | |
| 3520 | 3661 | pub const ImportResult = struct { |
| ... | ... | @@ -3533,56 +3674,83 @@ pub const ImportResult = struct { |
| 3533 | 3674 | module: ?*Package.Module, |
| 3534 | 3675 | }; |
| 3535 | 3676 | |
| 3536 | /// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of | |
| 3537 | /// this `AnalUnit` will cause them to be re-created (or not). | |
| 3538 | pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void { | |
| 3539 | const gpa = zcu.gpa; | |
| 3677 | /// Prepares `unit` for re-analysis by clearing all of the following state: | |
| 3678 | /// * Compile errors associated with `unit` | |
| 3679 | /// * Compile logs associated with `unit` | |
| 3680 | /// * Exports performed by `unit` | |
| 3681 | /// * Dependencies from `unit` on other things | |
| 3682 | /// * References from `unit` to other units | |
| 3683 | /// Delete all references in `reference_table` which are caused by `unit`, and all dependencies it | |
| 3684 | /// has. Called in preparation for re-analysis, which will recreate references and dependencies. | |
| 3685 | /// Re-analysis of the `AnalUnit` will cause appropriate references to be recreated. | |
| 3686 | pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void { | |
| 3687 | const gpa = zcu.comp.gpa; | |
| 3540 | 3688 | |
| 3541 | const exports_base, const exports_len = if (zcu.single_exports.fetchSwapRemove(anal_unit)) |kv| | |
| 3542 | .{ @intFromEnum(kv.value), 1 } | |
| 3543 | else if (zcu.multi_exports.fetchSwapRemove(anal_unit)) |info| | |
| 3544 | .{ info.value.index, info.value.len } | |
| 3545 | else | |
| 3689 | if (!dev.env.supports(.incremental)) { | |
| 3690 | // This is the first time `unit` is being analyzed, so there is no stale data to clear. | |
| 3546 | 3691 | return; |
| 3692 | } | |
| 3547 | 3693 | |
| 3548 | const exports = zcu.all_exports.items[exports_base..][0..exports_len]; | |
| 3694 | // Compile errors | |
| 3695 | if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| { | |
| 3696 | kv.value.destroy(gpa); | |
| 3697 | } else if (zcu.dependency_loop_nodes.swapRemove(unit)) { | |
| 3698 | _ = zcu.dependency_loops.swapRemove(unit); | |
| 3699 | _ = zcu.transitive_failed_analysis.swapRemove(unit); | |
| 3700 | } else { | |
| 3701 | _ = zcu.transitive_failed_analysis.swapRemove(unit); | |
| 3702 | } | |
| 3549 | 3703 | |
| 3550 | // In an only-c build, we're guaranteed to never use incremental compilation, so there are | |
| 3551 | // guaranteed not to be any exports in the output file that need deleting (since we only call | |
| 3552 | // `updateExports` on flush). | |
| 3553 | // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports | |
| 3554 | // within a single update. | |
| 3555 | if (dev.env.supports(.incremental)) { | |
| 3556 | for (exports, exports_base..) |exp, export_index_usize| { | |
| 3557 | const export_idx: Export.Index = @enumFromInt(export_index_usize); | |
| 3704 | // Compile logs | |
| 3705 | if (zcu.compile_logs.fetchSwapRemove(unit)) |kv| { | |
| 3706 | var opt_line_idx = kv.value.first_line.toOptional(); | |
| 3707 | while (opt_line_idx.unwrap()) |line_idx| { | |
| 3708 | zcu.free_compile_log_lines.append(gpa, line_idx) catch { | |
| 3709 | // This space will be reused eventually, so we need not propagate this error. | |
| 3710 | // Just leak it for now, and let GC reclaim it later on. | |
| 3711 | break; | |
| 3712 | }; | |
| 3713 | opt_line_idx = line_idx.get(zcu).next; | |
| 3714 | } | |
| 3715 | } | |
| 3716 | ||
| 3717 | // Exports | |
| 3718 | exports: { | |
| 3719 | const base: u32, const len: u32 = index: { | |
| 3720 | if (zcu.single_exports.fetchSwapRemove(unit)) |kv| { | |
| 3721 | break :index .{ @intFromEnum(kv.value), 1 }; | |
| 3722 | } | |
| 3723 | if (zcu.multi_exports.fetchSwapRemove(unit)) |kv| { | |
| 3724 | break :index .{ kv.value.index, kv.value.len }; | |
| 3725 | } | |
| 3726 | break :exports; | |
| 3727 | }; | |
| 3728 | for (zcu.all_exports.items[base..][0..len], base..) |exp, exp_index_usize| { | |
| 3729 | const exp_index: Export.Index = @enumFromInt(exp_index_usize); | |
| 3558 | 3730 | if (zcu.comp.bin_file) |lf| { |
| 3559 | 3731 | lf.deleteExport(exp.exported, exp.opts.name); |
| 3560 | 3732 | } |
| 3561 | if (zcu.failed_exports.fetchSwapRemove(export_idx)) |failed_kv| { | |
| 3733 | if (zcu.failed_exports.fetchSwapRemove(exp_index)) |failed_kv| { | |
| 3562 | 3734 | failed_kv.value.destroy(gpa); |
| 3563 | 3735 | } |
| 3564 | 3736 | } |
| 3737 | zcu.free_exports.ensureUnusedCapacity(gpa, len) catch { | |
| 3738 | // This space will be reused eventually, so we need not propagate this error. | |
| 3739 | // Just leak it for now, and let GC reclaim it later on. | |
| 3740 | break :exports; | |
| 3741 | }; | |
| 3742 | for (base..base + len) |exp_index| { | |
| 3743 | zcu.free_exports.appendAssumeCapacity(@enumFromInt(exp_index)); | |
| 3744 | } | |
| 3565 | 3745 | } |
| 3566 | 3746 | |
| 3567 | zcu.free_exports.ensureUnusedCapacity(gpa, exports_len) catch { | |
| 3568 | // This space will be reused eventually, so we need not propagate this error. | |
| 3569 | // Just leak it for now, and let GC reclaim it later on. | |
| 3570 | return; | |
| 3571 | }; | |
| 3572 | for (exports_base..exports_base + exports_len) |export_idx| { | |
| 3573 | zcu.free_exports.appendAssumeCapacity(@enumFromInt(export_idx)); | |
| 3574 | } | |
| 3575 | } | |
| 3576 | ||
| 3577 | /// Delete all references in `reference_table` which are caused by this `AnalUnit`. | |
| 3578 | /// Re-analysis of the `AnalUnit` will cause appropriate references to be recreated. | |
| 3579 | pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { | |
| 3580 | const gpa = zcu.gpa; | |
| 3747 | // Dependencies | |
| 3748 | zcu.intern_pool.removeDependenciesForDepender(gpa, unit); | |
| 3581 | 3749 | |
| 3750 | // References | |
| 3582 | 3751 | zcu.clearCachedResolvedReferences(); |
| 3583 | ||
| 3584 | 3752 | unit_refs: { |
| 3585 | const kv = zcu.reference_table.fetchSwapRemove(anal_unit) orelse break :unit_refs; | |
| 3753 | const kv = zcu.reference_table.fetchSwapRemove(unit) orelse break :unit_refs; | |
| 3586 | 3754 | var idx = kv.value; |
| 3587 | 3755 | |
| 3588 | 3756 | while (idx != std.math.maxInt(u32)) { |
| ... | ... | @@ -3610,9 +3778,8 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { |
| 3610 | 3778 | } |
| 3611 | 3779 | } |
| 3612 | 3780 | } |
| 3613 | ||
| 3614 | 3781 | type_refs: { |
| 3615 | const kv = zcu.type_reference_table.fetchSwapRemove(anal_unit) orelse break :type_refs; | |
| 3782 | const kv = zcu.type_reference_table.fetchSwapRemove(unit) orelse break :type_refs; | |
| 3616 | 3783 | var idx = kv.value; |
| 3617 | 3784 | |
| 3618 | 3785 | while (idx != std.math.maxInt(u32)) { |
| ... | ... | @@ -3626,22 +3793,6 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { |
| 3626 | 3793 | } |
| 3627 | 3794 | } |
| 3628 | 3795 | |
| 3629 | /// Delete all compile logs performed by this `AnalUnit`. | |
| 3630 | /// Re-analysis of the `AnalUnit` will cause logs to be rediscovered. | |
| 3631 | pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void { | |
| 3632 | const kv = zcu.compile_logs.fetchSwapRemove(anal_unit) orelse return; | |
| 3633 | const gpa = zcu.gpa; | |
| 3634 | var opt_line_idx = kv.value.first_line.toOptional(); | |
| 3635 | while (opt_line_idx.unwrap()) |line_idx| { | |
| 3636 | zcu.free_compile_log_lines.append(gpa, line_idx) catch { | |
| 3637 | // This space will be reused eventually, so we need not propagate this error. | |
| 3638 | // Just leak it for now, and let GC reclaim it later on. | |
| 3639 | return; | |
| 3640 | }; | |
| 3641 | opt_line_idx = line_idx.get(zcu).next; | |
| 3642 | } | |
| 3643 | } | |
| 3644 | ||
| 3645 | 3796 | pub fn addInlineReferenceFrame(zcu: *Zcu, frame: InlineReferenceFrame) Allocator.Error!Zcu.InlineReferenceFrame.Index { |
| 3646 | 3797 | const frame_idx: InlineReferenceFrame.Index = zcu.free_inline_reference_frames.pop() orelse idx: { |
| 3647 | 3798 | _ = try zcu.inline_reference_frames.addOne(zcu.gpa); |
| ... | ... | @@ -3851,9 +4002,9 @@ pub const AtomicPtrAlignmentDiagnostics = struct { |
| 3851 | 4002 | max_bits: u16 = undefined, |
| 3852 | 4003 | }; |
| 3853 | 4004 | |
| 3854 | /// If ABI alignment of `ty` is OK for atomic operations, returns 0. | |
| 3855 | /// Otherwise returns the alignment required on a pointer for the target | |
| 3856 | /// to perform atomic operations. | |
| 4005 | /// Returns the alignment required for the target to perform atomic operations on type `ty` (that | |
| 4006 | /// is, the required align attribute on the pointer). If the ABI alignment of `ty` is sufficient, | |
| 4007 | /// returns `.none`. | |
| 3857 | 4008 | // TODO this function does not take into account CPU features, which can affect |
| 3858 | 4009 | // this value. Audit this! |
| 3859 | 4010 | pub fn atomicPtrAlignment( |
| ... | ... | @@ -3908,8 +4059,7 @@ pub fn atomicPtrAlignment( |
| 3908 | 4059 | return error.BadType; |
| 3909 | 4060 | } |
| 3910 | 4061 | |
| 3911 | /// Returns null in the following cases: | |
| 3912 | /// * Not a struct. | |
| 4062 | /// Returns null if `ty` is not a struct. | |
| 3913 | 4063 | pub fn typeToStruct(zcu: *const Zcu, ty: Type) ?InternPool.LoadedStructType { |
| 3914 | 4064 | if (ty.ip_index == .none) return null; |
| 3915 | 4065 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -3936,7 +4086,6 @@ pub fn structPackedFieldBitOffset( |
| 3936 | 4086 | ) u16 { |
| 3937 | 4087 | const ip = &zcu.intern_pool; |
| 3938 | 4088 | assert(struct_type.layout == .@"packed"); |
| 3939 | assert(struct_type.haveLayout(ip)); | |
| 3940 | 4089 | var bit_sum: u64 = 0; |
| 3941 | 4090 | for (0..struct_type.field_types.len) |i| { |
| 3942 | 4091 | if (i == field_index) { |
| ... | ... | @@ -3995,8 +4144,10 @@ pub const UnionLayout = struct { |
| 3995 | 4144 | pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionType, enum_tag: Value) ?u32 { |
| 3996 | 4145 | const ip = &zcu.intern_pool; |
| 3997 | 4146 | if (enum_tag.toIntern() == .none) return null; |
| 3998 | assert(ip.typeOf(enum_tag.toIntern()) == loaded_union.enum_tag_ty); | |
| 3999 | return loaded_union.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern()); | |
| 4147 | const enum_tag_key = ip.indexToKey(enum_tag.toIntern()).enum_tag; | |
| 4148 | assert(enum_tag_key.ty == loaded_union.enum_tag_type); | |
| 4149 | const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 4150 | return loaded_enum.tagValueIndex(ip, enum_tag_key.int); | |
| 4000 | 4151 | } |
| 4001 | 4152 | |
| 4002 | 4153 | pub const ResolvedReference = struct { |
| ... | ... | @@ -4012,13 +4163,13 @@ pub const ResolvedReference = struct { |
| 4012 | 4163 | /// If an `AnalUnit` is not in the returned map, it is unreferenced. |
| 4013 | 4164 | /// The returned hashmap is owned by the `Zcu`, so should not be freed by the caller. |
| 4014 | 4165 | /// This hashmap is cached, so repeated calls to this function are cheap. |
| 4015 | pub fn resolveReferences(zcu: *Zcu) !*const std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | |
| 4166 | pub fn resolveReferences(zcu: *Zcu) Allocator.Error!*const std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | |
| 4016 | 4167 | if (zcu.resolved_references == null) { |
| 4017 | 4168 | zcu.resolved_references = try zcu.resolveReferencesInner(); |
| 4018 | 4169 | } |
| 4019 | 4170 | return &zcu.resolved_references.?; |
| 4020 | 4171 | } |
| 4021 | fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | |
| 4172 | fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | |
| 4022 | 4173 | const gpa = zcu.gpa; |
| 4023 | 4174 | const comp = zcu.comp; |
| 4024 | 4175 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -4049,32 +4200,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4049 | 4200 | const referencer = types.values()[type_idx]; |
| 4050 | 4201 | type_idx += 1; |
| 4051 | 4202 | |
| 4052 | log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); | |
| 4053 | ||
| 4054 | // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced. | |
| 4055 | const has_resolution: bool = switch (ip.indexToKey(ty)) { | |
| 4056 | .struct_type, .union_type => true, | |
| 4057 | .enum_type => |k| k != .generated_tag, | |
| 4058 | .opaque_type => false, | |
| 4059 | else => unreachable, | |
| 4060 | }; | |
| 4061 | if (has_resolution) { | |
| 4062 | // this should only be referenced by the type | |
| 4063 | const unit: AnalUnit = .wrap(.{ .type = ty }); | |
| 4064 | try units.putNoClobber(gpa, unit, referencer); | |
| 4065 | } | |
| 4066 | ||
| 4067 | // If this is a union with a generated tag, its tag type is automatically referenced. | |
| 4068 | // We don't add this reference for non-generated tags, as those will already be referenced via the union's type resolution, with a better source location. | |
| 4069 | if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| { | |
| 4070 | const tag_ty = union_obj.enum_tag_ty; | |
| 4071 | if (tag_ty != .none) { | |
| 4072 | if (ip.indexToKey(tag_ty).enum_type == .generated_tag) { | |
| 4073 | const gop = try types.getOrPut(gpa, tag_ty); | |
| 4074 | if (!gop.found_existing) gop.value_ptr.* = referencer; | |
| 4075 | } | |
| 4076 | } | |
| 4077 | } | |
| 4203 | refs_log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); | |
| 4078 | 4204 | |
| 4079 | 4205 | // Queue any decls within this type which would be automatically analyzed. |
| 4080 | 4206 | // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`. |
| ... | ... | @@ -4084,7 +4210,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4084 | 4210 | const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); |
| 4085 | 4211 | const gop = try units.getOrPut(gpa, unit); |
| 4086 | 4212 | if (!gop.found_existing) { |
| 4087 | log.debug("type '{f}': ref comptime %{}", .{ | |
| 4213 | refs_log.debug("type '{f}': ref comptime %{}", .{ | |
| 4088 | 4214 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4089 | 4215 | @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue), |
| 4090 | 4216 | }); |
| ... | ... | @@ -4118,7 +4244,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4118 | 4244 | { |
| 4119 | 4245 | const gop = try units.getOrPut(gpa, .wrap(.{ .nav_val = nav_id })); |
| 4120 | 4246 | if (!gop.found_existing) { |
| 4121 | log.debug("type '{f}': ref test %{}", .{ | |
| 4247 | refs_log.debug("type '{f}': ref test %{}", .{ | |
| 4122 | 4248 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4123 | 4249 | @intFromEnum(inst_info.inst), |
| 4124 | 4250 | }); |
| ... | ... | @@ -4141,7 +4267,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4141 | 4267 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 4142 | 4268 | const gop = try units.getOrPut(gpa, unit); |
| 4143 | 4269 | if (!gop.found_existing) { |
| 4144 | log.debug("type '{f}': ref named %{}", .{ | |
| 4270 | refs_log.debug("type '{f}': ref named %{}", .{ | |
| 4145 | 4271 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4146 | 4272 | @intFromEnum(inst_info.inst), |
| 4147 | 4273 | }); |
| ... | ... | @@ -4158,7 +4284,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4158 | 4284 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 4159 | 4285 | const gop = try units.getOrPut(gpa, unit); |
| 4160 | 4286 | if (!gop.found_existing) { |
| 4161 | log.debug("type '{f}': ref named %{}", .{ | |
| 4287 | refs_log.debug("type '{f}': ref named %{}", .{ | |
| 4162 | 4288 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), |
| 4163 | 4289 | @intFromEnum(inst_info.inst), |
| 4164 | 4290 | }); |
| ... | ... | @@ -4173,18 +4299,25 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4173 | 4299 | unit_idx += 1; |
| 4174 | 4300 | |
| 4175 | 4301 | // `nav_val` and `nav_ty` reference each other *implicitly* to save memory. |
| 4302 | // Likewise for `type_layout` and `struct_defaults` of a struct type. | |
| 4176 | 4303 | queue_paired: { |
| 4177 | 4304 | const other: AnalUnit = .wrap(switch (unit.unwrap()) { |
| 4178 | 4305 | .nav_val => |n| .{ .nav_ty = n }, |
| 4179 | 4306 | .nav_ty => |n| .{ .nav_val = n }, |
| 4180 | .@"comptime", .type, .func, .memoized_state => break :queue_paired, | |
| 4307 | .struct_defaults => |ty| .{ .type_layout = ty }, | |
| 4308 | .type_layout => |ty| switch (ip.indexToKey(ty)) { | |
| 4309 | .struct_type => .{ .struct_defaults = ty }, | |
| 4310 | .union_type, .enum_type, .opaque_type => break :queue_paired, | |
| 4311 | else => unreachable, | |
| 4312 | }, | |
| 4313 | .@"comptime", .func, .memoized_state => break :queue_paired, | |
| 4181 | 4314 | }); |
| 4182 | 4315 | const gop = try units.getOrPut(gpa, other); |
| 4183 | 4316 | if (gop.found_existing) break :queue_paired; |
| 4184 | gop.value_ptr.* = units.values()[unit_idx]; // same reference location | |
| 4317 | gop.value_ptr.* = units.values()[unit_idx - 1]; // same reference location | |
| 4185 | 4318 | } |
| 4186 | 4319 | |
| 4187 | log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); | |
| 4320 | refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); | |
| 4188 | 4321 | |
| 4189 | 4322 | if (zcu.reference_table.get(unit)) |first_ref_idx| { |
| 4190 | 4323 | assert(first_ref_idx != std.math.maxInt(u32)); |
| ... | ... | @@ -4193,7 +4326,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4193 | 4326 | const ref = zcu.all_references.items[ref_idx]; |
| 4194 | 4327 | const gop = try units.getOrPut(gpa, ref.referenced); |
| 4195 | 4328 | if (!gop.found_existing) { |
| 4196 | log.debug("unit '{f}': ref unit '{f}'", .{ | |
| 4329 | refs_log.debug("unit '{f}': ref unit '{f}'", .{ | |
| 4197 | 4330 | zcu.fmtAnalUnit(unit), |
| 4198 | 4331 | zcu.fmtAnalUnit(ref.referenced), |
| 4199 | 4332 | }); |
| ... | ... | @@ -4213,7 +4346,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R |
| 4213 | 4346 | const ref = zcu.all_type_references.items[ref_idx]; |
| 4214 | 4347 | const gop = try types.getOrPut(gpa, ref.referenced); |
| 4215 | 4348 | if (!gop.found_existing) { |
| 4216 | log.debug("unit '{f}': ref type '{f}'", .{ | |
| 4349 | refs_log.debug("unit '{f}': ref type '{f}'", .{ | |
| 4217 | 4350 | zcu.fmtAnalUnit(unit), |
| 4218 | 4351 | Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip), |
| 4219 | 4352 | }); |
| ... | ... | @@ -4298,6 +4431,16 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File { |
| 4298 | 4431 | return zcu.fileByIndex(zcu.navFileScopeIndex(nav)); |
| 4299 | 4432 | } |
| 4300 | 4433 | |
| 4434 | pub fn navAlignment(zcu: *Zcu, nav_index: InternPool.Nav.Index) InternPool.Alignment { | |
| 4435 | const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) { | |
| 4436 | .unresolved => unreachable, | |
| 4437 | .type_resolved => |r| .{ .fromInterned(r.type), r.alignment }, | |
| 4438 | .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment }, | |
| 4439 | }; | |
| 4440 | if (alignment != .none) return alignment; | |
| 4441 | return ty.abiAlignment(zcu); | |
| 4442 | } | |
| 4443 | ||
| 4301 | 4444 | pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Alt(FormatAnalUnit, formatAnalUnit) { |
| 4302 | 4445 | return .{ .data = .{ .unit = unit, .zcu = zcu } }; |
| 4303 | 4446 | } |
| ... | ... | @@ -4305,11 +4448,7 @@ pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Alt(FormatDependee |
| 4305 | 4448 | return .{ .data = .{ .dependee = d, .zcu = zcu } }; |
| 4306 | 4449 | } |
| 4307 | 4450 | |
| 4308 | const FormatAnalUnit = struct { | |
| 4309 | unit: AnalUnit, | |
| 4310 | zcu: *Zcu, | |
| 4311 | }; | |
| 4312 | ||
| 4451 | const FormatAnalUnit = struct { unit: AnalUnit, zcu: *const Zcu }; | |
| 4313 | 4452 | fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void { |
| 4314 | 4453 | const zcu = data.zcu; |
| 4315 | 4454 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -4323,9 +4462,8 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void |
| 4323 | 4462 | return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)}); |
| 4324 | 4463 | } |
| 4325 | 4464 | }, |
| 4326 | .nav_val => |nav| return writer.print("nav_val('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), | |
| 4327 | .nav_ty => |nav| return writer.print("nav_ty('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), | |
| 4328 | .type => |ty| return writer.print("ty('{f}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), | |
| 4465 | .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), | |
| 4466 | .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), | |
| 4329 | 4467 | .func => |func| { |
| 4330 | 4468 | const nav = zcu.funcInfo(func).owner_nav; |
| 4331 | 4469 | return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); |
| ... | ... | @@ -4334,8 +4472,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void |
| 4334 | 4472 | } |
| 4335 | 4473 | } |
| 4336 | 4474 | |
| 4337 | const FormatDependee = struct { dependee: InternPool.Dependee, zcu: *Zcu }; | |
| 4338 | ||
| 4475 | const FormatDependee = struct { dependee: InternPool.Dependee, zcu: *const Zcu }; | |
| 4339 | 4476 | fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void { |
| 4340 | 4477 | const zcu = data.zcu; |
| 4341 | 4478 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -4347,18 +4484,17 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void |
| 4347 | 4484 | const file_path = zcu.fileByIndex(info.file).path; |
| 4348 | 4485 | return writer.print("inst('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) }); |
| 4349 | 4486 | }, |
| 4350 | .nav_val => |nav| { | |
| 4487 | .nav_val, .nav_ty => |nav, tag| { | |
| 4351 | 4488 | const fqn = ip.getNav(nav).fqn; |
| 4352 | return writer.print("nav_val('{f}')", .{fqn.fmt(ip)}); | |
| 4489 | return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); | |
| 4353 | 4490 | }, |
| 4354 | .nav_ty => |nav| { | |
| 4355 | const fqn = ip.getNav(nav).fqn; | |
| 4356 | return writer.print("nav_ty('{f}')", .{fqn.fmt(ip)}); | |
| 4491 | .type_layout, .struct_defaults => |ip_index, tag| { | |
| 4492 | const name = Type.fromInterned(ip_index).containerTypeName(ip); | |
| 4493 | return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) }); | |
| 4357 | 4494 | }, |
| 4358 | .interned => |ip_index| switch (ip.indexToKey(ip_index)) { | |
| 4359 | .struct_type, .union_type, .enum_type => return writer.print("type('{f}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}), | |
| 4360 | .func => |f| return writer.print("ies('{f}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), | |
| 4361 | else => unreachable, | |
| 4495 | .func_ies => |ip_index| { | |
| 4496 | const fqn = ip.getNav(ip.indexToKey(ip_index).func.owner_nav).fqn; | |
| 4497 | return writer.print("func_ies('{f}')", .{fqn.fmt(ip)}); | |
| 4362 | 4498 | }, |
| 4363 | 4499 | .zon_file => |file| { |
| 4364 | 4500 | const file_path = zcu.fileByIndex(file).path; |
| ... | ... | @@ -4386,32 +4522,6 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void |
| 4386 | 4522 | } |
| 4387 | 4523 | } |
| 4388 | 4524 | |
| 4389 | /// Given the `InternPool.Index` of a function, set its resolved IES to `.none` if it | |
| 4390 | /// may be outdated. `Sema` should do this before ever loading a resolved IES. | |
| 4391 | pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void { | |
| 4392 | const unit = AnalUnit.wrap(.{ .func = func_index }); | |
| 4393 | if (zcu.outdated.contains(unit) or zcu.potentially_outdated.contains(unit)) { | |
| 4394 | // We're consulting the resolved IES now, but the function is outdated, so its | |
| 4395 | // IES may have changed. We have to assume the IES is outdated and set the resolved | |
| 4396 | // set back to `.none`. | |
| 4397 | // | |
| 4398 | // This will cause `PerThread.analyzeFnBody` to mark the IES as outdated when it's | |
| 4399 | // eventually hit. | |
| 4400 | // | |
| 4401 | // Since the IES needs to be resolved, the function body will now definitely need | |
| 4402 | // re-analysis (even if the IES turns out to be the same!), so mark it as | |
| 4403 | // definitely-outdated if it's only PO. | |
| 4404 | if (zcu.potentially_outdated.fetchSwapRemove(unit)) |kv| { | |
| 4405 | const gpa = zcu.gpa; | |
| 4406 | try zcu.outdated.putNoClobber(gpa, unit, kv.value); | |
| 4407 | if (kv.value == 0) { | |
| 4408 | try zcu.outdated_ready.put(gpa, unit, {}); | |
| 4409 | } | |
| 4410 | } | |
| 4411 | zcu.intern_pool.funcSetIesResolved(zcu.comp.io, func_index, .none); | |
| 4412 | } | |
| 4413 | } | |
| 4414 | ||
| 4415 | 4525 | pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enum) { |
| 4416 | 4526 | ok, |
| 4417 | 4527 | bad_arch: []const std.Target.Cpu.Arch, // value is allowed archs for cc |
| ... | ... | @@ -4747,6 +4857,304 @@ fn explainWhyFileIsInModule( |
| 4747 | 4857 | } |
| 4748 | 4858 | } |
| 4749 | 4859 | |
| 4860 | pub fn addDependencyLoopErrors(zcu: *Zcu, eb: *std.zig.ErrorBundle.Wip) Allocator.Error!void { | |
| 4861 | const gpa = zcu.comp.gpa; | |
| 4862 | ||
| 4863 | const all_references = try zcu.resolveReferences(); | |
| 4864 | ||
| 4865 | var units: std.ArrayList(AnalUnit) = .empty; | |
| 4866 | defer units.deinit(gpa); | |
| 4867 | ||
| 4868 | // TODO: sort the dependency loops somehow to make the error bundle reproducible | |
| 4869 | for (zcu.dependency_loops.keys()) |arbitrary_unit| { | |
| 4870 | units.clearRetainingCapacity(); | |
| 4871 | ||
| 4872 | var cur = arbitrary_unit; | |
| 4873 | while (true) { | |
| 4874 | try units.append(gpa, cur); | |
| 4875 | cur = zcu.dependency_loop_nodes.get(cur).?.unit; | |
| 4876 | if (cur == arbitrary_unit) break; | |
| 4877 | } | |
| 4878 | ||
| 4879 | // `units` now contains all units in the loop. We need to pick a starting point somewhere | |
| 4880 | // along that loop to begin. We will pick whichever node has the shortest reference trace, | |
| 4881 | // because the other units may well just be referenced *by* that one! This is also likely | |
| 4882 | // to match the user's intuition for where the loop "starts". | |
| 4883 | var start_index: usize = 0; | |
| 4884 | var start_depth: u32 = depth: { | |
| 4885 | var depth: u32 = 0; | |
| 4886 | var opt_ref = all_references.get(units.items[0]) orelse { | |
| 4887 | // This dependency loop is actually unreferenced, so we don't need to emit a compile | |
| 4888 | // error at all! Move onto the next dependency loop. | |
| 4889 | continue; | |
| 4890 | }; | |
| 4891 | while (opt_ref) |ref| : (opt_ref = all_references.get(ref.referencer).?) depth += 1; | |
| 4892 | break :depth depth; | |
| 4893 | }; | |
| 4894 | for (units.items[1..], 1..) |unit, index| { | |
| 4895 | var depth: u32 = 0; | |
| 4896 | var opt_ref = all_references.get(unit).?; | |
| 4897 | while (opt_ref) |ref| : (opt_ref = all_references.get(ref.referencer).?) depth += 1; | |
| 4898 | if (depth < start_depth) { | |
| 4899 | start_index = index; | |
| 4900 | start_depth = depth; | |
| 4901 | } | |
| 4902 | } | |
| 4903 | ||
| 4904 | // Collect a reference trace for the start of the loop. | |
| 4905 | var ref_trace: std.ArrayList(std.zig.ErrorBundle.ReferenceTrace) = .empty; | |
| 4906 | defer ref_trace.deinit(gpa); | |
| 4907 | const frame_limit = zcu.comp.reference_trace orelse 0; | |
| 4908 | try zcu.populateReferenceTrace(units.items[start_index], frame_limit, eb, &ref_trace); | |
| 4909 | ||
| 4910 | if (units.items.len == 1) { | |
| 4911 | // Don't do a complicated message with multiple notes, just do a single error message. | |
| 4912 | assert(start_index == 0); | |
| 4913 | const root_msg = addDependencyLoopErrorLine(zcu, eb, units.items[start_index], ref_trace.items) catch |err| switch (err) { | |
| 4914 | error.AlreadyReported => return, // give up on the dep loop error | |
| 4915 | error.OutOfMemory => |e| return e, | |
| 4916 | }; | |
| 4917 | try eb.root_list.append(eb.gpa, root_msg); | |
| 4918 | continue; | |
| 4919 | } | |
| 4920 | ||
| 4921 | // Collect all notes first so we don't leave an incomplete root error message on `error.AlreadyReported`. | |
| 4922 | const note_buf = try gpa.alloc(std.zig.ErrorBundle.MessageIndex, units.items.len + 1); | |
| 4923 | defer gpa.free(note_buf); | |
| 4924 | note_buf[0] = addDependencyLoopErrorLine(zcu, eb, units.items[start_index], ref_trace.items) catch |err| switch (err) { | |
| 4925 | error.AlreadyReported => return, // give up on the dep loop error | |
| 4926 | error.OutOfMemory => |e| return e, | |
| 4927 | }; | |
| 4928 | for (units.items[start_index + 1 ..], note_buf[1 .. units.items.len - start_index]) |unit, *note| { | |
| 4929 | note.* = addDependencyLoopErrorLine(zcu, eb, unit, &.{}) catch |err| switch (err) { | |
| 4930 | error.AlreadyReported => return, // give up on the dep loop error | |
| 4931 | error.OutOfMemory => |e| return e, | |
| 4932 | }; | |
| 4933 | } | |
| 4934 | for (units.items[0..start_index], note_buf[units.items.len - start_index .. units.items.len]) |unit, *note| { | |
| 4935 | note.* = addDependencyLoopErrorLine(zcu, eb, unit, &.{}) catch |err| switch (err) { | |
| 4936 | error.AlreadyReported => return, // give up on the dep loop error | |
| 4937 | error.OutOfMemory => |e| return e, | |
| 4938 | }; | |
| 4939 | } | |
| 4940 | note_buf[units.items.len] = try eb.addErrorMessage(.{ | |
| 4941 | .msg = try eb.addString("eliminate any one of these dependencies to break the loop"), | |
| 4942 | .src_loc = .none, | |
| 4943 | }); | |
| 4944 | ||
| 4945 | try eb.addRootErrorMessage(.{ | |
| 4946 | .msg = try eb.printString("dependency loop with length {d}", .{units.items.len}), | |
| 4947 | .src_loc = .none, | |
| 4948 | .notes_len = @intCast(units.items.len + 1), | |
| 4949 | }); | |
| 4950 | const notes_start = try eb.reserveNotes(@intCast(units.items.len + 1)); | |
| 4951 | const notes: []std.zig.ErrorBundle.MessageIndex = @ptrCast(eb.extra.items[notes_start..]); | |
| 4952 | @memcpy(notes, note_buf); | |
| 4953 | } | |
| 4954 | } | |
| 4955 | fn addDependencyLoopErrorLine( | |
| 4956 | zcu: *Zcu, | |
| 4957 | eb: *std.zig.ErrorBundle.Wip, | |
| 4958 | source_unit: AnalUnit, | |
| 4959 | ref_trace: []const std.zig.ErrorBundle.ReferenceTrace, | |
| 4960 | ) (Allocator.Error || error{AlreadyReported})!std.zig.ErrorBundle.MessageIndex { | |
| 4961 | const ip = &zcu.intern_pool; | |
| 4962 | const comp = zcu.comp; | |
| 4963 | ||
| 4964 | const fmt_source: std.fmt.Alt(FormatAnalUnit, formatDependencyLoopSourceUnit) = .{ .data = .{ | |
| 4965 | .unit = source_unit, | |
| 4966 | .zcu = zcu, | |
| 4967 | } }; | |
| 4968 | ||
| 4969 | const dep_node = zcu.dependency_loop_nodes.get(source_unit).?; | |
| 4970 | ||
| 4971 | const msg: std.zig.ErrorBundle.String = if (dep_node.unit == source_unit) switch (source_unit.unwrap()) { | |
| 4972 | .@"comptime" => unreachable, // cannot be involved in a dependency loop | |
| 4973 | .nav_ty, .nav_val => try eb.printString("{f} depends on itself here", .{fmt_source}), | |
| 4974 | .memoized_state => unreachable, // memoized_state definitely does not *directly* depend on itself | |
| 4975 | .func => try eb.printString("{f} uses its own inferred error set here", .{fmt_source}), | |
| 4976 | .type_layout => try eb.printString("{f} depends on itself {s}", .{ | |
| 4977 | fmt_source, | |
| 4978 | dep_node.reason.type_layout_reason.msg(), | |
| 4979 | }), | |
| 4980 | .struct_defaults => |ty| try eb.printString( | |
| 4981 | "default field values of '{f}' depend on themselves for initialization here", | |
| 4982 | .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}, | |
| 4983 | ), | |
| 4984 | } else switch (dep_node.unit.unwrap()) { | |
| 4985 | .@"comptime" => unreachable, // cannot be involved in a dependency loop | |
| 4986 | .nav_val => |nav| try eb.printString("{f} uses value of declaration '{f}' here", .{ | |
| 4987 | fmt_source, ip.getNav(nav).fqn.fmt(ip), | |
| 4988 | }), | |
| 4989 | .nav_ty => |nav| try eb.printString("{f} uses type of declaration '{f}' here", .{ | |
| 4990 | fmt_source, ip.getNav(nav).fqn.fmt(ip), | |
| 4991 | }), | |
| 4992 | .memoized_state => |stage| switch (stage) { | |
| 4993 | .panic => try eb.printString("{f} requires panic handler for call here", .{fmt_source}), | |
| 4994 | else => try eb.printString("{f} requires 'std.builtin' declarations here", .{fmt_source}), | |
| 4995 | }, | |
| 4996 | .func => |func| try eb.printString("{f} uses inferred error set of function '{f}' here", .{ | |
| 4997 | fmt_source, ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), | |
| 4998 | }), | |
| 4999 | .type_layout => |ty| try eb.printString("{f} depends on type '{f}' {s}", .{ | |
| 5000 | fmt_source, | |
| 5001 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | |
| 5002 | dep_node.reason.type_layout_reason.msg(), | |
| 5003 | }), | |
| 5004 | .struct_defaults => |ty| try eb.printString( | |
| 5005 | "{f} uses default field values of '{f}' here", | |
| 5006 | .{ fmt_source, Type.fromInterned(ty).containerTypeName(ip).fmt(ip) }, | |
| 5007 | ), | |
| 5008 | }; | |
| 5009 | ||
| 5010 | const src_loc = dep_node.reason.src.upgrade(zcu); | |
| 5011 | const source = src_loc.file_scope.getSource(zcu) catch |err| { | |
| 5012 | try Compilation.unableToLoadZcuFile(zcu, eb, src_loc.file_scope, err); | |
| 5013 | return error.AlreadyReported; | |
| 5014 | }; | |
| 5015 | const span = src_loc.span(zcu) catch |err| { | |
| 5016 | try Compilation.unableToLoadZcuFile(zcu, eb, src_loc.file_scope, err); | |
| 5017 | return error.AlreadyReported; | |
| 5018 | }; | |
| 5019 | const loc = std.zig.findLineColumn(source, span.main); | |
| 5020 | const eb_src = try eb.addSourceLocation(.{ | |
| 5021 | .src_path = try eb.printString("{f}", .{src_loc.file_scope.path.fmt(comp)}), | |
| 5022 | .span_start = span.start, | |
| 5023 | .span_main = span.main, | |
| 5024 | .span_end = span.end, | |
| 5025 | .line = @intCast(loc.line), | |
| 5026 | .column = @intCast(loc.column), | |
| 5027 | .source_line = try eb.addString(loc.source_line), | |
| 5028 | .reference_trace_len = @intCast(ref_trace.len), | |
| 5029 | }); | |
| 5030 | for (ref_trace) |rt| try eb.addReferenceTrace(rt); | |
| 5031 | return eb.addErrorMessage(.{ | |
| 5032 | .msg = msg, | |
| 5033 | .src_loc = eb_src, | |
| 5034 | }); | |
| 5035 | } | |
| 5036 | fn formatDependencyLoopSourceUnit(data: FormatAnalUnit, w: *Io.Writer) Io.Writer.Error!void { | |
| 5037 | const zcu = data.zcu; | |
| 5038 | const ip = &zcu.intern_pool; | |
| 5039 | switch (data.unit.unwrap()) { | |
| 5040 | .@"comptime" => unreachable, // cannot be involved in a dependency loop | |
| 5041 | .nav_val => |nav| try w.print("value of declaration '{f}'", .{ip.getNav(nav).fqn.fmt(ip)}), | |
| 5042 | .nav_ty => |nav| try w.print("type of declaration '{f}'", .{ip.getNav(nav).fqn.fmt(ip)}), | |
| 5043 | .memoized_state => |stage| switch (stage) { | |
| 5044 | .panic => try w.writeAll("panic handler"), | |
| 5045 | else => try w.writeAll("'std.builtin' declarations"), | |
| 5046 | }, | |
| 5047 | .type_layout => |ty| try w.print("type '{f}'", .{ | |
| 5048 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | |
| 5049 | }), | |
| 5050 | .struct_defaults => |ty| try w.print("default field value of '{f}'", .{ | |
| 5051 | Type.fromInterned(ty).containerTypeName(ip).fmt(ip), | |
| 5052 | }), | |
| 5053 | .func => |func| try w.print("function '{f}'", .{ | |
| 5054 | ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), | |
| 5055 | }), | |
| 5056 | } | |
| 5057 | } | |
| 5058 | ||
| 5059 | pub fn populateReferenceTrace( | |
| 5060 | zcu: *Zcu, | |
| 5061 | root: AnalUnit, | |
| 5062 | frame_limit: u32, | |
| 5063 | eb: *std.zig.ErrorBundle.Wip, | |
| 5064 | ref_trace: *std.ArrayList(std.zig.ErrorBundle.ReferenceTrace), | |
| 5065 | ) Allocator.Error!void { | |
| 5066 | const ip = &zcu.intern_pool; | |
| 5067 | const gpa = zcu.comp.gpa; | |
| 5068 | ||
| 5069 | if (frame_limit == 0) return; | |
| 5070 | ||
| 5071 | const all_references = try zcu.resolveReferences(); | |
| 5072 | ||
| 5073 | var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty; | |
| 5074 | defer seen.deinit(gpa); | |
| 5075 | ||
| 5076 | var referenced_by = root; | |
| 5077 | while (all_references.get(referenced_by)) |maybe_ref| { | |
| 5078 | const ref = maybe_ref orelse break; | |
| 5079 | const gop = try seen.getOrPut(gpa, ref.referencer); | |
| 5080 | if (gop.found_existing) break; | |
| 5081 | if (ref_trace.items.len < frame_limit) { | |
| 5082 | var last_call_src = ref.src; | |
| 5083 | var opt_inline_frame = ref.inline_frame; | |
| 5084 | while (opt_inline_frame.unwrap()) |inline_frame| { | |
| 5085 | const f = inline_frame.ptr(zcu).*; | |
| 5086 | const func_nav = ip.indexToKey(f.callee).func.owner_nav; | |
| 5087 | const func_name = ip.getNav(func_nav).name.toSlice(ip); | |
| 5088 | addReferenceTraceFrame(zcu, eb, ref_trace, func_name, last_call_src, true) catch |err| switch (err) { | |
| 5089 | error.OutOfMemory => |e| return e, | |
| 5090 | error.AlreadyReported => { | |
| 5091 | // An incomplete reference trace isn't the end of the world; just cut it off. | |
| 5092 | return; | |
| 5093 | }, | |
| 5094 | }; | |
| 5095 | last_call_src = f.call_src; | |
| 5096 | opt_inline_frame = f.parent; | |
| 5097 | } | |
| 5098 | const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { | |
| 5099 | .@"comptime" => "comptime", | |
| 5100 | .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), | |
| 5101 | .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), | |
| 5102 | .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), | |
| 5103 | .memoized_state => null, | |
| 5104 | }; | |
| 5105 | if (root_name) |n| { | |
| 5106 | addReferenceTraceFrame(zcu, eb, ref_trace, n, last_call_src, false) catch |err| switch (err) { | |
| 5107 | error.OutOfMemory => |e| return e, | |
| 5108 | error.AlreadyReported => { | |
| 5109 | // An incomplete reference trace isn't the end of the world; just cut it off. | |
| 5110 | return; | |
| 5111 | }, | |
| 5112 | }; | |
| 5113 | } | |
| 5114 | } | |
| 5115 | referenced_by = ref.referencer; | |
| 5116 | } | |
| 5117 | ||
| 5118 | if (seen.count() > ref_trace.items.len) { | |
| 5119 | try ref_trace.append(gpa, .{ | |
| 5120 | .decl_name = @intCast(seen.count() - ref_trace.items.len), | |
| 5121 | .src_loc = .none, | |
| 5122 | }); | |
| 5123 | } | |
| 5124 | } | |
| 5125 | fn addReferenceTraceFrame( | |
| 5126 | zcu: *Zcu, | |
| 5127 | eb: *std.zig.ErrorBundle.Wip, | |
| 5128 | ref_trace: *std.ArrayList(std.zig.ErrorBundle.ReferenceTrace), | |
| 5129 | name: []const u8, | |
| 5130 | lazy_src: Zcu.LazySrcLoc, | |
| 5131 | inlined: bool, | |
| 5132 | ) error{ OutOfMemory, AlreadyReported }!void { | |
| 5133 | const gpa = zcu.gpa; | |
| 5134 | const src = lazy_src.upgrade(zcu); | |
| 5135 | const source = src.file_scope.getSource(zcu) catch |err| { | |
| 5136 | try Compilation.unableToLoadZcuFile(zcu, eb, src.file_scope, err); | |
| 5137 | return error.AlreadyReported; | |
| 5138 | }; | |
| 5139 | const span = src.span(zcu) catch |err| { | |
| 5140 | try Compilation.unableToLoadZcuFile(zcu, eb, src.file_scope, err); | |
| 5141 | return error.AlreadyReported; | |
| 5142 | }; | |
| 5143 | const loc = std.zig.findLineColumn(source, span.main); | |
| 5144 | try ref_trace.append(gpa, .{ | |
| 5145 | .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }), | |
| 5146 | .src_loc = try eb.addSourceLocation(.{ | |
| 5147 | .src_path = try eb.printString("{f}", .{src.file_scope.path.fmt(zcu.comp)}), | |
| 5148 | .span_start = span.start, | |
| 5149 | .span_main = span.main, | |
| 5150 | .span_end = span.end, | |
| 5151 | .line = @intCast(loc.line), | |
| 5152 | .column = @intCast(loc.column), | |
| 5153 | .source_line = 0, | |
| 5154 | }), | |
| 5155 | }); | |
| 5156 | } | |
| 5157 | ||
| 4750 | 5158 | const TrackedUnitSema = struct { |
| 4751 | 5159 | /// `null` means we created the node, so should end it. |
| 4752 | 5160 | old_name: ?[std.Progress.Node.max_name_len]u8, |
src/Zcu/PerThread.zig+1060-1109| ... | ... | @@ -27,7 +27,9 @@ const introspect = @import("../introspect.zig"); |
| 27 | 27 | const Module = @import("../Package.zig").Module; |
| 28 | 28 | const Sema = @import("../Sema.zig"); |
| 29 | 29 | const target_util = @import("../target.zig"); |
| 30 | const trace = @import("../tracy.zig").trace; | |
| 30 | const tracy = @import("../tracy.zig"); | |
| 31 | const trace = tracy.trace; | |
| 32 | const traceNamed = tracy.traceNamed; | |
| 31 | 33 | const Type = @import("../Type.zig"); |
| 32 | 34 | const Value = @import("../Value.zig"); |
| 33 | 35 | const Zcu = @import("../Zcu.zig"); |
| ... | ... | @@ -125,6 +127,329 @@ pub fn deactivate(pt: Zcu.PerThread) void { |
| 125 | 127 | pt.zcu.intern_pool.deactivate(); |
| 126 | 128 | } |
| 127 | 129 | |
| 130 | /// Called from `Compilation.performAllTheWork`. Performs one incremental update of the ZCU: detects | |
| 131 | /// changes to files, runs AstGen, and then enters the main semantic analysis loop, where we build | |
| 132 | /// up a graph of declarations, functions, etc, while also sending declarations and functions to | |
| 133 | /// codegen as they are analyzed. | |
| 134 | pub fn update( | |
| 135 | pt: Zcu.PerThread, | |
| 136 | main_progress_node: std.Progress.Node, | |
| 137 | decl_work_timer: *?Compilation.Timer, | |
| 138 | ) (Allocator.Error || Io.Cancelable)!void { | |
| 139 | const zcu = pt.zcu; | |
| 140 | const comp = zcu.comp; | |
| 141 | const gpa = comp.gpa; | |
| 142 | const io = comp.io; | |
| 143 | ||
| 144 | { | |
| 145 | const tracy_trace = traceNamed(@src(), "astgen"); | |
| 146 | defer tracy_trace.end(); | |
| 147 | ||
| 148 | const zir_prog_node = main_progress_node.start("AST Lowering", 0); | |
| 149 | defer zir_prog_node.end(); | |
| 150 | ||
| 151 | var timer = comp.startTimer(); | |
| 152 | defer if (timer.finish(io)) |ns| { | |
| 153 | comp.mutex.lockUncancelable(io); | |
| 154 | defer comp.mutex.unlock(io); | |
| 155 | comp.time_report.?.stats.real_ns_files = ns; | |
| 156 | }; | |
| 157 | ||
| 158 | var astgen_group: Io.Group = .init; | |
| 159 | defer astgen_group.cancel(io); | |
| 160 | ||
| 161 | // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs, | |
| 162 | // because on single-threaded targets the worker will be run eagerly, meaning the | |
| 163 | // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So, | |
| 164 | // build up a list of the files to update *before* we spawn any jobs. | |
| 165 | var astgen_work_items: std.MultiArrayList(struct { | |
| 166 | file_index: Zcu.File.Index, | |
| 167 | file: *Zcu.File, | |
| 168 | }) = .empty; | |
| 169 | defer astgen_work_items.deinit(gpa); | |
| 170 | // Not every item in `import_table` will need updating, because some are builtin.zig | |
| 171 | // files. However, most will, so let's just reserve sufficient capacity upfront. | |
| 172 | try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count()); | |
| 173 | for (zcu.import_table.keys()) |file_index| { | |
| 174 | const file = zcu.fileByIndex(file_index); | |
| 175 | if (file.is_builtin) { | |
| 176 | // This is a `builtin.zig`, so updating is redundant. However, we want to make | |
| 177 | // sure the file contents are still correct on disk, since it can improve the | |
| 178 | // debugging experience better. That job only needs `file`, so we can kick it | |
| 179 | // off right now. | |
| 180 | astgen_group.async(io, workerUpdateBuiltinFile, .{ comp, file }); | |
| 181 | continue; | |
| 182 | } | |
| 183 | astgen_work_items.appendAssumeCapacity(.{ | |
| 184 | .file_index = file_index, | |
| 185 | .file = file, | |
| 186 | }); | |
| 187 | } | |
| 188 | ||
| 189 | // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs. | |
| 190 | for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| { | |
| 191 | astgen_group.async(io, workerUpdateFile, .{ | |
| 192 | comp, file, file_index, zir_prog_node, &astgen_group, | |
| 193 | }); | |
| 194 | } | |
| 195 | ||
| 196 | // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here | |
| 197 | // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one | |
| 198 | // `@embedFile` can't trigger analysis of a new `@embedFile`! | |
| 199 | for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| { | |
| 200 | const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); | |
| 201 | astgen_group.async(io, workerUpdateEmbedFile, .{ | |
| 202 | comp, ef_index, ef, | |
| 203 | }); | |
| 204 | } | |
| 205 | ||
| 206 | try astgen_group.await(io); | |
| 207 | } | |
| 208 | ||
| 209 | // On an incremental update, a source file might become "dead", in that all imports of | |
| 210 | // the file were removed. This could even change what module the file belongs to! As such, | |
| 211 | // we do a traversal over the files, to figure out which ones are alive and the modules | |
| 212 | // they belong to. | |
| 213 | const any_fatal_files = try pt.computeAliveFiles(); | |
| 214 | ||
| 215 | // If the cache mode is `whole`, add every alive source file to the manifest. | |
| 216 | switch (comp.cache_use) { | |
| 217 | .whole => |whole| if (whole.cache_manifest) |man| { | |
| 218 | for (zcu.alive_files.keys()) |file_index| { | |
| 219 | const file = zcu.fileByIndex(file_index); | |
| 220 | ||
| 221 | switch (file.status) { | |
| 222 | .never_loaded => unreachable, // AstGen tried to load it | |
| 223 | .retryable_failure => continue, // the file cannot be read; this is a guaranteed error | |
| 224 | .astgen_failure, .success => {}, // the file was read successfully | |
| 225 | } | |
| 226 | ||
| 227 | const path = try file.path.toAbsolute(comp.dirs, gpa); | |
| 228 | defer gpa.free(path); | |
| 229 | ||
| 230 | const result = res: { | |
| 231 | try whole.cache_manifest_mutex.lock(io); | |
| 232 | defer whole.cache_manifest_mutex.unlock(io); | |
| 233 | if (file.source) |source| { | |
| 234 | break :res man.addFilePostContents(path, source, file.stat); | |
| 235 | } else { | |
| 236 | break :res man.addFilePost(path); | |
| 237 | } | |
| 238 | }; | |
| 239 | result catch |err| switch (err) { | |
| 240 | error.OutOfMemory => |e| return e, | |
| 241 | else => { | |
| 242 | try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); | |
| 243 | continue; | |
| 244 | }, | |
| 245 | }; | |
| 246 | } | |
| 247 | }, | |
| 248 | .none, .incremental => {}, | |
| 249 | } | |
| 250 | ||
| 251 | if (comp.time_report) |*tr| { | |
| 252 | tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); | |
| 253 | } | |
| 254 | ||
| 255 | if (any_fatal_files or | |
| 256 | zcu.multi_module_err != null or | |
| 257 | zcu.failed_imports.items.len > 0 or | |
| 258 | comp.alloc_failure_occurred) | |
| 259 | { | |
| 260 | // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents | |
| 261 | // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. | |
| 262 | // However, this means our analysis data is invalid, so we want to omit all analysis errors. | |
| 263 | zcu.skip_analysis_this_update = true; | |
| 264 | return; | |
| 265 | } | |
| 266 | ||
| 267 | if (comp.config.incremental) { | |
| 268 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); | |
| 269 | defer update_zir_refs_node.end(); | |
| 270 | try pt.updateZirRefs(); | |
| 271 | } | |
| 272 | ||
| 273 | try zcu.flushRetryableFailures(); | |
| 274 | ||
| 275 | if (!zcu.backendSupportsFeature(.separate_thread)) { | |
| 276 | // Close the ZCU task queue. Prelink may still be running, but the closed | |
| 277 | // queue will cause the linker task to exit once prelink finishes. The | |
| 278 | // closed queue also communicates to `enqueueZcu` that it should wait for | |
| 279 | // the linker task to finish and then run ZCU tasks serially. | |
| 280 | comp.link_queue.finishZcuQueue(comp); | |
| 281 | } | |
| 282 | ||
| 283 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | |
| 284 | if (comp.bin_file != null) { | |
| 285 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); | |
| 286 | } | |
| 287 | // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. | |
| 288 | // That prevents the "Code Generation" node from constantly disappearing and reappearing when | |
| 289 | // we're probably going to analyze more functions at some point. | |
| 290 | assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes | |
| 291 | ||
| 292 | defer { | |
| 293 | zcu.sema_prog_node.end(); | |
| 294 | zcu.sema_prog_node = .none; | |
| 295 | if (zcu.pending_codegen_jobs.fetchSub(1, .monotonic) == 1) { | |
| 296 | // Decremented to 0, so all done. | |
| 297 | zcu.codegen_prog_node.end(); | |
| 298 | zcu.codegen_prog_node = .none; | |
| 299 | } | |
| 300 | } | |
| 301 | ||
| 302 | // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). | |
| 303 | decl_work_timer.* = comp.startTimer(); | |
| 304 | ||
| 305 | // To kick off semantic analysis, populate the root source file of any module we have marked | |
| 306 | // as an analysis root. Declarations in these files which want eager analysis---those being | |
| 307 | // `comptime` declarations, any declarations marked `export`, and `test` declarations in the | |
| 308 | // main module if this is a test compilation---become referenced, and so will be picked up | |
| 309 | // up by the main semantic analysis loop below. | |
| 310 | for (zcu.analysisRoots()) |analysis_root_mod| { | |
| 311 | const analysis_root_file = zcu.module_roots.get(analysis_root_mod).?.unwrap().?; | |
| 312 | try pt.ensureFilePopulated(analysis_root_file); | |
| 313 | } | |
| 314 | ||
| 315 | // This is the main semantic analysis loop, which is essentially the main loop of the whole | |
| 316 | // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed, | |
| 317 | // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze. | |
| 318 | while (try zcu.findOutdatedToAnalyze()) |unit| { | |
| 319 | const tracy_trace = traceNamed(@src(), "analyze_outdated"); | |
| 320 | defer tracy_trace.end(); | |
| 321 | ||
| 322 | const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) { | |
| 323 | .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), | |
| 324 | .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), | |
| 325 | .nav_val => |nav| pt.ensureNavValUpToDate(nav, null), | |
| 326 | .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null), | |
| 327 | .struct_defaults => |ty| res: { | |
| 328 | // Unlike the other functions, this one requires that the type layout is resolved first. | |
| 329 | pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null) catch |err| switch (err) { | |
| 330 | error.OutOfMemory, | |
| 331 | error.Canceled, | |
| 332 | => |e| return e, | |
| 333 | ||
| 334 | error.AnalysisFail => {}, // already reported | |
| 335 | }; | |
| 336 | break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null); | |
| 337 | }, | |
| 338 | .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage, null), | |
| 339 | .func => |func| pt.ensureFuncBodyUpToDate(func, null), | |
| 340 | }; | |
| 341 | maybe_err catch |err| switch (err) { | |
| 342 | error.OutOfMemory, | |
| 343 | error.Canceled, | |
| 344 | => |e| return e, | |
| 345 | ||
| 346 | error.AnalysisFail => {}, // already reported | |
| 347 | }; | |
| 348 | } | |
| 349 | } | |
| 350 | fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { | |
| 351 | Builtin.updateFileOnDisk(file, comp) catch |err| comp.lockAndSetMiscFailure( | |
| 352 | .write_builtin_zig, | |
| 353 | "unable to write '{f}': {s}", | |
| 354 | .{ file.path.fmt(comp), @errorName(err) }, | |
| 355 | ); | |
| 356 | } | |
| 357 | fn workerUpdateFile( | |
| 358 | comp: *Compilation, | |
| 359 | file: *Zcu.File, | |
| 360 | file_index: Zcu.File.Index, | |
| 361 | prog_node: std.Progress.Node, | |
| 362 | group: *Io.Group, | |
| 363 | ) void { | |
| 364 | const io = comp.io; | |
| 365 | const tid: Zcu.PerThread.Id = .acquire(io); | |
| 366 | defer tid.release(io); | |
| 367 | ||
| 368 | const child_prog_node = prog_node.start(std.fs.path.basename(file.path.sub_path), 0); | |
| 369 | defer child_prog_node.end(); | |
| 370 | ||
| 371 | const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); | |
| 372 | defer pt.deactivate(); | |
| 373 | pt.updateFile(file_index, file) catch |err| { | |
| 374 | pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) { | |
| 375 | error.OutOfMemory => { | |
| 376 | comp.mutex.lockUncancelable(io); | |
| 377 | defer comp.mutex.unlock(io); | |
| 378 | comp.setAllocFailure(); | |
| 379 | }, | |
| 380 | }; | |
| 381 | return; | |
| 382 | }; | |
| 383 | ||
| 384 | switch (file.getMode()) { | |
| 385 | .zig => {}, // continue to logic below | |
| 386 | .zon => return, // ZON can't import anything so we're done | |
| 387 | } | |
| 388 | ||
| 389 | // Discover all imports in the file. Imports of modules we ignore for now since we don't | |
| 390 | // know which module we're in, but imports of file paths might need us to queue up other | |
| 391 | // AstGen jobs. | |
| 392 | const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 393 | if (imports_index != 0) { | |
| 394 | const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); | |
| 395 | var import_i: u32 = 0; | |
| 396 | var extra_index = extra.end; | |
| 397 | ||
| 398 | while (import_i < extra.data.imports_len) : (import_i += 1) { | |
| 399 | const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 400 | extra_index = item.end; | |
| 401 | ||
| 402 | const import_path = file.zir.?.nullTerminatedString(item.data.name); | |
| 403 | ||
| 404 | if (pt.discoverImport(file.path, import_path)) |res| switch (res) { | |
| 405 | .module, .existing_file => {}, | |
| 406 | .new_file => |new| { | |
| 407 | group.async(io, workerUpdateFile, .{ | |
| 408 | comp, new.file, new.index, prog_node, group, | |
| 409 | }); | |
| 410 | }, | |
| 411 | } else |err| switch (err) { | |
| 412 | error.OutOfMemory => { | |
| 413 | comp.mutex.lockUncancelable(io); | |
| 414 | defer comp.mutex.unlock(io); | |
| 415 | comp.setAllocFailure(); | |
| 416 | }, | |
| 417 | } | |
| 418 | } | |
| 419 | } | |
| 420 | } | |
| 421 | fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { | |
| 422 | const io = comp.io; | |
| 423 | const tid: Zcu.PerThread.Id = .acquire(io); | |
| 424 | defer tid.release(io); | |
| 425 | detectEmbedFileUpdate(comp, tid, ef_index, ef) catch |err| switch (err) { | |
| 426 | error.OutOfMemory => { | |
| 427 | comp.mutex.lockUncancelable(io); | |
| 428 | defer comp.mutex.unlock(io); | |
| 429 | comp.setAllocFailure(); | |
| 430 | }, | |
| 431 | }; | |
| 432 | } | |
| 433 | fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void { | |
| 434 | const io = comp.io; | |
| 435 | const zcu = comp.zcu.?; | |
| 436 | const pt: Zcu.PerThread = .activate(zcu, tid); | |
| 437 | defer pt.deactivate(); | |
| 438 | ||
| 439 | const old_val = ef.val; | |
| 440 | const old_err = ef.err; | |
| 441 | ||
| 442 | try pt.updateEmbedFile(ef, null); | |
| 443 | ||
| 444 | if (ef.val != .none and ef.val == old_val) return; // success, value unchanged | |
| 445 | if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged | |
| 446 | ||
| 447 | comp.mutex.lockUncancelable(io); | |
| 448 | defer comp.mutex.unlock(io); | |
| 449 | ||
| 450 | try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index }); | |
| 451 | } | |
| 452 | ||
| 128 | 453 | fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { |
| 129 | 454 | const zcu = pt.zcu; |
| 130 | 455 | const gpa = zcu.gpa; |
| ... | ... | @@ -156,8 +481,8 @@ pub fn updateFile( |
| 156 | 481 | ) !void { |
| 157 | 482 | dev.check(.ast_gen); |
| 158 | 483 | |
| 159 | const tracy = trace(@src()); | |
| 160 | defer tracy.end(); | |
| 484 | const tracy_trace = trace(@src()); | |
| 485 | defer tracy_trace.end(); | |
| 161 | 486 | |
| 162 | 487 | const zcu = pt.zcu; |
| 163 | 488 | const comp = zcu.comp; |
| ... | ... | @@ -484,7 +809,7 @@ fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.AutoArrayHashMapUnman |
| 484 | 809 | updated_files.deinit(gpa); |
| 485 | 810 | } |
| 486 | 811 | |
| 487 | pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { | |
| 812 | fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { | |
| 488 | 813 | assert(pt.tid == .main); |
| 489 | 814 | const zcu = pt.zcu; |
| 490 | 815 | const comp = zcu.comp; |
| ... | ... | @@ -566,7 +891,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 566 | 891 | const old_line = old_zir.getDeclaration(old_inst).src_line; |
| 567 | 892 | const new_line = new_zir.getDeclaration(new_inst).src_line; |
| 568 | 893 | if (old_line != new_line) { |
| 569 | try comp.queueJob(.{ .update_line_number = tracked_inst_index }); | |
| 894 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index }); | |
| 570 | 895 | } |
| 571 | 896 | }, |
| 572 | 897 | else => {}, |
| ... | ... | @@ -598,44 +923,38 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 598 | 923 | // Value is whether the declaration is `pub`. |
| 599 | 924 | var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, bool) = .empty; |
| 600 | 925 | defer old_names.deinit(zcu.gpa); |
| 601 | { | |
| 602 | var it = old_zir.declIterator(old_inst); | |
| 603 | while (it.next()) |decl_inst| { | |
| 604 | const old_decl = old_zir.getDeclaration(decl_inst); | |
| 605 | if (old_decl.name == .empty) continue; | |
| 606 | const name_ip = try zcu.intern_pool.getOrPutString( | |
| 607 | zcu.gpa, | |
| 608 | io, | |
| 609 | pt.tid, | |
| 610 | old_zir.nullTerminatedString(old_decl.name), | |
| 611 | .no_embedded_nulls, | |
| 612 | ); | |
| 613 | try old_names.put(zcu.gpa, name_ip, old_decl.is_pub); | |
| 614 | } | |
| 926 | for (old_zir.typeDecls(old_inst)) |decl_inst| { | |
| 927 | const old_decl = old_zir.getDeclaration(decl_inst); | |
| 928 | if (old_decl.name == .empty) continue; | |
| 929 | const name_ip = try zcu.intern_pool.getOrPutString( | |
| 930 | zcu.gpa, | |
| 931 | io, | |
| 932 | pt.tid, | |
| 933 | old_zir.nullTerminatedString(old_decl.name), | |
| 934 | .no_embedded_nulls, | |
| 935 | ); | |
| 936 | try old_names.put(zcu.gpa, name_ip, old_decl.is_pub); | |
| 615 | 937 | } |
| 616 | 938 | var any_change = false; |
| 617 | { | |
| 618 | var it = new_zir.declIterator(new_inst); | |
| 619 | while (it.next()) |decl_inst| { | |
| 620 | const new_decl = new_zir.getDeclaration(decl_inst); | |
| 621 | if (new_decl.name == .empty) continue; | |
| 622 | const name_ip = try zcu.intern_pool.getOrPutString( | |
| 623 | zcu.gpa, | |
| 624 | io, | |
| 625 | pt.tid, | |
| 626 | new_zir.nullTerminatedString(new_decl.name), | |
| 627 | .no_embedded_nulls, | |
| 628 | ); | |
| 629 | if (old_names.fetchSwapRemove(name_ip)) |kv| { | |
| 630 | if (kv.value == new_decl.is_pub) continue; | |
| 631 | } | |
| 632 | // Name added, or changed whether it's pub | |
| 633 | any_change = true; | |
| 634 | try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{ | |
| 635 | .namespace = tracked_inst_index, | |
| 636 | .name = name_ip, | |
| 637 | } }); | |
| 939 | for (new_zir.typeDecls(new_inst)) |decl_inst| { | |
| 940 | const new_decl = new_zir.getDeclaration(decl_inst); | |
| 941 | if (new_decl.name == .empty) continue; | |
| 942 | const name_ip = try zcu.intern_pool.getOrPutString( | |
| 943 | zcu.gpa, | |
| 944 | io, | |
| 945 | pt.tid, | |
| 946 | new_zir.nullTerminatedString(new_decl.name), | |
| 947 | .no_embedded_nulls, | |
| 948 | ); | |
| 949 | if (old_names.fetchSwapRemove(name_ip)) |kv| { | |
| 950 | if (kv.value == new_decl.is_pub) continue; | |
| 638 | 951 | } |
| 952 | // Name added, or changed whether it's pub | |
| 953 | any_change = true; | |
| 954 | try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{ | |
| 955 | .namespace = tracked_inst_index, | |
| 956 | .name = name_ip, | |
| 957 | } }); | |
| 639 | 958 | } |
| 640 | 959 | // The only elements remaining in `old_names` now are any names which were removed. |
| 641 | 960 | for (old_names.keys()) |name_ip| { |
| ... | ... | @@ -674,32 +993,74 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 674 | 993 | } |
| 675 | 994 | } |
| 676 | 995 | |
| 677 | /// Ensures that `zcu.fileRootType` on this `file_index` gives an up-to-date answer. | |
| 678 | /// Returns `error.AnalysisFail` if the file has an error. | |
| 679 | pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { | |
| 680 | const file_root_type = pt.zcu.fileRootType(file_index); | |
| 681 | if (file_root_type != .none) { | |
| 682 | if (pt.ensureTypeUpToDate(file_root_type)) |_| { | |
| 683 | return; | |
| 684 | } else |err| switch (err) { | |
| 685 | error.AnalysisFail => { | |
| 686 | // The file's root `struct_decl` has, at some point, been lost, because the file failed AstGen. | |
| 687 | // Clear `file_root_type`, and try the `semaFile` call below, in case the instruction has since | |
| 688 | // been discovered under a new `TrackedInst.Index`. | |
| 689 | pt.zcu.setFileRootType(file_index, .none); | |
| 690 | }, | |
| 691 | else => |e| return e, | |
| 692 | } | |
| 693 | } | |
| 694 | return pt.semaFile(file_index); | |
| 996 | /// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies | |
| 997 | /// that the file's namespace is scanned, discovering declarations. | |
| 998 | /// | |
| 999 | /// Typical Zig compilations begin by claling this function on the root source file of the standard | |
| 1000 | /// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in | |
| 1001 | /// that file, which is queued for analysis, and everything goes from there. | |
| 1002 | pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { | |
| 1003 | dev.check(.sema); | |
| 1004 | ||
| 1005 | const tracy_trace = trace(@src()); | |
| 1006 | defer tracy_trace.end(); | |
| 1007 | ||
| 1008 | const zcu = pt.zcu; | |
| 1009 | const comp = zcu.comp; | |
| 1010 | const io = comp.io; | |
| 1011 | const gpa = comp.gpa; | |
| 1012 | const ip = &zcu.intern_pool; | |
| 1013 | ||
| 1014 | if (zcu.fileRootType(file_index) != .none) return; // already good | |
| 1015 | ||
| 1016 | if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1; | |
| 1017 | ||
| 1018 | const file = zcu.fileByIndex(file_index); | |
| 1019 | assert(file.getMode() == .zig); | |
| 1020 | const struct_decl = file.zir.?.getStructDecl(.main_struct_inst); | |
| 1021 | const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ | |
| 1022 | .file = file_index, | |
| 1023 | .inst = .main_struct_inst, | |
| 1024 | }); | |
| 1025 | const wip: InternPool.WipContainerType = switch (try ip.getDeclaredStructType(gpa, io, pt.tid, .{ | |
| 1026 | .zir_index = tracked_inst, | |
| 1027 | .captures = &.{}, | |
| 1028 | .fields_len = @intCast(struct_decl.field_names.len), | |
| 1029 | .layout = struct_decl.layout, | |
| 1030 | .any_comptime_fields = struct_decl.field_comptime_bits != null, | |
| 1031 | .any_field_defaults = struct_decl.field_default_body_lens != null, | |
| 1032 | .any_field_aligns = struct_decl.field_align_body_lens != null, | |
| 1033 | .packed_backing_mode = if (struct_decl.backing_int_type_body != null) .explicit else .auto, | |
| 1034 | })) { | |
| 1035 | .existing => unreachable, // it would have been set as `zcu.fileRootType` already | |
| 1036 | .wip => |wip| wip, | |
| 1037 | }; | |
| 1038 | errdefer wip.cancel(ip, pt.tid); | |
| 1039 | ||
| 1040 | wip.setName(ip, try file.internFullyQualifiedName(pt), .none); | |
| 1041 | const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ | |
| 1042 | .parent = .none, | |
| 1043 | .owner_type = wip.index, | |
| 1044 | .file_scope = file_index, | |
| 1045 | .generation = zcu.generation, | |
| 1046 | }); | |
| 1047 | errdefer pt.destroyNamespace(new_namespace_index); | |
| 1048 | try pt.scanNamespace(new_namespace_index, struct_decl.decls); | |
| 1049 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); | |
| 1050 | zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index)); | |
| 695 | 1051 | } |
| 696 | 1052 | |
| 697 | 1053 | /// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary. |
| 698 | 1054 | /// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore |
| 699 | 1055 | /// this, since the error is already registered, but it must not use the value of memoized fields. |
| 700 | pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.SemaError!void { | |
| 701 | const tracy = trace(@src()); | |
| 702 | defer tracy.end(); | |
| 1056 | pub fn ensureMemoizedStateUpToDate( | |
| 1057 | pt: Zcu.PerThread, | |
| 1058 | stage: InternPool.MemoizedStateStage, | |
| 1059 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. | |
| 1060 | reason: ?*const Zcu.DependencyReason, | |
| 1061 | ) Zcu.SemaError!void { | |
| 1062 | const tracy_trace = trace(@src()); | |
| 1063 | defer tracy_trace.end(); | |
| 703 | 1064 | |
| 704 | 1065 | const zcu = pt.zcu; |
| 705 | 1066 | const gpa = zcu.gpa; |
| ... | ... | @@ -710,19 +1071,11 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 710 | 1071 | |
| 711 | 1072 | assert(!zcu.analysis_in_progress.contains(unit)); |
| 712 | 1073 | |
| 713 | const was_outdated = zcu.outdated.swapRemove(unit) or zcu.potentially_outdated.swapRemove(unit); | |
| 1074 | const was_outdated = zcu.clearOutdatedState(unit); | |
| 714 | 1075 | const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit); |
| 715 | 1076 | |
| 716 | 1077 | if (was_outdated) { |
| 717 | dev.check(.incremental); | |
| 718 | _ = zcu.outdated_ready.swapRemove(unit); | |
| 719 | // No need for `deleteUnitExports` because we never export anything. | |
| 720 | zcu.deleteUnitReferences(unit); | |
| 721 | zcu.deleteUnitCompileLogs(unit); | |
| 722 | if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| { | |
| 723 | kv.value.destroy(gpa); | |
| 724 | } | |
| 725 | _ = zcu.transitive_failed_analysis.swapRemove(unit); | |
| 1078 | zcu.resetUnit(unit); | |
| 726 | 1079 | } else { |
| 727 | 1080 | if (prev_failed) return error.AnalysisFail; |
| 728 | 1081 | // We use an arbitrary element to check if the state has been resolved yet. |
| ... | ... | @@ -741,7 +1094,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 741 | 1094 | info.deps.clearRetainingCapacity(); |
| 742 | 1095 | } |
| 743 | 1096 | |
| 744 | const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage)) |any_changed| | |
| 1097 | const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed| | |
| 745 | 1098 | .{ any_changed or prev_failed, false } |
| 746 | 1099 | else |err| switch (err) { |
| 747 | 1100 | error.AnalysisFail => res: { |
| ... | ... | @@ -774,39 +1127,20 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 774 | 1127 | if (new_failed) return error.AnalysisFail; |
| 775 | 1128 | } |
| 776 | 1129 | |
| 777 | fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool { | |
| 1130 | fn analyzeMemoizedState( | |
| 1131 | pt: Zcu.PerThread, | |
| 1132 | stage: InternPool.MemoizedStateStage, | |
| 1133 | reason: ?*const Zcu.DependencyReason, | |
| 1134 | ) Zcu.CompileError!bool { | |
| 778 | 1135 | const zcu = pt.zcu; |
| 779 | const ip = &zcu.intern_pool; | |
| 780 | 1136 | const comp = zcu.comp; |
| 781 | 1137 | const gpa = comp.gpa; |
| 782 | const io = comp.io; | |
| 783 | 1138 | |
| 784 | 1139 | const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); |
| 785 | 1140 | |
| 786 | try zcu.analysis_in_progress.putNoClobber(gpa, unit, {}); | |
| 1141 | try zcu.analysis_in_progress.putNoClobber(gpa, unit, reason); | |
| 787 | 1142 | defer assert(zcu.analysis_in_progress.swapRemove(unit)); |
| 788 | 1143 | |
| 789 | // Before we begin, collect: | |
| 790 | // * The type `std`, and its namespace | |
| 791 | // * The type `std.builtin`, and its namespace | |
| 792 | // * A semi-reasonable source location | |
| 793 | const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; | |
| 794 | try pt.ensureFileAnalyzed(std_file_index); | |
| 795 | const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); | |
| 796 | const std_namespace = std_type.getNamespaceIndex(zcu); | |
| 797 | try pt.ensureNamespaceUpToDate(std_namespace); | |
| 798 | const builtin_str = try ip.getOrPutString(gpa, io, pt.tid, "builtin", .no_embedded_nulls); | |
| 799 | const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse | |
| 800 | @panic("lib/std.zig is corrupt and missing 'builtin'"); | |
| 801 | try pt.ensureNavValUpToDate(builtin_nav); | |
| 802 | const builtin_type: Type = .fromInterned(ip.getNav(builtin_nav).status.fully_resolved.val); | |
| 803 | const builtin_namespace = builtin_type.getNamespaceIndex(zcu); | |
| 804 | try pt.ensureNamespaceUpToDate(builtin_namespace); | |
| 805 | const src: Zcu.LazySrcLoc = .{ | |
| 806 | .base_node_inst = builtin_type.typeDeclInst(zcu).?, | |
| 807 | .offset = .{ .byte_abs = 0 }, | |
| 808 | }; | |
| 809 | ||
| 810 | 1144 | var analysis_arena: std.heap.ArenaAllocator = .init(gpa); |
| 811 | 1145 | defer analysis_arena.deinit(); |
| 812 | 1146 | |
| ... | ... | @@ -827,30 +1161,15 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) |
| 827 | 1161 | }; |
| 828 | 1162 | defer sema.deinit(); |
| 829 | 1163 | |
| 830 | var block: Sema.Block = .{ | |
| 831 | .parent = null, | |
| 832 | .sema = &sema, | |
| 833 | .namespace = std_namespace, | |
| 834 | .instructions = .{}, | |
| 835 | .inlining = null, | |
| 836 | .comptime_reason = .{ .reason = .{ | |
| 837 | .src = src, | |
| 838 | .r = .{ .simple = .type }, | |
| 839 | } }, | |
| 840 | .src_base_inst = src.base_node_inst, | |
| 841 | .type_name_ctx = .empty, | |
| 842 | }; | |
| 843 | defer block.instructions.deinit(gpa); | |
| 844 | ||
| 845 | return sema.analyzeMemoizedState(&block, src, builtin_namespace, stage); | |
| 1164 | return sema.analyzeMemoizedState(stage); | |
| 846 | 1165 | } |
| 847 | 1166 | |
| 848 | 1167 | /// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis |
| 849 | 1168 | /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is |
| 850 | 1169 | /// free to ignore this, since the error is already registered. |
| 851 | 1170 | pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void { |
| 852 | const tracy = trace(@src()); | |
| 853 | defer tracy.end(); | |
| 1171 | const tracy_trace = trace(@src()); | |
| 1172 | defer tracy_trace.end(); | |
| 854 | 1173 | |
| 855 | 1174 | const zcu = pt.zcu; |
| 856 | 1175 | const gpa = zcu.gpa; |
| ... | ... | @@ -870,22 +1189,10 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 870 | 1189 | // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by |
| 871 | 1190 | // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. |
| 872 | 1191 | |
| 873 | const was_outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 874 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 1192 | const was_outdated = zcu.clearOutdatedState(anal_unit); | |
| 875 | 1193 | |
| 876 | 1194 | if (was_outdated) { |
| 877 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 878 | // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. | |
| 879 | if (dev.env.supports(.incremental)) { | |
| 880 | zcu.deleteUnitExports(anal_unit); | |
| 881 | zcu.deleteUnitReferences(anal_unit); | |
| 882 | zcu.deleteUnitCompileLogs(anal_unit); | |
| 883 | if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { | |
| 884 | kv.value.destroy(gpa); | |
| 885 | } | |
| 886 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | |
| 887 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 888 | } | |
| 1195 | zcu.resetUnit(anal_unit); | |
| 889 | 1196 | } else { |
| 890 | 1197 | // We can trust the current information about this unit. |
| 891 | 1198 | if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; |
| ... | ... | @@ -950,7 +1257,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 950 | 1257 | const file = zcu.fileByIndex(inst_resolved.file); |
| 951 | 1258 | const zir = file.zir.?; |
| 952 | 1259 | |
| 953 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); | |
| 1260 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, null); | |
| 954 | 1261 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); |
| 955 | 1262 | |
| 956 | 1263 | var analysis_arena: std.heap.ArenaAllocator = .init(gpa); |
| ... | ... | @@ -980,7 +1287,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 980 | 1287 | .parent = null, |
| 981 | 1288 | .sema = &sema, |
| 982 | 1289 | .namespace = comptime_unit.namespace, |
| 983 | .instructions = .{}, | |
| 1290 | .instructions = .empty, | |
| 984 | 1291 | .inlining = null, |
| 985 | 1292 | .comptime_reason = .{ .reason = .{ |
| 986 | 1293 | .src = .{ |
| ... | ... | @@ -1012,33 +1319,262 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 1012 | 1319 | try sema.flushExports(); |
| 1013 | 1320 | } |
| 1014 | 1321 | |
| 1322 | /// Ensures that the layout of the given `struct`, `union`, or `enum` type is fully up-to-date, | |
| 1323 | /// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!), union, or | |
| 1324 | /// enum type. Returns `error.AnalysisFail` if an analysis error is encountered during type | |
| 1325 | /// resolution; the caller is free to ignore this, since the error is already registered. | |
| 1326 | pub fn ensureTypeLayoutUpToDate( | |
| 1327 | pt: Zcu.PerThread, | |
| 1328 | ty: Type, | |
| 1329 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. | |
| 1330 | reason: ?*const Zcu.DependencyReason, | |
| 1331 | ) Zcu.SemaError!void { | |
| 1332 | const tracy_trace = trace(@src()); | |
| 1333 | defer tracy_trace.end(); | |
| 1334 | ||
| 1335 | const zcu = pt.zcu; | |
| 1336 | const ip = &zcu.intern_pool; | |
| 1337 | const comp = zcu.comp; | |
| 1338 | const gpa = comp.gpa; | |
| 1339 | ||
| 1340 | const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); | |
| 1341 | ||
| 1342 | log.debug("ensureTypeLayoutUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1343 | ||
| 1344 | assert(!zcu.analysis_in_progress.contains(anal_unit)); | |
| 1345 | ||
| 1346 | const was_outdated: bool = outdated: { | |
| 1347 | if (zcu.clearOutdatedState(anal_unit)) break :outdated true; | |
| 1348 | if (ip.setWantTypeLayout(comp.io, ty.toIntern())) { | |
| 1349 | // We'll analyze the layout for the first time, but if this is a struct type then its | |
| 1350 | // default field values also need to be analyzed. | |
| 1351 | if (ip.indexToKey(ty.toIntern()) == .struct_type) { | |
| 1352 | if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); | |
| 1353 | defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); | |
| 1354 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | |
| 1355 | try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 1); | |
| 1356 | zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = ty.toIntern() }), 0); | |
| 1357 | zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = ty.toIntern() }), {}); | |
| 1358 | } | |
| 1359 | break :outdated true; | |
| 1360 | } | |
| 1361 | break :outdated false; | |
| 1362 | }; | |
| 1363 | ||
| 1364 | if (was_outdated) { | |
| 1365 | zcu.resetUnit(anal_unit); | |
| 1366 | // For types, we already know that we have to invalidate all dependees. | |
| 1367 | // TODO: we actually *could* detect whether everything was the same. should we bother? | |
| 1368 | try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() }); | |
| 1369 | } else { | |
| 1370 | // We can trust the current information about this unit. | |
| 1371 | if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; | |
| 1372 | if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail; | |
| 1373 | return; | |
| 1374 | } | |
| 1375 | ||
| 1376 | if (comp.debugIncremental()) { | |
| 1377 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); | |
| 1378 | info.last_update_gen = zcu.generation; | |
| 1379 | info.deps.clearRetainingCapacity(); | |
| 1380 | } | |
| 1381 | ||
| 1382 | const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).toSlice(ip), null); | |
| 1383 | defer unit_tracking.end(zcu); | |
| 1384 | ||
| 1385 | try zcu.analysis_in_progress.put(gpa, anal_unit, reason); | |
| 1386 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1387 | ||
| 1388 | var analysis_arena: std.heap.ArenaAllocator = .init(gpa); | |
| 1389 | defer analysis_arena.deinit(); | |
| 1390 | ||
| 1391 | var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); | |
| 1392 | defer comptime_err_ret_trace.deinit(); | |
| 1393 | ||
| 1394 | const file = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu); | |
| 1395 | ||
| 1396 | var sema: Sema = .{ | |
| 1397 | .pt = pt, | |
| 1398 | .gpa = gpa, | |
| 1399 | .arena = analysis_arena.allocator(), | |
| 1400 | .code = file.zir.?, | |
| 1401 | .owner = anal_unit, | |
| 1402 | .func_index = .none, | |
| 1403 | .func_is_naked = false, | |
| 1404 | .fn_ret_ty = .void, | |
| 1405 | .fn_ret_ty_ies = null, | |
| 1406 | .comptime_err_ret_trace = &comptime_err_ret_trace, | |
| 1407 | }; | |
| 1408 | defer sema.deinit(); | |
| 1409 | ||
| 1410 | const result = switch (ty.zigTypeTag(zcu)) { | |
| 1411 | .@"enum" => Sema.type_resolution.resolveEnumLayout(&sema, ty), | |
| 1412 | .@"struct" => Sema.type_resolution.resolveStructLayout(&sema, ty), | |
| 1413 | .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty), | |
| 1414 | else => unreachable, | |
| 1415 | }; | |
| 1416 | const new_failed: bool = if (result) failed: { | |
| 1417 | break :failed false; | |
| 1418 | } else |err| switch (err) { | |
| 1419 | error.AnalysisFail => failed: { | |
| 1420 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1421 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1422 | // Since it does not, this must be a transitive failure. | |
| 1423 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1424 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1425 | } | |
| 1426 | break :failed true; | |
| 1427 | }, | |
| 1428 | error.OutOfMemory, | |
| 1429 | error.Canceled, | |
| 1430 | => |e| return e, | |
| 1431 | error.ComptimeReturn => unreachable, | |
| 1432 | error.ComptimeBreak => unreachable, | |
| 1433 | }; | |
| 1434 | ||
| 1435 | sema.flushExports() catch |err| switch (err) { | |
| 1436 | error.OutOfMemory => |e| return e, | |
| 1437 | }; | |
| 1438 | ||
| 1439 | // We don't need to `markDependeeOutdated`/`markPoDependeeUpToDate` here, because we already | |
| 1440 | // marked the layout as outdated at the top of this function. However, we do need to tell the | |
| 1441 | // debug info logic in the backend about this type. | |
| 1442 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 1443 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_container_type = .{ | |
| 1444 | .ty = ty.toIntern(), | |
| 1445 | .success = !new_failed, | |
| 1446 | } }); | |
| 1447 | ||
| 1448 | if (new_failed) return error.AnalysisFail; | |
| 1449 | } | |
| 1450 | ||
| 1451 | /// Ensures that the default field values of the given `struct` type are fully up-to-date, | |
| 1452 | /// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) type. Unlike | |
| 1453 | /// the other "ensure X up to date" functions, this particular function also asserts that the | |
| 1454 | /// *layout* of `ty` is *already* up-to-date (though it is okay for that resolution to have failed). | |
| 1455 | /// Returns `error.AnalysisFail` if an analysis error is encountered while resolving the default | |
| 1456 | /// field values; the caller is free to ignore this, since the error is already registered. | |
| 1457 | pub fn ensureStructDefaultsUpToDate( | |
| 1458 | pt: Zcu.PerThread, | |
| 1459 | ty: Type, | |
| 1460 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. | |
| 1461 | reason: ?*const Zcu.DependencyReason, | |
| 1462 | ) Zcu.SemaError!void { | |
| 1463 | const tracy_trace = trace(@src()); | |
| 1464 | defer tracy_trace.end(); | |
| 1465 | ||
| 1466 | const zcu = pt.zcu; | |
| 1467 | const ip = &zcu.intern_pool; | |
| 1468 | const comp = zcu.comp; | |
| 1469 | const gpa = comp.gpa; | |
| 1470 | ||
| 1471 | assert(ip.indexToKey(ty.toIntern()) == .struct_type); | |
| 1472 | ||
| 1473 | const anal_unit: AnalUnit = .wrap(.{ .struct_defaults = ty.toIntern() }); | |
| 1474 | ||
| 1475 | log.debug("ensureStructDefaultsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1476 | ||
| 1477 | assert(!zcu.analysis_in_progress.contains(anal_unit)); | |
| 1478 | ||
| 1479 | const was_outdated: bool = outdated: { | |
| 1480 | if (zcu.clearOutdatedState(anal_unit)) break :outdated true; | |
| 1481 | // The type layout should already be marked as "wanted" by this point, because a struct's | |
| 1482 | // layout must always be analyzed before its default values are. | |
| 1483 | assert(!ip.setWantTypeLayout(comp.io, ty.toIntern())); | |
| 1484 | break :outdated false; | |
| 1485 | }; | |
| 1486 | ||
| 1487 | if (was_outdated) { | |
| 1488 | zcu.resetUnit(anal_unit); | |
| 1489 | // For types, we already know that we have to invalidate all dependees. | |
| 1490 | // TODO: we actually *could* detect whether everything was the same. should we bother? | |
| 1491 | try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() }); | |
| 1492 | } else { | |
| 1493 | // We can trust the current information about this unit. | |
| 1494 | if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; | |
| 1495 | if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail; | |
| 1496 | return; | |
| 1497 | } | |
| 1498 | ||
| 1499 | if (zcu.comp.debugIncremental()) { | |
| 1500 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); | |
| 1501 | info.last_update_gen = zcu.generation; | |
| 1502 | info.deps.clearRetainingCapacity(); | |
| 1503 | } | |
| 1504 | ||
| 1505 | const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).toSlice(ip), null); | |
| 1506 | defer unit_tracking.end(zcu); | |
| 1507 | ||
| 1508 | try zcu.analysis_in_progress.put(gpa, anal_unit, reason); | |
| 1509 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1510 | ||
| 1511 | var analysis_arena: std.heap.ArenaAllocator = .init(gpa); | |
| 1512 | defer analysis_arena.deinit(); | |
| 1513 | ||
| 1514 | var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); | |
| 1515 | defer comptime_err_ret_trace.deinit(); | |
| 1516 | ||
| 1517 | const file = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu); | |
| 1518 | ||
| 1519 | var sema: Sema = .{ | |
| 1520 | .pt = pt, | |
| 1521 | .gpa = gpa, | |
| 1522 | .arena = analysis_arena.allocator(), | |
| 1523 | .code = file.zir.?, | |
| 1524 | .owner = anal_unit, | |
| 1525 | .func_index = .none, | |
| 1526 | .func_is_naked = false, | |
| 1527 | .fn_ret_ty = .void, | |
| 1528 | .fn_ret_ty_ies = null, | |
| 1529 | .comptime_err_ret_trace = &comptime_err_ret_trace, | |
| 1530 | }; | |
| 1531 | defer sema.deinit(); | |
| 1532 | ||
| 1533 | const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: { | |
| 1534 | break :failed false; | |
| 1535 | } else |err| switch (err) { | |
| 1536 | error.AnalysisFail => failed: { | |
| 1537 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1538 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1539 | // Since it does not, this must be a transitive failure. | |
| 1540 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1541 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1542 | } | |
| 1543 | break :failed true; | |
| 1544 | }, | |
| 1545 | error.OutOfMemory, | |
| 1546 | error.Canceled, | |
| 1547 | => |e| return e, | |
| 1548 | error.ComptimeReturn => unreachable, | |
| 1549 | error.ComptimeBreak => unreachable, | |
| 1550 | }; | |
| 1551 | ||
| 1552 | sema.flushExports() catch |err| switch (err) { | |
| 1553 | error.OutOfMemory => |e| return e, | |
| 1554 | }; | |
| 1555 | ||
| 1556 | // We don't need to `markDependeeOutdated`/`markPoDependeeUpToDate` here, because we already | |
| 1557 | // marked the struct defaults as outdated at the top of this function. | |
| 1558 | ||
| 1559 | if (new_failed) return error.AnalysisFail; | |
| 1560 | } | |
| 1561 | ||
| 1015 | 1562 | /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis |
| 1016 | 1563 | /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is |
| 1017 | 1564 | /// free to ignore this, since the error is already registered. |
| 1018 | pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void { | |
| 1019 | const tracy = trace(@src()); | |
| 1020 | defer tracy.end(); | |
| 1021 | ||
| 1022 | // TODO: document this elsewhere mlugg! | |
| 1023 | // For my own benefit, here's how a namespace update for a normal (non-file-root) type works: | |
| 1024 | // `const S = struct { ... };` | |
| 1025 | // We are adding or removing a declaration within this `struct`. | |
| 1026 | // * `S` registers a dependency on `.{ .src_hash = (declaration of S) }` | |
| 1027 | // * Any change to the `struct` body -- including changing a declaration -- invalidates this | |
| 1028 | // * `S` is re-analyzed, but notes: | |
| 1029 | // * there is an existing struct instance (at this `TrackedInst` with these captures) | |
| 1030 | // * the struct's resolution is up-to-date (because nothing about the fields changed) | |
| 1031 | // * so, it uses the same `struct` | |
| 1032 | // * but this doesn't stop it from updating the namespace! | |
| 1033 | // * we basically do `scanDecls`, updating the namespace as needed | |
| 1034 | // * so everyone lived happily ever after | |
| 1565 | pub fn ensureNavValUpToDate( | |
| 1566 | pt: Zcu.PerThread, | |
| 1567 | nav_id: InternPool.Nav.Index, | |
| 1568 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. | |
| 1569 | reason: ?*const Zcu.DependencyReason, | |
| 1570 | ) Zcu.SemaError!void { | |
| 1571 | const tracy_trace = trace(@src()); | |
| 1572 | defer tracy_trace.end(); | |
| 1035 | 1573 | |
| 1036 | 1574 | const zcu = pt.zcu; |
| 1037 | 1575 | const gpa = zcu.gpa; |
| 1038 | 1576 | const ip = &zcu.intern_pool; |
| 1039 | 1577 | |
| 1040 | _ = zcu.nav_val_analysis_queued.swapRemove(nav_id); | |
| 1041 | ||
| 1042 | 1578 | const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id }); |
| 1043 | 1579 | const nav = ip.getNav(nav_id); |
| 1044 | 1580 | |
| ... | ... | @@ -1046,6 +1582,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 1046 | 1582 | |
| 1047 | 1583 | assert(!zcu.analysis_in_progress.contains(anal_unit)); |
| 1048 | 1584 | |
| 1585 | try zcu.ensureNavValAnalysisQueued(nav_id); | |
| 1586 | ||
| 1049 | 1587 | // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the |
| 1050 | 1588 | // status is `.unresolved`, which indicates that the value is outdated because it has *never* |
| 1051 | 1589 | // been analyzed so far. |
| ... | ... | @@ -1055,30 +1593,18 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 1055 | 1593 | // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by |
| 1056 | 1594 | // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. |
| 1057 | 1595 | |
| 1058 | const was_outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 1059 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 1596 | const was_outdated = zcu.clearOutdatedState(anal_unit); | |
| 1060 | 1597 | |
| 1061 | 1598 | const prev_failed = zcu.failed_analysis.contains(anal_unit) or |
| 1062 | 1599 | zcu.transitive_failed_analysis.contains(anal_unit); |
| 1063 | 1600 | |
| 1064 | 1601 | if (was_outdated) { |
| 1065 | dev.check(.incremental); | |
| 1066 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 1067 | zcu.deleteUnitExports(anal_unit); | |
| 1068 | zcu.deleteUnitReferences(anal_unit); | |
| 1069 | zcu.deleteUnitCompileLogs(anal_unit); | |
| 1070 | if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { | |
| 1071 | kv.value.destroy(gpa); | |
| 1072 | } | |
| 1073 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | |
| 1074 | ip.removeDependenciesForDepender(gpa, anal_unit); | |
| 1602 | zcu.resetUnit(anal_unit); | |
| 1075 | 1603 | } else { |
| 1076 | 1604 | // We can trust the current information about this unit. |
| 1077 | 1605 | if (prev_failed) return error.AnalysisFail; |
| 1078 | switch (nav.status) { | |
| 1079 | .unresolved, .type_resolved => {}, | |
| 1080 | .fully_resolved => return, | |
| 1081 | } | |
| 1606 | assert(nav.status == .fully_resolved); | |
| 1607 | return; | |
| 1082 | 1608 | } |
| 1083 | 1609 | |
| 1084 | 1610 | if (zcu.comp.debugIncremental()) { |
| ... | ... | @@ -1090,7 +1616,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 1090 | 1616 | const unit_tracking = zcu.trackUnitSema(nav.fqn.toSlice(ip), nav.srcInst(ip)); |
| 1091 | 1617 | defer unit_tracking.end(zcu); |
| 1092 | 1618 | |
| 1093 | const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: { | |
| 1619 | const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id, reason)) |result| res: { | |
| 1094 | 1620 | break :res .{ |
| 1095 | 1621 | // If the unit has gone from failed to success, we still need to invalidate the dependencies. |
| 1096 | 1622 | result.val_changed or prev_failed, |
| ... | ... | @@ -1134,39 +1660,14 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 1134 | 1660 | } |
| 1135 | 1661 | } |
| 1136 | 1662 | |
| 1137 | // If there isn't a type annotation, then we have also just resolved the type. That means the | |
| 1138 | // the type is up-to-date, so it won't have the chance to mark its own dependency on the value; | |
| 1139 | // we must do that ourselves. | |
| 1140 | type_deps_on_val: { | |
| 1141 | const inst_resolved = nav.analysis.?.zir_index.resolveFull(ip) orelse break :type_deps_on_val; | |
| 1142 | const file = zcu.fileByIndex(inst_resolved.file); | |
| 1143 | const zir_decl = file.zir.?.getDeclaration(inst_resolved.inst); | |
| 1144 | if (zir_decl.type_body != null) break :type_deps_on_val; | |
| 1145 | // The type does indeed depend on the value. We are responsible for populating all state of | |
| 1146 | // the `nav_ty`, including exports, references, errors, and dependencies. | |
| 1147 | const ty_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id }); | |
| 1148 | const ty_was_outdated = zcu.outdated.swapRemove(ty_unit) or | |
| 1149 | zcu.potentially_outdated.swapRemove(ty_unit); | |
| 1150 | if (ty_was_outdated) { | |
| 1151 | _ = zcu.outdated_ready.swapRemove(ty_unit); | |
| 1152 | zcu.deleteUnitExports(ty_unit); | |
| 1153 | zcu.deleteUnitReferences(ty_unit); | |
| 1154 | zcu.deleteUnitCompileLogs(ty_unit); | |
| 1155 | if (zcu.failed_analysis.fetchSwapRemove(ty_unit)) |kv| { | |
| 1156 | kv.value.destroy(gpa); | |
| 1157 | } | |
| 1158 | _ = zcu.transitive_failed_analysis.swapRemove(ty_unit); | |
| 1159 | ip.removeDependenciesForDepender(gpa, ty_unit); | |
| 1160 | } | |
| 1161 | try pt.addDependency(ty_unit, .{ .nav_val = nav_id }); | |
| 1162 | if (new_failed) try zcu.transitive_failed_analysis.put(gpa, ty_unit, {}); | |
| 1163 | if (ty_was_outdated) try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id }); | |
| 1164 | } | |
| 1165 | ||
| 1166 | 1663 | if (new_failed) return error.AnalysisFail; |
| 1167 | 1664 | } |
| 1168 | 1665 | |
| 1169 | fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } { | |
| 1666 | fn analyzeNavVal( | |
| 1667 | pt: Zcu.PerThread, | |
| 1668 | nav_id: InternPool.Nav.Index, | |
| 1669 | reason: ?*const Zcu.DependencyReason, | |
| 1670 | ) Zcu.CompileError!struct { val_changed: bool } { | |
| 1170 | 1671 | const zcu = pt.zcu; |
| 1171 | 1672 | const ip = &zcu.intern_pool; |
| 1172 | 1673 | const comp = zcu.comp; |
| ... | ... | @@ -1183,16 +1684,8 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1183 | 1684 | const zir = file.zir.?; |
| 1184 | 1685 | const zir_decl = zir.getDeclaration(inst_resolved.inst); |
| 1185 | 1686 | |
| 1186 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); | |
| 1187 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | |
| 1188 | ||
| 1189 | // If there's no type body, we are also resolving the type here. | |
| 1190 | if (zir_decl.type_body == null) { | |
| 1191 | try zcu.analysis_in_progress.putNoClobber(gpa, .wrap(.{ .nav_ty = nav_id }), {}); | |
| 1192 | } | |
| 1193 | errdefer if (zir_decl.type_body == null) { | |
| 1194 | _ = zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id })); | |
| 1195 | }; | |
| 1687 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); | |
| 1688 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1196 | 1689 | |
| 1197 | 1690 | var analysis_arena: std.heap.ArenaAllocator = .init(gpa); |
| 1198 | 1691 | defer analysis_arena.deinit(); |
| ... | ... | @@ -1225,7 +1718,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1225 | 1718 | .parent = null, |
| 1226 | 1719 | .sema = &sema, |
| 1227 | 1720 | .namespace = old_nav.analysis.?.namespace, |
| 1228 | .instructions = .{}, | |
| 1721 | .instructions = .empty, | |
| 1229 | 1722 | .inlining = null, |
| 1230 | 1723 | .comptime_reason = undefined, // set below |
| 1231 | 1724 | .src_base_inst = old_nav.analysis.?.zir_index, |
| ... | ... | @@ -1246,9 +1739,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1246 | 1739 | |
| 1247 | 1740 | const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: { |
| 1248 | 1741 | // Since we have a type body, the type is resolved separately! |
| 1249 | // Of course, we need to make sure we depend on it properly. | |
| 1250 | try sema.declareDependency(.{ .nav_ty = nav_id }); | |
| 1251 | try pt.ensureNavTypeUpToDate(nav_id); | |
| 1742 | try sema.ensureNavResolved(&block, init_src, nav_id, .type); | |
| 1252 | 1743 | break :ty .fromInterned(ip.getNav(nav_id).typeOf(ip)); |
| 1253 | 1744 | } else null; |
| 1254 | 1745 | |
| ... | ... | @@ -1271,9 +1762,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1271 | 1762 | |
| 1272 | 1763 | const nav_ty: Type = maybe_ty orelse final_val.?.typeOf(zcu); |
| 1273 | 1764 | |
| 1274 | // First, we must resolve the declaration's type. To do this, we analyze the type body if available, | |
| 1275 | // or otherwise, we analyze the value body, populating `early_val` in the process. | |
| 1276 | ||
| 1277 | 1765 | const is_const = is_const: switch (zir_decl.kind) { |
| 1278 | 1766 | .@"comptime" => unreachable, // this is not a Nav |
| 1279 | 1767 | .unnamed_test, .@"test", .decltest => { |
| ... | ... | @@ -1360,7 +1848,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1360 | 1848 | |
| 1361 | 1849 | // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type, |
| 1362 | 1850 | // this resolves the type `type` (which needs no resolution), not the struct itself. |
| 1363 | try nav_ty.resolveLayout(pt); | |
| 1851 | try sema.ensureLayoutResolved(nav_ty, block.nodeOffset(.zero), if (zir_decl.kind == .@"var") .variable else .constant); | |
| 1364 | 1852 | |
| 1365 | 1853 | const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) { |
| 1366 | 1854 | .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen |
| ... | ... | @@ -1377,23 +1865,47 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1377 | 1865 | if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) { |
| 1378 | 1866 | return sema.fail(&block, align_src, "target does not support function alignment", .{}); |
| 1379 | 1867 | } |
| 1380 | } else if (try nav_ty.comptimeOnlySema(pt)) { | |
| 1868 | } else if (nav_ty.comptimeOnly(zcu)) { | |
| 1381 | 1869 | // alignment, linksection, addrspace annotations are not allowed for comptime-only types. |
| 1382 | const reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1870 | const cannot_align_reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1383 | 1871 | .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations* |
| 1384 | 1872 | else => "comptime-only type", |
| 1385 | 1873 | }; |
| 1386 | 1874 | if (zir_decl.align_body != null) { |
| 1387 | return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason}); | |
| 1875 | return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{cannot_align_reason}); | |
| 1388 | 1876 | } |
| 1389 | 1877 | if (zir_decl.linksection_body != null) { |
| 1390 | return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason}); | |
| 1878 | return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{cannot_align_reason}); | |
| 1391 | 1879 | } |
| 1392 | 1880 | if (zir_decl.addrspace_body != null) { |
| 1393 | return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason}); | |
| 1881 | return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{cannot_align_reason}); | |
| 1394 | 1882 | } |
| 1395 | 1883 | } |
| 1396 | 1884 | |
| 1885 | // We're about to resolve the value of the Nav. This causes the information about what the value | |
| 1886 | // was last update to be lost; therefore, if the `nav_ty` is currently out of date, it would | |
| 1887 | // incorrectly think it was unchanged when eventually analyzed. To avoid this, we need to detect | |
| 1888 | // that case and invalidate the dependee right now. | |
| 1889 | if (zcu.clearOutdatedState(.wrap(.{ .nav_ty = nav_id }))) { | |
| 1890 | assert(zir_decl.type_body == null); // otherwise we already resolved it with `Sema.ensureNavResolved` | |
| 1891 | zcu.resetUnit(.wrap(.{ .nav_ty = nav_id })); | |
| 1892 | try pt.addDependency(.wrap(.{ .nav_ty = nav_id }), .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!) | |
| 1893 | if (comp.debugIncremental()) { | |
| 1894 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, .wrap(.{ .nav_ty = nav_id })); | |
| 1895 | info.last_update_gen = zcu.generation; | |
| 1896 | info.deps.clearRetainingCapacity(); | |
| 1897 | } | |
| 1898 | const type_changed: bool = switch (old_nav.status) { | |
| 1899 | .unresolved => true, | |
| 1900 | .type_resolved => |old| old.type != nav_ty.toIntern(), | |
| 1901 | .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(), | |
| 1902 | }; | |
| 1903 | if (type_changed) { | |
| 1904 | try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id }); | |
| 1905 | } else { | |
| 1906 | try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id }); | |
| 1907 | } | |
| 1908 | } | |
| 1397 | 1909 | ip.resolveNavValue(io, nav_id, .{ |
| 1398 | 1910 | .val = nav_val.toIntern(), |
| 1399 | 1911 | .is_const = is_const, |
| ... | ... | @@ -1402,17 +1914,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1402 | 1914 | .@"addrspace" = modifiers.@"addrspace", |
| 1403 | 1915 | }); |
| 1404 | 1916 | |
| 1405 | // Mark the unit as completed before evaluating the export! | |
| 1406 | assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 1407 | if (zir_decl.type_body == null) { | |
| 1408 | assert(zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id }))); | |
| 1409 | } | |
| 1410 | ||
| 1411 | 1917 | if (zir_decl.linkage == .@"export") { |
| 1412 | 1918 | const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) }); |
| 1413 | 1919 | const name_slice = zir.nullTerminatedString(zir_decl.name); |
| 1414 | 1920 | const name_ip = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); |
| 1415 | try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id); | |
| 1921 | try sema.analyzeExportSelfNav(&block, export_src, name_ip); | |
| 1416 | 1922 | } |
| 1417 | 1923 | |
| 1418 | 1924 | try sema.flushExports(); |
| ... | ... | @@ -1420,25 +1926,37 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1420 | 1926 | queue_codegen: { |
| 1421 | 1927 | if (!queue_linker_work) break :queue_codegen; |
| 1422 | 1928 | |
| 1423 | if (!try nav_ty.hasRuntimeBitsSema(pt)) { | |
| 1424 | if (zcu.comp.config.use_llvm) break :queue_codegen; | |
| 1929 | if (!nav_ty.hasRuntimeBits(zcu)) { | |
| 1930 | if (comp.config.use_llvm) break :queue_codegen; | |
| 1425 | 1931 | if (file.mod.?.strip) break :queue_codegen; |
| 1426 | 1932 | } |
| 1427 | 1933 | |
| 1428 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 1429 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 1430 | try zcu.comp.queueJob(.{ .link_nav = nav_id }); | |
| 1934 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 1935 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .link_nav = nav_id }); | |
| 1431 | 1936 | } |
| 1432 | 1937 | |
| 1433 | switch (old_nav.status) { | |
| 1434 | .unresolved, .type_resolved => return .{ .val_changed = true }, | |
| 1435 | .fully_resolved => |old| return .{ .val_changed = old.val != nav_val.toIntern() }, | |
| 1938 | if (comp.config.is_test and zcu.test_functions.contains(nav_id)) { | |
| 1939 | // We just analyzed a test function's "value" (essentially its signature); now we need to | |
| 1940 | // implicitly reference the function *body*. `Zcu.resolveReferences` knows about this rule, | |
| 1941 | // so we don't need to mark an explicit reference, but we do need to make sure that the test | |
| 1942 | // body will actually get analyzed! | |
| 1943 | try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); | |
| 1436 | 1944 | } |
| 1945 | ||
| 1946 | return switch (old_nav.status) { | |
| 1947 | .unresolved, .type_resolved => .{ .val_changed = true }, | |
| 1948 | .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() }, | |
| 1949 | }; | |
| 1437 | 1950 | } |
| 1438 | 1951 | |
| 1439 | pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void { | |
| 1440 | const tracy = trace(@src()); | |
| 1441 | defer tracy.end(); | |
| 1952 | pub fn ensureNavTypeUpToDate( | |
| 1953 | pt: Zcu.PerThread, | |
| 1954 | nav_id: InternPool.Nav.Index, | |
| 1955 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. | |
| 1956 | reason: ?*const Zcu.DependencyReason, | |
| 1957 | ) Zcu.SemaError!void { | |
| 1958 | const tracy_trace = trace(@src()); | |
| 1959 | defer tracy_trace.end(); | |
| 1442 | 1960 | |
| 1443 | 1961 | const zcu = pt.zcu; |
| 1444 | 1962 | const gpa = zcu.gpa; |
| ... | ... | @@ -1451,17 +1969,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1451 | 1969 | |
| 1452 | 1970 | assert(!zcu.analysis_in_progress.contains(anal_unit)); |
| 1453 | 1971 | |
| 1454 | const type_resolved_by_value: bool = from_val: { | |
| 1455 | const analysis = nav.analysis orelse break :from_val false; | |
| 1456 | const inst_resolved = analysis.zir_index.resolveFull(ip) orelse break :from_val false; | |
| 1457 | const file = zcu.fileByIndex(inst_resolved.file); | |
| 1458 | const zir_decl = file.zir.?.getDeclaration(inst_resolved.inst); | |
| 1459 | break :from_val zir_decl.type_body == null; | |
| 1460 | }; | |
| 1461 | if (type_resolved_by_value) { | |
| 1462 | // Logic at the end of `ensureNavValUpToDate` is directly responsible for populating our state. | |
| 1463 | return pt.ensureNavValUpToDate(nav_id); | |
| 1464 | } | |
| 1972 | try zcu.ensureNavValAnalysisQueued(nav_id); | |
| 1465 | 1973 | |
| 1466 | 1974 | // Determine whether or not this `Nav`'s type is outdated. This also includes checking if the |
| 1467 | 1975 | // status is `.unresolved`, which indicates that the value is outdated because it has *never* |
| ... | ... | @@ -1472,30 +1980,18 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1472 | 1980 | // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by |
| 1473 | 1981 | // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. |
| 1474 | 1982 | |
| 1475 | const was_outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 1476 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 1983 | const was_outdated = zcu.clearOutdatedState(anal_unit); | |
| 1477 | 1984 | |
| 1478 | 1985 | const prev_failed = zcu.failed_analysis.contains(anal_unit) or |
| 1479 | 1986 | zcu.transitive_failed_analysis.contains(anal_unit); |
| 1480 | 1987 | |
| 1481 | 1988 | if (was_outdated) { |
| 1482 | dev.check(.incremental); | |
| 1483 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 1484 | zcu.deleteUnitExports(anal_unit); | |
| 1485 | zcu.deleteUnitReferences(anal_unit); | |
| 1486 | zcu.deleteUnitCompileLogs(anal_unit); | |
| 1487 | if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { | |
| 1488 | kv.value.destroy(gpa); | |
| 1489 | } | |
| 1490 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | |
| 1491 | ip.removeDependenciesForDepender(gpa, anal_unit); | |
| 1989 | zcu.resetUnit(anal_unit); | |
| 1492 | 1990 | } else { |
| 1493 | 1991 | // We can trust the current information about this unit. |
| 1494 | 1992 | if (prev_failed) return error.AnalysisFail; |
| 1495 | switch (nav.status) { | |
| 1496 | .unresolved => {}, | |
| 1497 | .type_resolved, .fully_resolved => return, | |
| 1498 | } | |
| 1993 | assert(nav.status != .unresolved); | |
| 1994 | return; | |
| 1499 | 1995 | } |
| 1500 | 1996 | |
| 1501 | 1997 | if (zcu.comp.debugIncremental()) { |
| ... | ... | @@ -1507,7 +2003,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1507 | 2003 | const unit_tracking = zcu.trackUnitSema(nav.fqn.toSlice(ip), nav.srcInst(ip)); |
| 1508 | 2004 | defer unit_tracking.end(zcu); |
| 1509 | 2005 | |
| 1510 | const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: { | |
| 2006 | const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id, reason)) |result| res: { | |
| 1511 | 2007 | break :res .{ |
| 1512 | 2008 | // If the unit has gone from failed to success, we still need to invalidate the dependencies. |
| 1513 | 2009 | result.type_changed or prev_failed, |
| ... | ... | @@ -1554,7 +2050,11 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1554 | 2050 | if (new_failed) return error.AnalysisFail; |
| 1555 | 2051 | } |
| 1556 | 2052 | |
| 1557 | fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } { | |
| 2053 | fn analyzeNavType( | |
| 2054 | pt: Zcu.PerThread, | |
| 2055 | nav_id: InternPool.Nav.Index, | |
| 2056 | reason: ?*const Zcu.DependencyReason, | |
| 2057 | ) Zcu.CompileError!struct { type_changed: bool } { | |
| 1558 | 2058 | const zcu = pt.zcu; |
| 1559 | 2059 | const comp = zcu.comp; |
| 1560 | 2060 | const gpa = comp.gpa; |
| ... | ... | @@ -1570,11 +2070,10 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1570 | 2070 | const file = zcu.fileByIndex(inst_resolved.file); |
| 1571 | 2071 | const zir = file.zir.?; |
| 1572 | 2072 | |
| 1573 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); | |
| 2073 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); | |
| 1574 | 2074 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); |
| 1575 | 2075 | |
| 1576 | 2076 | const zir_decl = zir.getDeclaration(inst_resolved.inst); |
| 1577 | const type_body = zir_decl.type_body.?; | |
| 1578 | 2077 | |
| 1579 | 2078 | var analysis_arena: std.heap.ArenaAllocator = .init(gpa); |
| 1580 | 2079 | defer analysis_arena.deinit(); |
| ... | ... | @@ -1607,7 +2106,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1607 | 2106 | .parent = null, |
| 1608 | 2107 | .sema = &sema, |
| 1609 | 2108 | .namespace = old_nav.analysis.?.namespace, |
| 1610 | .instructions = .{}, | |
| 2109 | .instructions = .empty, | |
| 1611 | 2110 | .inlining = null, |
| 1612 | 2111 | .comptime_reason = undefined, // set below |
| 1613 | 2112 | .src_base_inst = old_nav.analysis.?.zir_index, |
| ... | ... | @@ -1616,6 +2115,34 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1616 | 2115 | defer block.instructions.deinit(gpa); |
| 1617 | 2116 | |
| 1618 | 2117 | const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero }); |
| 2118 | const init_src = block.src(.{ .node_offset_var_decl_init = .zero }); | |
| 2119 | ||
| 2120 | const type_body = zir_decl.type_body orelse { | |
| 2121 | // There is no type annotation, so we just need to use the declaration's value. | |
| 2122 | // If the value had already been re-analyzed, it would have resolved the `nav_ty` unit as | |
| 2123 | // either outdated or up-to-date. So we know that `old_nav` does contain information from | |
| 2124 | // the previous update. As such, after this call, we will be able to determine whether the | |
| 2125 | // type changed. | |
| 2126 | try sema.ensureNavResolved(&block, init_src, nav_id, .fully); | |
| 2127 | const new = ip.getNav(nav_id).status.fully_resolved; | |
| 2128 | const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern"; | |
| 2129 | const changed = switch (old_nav.status) { | |
| 2130 | .unresolved => true, | |
| 2131 | .type_resolved => |r| r.type != ip.typeOf(new.val) or | |
| 2132 | r.alignment != new.alignment or | |
| 2133 | r.@"linksection" != new.@"linksection" or | |
| 2134 | r.@"addrspace" != new.@"addrspace" or | |
| 2135 | r.is_const != new.is_const or | |
| 2136 | r.is_extern_decl != new_is_extern_decl, | |
| 2137 | .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or | |
| 2138 | r.alignment != new.alignment or | |
| 2139 | r.@"linksection" != new.@"linksection" or | |
| 2140 | r.@"addrspace" != new.@"addrspace" or | |
| 2141 | r.is_const != new.is_const or | |
| 2142 | (old_nav.getExtern(ip) != null) != new_is_extern_decl, | |
| 2143 | }; | |
| 2144 | return .{ .type_changed = changed }; | |
| 2145 | }; | |
| 1619 | 2146 | |
| 1620 | 2147 | block.comptime_reason = .{ .reason = .{ |
| 1621 | 2148 | .src = ty_src, |
| ... | ... | @@ -1628,7 +2155,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1628 | 2155 | break :ty .fromInterned(type_ref.toInterned().?); |
| 1629 | 2156 | }; |
| 1630 | 2157 | |
| 1631 | try resolved_ty.resolveLayout(pt); | |
| 2158 | try sema.ensureLayoutResolved(resolved_ty, block.nodeOffset(.zero), if (zir_decl.kind == .@"var") .variable else .constant); | |
| 1632 | 2159 | |
| 1633 | 2160 | // In the case where the type is specified, this function is also responsible for resolving |
| 1634 | 2161 | // the pointer modifiers, i.e. alignment, linksection, addrspace. |
| ... | ... | @@ -1678,18 +2205,24 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1678 | 2205 | return .{ .type_changed = true }; |
| 1679 | 2206 | } |
| 1680 | 2207 | |
| 1681 | pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!void { | |
| 2208 | /// If `func_index` is not a runtime function (e.g. it has a comptime-only parameter type) then it | |
| 2209 | /// is still valid to call this function and use its `func_body` unit in general---analysis of the | |
| 2210 | /// runtime function body will simply fail. | |
| 2211 | pub fn ensureFuncBodyUpToDate( | |
| 2212 | pt: Zcu.PerThread, | |
| 2213 | func_index: InternPool.Index, | |
| 2214 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. | |
| 2215 | reason: ?*const Zcu.DependencyReason, | |
| 2216 | ) Zcu.SemaError!void { | |
| 1682 | 2217 | dev.check(.sema); |
| 1683 | 2218 | |
| 1684 | const tracy = trace(@src()); | |
| 1685 | defer tracy.end(); | |
| 2219 | const tracy_trace = trace(@src()); | |
| 2220 | defer tracy_trace.end(); | |
| 1686 | 2221 | |
| 1687 | 2222 | const zcu = pt.zcu; |
| 1688 | 2223 | const gpa = zcu.gpa; |
| 1689 | 2224 | const ip = &zcu.intern_pool; |
| 1690 | 2225 | |
| 1691 | _ = zcu.func_body_analysis_queued.swapRemove(func_index); | |
| 1692 | ||
| 1693 | 2226 | const anal_unit: AnalUnit = .wrap(.{ .func = func_index }); |
| 1694 | 2227 | |
| 1695 | 2228 | log.debug("ensureFuncBodyUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); |
| ... | ... | @@ -1700,27 +2233,17 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z |
| 1700 | 2233 | |
| 1701 | 2234 | assert(func.ty == func.uncoerced_ty); // analyze the body of the original function, not a coerced one |
| 1702 | 2235 | |
| 1703 | const was_outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 1704 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 2236 | const was_outdated = zcu.clearOutdatedState(anal_unit) or | |
| 2237 | ip.setWantRuntimeFnAnalysis(zcu.comp.io, func_index); | |
| 1705 | 2238 | |
| 1706 | 2239 | const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); |
| 1707 | 2240 | |
| 1708 | 2241 | if (was_outdated) { |
| 1709 | dev.check(.incremental); | |
| 1710 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 1711 | zcu.deleteUnitExports(anal_unit); | |
| 1712 | zcu.deleteUnitReferences(anal_unit); | |
| 1713 | zcu.deleteUnitCompileLogs(anal_unit); | |
| 1714 | if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { | |
| 1715 | kv.value.destroy(gpa); | |
| 1716 | } | |
| 1717 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | |
| 2242 | zcu.resetUnit(anal_unit); | |
| 1718 | 2243 | } else { |
| 1719 | 2244 | // We can trust the current information about this function. |
| 1720 | if (prev_failed) { | |
| 1721 | return error.AnalysisFail; | |
| 1722 | } | |
| 1723 | if (func.analysisUnordered(ip).is_analyzed) return; | |
| 2245 | if (prev_failed) return error.AnalysisFail; | |
| 2246 | return; | |
| 1724 | 2247 | } |
| 1725 | 2248 | |
| 1726 | 2249 | if (zcu.comp.debugIncremental()) { |
| ... | ... | @@ -1736,7 +2259,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z |
| 1736 | 2259 | ); |
| 1737 | 2260 | defer unit_tracking.end(zcu); |
| 1738 | 2261 | |
| 1739 | const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result| | |
| 2262 | const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result| | |
| 1740 | 2263 | .{ prev_failed or result.ies_outdated, false } |
| 1741 | 2264 | else |err| switch (err) { |
| 1742 | 2265 | error.AnalysisFail => res: { |
| ... | ... | @@ -1765,9 +2288,9 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z |
| 1765 | 2288 | |
| 1766 | 2289 | if (was_outdated) { |
| 1767 | 2290 | if (ies_outdated) { |
| 1768 | try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index }); | |
| 2291 | try zcu.markDependeeOutdated(.marked_po, .{ .func_ies = func_index }); | |
| 1769 | 2292 | } else { |
| 1770 | try zcu.markPoDependeeUpToDate(.{ .interned = func_index }); | |
| 2293 | try zcu.markPoDependeeUpToDate(.{ .func_ies = func_index }); | |
| 1771 | 2294 | } |
| 1772 | 2295 | } |
| 1773 | 2296 | |
| ... | ... | @@ -1777,6 +2300,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z |
| 1777 | 2300 | fn analyzeFuncBody( |
| 1778 | 2301 | pt: Zcu.PerThread, |
| 1779 | 2302 | func_index: InternPool.Index, |
| 2303 | reason: ?*const Zcu.DependencyReason, | |
| 1780 | 2304 | ) Zcu.SemaError!struct { ies_outdated: bool } { |
| 1781 | 2305 | const zcu = pt.zcu; |
| 1782 | 2306 | const gpa = zcu.gpa; |
| ... | ... | @@ -1785,29 +2309,6 @@ fn analyzeFuncBody( |
| 1785 | 2309 | const func = zcu.funcInfo(func_index); |
| 1786 | 2310 | const anal_unit = AnalUnit.wrap(.{ .func = func_index }); |
| 1787 | 2311 | |
| 1788 | // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing | |
| 1789 | // it would be a waste of time in the best case, and could cause codegen to give bogus | |
| 1790 | // results in the worst case. | |
| 1791 | ||
| 1792 | if (func.generic_owner == .none) { | |
| 1793 | // Among another things, this ensures that the function's `zir_body_inst` is correct. | |
| 1794 | try pt.ensureNavValUpToDate(func.owner_nav); | |
| 1795 | if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) { | |
| 1796 | // This function is no longer referenced! There's no point in re-analyzing it. | |
| 1797 | // Just mark a transitive failure and move on. | |
| 1798 | return error.AnalysisFail; | |
| 1799 | } | |
| 1800 | } else { | |
| 1801 | const go_nav = zcu.funcInfo(func.generic_owner).owner_nav; | |
| 1802 | // Among another things, this ensures that the function's `zir_body_inst` is correct. | |
| 1803 | try pt.ensureNavValUpToDate(go_nav); | |
| 1804 | if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) { | |
| 1805 | // The generic owner is no longer referenced, so this function is also unreferenced. | |
| 1806 | // There's no point in re-analyzing it. Just mark a transitive failure and move on. | |
| 1807 | return error.AnalysisFail; | |
| 1808 | } | |
| 1809 | } | |
| 1810 | ||
| 1811 | 2312 | // We'll want to remember what the IES used to be before the update for |
| 1812 | 2313 | // dependency invalidation purposes. |
| 1813 | 2314 | const old_resolved_ies = if (func.analysisUnordered(ip).inferred_error_set) |
| ... | ... | @@ -1817,8 +2318,9 @@ fn analyzeFuncBody( |
| 1817 | 2318 | |
| 1818 | 2319 | log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)}); |
| 1819 | 2320 | |
| 1820 | var air = try pt.analyzeFnBodyInner(func_index); | |
| 1821 | errdefer air.deinit(gpa); | |
| 2321 | var air = try pt.analyzeFuncBodyInner(func_index, reason); | |
| 2322 | var air_owned = true; | |
| 2323 | defer if (air_owned) air.deinit(gpa); | |
| 1822 | 2324 | |
| 1823 | 2325 | const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or |
| 1824 | 2326 | func.resolvedErrorSetUnordered(ip) != old_resolved_ies; |
| ... | ... | @@ -1828,103 +2330,24 @@ fn analyzeFuncBody( |
| 1828 | 2330 | const dump_air = build_options.enable_debug_extensions and comp.verbose_air; |
| 1829 | 2331 | const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); |
| 1830 | 2332 | |
| 1831 | if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) { | |
| 1832 | air.deinit(gpa); | |
| 1833 | return .{ .ies_outdated = ies_outdated }; | |
| 1834 | } | |
| 1835 | ||
| 1836 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 1837 | zcu.codegen_prog_node.increaseEstimatedTotalItems(1); | |
| 1838 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 1839 | try comp.queueJob(.{ .codegen_func = .{ | |
| 1840 | .func = func_index, | |
| 1841 | .air = air, | |
| 1842 | } }); | |
| 1843 | ||
| 1844 | return .{ .ies_outdated = ies_outdated }; | |
| 1845 | } | |
| 1846 | ||
| 1847 | pub fn semaMod(pt: Zcu.PerThread, mod: *Module) !void { | |
| 1848 | dev.check(.sema); | |
| 1849 | const file_index = pt.zcu.module_roots.get(mod).?.unwrap().?; | |
| 1850 | const root_type = pt.zcu.fileRootType(file_index); | |
| 1851 | if (root_type == .none) { | |
| 1852 | return pt.semaFile(file_index); | |
| 1853 | } | |
| 1854 | } | |
| 1855 | ||
| 1856 | fn createFileRootStruct( | |
| 1857 | pt: Zcu.PerThread, | |
| 1858 | file_index: Zcu.File.Index, | |
| 1859 | namespace_index: Zcu.Namespace.Index, | |
| 1860 | replace_existing: bool, | |
| 1861 | ) Allocator.Error!InternPool.Index { | |
| 1862 | const zcu = pt.zcu; | |
| 1863 | const gpa = zcu.gpa; | |
| 1864 | const io = zcu.comp.io; | |
| 1865 | const ip = &zcu.intern_pool; | |
| 1866 | const file = zcu.fileByIndex(file_index); | |
| 1867 | const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | |
| 1868 | assert(extended.opcode == .struct_decl); | |
| 1869 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 1870 | assert(!small.has_captures_len); | |
| 1871 | assert(!small.has_backing_int); | |
| 1872 | assert(small.layout == .auto); | |
| 1873 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; | |
| 1874 | const fields_len = if (small.has_fields_len) blk: { | |
| 1875 | const fields_len = file.zir.?.extra[extra_index]; | |
| 1876 | extra_index += 1; | |
| 1877 | break :blk fields_len; | |
| 1878 | } else 0; | |
| 1879 | const decls_len = if (small.has_decls_len) blk: { | |
| 1880 | const decls_len = file.zir.?.extra[extra_index]; | |
| 1881 | extra_index += 1; | |
| 1882 | break :blk decls_len; | |
| 1883 | } else 0; | |
| 1884 | const decls = file.zir.?.bodySlice(extra_index, decls_len); | |
| 1885 | extra_index += decls_len; | |
| 2333 | if (comp.bin_file != null or zcu.llvm_object != null or dump_air or dump_llvm_ir) { | |
| 2334 | zcu.codegen_prog_node.increaseEstimatedTotalItems(1); | |
| 2335 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 1886 | 2336 | |
| 1887 | const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ | |
| 1888 | .file = file_index, | |
| 1889 | .inst = .main_struct_inst, | |
| 1890 | }); | |
| 1891 | const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ | |
| 1892 | .layout = .auto, | |
| 1893 | .fields_len = fields_len, | |
| 1894 | .known_non_opv = small.known_non_opv, | |
| 1895 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, | |
| 1896 | .any_comptime_fields = small.any_comptime_fields, | |
| 1897 | .any_default_inits = small.any_default_inits, | |
| 1898 | .inits_resolved = false, | |
| 1899 | .any_aligned_fields = small.any_aligned_fields, | |
| 1900 | .key = .{ .declared = .{ | |
| 1901 | .zir_index = tracked_inst, | |
| 1902 | .captures = &.{}, | |
| 1903 | } }, | |
| 1904 | }, replace_existing)) { | |
| 1905 | .existing => unreachable, // we wouldn't be analysing the file root if this type existed | |
| 1906 | .wip => |wip| wip, | |
| 1907 | }; | |
| 1908 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 2337 | // Some linkers need to refer to the AIR. In that case, the linker is not running | |
| 2338 | // concurrently, so we'll just keep ownership of the AIR for ourselves instead of | |
| 2339 | // letting the codegen job destroy it. | |
| 2340 | const disown_air = zcu.backendSupportsFeature(.separate_thread); | |
| 1909 | 2341 | |
| 1910 | wip_ty.setName(ip, try file.internFullyQualifiedName(pt), .none); | |
| 1911 | ip.namespacePtr(namespace_index).owner_type = wip_ty.index; | |
| 2342 | // Begin the codegen task. If the codegen/link queue is backed up, this might | |
| 2343 | // block until the linker is able to process some tasks. | |
| 2344 | const codegen_task = try zcu.codegen_task_pool.start(zcu, func_index, &air, disown_air); | |
| 2345 | if (disown_air) air_owned = false; | |
| 1912 | 2346 | |
| 1913 | if (zcu.comp.config.incremental) { | |
| 1914 | try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); | |
| 2347 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .link_func = codegen_task }); | |
| 1915 | 2348 | } |
| 1916 | 2349 | |
| 1917 | try pt.scanNamespace(namespace_index, decls); | |
| 1918 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 1919 | codegen_type: { | |
| 1920 | if (file.mod.?.strip) break :codegen_type; | |
| 1921 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 1922 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 1923 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 1924 | } | |
| 1925 | zcu.setFileRootType(file_index, wip_ty.index); | |
| 1926 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 1927 | return wip_ty.finish(ip, namespace_index); | |
| 2350 | return .{ .ies_outdated = ies_outdated }; | |
| 1928 | 2351 | } |
| 1929 | 2352 | |
| 1930 | 2353 | /// Re-scan the namespace of a file's root struct type on an incremental update. |
| ... | ... | @@ -1945,48 +2368,11 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator. |
| 1945 | 2368 | }); |
| 1946 | 2369 | |
| 1947 | 2370 | const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu); |
| 1948 | const decls = decls: { | |
| 1949 | const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | |
| 1950 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 1951 | ||
| 1952 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; | |
| 1953 | extra_index += @intFromBool(small.has_fields_len); | |
| 1954 | const decls_len = if (small.has_decls_len) blk: { | |
| 1955 | const decls_len = file.zir.?.extra[extra_index]; | |
| 1956 | extra_index += 1; | |
| 1957 | break :blk decls_len; | |
| 1958 | } else 0; | |
| 1959 | break :decls file.zir.?.bodySlice(extra_index, decls_len); | |
| 1960 | }; | |
| 2371 | const decls = file.zir.?.getStructDecl(.main_struct_inst).decls; | |
| 1961 | 2372 | try pt.scanNamespace(namespace_index, decls); |
| 1962 | 2373 | zcu.namespacePtr(namespace_index).generation = zcu.generation; |
| 1963 | 2374 | } |
| 1964 | 2375 | |
| 1965 | fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { | |
| 1966 | const tracy = trace(@src()); | |
| 1967 | defer tracy.end(); | |
| 1968 | ||
| 1969 | const zcu = pt.zcu; | |
| 1970 | const file = zcu.fileByIndex(file_index); | |
| 1971 | assert(file.getMode() == .zig); | |
| 1972 | assert(zcu.fileRootType(file_index) == .none); | |
| 1973 | ||
| 1974 | assert(file.zir != null); | |
| 1975 | ||
| 1976 | const new_namespace_index = try pt.createNamespace(.{ | |
| 1977 | .parent = .none, | |
| 1978 | .owner_type = undefined, // set in `createFileRootStruct` | |
| 1979 | .file_scope = file_index, | |
| 1980 | .generation = zcu.generation, | |
| 1981 | }); | |
| 1982 | const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false); | |
| 1983 | errdefer zcu.intern_pool.remove(pt.tid, struct_ty); | |
| 1984 | ||
| 1985 | if (zcu.comp.time_report) |*tr| { | |
| 1986 | tr.stats.n_imported_files += 1; | |
| 1987 | } | |
| 1988 | } | |
| 1989 | ||
| 1990 | 2376 | /// Called by AstGen worker threads when an import is seen. If `new_file` is returned, the caller is |
| 1991 | 2377 | /// then responsible for queueing a new AstGen job for the new file. |
| 1992 | 2378 | /// Assumes that `comp.mutex` is NOT locked. It will be locked by this function where necessary. |
| ... | ... | @@ -2214,7 +2600,7 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{ |
| 2214 | 2600 | /// modify `pt.zcu.skip_analysis_this_update`. |
| 2215 | 2601 | /// |
| 2216 | 2602 | /// If an error is returned, `pt.zcu.alive_files` might contain undefined values. |
| 2217 | pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { | |
| 2603 | fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { | |
| 2218 | 2604 | const zcu = pt.zcu; |
| 2219 | 2605 | const comp = zcu.comp; |
| 2220 | 2606 | const gpa = zcu.gpa; |
| ... | ... | @@ -2655,8 +3041,8 @@ pub fn scanNamespace( |
| 2655 | 3041 | namespace_index: Zcu.Namespace.Index, |
| 2656 | 3042 | decls: []const Zir.Inst.Index, |
| 2657 | 3043 | ) Allocator.Error!void { |
| 2658 | const tracy = trace(@src()); | |
| 2659 | defer tracy.end(); | |
| 3044 | const tracy_trace = trace(@src()); | |
| 3045 | defer tracy_trace.end(); | |
| 2660 | 3046 | |
| 2661 | 3047 | const zcu = pt.zcu; |
| 2662 | 3048 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -2752,8 +3138,8 @@ const ScanDeclIter = struct { |
| 2752 | 3138 | } |
| 2753 | 3139 | |
| 2754 | 3140 | fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void { |
| 2755 | const tracy = trace(@src()); | |
| 2756 | defer tracy.end(); | |
| 3141 | const tracy_trace = trace(@src()); | |
| 3142 | defer tracy_trace.end(); | |
| 2757 | 3143 | |
| 2758 | 3144 | const pt = iter.pt; |
| 2759 | 3145 | const zcu = pt.zcu; |
| ... | ... | @@ -2806,89 +3192,76 @@ const ScanDeclIter = struct { |
| 2806 | 3192 | |
| 2807 | 3193 | const existing_unit = iter.existing_by_inst.get(tracked_inst); |
| 2808 | 3194 | |
| 2809 | const unit, const want_analysis = switch (decl.kind) { | |
| 2810 | .@"comptime" => unit: { | |
| 2811 | const cu = if (existing_unit) |eu| | |
| 2812 | eu.unwrap().@"comptime" | |
| 2813 | else | |
| 2814 | try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); | |
| 2815 | ||
| 2816 | const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); | |
| 2817 | ||
| 3195 | const name = maybe_name.unwrap() orelse { | |
| 3196 | // Only `comptime` declarations are unnamed. | |
| 3197 | assert(decl.kind == .@"comptime"); | |
| 3198 | if (existing_unit) |unit| { | |
| 3199 | try namespace.comptime_decls.append(gpa, unit.unwrap().@"comptime"); | |
| 3200 | } else { | |
| 3201 | const cu = try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); | |
| 3202 | try zcu.queueComptimeUnitAnalysis(cu); | |
| 2818 | 3203 | try namespace.comptime_decls.append(gpa, cu); |
| 3204 | } | |
| 3205 | return; | |
| 3206 | }; | |
| 2819 | 3207 | |
| 2820 | if (existing_unit == null) { | |
| 2821 | // For a `comptime` declaration, whether to analyze is based solely on whether the unit | |
| 2822 | // is outdated. So, add this fresh one to `outdated` and `outdated_ready`. | |
| 2823 | try zcu.outdated.ensureUnusedCapacity(gpa, 1); | |
| 2824 | try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); | |
| 2825 | zcu.outdated.putAssumeCapacityNoClobber(unit, 0); | |
| 2826 | zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); | |
| 2827 | } | |
| 3208 | const fqn = try namespace.internFullyQualifiedName(ip, gpa, io, pt.tid, name); | |
| 3209 | ||
| 3210 | const nav = if (existing_unit) |unit| nav: { | |
| 3211 | const nav = unit.unwrap().nav_val; | |
| 3212 | assert(ip.getNav(nav).name == name); | |
| 3213 | assert(ip.getNav(nav).fqn == fqn); | |
| 3214 | break :nav nav; | |
| 3215 | } else nav: { | |
| 3216 | const nav = try ip.createDeclNav(gpa, io, pt.tid, name, fqn, tracked_inst, namespace_index); | |
| 3217 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); | |
| 3218 | break :nav nav; | |
| 3219 | }; | |
| 2828 | 3220 | |
| 2829 | break :unit .{ unit, true }; | |
| 3221 | const want_analysis: bool = switch (decl.kind) { | |
| 3222 | .@"comptime" => unreachable, | |
| 3223 | .unnamed_test, .@"test", .decltest => a: { | |
| 3224 | const is_named = decl.kind != .unnamed_test; | |
| 3225 | try namespace.test_decls.append(gpa, nav); | |
| 3226 | // TODO: incremental compilation! | |
| 3227 | // * remove from `test_functions` if no longer matching filter | |
| 3228 | // * add to `test_functions` if newly passing filter | |
| 3229 | // This logic is unaware of incremental: we'll end up with duplicates. | |
| 3230 | // Perhaps we should add all test indiscriminately and filter at the end of the update. | |
| 3231 | if (!comp.config.is_test) break :a false; | |
| 3232 | if (file.mod != zcu.main_mod) break :a false; | |
| 3233 | if (is_named and comp.test_filters.len > 0) { | |
| 3234 | const fqn_slice = fqn.toSlice(ip); | |
| 3235 | for (comp.test_filters) |test_filter| { | |
| 3236 | if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break; | |
| 3237 | } else break :a false; | |
| 3238 | } | |
| 3239 | try zcu.test_functions.put(gpa, nav, {}); | |
| 3240 | break :a true; | |
| 2830 | 3241 | }, |
| 2831 | else => unit: { | |
| 2832 | const name = maybe_name.unwrap().?; | |
| 2833 | const fqn = try namespace.internFullyQualifiedName(ip, gpa, io, pt.tid, name); | |
| 2834 | const nav = if (existing_unit) |eu| eu.unwrap().nav_val else nav: { | |
| 2835 | const nav = try ip.createDeclNav(gpa, io, pt.tid, name, fqn, tracked_inst, namespace_index); | |
| 2836 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); | |
| 2837 | break :nav nav; | |
| 2838 | }; | |
| 2839 | ||
| 2840 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); | |
| 2841 | ||
| 2842 | assert(ip.getNav(nav).name == name); | |
| 2843 | assert(ip.getNav(nav).fqn == fqn); | |
| 2844 | ||
| 2845 | const want_analysis = switch (decl.kind) { | |
| 2846 | .@"comptime" => unreachable, | |
| 2847 | .unnamed_test, .@"test", .decltest => a: { | |
| 2848 | const is_named = decl.kind != .unnamed_test; | |
| 2849 | try namespace.test_decls.append(gpa, nav); | |
| 2850 | // TODO: incremental compilation! | |
| 2851 | // * remove from `test_functions` if no longer matching filter | |
| 2852 | // * add to `test_functions` if newly passing filter | |
| 2853 | // This logic is unaware of incremental: we'll end up with duplicates. | |
| 2854 | // Perhaps we should add all test indiscriminately and filter at the end of the update. | |
| 2855 | if (!comp.config.is_test) break :a false; | |
| 2856 | if (file.mod != zcu.main_mod) break :a false; | |
| 2857 | if (is_named and comp.test_filters.len > 0) { | |
| 2858 | const fqn_slice = fqn.toSlice(ip); | |
| 2859 | for (comp.test_filters) |test_filter| { | |
| 2860 | if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break; | |
| 2861 | } else break :a false; | |
| 2862 | } | |
| 2863 | try zcu.test_functions.put(gpa, nav, {}); | |
| 2864 | break :a true; | |
| 2865 | }, | |
| 2866 | .@"const", .@"var" => a: { | |
| 2867 | if (decl.is_pub) { | |
| 2868 | try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); | |
| 2869 | } else { | |
| 2870 | try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); | |
| 2871 | } | |
| 2872 | break :a false; | |
| 2873 | }, | |
| 2874 | }; | |
| 2875 | break :unit .{ unit, want_analysis }; | |
| 3242 | .@"const", .@"var" => a: { | |
| 3243 | if (decl.is_pub) { | |
| 3244 | try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); | |
| 3245 | } else { | |
| 3246 | try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); | |
| 3247 | } | |
| 3248 | break :a false; | |
| 2876 | 3249 | }, |
| 2877 | 3250 | }; |
| 2878 | 3251 | |
| 2879 | if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) { | |
| 2880 | log.debug( | |
| 2881 | "scanDecl queue analyze_comptime_unit file='{s}' unit={f}", | |
| 2882 | .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) }, | |
| 2883 | ); | |
| 2884 | try comp.queueJob(.{ .analyze_comptime_unit = unit }); | |
| 3252 | if (want_analysis or decl.linkage == .@"export") { | |
| 3253 | try zcu.ensureNavValAnalysisQueued(nav); | |
| 2885 | 3254 | } |
| 2886 | 3255 | } |
| 2887 | 3256 | }; |
| 2888 | 3257 | |
| 2889 | fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air { | |
| 2890 | const tracy = trace(@src()); | |
| 2891 | defer tracy.end(); | |
| 3258 | fn analyzeFuncBodyInner( | |
| 3259 | pt: Zcu.PerThread, | |
| 3260 | func_index: InternPool.Index, | |
| 3261 | reason: ?*const Zcu.DependencyReason, | |
| 3262 | ) Zcu.SemaError!Air { | |
| 3263 | const tracy_trace = trace(@src()); | |
| 3264 | defer tracy_trace.end(); | |
| 2892 | 3265 | |
| 2893 | 3266 | const zcu = pt.zcu; |
| 2894 | 3267 | const comp = zcu.comp; |
| ... | ... | @@ -2898,17 +3271,18 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2898 | 3271 | |
| 2899 | 3272 | const anal_unit = AnalUnit.wrap(.{ .func = func_index }); |
| 2900 | 3273 | const func = zcu.funcInfo(func_index); |
| 2901 | const inst_info = func.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; | |
| 2902 | const file = zcu.fileByIndex(inst_info.file); | |
| 2903 | const zir = file.zir.?; | |
| 2904 | 3274 | |
| 2905 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); | |
| 2906 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | |
| 3275 | // This is the `Nav` corresponding to the `declaration` instruction which the function or its generic owner originates from. | |
| 3276 | const decl_analysis = if (func.generic_owner == .none) | |
| 3277 | ip.getNav(func.owner_nav).analysis.? | |
| 3278 | else | |
| 3279 | ip.getNav(zcu.funcInfo(func.generic_owner).owner_nav).analysis.?; | |
| 2907 | 3280 | |
| 2908 | func.setAnalyzed(ip, io); | |
| 2909 | if (func.analysisUnordered(ip).inferred_error_set) { | |
| 2910 | func.setResolvedErrorSet(ip, io, .none); | |
| 2911 | } | |
| 3281 | const file = zcu.fileByIndex(decl_analysis.zir_index.resolveFile(ip)); | |
| 3282 | const zir = file.zir.?; | |
| 3283 | ||
| 3284 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); | |
| 3285 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 2912 | 3286 | |
| 2913 | 3287 | if (zcu.comp.time_report) |*tr| { |
| 2914 | 3288 | if (func.generic_owner != .none) { |
| ... | ... | @@ -2916,16 +3290,8 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2916 | 3290 | } |
| 2917 | 3291 | } |
| 2918 | 3292 | |
| 2919 | // This is the `Nau` corresponding to the `declaration` instruction which the function or its generic owner originates from. | |
| 2920 | const decl_nav = ip.getNav(if (func.generic_owner == .none) | |
| 2921 | func.owner_nav | |
| 2922 | else | |
| 2923 | zcu.funcInfo(func.generic_owner).owner_nav); | |
| 2924 | ||
| 2925 | 3293 | const func_nav = ip.getNav(func.owner_nav); |
| 2926 | 3294 | |
| 2927 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 2928 | ||
| 2929 | 3295 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| 2930 | 3296 | defer analysis_arena.deinit(); |
| 2931 | 3297 | |
| ... | ... | @@ -2957,9 +3323,30 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2957 | 3323 | |
| 2958 | 3324 | // Every runtime function has a dependency on the source of the Decl it originates from. |
| 2959 | 3325 | // It also depends on the value of its owner Decl. |
| 2960 | try sema.declareDependency(.{ .src_hash = decl_nav.analysis.?.zir_index }); | |
| 3326 | try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index }); | |
| 2961 | 3327 | try sema.declareDependency(.{ .nav_val = func.owner_nav }); |
| 2962 | 3328 | |
| 3329 | // Make sure that the declaration `Nav` still refers to this function (or its generic owner). | |
| 3330 | // This will not be the case if the incremental update has changed a function type or turned a | |
| 3331 | // `fn` decl into some other declaration. In that case, we must not run analysis: this function | |
| 3332 | // will not be referenced this update, and trying to generate it could be problematic since we | |
| 3333 | // assume the owner NAV actually, um, owns us. | |
| 3334 | // | |
| 3335 | // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary. | |
| 3336 | ||
| 3337 | if (func.generic_owner == .none) { | |
| 3338 | try pt.ensureNavValUpToDate(func.owner_nav, reason); | |
| 3339 | if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) { | |
| 3340 | return error.AnalysisFail; | |
| 3341 | } | |
| 3342 | } else { | |
| 3343 | const go_nav = zcu.funcInfo(func.generic_owner).owner_nav; | |
| 3344 | try pt.ensureNavValUpToDate(go_nav, reason); | |
| 3345 | if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) { | |
| 3346 | return error.AnalysisFail; | |
| 3347 | } | |
| 3348 | } | |
| 3349 | ||
| 2963 | 3350 | if (func.analysisUnordered(ip).inferred_error_set) { |
| 2964 | 3351 | const ies = try analysis_arena.allocator().create(Sema.InferredErrorSet); |
| 2965 | 3352 | ies.* = .{ .func = func_index }; |
| ... | ... | @@ -2977,11 +3364,11 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2977 | 3364 | var inner_block: Sema.Block = .{ |
| 2978 | 3365 | .parent = null, |
| 2979 | 3366 | .sema = &sema, |
| 2980 | .namespace = decl_nav.analysis.?.namespace, | |
| 2981 | .instructions = .{}, | |
| 3367 | .namespace = decl_analysis.namespace, | |
| 3368 | .instructions = .empty, | |
| 2982 | 3369 | .inlining = null, |
| 2983 | 3370 | .comptime_reason = null, |
| 2984 | .src_base_inst = decl_nav.analysis.?.zir_index, | |
| 3371 | .src_base_inst = decl_analysis.zir_index, | |
| 2985 | 3372 | .type_name_ctx = func_nav.fqn, |
| 2986 | 3373 | }; |
| 2987 | 3374 | defer inner_block.instructions.deinit(gpa); |
| ... | ... | @@ -3020,16 +3407,21 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 3020 | 3407 | const gop = sema.inst_map.getOrPutAssumeCapacity(inst); |
| 3021 | 3408 | if (gop.found_existing) continue; // provided above by comptime arg |
| 3022 | 3409 | |
| 3023 | const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index]; | |
| 3410 | const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]); | |
| 3024 | 3411 | runtime_param_index += 1; |
| 3025 | 3412 | |
| 3026 | const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) { | |
| 3027 | error.ComptimeReturn => unreachable, | |
| 3028 | error.ComptimeBreak => unreachable, | |
| 3029 | else => |e| return e, | |
| 3030 | }; | |
| 3031 | if (opt_opv) |opv| { | |
| 3032 | gop.value_ptr.* = Air.internedToRef(opv.toIntern()); | |
| 3413 | if (param_ty.isGenericPoison()) { | |
| 3414 | // We're guaranteed to get a compile error on the `fnHasRuntimeBits` check after this | |
| 3415 | // loop (the generic poison means this is a generic function). But `continue` here to | |
| 3416 | // avoid an illegal call to `onePossibleValue` below. | |
| 3417 | continue; | |
| 3418 | } | |
| 3419 | ||
| 3420 | const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }); | |
| 3421 | ||
| 3422 | try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter); | |
| 3423 | if (try param_ty.onePossibleValue(pt)) |opv| { | |
| 3424 | gop.value_ptr.* = .fromValue(opv); | |
| 3033 | 3425 | continue; |
| 3034 | 3426 | } |
| 3035 | 3427 | const arg_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); |
| ... | ... | @@ -3038,12 +3430,31 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 3038 | 3430 | sema.air_instructions.appendAssumeCapacity(.{ |
| 3039 | 3431 | .tag = .arg, |
| 3040 | 3432 | .data = .{ .arg = .{ |
| 3041 | .ty = Air.internedToRef(param_ty), | |
| 3433 | .ty = .fromIntern(param_ty.toIntern()), | |
| 3042 | 3434 | .zir_param_index = @intCast(zir_param_index), |
| 3043 | 3435 | } }, |
| 3044 | 3436 | }); |
| 3045 | 3437 | } |
| 3046 | 3438 | |
| 3439 | try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero }), .return_type); | |
| 3440 | ||
| 3441 | // The function type is now resolved, so we're ready to check whether it even makes sense to ask | |
| 3442 | // for it to be analyzed at runtime. | |
| 3443 | if (!fn_ty.fnHasRuntimeBits(zcu)) { | |
| 3444 | const description: []const u8 = switch (fn_ty_info.cc) { | |
| 3445 | .@"inline" => "inline", | |
| 3446 | else => "generic", | |
| 3447 | }; | |
| 3448 | // This error makes sense because the only reason this analysis would ever be requested is | |
| 3449 | // for IES resolution. | |
| 3450 | return sema.fail( | |
| 3451 | &inner_block, | |
| 3452 | inner_block.nodeOffset(.zero), | |
| 3453 | "cannot resolve inferred error set of {s} function type '{f}'", | |
| 3454 | .{ description, fn_ty.fmt(pt) }, | |
| 3455 | ); | |
| 3456 | } | |
| 3457 | ||
| 3047 | 3458 | const last_arg_index = inner_block.instructions.items.len; |
| 3048 | 3459 | |
| 3049 | 3460 | // Save the error trace as our first action in the function. |
| ... | ... | @@ -3103,21 +3514,6 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 3103 | 3514 | func.setResolvedErrorSet(ip, io, ies.resolved); |
| 3104 | 3515 | } |
| 3105 | 3516 | |
| 3106 | assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | |
| 3107 | ||
| 3108 | // Finally we must resolve the return type and parameter types so that backends | |
| 3109 | // have full access to type information. | |
| 3110 | // Crucially, this happens *after* we set the function state to success above, | |
| 3111 | // so that dependencies on the function body will now be satisfied rather than | |
| 3112 | // result in circular dependency errors. | |
| 3113 | // TODO: this can go away once we fix backends having to resolve `StackTrace`. | |
| 3114 | // The codegen timing guarantees that the parameter types will be populated. | |
| 3115 | sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(.zero)) catch |err| switch (err) { | |
| 3116 | error.ComptimeReturn => unreachable, | |
| 3117 | error.ComptimeBreak => unreachable, | |
| 3118 | else => |e| return e, | |
| 3119 | }; | |
| 3120 | ||
| 3121 | 3517 | try sema.flushExports(); |
| 3122 | 3518 | |
| 3123 | 3519 | defer { |
| ... | ... | @@ -3244,7 +3640,7 @@ pub fn processExports(pt: Zcu.PerThread) !void { |
| 3244 | 3640 | break :gop .{ gop.value_ptr, gop.found_existing }; |
| 3245 | 3641 | }, |
| 3246 | 3642 | }; |
| 3247 | if (!found_existing) value_ptr.* = .{}; | |
| 3643 | if (!found_existing) value_ptr.* = .empty; | |
| 3248 | 3644 | try value_ptr.append(gpa, export_idx); |
| 3249 | 3645 | } |
| 3250 | 3646 | |
| ... | ... | @@ -3273,7 +3669,7 @@ pub fn processExports(pt: Zcu.PerThread) !void { |
| 3273 | 3669 | break :gop .{ gop.value_ptr, gop.found_existing }; |
| 3274 | 3670 | }, |
| 3275 | 3671 | }; |
| 3276 | if (!found_existing) value_ptr.* = .{}; | |
| 3672 | if (!found_existing) value_ptr.* = .empty; | |
| 3277 | 3673 | try value_ptr.append(gpa, @enumFromInt(export_idx)); |
| 3278 | 3674 | } |
| 3279 | 3675 | } |
| ... | ... | @@ -3545,36 +3941,45 @@ pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool |
| 3545 | 3941 | |
| 3546 | 3942 | /// Essentially a shortcut for calling `intern_pool.getCoerced`. |
| 3547 | 3943 | /// However, this function also allows coercing `extern`s. The `InternPool` function can't do |
| 3548 | /// this because it requires potentially pushing to the job queue. | |
| 3944 | /// this because it requires potentially queueing a link task. | |
| 3549 | 3945 | pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value { |
| 3550 | 3946 | const ip = &pt.zcu.intern_pool; |
| 3551 | 3947 | const comp = pt.zcu.comp; |
| 3552 | 3948 | const gpa = comp.gpa; |
| 3553 | 3949 | const io = comp.io; |
| 3554 | 3950 | switch (ip.indexToKey(val.toIntern())) { |
| 3555 | .@"extern" => |e| { | |
| 3556 | const coerced = try pt.getExtern(.{ | |
| 3557 | .name = e.name, | |
| 3951 | .@"extern" => |@"extern"| { | |
| 3952 | // TODO: it's awkward to make this function cancelable. The problem is really that | |
| 3953 | // `getCoerced` is a bad API: it should be replaced with smaller, more specialized | |
| 3954 | // functions, so that this cancel point is only possible in the rare case that you | |
| 3955 | // may actually need to coerce an extern! | |
| 3956 | const old_prot = io.swapCancelProtection(.blocked); | |
| 3957 | defer _ = io.swapCancelProtection(old_prot); | |
| 3958 | const coerced = pt.getExtern(.{ | |
| 3959 | .name = @"extern".name, | |
| 3558 | 3960 | .ty = new_ty.toIntern(), |
| 3559 | .lib_name = e.lib_name, | |
| 3560 | .is_const = e.is_const, | |
| 3561 | .is_threadlocal = e.is_threadlocal, | |
| 3562 | .linkage = e.linkage, | |
| 3563 | .visibility = e.visibility, | |
| 3564 | .is_dll_import = e.is_dll_import, | |
| 3565 | .relocation = e.relocation, | |
| 3566 | .decoration = e.decoration, | |
| 3567 | .alignment = e.alignment, | |
| 3568 | .@"addrspace" = e.@"addrspace", | |
| 3569 | .zir_index = e.zir_index, | |
| 3961 | .lib_name = @"extern".lib_name, | |
| 3962 | .is_const = @"extern".is_const, | |
| 3963 | .is_threadlocal = @"extern".is_threadlocal, | |
| 3964 | .linkage = @"extern".linkage, | |
| 3965 | .visibility = @"extern".visibility, | |
| 3966 | .is_dll_import = @"extern".is_dll_import, | |
| 3967 | .relocation = @"extern".relocation, | |
| 3968 | .decoration = @"extern".decoration, | |
| 3969 | .alignment = @"extern".alignment, | |
| 3970 | .@"addrspace" = @"extern".@"addrspace", | |
| 3971 | .zir_index = @"extern".zir_index, | |
| 3570 | 3972 | .owner_nav = undefined, // ignored by `getExtern`. |
| 3571 | .source = e.source, | |
| 3572 | }); | |
| 3573 | return Value.fromInterned(coerced); | |
| 3973 | .source = @"extern".source, | |
| 3974 | }) catch |err| switch (err) { | |
| 3975 | error.Canceled => unreachable, // blocked above | |
| 3976 | error.OutOfMemory => |e| return e, | |
| 3977 | }; | |
| 3978 | return .fromInterned(coerced); | |
| 3574 | 3979 | }, |
| 3575 | 3980 | else => {}, |
| 3576 | 3981 | } |
| 3577 | return Value.fromInterned(try ip.getCoerced(gpa, io, pt.tid, val.toIntern(), new_ty.toIntern())); | |
| 3982 | return .fromInterned(try ip.getCoerced(gpa, io, pt.tid, val.toIntern(), new_ty.toIntern())); | |
| 3578 | 3983 | } |
| 3579 | 3984 | |
| 3580 | 3985 | pub fn intType(pt: Zcu.PerThread, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type { |
| ... | ... | @@ -3605,16 +4010,6 @@ pub fn ptrType(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Allocator.Error! |
| 3605 | 4010 | |
| 3606 | 4011 | if (info.flags.size == .c) canon_info.flags.is_allowzero = true; |
| 3607 | 4012 | |
| 3608 | // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee | |
| 3609 | // type, we change it to 0 here. If this causes an assertion trip because the | |
| 3610 | // pointee type needs to be resolved more, that needs to be done before calling | |
| 3611 | // this ptr() function. | |
| 3612 | if (info.flags.alignment != .none and | |
| 3613 | info.flags.alignment == Type.fromInterned(info.child).abiAlignment(pt.zcu)) | |
| 3614 | { | |
| 3615 | canon_info.flags.alignment = .none; | |
| 3616 | } | |
| 3617 | ||
| 3618 | 4013 | switch (info.flags.vector_index) { |
| 3619 | 4014 | // Canonicalize host_size. If it matches the bit size of the pointee type, |
| 3620 | 4015 | // we change it to 0 here. If this causes an assertion trip, the pointee type |
| ... | ... | @@ -3632,16 +4027,6 @@ pub fn ptrType(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Allocator.Error! |
| 3632 | 4027 | return Type.fromInterned(try pt.intern(.{ .ptr_type = canon_info })); |
| 3633 | 4028 | } |
| 3634 | 4029 | |
| 3635 | /// Like `ptrType`, but if `info` specifies an `alignment`, first ensures the pointer | |
| 3636 | /// child type's alignment is resolved so that an invalid alignment is not used. | |
| 3637 | /// In general, prefer this function during semantic analysis. | |
| 3638 | pub fn ptrTypeSema(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Zcu.SemaError!Type { | |
| 3639 | if (info.flags.alignment != .none) { | |
| 3640 | _ = try Type.fromInterned(info.child).abiAlignmentSema(pt); | |
| 3641 | } | |
| 3642 | return pt.ptrType(info); | |
| 3643 | } | |
| 3644 | ||
| 3645 | 4030 | pub fn singleMutPtrType(pt: Zcu.PerThread, child_type: Type) Allocator.Error!Type { |
| 3646 | 4031 | return pt.ptrType(.{ .child = child_type.toIntern() }); |
| 3647 | 4032 | } |
| ... | ... | @@ -3741,29 +4126,54 @@ pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Alloca |
| 3741 | 4126 | const ip = &pt.zcu.intern_pool; |
| 3742 | 4127 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 3743 | 4128 | |
| 3744 | if (enum_type.values.len == 0) { | |
| 4129 | assert(field_index < enum_type.field_names.len); | |
| 4130 | ||
| 4131 | if (enum_type.field_values.len == 0) { | |
| 3745 | 4132 | // Auto-numbered fields. |
| 3746 | 4133 | return Value.fromInterned(try pt.intern(.{ .enum_tag = .{ |
| 3747 | 4134 | .ty = ty.toIntern(), |
| 3748 | 4135 | .int = try pt.intern(.{ .int = .{ |
| 3749 | .ty = enum_type.tag_ty, | |
| 4136 | .ty = enum_type.int_tag_type, | |
| 3750 | 4137 | .storage = .{ .u64 = field_index }, |
| 3751 | 4138 | } }), |
| 3752 | 4139 | } })); |
| 3753 | 4140 | } |
| 3754 | 4141 | |
| 3755 | return Value.fromInterned(try pt.intern(.{ .enum_tag = .{ | |
| 4142 | return .fromInterned(try pt.intern(.{ .enum_tag = .{ | |
| 3756 | 4143 | .ty = ty.toIntern(), |
| 3757 | .int = enum_type.values.get(ip)[field_index], | |
| 4144 | .int = enum_type.field_values.get(ip)[field_index], | |
| 3758 | 4145 | } })); |
| 3759 | 4146 | } |
| 3760 | 4147 | |
| 3761 | 4148 | pub fn undefValue(pt: Zcu.PerThread, ty: Type) Allocator.Error!Value { |
| 3762 | return Value.fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); | |
| 4149 | if (std.debug.runtime_safety) { | |
| 4150 | // TODO: values of type `struct { comptime x: u8 = undefined }` are currently represented as | |
| 4151 | // undef. This is wrong: they should really be represented as empty aggregates instead, | |
| 4152 | // because `comptime` fields shouldn't factor into that decision! This is implemented | |
| 4153 | // through logic in `aggregateValue` and requires this weird workaround in what ought to be | |
| 4154 | // a straightforward assertion: | |
| 4155 | //assert(ty.classify(pt.zcu) != .one_possible_value); | |
| 4156 | if (ty.classify(pt.zcu) == .one_possible_value) { | |
| 4157 | const ip = &pt.zcu.intern_pool; | |
| 4158 | switch (ip.indexToKey(ty.toIntern())) { | |
| 4159 | else => unreachable, // assertion failure | |
| 4160 | .struct_type => { | |
| 4161 | const comptime_bits = ip.loadStructType(ty.toIntern()).field_is_comptime_bits.getAll(ip); | |
| 4162 | for (comptime_bits) |bag| { | |
| 4163 | if (@popCount(bag) > 0) break; | |
| 4164 | } else unreachable; // assertion failure | |
| 4165 | }, | |
| 4166 | .tuple_type => |tuple| for (tuple.values.get(ip)) |val| { | |
| 4167 | if (val != .none) break; | |
| 4168 | } else unreachable, // assertion failure | |
| 4169 | } | |
| 4170 | } | |
| 4171 | } | |
| 4172 | return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); | |
| 3763 | 4173 | } |
| 3764 | 4174 | |
| 3765 | 4175 | pub fn undefRef(pt: Zcu.PerThread, ty: Type) Allocator.Error!Air.Inst.Ref { |
| 3766 | return Air.internedToRef((try pt.undefValue(ty)).toIntern()); | |
| 4176 | return .fromValue(try pt.undefValue(ty)); | |
| 3767 | 4177 | } |
| 3768 | 4178 | |
| 3769 | 4179 | pub fn intValue(pt: Zcu.PerThread, ty: Type, x: anytype) Allocator.Error!Value { |
| ... | ... | @@ -3839,7 +4249,7 @@ pub fn aggregateValue(pt: Zcu.PerThread, ty: Type, elems: []const InternPool.Ind |
| 3839 | 4249 | for (elems) |elem| { |
| 3840 | 4250 | if (!Value.fromInterned(elem).isUndef(pt.zcu)) break; |
| 3841 | 4251 | } else if (elems.len > 0) { |
| 3842 | return pt.undefValue(ty); // all-undef | |
| 4252 | return pt.undefValue(ty); | |
| 3843 | 4253 | } |
| 3844 | 4254 | return .fromInterned(try pt.intern(.{ .aggregate = .{ |
| 3845 | 4255 | .ty = ty.toIntern(), |
| ... | ... | @@ -3877,6 +4287,15 @@ pub fn floatValue(pt: Zcu.PerThread, ty: Type, x: anytype) Allocator.Error!Value |
| 3877 | 4287 | } })); |
| 3878 | 4288 | } |
| 3879 | 4289 | |
| 4290 | /// Create a value whose type is a `packed struct` or `packed union`, from the backing integer value. | |
| 4291 | pub fn bitpackValue(pt: Zcu.PerThread, ty: Type, backing_int_val: Value) Allocator.Error!Value { | |
| 4292 | assert(backing_int_val.typeOf(pt.zcu).toIntern() == ty.bitpackBackingInt(pt.zcu).toIntern()); | |
| 4293 | return .fromInterned(try pt.intern(.{ .bitpack = .{ | |
| 4294 | .ty = ty.toIntern(), | |
| 4295 | .backing_int_val = backing_int_val.toIntern(), | |
| 4296 | } })); | |
| 4297 | } | |
| 4298 | ||
| 3880 | 4299 | pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value { |
| 3881 | 4300 | assert(pt.zcu.intern_pool.isOptionalType(opt_ty.toIntern())); |
| 3882 | 4301 | return Value.fromInterned(try pt.intern(.{ .opt = .{ |
| ... | ... | @@ -3916,7 +4335,7 @@ pub fn intFittingRange(pt: Zcu.PerThread, min: Value, max: Value) !Type { |
| 3916 | 4335 | assert(Value.order(min, max, zcu).compare(.lte)); |
| 3917 | 4336 | } |
| 3918 | 4337 | |
| 3919 | const sign = min.orderAgainstZero(zcu) == .lt; | |
| 4338 | const sign = min.compareHetero(.lt, .zero_comptime_int, zcu); | |
| 3920 | 4339 | |
| 3921 | 4340 | const min_val_bits = pt.intBitsForValue(min, sign); |
| 3922 | 4341 | const max_val_bits = pt.intBitsForValue(max, sign); |
| ... | ... | @@ -3955,12 +4374,6 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 { |
| 3955 | 4374 | |
| 3956 | 4375 | return @as(u16, @intCast(big.bitCountTwosComp())); |
| 3957 | 4376 | }, |
| 3958 | .lazy_align => |lazy_ty| { | |
| 3959 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(pt.zcu).toByteUnits() orelse 0) + @intFromBool(sign); | |
| 3960 | }, | |
| 3961 | .lazy_size => |lazy_ty| { | |
| 3962 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(pt.zcu)) + @intFromBool(sign); | |
| 3963 | }, | |
| 3964 | 4377 | } |
| 3965 | 4378 | } |
| 3966 | 4379 | |
| ... | ... | @@ -3975,10 +4388,7 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err |
| 3975 | 4388 | return pt.ptrType(.{ |
| 3976 | 4389 | .child = ty, |
| 3977 | 4390 | .flags = .{ |
| 3978 | .alignment = if (alignment == Type.fromInterned(ty).abiAlignment(zcu)) | |
| 3979 | .none | |
| 3980 | else | |
| 3981 | alignment, | |
| 4391 | .alignment = alignment, | |
| 3982 | 4392 | .address_space = @"addrspace", |
| 3983 | 4393 | .is_const = is_const, |
| 3984 | 4394 | }, |
| ... | ... | @@ -3988,392 +4398,19 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err |
| 3988 | 4398 | /// Intern an `.@"extern"`, creating a corresponding owner `Nav` if necessary. |
| 3989 | 4399 | /// If necessary, the new `Nav` is queued for codegen. |
| 3990 | 4400 | /// `key.owner_nav` is ignored and may be `undefined`. |
| 3991 | pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!InternPool.Index { | |
| 4401 | pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable || Allocator.Error)!InternPool.Index { | |
| 3992 | 4402 | const zcu = pt.zcu; |
| 3993 | 4403 | const comp = zcu.comp; |
| 4404 | Type.fromInterned(key.ty).assertHasLayout(zcu); | |
| 3994 | 4405 | const result = try zcu.intern_pool.getExtern(comp.gpa, comp.io, pt.tid, key); |
| 3995 | 4406 | if (result.new_nav.unwrap()) |nav| { |
| 3996 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 3997 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3998 | try comp.queueJob(.{ .link_nav = nav }); | |
| 3999 | 4407 | if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); |
| 4408 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 4409 | try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .link_nav = nav }); | |
| 4000 | 4410 | } |
| 4001 | 4411 | return result.index; |
| 4002 | 4412 | } |
| 4003 | 4413 | |
| 4004 | // TODO: this shouldn't need a `PerThread`! Fix the signature of `Type.abiAlignment`. | |
| 4005 | pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPool.Alignment { | |
| 4006 | const zcu = pt.zcu; | |
| 4007 | const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) { | |
| 4008 | .unresolved => unreachable, | |
| 4009 | .type_resolved => |r| .{ .fromInterned(r.type), r.alignment }, | |
| 4010 | .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment }, | |
| 4011 | }; | |
| 4012 | if (alignment != .none) return alignment; | |
| 4013 | return ty.abiAlignment(zcu); | |
| 4014 | } | |
| 4015 | ||
| 4016 | /// `ty` is a container type requiring resolution (struct, union, or enum). | |
| 4017 | /// If `ty` is outdated, it is recreated at a new `InternPool.Index`, which is returned. | |
| 4018 | /// If the type cannot be recreated because it has been lost, `error.AnalysisFail` is returned. | |
| 4019 | /// If `ty` is not outdated, that same `InternPool.Index` is returned. | |
| 4020 | /// If `ty` has already been replaced by this function, the new index will not be returned again. | |
| 4021 | /// Also, if `ty` is an enum, this function will resolve the new type if needed, and the call site | |
| 4022 | /// is responsible for checking `[transitive_]failed_analysis` to detect resolution failures. | |
| 4023 | pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index { | |
| 4024 | const zcu = pt.zcu; | |
| 4025 | const gpa = zcu.gpa; | |
| 4026 | const ip = &zcu.intern_pool; | |
| 4027 | ||
| 4028 | const anal_unit: AnalUnit = .wrap(.{ .type = ty }); | |
| 4029 | const outdated = zcu.outdated.swapRemove(anal_unit) or | |
| 4030 | zcu.potentially_outdated.swapRemove(anal_unit); | |
| 4031 | ||
| 4032 | if (outdated) { | |
| 4033 | _ = zcu.outdated_ready.swapRemove(anal_unit); | |
| 4034 | try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty }); | |
| 4035 | } | |
| 4036 | ||
| 4037 | const ty_key = switch (ip.indexToKey(ty)) { | |
| 4038 | .struct_type, .union_type, .enum_type => |key| key, | |
| 4039 | else => unreachable, | |
| 4040 | }; | |
| 4041 | const declared_ty_key = switch (ty_key) { | |
| 4042 | .reified => unreachable, // never outdated | |
| 4043 | .generated_tag => unreachable, // never outdated | |
| 4044 | .declared => |d| d, | |
| 4045 | }; | |
| 4046 | ||
| 4047 | if (declared_ty_key.zir_index.resolve(ip) == null) { | |
| 4048 | // The instruction has been lost -- this type is dead. | |
| 4049 | return error.AnalysisFail; | |
| 4050 | } | |
| 4051 | ||
| 4052 | if (!outdated) return ty; | |
| 4053 | ||
| 4054 | // We will recreate the type at a new `InternPool.Index`. | |
| 4055 | ||
| 4056 | // Delete old state which is no longer in use. Technically, this is not necessary: these exports, | |
| 4057 | // references, etc, will be ignored because the type itself is unreferenced. However, it allows | |
| 4058 | // reusing the memory which is currently being used to track this state. | |
| 4059 | zcu.deleteUnitExports(anal_unit); | |
| 4060 | zcu.deleteUnitReferences(anal_unit); | |
| 4061 | zcu.deleteUnitCompileLogs(anal_unit); | |
| 4062 | if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { | |
| 4063 | kv.value.destroy(gpa); | |
| 4064 | } | |
| 4065 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | |
| 4066 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 4067 | ||
| 4068 | if (zcu.comp.debugIncremental()) { | |
| 4069 | const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); | |
| 4070 | info.last_update_gen = zcu.generation; | |
| 4071 | info.deps.clearRetainingCapacity(); | |
| 4072 | } | |
| 4073 | ||
| 4074 | switch (ip.indexToKey(ty)) { | |
| 4075 | .struct_type => return pt.recreateStructType(ty, declared_ty_key), | |
| 4076 | .union_type => return pt.recreateUnionType(ty, declared_ty_key), | |
| 4077 | .enum_type => return pt.recreateEnumType(ty, declared_ty_key), | |
| 4078 | else => unreachable, | |
| 4079 | } | |
| 4080 | } | |
| 4081 | ||
| 4082 | fn recreateStructType( | |
| 4083 | pt: Zcu.PerThread, | |
| 4084 | old_ty: InternPool.Index, | |
| 4085 | key: InternPool.Key.NamespaceType.Declared, | |
| 4086 | ) Allocator.Error!InternPool.Index { | |
| 4087 | const zcu = pt.zcu; | |
| 4088 | const comp = zcu.comp; | |
| 4089 | const gpa = comp.gpa; | |
| 4090 | const io = comp.io; | |
| 4091 | const ip = &zcu.intern_pool; | |
| 4092 | ||
| 4093 | const inst_info = key.zir_index.resolveFull(ip).?; | |
| 4094 | const file = zcu.fileByIndex(inst_info.file); | |
| 4095 | const zir = file.zir.?; | |
| 4096 | ||
| 4097 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | |
| 4098 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | |
| 4099 | assert(extended.opcode == .struct_decl); | |
| 4100 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 4101 | const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); | |
| 4102 | var extra_index = extra.end; | |
| 4103 | ||
| 4104 | const captures_len = if (small.has_captures_len) blk: { | |
| 4105 | const captures_len = zir.extra[extra_index]; | |
| 4106 | extra_index += 1; | |
| 4107 | break :blk captures_len; | |
| 4108 | } else 0; | |
| 4109 | const fields_len = if (small.has_fields_len) blk: { | |
| 4110 | const fields_len = zir.extra[extra_index]; | |
| 4111 | extra_index += 1; | |
| 4112 | break :blk fields_len; | |
| 4113 | } else 0; | |
| 4114 | ||
| 4115 | assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` | |
| 4116 | ||
| 4117 | const struct_obj = ip.loadStructType(old_ty); | |
| 4118 | ||
| 4119 | const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ | |
| 4120 | .layout = small.layout, | |
| 4121 | .fields_len = fields_len, | |
| 4122 | .known_non_opv = small.known_non_opv, | |
| 4123 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, | |
| 4124 | .any_comptime_fields = small.any_comptime_fields, | |
| 4125 | .any_default_inits = small.any_default_inits, | |
| 4126 | .inits_resolved = false, | |
| 4127 | .any_aligned_fields = small.any_aligned_fields, | |
| 4128 | .key = .{ .declared_owned_captures = .{ | |
| 4129 | .zir_index = key.zir_index, | |
| 4130 | .captures = key.captures.owned, | |
| 4131 | } }, | |
| 4132 | }, true)) { | |
| 4133 | .wip => |wip| wip, | |
| 4134 | .existing => unreachable, // we passed `replace_existing` | |
| 4135 | }; | |
| 4136 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 4137 | ||
| 4138 | wip_ty.setName(ip, struct_obj.name, struct_obj.name_nav); | |
| 4139 | try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index }); | |
| 4140 | zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index; | |
| 4141 | // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive. | |
| 4142 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 4143 | ||
| 4144 | codegen_type: { | |
| 4145 | if (file.mod.?.strip) break :codegen_type; | |
| 4146 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 4147 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 4148 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 4149 | } | |
| 4150 | ||
| 4151 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 4152 | const new_ty = wip_ty.finish(ip, struct_obj.namespace); | |
| 4153 | if (inst_info.inst == .main_struct_inst) { | |
| 4154 | // This is the root type of a file! Update the reference. | |
| 4155 | zcu.setFileRootType(inst_info.file, new_ty); | |
| 4156 | } | |
| 4157 | return new_ty; | |
| 4158 | } | |
| 4159 | ||
| 4160 | fn recreateUnionType( | |
| 4161 | pt: Zcu.PerThread, | |
| 4162 | old_ty: InternPool.Index, | |
| 4163 | key: InternPool.Key.NamespaceType.Declared, | |
| 4164 | ) Allocator.Error!InternPool.Index { | |
| 4165 | const zcu = pt.zcu; | |
| 4166 | const comp = zcu.comp; | |
| 4167 | const gpa = comp.gpa; | |
| 4168 | const io = comp.io; | |
| 4169 | const ip = &zcu.intern_pool; | |
| 4170 | ||
| 4171 | const inst_info = key.zir_index.resolveFull(ip).?; | |
| 4172 | const file = zcu.fileByIndex(inst_info.file); | |
| 4173 | const zir = file.zir.?; | |
| 4174 | ||
| 4175 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | |
| 4176 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | |
| 4177 | assert(extended.opcode == .union_decl); | |
| 4178 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | |
| 4179 | const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); | |
| 4180 | var extra_index = extra.end; | |
| 4181 | ||
| 4182 | extra_index += @intFromBool(small.has_tag_type); | |
| 4183 | const captures_len = if (small.has_captures_len) blk: { | |
| 4184 | const captures_len = zir.extra[extra_index]; | |
| 4185 | extra_index += 1; | |
| 4186 | break :blk captures_len; | |
| 4187 | } else 0; | |
| 4188 | extra_index += @intFromBool(small.has_body_len); | |
| 4189 | const fields_len = if (small.has_fields_len) blk: { | |
| 4190 | const fields_len = zir.extra[extra_index]; | |
| 4191 | extra_index += 1; | |
| 4192 | break :blk fields_len; | |
| 4193 | } else 0; | |
| 4194 | ||
| 4195 | assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` | |
| 4196 | ||
| 4197 | const union_obj = ip.loadUnionType(old_ty); | |
| 4198 | ||
| 4199 | const namespace_index = union_obj.namespace; | |
| 4200 | ||
| 4201 | const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ | |
| 4202 | .flags = .{ | |
| 4203 | .layout = small.layout, | |
| 4204 | .status = .none, | |
| 4205 | .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) | |
| 4206 | .tagged | |
| 4207 | else if (small.layout != .auto) | |
| 4208 | .none | |
| 4209 | else switch (true) { // TODO | |
| 4210 | true => .safety, | |
| 4211 | false => .none, | |
| 4212 | }, | |
| 4213 | .any_aligned_fields = small.any_aligned_fields, | |
| 4214 | .requires_comptime = .unknown, | |
| 4215 | .assumed_runtime_bits = false, | |
| 4216 | .assumed_pointer_aligned = false, | |
| 4217 | .alignment = .none, | |
| 4218 | }, | |
| 4219 | .fields_len = fields_len, | |
| 4220 | .enum_tag_ty = .none, // set later | |
| 4221 | .field_types = &.{}, // set later | |
| 4222 | .field_aligns = &.{}, // set later | |
| 4223 | .key = .{ .declared_owned_captures = .{ | |
| 4224 | .zir_index = key.zir_index, | |
| 4225 | .captures = key.captures.owned, | |
| 4226 | } }, | |
| 4227 | }, true)) { | |
| 4228 | .wip => |wip| wip, | |
| 4229 | .existing => unreachable, // we passed `replace_existing` | |
| 4230 | }; | |
| 4231 | errdefer wip_ty.cancel(ip, pt.tid); | |
| 4232 | ||
| 4233 | wip_ty.setName(ip, union_obj.name, union_obj.name_nav); | |
| 4234 | try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index }); | |
| 4235 | zcu.namespacePtr(namespace_index).owner_type = wip_ty.index; | |
| 4236 | // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive. | |
| 4237 | try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); | |
| 4238 | ||
| 4239 | codegen_type: { | |
| 4240 | if (file.mod.?.strip) break :codegen_type; | |
| 4241 | // This job depends on any resolve_type_fully jobs queued up before it. | |
| 4242 | zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 4243 | try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); | |
| 4244 | } | |
| 4245 | ||
| 4246 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 4247 | return wip_ty.finish(ip, namespace_index); | |
| 4248 | } | |
| 4249 | ||
| 4250 | /// This *does* call `Sema.resolveDeclaredEnum`, but errors from it are not propagated. | |
| 4251 | /// Call sites are resposible for checking `[transitive_]failed_analysis` after `ensureTypeUpToDate` | |
| 4252 | /// returns in order to detect resolution failures. | |
| 4253 | fn recreateEnumType( | |
| 4254 | pt: Zcu.PerThread, | |
| 4255 | old_ty: InternPool.Index, | |
| 4256 | key: InternPool.Key.NamespaceType.Declared, | |
| 4257 | ) (Allocator.Error || Io.Cancelable)!InternPool.Index { | |
| 4258 | const zcu = pt.zcu; | |
| 4259 | const comp = zcu.comp; | |
| 4260 | const gpa = comp.gpa; | |
| 4261 | const io = comp.io; | |
| 4262 | const ip = &zcu.intern_pool; | |
| 4263 | ||
| 4264 | const inst_info = key.zir_index.resolveFull(ip).?; | |
| 4265 | const file = zcu.fileByIndex(inst_info.file); | |
| 4266 | const zir = file.zir.?; | |
| 4267 | ||
| 4268 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | |
| 4269 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | |
| 4270 | assert(extended.opcode == .enum_decl); | |
| 4271 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); | |
| 4272 | const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); | |
| 4273 | var extra_index = extra.end; | |
| 4274 | ||
| 4275 | const tag_type_ref = if (small.has_tag_type) blk: { | |
| 4276 | const tag_type_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); | |
| 4277 | extra_index += 1; | |
| 4278 | break :blk tag_type_ref; | |
| 4279 | } else .none; | |
| 4280 | ||
| 4281 | const captures_len = if (small.has_captures_len) blk: { | |
| 4282 | const captures_len = zir.extra[extra_index]; | |
| 4283 | extra_index += 1; | |
| 4284 | break :blk captures_len; | |
| 4285 | } else 0; | |
| 4286 | ||
| 4287 | const body_len = if (small.has_body_len) blk: { | |
| 4288 | const body_len = zir.extra[extra_index]; | |
| 4289 | extra_index += 1; | |
| 4290 | break :blk body_len; | |
| 4291 | } else 0; | |
| 4292 | ||
| 4293 | const fields_len = if (small.has_fields_len) blk: { | |
| 4294 | const fields_len = zir.extra[extra_index]; | |
| 4295 | extra_index += 1; | |
| 4296 | break :blk fields_len; | |
| 4297 | } else 0; | |
| 4298 | ||
| 4299 | const decls_len = if (small.has_decls_len) blk: { | |
| 4300 | const decls_len = zir.extra[extra_index]; | |
| 4301 | extra_index += 1; | |
| 4302 | break :blk decls_len; | |
| 4303 | } else 0; | |
| 4304 | ||
| 4305 | assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` | |
| 4306 | ||
| 4307 | extra_index += captures_len * 2; | |
| 4308 | extra_index += decls_len; | |
| 4309 | ||
| 4310 | const body = zir.bodySlice(extra_index, body_len); | |
| 4311 | extra_index += body.len; | |
| 4312 | ||
| 4313 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; | |
| 4314 | const body_end = extra_index; | |
| 4315 | extra_index += bit_bags_count; | |
| 4316 | ||
| 4317 | const any_values = for (zir.extra[body_end..][0..bit_bags_count]) |bag| { | |
| 4318 | if (bag != 0) break true; | |
| 4319 | } else false; | |
| 4320 | ||
| 4321 | const enum_obj = ip.loadEnumType(old_ty); | |
| 4322 | ||
| 4323 | const namespace_index = enum_obj.namespace; | |
| 4324 | ||
| 4325 | const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ | |
| 4326 | .has_values = any_values, | |
| 4327 | .tag_mode = if (small.nonexhaustive) | |
| 4328 | .nonexhaustive | |
| 4329 | else if (tag_type_ref == .none) | |
| 4330 | .auto | |
| 4331 | else | |
| 4332 | .explicit, | |
| 4333 | .fields_len = fields_len, | |
| 4334 | .key = .{ .declared_owned_captures = .{ | |
| 4335 | .zir_index = key.zir_index, | |
| 4336 | .captures = key.captures.owned, | |
| 4337 | } }, | |
| 4338 | }, true)) { | |
| 4339 | .wip => |wip| wip, | |
| 4340 | .existing => unreachable, // we passed `replace_existing` | |
| 4341 | }; | |
| 4342 | var done = true; | |
| 4343 | errdefer if (!done) wip_ty.cancel(ip, pt.tid); | |
| 4344 | ||
| 4345 | wip_ty.setName(ip, enum_obj.name, enum_obj.name_nav); | |
| 4346 | ||
| 4347 | zcu.namespacePtr(namespace_index).owner_type = wip_ty.index; | |
| 4348 | // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive. | |
| 4349 | ||
| 4350 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); | |
| 4351 | wip_ty.prepare(ip, namespace_index); | |
| 4352 | done = true; | |
| 4353 | ||
| 4354 | Sema.resolveDeclaredEnum( | |
| 4355 | pt, | |
| 4356 | wip_ty, | |
| 4357 | inst_info.inst, | |
| 4358 | key.zir_index, | |
| 4359 | namespace_index, | |
| 4360 | enum_obj.name, | |
| 4361 | small, | |
| 4362 | body, | |
| 4363 | tag_type_ref, | |
| 4364 | any_values, | |
| 4365 | fields_len, | |
| 4366 | zir, | |
| 4367 | body_end, | |
| 4368 | ) catch |err| switch (err) { | |
| 4369 | error.OutOfMemory => |e| return e, | |
| 4370 | error.Canceled => |e| return e, | |
| 4371 | error.AnalysisFail => {}, // call sites are responsible for checking `[transitive_]failed_analysis` to detect this | |
| 4372 | }; | |
| 4373 | ||
| 4374 | return wip_ty.index; | |
| 4375 | } | |
| 4376 | ||
| 4377 | 4414 | /// Given a namespace, re-scan its declarations from the type definition if they have not |
| 4378 | 4415 | /// yet been re-scanned on this update. |
| 4379 | 4416 | /// If the type declaration instruction has been lost, returns `error.AnalysisFail`. |
| ... | ... | @@ -4396,7 +4433,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace |
| 4396 | 4433 | }; |
| 4397 | 4434 | |
| 4398 | 4435 | const key = switch (full_key) { |
| 4399 | .reified, .generated_tag => { | |
| 4436 | .reified, .generated_union_tag => { | |
| 4400 | 4437 | // Namespace always empty, so up-to-date. |
| 4401 | 4438 | namespace.generation = zcu.generation; |
| 4402 | 4439 | return; |
| ... | ... | @@ -4408,123 +4445,37 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace |
| 4408 | 4445 | |
| 4409 | 4446 | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 4410 | 4447 | const file = zcu.fileByIndex(inst_info.file); |
| 4411 | const zir = file.zir.?; | |
| 4412 | ||
| 4413 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | |
| 4414 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | |
| 4448 | const zir = &file.zir.?; | |
| 4415 | 4449 | |
| 4416 | 4450 | const decls = switch (container) { |
| 4417 | .@"struct" => decls: { | |
| 4418 | assert(extended.opcode == .struct_decl); | |
| 4419 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 4420 | const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); | |
| 4421 | var extra_index = extra.end; | |
| 4422 | const captures_len = if (small.has_captures_len) blk: { | |
| 4423 | const captures_len = zir.extra[extra_index]; | |
| 4424 | extra_index += 1; | |
| 4425 | break :blk captures_len; | |
| 4426 | } else 0; | |
| 4427 | extra_index += @intFromBool(small.has_fields_len); | |
| 4428 | const decls_len = if (small.has_decls_len) blk: { | |
| 4429 | const decls_len = zir.extra[extra_index]; | |
| 4430 | extra_index += 1; | |
| 4431 | break :blk decls_len; | |
| 4432 | } else 0; | |
| 4433 | extra_index += captures_len * 2; | |
| 4434 | if (small.has_backing_int) { | |
| 4435 | const backing_int_body_len = zir.extra[extra_index]; | |
| 4436 | extra_index += 1; // backing_int_body_len | |
| 4437 | if (backing_int_body_len == 0) { | |
| 4438 | extra_index += 1; // backing_int_ref | |
| 4439 | } else { | |
| 4440 | extra_index += backing_int_body_len; // backing_int_body_inst | |
| 4441 | } | |
| 4442 | } | |
| 4443 | break :decls zir.bodySlice(extra_index, decls_len); | |
| 4444 | }, | |
| 4445 | .@"union" => decls: { | |
| 4446 | assert(extended.opcode == .union_decl); | |
| 4447 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | |
| 4448 | const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); | |
| 4449 | var extra_index = extra.end; | |
| 4450 | extra_index += @intFromBool(small.has_tag_type); | |
| 4451 | const captures_len = if (small.has_captures_len) blk: { | |
| 4452 | const captures_len = zir.extra[extra_index]; | |
| 4453 | extra_index += 1; | |
| 4454 | break :blk captures_len; | |
| 4455 | } else 0; | |
| 4456 | extra_index += @intFromBool(small.has_body_len); | |
| 4457 | extra_index += @intFromBool(small.has_fields_len); | |
| 4458 | const decls_len = if (small.has_decls_len) blk: { | |
| 4459 | const decls_len = zir.extra[extra_index]; | |
| 4460 | extra_index += 1; | |
| 4461 | break :blk decls_len; | |
| 4462 | } else 0; | |
| 4463 | extra_index += captures_len * 2; | |
| 4464 | break :decls zir.bodySlice(extra_index, decls_len); | |
| 4465 | }, | |
| 4466 | .@"enum" => decls: { | |
| 4467 | assert(extended.opcode == .enum_decl); | |
| 4468 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); | |
| 4469 | const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); | |
| 4470 | var extra_index = extra.end; | |
| 4471 | extra_index += @intFromBool(small.has_tag_type); | |
| 4472 | const captures_len = if (small.has_captures_len) blk: { | |
| 4473 | const captures_len = zir.extra[extra_index]; | |
| 4474 | extra_index += 1; | |
| 4475 | break :blk captures_len; | |
| 4476 | } else 0; | |
| 4477 | extra_index += @intFromBool(small.has_body_len); | |
| 4478 | extra_index += @intFromBool(small.has_fields_len); | |
| 4479 | const decls_len = if (small.has_decls_len) blk: { | |
| 4480 | const decls_len = zir.extra[extra_index]; | |
| 4481 | extra_index += 1; | |
| 4482 | break :blk decls_len; | |
| 4483 | } else 0; | |
| 4484 | extra_index += captures_len * 2; | |
| 4485 | break :decls zir.bodySlice(extra_index, decls_len); | |
| 4486 | }, | |
| 4487 | .@"opaque" => decls: { | |
| 4488 | assert(extended.opcode == .opaque_decl); | |
| 4489 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); | |
| 4490 | const extra = zir.extraData(Zir.Inst.OpaqueDecl, extended.operand); | |
| 4491 | var extra_index = extra.end; | |
| 4492 | const captures_len = if (small.has_captures_len) blk: { | |
| 4493 | const captures_len = zir.extra[extra_index]; | |
| 4494 | extra_index += 1; | |
| 4495 | break :blk captures_len; | |
| 4496 | } else 0; | |
| 4497 | const decls_len = if (small.has_decls_len) blk: { | |
| 4498 | const decls_len = zir.extra[extra_index]; | |
| 4499 | extra_index += 1; | |
| 4500 | break :blk decls_len; | |
| 4501 | } else 0; | |
| 4502 | extra_index += captures_len * 2; | |
| 4503 | break :decls zir.bodySlice(extra_index, decls_len); | |
| 4504 | }, | |
| 4451 | .@"struct" => zir.getStructDecl(inst_info.inst).decls, | |
| 4452 | .@"union" => zir.getUnionDecl(inst_info.inst).decls, | |
| 4453 | .@"enum" => zir.getEnumDecl(inst_info.inst).decls, | |
| 4454 | .@"opaque" => zir.getOpaqueDecl(inst_info.inst).decls, | |
| 4505 | 4455 | }; |
| 4506 | 4456 | |
| 4507 | 4457 | try pt.scanNamespace(namespace_index, decls); |
| 4508 | 4458 | namespace.generation = zcu.generation; |
| 4509 | 4459 | } |
| 4510 | 4460 | |
| 4511 | pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index { | |
| 4512 | const ptr_ty = (try pt.ptrTypeSema(.{ | |
| 4513 | .child = pt.zcu.intern_pool.typeOf(val), | |
| 4461 | pub fn uavValue(pt: Zcu.PerThread, val: Value) Zcu.SemaError!Value { | |
| 4462 | const zcu = pt.zcu; | |
| 4463 | const ptr_ty = try pt.ptrType(.{ | |
| 4464 | .child = val.typeOf(zcu).toIntern(), | |
| 4514 | 4465 | .flags = .{ |
| 4515 | 4466 | .alignment = .none, |
| 4516 | 4467 | .is_const = true, |
| 4517 | 4468 | .address_space = .generic, |
| 4518 | 4469 | }, |
| 4519 | })).toIntern(); | |
| 4520 | return pt.intern(.{ .ptr = .{ | |
| 4521 | .ty = ptr_ty, | |
| 4470 | }); | |
| 4471 | return .fromInterned(try pt.intern(.{ .ptr = .{ | |
| 4472 | .ty = ptr_ty.toIntern(), | |
| 4522 | 4473 | .base_addr = .{ .uav = .{ |
| 4523 | .val = val, | |
| 4524 | .orig_ty = ptr_ty, | |
| 4474 | .val = val.toIntern(), | |
| 4475 | .orig_ty = ptr_ty.toIntern(), | |
| 4525 | 4476 | } }, |
| 4526 | 4477 | .byte_offset = 0, |
| 4527 | } }); | |
| 4478 | } })); | |
| 4528 | 4479 | } |
| 4529 | 4480 | |
| 4530 | 4481 | pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dependee) Allocator.Error!void { |
src/codegen.zig+56-98| ... | ... | @@ -343,11 +343,9 @@ pub fn generateSymbol( |
| 343 | 343 | |
| 344 | 344 | .undef => unreachable, // handled above |
| 345 | 345 | .simple_value => |simple_value| switch (simple_value) { |
| 346 | .undefined => unreachable, // non-runtime value | |
| 347 | 346 | .void => unreachable, // non-runtime value |
| 348 | 347 | .null => unreachable, // non-runtime value |
| 349 | 348 | .@"unreachable" => unreachable, // non-runtime value |
| 350 | .empty_tuple => return, | |
| 351 | 349 | .false, .true => try w.writeByte(switch (simple_value) { |
| 352 | 350 | .false => 0, |
| 353 | 351 | .true => 1, |
| ... | ... | @@ -358,7 +356,6 @@ pub fn generateSymbol( |
| 358 | 356 | .@"extern", |
| 359 | 357 | .func, |
| 360 | 358 | .enum_literal, |
| 361 | .empty_enum_value, | |
| 362 | 359 | => unreachable, // non-runtime values |
| 363 | 360 | .int => { |
| 364 | 361 | const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; |
| ... | ... | @@ -377,7 +374,7 @@ pub fn generateSymbol( |
| 377 | 374 | .payload => 0, |
| 378 | 375 | }; |
| 379 | 376 | |
| 380 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 377 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 381 | 378 | try w.writeInt(u16, err_val, endian); |
| 382 | 379 | return; |
| 383 | 380 | } |
| ... | ... | @@ -571,46 +568,11 @@ pub fn generateSymbol( |
| 571 | 568 | .struct_type => { |
| 572 | 569 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 573 | 570 | switch (struct_type.layout) { |
| 574 | .@"packed" => { | |
| 575 | const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; | |
| 576 | const start = w.end; | |
| 577 | const buffer = try w.writableSlice(abi_size); | |
| 578 | @memset(buffer, 0); | |
| 579 | var bits: u16 = 0; | |
| 580 | ||
| 581 | for (struct_type.field_types.get(ip), 0..) |field_ty, index| { | |
| 582 | const field_val = switch (aggregate.storage) { | |
| 583 | .bytes => |bytes| try pt.intern(.{ .int = .{ | |
| 584 | .ty = field_ty, | |
| 585 | .storage = .{ .u64 = bytes.at(index, ip) }, | |
| 586 | } }), | |
| 587 | .elems => |elems| elems[index], | |
| 588 | .repeated_elem => |elem| elem, | |
| 589 | }; | |
| 590 | ||
| 591 | // pointer may point to a decl which must be marked used | |
| 592 | // but can also result in a relocation. Therefore we handle those separately. | |
| 593 | if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .pointer) { | |
| 594 | const field_offset = std.math.divExact(u16, bits, 8) catch |err| switch (err) { | |
| 595 | error.DivisionByZero => unreachable, | |
| 596 | error.UnexpectedRemainder => return error.RelocationNotByteAligned, | |
| 597 | }; | |
| 598 | w.end = start + field_offset; | |
| 599 | defer { | |
| 600 | assert(w.end == start + field_offset + @divExact(target.ptrBitWidth(), 8)); | |
| 601 | w.end = start + abi_size; | |
| 602 | } | |
| 603 | try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); | |
| 604 | } else { | |
| 605 | Value.fromInterned(field_val).writeToPackedMemory(.fromInterned(field_ty), pt, buffer, bits) catch unreachable; | |
| 606 | } | |
| 607 | bits += @intCast(Type.fromInterned(field_ty).bitSize(zcu)); | |
| 608 | } | |
| 609 | }, | |
| 571 | .@"packed" => unreachable, | |
| 610 | 572 | .auto, .@"extern" => { |
| 611 | 573 | const struct_begin = w.end; |
| 612 | 574 | const field_types = struct_type.field_types.get(ip); |
| 613 | const offsets = struct_type.offsets.get(ip); | |
| 575 | const offsets = struct_type.field_offsets.get(ip); | |
| 614 | 576 | |
| 615 | 577 | var it = struct_type.iterateRuntimeOrder(ip); |
| 616 | 578 | while (it.next()) |field_index| { |
| ... | ... | @@ -635,13 +597,11 @@ pub fn generateSymbol( |
| 635 | 597 | try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); |
| 636 | 598 | } |
| 637 | 599 | |
| 638 | const size = struct_type.sizeUnordered(ip); | |
| 639 | const alignment = struct_type.flagsUnordered(ip).alignment.toByteUnits().?; | |
| 600 | assert(struct_type.alignment.check(struct_type.size)); | |
| 640 | 601 | |
| 641 | const padding = math.cast( | |
| 642 | usize, | |
| 643 | std.mem.alignForward(u64, size, @max(alignment, 1)) - (w.end - struct_begin), | |
| 644 | ) orelse return error.Overflow; | |
| 602 | const padding = math.cast(usize, struct_type.size - (w.end - struct_begin)) orelse { | |
| 603 | return error.Overflow; | |
| 604 | }; | |
| 645 | 605 | if (padding > 0) try w.splatByteAll(0, padding); |
| 646 | 606 | }, |
| 647 | 607 | } |
| ... | ... | @@ -686,6 +646,7 @@ pub fn generateSymbol( |
| 686 | 646 | } |
| 687 | 647 | } |
| 688 | 648 | }, |
| 649 | .bitpack => |bitpack| try generateSymbol(bin_file, pt, src_loc, .fromInterned(bitpack.backing_int_val), w, reloc_parent), | |
| 689 | 650 | .memoized_call => unreachable, |
| 690 | 651 | } |
| 691 | 652 | } |
| ... | ... | @@ -739,7 +700,14 @@ fn lowerPtr( |
| 739 | 700 | }; |
| 740 | 701 | return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off); |
| 741 | 702 | }, |
| 742 | .arr_elem, .comptime_field, .comptime_alloc => unreachable, | |
| 703 | .arr_elem => |arr_elem| { | |
| 704 | const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu); | |
| 705 | assert(base_ptr_ty.ptrSize(zcu) == .many); | |
| 706 | const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu); | |
| 707 | return lowerPtr(bin_file, pt, src_loc, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index); | |
| 708 | }, | |
| 709 | .comptime_alloc => unreachable, | |
| 710 | .comptime_field => unreachable, | |
| 743 | 711 | }; |
| 744 | 712 | } |
| 745 | 713 | |
| ... | ... | @@ -820,9 +788,8 @@ fn lowerNavRef( |
| 820 | 788 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 821 | 789 | const is_obj = lf.comp.config.output_mode == .Obj; |
| 822 | 790 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); |
| 823 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; | |
| 824 | 791 | |
| 825 | if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) { | |
| 792 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { | |
| 826 | 793 | try w.splatByteAll(0xaa, ptr_width_bytes); |
| 827 | 794 | return; |
| 828 | 795 | } |
| ... | ... | @@ -834,7 +801,7 @@ fn lowerNavRef( |
| 834 | 801 | dev.check(link.File.Tag.wasm.devFeature()); |
| 835 | 802 | const wasm = lf.cast(.wasm).?; |
| 836 | 803 | assert(reloc_parent == .none); |
| 837 | if (is_fn_body) { | |
| 804 | if (nav_ty.zigTypeTag(zcu) == .@"fn") { | |
| 838 | 805 | const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); |
| 839 | 806 | if (!gop.found_existing) gop.value_ptr.* = {}; |
| 840 | 807 | if (is_obj) { |
| ... | ... | @@ -1060,51 +1027,41 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo |
| 1060 | 1027 | |
| 1061 | 1028 | switch (ty.zigTypeTag(zcu)) { |
| 1062 | 1029 | .void => return .none, |
| 1030 | .bool => return .{ .immediate = @intFromBool(val.toBool()) }, | |
| 1063 | 1031 | .pointer => switch (ty.ptrSize(zcu)) { |
| 1064 | 1032 | .slice => {}, |
| 1065 | else => switch (val.toIntern()) { | |
| 1066 | .null_value => { | |
| 1067 | return .{ .immediate = 0 }; | |
| 1068 | }, | |
| 1069 | else => switch (ip.indexToKey(val.toIntern())) { | |
| 1070 | .int => { | |
| 1071 | return .{ .immediate = val.toUnsignedInt(zcu) }; | |
| 1033 | .one, .many, .c => { | |
| 1034 | const ptr = ip.indexToKey(val.toIntern()).ptr; | |
| 1035 | if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset }; | |
| 1036 | if (ptr.byte_offset == 0) switch (ptr.base_addr) { | |
| 1037 | .int => unreachable, // handled above | |
| 1038 | ||
| 1039 | .nav => |nav_index| { | |
| 1040 | const nav = ip.getNav(nav_index); | |
| 1041 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 1042 | if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) { | |
| 1043 | return .{ .lea_nav = nav_index }; | |
| 1044 | } else { | |
| 1045 | // Create the 0xaa bit pattern... | |
| 1046 | const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); | |
| 1047 | // ...but align the pointer | |
| 1048 | const alignment = zcu.navAlignment(nav_index); | |
| 1049 | return .{ .immediate = alignment.forward(undef_ptr_bits) }; | |
| 1050 | } | |
| 1072 | 1051 | }, |
| 1073 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { | |
| 1074 | .nav => |nav| { | |
| 1075 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1076 | const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) { | |
| 1077 | 1 => 0xaa, | |
| 1078 | 2 => 0xaaaa, | |
| 1079 | 4 => 0xaaaaaaaa, | |
| 1080 | 8 => 0xaaaaaaaaaaaaaaaa, | |
| 1081 | else => unreachable, | |
| 1082 | }; | |
| 1083 | return .{ .immediate = imm }; | |
| 1084 | } | |
| 1085 | 1052 | |
| 1086 | if (ty.castPtrToFn(zcu)) |fn_ty| { | |
| 1087 | if (zcu.typeToFunc(fn_ty).?.is_generic) { | |
| 1088 | return .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? }; | |
| 1089 | } | |
| 1090 | } else if (ty.zigTypeTag(zcu) == .pointer) { | |
| 1091 | const elem_ty = ty.elemType2(zcu); | |
| 1092 | if (!elem_ty.hasRuntimeBits(zcu)) { | |
| 1093 | return .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? }; | |
| 1094 | } | |
| 1095 | } | |
| 1096 | ||
| 1097 | return .{ .lea_nav = nav }; | |
| 1098 | }, | |
| 1099 | .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).hasRuntimeBits(zcu)) | |
| 1100 | return .{ .lea_uav = uav } | |
| 1101 | else | |
| 1102 | return .{ .immediate = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu) | |
| 1103 | .forward(@intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() | 1)) / 3)) }, | |
| 1104 | else => {}, | |
| 1053 | .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 1054 | return .{ .lea_uav = uav }; | |
| 1055 | } else { | |
| 1056 | // Create the 0xaa bit pattern... | |
| 1057 | const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); | |
| 1058 | // ...but align the pointer | |
| 1059 | const alignment = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu); | |
| 1060 | return .{ .immediate = alignment.forward(undef_ptr_bits) }; | |
| 1105 | 1061 | }, |
| 1062 | ||
| 1106 | 1063 | else => {}, |
| 1107 | }, | |
| 1064 | }; | |
| 1108 | 1065 | }, |
| 1109 | 1066 | }, |
| 1110 | 1067 | .int => { |
| ... | ... | @@ -1117,9 +1074,6 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo |
| 1117 | 1074 | return .{ .immediate = unsigned }; |
| 1118 | 1075 | } |
| 1119 | 1076 | }, |
| 1120 | .bool => { | |
| 1121 | return .{ .immediate = @intFromBool(val.toBool()) }; | |
| 1122 | }, | |
| 1123 | 1077 | .optional => { |
| 1124 | 1078 | if (ty.isPtrLikeOptional(zcu)) { |
| 1125 | 1079 | return lowerValue( |
| ... | ... | @@ -1139,6 +1093,10 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo |
| 1139 | 1093 | target, |
| 1140 | 1094 | ); |
| 1141 | 1095 | }, |
| 1096 | .@"struct", .@"union" => if (ty.containerLayout(zcu) == .@"packed") { | |
| 1097 | const bitpack = ip.indexToKey(val.toIntern()).bitpack; | |
| 1098 | return lowerValue(pt, .fromInterned(bitpack.backing_int_val), target); | |
| 1099 | }, | |
| 1142 | 1100 | .error_set => { |
| 1143 | 1101 | const err_name = ip.indexToKey(val.toIntern()).err.name; |
| 1144 | 1102 | const error_index = ip.getErrorValueIfExists(err_name).?; |
| ... | ... | @@ -1147,7 +1105,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo |
| 1147 | 1105 | .error_union => { |
| 1148 | 1106 | const err_type = ty.errorUnionSet(zcu); |
| 1149 | 1107 | const payload_type = ty.errorUnionPayload(zcu); |
| 1150 | if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1108 | if (!payload_type.hasRuntimeBits(zcu)) { | |
| 1151 | 1109 | // We use the error type directly as the type. |
| 1152 | 1110 | const err_int_ty = try pt.errorIntType(); |
| 1153 | 1111 | switch (ip.indexToKey(val.toIntern()).error_union.val) { |
| ... | ... | @@ -1187,10 +1145,10 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo |
| 1187 | 1145 | } |
| 1188 | 1146 | |
| 1189 | 1147 | pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { |
| 1190 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; | |
| 1148 | if (!payload_ty.hasRuntimeBits(zcu)) return 0; | |
| 1191 | 1149 | const payload_align = payload_ty.abiAlignment(zcu); |
| 1192 | 1150 | const error_align = Type.anyerror.abiAlignment(zcu); |
| 1193 | if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1151 | if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBits(zcu)) { | |
| 1194 | 1152 | return 0; |
| 1195 | 1153 | } else { |
| 1196 | 1154 | return payload_align.forward(Type.anyerror.abiSize(zcu)); |
| ... | ... | @@ -1198,10 +1156,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { |
| 1198 | 1156 | } |
| 1199 | 1157 | |
| 1200 | 1158 | pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 { |
| 1201 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; | |
| 1159 | if (!payload_ty.hasRuntimeBits(zcu)) return 0; | |
| 1202 | 1160 | const payload_align = payload_ty.abiAlignment(zcu); |
| 1203 | 1161 | const error_align = Type.anyerror.abiAlignment(zcu); |
| 1204 | if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1162 | if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBits(zcu)) { | |
| 1205 | 1163 | return error_align.forward(payload_ty.abiSize(zcu)); |
| 1206 | 1164 | } else { |
| 1207 | 1165 | return 0; |
src/codegen/aarch64/Select.zig+63-88| ... | ... | @@ -2464,7 +2464,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2464 | 2464 | |
| 2465 | 2465 | const ty_pl = air.data(air.inst_index).ty_pl; |
| 2466 | 2466 | const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2467 | const elem_size = ty_pl.ty.toType().elemType2(zcu).abiSize(zcu); | |
| 2467 | const elem_size = ty_pl.ty.toType().childType(zcu).abiSize(zcu); | |
| 2468 | 2468 | |
| 2469 | 2469 | const base_vi = try isel.use(bin_op.lhs); |
| 2470 | 2470 | var base_part_it = base_vi.field(ty_pl.ty.toType(), 0, 8); |
| ... | ... | @@ -2791,17 +2791,17 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2791 | 2791 | } else return isel.fail("invalid constraint: '{s}'", .{constraint}); |
| 2792 | 2792 | } |
| 2793 | 2793 | |
| 2794 | const clobbers = ip.indexToKey(unwrapped_asm.clobbers).aggregate; | |
| 2795 | const clobbers_ty: ZigType = .fromInterned(clobbers.ty); | |
| 2794 | const clobbers_val: Constant = .fromInterned(unwrapped_asm.clobbers); | |
| 2795 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 2796 | var clobbers_bigint_buf: Constant.BigIntSpace = undefined; | |
| 2797 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 2796 | 2798 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { |
| 2797 | switch (switch (clobbers.storage) { | |
| 2798 | .bytes => unreachable, | |
| 2799 | .elems => |elems| elems[field_index], | |
| 2800 | .repeated_elem => |repeated_elem| repeated_elem, | |
| 2801 | }) { | |
| 2802 | else => unreachable, | |
| 2803 | .bool_false => continue, | |
| 2804 | .bool_true => {}, | |
| 2799 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 2800 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 2801 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 2802 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 2803 | 0 => continue, // field is false | |
| 2804 | 1 => {}, // field is true | |
| 2805 | 2805 | } |
| 2806 | 2806 | const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; |
| 2807 | 2807 | if (std.mem.eql(u8, clobber_name, "memory")) continue; |
| ... | ... | @@ -2816,14 +2816,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2816 | 2816 | } |
| 2817 | 2817 | } |
| 2818 | 2818 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { |
| 2819 | switch (switch (clobbers.storage) { | |
| 2820 | .bytes => unreachable, | |
| 2821 | .elems => |elems| elems[field_index], | |
| 2822 | .repeated_elem => |repeated_elem| repeated_elem, | |
| 2823 | }) { | |
| 2824 | else => unreachable, | |
| 2825 | .bool_false => continue, | |
| 2826 | .bool_true => {}, | |
| 2819 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 2820 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 2821 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 2822 | 0 => continue, // field is false | |
| 2823 | 1 => {}, // field is true | |
| 2827 | 2824 | } |
| 2828 | 2825 | const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; |
| 2829 | 2826 | if (std.mem.eql(u8, clobber_name, "memory")) continue; |
| ... | ... | @@ -2872,14 +2869,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2872 | 2869 | } |
| 2873 | 2870 | |
| 2874 | 2871 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { |
| 2875 | switch (switch (clobbers.storage) { | |
| 2876 | .bytes => unreachable, | |
| 2877 | .elems => |elems| elems[field_index], | |
| 2878 | .repeated_elem => |repeated_elem| repeated_elem, | |
| 2879 | }) { | |
| 2880 | else => unreachable, | |
| 2881 | .bool_false => continue, | |
| 2882 | .bool_true => {}, | |
| 2872 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 2873 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 2874 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 2875 | 0 => continue, // field is false | |
| 2876 | 1 => {}, // field is true | |
| 2883 | 2877 | } |
| 2884 | 2878 | const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; |
| 2885 | 2879 | if (std.mem.eql(u8, clobber_name, "memory")) continue; |
| ... | ... | @@ -3289,8 +3283,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3289 | 3283 | } else if (dst_ty.isSliceAtRuntime(zcu) and src_ty.isSliceAtRuntime(zcu)) { |
| 3290 | 3284 | try dst_vi.value.move(isel, ty_op.operand); |
| 3291 | 3285 | } else if (dst_tag == .error_union and src_tag == .error_union) { |
| 3292 | assert(dst_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu) == | |
| 3293 | src_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu)); | |
| 3286 | assert(dst_ty.errorUnionSet(zcu).hasRuntimeBits(zcu) == | |
| 3287 | src_ty.errorUnionSet(zcu).hasRuntimeBits(zcu)); | |
| 3294 | 3288 | if (dst_ty.errorUnionPayload(zcu).toIntern() == src_ty.errorUnionPayload(zcu).toIntern()) { |
| 3295 | 3289 | try dst_vi.value.move(isel, ty_op.operand); |
| 3296 | 3290 | } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); |
| ... | ... | @@ -4568,7 +4562,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4568 | 4562 | } |
| 4569 | 4563 | if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned( |
| 4570 | 4564 | case.items[0].toInterned().?, |
| 4571 | ).orderAgainstZero(zcu).compare(.eq)) { | |
| 4565 | ).compareHetero(.eq, .zero_comptime_int, zcu)) { | |
| 4572 | 4566 | try isel.emit(.cbnz( |
| 4573 | 4567 | cond_reg, |
| 4574 | 4568 | @intCast((isel.instructions.items.len + 1 - next_label) << 2), |
| ... | ... | @@ -6145,7 +6139,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6145 | 6139 | } else { |
| 6146 | 6140 | const elem_ptr_ra = try isel.allocIntReg(); |
| 6147 | 6141 | defer isel.freeReg(elem_ptr_ra); |
| 6148 | if (!try elem_vi.value.load(isel, slice_ty.elemType2(zcu), elem_ptr_ra, .{ | |
| 6142 | if (!try elem_vi.value.load(isel, slice_ty.childType(zcu), elem_ptr_ra, .{ | |
| 6149 | 6143 | .@"volatile" = ptr_info.flags.is_volatile, |
| 6150 | 6144 | })) break :unused; |
| 6151 | 6145 | const slice_vi = try isel.use(bin_op.lhs); |
| ... | ... | @@ -6253,7 +6247,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6253 | 6247 | } else { |
| 6254 | 6248 | const elem_ptr_ra = try isel.allocIntReg(); |
| 6255 | 6249 | defer isel.freeReg(elem_ptr_ra); |
| 6256 | if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{ | |
| 6250 | if (!try elem_vi.value.load(isel, ptr_ty.childType(zcu), elem_ptr_ra, .{ | |
| 6257 | 6251 | .@"volatile" = ptr_info.flags.is_volatile, |
| 6258 | 6252 | })) break :unused; |
| 6259 | 6253 | const base_vi = try isel.use(bin_op.lhs); |
| ... | ... | @@ -6594,7 +6588,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6594 | 6588 | if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte| |
| 6595 | 6589 | break :fill_byte .{ .constant = fill_byte }; |
| 6596 | 6590 | } |
| 6597 | switch (dst_ty.elemType2(zcu).abiSize(zcu)) { | |
| 6591 | switch (dst_ty.indexableElem(zcu).abiSize(zcu)) { | |
| 6598 | 6592 | 0 => unreachable, |
| 6599 | 6593 | 1 => break :fill_byte .{ .value = bin_op.rhs }, |
| 6600 | 6594 | 2, 4, 8 => |size| { |
| ... | ... | @@ -6899,11 +6893,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6899 | 6893 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 6900 | 6894 | while (field_it.next()) |field_index| { |
| 6901 | 6895 | const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 6902 | field_offset = field_ty.structFieldAlignment( | |
| 6903 | loaded_struct.fieldAlign(ip, field_index), | |
| 6904 | loaded_struct.layout, | |
| 6905 | zcu, | |
| 6906 | ).forward(field_offset); | |
| 6896 | field_offset = loaded_struct.field_offsets.get(ip)[field_index]; | |
| 6907 | 6897 | const field_size = field_ty.abiSize(zcu); |
| 6908 | 6898 | if (field_size == 0) continue; |
| 6909 | 6899 | var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size); |
| ... | ... | @@ -6911,7 +6901,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6911 | 6901 | try agg_part_vi.?.move(isel, elems[field_index]); |
| 6912 | 6902 | field_offset += field_size; |
| 6913 | 6903 | } |
| 6914 | assert(loaded_struct.flagsUnordered(ip).alignment.forward(field_offset) == agg_vi.value.size(isel)); | |
| 6904 | assert(loaded_struct.alignment.forward(field_offset) == agg_vi.value.size(isel)); | |
| 6915 | 6905 | }, |
| 6916 | 6906 | .tuple_type => |tuple_type| { |
| 6917 | 6907 | const elems: []const Air.Inst.Ref = |
| ... | ... | @@ -6953,23 +6943,23 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 6953 | 6943 | const union_layout = ZigType.getUnionLayout(loaded_union, zcu); |
| 6954 | 6944 | |
| 6955 | 6945 | if (union_layout.tag_size > 0) unused_tag: { |
| 6956 | const loaded_tag = loaded_union.loadTagType(ip); | |
| 6946 | const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 6957 | 6947 | var tag_it = union_vi.value.field(union_ty, union_layout.tagOffset(), union_layout.tag_size); |
| 6958 | 6948 | const tag_vi = try tag_it.only(isel); |
| 6959 | 6949 | const tag_ra = try tag_vi.?.defReg(isel) orelse break :unused_tag; |
| 6960 | 6950 | switch (union_layout.tag_size) { |
| 6961 | 6951 | 0 => unreachable, |
| 6962 | 1...4 => try isel.movImmediate(tag_ra.w(), @as(u32, switch (loaded_tag.values.len) { | |
| 6952 | 1...4 => try isel.movImmediate(tag_ra.w(), @as(u32, switch (loaded_tag.field_values.len) { | |
| 6963 | 6953 | 0 => extra.field_index, |
| 6964 | else => switch (ip.indexToKey(loaded_tag.values.get(ip)[extra.field_index]).int.storage) { | |
| 6954 | else => switch (ip.indexToKey(loaded_tag.field_values.get(ip)[extra.field_index]).int.storage) { | |
| 6965 | 6955 | .u64 => |imm| @intCast(imm), |
| 6966 | 6956 | .i64 => |imm| @bitCast(@as(i32, @intCast(imm))), |
| 6967 | 6957 | else => unreachable, |
| 6968 | 6958 | }, |
| 6969 | 6959 | })), |
| 6970 | 5...8 => try isel.movImmediate(tag_ra.x(), switch (loaded_tag.values.len) { | |
| 6960 | 5...8 => try isel.movImmediate(tag_ra.x(), switch (loaded_tag.field_values.len) { | |
| 6971 | 6961 | 0 => extra.field_index, |
| 6972 | else => switch (ip.indexToKey(loaded_tag.values.get(ip)[extra.field_index]).int.storage) { | |
| 6962 | else => switch (ip.indexToKey(loaded_tag.field_values.get(ip)[extra.field_index]).int.storage) { | |
| 6973 | 6963 | .u64 => |imm| imm, |
| 6974 | 6964 | .i64 => |imm| @bitCast(imm), |
| 6975 | 6965 | else => unreachable, |
| ... | ... | @@ -7217,7 +7207,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 7217 | 7207 | const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused; |
| 7218 | 7208 | |
| 7219 | 7209 | const ty_nav = air.data(air.inst_index).ty_nav; |
| 7220 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 7210 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 7221 | 7211 | false => { |
| 7222 | 7212 | try isel.nav_relocs.append(gpa, .{ |
| 7223 | 7213 | .nav = ty_nav.nav, |
| ... | ... | @@ -7240,7 +7230,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 7240 | 7230 | }); |
| 7241 | 7231 | try isel.emit(.adrp(ptr_ra.x(), 0)); |
| 7242 | 7232 | }, |
| 7243 | } else try isel.movImmediate(ptr_ra.x(), isel.pt.navAlignment(ty_nav.nav).forward(0xaaaaaaaaaaaaaaaa)); | |
| 7233 | } else try isel.movImmediate(ptr_ra.x(), zcu.navAlignment(ty_nav.nav).forward(0xaaaaaaaaaaaaaaaa)); | |
| 7244 | 7234 | } |
| 7245 | 7235 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 7246 | 7236 | }, |
| ... | ... | @@ -10397,7 +10387,7 @@ pub const Value = struct { |
| 10397 | 10387 | switch (loaded_struct.layout) { |
| 10398 | 10388 | .auto, .@"extern" => {}, |
| 10399 | 10389 | .@"packed" => continue :type_key .{ |
| 10400 | .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type, | |
| 10390 | .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, | |
| 10401 | 10391 | }, |
| 10402 | 10392 | } |
| 10403 | 10393 | const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0; |
| ... | ... | @@ -10412,7 +10402,7 @@ pub const Value = struct { |
| 10412 | 10402 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 10413 | 10403 | while (field_it.next()) |field_index| { |
| 10414 | 10404 | const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 10415 | const field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) { | |
| 10405 | const field_begin = switch (loaded_struct.field_aligns.getOrNone(ip, field_index)) { | |
| 10416 | 10406 | .none => field_ty.abiAlignment(zcu), |
| 10417 | 10407 | else => |field_align| field_align, |
| 10418 | 10408 | }.forward(field_end); |
| ... | ... | @@ -10510,7 +10500,7 @@ pub const Value = struct { |
| 10510 | 10500 | }, |
| 10511 | 10501 | .union_type => { |
| 10512 | 10502 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 10513 | switch (loaded_union.flagsUnordered(ip).layout) { | |
| 10503 | switch (loaded_union.layout) { | |
| 10514 | 10504 | .auto, .@"extern" => {}, |
| 10515 | 10505 | .@"packed" => continue :type_key .{ .int_type = .{ |
| 10516 | 10506 | .signedness = .unsigned, |
| ... | ... | @@ -10545,12 +10535,13 @@ pub const Value = struct { |
| 10545 | 10535 | const field_signedness = field_signedness: switch (field) { |
| 10546 | 10536 | .tag => { |
| 10547 | 10537 | if (offset >= field_begin and offset + size <= field_begin + field_size) { |
| 10548 | ty = .fromInterned(loaded_union.enum_tag_ty); | |
| 10538 | ty = .fromInterned(loaded_union.enum_tag_type); | |
| 10549 | 10539 | ty_size = field_size; |
| 10550 | 10540 | offset -= field_begin; |
| 10551 | continue :type_key ip.indexToKey(loaded_union.enum_tag_ty); | |
| 10541 | continue :type_key ip.indexToKey(loaded_union.enum_tag_type); | |
| 10552 | 10542 | } |
| 10553 | break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness; | |
| 10543 | const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 10544 | break :field_signedness ip.indexToKey(loaded_enum.int_tag_type).int_type.signedness; | |
| 10554 | 10545 | }, |
| 10555 | 10546 | .payload => null, |
| 10556 | 10547 | }; |
| ... | ... | @@ -10580,7 +10571,7 @@ pub const Value = struct { |
| 10580 | 10571 | } |
| 10581 | 10572 | }, |
| 10582 | 10573 | .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, |
| 10583 | .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty), | |
| 10574 | .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type), | |
| 10584 | 10575 | .error_set_type, |
| 10585 | 10576 | .inferred_error_set_type, |
| 10586 | 10577 | => continue :type_key .{ .simple_type = .anyerror }, |
| ... | ... | @@ -10594,7 +10585,6 @@ pub const Value = struct { |
| 10594 | 10585 | .error_union, |
| 10595 | 10586 | .enum_literal, |
| 10596 | 10587 | .enum_tag, |
| 10597 | .empty_enum_value, | |
| 10598 | 10588 | .float, |
| 10599 | 10589 | .ptr, |
| 10600 | 10590 | .slice, |
| ... | ... | @@ -10717,7 +10707,6 @@ pub const Value = struct { |
| 10717 | 10707 | .inferred_error_set_type, |
| 10718 | 10708 | |
| 10719 | 10709 | .enum_literal, |
| 10720 | .empty_enum_value, | |
| 10721 | 10710 | .memoized_call, |
| 10722 | 10711 | => unreachable, // not a runtime value |
| 10723 | 10712 | .undef => break :free try isel.emit(if (mat.ra.isVector()) .movi(switch (size) { |
| ... | ... | @@ -10738,7 +10727,7 @@ pub const Value = struct { |
| 10738 | 10727 | } }), |
| 10739 | 10728 | }), |
| 10740 | 10729 | .simple_value => |simple_value| switch (simple_value) { |
| 10741 | .undefined, .void, .null, .empty_tuple, .@"unreachable" => unreachable, | |
| 10730 | .void, .null, .@"unreachable" => unreachable, | |
| 10742 | 10731 | .true => continue :constant_key .{ .int = .{ |
| 10743 | 10732 | .ty = .bool_type, |
| 10744 | 10733 | .storage = .{ .u64 = 1 }, |
| ... | ... | @@ -10748,7 +10737,7 @@ pub const Value = struct { |
| 10748 | 10737 | .storage = .{ .u64 = 0 }, |
| 10749 | 10738 | } }, |
| 10750 | 10739 | }, |
| 10751 | .int => |int| break :free storage: switch (int.storage) { | |
| 10740 | .int => |int| break :free switch (int.storage) { | |
| 10752 | 10741 | .u64 => |imm| try isel.movImmediate(switch (size) { |
| 10753 | 10742 | else => unreachable, |
| 10754 | 10743 | 1...4 => mat.ra.w(), |
| ... | ... | @@ -10780,12 +10769,6 @@ pub const Value = struct { |
| 10780 | 10769 | } |
| 10781 | 10770 | try isel.movImmediate(mat.ra.x(), imm); |
| 10782 | 10771 | }, |
| 10783 | .lazy_align => |ty| continue :storage .{ | |
| 10784 | .u64 = ZigType.fromInterned(ty).abiAlignment(zcu).toByteUnits().?, | |
| 10785 | }, | |
| 10786 | .lazy_size => |ty| continue :storage .{ | |
| 10787 | .u64 = ZigType.fromInterned(ty).abiSize(zcu), | |
| 10788 | }, | |
| 10789 | 10772 | }, |
| 10790 | 10773 | .err => |err| continue :constant_key .{ .int = .{ |
| 10791 | 10774 | .ty = err.ty, |
| ... | ... | @@ -10931,7 +10914,7 @@ pub const Value = struct { |
| 10931 | 10914 | .ptr => |ptr| { |
| 10932 | 10915 | assert(offset == 0 and size == 8); |
| 10933 | 10916 | break :free switch (ptr.base_addr) { |
| 10934 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 10917 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).typeOf(ip)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 10935 | 10918 | false => { |
| 10936 | 10919 | try isel.nav_relocs.append(zcu.gpa, .{ |
| 10937 | 10920 | .nav = nav, |
| ... | ... | @@ -10965,9 +10948,9 @@ pub const Value = struct { |
| 10965 | 10948 | }, |
| 10966 | 10949 | } else continue :constant_key .{ .int = .{ |
| 10967 | 10950 | .ty = .usize_type, |
| 10968 | .storage = .{ .u64 = isel.pt.navAlignment(nav).forward(0xaaaaaaaaaaaaaaaa) }, | |
| 10951 | .storage = .{ .u64 = zcu.navAlignment(nav).forward(0xaaaaaaaaaaaaaaaa) }, | |
| 10969 | 10952 | } }, |
| 10970 | .uav => |uav| if (ZigType.fromInterned(ip.typeOf(uav.val)).isFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 10953 | .uav => |uav| if (ZigType.fromInterned(ip.typeOf(uav.val)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 10971 | 10954 | false => { |
| 10972 | 10955 | try isel.uav_relocs.append(zcu.gpa, .{ |
| 10973 | 10956 | .uav = uav, |
| ... | ... | @@ -11092,13 +11075,9 @@ pub const Value = struct { |
| 11092 | 11075 | var field_offset: u64 = 0; |
| 11093 | 11076 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 11094 | 11077 | while (field_it.next()) |field_index| { |
| 11095 | if (loaded_struct.fieldIsComptime(ip, field_index)) continue; | |
| 11078 | if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; | |
| 11096 | 11079 | const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 11097 | field_offset = field_ty.structFieldAlignment( | |
| 11098 | loaded_struct.fieldAlign(ip, field_index), | |
| 11099 | loaded_struct.layout, | |
| 11100 | zcu, | |
| 11101 | ).forward(field_offset); | |
| 11080 | field_offset = loaded_struct.field_offsets.get(ip)[field_index]; | |
| 11102 | 11081 | const field_size = field_ty.abiSize(zcu); |
| 11103 | 11082 | if (offset >= field_offset and offset + size <= field_offset + field_size) { |
| 11104 | 11083 | offset -= field_offset; |
| ... | ... | @@ -11140,7 +11119,7 @@ pub const Value = struct { |
| 11140 | 11119 | .un => |un| { |
| 11141 | 11120 | const loaded_union = ip.loadUnionType(un.ty); |
| 11142 | 11121 | const union_layout = ZigType.getUnionLayout(loaded_union, zcu); |
| 11143 | if (loaded_union.hasTag(ip)) { | |
| 11122 | if (loaded_union.has_runtime_tag) { | |
| 11144 | 11123 | const tag_offset = union_layout.tagOffset(); |
| 11145 | 11124 | if (offset >= tag_offset and offset + size <= tag_offset + union_layout.tag_size) { |
| 11146 | 11125 | offset -= tag_offset; |
| ... | ... | @@ -11414,7 +11393,6 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e |
| 11414 | 11393 | .inferred_error_set_type, |
| 11415 | 11394 | |
| 11416 | 11395 | .enum_literal, |
| 11417 | .empty_enum_value, | |
| 11418 | 11396 | .memoized_call, |
| 11419 | 11397 | => unreachable, // not a runtime value |
| 11420 | 11398 | .err => |err| { |
| ... | ... | @@ -11486,13 +11464,9 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e |
| 11486 | 11464 | var field_offset: u64 = 0; |
| 11487 | 11465 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 11488 | 11466 | while (field_it.next()) |field_index| { |
| 11489 | if (loaded_struct.fieldIsComptime(ip, field_index)) continue; | |
| 11467 | if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; | |
| 11490 | 11468 | const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 11491 | field_offset = field_ty.structFieldAlignment( | |
| 11492 | loaded_struct.fieldAlign(ip, field_index), | |
| 11493 | loaded_struct.layout, | |
| 11494 | zcu, | |
| 11495 | ).forward(field_offset); | |
| 11469 | field_offset = loaded_struct.field_offsets.get(ip)[field_index]; | |
| 11496 | 11470 | const field_size = field_ty.abiSize(zcu); |
| 11497 | 11471 | if (!try isel.writeToMemory(.fromInterned(switch (aggregate.storage) { |
| 11498 | 11472 | .bytes => unreachable, |
| ... | ... | @@ -12091,7 +12065,7 @@ pub const CallAbiIterator = struct { |
| 12091 | 12065 | const zcu = isel.pt.zcu; |
| 12092 | 12066 | const ip = &zcu.intern_pool; |
| 12093 | 12067 | |
| 12094 | if (ty.isNoReturn(zcu) or !ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; | |
| 12068 | if (!ty.hasRuntimeBits(zcu)) return null; | |
| 12095 | 12069 | try isel.values.ensureUnusedCapacity(zcu.gpa, Value.max_parts); |
| 12096 | 12070 | const wip_vi = isel.initValue(ty); |
| 12097 | 12071 | type_key: switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -12195,7 +12169,7 @@ pub const CallAbiIterator = struct { |
| 12195 | 12169 | switch (loaded_struct.layout) { |
| 12196 | 12170 | .auto, .@"extern" => {}, |
| 12197 | 12171 | .@"packed" => continue :type_key .{ |
| 12198 | .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type, | |
| 12172 | .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, | |
| 12199 | 12173 | }, |
| 12200 | 12174 | } |
| 12201 | 12175 | const size = wip_vi.size(isel); |
| ... | ... | @@ -12219,7 +12193,7 @@ pub const CallAbiIterator = struct { |
| 12219 | 12193 | const field_end = next_field_end; |
| 12220 | 12194 | const next_field_begin = if (field_it.next()) |field_index| next_field_begin: { |
| 12221 | 12195 | const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 12222 | const next_field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) { | |
| 12196 | const next_field_begin = switch (loaded_struct.field_aligns.getOrNone(ip, field_index)) { | |
| 12223 | 12197 | .none => field_ty.abiAlignment(zcu), |
| 12224 | 12198 | else => |field_align| field_align, |
| 12225 | 12199 | }.forward(field_end); |
| ... | ... | @@ -12285,7 +12259,7 @@ pub const CallAbiIterator = struct { |
| 12285 | 12259 | }, |
| 12286 | 12260 | .union_type => { |
| 12287 | 12261 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 12288 | switch (loaded_union.flagsUnordered(ip).layout) { | |
| 12262 | switch (loaded_union.layout) { | |
| 12289 | 12263 | .auto, .@"extern" => {}, |
| 12290 | 12264 | .@"packed" => continue :type_key .{ .int_type = .{ |
| 12291 | 12265 | .signedness = .unsigned, |
| ... | ... | @@ -12318,7 +12292,9 @@ pub const CallAbiIterator = struct { |
| 12318 | 12292 | } |
| 12319 | 12293 | }, |
| 12320 | 12294 | .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, |
| 12321 | .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty), | |
| 12295 | .enum_type => continue :type_key .{ | |
| 12296 | .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type, | |
| 12297 | }, | |
| 12322 | 12298 | .error_set_type, |
| 12323 | 12299 | .inferred_error_set_type, |
| 12324 | 12300 | => continue :type_key .{ .simple_type = .anyerror }, |
| ... | ... | @@ -12332,7 +12308,6 @@ pub const CallAbiIterator = struct { |
| 12332 | 12308 | .error_union, |
| 12333 | 12309 | .enum_literal, |
| 12334 | 12310 | .enum_tag, |
| 12335 | .empty_enum_value, | |
| 12336 | 12311 | .float, |
| 12337 | 12312 | .ptr, |
| 12338 | 12313 | .slice, |
| ... | ... | @@ -12424,8 +12399,8 @@ pub const CallAbiIterator = struct { |
| 12424 | 12399 | const ip = &zcu.intern_pool; |
| 12425 | 12400 | var common_fdt: ?FundamentalDataType = null; |
| 12426 | 12401 | for (0.., loaded_struct.field_types.get(ip)) |field_index, field_ty| { |
| 12427 | if (loaded_struct.fieldIsComptime(ip, field_index)) continue; | |
| 12428 | if (loaded_struct.fieldAlign(ip, field_index) != .none) return null; | |
| 12402 | if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; | |
| 12403 | if (loaded_struct.field_aligns.getOrNone(ip, field_index) != .none) return null; | |
| 12429 | 12404 | if (!ZigType.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; |
| 12430 | 12405 | const fdt = homogeneousAggregateBaseType(zcu, field_ty); |
| 12431 | 12406 | if (common_fdt == null) common_fdt = fdt else if (fdt != common_fdt) return null; |
src/codegen/aarch64/abi.zig+1-1| ... | ... | @@ -13,7 +13,7 @@ pub const Class = union(enum) { |
| 13 | 13 | |
| 14 | 14 | /// For `float_array` the second element will be the amount of floats. |
| 15 | 15 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 16 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 16 | assert(ty.hasRuntimeBits(zcu)); | |
| 17 | 17 | |
| 18 | 18 | var maybe_float_bits: ?u16 = null; |
| 19 | 19 | switch (ty.zigTypeTag(zcu)) { |
src/codegen/arm/abi.zig+13-11| ... | ... | @@ -23,7 +23,7 @@ pub const Class = union(enum) { |
| 23 | 23 | pub const Context = enum { ret, arg }; |
| 24 | 24 | |
| 25 | 25 | pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 26 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 26 | assert(ty.hasRuntimeBits(zcu)); | |
| 27 | 27 | |
| 28 | 28 | var maybe_float_bits: ?u16 = null; |
| 29 | 29 | const max_byval_size = 512; |
| ... | ... | @@ -39,22 +39,22 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 39 | 39 | const float_count = countFloats(ty, zcu, &maybe_float_bits); |
| 40 | 40 | if (float_count <= byval_float_count) return .byval; |
| 41 | 41 | |
| 42 | if (ty.abiAlignment(zcu).compare(.gt, .@"32")) { | |
| 43 | return Class.arrSize(bit_size, 64); | |
| 44 | } | |
| 45 | ||
| 42 | 46 | const fields = ty.structFieldCount(zcu); |
| 43 | 47 | var i: u32 = 0; |
| 44 | 48 | while (i < fields) : (i += 1) { |
| 45 | 49 | const field_ty = ty.fieldType(i, zcu); |
| 46 | const field_alignment = ty.fieldAlignment(i, zcu); | |
| 47 | const field_size = field_ty.bitSize(zcu); | |
| 48 | if (field_size > 32 or field_alignment.compare(.gt, .@"32")) { | |
| 49 | return Class.arrSize(bit_size, 64); | |
| 50 | } | |
| 50 | if (field_ty.bitSize(zcu) > 32) return Class.arrSize(bit_size, 64); | |
| 51 | 51 | } |
| 52 | 52 | return Class.arrSize(bit_size, 32); |
| 53 | 53 | }, |
| 54 | 54 | .@"union" => { |
| 55 | 55 | const bit_size = ty.bitSize(zcu); |
| 56 | 56 | const union_obj = zcu.typeToUnion(ty).?; |
| 57 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | |
| 57 | if (union_obj.layout == .@"packed") { | |
| 58 | 58 | if (bit_size > 64) return .memory; |
| 59 | 59 | return .byval; |
| 60 | 60 | } |
| ... | ... | @@ -62,10 +62,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 62 | 62 | const float_count = countFloats(ty, zcu, &maybe_float_bits); |
| 63 | 63 | if (float_count <= byval_float_count) return .byval; |
| 64 | 64 | |
| 65 | for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| { | |
| 66 | if (Type.fromInterned(field_ty).bitSize(zcu) > 32 or | |
| 67 | ty.fieldAlignment(field_index, zcu).compare(.gt, .@"32")) | |
| 68 | { | |
| 65 | if (union_obj.alignment.compareStrict(.gt, .@"32")) { | |
| 66 | return Class.arrSize(bit_size, 64); | |
| 67 | } | |
| 68 | ||
| 69 | for (union_obj.field_types.get(ip)) |field_ty| { | |
| 70 | if (Type.fromInterned(field_ty).bitSize(zcu) > 32) { | |
| 69 | 71 | return Class.arrSize(bit_size, 64); |
| 70 | 72 | } |
| 71 | 73 | } |
src/codegen/c.zig+2390-3190| ... | ... | @@ -50,32 +50,39 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { |
| 50 | 50 | /// * The types used, so declarations can be emitted in `flush` |
| 51 | 51 | /// * The lazy functions used, so definitions can be emitted in `flush` |
| 52 | 52 | pub const Mir = struct { |
| 53 | // These remaining fields are essentially just an owned version of `link.C.AvBlock`. | |
| 54 | fwd_decl: []u8, | |
| 55 | code_header: []u8, | |
| 56 | code: []u8, | |
| 53 | 57 | /// This map contains all the UAVs we saw generating this function. |
| 54 | 58 | /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields. |
| 55 | 59 | /// Key is the value of the UAV; value is the UAV's alignment, or |
| 56 | 60 | /// `.none` for natural alignment. The specified alignment is never |
| 57 | 61 | /// less than the natural alignment. |
| 58 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 59 | // These remaining fields are essentially just an owned version of `link.C.AvBlock`. | |
| 60 | code_header: []u8, | |
| 61 | code: []u8, | |
| 62 | fwd_decl: []u8, | |
| 63 | ctype_pool: CType.Pool, | |
| 64 | lazy_fns: LazyFnMap, | |
| 62 | need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 63 | ctype_deps: CType.Dependencies, | |
| 64 | /// Key is an enum type for which we need a generated `@tagName` function. | |
| 65 | need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 66 | /// Key is a function Nav for which we need a generated `zig_never_tail` wrapper. | |
| 67 | need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), | |
| 68 | /// Key is a function Nav for which we need a generated `zig_never_inline` wrapper. | |
| 69 | need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), | |
| 65 | 70 | |
| 66 | 71 | pub fn deinit(mir: *Mir, gpa: Allocator) void { |
| 67 | mir.uavs.deinit(gpa); | |
| 72 | gpa.free(mir.fwd_decl); | |
| 68 | 73 | gpa.free(mir.code_header); |
| 69 | 74 | gpa.free(mir.code); |
| 70 | gpa.free(mir.fwd_decl); | |
| 71 | mir.ctype_pool.deinit(gpa); | |
| 72 | mir.lazy_fns.deinit(gpa); | |
| 75 | mir.need_uavs.deinit(gpa); | |
| 76 | mir.ctype_deps.deinit(gpa); | |
| 77 | mir.need_tag_name_funcs.deinit(gpa); | |
| 78 | mir.need_never_tail_funcs.deinit(gpa); | |
| 79 | mir.need_never_inline_funcs.deinit(gpa); | |
| 73 | 80 | } |
| 74 | 81 | }; |
| 75 | 82 | |
| 76 | pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail}; | |
| 83 | pub const Error = Writer.Error || Allocator.Error || error{AnalysisFail}; | |
| 77 | 84 | |
| 78 | pub const CType = @import("c/Type.zig"); | |
| 85 | pub const CType = @import("c/type.zig").CType; | |
| 79 | 86 | |
| 80 | 87 | pub const CValue = union(enum) { |
| 81 | 88 | none: void, |
| ... | ... | @@ -87,8 +94,6 @@ pub const CValue = union(enum) { |
| 87 | 94 | constant: Value, |
| 88 | 95 | /// Index into the parameters |
| 89 | 96 | arg: usize, |
| 90 | /// The array field of a parameter | |
| 91 | arg_array: usize, | |
| 92 | 97 | /// Index into a tuple's fields |
| 93 | 98 | field: usize, |
| 94 | 99 | /// By-value |
| ... | ... | @@ -100,8 +105,6 @@ pub const CValue = union(enum) { |
| 100 | 105 | identifier: []const u8, |
| 101 | 106 | /// Rendered as "payload." followed by as identifier (using fmtIdent) |
| 102 | 107 | payload_identifier: []const u8, |
| 103 | /// Rendered with fmtCTypePoolString | |
| 104 | ctype_pool_string: CType.Pool.String, | |
| 105 | 108 | |
| 106 | 109 | fn eql(lhs: CValue, rhs: CValue) bool { |
| 107 | 110 | return switch (lhs) { |
| ... | ... | @@ -122,10 +125,6 @@ pub const CValue = union(enum) { |
| 122 | 125 | .arg => |rhs_arg_index| lhs_arg_index == rhs_arg_index, |
| 123 | 126 | else => false, |
| 124 | 127 | }, |
| 125 | .arg_array => |lhs_arg_index| switch (rhs) { | |
| 126 | .arg_array => |rhs_arg_index| lhs_arg_index == rhs_arg_index, | |
| 127 | else => false, | |
| 128 | }, | |
| 129 | 128 | .field => |lhs_field_index| switch (rhs) { |
| 130 | 129 | .field => |rhs_field_index| lhs_field_index == rhs_field_index, |
| 131 | 130 | else => false, |
| ... | ... | @@ -150,10 +149,6 @@ pub const CValue = union(enum) { |
| 150 | 149 | .payload_identifier => |rhs_id| std.mem.eql(u8, lhs_id, rhs_id), |
| 151 | 150 | else => false, |
| 152 | 151 | }, |
| 153 | .ctype_pool_string => |lhs_str| switch (rhs) { | |
| 154 | .ctype_pool_string => |rhs_str| lhs_str.index == rhs_str.index, | |
| 155 | else => false, | |
| 156 | }, | |
| 157 | 152 | }; |
| 158 | 153 | } |
| 159 | 154 | }; |
| ... | ... | @@ -163,53 +158,24 @@ const BlockData = struct { |
| 163 | 158 | result: CValue, |
| 164 | 159 | }; |
| 165 | 160 | |
| 166 | pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); | |
| 167 | ||
| 168 | pub const LazyFnKey = union(enum) { | |
| 169 | tag_name: InternPool.Index, | |
| 170 | never_tail: InternPool.Nav.Index, | |
| 171 | never_inline: InternPool.Nav.Index, | |
| 172 | }; | |
| 173 | pub const LazyFnValue = struct { | |
| 174 | fn_name: CType.Pool.String, | |
| 175 | }; | |
| 176 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); | |
| 177 | ||
| 178 | const Local = struct { | |
| 179 | ctype: CType, | |
| 180 | flags: packed struct(u32) { | |
| 181 | alignas: CType.AlignAs, | |
| 182 | _: u20 = undefined, | |
| 183 | }, | |
| 184 | ||
| 185 | fn getType(local: Local) LocalType { | |
| 186 | return .{ .ctype = local.ctype, .alignas = local.flags.alignas }; | |
| 187 | } | |
| 161 | const LocalType = struct { | |
| 162 | type: Type, | |
| 163 | alignment: Alignment, | |
| 188 | 164 | }; |
| 189 | 165 | |
| 190 | 166 | const LocalIndex = u16; |
| 191 | const LocalType = struct { ctype: CType, alignas: CType.AlignAs }; | |
| 192 | 167 | const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); |
| 193 | 168 | const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); |
| 194 | 169 | |
| 195 | 170 | const ValueRenderLocation = enum { |
| 196 | FunctionArgument, | |
| 197 | Initializer, | |
| 198 | StaticInitializer, | |
| 199 | Other, | |
| 171 | initializer, | |
| 172 | static_initializer, | |
| 173 | other, | |
| 200 | 174 | |
| 201 | 175 | fn isInitializer(loc: ValueRenderLocation) bool { |
| 202 | 176 | return switch (loc) { |
| 203 | .Initializer, .StaticInitializer => true, | |
| 204 | else => false, | |
| 205 | }; | |
| 206 | } | |
| 207 | ||
| 208 | fn toCTypeKind(loc: ValueRenderLocation) CType.Kind { | |
| 209 | return switch (loc) { | |
| 210 | .FunctionArgument => .parameter, | |
| 211 | .Initializer, .Other => .complete, | |
| 212 | .StaticInitializer => .global, | |
| 177 | .initializer, .static_initializer => true, | |
| 178 | .other => false, | |
| 213 | 179 | }; |
| 214 | 180 | } |
| 215 | 181 | }; |
| ... | ... | @@ -334,16 +300,31 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ |
| 334 | 300 | }); |
| 335 | 301 | |
| 336 | 302 | fn isReservedIdent(ident: []const u8) bool { |
| 337 | if (ident.len >= 2 and ident[0] == '_') { // C language | |
| 303 | // C language | |
| 304 | if (ident.len >= 2 and ident[0] == '_') { | |
| 338 | 305 | switch (ident[1]) { |
| 339 | 306 | 'A'...'Z', '_' => return true, |
| 340 | else => return false, | |
| 307 | else => {}, | |
| 341 | 308 | } |
| 342 | } else if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or | |
| 309 | } | |
| 310 | ||
| 311 | // windows.h | |
| 312 | if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or | |
| 343 | 313 | mem.startsWith(u8, ident, "DUMMYUNIONNAME")) |
| 344 | { // windows.h | |
| 314 | { | |
| 315 | return true; | |
| 316 | } | |
| 317 | ||
| 318 | // CType | |
| 319 | if (mem.startsWith(u8, ident, "enum__") or | |
| 320 | mem.startsWith(u8, ident, "bitpack__") or | |
| 321 | mem.startsWith(u8, ident, "aligned__") or | |
| 322 | mem.startsWith(u8, ident, "fn__")) | |
| 323 | { | |
| 345 | 324 | return true; |
| 346 | } else return reserved_idents.has(ident); | |
| 325 | } | |
| 326 | ||
| 327 | return reserved_idents.has(ident); | |
| 347 | 328 | } |
| 348 | 329 | |
| 349 | 330 | fn formatIdentSolo(ident: []const u8, w: *Writer) Writer.Error!void { |
| ... | ... | @@ -361,7 +342,7 @@ fn formatIdentOptions(ident: []const u8, w: *Writer, solo: bool) Writer.Error!vo |
| 361 | 342 | for (ident, 0..) |c, i| { |
| 362 | 343 | switch (c) { |
| 363 | 344 | 'a'...'z', 'A'...'Z', '_' => try w.writeByte(c), |
| 364 | '.' => try w.writeByte('_'), | |
| 345 | '.', ' ' => try w.writeByte('_'), | |
| 365 | 346 | '0'...'9' => if (i == 0) { |
| 366 | 347 | try w.print("_{x:2}", .{c}); |
| 367 | 348 | } else { |
| ... | ... | @@ -380,29 +361,6 @@ pub fn fmtIdentUnsolo(ident: []const u8) std.fmt.Alt([]const u8, formatIdentUnso |
| 380 | 361 | return .{ .data = ident }; |
| 381 | 362 | } |
| 382 | 363 | |
| 383 | const CTypePoolStringFormatData = struct { | |
| 384 | ctype_pool_string: CType.Pool.String, | |
| 385 | ctype_pool: *const CType.Pool, | |
| 386 | solo: bool, | |
| 387 | }; | |
| 388 | fn formatCTypePoolString(data: CTypePoolStringFormatData, w: *Writer) Writer.Error!void { | |
| 389 | if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice| | |
| 390 | try formatIdentOptions(slice, w, data.solo) | |
| 391 | else | |
| 392 | try w.print("{f}", .{data.ctype_pool_string.fmt(data.ctype_pool)}); | |
| 393 | } | |
| 394 | pub fn fmtCTypePoolString( | |
| 395 | ctype_pool_string: CType.Pool.String, | |
| 396 | ctype_pool: *const CType.Pool, | |
| 397 | solo: bool, | |
| 398 | ) std.fmt.Alt(CTypePoolStringFormatData, formatCTypePoolString) { | |
| 399 | return .{ .data = .{ | |
| 400 | .ctype_pool_string = ctype_pool_string, | |
| 401 | .ctype_pool = ctype_pool, | |
| 402 | .solo = solo, | |
| 403 | } }; | |
| 404 | } | |
| 405 | ||
| 406 | 364 | // Returns true if `formatIdent` would make any edits to ident. |
| 407 | 365 | // This must be kept in sync with `formatIdent`. |
| 408 | 366 | pub fn isMangledIdent(ident: []const u8, solo: bool) bool { |
| ... | ... | @@ -417,21 +375,26 @@ pub fn isMangledIdent(ident: []const u8, solo: bool) bool { |
| 417 | 375 | return false; |
| 418 | 376 | } |
| 419 | 377 | |
| 420 | /// This data is available when outputting .c code for a `InternPool.Index` | |
| 421 | /// that corresponds to `func`. | |
| 422 | /// It is not available when generating .h file. | |
| 378 | /// This data is available when rendering C source code for an interned function. | |
| 423 | 379 | pub const Function = struct { |
| 424 | 380 | air: Air, |
| 425 | 381 | liveness: Air.Liveness, |
| 426 | value_map: CValueMap, | |
| 382 | value_map: std.AutoHashMap(Air.Inst.Ref, CValue), | |
| 427 | 383 | blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .empty, |
| 428 | 384 | next_arg_index: u32 = 0, |
| 429 | 385 | next_block_index: u32 = 0, |
| 430 | object: Object, | |
| 431 | lazy_fns: LazyFnMap, | |
| 386 | dg: DeclGen, | |
| 387 | code: Writer.Allocating, | |
| 388 | indent_counter: usize, | |
| 389 | /// Key is an enum type for which we need a generated `@tagName` function. | |
| 390 | need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 391 | /// Key is a function Nav for which we need a generated `zig_never_tail` wrapper. | |
| 392 | need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), | |
| 393 | /// Key is a function Nav for which we need a generated `zig_never_inline` wrapper. | |
| 394 | need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), | |
| 432 | 395 | func_index: InternPool.Index, |
| 433 | 396 | /// All the locals, to be emitted at the top of the function. |
| 434 | locals: std.ArrayList(Local) = .empty, | |
| 397 | locals: std.ArrayList(LocalType) = .empty, | |
| 435 | 398 | /// Which locals are available for reuse, based on Type. |
| 436 | 399 | free_locals_map: LocalsMap = .{}, |
| 437 | 400 | /// Locals which will not be freed by Liveness. This is used after a |
| ... | ... | @@ -445,37 +408,41 @@ pub const Function = struct { |
| 445 | 408 | /// for the switch cond. Dispatches should set this local to the new cond. |
| 446 | 409 | loop_switch_conds: std.AutoHashMapUnmanaged(Air.Inst.Index, LocalIndex) = .empty, |
| 447 | 410 | |
| 411 | const indent_width = 1; | |
| 412 | const indent_char = ' '; | |
| 413 | ||
| 414 | fn newline(f: *Function) !void { | |
| 415 | const w = &f.code.writer; | |
| 416 | try w.writeByte('\n'); | |
| 417 | try w.splatByteAll(indent_char, f.indent_counter); | |
| 418 | } | |
| 419 | fn indent(f: *Function) void { | |
| 420 | f.indent_counter += indent_width; | |
| 421 | } | |
| 422 | fn outdent(f: *Function) !void { | |
| 423 | f.indent_counter -= indent_width; | |
| 424 | const written = f.code.written(); | |
| 425 | switch (written[written.len - 1]) { | |
| 426 | indent_char => f.code.shrinkRetainingCapacity(written.len - indent_width), | |
| 427 | '\n' => try f.code.writer.splatByteAll(indent_char, f.indent_counter), | |
| 428 | else => { | |
| 429 | std.debug.print("\"{f}\"\n", .{std.zig.fmtString(written[written.len -| 100..])}); | |
| 430 | unreachable; | |
| 431 | }, | |
| 432 | } | |
| 433 | } | |
| 434 | ||
| 448 | 435 | fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue { |
| 449 | 436 | const gop = try f.value_map.getOrPut(ref); |
| 450 | if (gop.found_existing) return gop.value_ptr.*; | |
| 451 | ||
| 452 | const pt = f.object.dg.pt; | |
| 453 | const zcu = pt.zcu; | |
| 454 | const val = (try f.air.value(ref, pt)).?; | |
| 455 | const ty = f.typeOf(ref); | |
| 456 | ||
| 457 | const result: CValue = if (lowersToArray(ty, zcu)) result: { | |
| 458 | const ch = &f.object.code_header.writer; | |
| 459 | const decl_c_value = try f.allocLocalValue(.{ | |
| 460 | .ctype = try f.ctypeFromType(ty, .complete), | |
| 461 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)), | |
| 462 | }); | |
| 463 | const gpa = f.object.dg.gpa; | |
| 464 | try f.allocs.put(gpa, decl_c_value.new_local, false); | |
| 465 | try ch.writeAll("static "); | |
| 466 | try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete); | |
| 467 | try ch.writeAll(" = "); | |
| 468 | try f.object.dg.renderValue(ch, val, .StaticInitializer); | |
| 469 | try ch.writeAll(";\n "); | |
| 470 | break :result .{ .local = decl_c_value.new_local }; | |
| 471 | } else .{ .constant = val }; | |
| 472 | ||
| 473 | gop.value_ptr.* = result; | |
| 474 | return result; | |
| 437 | if (!gop.found_existing) { | |
| 438 | const val = try f.air.value(ref, f.dg.pt); | |
| 439 | gop.value_ptr.* = .{ .constant = val.? }; | |
| 440 | } | |
| 441 | return gop.value_ptr.*; | |
| 475 | 442 | } |
| 476 | 443 | |
| 477 | 444 | fn wantSafety(f: *Function) bool { |
| 478 | return switch (f.object.dg.pt.zcu.optimizeMode()) { | |
| 445 | return switch (f.dg.pt.zcu.optimizeMode()) { | |
| 479 | 446 | .Debug, .ReleaseSafe => true, |
| 480 | 447 | .ReleaseFast, .ReleaseSmall => false, |
| 481 | 448 | }; |
| ... | ... | @@ -485,18 +452,16 @@ pub const Function = struct { |
| 485 | 452 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| 486 | 453 | /// that responsibility lies with the caller. |
| 487 | 454 | fn allocLocalValue(f: *Function, local_type: LocalType) !CValue { |
| 488 | try f.locals.ensureUnusedCapacity(f.object.dg.gpa, 1); | |
| 489 | defer f.locals.appendAssumeCapacity(.{ | |
| 490 | .ctype = local_type.ctype, | |
| 491 | .flags = .{ .alignas = local_type.alignas }, | |
| 492 | }); | |
| 493 | return .{ .new_local = @intCast(f.locals.items.len) }; | |
| 455 | try f.locals.ensureUnusedCapacity(f.dg.gpa, 1); | |
| 456 | const index = f.locals.items.len; | |
| 457 | f.locals.appendAssumeCapacity(local_type); | |
| 458 | return .{ .new_local = @intCast(index) }; | |
| 494 | 459 | } |
| 495 | 460 | |
| 496 | 461 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { |
| 497 | 462 | return f.allocAlignedLocal(inst, .{ |
| 498 | .ctype = try f.ctypeFromType(ty, .complete), | |
| 499 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(f.object.dg.pt.zcu)), | |
| 463 | .type = ty, | |
| 464 | .alignment = .none, | |
| 500 | 465 | }); |
| 501 | 466 | } |
| 502 | 467 | |
| ... | ... | @@ -524,11 +489,10 @@ pub const Function = struct { |
| 524 | 489 | .none => unreachable, |
| 525 | 490 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| 526 | 491 | .local_ref => |i| try w.print("&t{d}", .{i}), |
| 527 | .constant => |val| try f.object.dg.renderValue(w, val, location), | |
| 492 | .constant => |val| try f.dg.renderValue(w, val, location), | |
| 528 | 493 | .arg => |i| try w.print("a{d}", .{i}), |
| 529 | .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), | |
| 530 | .undef => |ty| try f.object.dg.renderUndefValue(w, ty, location), | |
| 531 | else => try f.object.dg.writeCValue(w, c_value), | |
| 494 | .undef => |ty| try f.dg.renderUndefValue(w, ty, location), | |
| 495 | else => try f.dg.writeCValue(w, c_value), | |
| 532 | 496 | } |
| 533 | 497 | } |
| 534 | 498 | |
| ... | ... | @@ -537,17 +501,12 @@ pub const Function = struct { |
| 537 | 501 | .none => unreachable, |
| 538 | 502 | .new_local, .local, .constant => { |
| 539 | 503 | try w.writeAll("(*"); |
| 540 | try f.writeCValue(w, c_value, .Other); | |
| 504 | try f.writeCValue(w, c_value, .other); | |
| 541 | 505 | try w.writeByte(')'); |
| 542 | 506 | }, |
| 543 | 507 | .local_ref => |i| try w.print("t{d}", .{i}), |
| 544 | 508 | .arg => |i| try w.print("(*a{d})", .{i}), |
| 545 | .arg_array => |i| { | |
| 546 | try w.writeAll("(*"); | |
| 547 | try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }); | |
| 548 | try w.writeByte(')'); | |
| 549 | }, | |
| 550 | else => try f.object.dg.writeCValueDeref(w, c_value), | |
| 509 | else => try f.dg.writeCValueDeref(w, c_value), | |
| 551 | 510 | } |
| 552 | 511 | } |
| 553 | 512 | |
| ... | ... | @@ -558,119 +517,77 @@ pub const Function = struct { |
| 558 | 517 | member: CValue, |
| 559 | 518 | ) Error!void { |
| 560 | 519 | switch (c_value) { |
| 561 | .new_local, .local, .local_ref, .constant, .arg, .arg_array => { | |
| 562 | try f.writeCValue(w, c_value, .Other); | |
| 520 | .new_local, .local, .local_ref, .constant, .arg => { | |
| 521 | try f.writeCValue(w, c_value, .other); | |
| 563 | 522 | try w.writeByte('.'); |
| 564 | try f.writeCValue(w, member, .Other); | |
| 523 | try f.writeCValue(w, member, .other); | |
| 565 | 524 | }, |
| 566 | else => return f.object.dg.writeCValueMember(w, c_value, member), | |
| 525 | else => return f.dg.writeCValueMember(w, c_value, member), | |
| 567 | 526 | } |
| 568 | 527 | } |
| 569 | 528 | |
| 570 | 529 | fn writeCValueDerefMember(f: *Function, w: *Writer, c_value: CValue, member: CValue) !void { |
| 571 | 530 | switch (c_value) { |
| 572 | .new_local, .local, .arg, .arg_array => { | |
| 573 | try f.writeCValue(w, c_value, .Other); | |
| 531 | .new_local, .local, .arg => { | |
| 532 | try f.writeCValue(w, c_value, .other); | |
| 574 | 533 | try w.writeAll("->"); |
| 575 | 534 | }, |
| 576 | 535 | .constant => { |
| 577 | 536 | try w.writeByte('('); |
| 578 | try f.writeCValue(w, c_value, .Other); | |
| 537 | try f.writeCValue(w, c_value, .other); | |
| 579 | 538 | try w.writeAll(")->"); |
| 580 | 539 | }, |
| 581 | 540 | .local_ref => { |
| 582 | 541 | try f.writeCValueDeref(w, c_value); |
| 583 | 542 | try w.writeByte('.'); |
| 584 | 543 | }, |
| 585 | else => return f.object.dg.writeCValueDerefMember(w, c_value, member), | |
| 544 | else => return f.dg.writeCValueDerefMember(w, c_value, member), | |
| 586 | 545 | } |
| 587 | try f.writeCValue(w, member, .Other); | |
| 546 | try f.writeCValue(w, member, .other); | |
| 588 | 547 | } |
| 589 | 548 | |
| 590 | 549 | fn fail(f: *Function, comptime format: []const u8, args: anytype) Error { |
| 591 | return f.object.dg.fail(format, args); | |
| 592 | } | |
| 593 | ||
| 594 | fn ctypeFromType(f: *Function, ty: Type, kind: CType.Kind) !CType { | |
| 595 | return f.object.dg.ctypeFromType(ty, kind); | |
| 596 | } | |
| 597 | ||
| 598 | fn byteSize(f: *Function, ctype: CType) u64 { | |
| 599 | return f.object.dg.byteSize(ctype); | |
| 600 | } | |
| 601 | ||
| 602 | fn renderType(f: *Function, w: *Writer, ctype: Type) !void { | |
| 603 | return f.object.dg.renderType(w, ctype); | |
| 550 | return f.dg.fail(format, args); | |
| 604 | 551 | } |
| 605 | 552 | |
| 606 | fn renderCType(f: *Function, w: *Writer, ctype: CType) !void { | |
| 607 | return f.object.dg.renderCType(w, ctype); | |
| 553 | fn renderType(f: *Function, w: *Writer, ty: Type) !void { | |
| 554 | return f.dg.renderType(w, ty); | |
| 608 | 555 | } |
| 609 | 556 | |
| 610 | 557 | fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { |
| 611 | return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); | |
| 558 | return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); | |
| 612 | 559 | } |
| 613 | 560 | |
| 614 | 561 | fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { |
| 615 | return f.object.dg.fmtIntLiteralDec(val, .Other); | |
| 562 | return f.dg.fmtIntLiteralDec(val, .other); | |
| 616 | 563 | } |
| 617 | 564 | |
| 618 | 565 | fn fmtIntLiteralHex(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { |
| 619 | return f.object.dg.fmtIntLiteralHex(val, .Other); | |
| 620 | } | |
| 621 | ||
| 622 | fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 { | |
| 623 | const gpa = f.object.dg.gpa; | |
| 624 | const pt = f.object.dg.pt; | |
| 625 | const zcu = pt.zcu; | |
| 626 | const ip = &zcu.intern_pool; | |
| 627 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 628 | ||
| 629 | const gop = try f.lazy_fns.getOrPut(gpa, key); | |
| 630 | if (!gop.found_existing) { | |
| 631 | errdefer _ = f.lazy_fns.pop(); | |
| 632 | ||
| 633 | gop.value_ptr.* = .{ | |
| 634 | .fn_name = switch (key) { | |
| 635 | .tag_name, | |
| 636 | => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{ | |
| 637 | @tagName(key), | |
| 638 | fmtIdentUnsolo(ip.loadEnumType(enum_ty).name.toSlice(ip)), | |
| 639 | @intFromEnum(enum_ty), | |
| 640 | }), | |
| 641 | .never_tail, | |
| 642 | .never_inline, | |
| 643 | => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{ | |
| 644 | @tagName(key), | |
| 645 | fmtIdentUnsolo(ip.getNav(owner_nav).name.toSlice(ip)), | |
| 646 | @intFromEnum(owner_nav), | |
| 647 | }), | |
| 648 | }, | |
| 649 | }; | |
| 650 | } | |
| 651 | return gop.value_ptr.fn_name.toSlice(ctype_pool).?; | |
| 566 | return f.dg.fmtIntLiteralHex(val, .other); | |
| 652 | 567 | } |
| 653 | 568 | |
| 654 | 569 | pub fn deinit(f: *Function) void { |
| 655 | const gpa = f.object.dg.gpa; | |
| 570 | const gpa = f.dg.gpa; | |
| 656 | 571 | f.allocs.deinit(gpa); |
| 657 | 572 | f.locals.deinit(gpa); |
| 658 | 573 | deinitFreeLocalsMap(gpa, &f.free_locals_map); |
| 659 | 574 | f.blocks.deinit(gpa); |
| 660 | 575 | f.value_map.deinit(); |
| 661 | f.lazy_fns.deinit(gpa); | |
| 576 | f.need_tag_name_funcs.deinit(gpa); | |
| 577 | f.need_never_tail_funcs.deinit(gpa); | |
| 578 | f.need_never_inline_funcs.deinit(gpa); | |
| 662 | 579 | f.loop_switch_conds.deinit(gpa); |
| 663 | 580 | } |
| 664 | 581 | |
| 665 | 582 | fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { |
| 666 | return f.air.typeOf(inst, &f.object.dg.pt.zcu.intern_pool); | |
| 583 | return f.air.typeOf(inst, &f.dg.pt.zcu.intern_pool); | |
| 667 | 584 | } |
| 668 | 585 | |
| 669 | 586 | fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type { |
| 670 | return f.air.typeOfIndex(inst, &f.object.dg.pt.zcu.intern_pool); | |
| 587 | return f.air.typeOfIndex(inst, &f.dg.pt.zcu.intern_pool); | |
| 671 | 588 | } |
| 672 | 589 | |
| 673 | fn copyCValue(f: *Function, ctype: CType, dst: CValue, src: CValue) !void { | |
| 590 | fn copyCValue(f: *Function, dst: CValue, src: CValue) !void { | |
| 674 | 591 | switch (dst) { |
| 675 | 592 | .new_local, .local => |dst_local_index| switch (src) { |
| 676 | 593 | .new_local, .local => |src_local_index| if (dst_local_index == src_local_index) return, |
| ... | ... | @@ -678,12 +595,12 @@ pub const Function = struct { |
| 678 | 595 | }, |
| 679 | 596 | else => {}, |
| 680 | 597 | } |
| 681 | const w = &f.object.code.writer; | |
| 682 | const a = try Assignment.start(f, w, ctype); | |
| 683 | try f.writeCValue(w, dst, .Other); | |
| 684 | try a.assign(f, w); | |
| 685 | try f.writeCValue(w, src, .Other); | |
| 686 | try a.end(f, w); | |
| 598 | const w = &f.code.writer; | |
| 599 | try f.writeCValue(w, dst, .other); | |
| 600 | try w.writeAll(" = "); | |
| 601 | try f.writeCValue(w, src, .other); | |
| 602 | try w.writeByte(';'); | |
| 603 | try f.newline(); | |
| 687 | 604 | } |
| 688 | 605 | |
| 689 | 606 | fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue { |
| ... | ... | @@ -694,7 +611,7 @@ pub const Function = struct { |
| 694 | 611 | else => { |
| 695 | 612 | try freeCValue(f, inst, src); |
| 696 | 613 | const dst = try f.allocLocal(inst, ty); |
| 697 | try f.copyCValue(try f.ctypeFromType(ty, .complete), dst, src); | |
| 614 | try f.copyCValue(dst, src); | |
| 698 | 615 | return dst; |
| 699 | 616 | }, |
| 700 | 617 | } |
| ... | ... | @@ -708,51 +625,17 @@ pub const Function = struct { |
| 708 | 625 | } |
| 709 | 626 | }; |
| 710 | 627 | |
| 711 | /// This data is available when outputting .c code for a `Zcu`. | |
| 712 | /// It is not available when generating .h file. | |
| 713 | pub const Object = struct { | |
| 714 | dg: DeclGen, | |
| 715 | code_header: Writer.Allocating, | |
| 716 | code: Writer.Allocating, | |
| 717 | indent_counter: usize, | |
| 718 | ||
| 719 | const indent_width = 1; | |
| 720 | const indent_char = ' '; | |
| 721 | ||
| 722 | fn newline(o: *Object) !void { | |
| 723 | const w = &o.code.writer; | |
| 724 | try w.writeByte('\n'); | |
| 725 | try w.splatByteAll(indent_char, o.indent_counter); | |
| 726 | } | |
| 727 | fn indent(o: *Object) void { | |
| 728 | o.indent_counter += indent_width; | |
| 729 | } | |
| 730 | fn outdent(o: *Object) !void { | |
| 731 | o.indent_counter -= indent_width; | |
| 732 | const written = o.code.written(); | |
| 733 | switch (written[written.len - 1]) { | |
| 734 | indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width), | |
| 735 | '\n' => try o.code.writer.splatByteAll(indent_char, o.indent_counter), | |
| 736 | else => { | |
| 737 | std.debug.print("\"{f}\"\n", .{std.zig.fmtString(written[written.len -| 100..])}); | |
| 738 | unreachable; | |
| 739 | }, | |
| 740 | } | |
| 741 | } | |
| 742 | }; | |
| 743 | ||
| 744 | /// This data is available both when outputting .c code and when outputting an .h file. | |
| 628 | /// This data is available when rendering *any* C source code (function or otherwise). | |
| 745 | 629 | pub const DeclGen = struct { |
| 746 | 630 | gpa: Allocator, |
| 631 | arena: Allocator, | |
| 747 | 632 | pt: Zcu.PerThread, |
| 748 | 633 | mod: *Module, |
| 749 | pass: Pass, | |
| 634 | owner_nav: InternPool.Nav.Index.Optional, | |
| 750 | 635 | is_naked_fn: bool, |
| 751 | 636 | expected_block: ?u32, |
| 752 | fwd_decl: Writer.Allocating, | |
| 753 | 637 | error_msg: ?*Zcu.ErrorMsg, |
| 754 | ctype_pool: CType.Pool, | |
| 755 | scratch: std.ArrayList(u32), | |
| 638 | ctype_deps: CType.Dependencies, | |
| 756 | 639 | /// This map contains all the UAVs we saw generating this function. |
| 757 | 640 | /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields. |
| 758 | 641 | /// Key is the value of the UAV; value is the UAV's alignment, or |
| ... | ... | @@ -760,16 +643,10 @@ pub const DeclGen = struct { |
| 760 | 643 | /// less than the natural alignment. |
| 761 | 644 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), |
| 762 | 645 | |
| 763 | pub const Pass = union(enum) { | |
| 764 | nav: InternPool.Nav.Index, | |
| 765 | uav: InternPool.Index, | |
| 766 | flush, | |
| 767 | }; | |
| 768 | ||
| 769 | 646 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { |
| 770 | 647 | @branchHint(.cold); |
| 771 | 648 | const zcu = dg.pt.zcu; |
| 772 | const src_loc = zcu.navSrcLoc(dg.pass.nav); | |
| 649 | const src_loc = zcu.navSrcLoc(dg.owner_nav.unwrap().?); | |
| 773 | 650 | dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args); |
| 774 | 651 | return error.AnalysisFail; |
| 775 | 652 | } |
| ... | ... | @@ -783,14 +660,13 @@ pub const DeclGen = struct { |
| 783 | 660 | const pt = dg.pt; |
| 784 | 661 | const zcu = pt.zcu; |
| 785 | 662 | const ip = &zcu.intern_pool; |
| 786 | const ctype_pool = &dg.ctype_pool; | |
| 787 | 663 | const uav_val = Value.fromInterned(uav.val); |
| 788 | 664 | const uav_ty = uav_val.typeOf(zcu); |
| 789 | 665 | |
| 790 | 666 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 791 | 667 | const ptr_ty: Type = .fromInterned(uav.orig_ty); |
| 792 | if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isFnOrHasRuntimeBits(zcu)) { | |
| 793 | return dg.writeCValue(w, .{ .undef = ptr_ty }); | |
| 668 | if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 669 | return dg.renderUndefValue(w, ptr_ty, location); | |
| 794 | 670 | } |
| 795 | 671 | |
| 796 | 672 | // Chase function values in order to be able to reference the original function. |
| ... | ... | @@ -805,14 +681,12 @@ pub const DeclGen = struct { |
| 805 | 681 | // them). The analysis until now should ensure that the C function |
| 806 | 682 | // pointers are compatible. If they are not, then there is a bug |
| 807 | 683 | // somewhere and we should let the C compiler tell us about it. |
| 808 | const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); | |
| 809 | const elem_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; | |
| 810 | const uav_ctype = try dg.ctypeFromType(uav_ty, .complete); | |
| 811 | const need_cast = !elem_ctype.eql(uav_ctype) and | |
| 812 | (elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function); | |
| 684 | const elem_ty = ptr_ty.childType(zcu); | |
| 685 | const need_cast = elem_ty.toIntern() != uav_ty.toIntern() and | |
| 686 | elem_ty.zigTypeTag(zcu) != .@"fn" or uav_ty.zigTypeTag(zcu) != .@"fn"; | |
| 813 | 687 | if (need_cast) { |
| 814 | 688 | try w.writeAll("(("); |
| 815 | try dg.renderCType(w, ptr_ctype); | |
| 689 | try dg.renderType(w, ptr_ty); | |
| 816 | 690 | try w.writeByte(')'); |
| 817 | 691 | } |
| 818 | 692 | try w.writeByte('&'); |
| ... | ... | @@ -842,11 +716,9 @@ pub const DeclGen = struct { |
| 842 | 716 | nav_index: InternPool.Nav.Index, |
| 843 | 717 | location: ValueRenderLocation, |
| 844 | 718 | ) Error!void { |
| 845 | _ = location; | |
| 846 | 719 | const pt = dg.pt; |
| 847 | 720 | const zcu = pt.zcu; |
| 848 | 721 | const ip = &zcu.intern_pool; |
| 849 | const ctype_pool = &dg.ctype_pool; | |
| 850 | 722 | |
| 851 | 723 | // Chase function values in order to be able to reference the original function. |
| 852 | 724 | const owner_nav = switch (ip.getNav(nav_index).status) { |
| ... | ... | @@ -862,26 +734,24 @@ pub const DeclGen = struct { |
| 862 | 734 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 863 | 735 | const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip)); |
| 864 | 736 | const ptr_ty = try pt.navPtrType(owner_nav); |
| 865 | if (!nav_ty.isFnOrHasRuntimeBits(zcu)) { | |
| 866 | return dg.writeCValue(w, .{ .undef = ptr_ty }); | |
| 737 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 738 | return dg.renderUndefValue(w, ptr_ty, location); | |
| 867 | 739 | } |
| 868 | 740 | |
| 869 | 741 | // We shouldn't cast C function pointers as this is UB (when you call |
| 870 | 742 | // them). The analysis until now should ensure that the C function |
| 871 | 743 | // pointers are compatible. If they are not, then there is a bug |
| 872 | 744 | // somewhere and we should let the C compiler tell us about it. |
| 873 | const ctype = try dg.ctypeFromType(ptr_ty, .complete); | |
| 874 | const elem_ctype = ctype.info(ctype_pool).pointer.elem_ctype; | |
| 875 | const nav_ctype = try dg.ctypeFromType(nav_ty, .complete); | |
| 876 | const need_cast = !elem_ctype.eql(nav_ctype) and | |
| 877 | (elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function); | |
| 745 | const elem_ty = ptr_ty.childType(zcu); | |
| 746 | const need_cast = elem_ty.toIntern() != nav_ty.toIntern() and | |
| 747 | elem_ty.zigTypeTag(zcu) != .@"fn" or nav_ty.zigTypeTag(zcu) != .@"fn"; | |
| 878 | 748 | if (need_cast) { |
| 879 | 749 | try w.writeAll("(("); |
| 880 | try dg.renderCType(w, ctype); | |
| 750 | try dg.renderType(w, ptr_ty); | |
| 881 | 751 | try w.writeByte(')'); |
| 882 | 752 | } |
| 883 | 753 | try w.writeByte('&'); |
| 884 | try dg.renderNavName(w, owner_nav); | |
| 754 | try renderNavName(w, owner_nav, ip); | |
| 885 | 755 | if (need_cast) try w.writeByte(')'); |
| 886 | 756 | } |
| 887 | 757 | |
| ... | ... | @@ -896,11 +766,10 @@ pub const DeclGen = struct { |
| 896 | 766 | switch (derivation) { |
| 897 | 767 | .comptime_alloc_ptr, .comptime_field_ptr => unreachable, |
| 898 | 768 | .int => |int| { |
| 899 | const ptr_ctype = try dg.ctypeFromType(int.ptr_ty, .complete); | |
| 900 | 769 | const addr_val = try pt.intValue(.usize, int.addr); |
| 901 | 770 | try w.writeByte('('); |
| 902 | try dg.renderCType(w, ptr_ctype); | |
| 903 | try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .Other)}); | |
| 771 | try dg.renderType(w, int.ptr_ty); | |
| 772 | try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .other)}); | |
| 904 | 773 | }, |
| 905 | 774 | |
| 906 | 775 | .nav_ptr => |nav| try dg.renderNav(w, nav, location), |
| ... | ... | @@ -915,14 +784,10 @@ pub const DeclGen = struct { |
| 915 | 784 | .field_ptr => |field| { |
| 916 | 785 | const parent_ptr_ty = try field.parent.ptrType(pt); |
| 917 | 786 | |
| 918 | // Ensure complete type definition is available before accessing fields. | |
| 919 | _ = try dg.ctypeFromType(parent_ptr_ty.childType(zcu), .complete); | |
| 920 | ||
| 921 | 787 | switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, zcu)) { |
| 922 | 788 | .begin => { |
| 923 | const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete); | |
| 924 | 789 | try w.writeByte('('); |
| 925 | try dg.renderCType(w, ptr_ctype); | |
| 790 | try dg.renderType(w, field.result_ptr_ty); | |
| 926 | 791 | try w.writeByte(')'); |
| 927 | 792 | try dg.renderPointer(w, field.parent.*, location); |
| 928 | 793 | }, |
| ... | ... | @@ -933,51 +798,40 @@ pub const DeclGen = struct { |
| 933 | 798 | try dg.writeCValue(w, name); |
| 934 | 799 | }, |
| 935 | 800 | .byte_offset => |byte_offset| { |
| 936 | const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete); | |
| 937 | 801 | try w.writeByte('('); |
| 938 | try dg.renderCType(w, ptr_ctype); | |
| 802 | try dg.renderType(w, field.result_ptr_ty); | |
| 939 | 803 | try w.writeByte(')'); |
| 940 | 804 | const offset_val = try pt.intValue(.usize, byte_offset); |
| 941 | 805 | try w.writeAll("((char *)"); |
| 942 | 806 | try dg.renderPointer(w, field.parent.*, location); |
| 943 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)}); | |
| 807 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .other)}); | |
| 944 | 808 | }, |
| 945 | 809 | } |
| 946 | 810 | }, |
| 947 | 811 | |
| 948 | 812 | .elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) { |
| 949 | 813 | // Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer. |
| 950 | const ptr_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete); | |
| 951 | 814 | try w.writeByte('('); |
| 952 | try dg.renderCType(w, ptr_ctype); | |
| 815 | try dg.renderType(w, elem.result_ptr_ty); | |
| 953 | 816 | try w.writeByte(')'); |
| 954 | 817 | try dg.renderPointer(w, elem.parent.*, location); |
| 955 | 818 | } else { |
| 956 | 819 | const index_val = try pt.intValue(.usize, elem.elem_idx); |
| 957 | // We want to do pointer arithmetic on a pointer to the element type. | |
| 958 | // We might have a pointer-to-array. In this case, we must cast first. | |
| 959 | const result_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete); | |
| 960 | const parent_ctype = try dg.ctypeFromType(try elem.parent.ptrType(pt), .complete); | |
| 961 | if (result_ctype.eql(parent_ctype)) { | |
| 962 | // The pointer already has an appropriate type - just do the arithmetic. | |
| 820 | try w.writeByte('('); | |
| 821 | // We want to do pointer arithmetic on a pointer to the element type, but the parent | |
| 822 | // might be a pointer-to-array, in which case we must cast it. | |
| 823 | if (elem.result_ptr_ty.toIntern() != (try elem.parent.ptrType(pt)).toIntern()) { | |
| 963 | 824 | try w.writeByte('('); |
| 964 | try dg.renderPointer(w, elem.parent.*, location); | |
| 965 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)}); | |
| 966 | } else { | |
| 967 | // We probably have an array pointer `T (*)[n]`. Cast to an element pointer, | |
| 968 | // and *then* apply the index. | |
| 969 | try w.writeAll("(("); | |
| 970 | try dg.renderCType(w, result_ctype); | |
| 825 | try dg.renderType(w, elem.result_ptr_ty); | |
| 971 | 826 | try w.writeByte(')'); |
| 972 | try dg.renderPointer(w, elem.parent.*, location); | |
| 973 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)}); | |
| 974 | 827 | } |
| 828 | try dg.renderPointer(w, elem.parent.*, location); | |
| 829 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .other)}); | |
| 975 | 830 | }, |
| 976 | 831 | |
| 977 | 832 | .offset_and_cast => |oac| { |
| 978 | const ptr_ctype = try dg.ctypeFromType(oac.new_ptr_ty, .complete); | |
| 979 | 833 | try w.writeByte('('); |
| 980 | try dg.renderCType(w, ptr_ctype); | |
| 834 | try dg.renderType(w, oac.new_ptr_ty); | |
| 981 | 835 | try w.writeByte(')'); |
| 982 | 836 | if (oac.byte_offset == 0) { |
| 983 | 837 | try dg.renderPointer(w, oac.parent.*, location); |
| ... | ... | @@ -985,14 +839,40 @@ pub const DeclGen = struct { |
| 985 | 839 | const offset_val = try pt.intValue(.usize, oac.byte_offset); |
| 986 | 840 | try w.writeAll("((char *)"); |
| 987 | 841 | try dg.renderPointer(w, oac.parent.*, location); |
| 988 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)}); | |
| 842 | try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .other)}); | |
| 989 | 843 | } |
| 990 | 844 | }, |
| 991 | 845 | } |
| 992 | 846 | } |
| 993 | 847 | |
| 994 | fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void { | |
| 995 | try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))}); | |
| 848 | fn renderValueAsLvalue( | |
| 849 | dg: *DeclGen, | |
| 850 | w: *Writer, | |
| 851 | val: Value, | |
| 852 | ) Error!void { | |
| 853 | const zcu = dg.pt.zcu; | |
| 854 | ||
| 855 | // If the type of `val` lowers to a C struct or union type, then `renderValue` will render | |
| 856 | // it as a compound literal, and compound literals are already lvalues. | |
| 857 | const ty = val.typeOf(zcu); | |
| 858 | const is_aggregate: bool = switch (ty.zigTypeTag(zcu)) { | |
| 859 | .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { | |
| 860 | .auto, .@"extern" => true, | |
| 861 | .@"packed" => false, | |
| 862 | }, | |
| 863 | .array, | |
| 864 | .vector, | |
| 865 | .error_union, | |
| 866 | .optional, | |
| 867 | => true, | |
| 868 | else => false, | |
| 869 | }; | |
| 870 | if (is_aggregate) return renderValue(dg, w, val, .other); | |
| 871 | ||
| 872 | // Otherwise, use a UAV. | |
| 873 | const gop = try dg.uavs.getOrPut(dg.gpa, val.toIntern()); | |
| 874 | if (!gop.found_existing) gop.value_ptr.* = .none; | |
| 875 | try renderUavName(w, val); | |
| 996 | 876 | } |
| 997 | 877 | |
| 998 | 878 | fn renderValue( |
| ... | ... | @@ -1005,16 +885,13 @@ pub const DeclGen = struct { |
| 1005 | 885 | const zcu = pt.zcu; |
| 1006 | 886 | const ip = &zcu.intern_pool; |
| 1007 | 887 | const target = &dg.mod.resolved_target.result; |
| 1008 | const ctype_pool = &dg.ctype_pool; | |
| 1009 | 888 | |
| 1010 | 889 | const initializer_type: ValueRenderLocation = switch (location) { |
| 1011 | .StaticInitializer => .StaticInitializer, | |
| 1012 | else => .Initializer, | |
| 890 | .static_initializer => .static_initializer, | |
| 891 | else => .initializer, | |
| 1013 | 892 | }; |
| 1014 | 893 | |
| 1015 | 894 | const ty = val.typeOf(zcu); |
| 1016 | if (val.isUndef(zcu)) return dg.renderUndefValue(w, ty, location); | |
| 1017 | const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); | |
| 1018 | 895 | switch (ip.indexToKey(val.toIntern())) { |
| 1019 | 896 | // types, not values |
| 1020 | 897 | .int_type, |
| ... | ... | @@ -1037,13 +914,11 @@ pub const DeclGen = struct { |
| 1037 | 914 | .memoized_call, |
| 1038 | 915 | => unreachable, |
| 1039 | 916 | |
| 1040 | .undef => unreachable, // handled above | |
| 917 | .undef => try dg.renderUndefValue(w, ty, location), | |
| 1041 | 918 | .simple_value => |simple_value| switch (simple_value) { |
| 1042 | 919 | // non-runtime values |
| 1043 | .undefined => unreachable, | |
| 1044 | 920 | .void => unreachable, |
| 1045 | 921 | .null => unreachable, |
| 1046 | .empty_tuple => unreachable, | |
| 1047 | 922 | .@"unreachable" => unreachable, |
| 1048 | 923 | |
| 1049 | 924 | .false => try w.writeAll("false"), |
| ... | ... | @@ -1053,59 +928,30 @@ pub const DeclGen = struct { |
| 1053 | 928 | .@"extern", |
| 1054 | 929 | .func, |
| 1055 | 930 | .enum_literal, |
| 1056 | .empty_enum_value, | |
| 1057 | 931 | => unreachable, // non-runtime values |
| 1058 | .int => |int| switch (int.storage) { | |
| 1059 | .u64, .i64, .big_int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), | |
| 1060 | .lazy_align, .lazy_size => { | |
| 1061 | try w.writeAll("(("); | |
| 1062 | try dg.renderCType(w, ctype); | |
| 1063 | try w.print("){f})", .{try dg.fmtIntLiteralHex( | |
| 1064 | try pt.intValue(.usize, val.toUnsignedInt(zcu)), | |
| 1065 | .Other, | |
| 1066 | )}); | |
| 1067 | }, | |
| 1068 | }, | |
| 1069 | .err => |err| try dg.renderErrorName(w, err.name), | |
| 1070 | .error_union => |error_union| switch (ctype.info(ctype_pool)) { | |
| 1071 | .basic => switch (error_union.val) { | |
| 1072 | .err_name => |err_name| try dg.renderErrorName(w, err_name), | |
| 932 | .int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), | |
| 933 | .err => |err| try renderErrorName(w, err.name.toSlice(ip)), | |
| 934 | .error_union => |error_union| { | |
| 935 | if (!location.isInitializer()) { | |
| 936 | try w.writeByte('('); | |
| 937 | try dg.renderType(w, ty); | |
| 938 | try w.writeByte(')'); | |
| 939 | } | |
| 940 | try w.writeAll("{ .error = "); | |
| 941 | switch (error_union.val) { | |
| 942 | .err_name => |err_name| try renderErrorName(w, err_name.toSlice(ip)), | |
| 1073 | 943 | .payload => try w.writeByte('0'), |
| 1074 | }, | |
| 1075 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 1076 | .aggregate => |aggregate| { | |
| 1077 | if (!location.isInitializer()) { | |
| 1078 | try w.writeByte('('); | |
| 1079 | try dg.renderCType(w, ctype); | |
| 1080 | try w.writeByte(')'); | |
| 1081 | } | |
| 1082 | try w.writeByte('{'); | |
| 1083 | for (0..aggregate.fields.len) |field_index| { | |
| 1084 | if (field_index > 0) try w.writeByte(','); | |
| 1085 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { | |
| 1086 | .@"error" => switch (error_union.val) { | |
| 1087 | .err_name => |err_name| try dg.renderErrorName(w, err_name), | |
| 1088 | .payload => try w.writeByte('0'), | |
| 1089 | }, | |
| 1090 | .payload => switch (error_union.val) { | |
| 1091 | .err_name => try dg.renderUndefValue( | |
| 1092 | w, | |
| 1093 | ty.errorUnionPayload(zcu), | |
| 1094 | initializer_type, | |
| 1095 | ), | |
| 1096 | .payload => |payload| try dg.renderValue( | |
| 1097 | w, | |
| 1098 | Value.fromInterned(payload), | |
| 1099 | initializer_type, | |
| 1100 | ), | |
| 1101 | }, | |
| 1102 | else => unreachable, | |
| 1103 | } | |
| 944 | } | |
| 945 | if (ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { | |
| 946 | try w.writeAll(", .payload = "); | |
| 947 | switch (error_union.val) { | |
| 948 | .err_name => try dg.renderUndefValue(w, ty.errorUnionPayload(zcu), initializer_type), | |
| 949 | .payload => |payload| try dg.renderValue(w, .fromInterned(payload), initializer_type), | |
| 1104 | 950 | } |
| 1105 | try w.writeByte('}'); | |
| 1106 | }, | |
| 951 | } | |
| 952 | try w.writeAll(" }"); | |
| 1107 | 953 | }, |
| 1108 | .enum_tag => |enum_tag| try dg.renderValue(w, Value.fromInterned(enum_tag.int), location), | |
| 954 | .enum_tag => |enum_tag| try dg.renderValue(w, .fromInterned(enum_tag.int), location), | |
| 1109 | 955 | .float => { |
| 1110 | 956 | const bits = ty.floatBits(target); |
| 1111 | 957 | const f128_val = val.toFloat(f128, zcu); |
| ... | ... | @@ -1156,7 +1002,7 @@ pub const DeclGen = struct { |
| 1156 | 1002 | else |
| 1157 | 1003 | unreachable; |
| 1158 | 1004 | |
| 1159 | if (location == .StaticInitializer) { | |
| 1005 | if (location == .static_initializer) { | |
| 1160 | 1006 | if (!std.math.isNan(f128_val) and std.math.isSignalNan(f128_val)) |
| 1161 | 1007 | return dg.fail("TODO: C backend: implement nans rendering in static initializers", .{}); |
| 1162 | 1008 | |
| ... | ... | @@ -1167,9 +1013,11 @@ pub const DeclGen = struct { |
| 1167 | 1013 | // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); |
| 1168 | 1014 | } |
| 1169 | 1015 | |
| 1170 | try w.writeAll("zig_"); | |
| 1171 | try w.writeAll(if (location == .StaticInitializer) "init" else "make"); | |
| 1172 | try w.writeAll("_special_"); | |
| 1016 | if (location == .static_initializer) { | |
| 1017 | try w.writeAll("zig_init_special_"); | |
| 1018 | } else { | |
| 1019 | try w.writeAll("zig_make_special_"); | |
| 1020 | } | |
| 1173 | 1021 | try dg.renderTypeForBuiltinFnName(w, ty); |
| 1174 | 1022 | try w.writeByte('('); |
| 1175 | 1023 | if (std.math.signbit(f128_val)) try w.writeByte('-'); |
| ... | ... | @@ -1196,105 +1044,85 @@ pub const DeclGen = struct { |
| 1196 | 1044 | if (!empty) try w.writeByte(')'); |
| 1197 | 1045 | }, |
| 1198 | 1046 | .slice => |slice| { |
| 1199 | const aggregate = ctype.info(ctype_pool).aggregate; | |
| 1200 | 1047 | if (!location.isInitializer()) { |
| 1201 | 1048 | try w.writeByte('('); |
| 1202 | try dg.renderCType(w, ctype); | |
| 1049 | try dg.renderType(w, ty); | |
| 1203 | 1050 | try w.writeByte(')'); |
| 1204 | 1051 | } |
| 1205 | 1052 | try w.writeByte('{'); |
| 1206 | for (0..aggregate.fields.len) |field_index| { | |
| 1207 | if (field_index > 0) try w.writeByte(','); | |
| 1208 | try dg.renderValue(w, Value.fromInterned( | |
| 1209 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { | |
| 1210 | .ptr => slice.ptr, | |
| 1211 | .len => slice.len, | |
| 1212 | else => unreachable, | |
| 1213 | }, | |
| 1214 | ), initializer_type); | |
| 1215 | } | |
| 1053 | try dg.renderValue(w, .fromInterned(slice.ptr), initializer_type); | |
| 1054 | try w.writeByte(','); | |
| 1055 | try dg.renderValue(w, .fromInterned(slice.len), initializer_type); | |
| 1216 | 1056 | try w.writeByte('}'); |
| 1217 | 1057 | }, |
| 1218 | 1058 | .ptr => { |
| 1219 | var arena = std.heap.ArenaAllocator.init(zcu.gpa); | |
| 1220 | defer arena.deinit(); | |
| 1221 | const derivation = try val.pointerDerivation(arena.allocator(), pt); | |
| 1059 | const derivation = try val.pointerDerivation(dg.arena, pt, null); | |
| 1060 | try w.writeByte('('); | |
| 1222 | 1061 | try dg.renderPointer(w, derivation, location); |
| 1062 | try w.writeByte(')'); | |
| 1223 | 1063 | }, |
| 1224 | .opt => |opt| switch (ctype.info(ctype_pool)) { | |
| 1225 | .basic => if (ctype.isBool()) try w.writeAll(switch (opt.val) { | |
| 1226 | .none => "true", | |
| 1227 | else => "false", | |
| 1228 | }) else switch (opt.val) { | |
| 1064 | .opt => |opt| switch (CType.classifyOptional(ty, zcu)) { | |
| 1065 | .npv_payload => unreachable, // opv optional | |
| 1066 | .opv_payload => { | |
| 1067 | if (!location.isInitializer()) { | |
| 1068 | try w.writeByte('('); | |
| 1069 | try dg.renderType(w, ty); | |
| 1070 | try w.writeByte(')'); | |
| 1071 | } | |
| 1072 | try w.writeAll(switch (opt.val) { | |
| 1073 | .none => "{.is_null = true}", | |
| 1074 | else => "{.is_null = false}", | |
| 1075 | }); | |
| 1076 | }, | |
| 1077 | .error_set => switch (opt.val) { | |
| 1229 | 1078 | .none => try w.writeByte('0'), |
| 1230 | else => |payload| switch (ip.indexToKey(payload)) { | |
| 1231 | .undef => |err_ty| try dg.renderUndefValue( | |
| 1232 | w, | |
| 1233 | .fromInterned(err_ty), | |
| 1234 | location, | |
| 1235 | ), | |
| 1236 | .err => |err| try dg.renderErrorName(w, err.name), | |
| 1237 | else => unreachable, | |
| 1238 | }, | |
| 1079 | else => |payload_val| try dg.renderValue(w, .fromInterned(payload_val), location), | |
| 1239 | 1080 | }, |
| 1240 | .pointer => switch (opt.val) { | |
| 1081 | .ptr_like => switch (opt.val) { | |
| 1241 | 1082 | .none => try w.writeAll("NULL"), |
| 1242 | else => |payload| try dg.renderValue(w, Value.fromInterned(payload), location), | |
| 1083 | else => |payload_val| try dg.renderValue(w, .fromInterned(payload_val), location), | |
| 1243 | 1084 | }, |
| 1244 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 1245 | .aggregate => |aggregate| { | |
| 1246 | switch (opt.val) { | |
| 1247 | .none => {}, | |
| 1248 | else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) { | |
| 1249 | .is_null, .payload => {}, | |
| 1250 | .ptr, .len => return dg.renderValue( | |
| 1251 | w, | |
| 1252 | Value.fromInterned(payload), | |
| 1253 | location, | |
| 1254 | ), | |
| 1255 | else => unreachable, | |
| 1256 | }, | |
| 1257 | } | |
| 1085 | .slice_like => switch (opt.val) { | |
| 1086 | .none => { | |
| 1087 | if (!location.isInitializer()) { | |
| 1088 | try w.writeByte('('); | |
| 1089 | try dg.renderType(w, ty); | |
| 1090 | try w.writeByte(')'); | |
| 1091 | } | |
| 1092 | try w.writeAll("{NULL,"); | |
| 1093 | try dg.renderUndefValue(w, .usize, initializer_type); | |
| 1094 | try w.writeByte('}'); | |
| 1095 | }, | |
| 1096 | else => |payload_val| try dg.renderValue(w, .fromInterned(payload_val), location), | |
| 1097 | }, | |
| 1098 | .@"struct" => { | |
| 1258 | 1099 | if (!location.isInitializer()) { |
| 1259 | 1100 | try w.writeByte('('); |
| 1260 | try dg.renderCType(w, ctype); | |
| 1101 | try dg.renderType(w, ty); | |
| 1261 | 1102 | try w.writeByte(')'); |
| 1262 | 1103 | } |
| 1263 | try w.writeByte('{'); | |
| 1264 | for (0..aggregate.fields.len) |field_index| { | |
| 1265 | if (field_index > 0) try w.writeByte(','); | |
| 1266 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { | |
| 1267 | .is_null => try w.writeAll(switch (opt.val) { | |
| 1268 | .none => "true", | |
| 1269 | else => "false", | |
| 1270 | }), | |
| 1271 | .payload => switch (opt.val) { | |
| 1272 | .none => try dg.renderUndefValue( | |
| 1273 | w, | |
| 1274 | ty.optionalChild(zcu), | |
| 1275 | initializer_type, | |
| 1276 | ), | |
| 1277 | else => |payload| try dg.renderValue( | |
| 1278 | w, | |
| 1279 | Value.fromInterned(payload), | |
| 1280 | initializer_type, | |
| 1281 | ), | |
| 1282 | }, | |
| 1283 | .ptr => try w.writeAll("NULL"), | |
| 1284 | .len => try dg.renderUndefValue(w, .usize, initializer_type), | |
| 1285 | else => unreachable, | |
| 1286 | } | |
| 1104 | switch (opt.val) { | |
| 1105 | .none => { | |
| 1106 | try w.writeAll("{ .is_null = true, .payload = "); | |
| 1107 | try dg.renderUndefValue(w, ty.optionalChild(zcu), initializer_type); | |
| 1108 | try w.writeAll(" }"); | |
| 1109 | }, | |
| 1110 | else => |payload_val| { | |
| 1111 | try w.writeAll("{ .is_null = false, .payload = "); | |
| 1112 | try dg.renderValue(w, .fromInterned(payload_val), initializer_type); | |
| 1113 | try w.writeAll(" }"); | |
| 1114 | }, | |
| 1287 | 1115 | } |
| 1288 | try w.writeByte('}'); | |
| 1289 | 1116 | }, |
| 1290 | 1117 | }, |
| 1291 | 1118 | .aggregate => switch (ip.indexToKey(ty.toIntern())) { |
| 1292 | 1119 | .array_type, .vector_type => { |
| 1293 | if (location == .FunctionArgument) { | |
| 1120 | if (!location.isInitializer()) { | |
| 1294 | 1121 | try w.writeByte('('); |
| 1295 | try dg.renderCType(w, ctype); | |
| 1122 | try dg.renderType(w, ty); | |
| 1296 | 1123 | try w.writeByte(')'); |
| 1297 | 1124 | } |
| 1125 | try w.writeByte('{'); | |
| 1298 | 1126 | const ai = ty.arrayInfo(zcu); |
| 1299 | 1127 | if (ai.elem_type.eql(.u8, zcu)) { |
| 1300 | 1128 | var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu))); |
| ... | ... | @@ -1327,11 +1155,12 @@ pub const DeclGen = struct { |
| 1327 | 1155 | } |
| 1328 | 1156 | try w.writeByte('}'); |
| 1329 | 1157 | } |
| 1158 | try w.writeByte('}'); | |
| 1330 | 1159 | }, |
| 1331 | 1160 | .tuple_type => |tuple| { |
| 1332 | 1161 | if (!location.isInitializer()) { |
| 1333 | 1162 | try w.writeByte('('); |
| 1334 | try dg.renderCType(w, ctype); | |
| 1163 | try dg.renderType(w, ty); | |
| 1335 | 1164 | try w.writeByte(')'); |
| 1336 | 1165 | } |
| 1337 | 1166 | |
| ... | ... | @@ -1341,7 +1170,7 @@ pub const DeclGen = struct { |
| 1341 | 1170 | const comptime_val = tuple.values.get(ip)[field_index]; |
| 1342 | 1171 | if (comptime_val != .none) continue; |
| 1343 | 1172 | const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]); |
| 1344 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1173 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 1345 | 1174 | |
| 1346 | 1175 | if (!empty) try w.writeByte(','); |
| 1347 | 1176 | |
| ... | ... | @@ -1363,139 +1192,95 @@ pub const DeclGen = struct { |
| 1363 | 1192 | }, |
| 1364 | 1193 | .struct_type => { |
| 1365 | 1194 | const loaded_struct = ip.loadStructType(ty.toIntern()); |
| 1366 | switch (loaded_struct.layout) { | |
| 1367 | .auto, .@"extern" => { | |
| 1368 | if (!location.isInitializer()) { | |
| 1369 | try w.writeByte('('); | |
| 1370 | try dg.renderCType(w, ctype); | |
| 1371 | try w.writeByte(')'); | |
| 1372 | } | |
| 1195 | assert(loaded_struct.layout != .@"packed"); | |
| 1373 | 1196 | |
| 1374 | try w.writeByte('{'); | |
| 1375 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | |
| 1376 | var need_comma = false; | |
| 1377 | while (field_it.next()) |field_index| { | |
| 1378 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1379 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1197 | if (!location.isInitializer()) { | |
| 1198 | try w.writeByte('('); | |
| 1199 | try dg.renderType(w, ty); | |
| 1200 | try w.writeByte(')'); | |
| 1201 | } | |
| 1380 | 1202 | |
| 1381 | if (need_comma) try w.writeByte(','); | |
| 1382 | need_comma = true; | |
| 1383 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 1384 | .bytes => |bytes| try pt.intern(.{ .int = .{ | |
| 1385 | .ty = field_ty.toIntern(), | |
| 1386 | .storage = .{ .u64 = bytes.at(field_index, ip) }, | |
| 1387 | } }), | |
| 1388 | .elems => |elems| elems[field_index], | |
| 1389 | .repeated_elem => |elem| elem, | |
| 1390 | }; | |
| 1391 | try dg.renderValue(w, Value.fromInterned(field_val), initializer_type); | |
| 1392 | } | |
| 1393 | try w.writeByte('}'); | |
| 1394 | }, | |
| 1395 | .@"packed" => { | |
| 1396 | // https://github.com/ziglang/zig/issues/24657 will eliminate most of the | |
| 1397 | // following logic, leaving only the recursive `renderValue` call. Once | |
| 1398 | // that proposal is implemented, a `packed struct` will literally be | |
| 1399 | // represented in the InternPool by its comptime-known backing integer. | |
| 1400 | var arena: std.heap.ArenaAllocator = .init(zcu.gpa); | |
| 1401 | defer arena.deinit(); | |
| 1402 | const backing_ty: Type = .fromInterned(loaded_struct.backingIntTypeUnordered(ip)); | |
| 1403 | const buf = try arena.allocator().alloc(u8, @intCast(ty.abiSize(zcu))); | |
| 1404 | val.writeToMemory(pt, buf) catch |err| switch (err) { | |
| 1405 | error.IllDefinedMemoryLayout => unreachable, | |
| 1406 | error.OutOfMemory => |e| return e, | |
| 1407 | error.ReinterpretDeclRef, error.Unimplemented => return dg.fail("TODO: C backend: lower packed struct value", .{}), | |
| 1408 | }; | |
| 1409 | const backing_val: Value = try .readUintFromMemory(backing_ty, pt, buf, arena.allocator()); | |
| 1410 | return dg.renderValue(w, backing_val, location); | |
| 1411 | }, | |
| 1203 | try w.writeByte('{'); | |
| 1204 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | |
| 1205 | var need_comma = false; | |
| 1206 | while (field_it.next()) |field_index| { | |
| 1207 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1208 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 1209 | ||
| 1210 | if (need_comma) try w.writeByte(','); | |
| 1211 | need_comma = true; | |
| 1212 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | |
| 1213 | .bytes => |bytes| try pt.intern(.{ .int = .{ | |
| 1214 | .ty = field_ty.toIntern(), | |
| 1215 | .storage = .{ .u64 = bytes.at(field_index, ip) }, | |
| 1216 | } }), | |
| 1217 | .elems => |elems| elems[field_index], | |
| 1218 | .repeated_elem => |elem| elem, | |
| 1219 | }; | |
| 1220 | try dg.renderValue(w, Value.fromInterned(field_val), initializer_type); | |
| 1412 | 1221 | } |
| 1222 | try w.writeByte('}'); | |
| 1413 | 1223 | }, |
| 1414 | 1224 | else => unreachable, |
| 1415 | 1225 | }, |
| 1226 | .bitpack => |bitpack| return dg.renderValue(w, .fromInterned(bitpack.backing_int_val), location), | |
| 1416 | 1227 | .un => |un| { |
| 1417 | 1228 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 1418 | if (loaded_union.flagsUnordered(ip).layout == .@"packed") { | |
| 1419 | // https://github.com/ziglang/zig/issues/24657 will eliminate most of the | |
| 1420 | // following logic, leaving only the recursive `renderValue` call. Once | |
| 1421 | // that proposal is implemented, a `packed union` will literally be | |
| 1422 | // represented in the InternPool by its comptime-known backing integer. | |
| 1423 | var arena: std.heap.ArenaAllocator = .init(zcu.gpa); | |
| 1424 | defer arena.deinit(); | |
| 1425 | const backing_ty = try ty.unionBackingType(pt); | |
| 1426 | const buf = try arena.allocator().alloc(u8, @intCast(ty.abiSize(zcu))); | |
| 1427 | val.writeToMemory(pt, buf) catch |err| switch (err) { | |
| 1428 | error.IllDefinedMemoryLayout => unreachable, | |
| 1429 | error.OutOfMemory => |e| return e, | |
| 1430 | error.ReinterpretDeclRef, error.Unimplemented => return dg.fail("TODO: C backend: lower packed union value", .{}), | |
| 1431 | }; | |
| 1432 | const backing_val: Value = try .readUintFromMemory(backing_ty, pt, buf, arena.allocator()); | |
| 1433 | return dg.renderValue(w, backing_val, location); | |
| 1434 | } | |
| 1435 | 1229 | if (un.tag == .none) { |
| 1436 | const backing_ty = try ty.unionBackingType(pt); | |
| 1437 | assert(loaded_union.flagsUnordered(ip).layout == .@"extern"); | |
| 1438 | if (location == .StaticInitializer) { | |
| 1230 | assert(loaded_union.layout == .@"extern"); | |
| 1231 | if (location == .static_initializer) { | |
| 1439 | 1232 | return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); |
| 1440 | 1233 | } |
| 1441 | 1234 | |
| 1442 | 1235 | const ptr_ty = try pt.singleConstPtrType(ty); |
| 1443 | try w.writeAll("*(("); | |
| 1236 | try w.writeAll("*("); | |
| 1444 | 1237 | try dg.renderType(w, ptr_ty); |
| 1445 | try w.writeAll(")("); | |
| 1446 | try dg.renderType(w, backing_ty); | |
| 1447 | try w.writeAll("){"); | |
| 1448 | try dg.renderValue(w, Value.fromInterned(un.val), location); | |
| 1449 | try w.writeAll("})"); | |
| 1238 | try w.writeAll(")&"); | |
| 1239 | // We need an lvalue for '&'. | |
| 1240 | try dg.renderValueAsLvalue(w, .fromInterned(un.val)); | |
| 1450 | 1241 | } else { |
| 1451 | 1242 | if (!location.isInitializer()) { |
| 1452 | 1243 | try w.writeByte('('); |
| 1453 | try dg.renderCType(w, ctype); | |
| 1244 | try dg.renderType(w, ty); | |
| 1454 | 1245 | try w.writeByte(')'); |
| 1455 | 1246 | } |
| 1247 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) { | |
| 1248 | assert(loaded_union.has_runtime_tag); // otherwise it does not have runtime bits | |
| 1249 | try w.writeAll("{ .tag = "); | |
| 1250 | try dg.renderValue(w, .fromInterned(un.tag), initializer_type); | |
| 1251 | try w.writeAll(" }"); | |
| 1252 | return; | |
| 1253 | } | |
| 1456 | 1254 | |
| 1457 | const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; | |
| 1458 | const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 1459 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; | |
| 1460 | ||
| 1461 | const has_tag = loaded_union.hasTag(ip); | |
| 1462 | if (has_tag) try w.writeByte('{'); | |
| 1463 | const aggregate = ctype.info(ctype_pool).aggregate; | |
| 1464 | for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { | |
| 1465 | if (outer_field_index > 0) try w.writeByte(','); | |
| 1466 | switch (if (has_tag) | |
| 1467 | aggregate.fields.at(outer_field_index, ctype_pool).name.index | |
| 1468 | else | |
| 1469 | .payload) { | |
| 1470 | .tag => try dg.renderValue( | |
| 1471 | w, | |
| 1472 | Value.fromInterned(un.tag), | |
| 1473 | initializer_type, | |
| 1474 | ), | |
| 1475 | .payload => { | |
| 1476 | try w.writeByte('{'); | |
| 1477 | if (field_ty.hasRuntimeBits(zcu)) { | |
| 1478 | try w.print(" .{f} = ", .{fmtIdentSolo(field_name.toSlice(ip))}); | |
| 1479 | try dg.renderValue( | |
| 1480 | w, | |
| 1481 | Value.fromInterned(un.val), | |
| 1482 | initializer_type, | |
| 1483 | ); | |
| 1484 | try w.writeByte(' '); | |
| 1485 | } else for (0..loaded_union.field_types.len) |inner_field_index| { | |
| 1486 | const inner_field_ty: Type = .fromInterned( | |
| 1487 | loaded_union.field_types.get(ip)[inner_field_index], | |
| 1488 | ); | |
| 1489 | if (!inner_field_ty.hasRuntimeBits(zcu)) continue; | |
| 1490 | try dg.renderUndefValue(w, inner_field_ty, initializer_type); | |
| 1491 | break; | |
| 1492 | } | |
| 1493 | try w.writeByte('}'); | |
| 1494 | }, | |
| 1495 | else => unreachable, | |
| 1496 | } | |
| 1255 | if (loaded_union.layout == .auto) try w.writeByte('{'); | |
| 1256 | ||
| 1257 | if (loaded_union.has_runtime_tag) { | |
| 1258 | try w.writeAll(" .tag = "); | |
| 1259 | try dg.renderValue(w, .fromInterned(un.tag), initializer_type); | |
| 1260 | try w.writeAll(", .payload = "); | |
| 1261 | } | |
| 1262 | ||
| 1263 | const enum_tag_ty: Type = .fromInterned(loaded_union.enum_tag_type); | |
| 1264 | const active_field_index = enum_tag_ty.enumTagFieldIndex(.fromInterned(un.tag), zcu).?; | |
| 1265 | const active_field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[active_field_index]); | |
| 1266 | if (active_field_ty.hasRuntimeBits(zcu)) { | |
| 1267 | const active_field_name = enum_tag_ty.enumFieldName(active_field_index, zcu); | |
| 1268 | try w.print("{{ .{f} = ", .{fmtIdentSolo(active_field_name.toSlice(ip))}); | |
| 1269 | try dg.renderValue(w, .fromInterned(un.val), initializer_type); | |
| 1270 | try w.writeAll(" }"); | |
| 1271 | } else { | |
| 1272 | const first_field_ty: Type = for (loaded_union.field_types.get(ip)) |field_ty_ip| { | |
| 1273 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 1274 | if (!field_ty.hasRuntimeBits(pt.zcu)) continue; | |
| 1275 | break field_ty; | |
| 1276 | } else unreachable; | |
| 1277 | try w.writeByte('{'); | |
| 1278 | try dg.renderUndefValue(w, first_field_ty, initializer_type); | |
| 1279 | try w.writeByte('}'); | |
| 1497 | 1280 | } |
| 1498 | if (has_tag) try w.writeByte('}'); | |
| 1281 | ||
| 1282 | if (loaded_union.has_runtime_tag) try w.writeByte(' '); | |
| 1283 | if (loaded_union.layout == .auto) try w.writeByte('}'); | |
| 1499 | 1284 | } |
| 1500 | 1285 | }, |
| 1501 | 1286 | } |
| ... | ... | @@ -1511,11 +1296,10 @@ pub const DeclGen = struct { |
| 1511 | 1296 | const zcu = pt.zcu; |
| 1512 | 1297 | const ip = &zcu.intern_pool; |
| 1513 | 1298 | const target = &dg.mod.resolved_target.result; |
| 1514 | const ctype_pool = &dg.ctype_pool; | |
| 1515 | 1299 | |
| 1516 | 1300 | const initializer_type: ValueRenderLocation = switch (location) { |
| 1517 | .StaticInitializer => .StaticInitializer, | |
| 1518 | else => .Initializer, | |
| 1301 | .static_initializer => .static_initializer, | |
| 1302 | else => .initializer, | |
| 1519 | 1303 | }; |
| 1520 | 1304 | |
| 1521 | 1305 | const safety_on = switch (zcu.optimizeMode()) { |
| ... | ... | @@ -1523,7 +1307,6 @@ pub const DeclGen = struct { |
| 1523 | 1307 | .ReleaseFast, .ReleaseSmall => false, |
| 1524 | 1308 | }; |
| 1525 | 1309 | |
| 1526 | const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); | |
| 1527 | 1310 | switch (ty.toIntern()) { |
| 1528 | 1311 | .c_longdouble_type, |
| 1529 | 1312 | .f16_type, |
| ... | ... | @@ -1548,76 +1331,109 @@ pub const DeclGen = struct { |
| 1548 | 1331 | else => unreachable, |
| 1549 | 1332 | } |
| 1550 | 1333 | try w.writeAll(", "); |
| 1551 | try dg.renderUndefValue(w, repr_ty, .FunctionArgument); | |
| 1334 | try dg.renderUndefValue(w, repr_ty, .other); | |
| 1552 | 1335 | return w.writeByte(')'); |
| 1553 | 1336 | }, |
| 1554 | 1337 | .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"), |
| 1555 | 1338 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 1556 | .simple_type, | |
| 1339 | .simple_type, // anyerror, c_char (etc), usize, isize | |
| 1557 | 1340 | .int_type, |
| 1558 | 1341 | .enum_type, |
| 1559 | 1342 | .error_set_type, |
| 1560 | 1343 | .inferred_error_set_type, |
| 1561 | => return w.print("{f}", .{ | |
| 1562 | try dg.fmtIntLiteralHex(try pt.undefValue(ty), location), | |
| 1563 | }), | |
| 1344 | => switch (CType.classifyInt(ty, zcu)) { | |
| 1345 | .void => unreachable, // opv | |
| 1346 | .small => |s| { | |
| 1347 | const int = ty.intInfo(zcu); | |
| 1348 | var buf: [std.math.big.int.calcTwosCompLimbCount(128)]std.math.big.Limb = undefined; | |
| 1349 | var bigint: std.math.big.int.Mutable = .init(&buf, undefPattern(u128)); | |
| 1350 | bigint.truncate(bigint.toConst(), int.signedness, int.bits); | |
| 1351 | const fmt_undef: FormatInt128 = .{ | |
| 1352 | .target = zcu.getTarget(), | |
| 1353 | .int_cty = s, | |
| 1354 | .val = bigint.toConst(), | |
| 1355 | .is_global = location == .static_initializer, | |
| 1356 | .base = 16, | |
| 1357 | .case = .lower, | |
| 1358 | }; | |
| 1359 | try w.print("{f}", .{fmt_undef}); | |
| 1360 | }, | |
| 1361 | .big => |big| { | |
| 1362 | var buf: [std.math.big.int.calcTwosCompLimbCount(128)]std.math.big.Limb = undefined; | |
| 1363 | var limb_bigint: std.math.big.int.Mutable = .init(&buf, undefPattern(u128)); | |
| 1364 | limb_bigint.truncate(limb_bigint.toConst(), .unsigned, big.limb_size.bits()); | |
| 1365 | const fmt_undef_limb: FormatInt128 = .{ | |
| 1366 | .target = zcu.getTarget(), | |
| 1367 | .int_cty = big.limb_size.unsigned(), | |
| 1368 | .val = limb_bigint.toConst(), | |
| 1369 | .is_global = location == .static_initializer, | |
| 1370 | .base = 16, | |
| 1371 | .case = .lower, | |
| 1372 | }; | |
| 1373 | ||
| 1374 | if (!location.isInitializer()) { | |
| 1375 | try w.writeByte('('); | |
| 1376 | try dg.renderType(w, ty); | |
| 1377 | try w.writeByte(')'); | |
| 1378 | } | |
| 1379 | try w.writeAll("{{"); | |
| 1380 | try w.print("{f}", .{fmt_undef_limb}); | |
| 1381 | for (1..big.limbs_len) |_| { | |
| 1382 | try w.print(",{f}", .{fmt_undef_limb}); | |
| 1383 | } | |
| 1384 | try w.writeAll("}}"); | |
| 1385 | }, | |
| 1386 | }, | |
| 1564 | 1387 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 1565 | 1388 | .one, .many, .c => { |
| 1566 | 1389 | try w.writeAll("(("); |
| 1567 | try dg.renderCType(w, ctype); | |
| 1568 | return w.print("){f})", .{ | |
| 1569 | try dg.fmtIntLiteralHex(.undef_usize, .Other), | |
| 1570 | }); | |
| 1390 | try dg.renderType(w, ty); | |
| 1391 | try w.writeByte(')'); | |
| 1392 | try dg.renderUndefValue(w, .usize, location); | |
| 1393 | try w.writeByte(')'); | |
| 1571 | 1394 | }, |
| 1572 | 1395 | .slice => { |
| 1573 | 1396 | if (!location.isInitializer()) { |
| 1574 | 1397 | try w.writeByte('('); |
| 1575 | try dg.renderCType(w, ctype); | |
| 1398 | try dg.renderType(w, ty); | |
| 1576 | 1399 | try w.writeByte(')'); |
| 1577 | 1400 | } |
| 1578 | 1401 | |
| 1579 | try w.writeAll("{("); | |
| 1580 | const ptr_ty = ty.slicePtrFieldType(zcu); | |
| 1581 | try dg.renderType(w, ptr_ty); | |
| 1582 | return w.print("){f}, {0f}}}", .{ | |
| 1583 | try dg.fmtIntLiteralHex(.undef_usize, .Other), | |
| 1584 | }); | |
| 1402 | try w.writeByte('{'); | |
| 1403 | try dg.renderUndefValue(w, ty.slicePtrFieldType(zcu), initializer_type); | |
| 1404 | try w.writeByte(','); | |
| 1405 | try dg.renderUndefValue(w, .usize, initializer_type); | |
| 1406 | try w.writeByte('}'); | |
| 1585 | 1407 | }, |
| 1586 | 1408 | }, |
| 1587 | .opt_type => |child_type| switch (ctype.info(ctype_pool)) { | |
| 1588 | .basic, .pointer => try dg.renderUndefValue( | |
| 1589 | w, | |
| 1590 | .fromInterned(if (ctype.isBool()) .bool_type else child_type), | |
| 1591 | location, | |
| 1592 | ), | |
| 1593 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 1594 | .aggregate => |aggregate| { | |
| 1595 | switch (aggregate.fields.at(0, ctype_pool).name.index) { | |
| 1596 | .is_null, .payload => {}, | |
| 1597 | .ptr, .len => return dg.renderUndefValue( | |
| 1598 | w, | |
| 1599 | .fromInterned(child_type), | |
| 1600 | location, | |
| 1601 | ), | |
| 1602 | else => unreachable, | |
| 1603 | } | |
| 1409 | .opt_type => |child_type| switch (CType.classifyOptional(ty, zcu)) { | |
| 1410 | .npv_payload => unreachable, // opv optional | |
| 1411 | ||
| 1412 | .error_set, | |
| 1413 | .ptr_like, | |
| 1414 | .slice_like, | |
| 1415 | => try dg.renderUndefValue(w, .fromInterned(child_type), location), | |
| 1416 | ||
| 1417 | .opv_payload => { | |
| 1604 | 1418 | if (!location.isInitializer()) { |
| 1605 | 1419 | try w.writeByte('('); |
| 1606 | try dg.renderCType(w, ctype); | |
| 1420 | try dg.renderType(w, ty); | |
| 1607 | 1421 | try w.writeByte(')'); |
| 1608 | 1422 | } |
| 1609 | try w.writeByte('{'); | |
| 1610 | for (0..aggregate.fields.len) |field_index| { | |
| 1611 | if (field_index > 0) try w.writeByte(','); | |
| 1612 | try dg.renderUndefValue(w, .fromInterned( | |
| 1613 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { | |
| 1614 | .is_null => .bool_type, | |
| 1615 | .payload => child_type, | |
| 1616 | else => unreachable, | |
| 1617 | }, | |
| 1618 | ), initializer_type); | |
| 1423 | try w.writeAll(if (safety_on) "{.is_null=0xaa}" else "{.is_null=false}"); | |
| 1424 | }, | |
| 1425 | ||
| 1426 | .@"struct" => { | |
| 1427 | if (!location.isInitializer()) { | |
| 1428 | try w.writeByte('('); | |
| 1429 | try dg.renderType(w, ty); | |
| 1430 | try w.writeByte(')'); | |
| 1619 | 1431 | } |
| 1620 | try w.writeByte('}'); | |
| 1432 | try w.writeAll("{ .is_null = "); | |
| 1433 | try dg.renderUndefValue(w, .bool, initializer_type); | |
| 1434 | try w.writeAll(", .payload = "); | |
| 1435 | try dg.renderUndefValue(w, .fromInterned(child_type), initializer_type); | |
| 1436 | try w.writeAll(" }"); | |
| 1621 | 1437 | }, |
| 1622 | 1438 | }, |
| 1623 | 1439 | .struct_type => { |
| ... | ... | @@ -1626,16 +1442,15 @@ pub const DeclGen = struct { |
| 1626 | 1442 | .auto, .@"extern" => { |
| 1627 | 1443 | if (!location.isInitializer()) { |
| 1628 | 1444 | try w.writeByte('('); |
| 1629 | try dg.renderCType(w, ctype); | |
| 1445 | try dg.renderType(w, ty); | |
| 1630 | 1446 | try w.writeByte(')'); |
| 1631 | 1447 | } |
| 1632 | ||
| 1633 | 1448 | try w.writeByte('{'); |
| 1634 | 1449 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 1635 | 1450 | var need_comma = false; |
| 1636 | 1451 | while (field_it.next()) |field_index| { |
| 1637 | 1452 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1638 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1453 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 1639 | 1454 | |
| 1640 | 1455 | if (need_comma) try w.writeByte(','); |
| 1641 | 1456 | need_comma = true; |
| ... | ... | @@ -1643,17 +1458,13 @@ pub const DeclGen = struct { |
| 1643 | 1458 | } |
| 1644 | 1459 | return w.writeByte('}'); |
| 1645 | 1460 | }, |
| 1646 | .@"packed" => return dg.renderUndefValue( | |
| 1647 | w, | |
| 1648 | .fromInterned(loaded_struct.backingIntTypeUnordered(ip)), | |
| 1649 | location, | |
| 1650 | ), | |
| 1461 | .@"packed" => return dg.renderUndefValue(w, ty.bitpackBackingInt(zcu), location), | |
| 1651 | 1462 | } |
| 1652 | 1463 | }, |
| 1653 | 1464 | .tuple_type => |tuple_info| { |
| 1654 | 1465 | if (!location.isInitializer()) { |
| 1655 | 1466 | try w.writeByte('('); |
| 1656 | try dg.renderCType(w, ctype); | |
| 1467 | try dg.renderType(w, ty); | |
| 1657 | 1468 | try w.writeByte(')'); |
| 1658 | 1469 | } |
| 1659 | 1470 | |
| ... | ... | @@ -1662,7 +1473,7 @@ pub const DeclGen = struct { |
| 1662 | 1473 | for (0..tuple_info.types.len) |field_index| { |
| 1663 | 1474 | if (tuple_info.values.get(ip)[field_index] != .none) continue; |
| 1664 | 1475 | const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); |
| 1665 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1476 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 1666 | 1477 | |
| 1667 | 1478 | if (need_comma) try w.writeByte(','); |
| 1668 | 1479 | need_comma = true; |
| ... | ... | @@ -1672,88 +1483,65 @@ pub const DeclGen = struct { |
| 1672 | 1483 | }, |
| 1673 | 1484 | .union_type => { |
| 1674 | 1485 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 1675 | switch (loaded_union.flagsUnordered(ip).layout) { | |
| 1486 | switch (loaded_union.layout) { | |
| 1676 | 1487 | .auto, .@"extern" => { |
| 1677 | 1488 | if (!location.isInitializer()) { |
| 1678 | 1489 | try w.writeByte('('); |
| 1679 | try dg.renderCType(w, ctype); | |
| 1490 | try dg.renderType(w, ty); | |
| 1680 | 1491 | try w.writeByte(')'); |
| 1681 | 1492 | } |
| 1682 | 1493 | |
| 1683 | const has_tag = loaded_union.hasTag(ip); | |
| 1684 | if (has_tag) try w.writeByte('{'); | |
| 1685 | const aggregate = ctype.info(ctype_pool).aggregate; | |
| 1686 | for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { | |
| 1687 | if (outer_field_index > 0) try w.writeByte(','); | |
| 1688 | switch (if (has_tag) | |
| 1689 | aggregate.fields.at(outer_field_index, ctype_pool).name.index | |
| 1690 | else | |
| 1691 | .payload) { | |
| 1692 | .tag => try dg.renderUndefValue( | |
| 1693 | w, | |
| 1694 | .fromInterned(loaded_union.enum_tag_ty), | |
| 1695 | initializer_type, | |
| 1696 | ), | |
| 1697 | .payload => { | |
| 1698 | try w.writeByte('{'); | |
| 1699 | for (0..loaded_union.field_types.len) |inner_field_index| { | |
| 1700 | const inner_field_ty: Type = .fromInterned( | |
| 1701 | loaded_union.field_types.get(ip)[inner_field_index], | |
| 1702 | ); | |
| 1703 | if (!inner_field_ty.hasRuntimeBits(pt.zcu)) continue; | |
| 1704 | try dg.renderUndefValue( | |
| 1705 | w, | |
| 1706 | inner_field_ty, | |
| 1707 | initializer_type, | |
| 1708 | ); | |
| 1709 | break; | |
| 1710 | } | |
| 1711 | try w.writeByte('}'); | |
| 1712 | }, | |
| 1713 | else => unreachable, | |
| 1714 | } | |
| 1494 | const first_field_ty: Type = for (loaded_union.field_types.get(ip)) |field_ty_ip| { | |
| 1495 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 1496 | if (!field_ty.hasRuntimeBits(pt.zcu)) continue; | |
| 1497 | break field_ty; | |
| 1498 | } else { | |
| 1499 | assert(loaded_union.has_runtime_tag); // otherwise it does not have runtime bits | |
| 1500 | try w.writeAll("{ .tag = "); | |
| 1501 | try dg.renderUndefValue(w, .fromInterned(loaded_union.enum_tag_type), initializer_type); | |
| 1502 | try w.writeAll(" }"); | |
| 1503 | return; | |
| 1504 | }; | |
| 1505 | ||
| 1506 | if (loaded_union.layout == .auto) try w.writeByte('{'); | |
| 1507 | ||
| 1508 | if (loaded_union.has_runtime_tag) { | |
| 1509 | try w.writeAll(" .tag = "); | |
| 1510 | try dg.renderUndefValue(w, .fromInterned(loaded_union.enum_tag_type), initializer_type); | |
| 1511 | try w.writeAll(", .payload = "); | |
| 1715 | 1512 | } |
| 1716 | if (has_tag) try w.writeByte('}'); | |
| 1513 | ||
| 1514 | try w.writeByte('{'); | |
| 1515 | try dg.renderUndefValue(w, first_field_ty, initializer_type); | |
| 1516 | try w.writeByte('}'); | |
| 1517 | ||
| 1518 | if (loaded_union.has_runtime_tag) try w.writeByte(' '); | |
| 1519 | if (loaded_union.layout == .auto) try w.writeByte('}'); | |
| 1717 | 1520 | }, |
| 1718 | .@"packed" => return dg.renderUndefValue( | |
| 1719 | w, | |
| 1720 | try ty.unionBackingType(pt), | |
| 1721 | location, | |
| 1722 | ), | |
| 1521 | .@"packed" => return dg.renderUndefValue(w, ty.bitpackBackingInt(zcu), location), | |
| 1723 | 1522 | } |
| 1724 | 1523 | }, |
| 1725 | .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) { | |
| 1726 | .basic => try dg.renderUndefValue( | |
| 1727 | w, | |
| 1728 | .fromInterned(error_union_type.error_set_type), | |
| 1729 | location, | |
| 1730 | ), | |
| 1731 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 1732 | .aggregate => |aggregate| { | |
| 1733 | if (!location.isInitializer()) { | |
| 1734 | try w.writeByte('('); | |
| 1735 | try dg.renderCType(w, ctype); | |
| 1736 | try w.writeByte(')'); | |
| 1737 | } | |
| 1738 | try w.writeByte('{'); | |
| 1739 | for (0..aggregate.fields.len) |field_index| { | |
| 1740 | if (field_index > 0) try w.writeByte(','); | |
| 1741 | try dg.renderUndefValue( | |
| 1742 | w, | |
| 1743 | .fromInterned( | |
| 1744 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { | |
| 1745 | .@"error" => error_union_type.error_set_type, | |
| 1746 | .payload => error_union_type.payload_type, | |
| 1747 | else => unreachable, | |
| 1748 | }, | |
| 1749 | ), | |
| 1750 | initializer_type, | |
| 1751 | ); | |
| 1752 | } | |
| 1753 | try w.writeByte('}'); | |
| 1754 | }, | |
| 1524 | .error_union_type => |error_union| { | |
| 1525 | if (!location.isInitializer()) { | |
| 1526 | try w.writeByte('('); | |
| 1527 | try dg.renderType(w, ty); | |
| 1528 | try w.writeByte(')'); | |
| 1529 | } | |
| 1530 | try w.writeAll("{ .error = "); | |
| 1531 | try dg.renderUndefValue(w, .fromInterned(error_union.error_set_type), initializer_type); | |
| 1532 | if (Type.fromInterned(error_union.payload_type).hasRuntimeBits(zcu)) { | |
| 1533 | try w.writeAll(", .payload = "); | |
| 1534 | try dg.renderUndefValue(w, .fromInterned(error_union.payload_type), initializer_type); | |
| 1535 | } | |
| 1536 | try w.writeAll(" }"); | |
| 1755 | 1537 | }, |
| 1756 | 1538 | .array_type, .vector_type => { |
| 1539 | if (!location.isInitializer()) { | |
| 1540 | try w.writeByte('('); | |
| 1541 | try dg.renderType(w, ty); | |
| 1542 | try w.writeByte(')'); | |
| 1543 | } | |
| 1544 | try w.writeByte('{'); | |
| 1757 | 1545 | const ai = ty.arrayInfo(zcu); |
| 1758 | 1546 | if (ai.elem_type.eql(.u8, zcu)) { |
| 1759 | 1547 | var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu))); |
| ... | ... | @@ -1764,14 +1552,8 @@ pub const DeclGen = struct { |
| 1764 | 1552 | const s_u8: u8 = @intCast(s.toUnsignedInt(zcu)); |
| 1765 | 1553 | if (s_u8 != 0) try literal.writeChar(s_u8); |
| 1766 | 1554 | } |
| 1767 | return literal.end(); | |
| 1555 | try literal.end(); | |
| 1768 | 1556 | } else { |
| 1769 | if (!location.isInitializer()) { | |
| 1770 | try w.writeByte('('); | |
| 1771 | try dg.renderCType(w, ctype); | |
| 1772 | try w.writeByte(')'); | |
| 1773 | } | |
| 1774 | ||
| 1775 | 1557 | try w.writeByte('{'); |
| 1776 | 1558 | var index: u64 = 0; |
| 1777 | 1559 | while (index < ai.len) : (index += 1) { |
| ... | ... | @@ -1782,8 +1564,9 @@ pub const DeclGen = struct { |
| 1782 | 1564 | if (index > 0) try w.writeAll(", "); |
| 1783 | 1565 | try dg.renderValue(w, s, location); |
| 1784 | 1566 | } |
| 1785 | return w.writeByte('}'); | |
| 1567 | try w.writeByte('}'); | |
| 1786 | 1568 | } |
| 1569 | try w.writeByte('}'); | |
| 1787 | 1570 | }, |
| 1788 | 1571 | .anyframe_type, |
| 1789 | 1572 | .opaque_type, |
| ... | ... | @@ -1800,13 +1583,13 @@ pub const DeclGen = struct { |
| 1800 | 1583 | .error_union, |
| 1801 | 1584 | .enum_literal, |
| 1802 | 1585 | .enum_tag, |
| 1803 | .empty_enum_value, | |
| 1804 | 1586 | .float, |
| 1805 | 1587 | .ptr, |
| 1806 | 1588 | .slice, |
| 1807 | 1589 | .opt, |
| 1808 | 1590 | .aggregate, |
| 1809 | 1591 | .un, |
| 1592 | .bitpack, | |
| 1810 | 1593 | .memoized_call, |
| 1811 | 1594 | => unreachable, // values, not types |
| 1812 | 1595 | }, |
| ... | ... | @@ -1818,10 +1601,11 @@ pub const DeclGen = struct { |
| 1818 | 1601 | w: *Writer, |
| 1819 | 1602 | fn_val: Value, |
| 1820 | 1603 | fn_align: InternPool.Alignment, |
| 1821 | kind: CType.Kind, | |
| 1604 | kind: enum { forward_decl, definition }, | |
| 1822 | 1605 | name: union(enum) { |
| 1823 | 1606 | nav: InternPool.Nav.Index, |
| 1824 | fmt_ctype_pool_string: std.fmt.Alt(CTypePoolStringFormatData, formatCTypePoolString), | |
| 1607 | nav_never_tail: InternPool.Nav.Index, | |
| 1608 | nav_never_inline: InternPool.Nav.Index, | |
| 1825 | 1609 | @"export": struct { |
| 1826 | 1610 | main_name: InternPool.NullTerminatedString, |
| 1827 | 1611 | extern_name: InternPool.NullTerminatedString, |
| ... | ... | @@ -1832,14 +1616,12 @@ pub const DeclGen = struct { |
| 1832 | 1616 | const ip = &zcu.intern_pool; |
| 1833 | 1617 | |
| 1834 | 1618 | const fn_ty = fn_val.typeOf(zcu); |
| 1835 | const fn_ctype = try dg.ctypeFromType(fn_ty, kind); | |
| 1836 | 1619 | |
| 1837 | 1620 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 1838 | 1621 | if (fn_info.cc == .naked) { |
| 1839 | 1622 | switch (kind) { |
| 1840 | .forward => try w.writeAll("zig_naked_decl "), | |
| 1841 | .complete => try w.writeAll("zig_naked "), | |
| 1842 | else => unreachable, | |
| 1623 | .forward_decl => try w.writeAll("zig_naked_decl "), | |
| 1624 | .definition => try w.writeAll("zig_naked "), | |
| 1843 | 1625 | } |
| 1844 | 1626 | } |
| 1845 | 1627 | |
| ... | ... | @@ -1849,45 +1631,63 @@ pub const DeclGen = struct { |
| 1849 | 1631 | if (func_analysis.branch_hint == .cold) |
| 1850 | 1632 | try w.writeAll("zig_cold "); |
| 1851 | 1633 | |
| 1852 | if (kind == .complete and func_analysis.disable_intrinsics or dg.mod.no_builtin) | |
| 1634 | if (kind == .definition and func_analysis.disable_intrinsics or dg.mod.no_builtin) | |
| 1853 | 1635 | try w.writeAll("zig_no_builtin "); |
| 1854 | 1636 | } |
| 1855 | 1637 | |
| 1856 | 1638 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); |
| 1857 | 1639 | |
| 1858 | var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{}); | |
| 1640 | // While incomplete types are usually an acceptable substitute for "void", this is not true | |
| 1641 | // in function return types, where "void" is the only incomplete type permitted. | |
| 1642 | const actual_return_type: Type = .fromInterned(fn_info.return_type); | |
| 1643 | const effective_return_type: Type = switch (actual_return_type.classify(zcu)) { | |
| 1644 | .no_possible_value => .noreturn, | |
| 1645 | .one_possible_value, .fully_comptime => .void, // no runtime bits | |
| 1646 | .partially_comptime, .runtime => actual_return_type, // yes runtime bits | |
| 1647 | }; | |
| 1859 | 1648 | |
| 1649 | const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu); | |
| 1650 | try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); | |
| 1860 | 1651 | if (toCallingConvention(fn_info.cc, zcu)) |call_conv| { |
| 1861 | try w.print("{f}zig_callconv({s})", .{ trailing, call_conv }); | |
| 1862 | trailing = .maybe_space; | |
| 1652 | try w.print("zig_callconv({s}) ", .{call_conv}); | |
| 1863 | 1653 | } |
| 1864 | ||
| 1865 | try w.print("{f}", .{trailing}); | |
| 1866 | 1654 | switch (name) { |
| 1867 | .nav => |nav| try dg.renderNavName(w, nav), | |
| 1868 | .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}), | |
| 1655 | .nav => |nav| try renderNavName(w, nav, ip), | |
| 1656 | .nav_never_tail => |nav| try w.print("zig_never_tail_{f}__{d}", .{ | |
| 1657 | fmtIdentUnsolo(ip.getNav(nav).name.toSlice(ip)), @intFromEnum(nav), | |
| 1658 | }), | |
| 1659 | .nav_never_inline => |nav| try w.print("zig_never_inline_{f}__{d}", .{ | |
| 1660 | fmtIdentUnsolo(ip.getNav(nav).name.toSlice(ip)), @intFromEnum(nav), | |
| 1661 | }), | |
| 1869 | 1662 | .@"export" => |@"export"| try w.print("{f}", .{fmtIdentSolo(@"export".extern_name.toSlice(ip))}), |
| 1870 | 1663 | } |
| 1871 | ||
| 1872 | try renderTypeSuffix( | |
| 1873 | dg.pass, | |
| 1874 | &dg.ctype_pool, | |
| 1875 | zcu, | |
| 1876 | w, | |
| 1877 | fn_ctype, | |
| 1878 | .suffix, | |
| 1879 | CQualifiers.init(.{ .@"const" = switch (kind) { | |
| 1880 | .forward => false, | |
| 1881 | .complete => true, | |
| 1882 | else => unreachable, | |
| 1883 | } }), | |
| 1884 | ); | |
| 1664 | { | |
| 1665 | try w.writeByte('('); | |
| 1666 | var c_param_index: u32 = 0; | |
| 1667 | for (fn_info.param_types.get(ip)) |param_ty_ip| { | |
| 1668 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 1669 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 1670 | if (c_param_index != 0) try w.writeAll(", "); | |
| 1671 | try dg.renderTypeAndName(w, param_ty, .{ .arg = c_param_index }, .{ | |
| 1672 | .@"const" = kind == .definition, | |
| 1673 | }, .none); | |
| 1674 | c_param_index += 1; | |
| 1675 | } | |
| 1676 | if (fn_info.is_var_args) { | |
| 1677 | if (c_param_index != 0) try w.writeAll(", "); | |
| 1678 | try w.writeAll("..."); | |
| 1679 | } else if (c_param_index == 0) { | |
| 1680 | try w.writeAll("void"); | |
| 1681 | } | |
| 1682 | try w.writeByte(')'); | |
| 1683 | } | |
| 1684 | try w.print("{f}", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)}); | |
| 1885 | 1685 | |
| 1886 | 1686 | switch (kind) { |
| 1887 | .forward => { | |
| 1687 | .forward_decl => { | |
| 1888 | 1688 | if (fn_align.toByteUnits()) |a| try w.print(" zig_align_fn({})", .{a}); |
| 1889 | 1689 | switch (name) { |
| 1890 | .nav, .fmt_ctype_pool_string => {}, | |
| 1690 | .nav, .nav_never_tail, .nav_never_inline => {}, | |
| 1891 | 1691 | .@"export" => |@"export"| { |
| 1892 | 1692 | const extern_name = @"export".extern_name.toSlice(ip); |
| 1893 | 1693 | const is_mangled = isMangledIdent(extern_name, true); |
| ... | ... | @@ -1911,38 +1711,16 @@ pub const DeclGen = struct { |
| 1911 | 1711 | }, |
| 1912 | 1712 | } |
| 1913 | 1713 | }, |
| 1914 | .complete => {}, | |
| 1915 | else => unreachable, | |
| 1714 | .definition => {}, | |
| 1916 | 1715 | } |
| 1917 | 1716 | } |
| 1918 | 1717 | |
| 1919 | fn ctypeFromType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { | |
| 1920 | defer std.debug.assert(dg.scratch.items.len == 0); | |
| 1921 | return dg.ctype_pool.fromType(dg.gpa, &dg.scratch, ty, dg.pt, dg.mod, kind); | |
| 1922 | } | |
| 1923 | ||
| 1924 | fn byteSize(dg: *DeclGen, ctype: CType) u64 { | |
| 1925 | return ctype.byteSize(&dg.ctype_pool, dg.mod); | |
| 1926 | } | |
| 1927 | ||
| 1928 | /// Renders a type as a single identifier, generating intermediate typedefs | |
| 1929 | /// if necessary. | |
| 1930 | /// | |
| 1931 | /// This is guaranteed to be valid in both typedefs and declarations/definitions. | |
| 1932 | /// | |
| 1933 | /// There are three type formats in total that we support rendering: | |
| 1934 | /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | | |
| 1935 | /// |---------------------|-----------------|---------------------| | |
| 1936 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | | |
| 1937 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | | |
| 1938 | /// | |
| 1939 | fn renderType(dg: *DeclGen, w: *Writer, t: Type) Error!void { | |
| 1940 | try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); | |
| 1941 | } | |
| 1942 | ||
| 1943 | fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void { | |
| 1944 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{}); | |
| 1945 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{}); | |
| 1718 | /// Renders the C lowering of the given Zig type to `w`. This renders the type name---to render | |
| 1719 | /// a declarator with this type, see instead `renderTypeAndName`. | |
| 1720 | fn renderType(dg: *DeclGen, w: *Writer, ty: Type) (Writer.Error || Allocator.Error)!void { | |
| 1721 | const zcu = dg.pt.zcu; | |
| 1722 | const cty: CType = try .lower(ty, &dg.ctype_deps, dg.arena, zcu); | |
| 1723 | try w.print("{f}", .{cty.fmtTypeName(zcu)}); | |
| 1946 | 1724 | } |
| 1947 | 1725 | |
| 1948 | 1726 | const IntCastContext = union(enum) { |
| ... | ... | @@ -2046,7 +1824,7 @@ pub const DeclGen = struct { |
| 2046 | 1824 | try w.writeAll("zig_lo_"); |
| 2047 | 1825 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 2048 | 1826 | try w.writeByte('('); |
| 2049 | try context.writeValue(dg, w, .FunctionArgument); | |
| 1827 | try context.writeValue(dg, w, .other); | |
| 2050 | 1828 | try w.writeByte(')'); |
| 2051 | 1829 | } else if (dest_bits > 64 and src_bits <= 64) { |
| 2052 | 1830 | try w.writeAll("zig_make_"); |
| ... | ... | @@ -2057,7 +1835,7 @@ pub const DeclGen = struct { |
| 2057 | 1835 | try dg.renderType(w, src_eff_ty); |
| 2058 | 1836 | try w.writeByte(')'); |
| 2059 | 1837 | } |
| 2060 | try context.writeValue(dg, w, .FunctionArgument); | |
| 1838 | try context.writeValue(dg, w, .other); | |
| 2061 | 1839 | try w.writeByte(')'); |
| 2062 | 1840 | } else { |
| 2063 | 1841 | assert(!src_is_ptr); |
| ... | ... | @@ -2066,23 +1844,16 @@ pub const DeclGen = struct { |
| 2066 | 1844 | try w.writeAll("(zig_hi_"); |
| 2067 | 1845 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 2068 | 1846 | try w.writeByte('('); |
| 2069 | try context.writeValue(dg, w, .FunctionArgument); | |
| 1847 | try context.writeValue(dg, w, .other); | |
| 2070 | 1848 | try w.writeAll("), zig_lo_"); |
| 2071 | 1849 | try dg.renderTypeForBuiltinFnName(w, src_eff_ty); |
| 2072 | 1850 | try w.writeByte('('); |
| 2073 | try context.writeValue(dg, w, .FunctionArgument); | |
| 1851 | try context.writeValue(dg, w, .other); | |
| 2074 | 1852 | try w.writeAll("))"); |
| 2075 | 1853 | } |
| 2076 | 1854 | } |
| 2077 | 1855 | |
| 2078 | /// Renders a type and name in field declaration/definition format. | |
| 2079 | /// | |
| 2080 | /// There are three type formats in total that we support rendering: | |
| 2081 | /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | | |
| 2082 | /// |---------------------|-----------------|---------------------| | |
| 2083 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | | |
| 2084 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | | |
| 2085 | /// | |
| 1856 | /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type. | |
| 2086 | 1857 | fn renderTypeAndName( |
| 2087 | 1858 | dg: *DeclGen, |
| 2088 | 1859 | w: *Writer, |
| ... | ... | @@ -2090,73 +1861,47 @@ pub const DeclGen = struct { |
| 2090 | 1861 | name: CValue, |
| 2091 | 1862 | qualifiers: CQualifiers, |
| 2092 | 1863 | alignment: Alignment, |
| 2093 | kind: CType.Kind, | |
| 2094 | ) !void { | |
| 2095 | try dg.renderCTypeAndName( | |
| 2096 | w, | |
| 2097 | try dg.ctypeFromType(ty, kind), | |
| 2098 | name, | |
| 2099 | qualifiers, | |
| 2100 | CType.AlignAs.fromAlignment(.{ | |
| 2101 | .@"align" = alignment, | |
| 2102 | .abi = ty.abiAlignment(dg.pt.zcu), | |
| 2103 | }), | |
| 2104 | ); | |
| 2105 | } | |
| 2106 | ||
| 2107 | fn renderCTypeAndName( | |
| 2108 | dg: *DeclGen, | |
| 2109 | w: *Writer, | |
| 2110 | ctype: CType, | |
| 2111 | name: CValue, | |
| 2112 | qualifiers: CQualifiers, | |
| 2113 | alignas: CType.AlignAs, | |
| 2114 | 1864 | ) !void { |
| 2115 | 1865 | const zcu = dg.pt.zcu; |
| 2116 | switch (alignas.abiOrder()) { | |
| 2117 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), | |
| 1866 | const ip = &zcu.intern_pool; | |
| 1867 | const cty: CType = try .lower(ty, &dg.ctype_deps, dg.arena, zcu); | |
| 1868 | try w.print("{f}", .{cty.fmtDeclaratorPrefix(zcu)}); | |
| 1869 | if (alignment != .none) switch (alignment.order(ty.abiAlignment(zcu))) { | |
| 1870 | .lt => try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}), | |
| 2118 | 1871 | .eq => {}, |
| 2119 | .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), | |
| 2120 | } | |
| 2121 | ||
| 2122 | try w.print("{f}", .{ | |
| 2123 | try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers), | |
| 2124 | }); | |
| 2125 | try dg.writeName(w, name); | |
| 2126 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{}); | |
| 2127 | if (ctype.isNonString(&dg.ctype_pool)) try w.writeAll(" zig_nonstring"); | |
| 2128 | } | |
| 2129 | ||
| 2130 | fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void { | |
| 2131 | switch (c_value) { | |
| 1872 | .gt => try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}), | |
| 1873 | }; | |
| 1874 | if (qualifiers.@"const") try w.writeAll("const "); | |
| 1875 | if (qualifiers.@"volatile") try w.writeAll("volatile "); | |
| 1876 | if (qualifiers.restrict) try w.writeAll("restrict "); | |
| 1877 | switch (name) { | |
| 2132 | 1878 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| 1879 | .arg => |i| try w.print("a{d}", .{i}), | |
| 2133 | 1880 | .constant => |uav| try renderUavName(w, uav), |
| 2134 | .nav => |nav| try dg.renderNavName(w, nav), | |
| 1881 | .nav => |nav| try renderNavName(w, nav, ip), | |
| 2135 | 1882 | .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}), |
| 2136 | 1883 | else => unreachable, |
| 2137 | 1884 | } |
| 1885 | try w.print("{f}", .{cty.fmtDeclaratorSuffix(zcu)}); | |
| 2138 | 1886 | } |
| 2139 | 1887 | |
| 2140 | 1888 | fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void { |
| 2141 | 1889 | switch (c_value) { |
| 2142 | 1890 | .none, .new_local, .local, .local_ref => unreachable, |
| 2143 | 1891 | .constant => |uav| try renderUavName(w, uav), |
| 2144 | .arg, .arg_array => unreachable, | |
| 1892 | .arg => unreachable, | |
| 2145 | 1893 | .field => |i| try w.print("f{d}", .{i}), |
| 2146 | .nav => |nav| try dg.renderNavName(w, nav), | |
| 1894 | .nav => |nav| try renderNavName(w, nav, &dg.pt.zcu.intern_pool), | |
| 2147 | 1895 | .nav_ref => |nav| { |
| 2148 | 1896 | try w.writeByte('&'); |
| 2149 | try dg.renderNavName(w, nav); | |
| 1897 | try renderNavName(w, nav, &dg.pt.zcu.intern_pool); | |
| 2150 | 1898 | }, |
| 2151 | .undef => |ty| try dg.renderUndefValue(w, ty, .Other), | |
| 1899 | .undef => |ty| try dg.renderUndefValue(w, ty, .other), | |
| 2152 | 1900 | .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}), |
| 2153 | 1901 | .payload_identifier => |ident| try w.print("{f}.{f}", .{ |
| 2154 | 1902 | fmtIdentSolo("payload"), |
| 2155 | 1903 | fmtIdentSolo(ident), |
| 2156 | 1904 | }), |
| 2157 | .ctype_pool_string => |string| try w.print("{f}", .{ | |
| 2158 | fmtCTypePoolString(string, &dg.ctype_pool, true), | |
| 2159 | }), | |
| 2160 | 1905 | } |
| 2161 | 1906 | } |
| 2162 | 1907 | |
| ... | ... | @@ -2168,16 +1913,14 @@ pub const DeclGen = struct { |
| 2168 | 1913 | .local_ref, |
| 2169 | 1914 | .constant, |
| 2170 | 1915 | .arg, |
| 2171 | .arg_array, | |
| 2172 | .ctype_pool_string, | |
| 2173 | 1916 | => unreachable, |
| 2174 | 1917 | .field => |i| try w.print("f{d}", .{i}), |
| 2175 | 1918 | .nav => |nav| { |
| 2176 | 1919 | try w.writeAll("(*"); |
| 2177 | try dg.renderNavName(w, nav); | |
| 1920 | try renderNavName(w, nav, &dg.pt.zcu.intern_pool); | |
| 2178 | 1921 | try w.writeByte(')'); |
| 2179 | 1922 | }, |
| 2180 | .nav_ref => |nav| try dg.renderNavName(w, nav), | |
| 1923 | .nav_ref => |nav| try renderNavName(w, nav, &dg.pt.zcu.intern_pool), | |
| 2181 | 1924 | .undef => unreachable, |
| 2182 | 1925 | .identifier => |ident| try w.print("(*{f})", .{fmtIdentSolo(ident)}), |
| 2183 | 1926 | .payload_identifier => |ident| try w.print("(*{f}.{f})", .{ |
| ... | ... | @@ -2213,8 +1956,6 @@ pub const DeclGen = struct { |
| 2213 | 1956 | .field, |
| 2214 | 1957 | .undef, |
| 2215 | 1958 | .arg, |
| 2216 | .arg_array, | |
| 2217 | .ctype_pool_string, | |
| 2218 | 1959 | => unreachable, |
| 2219 | 1960 | .nav, .identifier, .payload_identifier => { |
| 2220 | 1961 | try dg.writeCValue(w, c_value); |
| ... | ... | @@ -2228,101 +1969,36 @@ pub const DeclGen = struct { |
| 2228 | 1969 | try dg.writeCValue(w, member); |
| 2229 | 1970 | } |
| 2230 | 1971 | |
| 2231 | fn renderFwdDecl( | |
| 2232 | dg: *DeclGen, | |
| 2233 | nav_index: InternPool.Nav.Index, | |
| 2234 | flags: packed struct { | |
| 2235 | is_const: bool, | |
| 2236 | is_threadlocal: bool, | |
| 2237 | linkage: std.builtin.GlobalLinkage, | |
| 2238 | visibility: std.builtin.SymbolVisibility, | |
| 2239 | }, | |
| 2240 | ) !void { | |
| 1972 | fn renderTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ty: Type) !void { | |
| 2241 | 1973 | const zcu = dg.pt.zcu; |
| 2242 | const ip = &zcu.intern_pool; | |
| 2243 | const nav = ip.getNav(nav_index); | |
| 2244 | const fwd = &dg.fwd_decl.writer; | |
| 2245 | try fwd.writeAll(switch (flags.linkage) { | |
| 2246 | .internal => "static ", | |
| 2247 | .strong, .weak, .link_once => "zig_extern ", | |
| 2248 | }); | |
| 2249 | switch (flags.linkage) { | |
| 2250 | .internal, .strong => {}, | |
| 2251 | .weak => try fwd.writeAll("zig_weak_linkage "), | |
| 2252 | .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), | |
| 2253 | } | |
| 2254 | switch (flags.linkage) { | |
| 2255 | .internal => {}, | |
| 2256 | .strong, .weak, .link_once => try fwd.print("zig_visibility({s}) ", .{@tagName(flags.visibility)}), | |
| 1974 | switch (ty.zigTypeTag(zcu)) { | |
| 1975 | .bool => return w.writeAll("u8"), | |
| 1976 | .float => return w.print("f{d}", .{ty.floatBits(zcu.getTarget())}), | |
| 1977 | else => {}, | |
| 2257 | 1978 | } |
| 2258 | if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); | |
| 2259 | try dg.renderTypeAndName( | |
| 2260 | fwd, | |
| 2261 | .fromInterned(nav.typeOf(ip)), | |
| 2262 | .{ .nav = nav_index }, | |
| 2263 | CQualifiers.init(.{ .@"const" = flags.is_const }), | |
| 2264 | nav.getAlignment(), | |
| 2265 | .complete, | |
| 2266 | ); | |
| 2267 | try fwd.writeAll(";\n"); | |
| 2268 | } | |
| 2269 | ||
| 2270 | fn renderNavName(dg: *DeclGen, w: *Writer, nav_index: InternPool.Nav.Index) !void { | |
| 2271 | const zcu = dg.pt.zcu; | |
| 2272 | const ip = &zcu.intern_pool; | |
| 2273 | const nav = ip.getNav(nav_index); | |
| 2274 | if (nav.getExtern(ip)) |@"extern"| { | |
| 2275 | try w.print("{f}", .{ | |
| 2276 | fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), | |
| 2277 | }); | |
| 2278 | } else { | |
| 2279 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), | |
| 2280 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | |
| 2281 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); | |
| 2282 | try w.print("{f}__{d}", .{ | |
| 2283 | fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]), | |
| 2284 | @intFromEnum(nav_index), | |
| 2285 | }); | |
| 1979 | if (ty.isPtrAtRuntime(zcu)) { | |
| 1980 | return w.print("p{d}", .{zcu.getTarget().ptrBitWidth()}); | |
| 2286 | 1981 | } |
| 2287 | } | |
| 2288 | ||
| 2289 | fn renderUavName(w: *Writer, uav: Value) !void { | |
| 2290 | try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); | |
| 2291 | } | |
| 2292 | ||
| 2293 | fn renderTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ty: Type) !void { | |
| 2294 | try dg.renderCTypeForBuiltinFnName(w, try dg.ctypeFromType(ty, .complete)); | |
| 2295 | } | |
| 2296 | ||
| 2297 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ctype: CType) !void { | |
| 2298 | switch (ctype.info(&dg.ctype_pool)) { | |
| 2299 | else => |ctype_info| try w.print("{c}{d}", .{ | |
| 2300 | if (ctype.isBool()) | |
| 2301 | signAbbrev(.unsigned) | |
| 2302 | else if (ctype.isInteger()) | |
| 2303 | signAbbrev(ctype.signedness(dg.mod)) | |
| 2304 | else if (ctype.isFloat()) | |
| 2305 | @as(u8, 'f') | |
| 2306 | else if (ctype_info == .pointer) | |
| 2307 | @as(u8, 'p') | |
| 2308 | else | |
| 2309 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}), | |
| 2310 | if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8, | |
| 1982 | switch (CType.classifyInt(ty, zcu)) { | |
| 1983 | .void => unreachable, // opv | |
| 1984 | .small => try w.print("{c}{d}", .{ | |
| 1985 | signAbbrev(ty.intInfo(zcu).signedness), | |
| 1986 | ty.abiSize(zcu) * 8, | |
| 2311 | 1987 | }), |
| 2312 | .array => try w.writeAll("big"), | |
| 1988 | .big => try w.writeAll("big"), | |
| 2313 | 1989 | } |
| 2314 | 1990 | } |
| 2315 | 1991 | |
| 2316 | 1992 | fn renderBuiltinInfo(dg: *DeclGen, w: *Writer, ty: Type, info: BuiltinInfo) !void { |
| 2317 | const ctype = try dg.ctypeFromType(ty, .complete); | |
| 2318 | const is_big = ctype.info(&dg.ctype_pool) == .array; | |
| 1993 | const pt = dg.pt; | |
| 1994 | const zcu = pt.zcu; | |
| 1995 | ||
| 1996 | const is_big = lowersToBigInt(ty, zcu); | |
| 2319 | 1997 | switch (info) { |
| 2320 | 1998 | .none => if (!is_big) return, |
| 2321 | 1999 | .bits => {}, |
| 2322 | 2000 | } |
| 2323 | 2001 | |
| 2324 | const pt = dg.pt; | |
| 2325 | const zcu = pt.zcu; | |
| 2326 | 2002 | const int_info: std.builtin.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{ |
| 2327 | 2003 | .signedness = .unsigned, |
| 2328 | 2004 | .bits = @intCast(ty.bitSize(zcu)), |
| ... | ... | @@ -2331,7 +2007,7 @@ pub const DeclGen = struct { |
| 2331 | 2007 | if (is_big) try w.print(", {}", .{int_info.signedness == .signed}); |
| 2332 | 2008 | try w.print(", {f}", .{try dg.fmtIntLiteralDec( |
| 2333 | 2009 | try pt.intValue(if (is_big) .u16 else .u8, int_info.bits), |
| 2334 | .FunctionArgument, | |
| 2010 | .other, | |
| 2335 | 2011 | )}); |
| 2336 | 2012 | } |
| 2337 | 2013 | |
| ... | ... | @@ -2342,15 +2018,13 @@ pub const DeclGen = struct { |
| 2342 | 2018 | base: u8, |
| 2343 | 2019 | case: std.fmt.Case, |
| 2344 | 2020 | ) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { |
| 2345 | const zcu = dg.pt.zcu; | |
| 2346 | const kind = loc.toCTypeKind(); | |
| 2347 | const ty = val.typeOf(zcu); | |
| 2021 | // If there's a bigint type involved, mark a dependency on it. | |
| 2022 | const cty: CType = try .lower(val.typeOf(dg.pt.zcu), &dg.ctype_deps, dg.arena, dg.pt.zcu); | |
| 2348 | 2023 | return .{ .data = .{ |
| 2349 | 2024 | .dg = dg, |
| 2350 | .int_info = ty.intInfo(zcu), | |
| 2351 | .kind = kind, | |
| 2352 | .ctype = try dg.ctypeFromType(ty, kind), | |
| 2025 | .loc = loc, | |
| 2353 | 2026 | .val = val, |
| 2027 | .cty = cty, | |
| 2354 | 2028 | .base = base, |
| 2355 | 2029 | .case = case, |
| 2356 | 2030 | } }; |
| ... | ... | @@ -2373,339 +2047,11 @@ pub const DeclGen = struct { |
| 2373 | 2047 | } |
| 2374 | 2048 | }; |
| 2375 | 2049 | |
| 2376 | const CTypeFix = enum { prefix, suffix }; | |
| 2377 | const CQualifiers = std.enums.EnumSet(enum { @"const", @"volatile", restrict }); | |
| 2378 | const Const = CQualifiers.init(.{ .@"const" = true }); | |
| 2379 | const RenderCTypeTrailing = enum { | |
| 2380 | no_space, | |
| 2381 | maybe_space, | |
| 2382 | ||
| 2383 | pub fn format(self: @This(), w: *Writer) Writer.Error!void { | |
| 2384 | switch (self) { | |
| 2385 | .no_space => {}, | |
| 2386 | .maybe_space => try w.writeByte(' '), | |
| 2387 | } | |
| 2388 | } | |
| 2050 | const CQualifiers = packed struct { | |
| 2051 | @"const": bool = false, | |
| 2052 | @"volatile": bool = false, | |
| 2053 | restrict: bool = false, | |
| 2389 | 2054 | }; |
| 2390 | fn renderAlignedTypeName(w: *Writer, ctype: CType) !void { | |
| 2391 | try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)}); | |
| 2392 | } | |
| 2393 | fn renderFwdDeclTypeName( | |
| 2394 | zcu: *Zcu, | |
| 2395 | w: *Writer, | |
| 2396 | ctype: CType, | |
| 2397 | fwd_decl: CType.Info.FwdDecl, | |
| 2398 | attributes: []const u8, | |
| 2399 | ) !void { | |
| 2400 | const ip = &zcu.intern_pool; | |
| 2401 | try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); | |
| 2402 | switch (fwd_decl.name) { | |
| 2403 | .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), | |
| 2404 | .index => |index| try w.print("{f}__{d}", .{ | |
| 2405 | fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)), | |
| 2406 | @intFromEnum(index), | |
| 2407 | }), | |
| 2408 | } | |
| 2409 | } | |
| 2410 | fn renderTypePrefix( | |
| 2411 | pass: DeclGen.Pass, | |
| 2412 | ctype_pool: *const CType.Pool, | |
| 2413 | zcu: *Zcu, | |
| 2414 | w: *Writer, | |
| 2415 | ctype: CType, | |
| 2416 | parent_fix: CTypeFix, | |
| 2417 | qualifiers: CQualifiers, | |
| 2418 | ) Writer.Error!RenderCTypeTrailing { | |
| 2419 | var trailing = RenderCTypeTrailing.maybe_space; | |
| 2420 | switch (ctype.info(ctype_pool)) { | |
| 2421 | .basic => |basic_info| try w.writeAll(@tagName(basic_info)), | |
| 2422 | ||
| 2423 | .pointer => |pointer_info| { | |
| 2424 | try w.print("{f}*", .{try renderTypePrefix( | |
| 2425 | pass, | |
| 2426 | ctype_pool, | |
| 2427 | zcu, | |
| 2428 | w, | |
| 2429 | pointer_info.elem_ctype, | |
| 2430 | .prefix, | |
| 2431 | CQualifiers.init(.{ | |
| 2432 | .@"const" = pointer_info.@"const", | |
| 2433 | .@"volatile" = pointer_info.@"volatile", | |
| 2434 | }), | |
| 2435 | )}); | |
| 2436 | trailing = .no_space; | |
| 2437 | }, | |
| 2438 | ||
| 2439 | .aligned => switch (pass) { | |
| 2440 | .nav => |nav| try w.print("nav__{d}_{d}", .{ | |
| 2441 | @intFromEnum(nav), @intFromEnum(ctype.index), | |
| 2442 | }), | |
| 2443 | .uav => |uav| try w.print("uav__{d}_{d}", .{ | |
| 2444 | @intFromEnum(uav), @intFromEnum(ctype.index), | |
| 2445 | }), | |
| 2446 | .flush => try renderAlignedTypeName(w, ctype), | |
| 2447 | }, | |
| 2448 | ||
| 2449 | .array, .vector => |sequence_info| { | |
| 2450 | const child_trailing = try renderTypePrefix( | |
| 2451 | pass, | |
| 2452 | ctype_pool, | |
| 2453 | zcu, | |
| 2454 | w, | |
| 2455 | sequence_info.elem_ctype, | |
| 2456 | .suffix, | |
| 2457 | qualifiers, | |
| 2458 | ); | |
| 2459 | switch (parent_fix) { | |
| 2460 | .prefix => { | |
| 2461 | try w.print("{f}(", .{child_trailing}); | |
| 2462 | return .no_space; | |
| 2463 | }, | |
| 2464 | .suffix => return child_trailing, | |
| 2465 | } | |
| 2466 | }, | |
| 2467 | ||
| 2468 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 2469 | .anon => switch (pass) { | |
| 2470 | .nav => |nav| try w.print("nav__{d}_{d}", .{ | |
| 2471 | @intFromEnum(nav), @intFromEnum(ctype.index), | |
| 2472 | }), | |
| 2473 | .uav => |uav| try w.print("uav__{d}_{d}", .{ | |
| 2474 | @intFromEnum(uav), @intFromEnum(ctype.index), | |
| 2475 | }), | |
| 2476 | .flush => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | |
| 2477 | }, | |
| 2478 | .index => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | |
| 2479 | }, | |
| 2480 | ||
| 2481 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | |
| 2482 | .anon => { | |
| 2483 | try w.print("{s} {s}", .{ | |
| 2484 | @tagName(aggregate_info.tag), | |
| 2485 | if (aggregate_info.@"packed") "zig_packed(" else "", | |
| 2486 | }); | |
| 2487 | try renderFields(zcu, w, ctype_pool, aggregate_info, 1); | |
| 2488 | if (aggregate_info.@"packed") try w.writeByte(')'); | |
| 2489 | }, | |
| 2490 | .fwd_decl => |fwd_decl| return renderTypePrefix( | |
| 2491 | pass, | |
| 2492 | ctype_pool, | |
| 2493 | zcu, | |
| 2494 | w, | |
| 2495 | fwd_decl, | |
| 2496 | parent_fix, | |
| 2497 | qualifiers, | |
| 2498 | ), | |
| 2499 | }, | |
| 2500 | ||
| 2501 | .function => |function_info| { | |
| 2502 | const child_trailing = try renderTypePrefix( | |
| 2503 | pass, | |
| 2504 | ctype_pool, | |
| 2505 | zcu, | |
| 2506 | w, | |
| 2507 | function_info.return_ctype, | |
| 2508 | .suffix, | |
| 2509 | .{}, | |
| 2510 | ); | |
| 2511 | switch (parent_fix) { | |
| 2512 | .prefix => { | |
| 2513 | try w.print("{f}(", .{child_trailing}); | |
| 2514 | return .no_space; | |
| 2515 | }, | |
| 2516 | .suffix => return child_trailing, | |
| 2517 | } | |
| 2518 | }, | |
| 2519 | } | |
| 2520 | var qualifier_it = qualifiers.iterator(); | |
| 2521 | while (qualifier_it.next()) |qualifier| { | |
| 2522 | try w.print("{f}{s}", .{ trailing, @tagName(qualifier) }); | |
| 2523 | trailing = .maybe_space; | |
| 2524 | } | |
| 2525 | return trailing; | |
| 2526 | } | |
| 2527 | fn renderTypeSuffix( | |
| 2528 | pass: DeclGen.Pass, | |
| 2529 | ctype_pool: *const CType.Pool, | |
| 2530 | zcu: *Zcu, | |
| 2531 | w: *Writer, | |
| 2532 | ctype: CType, | |
| 2533 | parent_fix: CTypeFix, | |
| 2534 | qualifiers: CQualifiers, | |
| 2535 | ) Writer.Error!void { | |
| 2536 | switch (ctype.info(ctype_pool)) { | |
| 2537 | .basic, .aligned, .fwd_decl, .aggregate => {}, | |
| 2538 | .pointer => |pointer_info| try renderTypeSuffix( | |
| 2539 | pass, | |
| 2540 | ctype_pool, | |
| 2541 | zcu, | |
| 2542 | w, | |
| 2543 | pointer_info.elem_ctype, | |
| 2544 | .prefix, | |
| 2545 | .{}, | |
| 2546 | ), | |
| 2547 | .array, .vector => |sequence_info| { | |
| 2548 | switch (parent_fix) { | |
| 2549 | .prefix => try w.writeByte(')'), | |
| 2550 | .suffix => {}, | |
| 2551 | } | |
| 2552 | ||
| 2553 | try w.print("[{}]", .{sequence_info.len}); | |
| 2554 | try renderTypeSuffix(pass, ctype_pool, zcu, w, sequence_info.elem_ctype, .suffix, .{}); | |
| 2555 | }, | |
| 2556 | .function => |function_info| { | |
| 2557 | switch (parent_fix) { | |
| 2558 | .prefix => try w.writeByte(')'), | |
| 2559 | .suffix => {}, | |
| 2560 | } | |
| 2561 | ||
| 2562 | try w.writeByte('('); | |
| 2563 | var need_comma = false; | |
| 2564 | for (0..function_info.param_ctypes.len) |param_index| { | |
| 2565 | const param_type = function_info.param_ctypes.at(param_index, ctype_pool); | |
| 2566 | if (need_comma) try w.writeAll(", "); | |
| 2567 | need_comma = true; | |
| 2568 | const trailing = | |
| 2569 | try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers); | |
| 2570 | if (qualifiers.contains(.@"const")) try w.print("{f}a{d}", .{ trailing, param_index }); | |
| 2571 | try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{}); | |
| 2572 | } | |
| 2573 | if (function_info.varargs) { | |
| 2574 | if (need_comma) try w.writeAll(", "); | |
| 2575 | need_comma = true; | |
| 2576 | try w.writeAll("..."); | |
| 2577 | } | |
| 2578 | if (!need_comma) try w.writeAll("void"); | |
| 2579 | try w.writeByte(')'); | |
| 2580 | ||
| 2581 | try renderTypeSuffix(pass, ctype_pool, zcu, w, function_info.return_ctype, .suffix, .{}); | |
| 2582 | }, | |
| 2583 | } | |
| 2584 | } | |
| 2585 | fn renderFields( | |
| 2586 | zcu: *Zcu, | |
| 2587 | w: *Writer, | |
| 2588 | ctype_pool: *const CType.Pool, | |
| 2589 | aggregate_info: CType.Info.Aggregate, | |
| 2590 | indent: usize, | |
| 2591 | ) !void { | |
| 2592 | try w.writeAll("{\n"); | |
| 2593 | for (0..aggregate_info.fields.len) |field_index| { | |
| 2594 | const field_info = aggregate_info.fields.at(field_index, ctype_pool); | |
| 2595 | try w.splatByteAll(' ', indent + 1); | |
| 2596 | switch (field_info.alignas.abiOrder()) { | |
| 2597 | .lt => { | |
| 2598 | std.debug.assert(aggregate_info.@"packed"); | |
| 2599 | if (field_info.alignas.@"align" != .@"1") try w.print("zig_under_align({}) ", .{ | |
| 2600 | field_info.alignas.toByteUnits(), | |
| 2601 | }); | |
| 2602 | }, | |
| 2603 | .eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1") | |
| 2604 | try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}), | |
| 2605 | .gt => { | |
| 2606 | std.debug.assert(field_info.alignas.@"align" != .@"1"); | |
| 2607 | try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}); | |
| 2608 | }, | |
| 2609 | } | |
| 2610 | const trailing = try renderTypePrefix( | |
| 2611 | .flush, | |
| 2612 | ctype_pool, | |
| 2613 | zcu, | |
| 2614 | w, | |
| 2615 | field_info.ctype, | |
| 2616 | .suffix, | |
| 2617 | .{}, | |
| 2618 | ); | |
| 2619 | try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) }); | |
| 2620 | try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{}); | |
| 2621 | if (field_info.ctype.isNonString(ctype_pool)) try w.writeAll(" zig_nonstring"); | |
| 2622 | try w.writeAll(";\n"); | |
| 2623 | } | |
| 2624 | try w.splatByteAll(' ', indent); | |
| 2625 | try w.writeByte('}'); | |
| 2626 | } | |
| 2627 | ||
| 2628 | pub fn genTypeDecl( | |
| 2629 | zcu: *Zcu, | |
| 2630 | w: *Writer, | |
| 2631 | global_ctype_pool: *const CType.Pool, | |
| 2632 | global_ctype: CType, | |
| 2633 | pass: DeclGen.Pass, | |
| 2634 | decl_ctype_pool: *const CType.Pool, | |
| 2635 | decl_ctype: CType, | |
| 2636 | found_existing: bool, | |
| 2637 | ) !void { | |
| 2638 | switch (global_ctype.info(global_ctype_pool)) { | |
| 2639 | .basic, .pointer, .array, .vector, .function => {}, | |
| 2640 | .aligned => |aligned_info| { | |
| 2641 | if (!found_existing) { | |
| 2642 | std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt)); | |
| 2643 | try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()}); | |
| 2644 | try w.print("{f}", .{try renderTypePrefix( | |
| 2645 | .flush, | |
| 2646 | global_ctype_pool, | |
| 2647 | zcu, | |
| 2648 | w, | |
| 2649 | aligned_info.ctype, | |
| 2650 | .suffix, | |
| 2651 | .{}, | |
| 2652 | )}); | |
| 2653 | try renderAlignedTypeName(w, global_ctype); | |
| 2654 | try renderTypeSuffix(.flush, global_ctype_pool, zcu, w, aligned_info.ctype, .suffix, .{}); | |
| 2655 | try w.writeAll(";\n"); | |
| 2656 | } | |
| 2657 | switch (pass) { | |
| 2658 | .nav, .uav => { | |
| 2659 | try w.writeAll("typedef "); | |
| 2660 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); | |
| 2661 | try w.writeByte(' '); | |
| 2662 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{}); | |
| 2663 | try w.writeAll(";\n"); | |
| 2664 | }, | |
| 2665 | .flush => {}, | |
| 2666 | } | |
| 2667 | }, | |
| 2668 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 2669 | .anon => switch (pass) { | |
| 2670 | .nav, .uav => { | |
| 2671 | try w.writeAll("typedef "); | |
| 2672 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); | |
| 2673 | try w.writeByte(' '); | |
| 2674 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{}); | |
| 2675 | try w.writeAll(";\n"); | |
| 2676 | }, | |
| 2677 | .flush => {}, | |
| 2678 | }, | |
| 2679 | .index => |index| if (!found_existing) { | |
| 2680 | const ip = &zcu.intern_pool; | |
| 2681 | const ty: Type = .fromInterned(index); | |
| 2682 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); | |
| 2683 | try w.writeByte(';'); | |
| 2684 | const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip); | |
| 2685 | if (!zcu.fileByIndex(file_scope).mod.?.strip) try w.print(" /* {f} */", .{ | |
| 2686 | ty.containerTypeName(ip).fmt(ip), | |
| 2687 | }); | |
| 2688 | try w.writeByte('\n'); | |
| 2689 | }, | |
| 2690 | }, | |
| 2691 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | |
| 2692 | .anon => {}, | |
| 2693 | .fwd_decl => |fwd_decl| if (!found_existing) { | |
| 2694 | try renderFwdDeclTypeName( | |
| 2695 | zcu, | |
| 2696 | w, | |
| 2697 | fwd_decl, | |
| 2698 | fwd_decl.info(global_ctype_pool).fwd_decl, | |
| 2699 | if (aggregate_info.@"packed") "zig_packed(" else "", | |
| 2700 | ); | |
| 2701 | try w.writeByte(' '); | |
| 2702 | try renderFields(zcu, w, global_ctype_pool, aggregate_info, 0); | |
| 2703 | if (aggregate_info.@"packed") try w.writeByte(')'); | |
| 2704 | try w.writeAll(";\n"); | |
| 2705 | }, | |
| 2706 | }, | |
| 2707 | } | |
| 2708 | } | |
| 2709 | 2055 | |
| 2710 | 2056 | pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { |
| 2711 | 2057 | for (zcu.global_assembly.values()) |asm_source| { |
| ... | ... | @@ -2713,200 +2059,128 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { |
| 2713 | 2059 | } |
| 2714 | 2060 | } |
| 2715 | 2061 | |
| 2716 | pub fn genErrDecls(o: *Object) Error!void { | |
| 2717 | const pt = o.dg.pt; | |
| 2718 | const zcu = pt.zcu; | |
| 2062 | pub fn genErrDecls( | |
| 2063 | zcu: *const Zcu, | |
| 2064 | w: *Writer, | |
| 2065 | slice_const_u8_sentinel_0_type_name: []const u8, | |
| 2066 | ) Writer.Error!void { | |
| 2719 | 2067 | const ip = &zcu.intern_pool; |
| 2720 | const w = &o.code.writer; | |
| 2721 | 2068 | |
| 2722 | var max_name_len: usize = 0; | |
| 2723 | // do not generate an invalid empty enum when the global error set is empty | |
| 2724 | 2069 | const names = ip.global_error_set.getNamesFromMainThread(); |
| 2070 | // Don't generate an invalid empty enum if the global error set is empty! | |
| 2725 | 2071 | if (names.len > 0) { |
| 2726 | try w.writeAll("enum {"); | |
| 2727 | o.indent(); | |
| 2728 | try o.newline(); | |
| 2072 | try w.writeAll("enum {\n"); | |
| 2729 | 2073 | for (names, 1..) |name_nts, value| { |
| 2730 | const name = name_nts.toSlice(ip); | |
| 2731 | max_name_len = @max(name.len, max_name_len); | |
| 2732 | const err_val = try pt.intern(.{ .err = .{ | |
| 2733 | .ty = .anyerror_type, | |
| 2734 | .name = name_nts, | |
| 2735 | } }); | |
| 2736 | try o.dg.renderValue(w, Value.fromInterned(err_val), .Other); | |
| 2737 | try w.print(" = {d}u,", .{value}); | |
| 2738 | try o.newline(); | |
| 2074 | try w.writeByte(' '); | |
| 2075 | try renderErrorName(w, name_nts.toSlice(ip)); | |
| 2076 | try w.print(" = {d}u,\n", .{value}); | |
| 2739 | 2077 | } |
| 2740 | try o.outdent(); | |
| 2741 | try w.writeAll("};"); | |
| 2742 | try o.newline(); | |
| 2743 | } | |
| 2744 | const array_identifier = "zig_errorName"; | |
| 2745 | const name_prefix = array_identifier ++ "_"; | |
| 2746 | const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + max_name_len); | |
| 2747 | defer o.dg.gpa.free(name_buf); | |
| 2748 | ||
| 2749 | @memcpy(name_buf[0..name_prefix.len], name_prefix); | |
| 2750 | for (names) |name| { | |
| 2751 | const name_slice = name.toSlice(ip); | |
| 2752 | @memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice); | |
| 2753 | const identifier = name_buf[0 .. name_prefix.len + name_slice.len]; | |
| 2754 | ||
| 2755 | const name_ty = try pt.arrayType(.{ | |
| 2756 | .len = name_slice.len, | |
| 2757 | .child = .u8_type, | |
| 2758 | .sentinel = .zero_u8, | |
| 2759 | }); | |
| 2760 | const name_val = try pt.intern(.{ .aggregate = .{ | |
| 2761 | .ty = name_ty.toIntern(), | |
| 2762 | .storage = .{ .bytes = name.toString() }, | |
| 2763 | } }); | |
| 2078 | try w.writeAll("};\n"); | |
| 2079 | } | |
| 2764 | 2080 | |
| 2765 | try w.writeAll("static "); | |
| 2766 | try o.dg.renderTypeAndName( | |
| 2767 | w, | |
| 2768 | name_ty, | |
| 2769 | .{ .identifier = identifier }, | |
| 2770 | Const, | |
| 2771 | .none, | |
| 2772 | .complete, | |
| 2081 | for (names) |name_nts| { | |
| 2082 | const name = name_nts.toSlice(ip); | |
| 2083 | try w.print( | |
| 2084 | "static uint8_t const zig_errorName_{f}[] = {f};\n", | |
| 2085 | .{ fmtIdentUnsolo(name), fmtStringLiteral(name, 0) }, | |
| 2773 | 2086 | ); |
| 2774 | try w.writeAll(" = "); | |
| 2775 | try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer); | |
| 2776 | try w.writeByte(';'); | |
| 2777 | try o.newline(); | |
| 2778 | 2087 | } |
| 2779 | 2088 | |
| 2780 | const name_array_ty = try pt.arrayType(.{ | |
| 2781 | .len = 1 + names.len, | |
| 2782 | .child = .slice_const_u8_sentinel_0_type, | |
| 2783 | }); | |
| 2784 | ||
| 2785 | try w.writeAll("static "); | |
| 2786 | try o.dg.renderTypeAndName( | |
| 2787 | w, | |
| 2788 | name_array_ty, | |
| 2789 | .{ .identifier = array_identifier }, | |
| 2790 | Const, | |
| 2791 | .none, | |
| 2792 | .complete, | |
| 2089 | try w.print( | |
| 2090 | "static {s} const zig_errorName[{d}] = {{", | |
| 2091 | .{ slice_const_u8_sentinel_0_type_name, names.len }, | |
| 2793 | 2092 | ); |
| 2794 | try w.writeAll(" = {"); | |
| 2795 | for (names, 1..) |name_nts, val| { | |
| 2093 | if (names.len > 0) try w.writeByte('\n'); | |
| 2094 | for (names) |name_nts| { | |
| 2796 | 2095 | const name = name_nts.toSlice(ip); |
| 2797 | if (val > 1) try w.writeAll(", "); | |
| 2798 | try w.print("{{" ++ name_prefix ++ "{f}, {f}}}", .{ | |
| 2799 | fmtIdentUnsolo(name), | |
| 2800 | try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer), | |
| 2096 | try w.print( | |
| 2097 | " {{zig_errorName_{f},{d}}},\n", | |
| 2098 | .{ fmtIdentUnsolo(name), name.len }, | |
| 2099 | ); | |
| 2100 | } | |
| 2101 | try w.writeAll("};\n"); | |
| 2102 | } | |
| 2103 | ||
| 2104 | pub fn genTagNameFn( | |
| 2105 | zcu: *const Zcu, | |
| 2106 | w: *Writer, | |
| 2107 | slice_const_u8_sentinel_0_type_name: []const u8, | |
| 2108 | enum_ty: Type, | |
| 2109 | enum_type_name: []const u8, | |
| 2110 | ) Writer.Error!void { | |
| 2111 | const ip = &zcu.intern_pool; | |
| 2112 | const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); | |
| 2113 | assert(loaded_enum.field_names.len > 0); | |
| 2114 | if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { | |
| 2115 | @panic("TODO CBE: tagName for enum over 64 bits"); | |
| 2116 | } | |
| 2117 | ||
| 2118 | try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ | |
| 2119 | slice_const_u8_sentinel_0_type_name, | |
| 2120 | fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), | |
| 2121 | @intFromEnum(enum_ty.toIntern()), | |
| 2122 | enum_type_name, | |
| 2123 | }); | |
| 2124 | for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| { | |
| 2125 | try w.print(" static uint8_t const name{d}[] = {f};\n", .{ | |
| 2126 | field_index, fmtStringLiteral(field_name.toSlice(ip), 0), | |
| 2801 | 2127 | }); |
| 2802 | 2128 | } |
| 2803 | try w.writeAll("};"); | |
| 2804 | try o.newline(); | |
| 2129 | ||
| 2130 | try w.writeAll(" switch (tag) {\n"); | |
| 2131 | const field_values = loaded_enum.field_values.get(ip); | |
| 2132 | for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| { | |
| 2133 | const field_int: i65 = int: { | |
| 2134 | if (field_values.len == 0) break :int field_index; | |
| 2135 | const field_val: Value = .fromInterned(field_values[field_index]); | |
| 2136 | break :int field_val.getUnsignedInt(zcu) orelse field_val.toSignedInt(zcu); | |
| 2137 | }; | |
| 2138 | try w.print(" case {d}: return ({s}){{name{d},{d}}};\n", .{ | |
| 2139 | field_int, | |
| 2140 | slice_const_u8_sentinel_0_type_name, | |
| 2141 | field_index, | |
| 2142 | field_name.toSlice(ip).len, | |
| 2143 | }); | |
| 2144 | } | |
| 2145 | try w.writeAll( | |
| 2146 | \\ } | |
| 2147 | \\ zig_unreachable(); | |
| 2148 | \\} | |
| 2149 | \\ | |
| 2150 | ); | |
| 2805 | 2151 | } |
| 2806 | 2152 | |
| 2807 | pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) Error!void { | |
| 2808 | const pt = o.dg.pt; | |
| 2809 | const zcu = pt.zcu; | |
| 2153 | pub fn genLazyCallModifierFn( | |
| 2154 | dg: *DeclGen, | |
| 2155 | fn_nav: InternPool.Nav.Index, | |
| 2156 | kind: enum { never_tail, never_inline }, | |
| 2157 | w: *Writer, | |
| 2158 | ) Error!void { | |
| 2159 | const zcu = dg.pt.zcu; | |
| 2810 | 2160 | const ip = &zcu.intern_pool; |
| 2811 | const ctype_pool = &o.dg.ctype_pool; | |
| 2812 | const w = &o.code.writer; | |
| 2813 | const key = lazy_fn.key_ptr.*; | |
| 2814 | const val = lazy_fn.value_ptr; | |
| 2815 | switch (key) { | |
| 2816 | .tag_name => |enum_ty_ip| { | |
| 2817 | const enum_ty: Type = .fromInterned(enum_ty_ip); | |
| 2818 | const name_slice_ty: Type = .slice_const_u8_sentinel_0; | |
| 2819 | ||
| 2820 | try w.writeAll("static "); | |
| 2821 | try o.dg.renderType(w, name_slice_ty); | |
| 2822 | try w.print(" {f}(", .{val.fn_name.fmt(lazy_ctype_pool)}); | |
| 2823 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); | |
| 2824 | try w.writeAll(") {"); | |
| 2825 | o.indent(); | |
| 2826 | try o.newline(); | |
| 2827 | try w.writeAll("switch (tag) {"); | |
| 2828 | o.indent(); | |
| 2829 | try o.newline(); | |
| 2830 | const tag_names = enum_ty.enumFields(zcu); | |
| 2831 | for (0..tag_names.len) |tag_index| { | |
| 2832 | const tag_name = tag_names.get(ip)[tag_index]; | |
| 2833 | const tag_name_len = tag_name.length(ip); | |
| 2834 | const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index)); | |
| 2835 | ||
| 2836 | const name_ty = try pt.arrayType(.{ | |
| 2837 | .len = tag_name_len, | |
| 2838 | .child = .u8_type, | |
| 2839 | .sentinel = .zero_u8, | |
| 2840 | }); | |
| 2841 | const name_val = try pt.intern(.{ .aggregate = .{ | |
| 2842 | .ty = name_ty.toIntern(), | |
| 2843 | .storage = .{ .bytes = tag_name.toString() }, | |
| 2844 | } }); | |
| 2845 | 2161 | |
| 2846 | try w.print("case {f}: {{", .{ | |
| 2847 | try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other), | |
| 2848 | }); | |
| 2849 | o.indent(); | |
| 2850 | try o.newline(); | |
| 2851 | try w.writeAll("static "); | |
| 2852 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete); | |
| 2853 | try w.writeAll(" = "); | |
| 2854 | try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer); | |
| 2855 | try w.writeByte(';'); | |
| 2856 | try o.newline(); | |
| 2857 | try w.writeAll("return ("); | |
| 2858 | try o.dg.renderType(w, name_slice_ty); | |
| 2859 | try w.print("){{{f}, {f}}};", .{ | |
| 2860 | fmtIdentUnsolo("name"), | |
| 2861 | try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other), | |
| 2862 | }); | |
| 2863 | try o.newline(); | |
| 2864 | try o.outdent(); | |
| 2865 | try w.writeByte('}'); | |
| 2866 | try o.newline(); | |
| 2867 | } | |
| 2868 | try o.outdent(); | |
| 2869 | try w.writeByte('}'); | |
| 2870 | try o.newline(); | |
| 2871 | try airUnreach(o); | |
| 2872 | try o.outdent(); | |
| 2873 | try w.writeByte('}'); | |
| 2874 | try o.newline(); | |
| 2875 | }, | |
| 2876 | .never_tail, .never_inline => |fn_nav_index| { | |
| 2877 | const fn_val = zcu.navValue(fn_nav_index); | |
| 2878 | const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete); | |
| 2879 | const fn_info = fn_ctype.info(ctype_pool).function; | |
| 2880 | const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool, true); | |
| 2881 | ||
| 2882 | const fwd = &o.dg.fwd_decl.writer; | |
| 2883 | try fwd.print("static zig_{s} ", .{@tagName(key)}); | |
| 2884 | try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{ | |
| 2885 | .fmt_ctype_pool_string = fn_name, | |
| 2886 | }); | |
| 2887 | try fwd.writeAll(";\n"); | |
| 2162 | const fn_val = zcu.navValue(fn_nav); | |
| 2888 | 2163 | |
| 2889 | try w.print("zig_{s} ", .{@tagName(key)}); | |
| 2890 | try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{ | |
| 2891 | .fmt_ctype_pool_string = fn_name, | |
| 2892 | }); | |
| 2893 | try w.writeAll(" {"); | |
| 2894 | o.indent(); | |
| 2895 | try o.newline(); | |
| 2896 | try w.writeAll("return "); | |
| 2897 | try o.dg.renderNavName(w, fn_nav_index); | |
| 2898 | try w.writeByte('('); | |
| 2899 | for (0..fn_info.param_ctypes.len) |arg| { | |
| 2900 | if (arg > 0) try w.writeAll(", "); | |
| 2901 | try w.print("a{d}", .{arg}); | |
| 2902 | } | |
| 2903 | try w.writeAll(");"); | |
| 2904 | try o.newline(); | |
| 2905 | try o.outdent(); | |
| 2906 | try w.writeByte('}'); | |
| 2907 | try o.newline(); | |
| 2908 | }, | |
| 2164 | try w.print("static zig_{t} ", .{kind}); | |
| 2165 | try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) { | |
| 2166 | .never_tail => .{ .nav_never_tail = fn_nav }, | |
| 2167 | .never_inline => .{ .nav_never_inline = fn_nav }, | |
| 2168 | }); | |
| 2169 | try w.writeAll(" {\n return "); | |
| 2170 | try renderNavName(w, fn_nav, ip); | |
| 2171 | try w.writeByte('('); | |
| 2172 | { | |
| 2173 | const func_type = ip.indexToKey(fn_val.typeOf(zcu).toIntern()).func_type; | |
| 2174 | var c_param_index: u32 = 0; | |
| 2175 | for (func_type.param_types.get(ip)) |param_ty_ip| { | |
| 2176 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 2177 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 2178 | if (c_param_index != 0) try w.writeAll(", "); | |
| 2179 | try w.print("a{d}", .{c_param_index}); | |
| 2180 | c_param_index += 1; | |
| 2181 | } | |
| 2909 | 2182 | } |
| 2183 | try w.writeAll(");\n}\n"); | |
| 2910 | 2184 | } |
| 2911 | 2185 | |
| 2912 | 2186 | pub fn generate( |
| ... | ... | @@ -2925,110 +2199,109 @@ pub fn generate( |
| 2925 | 2199 | |
| 2926 | 2200 | const func = zcu.funcInfo(func_index); |
| 2927 | 2201 | |
| 2202 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 2203 | defer arena.deinit(); | |
| 2204 | ||
| 2928 | 2205 | var function: Function = .{ |
| 2929 | 2206 | .value_map = .init(gpa), |
| 2930 | 2207 | .air = air.*, |
| 2931 | 2208 | .liveness = liveness.*.?, |
| 2932 | 2209 | .func_index = func_index, |
| 2933 | .object = .{ | |
| 2934 | .dg = .{ | |
| 2935 | .gpa = gpa, | |
| 2936 | .pt = pt, | |
| 2937 | .mod = zcu.navFileScope(func.owner_nav).mod.?, | |
| 2938 | .error_msg = null, | |
| 2939 | .pass = .{ .nav = func.owner_nav }, | |
| 2940 | .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked, | |
| 2941 | .expected_block = null, | |
| 2942 | .fwd_decl = .init(gpa), | |
| 2943 | .ctype_pool = .empty, | |
| 2944 | .scratch = .empty, | |
| 2945 | .uavs = .empty, | |
| 2946 | }, | |
| 2947 | .code_header = .init(gpa), | |
| 2948 | .code = .init(gpa), | |
| 2949 | .indent_counter = 0, | |
| 2210 | .dg = .{ | |
| 2211 | .gpa = gpa, | |
| 2212 | .arena = arena.allocator(), | |
| 2213 | .pt = pt, | |
| 2214 | .mod = zcu.navFileScope(func.owner_nav).mod.?, | |
| 2215 | .error_msg = null, | |
| 2216 | .owner_nav = func.owner_nav.toOptional(), | |
| 2217 | .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked, | |
| 2218 | .expected_block = null, | |
| 2219 | .ctype_deps = .empty, | |
| 2220 | .uavs = .empty, | |
| 2950 | 2221 | }, |
| 2951 | .lazy_fns = .empty, | |
| 2222 | .code = .init(gpa), | |
| 2223 | .indent_counter = 0, | |
| 2224 | .need_tag_name_funcs = .empty, | |
| 2225 | .need_never_tail_funcs = .empty, | |
| 2226 | .need_never_inline_funcs = .empty, | |
| 2952 | 2227 | }; |
| 2953 | 2228 | defer { |
| 2954 | function.object.code_header.deinit(); | |
| 2955 | function.object.code.deinit(); | |
| 2956 | function.object.dg.fwd_decl.deinit(); | |
| 2957 | function.object.dg.ctype_pool.deinit(gpa); | |
| 2958 | function.object.dg.scratch.deinit(gpa); | |
| 2959 | function.object.dg.uavs.deinit(gpa); | |
| 2229 | function.code.deinit(); | |
| 2230 | function.dg.ctype_deps.deinit(gpa); | |
| 2231 | function.dg.uavs.deinit(gpa); | |
| 2960 | 2232 | function.deinit(); |
| 2961 | 2233 | } |
| 2962 | try function.object.dg.ctype_pool.init(gpa); | |
| 2963 | 2234 | |
| 2964 | genFunc(&function) catch |err| switch (err) { | |
| 2965 | error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?), | |
| 2966 | error.OutOfMemory => return error.OutOfMemory, | |
| 2235 | var fwd_decl: Writer.Allocating = .init(gpa); | |
| 2236 | defer fwd_decl.deinit(); | |
| 2237 | ||
| 2238 | var code_header: Writer.Allocating = .init(gpa); | |
| 2239 | defer code_header.deinit(); | |
| 2240 | ||
| 2241 | genFunc(&function, &fwd_decl.writer, &code_header.writer) catch |err| switch (err) { | |
| 2242 | error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.dg.error_msg.?), | |
| 2967 | 2243 | error.WriteFailed => return error.OutOfMemory, |
| 2244 | error.OutOfMemory => |e| return e, | |
| 2968 | 2245 | }; |
| 2969 | 2246 | |
| 2970 | 2247 | var mir: Mir = .{ |
| 2971 | .uavs = .empty, | |
| 2972 | .code = &.{}, | |
| 2973 | .code_header = &.{}, | |
| 2974 | 2248 | .fwd_decl = &.{}, |
| 2975 | .ctype_pool = .empty, | |
| 2976 | .lazy_fns = .empty, | |
| 2249 | .code_header = &.{}, | |
| 2250 | .code = &.{}, | |
| 2251 | .ctype_deps = function.dg.ctype_deps.move(), | |
| 2252 | .need_uavs = function.dg.uavs.move(), | |
| 2253 | .need_tag_name_funcs = function.need_tag_name_funcs.move(), | |
| 2254 | .need_never_tail_funcs = function.need_never_tail_funcs.move(), | |
| 2255 | .need_never_inline_funcs = function.need_never_inline_funcs.move(), | |
| 2977 | 2256 | }; |
| 2978 | 2257 | errdefer mir.deinit(gpa); |
| 2979 | mir.uavs = function.object.dg.uavs.move(); | |
| 2980 | mir.code_header = try function.object.code_header.toOwnedSlice(); | |
| 2981 | mir.code = try function.object.code.toOwnedSlice(); | |
| 2982 | mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice(); | |
| 2983 | mir.ctype_pool = function.object.dg.ctype_pool.move(); | |
| 2984 | mir.lazy_fns = function.lazy_fns.move(); | |
| 2258 | mir.fwd_decl = try fwd_decl.toOwnedSlice(); | |
| 2259 | mir.code_header = try code_header.toOwnedSlice(); | |
| 2260 | mir.code = try function.code.toOwnedSlice(); | |
| 2985 | 2261 | return mir; |
| 2986 | 2262 | } |
| 2987 | 2263 | |
| 2988 | pub fn genFunc(f: *Function) Error!void { | |
| 2264 | pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) Error!void { | |
| 2989 | 2265 | const tracy = trace(@src()); |
| 2990 | 2266 | defer tracy.end(); |
| 2991 | 2267 | |
| 2992 | const o = &f.object; | |
| 2993 | const zcu = o.dg.pt.zcu; | |
| 2268 | const zcu = f.dg.pt.zcu; | |
| 2994 | 2269 | const ip = &zcu.intern_pool; |
| 2995 | const gpa = o.dg.gpa; | |
| 2996 | const nav_index = o.dg.pass.nav; | |
| 2270 | const gpa = f.dg.gpa; | |
| 2271 | const nav_index = f.dg.owner_nav.unwrap().?; | |
| 2997 | 2272 | const nav_val = zcu.navValue(nav_index); |
| 2998 | 2273 | const nav = ip.getNav(nav_index); |
| 2999 | 2274 | |
| 3000 | const fwd = &o.dg.fwd_decl.writer; | |
| 3001 | try fwd.writeAll("static "); | |
| 3002 | try o.dg.renderFunctionSignature( | |
| 3003 | fwd, | |
| 2275 | try fwd_decl_writer.writeAll("static "); | |
| 2276 | try f.dg.renderFunctionSignature( | |
| 2277 | fwd_decl_writer, | |
| 3004 | 2278 | nav_val, |
| 3005 | 2279 | nav.status.fully_resolved.alignment, |
| 3006 | .forward, | |
| 2280 | .forward_decl, | |
| 3007 | 2281 | .{ .nav = nav_index }, |
| 3008 | 2282 | ); |
| 3009 | try fwd.writeAll(";\n"); | |
| 2283 | try fwd_decl_writer.writeAll(";\n"); | |
| 3010 | 2284 | |
| 3011 | const ch = &o.code_header.writer; | |
| 3012 | 2285 | if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s| |
| 3013 | try ch.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)}); | |
| 3014 | try o.dg.renderFunctionSignature( | |
| 3015 | ch, | |
| 2286 | try header_writer.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)}); | |
| 2287 | try f.dg.renderFunctionSignature( | |
| 2288 | header_writer, | |
| 3016 | 2289 | nav_val, |
| 3017 | 2290 | .none, |
| 3018 | .complete, | |
| 2291 | .definition, | |
| 3019 | 2292 | .{ .nav = nav_index }, |
| 3020 | 2293 | ); |
| 3021 | try ch.writeAll(" {\n "); | |
| 2294 | try header_writer.writeAll(" {\n "); | |
| 3022 | 2295 | |
| 3023 | 2296 | f.free_locals_map.clearRetainingCapacity(); |
| 3024 | 2297 | |
| 3025 | 2298 | const main_body = f.air.getMainBody(); |
| 3026 | o.indent(); | |
| 2299 | f.indent(); | |
| 3027 | 2300 | try genBodyResolveState(f, undefined, &.{}, main_body, true); |
| 3028 | try o.outdent(); | |
| 3029 | try o.code.writer.writeByte('}'); | |
| 3030 | try o.newline(); | |
| 3031 | if (o.dg.expected_block) |_| | |
| 2301 | try f.outdent(); | |
| 2302 | try f.code.writer.writeByte('}'); | |
| 2303 | try f.newline(); | |
| 2304 | if (f.dg.expected_block) |_| | |
| 3032 | 2305 | return f.fail("runtime code not allowed in naked function", .{}); |
| 3033 | 2306 | |
| 3034 | 2307 | // Take advantage of the free_locals map to bucket locals per type. All |
| ... | ... | @@ -3042,155 +2315,204 @@ pub fn genFunc(f: *Function) Error!void { |
| 3042 | 2315 | if (!should_emit) continue; |
| 3043 | 2316 | const local = f.locals.items[local_index]; |
| 3044 | 2317 | log.debug("inserting local {d} into free_locals", .{local_index}); |
| 3045 | const gop = try free_locals.getOrPut(gpa, local.getType()); | |
| 2318 | const gop = try free_locals.getOrPut(gpa, local); | |
| 3046 | 2319 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 3047 | 2320 | try gop.value_ptr.putNoClobber(gpa, local_index, {}); |
| 3048 | 2321 | } |
| 3049 | 2322 | |
| 3050 | 2323 | const SortContext = struct { |
| 2324 | zcu: *const Zcu, | |
| 3051 | 2325 | keys: []const LocalType, |
| 3052 | 2326 | |
| 3053 | 2327 | pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { |
| 3054 | const lhs_ty = ctx.keys[lhs_index]; | |
| 3055 | const rhs_ty = ctx.keys[rhs_index]; | |
| 3056 | return lhs_ty.alignas.order(rhs_ty.alignas).compare(.gt); | |
| 2328 | const lhs = ctx.keys[lhs_index]; | |
| 2329 | const rhs = ctx.keys[rhs_index]; | |
| 2330 | const lhs_align = switch (lhs.alignment) { | |
| 2331 | .none => lhs.type.abiAlignment(ctx.zcu), | |
| 2332 | else => |a| a, | |
| 2333 | }; | |
| 2334 | const rhs_align = switch (rhs.alignment) { | |
| 2335 | .none => rhs.type.abiAlignment(ctx.zcu), | |
| 2336 | else => |a| a, | |
| 2337 | }; | |
| 2338 | return Alignment.compareStrict(lhs_align, .gt, rhs_align); | |
| 3057 | 2339 | } |
| 3058 | 2340 | }; |
| 3059 | free_locals.sort(SortContext{ .keys = free_locals.keys() }); | |
| 2341 | free_locals.sort(SortContext{ | |
| 2342 | .zcu = zcu, | |
| 2343 | .keys = free_locals.keys(), | |
| 2344 | }); | |
| 3060 | 2345 | |
| 3061 | 2346 | for (free_locals.values()) |list| { |
| 3062 | 2347 | for (list.keys()) |local_index| { |
| 3063 | 2348 | const local = f.locals.items[local_index]; |
| 3064 | try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas); | |
| 3065 | try ch.writeAll(";\n "); | |
| 2349 | try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment); | |
| 2350 | try header_writer.writeAll(";\n "); | |
| 3066 | 2351 | } |
| 3067 | 2352 | } |
| 3068 | 2353 | } |
| 3069 | 2354 | |
| 3070 | pub fn genDecl(o: *Object) Error!void { | |
| 2355 | pub fn genDecl(dg: *DeclGen, w: *Writer) Error!void { | |
| 3071 | 2356 | const tracy = trace(@src()); |
| 3072 | 2357 | defer tracy.end(); |
| 3073 | 2358 | |
| 3074 | const pt = o.dg.pt; | |
| 2359 | const pt = dg.pt; | |
| 3075 | 2360 | const zcu = pt.zcu; |
| 3076 | 2361 | const ip = &zcu.intern_pool; |
| 3077 | const nav = ip.getNav(o.dg.pass.nav); | |
| 2362 | const nav = ip.getNav(dg.owner_nav.unwrap().?); | |
| 3078 | 2363 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); |
| 3079 | 2364 | |
| 3080 | if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return; | |
| 3081 | switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 3082 | .@"extern" => |@"extern"| { | |
| 3083 | if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ | |
| 3084 | .is_const = @"extern".is_const, | |
| 3085 | .is_threadlocal = @"extern".is_threadlocal, | |
| 3086 | .linkage = @"extern".linkage, | |
| 3087 | .visibility = @"extern".visibility, | |
| 3088 | }); | |
| 2365 | const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 2366 | else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) }, | |
| 2367 | .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) }, | |
| 2368 | .@"extern" => return, | |
| 2369 | }; | |
| 3089 | 2370 | |
| 3090 | const fwd = &o.dg.fwd_decl.writer; | |
| 3091 | try fwd.writeAll("zig_extern "); | |
| 3092 | try o.dg.renderFunctionSignature( | |
| 3093 | fwd, | |
| 3094 | Value.fromInterned(nav.status.fully_resolved.val), | |
| 3095 | nav.status.fully_resolved.alignment, | |
| 3096 | .forward, | |
| 3097 | .{ .@"export" = .{ | |
| 3098 | .main_name = nav.name, | |
| 3099 | .extern_name = nav.name, | |
| 3100 | } }, | |
| 3101 | ); | |
| 3102 | try fwd.writeAll(";\n"); | |
| 3103 | }, | |
| 3104 | .variable => |variable| { | |
| 3105 | try o.dg.renderFwdDecl(o.dg.pass.nav, .{ | |
| 3106 | .is_const = false, | |
| 3107 | .is_threadlocal = variable.is_threadlocal, | |
| 3108 | .linkage = .internal, | |
| 3109 | .visibility = .default, | |
| 3110 | }); | |
| 3111 | const w = &o.code.writer; | |
| 3112 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); | |
| 3113 | if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| | |
| 3114 | try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)}); | |
| 3115 | try o.dg.renderTypeAndName( | |
| 3116 | w, | |
| 3117 | nav_ty, | |
| 3118 | .{ .nav = o.dg.pass.nav }, | |
| 3119 | .{}, | |
| 3120 | nav.status.fully_resolved.alignment, | |
| 3121 | .complete, | |
| 3122 | ); | |
| 3123 | try w.writeAll(" = "); | |
| 3124 | try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); | |
| 3125 | try w.writeByte(';'); | |
| 3126 | try o.newline(); | |
| 3127 | }, | |
| 3128 | else => try genDeclValue( | |
| 3129 | o, | |
| 3130 | Value.fromInterned(nav.status.fully_resolved.val), | |
| 3131 | .{ .nav = o.dg.pass.nav }, | |
| 3132 | nav.status.fully_resolved.alignment, | |
| 3133 | nav.status.fully_resolved.@"linksection", | |
| 3134 | ), | |
| 2371 | if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s| { | |
| 2372 | try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)}); | |
| 3135 | 2373 | } |
| 2374 | ||
| 2375 | // We don't bother underaligning---it's unnecessary and hurts compatibility. | |
| 2376 | const a = nav.status.fully_resolved.alignment; | |
| 2377 | if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) { | |
| 2378 | try w.print("zig_align({d}) ", .{a.toByteUnits().?}); | |
| 2379 | } | |
| 2380 | ||
| 2381 | try genDeclValue(dg, w, .{ | |
| 2382 | .name = .{ .nav = dg.owner_nav.unwrap().? }, | |
| 2383 | .@"const" = is_const, | |
| 2384 | .@"threadlocal" = is_threadlocal, | |
| 2385 | .init_val = init_val, | |
| 2386 | }); | |
| 3136 | 2387 | } |
| 2388 | pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { | |
| 2389 | const tracy = trace(@src()); | |
| 2390 | defer tracy.end(); | |
| 3137 | 2391 | |
| 3138 | pub fn genDeclValue( | |
| 3139 | o: *Object, | |
| 3140 | val: Value, | |
| 3141 | decl_c_value: CValue, | |
| 3142 | alignment: Alignment, | |
| 3143 | @"linksection": InternPool.OptionalNullTerminatedString, | |
| 3144 | ) Error!void { | |
| 3145 | const zcu = o.dg.pt.zcu; | |
| 3146 | const ty = val.typeOf(zcu); | |
| 2392 | const pt = dg.pt; | |
| 2393 | const zcu = pt.zcu; | |
| 2394 | const ip = &zcu.intern_pool; | |
| 2395 | const nav = ip.getNav(dg.owner_nav.unwrap().?); | |
| 2396 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 3147 | 2397 | |
| 3148 | const fwd = &o.dg.fwd_decl.writer; | |
| 3149 | try fwd.writeAll("static "); | |
| 3150 | try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete); | |
| 3151 | try fwd.writeAll(";\n"); | |
| 2398 | const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 2399 | else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) }, | |
| 2400 | .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) }, | |
| 3152 | 2401 | |
| 3153 | const w = &o.code.writer; | |
| 3154 | if (@"linksection".toSlice(&zcu.intern_pool)) |s| | |
| 3155 | try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)}); | |
| 3156 | try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); | |
| 2402 | .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { | |
| 2403 | .@"fn" => { | |
| 2404 | try w.writeAll("zig_extern "); | |
| 2405 | try dg.renderFunctionSignature( | |
| 2406 | w, | |
| 2407 | Value.fromInterned(nav.status.fully_resolved.val), | |
| 2408 | nav.status.fully_resolved.alignment, | |
| 2409 | .forward_decl, | |
| 2410 | .{ .@"export" = .{ | |
| 2411 | .main_name = nav.name, | |
| 2412 | .extern_name = nav.name, | |
| 2413 | } }, | |
| 2414 | ); | |
| 2415 | try w.writeAll(";\n"); | |
| 2416 | return; | |
| 2417 | }, | |
| 2418 | else => { | |
| 2419 | switch (@"extern".linkage) { | |
| 2420 | .internal => try w.writeAll("static "), | |
| 2421 | .strong => try w.print("zig_extern zig_visibility({t}) ", .{@"extern".visibility}), | |
| 2422 | .weak => try w.print("zig_extern zig_weak_linkage zig_visibility({t}) ", .{@"extern".visibility}), | |
| 2423 | .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), | |
| 2424 | } | |
| 2425 | if (@"extern".is_threadlocal and !dg.mod.single_threaded) { | |
| 2426 | try w.writeAll("zig_threadlocal "); | |
| 2427 | } | |
| 2428 | try dg.renderTypeAndName( | |
| 2429 | w, | |
| 2430 | .fromInterned(nav.typeOf(ip)), | |
| 2431 | .{ .nav = dg.owner_nav.unwrap().? }, | |
| 2432 | .{ .@"const" = @"extern".is_const }, | |
| 2433 | nav.getAlignment(), | |
| 2434 | ); | |
| 2435 | try w.writeAll(";\n"); | |
| 2436 | return; | |
| 2437 | }, | |
| 2438 | }, | |
| 2439 | }; | |
| 2440 | ||
| 2441 | // We don't bother underaligning---it's unnecessary and hurts compatibility. | |
| 2442 | const a = nav.status.fully_resolved.alignment; | |
| 2443 | if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) { | |
| 2444 | try w.print("zig_align({d}) ", .{a.toByteUnits().?}); | |
| 2445 | } | |
| 2446 | ||
| 2447 | try genDeclValueFwd(dg, w, .{ | |
| 2448 | .name = .{ .nav = dg.owner_nav.unwrap().? }, | |
| 2449 | .@"const" = is_const, | |
| 2450 | .@"threadlocal" = is_threadlocal, | |
| 2451 | .init_val = init_val, | |
| 2452 | }); | |
| 2453 | } | |
| 2454 | pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct { | |
| 2455 | name: CValue, | |
| 2456 | @"const": bool, | |
| 2457 | @"threadlocal": bool, | |
| 2458 | init_val: Value, | |
| 2459 | }) Error!void { | |
| 2460 | const zcu = dg.pt.zcu; | |
| 2461 | const ty = options.init_val.typeOf(zcu); | |
| 2462 | if (options.@"threadlocal" and !dg.mod.single_threaded) { | |
| 2463 | try w.writeAll("zig_threadlocal "); | |
| 2464 | } | |
| 2465 | try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); | |
| 3157 | 2466 | try w.writeAll(" = "); |
| 3158 | try o.dg.renderValue(w, val, .StaticInitializer); | |
| 3159 | try w.writeByte(';'); | |
| 3160 | try o.newline(); | |
| 2467 | try dg.renderValue(w, options.init_val, .static_initializer); | |
| 2468 | try w.writeAll(";\n"); | |
| 2469 | } | |
| 2470 | pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct { | |
| 2471 | name: CValue, | |
| 2472 | @"const": bool, | |
| 2473 | @"threadlocal": bool, | |
| 2474 | init_val: Value, | |
| 2475 | }) Error!void { | |
| 2476 | const zcu = dg.pt.zcu; | |
| 2477 | const ty = options.init_val.typeOf(zcu); | |
| 2478 | try w.writeAll("static "); | |
| 2479 | if (options.@"threadlocal" and !dg.mod.single_threaded) { | |
| 2480 | try w.writeAll("zig_threadlocal "); | |
| 2481 | } | |
| 2482 | try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); | |
| 2483 | try w.writeAll(";\n"); | |
| 3161 | 2484 | } |
| 3162 | 2485 | |
| 3163 | pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void { | |
| 2486 | pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void { | |
| 3164 | 2487 | const zcu = dg.pt.zcu; |
| 3165 | 2488 | const ip = &zcu.intern_pool; |
| 3166 | const fwd = &dg.fwd_decl.writer; | |
| 3167 | 2489 | |
| 3168 | 2490 | const main_name = export_indices[0].ptr(zcu).opts.name; |
| 3169 | try fwd.writeAll("#define "); | |
| 2491 | try w.writeAll("#define "); | |
| 3170 | 2492 | switch (exported) { |
| 3171 | .nav => |nav| try dg.renderNavName(fwd, nav), | |
| 3172 | .uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)), | |
| 2493 | .nav => |nav| try renderNavName(w, nav, ip), | |
| 2494 | .uav => |uav| try renderUavName(w, Value.fromInterned(uav)), | |
| 3173 | 2495 | } |
| 3174 | try fwd.writeByte(' '); | |
| 3175 | try fwd.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))}); | |
| 3176 | try fwd.writeByte('\n'); | |
| 2496 | try w.writeByte(' '); | |
| 2497 | try w.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))}); | |
| 2498 | try w.writeByte('\n'); | |
| 3177 | 2499 | |
| 3178 | 2500 | const exported_val = exported.getValue(zcu); |
| 3179 | 2501 | if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { |
| 3180 | 2502 | const @"export" = export_index.ptr(zcu); |
| 3181 | try fwd.writeAll("zig_extern "); | |
| 3182 | if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn "); | |
| 2503 | try w.writeAll("zig_extern "); | |
| 2504 | if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn "); | |
| 3183 | 2505 | try dg.renderFunctionSignature( |
| 3184 | fwd, | |
| 2506 | w, | |
| 3185 | 2507 | exported.getValue(zcu), |
| 3186 | 2508 | exported.getAlign(zcu), |
| 3187 | .forward, | |
| 2509 | .forward_decl, | |
| 3188 | 2510 | .{ .@"export" = .{ |
| 3189 | 2511 | .main_name = main_name, |
| 3190 | 2512 | .extern_name = @"export".opts.name, |
| 3191 | 2513 | } }, |
| 3192 | 2514 | ); |
| 3193 | try fwd.writeAll(";\n"); | |
| 2515 | try w.writeAll(";\n"); | |
| 3194 | 2516 | }; |
| 3195 | 2517 | const is_const = switch (ip.indexToKey(exported_val.toIntern())) { |
| 3196 | 2518 | .func => unreachable, |
| ... | ... | @@ -3200,39 +2522,38 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const |
| 3200 | 2522 | }; |
| 3201 | 2523 | for (export_indices) |export_index| { |
| 3202 | 2524 | const @"export" = export_index.ptr(zcu); |
| 3203 | try fwd.writeAll("zig_extern "); | |
| 3204 | if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage "); | |
| 3205 | if (@"export".opts.section.toSlice(ip)) |s| try fwd.print("zig_linksection({f}) ", .{ | |
| 2525 | try w.writeAll("zig_extern "); | |
| 2526 | if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage "); | |
| 2527 | if (@"export".opts.section.toSlice(ip)) |s| try w.print("zig_linksection({f}) ", .{ | |
| 3206 | 2528 | fmtStringLiteral(s, null), |
| 3207 | 2529 | }); |
| 3208 | 2530 | const extern_name = @"export".opts.name.toSlice(ip); |
| 3209 | 2531 | const is_mangled = isMangledIdent(extern_name, true); |
| 3210 | 2532 | const is_export = @"export".opts.name != main_name; |
| 3211 | 2533 | try dg.renderTypeAndName( |
| 3212 | fwd, | |
| 2534 | w, | |
| 3213 | 2535 | exported.getValue(zcu).typeOf(zcu), |
| 3214 | 2536 | .{ .identifier = extern_name }, |
| 3215 | CQualifiers.init(.{ .@"const" = is_const }), | |
| 2537 | .{ .@"const" = is_const }, | |
| 3216 | 2538 | exported.getAlign(zcu), |
| 3217 | .complete, | |
| 3218 | 2539 | ); |
| 3219 | 2540 | if (is_mangled and is_export) { |
| 3220 | try fwd.print(" zig_mangled_export({f}, {f}, {f})", .{ | |
| 2541 | try w.print(" zig_mangled_export({f}, {f}, {f})", .{ | |
| 3221 | 2542 | fmtIdentSolo(extern_name), |
| 3222 | 2543 | fmtStringLiteral(extern_name, null), |
| 3223 | 2544 | fmtStringLiteral(main_name.toSlice(ip), null), |
| 3224 | 2545 | }); |
| 3225 | 2546 | } else if (is_mangled) { |
| 3226 | try fwd.print(" zig_mangled({f}, {f})", .{ | |
| 2547 | try w.print(" zig_mangled({f}, {f})", .{ | |
| 3227 | 2548 | fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null), |
| 3228 | 2549 | }); |
| 3229 | 2550 | } else if (is_export) { |
| 3230 | try fwd.print(" zig_export({f}, {f})", .{ | |
| 2551 | try w.print(" zig_export({f}, {f})", .{ | |
| 3231 | 2552 | fmtStringLiteral(main_name.toSlice(ip), null), |
| 3232 | 2553 | fmtStringLiteral(extern_name, null), |
| 3233 | 2554 | }); |
| 3234 | 2555 | } |
| 3235 | try fwd.writeAll(";\n"); | |
| 2556 | try w.writeAll(";\n"); | |
| 3236 | 2557 | } |
| 3237 | 2558 | } |
| 3238 | 2559 | |
| ... | ... | @@ -3241,15 +2562,15 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const |
| 3241 | 2562 | /// have been added to `free_locals_map`. For a version of this function that restores this state, |
| 3242 | 2563 | /// see `genBodyResolveState`. |
| 3243 | 2564 | fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3244 | const w = &f.object.code.writer; | |
| 2565 | const w = &f.code.writer; | |
| 3245 | 2566 | if (body.len == 0) { |
| 3246 | 2567 | try w.writeAll("{}"); |
| 3247 | 2568 | } else { |
| 3248 | 2569 | try w.writeByte('{'); |
| 3249 | f.object.indent(); | |
| 3250 | try f.object.newline(); | |
| 2570 | f.indent(); | |
| 2571 | try f.newline(); | |
| 3251 | 2572 | try genBodyInner(f, body); |
| 3252 | try f.object.outdent(); | |
| 2573 | try f.outdent(); | |
| 3253 | 2574 | try w.writeByte('}'); |
| 3254 | 2575 | } |
| 3255 | 2576 | } |
| ... | ... | @@ -3263,13 +2584,13 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3263 | 2584 | fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) Error!void { |
| 3264 | 2585 | if (body.len == 0) { |
| 3265 | 2586 | // Don't go to the expense of cloning everything! |
| 3266 | if (!inner) try f.object.code.writer.writeAll("{}"); | |
| 2587 | if (!inner) try f.code.writer.writeAll("{}"); | |
| 3267 | 2588 | return; |
| 3268 | 2589 | } |
| 3269 | 2590 | |
| 3270 | 2591 | // TODO: we can probably avoid the copies in some other common cases too. |
| 3271 | 2592 | |
| 3272 | const gpa = f.object.dg.gpa; | |
| 2593 | const gpa = f.dg.gpa; | |
| 3273 | 2594 | |
| 3274 | 2595 | // Save the original value_map and free_locals_map so that we can restore them after the body. |
| 3275 | 2596 | var old_value_map = try f.value_map.clone(); |
| ... | ... | @@ -3310,13 +2631,13 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con |
| 3310 | 2631 | } |
| 3311 | 2632 | |
| 3312 | 2633 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3313 | const zcu = f.object.dg.pt.zcu; | |
| 2634 | const zcu = f.dg.pt.zcu; | |
| 3314 | 2635 | const ip = &zcu.intern_pool; |
| 3315 | 2636 | const air_tags = f.air.instructions.items(.tag); |
| 3316 | 2637 | const air_datas = f.air.instructions.items(.data); |
| 3317 | 2638 | |
| 3318 | 2639 | for (body) |inst| { |
| 3319 | if (f.object.dg.expected_block) |_| | |
| 2640 | if (f.dg.expected_block) |_| | |
| 3320 | 2641 | return f.fail("runtime code not allowed in naked function", .{}); |
| 3321 | 2642 | if (f.liveness.isUnused(inst) and !f.air.mustLower(inst, ip)) |
| 3322 | 2643 | continue; |
| ... | ... | @@ -3585,8 +2906,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3585 | 2906 | .ret => return airRet(f, inst, false), |
| 3586 | 2907 | .ret_safe => return airRet(f, inst, false), // TODO |
| 3587 | 2908 | .ret_load => return airRet(f, inst, true), |
| 3588 | .trap => return airTrap(f, &f.object.code.writer), | |
| 3589 | .unreach => return airUnreach(&f.object), | |
| 2909 | .trap => return airTrap(f), | |
| 2910 | .unreach => return airUnreach(f), | |
| 3590 | 2911 | |
| 3591 | 2912 | // Instructions which may be `noreturn`. |
| 3592 | 2913 | .block => res: { |
| ... | ... | @@ -3629,177 +2950,159 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3629 | 2950 | const operand = try f.resolveInst(ty_op.operand); |
| 3630 | 2951 | try reap(f, inst, &.{ty_op.operand}); |
| 3631 | 2952 | |
| 3632 | const w = &f.object.code.writer; | |
| 2953 | const w = &f.code.writer; | |
| 3633 | 2954 | const local = try f.allocLocal(inst, inst_ty); |
| 3634 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3635 | try f.writeCValue(w, local, .Other); | |
| 3636 | try a.assign(f, w); | |
| 2955 | try f.writeCValue(w, local, .other); | |
| 2956 | try w.writeAll(" = "); | |
| 3637 | 2957 | if (is_ptr) { |
| 3638 | 2958 | try w.writeByte('&'); |
| 3639 | 2959 | try f.writeCValueDerefMember(w, operand, .{ .identifier = field_name }); |
| 3640 | 2960 | } else try f.writeCValueMember(w, operand, .{ .identifier = field_name }); |
| 3641 | try a.end(f, w); | |
| 2961 | try w.writeByte(';'); | |
| 2962 | try f.newline(); | |
| 3642 | 2963 | return local; |
| 3643 | 2964 | } |
| 3644 | 2965 | |
| 3645 | 2966 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3646 | const zcu = f.object.dg.pt.zcu; | |
| 2967 | const zcu = f.dg.pt.zcu; | |
| 3647 | 2968 | const inst_ty = f.typeOfIndex(inst); |
| 3648 | 2969 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3649 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3650 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | |
| 3651 | return .none; | |
| 3652 | } | |
| 2970 | assert(inst_ty.hasRuntimeBits(zcu)); | |
| 3653 | 2971 | |
| 3654 | 2972 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3655 | 2973 | const index = try f.resolveInst(bin_op.rhs); |
| 3656 | 2974 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3657 | 2975 | |
| 3658 | const w = &f.object.code.writer; | |
| 2976 | const w = &f.code.writer; | |
| 3659 | 2977 | const local = try f.allocLocal(inst, inst_ty); |
| 3660 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3661 | try f.writeCValue(w, local, .Other); | |
| 3662 | try a.assign(f, w); | |
| 3663 | try f.writeCValue(w, ptr, .Other); | |
| 2978 | try f.writeCValue(w, local, .other); | |
| 2979 | try w.writeAll(" = "); | |
| 2980 | switch (f.typeOf(bin_op.lhs).ptrSize(zcu)) { | |
| 2981 | .one => try f.writeCValueDerefMember(w, ptr, .{ .identifier = "array" }), | |
| 2982 | .many, .c => try f.writeCValue(w, ptr, .other), | |
| 2983 | .slice => unreachable, | |
| 2984 | } | |
| 3664 | 2985 | try w.writeByte('['); |
| 3665 | try f.writeCValue(w, index, .Other); | |
| 3666 | try w.writeByte(']'); | |
| 3667 | try a.end(f, w); | |
| 2986 | try f.writeCValue(w, index, .other); | |
| 2987 | try w.writeAll("];"); | |
| 2988 | try f.newline(); | |
| 3668 | 2989 | return local; |
| 3669 | 2990 | } |
| 3670 | 2991 | |
| 3671 | 2992 | fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3672 | const pt = f.object.dg.pt; | |
| 2993 | const pt = f.dg.pt; | |
| 3673 | 2994 | const zcu = pt.zcu; |
| 3674 | 2995 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3675 | 2996 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3676 | 2997 | |
| 3677 | 2998 | const inst_ty = f.typeOfIndex(inst); |
| 3678 | 2999 | const ptr_ty = f.typeOf(bin_op.lhs); |
| 3679 | const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu); | |
| 3000 | assert(ptr_ty.indexableElem(zcu).hasRuntimeBits(zcu)); | |
| 3680 | 3001 | |
| 3681 | 3002 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3682 | 3003 | const index = try f.resolveInst(bin_op.rhs); |
| 3683 | 3004 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3684 | 3005 | |
| 3685 | const w = &f.object.code.writer; | |
| 3006 | const w = &f.code.writer; | |
| 3686 | 3007 | const local = try f.allocLocal(inst, inst_ty); |
| 3687 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3688 | try f.writeCValue(w, local, .Other); | |
| 3689 | try a.assign(f, w); | |
| 3690 | try w.writeByte('('); | |
| 3691 | try f.renderType(w, inst_ty); | |
| 3692 | try w.writeByte(')'); | |
| 3693 | if (elem_has_bits) try w.writeByte('&'); | |
| 3694 | if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) { | |
| 3695 | // It's a pointer to an array, so we need to de-reference. | |
| 3696 | try f.writeCValueDeref(w, ptr); | |
| 3697 | } else try f.writeCValue(w, ptr, .Other); | |
| 3698 | if (elem_has_bits) { | |
| 3699 | try w.writeByte('['); | |
| 3700 | try f.writeCValue(w, index, .Other); | |
| 3701 | try w.writeByte(']'); | |
| 3008 | try f.writeCValue(w, local, .other); | |
| 3009 | try w.writeAll(" = "); | |
| 3010 | try w.writeByte('&'); | |
| 3011 | if (ptr_ty.ptrSize(zcu) == .one) { | |
| 3012 | // `*[n]T` was turned into a pointer to `struct { T array[n]; }` | |
| 3013 | try f.writeCValueDerefMember(w, ptr, .{ .identifier = "array" }); | |
| 3014 | } else { | |
| 3015 | try f.writeCValue(w, ptr, .other); | |
| 3702 | 3016 | } |
| 3703 | try a.end(f, w); | |
| 3017 | try w.writeByte('['); | |
| 3018 | try f.writeCValue(w, index, .other); | |
| 3019 | try w.writeAll("];"); | |
| 3020 | try f.newline(); | |
| 3704 | 3021 | return local; |
| 3705 | 3022 | } |
| 3706 | 3023 | |
| 3707 | 3024 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3708 | const zcu = f.object.dg.pt.zcu; | |
| 3025 | const zcu = f.dg.pt.zcu; | |
| 3709 | 3026 | const inst_ty = f.typeOfIndex(inst); |
| 3710 | 3027 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3711 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3712 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | |
| 3713 | return .none; | |
| 3714 | } | |
| 3028 | assert(inst_ty.hasRuntimeBits(zcu)); | |
| 3715 | 3029 | |
| 3716 | 3030 | const slice = try f.resolveInst(bin_op.lhs); |
| 3717 | 3031 | const index = try f.resolveInst(bin_op.rhs); |
| 3718 | 3032 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3719 | 3033 | |
| 3720 | const w = &f.object.code.writer; | |
| 3034 | const w = &f.code.writer; | |
| 3721 | 3035 | const local = try f.allocLocal(inst, inst_ty); |
| 3722 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3723 | try f.writeCValue(w, local, .Other); | |
| 3724 | try a.assign(f, w); | |
| 3036 | try f.writeCValue(w, local, .other); | |
| 3037 | try w.writeAll(" = "); | |
| 3725 | 3038 | try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); |
| 3726 | 3039 | try w.writeByte('['); |
| 3727 | try f.writeCValue(w, index, .Other); | |
| 3728 | try w.writeByte(']'); | |
| 3729 | try a.end(f, w); | |
| 3040 | try f.writeCValue(w, index, .other); | |
| 3041 | try w.writeAll("];"); | |
| 3042 | try f.newline(); | |
| 3730 | 3043 | return local; |
| 3731 | 3044 | } |
| 3732 | 3045 | |
| 3733 | 3046 | fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3734 | const pt = f.object.dg.pt; | |
| 3047 | const pt = f.dg.pt; | |
| 3735 | 3048 | const zcu = pt.zcu; |
| 3736 | 3049 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3737 | 3050 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3738 | 3051 | |
| 3739 | 3052 | const inst_ty = f.typeOfIndex(inst); |
| 3740 | 3053 | const slice_ty = f.typeOf(bin_op.lhs); |
| 3741 | const elem_ty = slice_ty.elemType2(zcu); | |
| 3742 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 3054 | const elem_ty = slice_ty.childType(zcu); | |
| 3055 | assert(elem_ty.hasRuntimeBits(zcu)); | |
| 3743 | 3056 | |
| 3744 | 3057 | const slice = try f.resolveInst(bin_op.lhs); |
| 3745 | 3058 | const index = try f.resolveInst(bin_op.rhs); |
| 3746 | 3059 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3747 | 3060 | |
| 3748 | const w = &f.object.code.writer; | |
| 3061 | const w = &f.code.writer; | |
| 3749 | 3062 | const local = try f.allocLocal(inst, inst_ty); |
| 3750 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3751 | try f.writeCValue(w, local, .Other); | |
| 3752 | try a.assign(f, w); | |
| 3753 | if (elem_has_bits) try w.writeByte('&'); | |
| 3063 | try f.writeCValue(w, local, .other); | |
| 3064 | try w.writeAll(" = "); | |
| 3065 | try w.writeByte('&'); | |
| 3754 | 3066 | try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); |
| 3755 | if (elem_has_bits) { | |
| 3756 | try w.writeByte('['); | |
| 3757 | try f.writeCValue(w, index, .Other); | |
| 3758 | try w.writeByte(']'); | |
| 3759 | } | |
| 3760 | try a.end(f, w); | |
| 3067 | try w.writeByte('['); | |
| 3068 | try f.writeCValue(w, index, .other); | |
| 3069 | try w.writeAll("];"); | |
| 3070 | try f.newline(); | |
| 3761 | 3071 | return local; |
| 3762 | 3072 | } |
| 3763 | 3073 | |
| 3764 | 3074 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3765 | const zcu = f.object.dg.pt.zcu; | |
| 3075 | const zcu = f.dg.pt.zcu; | |
| 3766 | 3076 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3767 | 3077 | const inst_ty = f.typeOfIndex(inst); |
| 3768 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3769 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | |
| 3770 | return .none; | |
| 3771 | } | |
| 3078 | assert(inst_ty.hasRuntimeBits(zcu)); | |
| 3772 | 3079 | |
| 3773 | 3080 | const array = try f.resolveInst(bin_op.lhs); |
| 3774 | 3081 | const index = try f.resolveInst(bin_op.rhs); |
| 3775 | 3082 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3776 | 3083 | |
| 3777 | const w = &f.object.code.writer; | |
| 3084 | const w = &f.code.writer; | |
| 3778 | 3085 | const local = try f.allocLocal(inst, inst_ty); |
| 3779 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 3780 | try f.writeCValue(w, local, .Other); | |
| 3781 | try a.assign(f, w); | |
| 3782 | try f.writeCValue(w, array, .Other); | |
| 3086 | try f.writeCValue(w, local, .other); | |
| 3087 | try w.writeAll(" = "); | |
| 3088 | try f.writeCValueMember(w, array, .{ .identifier = "array" }); | |
| 3783 | 3089 | try w.writeByte('['); |
| 3784 | try f.writeCValue(w, index, .Other); | |
| 3785 | try w.writeByte(']'); | |
| 3786 | try a.end(f, w); | |
| 3090 | try f.writeCValue(w, index, .other); | |
| 3091 | try w.writeAll("];"); | |
| 3092 | try f.newline(); | |
| 3787 | 3093 | return local; |
| 3788 | 3094 | } |
| 3789 | 3095 | |
| 3790 | 3096 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3791 | const pt = f.object.dg.pt; | |
| 3097 | const pt = f.dg.pt; | |
| 3792 | 3098 | const zcu = pt.zcu; |
| 3793 | 3099 | const inst_ty = f.typeOfIndex(inst); |
| 3794 | 3100 | const elem_ty = inst_ty.childType(zcu); |
| 3795 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; | |
| 3101 | if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; | |
| 3796 | 3102 | |
| 3797 | 3103 | const local = try f.allocLocalValue(.{ |
| 3798 | .ctype = try f.ctypeFromType(elem_ty, .complete), | |
| 3799 | .alignas = CType.AlignAs.fromAlignment(.{ | |
| 3800 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, | |
| 3801 | .abi = elem_ty.abiAlignment(zcu), | |
| 3802 | }), | |
| 3104 | .type = elem_ty, | |
| 3105 | .alignment = inst_ty.ptrInfo(zcu).flags.alignment, | |
| 3803 | 3106 | }); |
| 3804 | 3107 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3805 | 3108 | try f.allocs.put(zcu.gpa, local.new_local, true); |
| ... | ... | @@ -3810,11 +3113,11 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3810 | 3113 | // For packed aggregates, we zero-initialize to try and work around a design flaw |
| 3811 | 3114 | // related to how `packed`, `undefined`, and RLS interact. See comment in `airStore` |
| 3812 | 3115 | // for details. |
| 3813 | const w = &f.object.code.writer; | |
| 3116 | const w = &f.code.writer; | |
| 3814 | 3117 | try w.print("memset(&t{d}, 0x00, sizeof(", .{local.new_local}); |
| 3815 | 3118 | try f.renderType(w, elem_ty); |
| 3816 | 3119 | try w.writeAll("));"); |
| 3817 | try f.object.newline(); | |
| 3120 | try f.newline(); | |
| 3818 | 3121 | }, |
| 3819 | 3122 | .auto, .@"extern" => {}, |
| 3820 | 3123 | }, |
| ... | ... | @@ -3825,18 +3128,15 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3825 | 3128 | } |
| 3826 | 3129 | |
| 3827 | 3130 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3828 | const pt = f.object.dg.pt; | |
| 3131 | const pt = f.dg.pt; | |
| 3829 | 3132 | const zcu = pt.zcu; |
| 3830 | 3133 | const inst_ty = f.typeOfIndex(inst); |
| 3831 | 3134 | const elem_ty = inst_ty.childType(zcu); |
| 3832 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; | |
| 3135 | if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; | |
| 3833 | 3136 | |
| 3834 | 3137 | const local = try f.allocLocalValue(.{ |
| 3835 | .ctype = try f.ctypeFromType(elem_ty, .complete), | |
| 3836 | .alignas = CType.AlignAs.fromAlignment(.{ | |
| 3837 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, | |
| 3838 | .abi = elem_ty.abiAlignment(zcu), | |
| 3839 | }), | |
| 3138 | .type = elem_ty, | |
| 3139 | .alignment = inst_ty.ptrInfo(zcu).flags.alignment, | |
| 3840 | 3140 | }); |
| 3841 | 3141 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3842 | 3142 | try f.allocs.put(zcu.gpa, local.new_local, true); |
| ... | ... | @@ -3847,11 +3147,11 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3847 | 3147 | // For packed aggregates, we zero-initialize to try and work around a design flaw |
| 3848 | 3148 | // related to how `packed`, `undefined`, and RLS interact. See comment in `airStore` |
| 3849 | 3149 | // for details. |
| 3850 | const w = &f.object.code.writer; | |
| 3150 | const w = &f.code.writer; | |
| 3851 | 3151 | try w.print("memset(&t{d}, 0x00, sizeof(", .{local.new_local}); |
| 3852 | 3152 | try f.renderType(w, elem_ty); |
| 3853 | 3153 | try w.writeAll("));"); |
| 3854 | try f.object.newline(); | |
| 3154 | try f.newline(); | |
| 3855 | 3155 | }, |
| 3856 | 3156 | .auto, .@"extern" => {}, |
| 3857 | 3157 | }, |
| ... | ... | @@ -3862,24 +3162,18 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3862 | 3162 | } |
| 3863 | 3163 | |
| 3864 | 3164 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3865 | const inst_ty = f.typeOfIndex(inst); | |
| 3866 | const inst_ctype = try f.ctypeFromType(inst_ty, .parameter); | |
| 3867 | ||
| 3868 | 3165 | const i = f.next_arg_index; |
| 3869 | 3166 | f.next_arg_index += 1; |
| 3870 | const result: CValue = if (inst_ctype.eql(try f.ctypeFromType(inst_ty, .complete))) | |
| 3871 | .{ .arg = i } | |
| 3872 | else | |
| 3873 | .{ .arg_array = i }; | |
| 3167 | const result: CValue = .{ .arg = i }; | |
| 3874 | 3168 | |
| 3875 | 3169 | if (f.liveness.isUnused(inst)) { |
| 3876 | const w = &f.object.code.writer; | |
| 3170 | const w = &f.code.writer; | |
| 3877 | 3171 | try w.writeByte('('); |
| 3878 | 3172 | try f.renderType(w, .void); |
| 3879 | 3173 | try w.writeByte(')'); |
| 3880 | try f.writeCValue(w, result, .Other); | |
| 3174 | try f.writeCValue(w, result, .other); | |
| 3881 | 3175 | try w.writeByte(';'); |
| 3882 | try f.object.newline(); | |
| 3176 | try f.newline(); | |
| 3883 | 3177 | return .none; |
| 3884 | 3178 | } |
| 3885 | 3179 | |
| ... | ... | @@ -3887,7 +3181,7 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3887 | 3181 | } |
| 3888 | 3182 | |
| 3889 | 3183 | fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3890 | const pt = f.object.dg.pt; | |
| 3184 | const pt = f.dg.pt; | |
| 3891 | 3185 | const zcu = pt.zcu; |
| 3892 | 3186 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3893 | 3187 | |
| ... | ... | @@ -3900,10 +3194,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3900 | 3194 | // bit-pointers we see here are vector element pointers. |
| 3901 | 3195 | assert(ptr_info.packed_offset.host_size == 0 or ptr_info.flags.vector_index != .none); |
| 3902 | 3196 | |
| 3903 | if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3904 | try reap(f, inst, &.{ty_op.operand}); | |
| 3905 | return .none; | |
| 3906 | } | |
| 3197 | assert(src_ty.hasRuntimeBits(zcu)); | |
| 3907 | 3198 | |
| 3908 | 3199 | const operand = try f.resolveInst(ty_op.operand); |
| 3909 | 3200 | |
| ... | ... | @@ -3913,94 +3204,69 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3913 | 3204 | ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) |
| 3914 | 3205 | else |
| 3915 | 3206 | true; |
| 3916 | const is_array = lowersToArray(src_ty, zcu); | |
| 3917 | const need_memcpy = !is_aligned or is_array; | |
| 3918 | 3207 | |
| 3919 | const w = &f.object.code.writer; | |
| 3208 | const w = &f.code.writer; | |
| 3920 | 3209 | const local = try f.allocLocal(inst, src_ty); |
| 3921 | 3210 | const v = try Vectorize.start(f, inst, w, ptr_ty); |
| 3922 | 3211 | |
| 3923 | if (need_memcpy) { | |
| 3924 | try w.writeAll("memcpy("); | |
| 3925 | if (!is_array) try w.writeByte('&'); | |
| 3926 | try f.writeCValue(w, local, .Other); | |
| 3212 | if (!is_aligned) { | |
| 3213 | try w.writeAll("memcpy(&"); | |
| 3214 | try f.writeCValue(w, local, .other); | |
| 3927 | 3215 | try v.elem(f, w); |
| 3928 | 3216 | try w.writeAll(", (const char *)"); |
| 3929 | try f.writeCValue(w, operand, .Other); | |
| 3217 | try f.writeCValue(w, operand, .other); | |
| 3930 | 3218 | try v.elem(f, w); |
| 3931 | 3219 | try w.writeAll(", sizeof("); |
| 3932 | 3220 | try f.renderType(w, src_ty); |
| 3933 | 3221 | try w.writeAll("))"); |
| 3934 | 3222 | } else { |
| 3935 | try f.writeCValue(w, local, .Other); | |
| 3223 | try f.writeCValue(w, local, .other); | |
| 3936 | 3224 | try v.elem(f, w); |
| 3937 | 3225 | try w.writeAll(" = "); |
| 3938 | 3226 | try f.writeCValueDeref(w, operand); |
| 3939 | 3227 | try v.elem(f, w); |
| 3940 | 3228 | } |
| 3941 | 3229 | try w.writeByte(';'); |
| 3942 | try f.object.newline(); | |
| 3230 | try f.newline(); | |
| 3943 | 3231 | try v.end(f, inst, w); |
| 3944 | 3232 | |
| 3945 | 3233 | return local; |
| 3946 | 3234 | } |
| 3947 | 3235 | |
| 3948 | 3236 | fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { |
| 3949 | const pt = f.object.dg.pt; | |
| 3237 | const pt = f.dg.pt; | |
| 3950 | 3238 | const zcu = pt.zcu; |
| 3951 | 3239 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3952 | const w = &f.object.code.writer; | |
| 3240 | const w = &f.code.writer; | |
| 3953 | 3241 | const op_inst = un_op.toIndex(); |
| 3954 | 3242 | const op_ty = f.typeOf(un_op); |
| 3955 | 3243 | const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty; |
| 3956 | const ret_ctype = try f.ctypeFromType(ret_ty, .parameter); | |
| 3957 | 3244 | |
| 3958 | 3245 | if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { |
| 3959 | 3246 | try reap(f, inst, &.{un_op}); |
| 3960 | 3247 | _ = try airCall(f, op_inst.?, .always_tail); |
| 3961 | } else if (ret_ctype.index != .void) { | |
| 3248 | } else if (ret_ty.hasRuntimeBits(zcu)) { | |
| 3962 | 3249 | const operand = try f.resolveInst(un_op); |
| 3963 | 3250 | try reap(f, inst, &.{un_op}); |
| 3964 | var deref = is_ptr; | |
| 3965 | const is_array = lowersToArray(ret_ty, zcu); | |
| 3966 | const ret_val = if (is_array) ret_val: { | |
| 3967 | const array_local = try f.allocAlignedLocal(inst, .{ | |
| 3968 | .ctype = ret_ctype, | |
| 3969 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), | |
| 3970 | }); | |
| 3971 | try w.writeAll("memcpy("); | |
| 3972 | try f.writeCValueMember(w, array_local, .{ .identifier = "array" }); | |
| 3973 | try w.writeAll(", "); | |
| 3974 | if (deref) | |
| 3975 | try f.writeCValueDeref(w, operand) | |
| 3976 | else | |
| 3977 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 3978 | deref = false; | |
| 3979 | try w.writeAll(", sizeof("); | |
| 3980 | try f.renderType(w, ret_ty); | |
| 3981 | try w.writeAll("));"); | |
| 3982 | try f.object.newline(); | |
| 3983 | break :ret_val array_local; | |
| 3984 | } else operand; | |
| 3985 | 3251 | |
| 3986 | 3252 | try w.writeAll("return "); |
| 3987 | if (deref) | |
| 3988 | try f.writeCValueDeref(w, ret_val) | |
| 3989 | else | |
| 3990 | try f.writeCValue(w, ret_val, .Other); | |
| 3991 | try w.writeAll(";\n"); | |
| 3992 | if (is_array) { | |
| 3993 | try freeLocal(f, inst, ret_val.new_local, null); | |
| 3253 | if (is_ptr) { | |
| 3254 | try f.writeCValueDeref(w, operand); | |
| 3255 | } else switch (operand) { | |
| 3256 | // Instead of 'return &local', emit 'return undefined'. | |
| 3257 | .local_ref => try f.dg.renderUndefValue(w, ret_ty, .other), | |
| 3258 | else => try f.writeCValue(w, operand, .other), | |
| 3994 | 3259 | } |
| 3260 | try w.writeAll(";\n"); | |
| 3995 | 3261 | } else { |
| 3996 | 3262 | try reap(f, inst, &.{un_op}); |
| 3997 | 3263 | // Not even allowed to return void in a naked function. |
| 3998 | if (!f.object.dg.is_naked_fn) try w.writeAll("return;\n"); | |
| 3264 | if (!f.dg.is_naked_fn) try w.writeAll("return;\n"); | |
| 3999 | 3265 | } |
| 4000 | 3266 | } |
| 4001 | 3267 | |
| 4002 | 3268 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4003 | const pt = f.object.dg.pt; | |
| 3269 | const pt = f.dg.pt; | |
| 4004 | 3270 | const zcu = pt.zcu; |
| 4005 | 3271 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4006 | 3272 | |
| ... | ... | @@ -4012,23 +3278,26 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4012 | 3278 | const operand_ty = f.typeOf(ty_op.operand); |
| 4013 | 3279 | const scalar_ty = operand_ty.scalarType(zcu); |
| 4014 | 3280 | |
| 4015 | if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand); | |
| 3281 | // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct. | |
| 3282 | if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) { | |
| 3283 | return f.moveCValue(inst, inst_ty, operand); | |
| 3284 | } | |
| 4016 | 3285 | |
| 4017 | const w = &f.object.code.writer; | |
| 3286 | const w = &f.code.writer; | |
| 4018 | 3287 | const local = try f.allocLocal(inst, inst_ty); |
| 4019 | 3288 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 4020 | const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); | |
| 4021 | try f.writeCValue(w, local, .Other); | |
| 3289 | try f.writeCValue(w, local, .other); | |
| 4022 | 3290 | try v.elem(f, w); |
| 4023 | try a.assign(f, w); | |
| 4024 | try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .Other); | |
| 4025 | try a.end(f, w); | |
| 3291 | try w.writeAll(" = "); | |
| 3292 | try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other); | |
| 3293 | try w.writeByte(';'); | |
| 3294 | try f.newline(); | |
| 4026 | 3295 | try v.end(f, inst, w); |
| 4027 | 3296 | return local; |
| 4028 | 3297 | } |
| 4029 | 3298 | |
| 4030 | 3299 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4031 | const pt = f.object.dg.pt; | |
| 3300 | const pt = f.dg.pt; | |
| 4032 | 3301 | const zcu = pt.zcu; |
| 4033 | 3302 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4034 | 3303 | |
| ... | ... | @@ -4050,13 +3319,12 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4050 | 3319 | const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); |
| 4051 | 3320 | if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); |
| 4052 | 3321 | |
| 4053 | const w = &f.object.code.writer; | |
| 3322 | const w = &f.code.writer; | |
| 4054 | 3323 | const local = try f.allocLocal(inst, inst_ty); |
| 4055 | 3324 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 4056 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete)); | |
| 4057 | try f.writeCValue(w, local, .Other); | |
| 3325 | try f.writeCValue(w, local, .other); | |
| 4058 | 3326 | try v.elem(f, w); |
| 4059 | try a.assign(f, w); | |
| 3327 | try w.writeAll(" = "); | |
| 4060 | 3328 | if (need_cast) { |
| 4061 | 3329 | try w.writeByte('('); |
| 4062 | 3330 | try f.renderType(w, inst_scalar_ty); |
| ... | ... | @@ -4064,18 +3332,18 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4064 | 3332 | } |
| 4065 | 3333 | if (need_lo) { |
| 4066 | 3334 | try w.writeAll("zig_lo_"); |
| 4067 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3335 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4068 | 3336 | try w.writeByte('('); |
| 4069 | 3337 | } |
| 4070 | 3338 | if (!need_mask) { |
| 4071 | try f.writeCValue(w, operand, .Other); | |
| 3339 | try f.writeCValue(w, operand, .other); | |
| 4072 | 3340 | try v.elem(f, w); |
| 4073 | 3341 | } else switch (dest_int_info.signedness) { |
| 4074 | 3342 | .unsigned => { |
| 4075 | 3343 | try w.writeAll("zig_and_"); |
| 4076 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3344 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4077 | 3345 | try w.writeByte('('); |
| 4078 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 3346 | try f.writeCValue(w, operand, .other); | |
| 4079 | 3347 | try v.elem(f, w); |
| 4080 | 3348 | try w.print(", {f})", .{ |
| 4081 | 3349 | try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), |
| ... | ... | @@ -4087,7 +3355,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4087 | 3355 | const shift_val = try pt.intValue(.u8, c_bits - dest_bits); |
| 4088 | 3356 | |
| 4089 | 3357 | try w.writeAll("zig_shr_"); |
| 4090 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3358 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4091 | 3359 | if (c_bits == 128) { |
| 4092 | 3360 | try w.print("(zig_bitCast_i{d}(", .{c_bits}); |
| 4093 | 3361 | } else { |
| ... | ... | @@ -4099,7 +3367,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4099 | 3367 | } else { |
| 4100 | 3368 | try w.print("(uint{d}_t)", .{c_bits}); |
| 4101 | 3369 | } |
| 4102 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 3370 | try f.writeCValue(w, operand, .other); | |
| 4103 | 3371 | try v.elem(f, w); |
| 4104 | 3372 | if (c_bits == 128) try w.writeByte(')'); |
| 4105 | 3373 | try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); |
| ... | ... | @@ -4108,13 +3376,14 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4108 | 3376 | }, |
| 4109 | 3377 | } |
| 4110 | 3378 | if (need_lo) try w.writeByte(')'); |
| 4111 | try a.end(f, w); | |
| 3379 | try w.writeByte(';'); | |
| 3380 | try f.newline(); | |
| 4112 | 3381 | try v.end(f, inst, w); |
| 4113 | 3382 | return local; |
| 4114 | 3383 | } |
| 4115 | 3384 | |
| 4116 | 3385 | fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4117 | const pt = f.object.dg.pt; | |
| 3386 | const pt = f.dg.pt; | |
| 4118 | 3387 | const zcu = pt.zcu; |
| 4119 | 3388 | // *a = b; |
| 4120 | 3389 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -4132,7 +3401,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4132 | 3401 | |
| 4133 | 3402 | const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndef(zcu) else false; |
| 4134 | 3403 | |
| 4135 | const w = &f.object.code.writer; | |
| 3404 | const w = &f.code.writer; | |
| 4136 | 3405 | if (val_is_undef) { |
| 4137 | 3406 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4138 | 3407 | if (safety and ptr_info.packed_offset.host_size == 0) { |
| ... | ... | @@ -4152,11 +3421,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4152 | 3421 | }, |
| 4153 | 3422 | }; |
| 4154 | 3423 | try w.writeAll("memset("); |
| 4155 | try f.writeCValue(w, ptr_val, .FunctionArgument); | |
| 3424 | try f.writeCValue(w, ptr_val, .other); | |
| 4156 | 3425 | try w.print(", {s}, sizeof(", .{byte_str}); |
| 4157 | 3426 | try f.renderType(w, .fromInterned(ptr_info.child)); |
| 4158 | 3427 | try w.writeAll("));"); |
| 4159 | try f.object.newline(); | |
| 3428 | try f.newline(); | |
| 4160 | 3429 | } |
| 4161 | 3430 | return .none; |
| 4162 | 3431 | } |
| ... | ... | @@ -4165,46 +3434,29 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4165 | 3434 | ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) |
| 4166 | 3435 | else |
| 4167 | 3436 | true; |
| 4168 | const is_array = lowersToArray(.fromInterned(ptr_info.child), zcu); | |
| 4169 | const need_memcpy = !is_aligned or is_array; | |
| 4170 | 3437 | |
| 4171 | 3438 | const src_val = try f.resolveInst(bin_op.rhs); |
| 4172 | 3439 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4173 | 3440 | |
| 4174 | const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete); | |
| 4175 | if (need_memcpy) { | |
| 4176 | // For this memcpy to safely work we need the rhs to have the same | |
| 4177 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). | |
| 4178 | assert(src_ty.eql(.fromInterned(ptr_info.child), zcu)); | |
| 4179 | ||
| 4180 | // If the source is a constant, writeCValue will emit a brace initialization | |
| 4181 | // so work around this by initializing into new local. | |
| 4182 | // TODO this should be done by manually initializing elements of the dest array | |
| 4183 | const array_src = if (src_val == .constant) blk: { | |
| 4184 | const new_local = try f.allocLocal(inst, src_ty); | |
| 4185 | try f.writeCValue(w, new_local, .Other); | |
| 4186 | try w.writeAll(" = "); | |
| 4187 | try f.writeCValue(w, src_val, .Other); | |
| 4188 | try w.writeByte(';'); | |
| 4189 | try f.object.newline(); | |
| 4190 | ||
| 4191 | break :blk new_local; | |
| 4192 | } else src_val; | |
| 3441 | if (!is_aligned) { | |
| 3442 | // For this memcpy to safely work we need the rhs to have the same | |
| 3443 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). | |
| 3444 | assert(src_ty.eql(.fromInterned(ptr_info.child), zcu)); | |
| 4193 | 3445 | |
| 4194 | 3446 | const v = try Vectorize.start(f, inst, w, ptr_ty); |
| 4195 | 3447 | try w.writeAll("memcpy((char *)"); |
| 4196 | try f.writeCValue(w, ptr_val, .FunctionArgument); | |
| 3448 | try f.writeCValue(w, ptr_val, .other); | |
| 4197 | 3449 | try v.elem(f, w); |
| 4198 | try w.writeAll(", "); | |
| 4199 | if (!is_array) try w.writeByte('&'); | |
| 4200 | try f.writeCValue(w, array_src, .FunctionArgument); | |
| 3450 | try w.writeAll(", &"); | |
| 3451 | switch (src_val) { | |
| 3452 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 3453 | else => try f.writeCValue(w, src_val, .other), | |
| 3454 | } | |
| 4201 | 3455 | try v.elem(f, w); |
| 4202 | 3456 | try w.writeAll(", sizeof("); |
| 4203 | 3457 | try f.renderType(w, src_ty); |
| 4204 | try w.writeAll("))"); | |
| 4205 | try f.freeCValue(inst, array_src); | |
| 4206 | try w.writeByte(';'); | |
| 4207 | try f.object.newline(); | |
| 3458 | try w.writeAll("));"); | |
| 3459 | try f.newline(); | |
| 4208 | 3460 | try v.end(f, inst, w); |
| 4209 | 3461 | } else { |
| 4210 | 3462 | switch (ptr_val) { |
| ... | ... | @@ -4216,20 +3468,20 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4216 | 3468 | else => {}, |
| 4217 | 3469 | } |
| 4218 | 3470 | const v = try Vectorize.start(f, inst, w, ptr_ty); |
| 4219 | const a = try Assignment.start(f, w, src_scalar_ctype); | |
| 4220 | 3471 | try f.writeCValueDeref(w, ptr_val); |
| 4221 | 3472 | try v.elem(f, w); |
| 4222 | try a.assign(f, w); | |
| 4223 | try f.writeCValue(w, src_val, .Other); | |
| 3473 | try w.writeAll(" = "); | |
| 3474 | try f.writeCValue(w, src_val, .other); | |
| 4224 | 3475 | try v.elem(f, w); |
| 4225 | try a.end(f, w); | |
| 3476 | try w.writeByte(';'); | |
| 3477 | try f.newline(); | |
| 4226 | 3478 | try v.end(f, inst, w); |
| 4227 | 3479 | } |
| 4228 | 3480 | return .none; |
| 4229 | 3481 | } |
| 4230 | 3482 | |
| 4231 | 3483 | fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { |
| 4232 | const pt = f.object.dg.pt; | |
| 3484 | const pt = f.dg.pt; | |
| 4233 | 3485 | const zcu = pt.zcu; |
| 4234 | 3486 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4235 | 3487 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -4242,7 +3494,9 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 4242 | 3494 | const operand_ty = f.typeOf(bin_op.lhs); |
| 4243 | 3495 | const scalar_ty = operand_ty.scalarType(zcu); |
| 4244 | 3496 | |
| 4245 | const w = &f.object.code.writer; | |
| 3497 | const ref_arg = lowersToBigInt(scalar_ty, zcu); | |
| 3498 | ||
| 3499 | const w = &f.code.writer; | |
| 4246 | 3500 | const local = try f.allocLocal(inst, inst_ty); |
| 4247 | 3501 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 4248 | 3502 | try f.writeCValueMember(w, local, .{ .field = 1 }); |
| ... | ... | @@ -4250,26 +3504,28 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 4250 | 3504 | try w.writeAll(" = zig_"); |
| 4251 | 3505 | try w.writeAll(operation); |
| 4252 | 3506 | try w.writeAll("o_"); |
| 4253 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3507 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 4254 | 3508 | try w.writeAll("(&"); |
| 4255 | 3509 | try f.writeCValueMember(w, local, .{ .field = 0 }); |
| 4256 | 3510 | try v.elem(f, w); |
| 4257 | 3511 | try w.writeAll(", "); |
| 4258 | try f.writeCValue(w, lhs, .FunctionArgument); | |
| 3512 | if (ref_arg) try w.writeByte('&'); | |
| 3513 | try f.writeCValue(w, lhs, .other); | |
| 4259 | 3514 | try v.elem(f, w); |
| 4260 | 3515 | try w.writeAll(", "); |
| 4261 | try f.writeCValue(w, rhs, .FunctionArgument); | |
| 3516 | if (ref_arg) try w.writeByte('&'); | |
| 3517 | try f.writeCValue(w, rhs, .other); | |
| 4262 | 3518 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); |
| 4263 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 3519 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 4264 | 3520 | try w.writeAll(");"); |
| 4265 | try f.object.newline(); | |
| 3521 | try f.newline(); | |
| 4266 | 3522 | try v.end(f, inst, w); |
| 4267 | 3523 | |
| 4268 | 3524 | return local; |
| 4269 | 3525 | } |
| 4270 | 3526 | |
| 4271 | 3527 | fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4272 | const pt = f.object.dg.pt; | |
| 3528 | const pt = f.dg.pt; | |
| 4273 | 3529 | const zcu = pt.zcu; |
| 4274 | 3530 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4275 | 3531 | const operand_ty = f.typeOf(ty_op.operand); |
| ... | ... | @@ -4281,17 +3537,17 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4281 | 3537 | |
| 4282 | 3538 | const inst_ty = f.typeOfIndex(inst); |
| 4283 | 3539 | |
| 4284 | const w = &f.object.code.writer; | |
| 3540 | const w = &f.code.writer; | |
| 4285 | 3541 | const local = try f.allocLocal(inst, inst_ty); |
| 4286 | 3542 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 4287 | try f.writeCValue(w, local, .Other); | |
| 3543 | try f.writeCValue(w, local, .other); | |
| 4288 | 3544 | try v.elem(f, w); |
| 4289 | 3545 | try w.writeAll(" = "); |
| 4290 | 3546 | try w.writeByte('!'); |
| 4291 | try f.writeCValue(w, op, .Other); | |
| 3547 | try f.writeCValue(w, op, .other); | |
| 4292 | 3548 | try v.elem(f, w); |
| 4293 | 3549 | try w.writeByte(';'); |
| 4294 | try f.object.newline(); | |
| 3550 | try f.newline(); | |
| 4295 | 3551 | try v.end(f, inst, w); |
| 4296 | 3552 | |
| 4297 | 3553 | return local; |
| ... | ... | @@ -4304,7 +3560,7 @@ fn airBinOp( |
| 4304 | 3560 | operation: []const u8, |
| 4305 | 3561 | info: BuiltinInfo, |
| 4306 | 3562 | ) !CValue { |
| 4307 | const pt = f.object.dg.pt; | |
| 3563 | const pt = f.dg.pt; | |
| 4308 | 3564 | const zcu = pt.zcu; |
| 4309 | 3565 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4310 | 3566 | const operand_ty = f.typeOf(bin_op.lhs); |
| ... | ... | @@ -4318,21 +3574,21 @@ fn airBinOp( |
| 4318 | 3574 | |
| 4319 | 3575 | const inst_ty = f.typeOfIndex(inst); |
| 4320 | 3576 | |
| 4321 | const w = &f.object.code.writer; | |
| 3577 | const w = &f.code.writer; | |
| 4322 | 3578 | const local = try f.allocLocal(inst, inst_ty); |
| 4323 | 3579 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 4324 | try f.writeCValue(w, local, .Other); | |
| 3580 | try f.writeCValue(w, local, .other); | |
| 4325 | 3581 | try v.elem(f, w); |
| 4326 | 3582 | try w.writeAll(" = "); |
| 4327 | try f.writeCValue(w, lhs, .Other); | |
| 3583 | try f.writeCValue(w, lhs, .other); | |
| 4328 | 3584 | try v.elem(f, w); |
| 4329 | 3585 | try w.writeByte(' '); |
| 4330 | 3586 | try w.writeAll(operator); |
| 4331 | 3587 | try w.writeByte(' '); |
| 4332 | try f.writeCValue(w, rhs, .Other); | |
| 3588 | try f.writeCValue(w, rhs, .other); | |
| 4333 | 3589 | try v.elem(f, w); |
| 4334 | 3590 | try w.writeByte(';'); |
| 4335 | try f.object.newline(); | |
| 3591 | try f.newline(); | |
| 4336 | 3592 | try v.end(f, inst, w); |
| 4337 | 3593 | |
| 4338 | 3594 | return local; |
| ... | ... | @@ -4344,7 +3600,7 @@ fn airCmpOp( |
| 4344 | 3600 | data: anytype, |
| 4345 | 3601 | operator: std.math.CompareOperator, |
| 4346 | 3602 | ) !CValue { |
| 4347 | const pt = f.object.dg.pt; | |
| 3603 | const pt = f.dg.pt; | |
| 4348 | 3604 | const zcu = pt.zcu; |
| 4349 | 3605 | const lhs_ty = f.typeOf(data.lhs); |
| 4350 | 3606 | const scalar_ty = lhs_ty.scalarType(zcu); |
| ... | ... | @@ -4369,26 +3625,26 @@ fn airCmpOp( |
| 4369 | 3625 | |
| 4370 | 3626 | const rhs_ty = f.typeOf(data.rhs); |
| 4371 | 3627 | const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu); |
| 4372 | const w = &f.object.code.writer; | |
| 3628 | const w = &f.code.writer; | |
| 4373 | 3629 | const local = try f.allocLocal(inst, inst_ty); |
| 4374 | 3630 | const v = try Vectorize.start(f, inst, w, lhs_ty); |
| 4375 | const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); | |
| 4376 | try f.writeCValue(w, local, .Other); | |
| 3631 | try f.writeCValue(w, local, .other); | |
| 4377 | 3632 | try v.elem(f, w); |
| 4378 | try a.assign(f, w); | |
| 3633 | try w.writeAll(" = "); | |
| 4379 | 3634 | if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) { |
| 4380 | 3635 | .lt, .neq, .gt => "false", |
| 4381 | 3636 | .lte, .eq, .gte => "true", |
| 4382 | 3637 | }) else { |
| 4383 | 3638 | if (need_cast) try w.writeAll("(void*)"); |
| 4384 | try f.writeCValue(w, lhs, .Other); | |
| 3639 | try f.writeCValue(w, lhs, .other); | |
| 4385 | 3640 | try v.elem(f, w); |
| 4386 | 3641 | try w.writeAll(compareOperatorC(operator)); |
| 4387 | 3642 | if (need_cast) try w.writeAll("(void*)"); |
| 4388 | try f.writeCValue(w, rhs, .Other); | |
| 3643 | try f.writeCValue(w, rhs, .other); | |
| 4389 | 3644 | try v.elem(f, w); |
| 4390 | 3645 | } |
| 4391 | try a.end(f, w); | |
| 3646 | try w.writeByte(';'); | |
| 3647 | try f.newline(); | |
| 4392 | 3648 | try v.end(f, inst, w); |
| 4393 | 3649 | |
| 4394 | 3650 | return local; |
| ... | ... | @@ -4399,9 +3655,8 @@ fn airEquality( |
| 4399 | 3655 | inst: Air.Inst.Index, |
| 4400 | 3656 | operator: std.math.CompareOperator, |
| 4401 | 3657 | ) !CValue { |
| 4402 | const pt = f.object.dg.pt; | |
| 3658 | const pt = f.dg.pt; | |
| 4403 | 3659 | const zcu = pt.zcu; |
| 4404 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 4405 | 3660 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4406 | 3661 | |
| 4407 | 3662 | const operand_ty = f.typeOf(bin_op.lhs); |
| ... | ... | @@ -4422,54 +3677,64 @@ fn airEquality( |
| 4422 | 3677 | const rhs = try f.resolveInst(bin_op.rhs); |
| 4423 | 3678 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4424 | 3679 | |
| 4425 | const w = &f.object.code.writer; | |
| 3680 | if (lhs.eql(rhs)) { | |
| 3681 | // Avoid emitting a tautological comparison. | |
| 3682 | return .{ .constant = .makeBool(switch (operator) { | |
| 3683 | .eq, .lte, .gte => true, | |
| 3684 | .neq, .lt, .gt => false, | |
| 3685 | }) }; | |
| 3686 | } | |
| 3687 | ||
| 3688 | const w = &f.code.writer; | |
| 4426 | 3689 | const local = try f.allocLocal(inst, .bool); |
| 4427 | const a = try Assignment.start(f, w, .bool); | |
| 4428 | try f.writeCValue(w, local, .Other); | |
| 4429 | try a.assign(f, w); | |
| 3690 | try f.writeCValue(w, local, .other); | |
| 3691 | try w.writeAll(" = "); | |
| 4430 | 3692 | |
| 4431 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); | |
| 4432 | if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) { | |
| 4433 | .lt, .lte, .gte, .gt => unreachable, | |
| 4434 | .neq => "false", | |
| 4435 | .eq => "true", | |
| 4436 | }) else switch (operand_ctype.info(ctype_pool)) { | |
| 4437 | .basic, .pointer => { | |
| 4438 | try f.writeCValue(w, lhs, .Other); | |
| 4439 | try w.writeAll(compareOperatorC(operator)); | |
| 4440 | try f.writeCValue(w, rhs, .Other); | |
| 4441 | }, | |
| 4442 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 4443 | .aggregate => |aggregate| if (aggregate.fields.len == 2 and | |
| 4444 | (aggregate.fields.at(0, ctype_pool).name.index == .is_null or | |
| 4445 | aggregate.fields.at(1, ctype_pool).name.index == .is_null)) | |
| 4446 | { | |
| 4447 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 4448 | try w.writeAll(" || "); | |
| 4449 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 4450 | try w.writeAll(" ? "); | |
| 4451 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 4452 | try w.writeAll(compareOperatorC(operator)); | |
| 4453 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 4454 | try w.writeAll(" : "); | |
| 4455 | try f.writeCValueMember(w, lhs, .{ .identifier = "payload" }); | |
| 4456 | try w.writeAll(compareOperatorC(operator)); | |
| 4457 | try f.writeCValueMember(w, rhs, .{ .identifier = "payload" }); | |
| 4458 | } else for (0..aggregate.fields.len) |field_index| { | |
| 4459 | if (field_index > 0) try w.writeAll(switch (operator) { | |
| 4460 | .lt, .lte, .gte, .gt => unreachable, | |
| 4461 | .eq => " && ", | |
| 4462 | .neq => " || ", | |
| 4463 | }); | |
| 4464 | const field_name: CValue = .{ | |
| 4465 | .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name, | |
| 4466 | }; | |
| 4467 | try f.writeCValueMember(w, lhs, field_name); | |
| 4468 | try w.writeAll(compareOperatorC(operator)); | |
| 4469 | try f.writeCValueMember(w, rhs, field_name); | |
| 3693 | switch (operand_ty.zigTypeTag(zcu)) { | |
| 3694 | .optional => switch (CType.classifyOptional(operand_ty, zcu)) { | |
| 3695 | .npv_payload => unreachable, // opv optional | |
| 3696 | ||
| 3697 | .error_set, .ptr_like => {}, | |
| 3698 | ||
| 3699 | .slice_like => unreachable, // equality is not defined on slices | |
| 3700 | ||
| 3701 | .opv_payload => { | |
| 3702 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 3703 | try w.writeAll(compareOperatorC(operator)); | |
| 3704 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 3705 | try w.writeByte(';'); | |
| 3706 | try f.newline(); | |
| 3707 | return local; | |
| 3708 | }, | |
| 3709 | ||
| 3710 | .@"struct" => { | |
| 3711 | // `lhs.is_null || rhs.is_null ? lhs.is_null == rhs.is_null : lhs.payload == rhs.payload` | |
| 3712 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 3713 | try w.writeAll(" || "); | |
| 3714 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 3715 | try w.writeAll(" ? "); | |
| 3716 | try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); | |
| 3717 | try w.writeAll(compareOperatorC(operator)); | |
| 3718 | try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); | |
| 3719 | try w.writeAll(" : "); | |
| 3720 | try f.writeCValueMember(w, lhs, .{ .identifier = "payload" }); | |
| 3721 | try w.writeAll(compareOperatorC(operator)); | |
| 3722 | try f.writeCValueMember(w, rhs, .{ .identifier = "payload" }); | |
| 3723 | try w.writeByte(';'); | |
| 3724 | try f.newline(); | |
| 3725 | return local; | |
| 3726 | }, | |
| 4470 | 3727 | }, |
| 3728 | .bool, .int, .pointer, .@"enum", .error_set => {}, | |
| 3729 | .@"struct", .@"union" => assert(operand_ty.containerLayout(zcu) == .@"packed"), | |
| 3730 | else => unreachable, | |
| 4471 | 3731 | } |
| 4472 | try a.end(f, w); | |
| 3732 | ||
| 3733 | try f.writeCValue(w, lhs, .other); | |
| 3734 | try w.writeAll(compareOperatorC(operator)); | |
| 3735 | try f.writeCValue(w, rhs, .other); | |
| 3736 | try w.writeByte(';'); | |
| 3737 | try f.newline(); | |
| 4473 | 3738 | |
| 4474 | 3739 | return local; |
| 4475 | 3740 | } |
| ... | ... | @@ -4480,18 +3745,18 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4480 | 3745 | const operand = try f.resolveInst(un_op); |
| 4481 | 3746 | try reap(f, inst, &.{un_op}); |
| 4482 | 3747 | |
| 4483 | const w = &f.object.code.writer; | |
| 3748 | const w = &f.code.writer; | |
| 4484 | 3749 | const local = try f.allocLocal(inst, .bool); |
| 4485 | try f.writeCValue(w, local, .Other); | |
| 3750 | try f.writeCValue(w, local, .other); | |
| 4486 | 3751 | try w.writeAll(" = "); |
| 4487 | try f.writeCValue(w, operand, .Other); | |
| 3752 | try f.writeCValue(w, operand, .other); | |
| 4488 | 3753 | try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")}); |
| 4489 | try f.object.newline(); | |
| 3754 | try f.newline(); | |
| 4490 | 3755 | return local; |
| 4491 | 3756 | } |
| 4492 | 3757 | |
| 4493 | 3758 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4494 | const pt = f.object.dg.pt; | |
| 3759 | const pt = f.dg.pt; | |
| 4495 | 3760 | const zcu = pt.zcu; |
| 4496 | 3761 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4497 | 3762 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -4502,40 +3767,36 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4502 | 3767 | |
| 4503 | 3768 | const inst_ty = f.typeOfIndex(inst); |
| 4504 | 3769 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 4505 | const elem_ty = inst_scalar_ty.elemType2(zcu); | |
| 4506 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs); | |
| 4507 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 3770 | const elem_ty = inst_scalar_ty.indexableElem(zcu); | |
| 3771 | assert(elem_ty.hasRuntimeBits(zcu)); | |
| 4508 | 3772 | |
| 4509 | 3773 | const local = try f.allocLocal(inst, inst_ty); |
| 4510 | const w = &f.object.code.writer; | |
| 3774 | const w = &f.code.writer; | |
| 4511 | 3775 | const v = try Vectorize.start(f, inst, w, inst_ty); |
| 4512 | const a = try Assignment.start(f, w, inst_scalar_ctype); | |
| 4513 | try f.writeCValue(w, local, .Other); | |
| 3776 | try f.writeCValue(w, local, .other); | |
| 4514 | 3777 | try v.elem(f, w); |
| 4515 | try a.assign(f, w); | |
| 3778 | try w.writeAll(" = "); | |
| 4516 | 3779 | // We must convert to and from integer types to prevent UB if the operation |
| 4517 | 3780 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB |
| 4518 | 3781 | // if the result is NULL and then dereferenced. |
| 4519 | 3782 | try w.writeByte('('); |
| 4520 | try f.renderCType(w, inst_scalar_ctype); | |
| 3783 | try f.renderType(w, inst_scalar_ty); | |
| 4521 | 3784 | try w.writeAll(")(((uintptr_t)"); |
| 4522 | try f.writeCValue(w, lhs, .Other); | |
| 3785 | try f.writeCValue(w, lhs, .other); | |
| 4523 | 3786 | try v.elem(f, w); |
| 4524 | try w.writeAll(") "); | |
| 4525 | try w.writeByte(operator); | |
| 4526 | try w.writeAll(" ("); | |
| 4527 | try f.writeCValue(w, rhs, .Other); | |
| 3787 | try w.print(") {c} (", .{operator}); | |
| 3788 | try f.writeCValue(w, rhs, .other); | |
| 4528 | 3789 | try v.elem(f, w); |
| 4529 | 3790 | try w.writeAll("*sizeof("); |
| 4530 | 3791 | try f.renderType(w, elem_ty); |
| 4531 | try w.writeAll(")))"); | |
| 4532 | try a.end(f, w); | |
| 3792 | try w.writeAll(")));"); | |
| 3793 | try f.newline(); | |
| 4533 | 3794 | try v.end(f, inst, w); |
| 4534 | 3795 | return local; |
| 4535 | 3796 | } |
| 4536 | 3797 | |
| 4537 | 3798 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 4538 | const pt = f.object.dg.pt; | |
| 3799 | const pt = f.dg.pt; | |
| 4539 | 3800 | const zcu = pt.zcu; |
| 4540 | 3801 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4541 | 3802 | |
| ... | ... | @@ -4549,36 +3810,34 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons |
| 4549 | 3810 | const rhs = try f.resolveInst(bin_op.rhs); |
| 4550 | 3811 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4551 | 3812 | |
| 4552 | const w = &f.object.code.writer; | |
| 3813 | const w = &f.code.writer; | |
| 4553 | 3814 | const local = try f.allocLocal(inst, inst_ty); |
| 4554 | 3815 | const v = try Vectorize.start(f, inst, w, inst_ty); |
| 4555 | try f.writeCValue(w, local, .Other); | |
| 3816 | try f.writeCValue(w, local, .other); | |
| 4556 | 3817 | try v.elem(f, w); |
| 4557 | 3818 | // (lhs <> rhs) ? lhs : rhs |
| 4558 | 3819 | try w.writeAll(" = ("); |
| 4559 | try f.writeCValue(w, lhs, .Other); | |
| 3820 | try f.writeCValue(w, lhs, .other); | |
| 4560 | 3821 | try v.elem(f, w); |
| 4561 | 3822 | try w.writeByte(' '); |
| 4562 | 3823 | try w.writeByte(operator); |
| 4563 | 3824 | try w.writeByte(' '); |
| 4564 | try f.writeCValue(w, rhs, .Other); | |
| 3825 | try f.writeCValue(w, rhs, .other); | |
| 4565 | 3826 | try v.elem(f, w); |
| 4566 | 3827 | try w.writeAll(") ? "); |
| 4567 | try f.writeCValue(w, lhs, .Other); | |
| 3828 | try f.writeCValue(w, lhs, .other); | |
| 4568 | 3829 | try v.elem(f, w); |
| 4569 | 3830 | try w.writeAll(" : "); |
| 4570 | try f.writeCValue(w, rhs, .Other); | |
| 3831 | try f.writeCValue(w, rhs, .other); | |
| 4571 | 3832 | try v.elem(f, w); |
| 4572 | 3833 | try w.writeByte(';'); |
| 4573 | try f.object.newline(); | |
| 3834 | try f.newline(); | |
| 4574 | 3835 | try v.end(f, inst, w); |
| 4575 | 3836 | |
| 4576 | 3837 | return local; |
| 4577 | 3838 | } |
| 4578 | 3839 | |
| 4579 | 3840 | fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4580 | const pt = f.object.dg.pt; | |
| 4581 | const zcu = pt.zcu; | |
| 4582 | 3841 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4583 | 3842 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4584 | 3843 | |
| ... | ... | @@ -4587,24 +3846,22 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4587 | 3846 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4588 | 3847 | |
| 4589 | 3848 | const inst_ty = f.typeOfIndex(inst); |
| 4590 | const ptr_ty = inst_ty.slicePtrFieldType(zcu); | |
| 4591 | 3849 | |
| 4592 | const w = &f.object.code.writer; | |
| 3850 | const w = &f.code.writer; | |
| 4593 | 3851 | const local = try f.allocLocal(inst, inst_ty); |
| 4594 | { | |
| 4595 | const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete)); | |
| 4596 | try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); | |
| 4597 | try a.assign(f, w); | |
| 4598 | try f.writeCValue(w, ptr, .Other); | |
| 4599 | try a.end(f, w); | |
| 4600 | } | |
| 4601 | { | |
| 4602 | const a = try Assignment.start(f, w, .usize); | |
| 4603 | try f.writeCValueMember(w, local, .{ .identifier = "len" }); | |
| 4604 | try a.assign(f, w); | |
| 4605 | try f.writeCValue(w, len, .Other); | |
| 4606 | try a.end(f, w); | |
| 4607 | } | |
| 3852 | ||
| 3853 | try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); | |
| 3854 | try w.writeAll(" = "); | |
| 3855 | try f.writeCValue(w, ptr, .other); | |
| 3856 | try w.writeByte(';'); | |
| 3857 | try f.newline(); | |
| 3858 | ||
| 3859 | try f.writeCValueMember(w, local, .{ .identifier = "len" }); | |
| 3860 | try w.writeAll(" = "); | |
| 3861 | try f.writeCValue(w, len, .other); | |
| 3862 | try w.writeByte(';'); | |
| 3863 | try f.newline(); | |
| 3864 | ||
| 4608 | 3865 | return local; |
| 4609 | 3866 | } |
| 4610 | 3867 | |
| ... | ... | @@ -4613,14 +3870,14 @@ fn airCall( |
| 4613 | 3870 | inst: Air.Inst.Index, |
| 4614 | 3871 | modifier: std.builtin.CallModifier, |
| 4615 | 3872 | ) !CValue { |
| 4616 | const pt = f.object.dg.pt; | |
| 3873 | const pt = f.dg.pt; | |
| 4617 | 3874 | const zcu = pt.zcu; |
| 4618 | 3875 | const ip = &zcu.intern_pool; |
| 4619 | 3876 | // Not even allowed to call panic in a naked function. |
| 4620 | if (f.object.dg.is_naked_fn) return .none; | |
| 3877 | if (f.dg.is_naked_fn) return .none; | |
| 4621 | 3878 | |
| 4622 | const gpa = f.object.dg.gpa; | |
| 4623 | const w = &f.object.code.writer; | |
| 3879 | const gpa = f.dg.gpa; | |
| 3880 | const w = &f.code.writer; | |
| 4624 | 3881 | |
| 4625 | 3882 | const call = f.air.unwrapCall(inst); |
| 4626 | 3883 | const args = call.args; |
| ... | ... | @@ -4629,27 +3886,11 @@ fn airCall( |
| 4629 | 3886 | defer gpa.free(resolved_args); |
| 4630 | 3887 | for (resolved_args, args) |*resolved_arg, arg| { |
| 4631 | 3888 | const arg_ty = f.typeOf(arg); |
| 4632 | const arg_ctype = try f.ctypeFromType(arg_ty, .parameter); | |
| 4633 | if (arg_ctype.index == .void) { | |
| 3889 | if (!arg_ty.hasRuntimeBits(zcu)) { | |
| 4634 | 3890 | resolved_arg.* = .none; |
| 4635 | 3891 | continue; |
| 4636 | 3892 | } |
| 4637 | 3893 | resolved_arg.* = try f.resolveInst(arg); |
| 4638 | if (!arg_ctype.eql(try f.ctypeFromType(arg_ty, .complete))) { | |
| 4639 | const array_local = try f.allocAlignedLocal(inst, .{ | |
| 4640 | .ctype = arg_ctype, | |
| 4641 | .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)), | |
| 4642 | }); | |
| 4643 | try w.writeAll("memcpy("); | |
| 4644 | try f.writeCValueMember(w, array_local, .{ .identifier = "array" }); | |
| 4645 | try w.writeAll(", "); | |
| 4646 | try f.writeCValue(w, resolved_arg.*, .FunctionArgument); | |
| 4647 | try w.writeAll(", sizeof("); | |
| 4648 | try f.renderCType(w, arg_ctype); | |
| 4649 | try w.writeAll("));"); | |
| 4650 | try f.object.newline(); | |
| 4651 | resolved_arg.* = array_local; | |
| 4652 | } | |
| 4653 | 3894 | } |
| 4654 | 3895 | |
| 4655 | 3896 | const callee = try f.resolveInst(call.callee); |
| ... | ... | @@ -4668,28 +3909,22 @@ fn airCall( |
| 4668 | 3909 | }; |
| 4669 | 3910 | const fn_info = zcu.typeToFunc(if (callee_is_ptr) callee_ty.childType(zcu) else callee_ty).?; |
| 4670 | 3911 | const ret_ty: Type = .fromInterned(fn_info.return_type); |
| 4671 | const ret_ctype: CType = if (ret_ty.isNoReturn(zcu)) | |
| 4672 | .void | |
| 4673 | else | |
| 4674 | try f.ctypeFromType(ret_ty, .parameter); | |
| 4675 | 3912 | |
| 4676 | 3913 | const result_local = result: { |
| 4677 | 3914 | if (modifier == .always_tail) { |
| 4678 | 3915 | try w.writeAll("zig_always_tail return "); |
| 4679 | 3916 | break :result .none; |
| 4680 | } else if (ret_ctype.index == .void) { | |
| 3917 | } else if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 4681 | 3918 | break :result .none; |
| 4682 | 3919 | } else if (f.liveness.isUnused(inst)) { |
| 4683 | try w.writeByte('('); | |
| 4684 | try f.renderCType(w, .void); | |
| 4685 | try w.writeByte(')'); | |
| 3920 | try w.writeAll("(void)"); | |
| 4686 | 3921 | break :result .none; |
| 4687 | 3922 | } else { |
| 4688 | 3923 | const local = try f.allocAlignedLocal(inst, .{ |
| 4689 | .ctype = ret_ctype, | |
| 4690 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), | |
| 3924 | .type = ret_ty, | |
| 3925 | .alignment = .none, | |
| 4691 | 3926 | }); |
| 4692 | try f.writeCValue(w, local, .Other); | |
| 3927 | try f.writeCValue(w, local, .other); | |
| 4693 | 3928 | try w.writeAll(" = "); |
| 4694 | 3929 | break :result local; |
| 4695 | 3930 | } |
| ... | ... | @@ -4716,8 +3951,19 @@ fn airCall( |
| 4716 | 3951 | if (!callee_is_ptr) try w.writeByte('&'); |
| 4717 | 3952 | } |
| 4718 | 3953 | switch (modifier) { |
| 4719 | .auto, .always_tail => try f.object.dg.renderNavName(w, fn_nav), | |
| 4720 | inline .never_tail, .never_inline => |m| try w.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))), | |
| 3954 | .auto, .always_tail => try renderNavName(w, fn_nav, ip), | |
| 3955 | .never_tail => { | |
| 3956 | try f.need_never_tail_funcs.put(gpa, fn_nav, {}); | |
| 3957 | try w.print("zig_never_tail_{f}__{d}", .{ | |
| 3958 | fmtIdentUnsolo(ip.getNav(fn_nav).name.toSlice(ip)), @intFromEnum(fn_nav), | |
| 3959 | }); | |
| 3960 | }, | |
| 3961 | .never_inline => { | |
| 3962 | try f.need_never_inline_funcs.put(gpa, fn_nav, {}); | |
| 3963 | try w.print("zig_never_inline_{f}__{d}", .{ | |
| 3964 | fmtIdentUnsolo(ip.getNav(fn_nav).name.toSlice(ip)), @intFromEnum(fn_nav), | |
| 3965 | }); | |
| 3966 | }, | |
| 4721 | 3967 | else => unreachable, |
| 4722 | 3968 | } |
| 4723 | 3969 | if (need_cast) try w.writeByte(')'); |
| ... | ... | @@ -4730,7 +3976,7 @@ fn airCall( |
| 4730 | 3976 | else => unreachable, |
| 4731 | 3977 | } |
| 4732 | 3978 | // Fall back to function pointer call. |
| 4733 | try f.writeCValue(w, callee, .Other); | |
| 3979 | try f.writeCValue(w, callee, .other); | |
| 4734 | 3980 | } |
| 4735 | 3981 | |
| 4736 | 3982 | try w.writeByte('('); |
| ... | ... | @@ -4739,38 +3985,20 @@ fn airCall( |
| 4739 | 3985 | if (resolved_arg == .none) continue; |
| 4740 | 3986 | if (need_comma) try w.writeAll(", "); |
| 4741 | 3987 | need_comma = true; |
| 4742 | try f.writeCValue(w, resolved_arg, .FunctionArgument); | |
| 4743 | try f.freeCValue(inst, resolved_arg); | |
| 3988 | try f.writeCValue(w, resolved_arg, .other); | |
| 4744 | 3989 | } |
| 4745 | 3990 | try w.writeAll(");"); |
| 4746 | 3991 | switch (modifier) { |
| 4747 | 3992 | .always_tail => try w.writeByte('\n'), |
| 4748 | else => try f.object.newline(), | |
| 3993 | else => try f.newline(), | |
| 4749 | 3994 | } |
| 4750 | 3995 | |
| 4751 | const result = result: { | |
| 4752 | if (result_local == .none or !lowersToArray(ret_ty, zcu)) | |
| 4753 | break :result result_local; | |
| 4754 | ||
| 4755 | const array_local = try f.allocLocal(inst, ret_ty); | |
| 4756 | try w.writeAll("memcpy("); | |
| 4757 | try f.writeCValue(w, array_local, .FunctionArgument); | |
| 4758 | try w.writeAll(", "); | |
| 4759 | try f.writeCValueMember(w, result_local, .{ .identifier = "array" }); | |
| 4760 | try w.writeAll(", sizeof("); | |
| 4761 | try f.renderType(w, ret_ty); | |
| 4762 | try w.writeAll("));"); | |
| 4763 | try f.object.newline(); | |
| 4764 | try freeLocal(f, inst, result_local.new_local, null); | |
| 4765 | break :result array_local; | |
| 4766 | }; | |
| 4767 | ||
| 4768 | return result; | |
| 3996 | return result_local; | |
| 4769 | 3997 | } |
| 4770 | 3998 | |
| 4771 | 3999 | fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4772 | 4000 | const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 4773 | const w = &f.object.code.writer; | |
| 4001 | const w = &f.code.writer; | |
| 4774 | 4002 | // TODO re-evaluate whether to emit these or not. If we naively emit |
| 4775 | 4003 | // these directives, the output file will report bogus line numbers because |
| 4776 | 4004 | // every newline after the #line directive adds one to the line. |
| ... | ... | @@ -4779,32 +4007,32 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4779 | 4007 | // newlines until the next dbg_stmt occurs. |
| 4780 | 4008 | // Perhaps an additional compilation option is in order? |
| 4781 | 4009 | //try w.print("#line {d}", .{dbg_stmt.line + 1}); |
| 4782 | //try f.object.newline(); | |
| 4010 | //try f.newline(); | |
| 4783 | 4011 | try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); |
| 4784 | try f.object.newline(); | |
| 4012 | try f.newline(); | |
| 4785 | 4013 | return .none; |
| 4786 | 4014 | } |
| 4787 | 4015 | |
| 4788 | 4016 | fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue { |
| 4789 | try f.object.code.writer.writeAll("(void)0;"); | |
| 4790 | try f.object.newline(); | |
| 4017 | try f.code.writer.writeAll("(void)0;"); | |
| 4018 | try f.newline(); | |
| 4791 | 4019 | return .none; |
| 4792 | 4020 | } |
| 4793 | 4021 | |
| 4794 | 4022 | fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4795 | const pt = f.object.dg.pt; | |
| 4023 | const pt = f.dg.pt; | |
| 4796 | 4024 | const zcu = pt.zcu; |
| 4797 | 4025 | const ip = &zcu.intern_pool; |
| 4798 | 4026 | const block = f.air.unwrapDbgBlock(inst); |
| 4799 | 4027 | const owner_nav = ip.getNav(zcu.funcInfo(block.func).owner_nav); |
| 4800 | const w = &f.object.code.writer; | |
| 4028 | const w = &f.code.writer; | |
| 4801 | 4029 | try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)}); |
| 4802 | try f.object.newline(); | |
| 4030 | try f.newline(); | |
| 4803 | 4031 | return lowerBlock(f, inst, block.body); |
| 4804 | 4032 | } |
| 4805 | 4033 | |
| 4806 | 4034 | fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4807 | const pt = f.object.dg.pt; | |
| 4035 | const pt = f.dg.pt; | |
| 4808 | 4036 | const zcu = pt.zcu; |
| 4809 | 4037 | const tag = f.air.instructions.items(.tag)[@intFromEnum(inst)]; |
| 4810 | 4038 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| ... | ... | @@ -4813,9 +4041,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4813 | 4041 | if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); |
| 4814 | 4042 | |
| 4815 | 4043 | try reap(f, inst, &.{pl_op.operand}); |
| 4816 | const w = &f.object.code.writer; | |
| 4044 | const w = &f.code.writer; | |
| 4817 | 4045 | try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) }); |
| 4818 | try f.object.newline(); | |
| 4046 | try f.newline(); | |
| 4819 | 4047 | return .none; |
| 4820 | 4048 | } |
| 4821 | 4049 | |
| ... | ... | @@ -4825,21 +4053,21 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4825 | 4053 | } |
| 4826 | 4054 | |
| 4827 | 4055 | fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue { |
| 4828 | const pt = f.object.dg.pt; | |
| 4056 | const pt = f.dg.pt; | |
| 4829 | 4057 | const zcu = pt.zcu; |
| 4830 | 4058 | const liveness_block = f.liveness.getBlock(inst); |
| 4831 | 4059 | |
| 4832 | 4060 | const block_id = f.next_block_index; |
| 4833 | 4061 | f.next_block_index += 1; |
| 4834 | const w = &f.object.code.writer; | |
| 4062 | const w = &f.code.writer; | |
| 4835 | 4063 | |
| 4836 | 4064 | const inst_ty = f.typeOfIndex(inst); |
| 4837 | const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst)) | |
| 4065 | const result = if (inst_ty.hasRuntimeBits(zcu) and !f.liveness.isUnused(inst)) | |
| 4838 | 4066 | try f.allocLocal(inst, inst_ty) |
| 4839 | 4067 | else |
| 4840 | 4068 | .none; |
| 4841 | 4069 | |
| 4842 | try f.blocks.putNoClobber(f.object.dg.gpa, inst, .{ | |
| 4070 | try f.blocks.putNoClobber(f.dg.gpa, inst, .{ | |
| 4843 | 4071 | .block_id = block_id, |
| 4844 | 4072 | .result = result, |
| 4845 | 4073 | }); |
| ... | ... | @@ -4854,23 +4082,23 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 4854 | 4082 | } |
| 4855 | 4083 | |
| 4856 | 4084 | // noreturn blocks have no `br` instructions reaching them, so we don't want a label |
| 4857 | if (f.object.dg.is_naked_fn) { | |
| 4858 | if (f.object.dg.expected_block) |expected_block| { | |
| 4085 | if (f.dg.is_naked_fn) { | |
| 4086 | if (f.dg.expected_block) |expected_block| { | |
| 4859 | 4087 | if (block_id != expected_block) |
| 4860 | 4088 | return f.fail("runtime code not allowed in naked function", .{}); |
| 4861 | f.object.dg.expected_block = null; | |
| 4089 | f.dg.expected_block = null; | |
| 4862 | 4090 | } |
| 4863 | 4091 | } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) { |
| 4864 | 4092 | // label must be followed by an expression, include an empty one. |
| 4865 | 4093 | try w.print("\nzig_block_{d}:;", .{block_id}); |
| 4866 | try f.object.newline(); | |
| 4094 | try f.newline(); | |
| 4867 | 4095 | } |
| 4868 | 4096 | |
| 4869 | 4097 | return result; |
| 4870 | 4098 | } |
| 4871 | 4099 | |
| 4872 | 4100 | fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4873 | const pt = f.object.dg.pt; | |
| 4101 | const pt = f.dg.pt; | |
| 4874 | 4102 | const unwrapped_try = f.air.unwrapTry(inst); |
| 4875 | 4103 | const body = unwrapped_try.else_body; |
| 4876 | 4104 | const err_union_ty = f.air.typeOf(unwrapped_try.error_union, &pt.zcu.intern_pool); |
| ... | ... | @@ -4878,7 +4106,7 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4878 | 4106 | } |
| 4879 | 4107 | |
| 4880 | 4108 | fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4881 | const pt = f.object.dg.pt; | |
| 4109 | const pt = f.dg.pt; | |
| 4882 | 4110 | const unwrapped_try = f.air.unwrapTryPtr(inst); |
| 4883 | 4111 | const body = unwrapped_try.else_body; |
| 4884 | 4112 | const err_union_ty = f.air.typeOf(unwrapped_try.error_union_ptr, &pt.zcu.intern_pool).childType(pt.zcu); |
| ... | ... | @@ -4893,46 +4121,38 @@ fn lowerTry( |
| 4893 | 4121 | err_union_ty: Type, |
| 4894 | 4122 | is_ptr: bool, |
| 4895 | 4123 | ) !CValue { |
| 4896 | const pt = f.object.dg.pt; | |
| 4124 | const pt = f.dg.pt; | |
| 4897 | 4125 | const zcu = pt.zcu; |
| 4898 | 4126 | const err_union = try f.resolveInst(operand); |
| 4899 | 4127 | const inst_ty = f.typeOfIndex(inst); |
| 4900 | 4128 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4901 | const w = &f.object.code.writer; | |
| 4129 | const w = &f.code.writer; | |
| 4902 | 4130 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 4903 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 4904 | 4131 | |
| 4905 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { | |
| 4906 | try w.writeAll("if ("); | |
| 4907 | if (!payload_has_bits) { | |
| 4908 | if (is_ptr) | |
| 4909 | try f.writeCValueDeref(w, err_union) | |
| 4910 | else | |
| 4911 | try f.writeCValue(w, err_union, .Other); | |
| 4912 | } else { | |
| 4913 | // Reap the operand so that it can be reused inside genBody. | |
| 4914 | // Remember we must avoid calling reap() twice for the same operand | |
| 4915 | // in this function. | |
| 4916 | try reap(f, inst, &.{operand}); | |
| 4917 | if (is_ptr) | |
| 4918 | try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" }) | |
| 4919 | else | |
| 4920 | try f.writeCValueMember(w, err_union, .{ .identifier = "error" }); | |
| 4921 | } | |
| 4922 | try w.writeAll(") "); | |
| 4132 | try w.writeAll("if ("); | |
| 4923 | 4133 | |
| 4924 | try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); | |
| 4925 | try f.object.newline(); | |
| 4926 | if (f.object.dg.expected_block) |_| | |
| 4927 | return f.fail("runtime code not allowed in naked function", .{}); | |
| 4928 | } | |
| 4134 | // Reap the operand so that it can be reused inside genBody. | |
| 4135 | // Remember we must avoid calling reap() twice for the same operand | |
| 4136 | // in this function. | |
| 4137 | try reap(f, inst, &.{operand}); | |
| 4138 | if (is_ptr) | |
| 4139 | try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" }) | |
| 4140 | else | |
| 4141 | try f.writeCValueMember(w, err_union, .{ .identifier = "error" }); | |
| 4142 | ||
| 4143 | try w.writeAll(") "); | |
| 4144 | ||
| 4145 | try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); | |
| 4146 | try f.newline(); | |
| 4147 | if (f.dg.expected_block) |_| | |
| 4148 | return f.fail("runtime code not allowed in naked function", .{}); | |
| 4929 | 4149 | |
| 4930 | 4150 | // Now we have the "then branch" (in terms of the liveness data); process any deaths. |
| 4931 | 4151 | for (liveness_condbr.then_deaths) |death| { |
| 4932 | 4152 | try die(f, inst, death.toRef()); |
| 4933 | 4153 | } |
| 4934 | 4154 | |
| 4935 | if (!payload_has_bits) { | |
| 4155 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 4936 | 4156 | if (!is_ptr) { |
| 4937 | 4157 | return .none; |
| 4938 | 4158 | } else { |
| ... | ... | @@ -4945,14 +4165,14 @@ fn lowerTry( |
| 4945 | 4165 | if (f.liveness.isUnused(inst)) return .none; |
| 4946 | 4166 | |
| 4947 | 4167 | const local = try f.allocLocal(inst, inst_ty); |
| 4948 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 4949 | try f.writeCValue(w, local, .Other); | |
| 4950 | try a.assign(f, w); | |
| 4168 | try f.writeCValue(w, local, .other); | |
| 4169 | try w.writeAll(" = "); | |
| 4951 | 4170 | if (is_ptr) { |
| 4952 | 4171 | try w.writeByte('&'); |
| 4953 | 4172 | try f.writeCValueDerefMember(w, err_union, .{ .identifier = "payload" }); |
| 4954 | 4173 | } else try f.writeCValueMember(w, err_union, .{ .identifier = "payload" }); |
| 4955 | try a.end(f, w); | |
| 4174 | try w.writeByte(';'); | |
| 4175 | try f.newline(); | |
| 4956 | 4176 | return local; |
| 4957 | 4177 | } |
| 4958 | 4178 | |
| ... | ... | @@ -4960,25 +4180,24 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void { |
| 4960 | 4180 | const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 4961 | 4181 | const block = f.blocks.get(branch.block_inst).?; |
| 4962 | 4182 | const result = block.result; |
| 4963 | const w = &f.object.code.writer; | |
| 4183 | const w = &f.code.writer; | |
| 4964 | 4184 | |
| 4965 | if (f.object.dg.is_naked_fn) { | |
| 4185 | if (f.dg.is_naked_fn) { | |
| 4966 | 4186 | if (result != .none) return f.fail("runtime code not allowed in naked function", .{}); |
| 4967 | f.object.dg.expected_block = block.block_id; | |
| 4187 | f.dg.expected_block = block.block_id; | |
| 4968 | 4188 | return; |
| 4969 | 4189 | } |
| 4970 | 4190 | |
| 4971 | 4191 | // If result is .none then the value of the block is unused. |
| 4972 | 4192 | if (result != .none) { |
| 4973 | const operand_ty = f.typeOf(branch.operand); | |
| 4974 | 4193 | const operand = try f.resolveInst(branch.operand); |
| 4975 | 4194 | try reap(f, inst, &.{branch.operand}); |
| 4976 | 4195 | |
| 4977 | const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); | |
| 4978 | try f.writeCValue(w, result, .Other); | |
| 4979 | try a.assign(f, w); | |
| 4980 | try f.writeCValue(w, operand, .Other); | |
| 4981 | try a.end(f, w); | |
| 4196 | try f.writeCValue(w, result, .other); | |
| 4197 | try w.writeAll(" = "); | |
| 4198 | try f.writeCValue(w, operand, .other); | |
| 4199 | try w.writeByte(';'); | |
| 4200 | try f.newline(); | |
| 4982 | 4201 | } |
| 4983 | 4202 | |
| 4984 | 4203 | try w.print("goto zig_block_{d};\n", .{block.block_id}); |
| ... | ... | @@ -4986,14 +4205,14 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void { |
| 4986 | 4205 | |
| 4987 | 4206 | fn airRepeat(f: *Function, inst: Air.Inst.Index) !void { |
| 4988 | 4207 | const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat; |
| 4989 | try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); | |
| 4208 | try f.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); | |
| 4990 | 4209 | } |
| 4991 | 4210 | |
| 4992 | 4211 | fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| 4993 | const pt = f.object.dg.pt; | |
| 4212 | const pt = f.dg.pt; | |
| 4994 | 4213 | const zcu = pt.zcu; |
| 4995 | 4214 | const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 4996 | const w = &f.object.code.writer; | |
| 4215 | const w = &f.code.writer; | |
| 4997 | 4216 | |
| 4998 | 4217 | if (try f.air.value(br.operand, pt)) |cond_val| { |
| 4999 | 4218 | // Comptime-known dispatch. Iterate the cases to find the correct |
| ... | ... | @@ -5022,11 +4241,11 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| 5022 | 4241 | // Runtime-known dispatch. Set the switch condition, and branch back. |
| 5023 | 4242 | const cond = try f.resolveInst(br.operand); |
| 5024 | 4243 | const cond_local = f.loop_switch_conds.get(br.block_inst).?; |
| 5025 | try f.writeCValue(w, .{ .local = cond_local }, .Other); | |
| 4244 | try f.writeCValue(w, .{ .local = cond_local }, .other); | |
| 5026 | 4245 | try w.writeAll(" = "); |
| 5027 | try f.writeCValue(w, cond, .Other); | |
| 4246 | try f.writeCValue(w, cond, .other); | |
| 5028 | 4247 | try w.writeByte(';'); |
| 5029 | try f.object.newline(); | |
| 4248 | try f.newline(); | |
| 5030 | 4249 | try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)}); |
| 5031 | 4250 | } |
| 5032 | 4251 | |
| ... | ... | @@ -5043,11 +4262,10 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5043 | 4262 | } |
| 5044 | 4263 | |
| 5045 | 4264 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CValue { |
| 5046 | const pt = f.object.dg.pt; | |
| 4265 | const pt = f.dg.pt; | |
| 5047 | 4266 | const zcu = pt.zcu; |
| 5048 | const target = &f.object.dg.mod.resolved_target.result; | |
| 5049 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 5050 | const w = &f.object.code.writer; | |
| 4267 | const target = &f.dg.mod.resolved_target.result; | |
| 4268 | const w = &f.code.writer; | |
| 5051 | 4269 | |
| 5052 | 4270 | if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { |
| 5053 | 4271 | const src_info = dest_ty.intInfo(zcu); |
| ... | ... | @@ -5058,26 +4276,16 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal |
| 5058 | 4276 | |
| 5059 | 4277 | if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) { |
| 5060 | 4278 | const local = try f.allocLocal(null, dest_ty); |
| 5061 | try f.writeCValue(w, local, .Other); | |
| 4279 | try f.writeCValue(w, local, .other); | |
| 5062 | 4280 | try w.writeAll(" = ("); |
| 5063 | 4281 | try f.renderType(w, dest_ty); |
| 5064 | 4282 | try w.writeByte(')'); |
| 5065 | try f.writeCValue(w, operand, .Other); | |
| 4283 | try f.writeCValue(w, operand, .other); | |
| 5066 | 4284 | try w.writeByte(';'); |
| 5067 | try f.object.newline(); | |
| 4285 | try f.newline(); | |
| 5068 | 4286 | return local; |
| 5069 | 4287 | } |
| 5070 | 4288 | |
| 5071 | const operand_lval = if (operand == .constant) blk: { | |
| 5072 | const operand_local = try f.allocLocal(null, operand_ty); | |
| 5073 | try f.writeCValue(w, operand_local, .Other); | |
| 5074 | try w.writeAll(" = "); | |
| 5075 | try f.writeCValue(w, operand, .Other); | |
| 5076 | try w.writeByte(';'); | |
| 5077 | try f.object.newline(); | |
| 5078 | break :blk operand_local; | |
| 5079 | } else operand; | |
| 5080 | ||
| 5081 | 4289 | const local = try f.allocLocal(null, dest_ty); |
| 5082 | 4290 | // On big-endian targets, copying ABI integers with padding bits is awkward, because the padding bits are at the low bytes of the value. |
| 5083 | 4291 | // We need to offset the source or destination pointer appropriately and copy the right number of bytes. |
| ... | ... | @@ -5085,141 +4293,134 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal |
| 5085 | 4293 | // e.g. [10]u8 -> u80. We need to offset the destination so that we copy to the least significant bits of the integer. |
| 5086 | 4294 | const offset = dest_ty.abiSize(zcu) - operand_ty.abiSize(zcu); |
| 5087 | 4295 | try w.writeAll("memcpy((char *)&"); |
| 5088 | try f.writeCValue(w, local, .Other); | |
| 4296 | try f.writeCValue(w, local, .other); | |
| 5089 | 4297 | try w.print(" + {d}, &", .{offset}); |
| 5090 | try f.writeCValue(w, operand_lval, .Other); | |
| 4298 | switch (operand) { | |
| 4299 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 4300 | else => try f.writeCValue(w, operand, .other), | |
| 4301 | } | |
| 5091 | 4302 | try w.print(", {d});", .{operand_ty.abiSize(zcu)}); |
| 5092 | 4303 | } else if (target.cpu.arch.endian() == .big and operand_ty.isAbiInt(zcu) and !dest_ty.isAbiInt(zcu)) { |
| 5093 | 4304 | // e.g. u80 -> [10]u8. We need to offset the source so that we copy from the least significant bits of the integer. |
| 5094 | 4305 | const offset = operand_ty.abiSize(zcu) - dest_ty.abiSize(zcu); |
| 5095 | 4306 | try w.writeAll("memcpy(&"); |
| 5096 | try f.writeCValue(w, local, .Other); | |
| 4307 | try f.writeCValue(w, local, .other); | |
| 5097 | 4308 | try w.writeAll(", (const char *)&"); |
| 5098 | try f.writeCValue(w, operand_lval, .Other); | |
| 4309 | switch (operand) { | |
| 4310 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 4311 | else => try f.writeCValue(w, operand, .other), | |
| 4312 | } | |
| 5099 | 4313 | try w.print(" + {d}, {d});", .{ offset, dest_ty.abiSize(zcu) }); |
| 5100 | 4314 | } else { |
| 5101 | 4315 | try w.writeAll("memcpy(&"); |
| 5102 | try f.writeCValue(w, local, .Other); | |
| 4316 | try f.writeCValue(w, local, .other); | |
| 5103 | 4317 | try w.writeAll(", &"); |
| 5104 | try f.writeCValue(w, operand_lval, .Other); | |
| 4318 | switch (operand) { | |
| 4319 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 4320 | else => try f.writeCValue(w, operand, .other), | |
| 4321 | } | |
| 5105 | 4322 | try w.print(", {d});", .{@min(dest_ty.abiSize(zcu), operand_ty.abiSize(zcu))}); |
| 5106 | 4323 | } |
| 5107 | 4324 | |
| 5108 | try f.object.newline(); | |
| 4325 | try f.newline(); | |
| 5109 | 4326 | |
| 5110 | 4327 | // Ensure padding bits have the expected value. |
| 5111 | 4328 | if (dest_ty.isAbiInt(zcu)) { |
| 5112 | const dest_ctype = try f.ctypeFromType(dest_ty, .complete); | |
| 5113 | const dest_info = dest_ty.intInfo(zcu); | |
| 5114 | var bits: u16 = dest_info.bits; | |
| 5115 | var wrap_ctype: ?CType = null; | |
| 5116 | var need_bitcasts = false; | |
| 5117 | ||
| 5118 | try f.writeCValue(w, local, .Other); | |
| 5119 | switch (dest_ctype.info(ctype_pool)) { | |
| 5120 | else => {}, | |
| 5121 | .array => |array_info| { | |
| 5122 | try w.print("[{d}]", .{switch (target.cpu.arch.endian()) { | |
| 5123 | .little => array_info.len - 1, | |
| 5124 | .big => 0, | |
| 5125 | }}); | |
| 5126 | wrap_ctype = array_info.elem_ctype.toSignedness(dest_info.signedness); | |
| 5127 | need_bitcasts = wrap_ctype.?.index == .zig_i128; | |
| 5128 | bits -= 1; | |
| 5129 | bits %= @as(u16, @intCast(f.byteSize(array_info.elem_ctype) * 8)); | |
| 5130 | bits += 1; | |
| 4329 | switch (CType.classifyInt(dest_ty, zcu)) { | |
| 4330 | .void => unreachable, // opv | |
| 4331 | .small => { | |
| 4332 | try f.writeCValue(w, local, .other); | |
| 4333 | try w.writeAll(" = zig_wrap_"); | |
| 4334 | try f.dg.renderTypeForBuiltinFnName(w, dest_ty); | |
| 4335 | try w.writeByte('('); | |
| 4336 | try f.writeCValue(w, local, .other); | |
| 4337 | try f.dg.renderBuiltinInfo(w, dest_ty, .bits); | |
| 4338 | try w.writeAll(");"); | |
| 4339 | try f.newline(); | |
| 5131 | 4340 | }, |
| 5132 | } | |
| 5133 | try w.writeAll(" = "); | |
| 5134 | if (need_bitcasts) { | |
| 5135 | try w.writeAll("zig_bitCast_"); | |
| 5136 | try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?.toUnsigned()); | |
| 5137 | try w.writeByte('('); | |
| 5138 | } | |
| 5139 | try w.writeAll("zig_wrap_"); | |
| 5140 | const info_ty = try pt.intType(dest_info.signedness, bits); | |
| 5141 | if (wrap_ctype) |ctype| | |
| 5142 | try f.object.dg.renderCTypeForBuiltinFnName(w, ctype) | |
| 5143 | else | |
| 5144 | try f.object.dg.renderTypeForBuiltinFnName(w, info_ty); | |
| 5145 | try w.writeByte('('); | |
| 5146 | if (need_bitcasts) { | |
| 5147 | try w.writeAll("zig_bitCast_"); | |
| 5148 | try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?); | |
| 5149 | try w.writeByte('('); | |
| 5150 | } | |
| 5151 | try f.writeCValue(w, local, .Other); | |
| 5152 | switch (dest_ctype.info(ctype_pool)) { | |
| 5153 | else => {}, | |
| 5154 | .array => |array_info| try w.print("[{d}]", .{ | |
| 5155 | switch (target.cpu.arch.endian()) { | |
| 5156 | .little => array_info.len - 1, | |
| 4341 | .big => |big| { | |
| 4342 | const dest_info = dest_ty.intInfo(zcu); | |
| 4343 | const padding_index: u16 = switch (target.cpu.arch.endian()) { | |
| 4344 | .little => big.limbs_len - 1, | |
| 5157 | 4345 | .big => 0, |
| 5158 | }, | |
| 5159 | }), | |
| 4346 | }; | |
| 4347 | const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1; | |
| 4348 | if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) { | |
| 4349 | try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); | |
| 4350 | try w.print("[{d}] = zig_wrap_{c}{d}(", .{ | |
| 4351 | padding_index, | |
| 4352 | signAbbrev(dest_info.signedness), | |
| 4353 | big.limb_size.bits(), | |
| 4354 | }); | |
| 4355 | try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); | |
| 4356 | try w.print("[{d}], {d});", .{ padding_index, wrap_bits }); | |
| 4357 | } else { | |
| 4358 | try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); | |
| 4359 | try w.print("[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{ | |
| 4360 | padding_index, | |
| 4361 | }); | |
| 4362 | try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); | |
| 4363 | try w.print("[{d}]), {d}));", .{ padding_index, wrap_bits }); | |
| 4364 | try f.newline(); | |
| 4365 | } | |
| 4366 | }, | |
| 5160 | 4367 | } |
| 5161 | if (need_bitcasts) try w.writeByte(')'); | |
| 5162 | try f.object.dg.renderBuiltinInfo(w, info_ty, .bits); | |
| 5163 | if (need_bitcasts) try w.writeByte(')'); | |
| 5164 | try w.writeAll(");"); | |
| 5165 | try f.object.newline(); | |
| 5166 | 4368 | } |
| 5167 | 4369 | |
| 5168 | try f.freeCValue(null, operand_lval); | |
| 5169 | 4370 | return local; |
| 5170 | 4371 | } |
| 5171 | 4372 | |
| 5172 | fn airTrap(f: *Function, w: *Writer) !void { | |
| 4373 | fn airTrap(f: *Function) !void { | |
| 5173 | 4374 | // Not even allowed to call trap in a naked function. |
| 5174 | if (f.object.dg.is_naked_fn) return; | |
| 5175 | try w.writeAll("zig_trap();\n"); | |
| 4375 | if (f.dg.is_naked_fn) return; | |
| 4376 | try f.code.writer.writeAll("zig_trap();\n"); | |
| 5176 | 4377 | } |
| 5177 | 4378 | |
| 5178 | 4379 | fn airBreakpoint(f: *Function) !CValue { |
| 5179 | const w = &f.object.code.writer; | |
| 4380 | const w = &f.code.writer; | |
| 5180 | 4381 | try w.writeAll("zig_breakpoint();"); |
| 5181 | try f.object.newline(); | |
| 4382 | try f.newline(); | |
| 5182 | 4383 | return .none; |
| 5183 | 4384 | } |
| 5184 | 4385 | |
| 5185 | 4386 | fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5186 | const w = &f.object.code.writer; | |
| 4387 | const w = &f.code.writer; | |
| 5187 | 4388 | const local = try f.allocLocal(inst, .usize); |
| 5188 | try f.writeCValue(w, local, .Other); | |
| 4389 | try f.writeCValue(w, local, .other); | |
| 5189 | 4390 | try w.writeAll(" = ("); |
| 5190 | 4391 | try f.renderType(w, .usize); |
| 5191 | 4392 | try w.writeAll(")zig_return_address();"); |
| 5192 | try f.object.newline(); | |
| 4393 | try f.newline(); | |
| 5193 | 4394 | return local; |
| 5194 | 4395 | } |
| 5195 | 4396 | |
| 5196 | 4397 | fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5197 | const w = &f.object.code.writer; | |
| 4398 | const w = &f.code.writer; | |
| 5198 | 4399 | const local = try f.allocLocal(inst, .usize); |
| 5199 | try f.writeCValue(w, local, .Other); | |
| 4400 | try f.writeCValue(w, local, .other); | |
| 5200 | 4401 | try w.writeAll(" = ("); |
| 5201 | 4402 | try f.renderType(w, .usize); |
| 5202 | 4403 | try w.writeAll(")zig_frame_address();"); |
| 5203 | try f.object.newline(); | |
| 4404 | try f.newline(); | |
| 5204 | 4405 | return local; |
| 5205 | 4406 | } |
| 5206 | 4407 | |
| 5207 | fn airUnreach(o: *Object) !void { | |
| 4408 | fn airUnreach(f: *Function) !void { | |
| 5208 | 4409 | // Not even allowed to call unreachable in a naked function. |
| 5209 | if (o.dg.is_naked_fn) return; | |
| 5210 | try o.code.writer.writeAll("zig_unreachable();\n"); | |
| 4410 | if (f.dg.is_naked_fn) return; | |
| 4411 | try f.code.writer.writeAll("zig_unreachable();\n"); | |
| 5211 | 4412 | } |
| 5212 | 4413 | |
| 5213 | 4414 | fn airLoop(f: *Function, inst: Air.Inst.Index) !void { |
| 5214 | 4415 | const block = f.air.unwrapBlock(inst); |
| 5215 | const w = &f.object.code.writer; | |
| 4416 | const w = &f.code.writer; | |
| 5216 | 4417 | |
| 5217 | 4418 | // `repeat` instructions matching this loop will branch to |
| 5218 | 4419 | // this label. Since we need a label for arbitrary `repeat` |
| 5219 | 4420 | // anyway, there's actually no need to use a "real" looping |
| 5220 | 4421 | // construct at all! |
| 5221 | 4422 | try w.print("zig_loop_{d}:", .{@intFromEnum(inst)}); |
| 5222 | try f.object.newline(); | |
| 4423 | try f.newline(); | |
| 5223 | 4424 | try genBodyInner(f, block.body); // no need to restore state, we're noreturn |
| 5224 | 4425 | } |
| 5225 | 4426 | |
| ... | ... | @@ -5230,15 +4431,15 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void { |
| 5230 | 4431 | const then_body = cond_br.then_body; |
| 5231 | 4432 | const else_body = cond_br.else_body; |
| 5232 | 4433 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 5233 | const w = &f.object.code.writer; | |
| 4434 | const w = &f.code.writer; | |
| 5234 | 4435 | |
| 5235 | 4436 | try w.writeAll("if ("); |
| 5236 | try f.writeCValue(w, cond, .Other); | |
| 4437 | try f.writeCValue(w, cond, .other); | |
| 5237 | 4438 | try w.writeAll(") "); |
| 5238 | 4439 | |
| 5239 | 4440 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); |
| 5240 | try f.object.newline(); | |
| 5241 | if (else_body.len > 0) if (f.object.dg.expected_block) |_| | |
| 4441 | try f.newline(); | |
| 4442 | if (else_body.len > 0) if (f.dg.expected_block) |_| | |
| 5242 | 4443 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5243 | 4444 | |
| 5244 | 4445 | // We don't need to use `genBodyResolveState` for the else block, because this instruction is |
| ... | ... | @@ -5256,23 +4457,23 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void { |
| 5256 | 4457 | } |
| 5257 | 4458 | |
| 5258 | 4459 | fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void { |
| 5259 | const pt = f.object.dg.pt; | |
| 4460 | const pt = f.dg.pt; | |
| 5260 | 4461 | const zcu = pt.zcu; |
| 5261 | const gpa = f.object.dg.gpa; | |
| 4462 | const gpa = f.dg.gpa; | |
| 5262 | 4463 | const switch_br = f.air.unwrapSwitch(inst); |
| 5263 | 4464 | const init_condition = try f.resolveInst(switch_br.operand); |
| 5264 | 4465 | try reap(f, inst, &.{switch_br.operand}); |
| 5265 | 4466 | const condition_ty = f.typeOf(switch_br.operand); |
| 5266 | const w = &f.object.code.writer; | |
| 4467 | const w = &f.code.writer; | |
| 5267 | 4468 | |
| 5268 | 4469 | // For dispatches, we will create a local alloc to contain the condition value. |
| 5269 | 4470 | // This may not result in optimal codegen for switch loops, but it minimizes the |
| 5270 | 4471 | // amount of C code we generate, which is probably more desirable here (and is simpler). |
| 5271 | 4472 | const condition = if (is_dispatch_loop) cond: { |
| 5272 | 4473 | const new_local = try f.allocLocal(inst, condition_ty); |
| 5273 | try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition); | |
| 4474 | try f.copyCValue(new_local, init_condition); | |
| 5274 | 4475 | try w.print("zig_switch_{d}_loop:", .{@intFromEnum(inst)}); |
| 5275 | try f.object.newline(); | |
| 4476 | try f.newline(); | |
| 5276 | 4477 | try f.loop_switch_conds.put(gpa, inst, new_local.new_local); |
| 5277 | 4478 | break :cond new_local; |
| 5278 | 4479 | } else init_condition; |
| ... | ... | @@ -5294,9 +4495,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5294 | 4495 | try f.renderType(w, lowered_condition_ty); |
| 5295 | 4496 | try w.writeByte(')'); |
| 5296 | 4497 | } |
| 5297 | try f.writeCValue(w, condition, .Other); | |
| 4498 | try f.writeCValue(w, condition, .other); | |
| 5298 | 4499 | try w.writeAll(") {"); |
| 5299 | f.object.indent(); | |
| 4500 | f.indent(); | |
| 5300 | 4501 | |
| 5301 | 4502 | const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1); |
| 5302 | 4503 | defer gpa.free(liveness.deaths); |
| ... | ... | @@ -5309,7 +4510,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5309 | 4510 | continue; |
| 5310 | 4511 | } |
| 5311 | 4512 | for (case.items) |item| { |
| 5312 | try f.object.newline(); | |
| 4513 | try f.newline(); | |
| 5313 | 4514 | try w.writeAll("case "); |
| 5314 | 4515 | const item_value = try f.air.value(item, pt); |
| 5315 | 4516 | // If `item_value` is a pointer with a known integer address, print the address |
| ... | ... | @@ -5326,28 +4527,28 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5326 | 4527 | try f.renderType(w, .usize); |
| 5327 | 4528 | try w.writeByte(')'); |
| 5328 | 4529 | } |
| 5329 | try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other); | |
| 4530 | try f.dg.renderValue(w, (try f.air.value(item, pt)).?, .other); | |
| 5330 | 4531 | } |
| 5331 | 4532 | try w.writeByte(':'); |
| 5332 | 4533 | } |
| 5333 | 4534 | try w.writeAll(" {"); |
| 5334 | f.object.indent(); | |
| 5335 | try f.object.newline(); | |
| 4535 | f.indent(); | |
| 4536 | try f.newline(); | |
| 5336 | 4537 | if (is_dispatch_loop) { |
| 5337 | 4538 | try w.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx }); |
| 5338 | try f.object.newline(); | |
| 4539 | try f.newline(); | |
| 5339 | 4540 | } |
| 5340 | 4541 | try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); |
| 5341 | try f.object.outdent(); | |
| 4542 | try f.outdent(); | |
| 5342 | 4543 | try w.writeByte('}'); |
| 5343 | if (f.object.dg.expected_block) |_| | |
| 4544 | if (f.dg.expected_block) |_| | |
| 5344 | 4545 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5345 | 4546 | |
| 5346 | 4547 | // The case body must be noreturn so we don't need to insert a break. |
| 5347 | 4548 | } |
| 5348 | 4549 | |
| 5349 | 4550 | const else_body = it.elseBody(); |
| 5350 | try f.object.newline(); | |
| 4551 | try f.newline(); | |
| 5351 | 4552 | |
| 5352 | 4553 | try w.writeAll("default: "); |
| 5353 | 4554 | if (any_range_cases) { |
| ... | ... | @@ -5360,33 +4561,33 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5360 | 4561 | try w.writeAll("if ("); |
| 5361 | 4562 | for (case.items, 0..) |item, item_i| { |
| 5362 | 4563 | if (item_i != 0) try w.writeAll(" || "); |
| 5363 | try f.writeCValue(w, condition, .Other); | |
| 4564 | try f.writeCValue(w, condition, .other); | |
| 5364 | 4565 | try w.writeAll(" == "); |
| 5365 | try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other); | |
| 4566 | try f.dg.renderValue(w, (try f.air.value(item, pt)).?, .other); | |
| 5366 | 4567 | } |
| 5367 | 4568 | for (case.ranges, 0..) |range, range_i| { |
| 5368 | 4569 | if (case.items.len != 0 or range_i != 0) try w.writeAll(" || "); |
| 5369 | 4570 | // "(x >= lower && x <= upper)" |
| 5370 | 4571 | try w.writeByte('('); |
| 5371 | try f.writeCValue(w, condition, .Other); | |
| 4572 | try f.writeCValue(w, condition, .other); | |
| 5372 | 4573 | try w.writeAll(" >= "); |
| 5373 | try f.object.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .Other); | |
| 4574 | try f.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .other); | |
| 5374 | 4575 | try w.writeAll(" && "); |
| 5375 | try f.writeCValue(w, condition, .Other); | |
| 4576 | try f.writeCValue(w, condition, .other); | |
| 5376 | 4577 | try w.writeAll(" <= "); |
| 5377 | try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other); | |
| 4578 | try f.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .other); | |
| 5378 | 4579 | try w.writeByte(')'); |
| 5379 | 4580 | } |
| 5380 | 4581 | try w.writeAll(") {"); |
| 5381 | f.object.indent(); | |
| 5382 | try f.object.newline(); | |
| 4582 | f.indent(); | |
| 4583 | try f.newline(); | |
| 5383 | 4584 | if (is_dispatch_loop) { |
| 5384 | 4585 | try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx }); |
| 5385 | 4586 | } |
| 5386 | 4587 | try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); |
| 5387 | try f.object.outdent(); | |
| 4588 | try f.outdent(); | |
| 5388 | 4589 | try w.writeByte('}'); |
| 5389 | if (f.object.dg.expected_block) |_| | |
| 4590 | if (f.dg.expected_block) |_| | |
| 5390 | 4591 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5391 | 4592 | } |
| 5392 | 4593 | } |
| ... | ... | @@ -5400,16 +4601,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5400 | 4601 | try die(f, inst, death.toRef()); |
| 5401 | 4602 | } |
| 5402 | 4603 | try genBody(f, else_body); |
| 5403 | if (f.object.dg.expected_block) |_| | |
| 4604 | if (f.dg.expected_block) |_| | |
| 5404 | 4605 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5405 | } else try airUnreach(&f.object); | |
| 5406 | try f.object.newline(); | |
| 5407 | try f.object.outdent(); | |
| 4606 | } else try airUnreach(f); | |
| 4607 | try f.newline(); | |
| 4608 | try f.outdent(); | |
| 5408 | 4609 | try w.writeAll("}\n"); |
| 5409 | 4610 | } |
| 5410 | 4611 | |
| 5411 | 4612 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { |
| 5412 | const dg = f.object.dg; | |
| 4613 | const dg = f.dg; | |
| 5413 | 4614 | const target = &dg.mod.resolved_target.result; |
| 5414 | 4615 | return switch (constraint[0]) { |
| 5415 | 4616 | '{' => true, |
| ... | ... | @@ -5429,28 +4630,28 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool |
| 5429 | 4630 | } |
| 5430 | 4631 | |
| 5431 | 4632 | fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5432 | const pt = f.object.dg.pt; | |
| 4633 | const pt = f.dg.pt; | |
| 5433 | 4634 | const zcu = pt.zcu; |
| 5434 | 4635 | const unwrapped_asm = f.air.unwrapAsm(inst); |
| 5435 | 4636 | const is_volatile = unwrapped_asm.is_volatile; |
| 5436 | const gpa = f.object.dg.gpa; | |
| 4637 | const gpa = f.dg.gpa; | |
| 5437 | 4638 | const outputs = unwrapped_asm.outputs; |
| 5438 | 4639 | const inputs = unwrapped_asm.inputs; |
| 5439 | 4640 | |
| 5440 | 4641 | const result = result: { |
| 5441 | const w = &f.object.code.writer; | |
| 4642 | const w = &f.code.writer; | |
| 5442 | 4643 | const inst_ty = f.typeOfIndex(inst); |
| 5443 | const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: { | |
| 4644 | const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { | |
| 5444 | 4645 | const inst_local = try f.allocLocalValue(.{ |
| 5445 | .ctype = try f.ctypeFromType(inst_ty, .complete), | |
| 5446 | .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)), | |
| 4646 | .type = inst_ty, | |
| 4647 | .alignment = .none, | |
| 5447 | 4648 | }); |
| 5448 | 4649 | if (f.wantSafety()) { |
| 5449 | try f.writeCValue(w, inst_local, .Other); | |
| 4650 | try f.writeCValue(w, inst_local, .other); | |
| 5450 | 4651 | try w.writeAll(" = "); |
| 5451 | try f.writeCValue(w, .{ .undef = inst_ty }, .Other); | |
| 4652 | try f.writeCValue(w, .{ .undef = inst_ty }, .other); | |
| 5452 | 4653 | try w.writeByte(';'); |
| 5453 | try f.object.newline(); | |
| 4654 | try f.newline(); | |
| 5454 | 4655 | } |
| 5455 | 4656 | break :local inst_local; |
| 5456 | 4657 | } else .none; |
| ... | ... | @@ -5471,20 +4672,20 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5471 | 4672 | const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu); |
| 5472 | 4673 | try w.writeAll("register "); |
| 5473 | 4674 | const output_local = try f.allocLocalValue(.{ |
| 5474 | .ctype = try f.ctypeFromType(output_ty, .complete), | |
| 5475 | .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)), | |
| 4675 | .type = output_ty, | |
| 4676 | .alignment = .none, | |
| 5476 | 4677 | }); |
| 5477 | 4678 | try f.allocs.put(gpa, output_local.new_local, false); |
| 5478 | try f.object.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none, .complete); | |
| 4679 | try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none); | |
| 5479 | 4680 | try w.writeAll(" __asm(\""); |
| 5480 | 4681 | try w.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| 5481 | 4682 | try w.writeAll("\")"); |
| 5482 | 4683 | if (f.wantSafety()) { |
| 5483 | 4684 | try w.writeAll(" = "); |
| 5484 | try f.writeCValue(w, .{ .undef = output_ty }, .Other); | |
| 4685 | try f.writeCValue(w, .{ .undef = output_ty }, .other); | |
| 5485 | 4686 | } |
| 5486 | 4687 | try w.writeByte(';'); |
| 5487 | try f.object.newline(); | |
| 4688 | try f.newline(); | |
| 5488 | 4689 | } |
| 5489 | 4690 | } |
| 5490 | 4691 | |
| ... | ... | @@ -5504,29 +4705,29 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5504 | 4705 | const input_ty = f.typeOf(input.operand); |
| 5505 | 4706 | if (is_reg) try w.writeAll("register "); |
| 5506 | 4707 | const input_local = try f.allocLocalValue(.{ |
| 5507 | .ctype = try f.ctypeFromType(input_ty, .complete), | |
| 5508 | .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)), | |
| 4708 | .type = input_ty, | |
| 4709 | .alignment = .none, | |
| 5509 | 4710 | }); |
| 5510 | 4711 | try f.allocs.put(gpa, input_local.new_local, false); |
| 5511 | 4712 | // Do not render the declaration as `const` qualified if we're generating an |
| 5512 | 4713 | // explicit `register` local, as GCC will ignore the constraint completely. |
| 5513 | try f.object.dg.renderTypeAndName(w, input_ty, input_local, if (is_reg) .{} else Const, .none, .complete); | |
| 4714 | try f.dg.renderTypeAndName(w, input_ty, input_local, .{ .@"const" = is_reg }, .none); | |
| 5514 | 4715 | if (is_reg) { |
| 5515 | 4716 | try w.writeAll(" __asm(\""); |
| 5516 | 4717 | try w.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| 5517 | 4718 | try w.writeAll("\")"); |
| 5518 | 4719 | } |
| 5519 | 4720 | try w.writeAll(" = "); |
| 5520 | try f.writeCValue(w, input_val, .Other); | |
| 4721 | try f.writeCValue(w, input_val, .other); | |
| 5521 | 4722 | try w.writeByte(';'); |
| 5522 | try f.object.newline(); | |
| 4723 | try f.newline(); | |
| 5523 | 4724 | } |
| 5524 | 4725 | } |
| 5525 | 4726 | |
| 5526 | 4727 | { |
| 5527 | 4728 | const asm_source = unwrapped_asm.source; |
| 5528 | 4729 | |
| 5529 | var stack = std.heap.stackFallback(256, f.object.dg.gpa); | |
| 4730 | var stack = std.heap.stackFallback(256, f.dg.gpa); | |
| 5530 | 4731 | const allocator = stack.get(); |
| 5531 | 4732 | const fixed_asm_source = try allocator.alloc(u8, asm_source.len); |
| 5532 | 4733 | defer allocator.free(fixed_asm_source); |
| ... | ... | @@ -5592,10 +4793,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5592 | 4793 | const is_reg = constraint[1] == '{'; |
| 5593 | 4794 | try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)}); |
| 5594 | 4795 | if (is_reg) { |
| 5595 | try f.writeCValue(w, .{ .local = locals_index }, .Other); | |
| 4796 | try f.writeCValue(w, .{ .local = locals_index }, .other); | |
| 5596 | 4797 | locals_index += 1; |
| 5597 | 4798 | } else if (output.operand == .none) { |
| 5598 | try f.writeCValue(w, inst_local, .FunctionArgument); | |
| 4799 | try f.writeCValue(w, inst_local, .other); | |
| 5599 | 4800 | } else { |
| 5600 | 4801 | try f.writeCValueDeref(w, try f.resolveInst(output.operand)); |
| 5601 | 4802 | } |
| ... | ... | @@ -5619,57 +4820,54 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5619 | 4820 | const input_local_idx = locals_index; |
| 5620 | 4821 | locals_index += 1; |
| 5621 | 4822 | break :local .{ .local = input_local_idx }; |
| 5622 | } else input_val, .Other); | |
| 4823 | } else input_val, .other); | |
| 5623 | 4824 | try w.writeByte(')'); |
| 5624 | 4825 | } |
| 5625 | 4826 | try w.writeByte(':'); |
| 5626 | 4827 | const ip = &zcu.intern_pool; |
| 5627 | const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; | |
| 5628 | const struct_type: Type = .fromInterned(aggregate.ty); | |
| 5629 | switch (aggregate.storage) { | |
| 5630 | .elems => |elems| for (elems, 0..) |elem, i| switch (elem) { | |
| 5631 | .bool_true => { | |
| 5632 | const field_name = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 5633 | assert(field_name.len != 0); | |
| 5634 | ||
| 5635 | const target = &f.object.dg.mod.resolved_target.result; | |
| 5636 | var c_name_buf: [16]u8 = undefined; | |
| 5637 | const name = | |
| 5638 | if ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'r') name: { | |
| 5639 | // Convert "rN" to "$N" | |
| 5640 | const c_name = (&c_name_buf)[0..field_name.len]; | |
| 5641 | @memcpy(c_name, field_name); | |
| 5642 | c_name_buf[0] = '$'; | |
| 5643 | break :name c_name; | |
| 5644 | } else if ((target.cpu.arch.isMIPS() and (mem.startsWith(u8, field_name, "fcc") or field_name[0] == 'w')) or | |
| 5645 | ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'f') or | |
| 5646 | (target.cpu.arch == .kvx and !mem.eql(u8, field_name, "memory"))) name: { | |
| 5647 | // "$" prefix for these registers | |
| 5648 | c_name_buf[0] = '$'; | |
| 5649 | @memcpy((&c_name_buf)[1..][0..field_name.len], field_name); | |
| 5650 | break :name (&c_name_buf)[0 .. 1 + field_name.len]; | |
| 5651 | } else if (target.cpu.arch.isSPARC() and | |
| 5652 | (mem.eql(u8, field_name, "ccr") or mem.eql(u8, field_name, "icc") or mem.eql(u8, field_name, "xcc"))) name: { | |
| 5653 | // C compilers just use `icc` to encompass all of these. | |
| 5654 | break :name "icc"; | |
| 5655 | } else field_name; | |
| 5656 | ||
| 5657 | try w.print(" {f}", .{fmtStringLiteral(name, null)}); | |
| 5658 | (try w.writableArray(1))[0] = ','; | |
| 5659 | }, | |
| 5660 | .bool_false => continue, | |
| 5661 | else => unreachable, | |
| 5662 | }, | |
| 5663 | .repeated_elem => |elem| switch (elem) { | |
| 5664 | .bool_true => @panic("TODO"), | |
| 5665 | .bool_false => {}, | |
| 5666 | else => unreachable, | |
| 5667 | }, | |
| 5668 | .bytes => @panic("TODO"), | |
| 4828 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 4829 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 4830 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 4831 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 4832 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 4833 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 4834 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 4835 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 4836 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 4837 | 0 => continue, // field is false | |
| 4838 | 1 => {}, // field is true | |
| 4839 | } | |
| 4840 | const field_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 4841 | assert(field_name.len != 0); | |
| 4842 | ||
| 4843 | const target = &f.dg.mod.resolved_target.result; | |
| 4844 | var c_name_buf: [16]u8 = undefined; | |
| 4845 | const name = | |
| 4846 | if ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'r') name: { | |
| 4847 | // Convert "rN" to "$N" | |
| 4848 | const c_name = (&c_name_buf)[0..field_name.len]; | |
| 4849 | @memcpy(c_name, field_name); | |
| 4850 | c_name_buf[0] = '$'; | |
| 4851 | break :name c_name; | |
| 4852 | } else if ((target.cpu.arch.isMIPS() and (mem.startsWith(u8, field_name, "fcc") or field_name[0] == 'w')) or | |
| 4853 | ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'f') or | |
| 4854 | (target.cpu.arch == .kvx and !mem.eql(u8, field_name, "memory"))) name: { | |
| 4855 | // "$" prefix for these registers | |
| 4856 | c_name_buf[0] = '$'; | |
| 4857 | @memcpy((&c_name_buf)[1..][0..field_name.len], field_name); | |
| 4858 | break :name (&c_name_buf)[0 .. 1 + field_name.len]; | |
| 4859 | } else if (target.cpu.arch.isSPARC() and | |
| 4860 | (mem.eql(u8, field_name, "ccr") or mem.eql(u8, field_name, "icc") or mem.eql(u8, field_name, "xcc"))) name: { | |
| 4861 | // C compilers just use `icc` to encompass all of these. | |
| 4862 | break :name "icc"; | |
| 4863 | } else field_name; | |
| 4864 | ||
| 4865 | try w.print(" {f}", .{fmtStringLiteral(name, null)}); | |
| 4866 | (try w.writableArray(1))[0] = ','; | |
| 5669 | 4867 | } |
| 5670 | 4868 | w.undo(1); // erase the last comma |
| 5671 | 4869 | try w.writeAll(");"); |
| 5672 | try f.object.newline(); | |
| 4870 | try f.newline(); | |
| 5673 | 4871 | |
| 5674 | 4872 | locals_index = locals_begin; |
| 5675 | 4873 | it = unwrapped_asm.iterateOutputs(); |
| ... | ... | @@ -5683,10 +4881,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5683 | 4881 | else |
| 5684 | 4882 | try f.resolveInst(output.operand)); |
| 5685 | 4883 | try w.writeAll(" = "); |
| 5686 | try f.writeCValue(w, .{ .local = locals_index }, .Other); | |
| 4884 | try f.writeCValue(w, .{ .local = locals_index }, .other); | |
| 5687 | 4885 | locals_index += 1; |
| 5688 | 4886 | try w.writeByte(';'); |
| 5689 | try f.object.newline(); | |
| 4887 | try f.newline(); | |
| 5690 | 4888 | } |
| 5691 | 4889 | } |
| 5692 | 4890 | |
| ... | ... | @@ -5708,147 +4906,145 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5708 | 4906 | fn airIsNull( |
| 5709 | 4907 | f: *Function, |
| 5710 | 4908 | inst: Air.Inst.Index, |
| 5711 | operator: std.math.CompareOperator, | |
| 4909 | operator: enum { eq, neq }, | |
| 5712 | 4910 | is_ptr: bool, |
| 5713 | 4911 | ) !CValue { |
| 5714 | const pt = f.object.dg.pt; | |
| 4912 | const pt = f.dg.pt; | |
| 5715 | 4913 | const zcu = pt.zcu; |
| 5716 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 5717 | 4914 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5718 | 4915 | |
| 5719 | const w = &f.object.code.writer; | |
| 4916 | const w = &f.code.writer; | |
| 5720 | 4917 | const operand = try f.resolveInst(un_op); |
| 5721 | 4918 | try reap(f, inst, &.{un_op}); |
| 5722 | 4919 | |
| 5723 | 4920 | const local = try f.allocLocal(inst, .bool); |
| 5724 | const a = try Assignment.start(f, w, .bool); | |
| 5725 | try f.writeCValue(w, local, .Other); | |
| 5726 | try a.assign(f, w); | |
| 4921 | try f.writeCValue(w, local, .other); | |
| 4922 | try w.writeAll(" = "); | |
| 5727 | 4923 | |
| 5728 | 4924 | const operand_ty = f.typeOf(un_op); |
| 5729 | 4925 | const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 5730 | const opt_ctype = try f.ctypeFromType(optional_ty, .complete); | |
| 5731 | const rhs = switch (opt_ctype.info(ctype_pool)) { | |
| 5732 | .basic, .pointer => rhs: { | |
| 5733 | if (is_ptr) | |
| 5734 | try f.writeCValueDeref(w, operand) | |
| 5735 | else | |
| 5736 | try f.writeCValue(w, operand, .Other); | |
| 5737 | break :rhs if (opt_ctype.isBool()) | |
| 5738 | "true" | |
| 5739 | else if (opt_ctype.isInteger()) | |
| 5740 | "0" | |
| 5741 | else | |
| 5742 | "NULL"; | |
| 4926 | ||
| 4927 | const pre: []const u8, const maybe_field: ?[]const u8, const post: []const u8 = switch (operator) { | |
| 4928 | // zig fmt: off | |
| 4929 | .eq => switch (CType.classifyOptional(optional_ty, zcu)) { | |
| 4930 | .npv_payload => unreachable, // opv optional | |
| 4931 | .error_set => .{ "", null, " == 0" }, | |
| 4932 | .ptr_like => .{ "", null, " == NULL" }, | |
| 4933 | .slice_like => .{ "", "ptr", " == NULL" }, | |
| 4934 | .opv_payload => .{ "", "is_null", "" }, | |
| 4935 | .@"struct" => .{ "", "is_null", "" }, | |
| 5743 | 4936 | }, |
| 5744 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 5745 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { | |
| 5746 | .is_null, .payload => rhs: { | |
| 5747 | if (is_ptr) | |
| 5748 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }) | |
| 5749 | else | |
| 5750 | try f.writeCValueMember(w, operand, .{ .identifier = "is_null" }); | |
| 5751 | break :rhs "true"; | |
| 5752 | }, | |
| 5753 | .ptr, .len => rhs: { | |
| 5754 | if (is_ptr) | |
| 5755 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "ptr" }) | |
| 5756 | else | |
| 5757 | try f.writeCValueMember(w, operand, .{ .identifier = "ptr" }); | |
| 5758 | break :rhs "NULL"; | |
| 5759 | }, | |
| 5760 | else => unreachable, | |
| 4937 | .neq => switch (CType.classifyOptional(optional_ty, zcu)) { | |
| 4938 | .npv_payload => unreachable, // opv optional | |
| 4939 | .error_set => .{ "", null, " != 0" }, | |
| 4940 | .ptr_like => .{ "", null, " != NULL" }, | |
| 4941 | .slice_like => .{ "", "ptr", " != NULL" }, | |
| 4942 | .opv_payload => .{ "!", "is_null", "" }, | |
| 4943 | .@"struct" => .{ "!", "is_null", "" }, | |
| 5761 | 4944 | }, |
| 4945 | // zig fmt: on | |
| 5762 | 4946 | }; |
| 5763 | try w.writeAll(compareOperatorC(operator)); | |
| 5764 | try w.writeAll(rhs); | |
| 5765 | try a.end(f, w); | |
| 4947 | ||
| 4948 | try w.writeAll(pre); | |
| 4949 | if (maybe_field) |field| { | |
| 4950 | if (is_ptr) { | |
| 4951 | try f.writeCValueDerefMember(w, operand, .{ .identifier = field }); | |
| 4952 | } else { | |
| 4953 | try f.writeCValueMember(w, operand, .{ .identifier = field }); | |
| 4954 | } | |
| 4955 | } else { | |
| 4956 | if (is_ptr) { | |
| 4957 | try f.writeCValueDeref(w, operand); | |
| 4958 | } else { | |
| 4959 | try f.writeCValue(w, operand, .other); | |
| 4960 | } | |
| 4961 | } | |
| 4962 | try w.writeAll(post); | |
| 4963 | ||
| 4964 | try w.writeByte(';'); | |
| 4965 | try f.newline(); | |
| 5766 | 4966 | return local; |
| 5767 | 4967 | } |
| 5768 | 4968 | |
| 5769 | 4969 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 5770 | const pt = f.object.dg.pt; | |
| 4970 | const pt = f.dg.pt; | |
| 5771 | 4971 | const zcu = pt.zcu; |
| 5772 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 5773 | 4972 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5774 | 4973 | |
| 5775 | 4974 | const inst_ty = f.typeOfIndex(inst); |
| 5776 | 4975 | const operand_ty = f.typeOf(ty_op.operand); |
| 5777 | 4976 | const opt_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 5778 | const opt_ctype = try f.ctypeFromType(opt_ty, .complete); | |
| 5779 | if (opt_ctype.isBool()) return if (is_ptr) .{ .undef = inst_ty } else .none; | |
| 5780 | 4977 | |
| 5781 | 4978 | const operand = try f.resolveInst(ty_op.operand); |
| 5782 | switch (opt_ctype.info(ctype_pool)) { | |
| 5783 | .basic, .pointer => return f.moveCValue(inst, inst_ty, operand), | |
| 5784 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 5785 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { | |
| 5786 | .is_null, .payload => { | |
| 5787 | const w = &f.object.code.writer; | |
| 5788 | const local = try f.allocLocal(inst, inst_ty); | |
| 5789 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 5790 | try f.writeCValue(w, local, .Other); | |
| 5791 | try a.assign(f, w); | |
| 5792 | if (is_ptr) { | |
| 5793 | try w.writeByte('&'); | |
| 5794 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); | |
| 5795 | } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); | |
| 5796 | try a.end(f, w); | |
| 5797 | return local; | |
| 5798 | }, | |
| 5799 | .ptr, .len => return f.moveCValue(inst, inst_ty, operand), | |
| 5800 | else => unreachable, | |
| 4979 | ||
| 4980 | switch (CType.classifyOptional(opt_ty, zcu)) { | |
| 4981 | .npv_payload => unreachable, // opv optional | |
| 4982 | ||
| 4983 | .opv_payload => return if (is_ptr) .{ .undef = inst_ty } else .none, | |
| 4984 | ||
| 4985 | .error_set, | |
| 4986 | .ptr_like, | |
| 4987 | .slice_like, | |
| 4988 | => return f.moveCValue(inst, inst_ty, operand), | |
| 4989 | ||
| 4990 | .@"struct" => { | |
| 4991 | const w = &f.code.writer; | |
| 4992 | const local = try f.allocLocal(inst, inst_ty); | |
| 4993 | try f.writeCValue(w, local, .other); | |
| 4994 | try w.writeAll(" = "); | |
| 4995 | if (is_ptr) { | |
| 4996 | try w.writeByte('&'); | |
| 4997 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); | |
| 4998 | } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); | |
| 4999 | try w.writeByte(';'); | |
| 5000 | try f.newline(); | |
| 5001 | return local; | |
| 5801 | 5002 | }, |
| 5802 | 5003 | } |
| 5803 | 5004 | } |
| 5804 | 5005 | |
| 5805 | 5006 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5806 | const pt = f.object.dg.pt; | |
| 5007 | const pt = f.dg.pt; | |
| 5807 | 5008 | const zcu = pt.zcu; |
| 5808 | 5009 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5809 | const w = &f.object.code.writer; | |
| 5010 | const w = &f.code.writer; | |
| 5810 | 5011 | const operand = try f.resolveInst(ty_op.operand); |
| 5811 | 5012 | try reap(f, inst, &.{ty_op.operand}); |
| 5812 | 5013 | const operand_ty = f.typeOf(ty_op.operand); |
| 5014 | const opt_ty = operand_ty.childType(zcu); | |
| 5813 | 5015 | |
| 5814 | 5016 | const inst_ty = f.typeOfIndex(inst); |
| 5815 | const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete); | |
| 5816 | switch (opt_ctype.info(&f.object.dg.ctype_pool)) { | |
| 5817 | .basic => { | |
| 5818 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5819 | try f.writeCValueDeref(w, operand); | |
| 5820 | try a.assign(f, w); | |
| 5821 | try f.object.dg.renderValue(w, Value.false, .Other); | |
| 5822 | try a.end(f, w); | |
| 5823 | return .none; | |
| 5824 | }, | |
| 5825 | .pointer => { | |
| 5826 | if (f.liveness.isUnused(inst)) return .none; | |
| 5827 | const local = try f.allocLocal(inst, inst_ty); | |
| 5828 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5829 | try f.writeCValue(w, local, .Other); | |
| 5830 | try a.assign(f, w); | |
| 5831 | try f.writeCValue(w, operand, .Other); | |
| 5832 | try a.end(f, w); | |
| 5833 | return local; | |
| 5017 | ||
| 5018 | switch (CType.classifyOptional(opt_ty, zcu)) { | |
| 5019 | .npv_payload => unreachable, // opv optional | |
| 5020 | ||
| 5021 | .opv_payload => { | |
| 5022 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); | |
| 5023 | try w.writeAll(" = "); | |
| 5024 | try f.dg.renderValue(w, .false, .other); | |
| 5025 | try w.writeByte(';'); | |
| 5026 | try f.newline(); | |
| 5027 | return .{ .undef = inst_ty }; | |
| 5834 | 5028 | }, |
| 5835 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 5836 | .aggregate => { | |
| 5837 | { | |
| 5838 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5839 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); | |
| 5840 | try a.assign(f, w); | |
| 5841 | try f.object.dg.renderValue(w, Value.false, .Other); | |
| 5842 | try a.end(f, w); | |
| 5843 | } | |
| 5029 | ||
| 5030 | .error_set, | |
| 5031 | .ptr_like, | |
| 5032 | .slice_like, | |
| 5033 | => return f.moveCValue(inst, inst_ty, operand), | |
| 5034 | ||
| 5035 | .@"struct" => { | |
| 5036 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); | |
| 5037 | try w.writeAll(" = "); | |
| 5038 | try f.dg.renderValue(w, .false, .other); | |
| 5039 | try w.writeByte(';'); | |
| 5040 | try f.newline(); | |
| 5844 | 5041 | if (f.liveness.isUnused(inst)) return .none; |
| 5845 | 5042 | const local = try f.allocLocal(inst, inst_ty); |
| 5846 | const a = try Assignment.start(f, w, opt_ctype); | |
| 5847 | try f.writeCValue(w, local, .Other); | |
| 5848 | try a.assign(f, w); | |
| 5849 | try w.writeByte('&'); | |
| 5043 | try f.writeCValue(w, local, .other); | |
| 5044 | try w.writeAll(" = &"); | |
| 5850 | 5045 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); |
| 5851 | try a.end(f, w); | |
| 5046 | try w.writeByte(';'); | |
| 5047 | try f.newline(); | |
| 5852 | 5048 | return local; |
| 5853 | 5049 | }, |
| 5854 | 5050 | } |
| ... | ... | @@ -5870,12 +5066,12 @@ fn fieldLocation( |
| 5870 | 5066 | .struct_type => { |
| 5871 | 5067 | const loaded_struct = ip.loadStructType(container_ty.toIntern()); |
| 5872 | 5068 | return switch (loaded_struct.layout) { |
| 5873 | .auto, .@"extern" => if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 5069 | .auto, .@"extern" => if (!container_ty.hasRuntimeBits(zcu)) | |
| 5874 | 5070 | .begin |
| 5875 | else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) | |
| 5876 | .{ .byte_offset = loaded_struct.offsets.get(ip)[field_index] } | |
| 5071 | else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) | |
| 5072 | .{ .byte_offset = loaded_struct.field_offsets.get(ip)[field_index] } | |
| 5877 | 5073 | else |
| 5878 | .{ .field = .{ .identifier = loaded_struct.fieldName(ip, field_index).toSlice(ip) } }, | |
| 5074 | .{ .field = .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) } }, | |
| 5879 | 5075 | .@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) |
| 5880 | 5076 | .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) + |
| 5881 | 5077 | container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } |
| ... | ... | @@ -5883,27 +5079,29 @@ fn fieldLocation( |
| 5883 | 5079 | .begin, |
| 5884 | 5080 | }; |
| 5885 | 5081 | }, |
| 5886 | .tuple_type => return if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 5082 | .tuple_type => return if (!container_ty.hasRuntimeBits(zcu)) | |
| 5887 | 5083 | .begin |
| 5888 | else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) | |
| 5084 | else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) | |
| 5889 | 5085 | .{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) } |
| 5890 | 5086 | else |
| 5891 | 5087 | .{ .field = .{ .field = field_index } }, |
| 5892 | 5088 | .union_type => { |
| 5893 | 5089 | const loaded_union = ip.loadUnionType(container_ty.toIntern()); |
| 5894 | switch (loaded_union.flagsUnordered(ip).layout) { | |
| 5895 | .auto, .@"extern" => { | |
| 5090 | switch (loaded_union.layout) { | |
| 5091 | .auto => { | |
| 5896 | 5092 | const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); |
| 5897 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 5898 | return if (loaded_union.hasTag(ip) and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) | |
| 5899 | .{ .field = .{ .identifier = "payload" } } | |
| 5900 | else | |
| 5901 | .begin; | |
| 5902 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; | |
| 5903 | return .{ .field = if (loaded_union.hasTag(ip)) | |
| 5904 | .{ .payload_identifier = field_name.toSlice(ip) } | |
| 5905 | else | |
| 5906 | .{ .identifier = field_name.toSlice(ip) } }; | |
| 5093 | if (!field_ty.hasRuntimeBits(zcu)) { | |
| 5094 | if (container_ty.unionHasAllZeroBitFieldTypes(zcu)) return .begin; | |
| 5095 | return .{ .field = .{ .identifier = "payload" } }; | |
| 5096 | } | |
| 5097 | const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; | |
| 5098 | return .{ .field = .{ .payload_identifier = field_name.toSlice(ip) } }; | |
| 5099 | }, | |
| 5100 | .@"extern" => { | |
| 5101 | const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 5102 | if (!field_ty.hasRuntimeBits(zcu)) return .begin; | |
| 5103 | const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; | |
| 5104 | return .{ .field = .{ .identifier = field_name.toSlice(ip) } }; | |
| 5907 | 5105 | }, |
| 5908 | 5106 | .@"packed" => return .begin, |
| 5909 | 5107 | } |
| ... | ... | @@ -5940,7 +5138,7 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue |
| 5940 | 5138 | } |
| 5941 | 5139 | |
| 5942 | 5140 | fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5943 | const pt = f.object.dg.pt; | |
| 5141 | const pt = f.dg.pt; | |
| 5944 | 5142 | const zcu = pt.zcu; |
| 5945 | 5143 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5946 | 5144 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| ... | ... | @@ -5952,26 +5150,26 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5952 | 5150 | const field_ptr_val = try f.resolveInst(extra.field_ptr); |
| 5953 | 5151 | try reap(f, inst, &.{extra.field_ptr}); |
| 5954 | 5152 | |
| 5955 | const w = &f.object.code.writer; | |
| 5153 | const w = &f.code.writer; | |
| 5956 | 5154 | const local = try f.allocLocal(inst, container_ptr_ty); |
| 5957 | try f.writeCValue(w, local, .Other); | |
| 5155 | try f.writeCValue(w, local, .other); | |
| 5958 | 5156 | try w.writeAll(" = ("); |
| 5959 | 5157 | try f.renderType(w, container_ptr_ty); |
| 5960 | 5158 | try w.writeByte(')'); |
| 5961 | 5159 | |
| 5962 | 5160 | switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) { |
| 5963 | .begin => try f.writeCValue(w, field_ptr_val, .Other), | |
| 5161 | .begin => try f.writeCValue(w, field_ptr_val, .other), | |
| 5964 | 5162 | .field => |field| { |
| 5965 | 5163 | const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8); |
| 5966 | 5164 | |
| 5967 | 5165 | try w.writeAll("(("); |
| 5968 | 5166 | try f.renderType(w, u8_ptr_ty); |
| 5969 | 5167 | try w.writeByte(')'); |
| 5970 | try f.writeCValue(w, field_ptr_val, .Other); | |
| 5168 | try f.writeCValue(w, field_ptr_val, .other); | |
| 5971 | 5169 | try w.writeAll(" - offsetof("); |
| 5972 | 5170 | try f.renderType(w, container_ty); |
| 5973 | 5171 | try w.writeAll(", "); |
| 5974 | try f.writeCValue(w, field, .Other); | |
| 5172 | try f.writeCValue(w, field, .other); | |
| 5975 | 5173 | try w.writeAll("))"); |
| 5976 | 5174 | }, |
| 5977 | 5175 | .byte_offset => |byte_offset| { |
| ... | ... | @@ -5980,7 +5178,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5980 | 5178 | try w.writeAll("(("); |
| 5981 | 5179 | try f.renderType(w, u8_ptr_ty); |
| 5982 | 5180 | try w.writeByte(')'); |
| 5983 | try f.writeCValue(w, field_ptr_val, .Other); | |
| 5181 | try f.writeCValue(w, field_ptr_val, .other); | |
| 5984 | 5182 | try w.print(" - {f})", .{ |
| 5985 | 5183 | try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)), |
| 5986 | 5184 | }); |
| ... | ... | @@ -5988,7 +5186,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5988 | 5186 | } |
| 5989 | 5187 | |
| 5990 | 5188 | try w.writeByte(';'); |
| 5991 | try f.object.newline(); | |
| 5189 | try f.newline(); | |
| 5992 | 5190 | return local; |
| 5993 | 5191 | } |
| 5994 | 5192 | |
| ... | ... | @@ -5999,23 +5197,19 @@ fn fieldPtr( |
| 5999 | 5197 | container_ptr_val: CValue, |
| 6000 | 5198 | field_index: u32, |
| 6001 | 5199 | ) !CValue { |
| 6002 | const pt = f.object.dg.pt; | |
| 5200 | const pt = f.dg.pt; | |
| 6003 | 5201 | const zcu = pt.zcu; |
| 6004 | const container_ty = container_ptr_ty.childType(zcu); | |
| 6005 | 5202 | const field_ptr_ty = f.typeOfIndex(inst); |
| 6006 | 5203 | |
| 6007 | // Ensure complete type definition is visible before accessing fields. | |
| 6008 | _ = try f.ctypeFromType(container_ty, .complete); | |
| 6009 | ||
| 6010 | const w = &f.object.code.writer; | |
| 5204 | const w = &f.code.writer; | |
| 6011 | 5205 | const local = try f.allocLocal(inst, field_ptr_ty); |
| 6012 | try f.writeCValue(w, local, .Other); | |
| 5206 | try f.writeCValue(w, local, .other); | |
| 6013 | 5207 | try w.writeAll(" = ("); |
| 6014 | 5208 | try f.renderType(w, field_ptr_ty); |
| 6015 | 5209 | try w.writeByte(')'); |
| 6016 | 5210 | |
| 6017 | 5211 | switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) { |
| 6018 | .begin => try f.writeCValue(w, container_ptr_val, .Other), | |
| 5212 | .begin => try f.writeCValue(w, container_ptr_val, .other), | |
| 6019 | 5213 | .field => |field| { |
| 6020 | 5214 | try w.writeByte('&'); |
| 6021 | 5215 | try f.writeCValueDerefMember(w, container_ptr_val, field); |
| ... | ... | @@ -6026,7 +5220,7 @@ fn fieldPtr( |
| 6026 | 5220 | try w.writeAll("(("); |
| 6027 | 5221 | try f.renderType(w, u8_ptr_ty); |
| 6028 | 5222 | try w.writeByte(')'); |
| 6029 | try f.writeCValue(w, container_ptr_val, .Other); | |
| 5223 | try f.writeCValue(w, container_ptr_val, .other); | |
| 6030 | 5224 | try w.print(" + {f})", .{ |
| 6031 | 5225 | try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)), |
| 6032 | 5226 | }); |
| ... | ... | @@ -6034,61 +5228,51 @@ fn fieldPtr( |
| 6034 | 5228 | } |
| 6035 | 5229 | |
| 6036 | 5230 | try w.writeByte(';'); |
| 6037 | try f.object.newline(); | |
| 5231 | try f.newline(); | |
| 6038 | 5232 | return local; |
| 6039 | 5233 | } |
| 6040 | 5234 | |
| 6041 | 5235 | fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6042 | const pt = f.object.dg.pt; | |
| 5236 | const pt = f.dg.pt; | |
| 6043 | 5237 | const zcu = pt.zcu; |
| 6044 | 5238 | const ip = &zcu.intern_pool; |
| 6045 | 5239 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6046 | 5240 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 6047 | 5241 | |
| 6048 | 5242 | const inst_ty = f.typeOfIndex(inst); |
| 6049 | if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 6050 | try reap(f, inst, &.{extra.struct_operand}); | |
| 6051 | return .none; | |
| 6052 | } | |
| 5243 | assert(inst_ty.hasRuntimeBits(zcu)); | |
| 6053 | 5244 | |
| 6054 | 5245 | const struct_byval = try f.resolveInst(extra.struct_operand); |
| 6055 | 5246 | try reap(f, inst, &.{extra.struct_operand}); |
| 6056 | 5247 | const struct_ty = f.typeOf(extra.struct_operand); |
| 6057 | const w = &f.object.code.writer; | |
| 6058 | ||
| 6059 | // Ensure complete type definition is visible before accessing fields. | |
| 6060 | _ = try f.ctypeFromType(struct_ty, .complete); | |
| 5248 | const w = &f.code.writer; | |
| 6061 | 5249 | |
| 6062 | 5250 | assert(struct_ty.containerLayout(zcu) != .@"packed"); // `Air.Legalize.Feature.expand_packed_struct_field_val` handles this case |
| 6063 | 5251 | const field_name: CValue = switch (ip.indexToKey(struct_ty.toIntern())) { |
| 6064 | 5252 | .struct_type => .{ .identifier = struct_ty.structFieldName(extra.field_index, zcu).unwrap().?.toSlice(ip) }, |
| 6065 | 5253 | .union_type => name: { |
| 6066 | 5254 | const union_type = ip.loadUnionType(struct_ty.toIntern()); |
| 6067 | const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_ty); | |
| 5255 | const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); | |
| 6068 | 5256 | const field_name_str = enum_tag_ty.enumFieldName(extra.field_index, zcu).toSlice(ip); |
| 6069 | if (union_type.hasTag(ip)) { | |
| 6070 | break :name .{ .payload_identifier = field_name_str }; | |
| 6071 | } else { | |
| 6072 | break :name .{ .identifier = field_name_str }; | |
| 6073 | } | |
| 5257 | break :name .{ .payload_identifier = field_name_str }; | |
| 6074 | 5258 | }, |
| 6075 | 5259 | .tuple_type => .{ .field = extra.field_index }, |
| 6076 | 5260 | else => unreachable, |
| 6077 | 5261 | }; |
| 6078 | 5262 | |
| 6079 | 5263 | const local = try f.allocLocal(inst, inst_ty); |
| 6080 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 6081 | try f.writeCValue(w, local, .Other); | |
| 6082 | try a.assign(f, w); | |
| 5264 | try f.writeCValue(w, local, .other); | |
| 5265 | try w.writeAll(" = "); | |
| 6083 | 5266 | try f.writeCValueMember(w, struct_byval, field_name); |
| 6084 | try a.end(f, w); | |
| 5267 | try w.writeByte(';'); | |
| 5268 | try f.newline(); | |
| 6085 | 5269 | return local; |
| 6086 | 5270 | } |
| 6087 | 5271 | |
| 6088 | 5272 | /// *(E!T) -> E |
| 6089 | 5273 | /// Note that the result is never a pointer. |
| 6090 | 5274 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6091 | const pt = f.object.dg.pt; | |
| 5275 | const pt = f.dg.pt; | |
| 6092 | 5276 | const zcu = pt.zcu; |
| 6093 | 5277 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6094 | 5278 | |
| ... | ... | @@ -6098,37 +5282,23 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6098 | 5282 | try reap(f, inst, &.{ty_op.operand}); |
| 6099 | 5283 | |
| 6100 | 5284 | const operand_is_ptr = operand_ty.zigTypeTag(zcu) == .pointer; |
| 6101 | const error_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; | |
| 6102 | const error_ty = error_union_ty.errorUnionSet(zcu); | |
| 6103 | const payload_ty = error_union_ty.errorUnionPayload(zcu); | |
| 6104 | 5285 | const local = try f.allocLocal(inst, inst_ty); |
| 6105 | 5286 | |
| 6106 | if (!payload_ty.hasRuntimeBits(zcu) and operand == .local and operand.local == local.new_local) { | |
| 6107 | // The store will be 'x = x'; elide it. | |
| 6108 | return local; | |
| 6109 | } | |
| 6110 | ||
| 6111 | const w = &f.object.code.writer; | |
| 6112 | try f.writeCValue(w, local, .Other); | |
| 5287 | const w = &f.code.writer; | |
| 5288 | try f.writeCValue(w, local, .other); | |
| 6113 | 5289 | try w.writeAll(" = "); |
| 6114 | 5290 | |
| 6115 | if (!payload_ty.hasRuntimeBits(zcu)) | |
| 6116 | try f.writeCValue(w, operand, .Other) | |
| 6117 | else if (error_ty.errorSetIsEmpty(zcu)) | |
| 6118 | try w.print("{f}", .{ | |
| 6119 | try f.fmtIntLiteralDec(try pt.intValue(try pt.errorIntType(), 0)), | |
| 6120 | }) | |
| 6121 | else if (operand_is_ptr) | |
| 5291 | if (operand_is_ptr) | |
| 6122 | 5292 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) |
| 6123 | 5293 | else |
| 6124 | 5294 | try f.writeCValueMember(w, operand, .{ .identifier = "error" }); |
| 6125 | 5295 | try w.writeByte(';'); |
| 6126 | try f.object.newline(); | |
| 5296 | try f.newline(); | |
| 6127 | 5297 | return local; |
| 6128 | 5298 | } |
| 6129 | 5299 | |
| 6130 | 5300 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 6131 | const pt = f.object.dg.pt; | |
| 5301 | const pt = f.dg.pt; | |
| 6132 | 5302 | const zcu = pt.zcu; |
| 6133 | 5303 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6134 | 5304 | |
| ... | ... | @@ -6138,154 +5308,124 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 6138 | 5308 | const operand_ty = f.typeOf(ty_op.operand); |
| 6139 | 5309 | const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 6140 | 5310 | |
| 6141 | const w = &f.object.code.writer; | |
| 5311 | const w = &f.code.writer; | |
| 6142 | 5312 | if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { |
| 6143 | if (!is_ptr) return .none; | |
| 6144 | ||
| 5313 | assert(is_ptr); // opv bug in sema | |
| 6145 | 5314 | const local = try f.allocLocal(inst, inst_ty); |
| 6146 | try f.writeCValue(w, local, .Other); | |
| 5315 | try f.writeCValue(w, local, .other); | |
| 6147 | 5316 | try w.writeAll(" = ("); |
| 6148 | 5317 | try f.renderType(w, inst_ty); |
| 6149 | 5318 | try w.writeByte(')'); |
| 6150 | try f.writeCValue(w, operand, .Other); | |
| 5319 | try f.writeCValue(w, operand, .other); | |
| 6151 | 5320 | try w.writeByte(';'); |
| 6152 | try f.object.newline(); | |
| 5321 | try f.newline(); | |
| 6153 | 5322 | return local; |
| 6154 | 5323 | } |
| 6155 | 5324 | |
| 6156 | 5325 | const local = try f.allocLocal(inst, inst_ty); |
| 6157 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 6158 | try f.writeCValue(w, local, .Other); | |
| 6159 | try a.assign(f, w); | |
| 5326 | try f.writeCValue(w, local, .other); | |
| 5327 | try w.writeAll(" = "); | |
| 6160 | 5328 | if (is_ptr) { |
| 6161 | 5329 | try w.writeByte('&'); |
| 6162 | 5330 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); |
| 6163 | 5331 | } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); |
| 6164 | try a.end(f, w); | |
| 5332 | try w.writeByte(';'); | |
| 5333 | try f.newline(); | |
| 6165 | 5334 | return local; |
| 6166 | 5335 | } |
| 6167 | 5336 | |
| 6168 | 5337 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6169 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 5338 | const zcu = f.dg.pt.zcu; | |
| 6170 | 5339 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6171 | 5340 | |
| 6172 | 5341 | const inst_ty = f.typeOfIndex(inst); |
| 6173 | const inst_ctype = try f.ctypeFromType(inst_ty, .complete); | |
| 6174 | if (inst_ctype.isBool()) return .{ .constant = Value.true }; | |
| 6175 | 5342 | |
| 6176 | 5343 | const operand = try f.resolveInst(ty_op.operand); |
| 6177 | switch (inst_ctype.info(ctype_pool)) { | |
| 6178 | .basic, .pointer => return f.moveCValue(inst, inst_ty, operand), | |
| 6179 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, | |
| 6180 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { | |
| 6181 | .is_null, .payload => { | |
| 6182 | const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete); | |
| 6183 | const w = &f.object.code.writer; | |
| 6184 | const local = try f.allocLocal(inst, inst_ty); | |
| 6185 | { | |
| 6186 | const a = try Assignment.start(f, w, .bool); | |
| 6187 | try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); | |
| 6188 | try a.assign(f, w); | |
| 6189 | try w.writeAll("false"); | |
| 6190 | try a.end(f, w); | |
| 6191 | } | |
| 6192 | { | |
| 6193 | const a = try Assignment.start(f, w, operand_ctype); | |
| 6194 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6195 | try a.assign(f, w); | |
| 6196 | try f.writeCValue(w, operand, .Other); | |
| 6197 | try a.end(f, w); | |
| 6198 | } | |
| 6199 | return local; | |
| 6200 | }, | |
| 6201 | .ptr, .len => return f.moveCValue(inst, inst_ty, operand), | |
| 6202 | else => unreachable, | |
| 5344 | ||
| 5345 | switch (CType.classifyOptional(inst_ty, zcu)) { | |
| 5346 | .npv_payload => unreachable, // opv optional | |
| 5347 | ||
| 5348 | .opv_payload => unreachable, // opv bug in Sema | |
| 5349 | ||
| 5350 | .error_set, | |
| 5351 | .ptr_like, | |
| 5352 | .slice_like, | |
| 5353 | => return f.moveCValue(inst, inst_ty, operand), | |
| 5354 | ||
| 5355 | .@"struct" => { | |
| 5356 | const w = &f.code.writer; | |
| 5357 | const local = try f.allocLocal(inst, inst_ty); | |
| 5358 | ||
| 5359 | try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); | |
| 5360 | try w.writeAll(" = false;"); | |
| 5361 | try f.newline(); | |
| 5362 | ||
| 5363 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 5364 | try w.writeAll(" = "); | |
| 5365 | try f.writeCValue(w, operand, .other); | |
| 5366 | try w.writeByte(';'); | |
| 5367 | try f.newline(); | |
| 5368 | ||
| 5369 | return local; | |
| 6203 | 5370 | }, |
| 6204 | 5371 | } |
| 6205 | 5372 | } |
| 6206 | 5373 | |
| 6207 | 5374 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6208 | const pt = f.object.dg.pt; | |
| 5375 | const pt = f.dg.pt; | |
| 6209 | 5376 | const zcu = pt.zcu; |
| 6210 | 5377 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6211 | 5378 | |
| 6212 | 5379 | const inst_ty = f.typeOfIndex(inst); |
| 6213 | 5380 | const payload_ty = inst_ty.errorUnionPayload(zcu); |
| 6214 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 6215 | const err_ty = inst_ty.errorUnionSet(zcu); | |
| 6216 | 5381 | const err = try f.resolveInst(ty_op.operand); |
| 6217 | 5382 | try reap(f, inst, &.{ty_op.operand}); |
| 6218 | 5383 | |
| 6219 | const w = &f.object.code.writer; | |
| 5384 | const w = &f.code.writer; | |
| 6220 | 5385 | const local = try f.allocLocal(inst, inst_ty); |
| 6221 | 5386 | |
| 6222 | if (repr_is_err and err == .local and err.local == local.new_local) { | |
| 6223 | // The store will be 'x = x'; elide it. | |
| 6224 | return local; | |
| 6225 | } | |
| 6226 | ||
| 6227 | if (!repr_is_err) { | |
| 6228 | const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); | |
| 5387 | if (payload_ty.hasRuntimeBits(zcu)) { | |
| 6229 | 5388 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); |
| 6230 | try a.assign(f, w); | |
| 6231 | try f.object.dg.renderUndefValue(w, payload_ty, .Other); | |
| 6232 | try a.end(f, w); | |
| 6233 | } | |
| 6234 | { | |
| 6235 | const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete)); | |
| 6236 | if (repr_is_err) | |
| 6237 | try f.writeCValue(w, local, .Other) | |
| 6238 | else | |
| 6239 | try f.writeCValueMember(w, local, .{ .identifier = "error" }); | |
| 6240 | try a.assign(f, w); | |
| 6241 | try f.writeCValue(w, err, .Other); | |
| 6242 | try a.end(f, w); | |
| 5389 | try w.writeAll(" = "); | |
| 5390 | try f.dg.renderUndefValue(w, payload_ty, .other); | |
| 5391 | try w.writeByte(';'); | |
| 5392 | try f.newline(); | |
| 6243 | 5393 | } |
| 5394 | ||
| 5395 | try f.writeCValueMember(w, local, .{ .identifier = "error" }); | |
| 5396 | try w.writeAll(" = "); | |
| 5397 | try f.writeCValue(w, err, .other); | |
| 5398 | try w.writeByte(';'); | |
| 5399 | try f.newline(); | |
| 5400 | ||
| 6244 | 5401 | return local; |
| 6245 | 5402 | } |
| 6246 | 5403 | |
| 6247 | 5404 | fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6248 | const pt = f.object.dg.pt; | |
| 6249 | const zcu = pt.zcu; | |
| 6250 | const w = &f.object.code.writer; | |
| 5405 | const pt = f.dg.pt; | |
| 5406 | const w = &f.code.writer; | |
| 6251 | 5407 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6252 | 5408 | const inst_ty = f.typeOfIndex(inst); |
| 6253 | 5409 | const operand = try f.resolveInst(ty_op.operand); |
| 6254 | const operand_ty = f.typeOf(ty_op.operand); | |
| 6255 | const error_union_ty = operand_ty.childType(zcu); | |
| 6256 | 5410 | |
| 6257 | const payload_ty = error_union_ty.errorUnionPayload(zcu); | |
| 6258 | 5411 | const err_int_ty = try pt.errorIntType(); |
| 6259 | 5412 | const no_err = try pt.intValue(err_int_ty, 0); |
| 6260 | 5413 | try reap(f, inst, &.{ty_op.operand}); |
| 6261 | 5414 | |
| 6262 | 5415 | // First, set the non-error value. |
| 6263 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 6264 | const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); | |
| 6265 | try f.writeCValueDeref(w, operand); | |
| 6266 | try a.assign(f, w); | |
| 6267 | try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)}); | |
| 6268 | try a.end(f, w); | |
| 6269 | return .none; | |
| 6270 | } | |
| 6271 | { | |
| 6272 | const a = try Assignment.start(f, w, try f.ctypeFromType(err_int_ty, .complete)); | |
| 6273 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }); | |
| 6274 | try a.assign(f, w); | |
| 6275 | try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)}); | |
| 6276 | try a.end(f, w); | |
| 6277 | } | |
| 5416 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }); | |
| 5417 | try w.print(" = {f};", .{try f.fmtIntLiteralDec(no_err)}); | |
| 5418 | try f.newline(); | |
| 6278 | 5419 | |
| 6279 | 5420 | // Then return the payload pointer (only if it is used) |
| 6280 | 5421 | if (f.liveness.isUnused(inst)) return .none; |
| 6281 | 5422 | |
| 6282 | 5423 | const local = try f.allocLocal(inst, inst_ty); |
| 6283 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 6284 | try f.writeCValue(w, local, .Other); | |
| 6285 | try a.assign(f, w); | |
| 6286 | try w.writeByte('&'); | |
| 5424 | try f.writeCValue(w, local, .other); | |
| 5425 | try w.writeAll(" = &"); | |
| 6287 | 5426 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); |
| 6288 | try a.end(f, w); | |
| 5427 | try w.writeByte(';'); | |
| 5428 | try f.newline(); | |
| 6289 | 5429 | return local; |
| 6290 | 5430 | } |
| 6291 | 5431 | |
| ... | ... | @@ -6305,131 +5445,96 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6305 | 5445 | } |
| 6306 | 5446 | |
| 6307 | 5447 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6308 | const pt = f.object.dg.pt; | |
| 5448 | const pt = f.dg.pt; | |
| 6309 | 5449 | const zcu = pt.zcu; |
| 6310 | 5450 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6311 | 5451 | |
| 6312 | 5452 | const inst_ty = f.typeOfIndex(inst); |
| 6313 | 5453 | const payload_ty = inst_ty.errorUnionPayload(zcu); |
| 6314 | 5454 | const payload = try f.resolveInst(ty_op.operand); |
| 6315 | const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 6316 | const err_ty = inst_ty.errorUnionSet(zcu); | |
| 5455 | assert(payload_ty.hasRuntimeBits(zcu)); | |
| 6317 | 5456 | try reap(f, inst, &.{ty_op.operand}); |
| 6318 | 5457 | |
| 6319 | const w = &f.object.code.writer; | |
| 5458 | const w = &f.code.writer; | |
| 6320 | 5459 | const local = try f.allocLocal(inst, inst_ty); |
| 6321 | if (!repr_is_err) { | |
| 6322 | const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); | |
| 6323 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6324 | try a.assign(f, w); | |
| 6325 | try f.writeCValue(w, payload, .Other); | |
| 6326 | try a.end(f, w); | |
| 6327 | } | |
| 6328 | { | |
| 6329 | const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete)); | |
| 6330 | if (repr_is_err) | |
| 6331 | try f.writeCValue(w, local, .Other) | |
| 6332 | else | |
| 6333 | try f.writeCValueMember(w, local, .{ .identifier = "error" }); | |
| 6334 | try a.assign(f, w); | |
| 6335 | try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other); | |
| 6336 | try a.end(f, w); | |
| 6337 | } | |
| 5460 | ||
| 5461 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 5462 | try w.writeAll(" = "); | |
| 5463 | try f.writeCValue(w, payload, .other); | |
| 5464 | try w.writeByte(';'); | |
| 5465 | try f.newline(); | |
| 5466 | ||
| 5467 | try f.writeCValueMember(w, local, .{ .identifier = "error" }); | |
| 5468 | try w.writeAll(" = "); | |
| 5469 | try f.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .other); | |
| 5470 | try w.writeByte(';'); | |
| 5471 | try f.newline(); | |
| 5472 | ||
| 6338 | 5473 | return local; |
| 6339 | 5474 | } |
| 6340 | 5475 | |
| 6341 | 5476 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { |
| 6342 | const pt = f.object.dg.pt; | |
| 6343 | const zcu = pt.zcu; | |
| 5477 | const pt = f.dg.pt; | |
| 6344 | 5478 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 6345 | 5479 | |
| 6346 | const w = &f.object.code.writer; | |
| 5480 | const w = &f.code.writer; | |
| 6347 | 5481 | const operand = try f.resolveInst(un_op); |
| 6348 | 5482 | try reap(f, inst, &.{un_op}); |
| 6349 | const operand_ty = f.typeOf(un_op); | |
| 6350 | 5483 | const local = try f.allocLocal(inst, .bool); |
| 6351 | const err_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; | |
| 6352 | const payload_ty = err_union_ty.errorUnionPayload(zcu); | |
| 6353 | const error_ty = err_union_ty.errorUnionSet(zcu); | |
| 6354 | 5484 | |
| 6355 | const a = try Assignment.start(f, w, .bool); | |
| 6356 | try f.writeCValue(w, local, .Other); | |
| 6357 | try a.assign(f, w); | |
| 5485 | try f.writeCValue(w, local, .other); | |
| 5486 | try w.writeAll(" = "); | |
| 6358 | 5487 | const err_int_ty = try pt.errorIntType(); |
| 6359 | if (!error_ty.errorSetIsEmpty(zcu)) | |
| 6360 | if (payload_ty.hasRuntimeBits(zcu)) | |
| 6361 | if (is_ptr) | |
| 6362 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) | |
| 6363 | else | |
| 6364 | try f.writeCValueMember(w, operand, .{ .identifier = "error" }) | |
| 6365 | else | |
| 6366 | try f.writeCValue(w, operand, .Other) | |
| 5488 | if (is_ptr) | |
| 5489 | try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) | |
| 6367 | 5490 | else |
| 6368 | try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other); | |
| 6369 | try w.writeByte(' '); | |
| 6370 | try w.writeAll(operator); | |
| 6371 | try w.writeByte(' '); | |
| 6372 | try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other); | |
| 6373 | try a.end(f, w); | |
| 5491 | try f.writeCValueMember(w, operand, .{ .identifier = "error" }); | |
| 5492 | try w.print(" {s} ", .{operator}); | |
| 5493 | try f.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .other); | |
| 5494 | try w.writeByte(';'); | |
| 5495 | try f.newline(); | |
| 6374 | 5496 | return local; |
| 6375 | 5497 | } |
| 6376 | 5498 | |
| 6377 | 5499 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6378 | const pt = f.object.dg.pt; | |
| 5500 | const pt = f.dg.pt; | |
| 6379 | 5501 | const zcu = pt.zcu; |
| 6380 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 6381 | 5502 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6382 | 5503 | |
| 6383 | 5504 | const operand = try f.resolveInst(ty_op.operand); |
| 6384 | 5505 | try reap(f, inst, &.{ty_op.operand}); |
| 6385 | 5506 | const inst_ty = f.typeOfIndex(inst); |
| 6386 | const ptr_ty = inst_ty.slicePtrFieldType(zcu); | |
| 6387 | const w = &f.object.code.writer; | |
| 5507 | const w = &f.code.writer; | |
| 6388 | 5508 | const local = try f.allocLocal(inst, inst_ty); |
| 6389 | 5509 | const operand_ty = f.typeOf(ty_op.operand); |
| 6390 | 5510 | const array_ty = operand_ty.childType(zcu); |
| 6391 | 5511 | |
| 6392 | { | |
| 6393 | const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete)); | |
| 6394 | try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); | |
| 6395 | try a.assign(f, w); | |
| 6396 | if (operand == .undef) { | |
| 6397 | try f.writeCValue(w, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Other); | |
| 6398 | } else { | |
| 6399 | const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete); | |
| 6400 | const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; | |
| 6401 | const elem_ty = array_ty.childType(zcu); | |
| 6402 | const elem_ctype = try f.ctypeFromType(elem_ty, .complete); | |
| 6403 | if (!ptr_child_ctype.eql(elem_ctype)) { | |
| 6404 | try w.writeByte('('); | |
| 6405 | try f.renderCType(w, ptr_ctype); | |
| 6406 | try w.writeByte(')'); | |
| 6407 | } | |
| 6408 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); | |
| 6409 | const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype; | |
| 6410 | if (operand_child_ctype.info(ctype_pool) == .array) { | |
| 6411 | try w.writeByte('&'); | |
| 6412 | try f.writeCValueDeref(w, operand); | |
| 6413 | try w.print("[{f}]", .{try f.fmtIntLiteralDec(.zero_usize)}); | |
| 6414 | } else try f.writeCValue(w, operand, .Other); | |
| 6415 | } | |
| 6416 | try a.end(f, w); | |
| 6417 | } | |
| 6418 | { | |
| 6419 | const a = try Assignment.start(f, w, .usize); | |
| 6420 | try f.writeCValueMember(w, local, .{ .identifier = "len" }); | |
| 6421 | try a.assign(f, w); | |
| 6422 | try w.print("{f}", .{ | |
| 6423 | try f.fmtIntLiteralDec(try pt.intValue(.usize, array_ty.arrayLen(zcu))), | |
| 6424 | }); | |
| 6425 | try a.end(f, w); | |
| 6426 | } | |
| 5512 | // We have a `*[n]T`, which was turned into to a pointer to `struct { T array[n]; }`. | |
| 5513 | // Ideally we would want to use 'operand->array' to convert to a `T *` (we get a `T []` | |
| 5514 | // which decays to a pointer), but if the element type is zero-bit or the array length is | |
| 5515 | // zero, there will not be an `array` member (the array type lowers to `void`). We cannot | |
| 5516 | // check the type layout here because it may not be resolved, so in this instance, we must | |
| 5517 | // use a pointer cast. | |
| 5518 | try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); | |
| 5519 | try w.writeAll(" = ("); | |
| 5520 | try f.dg.renderType(w, inst_ty.slicePtrFieldType(zcu)); | |
| 5521 | try w.writeByte(')'); | |
| 5522 | try f.writeCValue(w, operand, .other); | |
| 5523 | try w.writeByte(';'); | |
| 5524 | try f.newline(); | |
| 5525 | ||
| 5526 | try f.writeCValueMember(w, local, .{ .identifier = "len" }); | |
| 5527 | try w.print(" = {f}", .{ | |
| 5528 | try f.fmtIntLiteralDec(try pt.intValue(.usize, array_ty.arrayLen(zcu))), | |
| 5529 | }); | |
| 5530 | try w.writeByte(';'); | |
| 5531 | try f.newline(); | |
| 6427 | 5532 | |
| 6428 | 5533 | return local; |
| 6429 | 5534 | } |
| 6430 | 5535 | |
| 6431 | 5536 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6432 | const pt = f.object.dg.pt; | |
| 5537 | const pt = f.dg.pt; | |
| 6433 | 5538 | const zcu = pt.zcu; |
| 6434 | 5539 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6435 | 5540 | |
| ... | ... | @@ -6439,7 +5544,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6439 | 5544 | try reap(f, inst, &.{ty_op.operand}); |
| 6440 | 5545 | const operand_ty = f.typeOf(ty_op.operand); |
| 6441 | 5546 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6442 | const target = &f.object.dg.mod.resolved_target.result; | |
| 5547 | const target = &f.dg.mod.resolved_target.result; | |
| 6443 | 5548 | const operation = if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isRuntimeFloat()) |
| 6444 | 5549 | if (inst_scalar_ty.floatBits(target) < scalar_ty.floatBits(target)) "trunc" else "extend" |
| 6445 | 5550 | else if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) |
| ... | ... | @@ -6449,16 +5554,15 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6449 | 5554 | else |
| 6450 | 5555 | unreachable; |
| 6451 | 5556 | |
| 6452 | const w = &f.object.code.writer; | |
| 5557 | const w = &f.code.writer; | |
| 6453 | 5558 | const local = try f.allocLocal(inst, inst_ty); |
| 6454 | 5559 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 6455 | const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); | |
| 6456 | try f.writeCValue(w, local, .Other); | |
| 5560 | try f.writeCValue(w, local, .other); | |
| 6457 | 5561 | try v.elem(f, w); |
| 6458 | try a.assign(f, w); | |
| 5562 | try w.writeAll(" = "); | |
| 6459 | 5563 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 6460 | 5564 | try w.writeAll("zig_wrap_"); |
| 6461 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 5565 | try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 6462 | 5566 | try w.writeByte('('); |
| 6463 | 5567 | } |
| 6464 | 5568 | try w.writeAll("zig_"); |
| ... | ... | @@ -6466,14 +5570,15 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6466 | 5570 | try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); |
| 6467 | 5571 | try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); |
| 6468 | 5572 | try w.writeByte('('); |
| 6469 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 5573 | try f.writeCValue(w, operand, .other); | |
| 6470 | 5574 | try v.elem(f, w); |
| 6471 | 5575 | try w.writeByte(')'); |
| 6472 | 5576 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 6473 | try f.object.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); | |
| 5577 | try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); | |
| 6474 | 5578 | try w.writeByte(')'); |
| 6475 | 5579 | } |
| 6476 | try a.end(f, w); | |
| 5580 | try w.writeByte(';'); | |
| 5581 | try f.newline(); | |
| 6477 | 5582 | try v.end(f, inst, w); |
| 6478 | 5583 | |
| 6479 | 5584 | return local; |
| ... | ... | @@ -6486,7 +5591,7 @@ fn airUnBuiltinCall( |
| 6486 | 5591 | operation: []const u8, |
| 6487 | 5592 | info: BuiltinInfo, |
| 6488 | 5593 | ) !CValue { |
| 6489 | const pt = f.object.dg.pt; | |
| 5594 | const pt = f.dg.pt; | |
| 6490 | 5595 | const zcu = pt.zcu; |
| 6491 | 5596 | |
| 6492 | 5597 | const operand = try f.resolveInst(operand_ref); |
| ... | ... | @@ -6496,30 +5601,32 @@ fn airUnBuiltinCall( |
| 6496 | 5601 | const operand_ty = f.typeOf(operand_ref); |
| 6497 | 5602 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6498 | 5603 | |
| 6499 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 6500 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 5604 | const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); | |
| 5605 | const ref_arg = lowersToBigInt(scalar_ty, zcu); | |
| 6501 | 5606 | |
| 6502 | const w = &f.object.code.writer; | |
| 5607 | const w = &f.code.writer; | |
| 6503 | 5608 | const local = try f.allocLocal(inst, inst_ty); |
| 6504 | 5609 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 6505 | 5610 | if (!ref_ret) { |
| 6506 | try f.writeCValue(w, local, .Other); | |
| 5611 | try f.writeCValue(w, local, .other); | |
| 6507 | 5612 | try v.elem(f, w); |
| 6508 | 5613 | try w.writeAll(" = "); |
| 6509 | 5614 | } |
| 6510 | 5615 | try w.print("zig_{s}_", .{operation}); |
| 6511 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 5616 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6512 | 5617 | try w.writeByte('('); |
| 6513 | 5618 | if (ref_ret) { |
| 6514 | try f.writeCValue(w, local, .FunctionArgument); | |
| 5619 | try w.writeByte('&'); | |
| 5620 | try f.writeCValue(w, local, .other); | |
| 6515 | 5621 | try v.elem(f, w); |
| 6516 | 5622 | try w.writeAll(", "); |
| 6517 | 5623 | } |
| 6518 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 5624 | if (ref_arg) try w.writeByte('&'); | |
| 5625 | try f.writeCValue(w, operand, .other); | |
| 6519 | 5626 | try v.elem(f, w); |
| 6520 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 5627 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 6521 | 5628 | try w.writeAll(");"); |
| 6522 | try f.object.newline(); | |
| 5629 | try f.newline(); | |
| 6523 | 5630 | try v.end(f, inst, w); |
| 6524 | 5631 | |
| 6525 | 5632 | return local; |
| ... | ... | @@ -6531,13 +5638,12 @@ fn airBinBuiltinCall( |
| 6531 | 5638 | operation: []const u8, |
| 6532 | 5639 | info: BuiltinInfo, |
| 6533 | 5640 | ) !CValue { |
| 6534 | const pt = f.object.dg.pt; | |
| 5641 | const pt = f.dg.pt; | |
| 6535 | 5642 | const zcu = pt.zcu; |
| 6536 | 5643 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6537 | 5644 | |
| 6538 | 5645 | const operand_ty = f.typeOf(bin_op.lhs); |
| 6539 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); | |
| 6540 | const is_big = operand_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 5646 | const is_big = lowersToBigInt(operand_ty, zcu); | |
| 6541 | 5647 | |
| 6542 | 5648 | const lhs = try f.resolveInst(bin_op.lhs); |
| 6543 | 5649 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -6547,32 +5653,35 @@ fn airBinBuiltinCall( |
| 6547 | 5653 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6548 | 5654 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6549 | 5655 | |
| 6550 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 6551 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 5656 | const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); | |
| 5657 | const ref_arg = lowersToBigInt(scalar_ty, zcu); | |
| 6552 | 5658 | |
| 6553 | const w = &f.object.code.writer; | |
| 5659 | const w = &f.code.writer; | |
| 6554 | 5660 | const local = try f.allocLocal(inst, inst_ty); |
| 6555 | 5661 | if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6556 | 5662 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 6557 | 5663 | if (!ref_ret) { |
| 6558 | try f.writeCValue(w, local, .Other); | |
| 5664 | try f.writeCValue(w, local, .other); | |
| 6559 | 5665 | try v.elem(f, w); |
| 6560 | 5666 | try w.writeAll(" = "); |
| 6561 | 5667 | } |
| 6562 | 5668 | try w.print("zig_{s}_", .{operation}); |
| 6563 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 5669 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6564 | 5670 | try w.writeByte('('); |
| 6565 | 5671 | if (ref_ret) { |
| 6566 | try f.writeCValue(w, local, .FunctionArgument); | |
| 5672 | try w.writeByte('&'); | |
| 5673 | try f.writeCValue(w, local, .other); | |
| 6567 | 5674 | try v.elem(f, w); |
| 6568 | 5675 | try w.writeAll(", "); |
| 6569 | 5676 | } |
| 6570 | try f.writeCValue(w, lhs, .FunctionArgument); | |
| 5677 | if (ref_arg) try w.writeByte('&'); | |
| 5678 | try f.writeCValue(w, lhs, .other); | |
| 6571 | 5679 | try v.elem(f, w); |
| 6572 | 5680 | try w.writeAll(", "); |
| 6573 | try f.writeCValue(w, rhs, .FunctionArgument); | |
| 5681 | if (ref_arg) try w.writeByte('&'); | |
| 5682 | try f.writeCValue(w, rhs, .other); | |
| 6574 | 5683 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); |
| 6575 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 5684 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 6576 | 5685 | try w.writeAll(");\n"); |
| 6577 | 5686 | try v.end(f, inst, w); |
| 6578 | 5687 | |
| ... | ... | @@ -6587,7 +5696,7 @@ fn airCmpBuiltinCall( |
| 6587 | 5696 | operation: enum { cmp, operator }, |
| 6588 | 5697 | info: BuiltinInfo, |
| 6589 | 5698 | ) !CValue { |
| 6590 | const pt = f.object.dg.pt; | |
| 5699 | const pt = f.dg.pt; | |
| 6591 | 5700 | const zcu = pt.zcu; |
| 6592 | 5701 | const lhs = try f.resolveInst(data.lhs); |
| 6593 | 5702 | const rhs = try f.resolveInst(data.rhs); |
| ... | ... | @@ -6598,14 +5707,14 @@ fn airCmpBuiltinCall( |
| 6598 | 5707 | const operand_ty = f.typeOf(data.lhs); |
| 6599 | 5708 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6600 | 5709 | |
| 6601 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 6602 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 5710 | const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); | |
| 5711 | const ref_arg = lowersToBigInt(scalar_ty, zcu); | |
| 6603 | 5712 | |
| 6604 | const w = &f.object.code.writer; | |
| 5713 | const w = &f.code.writer; | |
| 6605 | 5714 | const local = try f.allocLocal(inst, inst_ty); |
| 6606 | 5715 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 6607 | 5716 | if (!ref_ret) { |
| 6608 | try f.writeCValue(w, local, .Other); | |
| 5717 | try f.writeCValue(w, local, .other); | |
| 6609 | 5718 | try v.elem(f, w); |
| 6610 | 5719 | try w.writeAll(" = "); |
| 6611 | 5720 | } |
| ... | ... | @@ -6613,33 +5722,36 @@ fn airCmpBuiltinCall( |
| 6613 | 5722 | else => @tagName(operation), |
| 6614 | 5723 | .operator => compareOperatorAbbrev(operator), |
| 6615 | 5724 | }}); |
| 6616 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 5725 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6617 | 5726 | try w.writeByte('('); |
| 6618 | 5727 | if (ref_ret) { |
| 6619 | try f.writeCValue(w, local, .FunctionArgument); | |
| 5728 | try w.writeByte('&'); | |
| 5729 | try f.writeCValue(w, local, .other); | |
| 6620 | 5730 | try v.elem(f, w); |
| 6621 | 5731 | try w.writeAll(", "); |
| 6622 | 5732 | } |
| 6623 | try f.writeCValue(w, lhs, .FunctionArgument); | |
| 5733 | if (ref_arg) try w.writeByte('&'); | |
| 5734 | try f.writeCValue(w, lhs, .other); | |
| 6624 | 5735 | try v.elem(f, w); |
| 6625 | 5736 | try w.writeAll(", "); |
| 6626 | try f.writeCValue(w, rhs, .FunctionArgument); | |
| 5737 | if (ref_arg) try w.writeByte('&'); | |
| 5738 | try f.writeCValue(w, rhs, .other); | |
| 6627 | 5739 | try v.elem(f, w); |
| 6628 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 5740 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 6629 | 5741 | try w.writeByte(')'); |
| 6630 | 5742 | if (!ref_ret) try w.print("{s}{f}", .{ |
| 6631 | 5743 | compareOperatorC(operator), |
| 6632 | 5744 | try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)), |
| 6633 | 5745 | }); |
| 6634 | 5746 | try w.writeByte(';'); |
| 6635 | try f.object.newline(); | |
| 5747 | try f.newline(); | |
| 6636 | 5748 | try v.end(f, inst, w); |
| 6637 | 5749 | |
| 6638 | 5750 | return local; |
| 6639 | 5751 | } |
| 6640 | 5752 | |
| 6641 | 5753 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { |
| 6642 | const pt = f.object.dg.pt; | |
| 5754 | const pt = f.dg.pt; | |
| 6643 | 5755 | const zcu = pt.zcu; |
| 6644 | 5756 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6645 | 5757 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| ... | ... | @@ -6649,9 +5761,8 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6649 | 5761 | const new_value = try f.resolveInst(extra.new_value); |
| 6650 | 5762 | const ptr_ty = f.typeOf(extra.ptr); |
| 6651 | 5763 | const ty = ptr_ty.childType(zcu); |
| 6652 | const ctype = try f.ctypeFromType(ty, .complete); | |
| 6653 | 5764 | |
| 6654 | const w = &f.object.code.writer; | |
| 5765 | const w = &f.code.writer; | |
| 6655 | 5766 | const new_value_mat = try Materialize.start(f, inst, ty, new_value); |
| 6656 | 5767 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); |
| 6657 | 5768 | |
| ... | ... | @@ -6662,13 +5773,11 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6662 | 5773 | |
| 6663 | 5774 | const local = try f.allocLocal(inst, inst_ty); |
| 6664 | 5775 | if (inst_ty.isPtrLikeOptional(zcu)) { |
| 6665 | { | |
| 6666 | const a = try Assignment.start(f, w, ctype); | |
| 6667 | try f.writeCValue(w, local, .Other); | |
| 6668 | try a.assign(f, w); | |
| 6669 | try f.writeCValue(w, expected_value, .Other); | |
| 6670 | try a.end(f, w); | |
| 6671 | } | |
| 5776 | try f.writeCValue(w, local, .other); | |
| 5777 | try w.writeAll(" = "); | |
| 5778 | try f.writeCValue(w, expected_value, .other); | |
| 5779 | try w.writeByte(';'); | |
| 5780 | try f.newline(); | |
| 6672 | 5781 | |
| 6673 | 5782 | try w.writeAll("if ("); |
| 6674 | 5783 | try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| ... | ... | @@ -6676,9 +5785,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6676 | 5785 | try w.writeByte(')'); |
| 6677 | 5786 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); |
| 6678 | 5787 | try w.writeAll(" *)"); |
| 6679 | try f.writeCValue(w, ptr, .Other); | |
| 5788 | try f.writeCValue(w, ptr, .other); | |
| 6680 | 5789 | try w.writeAll(", "); |
| 6681 | try f.writeCValue(w, local, .FunctionArgument); | |
| 5790 | try f.writeCValue(w, local, .other); | |
| 6682 | 5791 | try w.writeAll(", "); |
| 6683 | 5792 | try new_value_mat.mat(f, w); |
| 6684 | 5793 | try w.writeAll(", "); |
| ... | ... | @@ -6686,56 +5795,49 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6686 | 5795 | try w.writeAll(", "); |
| 6687 | 5796 | try writeMemoryOrder(w, extra.failureOrder()); |
| 6688 | 5797 | try w.writeAll(", "); |
| 6689 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 5798 | try f.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6690 | 5799 | try w.writeAll(", "); |
| 6691 | 5800 | try f.renderType(w, repr_ty); |
| 6692 | 5801 | try w.writeByte(')'); |
| 6693 | 5802 | try w.writeAll(") {"); |
| 6694 | f.object.indent(); | |
| 6695 | try f.object.newline(); | |
| 6696 | { | |
| 6697 | const a = try Assignment.start(f, w, ctype); | |
| 6698 | try f.writeCValue(w, local, .Other); | |
| 6699 | try a.assign(f, w); | |
| 6700 | try w.writeAll("NULL"); | |
| 6701 | try a.end(f, w); | |
| 6702 | } | |
| 6703 | try f.object.outdent(); | |
| 5803 | f.indent(); | |
| 5804 | try f.newline(); | |
| 5805 | ||
| 5806 | try f.writeCValue(w, local, .other); | |
| 5807 | try w.writeAll(" = NULL;"); | |
| 5808 | try f.newline(); | |
| 5809 | ||
| 5810 | try f.outdent(); | |
| 6704 | 5811 | try w.writeByte('}'); |
| 6705 | try f.object.newline(); | |
| 5812 | try f.newline(); | |
| 6706 | 5813 | } else { |
| 6707 | { | |
| 6708 | const a = try Assignment.start(f, w, ctype); | |
| 6709 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6710 | try a.assign(f, w); | |
| 6711 | try f.writeCValue(w, expected_value, .Other); | |
| 6712 | try a.end(f, w); | |
| 6713 | } | |
| 6714 | { | |
| 6715 | const a = try Assignment.start(f, w, .bool); | |
| 6716 | try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); | |
| 6717 | try a.assign(f, w); | |
| 6718 | try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | |
| 6719 | try f.renderType(w, ty); | |
| 6720 | try w.writeByte(')'); | |
| 6721 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 6722 | try w.writeAll(" *)"); | |
| 6723 | try f.writeCValue(w, ptr, .Other); | |
| 6724 | try w.writeAll(", "); | |
| 6725 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 6726 | try w.writeAll(", "); | |
| 6727 | try new_value_mat.mat(f, w); | |
| 6728 | try w.writeAll(", "); | |
| 6729 | try writeMemoryOrder(w, extra.successOrder()); | |
| 6730 | try w.writeAll(", "); | |
| 6731 | try writeMemoryOrder(w, extra.failureOrder()); | |
| 6732 | try w.writeAll(", "); | |
| 6733 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6734 | try w.writeAll(", "); | |
| 6735 | try f.renderType(w, repr_ty); | |
| 6736 | try w.writeByte(')'); | |
| 6737 | try a.end(f, w); | |
| 6738 | } | |
| 5814 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 5815 | try w.writeAll(" = "); | |
| 5816 | try f.writeCValue(w, expected_value, .other); | |
| 5817 | try w.writeByte(';'); | |
| 5818 | try f.newline(); | |
| 5819 | ||
| 5820 | try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); | |
| 5821 | try w.print(" = zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | |
| 5822 | try f.renderType(w, ty); | |
| 5823 | try w.writeByte(')'); | |
| 5824 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); | |
| 5825 | try w.writeAll(" *)"); | |
| 5826 | try f.writeCValue(w, ptr, .other); | |
| 5827 | try w.writeAll(", "); | |
| 5828 | try f.writeCValueMember(w, local, .{ .identifier = "payload" }); | |
| 5829 | try w.writeAll(", "); | |
| 5830 | try new_value_mat.mat(f, w); | |
| 5831 | try w.writeAll(", "); | |
| 5832 | try writeMemoryOrder(w, extra.successOrder()); | |
| 5833 | try w.writeAll(", "); | |
| 5834 | try writeMemoryOrder(w, extra.failureOrder()); | |
| 5835 | try w.writeAll(", "); | |
| 5836 | try f.dg.renderTypeForBuiltinFnName(w, ty); | |
| 5837 | try w.writeAll(", "); | |
| 5838 | try f.renderType(w, repr_ty); | |
| 5839 | try w.writeAll(");"); | |
| 5840 | try f.newline(); | |
| 6739 | 5841 | } |
| 6740 | 5842 | try new_value_mat.end(f, inst); |
| 6741 | 5843 | |
| ... | ... | @@ -6748,7 +5850,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6748 | 5850 | } |
| 6749 | 5851 | |
| 6750 | 5852 | fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6751 | const pt = f.object.dg.pt; | |
| 5853 | const pt = f.dg.pt; | |
| 6752 | 5854 | const zcu = pt.zcu; |
| 6753 | 5855 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6754 | 5856 | const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| ... | ... | @@ -6758,7 +5860,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6758 | 5860 | const ptr = try f.resolveInst(pl_op.operand); |
| 6759 | 5861 | const operand = try f.resolveInst(extra.operand); |
| 6760 | 5862 | |
| 6761 | const w = &f.object.code.writer; | |
| 5863 | const w = &f.code.writer; | |
| 6762 | 5864 | const operand_mat = try Materialize.start(f, inst, ty, operand); |
| 6763 | 5865 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); |
| 6764 | 5866 | |
| ... | ... | @@ -6771,7 +5873,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6771 | 5873 | try w.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); |
| 6772 | 5874 | if (is_float) try w.writeAll("_float") else if (is_128) try w.writeAll("_int128"); |
| 6773 | 5875 | try w.writeByte('('); |
| 6774 | try f.writeCValue(w, local, .Other); | |
| 5876 | try f.writeCValue(w, local, .other); | |
| 6775 | 5877 | try w.writeAll(", ("); |
| 6776 | 5878 | const use_atomic = switch (extra.op()) { |
| 6777 | 5879 | else => true, |
| ... | ... | @@ -6783,17 +5885,17 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6783 | 5885 | if (use_atomic) try w.writeByte(')'); |
| 6784 | 5886 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); |
| 6785 | 5887 | try w.writeAll(" *)"); |
| 6786 | try f.writeCValue(w, ptr, .Other); | |
| 5888 | try f.writeCValue(w, ptr, .other); | |
| 6787 | 5889 | try w.writeAll(", "); |
| 6788 | 5890 | try operand_mat.mat(f, w); |
| 6789 | 5891 | try w.writeAll(", "); |
| 6790 | 5892 | try writeMemoryOrder(w, extra.ordering()); |
| 6791 | 5893 | try w.writeAll(", "); |
| 6792 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 5894 | try f.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6793 | 5895 | try w.writeAll(", "); |
| 6794 | 5896 | try f.renderType(w, repr_ty); |
| 6795 | 5897 | try w.writeAll(");"); |
| 6796 | try f.object.newline(); | |
| 5898 | try f.newline(); | |
| 6797 | 5899 | try operand_mat.end(f, inst); |
| 6798 | 5900 | |
| 6799 | 5901 | if (f.liveness.isUnused(inst)) { |
| ... | ... | @@ -6805,7 +5907,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6805 | 5907 | } |
| 6806 | 5908 | |
| 6807 | 5909 | fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6808 | const pt = f.object.dg.pt; | |
| 5910 | const pt = f.dg.pt; | |
| 6809 | 5911 | const zcu = pt.zcu; |
| 6810 | 5912 | const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 6811 | 5913 | const ptr = try f.resolveInst(atomic_load.ptr); |
| ... | ... | @@ -6819,31 +5921,31 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6819 | 5921 | ty; |
| 6820 | 5922 | |
| 6821 | 5923 | const inst_ty = f.typeOfIndex(inst); |
| 6822 | const w = &f.object.code.writer; | |
| 5924 | const w = &f.code.writer; | |
| 6823 | 5925 | const local = try f.allocLocal(inst, inst_ty); |
| 6824 | 5926 | |
| 6825 | 5927 | try w.writeAll("zig_atomic_load("); |
| 6826 | try f.writeCValue(w, local, .Other); | |
| 5928 | try f.writeCValue(w, local, .other); | |
| 6827 | 5929 | try w.writeAll(", (zig_atomic("); |
| 6828 | 5930 | try f.renderType(w, ty); |
| 6829 | 5931 | try w.writeByte(')'); |
| 6830 | 5932 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); |
| 6831 | 5933 | try w.writeAll(" *)"); |
| 6832 | try f.writeCValue(w, ptr, .Other); | |
| 5934 | try f.writeCValue(w, ptr, .other); | |
| 6833 | 5935 | try w.writeAll(", "); |
| 6834 | 5936 | try writeMemoryOrder(w, atomic_load.order); |
| 6835 | 5937 | try w.writeAll(", "); |
| 6836 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 5938 | try f.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6837 | 5939 | try w.writeAll(", "); |
| 6838 | 5940 | try f.renderType(w, repr_ty); |
| 6839 | 5941 | try w.writeAll(");"); |
| 6840 | try f.object.newline(); | |
| 5942 | try f.newline(); | |
| 6841 | 5943 | |
| 6842 | 5944 | return local; |
| 6843 | 5945 | } |
| 6844 | 5946 | |
| 6845 | 5947 | fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { |
| 6846 | const pt = f.object.dg.pt; | |
| 5948 | const pt = f.dg.pt; | |
| 6847 | 5949 | const zcu = pt.zcu; |
| 6848 | 5950 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6849 | 5951 | const ptr_ty = f.typeOf(bin_op.lhs); |
| ... | ... | @@ -6851,7 +5953,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6851 | 5953 | const ptr = try f.resolveInst(bin_op.lhs); |
| 6852 | 5954 | const element = try f.resolveInst(bin_op.rhs); |
| 6853 | 5955 | |
| 6854 | const w = &f.object.code.writer; | |
| 5956 | const w = &f.code.writer; | |
| 6855 | 5957 | const element_mat = try Materialize.start(f, inst, ty, element); |
| 6856 | 5958 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6857 | 5959 | |
| ... | ... | @@ -6865,32 +5967,22 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6865 | 5967 | try w.writeByte(')'); |
| 6866 | 5968 | if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); |
| 6867 | 5969 | try w.writeAll(" *)"); |
| 6868 | try f.writeCValue(w, ptr, .Other); | |
| 5970 | try f.writeCValue(w, ptr, .other); | |
| 6869 | 5971 | try w.writeAll(", "); |
| 6870 | 5972 | try element_mat.mat(f, w); |
| 6871 | 5973 | try w.print(", {s}, ", .{order}); |
| 6872 | try f.object.dg.renderTypeForBuiltinFnName(w, ty); | |
| 5974 | try f.dg.renderTypeForBuiltinFnName(w, ty); | |
| 6873 | 5975 | try w.writeAll(", "); |
| 6874 | 5976 | try f.renderType(w, repr_ty); |
| 6875 | 5977 | try w.writeAll(");"); |
| 6876 | try f.object.newline(); | |
| 5978 | try f.newline(); | |
| 6877 | 5979 | try element_mat.end(f, inst); |
| 6878 | 5980 | |
| 6879 | 5981 | return .none; |
| 6880 | 5982 | } |
| 6881 | 5983 | |
| 6882 | fn writeSliceOrPtr(f: *Function, w: *Writer, ptr: CValue, ptr_ty: Type) !void { | |
| 6883 | const pt = f.object.dg.pt; | |
| 6884 | const zcu = pt.zcu; | |
| 6885 | if (ptr_ty.isSlice(zcu)) { | |
| 6886 | try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" }); | |
| 6887 | } else { | |
| 6888 | try f.writeCValue(w, ptr, .FunctionArgument); | |
| 6889 | } | |
| 6890 | } | |
| 6891 | ||
| 6892 | 5984 | fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6893 | const pt = f.object.dg.pt; | |
| 5985 | const pt = f.dg.pt; | |
| 6894 | 5986 | const zcu = pt.zcu; |
| 6895 | 5987 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6896 | 5988 | const dest_ty = f.typeOf(bin_op.lhs); |
| ... | ... | @@ -6899,7 +5991,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6899 | 5991 | const elem_ty = f.typeOf(bin_op.rhs); |
| 6900 | 5992 | const elem_abi_size = elem_ty.abiSize(zcu); |
| 6901 | 5993 | const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndef(zcu) else false; |
| 6902 | const w = &f.object.code.writer; | |
| 5994 | const w = &f.code.writer; | |
| 6903 | 5995 | |
| 6904 | 5996 | if (val_is_undef) { |
| 6905 | 5997 | if (!safety) { |
| ... | ... | @@ -6913,153 +6005,128 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6913 | 6005 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); |
| 6914 | 6006 | try w.writeAll(", 0xaa, "); |
| 6915 | 6007 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); |
| 6916 | if (elem_abi_size > 1) { | |
| 6917 | try w.print(" * {d}", .{elem_abi_size}); | |
| 6918 | } | |
| 6919 | try w.writeAll(");"); | |
| 6920 | try f.object.newline(); | |
| 6921 | 6008 | }, |
| 6922 | 6009 | .one => { |
| 6923 | const array_ty = dest_ty.childType(zcu); | |
| 6924 | const len = array_ty.arrayLen(zcu) * elem_abi_size; | |
| 6925 | ||
| 6926 | try f.writeCValue(w, dest_slice, .FunctionArgument); | |
| 6927 | try w.print(", 0xaa, {d});", .{len}); | |
| 6928 | try f.object.newline(); | |
| 6010 | try f.writeCValue(w, dest_slice, .other); | |
| 6011 | try w.print(", 0xaa, {d}", .{dest_ty.childType(zcu).arrayLen(zcu)}); | |
| 6929 | 6012 | }, |
| 6930 | 6013 | .many, .c => unreachable, |
| 6931 | 6014 | } |
| 6015 | if (elem_abi_size > 0) try w.print(" * {d}", .{elem_abi_size}); | |
| 6016 | try w.writeAll(");"); | |
| 6017 | try f.newline(); | |
| 6932 | 6018 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6933 | 6019 | return .none; |
| 6934 | 6020 | } |
| 6935 | 6021 | |
| 6936 | if (elem_abi_size > 1 or dest_ty.isVolatilePtr(zcu)) { | |
| 6937 | // For the assignment in this loop, the array pointer needs to get | |
| 6938 | // casted to a regular pointer, otherwise an error like this occurs: | |
| 6939 | // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable | |
| 6940 | const elem_ptr_ty = try pt.ptrType(.{ | |
| 6941 | .child = elem_ty.toIntern(), | |
| 6942 | .flags = .{ | |
| 6943 | .size = .c, | |
| 6944 | }, | |
| 6945 | }); | |
| 6946 | ||
| 6947 | const index = try f.allocLocal(inst, .usize); | |
| 6948 | ||
| 6949 | try w.writeAll("for ("); | |
| 6950 | try f.writeCValue(w, index, .Other); | |
| 6951 | try w.writeAll(" = "); | |
| 6952 | try f.object.dg.renderValue(w, .zero_usize, .Other); | |
| 6953 | try w.writeAll("; "); | |
| 6954 | try f.writeCValue(w, index, .Other); | |
| 6955 | try w.writeAll(" != "); | |
| 6022 | if (elem_abi_size == 1 and !dest_ty.isVolatilePtr(zcu)) { | |
| 6023 | const bitcasted = try bitcast(f, .u8, value, elem_ty); | |
| 6024 | try w.writeAll("memset("); | |
| 6956 | 6025 | switch (dest_ty.ptrSize(zcu)) { |
| 6957 | 6026 | .slice => { |
| 6027 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); | |
| 6028 | try w.writeAll(", "); | |
| 6029 | try f.writeCValue(w, bitcasted, .other); | |
| 6030 | try w.writeAll(", "); | |
| 6958 | 6031 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); |
| 6959 | 6032 | }, |
| 6960 | 6033 | .one => { |
| 6961 | const array_ty = dest_ty.childType(zcu); | |
| 6962 | try w.print("{d}", .{array_ty.arrayLen(zcu)}); | |
| 6034 | try f.writeCValue(w, dest_slice, .other); | |
| 6035 | try w.writeAll(", "); | |
| 6036 | try f.writeCValue(w, bitcasted, .other); | |
| 6037 | try w.print(", {d}", .{dest_ty.childType(zcu).arrayLen(zcu)}); | |
| 6963 | 6038 | }, |
| 6964 | 6039 | .many, .c => unreachable, |
| 6965 | 6040 | } |
| 6966 | try w.writeAll("; ++"); | |
| 6967 | try f.writeCValue(w, index, .Other); | |
| 6968 | try w.writeAll(") "); | |
| 6969 | ||
| 6970 | const a = try Assignment.start(f, w, try f.ctypeFromType(elem_ty, .complete)); | |
| 6971 | try w.writeAll("(("); | |
| 6972 | try f.renderType(w, elem_ptr_ty); | |
| 6973 | try w.writeByte(')'); | |
| 6974 | try writeSliceOrPtr(f, w, dest_slice, dest_ty); | |
| 6975 | try w.writeAll(")["); | |
| 6976 | try f.writeCValue(w, index, .Other); | |
| 6977 | try w.writeByte(']'); | |
| 6978 | try a.assign(f, w); | |
| 6979 | try f.writeCValue(w, value, .Other); | |
| 6980 | try a.end(f, w); | |
| 6981 | ||
| 6041 | try w.writeAll(");"); | |
| 6042 | try f.newline(); | |
| 6043 | try f.freeCValue(inst, bitcasted); | |
| 6982 | 6044 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6983 | try freeLocal(f, inst, index.new_local, null); | |
| 6984 | ||
| 6985 | 6045 | return .none; |
| 6986 | 6046 | } |
| 6987 | 6047 | |
| 6988 | const bitcasted = try bitcast(f, .u8, value, elem_ty); | |
| 6048 | // Fallback path: use a `for` loop. | |
| 6989 | 6049 | |
| 6990 | try w.writeAll("memset("); | |
| 6050 | const index = try f.allocLocal(inst, .usize); | |
| 6051 | ||
| 6052 | try w.writeAll("for ("); | |
| 6053 | try f.writeCValue(w, index, .other); | |
| 6054 | try w.writeAll(" = "); | |
| 6055 | try f.dg.renderValue(w, .zero_usize, .other); | |
| 6056 | try w.writeAll("; "); | |
| 6057 | try f.writeCValue(w, index, .other); | |
| 6058 | try w.writeAll(" != "); | |
| 6991 | 6059 | switch (dest_ty.ptrSize(zcu)) { |
| 6992 | .slice => { | |
| 6993 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); | |
| 6994 | try w.writeAll(", "); | |
| 6995 | try f.writeCValue(w, bitcasted, .FunctionArgument); | |
| 6996 | try w.writeAll(", "); | |
| 6997 | try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); | |
| 6998 | try w.writeAll(");"); | |
| 6999 | try f.object.newline(); | |
| 7000 | }, | |
| 7001 | .one => { | |
| 7002 | const array_ty = dest_ty.childType(zcu); | |
| 7003 | const len = array_ty.arrayLen(zcu) * elem_abi_size; | |
| 6060 | .slice => try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }), | |
| 6061 | .one => try w.print("{d}", .{dest_ty.childType(zcu).arrayLen(zcu)}), | |
| 6062 | .many, .c => unreachable, | |
| 6063 | } | |
| 6064 | try w.writeAll("; ++"); | |
| 6065 | try f.writeCValue(w, index, .other); | |
| 6066 | try w.writeAll(") "); | |
| 7004 | 6067 | |
| 7005 | try f.writeCValue(w, dest_slice, .FunctionArgument); | |
| 7006 | try w.writeAll(", "); | |
| 7007 | try f.writeCValue(w, bitcasted, .FunctionArgument); | |
| 7008 | try w.print(", {d});", .{len}); | |
| 7009 | try f.object.newline(); | |
| 7010 | }, | |
| 6068 | switch (dest_ty.ptrSize(zcu)) { | |
| 6069 | .slice => try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }), | |
| 6070 | .one => try f.writeCValueDerefMember(w, dest_slice, .{ .identifier = "array" }), | |
| 7011 | 6071 | .many, .c => unreachable, |
| 7012 | 6072 | } |
| 7013 | try f.freeCValue(inst, bitcasted); | |
| 6073 | try w.writeByte('['); | |
| 6074 | try f.writeCValue(w, index, .other); | |
| 6075 | try w.writeAll("] = "); | |
| 6076 | try f.writeCValue(w, value, .other); | |
| 6077 | try w.writeByte(';'); | |
| 6078 | try f.newline(); | |
| 6079 | ||
| 7014 | 6080 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6081 | try freeLocal(f, inst, index.new_local, null); | |
| 6082 | ||
| 7015 | 6083 | return .none; |
| 7016 | 6084 | } |
| 7017 | 6085 | |
| 7018 | 6086 | fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CValue { |
| 7019 | const pt = f.object.dg.pt; | |
| 6087 | const pt = f.dg.pt; | |
| 7020 | 6088 | const zcu = pt.zcu; |
| 7021 | 6089 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7022 | 6090 | const dest_ptr = try f.resolveInst(bin_op.lhs); |
| 7023 | 6091 | const src_ptr = try f.resolveInst(bin_op.rhs); |
| 7024 | 6092 | const dest_ty = f.typeOf(bin_op.lhs); |
| 7025 | 6093 | const src_ty = f.typeOf(bin_op.rhs); |
| 7026 | const w = &f.object.code.writer; | |
| 6094 | const w = &f.code.writer; | |
| 7027 | 6095 | |
| 7028 | 6096 | if (dest_ty.ptrSize(zcu) != .one) { |
| 7029 | 6097 | try w.writeAll("if ("); |
| 7030 | try writeArrayLen(f, dest_ptr, dest_ty); | |
| 6098 | try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }); | |
| 7031 | 6099 | try w.writeAll(" != 0) "); |
| 7032 | 6100 | } |
| 7033 | 6101 | try w.writeAll(function_paren); |
| 7034 | try writeSliceOrPtr(f, w, dest_ptr, dest_ty); | |
| 6102 | switch (dest_ty.ptrSize(zcu)) { | |
| 6103 | .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "ptr" }), | |
| 6104 | .one => try f.writeCValueDerefMember(w, dest_ptr, .{ .identifier = "array" }), | |
| 6105 | .many, .c => unreachable, | |
| 6106 | } | |
| 7035 | 6107 | try w.writeAll(", "); |
| 7036 | try writeSliceOrPtr(f, w, src_ptr, src_ty); | |
| 6108 | switch (src_ty.ptrSize(zcu)) { | |
| 6109 | .slice => try f.writeCValueMember(w, src_ptr, .{ .identifier = "ptr" }), | |
| 6110 | .one => try f.writeCValueDerefMember(w, src_ptr, .{ .identifier = "array" }), | |
| 6111 | .many, .c => try f.writeCValue(w, src_ptr, .other), | |
| 6112 | } | |
| 7037 | 6113 | try w.writeAll(", "); |
| 7038 | try writeArrayLen(f, dest_ptr, dest_ty); | |
| 6114 | switch (dest_ty.ptrSize(zcu)) { | |
| 6115 | .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }), | |
| 6116 | .one => try w.print("{d}", .{dest_ty.childType(zcu).arrayLen(zcu)}), | |
| 6117 | .many, .c => unreachable, | |
| 6118 | } | |
| 7039 | 6119 | try w.writeAll(" * sizeof("); |
| 7040 | try f.renderType(w, dest_ty.elemType2(zcu)); | |
| 6120 | try f.renderType(w, dest_ty.indexableElem(zcu)); | |
| 7041 | 6121 | try w.writeAll("));"); |
| 7042 | try f.object.newline(); | |
| 6122 | try f.newline(); | |
| 7043 | 6123 | |
| 7044 | 6124 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 7045 | 6125 | return .none; |
| 7046 | 6126 | } |
| 7047 | 6127 | |
| 7048 | fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void { | |
| 7049 | const pt = f.object.dg.pt; | |
| 7050 | const zcu = pt.zcu; | |
| 7051 | const w = &f.object.code.writer; | |
| 7052 | switch (dest_ty.ptrSize(zcu)) { | |
| 7053 | .one => try w.print("{f}", .{ | |
| 7054 | try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))), | |
| 7055 | }), | |
| 7056 | .many, .c => unreachable, | |
| 7057 | .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }), | |
| 7058 | } | |
| 7059 | } | |
| 7060 | ||
| 7061 | 6128 | fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7062 | const pt = f.object.dg.pt; | |
| 6129 | const pt = f.dg.pt; | |
| 7063 | 6130 | const zcu = pt.zcu; |
| 7064 | 6131 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 7065 | 6132 | const union_ptr = try f.resolveInst(bin_op.lhs); |
| ... | ... | @@ -7069,19 +6136,18 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7069 | 6136 | const union_ty = f.typeOf(bin_op.lhs).childType(zcu); |
| 7070 | 6137 | const layout = union_ty.unionGetLayout(zcu); |
| 7071 | 6138 | if (layout.tag_size == 0) return .none; |
| 7072 | const tag_ty = union_ty.unionTagTypeSafety(zcu).?; | |
| 7073 | 6139 | |
| 7074 | const w = &f.object.code.writer; | |
| 7075 | const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); | |
| 6140 | const w = &f.code.writer; | |
| 7076 | 6141 | try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" }); |
| 7077 | try a.assign(f, w); | |
| 7078 | try f.writeCValue(w, new_tag, .Other); | |
| 7079 | try a.end(f, w); | |
| 6142 | try w.writeAll(" = "); | |
| 6143 | try f.writeCValue(w, new_tag, .other); | |
| 6144 | try w.writeByte(';'); | |
| 6145 | try f.newline(); | |
| 7080 | 6146 | return .none; |
| 7081 | 6147 | } |
| 7082 | 6148 | |
| 7083 | 6149 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7084 | const pt = f.object.dg.pt; | |
| 6150 | const pt = f.dg.pt; | |
| 7085 | 6151 | const zcu = pt.zcu; |
| 7086 | 6152 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 7087 | 6153 | |
| ... | ... | @@ -7093,17 +6159,20 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7093 | 6159 | if (layout.tag_size == 0) return .none; |
| 7094 | 6160 | |
| 7095 | 6161 | const inst_ty = f.typeOfIndex(inst); |
| 7096 | const w = &f.object.code.writer; | |
| 6162 | const w = &f.code.writer; | |
| 7097 | 6163 | const local = try f.allocLocal(inst, inst_ty); |
| 7098 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); | |
| 7099 | try f.writeCValue(w, local, .Other); | |
| 7100 | try a.assign(f, w); | |
| 6164 | try f.writeCValue(w, local, .other); | |
| 6165 | try w.writeAll(" = "); | |
| 7101 | 6166 | try f.writeCValueMember(w, operand, .{ .identifier = "tag" }); |
| 7102 | try a.end(f, w); | |
| 6167 | try w.writeByte(';'); | |
| 6168 | try f.newline(); | |
| 7103 | 6169 | return local; |
| 7104 | 6170 | } |
| 7105 | 6171 | |
| 7106 | 6172 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6173 | const zcu = f.dg.pt.zcu; | |
| 6174 | const ip = &zcu.intern_pool; | |
| 6175 | const gpa = zcu.comp.gpa; | |
| 7107 | 6176 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7108 | 6177 | |
| 7109 | 6178 | const inst_ty = f.typeOfIndex(inst); |
| ... | ... | @@ -7111,15 +6180,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7111 | 6180 | const operand = try f.resolveInst(un_op); |
| 7112 | 6181 | try reap(f, inst, &.{un_op}); |
| 7113 | 6182 | |
| 7114 | const w = &f.object.code.writer; | |
| 6183 | const w = &f.code.writer; | |
| 7115 | 6184 | const local = try f.allocLocal(inst, inst_ty); |
| 7116 | try f.writeCValue(w, local, .Other); | |
| 7117 | try w.print(" = {s}(", .{ | |
| 7118 | try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }), | |
| 6185 | try f.writeCValue(w, local, .other); | |
| 6186 | try f.need_tag_name_funcs.put(gpa, enum_ty.toIntern(), {}); | |
| 6187 | try w.print(" = zig_tagName_{f}__{d}(", .{ | |
| 6188 | fmtIdentUnsolo(enum_ty.containerTypeName(ip).toSlice(ip)), | |
| 6189 | @intFromEnum(enum_ty.toIntern()), | |
| 7119 | 6190 | }); |
| 7120 | try f.writeCValue(w, operand, .Other); | |
| 6191 | try f.writeCValue(w, operand, .other); | |
| 7121 | 6192 | try w.writeAll(");"); |
| 7122 | try f.object.newline(); | |
| 6193 | try f.newline(); | |
| 7123 | 6194 | |
| 7124 | 6195 | return local; |
| 7125 | 6196 | } |
| ... | ... | @@ -7127,40 +6198,37 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7127 | 6198 | fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7128 | 6199 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7129 | 6200 | |
| 7130 | const w = &f.object.code.writer; | |
| 6201 | const w = &f.code.writer; | |
| 7131 | 6202 | const inst_ty = f.typeOfIndex(inst); |
| 7132 | 6203 | const operand = try f.resolveInst(un_op); |
| 7133 | 6204 | try reap(f, inst, &.{un_op}); |
| 7134 | 6205 | const local = try f.allocLocal(inst, inst_ty); |
| 7135 | try f.writeCValue(w, local, .Other); | |
| 6206 | try f.writeCValue(w, local, .other); | |
| 7136 | 6207 | |
| 7137 | 6208 | try w.writeAll(" = zig_errorName["); |
| 7138 | try f.writeCValue(w, operand, .Other); | |
| 6209 | try f.writeCValue(w, operand, .other); | |
| 7139 | 6210 | try w.writeAll(" - 1];"); |
| 7140 | try f.object.newline(); | |
| 6211 | try f.newline(); | |
| 7141 | 6212 | return local; |
| 7142 | 6213 | } |
| 7143 | 6214 | |
| 7144 | 6215 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7145 | const pt = f.object.dg.pt; | |
| 7146 | const zcu = pt.zcu; | |
| 7147 | 6216 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 7148 | 6217 | |
| 7149 | 6218 | const operand = try f.resolveInst(ty_op.operand); |
| 7150 | 6219 | try reap(f, inst, &.{ty_op.operand}); |
| 7151 | 6220 | |
| 7152 | 6221 | const inst_ty = f.typeOfIndex(inst); |
| 7153 | const inst_scalar_ty = inst_ty.scalarType(zcu); | |
| 7154 | 6222 | |
| 7155 | const w = &f.object.code.writer; | |
| 6223 | const w = &f.code.writer; | |
| 7156 | 6224 | const local = try f.allocLocal(inst, inst_ty); |
| 7157 | 6225 | const v = try Vectorize.start(f, inst, w, inst_ty); |
| 7158 | const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete)); | |
| 7159 | try f.writeCValue(w, local, .Other); | |
| 6226 | try f.writeCValue(w, local, .other); | |
| 7160 | 6227 | try v.elem(f, w); |
| 7161 | try a.assign(f, w); | |
| 7162 | try f.writeCValue(w, operand, .Other); | |
| 7163 | try a.end(f, w); | |
| 6228 | try w.writeAll(" = "); | |
| 6229 | try f.writeCValue(w, operand, .other); | |
| 6230 | try w.writeByte(';'); | |
| 6231 | try f.newline(); | |
| 7164 | 6232 | try v.end(f, inst, w); |
| 7165 | 6233 | |
| 7166 | 6234 | return local; |
| ... | ... | @@ -7177,29 +6245,29 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7177 | 6245 | |
| 7178 | 6246 | const inst_ty = f.typeOfIndex(inst); |
| 7179 | 6247 | |
| 7180 | const w = &f.object.code.writer; | |
| 6248 | const w = &f.code.writer; | |
| 7181 | 6249 | const local = try f.allocLocal(inst, inst_ty); |
| 7182 | 6250 | const v = try Vectorize.start(f, inst, w, inst_ty); |
| 7183 | try f.writeCValue(w, local, .Other); | |
| 6251 | try f.writeCValue(w, local, .other); | |
| 7184 | 6252 | try v.elem(f, w); |
| 7185 | 6253 | try w.writeAll(" = "); |
| 7186 | try f.writeCValue(w, pred, .Other); | |
| 6254 | try f.writeCValue(w, pred, .other); | |
| 7187 | 6255 | try v.elem(f, w); |
| 7188 | 6256 | try w.writeAll(" ? "); |
| 7189 | try f.writeCValue(w, lhs, .Other); | |
| 6257 | try f.writeCValue(w, lhs, .other); | |
| 7190 | 6258 | try v.elem(f, w); |
| 7191 | 6259 | try w.writeAll(" : "); |
| 7192 | try f.writeCValue(w, rhs, .Other); | |
| 6260 | try f.writeCValue(w, rhs, .other); | |
| 7193 | 6261 | try v.elem(f, w); |
| 7194 | 6262 | try w.writeByte(';'); |
| 7195 | try f.object.newline(); | |
| 6263 | try f.newline(); | |
| 7196 | 6264 | try v.end(f, inst, w); |
| 7197 | 6265 | |
| 7198 | 6266 | return local; |
| 7199 | 6267 | } |
| 7200 | 6268 | |
| 7201 | 6269 | fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7202 | const pt = f.object.dg.pt; | |
| 6270 | const pt = f.dg.pt; | |
| 7203 | 6271 | const zcu = pt.zcu; |
| 7204 | 6272 | |
| 7205 | 6273 | const unwrapped = f.air.unwrapShuffleOne(zcu, inst); |
| ... | ... | @@ -7207,22 +6275,22 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7207 | 6275 | const operand = try f.resolveInst(unwrapped.operand); |
| 7208 | 6276 | const inst_ty = unwrapped.result_ty; |
| 7209 | 6277 | |
| 7210 | const w = &f.object.code.writer; | |
| 6278 | const w = &f.code.writer; | |
| 7211 | 6279 | const local = try f.allocLocal(inst, inst_ty); |
| 7212 | 6280 | try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand |
| 7213 | 6281 | for (mask, 0..) |mask_elem, out_idx| { |
| 7214 | try f.writeCValue(w, local, .Other); | |
| 6282 | try f.writeCValueMember(w, local, .{ .identifier = "array" }); | |
| 7215 | 6283 | try w.writeByte('['); |
| 7216 | try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other); | |
| 6284 | try f.dg.renderValue(w, try pt.intValue(.usize, out_idx), .other); | |
| 7217 | 6285 | try w.writeAll("] = "); |
| 7218 | 6286 | switch (mask_elem.unwrap()) { |
| 7219 | 6287 | .elem => |src_idx| { |
| 7220 | try f.writeCValue(w, operand, .Other); | |
| 6288 | try f.writeCValueMember(w, operand, .{ .identifier = "array" }); | |
| 7221 | 6289 | try w.writeByte('['); |
| 7222 | try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); | |
| 6290 | try f.dg.renderValue(w, try pt.intValue(.usize, src_idx), .other); | |
| 7223 | 6291 | try w.writeByte(']'); |
| 7224 | 6292 | }, |
| 7225 | .value => |val| try f.object.dg.renderValue(w, .fromInterned(val), .Other), | |
| 6293 | .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other), | |
| 7226 | 6294 | } |
| 7227 | 6295 | try w.writeAll(";\n"); |
| 7228 | 6296 | } |
| ... | ... | @@ -7231,7 +6299,7 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7231 | 6299 | } |
| 7232 | 6300 | |
| 7233 | 6301 | fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7234 | const pt = f.object.dg.pt; | |
| 6302 | const pt = f.dg.pt; | |
| 7235 | 6303 | const zcu = pt.zcu; |
| 7236 | 6304 | |
| 7237 | 6305 | const unwrapped = f.air.unwrapShuffleTwo(zcu, inst); |
| ... | ... | @@ -7241,38 +6309,38 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7241 | 6309 | const inst_ty = unwrapped.result_ty; |
| 7242 | 6310 | const elem_ty = inst_ty.childType(zcu); |
| 7243 | 6311 | |
| 7244 | const w = &f.object.code.writer; | |
| 6312 | const w = &f.code.writer; | |
| 7245 | 6313 | const local = try f.allocLocal(inst, inst_ty); |
| 7246 | 6314 | try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands |
| 7247 | 6315 | for (mask, 0..) |mask_elem, out_idx| { |
| 7248 | try f.writeCValue(w, local, .Other); | |
| 6316 | try f.writeCValueMember(w, local, .{ .identifier = "array" }); | |
| 7249 | 6317 | try w.writeByte('['); |
| 7250 | try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other); | |
| 6318 | try f.dg.renderValue(w, try pt.intValue(.usize, out_idx), .other); | |
| 7251 | 6319 | try w.writeAll("] = "); |
| 7252 | 6320 | switch (mask_elem.unwrap()) { |
| 7253 | 6321 | .a_elem => |src_idx| { |
| 7254 | try f.writeCValue(w, operand_a, .Other); | |
| 6322 | try f.writeCValueMember(w, operand_a, .{ .identifier = "array" }); | |
| 7255 | 6323 | try w.writeByte('['); |
| 7256 | try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); | |
| 6324 | try f.dg.renderValue(w, try pt.intValue(.usize, src_idx), .other); | |
| 7257 | 6325 | try w.writeByte(']'); |
| 7258 | 6326 | }, |
| 7259 | 6327 | .b_elem => |src_idx| { |
| 7260 | try f.writeCValue(w, operand_b, .Other); | |
| 6328 | try f.writeCValueMember(w, operand_b, .{ .identifier = "array" }); | |
| 7261 | 6329 | try w.writeByte('['); |
| 7262 | try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); | |
| 6330 | try f.dg.renderValue(w, try pt.intValue(.usize, src_idx), .other); | |
| 7263 | 6331 | try w.writeByte(']'); |
| 7264 | 6332 | }, |
| 7265 | .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other), | |
| 6333 | .undef => try f.dg.renderUndefValue(w, elem_ty, .other), | |
| 7266 | 6334 | } |
| 7267 | 6335 | try w.writeByte(';'); |
| 7268 | try f.object.newline(); | |
| 6336 | try f.newline(); | |
| 7269 | 6337 | } |
| 7270 | 6338 | |
| 7271 | 6339 | return local; |
| 7272 | 6340 | } |
| 7273 | 6341 | |
| 7274 | 6342 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7275 | const pt = f.object.dg.pt; | |
| 6343 | const pt = f.dg.pt; | |
| 7276 | 6344 | const zcu = pt.zcu; |
| 7277 | 6345 | const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce; |
| 7278 | 6346 | |
| ... | ... | @@ -7280,7 +6348,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7280 | 6348 | const operand = try f.resolveInst(reduce.operand); |
| 7281 | 6349 | try reap(f, inst, &.{reduce.operand}); |
| 7282 | 6350 | const operand_ty = f.typeOf(reduce.operand); |
| 7283 | const w = &f.object.code.writer; | |
| 6351 | const w = &f.code.writer; | |
| 7284 | 6352 | |
| 7285 | 6353 | const use_operator = scalar_ty.bitSize(zcu) <= 64; |
| 7286 | 6354 | const op: union(enum) { |
| ... | ... | @@ -7327,10 +6395,10 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7327 | 6395 | // } |
| 7328 | 6396 | |
| 7329 | 6397 | const accum = try f.allocLocal(inst, scalar_ty); |
| 7330 | try f.writeCValue(w, accum, .Other); | |
| 6398 | try f.writeCValue(w, accum, .other); | |
| 7331 | 6399 | try w.writeAll(" = "); |
| 7332 | 6400 | |
| 7333 | try f.object.dg.renderValue(w, switch (reduce.operation) { | |
| 6401 | try f.dg.renderValue(w, switch (reduce.operation) { | |
| 7334 | 6402 | .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) { |
| 7335 | 6403 | .bool => Value.false, |
| 7336 | 6404 | .int => try pt.intValue(scalar_ty, 0), |
| ... | ... | @@ -7366,58 +6434,58 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7366 | 6434 | .float => try pt.floatValue(scalar_ty, std.math.nan(f128)), |
| 7367 | 6435 | else => unreachable, |
| 7368 | 6436 | }, |
| 7369 | }, .Other); | |
| 6437 | }, .other); | |
| 7370 | 6438 | try w.writeByte(';'); |
| 7371 | try f.object.newline(); | |
| 6439 | try f.newline(); | |
| 7372 | 6440 | |
| 7373 | 6441 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 7374 | try f.writeCValue(w, accum, .Other); | |
| 6442 | try f.writeCValue(w, accum, .other); | |
| 7375 | 6443 | switch (op) { |
| 7376 | 6444 | .builtin => |func| { |
| 7377 | 6445 | try w.print(" = zig_{s}_", .{func.operation}); |
| 7378 | try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 6446 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 7379 | 6447 | try w.writeByte('('); |
| 7380 | try f.writeCValue(w, accum, .FunctionArgument); | |
| 6448 | try f.writeCValue(w, accum, .other); | |
| 7381 | 6449 | try w.writeAll(", "); |
| 7382 | try f.writeCValue(w, operand, .Other); | |
| 6450 | try f.writeCValue(w, operand, .other); | |
| 7383 | 6451 | try v.elem(f, w); |
| 7384 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, func.info); | |
| 6452 | try f.dg.renderBuiltinInfo(w, scalar_ty, func.info); | |
| 7385 | 6453 | try w.writeByte(')'); |
| 7386 | 6454 | }, |
| 7387 | 6455 | .infix => |ass| { |
| 7388 | 6456 | try w.writeAll(ass); |
| 7389 | try f.writeCValue(w, operand, .Other); | |
| 6457 | try f.writeCValue(w, operand, .other); | |
| 7390 | 6458 | try v.elem(f, w); |
| 7391 | 6459 | }, |
| 7392 | 6460 | .ternary => |cmp| { |
| 7393 | 6461 | try w.writeAll(" = "); |
| 7394 | try f.writeCValue(w, accum, .Other); | |
| 6462 | try f.writeCValue(w, accum, .other); | |
| 7395 | 6463 | try w.writeAll(cmp); |
| 7396 | try f.writeCValue(w, operand, .Other); | |
| 6464 | try f.writeCValue(w, operand, .other); | |
| 7397 | 6465 | try v.elem(f, w); |
| 7398 | 6466 | try w.writeAll(" ? "); |
| 7399 | try f.writeCValue(w, accum, .Other); | |
| 6467 | try f.writeCValue(w, accum, .other); | |
| 7400 | 6468 | try w.writeAll(" : "); |
| 7401 | try f.writeCValue(w, operand, .Other); | |
| 6469 | try f.writeCValue(w, operand, .other); | |
| 7402 | 6470 | try v.elem(f, w); |
| 7403 | 6471 | }, |
| 7404 | 6472 | } |
| 7405 | 6473 | try w.writeByte(';'); |
| 7406 | try f.object.newline(); | |
| 6474 | try f.newline(); | |
| 7407 | 6475 | try v.end(f, inst, w); |
| 7408 | 6476 | |
| 7409 | 6477 | return accum; |
| 7410 | 6478 | } |
| 7411 | 6479 | |
| 7412 | 6480 | fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7413 | const pt = f.object.dg.pt; | |
| 6481 | const pt = f.dg.pt; | |
| 7414 | 6482 | const zcu = pt.zcu; |
| 7415 | 6483 | const ip = &zcu.intern_pool; |
| 7416 | 6484 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 7417 | 6485 | const inst_ty = f.typeOfIndex(inst); |
| 7418 | 6486 | const len: usize = @intCast(inst_ty.arrayLen(zcu)); |
| 7419 | 6487 | const elements: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[ty_pl.payload..][0..len]); |
| 7420 | const gpa = f.object.dg.gpa; | |
| 6488 | const gpa = f.dg.gpa; | |
| 7421 | 6489 | const resolved_elements = try gpa.alloc(CValue, elements.len); |
| 7422 | 6490 | defer gpa.free(resolved_elements); |
| 7423 | 6491 | for (resolved_elements, elements) |*resolved_element, element| { |
| ... | ... | @@ -7430,28 +6498,23 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7430 | 6498 | } |
| 7431 | 6499 | } |
| 7432 | 6500 | |
| 7433 | const w = &f.object.code.writer; | |
| 6501 | const w = &f.code.writer; | |
| 7434 | 6502 | const local = try f.allocLocal(inst, inst_ty); |
| 7435 | 6503 | switch (ip.indexToKey(inst_ty.toIntern())) { |
| 7436 | 6504 | inline .array_type, .vector_type => |info, tag| { |
| 7437 | const a: Assignment = .{ | |
| 7438 | .ctype = try f.ctypeFromType(.fromInterned(info.child), .complete), | |
| 7439 | }; | |
| 7440 | 6505 | for (resolved_elements, 0..) |element, i| { |
| 7441 | try a.restart(f, w); | |
| 7442 | try f.writeCValue(w, local, .Other); | |
| 7443 | try w.print("[{d}]", .{i}); | |
| 7444 | try a.assign(f, w); | |
| 7445 | try f.writeCValue(w, element, .Other); | |
| 7446 | try a.end(f, w); | |
| 6506 | try f.writeCValueMember(w, local, .{ .identifier = "array" }); | |
| 6507 | try w.print("[{d}] = ", .{i}); | |
| 6508 | try f.writeCValue(w, element, .other); | |
| 6509 | try w.writeByte(';'); | |
| 6510 | try f.newline(); | |
| 7447 | 6511 | } |
| 7448 | 6512 | if (tag == .array_type and info.sentinel != .none) { |
| 7449 | try a.restart(f, w); | |
| 7450 | try f.writeCValue(w, local, .Other); | |
| 7451 | try w.print("[{d}]", .{info.len}); | |
| 7452 | try a.assign(f, w); | |
| 7453 | try f.object.dg.renderValue(w, Value.fromInterned(info.sentinel), .Other); | |
| 7454 | try a.end(f, w); | |
| 6513 | try f.writeCValueMember(w, local, .{ .identifier = "array" }); | |
| 6514 | try w.print("[{d}] = ", .{info.len}); | |
| 6515 | try f.dg.renderValue(w, Value.fromInterned(info.sentinel), .other); | |
| 6516 | try w.writeByte(';'); | |
| 6517 | try f.newline(); | |
| 7455 | 6518 | } |
| 7456 | 6519 | }, |
| 7457 | 6520 | .struct_type => { |
| ... | ... | @@ -7461,13 +6524,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7461 | 6524 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 7462 | 6525 | while (field_it.next()) |field_index| { |
| 7463 | 6526 | const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 7464 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 6527 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 7465 | 6528 | |
| 7466 | const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); | |
| 7467 | try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.fieldName(ip, field_index).toSlice(ip) }); | |
| 7468 | try a.assign(f, w); | |
| 7469 | try f.writeCValue(w, resolved_elements[field_index], .Other); | |
| 7470 | try a.end(f, w); | |
| 6529 | try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) }); | |
| 6530 | try w.writeAll(" = "); | |
| 6531 | try f.writeCValue(w, resolved_elements[field_index], .other); | |
| 6532 | try w.writeByte(';'); | |
| 6533 | try f.newline(); | |
| 7471 | 6534 | } |
| 7472 | 6535 | }, |
| 7473 | 6536 | .@"packed" => unreachable, // `Air.Legalize.Feature.expand_packed_struct_init` handles this case |
| ... | ... | @@ -7476,13 +6539,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7476 | 6539 | .tuple_type => |tuple_info| for (0..tuple_info.types.len) |field_index| { |
| 7477 | 6540 | if (tuple_info.values.get(ip)[field_index] != .none) continue; |
| 7478 | 6541 | const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); |
| 7479 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 6542 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 7480 | 6543 | |
| 7481 | const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); | |
| 7482 | 6544 | try f.writeCValueMember(w, local, .{ .field = field_index }); |
| 7483 | try a.assign(f, w); | |
| 7484 | try f.writeCValue(w, resolved_elements[field_index], .Other); | |
| 7485 | try a.end(f, w); | |
| 6545 | try w.writeAll(" = "); | |
| 6546 | try f.writeCValue(w, resolved_elements[field_index], .other); | |
| 6547 | try w.writeByte(';'); | |
| 6548 | try f.newline(); | |
| 7486 | 6549 | }, |
| 7487 | 6550 | else => unreachable, |
| 7488 | 6551 | } |
| ... | ... | @@ -7491,49 +6554,52 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7491 | 6554 | } |
| 7492 | 6555 | |
| 7493 | 6556 | fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7494 | const pt = f.object.dg.pt; | |
| 6557 | const pt = f.dg.pt; | |
| 7495 | 6558 | const zcu = pt.zcu; |
| 7496 | 6559 | const ip = &zcu.intern_pool; |
| 7497 | 6560 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 7498 | 6561 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 6562 | const field_index = extra.field_index; | |
| 7499 | 6563 | |
| 7500 | 6564 | const union_ty = f.typeOfIndex(inst); |
| 7501 | 6565 | const loaded_union = ip.loadUnionType(union_ty.toIntern()); |
| 7502 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; | |
| 7503 | const payload_ty = f.typeOf(extra.init); | |
| 6566 | const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 6567 | ||
| 7504 | 6568 | const payload = try f.resolveInst(extra.init); |
| 7505 | 6569 | try reap(f, inst, &.{extra.init}); |
| 7506 | 6570 | |
| 7507 | const w = &f.object.code.writer; | |
| 7508 | if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload); | |
| 6571 | const w = &f.code.writer; | |
| 6572 | if (loaded_union.layout == .@"packed") return f.moveCValue(inst, union_ty, payload); | |
| 7509 | 6573 | |
| 7510 | 6574 | const local = try f.allocLocal(inst, union_ty); |
| 7511 | 6575 | |
| 7512 | const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: { | |
| 7513 | const layout = union_ty.unionGetLayout(zcu); | |
| 7514 | if (layout.tag_size != 0) { | |
| 7515 | const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; | |
| 7516 | const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); | |
| 7517 | ||
| 7518 | const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); | |
| 7519 | try f.writeCValueMember(w, local, .{ .identifier = "tag" }); | |
| 7520 | try a.assign(f, w); | |
| 7521 | try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))}); | |
| 7522 | try a.end(f, w); | |
| 6576 | if (loaded_union.has_runtime_tag) { | |
| 6577 | try f.writeCValueMember(w, local, .{ .identifier = "tag" }); | |
| 6578 | if (loaded_enum.field_values.len == 0) { | |
| 6579 | // auto-numbered | |
| 6580 | try w.print(" = {d};", .{field_index}); | |
| 6581 | } else { | |
| 6582 | const tag_int_val: Value = .fromInterned(loaded_enum.field_values.get(ip)[field_index]); | |
| 6583 | try w.print(" = {f};", .{try f.fmtIntLiteralDec(tag_int_val)}); | |
| 7523 | 6584 | } |
| 7524 | break :field .{ .payload_identifier = field_name.toSlice(ip) }; | |
| 7525 | } else .{ .identifier = field_name.toSlice(ip) }; | |
| 7526 | ||
| 7527 | const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); | |
| 7528 | try f.writeCValueMember(w, local, field); | |
| 7529 | try a.assign(f, w); | |
| 7530 | try f.writeCValue(w, payload, .Other); | |
| 7531 | try a.end(f, w); | |
| 6585 | try f.newline(); | |
| 6586 | } | |
| 6587 | ||
| 6588 | const field_name_slice = loaded_enum.field_names.get(ip)[field_index].toSlice(ip); | |
| 6589 | switch (loaded_union.layout) { | |
| 6590 | .auto => try f.writeCValueMember(w, local, .{ .payload_identifier = field_name_slice }), | |
| 6591 | .@"extern" => try f.writeCValueMember(w, local, .{ .identifier = field_name_slice }), | |
| 6592 | .@"packed" => unreachable, | |
| 6593 | } | |
| 6594 | try w.writeAll(" = "); | |
| 6595 | try f.writeCValue(w, payload, .other); | |
| 6596 | try w.writeByte(';'); | |
| 6597 | try f.newline(); | |
| 7532 | 6598 | return local; |
| 7533 | 6599 | } |
| 7534 | 6600 | |
| 7535 | 6601 | fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7536 | const pt = f.object.dg.pt; | |
| 6602 | const pt = f.dg.pt; | |
| 7537 | 6603 | const zcu = pt.zcu; |
| 7538 | 6604 | const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; |
| 7539 | 6605 | |
| ... | ... | @@ -7541,16 +6607,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7541 | 6607 | const ptr = try f.resolveInst(prefetch.ptr); |
| 7542 | 6608 | try reap(f, inst, &.{prefetch.ptr}); |
| 7543 | 6609 | |
| 7544 | const w = &f.object.code.writer; | |
| 6610 | const w = &f.code.writer; | |
| 7545 | 6611 | switch (prefetch.cache) { |
| 7546 | 6612 | .data => { |
| 7547 | 6613 | try w.writeAll("zig_prefetch("); |
| 7548 | 6614 | if (ptr_ty.isSlice(zcu)) |
| 7549 | 6615 | try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" }) |
| 7550 | 6616 | else |
| 7551 | try f.writeCValue(w, ptr, .FunctionArgument); | |
| 6617 | try f.writeCValue(w, ptr, .other); | |
| 7552 | 6618 | try w.print(", {d}, {d});", .{ @intFromEnum(prefetch.rw), prefetch.locality }); |
| 7553 | try f.object.newline(); | |
| 6619 | try f.newline(); | |
| 7554 | 6620 | }, |
| 7555 | 6621 | // The available prefetch intrinsics do not accept a cache argument; only |
| 7556 | 6622 | // address, rw, and locality. |
| ... | ... | @@ -7563,14 +6629,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7563 | 6629 | fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7564 | 6630 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7565 | 6631 | |
| 7566 | const w = &f.object.code.writer; | |
| 6632 | const w = &f.code.writer; | |
| 7567 | 6633 | const inst_ty = f.typeOfIndex(inst); |
| 7568 | 6634 | const local = try f.allocLocal(inst, inst_ty); |
| 7569 | try f.writeCValue(w, local, .Other); | |
| 6635 | try f.writeCValue(w, local, .other); | |
| 7570 | 6636 | |
| 7571 | 6637 | try w.writeAll(" = "); |
| 7572 | 6638 | try w.print("zig_wasm_memory_size({d});", .{pl_op.payload}); |
| 7573 | try f.object.newline(); | |
| 6639 | try f.newline(); | |
| 7574 | 6640 | |
| 7575 | 6641 | return local; |
| 7576 | 6642 | } |
| ... | ... | @@ -7578,23 +6644,23 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7578 | 6644 | fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7579 | 6645 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7580 | 6646 | |
| 7581 | const w = &f.object.code.writer; | |
| 6647 | const w = &f.code.writer; | |
| 7582 | 6648 | const inst_ty = f.typeOfIndex(inst); |
| 7583 | 6649 | const operand = try f.resolveInst(pl_op.operand); |
| 7584 | 6650 | try reap(f, inst, &.{pl_op.operand}); |
| 7585 | 6651 | const local = try f.allocLocal(inst, inst_ty); |
| 7586 | try f.writeCValue(w, local, .Other); | |
| 6652 | try f.writeCValue(w, local, .other); | |
| 7587 | 6653 | |
| 7588 | 6654 | try w.writeAll(" = "); |
| 7589 | 6655 | try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload}); |
| 7590 | try f.writeCValue(w, operand, .FunctionArgument); | |
| 6656 | try f.writeCValue(w, operand, .other); | |
| 7591 | 6657 | try w.writeAll(");"); |
| 7592 | try f.object.newline(); | |
| 6658 | try f.newline(); | |
| 7593 | 6659 | return local; |
| 7594 | 6660 | } |
| 7595 | 6661 | |
| 7596 | 6662 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7597 | const pt = f.object.dg.pt; | |
| 6663 | const pt = f.dg.pt; | |
| 7598 | 6664 | const zcu = pt.zcu; |
| 7599 | 6665 | const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 7600 | 6666 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; |
| ... | ... | @@ -7607,24 +6673,24 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7607 | 6673 | const inst_ty = f.typeOfIndex(inst); |
| 7608 | 6674 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 7609 | 6675 | |
| 7610 | const w = &f.object.code.writer; | |
| 6676 | const w = &f.code.writer; | |
| 7611 | 6677 | const local = try f.allocLocal(inst, inst_ty); |
| 7612 | 6678 | const v = try Vectorize.start(f, inst, w, inst_ty); |
| 7613 | try f.writeCValue(w, local, .Other); | |
| 6679 | try f.writeCValue(w, local, .other); | |
| 7614 | 6680 | try v.elem(f, w); |
| 7615 | 6681 | try w.writeAll(" = zig_fma_"); |
| 7616 | try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 6682 | try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 7617 | 6683 | try w.writeByte('('); |
| 7618 | try f.writeCValue(w, mulend1, .FunctionArgument); | |
| 6684 | try f.writeCValue(w, mulend1, .other); | |
| 7619 | 6685 | try v.elem(f, w); |
| 7620 | 6686 | try w.writeAll(", "); |
| 7621 | try f.writeCValue(w, mulend2, .FunctionArgument); | |
| 6687 | try f.writeCValue(w, mulend2, .other); | |
| 7622 | 6688 | try v.elem(f, w); |
| 7623 | 6689 | try w.writeAll(", "); |
| 7624 | try f.writeCValue(w, addend, .FunctionArgument); | |
| 6690 | try f.writeCValue(w, addend, .other); | |
| 7625 | 6691 | try v.elem(f, w); |
| 7626 | 6692 | try w.writeAll(");"); |
| 7627 | try f.object.newline(); | |
| 6693 | try f.newline(); | |
| 7628 | 6694 | try v.end(f, inst, w); |
| 7629 | 6695 | |
| 7630 | 6696 | return local; |
| ... | ... | @@ -7632,34 +6698,33 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7632 | 6698 | |
| 7633 | 6699 | fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7634 | 6700 | const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 7635 | const w = &f.object.code.writer; | |
| 6701 | const w = &f.code.writer; | |
| 7636 | 6702 | const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty)); |
| 7637 | try f.writeCValue(w, local, .Other); | |
| 6703 | try f.writeCValue(w, local, .other); | |
| 7638 | 6704 | try w.writeAll(" = "); |
| 7639 | try f.object.dg.renderNav(w, ty_nav.nav, .Other); | |
| 6705 | try f.dg.renderNav(w, ty_nav.nav, .other); | |
| 7640 | 6706 | try w.writeByte(';'); |
| 7641 | try f.object.newline(); | |
| 6707 | try f.newline(); | |
| 7642 | 6708 | return local; |
| 7643 | 6709 | } |
| 7644 | 6710 | |
| 7645 | 6711 | fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7646 | const pt = f.object.dg.pt; | |
| 6712 | const pt = f.dg.pt; | |
| 7647 | 6713 | const zcu = pt.zcu; |
| 7648 | 6714 | const inst_ty = f.typeOfIndex(inst); |
| 7649 | const function_ty = zcu.navValue(f.object.dg.pass.nav).typeOf(zcu); | |
| 7650 | const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function; | |
| 7651 | assert(function_info.varargs); | |
| 7652 | 6715 | |
| 7653 | const w = &f.object.code.writer; | |
| 6716 | assert(Value.fromInterned(f.func_index).typeOf(zcu).fnIsVarArgs(zcu)); | |
| 6717 | ||
| 6718 | const w = &f.code.writer; | |
| 7654 | 6719 | const local = try f.allocLocal(inst, inst_ty); |
| 7655 | 6720 | try w.writeAll("va_start(*(va_list *)&"); |
| 7656 | try f.writeCValue(w, local, .Other); | |
| 7657 | if (function_info.param_ctypes.len > 0) { | |
| 6721 | try f.writeCValue(w, local, .other); | |
| 6722 | if (f.next_arg_index > 0) { | |
| 7658 | 6723 | try w.writeAll(", "); |
| 7659 | try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument); | |
| 6724 | try f.writeCValue(w, .{ .arg = f.next_arg_index - 1 }, .other); | |
| 7660 | 6725 | } |
| 7661 | 6726 | try w.writeAll(");"); |
| 7662 | try f.object.newline(); | |
| 6727 | try f.newline(); | |
| 7663 | 6728 | return local; |
| 7664 | 6729 | } |
| 7665 | 6730 | |
| ... | ... | @@ -7670,15 +6735,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7670 | 6735 | const va_list = try f.resolveInst(ty_op.operand); |
| 7671 | 6736 | try reap(f, inst, &.{ty_op.operand}); |
| 7672 | 6737 | |
| 7673 | const w = &f.object.code.writer; | |
| 6738 | const w = &f.code.writer; | |
| 7674 | 6739 | const local = try f.allocLocal(inst, inst_ty); |
| 7675 | try f.writeCValue(w, local, .Other); | |
| 6740 | try f.writeCValue(w, local, .other); | |
| 7676 | 6741 | try w.writeAll(" = va_arg(*(va_list *)"); |
| 7677 | try f.writeCValue(w, va_list, .Other); | |
| 6742 | try f.writeCValue(w, va_list, .other); | |
| 7678 | 6743 | try w.writeAll(", "); |
| 7679 | 6744 | try f.renderType(w, ty_op.ty.toType()); |
| 7680 | 6745 | try w.writeAll(");"); |
| 7681 | try f.object.newline(); | |
| 6746 | try f.newline(); | |
| 7682 | 6747 | return local; |
| 7683 | 6748 | } |
| 7684 | 6749 | |
| ... | ... | @@ -7688,11 +6753,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7688 | 6753 | const va_list = try f.resolveInst(un_op); |
| 7689 | 6754 | try reap(f, inst, &.{un_op}); |
| 7690 | 6755 | |
| 7691 | const w = &f.object.code.writer; | |
| 6756 | const w = &f.code.writer; | |
| 7692 | 6757 | try w.writeAll("va_end(*(va_list *)"); |
| 7693 | try f.writeCValue(w, va_list, .Other); | |
| 6758 | try f.writeCValue(w, va_list, .other); | |
| 7694 | 6759 | try w.writeAll(");"); |
| 7695 | try f.object.newline(); | |
| 6760 | try f.newline(); | |
| 7696 | 6761 | return .none; |
| 7697 | 6762 | } |
| 7698 | 6763 | |
| ... | ... | @@ -7703,14 +6768,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7703 | 6768 | const va_list = try f.resolveInst(ty_op.operand); |
| 7704 | 6769 | try reap(f, inst, &.{ty_op.operand}); |
| 7705 | 6770 | |
| 7706 | const w = &f.object.code.writer; | |
| 6771 | const w = &f.code.writer; | |
| 7707 | 6772 | const local = try f.allocLocal(inst, inst_ty); |
| 7708 | 6773 | try w.writeAll("va_copy(*(va_list *)&"); |
| 7709 | try f.writeCValue(w, local, .Other); | |
| 6774 | try f.writeCValue(w, local, .other); | |
| 7710 | 6775 | try w.writeAll(", *(va_list *)"); |
| 7711 | try f.writeCValue(w, va_list, .Other); | |
| 6776 | try f.writeCValue(w, va_list, .other); | |
| 7712 | 6777 | try w.writeAll(");"); |
| 7713 | try f.object.newline(); | |
| 6778 | try f.newline(); | |
| 7714 | 6779 | return local; |
| 7715 | 6780 | } |
| 7716 | 6781 | |
| ... | ... | @@ -8027,103 +7092,193 @@ fn undefPattern(comptime IntType: type) IntType { |
| 8027 | 7092 | |
| 8028 | 7093 | const FormatIntLiteralContext = struct { |
| 8029 | 7094 | dg: *DeclGen, |
| 8030 | int_info: InternPool.Key.IntType, | |
| 8031 | kind: CType.Kind, | |
| 8032 | ctype: CType, | |
| 7095 | loc: ValueRenderLocation, | |
| 8033 | 7096 | val: Value, |
| 7097 | cty: CType, | |
| 8034 | 7098 | base: u8, |
| 8035 | 7099 | case: std.fmt.Case, |
| 8036 | 7100 | }; |
| 8037 | 7101 | fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void { |
| 8038 | const pt = data.dg.pt; | |
| 8039 | const zcu = pt.zcu; | |
| 8040 | const target = &data.dg.mod.resolved_target.result; | |
| 8041 | const ctype_pool = &data.dg.ctype_pool; | |
| 8042 | ||
| 8043 | const ExpectedContents = struct { | |
| 8044 | const base = 10; | |
| 8045 | const bits = 128; | |
| 8046 | const limbs_count = BigInt.calcTwosCompLimbCount(bits); | |
| 8047 | ||
| 8048 | undef_limbs: [limbs_count]BigIntLimb, | |
| 8049 | wrap_limbs: [limbs_count]BigIntLimb, | |
| 8050 | to_string_buf: [bits]u8, | |
| 8051 | to_string_limbs: [BigInt.calcToStringLimbsBufferLen(limbs_count, base)]BigIntLimb, | |
| 8052 | }; | |
| 8053 | var stack align(@alignOf(ExpectedContents)) = | |
| 8054 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.dg.gpa); | |
| 8055 | const allocator = stack.get(); | |
| 8056 | ||
| 8057 | var undef_limbs: []BigIntLimb = &.{}; | |
| 8058 | defer allocator.free(undef_limbs); | |
| 8059 | ||
| 8060 | var int_buf: Value.BigIntSpace = undefined; | |
| 8061 | const int = if (data.val.isUndef(zcu)) blk: { | |
| 8062 | undef_limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)) catch return error.WriteFailed; | |
| 8063 | @memset(undef_limbs, undefPattern(BigIntLimb)); | |
| 8064 | ||
| 8065 | var undef_int = BigInt.Mutable{ | |
| 8066 | .limbs = undef_limbs, | |
| 8067 | .len = undef_limbs.len, | |
| 8068 | .positive = true, | |
| 8069 | }; | |
| 8070 | undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); | |
| 8071 | break :blk undef_int.toConst(); | |
| 8072 | } else data.val.toBigInt(&int_buf, zcu); | |
| 8073 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); | |
| 8074 | ||
| 8075 | const c_bits: usize = @intCast(data.ctype.byteSize(ctype_pool, data.dg.mod) * 8); | |
| 8076 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; | |
| 8077 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); | |
| 8078 | ||
| 8079 | var wrap = BigInt.Mutable{ | |
| 8080 | .limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)) catch return error.WriteFailed, | |
| 8081 | .len = undefined, | |
| 8082 | .positive = undefined, | |
| 8083 | }; | |
| 8084 | defer allocator.free(wrap.limbs); | |
| 8085 | ||
| 8086 | const c_limb_info: struct { | |
| 8087 | ctype: CType, | |
| 8088 | count: usize, | |
| 8089 | endian: std.builtin.Endian, | |
| 8090 | homogeneous: bool, | |
| 8091 | } = switch (data.ctype.info(ctype_pool)) { | |
| 8092 | .basic => |basic_info| switch (basic_info) { | |
| 8093 | else => .{ | |
| 8094 | .ctype = .void, | |
| 8095 | .count = 1, | |
| 8096 | .endian = .little, | |
| 8097 | .homogeneous = true, | |
| 7102 | const dg = data.dg; | |
| 7103 | const zcu = dg.pt.zcu; | |
| 7104 | const target = &dg.mod.resolved_target.result; | |
| 7105 | ||
| 7106 | const val = data.val; | |
| 7107 | const ty = val.typeOf(zcu); | |
| 7108 | ||
| 7109 | assert(!val.isUndef(zcu)); | |
| 7110 | ||
| 7111 | var space: Value.BigIntSpace = undefined; | |
| 7112 | const val_bigint = val.toBigInt(&space, zcu); | |
| 7113 | ||
| 7114 | switch (CType.classifyInt(ty, zcu)) { | |
| 7115 | .void => unreachable, // opv | |
| 7116 | .small => |int_cty| return FormatInt128.format(.{ | |
| 7117 | .target = zcu.getTarget(), | |
| 7118 | .int_cty = int_cty, | |
| 7119 | .val = val_bigint, | |
| 7120 | .is_global = data.loc == .static_initializer, | |
| 7121 | .base = data.base, | |
| 7122 | .case = data.case, | |
| 7123 | }, w), | |
| 7124 | .big => |big| { | |
| 7125 | if (!data.loc.isInitializer()) { | |
| 7126 | // Use `CType.fmtTypeName` directly to avoid the possibility of `error.OutOfMemory`. | |
| 7127 | try w.print("({f})", .{data.cty.fmtTypeName(zcu)}); | |
| 7128 | } | |
| 7129 | ||
| 7130 | try w.writeAll("{{"); | |
| 7131 | ||
| 7132 | var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined; | |
| 7133 | for (0..big.limbs_len) |limb_index| { | |
| 7134 | if (limb_index != 0) try w.writeAll(", "); | |
| 7135 | const limb_bit_offset: u16 = switch (target.cpu.arch.endian()) { | |
| 7136 | .little => @intCast(limb_index * big.limb_size.bits()), | |
| 7137 | .big => @intCast((big.limbs_len - limb_index - 1) * big.limb_size.bits()), | |
| 7138 | }; | |
| 7139 | var limb_bigint: std.math.big.int.Mutable = .{ | |
| 7140 | .limbs = &limb_buf, | |
| 7141 | .len = undefined, | |
| 7142 | .positive = undefined, | |
| 7143 | }; | |
| 7144 | limb_bigint.shiftRight(val_bigint, limb_bit_offset); | |
| 7145 | limb_bigint.truncate(limb_bigint.toConst(), .unsigned, big.limb_size.bits()); | |
| 7146 | try FormatInt128.format(.{ | |
| 7147 | .target = zcu.getTarget(), | |
| 7148 | .int_cty = big.limb_size.unsigned(), | |
| 7149 | .val = limb_bigint.toConst(), | |
| 7150 | .is_global = data.loc == .static_initializer, | |
| 7151 | .base = data.base, | |
| 7152 | .case = data.case, | |
| 7153 | }, w); | |
| 7154 | } | |
| 7155 | ||
| 7156 | try w.writeAll("}}"); | |
| 7157 | }, | |
| 7158 | } | |
| 7159 | } | |
| 7160 | const FormatInt128 = struct { | |
| 7161 | target: *const std.Target, | |
| 7162 | int_cty: CType.Int, | |
| 7163 | val: std.math.big.int.Const, | |
| 7164 | is_global: bool, | |
| 7165 | base: u8, | |
| 7166 | case: std.fmt.Case, | |
| 7167 | pub fn format(data: FormatInt128, w: *Writer) Writer.Error!void { | |
| 7168 | const target = data.target; | |
| 7169 | ||
| 7170 | const val = data.val; | |
| 7171 | const is_global = data.is_global; | |
| 7172 | const base = data.base; | |
| 7173 | const case = data.case; | |
| 7174 | ||
| 7175 | switch (data.int_cty) { | |
| 7176 | .uint8_t, | |
| 7177 | .uint16_t, | |
| 7178 | .uint32_t, | |
| 7179 | .uint64_t, | |
| 7180 | .@"unsigned short", | |
| 7181 | .@"unsigned int", | |
| 7182 | .@"unsigned long", | |
| 7183 | .@"unsigned long long", | |
| 7184 | .uintptr_t, | |
| 7185 | => |t| try w.print("{f}", .{ | |
| 7186 | fmtUnsignedIntLiteralSmall(target, t, val.toInt(u64) catch unreachable, is_global, base, case), | |
| 7187 | }), | |
| 7188 | ||
| 7189 | .int8_t, | |
| 7190 | .int16_t, | |
| 7191 | .int32_t, | |
| 7192 | .int64_t, | |
| 7193 | .char, | |
| 7194 | .@"signed short", | |
| 7195 | .@"signed int", | |
| 7196 | .@"signed long", | |
| 7197 | .@"signed long long", | |
| 7198 | .intptr_t, | |
| 7199 | => |t| try w.print("{f}", .{ | |
| 7200 | fmtSignedIntLiteralSmall(target, t, val.toInt(i64) catch unreachable, is_global, base, case), | |
| 7201 | }), | |
| 7202 | ||
| 7203 | .zig_u128 => { | |
| 7204 | const raw = val.toInt(u128) catch unreachable; | |
| 7205 | const lo: u64 = @truncate(raw); | |
| 7206 | const hi: u64 = @intCast(raw >> 64); | |
| 7207 | const macro_name: []const u8 = if (is_global) "zig_init_u128" else "zig_make_u128"; | |
| 7208 | try w.print("{s}({f}, {f})", .{ | |
| 7209 | macro_name, | |
| 7210 | fmtUnsignedIntLiteralSmall(target, .uint64_t, hi, is_global, base, case), | |
| 7211 | fmtUnsignedIntLiteralSmall(target, .uint64_t, lo, is_global, base, case), | |
| 7212 | }); | |
| 8098 | 7213 | }, |
| 8099 | .zig_u128, .zig_i128 => .{ | |
| 8100 | .ctype = .u64, | |
| 8101 | .count = 2, | |
| 8102 | .endian = .big, | |
| 8103 | .homogeneous = false, | |
| 7214 | ||
| 7215 | .zig_i128 => { | |
| 7216 | const raw = val.toInt(i128) catch unreachable; | |
| 7217 | const lo: u64 = @truncate(@as(u128, @bitCast(raw))); | |
| 7218 | const hi: i64 = @intCast(raw >> 64); | |
| 7219 | const macro_name: []const u8 = if (is_global) "zig_init_i128" else "zig_make_i128"; | |
| 7220 | try w.print("{s}({f}, {f})", .{ | |
| 7221 | macro_name, | |
| 7222 | fmtSignedIntLiteralSmall(target, .int64_t, hi, is_global, base, case), | |
| 7223 | fmtUnsignedIntLiteralSmall(target, .uint64_t, lo, is_global, base, case), | |
| 7224 | }); | |
| 8104 | 7225 | }, |
| 8105 | }, | |
| 8106 | .array => |array_info| .{ | |
| 8107 | .ctype = array_info.elem_ctype, | |
| 8108 | .count = @intCast(array_info.len), | |
| 8109 | .endian = target.cpu.arch.endian(), | |
| 8110 | .homogeneous = true, | |
| 8111 | }, | |
| 8112 | else => unreachable, | |
| 7226 | } | |
| 7227 | } | |
| 7228 | }; | |
| 7229 | fn fmtUnsignedIntLiteralSmall( | |
| 7230 | target: *const std.Target, | |
| 7231 | int_cty: CType.Int, | |
| 7232 | val: u64, | |
| 7233 | is_global: bool, | |
| 7234 | base: u8, | |
| 7235 | case: std.fmt.Case, | |
| 7236 | ) FormatUnsignedIntLiteralSmall { | |
| 7237 | return .{ | |
| 7238 | .target = target, | |
| 7239 | .int_cty = int_cty, | |
| 7240 | .val = val, | |
| 7241 | .is_global = is_global, | |
| 7242 | .base = base, | |
| 7243 | .case = case, | |
| 8113 | 7244 | }; |
| 8114 | if (c_limb_info.count == 1) { | |
| 8115 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or | |
| 8116 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) | |
| 8117 | return w.print("{s}_{s}", .{ | |
| 8118 | data.ctype.getStandardDefineAbbrev() orelse return w.print("zig_{s}Int_{c}{d}", .{ | |
| 8119 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, | |
| 8120 | }), | |
| 8121 | if (int.positive) "MAX" else "MIN", | |
| 8122 | }); | |
| 8123 | ||
| 8124 | if (!int.positive) try w.writeByte('-'); | |
| 8125 | try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool); | |
| 7245 | } | |
| 7246 | fn fmtSignedIntLiteralSmall( | |
| 7247 | target: *const std.Target, | |
| 7248 | int_cty: CType.Int, | |
| 7249 | val: i64, | |
| 7250 | is_global: bool, | |
| 7251 | base: u8, | |
| 7252 | case: std.fmt.Case, | |
| 7253 | ) FormatSignedIntLiteralSmall { | |
| 7254 | return .{ | |
| 7255 | .target = target, | |
| 7256 | .int_cty = int_cty, | |
| 7257 | .val = val, | |
| 7258 | .is_global = is_global, | |
| 7259 | .base = base, | |
| 7260 | .case = case, | |
| 7261 | }; | |
| 7262 | } | |
| 8126 | 7263 | |
| 7264 | const FormatSignedIntLiteralSmall = struct { | |
| 7265 | target: *const std.Target, | |
| 7266 | int_cty: CType.Int, | |
| 7267 | val: i64, | |
| 7268 | is_global: bool, | |
| 7269 | base: u8, | |
| 7270 | case: std.fmt.Case, | |
| 7271 | pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void { | |
| 7272 | const bits = data.int_cty.bits(data.target); | |
| 7273 | const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1); | |
| 7274 | const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1)); | |
| 7275 | if (data.val == max_int) { | |
| 7276 | return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); | |
| 7277 | } else if (data.val == min_int) { | |
| 7278 | return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)}); | |
| 7279 | } | |
| 7280 | if (data.val < 0) try w.writeByte('-'); | |
| 7281 | try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); | |
| 8127 | 7282 | switch (data.base) { |
| 8128 | 7283 | 2 => try w.writeAll("0b"), |
| 8129 | 7284 | 8 => try w.writeByte('0'), |
| ... | ... | @@ -8131,68 +7286,131 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void |
| 8131 | 7286 | 16 => try w.writeAll("0x"), |
| 8132 | 7287 | else => unreachable, |
| 8133 | 7288 | } |
| 8134 | const string = int.abs().toStringAlloc(allocator, data.base, data.case) catch | |
| 8135 | return error.WriteFailed; | |
| 8136 | defer allocator.free(string); | |
| 8137 | try w.writeAll(string); | |
| 8138 | } else { | |
| 8139 | try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool); | |
| 8140 | wrap.truncate(int, .unsigned, c_bits); | |
| 8141 | @memset(wrap.limbs[wrap.len..], 0); | |
| 8142 | wrap.len = wrap.limbs.len; | |
| 8143 | const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); | |
| 8144 | ||
| 8145 | var c_limb_int_info: std.builtin.Type.Int = .{ | |
| 8146 | .signedness = undefined, | |
| 8147 | .bits = @intCast(@divExact(c_bits, c_limb_info.count)), | |
| 8148 | }; | |
| 8149 | var c_limb_ctype: CType = undefined; | |
| 8150 | ||
| 8151 | var limb_offset: usize = 0; | |
| 8152 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; | |
| 8153 | while (limb_offset < wrap.len) : (limb_offset += limbs_per_c_limb) { | |
| 8154 | const limb_i = switch (c_limb_info.endian) { | |
| 8155 | .little => limb_offset, | |
| 8156 | .big => most_significant_limb_i - limb_offset, | |
| 8157 | }; | |
| 8158 | var c_limb_mut = BigInt.Mutable{ | |
| 8159 | .limbs = wrap.limbs[limb_i..][0..limbs_per_c_limb], | |
| 8160 | .len = undefined, | |
| 8161 | .positive = true, | |
| 8162 | }; | |
| 8163 | c_limb_mut.normalize(limbs_per_c_limb); | |
| 8164 | ||
| 8165 | if (limb_i == most_significant_limb_i and | |
| 8166 | !c_limb_info.homogeneous and data.int_info.signedness == .signed) | |
| 8167 | { | |
| 8168 | // most significant limb is actually signed | |
| 8169 | c_limb_int_info.signedness = .signed; | |
| 8170 | c_limb_ctype = c_limb_info.ctype.toSigned(); | |
| 8171 | ||
| 8172 | c_limb_mut.truncate( | |
| 8173 | c_limb_mut.toConst(), | |
| 8174 | .signed, | |
| 8175 | data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), | |
| 8176 | ); | |
| 8177 | } else { | |
| 8178 | c_limb_int_info.signedness = .unsigned; | |
| 8179 | c_limb_ctype = c_limb_info.ctype; | |
| 8180 | } | |
| 8181 | ||
| 8182 | if (limb_offset > 0) try w.writeAll(", "); | |
| 8183 | try formatIntLiteral(.{ | |
| 8184 | .dg = data.dg, | |
| 8185 | .int_info = c_limb_int_info, | |
| 8186 | .kind = data.kind, | |
| 8187 | .ctype = c_limb_ctype, | |
| 8188 | .val = pt.intValue_big(.comptime_int, c_limb_mut.toConst()) catch | |
| 8189 | return error.WriteFailed, | |
| 8190 | .base = data.base, | |
| 8191 | .case = data.case, | |
| 8192 | }, w); | |
| 7289 | // This `@abs` is safe thanks to the `min_int` case above. | |
| 7290 | try w.printInt(@abs(data.val), data.base, data.case, .{}); | |
| 7291 | try w.writeAll(intLiteralSuffix(data.int_cty)); | |
| 7292 | } | |
| 7293 | }; | |
| 7294 | const FormatUnsignedIntLiteralSmall = struct { | |
| 7295 | target: *const std.Target, | |
| 7296 | int_cty: CType.Int, | |
| 7297 | val: u64, | |
| 7298 | is_global: bool, | |
| 7299 | base: u8, | |
| 7300 | case: std.fmt.Case, | |
| 7301 | pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void { | |
| 7302 | const bits = data.int_cty.bits(data.target); | |
| 7303 | const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits); | |
| 7304 | if (data.val == max_int) { | |
| 7305 | return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); | |
| 7306 | } | |
| 7307 | try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); | |
| 7308 | switch (data.base) { | |
| 7309 | 2 => try w.writeAll("0b"), | |
| 7310 | 8 => try w.writeByte('0'), | |
| 7311 | 10 => {}, | |
| 7312 | 16 => try w.writeAll("0x"), | |
| 7313 | else => unreachable, | |
| 8193 | 7314 | } |
| 7315 | try w.printInt(data.val, data.base, data.case, .{}); | |
| 7316 | try w.writeAll(intLiteralSuffix(data.int_cty)); | |
| 8194 | 7317 | } |
| 8195 | try data.ctype.renderLiteralSuffix(w, ctype_pool); | |
| 7318 | }; | |
| 7319 | fn minMaxMacroPrefix(int_cty: CType.Int) []const u8 { | |
| 7320 | return switch (int_cty) { | |
| 7321 | // zig fmt: off | |
| 7322 | .char => "CHAR", | |
| 7323 | ||
| 7324 | .@"unsigned short" => "USHRT", | |
| 7325 | .@"unsigned int" => "UINT", | |
| 7326 | .@"unsigned long" => "ULONG", | |
| 7327 | .@"unsigned long long" => "ULLONG", | |
| 7328 | ||
| 7329 | .@"signed short" => "SHRT", | |
| 7330 | .@"signed int" => "INT", | |
| 7331 | .@"signed long" => "LONG", | |
| 7332 | .@"signed long long" => "LLONG", | |
| 7333 | ||
| 7334 | .uint8_t => "UINT8", | |
| 7335 | .uint16_t => "UINT16", | |
| 7336 | .uint32_t => "UINT32", | |
| 7337 | .uint64_t => "UINT64", | |
| 7338 | .zig_u128 => unreachable, | |
| 7339 | ||
| 7340 | .int8_t => "INT8", | |
| 7341 | .int16_t => "INT16", | |
| 7342 | .int32_t => "INT32", | |
| 7343 | .int64_t => "INT64", | |
| 7344 | .zig_i128 => unreachable, | |
| 7345 | ||
| 7346 | .uintptr_t => "UINTPTR", | |
| 7347 | .intptr_t => "INTPTR", | |
| 7348 | // zig fmt: on | |
| 7349 | }; | |
| 7350 | } | |
| 7351 | fn intLiteralPrefix(cty: CType.Int, is_global: bool) []const u8 { | |
| 7352 | return switch (cty) { | |
| 7353 | // zig fmt: off | |
| 7354 | .char => if (is_global) "" else "(char)", | |
| 7355 | ||
| 7356 | .@"unsigned short" => if (is_global) "" else "(unsigned short)", | |
| 7357 | .@"unsigned int" => "", | |
| 7358 | .@"unsigned long" => "", | |
| 7359 | .@"unsigned long long" => "", | |
| 7360 | ||
| 7361 | .@"signed short" => if (is_global) "" else "(signed short)", | |
| 7362 | .@"signed int" => "", | |
| 7363 | .@"signed long" => "", | |
| 7364 | .@"signed long long" => "", | |
| 7365 | ||
| 7366 | .uint8_t => "UINT8_C(", | |
| 7367 | .uint16_t => "UINT16_C(", | |
| 7368 | .uint32_t => "UINT32_C(", | |
| 7369 | .uint64_t => "UINT64_C(", | |
| 7370 | .zig_u128 => unreachable, | |
| 7371 | ||
| 7372 | .int8_t => "INT8_C(", | |
| 7373 | .int16_t => "INT16_C(", | |
| 7374 | .int32_t => "INT32_C(", | |
| 7375 | .int64_t => "INT64_C(", | |
| 7376 | .zig_i128 => unreachable, | |
| 7377 | ||
| 7378 | .uintptr_t => if (is_global) "" else "(uintptr_t)", | |
| 7379 | .intptr_t => if (is_global) "" else "(intptr_t)", | |
| 7380 | // zig fmt: on | |
| 7381 | }; | |
| 7382 | } | |
| 7383 | fn intLiteralSuffix(cty: CType.Int) []const u8 { | |
| 7384 | return switch (cty) { | |
| 7385 | // zig fmt: off | |
| 7386 | .char => "", | |
| 7387 | ||
| 7388 | .@"unsigned short" => "u", | |
| 7389 | .@"unsigned int" => "u", | |
| 7390 | .@"unsigned long" => "ul", | |
| 7391 | .@"unsigned long long" => "ull", | |
| 7392 | ||
| 7393 | .@"signed short" => "", | |
| 7394 | .@"signed int" => "", | |
| 7395 | .@"signed long" => "l", | |
| 7396 | .@"signed long long" => "ll", | |
| 7397 | ||
| 7398 | .uint8_t => ")", | |
| 7399 | .uint16_t => ")", | |
| 7400 | .uint32_t => ")", | |
| 7401 | .uint64_t => ")", | |
| 7402 | .zig_u128 => unreachable, | |
| 7403 | ||
| 7404 | .int8_t => ")", | |
| 7405 | .int16_t => ")", | |
| 7406 | .int32_t => ")", | |
| 7407 | .int64_t => ")", | |
| 7408 | .zig_i128 => unreachable, | |
| 7409 | ||
| 7410 | .uintptr_t => "ul", | |
| 7411 | .intptr_t => "", | |
| 7412 | // zig fmt: on | |
| 7413 | }; | |
| 8196 | 7414 | } |
| 8197 | 7415 | |
| 8198 | 7416 | const Materialize = struct { |
| ... | ... | @@ -8207,7 +7425,7 @@ const Materialize = struct { |
| 8207 | 7425 | } |
| 8208 | 7426 | |
| 8209 | 7427 | pub fn mat(self: Materialize, f: *Function, w: *Writer) !void { |
| 8210 | try f.writeCValue(w, self.local, .Other); | |
| 7428 | try f.writeCValue(w, self.local, .other); | |
| 8211 | 7429 | } |
| 8212 | 7430 | |
| 8213 | 7431 | pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -8215,95 +7433,52 @@ const Materialize = struct { |
| 8215 | 7433 | } |
| 8216 | 7434 | }; |
| 8217 | 7435 | |
| 8218 | const Assignment = struct { | |
| 8219 | ctype: CType, | |
| 8220 | ||
| 8221 | pub fn start(f: *Function, w: *Writer, ctype: CType) !Assignment { | |
| 8222 | const self: Assignment = .{ .ctype = ctype }; | |
| 8223 | try self.restart(f, w); | |
| 8224 | return self; | |
| 8225 | } | |
| 8226 | ||
| 8227 | pub fn restart(self: Assignment, f: *Function, w: *Writer) !void { | |
| 8228 | switch (self.strategy(f)) { | |
| 8229 | .assign => {}, | |
| 8230 | .memcpy => try w.writeAll("memcpy("), | |
| 8231 | } | |
| 8232 | } | |
| 8233 | ||
| 8234 | pub fn assign(self: Assignment, f: *Function, w: *Writer) !void { | |
| 8235 | switch (self.strategy(f)) { | |
| 8236 | .assign => try w.writeAll(" = "), | |
| 8237 | .memcpy => try w.writeAll(", "), | |
| 8238 | } | |
| 8239 | } | |
| 8240 | ||
| 8241 | pub fn end(self: Assignment, f: *Function, w: *Writer) !void { | |
| 8242 | switch (self.strategy(f)) { | |
| 8243 | .assign => {}, | |
| 8244 | .memcpy => { | |
| 8245 | try w.writeAll(", sizeof("); | |
| 8246 | try f.renderCType(w, self.ctype); | |
| 8247 | try w.writeAll("))"); | |
| 8248 | }, | |
| 8249 | } | |
| 8250 | try w.writeByte(';'); | |
| 8251 | try f.object.newline(); | |
| 8252 | } | |
| 8253 | ||
| 8254 | fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { | |
| 8255 | return switch (self.ctype.info(&f.object.dg.ctype_pool)) { | |
| 8256 | else => .assign, | |
| 8257 | .array, .vector => .memcpy, | |
| 8258 | }; | |
| 8259 | } | |
| 8260 | }; | |
| 8261 | ||
| 8262 | 7436 | const Vectorize = struct { |
| 8263 | 7437 | index: CValue = .none, |
| 8264 | 7438 | |
| 8265 | 7439 | pub fn start(f: *Function, inst: Air.Inst.Index, w: *Writer, ty: Type) !Vectorize { |
| 8266 | const pt = f.object.dg.pt; | |
| 7440 | const pt = f.dg.pt; | |
| 8267 | 7441 | const zcu = pt.zcu; |
| 8268 | return if (ty.zigTypeTag(zcu) == .vector) index: { | |
| 8269 | const local = try f.allocLocal(inst, .usize); | |
| 8270 | ||
| 8271 | try w.writeAll("for ("); | |
| 8272 | try f.writeCValue(w, local, .Other); | |
| 8273 | try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)}); | |
| 8274 | try f.writeCValue(w, local, .Other); | |
| 8275 | try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))}); | |
| 8276 | try f.writeCValue(w, local, .Other); | |
| 8277 | try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)}); | |
| 8278 | f.object.indent(); | |
| 8279 | try f.object.newline(); | |
| 8280 | ||
| 8281 | break :index .{ .index = local }; | |
| 8282 | } else .{}; | |
| 7442 | switch (ty.zigTypeTag(zcu)) { | |
| 7443 | else => return .{ .index = .none }, | |
| 7444 | .vector => { | |
| 7445 | const local = try f.allocLocal(inst, .usize); | |
| 7446 | try w.writeAll("for ("); | |
| 7447 | try f.writeCValue(w, local, .other); | |
| 7448 | try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)}); | |
| 7449 | try f.writeCValue(w, local, .other); | |
| 7450 | try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))}); | |
| 7451 | try f.writeCValue(w, local, .other); | |
| 7452 | try w.print(" += {f}) {{", .{try f.fmtIntLiteralDec(.one_usize)}); | |
| 7453 | f.indent(); | |
| 7454 | try f.newline(); | |
| 7455 | return .{ .index = local }; | |
| 7456 | }, | |
| 7457 | } | |
| 8283 | 7458 | } |
| 8284 | 7459 | |
| 8285 | 7460 | pub fn elem(self: Vectorize, f: *Function, w: *Writer) !void { |
| 8286 | 7461 | if (self.index != .none) { |
| 8287 | try w.writeByte('['); | |
| 8288 | try f.writeCValue(w, self.index, .Other); | |
| 7462 | try w.writeAll(".array["); | |
| 7463 | try f.writeCValue(w, self.index, .other); | |
| 8289 | 7464 | try w.writeByte(']'); |
| 8290 | 7465 | } |
| 8291 | 7466 | } |
| 8292 | 7467 | |
| 8293 | 7468 | pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void { |
| 8294 | 7469 | if (self.index != .none) { |
| 8295 | try f.object.outdent(); | |
| 7470 | try f.outdent(); | |
| 8296 | 7471 | try w.writeByte('}'); |
| 8297 | try f.object.newline(); | |
| 7472 | try f.newline(); | |
| 8298 | 7473 | try freeLocal(f, inst, self.index.new_local, null); |
| 8299 | 7474 | } |
| 8300 | 7475 | } |
| 8301 | 7476 | }; |
| 8302 | 7477 | |
| 8303 | fn lowersToArray(ty: Type, zcu: *Zcu) bool { | |
| 7478 | fn lowersToBigInt(ty: Type, zcu: *const Zcu) bool { | |
| 8304 | 7479 | return switch (ty.zigTypeTag(zcu)) { |
| 8305 | .array, .vector => return true, | |
| 8306 | else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null, | |
| 7480 | .int, .@"enum", .@"struct", .@"union" => CType.classifyInt(ty, zcu) == .big, | |
| 7481 | else => false, | |
| 8307 | 7482 | }; |
| 8308 | 7483 | } |
| 8309 | 7484 | |
| ... | ... | @@ -8329,8 +7504,8 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { |
| 8329 | 7504 | } |
| 8330 | 7505 | |
| 8331 | 7506 | fn freeLocal(f: *Function, inst: ?Air.Inst.Index, local_index: LocalIndex, ref_inst: ?Air.Inst.Index) !void { |
| 8332 | const gpa = f.object.dg.gpa; | |
| 8333 | const local = &f.locals.items[local_index]; | |
| 7507 | const gpa = f.dg.gpa; | |
| 7508 | const local = f.locals.items[local_index]; | |
| 8334 | 7509 | if (inst) |i| { |
| 8335 | 7510 | if (ref_inst) |operand| { |
| 8336 | 7511 | log.debug("%{d}: freeing t{d} (operand %{d})", .{ @intFromEnum(i), local_index, operand }); |
| ... | ... | @@ -8344,7 +7519,7 @@ fn freeLocal(f: *Function, inst: ?Air.Inst.Index, local_index: LocalIndex, ref_i |
| 8344 | 7519 | log.debug("freeing t{d}", .{local_index}); |
| 8345 | 7520 | } |
| 8346 | 7521 | } |
| 8347 | const gop = try f.free_locals_map.getOrPut(gpa, local.getType()); | |
| 7522 | const gop = try f.free_locals_map.getOrPut(gpa, local); | |
| 8348 | 7523 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 8349 | 7524 | if (std.debug.runtime_safety) { |
| 8350 | 7525 | // If this trips, an unfreeable allocation was attempted to be freed. |
| ... | ... | @@ -8401,3 +7576,28 @@ fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void { |
| 8401 | 7576 | } |
| 8402 | 7577 | map.deinit(gpa); |
| 8403 | 7578 | } |
| 7579 | ||
| 7580 | fn renderErrorName(w: *Writer, err_name: []const u8) Writer.Error!void { | |
| 7581 | try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name)}); | |
| 7582 | } | |
| 7583 | ||
| 7584 | fn renderNavName(w: *Writer, nav_index: InternPool.Nav.Index, ip: *const InternPool) !void { | |
| 7585 | const nav = ip.getNav(nav_index); | |
| 7586 | if (nav.getExtern(ip)) |@"extern"| { | |
| 7587 | try w.print("{f}", .{ | |
| 7588 | fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), | |
| 7589 | }); | |
| 7590 | } else { | |
| 7591 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), | |
| 7592 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. | |
| 7593 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); | |
| 7594 | try w.print("{f}__{d}", .{ | |
| 7595 | fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]), | |
| 7596 | @intFromEnum(nav_index), | |
| 7597 | }); | |
| 7598 | } | |
| 7599 | } | |
| 7600 | ||
| 7601 | fn renderUavName(w: *Writer, uav: Value) !void { | |
| 7602 | try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); | |
| 7603 | } |
src/codegen/c/Type.zig deleted-3472| ... | ... | @@ -1,3472 +0,0 @@ |
| 1 | index: CType.Index, | |
| 2 | ||
| 3 | pub const @"void": CType = .{ .index = .void }; | |
| 4 | pub const @"bool": CType = .{ .index = .bool }; | |
| 5 | pub const @"i8": CType = .{ .index = .int8_t }; | |
| 6 | pub const @"u8": CType = .{ .index = .uint8_t }; | |
| 7 | pub const @"i16": CType = .{ .index = .int16_t }; | |
| 8 | pub const @"u16": CType = .{ .index = .uint16_t }; | |
| 9 | pub const @"i32": CType = .{ .index = .int32_t }; | |
| 10 | pub const @"u32": CType = .{ .index = .uint32_t }; | |
| 11 | pub const @"i64": CType = .{ .index = .int64_t }; | |
| 12 | pub const @"u64": CType = .{ .index = .uint64_t }; | |
| 13 | pub const @"i128": CType = .{ .index = .zig_i128 }; | |
| 14 | pub const @"u128": CType = .{ .index = .zig_u128 }; | |
| 15 | pub const @"isize": CType = .{ .index = .intptr_t }; | |
| 16 | pub const @"usize": CType = .{ .index = .uintptr_t }; | |
| 17 | pub const @"f16": CType = .{ .index = .zig_f16 }; | |
| 18 | pub const @"f32": CType = .{ .index = .zig_f32 }; | |
| 19 | pub const @"f64": CType = .{ .index = .zig_f64 }; | |
| 20 | pub const @"f80": CType = .{ .index = .zig_f80 }; | |
| 21 | pub const @"f128": CType = .{ .index = .zig_f128 }; | |
| 22 | ||
| 23 | pub fn fromPoolIndex(pool_index: usize) CType { | |
| 24 | return .{ .index = @enumFromInt(CType.Index.first_pool_index + pool_index) }; | |
| 25 | } | |
| 26 | ||
| 27 | pub fn toPoolIndex(ctype: CType) ?u32 { | |
| 28 | const pool_index, const is_null = | |
| 29 | @subWithOverflow(@intFromEnum(ctype.index), CType.Index.first_pool_index); | |
| 30 | return switch (is_null) { | |
| 31 | 0 => pool_index, | |
| 32 | 1 => null, | |
| 33 | }; | |
| 34 | } | |
| 35 | ||
| 36 | pub fn eql(lhs: CType, rhs: CType) bool { | |
| 37 | return lhs.index == rhs.index; | |
| 38 | } | |
| 39 | ||
| 40 | pub fn isBool(ctype: CType) bool { | |
| 41 | return switch (ctype.index) { | |
| 42 | ._Bool, .bool => true, | |
| 43 | else => false, | |
| 44 | }; | |
| 45 | } | |
| 46 | ||
| 47 | pub fn isInteger(ctype: CType) bool { | |
| 48 | return switch (ctype.index) { | |
| 49 | .char, | |
| 50 | .@"signed char", | |
| 51 | .short, | |
| 52 | .int, | |
| 53 | .long, | |
| 54 | .@"long long", | |
| 55 | .@"unsigned char", | |
| 56 | .@"unsigned short", | |
| 57 | .@"unsigned int", | |
| 58 | .@"unsigned long", | |
| 59 | .@"unsigned long long", | |
| 60 | .size_t, | |
| 61 | .ptrdiff_t, | |
| 62 | .uint8_t, | |
| 63 | .int8_t, | |
| 64 | .uint16_t, | |
| 65 | .int16_t, | |
| 66 | .uint32_t, | |
| 67 | .int32_t, | |
| 68 | .uint64_t, | |
| 69 | .int64_t, | |
| 70 | .uintptr_t, | |
| 71 | .intptr_t, | |
| 72 | .zig_u128, | |
| 73 | .zig_i128, | |
| 74 | => true, | |
| 75 | else => false, | |
| 76 | }; | |
| 77 | } | |
| 78 | ||
| 79 | pub fn signedness(ctype: CType, mod: *Module) std.builtin.Signedness { | |
| 80 | return switch (ctype.index) { | |
| 81 | .char => mod.resolved_target.result.cCharSignedness(), | |
| 82 | .@"signed char", | |
| 83 | .short, | |
| 84 | .int, | |
| 85 | .long, | |
| 86 | .@"long long", | |
| 87 | .ptrdiff_t, | |
| 88 | .int8_t, | |
| 89 | .int16_t, | |
| 90 | .int32_t, | |
| 91 | .int64_t, | |
| 92 | .intptr_t, | |
| 93 | .zig_i128, | |
| 94 | => .signed, | |
| 95 | .@"unsigned char", | |
| 96 | .@"unsigned short", | |
| 97 | .@"unsigned int", | |
| 98 | .@"unsigned long", | |
| 99 | .@"unsigned long long", | |
| 100 | .size_t, | |
| 101 | .uint8_t, | |
| 102 | .uint16_t, | |
| 103 | .uint32_t, | |
| 104 | .uint64_t, | |
| 105 | .uintptr_t, | |
| 106 | .zig_u128, | |
| 107 | => .unsigned, | |
| 108 | else => unreachable, | |
| 109 | }; | |
| 110 | } | |
| 111 | ||
| 112 | pub fn isFloat(ctype: CType) bool { | |
| 113 | return switch (ctype.index) { | |
| 114 | .float, | |
| 115 | .double, | |
| 116 | .@"long double", | |
| 117 | .zig_f16, | |
| 118 | .zig_f32, | |
| 119 | .zig_f64, | |
| 120 | .zig_f80, | |
| 121 | .zig_f128, | |
| 122 | .zig_c_longdouble, | |
| 123 | => true, | |
| 124 | else => false, | |
| 125 | }; | |
| 126 | } | |
| 127 | ||
| 128 | pub fn toSigned(ctype: CType) CType { | |
| 129 | return switch (ctype.index) { | |
| 130 | .char, .@"signed char", .@"unsigned char" => .{ .index = .@"signed char" }, | |
| 131 | .short, .@"unsigned short" => .{ .index = .short }, | |
| 132 | .int, .@"unsigned int" => .{ .index = .int }, | |
| 133 | .long, .@"unsigned long" => .{ .index = .long }, | |
| 134 | .@"long long", .@"unsigned long long" => .{ .index = .@"long long" }, | |
| 135 | .size_t, .ptrdiff_t => .{ .index = .ptrdiff_t }, | |
| 136 | .uint8_t, .int8_t => .{ .index = .int8_t }, | |
| 137 | .uint16_t, .int16_t => .{ .index = .int16_t }, | |
| 138 | .uint32_t, .int32_t => .{ .index = .int32_t }, | |
| 139 | .uint64_t, .int64_t => .{ .index = .int64_t }, | |
| 140 | .uintptr_t, .intptr_t => .{ .index = .intptr_t }, | |
| 141 | .zig_u128, .zig_i128 => .{ .index = .zig_i128 }, | |
| 142 | .float, | |
| 143 | .double, | |
| 144 | .@"long double", | |
| 145 | .zig_f16, | |
| 146 | .zig_f32, | |
| 147 | .zig_f80, | |
| 148 | .zig_f128, | |
| 149 | .zig_c_longdouble, | |
| 150 | => ctype, | |
| 151 | else => unreachable, | |
| 152 | }; | |
| 153 | } | |
| 154 | ||
| 155 | pub fn toUnsigned(ctype: CType) CType { | |
| 156 | return switch (ctype.index) { | |
| 157 | .char, .@"signed char", .@"unsigned char" => .{ .index = .@"unsigned char" }, | |
| 158 | .short, .@"unsigned short" => .{ .index = .@"unsigned short" }, | |
| 159 | .int, .@"unsigned int" => .{ .index = .@"unsigned int" }, | |
| 160 | .long, .@"unsigned long" => .{ .index = .@"unsigned long" }, | |
| 161 | .@"long long", .@"unsigned long long" => .{ .index = .@"unsigned long long" }, | |
| 162 | .size_t, .ptrdiff_t => .{ .index = .size_t }, | |
| 163 | .uint8_t, .int8_t => .{ .index = .uint8_t }, | |
| 164 | .uint16_t, .int16_t => .{ .index = .uint16_t }, | |
| 165 | .uint32_t, .int32_t => .{ .index = .uint32_t }, | |
| 166 | .uint64_t, .int64_t => .{ .index = .uint64_t }, | |
| 167 | .uintptr_t, .intptr_t => .{ .index = .uintptr_t }, | |
| 168 | .zig_u128, .zig_i128 => .{ .index = .zig_u128 }, | |
| 169 | else => unreachable, | |
| 170 | }; | |
| 171 | } | |
| 172 | ||
| 173 | pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType { | |
| 174 | return switch (s) { | |
| 175 | .unsigned => ctype.toUnsigned(), | |
| 176 | .signed => ctype.toSigned(), | |
| 177 | }; | |
| 178 | } | |
| 179 | ||
| 180 | pub fn isAnyChar(ctype: CType) bool { | |
| 181 | return switch (ctype.index) { | |
| 182 | else => false, | |
| 183 | .char, .@"signed char", .@"unsigned char", .uint8_t, .int8_t => true, | |
| 184 | }; | |
| 185 | } | |
| 186 | ||
| 187 | pub fn isString(ctype: CType, pool: *const Pool) bool { | |
| 188 | return info: switch (ctype.info(pool)) { | |
| 189 | .basic, .fwd_decl, .aggregate, .function => false, | |
| 190 | .pointer => |pointer_info| pointer_info.elem_ctype.isAnyChar(), | |
| 191 | .aligned => |aligned_info| continue :info aligned_info.ctype.info(pool), | |
| 192 | .array, .vector => |sequence_info| sequence_info.elem_type.isAnyChar(), | |
| 193 | }; | |
| 194 | } | |
| 195 | ||
| 196 | pub fn isNonString(ctype: CType, pool: *const Pool) bool { | |
| 197 | var allow_pointer = true; | |
| 198 | return info: switch (ctype.info(pool)) { | |
| 199 | .basic, .fwd_decl, .aggregate, .function => false, | |
| 200 | .pointer => |pointer_info| allow_pointer and pointer_info.nonstring, | |
| 201 | .aligned => |aligned_info| continue :info aligned_info.ctype.info(pool), | |
| 202 | .array, .vector => |sequence_info| sequence_info.nonstring or { | |
| 203 | allow_pointer = false; | |
| 204 | continue :info sequence_info.elem_ctype.info(pool); | |
| 205 | }, | |
| 206 | }; | |
| 207 | } | |
| 208 | ||
| 209 | pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 { | |
| 210 | return switch (ctype.index) { | |
| 211 | .char => "CHAR", | |
| 212 | .@"signed char" => "SCHAR", | |
| 213 | .short => "SHRT", | |
| 214 | .int => "INT", | |
| 215 | .long => "LONG", | |
| 216 | .@"long long" => "LLONG", | |
| 217 | .@"unsigned char" => "UCHAR", | |
| 218 | .@"unsigned short" => "USHRT", | |
| 219 | .@"unsigned int" => "UINT", | |
| 220 | .@"unsigned long" => "ULONG", | |
| 221 | .@"unsigned long long" => "ULLONG", | |
| 222 | .float => "FLT", | |
| 223 | .double => "DBL", | |
| 224 | .@"long double" => "LDBL", | |
| 225 | .size_t => "SIZE", | |
| 226 | .ptrdiff_t => "PTRDIFF", | |
| 227 | .uint8_t => "UINT8", | |
| 228 | .int8_t => "INT8", | |
| 229 | .uint16_t => "UINT16", | |
| 230 | .int16_t => "INT16", | |
| 231 | .uint32_t => "UINT32", | |
| 232 | .int32_t => "INT32", | |
| 233 | .uint64_t => "UINT64", | |
| 234 | .int64_t => "INT64", | |
| 235 | .uintptr_t => "UINTPTR", | |
| 236 | .intptr_t => "INTPTR", | |
| 237 | else => null, | |
| 238 | }; | |
| 239 | } | |
| 240 | ||
| 241 | pub fn renderLiteralPrefix(ctype: CType, w: *Writer, kind: Kind, pool: *const Pool) Writer.Error!void { | |
| 242 | switch (ctype.info(pool)) { | |
| 243 | .basic => |basic_info| switch (basic_info) { | |
| 244 | .void => unreachable, | |
| 245 | ._Bool, | |
| 246 | .char, | |
| 247 | .@"signed char", | |
| 248 | .short, | |
| 249 | .@"unsigned short", | |
| 250 | .bool, | |
| 251 | .size_t, | |
| 252 | .ptrdiff_t, | |
| 253 | .uintptr_t, | |
| 254 | .intptr_t, | |
| 255 | => switch (kind) { | |
| 256 | else => try w.print("({s})", .{@tagName(basic_info)}), | |
| 257 | .global => {}, | |
| 258 | }, | |
| 259 | .int, | |
| 260 | .long, | |
| 261 | .@"long long", | |
| 262 | .@"unsigned char", | |
| 263 | .@"unsigned int", | |
| 264 | .@"unsigned long", | |
| 265 | .@"unsigned long long", | |
| 266 | .float, | |
| 267 | .double, | |
| 268 | .@"long double", | |
| 269 | => {}, | |
| 270 | .uint8_t, | |
| 271 | .int8_t, | |
| 272 | .uint16_t, | |
| 273 | .int16_t, | |
| 274 | .uint32_t, | |
| 275 | .int32_t, | |
| 276 | .uint64_t, | |
| 277 | .int64_t, | |
| 278 | => try w.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}), | |
| 279 | .zig_u128, | |
| 280 | .zig_i128, | |
| 281 | .zig_f16, | |
| 282 | .zig_f32, | |
| 283 | .zig_f64, | |
| 284 | .zig_f80, | |
| 285 | .zig_f128, | |
| 286 | .zig_c_longdouble, | |
| 287 | => try w.print("zig_{s}_{s}(", .{ | |
| 288 | switch (kind) { | |
| 289 | else => "make", | |
| 290 | .global => "init", | |
| 291 | }, | |
| 292 | @tagName(basic_info)["zig_".len..], | |
| 293 | }), | |
| 294 | .va_list => unreachable, | |
| 295 | _ => unreachable, | |
| 296 | }, | |
| 297 | .array, .vector => try w.writeByte('{'), | |
| 298 | else => unreachable, | |
| 299 | } | |
| 300 | } | |
| 301 | ||
| 302 | pub fn renderLiteralSuffix(ctype: CType, w: *Writer, pool: *const Pool) Writer.Error!void { | |
| 303 | switch (ctype.info(pool)) { | |
| 304 | .basic => |basic_info| switch (basic_info) { | |
| 305 | .void => unreachable, | |
| 306 | ._Bool => {}, | |
| 307 | .char, | |
| 308 | .@"signed char", | |
| 309 | .short, | |
| 310 | .int, | |
| 311 | => {}, | |
| 312 | .long => try w.writeByte('l'), | |
| 313 | .@"long long" => try w.writeAll("ll"), | |
| 314 | .@"unsigned char", | |
| 315 | .@"unsigned short", | |
| 316 | .@"unsigned int", | |
| 317 | => try w.writeByte('u'), | |
| 318 | .@"unsigned long", | |
| 319 | .size_t, | |
| 320 | .uintptr_t, | |
| 321 | => try w.writeAll("ul"), | |
| 322 | .@"unsigned long long" => try w.writeAll("ull"), | |
| 323 | .float => try w.writeByte('f'), | |
| 324 | .double => {}, | |
| 325 | .@"long double" => try w.writeByte('l'), | |
| 326 | .bool, | |
| 327 | .ptrdiff_t, | |
| 328 | .intptr_t, | |
| 329 | => {}, | |
| 330 | .uint8_t, | |
| 331 | .int8_t, | |
| 332 | .uint16_t, | |
| 333 | .int16_t, | |
| 334 | .uint32_t, | |
| 335 | .int32_t, | |
| 336 | .uint64_t, | |
| 337 | .int64_t, | |
| 338 | .zig_u128, | |
| 339 | .zig_i128, | |
| 340 | .zig_f16, | |
| 341 | .zig_f32, | |
| 342 | .zig_f64, | |
| 343 | .zig_f80, | |
| 344 | .zig_f128, | |
| 345 | .zig_c_longdouble, | |
| 346 | => try w.writeByte(')'), | |
| 347 | .va_list => unreachable, | |
| 348 | _ => unreachable, | |
| 349 | }, | |
| 350 | .array, .vector => try w.writeByte('}'), | |
| 351 | else => unreachable, | |
| 352 | } | |
| 353 | } | |
| 354 | ||
| 355 | pub fn floatActiveBits(ctype: CType, mod: *Module) u16 { | |
| 356 | const target = &mod.resolved_target.result; | |
| 357 | return switch (ctype.index) { | |
| 358 | .float => target.cTypeBitSize(.float), | |
| 359 | .double => target.cTypeBitSize(.double), | |
| 360 | .@"long double", .zig_c_longdouble => target.cTypeBitSize(.longdouble), | |
| 361 | .zig_f16 => 16, | |
| 362 | .zig_f32 => 32, | |
| 363 | .zig_f64 => 64, | |
| 364 | .zig_f80 => 80, | |
| 365 | .zig_f128 => 128, | |
| 366 | else => unreachable, | |
| 367 | }; | |
| 368 | } | |
| 369 | ||
| 370 | pub fn byteSize(ctype: CType, pool: *const Pool, mod: *Module) u64 { | |
| 371 | const target = &mod.resolved_target.result; | |
| 372 | return switch (ctype.info(pool)) { | |
| 373 | .basic => |basic_info| switch (basic_info) { | |
| 374 | .void => 0, | |
| 375 | .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, | |
| 376 | .short => target.cTypeByteSize(.short), | |
| 377 | .int => target.cTypeByteSize(.int), | |
| 378 | .long => target.cTypeByteSize(.long), | |
| 379 | .@"long long" => target.cTypeByteSize(.longlong), | |
| 380 | .@"unsigned short" => target.cTypeByteSize(.ushort), | |
| 381 | .@"unsigned int" => target.cTypeByteSize(.uint), | |
| 382 | .@"unsigned long" => target.cTypeByteSize(.ulong), | |
| 383 | .@"unsigned long long" => target.cTypeByteSize(.ulonglong), | |
| 384 | .float => target.cTypeByteSize(.float), | |
| 385 | .double => target.cTypeByteSize(.double), | |
| 386 | .@"long double" => target.cTypeByteSize(.longdouble), | |
| 387 | .size_t, | |
| 388 | .ptrdiff_t, | |
| 389 | .uintptr_t, | |
| 390 | .intptr_t, | |
| 391 | => @divExact(target.ptrBitWidth(), 8), | |
| 392 | .uint16_t, .int16_t, .zig_f16 => 2, | |
| 393 | .uint32_t, .int32_t, .zig_f32 => 4, | |
| 394 | .uint64_t, .int64_t, .zig_f64 => 8, | |
| 395 | .zig_u128, .zig_i128, .zig_f128 => 16, | |
| 396 | .zig_f80 => if (target.cTypeBitSize(.longdouble) == 80) | |
| 397 | target.cTypeByteSize(.longdouble) | |
| 398 | else | |
| 399 | 16, | |
| 400 | .zig_c_longdouble => target.cTypeByteSize(.longdouble), | |
| 401 | .va_list => unreachable, | |
| 402 | _ => unreachable, | |
| 403 | }, | |
| 404 | .pointer => @divExact(target.ptrBitWidth(), 8), | |
| 405 | .array, .vector => |sequence_info| sequence_info.elem_ctype.byteSize(pool, mod) * sequence_info.len, | |
| 406 | else => unreachable, | |
| 407 | }; | |
| 408 | } | |
| 409 | ||
| 410 | pub fn info(ctype: CType, pool: *const Pool) Info { | |
| 411 | const pool_index = ctype.toPoolIndex() orelse return .{ .basic = ctype.index }; | |
| 412 | const item = pool.items.get(pool_index); | |
| 413 | switch (item.tag) { | |
| 414 | .basic => unreachable, | |
| 415 | .pointer => return .{ .pointer = .{ | |
| 416 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | |
| 417 | } }, | |
| 418 | .pointer_const => return .{ .pointer = .{ | |
| 419 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | |
| 420 | .@"const" = true, | |
| 421 | } }, | |
| 422 | .pointer_volatile => return .{ .pointer = .{ | |
| 423 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | |
| 424 | .@"volatile" = true, | |
| 425 | } }, | |
| 426 | .pointer_const_volatile => return .{ .pointer = .{ | |
| 427 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | |
| 428 | .@"const" = true, | |
| 429 | .@"volatile" = true, | |
| 430 | } }, | |
| 431 | .aligned => { | |
| 432 | const extra = pool.getExtra(Pool.Aligned, item.data); | |
| 433 | return .{ .aligned = .{ | |
| 434 | .ctype = .{ .index = extra.ctype }, | |
| 435 | .alignas = extra.flags.alignas, | |
| 436 | } }; | |
| 437 | }, | |
| 438 | .array_small => { | |
| 439 | const extra = pool.getExtra(Pool.SequenceSmall, item.data); | |
| 440 | return .{ .array = .{ | |
| 441 | .elem_ctype = .{ .index = extra.elem_ctype }, | |
| 442 | .len = extra.len, | |
| 443 | } }; | |
| 444 | }, | |
| 445 | .array_large => { | |
| 446 | const extra = pool.getExtra(Pool.SequenceLarge, item.data); | |
| 447 | return .{ .array = .{ | |
| 448 | .elem_ctype = .{ .index = extra.elem_ctype }, | |
| 449 | .len = extra.len(), | |
| 450 | } }; | |
| 451 | }, | |
| 452 | .vector => { | |
| 453 | const extra = pool.getExtra(Pool.SequenceSmall, item.data); | |
| 454 | return .{ .vector = .{ | |
| 455 | .elem_ctype = .{ .index = extra.elem_ctype }, | |
| 456 | .len = extra.len, | |
| 457 | } }; | |
| 458 | }, | |
| 459 | .nonstring => { | |
| 460 | var child_info = info(.{ .index = @enumFromInt(item.data) }, pool); | |
| 461 | switch (child_info) { | |
| 462 | else => unreachable, | |
| 463 | .pointer => |*pointer_info| pointer_info.nonstring = true, | |
| 464 | .array, .vector => |*sequence_info| sequence_info.nonstring = true, | |
| 465 | } | |
| 466 | return child_info; | |
| 467 | }, | |
| 468 | .fwd_decl_struct_anon => { | |
| 469 | const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); | |
| 470 | return .{ .fwd_decl = .{ | |
| 471 | .tag = .@"struct", | |
| 472 | .name = .{ .anon = .{ | |
| 473 | .extra_index = extra_trail.trail.extra_index, | |
| 474 | .len = extra_trail.extra.fields_len, | |
| 475 | } }, | |
| 476 | } }; | |
| 477 | }, | |
| 478 | .fwd_decl_union_anon => { | |
| 479 | const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); | |
| 480 | return .{ .fwd_decl = .{ | |
| 481 | .tag = .@"union", | |
| 482 | .name = .{ .anon = .{ | |
| 483 | .extra_index = extra_trail.trail.extra_index, | |
| 484 | .len = extra_trail.extra.fields_len, | |
| 485 | } }, | |
| 486 | } }; | |
| 487 | }, | |
| 488 | .fwd_decl_struct => return .{ .fwd_decl = .{ | |
| 489 | .tag = .@"struct", | |
| 490 | .name = .{ .index = @enumFromInt(item.data) }, | |
| 491 | } }, | |
| 492 | .fwd_decl_union => return .{ .fwd_decl = .{ | |
| 493 | .tag = .@"union", | |
| 494 | .name = .{ .index = @enumFromInt(item.data) }, | |
| 495 | } }, | |
| 496 | .aggregate_struct_anon => { | |
| 497 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | |
| 498 | return .{ .aggregate = .{ | |
| 499 | .tag = .@"struct", | |
| 500 | .name = .{ .anon = .{ | |
| 501 | .index = extra_trail.extra.index, | |
| 502 | .id = extra_trail.extra.id, | |
| 503 | } }, | |
| 504 | .fields = .{ | |
| 505 | .extra_index = extra_trail.trail.extra_index, | |
| 506 | .len = extra_trail.extra.fields_len, | |
| 507 | }, | |
| 508 | } }; | |
| 509 | }, | |
| 510 | .aggregate_union_anon => { | |
| 511 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | |
| 512 | return .{ .aggregate = .{ | |
| 513 | .tag = .@"union", | |
| 514 | .name = .{ .anon = .{ | |
| 515 | .index = extra_trail.extra.index, | |
| 516 | .id = extra_trail.extra.id, | |
| 517 | } }, | |
| 518 | .fields = .{ | |
| 519 | .extra_index = extra_trail.trail.extra_index, | |
| 520 | .len = extra_trail.extra.fields_len, | |
| 521 | }, | |
| 522 | } }; | |
| 523 | }, | |
| 524 | .aggregate_struct_packed_anon => { | |
| 525 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | |
| 526 | return .{ .aggregate = .{ | |
| 527 | .tag = .@"struct", | |
| 528 | .@"packed" = true, | |
| 529 | .name = .{ .anon = .{ | |
| 530 | .index = extra_trail.extra.index, | |
| 531 | .id = extra_trail.extra.id, | |
| 532 | } }, | |
| 533 | .fields = .{ | |
| 534 | .extra_index = extra_trail.trail.extra_index, | |
| 535 | .len = extra_trail.extra.fields_len, | |
| 536 | }, | |
| 537 | } }; | |
| 538 | }, | |
| 539 | .aggregate_union_packed_anon => { | |
| 540 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | |
| 541 | return .{ .aggregate = .{ | |
| 542 | .tag = .@"union", | |
| 543 | .@"packed" = true, | |
| 544 | .name = .{ .anon = .{ | |
| 545 | .index = extra_trail.extra.index, | |
| 546 | .id = extra_trail.extra.id, | |
| 547 | } }, | |
| 548 | .fields = .{ | |
| 549 | .extra_index = extra_trail.trail.extra_index, | |
| 550 | .len = extra_trail.extra.fields_len, | |
| 551 | }, | |
| 552 | } }; | |
| 553 | }, | |
| 554 | .aggregate_struct => { | |
| 555 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | |
| 556 | return .{ .aggregate = .{ | |
| 557 | .tag = .@"struct", | |
| 558 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | |
| 559 | .fields = .{ | |
| 560 | .extra_index = extra_trail.trail.extra_index, | |
| 561 | .len = extra_trail.extra.fields_len, | |
| 562 | }, | |
| 563 | } }; | |
| 564 | }, | |
| 565 | .aggregate_union => { | |
| 566 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | |
| 567 | return .{ .aggregate = .{ | |
| 568 | .tag = .@"union", | |
| 569 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | |
| 570 | .fields = .{ | |
| 571 | .extra_index = extra_trail.trail.extra_index, | |
| 572 | .len = extra_trail.extra.fields_len, | |
| 573 | }, | |
| 574 | } }; | |
| 575 | }, | |
| 576 | .aggregate_struct_packed => { | |
| 577 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | |
| 578 | return .{ .aggregate = .{ | |
| 579 | .tag = .@"struct", | |
| 580 | .@"packed" = true, | |
| 581 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | |
| 582 | .fields = .{ | |
| 583 | .extra_index = extra_trail.trail.extra_index, | |
| 584 | .len = extra_trail.extra.fields_len, | |
| 585 | }, | |
| 586 | } }; | |
| 587 | }, | |
| 588 | .aggregate_union_packed => { | |
| 589 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | |
| 590 | return .{ .aggregate = .{ | |
| 591 | .tag = .@"union", | |
| 592 | .@"packed" = true, | |
| 593 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | |
| 594 | .fields = .{ | |
| 595 | .extra_index = extra_trail.trail.extra_index, | |
| 596 | .len = extra_trail.extra.fields_len, | |
| 597 | }, | |
| 598 | } }; | |
| 599 | }, | |
| 600 | .function => { | |
| 601 | const extra_trail = pool.getExtraTrail(Pool.Function, item.data); | |
| 602 | return .{ .function = .{ | |
| 603 | .return_ctype = .{ .index = extra_trail.extra.return_ctype }, | |
| 604 | .param_ctypes = .{ | |
| 605 | .extra_index = extra_trail.trail.extra_index, | |
| 606 | .len = extra_trail.extra.param_ctypes_len, | |
| 607 | }, | |
| 608 | .varargs = false, | |
| 609 | } }; | |
| 610 | }, | |
| 611 | .function_varargs => { | |
| 612 | const extra_trail = pool.getExtraTrail(Pool.Function, item.data); | |
| 613 | return .{ .function = .{ | |
| 614 | .return_ctype = .{ .index = extra_trail.extra.return_ctype }, | |
| 615 | .param_ctypes = .{ | |
| 616 | .extra_index = extra_trail.trail.extra_index, | |
| 617 | .len = extra_trail.extra.param_ctypes_len, | |
| 618 | }, | |
| 619 | .varargs = true, | |
| 620 | } }; | |
| 621 | }, | |
| 622 | } | |
| 623 | } | |
| 624 | ||
| 625 | pub fn hash(ctype: CType, pool: *const Pool) Pool.Map.Hash { | |
| 626 | return if (ctype.toPoolIndex()) |pool_index| | |
| 627 | pool.map.entries.items(.hash)[pool_index] | |
| 628 | else | |
| 629 | CType.Index.basic_hashes[@intFromEnum(ctype.index)]; | |
| 630 | } | |
| 631 | ||
| 632 | fn toForward(ctype: CType, pool: *Pool, allocator: std.mem.Allocator) !CType { | |
| 633 | return switch (ctype.info(pool)) { | |
| 634 | .basic, .pointer, .fwd_decl => ctype, | |
| 635 | .aligned => |aligned_info| pool.getAligned(allocator, .{ | |
| 636 | .ctype = try aligned_info.ctype.toForward(pool, allocator), | |
| 637 | .alignas = aligned_info.alignas, | |
| 638 | }), | |
| 639 | .array => |array_info| pool.getArray(allocator, .{ | |
| 640 | .elem_ctype = try array_info.elem_ctype.toForward(pool, allocator), | |
| 641 | .len = array_info.len, | |
| 642 | .nonstring = array_info.nonstring, | |
| 643 | }), | |
| 644 | .vector => |vector_info| pool.getVector(allocator, .{ | |
| 645 | .elem_ctype = try vector_info.elem_ctype.toForward(pool, allocator), | |
| 646 | .len = vector_info.len, | |
| 647 | .nonstring = vector_info.nonstring, | |
| 648 | }), | |
| 649 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | |
| 650 | .anon => ctype, | |
| 651 | .fwd_decl => |fwd_decl| fwd_decl, | |
| 652 | }, | |
| 653 | .function => unreachable, | |
| 654 | }; | |
| 655 | } | |
| 656 | ||
| 657 | const Index = enum(u32) { | |
| 658 | void, | |
| 659 | ||
| 660 | // C basic types | |
| 661 | char, | |
| 662 | ||
| 663 | @"signed char", | |
| 664 | short, | |
| 665 | int, | |
| 666 | long, | |
| 667 | @"long long", | |
| 668 | ||
| 669 | _Bool, | |
| 670 | @"unsigned char", | |
| 671 | @"unsigned short", | |
| 672 | @"unsigned int", | |
| 673 | @"unsigned long", | |
| 674 | @"unsigned long long", | |
| 675 | ||
| 676 | float, | |
| 677 | double, | |
| 678 | @"long double", | |
| 679 | ||
| 680 | // C header types | |
| 681 | // - stdbool.h | |
| 682 | bool, | |
| 683 | // - stddef.h | |
| 684 | size_t, | |
| 685 | ptrdiff_t, | |
| 686 | // - stdint.h | |
| 687 | uint8_t, | |
| 688 | int8_t, | |
| 689 | uint16_t, | |
| 690 | int16_t, | |
| 691 | uint32_t, | |
| 692 | int32_t, | |
| 693 | uint64_t, | |
| 694 | int64_t, | |
| 695 | uintptr_t, | |
| 696 | intptr_t, | |
| 697 | // - stdarg.h | |
| 698 | va_list, | |
| 699 | ||
| 700 | // zig.h types | |
| 701 | zig_u128, | |
| 702 | zig_i128, | |
| 703 | zig_f16, | |
| 704 | zig_f32, | |
| 705 | zig_f64, | |
| 706 | zig_f80, | |
| 707 | zig_f128, | |
| 708 | zig_c_longdouble, | |
| 709 | ||
| 710 | _, | |
| 711 | ||
| 712 | const first_pool_index: u32 = @typeInfo(CType.Index).@"enum".fields.len; | |
| 713 | const basic_hashes = init: { | |
| 714 | @setEvalBranchQuota(1_600); | |
| 715 | var basic_hashes_init: [first_pool_index]Pool.Map.Hash = undefined; | |
| 716 | for (&basic_hashes_init, 0..) |*basic_hash, index| { | |
| 717 | const ctype_index: CType.Index = @enumFromInt(index); | |
| 718 | var hasher = Pool.Hasher.init; | |
| 719 | hasher.update(@intFromEnum(ctype_index)); | |
| 720 | basic_hash.* = hasher.final(.basic); | |
| 721 | } | |
| 722 | break :init basic_hashes_init; | |
| 723 | }; | |
| 724 | }; | |
| 725 | ||
| 726 | const Slice = struct { | |
| 727 | extra_index: Pool.ExtraIndex, | |
| 728 | len: u32, | |
| 729 | ||
| 730 | pub fn at(slice: CType.Slice, index: usize, pool: *const Pool) CType { | |
| 731 | var extra: Pool.ExtraTrail = .{ .extra_index = slice.extra_index }; | |
| 732 | return .{ .index = extra.next(slice.len, CType.Index, pool)[index] }; | |
| 733 | } | |
| 734 | }; | |
| 735 | ||
| 736 | pub const Kind = enum { | |
| 737 | forward, | |
| 738 | forward_parameter, | |
| 739 | complete, | |
| 740 | global, | |
| 741 | parameter, | |
| 742 | ||
| 743 | pub fn isForward(kind: Kind) bool { | |
| 744 | return switch (kind) { | |
| 745 | .forward, .forward_parameter => true, | |
| 746 | .complete, .global, .parameter => false, | |
| 747 | }; | |
| 748 | } | |
| 749 | ||
| 750 | pub fn isParameter(kind: Kind) bool { | |
| 751 | return switch (kind) { | |
| 752 | .forward_parameter, .parameter => true, | |
| 753 | .forward, .complete, .global => false, | |
| 754 | }; | |
| 755 | } | |
| 756 | ||
| 757 | pub fn asParameter(kind: Kind) Kind { | |
| 758 | return switch (kind) { | |
| 759 | .forward, .forward_parameter => .forward_parameter, | |
| 760 | .complete, .parameter, .global => .parameter, | |
| 761 | }; | |
| 762 | } | |
| 763 | ||
| 764 | pub fn noParameter(kind: Kind) Kind { | |
| 765 | return switch (kind) { | |
| 766 | .forward, .forward_parameter => .forward, | |
| 767 | .complete, .parameter => .complete, | |
| 768 | .global => .global, | |
| 769 | }; | |
| 770 | } | |
| 771 | ||
| 772 | pub fn asComplete(kind: Kind) Kind { | |
| 773 | return switch (kind) { | |
| 774 | .forward, .complete => .complete, | |
| 775 | .forward_parameter, .parameter => .parameter, | |
| 776 | .global => .global, | |
| 777 | }; | |
| 778 | } | |
| 779 | }; | |
| 780 | ||
| 781 | pub const Info = union(enum) { | |
| 782 | basic: CType.Index, | |
| 783 | pointer: Pointer, | |
| 784 | aligned: Aligned, | |
| 785 | array: Sequence, | |
| 786 | vector: Sequence, | |
| 787 | fwd_decl: FwdDecl, | |
| 788 | aggregate: Aggregate, | |
| 789 | function: Function, | |
| 790 | ||
| 791 | const Tag = @typeInfo(Info).@"union".tag_type.?; | |
| 792 | ||
| 793 | pub const Pointer = struct { | |
| 794 | elem_ctype: CType, | |
| 795 | @"const": bool = false, | |
| 796 | @"volatile": bool = false, | |
| 797 | nonstring: bool = false, | |
| 798 | ||
| 799 | fn tag(pointer_info: Pointer) Pool.Tag { | |
| 800 | return @enumFromInt(@intFromEnum(Pool.Tag.pointer) + | |
| 801 | @as(u2, @bitCast(packed struct(u2) { | |
| 802 | @"const": bool, | |
| 803 | @"volatile": bool, | |
| 804 | }{ | |
| 805 | .@"const" = pointer_info.@"const", | |
| 806 | .@"volatile" = pointer_info.@"volatile", | |
| 807 | }))); | |
| 808 | } | |
| 809 | }; | |
| 810 | ||
| 811 | pub const Aligned = struct { | |
| 812 | ctype: CType, | |
| 813 | alignas: AlignAs, | |
| 814 | }; | |
| 815 | ||
| 816 | pub const Sequence = struct { | |
| 817 | elem_ctype: CType, | |
| 818 | len: u64, | |
| 819 | nonstring: bool = false, | |
| 820 | }; | |
| 821 | ||
| 822 | pub const AggregateTag = enum { @"enum", @"struct", @"union" }; | |
| 823 | ||
| 824 | pub const Field = struct { | |
| 825 | name: Pool.String, | |
| 826 | ctype: CType, | |
| 827 | alignas: AlignAs, | |
| 828 | ||
| 829 | pub const Slice = struct { | |
| 830 | extra_index: Pool.ExtraIndex, | |
| 831 | len: u32, | |
| 832 | ||
| 833 | pub fn at(slice: Field.Slice, index: usize, pool: *const Pool) Field { | |
| 834 | assert(index < slice.len); | |
| 835 | const extra = pool.getExtra(Pool.Field, @intCast(slice.extra_index + | |
| 836 | index * @typeInfo(Pool.Field).@"struct".fields.len)); | |
| 837 | return .{ | |
| 838 | .name = .{ .index = extra.name }, | |
| 839 | .ctype = .{ .index = extra.ctype }, | |
| 840 | .alignas = extra.flags.alignas, | |
| 841 | }; | |
| 842 | } | |
| 843 | ||
| 844 | fn eqlAdapted( | |
| 845 | lhs_slice: Field.Slice, | |
| 846 | lhs_pool: *const Pool, | |
| 847 | rhs_slice: Field.Slice, | |
| 848 | rhs_pool: *const Pool, | |
| 849 | pool_adapter: anytype, | |
| 850 | ) bool { | |
| 851 | if (lhs_slice.len != rhs_slice.len) return false; | |
| 852 | for (0..lhs_slice.len) |index| { | |
| 853 | if (!lhs_slice.at(index, lhs_pool).eqlAdapted( | |
| 854 | lhs_pool, | |
| 855 | rhs_slice.at(index, rhs_pool), | |
| 856 | rhs_pool, | |
| 857 | pool_adapter, | |
| 858 | )) return false; | |
| 859 | } | |
| 860 | return true; | |
| 861 | } | |
| 862 | }; | |
| 863 | ||
| 864 | fn eqlAdapted( | |
| 865 | lhs_field: Field, | |
| 866 | lhs_pool: *const Pool, | |
| 867 | rhs_field: Field, | |
| 868 | rhs_pool: *const Pool, | |
| 869 | pool_adapter: anytype, | |
| 870 | ) bool { | |
| 871 | if (!std.meta.eql(lhs_field.alignas, rhs_field.alignas)) return false; | |
| 872 | if (!pool_adapter.eql(lhs_field.ctype, rhs_field.ctype)) return false; | |
| 873 | return if (lhs_field.name.toPoolSlice(lhs_pool)) |lhs_name| | |
| 874 | if (rhs_field.name.toPoolSlice(rhs_pool)) |rhs_name| | |
| 875 | std.mem.eql(u8, lhs_name, rhs_name) | |
| 876 | else | |
| 877 | false | |
| 878 | else | |
| 879 | lhs_field.name.index == rhs_field.name.index; | |
| 880 | } | |
| 881 | }; | |
| 882 | ||
| 883 | pub const FwdDecl = struct { | |
| 884 | tag: AggregateTag, | |
| 885 | name: union(enum) { | |
| 886 | anon: Field.Slice, | |
| 887 | index: InternPool.Index, | |
| 888 | }, | |
| 889 | }; | |
| 890 | ||
| 891 | pub const Aggregate = struct { | |
| 892 | tag: AggregateTag, | |
| 893 | @"packed": bool = false, | |
| 894 | name: union(enum) { | |
| 895 | anon: struct { | |
| 896 | index: InternPool.Index, | |
| 897 | id: u32, | |
| 898 | }, | |
| 899 | fwd_decl: CType, | |
| 900 | }, | |
| 901 | fields: Field.Slice, | |
| 902 | }; | |
| 903 | ||
| 904 | pub const Function = struct { | |
| 905 | return_ctype: CType, | |
| 906 | param_ctypes: CType.Slice, | |
| 907 | varargs: bool = false, | |
| 908 | }; | |
| 909 | ||
| 910 | pub fn eqlAdapted( | |
| 911 | lhs_info: Info, | |
| 912 | lhs_pool: *const Pool, | |
| 913 | rhs_ctype: CType, | |
| 914 | rhs_pool: *const Pool, | |
| 915 | pool_adapter: anytype, | |
| 916 | ) bool { | |
| 917 | const rhs_info = rhs_ctype.info(rhs_pool); | |
| 918 | if (@as(Info.Tag, lhs_info) != @as(Info.Tag, rhs_info)) return false; | |
| 919 | return switch (lhs_info) { | |
| 920 | .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic, | |
| 921 | .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and | |
| 922 | lhs_pointer_info.@"volatile" == rhs_info.pointer.@"volatile" and | |
| 923 | lhs_pointer_info.nonstring == rhs_info.pointer.nonstring and | |
| 924 | pool_adapter.eql(lhs_pointer_info.elem_ctype, rhs_info.pointer.elem_ctype), | |
| 925 | .aligned => |lhs_aligned_info| std.meta.eql(lhs_aligned_info.alignas, rhs_info.aligned.alignas) and | |
| 926 | pool_adapter.eql(lhs_aligned_info.ctype, rhs_info.aligned.ctype), | |
| 927 | .array => |lhs_array_info| lhs_array_info.len == rhs_info.array.len and | |
| 928 | lhs_array_info.nonstring == rhs_info.array.nonstring and | |
| 929 | pool_adapter.eql(lhs_array_info.elem_ctype, rhs_info.array.elem_ctype), | |
| 930 | .vector => |lhs_vector_info| lhs_vector_info.len == rhs_info.vector.len and | |
| 931 | lhs_vector_info.nonstring == rhs_info.vector.nonstring and | |
| 932 | pool_adapter.eql(lhs_vector_info.elem_ctype, rhs_info.vector.elem_ctype), | |
| 933 | .fwd_decl => |lhs_fwd_decl_info| lhs_fwd_decl_info.tag == rhs_info.fwd_decl.tag and | |
| 934 | switch (lhs_fwd_decl_info.name) { | |
| 935 | .anon => |lhs_anon| rhs_info.fwd_decl.name == .anon and lhs_anon.eqlAdapted( | |
| 936 | lhs_pool, | |
| 937 | rhs_info.fwd_decl.name.anon, | |
| 938 | rhs_pool, | |
| 939 | pool_adapter, | |
| 940 | ), | |
| 941 | .index => |lhs_index| rhs_info.fwd_decl.name == .index and | |
| 942 | lhs_index == rhs_info.fwd_decl.name.index, | |
| 943 | }, | |
| 944 | .aggregate => |lhs_aggregate_info| lhs_aggregate_info.tag == rhs_info.aggregate.tag and | |
| 945 | lhs_aggregate_info.@"packed" == rhs_info.aggregate.@"packed" and | |
| 946 | switch (lhs_aggregate_info.name) { | |
| 947 | .anon => |lhs_anon| rhs_info.aggregate.name == .anon and | |
| 948 | lhs_anon.index == rhs_info.aggregate.name.anon.index and | |
| 949 | lhs_anon.id == rhs_info.aggregate.name.anon.id, | |
| 950 | .fwd_decl => |lhs_fwd_decl| rhs_info.aggregate.name == .fwd_decl and | |
| 951 | pool_adapter.eql(lhs_fwd_decl, rhs_info.aggregate.name.fwd_decl), | |
| 952 | } and lhs_aggregate_info.fields.eqlAdapted( | |
| 953 | lhs_pool, | |
| 954 | rhs_info.aggregate.fields, | |
| 955 | rhs_pool, | |
| 956 | pool_adapter, | |
| 957 | ), | |
| 958 | .function => |lhs_function_info| lhs_function_info.param_ctypes.len == | |
| 959 | rhs_info.function.param_ctypes.len and | |
| 960 | pool_adapter.eql(lhs_function_info.return_ctype, rhs_info.function.return_ctype) and | |
| 961 | for (0..lhs_function_info.param_ctypes.len) |param_index| { | |
| 962 | if (!pool_adapter.eql( | |
| 963 | lhs_function_info.param_ctypes.at(param_index, lhs_pool), | |
| 964 | rhs_info.function.param_ctypes.at(param_index, rhs_pool), | |
| 965 | )) break false; | |
| 966 | } else true, | |
| 967 | }; | |
| 968 | } | |
| 969 | }; | |
| 970 | ||
| 971 | pub const Pool = struct { | |
| 972 | map: Map, | |
| 973 | items: std.MultiArrayList(Item), | |
| 974 | extra: std.ArrayList(u32), | |
| 975 | ||
| 976 | string_map: Map, | |
| 977 | string_indices: std.ArrayList(u32), | |
| 978 | string_bytes: std.ArrayList(u8), | |
| 979 | ||
| 980 | const Map = std.AutoArrayHashMapUnmanaged(void, void); | |
| 981 | ||
| 982 | pub const String = struct { | |
| 983 | index: String.Index, | |
| 984 | ||
| 985 | const FormatData = struct { string: String, pool: *const Pool }; | |
| 986 | fn format(data: FormatData, writer: *Writer) Writer.Error!void { | |
| 987 | if (data.string.toSlice(data.pool)) |slice| | |
| 988 | try writer.writeAll(slice) | |
| 989 | else | |
| 990 | try writer.print("f{d}", .{@intFromEnum(data.string.index)}); | |
| 991 | } | |
| 992 | pub fn fmt(str: String, pool: *const Pool) std.fmt.Alt(FormatData, format) { | |
| 993 | return .{ .data = .{ .string = str, .pool = pool } }; | |
| 994 | } | |
| 995 | ||
| 996 | fn fromUnnamed(index: u31) String { | |
| 997 | return .{ .index = @enumFromInt(index) }; | |
| 998 | } | |
| 999 | ||
| 1000 | fn isNamed(str: String) bool { | |
| 1001 | return @intFromEnum(str.index) >= String.Index.first_named_index; | |
| 1002 | } | |
| 1003 | ||
| 1004 | pub fn toSlice(str: String, pool: *const Pool) ?[]const u8 { | |
| 1005 | return str.toPoolSlice(pool) orelse if (str.isNamed()) @tagName(str.index) else null; | |
| 1006 | } | |
| 1007 | ||
| 1008 | fn toPoolSlice(str: String, pool: *const Pool) ?[]const u8 { | |
| 1009 | if (str.toPoolIndex()) |pool_index| { | |
| 1010 | const start = pool.string_indices.items[pool_index + 0]; | |
| 1011 | const end = pool.string_indices.items[pool_index + 1]; | |
| 1012 | return pool.string_bytes.items[start..end]; | |
| 1013 | } else return null; | |
| 1014 | } | |
| 1015 | ||
| 1016 | fn fromPoolIndex(pool_index: usize) String { | |
| 1017 | return .{ .index = @enumFromInt(String.Index.first_pool_index + pool_index) }; | |
| 1018 | } | |
| 1019 | ||
| 1020 | fn toPoolIndex(str: String) ?u32 { | |
| 1021 | const pool_index, const is_null = | |
| 1022 | @subWithOverflow(@intFromEnum(str.index), String.Index.first_pool_index); | |
| 1023 | return switch (is_null) { | |
| 1024 | 0 => pool_index, | |
| 1025 | 1 => null, | |
| 1026 | }; | |
| 1027 | } | |
| 1028 | ||
| 1029 | const Index = enum(u32) { | |
| 1030 | array = first_named_index, | |
| 1031 | @"error", | |
| 1032 | is_null, | |
| 1033 | len, | |
| 1034 | payload, | |
| 1035 | ptr, | |
| 1036 | tag, | |
| 1037 | _, | |
| 1038 | ||
| 1039 | const first_named_index: u32 = 1 << 31; | |
| 1040 | const first_pool_index: u32 = first_named_index + @typeInfo(String.Index).@"enum".fields.len; | |
| 1041 | }; | |
| 1042 | ||
| 1043 | const Adapter = struct { | |
| 1044 | pool: *const Pool, | |
| 1045 | pub fn hash(_: @This(), slice: []const u8) Map.Hash { | |
| 1046 | return @truncate(Hasher.Impl.hash(1, slice)); | |
| 1047 | } | |
| 1048 | pub fn eql(string_adapter: @This(), lhs_slice: []const u8, _: void, rhs_index: usize) bool { | |
| 1049 | const rhs_string = String.fromPoolIndex(rhs_index); | |
| 1050 | const rhs_slice = rhs_string.toPoolSlice(string_adapter.pool).?; | |
| 1051 | return std.mem.eql(u8, lhs_slice, rhs_slice); | |
| 1052 | } | |
| 1053 | }; | |
| 1054 | }; | |
| 1055 | ||
| 1056 | pub const empty: Pool = .{ | |
| 1057 | .map = .{}, | |
| 1058 | .items = .{}, | |
| 1059 | .extra = .{}, | |
| 1060 | ||
| 1061 | .string_map = .{}, | |
| 1062 | .string_indices = .{}, | |
| 1063 | .string_bytes = .{}, | |
| 1064 | }; | |
| 1065 | ||
| 1066 | pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void { | |
| 1067 | if (pool.string_indices.items.len == 0) | |
| 1068 | try pool.string_indices.append(allocator, 0); | |
| 1069 | } | |
| 1070 | ||
| 1071 | pub fn deinit(pool: *Pool, allocator: std.mem.Allocator) void { | |
| 1072 | pool.map.deinit(allocator); | |
| 1073 | pool.items.deinit(allocator); | |
| 1074 | pool.extra.deinit(allocator); | |
| 1075 | ||
| 1076 | pool.string_map.deinit(allocator); | |
| 1077 | pool.string_indices.deinit(allocator); | |
| 1078 | pool.string_bytes.deinit(allocator); | |
| 1079 | ||
| 1080 | pool.* = undefined; | |
| 1081 | } | |
| 1082 | ||
| 1083 | pub fn move(pool: *Pool) Pool { | |
| 1084 | defer pool.* = empty; | |
| 1085 | return pool.*; | |
| 1086 | } | |
| 1087 | ||
| 1088 | pub fn clearRetainingCapacity(pool: *Pool) void { | |
| 1089 | pool.map.clearRetainingCapacity(); | |
| 1090 | pool.items.shrinkRetainingCapacity(0); | |
| 1091 | pool.extra.clearRetainingCapacity(); | |
| 1092 | ||
| 1093 | pool.string_map.clearRetainingCapacity(); | |
| 1094 | pool.string_indices.shrinkRetainingCapacity(1); | |
| 1095 | pool.string_bytes.clearRetainingCapacity(); | |
| 1096 | } | |
| 1097 | ||
| 1098 | pub fn freeUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator) void { | |
| 1099 | pool.map.shrinkAndFree(allocator, pool.map.count()); | |
| 1100 | pool.items.shrinkAndFree(allocator, pool.items.len); | |
| 1101 | pool.extra.shrinkAndFree(allocator, pool.extra.items.len); | |
| 1102 | ||
| 1103 | pool.string_map.shrinkAndFree(allocator, pool.string_map.count()); | |
| 1104 | pool.string_indices.shrinkAndFree(allocator, pool.string_indices.items.len); | |
| 1105 | pool.string_bytes.shrinkAndFree(allocator, pool.string_bytes.items.len); | |
| 1106 | } | |
| 1107 | ||
| 1108 | pub fn getPointer(pool: *Pool, allocator: std.mem.Allocator, pointer_info: Info.Pointer) !CType { | |
| 1109 | var hasher = Hasher.init; | |
| 1110 | hasher.update(pointer_info.elem_ctype.hash(pool)); | |
| 1111 | return pool.getNonString(allocator, try pool.tagData( | |
| 1112 | allocator, | |
| 1113 | hasher, | |
| 1114 | pointer_info.tag(), | |
| 1115 | @intFromEnum(pointer_info.elem_ctype.index), | |
| 1116 | ), pointer_info.nonstring); | |
| 1117 | } | |
| 1118 | ||
| 1119 | pub fn getAligned(pool: *Pool, allocator: std.mem.Allocator, aligned_info: Info.Aligned) !CType { | |
| 1120 | return pool.tagExtra(allocator, .aligned, Aligned, .{ | |
| 1121 | .ctype = aligned_info.ctype.index, | |
| 1122 | .flags = .{ .alignas = aligned_info.alignas }, | |
| 1123 | }); | |
| 1124 | } | |
| 1125 | ||
| 1126 | pub fn getArray(pool: *Pool, allocator: std.mem.Allocator, array_info: Info.Sequence) !CType { | |
| 1127 | return pool.getNonString(allocator, if (std.math.cast(u32, array_info.len)) |small_len| | |
| 1128 | try pool.tagExtra(allocator, .array_small, SequenceSmall, .{ | |
| 1129 | .elem_ctype = array_info.elem_ctype.index, | |
| 1130 | .len = small_len, | |
| 1131 | }) | |
| 1132 | else | |
| 1133 | try pool.tagExtra(allocator, .array_large, SequenceLarge, .{ | |
| 1134 | .elem_ctype = array_info.elem_ctype.index, | |
| 1135 | .len_lo = @truncate(array_info.len >> 0), | |
| 1136 | .len_hi = @truncate(array_info.len >> 32), | |
| 1137 | }), array_info.nonstring); | |
| 1138 | } | |
| 1139 | ||
| 1140 | pub fn getVector(pool: *Pool, allocator: std.mem.Allocator, vector_info: Info.Sequence) !CType { | |
| 1141 | return pool.getNonString(allocator, try pool.tagExtra(allocator, .vector, SequenceSmall, .{ | |
| 1142 | .elem_ctype = vector_info.elem_ctype.index, | |
| 1143 | .len = @intCast(vector_info.len), | |
| 1144 | }), vector_info.nonstring); | |
| 1145 | } | |
| 1146 | ||
| 1147 | pub fn getNonString( | |
| 1148 | pool: *Pool, | |
| 1149 | allocator: std.mem.Allocator, | |
| 1150 | child_ctype: CType, | |
| 1151 | nonstring: bool, | |
| 1152 | ) !CType { | |
| 1153 | if (!nonstring) return child_ctype; | |
| 1154 | var hasher = Hasher.init; | |
| 1155 | hasher.update(child_ctype.hash(pool)); | |
| 1156 | return pool.tagData(allocator, hasher, .nonstring, @intFromEnum(child_ctype.index)); | |
| 1157 | } | |
| 1158 | ||
| 1159 | pub fn getFwdDecl( | |
| 1160 | pool: *Pool, | |
| 1161 | allocator: std.mem.Allocator, | |
| 1162 | fwd_decl_info: struct { | |
| 1163 | tag: Info.AggregateTag, | |
| 1164 | name: union(enum) { | |
| 1165 | anon: []const Info.Field, | |
| 1166 | index: InternPool.Index, | |
| 1167 | }, | |
| 1168 | }, | |
| 1169 | ) !CType { | |
| 1170 | var hasher = Hasher.init; | |
| 1171 | switch (fwd_decl_info.name) { | |
| 1172 | .anon => |fields| { | |
| 1173 | const ExpectedContents = [32]CType; | |
| 1174 | var stack align(@max( | |
| 1175 | @alignOf(std.heap.StackFallbackAllocator(0)), | |
| 1176 | @alignOf(ExpectedContents), | |
| 1177 | )) = std.heap.stackFallback(@sizeOf(ExpectedContents), allocator); | |
| 1178 | const stack_allocator = stack.get(); | |
| 1179 | const field_ctypes = try stack_allocator.alloc(CType, fields.len); | |
| 1180 | defer stack_allocator.free(field_ctypes); | |
| 1181 | for (field_ctypes, fields) |*field_ctype, field| | |
| 1182 | field_ctype.* = try field.ctype.toForward(pool, allocator); | |
| 1183 | const extra: FwdDeclAnon = .{ .fields_len = @intCast(fields.len) }; | |
| 1184 | const extra_index = try pool.addExtra( | |
| 1185 | allocator, | |
| 1186 | FwdDeclAnon, | |
| 1187 | extra, | |
| 1188 | fields.len * @typeInfo(Field).@"struct".fields.len, | |
| 1189 | ); | |
| 1190 | for (fields, field_ctypes) |field, field_ctype| pool.addHashedExtraAssumeCapacity( | |
| 1191 | &hasher, | |
| 1192 | Field, | |
| 1193 | .{ | |
| 1194 | .name = field.name.index, | |
| 1195 | .ctype = field_ctype.index, | |
| 1196 | .flags = .{ .alignas = field.alignas }, | |
| 1197 | }, | |
| 1198 | ); | |
| 1199 | hasher.updateExtra(FwdDeclAnon, extra, pool); | |
| 1200 | return pool.tagTrailingExtra(allocator, hasher, switch (fwd_decl_info.tag) { | |
| 1201 | .@"struct" => .fwd_decl_struct_anon, | |
| 1202 | .@"union" => .fwd_decl_union_anon, | |
| 1203 | .@"enum" => unreachable, | |
| 1204 | }, extra_index); | |
| 1205 | }, | |
| 1206 | .index => |index| { | |
| 1207 | hasher.update(index); | |
| 1208 | return pool.tagData(allocator, hasher, switch (fwd_decl_info.tag) { | |
| 1209 | .@"struct" => .fwd_decl_struct, | |
| 1210 | .@"union" => .fwd_decl_union, | |
| 1211 | .@"enum" => unreachable, | |
| 1212 | }, @intFromEnum(index)); | |
| 1213 | }, | |
| 1214 | } | |
| 1215 | } | |
| 1216 | ||
| 1217 | pub fn getAggregate( | |
| 1218 | pool: *Pool, | |
| 1219 | allocator: std.mem.Allocator, | |
| 1220 | aggregate_info: struct { | |
| 1221 | tag: Info.AggregateTag, | |
| 1222 | @"packed": bool = false, | |
| 1223 | name: union(enum) { | |
| 1224 | anon: struct { | |
| 1225 | index: InternPool.Index, | |
| 1226 | id: u32, | |
| 1227 | }, | |
| 1228 | fwd_decl: CType, | |
| 1229 | }, | |
| 1230 | fields: []const Info.Field, | |
| 1231 | }, | |
| 1232 | ) !CType { | |
| 1233 | var hasher = Hasher.init; | |
| 1234 | switch (aggregate_info.name) { | |
| 1235 | .anon => |anon| { | |
| 1236 | const extra: AggregateAnon = .{ | |
| 1237 | .index = anon.index, | |
| 1238 | .id = anon.id, | |
| 1239 | .fields_len = @intCast(aggregate_info.fields.len), | |
| 1240 | }; | |
| 1241 | const extra_index = try pool.addExtra( | |
| 1242 | allocator, | |
| 1243 | AggregateAnon, | |
| 1244 | extra, | |
| 1245 | aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len, | |
| 1246 | ); | |
| 1247 | for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ | |
| 1248 | .name = field.name.index, | |
| 1249 | .ctype = field.ctype.index, | |
| 1250 | .flags = .{ .alignas = field.alignas }, | |
| 1251 | }); | |
| 1252 | hasher.updateExtra(AggregateAnon, extra, pool); | |
| 1253 | return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { | |
| 1254 | .@"struct" => switch (aggregate_info.@"packed") { | |
| 1255 | false => .aggregate_struct_anon, | |
| 1256 | true => .aggregate_struct_packed_anon, | |
| 1257 | }, | |
| 1258 | .@"union" => switch (aggregate_info.@"packed") { | |
| 1259 | false => .aggregate_union_anon, | |
| 1260 | true => .aggregate_union_packed_anon, | |
| 1261 | }, | |
| 1262 | .@"enum" => unreachable, | |
| 1263 | }, extra_index); | |
| 1264 | }, | |
| 1265 | .fwd_decl => |fwd_decl| { | |
| 1266 | const extra: Aggregate = .{ | |
| 1267 | .fwd_decl = fwd_decl.index, | |
| 1268 | .fields_len = @intCast(aggregate_info.fields.len), | |
| 1269 | }; | |
| 1270 | const extra_index = try pool.addExtra( | |
| 1271 | allocator, | |
| 1272 | Aggregate, | |
| 1273 | extra, | |
| 1274 | aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len, | |
| 1275 | ); | |
| 1276 | for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ | |
| 1277 | .name = field.name.index, | |
| 1278 | .ctype = field.ctype.index, | |
| 1279 | .flags = .{ .alignas = field.alignas }, | |
| 1280 | }); | |
| 1281 | hasher.updateExtra(Aggregate, extra, pool); | |
| 1282 | return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { | |
| 1283 | .@"struct" => switch (aggregate_info.@"packed") { | |
| 1284 | false => .aggregate_struct, | |
| 1285 | true => .aggregate_struct_packed, | |
| 1286 | }, | |
| 1287 | .@"union" => switch (aggregate_info.@"packed") { | |
| 1288 | false => .aggregate_union, | |
| 1289 | true => .aggregate_union_packed, | |
| 1290 | }, | |
| 1291 | .@"enum" => unreachable, | |
| 1292 | }, extra_index); | |
| 1293 | }, | |
| 1294 | } | |
| 1295 | } | |
| 1296 | ||
| 1297 | pub fn getFunction( | |
| 1298 | pool: *Pool, | |
| 1299 | allocator: std.mem.Allocator, | |
| 1300 | function_info: struct { | |
| 1301 | return_ctype: CType, | |
| 1302 | param_ctypes: []const CType, | |
| 1303 | varargs: bool = false, | |
| 1304 | }, | |
| 1305 | ) !CType { | |
| 1306 | var hasher = Hasher.init; | |
| 1307 | const extra: Function = .{ | |
| 1308 | .return_ctype = function_info.return_ctype.index, | |
| 1309 | .param_ctypes_len = @intCast(function_info.param_ctypes.len), | |
| 1310 | }; | |
| 1311 | const extra_index = try pool.addExtra(allocator, Function, extra, function_info.param_ctypes.len); | |
| 1312 | for (function_info.param_ctypes) |param_ctype| { | |
| 1313 | hasher.update(param_ctype.hash(pool)); | |
| 1314 | pool.extra.appendAssumeCapacity(@intFromEnum(param_ctype.index)); | |
| 1315 | } | |
| 1316 | hasher.updateExtra(Function, extra, pool); | |
| 1317 | return pool.tagTrailingExtra(allocator, hasher, switch (function_info.varargs) { | |
| 1318 | false => .function, | |
| 1319 | true => .function_varargs, | |
| 1320 | }, extra_index); | |
| 1321 | } | |
| 1322 | ||
| 1323 | pub fn fromFields( | |
| 1324 | pool: *Pool, | |
| 1325 | allocator: std.mem.Allocator, | |
| 1326 | tag: Info.AggregateTag, | |
| 1327 | fields: []Info.Field, | |
| 1328 | kind: Kind, | |
| 1329 | ) !CType { | |
| 1330 | sortFields(fields); | |
| 1331 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | |
| 1332 | .tag = tag, | |
| 1333 | .name = .{ .anon = fields }, | |
| 1334 | }); | |
| 1335 | return if (kind.isForward()) fwd_decl else pool.getAggregate(allocator, .{ | |
| 1336 | .tag = tag, | |
| 1337 | .name = .{ .fwd_decl = fwd_decl }, | |
| 1338 | .fields = fields, | |
| 1339 | }); | |
| 1340 | } | |
| 1341 | ||
| 1342 | pub fn fromIntInfo( | |
| 1343 | pool: *Pool, | |
| 1344 | allocator: std.mem.Allocator, | |
| 1345 | int_info: std.builtin.Type.Int, | |
| 1346 | mod: *Module, | |
| 1347 | kind: Kind, | |
| 1348 | ) !CType { | |
| 1349 | switch (int_info.bits) { | |
| 1350 | 0 => return .void, | |
| 1351 | 1...8 => switch (int_info.signedness) { | |
| 1352 | .signed => return .i8, | |
| 1353 | .unsigned => return .u8, | |
| 1354 | }, | |
| 1355 | 9...16 => switch (int_info.signedness) { | |
| 1356 | .signed => return .i16, | |
| 1357 | .unsigned => return .u16, | |
| 1358 | }, | |
| 1359 | 17...32 => switch (int_info.signedness) { | |
| 1360 | .signed => return .i32, | |
| 1361 | .unsigned => return .u32, | |
| 1362 | }, | |
| 1363 | 33...64 => switch (int_info.signedness) { | |
| 1364 | .signed => return .i64, | |
| 1365 | .unsigned => return .u64, | |
| 1366 | }, | |
| 1367 | 65...128 => switch (int_info.signedness) { | |
| 1368 | .signed => return .i128, | |
| 1369 | .unsigned => return .u128, | |
| 1370 | }, | |
| 1371 | else => { | |
| 1372 | const target = &mod.resolved_target.result; | |
| 1373 | const abi_align_bytes = std.zig.target.intAlignment(target, int_info.bits); | |
| 1374 | const limb_ctype = try pool.fromIntInfo(allocator, .{ | |
| 1375 | .signedness = .unsigned, | |
| 1376 | .bits = @intCast(abi_align_bytes * 8), | |
| 1377 | }, mod, kind.noParameter()); | |
| 1378 | const array_ctype = try pool.getArray(allocator, .{ | |
| 1379 | .len = @divExact(std.zig.target.intByteSize(target, int_info.bits), abi_align_bytes), | |
| 1380 | .elem_ctype = limb_ctype, | |
| 1381 | .nonstring = limb_ctype.isAnyChar(), | |
| 1382 | }); | |
| 1383 | if (!kind.isParameter()) return array_ctype; | |
| 1384 | var fields = [_]Info.Field{ | |
| 1385 | .{ | |
| 1386 | .name = .{ .index = .array }, | |
| 1387 | .ctype = array_ctype, | |
| 1388 | .alignas = AlignAs.fromAbiAlignment(.fromByteUnits(abi_align_bytes)), | |
| 1389 | }, | |
| 1390 | }; | |
| 1391 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1392 | }, | |
| 1393 | } | |
| 1394 | } | |
| 1395 | ||
| 1396 | pub fn fromType( | |
| 1397 | pool: *Pool, | |
| 1398 | allocator: std.mem.Allocator, | |
| 1399 | scratch: *std.ArrayList(u32), | |
| 1400 | ty: Type, | |
| 1401 | pt: Zcu.PerThread, | |
| 1402 | mod: *Module, | |
| 1403 | kind: Kind, | |
| 1404 | ) !CType { | |
| 1405 | const ip = &pt.zcu.intern_pool; | |
| 1406 | const zcu = pt.zcu; | |
| 1407 | switch (ty.toIntern()) { | |
| 1408 | .u0_type, | |
| 1409 | .i0_type, | |
| 1410 | .anyopaque_type, | |
| 1411 | .void_type, | |
| 1412 | .empty_tuple_type, | |
| 1413 | .type_type, | |
| 1414 | .comptime_int_type, | |
| 1415 | .comptime_float_type, | |
| 1416 | .null_type, | |
| 1417 | .undefined_type, | |
| 1418 | .enum_literal_type, | |
| 1419 | .optional_type_type, | |
| 1420 | .manyptr_const_type_type, | |
| 1421 | .slice_const_type_type, | |
| 1422 | => return .void, | |
| 1423 | .u1_type, .u8_type => return .u8, | |
| 1424 | .i8_type => return .i8, | |
| 1425 | .u16_type => return .u16, | |
| 1426 | .i16_type => return .i16, | |
| 1427 | .u29_type, .u32_type => return .u32, | |
| 1428 | .i32_type => return .i32, | |
| 1429 | .u64_type => return .u64, | |
| 1430 | .i64_type => return .i64, | |
| 1431 | .u80_type, .u128_type => return .u128, | |
| 1432 | .i128_type => return .i128, | |
| 1433 | .u256_type => return pool.fromIntInfo(allocator, .{ | |
| 1434 | .signedness = .unsigned, | |
| 1435 | .bits = 256, | |
| 1436 | }, mod, kind), | |
| 1437 | .usize_type => return .usize, | |
| 1438 | .isize_type => return .isize, | |
| 1439 | .c_char_type => return .{ .index = .char }, | |
| 1440 | .c_short_type => return .{ .index = .short }, | |
| 1441 | .c_ushort_type => return .{ .index = .@"unsigned short" }, | |
| 1442 | .c_int_type => return .{ .index = .int }, | |
| 1443 | .c_uint_type => return .{ .index = .@"unsigned int" }, | |
| 1444 | .c_long_type => return .{ .index = .long }, | |
| 1445 | .c_ulong_type => return .{ .index = .@"unsigned long" }, | |
| 1446 | .c_longlong_type => return .{ .index = .@"long long" }, | |
| 1447 | .c_ulonglong_type => return .{ .index = .@"unsigned long long" }, | |
| 1448 | .c_longdouble_type => return .{ .index = .@"long double" }, | |
| 1449 | .f16_type => return .f16, | |
| 1450 | .f32_type => return .f32, | |
| 1451 | .f64_type => return .f64, | |
| 1452 | .f80_type => return .f80, | |
| 1453 | .f128_type => return .f128, | |
| 1454 | .bool_type, .optional_noreturn_type => return .bool, | |
| 1455 | .noreturn_type, | |
| 1456 | .anyframe_type, | |
| 1457 | .generic_poison_type, | |
| 1458 | => unreachable, | |
| 1459 | .anyerror_type, | |
| 1460 | .anyerror_void_error_union_type, | |
| 1461 | .adhoc_inferred_error_set_type, | |
| 1462 | => return pool.fromIntInfo(allocator, .{ | |
| 1463 | .signedness = .unsigned, | |
| 1464 | .bits = pt.zcu.errorSetBits(), | |
| 1465 | }, mod, kind), | |
| 1466 | ||
| 1467 | .ptr_usize_type => return pool.getPointer(allocator, .{ | |
| 1468 | .elem_ctype = .usize, | |
| 1469 | }), | |
| 1470 | .ptr_const_comptime_int_type => return pool.getPointer(allocator, .{ | |
| 1471 | .elem_ctype = .void, | |
| 1472 | .@"const" = true, | |
| 1473 | }), | |
| 1474 | .manyptr_u8_type => return pool.getPointer(allocator, .{ | |
| 1475 | .elem_ctype = .u8, | |
| 1476 | .nonstring = true, | |
| 1477 | }), | |
| 1478 | .manyptr_const_u8_type => return pool.getPointer(allocator, .{ | |
| 1479 | .elem_ctype = .u8, | |
| 1480 | .@"const" = true, | |
| 1481 | .nonstring = true, | |
| 1482 | }), | |
| 1483 | .manyptr_const_u8_sentinel_0_type => return pool.getPointer(allocator, .{ | |
| 1484 | .elem_ctype = .u8, | |
| 1485 | .@"const" = true, | |
| 1486 | }), | |
| 1487 | .slice_const_u8_type => { | |
| 1488 | const target = &mod.resolved_target.result; | |
| 1489 | var fields = [_]Info.Field{ | |
| 1490 | .{ | |
| 1491 | .name = .{ .index = .ptr }, | |
| 1492 | .ctype = try pool.getPointer(allocator, .{ | |
| 1493 | .elem_ctype = .u8, | |
| 1494 | .@"const" = true, | |
| 1495 | .nonstring = true, | |
| 1496 | }), | |
| 1497 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), | |
| 1498 | }, | |
| 1499 | .{ | |
| 1500 | .name = .{ .index = .len }, | |
| 1501 | .ctype = .usize, | |
| 1502 | .alignas = AlignAs.fromAbiAlignment( | |
| 1503 | .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 1504 | ), | |
| 1505 | }, | |
| 1506 | }; | |
| 1507 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1508 | }, | |
| 1509 | .slice_const_u8_sentinel_0_type => { | |
| 1510 | const target = &mod.resolved_target.result; | |
| 1511 | var fields = [_]Info.Field{ | |
| 1512 | .{ | |
| 1513 | .name = .{ .index = .ptr }, | |
| 1514 | .ctype = try pool.getPointer(allocator, .{ | |
| 1515 | .elem_ctype = .u8, | |
| 1516 | .@"const" = true, | |
| 1517 | }), | |
| 1518 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), | |
| 1519 | }, | |
| 1520 | .{ | |
| 1521 | .name = .{ .index = .len }, | |
| 1522 | .ctype = .usize, | |
| 1523 | .alignas = AlignAs.fromAbiAlignment( | |
| 1524 | .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 1525 | ), | |
| 1526 | }, | |
| 1527 | }; | |
| 1528 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1529 | }, | |
| 1530 | ||
| 1531 | .manyptr_const_slice_const_u8_type => { | |
| 1532 | const target = &mod.resolved_target.result; | |
| 1533 | var fields: [2]Info.Field = .{ | |
| 1534 | .{ | |
| 1535 | .name = .{ .index = .ptr }, | |
| 1536 | .ctype = try pool.getPointer(allocator, .{ | |
| 1537 | .elem_ctype = .u8, | |
| 1538 | .@"const" = true, | |
| 1539 | .nonstring = true, | |
| 1540 | }), | |
| 1541 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), | |
| 1542 | }, | |
| 1543 | .{ | |
| 1544 | .name = .{ .index = .len }, | |
| 1545 | .ctype = .usize, | |
| 1546 | .alignas = AlignAs.fromAbiAlignment( | |
| 1547 | .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 1548 | ), | |
| 1549 | }, | |
| 1550 | }; | |
| 1551 | const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1552 | return pool.getPointer(allocator, .{ | |
| 1553 | .elem_ctype = slice_const_u8, | |
| 1554 | .@"const" = true, | |
| 1555 | }); | |
| 1556 | }, | |
| 1557 | .slice_const_slice_const_u8_type => { | |
| 1558 | const target = &mod.resolved_target.result; | |
| 1559 | var fields: [2]Info.Field = .{ | |
| 1560 | .{ | |
| 1561 | .name = .{ .index = .ptr }, | |
| 1562 | .ctype = try pool.getPointer(allocator, .{ | |
| 1563 | .elem_ctype = .u8, | |
| 1564 | .@"const" = true, | |
| 1565 | .nonstring = true, | |
| 1566 | }), | |
| 1567 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), | |
| 1568 | }, | |
| 1569 | .{ | |
| 1570 | .name = .{ .index = .len }, | |
| 1571 | .ctype = .usize, | |
| 1572 | .alignas = AlignAs.fromAbiAlignment( | |
| 1573 | .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 1574 | ), | |
| 1575 | }, | |
| 1576 | }; | |
| 1577 | const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, .forward); | |
| 1578 | fields = .{ | |
| 1579 | .{ | |
| 1580 | .name = .{ .index = .ptr }, | |
| 1581 | .ctype = try pool.getPointer(allocator, .{ | |
| 1582 | .elem_ctype = slice_const_u8, | |
| 1583 | .@"const" = true, | |
| 1584 | }), | |
| 1585 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), | |
| 1586 | }, | |
| 1587 | .{ | |
| 1588 | .name = .{ .index = .len }, | |
| 1589 | .ctype = .usize, | |
| 1590 | .alignas = AlignAs.fromAbiAlignment( | |
| 1591 | .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 1592 | ), | |
| 1593 | }, | |
| 1594 | }; | |
| 1595 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1596 | }, | |
| 1597 | ||
| 1598 | .vector_8_i8_type => { | |
| 1599 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1600 | .elem_ctype = .i8, | |
| 1601 | .len = 8, | |
| 1602 | .nonstring = true, | |
| 1603 | }); | |
| 1604 | if (!kind.isParameter()) return vector_ctype; | |
| 1605 | var fields = [_]Info.Field{ | |
| 1606 | .{ | |
| 1607 | .name = .{ .index = .array }, | |
| 1608 | .ctype = vector_ctype, | |
| 1609 | .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), | |
| 1610 | }, | |
| 1611 | }; | |
| 1612 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1613 | }, | |
| 1614 | .vector_16_i8_type => { | |
| 1615 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1616 | .elem_ctype = .i8, | |
| 1617 | .len = 16, | |
| 1618 | .nonstring = true, | |
| 1619 | }); | |
| 1620 | if (!kind.isParameter()) return vector_ctype; | |
| 1621 | var fields = [_]Info.Field{ | |
| 1622 | .{ | |
| 1623 | .name = .{ .index = .array }, | |
| 1624 | .ctype = vector_ctype, | |
| 1625 | .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), | |
| 1626 | }, | |
| 1627 | }; | |
| 1628 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1629 | }, | |
| 1630 | .vector_32_i8_type => { | |
| 1631 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1632 | .elem_ctype = .i8, | |
| 1633 | .len = 32, | |
| 1634 | .nonstring = true, | |
| 1635 | }); | |
| 1636 | if (!kind.isParameter()) return vector_ctype; | |
| 1637 | var fields = [_]Info.Field{ | |
| 1638 | .{ | |
| 1639 | .name = .{ .index = .array }, | |
| 1640 | .ctype = vector_ctype, | |
| 1641 | .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), | |
| 1642 | }, | |
| 1643 | }; | |
| 1644 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1645 | }, | |
| 1646 | .vector_64_i8_type => { | |
| 1647 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1648 | .elem_ctype = .i8, | |
| 1649 | .len = 64, | |
| 1650 | .nonstring = true, | |
| 1651 | }); | |
| 1652 | if (!kind.isParameter()) return vector_ctype; | |
| 1653 | var fields = [_]Info.Field{ | |
| 1654 | .{ | |
| 1655 | .name = .{ .index = .array }, | |
| 1656 | .ctype = vector_ctype, | |
| 1657 | .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), | |
| 1658 | }, | |
| 1659 | }; | |
| 1660 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1661 | }, | |
| 1662 | .vector_1_u8_type => { | |
| 1663 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1664 | .elem_ctype = .u8, | |
| 1665 | .len = 1, | |
| 1666 | .nonstring = true, | |
| 1667 | }); | |
| 1668 | if (!kind.isParameter()) return vector_ctype; | |
| 1669 | var fields = [_]Info.Field{ | |
| 1670 | .{ | |
| 1671 | .name = .{ .index = .array }, | |
| 1672 | .ctype = vector_ctype, | |
| 1673 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1674 | }, | |
| 1675 | }; | |
| 1676 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1677 | }, | |
| 1678 | .vector_2_u8_type => { | |
| 1679 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1680 | .elem_ctype = .u8, | |
| 1681 | .len = 2, | |
| 1682 | .nonstring = true, | |
| 1683 | }); | |
| 1684 | if (!kind.isParameter()) return vector_ctype; | |
| 1685 | var fields = [_]Info.Field{ | |
| 1686 | .{ | |
| 1687 | .name = .{ .index = .array }, | |
| 1688 | .ctype = vector_ctype, | |
| 1689 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1690 | }, | |
| 1691 | }; | |
| 1692 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1693 | }, | |
| 1694 | .vector_4_u8_type => { | |
| 1695 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1696 | .elem_ctype = .u8, | |
| 1697 | .len = 4, | |
| 1698 | .nonstring = true, | |
| 1699 | }); | |
| 1700 | if (!kind.isParameter()) return vector_ctype; | |
| 1701 | var fields = [_]Info.Field{ | |
| 1702 | .{ | |
| 1703 | .name = .{ .index = .array }, | |
| 1704 | .ctype = vector_ctype, | |
| 1705 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1706 | }, | |
| 1707 | }; | |
| 1708 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1709 | }, | |
| 1710 | .vector_8_u8_type => { | |
| 1711 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1712 | .elem_ctype = .u8, | |
| 1713 | .len = 8, | |
| 1714 | .nonstring = true, | |
| 1715 | }); | |
| 1716 | if (!kind.isParameter()) return vector_ctype; | |
| 1717 | var fields = [_]Info.Field{ | |
| 1718 | .{ | |
| 1719 | .name = .{ .index = .array }, | |
| 1720 | .ctype = vector_ctype, | |
| 1721 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1722 | }, | |
| 1723 | }; | |
| 1724 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1725 | }, | |
| 1726 | .vector_16_u8_type => { | |
| 1727 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1728 | .elem_ctype = .u8, | |
| 1729 | .len = 16, | |
| 1730 | .nonstring = true, | |
| 1731 | }); | |
| 1732 | if (!kind.isParameter()) return vector_ctype; | |
| 1733 | var fields = [_]Info.Field{ | |
| 1734 | .{ | |
| 1735 | .name = .{ .index = .array }, | |
| 1736 | .ctype = vector_ctype, | |
| 1737 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1738 | }, | |
| 1739 | }; | |
| 1740 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1741 | }, | |
| 1742 | .vector_32_u8_type => { | |
| 1743 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1744 | .elem_ctype = .u8, | |
| 1745 | .len = 32, | |
| 1746 | .nonstring = true, | |
| 1747 | }); | |
| 1748 | if (!kind.isParameter()) return vector_ctype; | |
| 1749 | var fields = [_]Info.Field{ | |
| 1750 | .{ | |
| 1751 | .name = .{ .index = .array }, | |
| 1752 | .ctype = vector_ctype, | |
| 1753 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1754 | }, | |
| 1755 | }; | |
| 1756 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1757 | }, | |
| 1758 | .vector_64_u8_type => { | |
| 1759 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1760 | .elem_ctype = .u8, | |
| 1761 | .len = 64, | |
| 1762 | .nonstring = true, | |
| 1763 | }); | |
| 1764 | if (!kind.isParameter()) return vector_ctype; | |
| 1765 | var fields = [_]Info.Field{ | |
| 1766 | .{ | |
| 1767 | .name = .{ .index = .array }, | |
| 1768 | .ctype = vector_ctype, | |
| 1769 | .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), | |
| 1770 | }, | |
| 1771 | }; | |
| 1772 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1773 | }, | |
| 1774 | .vector_2_i16_type => { | |
| 1775 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1776 | .elem_ctype = .i16, | |
| 1777 | .len = 2, | |
| 1778 | }); | |
| 1779 | if (!kind.isParameter()) return vector_ctype; | |
| 1780 | var fields = [_]Info.Field{ | |
| 1781 | .{ | |
| 1782 | .name = .{ .index = .array }, | |
| 1783 | .ctype = vector_ctype, | |
| 1784 | .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), | |
| 1785 | }, | |
| 1786 | }; | |
| 1787 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1788 | }, | |
| 1789 | .vector_4_i16_type => { | |
| 1790 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1791 | .elem_ctype = .i16, | |
| 1792 | .len = 4, | |
| 1793 | }); | |
| 1794 | if (!kind.isParameter()) return vector_ctype; | |
| 1795 | var fields = [_]Info.Field{ | |
| 1796 | .{ | |
| 1797 | .name = .{ .index = .array }, | |
| 1798 | .ctype = vector_ctype, | |
| 1799 | .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), | |
| 1800 | }, | |
| 1801 | }; | |
| 1802 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1803 | }, | |
| 1804 | .vector_8_i16_type => { | |
| 1805 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1806 | .elem_ctype = .i16, | |
| 1807 | .len = 8, | |
| 1808 | }); | |
| 1809 | if (!kind.isParameter()) return vector_ctype; | |
| 1810 | var fields = [_]Info.Field{ | |
| 1811 | .{ | |
| 1812 | .name = .{ .index = .array }, | |
| 1813 | .ctype = vector_ctype, | |
| 1814 | .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), | |
| 1815 | }, | |
| 1816 | }; | |
| 1817 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1818 | }, | |
| 1819 | .vector_16_i16_type => { | |
| 1820 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1821 | .elem_ctype = .i16, | |
| 1822 | .len = 16, | |
| 1823 | }); | |
| 1824 | if (!kind.isParameter()) return vector_ctype; | |
| 1825 | var fields = [_]Info.Field{ | |
| 1826 | .{ | |
| 1827 | .name = .{ .index = .array }, | |
| 1828 | .ctype = vector_ctype, | |
| 1829 | .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), | |
| 1830 | }, | |
| 1831 | }; | |
| 1832 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1833 | }, | |
| 1834 | .vector_32_i16_type => { | |
| 1835 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1836 | .elem_ctype = .i16, | |
| 1837 | .len = 32, | |
| 1838 | }); | |
| 1839 | if (!kind.isParameter()) return vector_ctype; | |
| 1840 | var fields = [_]Info.Field{ | |
| 1841 | .{ | |
| 1842 | .name = .{ .index = .array }, | |
| 1843 | .ctype = vector_ctype, | |
| 1844 | .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), | |
| 1845 | }, | |
| 1846 | }; | |
| 1847 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1848 | }, | |
| 1849 | .vector_4_u16_type => { | |
| 1850 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1851 | .elem_ctype = .u16, | |
| 1852 | .len = 4, | |
| 1853 | }); | |
| 1854 | if (!kind.isParameter()) return vector_ctype; | |
| 1855 | var fields = [_]Info.Field{ | |
| 1856 | .{ | |
| 1857 | .name = .{ .index = .array }, | |
| 1858 | .ctype = vector_ctype, | |
| 1859 | .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), | |
| 1860 | }, | |
| 1861 | }; | |
| 1862 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1863 | }, | |
| 1864 | .vector_8_u16_type => { | |
| 1865 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1866 | .elem_ctype = .u16, | |
| 1867 | .len = 8, | |
| 1868 | }); | |
| 1869 | if (!kind.isParameter()) return vector_ctype; | |
| 1870 | var fields = [_]Info.Field{ | |
| 1871 | .{ | |
| 1872 | .name = .{ .index = .array }, | |
| 1873 | .ctype = vector_ctype, | |
| 1874 | .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), | |
| 1875 | }, | |
| 1876 | }; | |
| 1877 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1878 | }, | |
| 1879 | .vector_16_u16_type => { | |
| 1880 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1881 | .elem_ctype = .u16, | |
| 1882 | .len = 16, | |
| 1883 | }); | |
| 1884 | if (!kind.isParameter()) return vector_ctype; | |
| 1885 | var fields = [_]Info.Field{ | |
| 1886 | .{ | |
| 1887 | .name = .{ .index = .array }, | |
| 1888 | .ctype = vector_ctype, | |
| 1889 | .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), | |
| 1890 | }, | |
| 1891 | }; | |
| 1892 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1893 | }, | |
| 1894 | .vector_32_u16_type => { | |
| 1895 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1896 | .elem_ctype = .u16, | |
| 1897 | .len = 32, | |
| 1898 | }); | |
| 1899 | if (!kind.isParameter()) return vector_ctype; | |
| 1900 | var fields = [_]Info.Field{ | |
| 1901 | .{ | |
| 1902 | .name = .{ .index = .array }, | |
| 1903 | .ctype = vector_ctype, | |
| 1904 | .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), | |
| 1905 | }, | |
| 1906 | }; | |
| 1907 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1908 | }, | |
| 1909 | .vector_2_i32_type => { | |
| 1910 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1911 | .elem_ctype = .i32, | |
| 1912 | .len = 2, | |
| 1913 | }); | |
| 1914 | if (!kind.isParameter()) return vector_ctype; | |
| 1915 | var fields = [_]Info.Field{ | |
| 1916 | .{ | |
| 1917 | .name = .{ .index = .array }, | |
| 1918 | .ctype = vector_ctype, | |
| 1919 | .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), | |
| 1920 | }, | |
| 1921 | }; | |
| 1922 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1923 | }, | |
| 1924 | .vector_4_i32_type => { | |
| 1925 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1926 | .elem_ctype = .i32, | |
| 1927 | .len = 4, | |
| 1928 | }); | |
| 1929 | if (!kind.isParameter()) return vector_ctype; | |
| 1930 | var fields = [_]Info.Field{ | |
| 1931 | .{ | |
| 1932 | .name = .{ .index = .array }, | |
| 1933 | .ctype = vector_ctype, | |
| 1934 | .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), | |
| 1935 | }, | |
| 1936 | }; | |
| 1937 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1938 | }, | |
| 1939 | .vector_8_i32_type => { | |
| 1940 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1941 | .elem_ctype = .i32, | |
| 1942 | .len = 8, | |
| 1943 | }); | |
| 1944 | if (!kind.isParameter()) return vector_ctype; | |
| 1945 | var fields = [_]Info.Field{ | |
| 1946 | .{ | |
| 1947 | .name = .{ .index = .array }, | |
| 1948 | .ctype = vector_ctype, | |
| 1949 | .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), | |
| 1950 | }, | |
| 1951 | }; | |
| 1952 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1953 | }, | |
| 1954 | .vector_16_i32_type => { | |
| 1955 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1956 | .elem_ctype = .i32, | |
| 1957 | .len = 16, | |
| 1958 | }); | |
| 1959 | if (!kind.isParameter()) return vector_ctype; | |
| 1960 | var fields = [_]Info.Field{ | |
| 1961 | .{ | |
| 1962 | .name = .{ .index = .array }, | |
| 1963 | .ctype = vector_ctype, | |
| 1964 | .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), | |
| 1965 | }, | |
| 1966 | }; | |
| 1967 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1968 | }, | |
| 1969 | .vector_4_u32_type => { | |
| 1970 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1971 | .elem_ctype = .u32, | |
| 1972 | .len = 4, | |
| 1973 | }); | |
| 1974 | if (!kind.isParameter()) return vector_ctype; | |
| 1975 | var fields = [_]Info.Field{ | |
| 1976 | .{ | |
| 1977 | .name = .{ .index = .array }, | |
| 1978 | .ctype = vector_ctype, | |
| 1979 | .alignas = AlignAs.fromAbiAlignment(Type.u32.abiAlignment(zcu)), | |
| 1980 | }, | |
| 1981 | }; | |
| 1982 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1983 | }, | |
| 1984 | .vector_8_u32_type => { | |
| 1985 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 1986 | .elem_ctype = .u32, | |
| 1987 | .len = 8, | |
| 1988 | }); | |
| 1989 | if (!kind.isParameter()) return vector_ctype; | |
| 1990 | var fields = [_]Info.Field{ | |
| 1991 | .{ | |
| 1992 | .name = .{ .index = .array }, | |
| 1993 | .ctype = vector_ctype, | |
| 1994 | .alignas = AlignAs.fromAbiAlignment(Type.u32.abiAlignment(zcu)), | |
| 1995 | }, | |
| 1996 | }; | |
| 1997 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 1998 | }, | |
| 1999 | .vector_16_u32_type => { | |
| 2000 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2001 | .elem_ctype = .u32, | |
| 2002 | .len = 16, | |
| 2003 | }); | |
| 2004 | if (!kind.isParameter()) return vector_ctype; | |
| 2005 | var fields = [_]Info.Field{ | |
| 2006 | .{ | |
| 2007 | .name = .{ .index = .array }, | |
| 2008 | .ctype = vector_ctype, | |
| 2009 | .alignas = AlignAs.fromAbiAlignment(Type.u32.abiAlignment(zcu)), | |
| 2010 | }, | |
| 2011 | }; | |
| 2012 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2013 | }, | |
| 2014 | .vector_2_i64_type => { | |
| 2015 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2016 | .elem_ctype = .i64, | |
| 2017 | .len = 2, | |
| 2018 | }); | |
| 2019 | if (!kind.isParameter()) return vector_ctype; | |
| 2020 | var fields = [_]Info.Field{ | |
| 2021 | .{ | |
| 2022 | .name = .{ .index = .array }, | |
| 2023 | .ctype = vector_ctype, | |
| 2024 | .alignas = AlignAs.fromAbiAlignment(Type.i64.abiAlignment(zcu)), | |
| 2025 | }, | |
| 2026 | }; | |
| 2027 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2028 | }, | |
| 2029 | .vector_4_i64_type => { | |
| 2030 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2031 | .elem_ctype = .i64, | |
| 2032 | .len = 4, | |
| 2033 | }); | |
| 2034 | if (!kind.isParameter()) return vector_ctype; | |
| 2035 | var fields = [_]Info.Field{ | |
| 2036 | .{ | |
| 2037 | .name = .{ .index = .array }, | |
| 2038 | .ctype = vector_ctype, | |
| 2039 | .alignas = AlignAs.fromAbiAlignment(Type.i64.abiAlignment(zcu)), | |
| 2040 | }, | |
| 2041 | }; | |
| 2042 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2043 | }, | |
| 2044 | .vector_8_i64_type => { | |
| 2045 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2046 | .elem_ctype = .i64, | |
| 2047 | .len = 8, | |
| 2048 | }); | |
| 2049 | if (!kind.isParameter()) return vector_ctype; | |
| 2050 | var fields = [_]Info.Field{ | |
| 2051 | .{ | |
| 2052 | .name = .{ .index = .array }, | |
| 2053 | .ctype = vector_ctype, | |
| 2054 | .alignas = AlignAs.fromAbiAlignment(Type.i64.abiAlignment(zcu)), | |
| 2055 | }, | |
| 2056 | }; | |
| 2057 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2058 | }, | |
| 2059 | .vector_2_u64_type => { | |
| 2060 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2061 | .elem_ctype = .u64, | |
| 2062 | .len = 2, | |
| 2063 | }); | |
| 2064 | if (!kind.isParameter()) return vector_ctype; | |
| 2065 | var fields = [_]Info.Field{ | |
| 2066 | .{ | |
| 2067 | .name = .{ .index = .array }, | |
| 2068 | .ctype = vector_ctype, | |
| 2069 | .alignas = AlignAs.fromAbiAlignment(Type.u64.abiAlignment(zcu)), | |
| 2070 | }, | |
| 2071 | }; | |
| 2072 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2073 | }, | |
| 2074 | .vector_4_u64_type => { | |
| 2075 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2076 | .elem_ctype = .u64, | |
| 2077 | .len = 4, | |
| 2078 | }); | |
| 2079 | if (!kind.isParameter()) return vector_ctype; | |
| 2080 | var fields = [_]Info.Field{ | |
| 2081 | .{ | |
| 2082 | .name = .{ .index = .array }, | |
| 2083 | .ctype = vector_ctype, | |
| 2084 | .alignas = AlignAs.fromAbiAlignment(Type.u64.abiAlignment(zcu)), | |
| 2085 | }, | |
| 2086 | }; | |
| 2087 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2088 | }, | |
| 2089 | .vector_8_u64_type => { | |
| 2090 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2091 | .elem_ctype = .u64, | |
| 2092 | .len = 8, | |
| 2093 | }); | |
| 2094 | if (!kind.isParameter()) return vector_ctype; | |
| 2095 | var fields = [_]Info.Field{ | |
| 2096 | .{ | |
| 2097 | .name = .{ .index = .array }, | |
| 2098 | .ctype = vector_ctype, | |
| 2099 | .alignas = AlignAs.fromAbiAlignment(Type.u64.abiAlignment(zcu)), | |
| 2100 | }, | |
| 2101 | }; | |
| 2102 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2103 | }, | |
| 2104 | .vector_1_u128_type => { | |
| 2105 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2106 | .elem_ctype = .u128, | |
| 2107 | .len = 1, | |
| 2108 | }); | |
| 2109 | if (!kind.isParameter()) return vector_ctype; | |
| 2110 | var fields = [_]Info.Field{ | |
| 2111 | .{ | |
| 2112 | .name = .{ .index = .array }, | |
| 2113 | .ctype = vector_ctype, | |
| 2114 | .alignas = AlignAs.fromAbiAlignment(Type.u128.abiAlignment(zcu)), | |
| 2115 | }, | |
| 2116 | }; | |
| 2117 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2118 | }, | |
| 2119 | .vector_2_u128_type => { | |
| 2120 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2121 | .elem_ctype = .u128, | |
| 2122 | .len = 2, | |
| 2123 | }); | |
| 2124 | if (!kind.isParameter()) return vector_ctype; | |
| 2125 | var fields = [_]Info.Field{ | |
| 2126 | .{ | |
| 2127 | .name = .{ .index = .array }, | |
| 2128 | .ctype = vector_ctype, | |
| 2129 | .alignas = AlignAs.fromAbiAlignment(Type.u128.abiAlignment(zcu)), | |
| 2130 | }, | |
| 2131 | }; | |
| 2132 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2133 | }, | |
| 2134 | .vector_1_u256_type => { | |
| 2135 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2136 | .elem_ctype = try pool.fromIntInfo(allocator, .{ | |
| 2137 | .signedness = .unsigned, | |
| 2138 | .bits = 256, | |
| 2139 | }, mod, kind), | |
| 2140 | .len = 1, | |
| 2141 | }); | |
| 2142 | if (!kind.isParameter()) return vector_ctype; | |
| 2143 | var fields = [_]Info.Field{ | |
| 2144 | .{ | |
| 2145 | .name = .{ .index = .array }, | |
| 2146 | .ctype = vector_ctype, | |
| 2147 | .alignas = AlignAs.fromAbiAlignment(Type.u256.abiAlignment(zcu)), | |
| 2148 | }, | |
| 2149 | }; | |
| 2150 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2151 | }, | |
| 2152 | .vector_4_f16_type => { | |
| 2153 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2154 | .elem_ctype = .f16, | |
| 2155 | .len = 4, | |
| 2156 | }); | |
| 2157 | if (!kind.isParameter()) return vector_ctype; | |
| 2158 | var fields = [_]Info.Field{ | |
| 2159 | .{ | |
| 2160 | .name = .{ .index = .array }, | |
| 2161 | .ctype = vector_ctype, | |
| 2162 | .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), | |
| 2163 | }, | |
| 2164 | }; | |
| 2165 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2166 | }, | |
| 2167 | .vector_8_f16_type => { | |
| 2168 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2169 | .elem_ctype = .f16, | |
| 2170 | .len = 8, | |
| 2171 | }); | |
| 2172 | if (!kind.isParameter()) return vector_ctype; | |
| 2173 | var fields = [_]Info.Field{ | |
| 2174 | .{ | |
| 2175 | .name = .{ .index = .array }, | |
| 2176 | .ctype = vector_ctype, | |
| 2177 | .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), | |
| 2178 | }, | |
| 2179 | }; | |
| 2180 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2181 | }, | |
| 2182 | .vector_16_f16_type => { | |
| 2183 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2184 | .elem_ctype = .f16, | |
| 2185 | .len = 16, | |
| 2186 | }); | |
| 2187 | if (!kind.isParameter()) return vector_ctype; | |
| 2188 | var fields = [_]Info.Field{ | |
| 2189 | .{ | |
| 2190 | .name = .{ .index = .array }, | |
| 2191 | .ctype = vector_ctype, | |
| 2192 | .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), | |
| 2193 | }, | |
| 2194 | }; | |
| 2195 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2196 | }, | |
| 2197 | .vector_32_f16_type => { | |
| 2198 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2199 | .elem_ctype = .f16, | |
| 2200 | .len = 32, | |
| 2201 | }); | |
| 2202 | if (!kind.isParameter()) return vector_ctype; | |
| 2203 | var fields = [_]Info.Field{ | |
| 2204 | .{ | |
| 2205 | .name = .{ .index = .array }, | |
| 2206 | .ctype = vector_ctype, | |
| 2207 | .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), | |
| 2208 | }, | |
| 2209 | }; | |
| 2210 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2211 | }, | |
| 2212 | .vector_2_f32_type => { | |
| 2213 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2214 | .elem_ctype = .f32, | |
| 2215 | .len = 2, | |
| 2216 | }); | |
| 2217 | if (!kind.isParameter()) return vector_ctype; | |
| 2218 | var fields = [_]Info.Field{ | |
| 2219 | .{ | |
| 2220 | .name = .{ .index = .array }, | |
| 2221 | .ctype = vector_ctype, | |
| 2222 | .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), | |
| 2223 | }, | |
| 2224 | }; | |
| 2225 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2226 | }, | |
| 2227 | .vector_4_f32_type => { | |
| 2228 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2229 | .elem_ctype = .f32, | |
| 2230 | .len = 4, | |
| 2231 | }); | |
| 2232 | if (!kind.isParameter()) return vector_ctype; | |
| 2233 | var fields = [_]Info.Field{ | |
| 2234 | .{ | |
| 2235 | .name = .{ .index = .array }, | |
| 2236 | .ctype = vector_ctype, | |
| 2237 | .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), | |
| 2238 | }, | |
| 2239 | }; | |
| 2240 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2241 | }, | |
| 2242 | .vector_8_f32_type => { | |
| 2243 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2244 | .elem_ctype = .f32, | |
| 2245 | .len = 8, | |
| 2246 | }); | |
| 2247 | if (!kind.isParameter()) return vector_ctype; | |
| 2248 | var fields = [_]Info.Field{ | |
| 2249 | .{ | |
| 2250 | .name = .{ .index = .array }, | |
| 2251 | .ctype = vector_ctype, | |
| 2252 | .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), | |
| 2253 | }, | |
| 2254 | }; | |
| 2255 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2256 | }, | |
| 2257 | .vector_16_f32_type => { | |
| 2258 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2259 | .elem_ctype = .f32, | |
| 2260 | .len = 16, | |
| 2261 | }); | |
| 2262 | if (!kind.isParameter()) return vector_ctype; | |
| 2263 | var fields = [_]Info.Field{ | |
| 2264 | .{ | |
| 2265 | .name = .{ .index = .array }, | |
| 2266 | .ctype = vector_ctype, | |
| 2267 | .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), | |
| 2268 | }, | |
| 2269 | }; | |
| 2270 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2271 | }, | |
| 2272 | .vector_2_f64_type => { | |
| 2273 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2274 | .elem_ctype = .f64, | |
| 2275 | .len = 2, | |
| 2276 | }); | |
| 2277 | if (!kind.isParameter()) return vector_ctype; | |
| 2278 | var fields = [_]Info.Field{ | |
| 2279 | .{ | |
| 2280 | .name = .{ .index = .array }, | |
| 2281 | .ctype = vector_ctype, | |
| 2282 | .alignas = AlignAs.fromAbiAlignment(Type.f64.abiAlignment(zcu)), | |
| 2283 | }, | |
| 2284 | }; | |
| 2285 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2286 | }, | |
| 2287 | .vector_4_f64_type => { | |
| 2288 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2289 | .elem_ctype = .f64, | |
| 2290 | .len = 4, | |
| 2291 | }); | |
| 2292 | if (!kind.isParameter()) return vector_ctype; | |
| 2293 | var fields = [_]Info.Field{ | |
| 2294 | .{ | |
| 2295 | .name = .{ .index = .array }, | |
| 2296 | .ctype = vector_ctype, | |
| 2297 | .alignas = AlignAs.fromAbiAlignment(Type.f64.abiAlignment(zcu)), | |
| 2298 | }, | |
| 2299 | }; | |
| 2300 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2301 | }, | |
| 2302 | .vector_8_f64_type => { | |
| 2303 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2304 | .elem_ctype = .f64, | |
| 2305 | .len = 8, | |
| 2306 | }); | |
| 2307 | if (!kind.isParameter()) return vector_ctype; | |
| 2308 | var fields = [_]Info.Field{ | |
| 2309 | .{ | |
| 2310 | .name = .{ .index = .array }, | |
| 2311 | .ctype = vector_ctype, | |
| 2312 | .alignas = AlignAs.fromAbiAlignment(Type.f64.abiAlignment(zcu)), | |
| 2313 | }, | |
| 2314 | }; | |
| 2315 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2316 | }, | |
| 2317 | ||
| 2318 | .undef, | |
| 2319 | .undef_bool, | |
| 2320 | .undef_usize, | |
| 2321 | .undef_u1, | |
| 2322 | .zero, | |
| 2323 | .zero_usize, | |
| 2324 | .zero_u1, | |
| 2325 | .zero_u8, | |
| 2326 | .one, | |
| 2327 | .one_usize, | |
| 2328 | .one_u1, | |
| 2329 | .one_u8, | |
| 2330 | .four_u8, | |
| 2331 | .negative_one, | |
| 2332 | .void_value, | |
| 2333 | .unreachable_value, | |
| 2334 | .null_value, | |
| 2335 | .bool_true, | |
| 2336 | .bool_false, | |
| 2337 | .empty_tuple, | |
| 2338 | .none, | |
| 2339 | => unreachable, // values, not types | |
| 2340 | ||
| 2341 | _ => |ip_index| switch (ip.indexToKey(ip_index)) { | |
| 2342 | .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind), | |
| 2343 | .ptr_type => |ptr_info| switch (ptr_info.flags.size) { | |
| 2344 | .one, .many, .c => { | |
| 2345 | const elem_ctype = elem_ctype: { | |
| 2346 | if (ptr_info.packed_offset.host_size > 0 and | |
| 2347 | ptr_info.flags.vector_index == .none) | |
| 2348 | break :elem_ctype try pool.fromIntInfo(allocator, .{ | |
| 2349 | .signedness = .unsigned, | |
| 2350 | .bits = ptr_info.packed_offset.host_size * 8, | |
| 2351 | }, mod, .forward); | |
| 2352 | const elem: Info.Aligned = .{ | |
| 2353 | .ctype = try pool.fromType( | |
| 2354 | allocator, | |
| 2355 | scratch, | |
| 2356 | Type.fromInterned(ptr_info.child), | |
| 2357 | pt, | |
| 2358 | mod, | |
| 2359 | .forward, | |
| 2360 | ), | |
| 2361 | .alignas = AlignAs.fromAlignment(.{ | |
| 2362 | .@"align" = ptr_info.flags.alignment, | |
| 2363 | .abi = Type.fromInterned(ptr_info.child).abiAlignment(zcu), | |
| 2364 | }), | |
| 2365 | }; | |
| 2366 | break :elem_ctype if (elem.alignas.abiOrder().compare(.gte)) | |
| 2367 | elem.ctype | |
| 2368 | else | |
| 2369 | try pool.getAligned(allocator, elem); | |
| 2370 | }; | |
| 2371 | const elem_tag: Info.Tag = switch (elem_ctype.info(pool)) { | |
| 2372 | .aligned => |aligned_info| aligned_info.ctype.info(pool), | |
| 2373 | else => |elem_tag| elem_tag, | |
| 2374 | }; | |
| 2375 | return pool.getPointer(allocator, .{ | |
| 2376 | .elem_ctype = elem_ctype, | |
| 2377 | .@"const" = switch (elem_tag) { | |
| 2378 | .basic, | |
| 2379 | .pointer, | |
| 2380 | .aligned, | |
| 2381 | .array, | |
| 2382 | .vector, | |
| 2383 | .fwd_decl, | |
| 2384 | .aggregate, | |
| 2385 | => ptr_info.flags.is_const, | |
| 2386 | .function => false, | |
| 2387 | }, | |
| 2388 | .@"volatile" = ptr_info.flags.is_volatile, | |
| 2389 | .nonstring = elem_ctype.isAnyChar() and switch (ptr_info.sentinel) { | |
| 2390 | .none => true, | |
| 2391 | .zero_u8 => false, | |
| 2392 | else => |sentinel| !Value.fromInterned(sentinel).compareAllWithZero(.eq, zcu), | |
| 2393 | }, | |
| 2394 | }); | |
| 2395 | }, | |
| 2396 | .slice => { | |
| 2397 | const target = &mod.resolved_target.result; | |
| 2398 | var fields = [_]Info.Field{ | |
| 2399 | .{ | |
| 2400 | .name = .{ .index = .ptr }, | |
| 2401 | .ctype = try pool.fromType( | |
| 2402 | allocator, | |
| 2403 | scratch, | |
| 2404 | Type.fromInterned(ip.slicePtrType(ip_index)), | |
| 2405 | pt, | |
| 2406 | mod, | |
| 2407 | kind, | |
| 2408 | ), | |
| 2409 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), | |
| 2410 | }, | |
| 2411 | .{ | |
| 2412 | .name = .{ .index = .len }, | |
| 2413 | .ctype = .usize, | |
| 2414 | .alignas = AlignAs.fromAbiAlignment( | |
| 2415 | .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), | |
| 2416 | ), | |
| 2417 | }, | |
| 2418 | }; | |
| 2419 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2420 | }, | |
| 2421 | }, | |
| 2422 | .array_type => |array_info| { | |
| 2423 | const len = array_info.lenIncludingSentinel(); | |
| 2424 | if (len == 0) return .void; | |
| 2425 | const elem_type = Type.fromInterned(array_info.child); | |
| 2426 | const elem_ctype = try pool.fromType( | |
| 2427 | allocator, | |
| 2428 | scratch, | |
| 2429 | elem_type, | |
| 2430 | pt, | |
| 2431 | mod, | |
| 2432 | kind.noParameter().asComplete(), | |
| 2433 | ); | |
| 2434 | if (elem_ctype.index == .void) return .void; | |
| 2435 | const array_ctype = try pool.getArray(allocator, .{ | |
| 2436 | .elem_ctype = elem_ctype, | |
| 2437 | .len = len, | |
| 2438 | .nonstring = elem_ctype.isAnyChar() and switch (array_info.sentinel) { | |
| 2439 | .none => true, | |
| 2440 | .zero_u8 => false, | |
| 2441 | else => |sentinel| !Value.fromInterned(sentinel).compareAllWithZero(.eq, zcu), | |
| 2442 | }, | |
| 2443 | }); | |
| 2444 | if (!kind.isParameter()) return array_ctype; | |
| 2445 | var fields = [_]Info.Field{ | |
| 2446 | .{ | |
| 2447 | .name = .{ .index = .array }, | |
| 2448 | .ctype = array_ctype, | |
| 2449 | .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), | |
| 2450 | }, | |
| 2451 | }; | |
| 2452 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2453 | }, | |
| 2454 | .vector_type => |vector_info| { | |
| 2455 | if (vector_info.len == 0) return .void; | |
| 2456 | const elem_type = Type.fromInterned(vector_info.child); | |
| 2457 | const elem_ctype = try pool.fromType( | |
| 2458 | allocator, | |
| 2459 | scratch, | |
| 2460 | elem_type, | |
| 2461 | pt, | |
| 2462 | mod, | |
| 2463 | kind.noParameter().asComplete(), | |
| 2464 | ); | |
| 2465 | if (elem_ctype.index == .void) return .void; | |
| 2466 | const vector_ctype = try pool.getVector(allocator, .{ | |
| 2467 | .elem_ctype = elem_ctype, | |
| 2468 | .len = vector_info.len, | |
| 2469 | .nonstring = elem_ctype.isAnyChar(), | |
| 2470 | }); | |
| 2471 | if (!kind.isParameter()) return vector_ctype; | |
| 2472 | var fields = [_]Info.Field{ | |
| 2473 | .{ | |
| 2474 | .name = .{ .index = .array }, | |
| 2475 | .ctype = vector_ctype, | |
| 2476 | .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), | |
| 2477 | }, | |
| 2478 | }; | |
| 2479 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2480 | }, | |
| 2481 | .opt_type => |payload_type| { | |
| 2482 | if (ip.isNoReturn(payload_type)) return .void; | |
| 2483 | const payload_ctype = try pool.fromType( | |
| 2484 | allocator, | |
| 2485 | scratch, | |
| 2486 | Type.fromInterned(payload_type), | |
| 2487 | pt, | |
| 2488 | mod, | |
| 2489 | kind.noParameter(), | |
| 2490 | ); | |
| 2491 | if (payload_ctype.index == .void) return .bool; | |
| 2492 | switch (payload_type) { | |
| 2493 | .anyerror_type => return payload_ctype, | |
| 2494 | else => switch (ip.indexToKey(payload_type)) { | |
| 2495 | .ptr_type => |payload_ptr_info| if (payload_ptr_info.flags.size != .c and | |
| 2496 | !payload_ptr_info.flags.is_allowzero) return payload_ctype, | |
| 2497 | .error_set_type, .inferred_error_set_type => return payload_ctype, | |
| 2498 | else => {}, | |
| 2499 | }, | |
| 2500 | } | |
| 2501 | var fields = [_]Info.Field{ | |
| 2502 | .{ | |
| 2503 | .name = .{ .index = .is_null }, | |
| 2504 | .ctype = .bool, | |
| 2505 | .alignas = AlignAs.fromAbiAlignment(.@"1"), | |
| 2506 | }, | |
| 2507 | .{ | |
| 2508 | .name = .{ .index = .payload }, | |
| 2509 | .ctype = payload_ctype, | |
| 2510 | .alignas = AlignAs.fromAbiAlignment( | |
| 2511 | Type.fromInterned(payload_type).abiAlignment(zcu), | |
| 2512 | ), | |
| 2513 | }, | |
| 2514 | }; | |
| 2515 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2516 | }, | |
| 2517 | .anyframe_type => unreachable, | |
| 2518 | .error_union_type => |error_union_info| { | |
| 2519 | const error_set_bits = pt.zcu.errorSetBits(); | |
| 2520 | const error_set_ctype = try pool.fromIntInfo(allocator, .{ | |
| 2521 | .signedness = .unsigned, | |
| 2522 | .bits = error_set_bits, | |
| 2523 | }, mod, kind); | |
| 2524 | if (ip.isNoReturn(error_union_info.payload_type)) return error_set_ctype; | |
| 2525 | const payload_type = Type.fromInterned(error_union_info.payload_type); | |
| 2526 | const payload_ctype = try pool.fromType( | |
| 2527 | allocator, | |
| 2528 | scratch, | |
| 2529 | payload_type, | |
| 2530 | pt, | |
| 2531 | mod, | |
| 2532 | kind.noParameter(), | |
| 2533 | ); | |
| 2534 | if (payload_ctype.index == .void) return error_set_ctype; | |
| 2535 | const target = &mod.resolved_target.result; | |
| 2536 | var fields = [_]Info.Field{ | |
| 2537 | .{ | |
| 2538 | .name = .{ .index = .@"error" }, | |
| 2539 | .ctype = error_set_ctype, | |
| 2540 | .alignas = AlignAs.fromAbiAlignment( | |
| 2541 | .fromByteUnits(std.zig.target.intAlignment(target, error_set_bits)), | |
| 2542 | ), | |
| 2543 | }, | |
| 2544 | .{ | |
| 2545 | .name = .{ .index = .payload }, | |
| 2546 | .ctype = payload_ctype, | |
| 2547 | .alignas = AlignAs.fromAbiAlignment(payload_type.abiAlignment(zcu)), | |
| 2548 | }, | |
| 2549 | }; | |
| 2550 | return pool.fromFields(allocator, .@"struct", &fields, kind); | |
| 2551 | }, | |
| 2552 | .simple_type => unreachable, | |
| 2553 | .struct_type => { | |
| 2554 | const loaded_struct = ip.loadStructType(ip_index); | |
| 2555 | switch (loaded_struct.layout) { | |
| 2556 | .auto, .@"extern" => { | |
| 2557 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | |
| 2558 | .tag = .@"struct", | |
| 2559 | .name = .{ .index = ip_index }, | |
| 2560 | }); | |
| 2561 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 2562 | fwd_decl | |
| 2563 | else | |
| 2564 | .void; | |
| 2565 | const scratch_top = scratch.items.len; | |
| 2566 | defer scratch.shrinkRetainingCapacity(scratch_top); | |
| 2567 | try scratch.ensureUnusedCapacity( | |
| 2568 | allocator, | |
| 2569 | loaded_struct.field_types.len * @typeInfo(Field).@"struct".fields.len, | |
| 2570 | ); | |
| 2571 | var hasher = Hasher.init; | |
| 2572 | var tag: Pool.Tag = .aggregate_struct; | |
| 2573 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | |
| 2574 | while (field_it.next()) |field_index| { | |
| 2575 | const field_type = Type.fromInterned( | |
| 2576 | loaded_struct.field_types.get(ip)[field_index], | |
| 2577 | ); | |
| 2578 | const field_ctype = try pool.fromType( | |
| 2579 | allocator, | |
| 2580 | scratch, | |
| 2581 | field_type, | |
| 2582 | pt, | |
| 2583 | mod, | |
| 2584 | kind.noParameter(), | |
| 2585 | ); | |
| 2586 | if (field_ctype.index == .void) continue; | |
| 2587 | const field_name = try pool.string(allocator, loaded_struct.fieldName(ip, field_index).toSlice(ip)); | |
| 2588 | const field_alignas = AlignAs.fromAlignment(.{ | |
| 2589 | .@"align" = loaded_struct.fieldAlign(ip, field_index), | |
| 2590 | .abi = field_type.abiAlignment(zcu), | |
| 2591 | }); | |
| 2592 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | |
| 2593 | .name = field_name.index, | |
| 2594 | .ctype = field_ctype.index, | |
| 2595 | .flags = .{ .alignas = field_alignas }, | |
| 2596 | }); | |
| 2597 | if (field_alignas.abiOrder().compare(.lt)) | |
| 2598 | tag = .aggregate_struct_packed; | |
| 2599 | } | |
| 2600 | const fields_len: u32 = @intCast(@divExact( | |
| 2601 | scratch.items.len - scratch_top, | |
| 2602 | @typeInfo(Field).@"struct".fields.len, | |
| 2603 | )); | |
| 2604 | if (fields_len == 0) return .void; | |
| 2605 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 2606 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ | |
| 2607 | .fwd_decl = fwd_decl.index, | |
| 2608 | .fields_len = fields_len, | |
| 2609 | }, fields_len * @typeInfo(Field).@"struct".fields.len); | |
| 2610 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | |
| 2611 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | |
| 2612 | }, | |
| 2613 | .@"packed" => return pool.fromType( | |
| 2614 | allocator, | |
| 2615 | scratch, | |
| 2616 | Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip)), | |
| 2617 | pt, | |
| 2618 | mod, | |
| 2619 | kind, | |
| 2620 | ), | |
| 2621 | } | |
| 2622 | }, | |
| 2623 | .tuple_type => |tuple_info| { | |
| 2624 | const scratch_top = scratch.items.len; | |
| 2625 | defer scratch.shrinkRetainingCapacity(scratch_top); | |
| 2626 | try scratch.ensureUnusedCapacity(allocator, tuple_info.types.len * | |
| 2627 | @typeInfo(Field).@"struct".fields.len); | |
| 2628 | var hasher = Hasher.init; | |
| 2629 | for (0..tuple_info.types.len) |field_index| { | |
| 2630 | if (tuple_info.values.get(ip)[field_index] != .none) continue; | |
| 2631 | const field_type = Type.fromInterned( | |
| 2632 | tuple_info.types.get(ip)[field_index], | |
| 2633 | ); | |
| 2634 | const field_ctype = try pool.fromType( | |
| 2635 | allocator, | |
| 2636 | scratch, | |
| 2637 | field_type, | |
| 2638 | pt, | |
| 2639 | mod, | |
| 2640 | kind.noParameter(), | |
| 2641 | ); | |
| 2642 | if (field_ctype.index == .void) continue; | |
| 2643 | const field_name = try pool.fmt(allocator, "f{d}", .{field_index}); | |
| 2644 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | |
| 2645 | .name = field_name.index, | |
| 2646 | .ctype = field_ctype.index, | |
| 2647 | .flags = .{ .alignas = AlignAs.fromAbiAlignment( | |
| 2648 | field_type.abiAlignment(zcu), | |
| 2649 | ) }, | |
| 2650 | }); | |
| 2651 | } | |
| 2652 | const fields_len: u32 = @intCast(@divExact( | |
| 2653 | scratch.items.len - scratch_top, | |
| 2654 | @typeInfo(Field).@"struct".fields.len, | |
| 2655 | )); | |
| 2656 | if (fields_len == 0) return .void; | |
| 2657 | if (kind.isForward()) { | |
| 2658 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 2659 | const extra_index = try pool.addHashedExtra( | |
| 2660 | allocator, | |
| 2661 | &hasher, | |
| 2662 | FwdDeclAnon, | |
| 2663 | .{ .fields_len = fields_len }, | |
| 2664 | fields_len * @typeInfo(Field).@"struct".fields.len, | |
| 2665 | ); | |
| 2666 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | |
| 2667 | return pool.tagTrailingExtra( | |
| 2668 | allocator, | |
| 2669 | hasher, | |
| 2670 | .fwd_decl_struct_anon, | |
| 2671 | extra_index, | |
| 2672 | ); | |
| 2673 | } | |
| 2674 | const fwd_decl = try pool.fromType(allocator, scratch, ty, pt, mod, .forward); | |
| 2675 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 2676 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ | |
| 2677 | .fwd_decl = fwd_decl.index, | |
| 2678 | .fields_len = fields_len, | |
| 2679 | }, fields_len * @typeInfo(Field).@"struct".fields.len); | |
| 2680 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | |
| 2681 | return pool.tagTrailingExtraAssumeCapacity(hasher, .aggregate_struct, extra_index); | |
| 2682 | }, | |
| 2683 | .union_type => { | |
| 2684 | const loaded_union = ip.loadUnionType(ip_index); | |
| 2685 | switch (loaded_union.flagsUnordered(ip).layout) { | |
| 2686 | .auto, .@"extern" => { | |
| 2687 | const has_tag = loaded_union.hasTag(ip); | |
| 2688 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | |
| 2689 | .tag = if (has_tag) .@"struct" else .@"union", | |
| 2690 | .name = .{ .index = ip_index }, | |
| 2691 | }); | |
| 2692 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 2693 | fwd_decl | |
| 2694 | else | |
| 2695 | .void; | |
| 2696 | const loaded_tag = loaded_union.loadTagType(ip); | |
| 2697 | const scratch_top = scratch.items.len; | |
| 2698 | defer scratch.shrinkRetainingCapacity(scratch_top); | |
| 2699 | try scratch.ensureUnusedCapacity( | |
| 2700 | allocator, | |
| 2701 | loaded_union.field_types.len * @typeInfo(Field).@"struct".fields.len, | |
| 2702 | ); | |
| 2703 | var hasher = Hasher.init; | |
| 2704 | var tag: Pool.Tag = .aggregate_union; | |
| 2705 | var payload_align: InternPool.Alignment = .@"1"; | |
| 2706 | for (0..loaded_union.field_types.len) |field_index| { | |
| 2707 | const field_type = Type.fromInterned( | |
| 2708 | loaded_union.field_types.get(ip)[field_index], | |
| 2709 | ); | |
| 2710 | if (ip.isNoReturn(field_type.toIntern())) continue; | |
| 2711 | const field_ctype = try pool.fromType( | |
| 2712 | allocator, | |
| 2713 | scratch, | |
| 2714 | field_type, | |
| 2715 | pt, | |
| 2716 | mod, | |
| 2717 | kind.noParameter(), | |
| 2718 | ); | |
| 2719 | if (field_ctype.index == .void) continue; | |
| 2720 | const field_name = try pool.string( | |
| 2721 | allocator, | |
| 2722 | loaded_tag.names.get(ip)[field_index].toSlice(ip), | |
| 2723 | ); | |
| 2724 | const field_alignas = AlignAs.fromAlignment(.{ | |
| 2725 | .@"align" = loaded_union.fieldAlign(ip, field_index), | |
| 2726 | .abi = field_type.abiAlignment(zcu), | |
| 2727 | }); | |
| 2728 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | |
| 2729 | .name = field_name.index, | |
| 2730 | .ctype = field_ctype.index, | |
| 2731 | .flags = .{ .alignas = field_alignas }, | |
| 2732 | }); | |
| 2733 | if (field_alignas.abiOrder().compare(.lt)) | |
| 2734 | tag = .aggregate_union_packed; | |
| 2735 | payload_align = payload_align.maxStrict(field_alignas.@"align"); | |
| 2736 | } | |
| 2737 | const fields_len: u32 = @intCast(@divExact( | |
| 2738 | scratch.items.len - scratch_top, | |
| 2739 | @typeInfo(Field).@"struct".fields.len, | |
| 2740 | )); | |
| 2741 | if (!has_tag) { | |
| 2742 | if (fields_len == 0) return .void; | |
| 2743 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 2744 | const extra_index = try pool.addHashedExtra( | |
| 2745 | allocator, | |
| 2746 | &hasher, | |
| 2747 | Aggregate, | |
| 2748 | .{ .fwd_decl = fwd_decl.index, .fields_len = fields_len }, | |
| 2749 | fields_len * @typeInfo(Field).@"struct".fields.len, | |
| 2750 | ); | |
| 2751 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | |
| 2752 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | |
| 2753 | } | |
| 2754 | try pool.ensureUnusedCapacity(allocator, 2); | |
| 2755 | var struct_fields: [2]Info.Field = undefined; | |
| 2756 | var struct_fields_len: usize = 0; | |
| 2757 | if (loaded_tag.tag_ty != .comptime_int_type) { | |
| 2758 | const tag_type = Type.fromInterned(loaded_tag.tag_ty); | |
| 2759 | const tag_ctype: CType = try pool.fromType( | |
| 2760 | allocator, | |
| 2761 | scratch, | |
| 2762 | tag_type, | |
| 2763 | pt, | |
| 2764 | mod, | |
| 2765 | kind.noParameter(), | |
| 2766 | ); | |
| 2767 | if (tag_ctype.index != .void) { | |
| 2768 | struct_fields[struct_fields_len] = .{ | |
| 2769 | .name = .{ .index = .tag }, | |
| 2770 | .ctype = tag_ctype, | |
| 2771 | .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), | |
| 2772 | }; | |
| 2773 | struct_fields_len += 1; | |
| 2774 | } | |
| 2775 | } | |
| 2776 | if (fields_len > 0) { | |
| 2777 | const payload_ctype = payload_ctype: { | |
| 2778 | const extra_index = try pool.addHashedExtra( | |
| 2779 | allocator, | |
| 2780 | &hasher, | |
| 2781 | AggregateAnon, | |
| 2782 | .{ | |
| 2783 | .index = ip_index, | |
| 2784 | .id = 0, | |
| 2785 | .fields_len = fields_len, | |
| 2786 | }, | |
| 2787 | fields_len * @typeInfo(Field).@"struct".fields.len, | |
| 2788 | ); | |
| 2789 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | |
| 2790 | break :payload_ctype pool.tagTrailingExtraAssumeCapacity( | |
| 2791 | hasher, | |
| 2792 | switch (tag) { | |
| 2793 | .aggregate_union => .aggregate_union_anon, | |
| 2794 | .aggregate_union_packed => .aggregate_union_packed_anon, | |
| 2795 | else => unreachable, | |
| 2796 | }, | |
| 2797 | extra_index, | |
| 2798 | ); | |
| 2799 | }; | |
| 2800 | if (payload_ctype.index != .void) { | |
| 2801 | struct_fields[struct_fields_len] = .{ | |
| 2802 | .name = .{ .index = .payload }, | |
| 2803 | .ctype = payload_ctype, | |
| 2804 | .alignas = AlignAs.fromAbiAlignment(payload_align), | |
| 2805 | }; | |
| 2806 | struct_fields_len += 1; | |
| 2807 | } | |
| 2808 | } | |
| 2809 | if (struct_fields_len == 0) return .void; | |
| 2810 | sortFields(struct_fields[0..struct_fields_len]); | |
| 2811 | return pool.getAggregate(allocator, .{ | |
| 2812 | .tag = .@"struct", | |
| 2813 | .name = .{ .fwd_decl = fwd_decl }, | |
| 2814 | .fields = struct_fields[0..struct_fields_len], | |
| 2815 | }); | |
| 2816 | }, | |
| 2817 | .@"packed" => return pool.fromIntInfo(allocator, .{ | |
| 2818 | .signedness = .unsigned, | |
| 2819 | .bits = @intCast(ty.bitSize(zcu)), | |
| 2820 | }, mod, kind), | |
| 2821 | } | |
| 2822 | }, | |
| 2823 | .opaque_type => return .void, | |
| 2824 | .enum_type => return pool.fromType( | |
| 2825 | allocator, | |
| 2826 | scratch, | |
| 2827 | Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), | |
| 2828 | pt, | |
| 2829 | mod, | |
| 2830 | kind, | |
| 2831 | ), | |
| 2832 | .func_type => |func_info| if (func_info.is_generic) return .void else { | |
| 2833 | const scratch_top = scratch.items.len; | |
| 2834 | defer scratch.shrinkRetainingCapacity(scratch_top); | |
| 2835 | try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len); | |
| 2836 | var hasher = Hasher.init; | |
| 2837 | const return_type = Type.fromInterned(func_info.return_type); | |
| 2838 | const return_ctype: CType = | |
| 2839 | if (!ip.isNoReturn(func_info.return_type)) try pool.fromType( | |
| 2840 | allocator, | |
| 2841 | scratch, | |
| 2842 | return_type, | |
| 2843 | pt, | |
| 2844 | mod, | |
| 2845 | kind.asParameter(), | |
| 2846 | ) else .void; | |
| 2847 | for (0..func_info.param_types.len) |param_index| { | |
| 2848 | const param_type = Type.fromInterned( | |
| 2849 | func_info.param_types.get(ip)[param_index], | |
| 2850 | ); | |
| 2851 | const param_ctype = try pool.fromType( | |
| 2852 | allocator, | |
| 2853 | scratch, | |
| 2854 | param_type, | |
| 2855 | pt, | |
| 2856 | mod, | |
| 2857 | kind.asParameter(), | |
| 2858 | ); | |
| 2859 | if (param_ctype.index == .void) continue; | |
| 2860 | hasher.update(param_ctype.hash(pool)); | |
| 2861 | scratch.appendAssumeCapacity(@intFromEnum(param_ctype.index)); | |
| 2862 | } | |
| 2863 | const param_ctypes_len: u32 = @intCast(scratch.items.len - scratch_top); | |
| 2864 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 2865 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Function, .{ | |
| 2866 | .return_ctype = return_ctype.index, | |
| 2867 | .param_ctypes_len = param_ctypes_len, | |
| 2868 | }, param_ctypes_len); | |
| 2869 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | |
| 2870 | return pool.tagTrailingExtraAssumeCapacity(hasher, switch (func_info.is_var_args) { | |
| 2871 | false => .function, | |
| 2872 | true => .function_varargs, | |
| 2873 | }, extra_index); | |
| 2874 | }, | |
| 2875 | .error_set_type, | |
| 2876 | .inferred_error_set_type, | |
| 2877 | => return pool.fromIntInfo(allocator, .{ | |
| 2878 | .signedness = .unsigned, | |
| 2879 | .bits = pt.zcu.errorSetBits(), | |
| 2880 | }, mod, kind), | |
| 2881 | ||
| 2882 | .undef, | |
| 2883 | .simple_value, | |
| 2884 | .variable, | |
| 2885 | .@"extern", | |
| 2886 | .func, | |
| 2887 | .int, | |
| 2888 | .err, | |
| 2889 | .error_union, | |
| 2890 | .enum_literal, | |
| 2891 | .enum_tag, | |
| 2892 | .empty_enum_value, | |
| 2893 | .float, | |
| 2894 | .ptr, | |
| 2895 | .slice, | |
| 2896 | .opt, | |
| 2897 | .aggregate, | |
| 2898 | .un, | |
| 2899 | .memoized_call, | |
| 2900 | => unreachable, // values, not types | |
| 2901 | }, | |
| 2902 | } | |
| 2903 | } | |
| 2904 | ||
| 2905 | pub fn getOrPutAdapted( | |
| 2906 | pool: *Pool, | |
| 2907 | allocator: std.mem.Allocator, | |
| 2908 | source_pool: *const Pool, | |
| 2909 | source_ctype: CType, | |
| 2910 | pool_adapter: anytype, | |
| 2911 | ) !struct { CType, bool } { | |
| 2912 | const tag = source_pool.items.items(.tag)[ | |
| 2913 | source_ctype.toPoolIndex() orelse return .{ source_ctype, true } | |
| 2914 | ]; | |
| 2915 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 2916 | const CTypeAdapter = struct { | |
| 2917 | pool: *const Pool, | |
| 2918 | source_pool: *const Pool, | |
| 2919 | source_info: Info, | |
| 2920 | pool_adapter: @TypeOf(pool_adapter), | |
| 2921 | pub fn hash(map_adapter: @This(), key_ctype: CType) Map.Hash { | |
| 2922 | return key_ctype.hash(map_adapter.source_pool); | |
| 2923 | } | |
| 2924 | pub fn eql(map_adapter: @This(), _: CType, _: void, pool_index: usize) bool { | |
| 2925 | return map_adapter.source_info.eqlAdapted( | |
| 2926 | map_adapter.source_pool, | |
| 2927 | .fromPoolIndex(pool_index), | |
| 2928 | map_adapter.pool, | |
| 2929 | map_adapter.pool_adapter, | |
| 2930 | ); | |
| 2931 | } | |
| 2932 | }; | |
| 2933 | const source_info = source_ctype.info(source_pool); | |
| 2934 | const gop = pool.map.getOrPutAssumeCapacityAdapted(source_ctype, CTypeAdapter{ | |
| 2935 | .pool = pool, | |
| 2936 | .source_pool = source_pool, | |
| 2937 | .source_info = source_info, | |
| 2938 | .pool_adapter = pool_adapter, | |
| 2939 | }); | |
| 2940 | errdefer _ = pool.map.pop(); | |
| 2941 | const ctype: CType = .fromPoolIndex(gop.index); | |
| 2942 | if (!gop.found_existing) switch (source_info) { | |
| 2943 | .basic => unreachable, | |
| 2944 | .pointer => |pointer_info| pool.items.appendAssumeCapacity(switch (pointer_info.nonstring) { | |
| 2945 | false => .{ | |
| 2946 | .tag = tag, | |
| 2947 | .data = @intFromEnum(pool_adapter.copy(pointer_info.elem_ctype).index), | |
| 2948 | }, | |
| 2949 | true => .{ | |
| 2950 | .tag = .nonstring, | |
| 2951 | .data = @intFromEnum(pool_adapter.copy(.{ .index = @enumFromInt( | |
| 2952 | source_pool.items.items(.data)[source_ctype.toPoolIndex().?], | |
| 2953 | ) }).index), | |
| 2954 | }, | |
| 2955 | }), | |
| 2956 | .aligned => |aligned_info| pool.items.appendAssumeCapacity(.{ | |
| 2957 | .tag = tag, | |
| 2958 | .data = try pool.addExtra(allocator, Aligned, .{ | |
| 2959 | .ctype = pool_adapter.copy(aligned_info.ctype).index, | |
| 2960 | .flags = .{ .alignas = aligned_info.alignas }, | |
| 2961 | }, 0), | |
| 2962 | }), | |
| 2963 | .array, .vector => |sequence_info| pool.items.appendAssumeCapacity(switch (sequence_info.nonstring) { | |
| 2964 | false => .{ | |
| 2965 | .tag = tag, | |
| 2966 | .data = switch (tag) { | |
| 2967 | .array_small, .vector => try pool.addExtra(allocator, SequenceSmall, .{ | |
| 2968 | .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, | |
| 2969 | .len = @intCast(sequence_info.len), | |
| 2970 | }, 0), | |
| 2971 | .array_large => try pool.addExtra(allocator, SequenceLarge, .{ | |
| 2972 | .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, | |
| 2973 | .len_lo = @truncate(sequence_info.len >> 0), | |
| 2974 | .len_hi = @truncate(sequence_info.len >> 32), | |
| 2975 | }, 0), | |
| 2976 | else => unreachable, | |
| 2977 | }, | |
| 2978 | }, | |
| 2979 | true => .{ | |
| 2980 | .tag = .nonstring, | |
| 2981 | .data = @intFromEnum(pool_adapter.copy(.{ .index = @enumFromInt( | |
| 2982 | source_pool.items.items(.data)[source_ctype.toPoolIndex().?], | |
| 2983 | ) }).index), | |
| 2984 | }, | |
| 2985 | }), | |
| 2986 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 2987 | .anon => |fields| { | |
| 2988 | pool.items.appendAssumeCapacity(.{ | |
| 2989 | .tag = tag, | |
| 2990 | .data = try pool.addExtra(allocator, FwdDeclAnon, .{ | |
| 2991 | .fields_len = fields.len, | |
| 2992 | }, fields.len * @typeInfo(Field).@"struct".fields.len), | |
| 2993 | }); | |
| 2994 | for (0..fields.len) |field_index| { | |
| 2995 | const field = fields.at(field_index, source_pool); | |
| 2996 | const field_name = if (field.name.toPoolSlice(source_pool)) |slice| | |
| 2997 | try pool.string(allocator, slice) | |
| 2998 | else | |
| 2999 | field.name; | |
| 3000 | pool.addExtraAssumeCapacity(Field, .{ | |
| 3001 | .name = field_name.index, | |
| 3002 | .ctype = pool_adapter.copy(field.ctype).index, | |
| 3003 | .flags = .{ .alignas = field.alignas }, | |
| 3004 | }); | |
| 3005 | } | |
| 3006 | }, | |
| 3007 | .index => |index| pool.items.appendAssumeCapacity(.{ | |
| 3008 | .tag = tag, | |
| 3009 | .data = @intFromEnum(index), | |
| 3010 | }), | |
| 3011 | }, | |
| 3012 | .aggregate => |aggregate_info| { | |
| 3013 | pool.items.appendAssumeCapacity(.{ | |
| 3014 | .tag = tag, | |
| 3015 | .data = switch (aggregate_info.name) { | |
| 3016 | .anon => |anon| try pool.addExtra(allocator, AggregateAnon, .{ | |
| 3017 | .index = anon.index, | |
| 3018 | .id = anon.id, | |
| 3019 | .fields_len = aggregate_info.fields.len, | |
| 3020 | }, aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len), | |
| 3021 | .fwd_decl => |fwd_decl| try pool.addExtra(allocator, Aggregate, .{ | |
| 3022 | .fwd_decl = pool_adapter.copy(fwd_decl).index, | |
| 3023 | .fields_len = aggregate_info.fields.len, | |
| 3024 | }, aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len), | |
| 3025 | }, | |
| 3026 | }); | |
| 3027 | for (0..aggregate_info.fields.len) |field_index| { | |
| 3028 | const field = aggregate_info.fields.at(field_index, source_pool); | |
| 3029 | const field_name = if (field.name.toPoolSlice(source_pool)) |slice| | |
| 3030 | try pool.string(allocator, slice) | |
| 3031 | else | |
| 3032 | field.name; | |
| 3033 | pool.addExtraAssumeCapacity(Field, .{ | |
| 3034 | .name = field_name.index, | |
| 3035 | .ctype = pool_adapter.copy(field.ctype).index, | |
| 3036 | .flags = .{ .alignas = field.alignas }, | |
| 3037 | }); | |
| 3038 | } | |
| 3039 | }, | |
| 3040 | .function => |function_info| { | |
| 3041 | pool.items.appendAssumeCapacity(.{ | |
| 3042 | .tag = tag, | |
| 3043 | .data = try pool.addExtra(allocator, Function, .{ | |
| 3044 | .return_ctype = pool_adapter.copy(function_info.return_ctype).index, | |
| 3045 | .param_ctypes_len = function_info.param_ctypes.len, | |
| 3046 | }, function_info.param_ctypes.len), | |
| 3047 | }); | |
| 3048 | for (0..function_info.param_ctypes.len) |param_index| pool.extra.appendAssumeCapacity( | |
| 3049 | @intFromEnum(pool_adapter.copy( | |
| 3050 | function_info.param_ctypes.at(param_index, source_pool), | |
| 3051 | ).index), | |
| 3052 | ); | |
| 3053 | }, | |
| 3054 | }; | |
| 3055 | assert(source_info.eqlAdapted(source_pool, ctype, pool, pool_adapter)); | |
| 3056 | assert(source_ctype.hash(source_pool) == ctype.hash(pool)); | |
| 3057 | return .{ ctype, gop.found_existing }; | |
| 3058 | } | |
| 3059 | ||
| 3060 | pub fn string(pool: *Pool, allocator: std.mem.Allocator, slice: []const u8) !String { | |
| 3061 | try pool.string_bytes.appendSlice(allocator, slice); | |
| 3062 | return pool.trailingString(allocator); | |
| 3063 | } | |
| 3064 | ||
| 3065 | pub fn fmt( | |
| 3066 | pool: *Pool, | |
| 3067 | allocator: std.mem.Allocator, | |
| 3068 | comptime fmt_str: []const u8, | |
| 3069 | fmt_args: anytype, | |
| 3070 | ) !String { | |
| 3071 | try pool.string_bytes.print(allocator, fmt_str, fmt_args); | |
| 3072 | return pool.trailingString(allocator); | |
| 3073 | } | |
| 3074 | ||
| 3075 | fn ensureUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator, len: u32) !void { | |
| 3076 | try pool.map.ensureUnusedCapacity(allocator, len); | |
| 3077 | try pool.items.ensureUnusedCapacity(allocator, len); | |
| 3078 | } | |
| 3079 | ||
| 3080 | const Hasher = struct { | |
| 3081 | const Impl = std.hash.Wyhash; | |
| 3082 | impl: Impl, | |
| 3083 | ||
| 3084 | const init: Hasher = .{ .impl = Impl.init(0) }; | |
| 3085 | ||
| 3086 | fn updateExtra(hasher: *Hasher, comptime Extra: type, extra: Extra, pool: *const Pool) void { | |
| 3087 | inline for (@typeInfo(Extra).@"struct".fields) |field| { | |
| 3088 | const value = @field(extra, field.name); | |
| 3089 | switch (field.type) { | |
| 3090 | Pool.Tag, String, CType => unreachable, | |
| 3091 | CType.Index => hasher.update((CType{ .index = value }).hash(pool)), | |
| 3092 | String.Index => if ((String{ .index = value }).toPoolSlice(pool)) |slice| | |
| 3093 | hasher.update(slice) | |
| 3094 | else | |
| 3095 | hasher.update(@intFromEnum(value)), | |
| 3096 | else => hasher.update(value), | |
| 3097 | } | |
| 3098 | } | |
| 3099 | } | |
| 3100 | fn update(hasher: *Hasher, data: anytype) void { | |
| 3101 | switch (@TypeOf(data)) { | |
| 3102 | Pool.Tag => @compileError("pass tag to final"), | |
| 3103 | CType, CType.Index => @compileError("hash ctype.hash(pool) instead"), | |
| 3104 | String, String.Index => @compileError("hash string.slice(pool) instead"), | |
| 3105 | u32, InternPool.Index, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)), | |
| 3106 | []const u8 => hasher.impl.update(data), | |
| 3107 | else => @compileError("unhandled type: " ++ @typeName(@TypeOf(data))), | |
| 3108 | } | |
| 3109 | } | |
| 3110 | ||
| 3111 | fn final(hasher: Hasher, tag: Pool.Tag) Map.Hash { | |
| 3112 | var impl = hasher.impl; | |
| 3113 | impl.update(std.mem.asBytes(&tag)); | |
| 3114 | return @truncate(impl.final()); | |
| 3115 | } | |
| 3116 | }; | |
| 3117 | ||
| 3118 | fn tagData( | |
| 3119 | pool: *Pool, | |
| 3120 | allocator: std.mem.Allocator, | |
| 3121 | hasher: Hasher, | |
| 3122 | tag: Pool.Tag, | |
| 3123 | data: u32, | |
| 3124 | ) !CType { | |
| 3125 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 3126 | const Key = struct { hash: Map.Hash, tag: Pool.Tag, data: u32 }; | |
| 3127 | const CTypeAdapter = struct { | |
| 3128 | pool: *const Pool, | |
| 3129 | pub fn hash(_: @This(), key: Key) Map.Hash { | |
| 3130 | return key.hash; | |
| 3131 | } | |
| 3132 | pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | |
| 3133 | const rhs_item = ctype_adapter.pool.items.get(rhs_index); | |
| 3134 | return lhs_key.tag == rhs_item.tag and lhs_key.data == rhs_item.data; | |
| 3135 | } | |
| 3136 | }; | |
| 3137 | const gop = pool.map.getOrPutAssumeCapacityAdapted( | |
| 3138 | Key{ .hash = hasher.final(tag), .tag = tag, .data = data }, | |
| 3139 | CTypeAdapter{ .pool = pool }, | |
| 3140 | ); | |
| 3141 | if (!gop.found_existing) pool.items.appendAssumeCapacity(.{ .tag = tag, .data = data }); | |
| 3142 | return .fromPoolIndex(gop.index); | |
| 3143 | } | |
| 3144 | ||
| 3145 | fn tagExtra( | |
| 3146 | pool: *Pool, | |
| 3147 | allocator: std.mem.Allocator, | |
| 3148 | tag: Pool.Tag, | |
| 3149 | comptime Extra: type, | |
| 3150 | extra: Extra, | |
| 3151 | ) !CType { | |
| 3152 | var hasher = Hasher.init; | |
| 3153 | hasher.updateExtra(Extra, extra, pool); | |
| 3154 | return pool.tagTrailingExtra( | |
| 3155 | allocator, | |
| 3156 | hasher, | |
| 3157 | tag, | |
| 3158 | try pool.addExtra(allocator, Extra, extra, 0), | |
| 3159 | ); | |
| 3160 | } | |
| 3161 | ||
| 3162 | fn tagTrailingExtra( | |
| 3163 | pool: *Pool, | |
| 3164 | allocator: std.mem.Allocator, | |
| 3165 | hasher: Hasher, | |
| 3166 | tag: Pool.Tag, | |
| 3167 | extra_index: ExtraIndex, | |
| 3168 | ) !CType { | |
| 3169 | try pool.ensureUnusedCapacity(allocator, 1); | |
| 3170 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | |
| 3171 | } | |
| 3172 | ||
| 3173 | fn tagTrailingExtraAssumeCapacity( | |
| 3174 | pool: *Pool, | |
| 3175 | hasher: Hasher, | |
| 3176 | tag: Pool.Tag, | |
| 3177 | extra_index: ExtraIndex, | |
| 3178 | ) CType { | |
| 3179 | const Key = struct { hash: Map.Hash, tag: Pool.Tag, extra: []const u32 }; | |
| 3180 | const CTypeAdapter = struct { | |
| 3181 | pool: *const Pool, | |
| 3182 | pub fn hash(_: @This(), key: Key) Map.Hash { | |
| 3183 | return key.hash; | |
| 3184 | } | |
| 3185 | pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | |
| 3186 | const rhs_item = ctype_adapter.pool.items.get(rhs_index); | |
| 3187 | if (lhs_key.tag != rhs_item.tag) return false; | |
| 3188 | const rhs_extra = ctype_adapter.pool.extra.items[rhs_item.data..]; | |
| 3189 | return std.mem.startsWith(u32, rhs_extra, lhs_key.extra); | |
| 3190 | } | |
| 3191 | }; | |
| 3192 | const gop = pool.map.getOrPutAssumeCapacityAdapted( | |
| 3193 | Key{ .hash = hasher.final(tag), .tag = tag, .extra = pool.extra.items[extra_index..] }, | |
| 3194 | CTypeAdapter{ .pool = pool }, | |
| 3195 | ); | |
| 3196 | if (gop.found_existing) | |
| 3197 | pool.extra.shrinkRetainingCapacity(extra_index) | |
| 3198 | else | |
| 3199 | pool.items.appendAssumeCapacity(.{ .tag = tag, .data = extra_index }); | |
| 3200 | return .fromPoolIndex(gop.index); | |
| 3201 | } | |
| 3202 | ||
| 3203 | fn sortFields(fields: []Info.Field) void { | |
| 3204 | std.mem.sort(Info.Field, fields, {}, struct { | |
| 3205 | fn before(_: void, lhs_field: Info.Field, rhs_field: Info.Field) bool { | |
| 3206 | return lhs_field.alignas.order(rhs_field.alignas).compare(.gt); | |
| 3207 | } | |
| 3208 | }.before); | |
| 3209 | } | |
| 3210 | ||
| 3211 | fn trailingString(pool: *Pool, allocator: std.mem.Allocator) !String { | |
| 3212 | const start = pool.string_indices.getLast(); | |
| 3213 | const slice: []const u8 = pool.string_bytes.items[start..]; | |
| 3214 | if (slice.len >= 2 and slice[0] == 'f' and switch (slice[1]) { | |
| 3215 | '0' => slice.len == 2, | |
| 3216 | '1'...'9' => true, | |
| 3217 | else => false, | |
| 3218 | }) if (std.fmt.parseInt(u31, slice[1..], 10)) |unnamed| { | |
| 3219 | pool.string_bytes.shrinkRetainingCapacity(start); | |
| 3220 | return String.fromUnnamed(unnamed); | |
| 3221 | } else |_| {}; | |
| 3222 | if (std.meta.stringToEnum(String.Index, slice)) |index| { | |
| 3223 | pool.string_bytes.shrinkRetainingCapacity(start); | |
| 3224 | return .{ .index = index }; | |
| 3225 | } | |
| 3226 | ||
| 3227 | try pool.string_map.ensureUnusedCapacity(allocator, 1); | |
| 3228 | try pool.string_indices.ensureUnusedCapacity(allocator, 1); | |
| 3229 | ||
| 3230 | const gop = pool.string_map.getOrPutAssumeCapacityAdapted(slice, String.Adapter{ .pool = pool }); | |
| 3231 | if (gop.found_existing) | |
| 3232 | pool.string_bytes.shrinkRetainingCapacity(start) | |
| 3233 | else | |
| 3234 | pool.string_indices.appendAssumeCapacity(@intCast(pool.string_bytes.items.len)); | |
| 3235 | return String.fromPoolIndex(gop.index); | |
| 3236 | } | |
| 3237 | ||
| 3238 | const Item = struct { | |
| 3239 | tag: Pool.Tag, | |
| 3240 | data: u32, | |
| 3241 | }; | |
| 3242 | ||
| 3243 | const ExtraIndex = u32; | |
| 3244 | ||
| 3245 | const Tag = enum(u8) { | |
| 3246 | basic, | |
| 3247 | pointer, | |
| 3248 | pointer_const, | |
| 3249 | pointer_volatile, | |
| 3250 | pointer_const_volatile, | |
| 3251 | aligned, | |
| 3252 | array_small, | |
| 3253 | array_large, | |
| 3254 | vector, | |
| 3255 | nonstring, | |
| 3256 | fwd_decl_struct_anon, | |
| 3257 | fwd_decl_union_anon, | |
| 3258 | fwd_decl_struct, | |
| 3259 | fwd_decl_union, | |
| 3260 | aggregate_struct_anon, | |
| 3261 | aggregate_struct_packed_anon, | |
| 3262 | aggregate_union_anon, | |
| 3263 | aggregate_union_packed_anon, | |
| 3264 | aggregate_struct, | |
| 3265 | aggregate_struct_packed, | |
| 3266 | aggregate_union, | |
| 3267 | aggregate_union_packed, | |
| 3268 | function, | |
| 3269 | function_varargs, | |
| 3270 | }; | |
| 3271 | ||
| 3272 | const Aligned = struct { | |
| 3273 | ctype: CType.Index, | |
| 3274 | flags: Flags, | |
| 3275 | ||
| 3276 | const Flags = packed struct(u32) { | |
| 3277 | alignas: AlignAs, | |
| 3278 | _: u20 = 0, | |
| 3279 | }; | |
| 3280 | }; | |
| 3281 | ||
| 3282 | const SequenceSmall = struct { | |
| 3283 | elem_ctype: CType.Index, | |
| 3284 | len: u32, | |
| 3285 | }; | |
| 3286 | ||
| 3287 | const SequenceLarge = struct { | |
| 3288 | elem_ctype: CType.Index, | |
| 3289 | len_lo: u32, | |
| 3290 | len_hi: u32, | |
| 3291 | ||
| 3292 | fn len(extra: SequenceLarge) u64 { | |
| 3293 | return @as(u64, extra.len_lo) << 0 | | |
| 3294 | @as(u64, extra.len_hi) << 32; | |
| 3295 | } | |
| 3296 | }; | |
| 3297 | ||
| 3298 | const Field = struct { | |
| 3299 | name: String.Index, | |
| 3300 | ctype: CType.Index, | |
| 3301 | flags: Flags, | |
| 3302 | ||
| 3303 | const Flags = Aligned.Flags; | |
| 3304 | }; | |
| 3305 | ||
| 3306 | const FwdDeclAnon = struct { | |
| 3307 | fields_len: u32, | |
| 3308 | }; | |
| 3309 | ||
| 3310 | const AggregateAnon = struct { | |
| 3311 | index: InternPool.Index, | |
| 3312 | id: u32, | |
| 3313 | fields_len: u32, | |
| 3314 | }; | |
| 3315 | ||
| 3316 | const Aggregate = struct { | |
| 3317 | fwd_decl: CType.Index, | |
| 3318 | fields_len: u32, | |
| 3319 | }; | |
| 3320 | ||
| 3321 | const Function = struct { | |
| 3322 | return_ctype: CType.Index, | |
| 3323 | param_ctypes_len: u32, | |
| 3324 | }; | |
| 3325 | ||
| 3326 | fn addExtra( | |
| 3327 | pool: *Pool, | |
| 3328 | allocator: std.mem.Allocator, | |
| 3329 | comptime Extra: type, | |
| 3330 | extra: Extra, | |
| 3331 | trailing_len: usize, | |
| 3332 | ) !ExtraIndex { | |
| 3333 | try pool.extra.ensureUnusedCapacity( | |
| 3334 | allocator, | |
| 3335 | @typeInfo(Extra).@"struct".fields.len + trailing_len, | |
| 3336 | ); | |
| 3337 | defer pool.addExtraAssumeCapacity(Extra, extra); | |
| 3338 | return @intCast(pool.extra.items.len); | |
| 3339 | } | |
| 3340 | fn addExtraAssumeCapacity(pool: *Pool, comptime Extra: type, extra: Extra) void { | |
| 3341 | addExtraAssumeCapacityTo(&pool.extra, Extra, extra); | |
| 3342 | } | |
| 3343 | fn addExtraAssumeCapacityTo( | |
| 3344 | array: *std.ArrayList(u32), | |
| 3345 | comptime Extra: type, | |
| 3346 | extra: Extra, | |
| 3347 | ) void { | |
| 3348 | inline for (@typeInfo(Extra).@"struct".fields) |field| { | |
| 3349 | const value = @field(extra, field.name); | |
| 3350 | array.appendAssumeCapacity(switch (field.type) { | |
| 3351 | u32 => value, | |
| 3352 | CType.Index, String.Index, InternPool.Index => @intFromEnum(value), | |
| 3353 | Aligned.Flags => @bitCast(value), | |
| 3354 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ | |
| 3355 | @typeName(field.type)), | |
| 3356 | }); | |
| 3357 | } | |
| 3358 | } | |
| 3359 | ||
| 3360 | fn addHashedExtra( | |
| 3361 | pool: *Pool, | |
| 3362 | allocator: std.mem.Allocator, | |
| 3363 | hasher: *Hasher, | |
| 3364 | comptime Extra: type, | |
| 3365 | extra: Extra, | |
| 3366 | trailing_len: usize, | |
| 3367 | ) !ExtraIndex { | |
| 3368 | hasher.updateExtra(Extra, extra, pool); | |
| 3369 | return pool.addExtra(allocator, Extra, extra, trailing_len); | |
| 3370 | } | |
| 3371 | fn addHashedExtraAssumeCapacity( | |
| 3372 | pool: *Pool, | |
| 3373 | hasher: *Hasher, | |
| 3374 | comptime Extra: type, | |
| 3375 | extra: Extra, | |
| 3376 | ) void { | |
| 3377 | hasher.updateExtra(Extra, extra, pool); | |
| 3378 | pool.addExtraAssumeCapacity(Extra, extra); | |
| 3379 | } | |
| 3380 | fn addHashedExtraAssumeCapacityTo( | |
| 3381 | pool: *Pool, | |
| 3382 | array: *std.ArrayList(u32), | |
| 3383 | hasher: *Hasher, | |
| 3384 | comptime Extra: type, | |
| 3385 | extra: Extra, | |
| 3386 | ) void { | |
| 3387 | hasher.updateExtra(Extra, extra, pool); | |
| 3388 | addExtraAssumeCapacityTo(array, Extra, extra); | |
| 3389 | } | |
| 3390 | ||
| 3391 | const ExtraTrail = struct { | |
| 3392 | extra_index: ExtraIndex, | |
| 3393 | ||
| 3394 | fn next( | |
| 3395 | extra_trail: *ExtraTrail, | |
| 3396 | len: u32, | |
| 3397 | comptime Extra: type, | |
| 3398 | pool: *const Pool, | |
| 3399 | ) []const Extra { | |
| 3400 | defer extra_trail.extra_index += @intCast(len); | |
| 3401 | return @ptrCast(pool.extra.items[extra_trail.extra_index..][0..len]); | |
| 3402 | } | |
| 3403 | }; | |
| 3404 | ||
| 3405 | fn getExtraTrail( | |
| 3406 | pool: *const Pool, | |
| 3407 | comptime Extra: type, | |
| 3408 | extra_index: ExtraIndex, | |
| 3409 | ) struct { extra: Extra, trail: ExtraTrail } { | |
| 3410 | var extra: Extra = undefined; | |
| 3411 | const fields = @typeInfo(Extra).@"struct".fields; | |
| 3412 | inline for (fields, pool.extra.items[extra_index..][0..fields.len]) |field, value| | |
| 3413 | @field(extra, field.name) = switch (field.type) { | |
| 3414 | u32 => value, | |
| 3415 | CType.Index, String.Index, InternPool.Index => @enumFromInt(value), | |
| 3416 | Aligned.Flags => @bitCast(value), | |
| 3417 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | |
| 3418 | }; | |
| 3419 | return .{ | |
| 3420 | .extra = extra, | |
| 3421 | .trail = .{ .extra_index = extra_index + @as(ExtraIndex, @intCast(fields.len)) }, | |
| 3422 | }; | |
| 3423 | } | |
| 3424 | ||
| 3425 | fn getExtra(pool: *const Pool, comptime Extra: type, extra_index: ExtraIndex) Extra { | |
| 3426 | return pool.getExtraTrail(Extra, extra_index).extra; | |
| 3427 | } | |
| 3428 | }; | |
| 3429 | ||
| 3430 | pub const AlignAs = packed struct { | |
| 3431 | @"align": InternPool.Alignment, | |
| 3432 | abi: InternPool.Alignment, | |
| 3433 | ||
| 3434 | pub fn fromAlignment(alignas: AlignAs) AlignAs { | |
| 3435 | assert(alignas.abi != .none); | |
| 3436 | return .{ | |
| 3437 | .@"align" = if (alignas.@"align" != .none) alignas.@"align" else alignas.abi, | |
| 3438 | .abi = alignas.abi, | |
| 3439 | }; | |
| 3440 | } | |
| 3441 | pub fn fromAbiAlignment(abi: InternPool.Alignment) AlignAs { | |
| 3442 | assert(abi != .none); | |
| 3443 | return .{ .@"align" = abi, .abi = abi }; | |
| 3444 | } | |
| 3445 | pub fn fromByteUnits(@"align": u64, abi: u64) AlignAs { | |
| 3446 | return fromAlignment(.{ | |
| 3447 | .@"align" = InternPool.Alignment.fromByteUnits(@"align"), | |
| 3448 | .abi = InternPool.Alignment.fromNonzeroByteUnits(abi), | |
| 3449 | }); | |
| 3450 | } | |
| 3451 | ||
| 3452 | pub fn order(lhs: AlignAs, rhs: AlignAs) std.math.Order { | |
| 3453 | return lhs.@"align".order(rhs.@"align"); | |
| 3454 | } | |
| 3455 | pub fn abiOrder(alignas: AlignAs) std.math.Order { | |
| 3456 | return alignas.@"align".order(alignas.abi); | |
| 3457 | } | |
| 3458 | pub fn toByteUnits(alignas: AlignAs) u64 { | |
| 3459 | return alignas.@"align".toByteUnits().?; | |
| 3460 | } | |
| 3461 | }; | |
| 3462 | ||
| 3463 | const std = @import("std"); | |
| 3464 | const assert = std.debug.assert; | |
| 3465 | const Writer = std.Io.Writer; | |
| 3466 | ||
| 3467 | const CType = @This(); | |
| 3468 | const InternPool = @import("../../InternPool.zig"); | |
| 3469 | const Module = @import("../../Package/Module.zig"); | |
| 3470 | const Type = @import("../../Type.zig"); | |
| 3471 | const Value = @import("../../Value.zig"); | |
| 3472 | const Zcu = @import("../../Zcu.zig"); |
src/codegen/c/type.zig created+1023| ... | ... | @@ -0,0 +1,1023 @@ |
| 1 | pub const CType = union(enum) { | |
| 2 | pub const render_defs = @import("type/render_defs.zig"); | |
| 3 | ||
| 4 | // The first nodes are primitive types (or standard typedefs). | |
| 5 | ||
| 6 | void, | |
| 7 | bool, | |
| 8 | int: Int, | |
| 9 | float: Float, | |
| 10 | ||
| 11 | // These next nodes are all typedefs, structs, or unions. | |
| 12 | ||
| 13 | @"fn": Type, | |
| 14 | @"enum": Type, | |
| 15 | bitpack: Type, | |
| 16 | @"struct": Type, | |
| 17 | union_auto: Type, | |
| 18 | union_extern: Type, | |
| 19 | slice: Type, | |
| 20 | opt: Type, | |
| 21 | arr: Type, | |
| 22 | vec: Type, | |
| 23 | errunion: struct { payload_ty: Type }, | |
| 24 | aligned: struct { | |
| 25 | ty: Type, | |
| 26 | alignment: InternPool.Alignment, | |
| 27 | }, | |
| 28 | bigint: BigInt, | |
| 29 | ||
| 30 | // The remaining nodes have children. | |
| 31 | ||
| 32 | pointer: struct { | |
| 33 | @"const": bool, | |
| 34 | @"volatile": bool, | |
| 35 | elem_ty: *const CType, | |
| 36 | nonstring: bool, | |
| 37 | }, | |
| 38 | array: struct { | |
| 39 | len: u64, | |
| 40 | elem_ty: *const CType, | |
| 41 | nonstring: bool, | |
| 42 | }, | |
| 43 | function: struct { | |
| 44 | param_tys: []const CType, | |
| 45 | ret_ty: *const CType, | |
| 46 | varargs: bool, | |
| 47 | }, | |
| 48 | ||
| 49 | /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears | |
| 50 | /// after the identifier in a declarator with this type. In this case, if this node is wrapped | |
| 51 | /// in a pointer type, we will need to add parentheses due to operator precedence. | |
| 52 | /// | |
| 53 | /// For instance, when lowering a Zig declaration `foo: *const fn (c_int) void`, it would be a | |
| 54 | /// bug to write the C declarator as `void *foo(int)`, because the `(int)` suffix declaring the | |
| 55 | /// function type has higher precedence than the `*` prefix declaring the pointer type. Instead, | |
| 56 | /// this type must be lowered as `void (*foo)(int)`. | |
| 57 | fn kind(cty: *const CType) enum { | |
| 58 | /// `cty` is just a C type specifier, i.e. a typedef or a named struct/union type. | |
| 59 | specifier, | |
| 60 | /// `cty` is a C function or array type. It will have a postfix "operator" in its suffix to | |
| 61 | /// declare the type, either `(...)` (for a function type) or `[...]` (for an array type). | |
| 62 | postfix_op, | |
| 63 | /// `cty` is a C pointer type. Its prefix will end with "*". | |
| 64 | pointer, | |
| 65 | } { | |
| 66 | return switch (cty.*) { | |
| 67 | .void, | |
| 68 | .bool, | |
| 69 | .int, | |
| 70 | .float, | |
| 71 | .@"fn", | |
| 72 | .@"enum", | |
| 73 | .bitpack, | |
| 74 | .@"struct", | |
| 75 | .union_auto, | |
| 76 | .union_extern, | |
| 77 | .slice, | |
| 78 | .opt, | |
| 79 | .arr, | |
| 80 | .vec, | |
| 81 | .errunion, | |
| 82 | .aligned, | |
| 83 | .bigint, | |
| 84 | => .specifier, | |
| 85 | ||
| 86 | .array, | |
| 87 | .function, | |
| 88 | => .postfix_op, | |
| 89 | ||
| 90 | .pointer => .pointer, | |
| 91 | }; | |
| 92 | } | |
| 93 | ||
| 94 | pub const Int = enum { | |
| 95 | char, | |
| 96 | ||
| 97 | @"unsigned short", | |
| 98 | @"unsigned int", | |
| 99 | @"unsigned long", | |
| 100 | @"unsigned long long", | |
| 101 | ||
| 102 | @"signed short", | |
| 103 | @"signed int", | |
| 104 | @"signed long", | |
| 105 | @"signed long long", | |
| 106 | ||
| 107 | uint8_t, | |
| 108 | uint16_t, | |
| 109 | uint32_t, | |
| 110 | uint64_t, | |
| 111 | zig_u128, | |
| 112 | ||
| 113 | int8_t, | |
| 114 | int16_t, | |
| 115 | int32_t, | |
| 116 | int64_t, | |
| 117 | zig_i128, | |
| 118 | ||
| 119 | uintptr_t, | |
| 120 | intptr_t, | |
| 121 | ||
| 122 | pub fn bits(int: Int, target: *const std.Target) u16 { | |
| 123 | return switch (int) { | |
| 124 | // zig fmt: off | |
| 125 | .char => target.cTypeBitSize(.char), | |
| 126 | ||
| 127 | .@"unsigned short" => target.cTypeBitSize(.ushort), | |
| 128 | .@"unsigned int" => target.cTypeBitSize(.uint), | |
| 129 | .@"unsigned long" => target.cTypeBitSize(.ulong), | |
| 130 | .@"unsigned long long" => target.cTypeBitSize(.ulonglong), | |
| 131 | ||
| 132 | .@"signed short" => target.cTypeBitSize(.short), | |
| 133 | .@"signed int" => target.cTypeBitSize(.int), | |
| 134 | .@"signed long" => target.cTypeBitSize(.long), | |
| 135 | .@"signed long long" => target.cTypeBitSize(.longlong), | |
| 136 | ||
| 137 | .uintptr_t, .intptr_t => target.ptrBitWidth(), | |
| 138 | ||
| 139 | .uint8_t, .int8_t => 8, | |
| 140 | .uint16_t, .int16_t => 16, | |
| 141 | .uint32_t, .int32_t => 32, | |
| 142 | .uint64_t, .int64_t => 64, | |
| 143 | .zig_u128, .zig_i128 => 128, | |
| 144 | // zig fmt: on | |
| 145 | }; | |
| 146 | } | |
| 147 | }; | |
| 148 | ||
| 149 | pub const BigInt = struct { | |
| 150 | limb_size: LimbSize, | |
| 151 | /// Always greater than 1. | |
| 152 | limbs_len: u16, | |
| 153 | ||
| 154 | pub const LimbSize = enum { | |
| 155 | @"8", | |
| 156 | @"16", | |
| 157 | @"32", | |
| 158 | @"64", | |
| 159 | @"128", | |
| 160 | pub fn bits(s: LimbSize) u8 { | |
| 161 | return switch (s) { | |
| 162 | .@"8" => 8, | |
| 163 | .@"16" => 16, | |
| 164 | .@"32" => 32, | |
| 165 | .@"64" => 64, | |
| 166 | .@"128" => 128, | |
| 167 | }; | |
| 168 | } | |
| 169 | pub fn unsigned(s: LimbSize) Int { | |
| 170 | return switch (s) { | |
| 171 | .@"8" => .uint8_t, | |
| 172 | .@"16" => .uint16_t, | |
| 173 | .@"32" => .uint32_t, | |
| 174 | .@"64" => .uint64_t, | |
| 175 | .@"128" => .zig_u128, | |
| 176 | }; | |
| 177 | } | |
| 178 | pub fn signed(s: LimbSize) Int { | |
| 179 | return switch (s) { | |
| 180 | .@"8" => .int8_t, | |
| 181 | .@"16" => .int16_t, | |
| 182 | .@"32" => .int32_t, | |
| 183 | .@"64" => .int64_t, | |
| 184 | .@"128" => .zig_i128, | |
| 185 | }; | |
| 186 | } | |
| 187 | }; | |
| 188 | }; | |
| 189 | ||
| 190 | pub const Float = enum { | |
| 191 | @"long double", | |
| 192 | zig_f16, | |
| 193 | zig_f32, | |
| 194 | zig_f64, | |
| 195 | zig_f80, | |
| 196 | zig_f128, | |
| 197 | zig_u128, | |
| 198 | zig_i128, | |
| 199 | }; | |
| 200 | ||
| 201 | pub fn isStringElem(cty: CType) bool { | |
| 202 | return switch (cty) { | |
| 203 | .int => |int| switch (int) { | |
| 204 | .char, .int8_t, .uint8_t => true, | |
| 205 | else => false, | |
| 206 | }, | |
| 207 | else => false, | |
| 208 | }; | |
| 209 | } | |
| 210 | ||
| 211 | pub fn lower( | |
| 212 | ty: Type, | |
| 213 | deps: *Dependencies, | |
| 214 | arena: Allocator, | |
| 215 | zcu: *const Zcu, | |
| 216 | ) Allocator.Error!CType { | |
| 217 | return lowerInner(ty, false, deps, arena, zcu); | |
| 218 | } | |
| 219 | fn lowerInner( | |
| 220 | start_ty: Type, | |
| 221 | allow_incomplete: bool, | |
| 222 | deps: *Dependencies, | |
| 223 | arena: Allocator, | |
| 224 | zcu: *const Zcu, | |
| 225 | ) Allocator.Error!CType { | |
| 226 | const gpa = zcu.comp.gpa; | |
| 227 | const ip = &zcu.intern_pool; | |
| 228 | var cur_ty = start_ty; | |
| 229 | while (true) { | |
| 230 | switch (cur_ty.zigTypeTag(zcu)) { | |
| 231 | .type, | |
| 232 | .comptime_int, | |
| 233 | .comptime_float, | |
| 234 | .undefined, | |
| 235 | .null, | |
| 236 | .enum_literal, | |
| 237 | .@"opaque", | |
| 238 | .noreturn, | |
| 239 | .void, | |
| 240 | => return .void, | |
| 241 | ||
| 242 | .bool => return .bool, | |
| 243 | ||
| 244 | .int, .error_set => switch (classifyInt(cur_ty, zcu)) { | |
| 245 | .void => return .void, | |
| 246 | .small => |s| return .{ .int = s }, | |
| 247 | .big => |big| { | |
| 248 | try deps.bigint.put(gpa, big, {}); | |
| 249 | return .{ .bigint = big }; | |
| 250 | }, | |
| 251 | }, | |
| 252 | ||
| 253 | .float => return .{ .float = switch (cur_ty.toIntern()) { | |
| 254 | .c_longdouble_type => .@"long double", | |
| 255 | .f16_type => .zig_f16, | |
| 256 | .f32_type => .zig_f32, | |
| 257 | .f64_type => .zig_f64, | |
| 258 | .f80_type => .zig_f80, | |
| 259 | .f128_type => .zig_f128, | |
| 260 | else => unreachable, | |
| 261 | } }, | |
| 262 | .vector => { | |
| 263 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 264 | return .{ .vec = cur_ty }; | |
| 265 | }, | |
| 266 | .array => { | |
| 267 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 268 | return .{ .arr = cur_ty }; | |
| 269 | }, | |
| 270 | ||
| 271 | .pointer => { | |
| 272 | const ptr = cur_ty.ptrInfo(zcu); | |
| 273 | switch (ptr.flags.size) { | |
| 274 | .slice => { | |
| 275 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 276 | return .{ .slice = cur_ty }; | |
| 277 | }, | |
| 278 | .one, .many, .c => { | |
| 279 | const elem_ty: Type = .fromInterned(ptr.child); | |
| 280 | const is_fn_ptr = elem_ty.zigTypeTag(zcu) == .@"fn"; | |
| 281 | const elem_cty: CType = elem_cty: { | |
| 282 | if (ptr.packed_offset.host_size > 0 and ptr.flags.vector_index == .none) { | |
| 283 | switch (classifyBitInt(.unsigned, ptr.packed_offset.host_size * 8, zcu)) { | |
| 284 | .void => break :elem_cty .void, | |
| 285 | .small => |s| break :elem_cty .{ .int = s }, | |
| 286 | .big => |big| { | |
| 287 | try deps.bigint.put(gpa, big, {}); | |
| 288 | break :elem_cty .{ .bigint = big }; | |
| 289 | }, | |
| 290 | } | |
| 291 | } | |
| 292 | if (ptr.flags.alignment != .none and !is_fn_ptr) { | |
| 293 | // The pointer has an explicit alignment---if it's an underalignment | |
| 294 | // then we need to use an "aligned" typedef. | |
| 295 | const ptr_align = ptr.flags.alignment; | |
| 296 | if (!alwaysHasLayout(elem_ty, ip) or | |
| 297 | ptr_align.compareStrict(.lt, elem_ty.abiAlignment(zcu))) | |
| 298 | { | |
| 299 | const gop = try deps.aligned_type_fwd.getOrPut(gpa, elem_ty.toIntern()); | |
| 300 | if (!gop.found_existing) gop.value_ptr.* = 0; | |
| 301 | gop.value_ptr.* |= @as(u64, 1) << ptr_align.toLog2Units(); | |
| 302 | break :elem_cty .{ .aligned = .{ | |
| 303 | .ty = elem_ty, | |
| 304 | .alignment = ptr_align, | |
| 305 | } }; | |
| 306 | } | |
| 307 | } | |
| 308 | break :elem_cty try .lowerInner(elem_ty, true, deps, arena, zcu); | |
| 309 | }; | |
| 310 | const elem_cty_buf = try arena.create(CType); | |
| 311 | elem_cty_buf.* = elem_cty; | |
| 312 | return .{ .pointer = .{ | |
| 313 | .@"const" = ptr.flags.is_const and !is_fn_ptr, | |
| 314 | .@"volatile" = ptr.flags.is_volatile and !is_fn_ptr, | |
| 315 | .elem_ty = elem_cty_buf, | |
| 316 | .nonstring = nonstring: { | |
| 317 | if (!elem_cty.isStringElem()) break :nonstring false; | |
| 318 | if (ptr.sentinel == .none) break :nonstring true; | |
| 319 | break :nonstring Value.compareHetero( | |
| 320 | .fromInterned(ptr.sentinel), | |
| 321 | .neq, | |
| 322 | .zero_comptime_int, | |
| 323 | zcu, | |
| 324 | ); | |
| 325 | }, | |
| 326 | } }; | |
| 327 | }, | |
| 328 | } | |
| 329 | }, | |
| 330 | ||
| 331 | .@"fn" => { | |
| 332 | const func_type = ip.indexToKey(cur_ty.toIntern()).func_type; | |
| 333 | direct: { | |
| 334 | const ret_ty: Type = .fromInterned(func_type.return_type); | |
| 335 | if (!alwaysHasLayout(ret_ty, ip)) break :direct; | |
| 336 | var params_len: usize = 0; // only counts parameter types with runtime bits | |
| 337 | for (func_type.param_types.get(ip)) |param_ty_ip| { | |
| 338 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 339 | if (!alwaysHasLayout(param_ty, ip)) break :direct; | |
| 340 | if (param_ty.hasRuntimeBits(zcu)) params_len += 1; | |
| 341 | } | |
| 342 | // We can actually write this function type directly! | |
| 343 | if (!cur_ty.fnHasRuntimeBits(zcu)) return .void; | |
| 344 | const ret_cty_buf = try arena.create(CType); | |
| 345 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 346 | // Incomplete function return types must always be `void`. | |
| 347 | ret_cty_buf.* = .void; | |
| 348 | } else { | |
| 349 | ret_cty_buf.* = try .lowerInner(ret_ty, allow_incomplete, deps, arena, zcu); | |
| 350 | } | |
| 351 | const param_cty_buf = try arena.alloc(CType, params_len); | |
| 352 | var param_index: usize = 0; | |
| 353 | for (func_type.param_types.get(ip)) |param_ty_ip| { | |
| 354 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 355 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 356 | param_cty_buf[param_index] = try .lowerInner(param_ty, allow_incomplete, deps, arena, zcu); | |
| 357 | param_index += 1; | |
| 358 | } | |
| 359 | assert(param_index == params_len); | |
| 360 | return .{ .function = .{ | |
| 361 | .ret_ty = ret_cty_buf, | |
| 362 | .param_tys = param_cty_buf, | |
| 363 | .varargs = func_type.is_var_args, | |
| 364 | } }; | |
| 365 | } | |
| 366 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 367 | return .{ .@"fn" = cur_ty }; | |
| 368 | }, | |
| 369 | ||
| 370 | .@"struct" => { | |
| 371 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 372 | switch (cur_ty.containerLayout(zcu)) { | |
| 373 | .auto, .@"extern" => return .{ .@"struct" = cur_ty }, | |
| 374 | .@"packed" => return .{ .bitpack = cur_ty }, | |
| 375 | } | |
| 376 | }, | |
| 377 | .@"union" => { | |
| 378 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 379 | switch (cur_ty.containerLayout(zcu)) { | |
| 380 | .auto => return .{ .union_auto = cur_ty }, | |
| 381 | .@"extern" => return .{ .union_extern = cur_ty }, | |
| 382 | .@"packed" => return .{ .bitpack = cur_ty }, | |
| 383 | } | |
| 384 | }, | |
| 385 | .@"enum" => { | |
| 386 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 387 | return .{ .@"enum" = cur_ty }; | |
| 388 | }, | |
| 389 | ||
| 390 | .optional => { | |
| 391 | // This query does not require any type resolution. | |
| 392 | if (cur_ty.optionalReprIsPayload(zcu)) { | |
| 393 | // Either a pointer-like optional, or an optional error set. Just lower the payload. | |
| 394 | cur_ty = cur_ty.optionalChild(zcu); | |
| 395 | continue; | |
| 396 | } | |
| 397 | if (alwaysHasLayout(cur_ty, ip)) switch (classifyOptional(cur_ty, zcu)) { | |
| 398 | .error_set, .ptr_like, .slice_like => unreachable, // handled above | |
| 399 | .npv_payload => return .void, | |
| 400 | .opv_payload, .@"struct" => {}, | |
| 401 | }; | |
| 402 | try deps.addType(gpa, cur_ty, allow_incomplete); | |
| 403 | return .{ .opt = cur_ty }; | |
| 404 | }, | |
| 405 | ||
| 406 | .error_union => { | |
| 407 | const payload_ty = cur_ty.errorUnionPayload(zcu); | |
| 408 | if (allow_incomplete) { | |
| 409 | try deps.errunion_type_fwd.put(gpa, payload_ty.toIntern(), {}); | |
| 410 | } else { | |
| 411 | try deps.errunion_type.put(gpa, payload_ty.toIntern(), {}); | |
| 412 | } | |
| 413 | return .{ .errunion = .{ | |
| 414 | .payload_ty = payload_ty, | |
| 415 | } }; | |
| 416 | }, | |
| 417 | ||
| 418 | .frame, | |
| 419 | .@"anyframe", | |
| 420 | => unreachable, | |
| 421 | } | |
| 422 | comptime unreachable; | |
| 423 | } | |
| 424 | } | |
| 425 | ||
| 426 | pub fn classifyOptional(opt_ty: Type, zcu: *const Zcu) enum { | |
| 427 | /// The optional is something like `?noreturn`; it lowers to `void`. | |
| 428 | npv_payload, | |
| 429 | /// The payload type is an error set; the representation matches that of the error set, with | |
| 430 | /// the value 0 representing `null`. | |
| 431 | error_set, | |
| 432 | /// The payload type is a non-optional pointer; the NULL pointer is used for `null`. | |
| 433 | ptr_like, | |
| 434 | /// The payload type is a non-optional slice; a NULL pointer field is used for `null`. | |
| 435 | slice_like, | |
| 436 | /// The optional is something like `?void`; it lowers to a struct, but one containing only | |
| 437 | /// one field `is_null` (the payload is omitted). | |
| 438 | opv_payload, | |
| 439 | /// The optional uses the "default" lowering of a struct with two fields, like this: | |
| 440 | /// struct optional_1234 { payload_ty payload; bool is_null; } | |
| 441 | @"struct", | |
| 442 | } { | |
| 443 | const payload_ty = opt_ty.optionalChild(zcu); | |
| 444 | if (opt_ty.optionalReprIsPayload(zcu)) { | |
| 445 | return switch (payload_ty.zigTypeTag(zcu)) { | |
| 446 | .error_set => .error_set, | |
| 447 | .pointer => if (payload_ty.isSlice(zcu)) .slice_like else .ptr_like, | |
| 448 | else => unreachable, | |
| 449 | }; | |
| 450 | } else { | |
| 451 | return switch (payload_ty.classify(zcu)) { | |
| 452 | .no_possible_value => .npv_payload, | |
| 453 | .one_possible_value => .opv_payload, | |
| 454 | else => .@"struct", | |
| 455 | }; | |
| 456 | } | |
| 457 | } | |
| 458 | ||
| 459 | pub const IntClass = union(enum) { | |
| 460 | /// The integer type is zero-bit, so lowers to `void`. | |
| 461 | void, | |
| 462 | /// The integer is under 128 bits long, so lowers to this C integer type. | |
| 463 | small: Int, | |
| 464 | /// The integer is over 128 bits long, so lowers to an array of limbs. | |
| 465 | big: BigInt, | |
| 466 | }; | |
| 467 | ||
| 468 | /// Asserts that `ty` is an integer, enum, bitpack, or error set. | |
| 469 | pub fn classifyInt(ty: Type, zcu: *const Zcu) IntClass { | |
| 470 | const int_ty: Type = switch (ty.zigTypeTag(zcu)) { | |
| 471 | .error_set => return classifyBitInt(.unsigned, zcu.errorSetBits(), zcu), | |
| 472 | .@"enum" => ty.intTagType(zcu), | |
| 473 | .@"struct", .@"union" => ty.bitpackBackingInt(zcu), | |
| 474 | .int => ty, | |
| 475 | else => unreachable, | |
| 476 | }; | |
| 477 | switch (int_ty.toIntern()) { | |
| 478 | // zig fmt: off | |
| 479 | .usize_type => return .{ .small = .uintptr_t }, | |
| 480 | .isize_type => return .{ .small = .intptr_t }, | |
| 481 | ||
| 482 | .c_char_type => return .{ .small = .char }, | |
| 483 | ||
| 484 | .c_short_type => return .{ .small = .@"signed short" }, | |
| 485 | .c_int_type => return .{ .small = .@"signed int" }, | |
| 486 | .c_long_type => return .{ .small = .@"signed long" }, | |
| 487 | .c_longlong_type => return .{ .small = .@"signed long long" }, | |
| 488 | ||
| 489 | .c_ushort_type => return .{ .small = .@"unsigned short" }, | |
| 490 | .c_uint_type => return .{ .small = .@"unsigned int" }, | |
| 491 | .c_ulong_type => return .{ .small = .@"unsigned long" }, | |
| 492 | .c_ulonglong_type => return .{ .small = .@"unsigned long long" }, | |
| 493 | // zig fmt: on | |
| 494 | ||
| 495 | else => { | |
| 496 | const int = ty.intInfo(zcu); | |
| 497 | return classifyBitInt(int.signedness, int.bits, zcu); | |
| 498 | }, | |
| 499 | } | |
| 500 | } | |
| 501 | fn classifyBitInt(signedness: std.builtin.Signedness, bits: u16, zcu: *const Zcu) IntClass { | |
| 502 | return switch (bits) { | |
| 503 | 0 => .void, | |
| 504 | 1...8 => switch (signedness) { | |
| 505 | .unsigned => .{ .small = .uint8_t }, | |
| 506 | .signed => .{ .small = .int8_t }, | |
| 507 | }, | |
| 508 | 9...16 => switch (signedness) { | |
| 509 | .unsigned => .{ .small = .uint16_t }, | |
| 510 | .signed => .{ .small = .int16_t }, | |
| 511 | }, | |
| 512 | 17...32 => switch (signedness) { | |
| 513 | .unsigned => .{ .small = .uint32_t }, | |
| 514 | .signed => .{ .small = .int32_t }, | |
| 515 | }, | |
| 516 | 33...64 => switch (signedness) { | |
| 517 | .unsigned => .{ .small = .uint64_t }, | |
| 518 | .signed => .{ .small = .int64_t }, | |
| 519 | }, | |
| 520 | 65...128 => switch (signedness) { | |
| 521 | .unsigned => .{ .small = .zig_u128 }, | |
| 522 | .signed => .{ .small = .zig_i128 }, | |
| 523 | }, | |
| 524 | else => { | |
| 525 | @branchHint(.unlikely); | |
| 526 | const target = zcu.getTarget(); | |
| 527 | const limb_bytes = std.zig.target.intAlignment(target, bits); | |
| 528 | return .{ .big = .{ | |
| 529 | .limb_size = switch (limb_bytes) { | |
| 530 | 1 => .@"8", | |
| 531 | 2 => .@"16", | |
| 532 | 4 => .@"32", | |
| 533 | 8 => .@"64", | |
| 534 | 16 => .@"128", | |
| 535 | else => unreachable, | |
| 536 | }, | |
| 537 | .limbs_len = @divExact( | |
| 538 | std.zig.target.intByteSize(target, bits), | |
| 539 | limb_bytes, | |
| 540 | ), | |
| 541 | } }; | |
| 542 | }, | |
| 543 | }; | |
| 544 | } | |
| 545 | ||
| 546 | /// Describes a set of types which must be declared or completed in the C source file before | |
| 547 | /// some string of rendered C code (such as a function), due to said C code using these types. | |
| 548 | pub const Dependencies = struct { | |
| 549 | /// Key is any Zig type which corresponds to a C `struct`, `union`, or `typedef`. That C | |
| 550 | /// type must be declared and complete. | |
| 551 | type: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 552 | ||
| 553 | /// Key is a Zig type which is the *payload* of an error union. The C `struct` type | |
| 554 | /// corresponding to such an error union must be declared and complete. | |
| 555 | /// | |
| 556 | /// These are separate from `type` to avoid redundant types for every different error set | |
| 557 | /// used with the same payload type---for instance a different C type for every `E!void`. | |
| 558 | errunion_type: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 559 | ||
| 560 | /// Like `type`, but the type does not necessarily need to be completed yet: a forward | |
| 561 | /// declaration is sufficient. | |
| 562 | type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 563 | ||
| 564 | /// Like `errunion_type`, but the type does not necessarily need to be completed yet: a | |
| 565 | /// forward declaration is sufficient. | |
| 566 | errunion_type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 567 | ||
| 568 | /// Key is a Zig type; value is a bitmask of alignments. For every bit which is set, an | |
| 569 | /// aligned typedef is required. For instance, if bit 3 is set, the C type 'aligned__8_foo' | |
| 570 | /// must be declared through `typedef` (but not necessarily completed yet). | |
| 571 | aligned_type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, u64), | |
| 572 | ||
| 573 | /// Key specifies a big-int type whose C `struct` must be declared and complete. | |
| 574 | bigint: std.AutoArrayHashMapUnmanaged(BigInt, void), | |
| 575 | ||
| 576 | pub const empty: Dependencies = .{ | |
| 577 | .type = .empty, | |
| 578 | .errunion_type = .empty, | |
| 579 | .type_fwd = .empty, | |
| 580 | .errunion_type_fwd = .empty, | |
| 581 | .aligned_type_fwd = .empty, | |
| 582 | .bigint = .empty, | |
| 583 | }; | |
| 584 | ||
| 585 | pub fn deinit(deps: *Dependencies, gpa: Allocator) void { | |
| 586 | deps.type.deinit(gpa); | |
| 587 | deps.errunion_type.deinit(gpa); | |
| 588 | deps.type_fwd.deinit(gpa); | |
| 589 | deps.errunion_type_fwd.deinit(gpa); | |
| 590 | deps.aligned_type_fwd.deinit(gpa); | |
| 591 | deps.bigint.deinit(gpa); | |
| 592 | } | |
| 593 | ||
| 594 | pub fn clearRetainingCapacity(deps: *Dependencies) void { | |
| 595 | deps.type.clearRetainingCapacity(); | |
| 596 | deps.errunion_type.clearRetainingCapacity(); | |
| 597 | deps.type_fwd.clearRetainingCapacity(); | |
| 598 | deps.errunion_type_fwd.clearRetainingCapacity(); | |
| 599 | deps.aligned_type_fwd.clearRetainingCapacity(); | |
| 600 | deps.bigint.clearRetainingCapacity(); | |
| 601 | } | |
| 602 | ||
| 603 | pub fn move(deps: *Dependencies) Dependencies { | |
| 604 | const moved = deps.*; | |
| 605 | deps.* = .empty; | |
| 606 | return moved; | |
| 607 | } | |
| 608 | ||
| 609 | fn addType(deps: *Dependencies, gpa: Allocator, ty: Type, allow_incomplete: bool) Allocator.Error!void { | |
| 610 | if (allow_incomplete) { | |
| 611 | try deps.type_fwd.put(gpa, ty.toIntern(), {}); | |
| 612 | } else { | |
| 613 | try deps.type.put(gpa, ty.toIntern(), {}); | |
| 614 | } | |
| 615 | } | |
| 616 | }; | |
| 617 | ||
| 618 | /// Formats the bytes which appear *before* the identifier in a declarator. This includes the | |
| 619 | /// type specifier and all "prefix type operators" in the declarator. e.g: | |
| 620 | /// * for the declarator "int foo", writes "int " | |
| 621 | /// * for the declarator "struct thing *foo", writes "struct thing *" | |
| 622 | /// * for the declarator "void *(*foo)(int)", writes "void *(*" | |
| 623 | pub fn fmtDeclaratorPrefix(cty: CType, zcu: *const Zcu) Formatter { | |
| 624 | return .{ | |
| 625 | .cty = cty, | |
| 626 | .zcu = zcu, | |
| 627 | .kind = .declarator_prefix, | |
| 628 | }; | |
| 629 | } | |
| 630 | /// Formats the bytes which appear *before* the identifier in a declarator. This includes the | |
| 631 | /// type specifier and all "prefix type operators" in the declarator. e.g: | |
| 632 | /// * for the declarator "int foo", writes "" | |
| 633 | /// * for the declarator "struct thing *foo", writes "" | |
| 634 | /// * for the declarator "void *(*foo)(int)", writes ")(int)" | |
| 635 | pub fn fmtDeclaratorSuffix(cty: CType, zcu: *const Zcu) Formatter { | |
| 636 | return .{ | |
| 637 | .cty = cty, | |
| 638 | .zcu = zcu, | |
| 639 | .kind = .declarator_suffix, | |
| 640 | }; | |
| 641 | } | |
| 642 | /// Like `fmtDeclaratorSuffix`, except never emits a `zig_nonstring` annotation. | |
| 643 | pub fn fmtDeclaratorSuffixIgnoreNonstring(cty: CType, zcu: *const Zcu) Formatter { | |
| 644 | return .{ | |
| 645 | .cty = cty, | |
| 646 | .zcu = zcu, | |
| 647 | .kind = .declarator_suffix_ignore_nonstring, | |
| 648 | }; | |
| 649 | } | |
| 650 | /// Formats a type's full name, e.g. "int", "struct foo *", "void *(uint32_t)". | |
| 651 | /// | |
| 652 | /// This is almost identical to `fmtDeclaratorPrefix` followed by `fmtDeclaratorSuffix`, but | |
| 653 | /// that sequence of calls may emit trailing whitespace where this one does not---for instance, | |
| 654 | /// those calls would write the type "void" as "void ". | |
| 655 | pub fn fmtTypeName(cty: CType, zcu: *const Zcu) Formatter { | |
| 656 | return .{ | |
| 657 | .cty = cty, | |
| 658 | .zcu = zcu, | |
| 659 | .kind = .type_name, | |
| 660 | }; | |
| 661 | } | |
| 662 | ||
| 663 | const Formatter = struct { | |
| 664 | cty: CType, | |
| 665 | zcu: *const Zcu, | |
| 666 | kind: enum { type_name, declarator_prefix, declarator_suffix, declarator_suffix_ignore_nonstring }, | |
| 667 | ||
| 668 | pub fn format(ctx: Formatter, w: *Writer) Writer.Error!void { | |
| 669 | switch (ctx.kind) { | |
| 670 | .type_name => { | |
| 671 | try ctx.cty.writeTypePrefix(w, ctx.zcu); | |
| 672 | try ctx.cty.writeTypeSuffix(w, ctx.zcu); | |
| 673 | }, | |
| 674 | .declarator_prefix => { | |
| 675 | try ctx.cty.writeTypePrefix(w, ctx.zcu); | |
| 676 | switch (ctx.cty.kind()) { | |
| 677 | .specifier => try w.writeByte(' '), // write "int " rather than "int" | |
| 678 | .pointer => {}, // we already have something like "foo *" | |
| 679 | .postfix_op => {}, // we already have something like "ret_ty " | |
| 680 | } | |
| 681 | }, | |
| 682 | .declarator_suffix => { | |
| 683 | try ctx.cty.writeTypeSuffix(w, ctx.zcu); | |
| 684 | const nonstring = switch (ctx.cty) { | |
| 685 | .array => |arr| arr.nonstring, | |
| 686 | .pointer => |ptr| ptr.nonstring, | |
| 687 | else => false, | |
| 688 | }; | |
| 689 | if (nonstring) try w.writeAll(" zig_nonstring"); | |
| 690 | }, | |
| 691 | .declarator_suffix_ignore_nonstring => { | |
| 692 | try ctx.cty.writeTypeSuffix(w, ctx.zcu); | |
| 693 | }, | |
| 694 | } | |
| 695 | } | |
| 696 | }; | |
| 697 | ||
| 698 | fn writeTypePrefix(cty: CType, w: *Writer, zcu: *const Zcu) Writer.Error!void { | |
| 699 | switch (cty) { | |
| 700 | .void => try w.writeAll("void"), | |
| 701 | .bool => try w.writeAll("bool"), | |
| 702 | .int => |int| try w.writeAll(@tagName(int)), | |
| 703 | .float => |float| try w.writeAll(@tagName(float)), | |
| 704 | .@"fn" => |ty| try w.print("{f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 705 | .@"enum" => |ty| try w.print("enum__{f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 706 | .bitpack => |ty| try w.print("bitpack__{f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 707 | .@"struct" => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 708 | .union_auto => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 709 | .union_extern => |ty| try w.print("union {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 710 | .slice => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 711 | .opt => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 712 | .arr => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 713 | .vec => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), | |
| 714 | .errunion => |eu| try w.print("struct errunion_{f}_{d}", .{ | |
| 715 | fmtZigType(eu.payload_ty, zcu), | |
| 716 | eu.payload_ty.toIntern(), | |
| 717 | }), | |
| 718 | .aligned => |aligned| try w.print("aligned__{d}_{f}_{d}", .{ | |
| 719 | aligned.alignment.toByteUnits().?, | |
| 720 | fmtZigType(aligned.ty, zcu), | |
| 721 | aligned.ty.toIntern(), | |
| 722 | }), | |
| 723 | .bigint => |bigint| try w.print("struct int_{d}x{d}", .{ | |
| 724 | bigint.limb_size.bits(), | |
| 725 | bigint.limbs_len, | |
| 726 | }), | |
| 727 | ||
| 728 | .pointer => |ptr| { | |
| 729 | try ptr.elem_ty.writeTypePrefix(w, zcu); | |
| 730 | switch (ptr.elem_ty.kind()) { | |
| 731 | .pointer, .postfix_op => {}, | |
| 732 | .specifier => { | |
| 733 | // We want "foo *" or "foo const *" rather than "foo*" or "fooconst *". | |
| 734 | try w.writeByte(' '); | |
| 735 | }, | |
| 736 | } | |
| 737 | if (ptr.@"const") try w.writeAll("const "); | |
| 738 | if (ptr.@"volatile") try w.writeAll("volatile "); | |
| 739 | switch (ptr.elem_ty.kind()) { | |
| 740 | .specifier, .pointer => {}, | |
| 741 | .postfix_op => { | |
| 742 | // Prefix "*" is lower precedence than postfix "(x)" or "[x]" so use parens | |
| 743 | // to disambiguate; e.g. "void (*foo)(int)" instead of "void *foo(int)". | |
| 744 | try w.writeByte('('); | |
| 745 | }, | |
| 746 | } | |
| 747 | try w.writeByte('*'); | |
| 748 | }, | |
| 749 | ||
| 750 | .array => |array| { | |
| 751 | try array.elem_ty.writeTypePrefix(w, zcu); | |
| 752 | switch (array.elem_ty.kind()) { | |
| 753 | .pointer, .postfix_op => {}, | |
| 754 | .specifier => { | |
| 755 | // We want e.g. "struct foo [5]" rather than "struct foo[5]". | |
| 756 | try w.writeByte(' '); | |
| 757 | }, | |
| 758 | } | |
| 759 | }, | |
| 760 | ||
| 761 | .function => |function| { | |
| 762 | try function.ret_ty.writeTypePrefix(w, zcu); | |
| 763 | switch (function.ret_ty.kind()) { | |
| 764 | .pointer, .postfix_op => {}, | |
| 765 | .specifier => { | |
| 766 | // We want e.g. "struct foo (void)" rather than "struct foo(void)". | |
| 767 | try w.writeByte(' '); | |
| 768 | }, | |
| 769 | } | |
| 770 | }, | |
| 771 | } | |
| 772 | } | |
| 773 | fn writeTypeSuffix(cty: CType, w: *Writer, zcu: *const Zcu) Writer.Error!void { | |
| 774 | switch (cty) { | |
| 775 | // simple type specifiers | |
| 776 | .void, | |
| 777 | .bool, | |
| 778 | .int, | |
| 779 | .float, | |
| 780 | .@"fn", | |
| 781 | .@"enum", | |
| 782 | .bitpack, | |
| 783 | .@"struct", | |
| 784 | .union_auto, | |
| 785 | .union_extern, | |
| 786 | .slice, | |
| 787 | .opt, | |
| 788 | .arr, | |
| 789 | .vec, | |
| 790 | .errunion, | |
| 791 | .aligned, | |
| 792 | .bigint, | |
| 793 | => {}, | |
| 794 | ||
| 795 | .pointer => |ptr| { | |
| 796 | // Match opening paren "(" write `writeTypePrefix`. | |
| 797 | switch (ptr.elem_ty.kind()) { | |
| 798 | .specifier, .pointer => {}, | |
| 799 | .postfix_op => try w.writeByte(')'), | |
| 800 | } | |
| 801 | try ptr.elem_ty.writeTypeSuffix(w, zcu); | |
| 802 | }, | |
| 803 | ||
| 804 | .array => |array| { | |
| 805 | try w.print("[{d}]", .{array.len}); | |
| 806 | try array.elem_ty.writeTypeSuffix(w, zcu); | |
| 807 | }, | |
| 808 | ||
| 809 | .function => |function| { | |
| 810 | if (function.param_tys.len == 0 and !function.varargs) { | |
| 811 | try w.writeAll("(void)"); | |
| 812 | } else { | |
| 813 | try w.writeByte('('); | |
| 814 | for (function.param_tys, 0..) |param_ty, param_index| { | |
| 815 | if (param_index > 0) try w.writeAll(", "); | |
| 816 | try param_ty.writeTypePrefix(w, zcu); | |
| 817 | try param_ty.writeTypeSuffix(w, zcu); | |
| 818 | } | |
| 819 | if (function.varargs) { | |
| 820 | if (function.param_tys.len > 0) try w.writeAll(", "); | |
| 821 | try w.writeAll("..."); | |
| 822 | } | |
| 823 | try w.writeByte(')'); | |
| 824 | } | |
| 825 | try function.ret_ty.writeTypeSuffix(w, zcu); | |
| 826 | }, | |
| 827 | } | |
| 828 | } | |
| 829 | ||
| 830 | /// Renders Zig types using only bytes allowed in C identifiers in a somewhat-understandable | |
| 831 | /// way. The output is *not* guaranteed to be unique. | |
| 832 | fn fmtZigType(ty: Type, zcu: *const Zcu) FormatZigType { | |
| 833 | return .{ .ty = ty, .zcu = zcu }; | |
| 834 | } | |
| 835 | const FormatZigType = struct { | |
| 836 | ty: Type, | |
| 837 | zcu: *const Zcu, | |
| 838 | pub fn format(ctx: FormatZigType, w: *Writer) Writer.Error!void { | |
| 839 | const ty = ctx.ty; | |
| 840 | const zcu = ctx.zcu; | |
| 841 | const ip = &zcu.intern_pool; | |
| 842 | switch (ty.zigTypeTag(zcu)) { | |
| 843 | .frame => unreachable, | |
| 844 | .@"anyframe" => unreachable, | |
| 845 | ||
| 846 | .type => try w.writeAll("type"), | |
| 847 | .void => try w.writeAll("void"), | |
| 848 | .bool => try w.writeAll("bool"), | |
| 849 | .noreturn => try w.writeAll("noreturn"), | |
| 850 | .comptime_int => try w.writeAll("comptime_int"), | |
| 851 | .comptime_float => try w.writeAll("comptime_float"), | |
| 852 | .enum_literal => try w.writeAll("enum_literal"), | |
| 853 | .undefined => try w.writeAll("undefined"), | |
| 854 | .null => try w.writeAll("null"), | |
| 855 | ||
| 856 | .int => switch (ty.toIntern()) { | |
| 857 | .usize_type => try w.writeAll("usize"), | |
| 858 | .isize_type => try w.writeAll("isize"), | |
| 859 | .c_char_type => try w.writeAll("c_char"), | |
| 860 | .c_short_type => try w.writeAll("c_short"), | |
| 861 | .c_ushort_type => try w.writeAll("c_ushort"), | |
| 862 | .c_int_type => try w.writeAll("c_int"), | |
| 863 | .c_uint_type => try w.writeAll("c_uint"), | |
| 864 | .c_long_type => try w.writeAll("c_long"), | |
| 865 | .c_ulong_type => try w.writeAll("c_ulong"), | |
| 866 | .c_longlong_type => try w.writeAll("c_longlong"), | |
| 867 | .c_ulonglong_type => try w.writeAll("c_ulonglong"), | |
| 868 | else => { | |
| 869 | const info = ty.intInfo(zcu); | |
| 870 | switch (info.signedness) { | |
| 871 | .unsigned => try w.print("u{d}", .{info.bits}), | |
| 872 | .signed => try w.print("i{d}", .{info.bits}), | |
| 873 | } | |
| 874 | }, | |
| 875 | }, | |
| 876 | .float => switch (ty.toIntern()) { | |
| 877 | .c_longdouble_type => try w.writeAll("c_longdouble"), | |
| 878 | .f16_type => try w.writeAll("f16"), | |
| 879 | .f32_type => try w.writeAll("f32"), | |
| 880 | .f64_type => try w.writeAll("f64"), | |
| 881 | .f80_type => try w.writeAll("f80"), | |
| 882 | .f128_type => try w.writeAll("f128"), | |
| 883 | else => unreachable, | |
| 884 | }, | |
| 885 | .error_set => switch (ty.toIntern()) { | |
| 886 | .anyerror_type => try w.writeAll("anyerror"), | |
| 887 | else => try w.print("error_{d}", .{@intFromEnum(ty.toIntern())}), | |
| 888 | }, | |
| 889 | .optional => try w.print("opt_{f}", .{fmtZigType(ty.optionalChild(zcu), zcu)}), | |
| 890 | .error_union => try w.print("errunion_{f}", .{fmtZigType(ty.errorUnionPayload(zcu), zcu)}), | |
| 891 | ||
| 892 | .pointer => switch (ty.ptrSize(zcu)) { | |
| 893 | .one, .many, .c => try w.print("ptr_{f}", .{fmtZigType(ty.childType(zcu), zcu)}), | |
| 894 | .slice => try w.print("slice_{f}", .{fmtZigType(ty.childType(zcu), zcu)}), | |
| 895 | }, | |
| 896 | .@"fn" => { | |
| 897 | const func_type = ip.indexToKey(ty.toIntern()).func_type; | |
| 898 | try w.writeAll("fn_"); // intentional double underscore to start | |
| 899 | for (func_type.param_types.get(ip)) |param_ty_ip| { | |
| 900 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 901 | if (param_ty.isGenericPoison()) { | |
| 902 | try w.writeAll("_Pgeneric"); | |
| 903 | } else { | |
| 904 | try w.print("_P{f}", .{fmtZigType(param_ty, zcu)}); | |
| 905 | } | |
| 906 | } | |
| 907 | if (func_type.is_var_args) { | |
| 908 | try w.writeAll("_VA"); | |
| 909 | } | |
| 910 | const ret_ty: Type = .fromInterned(func_type.return_type); | |
| 911 | if (ret_ty.isGenericPoison()) { | |
| 912 | try w.writeAll("_Rgeneric"); | |
| 913 | } else if (ret_ty.zigTypeTag(zcu) == .error_union and ret_ty.errorUnionPayload(zcu).isGenericPoison()) { | |
| 914 | try w.writeAll("_Rgeneric_ies"); | |
| 915 | } else { | |
| 916 | try w.print("_R{f}", .{fmtZigType(ret_ty, zcu)}); | |
| 917 | } | |
| 918 | }, | |
| 919 | ||
| 920 | .vector => try w.print("vec_{d}_{f}", .{ | |
| 921 | ty.arrayLen(zcu), | |
| 922 | fmtZigType(ty.childType(zcu), zcu), | |
| 923 | }), | |
| 924 | ||
| 925 | .array => if (ty.sentinel(zcu)) |s| try w.print("arr_{d}s{d}_{f}", .{ | |
| 926 | ty.arrayLen(zcu), | |
| 927 | @intFromEnum(s.toIntern()), | |
| 928 | fmtZigType(ty.childType(zcu), zcu), | |
| 929 | }) else try w.print("arr_{d}_{f}", .{ | |
| 930 | ty.arrayLen(zcu), | |
| 931 | fmtZigType(ty.childType(zcu), zcu), | |
| 932 | }), | |
| 933 | ||
| 934 | .@"struct" => if (ty.isTuple(zcu)) { | |
| 935 | const len = ty.structFieldCount(zcu); | |
| 936 | try w.print("tuple_{d}", .{len}); | |
| 937 | for (0..len) |field_index| { | |
| 938 | const field_ty = ty.fieldType(field_index, zcu); | |
| 939 | try w.print("_{f}", .{fmtZigType(field_ty, zcu)}); | |
| 940 | } | |
| 941 | } else { | |
| 942 | const name = ty.containerTypeName(ip).toSlice(ip); | |
| 943 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); | |
| 944 | }, | |
| 945 | .@"opaque" => if (ty.toIntern() == .anyopaque_type) { | |
| 946 | try w.writeAll("anyopaque"); | |
| 947 | } else { | |
| 948 | const name = ty.containerTypeName(ip).toSlice(ip); | |
| 949 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); | |
| 950 | }, | |
| 951 | .@"union", .@"enum" => { | |
| 952 | const name = ty.containerTypeName(ip).toSlice(ip); | |
| 953 | try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); | |
| 954 | }, | |
| 955 | } | |
| 956 | } | |
| 957 | }; | |
| 958 | ||
| 959 | /// Returns `true` if the layout of `ty` is known without any type resolution required. This | |
| 960 | /// allows some types to be lowered directly where 'typedef' would otherwise be necessary. | |
| 961 | fn alwaysHasLayout(ty: Type, ip: *const InternPool) bool { | |
| 962 | return switch (ip.indexToKey(ty.toIntern())) { | |
| 963 | .int_type, | |
| 964 | .ptr_type, | |
| 965 | .anyframe_type, | |
| 966 | .simple_type, | |
| 967 | .opaque_type, | |
| 968 | .error_set_type, | |
| 969 | .inferred_error_set_type, | |
| 970 | => true, | |
| 971 | ||
| 972 | .struct_type, | |
| 973 | .union_type, | |
| 974 | .enum_type, | |
| 975 | => false, | |
| 976 | ||
| 977 | .array_type => |arr| alwaysHasLayout(.fromInterned(arr.child), ip), | |
| 978 | .vector_type => |vec| alwaysHasLayout(.fromInterned(vec.child), ip), | |
| 979 | .opt_type => |child| alwaysHasLayout(.fromInterned(child), ip), | |
| 980 | .error_union_type => |eu| alwaysHasLayout(.fromInterned(eu.payload_type), ip), | |
| 981 | ||
| 982 | .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { | |
| 983 | if (!alwaysHasLayout(.fromInterned(field_ty), ip)) break false; | |
| 984 | } else true, | |
| 985 | ||
| 986 | .func_type => |f| for (f.param_types.get(ip)) |param_ty| { | |
| 987 | if (!alwaysHasLayout(.fromInterned(param_ty), ip)) break false; | |
| 988 | } else alwaysHasLayout(.fromInterned(f.return_type), ip), | |
| 989 | ||
| 990 | // values, not types | |
| 991 | .undef, | |
| 992 | .simple_value, | |
| 993 | .variable, | |
| 994 | .@"extern", | |
| 995 | .func, | |
| 996 | .int, | |
| 997 | .err, | |
| 998 | .error_union, | |
| 999 | .enum_literal, | |
| 1000 | .enum_tag, | |
| 1001 | .float, | |
| 1002 | .ptr, | |
| 1003 | .slice, | |
| 1004 | .opt, | |
| 1005 | .aggregate, | |
| 1006 | .un, | |
| 1007 | .bitpack, | |
| 1008 | // memoization, not types | |
| 1009 | .memoized_call, | |
| 1010 | => unreachable, | |
| 1011 | }; | |
| 1012 | } | |
| 1013 | }; | |
| 1014 | ||
| 1015 | const Zcu = @import("../../Zcu.zig"); | |
| 1016 | const Type = @import("../../Type.zig"); | |
| 1017 | const Value = @import("../../Value.zig"); | |
| 1018 | const InternPool = @import("../../InternPool.zig"); | |
| 1019 | ||
| 1020 | const std = @import("std"); | |
| 1021 | const assert = std.debug.assert; | |
| 1022 | const Allocator = std.mem.Allocator; | |
| 1023 | const Writer = std.Io.Writer; |
src/codegen/c/type/render_defs.zig created+710| ... | ... | @@ -0,0 +1,710 @@ |
| 1 | /// Renders the `typedef` for an aligned type. | |
| 2 | pub fn defineAligned( | |
| 3 | ty: Type, | |
| 4 | alignment: Alignment, | |
| 5 | complete: bool, | |
| 6 | deps: *CType.Dependencies, | |
| 7 | arena: Allocator, | |
| 8 | w: *Writer, | |
| 9 | pt: Zcu.PerThread, | |
| 10 | ) (Allocator.Error || Writer.Error)!void { | |
| 11 | const zcu = pt.zcu; | |
| 12 | ||
| 13 | const name_cty: CType = .{ .aligned = .{ | |
| 14 | .ty = ty, | |
| 15 | .alignment = alignment, | |
| 16 | } }; | |
| 17 | ||
| 18 | const cty: CType = try .lower(ty, deps, arena, zcu); | |
| 19 | ||
| 20 | try w.writeAll("typedef "); | |
| 21 | if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { | |
| 22 | try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); | |
| 23 | } | |
| 24 | try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{ | |
| 25 | cty.fmtDeclaratorPrefix(zcu), | |
| 26 | name_cty.fmtTypeName(zcu), | |
| 27 | cty.fmtDeclaratorSuffix(zcu), | |
| 28 | alignment.toByteUnits().?, | |
| 29 | ty.fmt(pt), | |
| 30 | }); | |
| 31 | } | |
| 32 | /// Renders the definition of a big-int `struct`. | |
| 33 | pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void { | |
| 34 | const name_cty: CType = .{ .bigint = .{ | |
| 35 | .limb_size = big.limb_size, | |
| 36 | .limbs_len = big.limbs_len, | |
| 37 | } }; | |
| 38 | const limb_cty: CType = .{ .int = big.limb_size.unsigned() }; | |
| 39 | const array_cty: CType = .{ .array = .{ | |
| 40 | .len = big.limbs_len, | |
| 41 | .elem_ty = &limb_cty, | |
| 42 | .nonstring = limb_cty.isStringElem(), | |
| 43 | } }; | |
| 44 | try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{ | |
| 45 | name_cty.fmtTypeName(zcu), | |
| 46 | array_cty.fmtDeclaratorPrefix(zcu), | |
| 47 | array_cty.fmtDeclaratorSuffix(zcu), | |
| 48 | big.limb_size.bits() * @as(u17, big.limbs_len), | |
| 49 | }); | |
| 50 | } | |
| 51 | ||
| 52 | /// Renders a forward declaration of the `struct` which represents an error union whose payload type | |
| 53 | /// is `payload_ty` (the error set type is unspecified). | |
| 54 | pub fn errunionFwdDecl(payload_ty: Type, w: *Writer, zcu: *const Zcu) Writer.Error!void { | |
| 55 | const name_cty: CType = .{ .errunion = .{ | |
| 56 | .payload_ty = payload_ty, | |
| 57 | } }; | |
| 58 | try w.print("{f};\n", .{name_cty.fmtTypeName(zcu)}); | |
| 59 | } | |
| 60 | /// Renders the definition of the `struct` which represents an error union whose payload type is | |
| 61 | /// `payload_ty` (the error set type is unspecified). | |
| 62 | /// | |
| 63 | /// Asserts that the layout of `payload_ty` is resolved. | |
| 64 | pub fn errunionDefineComplete( | |
| 65 | payload_ty: Type, | |
| 66 | deps: *CType.Dependencies, | |
| 67 | arena: Allocator, | |
| 68 | w: *Writer, | |
| 69 | pt: Zcu.PerThread, | |
| 70 | ) (Allocator.Error || Writer.Error)!void { | |
| 71 | const zcu = pt.zcu; | |
| 72 | ||
| 73 | payload_ty.assertHasLayout(zcu); | |
| 74 | ||
| 75 | const name_cty: CType = .{ .errunion = .{ | |
| 76 | .payload_ty = payload_ty, | |
| 77 | } }; | |
| 78 | ||
| 79 | const error_cty: CType = try .lower(.anyerror, deps, arena, zcu); | |
| 80 | ||
| 81 | if (payload_ty.hasRuntimeBits(zcu)) { | |
| 82 | const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu); | |
| 83 | try w.print( | |
| 84 | \\{f} {{ /* anyerror!{f} */ | |
| 85 | \\ {f}payload{f}; | |
| 86 | \\ {f}error{f}; | |
| 87 | \\}}; | |
| 88 | \\ | |
| 89 | , .{ | |
| 90 | name_cty.fmtTypeName(zcu), | |
| 91 | payload_ty.fmt(pt), | |
| 92 | payload_cty.fmtDeclaratorPrefix(zcu), | |
| 93 | payload_cty.fmtDeclaratorSuffix(zcu), | |
| 94 | error_cty.fmtDeclaratorPrefix(zcu), | |
| 95 | error_cty.fmtDeclaratorSuffix(zcu), | |
| 96 | }); | |
| 97 | } else { | |
| 98 | try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{ | |
| 99 | name_cty.fmtTypeName(zcu), | |
| 100 | error_cty.fmtDeclaratorPrefix(zcu), | |
| 101 | error_cty.fmtDeclaratorSuffix(zcu), | |
| 102 | payload_ty.fmt(pt), | |
| 103 | }); | |
| 104 | } | |
| 105 | } | |
| 106 | ||
| 107 | /// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that | |
| 108 | /// type. Does not write anything for error union types, because their forward declarations are | |
| 109 | /// instead rendered by `errunionFwdDecl`. | |
| 110 | pub fn fwdDecl(ty: Type, w: *Writer, zcu: *const Zcu) Writer.Error!void { | |
| 111 | const name_cty: CType = switch (ty.zigTypeTag(zcu)) { | |
| 112 | .@"struct" => switch (ty.containerLayout(zcu)) { | |
| 113 | .auto, .@"extern" => .{ .@"struct" = ty }, | |
| 114 | .@"packed" => return, | |
| 115 | }, | |
| 116 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 117 | .auto => .{ .union_auto = ty }, | |
| 118 | .@"extern" => .{ .union_extern = ty }, | |
| 119 | .@"packed" => return, | |
| 120 | }, | |
| 121 | .pointer => if (ty.isSlice(zcu)) .{ .slice = ty } else return, | |
| 122 | .optional => .{ .opt = ty }, | |
| 123 | .array => .{ .arr = ty }, | |
| 124 | .vector => .{ .vec = ty }, | |
| 125 | else => return, | |
| 126 | }; | |
| 127 | try w.print("{f};\n", .{name_cty.fmtTypeName(zcu)}); | |
| 128 | } | |
| 129 | ||
| 130 | /// If the Zig type `ty` lowers to a `typedef`, renders a typedef of that type to `void`, because | |
| 131 | /// the type's layout is not resolved. This is only necessary for `typedef`s because a `struct` or | |
| 132 | /// `union` which is never defined is already an incomplete type, just like `void`. | |
| 133 | pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!void { | |
| 134 | const zcu = pt.zcu; | |
| 135 | const name_cty: CType = switch (ty.zigTypeTag(zcu)) { | |
| 136 | .@"fn" => .{ .@"fn" = ty }, | |
| 137 | .@"enum" => .{ .@"enum" = ty }, | |
| 138 | .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { | |
| 139 | .auto, .@"extern" => return, | |
| 140 | .@"packed" => .{ .bitpack = ty }, | |
| 141 | }, | |
| 142 | else => return, | |
| 143 | }; | |
| 144 | try w.print("typedef void {f}; /* {f} */\n", .{ | |
| 145 | name_cty.fmtTypeName(zcu), | |
| 146 | ty.fmt(pt), | |
| 147 | }); | |
| 148 | } | |
| 149 | ||
| 150 | /// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the | |
| 151 | /// definition of that type. Does not write anything for error union types, because their | |
| 152 | /// definitions are instead rendered by `errunionDefine`. | |
| 153 | /// | |
| 154 | /// Asserts that the layout of `ty` is resolved. | |
| 155 | pub fn defineComplete( | |
| 156 | ty: Type, | |
| 157 | deps: *CType.Dependencies, | |
| 158 | arena: Allocator, | |
| 159 | w: *Writer, | |
| 160 | pt: Zcu.PerThread, | |
| 161 | ) (Allocator.Error || Writer.Error)!void { | |
| 162 | const zcu = pt.zcu; | |
| 163 | ||
| 164 | ty.assertHasLayout(zcu); | |
| 165 | ||
| 166 | switch (ty.zigTypeTag(zcu)) { | |
| 167 | .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) { | |
| 168 | const name_cty: CType = .{ .@"fn" = ty }; | |
| 169 | try w.print("typedef void {f}; /* {f} */\n", .{ | |
| 170 | name_cty.fmtTypeName(zcu), | |
| 171 | ty.fmt(pt), | |
| 172 | }); | |
| 173 | } else { | |
| 174 | const ip = &zcu.intern_pool; | |
| 175 | const func_type = ip.indexToKey(ty.toIntern()).func_type; | |
| 176 | ||
| 177 | // While incomplete types are usually an acceptable substitute for "void", this is not | |
| 178 | // true in function return types, where "void" is the only incomplete type permitted. | |
| 179 | const actual_ret_ty: Type = .fromInterned(func_type.return_type); | |
| 180 | const effective_ret_ty: Type = switch (actual_ret_ty.classify(zcu)) { | |
| 181 | .no_possible_value => .noreturn, | |
| 182 | .one_possible_value, .fully_comptime => .void, // no runtime bits | |
| 183 | .partially_comptime, .runtime => actual_ret_ty, // yes runtime bits | |
| 184 | }; | |
| 185 | ||
| 186 | const name_cty: CType = .{ .@"fn" = ty }; | |
| 187 | const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu); | |
| 188 | ||
| 189 | try w.print("typedef {f}{f}(", .{ | |
| 190 | ret_cty.fmtDeclaratorPrefix(zcu), | |
| 191 | name_cty.fmtTypeName(zcu), | |
| 192 | }); | |
| 193 | var any_params = false; | |
| 194 | for (func_type.param_types.get(ip)) |param_ty_ip| { | |
| 195 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 196 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 197 | if (any_params) try w.writeAll(", "); | |
| 198 | any_params = true; | |
| 199 | const param_cty: CType = try .lower(param_ty, deps, arena, zcu); | |
| 200 | try w.print("{f}", .{param_cty.fmtTypeName(zcu)}); | |
| 201 | } | |
| 202 | if (func_type.is_var_args) { | |
| 203 | if (any_params) try w.writeAll(", "); | |
| 204 | try w.writeAll("..."); | |
| 205 | } else if (!any_params) { | |
| 206 | try w.writeAll("void"); | |
| 207 | } | |
| 208 | try w.print("){f}; /* {f} */\n", .{ | |
| 209 | ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), | |
| 210 | ty.fmt(pt), | |
| 211 | }); | |
| 212 | }, | |
| 213 | .@"enum" => { | |
| 214 | const name_cty: CType = .{ .@"enum" = ty }; | |
| 215 | const cty: CType = try .lower(ty.intTagType(zcu), deps, arena, zcu); | |
| 216 | try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ | |
| 217 | cty.fmtDeclaratorPrefix(zcu), | |
| 218 | name_cty.fmtTypeName(zcu), | |
| 219 | cty.fmtDeclaratorSuffix(zcu), | |
| 220 | ty.fmt(pt), | |
| 221 | }); | |
| 222 | }, | |
| 223 | .@"struct" => if (ty.isTuple(zcu)) { | |
| 224 | try defineTuple(ty, deps, arena, w, pt); | |
| 225 | } else switch (ty.containerLayout(zcu)) { | |
| 226 | .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt), | |
| 227 | .@"packed" => try defineBitpack(ty, deps, arena, w, pt), | |
| 228 | }, | |
| 229 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 230 | .auto => try defineUnionAuto(ty, deps, arena, w, pt), | |
| 231 | .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt), | |
| 232 | .@"packed" => try defineBitpack(ty, deps, arena, w, pt), | |
| 233 | }, | |
| 234 | .pointer => if (ty.isSlice(zcu)) { | |
| 235 | const name_cty: CType = .{ .slice = ty }; | |
| 236 | const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu); | |
| 237 | try w.print( | |
| 238 | \\{f} {{ /* {f} */ | |
| 239 | \\ {f}ptr{f}; | |
| 240 | \\ size_t len; | |
| 241 | \\}}; | |
| 242 | \\ | |
| 243 | , .{ | |
| 244 | name_cty.fmtTypeName(zcu), | |
| 245 | ty.fmt(pt), | |
| 246 | ptr_cty.fmtDeclaratorPrefix(zcu), | |
| 247 | ptr_cty.fmtDeclaratorSuffix(zcu), | |
| 248 | }); | |
| 249 | // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess | |
| 250 | // slices up, and they're all obviously the same layout. | |
| 251 | }, | |
| 252 | .optional => switch (CType.classifyOptional(ty, zcu)) { | |
| 253 | .error_set, | |
| 254 | .ptr_like, | |
| 255 | .slice_like, | |
| 256 | .npv_payload, | |
| 257 | => {}, | |
| 258 | ||
| 259 | .opv_payload => { | |
| 260 | const name_cty: CType = .{ .opt = ty }; | |
| 261 | try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{ | |
| 262 | name_cty.fmtTypeName(zcu), | |
| 263 | ty.fmt(pt), | |
| 264 | }); | |
| 265 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 266 | }, | |
| 267 | ||
| 268 | .@"struct" => { | |
| 269 | const name_cty: CType = .{ .opt = ty }; | |
| 270 | const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu); | |
| 271 | try w.print( | |
| 272 | \\{f} {{ /* {f} */ | |
| 273 | \\ {f}payload{f}; | |
| 274 | \\ bool is_null; | |
| 275 | \\}}; | |
| 276 | \\ | |
| 277 | , .{ | |
| 278 | name_cty.fmtTypeName(zcu), | |
| 279 | ty.fmt(pt), | |
| 280 | payload_cty.fmtDeclaratorPrefix(zcu), | |
| 281 | payload_cty.fmtDeclaratorSuffix(zcu), | |
| 282 | }); | |
| 283 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 284 | }, | |
| 285 | }, | |
| 286 | .array => if (ty.hasRuntimeBits(zcu)) { | |
| 287 | const name_cty: CType = .{ .arr = ty }; | |
| 288 | const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); | |
| 289 | const array_cty: CType = .{ .array = .{ | |
| 290 | .len = ty.arrayLenIncludingSentinel(zcu), | |
| 291 | .elem_ty = &elem_cty, | |
| 292 | .nonstring = nonstring: { | |
| 293 | if (!elem_cty.isStringElem()) break :nonstring false; | |
| 294 | const s = ty.sentinel(zcu) orelse break :nonstring true; | |
| 295 | break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); | |
| 296 | }, | |
| 297 | } }; | |
| 298 | try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ | |
| 299 | name_cty.fmtTypeName(zcu), | |
| 300 | array_cty.fmtDeclaratorPrefix(zcu), | |
| 301 | array_cty.fmtDeclaratorSuffix(zcu), | |
| 302 | ty.fmt(pt), | |
| 303 | }); | |
| 304 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 305 | }, | |
| 306 | .vector => if (ty.hasRuntimeBits(zcu)) { | |
| 307 | const name_cty: CType = .{ .vec = ty }; | |
| 308 | const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); | |
| 309 | const array_cty: CType = .{ .array = .{ | |
| 310 | .len = ty.arrayLenIncludingSentinel(zcu), | |
| 311 | .elem_ty = &elem_cty, | |
| 312 | .nonstring = elem_cty.isStringElem(), | |
| 313 | } }; | |
| 314 | try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ | |
| 315 | name_cty.fmtTypeName(zcu), | |
| 316 | array_cty.fmtDeclaratorPrefix(zcu), | |
| 317 | array_cty.fmtDeclaratorSuffix(zcu), | |
| 318 | ty.fmt(pt), | |
| 319 | }); | |
| 320 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 321 | }, | |
| 322 | else => {}, | |
| 323 | } | |
| 324 | } | |
| 325 | fn defineBitpack( | |
| 326 | ty: Type, | |
| 327 | deps: *CType.Dependencies, | |
| 328 | arena: Allocator, | |
| 329 | w: *Writer, | |
| 330 | pt: Zcu.PerThread, | |
| 331 | ) (Allocator.Error || Writer.Error)!void { | |
| 332 | const zcu = pt.zcu; | |
| 333 | const name_cty: CType = .{ .bitpack = ty }; | |
| 334 | const cty: CType = try .lower(ty.bitpackBackingInt(zcu), deps, arena, zcu); | |
| 335 | try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ | |
| 336 | cty.fmtDeclaratorPrefix(zcu), | |
| 337 | name_cty.fmtTypeName(zcu), | |
| 338 | cty.fmtDeclaratorSuffix(zcu), | |
| 339 | ty.fmt(pt), | |
| 340 | }); | |
| 341 | } | |
| 342 | fn defineTuple( | |
| 343 | ty: Type, | |
| 344 | deps: *CType.Dependencies, | |
| 345 | arena: Allocator, | |
| 346 | w: *Writer, | |
| 347 | pt: Zcu.PerThread, | |
| 348 | ) (Allocator.Error || Writer.Error)!void { | |
| 349 | const zcu = pt.zcu; | |
| 350 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 351 | const ip = &zcu.intern_pool; | |
| 352 | const tuple = ip.indexToKey(ty.toIntern()).tuple_type; | |
| 353 | ||
| 354 | // Fields cannot be underaligned, because tuple fields cannot have specified alignments. | |
| 355 | // However, overaligned fields are possible thanks to intermediate zero-bit fields. | |
| 356 | ||
| 357 | const tuple_align = ty.abiAlignment(zcu); | |
| 358 | ||
| 359 | // If the alignment of other fields would not give the tuple sufficient alignment, we | |
| 360 | // need to align the first field (which does not affect its offset, because 0 is always | |
| 361 | // well-aligned) to indirectly specify the tuple alignment. | |
| 362 | const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { | |
| 363 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 364 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 365 | const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); | |
| 366 | if (natural_align.compareStrict(.gte, tuple_align)) break false; | |
| 367 | } else true; | |
| 368 | ||
| 369 | const name_cty: CType = .{ .@"struct" = ty }; | |
| 370 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 371 | name_cty.fmtTypeName(zcu), | |
| 372 | ty.fmt(pt), | |
| 373 | }); | |
| 374 | var zig_offset: u64 = 0; | |
| 375 | var c_offset: u64 = 0; | |
| 376 | for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| { | |
| 377 | if (field_val_ip != .none) continue; // `comptime` field | |
| 378 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 379 | const field_align = field_ty.abiAlignment(zcu); | |
| 380 | zig_offset = field_align.forward(zig_offset); | |
| 381 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 382 | c_offset = field_align.forward(c_offset); | |
| 383 | try w.writeByte(' '); | |
| 384 | if (zig_offset == 0 and overalign) { | |
| 385 | // This is the first field; specify its alignment to align the tuple. | |
| 386 | try writeFieldAlign(field_ty, tuple_align, w, zcu); | |
| 387 | } else if (zig_offset > c_offset) { | |
| 388 | // This field needs to be overaligned compared to what its offset would otherwise be. | |
| 389 | const need_align: Alignment = .minStrict( | |
| 390 | tuple_align, // don't make the struct more aligned than it should be | |
| 391 | .fromLog2Units(@ctz(zig_offset)), | |
| 392 | ); | |
| 393 | try writeFieldAlign(field_ty, need_align, w, zcu); | |
| 394 | c_offset = need_align.forward(c_offset); | |
| 395 | } | |
| 396 | const field_cty: CType = try .lower(field_ty, deps, arena, zcu); | |
| 397 | try w.print("{f}f{d}{f};\n", .{ | |
| 398 | field_cty.fmtDeclaratorPrefix(zcu), | |
| 399 | field_index, | |
| 400 | field_cty.fmtDeclaratorSuffix(zcu), | |
| 401 | }); | |
| 402 | const field_size = field_ty.abiSize(zcu); | |
| 403 | zig_offset += field_size; | |
| 404 | c_offset += field_size; | |
| 405 | } | |
| 406 | try w.writeAll("};\n"); | |
| 407 | ||
| 408 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 409 | } | |
| 410 | fn defineStruct( | |
| 411 | ty: Type, | |
| 412 | deps: *CType.Dependencies, | |
| 413 | arena: Allocator, | |
| 414 | w: *Writer, | |
| 415 | pt: Zcu.PerThread, | |
| 416 | ) (Allocator.Error || Writer.Error)!void { | |
| 417 | const zcu = pt.zcu; | |
| 418 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 419 | const ip = &zcu.intern_pool; | |
| 420 | ||
| 421 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 422 | ||
| 423 | // If there are any underaligned fields, we need to byte-pack the struct. | |
| 424 | const pack: bool = pack: { | |
| 425 | var it = struct_type.iterateRuntimeOrder(ip); | |
| 426 | var offset: u64 = 0; | |
| 427 | while (it.next()) |field_index| { | |
| 428 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 429 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 430 | const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); | |
| 431 | const natural_offset = natural_align.forward(offset); | |
| 432 | const actual_offset = struct_type.field_offsets.get(ip)[field_index]; | |
| 433 | if (actual_offset < natural_offset) break :pack true; | |
| 434 | // Also pack if any field is more aligned than the struct should be. | |
| 435 | if (natural_align.compareStrict(.gt, struct_type.alignment)) break :pack true; | |
| 436 | offset = actual_offset + field_ty.abiSize(zcu); | |
| 437 | } | |
| 438 | break :pack false; | |
| 439 | }; | |
| 440 | ||
| 441 | // If the alignment of other fields would not give the struct sufficient alignment, we | |
| 442 | // need to align the first field (which does not affect its offset, because 0 is always | |
| 443 | // well-aligned) to indirectly specify the struct alignment. | |
| 444 | const overalign: bool = switch (pack) { | |
| 445 | true => struct_type.alignment.compareStrict(.gt, .@"1"), | |
| 446 | false => overalign: { | |
| 447 | var it = struct_type.iterateRuntimeOrder(ip); | |
| 448 | while (it.next()) |field_index| { | |
| 449 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 450 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 451 | const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); | |
| 452 | if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false; | |
| 453 | } | |
| 454 | break :overalign true; | |
| 455 | }, | |
| 456 | }; | |
| 457 | ||
| 458 | if (pack) try w.writeAll("zig_packed("); | |
| 459 | const name_cty: CType = .{ .@"struct" = ty }; | |
| 460 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 461 | name_cty.fmtTypeName(zcu), | |
| 462 | ty.fmt(pt), | |
| 463 | }); | |
| 464 | var it = struct_type.iterateRuntimeOrder(ip); | |
| 465 | var offset: u64 = 0; | |
| 466 | while (it.next()) |field_index| { | |
| 467 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 468 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 469 | const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); | |
| 470 | const natural_offset = switch (pack) { | |
| 471 | true => offset, | |
| 472 | false => natural_align.forward(offset), | |
| 473 | }; | |
| 474 | const actual_offset = struct_type.field_offsets.get(ip)[field_index]; | |
| 475 | try w.writeByte(' '); | |
| 476 | if (actual_offset == 0 and overalign) { | |
| 477 | // This is the first field; specify its alignment to align the struct. | |
| 478 | try writeFieldAlign(field_ty, struct_type.alignment, w, zcu); | |
| 479 | } else if (actual_offset > natural_offset) { | |
| 480 | // This field needs to be underaligned or overaligned compared to what its | |
| 481 | // offset would otherwise be. | |
| 482 | const need_align: Alignment = .minStrict( | |
| 483 | struct_type.alignment, // don't make the struct more aligned than it should be | |
| 484 | .fromLog2Units(@ctz(actual_offset)), | |
| 485 | ); | |
| 486 | try writeFieldAlign(field_ty, need_align, w, zcu); | |
| 487 | } | |
| 488 | const field_cty: CType = try .lower(field_ty, deps, arena, zcu); | |
| 489 | const field_name = struct_type.field_names.get(ip)[field_index].toSlice(ip); | |
| 490 | try w.print("{f}{f}{f};\n", .{ | |
| 491 | field_cty.fmtDeclaratorPrefix(zcu), | |
| 492 | fmtIdentSolo(field_name), | |
| 493 | field_cty.fmtDeclaratorSuffix(zcu), | |
| 494 | }); | |
| 495 | offset = actual_offset + field_ty.abiSize(zcu); | |
| 496 | } | |
| 497 | assert(struct_type.alignment.forward(offset) == struct_type.size); | |
| 498 | try w.writeByte('}'); | |
| 499 | if (pack) try w.writeByte(')'); | |
| 500 | try w.writeAll(";\n"); | |
| 501 | ||
| 502 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 503 | } | |
| 504 | fn defineUnionAuto( | |
| 505 | ty: Type, | |
| 506 | deps: *CType.Dependencies, | |
| 507 | arena: Allocator, | |
| 508 | w: *Writer, | |
| 509 | pt: Zcu.PerThread, | |
| 510 | ) (Allocator.Error || Writer.Error)!void { | |
| 511 | const zcu = pt.zcu; | |
| 512 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 513 | const ip = &zcu.intern_pool; | |
| 514 | ||
| 515 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 516 | const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); | |
| 517 | ||
| 518 | const layout = Type.getUnionLayout(union_type, zcu); | |
| 519 | ||
| 520 | // If there are any underaligned fields, we need to byte-pack the union. | |
| 521 | const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { | |
| 522 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 523 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 524 | const natural_align = field_ty.abiAlignment(zcu); | |
| 525 | if (natural_align.compareStrict(.gt, union_type.alignment)) break true; | |
| 526 | // The tag will immediately follow the payload. This layout may put the tag in what would | |
| 527 | // otherwise be padding on the payload union, because if the most-aligned union field is not | |
| 528 | // the largest one, a larger field may make the payload "underaligned" overall. As such, we | |
| 529 | // need to check whether this field is okay with the payload size, and if not then we must | |
| 530 | // byte-pack. | |
| 531 | if (!natural_align.check(layout.payload_size)) break true; | |
| 532 | } else false; | |
| 533 | ||
| 534 | // If the alignment of other fields would not give the union sufficient alignment, we | |
| 535 | // need to align the first field (which does not affect its offset, because 0 is always | |
| 536 | // well-aligned) to indirectly specify the union alignment. | |
| 537 | const overalign: bool = switch (pack) { | |
| 538 | true => union_type.alignment.compareStrict(.gt, .@"1"), | |
| 539 | false => for (union_type.field_types.get(ip)) |field_ty_ip| { | |
| 540 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 541 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 542 | const natural_align = field_ty.abiAlignment(zcu); | |
| 543 | if (natural_align.compareStrict(.gte, union_type.alignment)) break false; | |
| 544 | } else overalign: { | |
| 545 | if (union_type.has_runtime_tag) { | |
| 546 | const tag_align = enum_tag_ty.abiAlignment(zcu); | |
| 547 | if (tag_align.compareStrict(.gte, union_type.alignment)) break :overalign false; | |
| 548 | } | |
| 549 | break :overalign true; | |
| 550 | }, | |
| 551 | }; | |
| 552 | ||
| 553 | const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu); | |
| 554 | ||
| 555 | const name_cty: CType = .{ .union_auto = ty }; | |
| 556 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 557 | name_cty.fmtTypeName(zcu), | |
| 558 | ty.fmt(pt), | |
| 559 | }); | |
| 560 | if (payload_has_bits) { | |
| 561 | try w.writeByte(' '); | |
| 562 | if (overalign) { | |
| 563 | // Specify the alignment of `union { ... } payload;` to align the union's `struct`. | |
| 564 | try w.print("zig_align({d}) ", .{union_type.alignment.toByteUnits().?}); | |
| 565 | } | |
| 566 | if (pack) try w.writeAll("zig_packed("); | |
| 567 | try w.writeAll("union {\n"); | |
| 568 | for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { | |
| 569 | const field_ty = ty.fieldType(field_index, zcu); | |
| 570 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 571 | const field_name = enum_tag_ty.enumFieldName(field_index, zcu).toSlice(ip); | |
| 572 | const field_cty: CType = try .lower(field_ty, deps, arena, zcu); | |
| 573 | try w.print(" {f}{f}{f};\n", .{ | |
| 574 | field_cty.fmtDeclaratorPrefix(zcu), | |
| 575 | fmtIdentSolo(field_name), | |
| 576 | field_cty.fmtDeclaratorSuffix(zcu), | |
| 577 | }); | |
| 578 | } | |
| 579 | try w.writeAll(" }"); | |
| 580 | if (pack) try w.writeByte(')'); | |
| 581 | try w.writeAll(" payload;\n"); | |
| 582 | } | |
| 583 | if (union_type.has_runtime_tag) { | |
| 584 | const tag_cty: CType = try .lower(enum_tag_ty, deps, arena, zcu); | |
| 585 | try w.print(" {f}tag{f};\n", .{ | |
| 586 | tag_cty.fmtDeclaratorPrefix(zcu), | |
| 587 | tag_cty.fmtDeclaratorSuffix(zcu), | |
| 588 | }); | |
| 589 | } | |
| 590 | try w.writeAll("};\n"); | |
| 591 | ||
| 592 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 593 | } | |
| 594 | fn defineUnionExtern( | |
| 595 | ty: Type, | |
| 596 | deps: *CType.Dependencies, | |
| 597 | arena: Allocator, | |
| 598 | w: *Writer, | |
| 599 | pt: Zcu.PerThread, | |
| 600 | ) (Allocator.Error || Writer.Error)!void { | |
| 601 | const zcu = pt.zcu; | |
| 602 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 603 | const ip = &zcu.intern_pool; | |
| 604 | ||
| 605 | const union_type = ip.loadUnionType(ty.toIntern()); | |
| 606 | assert(!union_type.has_runtime_tag); | |
| 607 | const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); | |
| 608 | ||
| 609 | // If there are any underaligned fields, we need to byte-pack the union. | |
| 610 | const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { | |
| 611 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 612 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 613 | const natural_align = field_ty.abiAlignment(zcu); | |
| 614 | if (natural_align.compareStrict(.gt, union_type.alignment)) break true; | |
| 615 | } else false; | |
| 616 | ||
| 617 | // If the alignment of other fields would not give the union sufficient alignment, we | |
| 618 | // need to align the first field (which does not affect its offset, because 0 is always | |
| 619 | // well-aligned) to indirectly specify the union alignment. | |
| 620 | const overalign: bool = switch (pack) { | |
| 621 | true => union_type.alignment.compareStrict(.gt, .@"1"), | |
| 622 | false => for (union_type.field_types.get(ip)) |field_ty_ip| { | |
| 623 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 624 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 625 | const natural_align = field_ty.abiAlignment(zcu); | |
| 626 | if (natural_align.compareStrict(.gte, union_type.alignment)) break false; | |
| 627 | } else overalign: { | |
| 628 | if (union_type.has_runtime_tag) { | |
| 629 | const tag_align = enum_tag_ty.abiAlignment(zcu); | |
| 630 | if (tag_align.compareStrict(.gte, union_type.alignment)) break :overalign false; | |
| 631 | } | |
| 632 | break :overalign true; | |
| 633 | }, | |
| 634 | }; | |
| 635 | ||
| 636 | if (pack) try w.writeAll("zig_packed("); | |
| 637 | ||
| 638 | const name_cty: CType = .{ .union_extern = ty }; | |
| 639 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 640 | name_cty.fmtTypeName(zcu), | |
| 641 | ty.fmt(pt), | |
| 642 | }); | |
| 643 | ||
| 644 | for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { | |
| 645 | const field_ty = ty.fieldType(field_index, zcu); | |
| 646 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 647 | const field_name = enum_tag_ty.enumFieldName(field_index, zcu).toSlice(ip); | |
| 648 | const field_cty: CType = try .lower(field_ty, deps, arena, zcu); | |
| 649 | try w.writeByte(' '); | |
| 650 | if (overalign and field_index == 0) { | |
| 651 | // This is the first field; specify its alignment to align the union. | |
| 652 | try writeFieldAlign(field_ty, union_type.alignment, w, zcu); | |
| 653 | } | |
| 654 | try w.print("{f}{f}{f};\n", .{ | |
| 655 | field_cty.fmtDeclaratorPrefix(zcu), | |
| 656 | fmtIdentSolo(field_name), | |
| 657 | field_cty.fmtDeclaratorSuffix(zcu), | |
| 658 | }); | |
| 659 | } | |
| 660 | try w.writeByte('}'); | |
| 661 | if (pack) try w.writeByte(')'); | |
| 662 | try w.writeAll(";\n"); | |
| 663 | ||
| 664 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 665 | } | |
| 666 | ||
| 667 | /// Writes an annotation which, placed before a struct/union field declaration with field type `ty`, | |
| 668 | /// will specify that field as having the given alignment. | |
| 669 | fn writeFieldAlign( | |
| 670 | ty: Type, | |
| 671 | alignment: Alignment, | |
| 672 | w: *Writer, | |
| 673 | zcu: *const Zcu, | |
| 674 | ) Writer.Error!void { | |
| 675 | if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { | |
| 676 | try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); | |
| 677 | } else { | |
| 678 | try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}); | |
| 679 | } | |
| 680 | } | |
| 681 | ||
| 682 | /// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`. | |
| 683 | fn writeStaticAssertLayout( | |
| 684 | ty: Type, | |
| 685 | cty: CType, | |
| 686 | w: *Writer, | |
| 687 | zcu: *const Zcu, | |
| 688 | ) Writer.Error!void { | |
| 689 | try w.print( | |
| 690 | \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size"); | |
| 691 | \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment"); | |
| 692 | \\ | |
| 693 | , .{ | |
| 694 | cty.fmtTypeName(zcu), ty.abiSize(zcu), | |
| 695 | cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?, | |
| 696 | }); | |
| 697 | } | |
| 698 | ||
| 699 | const std = @import("std"); | |
| 700 | const assert = std.debug.assert; | |
| 701 | const Writer = std.Io.Writer; | |
| 702 | const Allocator = std.mem.Allocator; | |
| 703 | ||
| 704 | const Zcu = @import("../../../Zcu.zig"); | |
| 705 | const Type = @import("../../../Type.zig"); | |
| 706 | const Value = @import("../../../Value.zig"); | |
| 707 | const CType = @import("../type.zig").CType; | |
| 708 | const Alignment = @import("../../../InternPool.zig").Alignment; | |
| 709 | ||
| 710 | const fmtIdentSolo = @import("../../c.zig").fmtIdentSolo; |
src/codegen/llvm.zig+916-1146| ... | ... | @@ -520,6 +520,21 @@ pub const Object = struct { |
| 520 | 520 | gpa: Allocator, |
| 521 | 521 | builder: Builder, |
| 522 | 522 | |
| 523 | /// This pool contains only types (and not `@as(type, undefined)`). It has two purposes: | |
| 524 | /// | |
| 525 | /// * Lazily tracking ABI alignment of types, so that `@"align"` attributes can be set to a | |
| 526 | /// type's ABI alignment before that type is fully resolved. Each type in the pool has a | |
| 527 | /// corresponding entry in `lazy_abi_aligns`. | |
| 528 | /// | |
| 529 | /// * If `!Object.builder.strip`, lazily tracking debug information types, so that debug | |
| 530 | /// information can handle indirect self-reference (and so that debug information works | |
| 531 | /// correctly across incremental updates). Each type has a corresponding entry in | |
| 532 | /// `debug_types`, provided that `Object.builder.strip` is `false`. | |
| 533 | type_pool: link.ConstPool, | |
| 534 | ||
| 535 | /// Keyed on `link.ConstPool.Index`. | |
| 536 | lazy_abi_aligns: std.ArrayList(Builder.Alignment.Lazy), | |
| 537 | ||
| 523 | 538 | debug_compile_unit: Builder.Metadata.Optional, |
| 524 | 539 | |
| 525 | 540 | debug_enums_fwd_ref: Builder.Metadata.Optional, |
| ... | ... | @@ -529,9 +544,13 @@ pub const Object = struct { |
| 529 | 544 | debug_globals: std.ArrayList(Builder.Metadata), |
| 530 | 545 | |
| 531 | 546 | debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata), |
| 532 | debug_type_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Metadata), | |
| 533 | 547 | |
| 534 | debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata), | |
| 548 | /// Keyed on `link.ConstPool.Index`. | |
| 549 | debug_types: std.ArrayList(Builder.Metadata), | |
| 550 | /// Initially `.none`, set if the type `anyerror` is lowered to a debug type. The type will not | |
| 551 | /// actually be created until `emit`, which must resolve this reference with an appropriate enum | |
| 552 | /// type from the global error set. | |
| 553 | debug_anyerror_fwd_ref: Builder.Metadata.Optional, | |
| 535 | 554 | |
| 536 | 555 | target: *const std.Target, |
| 537 | 556 | /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function, |
| ... | ... | @@ -654,35 +673,38 @@ pub const Object = struct { |
| 654 | 673 | obj.* = .{ |
| 655 | 674 | .gpa = gpa, |
| 656 | 675 | .builder = builder, |
| 676 | .type_pool = .empty, | |
| 677 | .lazy_abi_aligns = .empty, | |
| 657 | 678 | .debug_compile_unit = debug_compile_unit, |
| 658 | 679 | .debug_enums_fwd_ref = debug_enums_fwd_ref, |
| 659 | 680 | .debug_globals_fwd_ref = debug_globals_fwd_ref, |
| 660 | .debug_enums = .{}, | |
| 661 | .debug_globals = .{}, | |
| 662 | .debug_file_map = .{}, | |
| 663 | .debug_type_map = .{}, | |
| 664 | .debug_unresolved_namespace_scopes = .{}, | |
| 681 | .debug_enums = .empty, | |
| 682 | .debug_globals = .empty, | |
| 683 | .debug_file_map = .empty, | |
| 684 | .debug_types = .empty, | |
| 685 | .debug_anyerror_fwd_ref = .none, | |
| 665 | 686 | .target = target, |
| 666 | .nav_map = .{}, | |
| 667 | .uav_map = .{}, | |
| 668 | .enum_tag_name_map = .{}, | |
| 669 | .named_enum_map = .{}, | |
| 670 | .type_map = .{}, | |
| 687 | .nav_map = .empty, | |
| 688 | .uav_map = .empty, | |
| 689 | .enum_tag_name_map = .empty, | |
| 690 | .named_enum_map = .empty, | |
| 691 | .type_map = .empty, | |
| 671 | 692 | .error_name_table = .none, |
| 672 | 693 | .null_opt_usize = .no_init, |
| 673 | .struct_field_map = .{}, | |
| 674 | .used = .{}, | |
| 694 | .struct_field_map = .empty, | |
| 695 | .used = .empty, | |
| 675 | 696 | }; |
| 676 | 697 | return obj; |
| 677 | 698 | } |
| 678 | 699 | |
| 679 | 700 | pub fn deinit(self: *Object) void { |
| 680 | 701 | const gpa = self.gpa; |
| 702 | self.type_pool.deinit(gpa); | |
| 703 | self.lazy_abi_aligns.deinit(gpa); | |
| 681 | 704 | self.debug_enums.deinit(gpa); |
| 682 | 705 | self.debug_globals.deinit(gpa); |
| 683 | 706 | self.debug_file_map.deinit(gpa); |
| 684 | self.debug_type_map.deinit(gpa); | |
| 685 | self.debug_unresolved_namespace_scopes.deinit(gpa); | |
| 707 | self.debug_types.deinit(gpa); | |
| 686 | 708 | self.nav_map.deinit(gpa); |
| 687 | 709 | self.uav_map.deinit(gpa); |
| 688 | 710 | self.enum_tag_name_map.deinit(gpa); |
| ... | ... | @@ -824,19 +846,13 @@ pub const Object = struct { |
| 824 | 846 | } |
| 825 | 847 | |
| 826 | 848 | if (!o.builder.strip) { |
| 827 | { | |
| 828 | var i: usize = 0; | |
| 829 | while (i < o.debug_unresolved_namespace_scopes.count()) : (i += 1) { | |
| 830 | const namespace_index = o.debug_unresolved_namespace_scopes.keys()[i]; | |
| 831 | const fwd_ref = o.debug_unresolved_namespace_scopes.values()[i]; | |
| 832 | ||
| 833 | const namespace = zcu.namespacePtr(namespace_index); | |
| 834 | const debug_type = try o.lowerDebugType(pt, Type.fromInterned(namespace.owner_type)); | |
| 835 | ||
| 836 | o.builder.resolveDebugForwardReference(fwd_ref, debug_type); | |
| 837 | } | |
| 849 | if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| { | |
| 850 | const debug_anyerror_type = try o.lowerDebugAnyerrorType(pt); | |
| 851 | o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type); | |
| 838 | 852 | } |
| 839 | 853 | |
| 854 | try o.flushTypePool(pt); | |
| 855 | ||
| 840 | 856 | o.builder.resolveDebugForwardReference( |
| 841 | 857 | o.debug_enums_fwd_ref.unwrap().?, |
| 842 | 858 | try o.builder.metadataTuple(o.debug_enums.items), |
| ... | ... | @@ -1395,10 +1411,10 @@ pub const Object = struct { |
| 1395 | 1411 | if (ptr_info.flags.is_const) { |
| 1396 | 1412 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 1397 | 1413 | } |
| 1398 | const elem_align = (if (ptr_info.flags.alignment != .none) | |
| 1399 | @as(InternPool.Alignment, ptr_info.flags.alignment) | |
| 1400 | else | |
| 1401 | Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm(); | |
| 1414 | const elem_align: Builder.Alignment.Lazy = switch (ptr_info.flags.alignment) { | |
| 1415 | else => |a| .wrap(a.toLlvm()), | |
| 1416 | .none => try o.lazyAbiAlignment(pt, .fromInterned(ptr_info.child)), | |
| 1417 | }; | |
| 1402 | 1418 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 1403 | 1419 | const ptr_param = wip.arg(llvm_arg_i); |
| 1404 | 1420 | llvm_arg_i += 1; |
| ... | ... | @@ -1472,7 +1488,7 @@ pub const Object = struct { |
| 1472 | 1488 | |
| 1473 | 1489 | const line_number = zcu.navSrcLine(func.owner_nav) + 1; |
| 1474 | 1490 | const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern"; |
| 1475 | const debug_decl_type = try o.lowerDebugType(pt, fn_ty); | |
| 1491 | const debug_decl_type = try o.getDebugType(pt, fn_ty); | |
| 1476 | 1492 | |
| 1477 | 1493 | const subprogram = try o.builder.debugSubprogram( |
| 1478 | 1494 | file, |
| ... | ... | @@ -1522,7 +1538,7 @@ pub const Object = struct { |
| 1522 | 1538 | |
| 1523 | 1539 | break :f .{ |
| 1524 | 1540 | .counters_variable = counters_variable, |
| 1525 | .pcs = .{}, | |
| 1541 | .pcs = .empty, | |
| 1526 | 1542 | }; |
| 1527 | 1543 | }; |
| 1528 | 1544 | |
| ... | ... | @@ -1538,10 +1554,10 @@ pub const Object = struct { |
| 1538 | 1554 | .args = args.items, |
| 1539 | 1555 | .arg_index = 0, |
| 1540 | 1556 | .arg_inline_index = 0, |
| 1541 | .func_inst_table = .{}, | |
| 1542 | .blocks = .{}, | |
| 1543 | .loops = .{}, | |
| 1544 | .switch_dispatch_info = .{}, | |
| 1557 | .func_inst_table = .empty, | |
| 1558 | .blocks = .empty, | |
| 1559 | .loops = .empty, | |
| 1560 | .switch_dispatch_info = .empty, | |
| 1545 | 1561 | .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, |
| 1546 | 1562 | .file = file, |
| 1547 | 1563 | .scope = subprogram, |
| ... | ... | @@ -1599,6 +1615,7 @@ pub const Object = struct { |
| 1599 | 1615 | } |
| 1600 | 1616 | |
| 1601 | 1617 | try fg.wip.finish(); |
| 1618 | try o.flushTypePool(pt); | |
| 1602 | 1619 | } |
| 1603 | 1620 | |
| 1604 | 1621 | pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { |
| ... | ... | @@ -1615,6 +1632,11 @@ pub const Object = struct { |
| 1615 | 1632 | }, |
| 1616 | 1633 | else => |e| return e, |
| 1617 | 1634 | }; |
| 1635 | try self.flushTypePool(pt); | |
| 1636 | } | |
| 1637 | ||
| 1638 | fn flushTypePool(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { | |
| 1639 | try o.type_pool.flushPending(pt, .{ .llvm = o }); | |
| 1618 | 1640 | } |
| 1619 | 1641 | |
| 1620 | 1642 | pub fn updateExports( |
| ... | ... | @@ -1810,6 +1832,84 @@ pub const Object = struct { |
| 1810 | 1832 | } |
| 1811 | 1833 | } |
| 1812 | 1834 | |
| 1835 | pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { | |
| 1836 | try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); | |
| 1837 | } | |
| 1838 | ||
| 1839 | /// Should only be called by the `link.ConstPool` implementation. | |
| 1840 | /// | |
| 1841 | /// `val` is always a type because `o.type_pool` only contains types. | |
| 1842 | pub fn addConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { | |
| 1843 | const zcu = pt.zcu; | |
| 1844 | const gpa = zcu.comp.gpa; | |
| 1845 | assert(zcu.intern_pool.typeOf(val) == .type_type); | |
| 1846 | ||
| 1847 | { | |
| 1848 | assert(@intFromEnum(index) == o.lazy_abi_aligns.items.len); | |
| 1849 | try o.lazy_abi_aligns.ensureUnusedCapacity(gpa, 1); | |
| 1850 | const fwd_ref = try o.builder.alignmentForwardReference(); | |
| 1851 | o.lazy_abi_aligns.appendAssumeCapacity(fwd_ref); | |
| 1852 | } | |
| 1853 | ||
| 1854 | if (!o.builder.strip) { | |
| 1855 | assert(@intFromEnum(index) == o.debug_types.items.len); | |
| 1856 | try o.debug_types.ensureUnusedCapacity(gpa, 1); | |
| 1857 | const fwd_ref = try o.builder.debugForwardReference(); | |
| 1858 | o.debug_types.appendAssumeCapacity(fwd_ref); | |
| 1859 | if (val == .anyerror_type) { | |
| 1860 | assert(o.debug_anyerror_fwd_ref.is_none); | |
| 1861 | o.debug_anyerror_fwd_ref = fwd_ref.toOptional(); | |
| 1862 | } | |
| 1863 | } | |
| 1864 | } | |
| 1865 | /// Should only be called by the `link.ConstPool` implementation. | |
| 1866 | /// | |
| 1867 | /// `val` is always a type because `o.type_pool` only contains types. | |
| 1868 | pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { | |
| 1869 | const zcu = pt.zcu; | |
| 1870 | assert(zcu.intern_pool.typeOf(val) == .type_type); | |
| 1871 | ||
| 1872 | const ty: Type = .fromInterned(val); | |
| 1873 | ||
| 1874 | { | |
| 1875 | const fwd_ref = o.lazy_abi_aligns.items[@intFromEnum(index)]; | |
| 1876 | o.builder.resolveAlignmentForwardReference(fwd_ref, .fromByteUnits(1)); | |
| 1877 | } | |
| 1878 | ||
| 1879 | if (!o.builder.strip) { | |
| 1880 | assert(val != .anyerror_type); | |
| 1881 | const fwd_ref = o.debug_types.items[@intFromEnum(index)]; | |
| 1882 | const name_str = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); | |
| 1883 | const debug_incomplete_type = try o.builder.debugSignedType(name_str, 0); | |
| 1884 | o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type); | |
| 1885 | } | |
| 1886 | } | |
| 1887 | /// Should only be called by the `link.ConstPool` implementation. | |
| 1888 | /// | |
| 1889 | /// `val` is always a type because `o.type_pool` only contains types. | |
| 1890 | pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { | |
| 1891 | const zcu = pt.zcu; | |
| 1892 | assert(zcu.intern_pool.typeOf(val) == .type_type); | |
| 1893 | ||
| 1894 | const ty: Type = .fromInterned(val); | |
| 1895 | ||
| 1896 | { | |
| 1897 | const fwd_ref = o.lazy_abi_aligns.items[@intFromEnum(index)]; | |
| 1898 | o.builder.resolveAlignmentForwardReference(fwd_ref, ty.abiAlignment(zcu).toLlvm()); | |
| 1899 | } | |
| 1900 | ||
| 1901 | if (!o.builder.strip) { | |
| 1902 | const fwd_ref = o.debug_types.items[@intFromEnum(index)]; | |
| 1903 | if (val == .anyerror_type) { | |
| 1904 | // Don't lower this now; it will be populated in `emit` instead. | |
| 1905 | assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional()); | |
| 1906 | } else { | |
| 1907 | const debug_type = try o.lowerDebugType(pt, ty, fwd_ref); | |
| 1908 | o.builder.resolveDebugForwardReference(fwd_ref, debug_type); | |
| 1909 | } | |
| 1910 | } | |
| 1911 | } | |
| 1912 | ||
| 1813 | 1913 | fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata { |
| 1814 | 1914 | const gpa = o.gpa; |
| 1815 | 1915 | const gop = try o.debug_file_map.getOrPut(gpa, file_index); |
| ... | ... | @@ -1826,10 +1926,19 @@ pub const Object = struct { |
| 1826 | 1926 | return gop.value_ptr.*; |
| 1827 | 1927 | } |
| 1828 | 1928 | |
| 1829 | pub fn lowerDebugType( | |
| 1929 | fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata { | |
| 1930 | assert(!o.builder.strip); | |
| 1931 | const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); | |
| 1932 | return o.debug_types.items[@intFromEnum(index)]; | |
| 1933 | } | |
| 1934 | ||
| 1935 | /// In codegen logic, instead of calling this directly, use `getDebugType` to get a forward | |
| 1936 | /// reference which will be populated only when all necessary type resolution is complete. | |
| 1937 | fn lowerDebugType( | |
| 1830 | 1938 | o: *Object, |
| 1831 | 1939 | pt: Zcu.PerThread, |
| 1832 | 1940 | ty: Type, |
| 1941 | ty_fwd_ref: Builder.Metadata, | |
| 1833 | 1942 | ) Allocator.Error!Builder.Metadata { |
| 1834 | 1943 | assert(!o.builder.strip); |
| 1835 | 1944 | |
| ... | ... | @@ -1838,312 +1947,137 @@ pub const Object = struct { |
| 1838 | 1947 | const zcu = pt.zcu; |
| 1839 | 1948 | const ip = &zcu.intern_pool; |
| 1840 | 1949 | |
| 1841 | if (o.debug_type_map.get(ty.toIntern())) |debug_type| return debug_type; | |
| 1950 | const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); | |
| 1951 | ||
| 1952 | // lldb cannot handle non-byte-sized types, so in the logic below, bit sizes are padded up. | |
| 1953 | // For instance, `bool` is considered to be 8 bits, and `u60` is considered to be 64 bits. | |
| 1954 | ||
| 1955 | // I tried using variants (DW_TAG_variant_part + DW_TAG_variant) to encode error unions, | |
| 1956 | // tagged unions, etc; this would have told debuggers which field was active, which could | |
| 1957 | // improve UX significantly. GDB handles this perfectly fine, but unfortunately, LLDB has no | |
| 1958 | // handling for variants at all, and will never print fields in them, so I opted not to use | |
| 1959 | // them for now. | |
| 1842 | 1960 | |
| 1843 | 1961 | switch (ty.zigTypeTag(zcu)) { |
| 1844 | 1962 | .void, |
| 1845 | 1963 | .noreturn, |
| 1846 | => { | |
| 1847 | const debug_void_type = try o.builder.debugSignedType( | |
| 1848 | try o.builder.metadataString("void"), | |
| 1849 | 0, | |
| 1850 | ); | |
| 1851 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_void_type); | |
| 1852 | return debug_void_type; | |
| 1853 | }, | |
| 1964 | .comptime_int, | |
| 1965 | .comptime_float, | |
| 1966 | .type, | |
| 1967 | .undefined, | |
| 1968 | .null, | |
| 1969 | .enum_literal, | |
| 1970 | => return o.builder.debugSignedType(name, 0), | |
| 1971 | ||
| 1972 | .float => return o.builder.debugFloatType(name, ty.floatBits(target)), | |
| 1973 | ||
| 1974 | .bool => return o.builder.debugBoolType(name, 8), | |
| 1975 | ||
| 1854 | 1976 | .int => { |
| 1855 | 1977 | const info = ty.intInfo(zcu); |
| 1856 | assert(info.bits != 0); | |
| 1857 | const name = try o.allocTypeName(pt, ty); | |
| 1858 | defer gpa.free(name); | |
| 1859 | const builder_name = try o.builder.metadataString(name); | |
| 1860 | const debug_bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types | |
| 1861 | const debug_int_type = switch (info.signedness) { | |
| 1862 | .signed => try o.builder.debugSignedType(builder_name, debug_bits), | |
| 1863 | .unsigned => try o.builder.debugUnsignedType(builder_name, debug_bits), | |
| 1978 | const bits = ty.abiSize(zcu) * 8; | |
| 1979 | return switch (info.signedness) { | |
| 1980 | .signed => try o.builder.debugSignedType(name, bits), | |
| 1981 | .unsigned => try o.builder.debugUnsignedType(name, bits), | |
| 1864 | 1982 | }; |
| 1865 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_int_type); | |
| 1866 | return debug_int_type; | |
| 1867 | 1983 | }, |
| 1868 | .@"enum" => { | |
| 1869 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1870 | const debug_enum_type = try o.makeEmptyNamespaceDebugType(pt, ty); | |
| 1871 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_enum_type); | |
| 1872 | return debug_enum_type; | |
| 1873 | } | |
| 1874 | ||
| 1875 | const enum_type = ip.loadEnumType(ty.toIntern()); | |
| 1876 | const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); | |
| 1877 | defer gpa.free(enumerators); | |
| 1878 | ||
| 1879 | const int_ty = Type.fromInterned(enum_type.tag_ty); | |
| 1880 | const int_info = ty.intInfo(zcu); | |
| 1881 | assert(int_info.bits != 0); | |
| 1882 | ||
| 1883 | for (enum_type.names.get(ip), 0..) |field_name_ip, i| { | |
| 1884 | var bigint_space: Value.BigIntSpace = undefined; | |
| 1885 | const bigint = if (enum_type.values.len != 0) | |
| 1886 | Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, zcu) | |
| 1887 | else | |
| 1888 | std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); | |
| 1889 | ||
| 1890 | enumerators[i] = try o.builder.debugEnumerator( | |
| 1891 | try o.builder.metadataString(field_name_ip.toSlice(ip)), | |
| 1892 | int_info.signedness == .unsigned, | |
| 1893 | int_info.bits, | |
| 1894 | bigint, | |
| 1895 | ); | |
| 1896 | } | |
| 1897 | ||
| 1898 | const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); | |
| 1899 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 1900 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 1901 | else | |
| 1902 | file; | |
| 1903 | ||
| 1904 | const name = try o.allocTypeName(pt, ty); | |
| 1905 | defer gpa.free(name); | |
| 1906 | ||
| 1907 | const debug_enum_type = try o.builder.debugEnumerationType( | |
| 1908 | try o.builder.metadataString(name), | |
| 1909 | file, | |
| 1910 | scope, | |
| 1911 | ty.typeDeclSrcLine(zcu).? + 1, // Line | |
| 1912 | try o.lowerDebugType(pt, int_ty), | |
| 1913 | ty.abiSize(zcu) * 8, | |
| 1914 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 1915 | try o.builder.metadataTuple(enumerators), | |
| 1916 | ); | |
| 1917 | 1984 | |
| 1918 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_enum_type); | |
| 1919 | try o.debug_enums.append(gpa, debug_enum_type); | |
| 1920 | return debug_enum_type; | |
| 1921 | }, | |
| 1922 | .float => { | |
| 1923 | const bits = ty.floatBits(target); | |
| 1924 | const name = try o.allocTypeName(pt, ty); | |
| 1925 | defer gpa.free(name); | |
| 1926 | const debug_float_type = try o.builder.debugFloatType( | |
| 1927 | try o.builder.metadataString(name), | |
| 1928 | bits, | |
| 1929 | ); | |
| 1930 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_float_type); | |
| 1931 | return debug_float_type; | |
| 1932 | }, | |
| 1933 | .bool => { | |
| 1934 | const debug_bool_type = try o.builder.debugBoolType( | |
| 1935 | try o.builder.metadataString("bool"), | |
| 1936 | 8, // lldb cannot handle non-byte sized types | |
| 1937 | ); | |
| 1938 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type); | |
| 1939 | return debug_bool_type; | |
| 1940 | }, | |
| 1941 | 1985 | .pointer => { |
| 1942 | // Normalize everything that the debug info does not represent. | |
| 1943 | const ptr_info = ty.ptrInfo(zcu); | |
| 1944 | ||
| 1945 | if (ptr_info.sentinel != .none or | |
| 1946 | ptr_info.flags.address_space != .generic or | |
| 1947 | ptr_info.packed_offset.bit_offset != 0 or | |
| 1948 | ptr_info.packed_offset.host_size != 0 or | |
| 1949 | ptr_info.flags.vector_index != .none or | |
| 1950 | ptr_info.flags.is_allowzero or | |
| 1951 | ptr_info.flags.is_const or | |
| 1952 | ptr_info.flags.is_volatile or | |
| 1953 | ptr_info.flags.size == .many or ptr_info.flags.size == .c or | |
| 1954 | !Type.fromInterned(ptr_info.child).hasRuntimeBitsIgnoreComptime(zcu)) | |
| 1955 | { | |
| 1956 | const bland_ptr_ty = try pt.ptrType(.{ | |
| 1957 | .child = if (!Type.fromInterned(ptr_info.child).hasRuntimeBitsIgnoreComptime(zcu)) | |
| 1958 | .anyopaque_type | |
| 1959 | else | |
| 1960 | ptr_info.child, | |
| 1961 | .flags = .{ | |
| 1962 | .alignment = ptr_info.flags.alignment, | |
| 1963 | .size = switch (ptr_info.flags.size) { | |
| 1964 | .many, .c, .one => .one, | |
| 1965 | .slice => .slice, | |
| 1966 | }, | |
| 1967 | }, | |
| 1968 | }); | |
| 1969 | const debug_ptr_type = try o.lowerDebugType(pt, bland_ptr_ty); | |
| 1970 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_ptr_type); | |
| 1971 | return debug_ptr_type; | |
| 1972 | } | |
| 1973 | ||
| 1974 | const debug_fwd_ref = try o.builder.debugForwardReference(); | |
| 1975 | ||
| 1976 | // Set as forward reference while the type is lowered in case it references itself | |
| 1977 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); | |
| 1986 | const ptr_size = Type.ptrAbiSize(zcu.getTarget()); | |
| 1987 | const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); | |
| 1978 | 1988 | |
| 1979 | 1989 | if (ty.isSlice(zcu)) { |
| 1980 | const ptr_ty = ty.slicePtrFieldType(zcu); | |
| 1981 | const len_ty = Type.usize; | |
| 1982 | ||
| 1983 | const name = try o.allocTypeName(pt, ty); | |
| 1984 | defer gpa.free(name); | |
| 1985 | const line = 0; | |
| 1986 | ||
| 1987 | const ptr_size = ptr_ty.abiSize(zcu); | |
| 1988 | const ptr_align = ptr_ty.abiAlignment(zcu); | |
| 1989 | const len_size = len_ty.abiSize(zcu); | |
| 1990 | const len_align = len_ty.abiAlignment(zcu); | |
| 1991 | ||
| 1992 | const len_offset = len_align.forward(ptr_size); | |
| 1993 | ||
| 1994 | 1990 | const debug_ptr_type = try o.builder.debugMemberType( |
| 1995 | 1991 | try o.builder.metadataString("ptr"), |
| 1996 | null, // File | |
| 1997 | debug_fwd_ref, | |
| 1998 | 0, // Line | |
| 1999 | try o.lowerDebugType(pt, ptr_ty), | |
| 1992 | null, // file | |
| 1993 | ty_fwd_ref, | |
| 1994 | 0, // line | |
| 1995 | try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), | |
| 2000 | 1996 | ptr_size * 8, |
| 2001 | (ptr_align.toByteUnits() orelse 0) * 8, | |
| 2002 | 0, // Offset | |
| 1997 | ptr_align.toByteUnits().? * 8, | |
| 1998 | 0, // offset | |
| 2003 | 1999 | ); |
| 2004 | 2000 | |
| 2005 | 2001 | const debug_len_type = try o.builder.debugMemberType( |
| 2006 | 2002 | try o.builder.metadataString("len"), |
| 2007 | null, // File | |
| 2008 | debug_fwd_ref, | |
| 2009 | 0, // Line | |
| 2010 | try o.lowerDebugType(pt, len_ty), | |
| 2011 | len_size * 8, | |
| 2012 | (len_align.toByteUnits() orelse 0) * 8, | |
| 2013 | len_offset * 8, | |
| 2003 | null, // file | |
| 2004 | ty_fwd_ref, | |
| 2005 | 0, // line | |
| 2006 | try o.getDebugType(pt, .usize), | |
| 2007 | ptr_size * 8, | |
| 2008 | ptr_align.toByteUnits().? * 8, | |
| 2009 | ptr_size * 8, | |
| 2014 | 2010 | ); |
| 2015 | 2011 | |
| 2016 | const debug_slice_type = try o.builder.debugStructType( | |
| 2017 | try o.builder.metadataString(name), | |
| 2018 | null, // File | |
| 2019 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2020 | line, | |
| 2021 | null, // Underlying type | |
| 2022 | ty.abiSize(zcu) * 8, | |
| 2023 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2012 | return o.builder.debugStructType( | |
| 2013 | name, | |
| 2014 | null, // file | |
| 2015 | o.debug_compile_unit.unwrap().?, // scope | |
| 2016 | 0, // line | |
| 2017 | null, // underlying type | |
| 2018 | ptr_size * 2 * 8, | |
| 2019 | ptr_align.toByteUnits().? * 8, | |
| 2024 | 2020 | try o.builder.metadataTuple(&.{ |
| 2025 | 2021 | debug_ptr_type, |
| 2026 | 2022 | debug_len_type, |
| 2027 | 2023 | }), |
| 2028 | 2024 | ); |
| 2029 | ||
| 2030 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_slice_type); | |
| 2031 | ||
| 2032 | // Set to real type now that it has been lowered fully | |
| 2033 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2034 | map_ptr.* = debug_slice_type; | |
| 2035 | ||
| 2036 | return debug_slice_type; | |
| 2037 | 2025 | } |
| 2038 | 2026 | |
| 2039 | const debug_elem_ty = try o.lowerDebugType(pt, Type.fromInterned(ptr_info.child)); | |
| 2040 | ||
| 2041 | const name = try o.allocTypeName(pt, ty); | |
| 2042 | defer gpa.free(name); | |
| 2043 | ||
| 2044 | const debug_ptr_type = try o.builder.debugPointerType( | |
| 2045 | try o.builder.metadataString(name), | |
| 2046 | null, // File | |
| 2047 | null, // Scope | |
| 2048 | 0, // Line | |
| 2049 | debug_elem_ty, | |
| 2050 | target.ptrBitWidth(), | |
| 2051 | (ty.ptrAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2052 | 0, // Offset | |
| 2027 | return o.builder.debugPointerType( | |
| 2028 | name, | |
| 2029 | null, // file | |
| 2030 | o.debug_compile_unit.unwrap().?, // scope | |
| 2031 | 0, // line | |
| 2032 | try o.getDebugType(pt, ty.childType(zcu)), | |
| 2033 | ptr_size * 8, | |
| 2034 | ptr_align.toByteUnits().? * 8, | |
| 2035 | 0, // offset | |
| 2053 | 2036 | ); |
| 2054 | ||
| 2055 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_ptr_type); | |
| 2056 | ||
| 2057 | // Set to real type now that it has been lowered fully | |
| 2058 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2059 | map_ptr.* = debug_ptr_type; | |
| 2060 | ||
| 2061 | return debug_ptr_type; | |
| 2062 | }, | |
| 2063 | .@"opaque" => { | |
| 2064 | if (ty.toIntern() == .anyopaque_type) { | |
| 2065 | const debug_opaque_type = try o.builder.debugSignedType( | |
| 2066 | try o.builder.metadataString("anyopaque"), | |
| 2067 | 0, | |
| 2068 | ); | |
| 2069 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_opaque_type); | |
| 2070 | return debug_opaque_type; | |
| 2071 | } | |
| 2072 | ||
| 2073 | const name = try o.allocTypeName(pt, ty); | |
| 2074 | defer gpa.free(name); | |
| 2075 | ||
| 2076 | const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); | |
| 2077 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2078 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 2079 | else | |
| 2080 | file; | |
| 2081 | ||
| 2082 | const debug_opaque_type = try o.builder.debugStructType( | |
| 2083 | try o.builder.metadataString(name), | |
| 2084 | file, | |
| 2085 | scope, | |
| 2086 | ty.typeDeclSrcLine(zcu).? + 1, // Line | |
| 2087 | null, // Underlying type | |
| 2088 | 0, // Size | |
| 2089 | 0, // Align | |
| 2090 | null, // Fields | |
| 2091 | ); | |
| 2092 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_opaque_type); | |
| 2093 | return debug_opaque_type; | |
| 2094 | }, | |
| 2095 | .array => { | |
| 2096 | const debug_array_type = try o.builder.debugArrayType( | |
| 2097 | null, // Name | |
| 2098 | null, // File | |
| 2099 | null, // Scope | |
| 2100 | 0, // Line | |
| 2101 | try o.lowerDebugType(pt, ty.childType(zcu)), | |
| 2102 | ty.abiSize(zcu) * 8, | |
| 2103 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2104 | try o.builder.metadataTuple(&.{ | |
| 2105 | try o.builder.debugSubrange( | |
| 2106 | try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), | |
| 2107 | try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))), | |
| 2108 | ), | |
| 2109 | }), | |
| 2110 | ); | |
| 2111 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_array_type); | |
| 2112 | return debug_array_type; | |
| 2113 | 2037 | }, |
| 2038 | .array => return o.builder.debugArrayType( | |
| 2039 | name, | |
| 2040 | null, // file | |
| 2041 | o.debug_compile_unit.unwrap().?, // scope | |
| 2042 | 0, // line | |
| 2043 | try o.getDebugType(pt, ty.childType(zcu)), | |
| 2044 | ty.abiSize(zcu) * 8, | |
| 2045 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2046 | try o.builder.metadataTuple(&.{ | |
| 2047 | try o.builder.debugSubrange( | |
| 2048 | try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), | |
| 2049 | try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))), | |
| 2050 | ), | |
| 2051 | }), | |
| 2052 | ), | |
| 2114 | 2053 | .vector => { |
| 2115 | const elem_ty = ty.elemType2(zcu); | |
| 2054 | const elem_ty = ty.childType(zcu); | |
| 2116 | 2055 | // Vector elements cannot be padded since that would make |
| 2117 | // @bitSizOf(elem) * len > @bitSizOf(vec). | |
| 2056 | // @bitSizeOf(elem) * len > @bitSizOf(vec). | |
| 2118 | 2057 | // Neither gdb nor lldb seem to be able to display non-byte sized |
| 2119 | 2058 | // vectors properly. |
| 2120 | 2059 | const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) { |
| 2121 | 2060 | .int => blk: { |
| 2122 | 2061 | const info = elem_ty.intInfo(zcu); |
| 2123 | assert(info.bits != 0); | |
| 2124 | const name = try o.allocTypeName(pt, ty); | |
| 2125 | defer gpa.free(name); | |
| 2126 | const builder_name = try o.builder.metadataString(name); | |
| 2127 | 2062 | break :blk switch (info.signedness) { |
| 2128 | .signed => try o.builder.debugSignedType(builder_name, info.bits), | |
| 2129 | .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits), | |
| 2063 | .signed => try o.builder.debugSignedType(name, info.bits), | |
| 2064 | .unsigned => try o.builder.debugUnsignedType(name, info.bits), | |
| 2130 | 2065 | }; |
| 2131 | 2066 | }, |
| 2132 | .bool => try o.builder.debugBoolType( | |
| 2133 | try o.builder.metadataString("bool"), | |
| 2134 | 1, | |
| 2135 | ), | |
| 2136 | else => try o.lowerDebugType(pt, ty.childType(zcu)), | |
| 2067 | .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1), | |
| 2068 | // We don't pad pointers or floats, so we can lower those normally. | |
| 2069 | .pointer, .optional, .float => try o.getDebugType(pt, elem_ty), | |
| 2070 | else => unreachable, | |
| 2137 | 2071 | }; |
| 2138 | 2072 | |
| 2139 | const debug_vector_type = try o.builder.debugVectorType( | |
| 2140 | null, // Name | |
| 2141 | null, // File | |
| 2142 | null, // Scope | |
| 2143 | 0, // Line | |
| 2073 | return o.builder.debugVectorType( | |
| 2074 | name, | |
| 2075 | null, // file | |
| 2076 | o.debug_compile_unit.unwrap().?, // scope | |
| 2077 | 0, // line | |
| 2144 | 2078 | debug_elem_type, |
| 2145 | 2079 | ty.abiSize(zcu) * 8, |
| 2146 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2080 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2147 | 2081 | try o.builder.metadataTuple(&.{ |
| 2148 | 2082 | try o.builder.debugSubrange( |
| 2149 | 2083 | try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), |
| ... | ... | @@ -2151,566 +2085,574 @@ pub const Object = struct { |
| 2151 | 2085 | ), |
| 2152 | 2086 | }), |
| 2153 | 2087 | ); |
| 2154 | ||
| 2155 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_vector_type); | |
| 2156 | return debug_vector_type; | |
| 2157 | 2088 | }, |
| 2158 | 2089 | .optional => { |
| 2159 | const name = try o.allocTypeName(pt, ty); | |
| 2160 | defer gpa.free(name); | |
| 2161 | const child_ty = ty.optionalChild(zcu); | |
| 2162 | if (!child_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2163 | const debug_bool_type = try o.builder.debugBoolType( | |
| 2164 | try o.builder.metadataString(name), | |
| 2165 | 8, | |
| 2090 | const payload_ty = ty.optionalChild(zcu); | |
| 2091 | if (ty.optionalReprIsPayload(zcu)) { | |
| 2092 | return o.builder.debugTypedefType( | |
| 2093 | name, | |
| 2094 | null, // file | |
| 2095 | o.debug_compile_unit.unwrap().?, // scope | |
| 2096 | 0, // line | |
| 2097 | try o.getDebugType(pt, payload_ty), | |
| 2098 | ty.abiSize(zcu) * 8, | |
| 2099 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2100 | 0, // offset | |
| 2166 | 2101 | ); |
| 2167 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type); | |
| 2168 | return debug_bool_type; | |
| 2169 | 2102 | } |
| 2170 | 2103 | |
| 2171 | const debug_fwd_ref = try o.builder.debugForwardReference(); | |
| 2172 | ||
| 2173 | // Set as forward reference while the type is lowered in case it references itself | |
| 2174 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); | |
| 2175 | ||
| 2176 | if (ty.optionalReprIsPayload(zcu)) { | |
| 2177 | const debug_optional_type = try o.lowerDebugType(pt, child_ty); | |
| 2178 | ||
| 2179 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_optional_type); | |
| 2180 | ||
| 2181 | // Set to real type now that it has been lowered fully | |
| 2182 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2183 | map_ptr.* = debug_optional_type; | |
| 2184 | ||
| 2185 | return debug_optional_type; | |
| 2186 | } | |
| 2104 | const payload_size = payload_ty.abiSize(zcu); | |
| 2187 | 2105 | |
| 2188 | 2106 | const non_null_ty = Type.u8; |
| 2189 | const payload_size = child_ty.abiSize(zcu); | |
| 2190 | const payload_align = child_ty.abiAlignment(zcu); | |
| 2191 | 2107 | const non_null_size = non_null_ty.abiSize(zcu); |
| 2192 | 2108 | const non_null_align = non_null_ty.abiAlignment(zcu); |
| 2193 | 2109 | const non_null_offset = non_null_align.forward(payload_size); |
| 2194 | 2110 | |
| 2195 | const debug_data_type = try o.builder.debugMemberType( | |
| 2196 | try o.builder.metadataString("data"), | |
| 2197 | null, // File | |
| 2198 | debug_fwd_ref, | |
| 2199 | 0, // Line | |
| 2200 | try o.lowerDebugType(pt, child_ty), | |
| 2111 | const debug_payload_type = try o.builder.debugMemberType( | |
| 2112 | try o.builder.metadataString("payload"), | |
| 2113 | null, // file | |
| 2114 | ty_fwd_ref, // scope | |
| 2115 | 0, // line | |
| 2116 | try o.getDebugType(pt, payload_ty), | |
| 2201 | 2117 | payload_size * 8, |
| 2202 | (payload_align.toByteUnits() orelse 0) * 8, | |
| 2203 | 0, // Offset | |
| 2118 | payload_ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2119 | 0, // offset | |
| 2204 | 2120 | ); |
| 2205 | 2121 | |
| 2206 | 2122 | const debug_some_type = try o.builder.debugMemberType( |
| 2207 | 2123 | try o.builder.metadataString("some"), |
| 2208 | 2124 | null, |
| 2209 | debug_fwd_ref, | |
| 2125 | ty_fwd_ref, | |
| 2210 | 2126 | 0, |
| 2211 | try o.lowerDebugType(pt, non_null_ty), | |
| 2127 | try o.getDebugType(pt, non_null_ty), | |
| 2212 | 2128 | non_null_size * 8, |
| 2213 | (non_null_align.toByteUnits() orelse 0) * 8, | |
| 2129 | non_null_align.toByteUnits().? * 8, | |
| 2214 | 2130 | non_null_offset * 8, |
| 2215 | 2131 | ); |
| 2216 | 2132 | |
| 2217 | const debug_optional_type = try o.builder.debugStructType( | |
| 2218 | try o.builder.metadataString(name), | |
| 2219 | null, // File | |
| 2220 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2221 | 0, // Line | |
| 2222 | null, // Underlying type | |
| 2133 | return o.builder.debugStructType( | |
| 2134 | name, | |
| 2135 | null, // file | |
| 2136 | o.debug_compile_unit.unwrap().?, // scope | |
| 2137 | 0, // line | |
| 2138 | null, // underlying type | |
| 2223 | 2139 | ty.abiSize(zcu) * 8, |
| 2224 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2140 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2225 | 2141 | try o.builder.metadataTuple(&.{ |
| 2226 | debug_data_type, | |
| 2142 | debug_payload_type, | |
| 2227 | 2143 | debug_some_type, |
| 2228 | 2144 | }), |
| 2229 | 2145 | ); |
| 2230 | ||
| 2231 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_optional_type); | |
| 2232 | ||
| 2233 | // Set to real type now that it has been lowered fully | |
| 2234 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2235 | map_ptr.* = debug_optional_type; | |
| 2236 | ||
| 2237 | return debug_optional_type; | |
| 2238 | 2146 | }, |
| 2239 | 2147 | .error_union => { |
| 2148 | const error_ty = ty.errorUnionSet(zcu); | |
| 2240 | 2149 | const payload_ty = ty.errorUnionPayload(zcu); |
| 2241 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2242 | // TODO: Maybe remove? | |
| 2243 | const debug_error_union_type = try o.lowerDebugType(pt, Type.anyerror); | |
| 2244 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_union_type); | |
| 2245 | return debug_error_union_type; | |
| 2246 | } | |
| 2247 | ||
| 2248 | const name = try o.allocTypeName(pt, ty); | |
| 2249 | defer gpa.free(name); | |
| 2250 | 2150 | |
| 2251 | const error_size = Type.anyerror.abiSize(zcu); | |
| 2252 | const error_align = Type.anyerror.abiAlignment(zcu); | |
| 2151 | const error_size = error_ty.abiSize(zcu); | |
| 2152 | const error_align = error_ty.abiAlignment(zcu); | |
| 2253 | 2153 | const payload_size = payload_ty.abiSize(zcu); |
| 2254 | 2154 | const payload_align = payload_ty.abiAlignment(zcu); |
| 2255 | 2155 | |
| 2256 | var error_index: u32 = undefined; | |
| 2257 | var payload_index: u32 = undefined; | |
| 2258 | var error_offset: u64 = undefined; | |
| 2259 | var payload_offset: u64 = undefined; | |
| 2260 | if (error_align.compare(.gt, payload_align)) { | |
| 2261 | error_index = 0; | |
| 2262 | payload_index = 1; | |
| 2263 | error_offset = 0; | |
| 2264 | payload_offset = payload_align.forward(error_size); | |
| 2265 | } else { | |
| 2266 | payload_index = 0; | |
| 2267 | error_index = 1; | |
| 2268 | payload_offset = 0; | |
| 2269 | error_offset = error_align.forward(payload_size); | |
| 2270 | } | |
| 2271 | ||
| 2272 | const debug_fwd_ref = try o.builder.debugForwardReference(); | |
| 2156 | const error_offset: u64, const payload_offset: u64 = offsets: { | |
| 2157 | if (error_align.compare(.gt, payload_align)) { | |
| 2158 | break :offsets .{ 0, payload_align.forward(error_size) }; | |
| 2159 | } else { | |
| 2160 | break :offsets .{ error_align.forward(payload_size), 0 }; | |
| 2161 | } | |
| 2162 | }; | |
| 2273 | 2163 | |
| 2274 | var fields: [2]Builder.Metadata = undefined; | |
| 2275 | fields[error_index] = try o.builder.debugMemberType( | |
| 2276 | try o.builder.metadataString("tag"), | |
| 2277 | null, // File | |
| 2278 | debug_fwd_ref, | |
| 2279 | 0, // Line | |
| 2280 | try o.lowerDebugType(pt, Type.anyerror), | |
| 2164 | const error_field = try o.builder.debugMemberType( | |
| 2165 | try o.builder.metadataString("error"), | |
| 2166 | null, // file | |
| 2167 | ty_fwd_ref, | |
| 2168 | 0, // line | |
| 2169 | try o.getDebugType(pt, error_ty), | |
| 2281 | 2170 | error_size * 8, |
| 2282 | (error_align.toByteUnits() orelse 0) * 8, | |
| 2171 | error_align.toByteUnits().? * 8, | |
| 2283 | 2172 | error_offset * 8, |
| 2284 | 2173 | ); |
| 2285 | fields[payload_index] = try o.builder.debugMemberType( | |
| 2286 | try o.builder.metadataString("value"), | |
| 2287 | null, // File | |
| 2288 | debug_fwd_ref, | |
| 2289 | 0, // Line | |
| 2290 | try o.lowerDebugType(pt, payload_ty), | |
| 2174 | const payload_field = try o.builder.debugMemberType( | |
| 2175 | try o.builder.metadataString("payload"), | |
| 2176 | null, // file | |
| 2177 | ty_fwd_ref, // scope | |
| 2178 | 0, // line | |
| 2179 | try o.getDebugType(pt, payload_ty), | |
| 2291 | 2180 | payload_size * 8, |
| 2292 | (payload_align.toByteUnits() orelse 0) * 8, | |
| 2181 | payload_align.toByteUnits().? * 8, | |
| 2293 | 2182 | payload_offset * 8, |
| 2294 | 2183 | ); |
| 2295 | 2184 | |
| 2296 | const debug_error_union_type = try o.builder.debugStructType( | |
| 2297 | try o.builder.metadataString(name), | |
| 2185 | return try o.builder.debugStructType( | |
| 2186 | name, | |
| 2298 | 2187 | null, // File |
| 2299 | o.debug_compile_unit.unwrap().?, // Sope | |
| 2188 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2300 | 2189 | 0, // Line |
| 2301 | 2190 | null, // Underlying type |
| 2302 | 2191 | ty.abiSize(zcu) * 8, |
| 2303 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2304 | try o.builder.metadataTuple(&fields), | |
| 2192 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2193 | try o.builder.metadataTuple(&.{ error_field, payload_field }), | |
| 2305 | 2194 | ); |
| 2306 | ||
| 2307 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_error_union_type); | |
| 2308 | ||
| 2309 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_union_type); | |
| 2310 | return debug_error_union_type; | |
| 2311 | 2195 | }, |
| 2312 | 2196 | .error_set => { |
| 2313 | const debug_error_set = try o.builder.debugUnsignedType( | |
| 2314 | try o.builder.metadataString("anyerror"), | |
| 2315 | 16, | |
| 2197 | assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead | |
| 2198 | // Error sets are just named wrappers around `anyerror`. | |
| 2199 | return o.builder.debugTypedefType( | |
| 2200 | name, | |
| 2201 | null, // file | |
| 2202 | o.debug_compile_unit.unwrap().?, // scope | |
| 2203 | 0, // line | |
| 2204 | try o.getDebugType(pt, .anyerror), | |
| 2205 | ty.abiSize(zcu) * 8, | |
| 2206 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2207 | 0, // offset | |
| 2316 | 2208 | ); |
| 2317 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_set); | |
| 2318 | return debug_error_set; | |
| 2319 | 2209 | }, |
| 2320 | .@"struct" => { | |
| 2321 | const name = try o.allocTypeName(pt, ty); | |
| 2322 | defer gpa.free(name); | |
| 2323 | ||
| 2324 | if (zcu.typeToPackedStruct(ty)) |struct_type| { | |
| 2325 | const backing_int_ty = struct_type.backingIntTypeUnordered(ip); | |
| 2326 | if (backing_int_ty != .none) { | |
| 2327 | const info = Type.fromInterned(backing_int_ty).intInfo(zcu); | |
| 2328 | const builder_name = try o.builder.metadataString(name); | |
| 2329 | const debug_int_type = switch (info.signedness) { | |
| 2330 | .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(zcu) * 8), | |
| 2331 | .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(zcu) * 8), | |
| 2332 | }; | |
| 2333 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_int_type); | |
| 2334 | return debug_int_type; | |
| 2335 | } | |
| 2210 | .@"fn" => { | |
| 2211 | if (!ty.fnHasRuntimeBits(zcu)) { | |
| 2212 | return o.builder.debugSignedType(name, 0); | |
| 2336 | 2213 | } |
| 2337 | 2214 | |
| 2338 | switch (ip.indexToKey(ty.toIntern())) { | |
| 2339 | .tuple_type => |tuple| { | |
| 2340 | var fields: std.ArrayList(Builder.Metadata) = .empty; | |
| 2341 | defer fields.deinit(gpa); | |
| 2342 | ||
| 2343 | try fields.ensureUnusedCapacity(gpa, tuple.types.len); | |
| 2215 | const fn_info = zcu.typeToFunc(ty).?; | |
| 2344 | 2216 | |
| 2345 | comptime assert(struct_layout_version == 2); | |
| 2346 | var offset: u64 = 0; | |
| 2217 | var debug_param_types: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, 3 + fn_info.param_types.len); | |
| 2218 | defer debug_param_types.deinit(gpa); | |
| 2347 | 2219 | |
| 2348 | const debug_fwd_ref = try o.builder.debugForwardReference(); | |
| 2220 | // Return type goes first. | |
| 2221 | const sret = firstParamSRet(fn_info, zcu, target); | |
| 2222 | const ret_ty: Type = if (sret) .void else .fromInterned(fn_info.return_type); | |
| 2223 | debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ret_ty)); | |
| 2349 | 2224 | |
| 2350 | for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { | |
| 2351 | if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; | |
| 2225 | if (sret) { | |
| 2226 | const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type)); | |
| 2227 | debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ptr_ty)); | |
| 2228 | } | |
| 2352 | 2229 | |
| 2353 | const field_size = Type.fromInterned(field_ty).abiSize(zcu); | |
| 2354 | const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); | |
| 2355 | const field_offset = field_align.forward(offset); | |
| 2356 | offset = field_offset + field_size; | |
| 2230 | if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) { | |
| 2231 | // Stack trace pointer. | |
| 2232 | debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .ptr_usize)); | |
| 2233 | } | |
| 2357 | 2234 | |
| 2358 | var name_buf: [32]u8 = undefined; | |
| 2359 | const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{i}) catch unreachable; | |
| 2235 | for (fn_info.param_types.get(ip)) |param_ty_ip| { | |
| 2236 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 2237 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 2238 | if (isByRef(param_ty, zcu)) { | |
| 2239 | const ptr_ty = try pt.singleConstPtrType(param_ty); | |
| 2240 | debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ptr_ty)); | |
| 2241 | } else { | |
| 2242 | debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, param_ty)); | |
| 2243 | } | |
| 2244 | } | |
| 2360 | 2245 | |
| 2361 | fields.appendAssumeCapacity(try o.builder.debugMemberType( | |
| 2362 | try o.builder.metadataString(field_name), | |
| 2363 | null, // File | |
| 2364 | debug_fwd_ref, | |
| 2365 | 0, | |
| 2366 | try o.lowerDebugType(pt, Type.fromInterned(field_ty)), | |
| 2367 | field_size * 8, | |
| 2368 | (field_align.toByteUnits() orelse 0) * 8, | |
| 2369 | field_offset * 8, | |
| 2370 | )); | |
| 2371 | } | |
| 2246 | return o.builder.debugSubroutineType( | |
| 2247 | try o.builder.metadataTuple(debug_param_types.items), | |
| 2248 | ); | |
| 2249 | }, | |
| 2250 | .@"struct" => { | |
| 2251 | if (ty.isTuple(zcu)) { | |
| 2252 | const tuple = ip.indexToKey(ty.toIntern()).tuple_type; | |
| 2253 | var fields: std.ArrayList(Builder.Metadata) = .empty; | |
| 2254 | defer fields.deinit(gpa); | |
| 2372 | 2255 | |
| 2373 | const debug_struct_type = try o.builder.debugStructType( | |
| 2374 | try o.builder.metadataString(name), | |
| 2375 | null, // File | |
| 2376 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2377 | 0, // Line | |
| 2378 | null, // Underlying type | |
| 2379 | ty.abiSize(zcu) * 8, | |
| 2380 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2381 | try o.builder.metadataTuple(fields.items), | |
| 2382 | ); | |
| 2256 | try fields.ensureUnusedCapacity(gpa, tuple.types.len); | |
| 2383 | 2257 | |
| 2384 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_struct_type); | |
| 2258 | comptime assert(struct_layout_version == 2); | |
| 2259 | var offset: u64 = 0; | |
| 2385 | 2260 | |
| 2386 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type); | |
| 2387 | return debug_struct_type; | |
| 2388 | }, | |
| 2389 | .struct_type => { | |
| 2390 | if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) { | |
| 2391 | // This can happen if a struct type makes it all the way to | |
| 2392 | // flush() without ever being instantiated or referenced (even | |
| 2393 | // via pointer). The only reason we are hearing about it now is | |
| 2394 | // that it is being used as a namespace to put other debug types | |
| 2395 | // into. Therefore we can satisfy this by making an empty namespace, | |
| 2396 | // rather than changing the frontend to unnecessarily resolve the | |
| 2397 | // struct field types. | |
| 2398 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty); | |
| 2399 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type); | |
| 2400 | return debug_struct_type; | |
| 2401 | } | |
| 2402 | }, | |
| 2403 | else => {}, | |
| 2404 | } | |
| 2261 | for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val, i| { | |
| 2262 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 2263 | if (field_val != .none or !field_ty.hasRuntimeBits(zcu)) continue; | |
| 2264 | ||
| 2265 | const field_size = field_ty.abiSize(zcu); | |
| 2266 | const field_align = field_ty.abiAlignment(zcu); | |
| 2267 | const field_offset = field_align.forward(offset); | |
| 2268 | offset = field_offset + field_size; | |
| 2269 | ||
| 2270 | fields.appendAssumeCapacity(try o.builder.debugMemberType( | |
| 2271 | try o.builder.metadataStringFmt("{d}", .{i}), | |
| 2272 | null, // file | |
| 2273 | ty_fwd_ref, | |
| 2274 | 0, // line | |
| 2275 | try o.getDebugType(pt, field_ty), | |
| 2276 | field_size * 8, | |
| 2277 | field_align.toByteUnits().? * 8, | |
| 2278 | field_offset * 8, | |
| 2279 | )); | |
| 2280 | } | |
| 2405 | 2281 | |
| 2406 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2407 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty); | |
| 2408 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type); | |
| 2409 | return debug_struct_type; | |
| 2282 | return o.builder.debugStructType( | |
| 2283 | name, | |
| 2284 | null, // file | |
| 2285 | o.debug_compile_unit.unwrap().?, | |
| 2286 | 0, // line | |
| 2287 | null, // underlying type | |
| 2288 | ty.abiSize(zcu) * 8, | |
| 2289 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2290 | try o.builder.metadataTuple(fields.items), | |
| 2291 | ); | |
| 2410 | 2292 | } |
| 2411 | 2293 | |
| 2412 | 2294 | const struct_type = zcu.typeToStruct(ty).?; |
| 2413 | 2295 | |
| 2414 | var fields: std.ArrayList(Builder.Metadata) = .empty; | |
| 2415 | defer fields.deinit(gpa); | |
| 2416 | ||
| 2417 | try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len); | |
| 2296 | const file = try o.getDebugFile(pt, struct_type.zir_index.resolveFile(ip)); | |
| 2297 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2298 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 2299 | else | |
| 2300 | file; | |
| 2418 | 2301 | |
| 2419 | const debug_fwd_ref = try o.builder.debugForwardReference(); | |
| 2302 | const line = ty.typeDeclSrcLine(zcu).? + 1; | |
| 2420 | 2303 | |
| 2421 | // Set as forward reference while the type is lowered in case it references itself | |
| 2422 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); | |
| 2304 | var fields: std.ArrayList(Builder.Metadata) = .empty; | |
| 2305 | defer fields.deinit(gpa); | |
| 2423 | 2306 | |
| 2424 | comptime assert(struct_layout_version == 2); | |
| 2425 | var it = struct_type.iterateRuntimeOrder(ip); | |
| 2426 | while (it.next()) |field_index| { | |
| 2427 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 2428 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 2429 | const field_size = field_ty.abiSize(zcu); | |
| 2430 | const field_align = ty.fieldAlignment(field_index, zcu); | |
| 2431 | const field_offset = ty.structFieldOffset(field_index, zcu); | |
| 2432 | const field_name = struct_type.fieldName(ip, field_index); | |
| 2433 | fields.appendAssumeCapacity(try o.builder.debugMemberType( | |
| 2434 | try o.builder.metadataString(field_name.toSlice(ip)), | |
| 2435 | null, // File | |
| 2436 | debug_fwd_ref, | |
| 2437 | 0, // Line | |
| 2438 | try o.lowerDebugType(pt, field_ty), | |
| 2439 | field_size * 8, | |
| 2440 | (field_align.toByteUnits() orelse 0) * 8, | |
| 2441 | field_offset * 8, | |
| 2442 | )); | |
| 2307 | switch (struct_type.layout) { | |
| 2308 | .@"packed" => { | |
| 2309 | try fields.ensureTotalCapacityPrecise(gpa, 1); | |
| 2310 | fields.appendAssumeCapacity(try o.builder.debugMemberType( | |
| 2311 | try o.builder.metadataString("bits"), | |
| 2312 | null, // file | |
| 2313 | ty_fwd_ref, | |
| 2314 | 0, // line | |
| 2315 | try o.getDebugType(pt, .fromInterned(struct_type.packed_backing_int_type)), | |
| 2316 | ty.abiSize(zcu) * 8, | |
| 2317 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2318 | 0, // offset | |
| 2319 | )); | |
| 2320 | }, | |
| 2321 | .auto, .@"extern" => { | |
| 2322 | comptime assert(struct_layout_version == 2); | |
| 2323 | try fields.ensureTotalCapacityPrecise(gpa, struct_type.field_types.len); | |
| 2324 | var it = struct_type.iterateRuntimeOrder(ip); | |
| 2325 | while (it.next()) |field_index| { | |
| 2326 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 2327 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 2328 | const field_size = field_ty.abiSize(zcu); | |
| 2329 | const field_align = switch (ty.explicitFieldAlignment(field_index, zcu)) { | |
| 2330 | .none => field_ty.abiAlignment(zcu), | |
| 2331 | else => |a| a, | |
| 2332 | }; | |
| 2333 | const field_offset = struct_type.field_offsets.get(ip)[field_index]; | |
| 2334 | const field_name = struct_type.field_names.get(ip)[field_index]; | |
| 2335 | fields.appendAssumeCapacity(try o.builder.debugMemberType( | |
| 2336 | try o.builder.metadataString(field_name.toSlice(ip)), | |
| 2337 | null, // file | |
| 2338 | ty_fwd_ref, | |
| 2339 | 0, // line | |
| 2340 | try o.getDebugType(pt, field_ty), | |
| 2341 | field_size * 8, | |
| 2342 | field_align.toByteUnits().? * 8, | |
| 2343 | field_offset * 8, | |
| 2344 | )); | |
| 2345 | } | |
| 2346 | }, | |
| 2443 | 2347 | } |
| 2444 | 2348 | |
| 2445 | const debug_struct_type = try o.builder.debugStructType( | |
| 2446 | try o.builder.metadataString(name), | |
| 2447 | null, // File | |
| 2448 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2449 | 0, // Line | |
| 2450 | null, // Underlying type | |
| 2349 | return o.builder.debugStructType( | |
| 2350 | name, | |
| 2351 | file, | |
| 2352 | scope, | |
| 2353 | line, | |
| 2354 | null, // underlying type | |
| 2451 | 2355 | ty.abiSize(zcu) * 8, |
| 2452 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2356 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2453 | 2357 | try o.builder.metadataTuple(fields.items), |
| 2454 | 2358 | ); |
| 2455 | ||
| 2456 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_struct_type); | |
| 2457 | ||
| 2458 | // Set to real type now that it has been lowered fully | |
| 2459 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2460 | map_ptr.* = debug_struct_type; | |
| 2461 | ||
| 2462 | return debug_struct_type; | |
| 2463 | 2359 | }, |
| 2464 | 2360 | .@"union" => { |
| 2465 | const name = try o.allocTypeName(pt, ty); | |
| 2466 | defer gpa.free(name); | |
| 2467 | ||
| 2468 | 2361 | const union_type = ip.loadUnionType(ty.toIntern()); |
| 2469 | if (!union_type.haveFieldTypes(ip) or | |
| 2470 | !ty.hasRuntimeBitsIgnoreComptime(zcu) or | |
| 2471 | !union_type.haveLayout(ip)) | |
| 2472 | { | |
| 2473 | const debug_union_type = try o.makeEmptyNamespaceDebugType(pt, ty); | |
| 2474 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_union_type); | |
| 2475 | return debug_union_type; | |
| 2476 | } | |
| 2477 | 2362 | |
| 2478 | const layout = Type.getUnionLayout(union_type, zcu); | |
| 2363 | const file = try o.getDebugFile(pt, union_type.zir_index.resolveFile(ip)); | |
| 2364 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2365 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 2366 | else | |
| 2367 | file; | |
| 2479 | 2368 | |
| 2480 | const debug_fwd_ref = try o.builder.debugForwardReference(); | |
| 2369 | const line = ty.typeDeclSrcLine(zcu).? + 1; | |
| 2481 | 2370 | |
| 2482 | // Set as forward reference while the type is lowered in case it references itself | |
| 2483 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); | |
| 2371 | const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); | |
| 2484 | 2372 | |
| 2485 | if (layout.payload_size == 0) { | |
| 2486 | const debug_union_type = try o.builder.debugStructType( | |
| 2487 | try o.builder.metadataString(name), | |
| 2488 | null, // File | |
| 2489 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2490 | 0, // Line | |
| 2491 | null, // Underlying type | |
| 2373 | if (union_type.layout == .@"packed") { | |
| 2374 | const bitpack_field = try o.builder.debugMemberType( | |
| 2375 | try o.builder.metadataString("bits"), | |
| 2376 | null, // file | |
| 2377 | ty_fwd_ref, | |
| 2378 | 0, // line | |
| 2379 | try o.getDebugType(pt, .fromInterned(union_type.packed_backing_int_type)), | |
| 2492 | 2380 | ty.abiSize(zcu) * 8, |
| 2493 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2494 | try o.builder.metadataTuple( | |
| 2495 | &.{try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty))}, | |
| 2496 | ), | |
| 2381 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2382 | 0, // offset | |
| 2497 | 2383 | ); |
| 2384 | return o.builder.debugStructType( | |
| 2385 | name, | |
| 2386 | file, | |
| 2387 | scope, | |
| 2388 | line, | |
| 2389 | null, // underlying type | |
| 2390 | ty.abiSize(zcu) * 8, | |
| 2391 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2392 | try o.builder.metadataTuple(&.{bitpack_field}), | |
| 2393 | ); | |
| 2394 | } | |
| 2498 | 2395 | |
| 2499 | // Set to real type now that it has been lowered fully | |
| 2500 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2501 | map_ptr.* = debug_union_type; | |
| 2396 | const layout = Type.getUnionLayout(union_type, zcu); | |
| 2502 | 2397 | |
| 2503 | return debug_union_type; | |
| 2398 | if (layout.payload_size == 0) { | |
| 2399 | const fields_tuple: ?Builder.Metadata = fields: { | |
| 2400 | if (layout.tag_size == 0) break :fields null; | |
| 2401 | break :fields try o.builder.metadataTuple(&.{ | |
| 2402 | try o.builder.debugMemberType( | |
| 2403 | try o.builder.metadataString("tag"), | |
| 2404 | null, // file | |
| 2405 | ty_fwd_ref, | |
| 2406 | 0, // line | |
| 2407 | try o.getDebugType(pt, enum_tag_ty), | |
| 2408 | layout.tag_size * 8, | |
| 2409 | layout.tag_align.toByteUnits().? * 8, | |
| 2410 | 0, // offset | |
| 2411 | ), | |
| 2412 | }); | |
| 2413 | }; | |
| 2414 | return o.builder.debugStructType( | |
| 2415 | name, | |
| 2416 | file, | |
| 2417 | scope, | |
| 2418 | line, | |
| 2419 | null, // underlying type | |
| 2420 | ty.abiSize(zcu) * 8, | |
| 2421 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2422 | fields_tuple, | |
| 2423 | ); | |
| 2504 | 2424 | } |
| 2505 | 2425 | |
| 2506 | var fields: std.ArrayList(Builder.Metadata) = .empty; | |
| 2426 | var fields: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, union_type.field_types.len); | |
| 2507 | 2427 | defer fields.deinit(gpa); |
| 2508 | 2428 | |
| 2509 | try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len); | |
| 2510 | ||
| 2511 | const debug_union_fwd_ref = if (layout.tag_size == 0) | |
| 2512 | debug_fwd_ref | |
| 2429 | const payload_fwd_ref = if (layout.tag_size == 0) | |
| 2430 | ty_fwd_ref | |
| 2513 | 2431 | else |
| 2514 | 2432 | try o.builder.debugForwardReference(); |
| 2515 | 2433 | |
| 2516 | const tag_type = union_type.loadTagType(ip); | |
| 2517 | ||
| 2518 | for (0..tag_type.names.len) |field_index| { | |
| 2434 | for (0..union_type.field_types.len) |field_index| { | |
| 2519 | 2435 | const field_ty = union_type.field_types.get(ip)[field_index]; |
| 2520 | if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 2521 | 2436 | |
| 2522 | 2437 | const field_size = Type.fromInterned(field_ty).abiSize(zcu); |
| 2523 | const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) { | |
| 2524 | .@"packed" => .none, | |
| 2525 | .auto, .@"extern" => ty.fieldAlignment(field_index, zcu), | |
| 2526 | }; | |
| 2438 | const field_align: InternPool.Alignment = ty.explicitFieldAlignment(field_index, zcu); | |
| 2527 | 2439 | |
| 2528 | const field_name = tag_type.names.get(ip)[field_index]; | |
| 2440 | const field_name = enum_tag_ty.enumFieldName(field_index, zcu); | |
| 2529 | 2441 | fields.appendAssumeCapacity(try o.builder.debugMemberType( |
| 2530 | 2442 | try o.builder.metadataString(field_name.toSlice(ip)), |
| 2531 | null, // File | |
| 2532 | debug_union_fwd_ref, | |
| 2533 | 0, // Line | |
| 2534 | try o.lowerDebugType(pt, Type.fromInterned(field_ty)), | |
| 2443 | null, // file | |
| 2444 | payload_fwd_ref, | |
| 2445 | 0, // line | |
| 2446 | try o.getDebugType(pt, .fromInterned(field_ty)), | |
| 2535 | 2447 | field_size * 8, |
| 2536 | 2448 | (field_align.toByteUnits() orelse 0) * 8, |
| 2537 | 0, // Offset | |
| 2449 | 0, // offset | |
| 2538 | 2450 | )); |
| 2539 | 2451 | } |
| 2540 | 2452 | |
| 2541 | var union_name_buf: ?[:0]const u8 = null; | |
| 2542 | defer if (union_name_buf) |buf| gpa.free(buf); | |
| 2543 | const union_name = if (layout.tag_size == 0) name else name: { | |
| 2544 | union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0); | |
| 2545 | break :name union_name_buf.?; | |
| 2546 | }; | |
| 2547 | ||
| 2548 | const debug_union_type = try o.builder.debugUnionType( | |
| 2549 | try o.builder.metadataString(union_name), | |
| 2550 | null, // File | |
| 2551 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2552 | 0, // Line | |
| 2553 | null, // Underlying type | |
| 2453 | const debug_payload_type = try o.builder.debugUnionType( | |
| 2454 | payload_name: { | |
| 2455 | if (layout.tag_size == 0) break :payload_name name; | |
| 2456 | break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(pt)}); | |
| 2457 | }, | |
| 2458 | file, | |
| 2459 | scope, | |
| 2460 | line, | |
| 2461 | null, // underlying type | |
| 2554 | 2462 | layout.payload_size * 8, |
| 2555 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2463 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2556 | 2464 | try o.builder.metadataTuple(fields.items), |
| 2557 | 2465 | ); |
| 2558 | 2466 | |
| 2559 | o.builder.resolveDebugForwardReference(debug_union_fwd_ref, debug_union_type); | |
| 2560 | ||
| 2561 | 2467 | if (layout.tag_size == 0) { |
| 2562 | // Set to real type now that it has been lowered fully | |
| 2563 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2564 | map_ptr.* = debug_union_type; | |
| 2565 | ||
| 2566 | return debug_union_type; | |
| 2468 | return debug_payload_type; | |
| 2567 | 2469 | } |
| 2568 | 2470 | |
| 2569 | var tag_offset: u64 = undefined; | |
| 2570 | var payload_offset: u64 = undefined; | |
| 2571 | if (layout.tag_align.compare(.gte, layout.payload_align)) { | |
| 2572 | tag_offset = 0; | |
| 2573 | payload_offset = layout.payload_align.forward(layout.tag_size); | |
| 2574 | } else { | |
| 2575 | payload_offset = 0; | |
| 2576 | tag_offset = layout.tag_align.forward(layout.payload_size); | |
| 2577 | } | |
| 2471 | o.builder.resolveDebugForwardReference(payload_fwd_ref, debug_payload_type); | |
| 2578 | 2472 | |
| 2579 | const debug_tag_type = try o.builder.debugMemberType( | |
| 2473 | const tag_offset: u64, const payload_offset: u64 = offsets: { | |
| 2474 | if (layout.tag_align.compare(.gte, layout.payload_align)) { | |
| 2475 | break :offsets .{ 0, layout.payload_align.forward(layout.tag_size) }; | |
| 2476 | } else { | |
| 2477 | break :offsets .{ layout.tag_align.forward(layout.payload_size), 0 }; | |
| 2478 | } | |
| 2479 | }; | |
| 2480 | ||
| 2481 | const tag_member_type = try o.builder.debugMemberType( | |
| 2580 | 2482 | try o.builder.metadataString("tag"), |
| 2581 | null, // File | |
| 2582 | debug_fwd_ref, | |
| 2583 | 0, // Line | |
| 2584 | try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty)), | |
| 2483 | null, // file | |
| 2484 | ty_fwd_ref, | |
| 2485 | 0, // line | |
| 2486 | try o.getDebugType(pt, enum_tag_ty), | |
| 2585 | 2487 | layout.tag_size * 8, |
| 2586 | (layout.tag_align.toByteUnits() orelse 0) * 8, | |
| 2488 | layout.tag_align.toByteUnits().? * 8, | |
| 2587 | 2489 | tag_offset * 8, |
| 2588 | 2490 | ); |
| 2589 | 2491 | |
| 2590 | const debug_payload_type = try o.builder.debugMemberType( | |
| 2492 | const payload_member_type = try o.builder.debugMemberType( | |
| 2591 | 2493 | try o.builder.metadataString("payload"), |
| 2592 | null, // File | |
| 2593 | debug_fwd_ref, | |
| 2594 | 0, // Line | |
| 2595 | debug_union_type, | |
| 2494 | null, // file | |
| 2495 | ty_fwd_ref, | |
| 2496 | 0, // line | |
| 2497 | debug_payload_type, | |
| 2596 | 2498 | layout.payload_size * 8, |
| 2597 | (layout.payload_align.toByteUnits() orelse 0) * 8, | |
| 2499 | layout.payload_align.toByteUnits().? * 8, | |
| 2598 | 2500 | payload_offset * 8, |
| 2599 | 2501 | ); |
| 2600 | 2502 | |
| 2601 | 2503 | const full_fields: [2]Builder.Metadata = |
| 2602 | 2504 | if (layout.tag_align.compare(.gte, layout.payload_align)) |
| 2603 | .{ debug_tag_type, debug_payload_type } | |
| 2505 | .{ tag_member_type, payload_member_type } | |
| 2604 | 2506 | else |
| 2605 | .{ debug_payload_type, debug_tag_type }; | |
| 2507 | .{ payload_member_type, tag_member_type }; | |
| 2606 | 2508 | |
| 2607 | const debug_tagged_union_type = try o.builder.debugStructType( | |
| 2608 | try o.builder.metadataString(name), | |
| 2609 | null, // File | |
| 2610 | o.debug_compile_unit.unwrap().?, // Scope | |
| 2611 | 0, // Line | |
| 2612 | null, // Underlying type | |
| 2509 | return o.builder.debugStructType( | |
| 2510 | name, | |
| 2511 | file, | |
| 2512 | scope, | |
| 2513 | line, | |
| 2514 | null, // underlying type | |
| 2613 | 2515 | ty.abiSize(zcu) * 8, |
| 2614 | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, | |
| 2516 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2615 | 2517 | try o.builder.metadataTuple(&full_fields), |
| 2616 | 2518 | ); |
| 2519 | }, | |
| 2520 | .@"enum" => { | |
| 2521 | const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); | |
| 2522 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2523 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 2524 | else | |
| 2525 | file; | |
| 2617 | 2526 | |
| 2618 | o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_tagged_union_type); | |
| 2619 | ||
| 2620 | // Set to real type now that it has been lowered fully | |
| 2621 | const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; | |
| 2622 | map_ptr.* = debug_tagged_union_type; | |
| 2527 | const line = ty.typeDeclSrcLine(zcu).? + 1; | |
| 2623 | 2528 | |
| 2624 | return debug_tagged_union_type; | |
| 2625 | }, | |
| 2626 | .@"fn" => { | |
| 2627 | const fn_info = zcu.typeToFunc(ty).?; | |
| 2529 | if (!ty.hasRuntimeBits(zcu)) { | |
| 2530 | return o.builder.debugStructType( | |
| 2531 | name, | |
| 2532 | file, | |
| 2533 | scope, | |
| 2534 | line, | |
| 2535 | null, // underlying type | |
| 2536 | ty.abiSize(zcu) * 8, | |
| 2537 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2538 | null, // fields | |
| 2539 | ); | |
| 2540 | } | |
| 2628 | 2541 | |
| 2629 | var debug_param_types = std.array_list.Managed(Builder.Metadata).init(gpa); | |
| 2630 | defer debug_param_types.deinit(); | |
| 2542 | const enum_type = ip.loadEnumType(ty.toIntern()); | |
| 2543 | const enumerators = try gpa.alloc(Builder.Metadata, enum_type.field_names.len); | |
| 2544 | defer gpa.free(enumerators); | |
| 2631 | 2545 | |
| 2632 | try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len); | |
| 2546 | const int_ty: Type = .fromInterned(enum_type.int_tag_type); | |
| 2547 | const int_info = ty.intInfo(zcu); | |
| 2548 | assert(int_info.bits != 0); | |
| 2633 | 2549 | |
| 2634 | // Return type goes first. | |
| 2635 | if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2636 | const sret = firstParamSRet(fn_info, zcu, target); | |
| 2637 | const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type); | |
| 2638 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ret_ty)); | |
| 2639 | ||
| 2640 | if (sret) { | |
| 2641 | const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type)); | |
| 2642 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty)); | |
| 2643 | } | |
| 2644 | } else { | |
| 2645 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, Type.void)); | |
| 2550 | for (enumerators, enum_type.field_names.get(ip), 0..) |*out, field_name, field_index| { | |
| 2551 | var space: Value.BigIntSpace = undefined; | |
| 2552 | const field_val: std.math.big.int.Const = switch (enum_type.field_values.len) { | |
| 2553 | 0 => std.math.big.int.Mutable.init(&space.limbs, field_index).toConst(), | |
| 2554 | else => Value.fromInterned(enum_type.field_values.get(ip)[field_index]).toBigInt(&space, zcu), | |
| 2555 | }; | |
| 2556 | out.* = try o.builder.debugEnumerator( | |
| 2557 | try o.builder.metadataString(field_name.toSlice(ip)), | |
| 2558 | int_info.signedness == .unsigned, | |
| 2559 | int_info.bits, | |
| 2560 | field_val, | |
| 2561 | ); | |
| 2646 | 2562 | } |
| 2647 | 2563 | |
| 2648 | if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) { | |
| 2649 | // Stack trace pointer. | |
| 2650 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, .fromInterned(.ptr_usize_type))); | |
| 2564 | const debug_enum_type = try o.builder.debugEnumerationType( | |
| 2565 | name, | |
| 2566 | file, | |
| 2567 | scope, | |
| 2568 | line, | |
| 2569 | try o.getDebugType(pt, int_ty), | |
| 2570 | ty.abiSize(zcu) * 8, | |
| 2571 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2572 | try o.builder.metadataTuple(enumerators), | |
| 2573 | ); | |
| 2574 | try o.debug_enums.append(gpa, debug_enum_type); | |
| 2575 | return debug_enum_type; | |
| 2576 | }, | |
| 2577 | .@"opaque" => { | |
| 2578 | if (ty.toIntern() == .anyopaque_type) { | |
| 2579 | return o.builder.debugSignedType(name, 0); | |
| 2651 | 2580 | } |
| 2652 | 2581 | |
| 2653 | for (0..fn_info.param_types.len) |i| { | |
| 2654 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[i]); | |
| 2655 | if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 2582 | const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); | |
| 2583 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2584 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 2585 | else | |
| 2586 | file; | |
| 2656 | 2587 | |
| 2657 | if (isByRef(param_ty, zcu)) { | |
| 2658 | const ptr_ty = try pt.singleMutPtrType(param_ty); | |
| 2659 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty)); | |
| 2660 | } else { | |
| 2661 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, param_ty)); | |
| 2662 | } | |
| 2663 | } | |
| 2588 | const line = ty.typeDeclSrcLine(zcu).? + 1; | |
| 2664 | 2589 | |
| 2665 | const debug_function_type = try o.builder.debugSubroutineType( | |
| 2666 | try o.builder.metadataTuple(debug_param_types.items), | |
| 2590 | return o.builder.debugStructType( | |
| 2591 | name, | |
| 2592 | file, | |
| 2593 | scope, | |
| 2594 | line, | |
| 2595 | null, // underlying type | |
| 2596 | 0, // size | |
| 2597 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2598 | null, // fields | |
| 2667 | 2599 | ); |
| 2668 | ||
| 2669 | try o.debug_type_map.put(gpa, ty.toIntern(), debug_function_type); | |
| 2670 | return debug_function_type; | |
| 2671 | 2600 | }, |
| 2672 | .comptime_int => unreachable, | |
| 2673 | .comptime_float => unreachable, | |
| 2674 | .type => unreachable, | |
| 2675 | .undefined => unreachable, | |
| 2676 | .null => unreachable, | |
| 2677 | .enum_literal => unreachable, | |
| 2678 | ||
| 2679 | 2601 | .frame => @panic("TODO implement lowerDebugType for Frame types"), |
| 2680 | 2602 | .@"anyframe" => @panic("TODO implement lowerDebugType for AnyFrame types"), |
| 2681 | 2603 | } |
| 2682 | 2604 | } |
| 2683 | 2605 | |
| 2684 | fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { | |
| 2606 | /// Called in `emit` so that the global error set is fully populated. | |
| 2607 | fn lowerDebugAnyerrorType(o: *Object, pt: Zcu.PerThread) Allocator.Error!Builder.Metadata { | |
| 2685 | 2608 | const zcu = pt.zcu; |
| 2686 | const namespace = zcu.namespacePtr(namespace_index); | |
| 2687 | if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope); | |
| 2609 | const ip = &zcu.intern_pool; | |
| 2610 | const gpa = zcu.comp.gpa; | |
| 2688 | 2611 | |
| 2689 | const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index); | |
| 2612 | const error_set_bits = zcu.errorSetBits(); | |
| 2613 | const error_names = ip.global_error_set.getNamesFromMainThread(); | |
| 2690 | 2614 | |
| 2691 | if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference(); | |
| 2615 | const enumerators = try gpa.alloc(Builder.Metadata, error_names.len + 1); | |
| 2616 | defer gpa.free(enumerators); | |
| 2692 | 2617 | |
| 2693 | return gop.value_ptr.*; | |
| 2618 | // The value 0 means "no error" in optionals and error unions. | |
| 2619 | enumerators[0] = try o.builder.debugEnumerator( | |
| 2620 | try o.builder.metadataString("null"), | |
| 2621 | true, // unsigned, | |
| 2622 | error_set_bits, | |
| 2623 | .{ .limbs = &.{0}, .positive = true }, // zero | |
| 2624 | ); | |
| 2625 | ||
| 2626 | for (enumerators[1..], error_names, 1..) |*out, error_name, error_value| { | |
| 2627 | var space: Value.BigIntSpace = undefined; | |
| 2628 | var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value); | |
| 2629 | out.* = try o.builder.debugEnumerator( | |
| 2630 | try o.builder.metadataStringFmt("error.{f}", .{error_name.fmtId(ip)}), | |
| 2631 | true, // unsigned | |
| 2632 | error_set_bits, | |
| 2633 | bigint.toConst(), | |
| 2634 | ); | |
| 2635 | } | |
| 2636 | ||
| 2637 | const debug_enum_type = try o.builder.debugEnumerationType( | |
| 2638 | try o.builder.metadataString("anyerror"), | |
| 2639 | null, // file | |
| 2640 | o.debug_compile_unit.unwrap().?, // scope | |
| 2641 | 0, // line | |
| 2642 | try o.getDebugType(pt, try pt.intType(.unsigned, error_set_bits)), | |
| 2643 | Type.anyerror.abiSize(zcu) * 8, | |
| 2644 | Type.anyerror.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2645 | try o.builder.metadataTuple(enumerators), | |
| 2646 | ); | |
| 2647 | try o.debug_enums.append(gpa, debug_enum_type); | |
| 2648 | return debug_enum_type; | |
| 2694 | 2649 | } |
| 2695 | 2650 | |
| 2696 | fn makeEmptyNamespaceDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) !Builder.Metadata { | |
| 2651 | fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { | |
| 2697 | 2652 | const zcu = pt.zcu; |
| 2698 | const ip = &zcu.intern_pool; | |
| 2699 | const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); | |
| 2700 | const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| | |
| 2701 | try o.namespaceToDebugScope(pt, parent_namespace) | |
| 2702 | else | |
| 2703 | file; | |
| 2704 | return o.builder.debugStructType( | |
| 2705 | try o.builder.metadataString(ty.containerTypeName(ip).toSlice(ip)), // TODO use fully qualified name | |
| 2706 | file, | |
| 2707 | scope, | |
| 2708 | ty.typeDeclSrcLine(zcu).? + 1, | |
| 2709 | null, | |
| 2710 | 0, | |
| 2711 | 0, | |
| 2712 | null, | |
| 2713 | ); | |
| 2653 | const namespace = zcu.namespacePtr(namespace_index); | |
| 2654 | if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope); | |
| 2655 | return o.getDebugType(pt, .fromInterned(namespace.owner_type)); | |
| 2714 | 2656 | } |
| 2715 | 2657 | |
| 2716 | 2658 | fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 { |
| ... | ... | @@ -2804,7 +2746,7 @@ pub const Object = struct { |
| 2804 | 2746 | function_index.setCallConv(cc_info.llvm_cc, &o.builder); |
| 2805 | 2747 | |
| 2806 | 2748 | if (cc_info.align_stack) { |
| 2807 | try attributes.addFnAttr(.{ .alignstack = .fromByteUnits(target.stackAlignment()) }, &o.builder); | |
| 2749 | try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); | |
| 2808 | 2750 | } else { |
| 2809 | 2751 | _ = try attributes.removeFnAttr(.alignstack); |
| 2810 | 2752 | } |
| ... | ... | @@ -2885,40 +2827,6 @@ pub const Object = struct { |
| 2885 | 2827 | |
| 2886 | 2828 | if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); |
| 2887 | 2829 | |
| 2888 | // Add parameter attributes. We handle only the case of extern functions (no body) | |
| 2889 | // because functions with bodies are handled in `updateFunc`. | |
| 2890 | if (is_extern) { | |
| 2891 | var it = iterateParamTypes(o, pt, fn_info); | |
| 2892 | it.llvm_index = llvm_arg_i; | |
| 2893 | while (try it.next()) |lowering| switch (lowering) { | |
| 2894 | .byval => { | |
| 2895 | const param_index = it.zig_index - 1; | |
| 2896 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); | |
| 2897 | if (!isByRef(param_ty, zcu)) { | |
| 2898 | try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); | |
| 2899 | } | |
| 2900 | }, | |
| 2901 | .byref => { | |
| 2902 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | |
| 2903 | const param_llvm_ty = try o.lowerType(pt, param_ty); | |
| 2904 | const alignment = param_ty.abiAlignment(zcu); | |
| 2905 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); | |
| 2906 | }, | |
| 2907 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), | |
| 2908 | // No attributes needed for these. | |
| 2909 | .no_bits, | |
| 2910 | .abi_sized_int, | |
| 2911 | .multiple_llvm_types, | |
| 2912 | .float_array, | |
| 2913 | .i32_array, | |
| 2914 | .i64_array, | |
| 2915 | => continue, | |
| 2916 | ||
| 2917 | .slice => unreachable, // extern functions do not support slice types. | |
| 2918 | ||
| 2919 | }; | |
| 2920 | } | |
| 2921 | ||
| 2922 | 2830 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 2923 | 2831 | return function_index; |
| 2924 | 2832 | } |
| ... | ... | @@ -3223,7 +3131,7 @@ pub const Object = struct { |
| 3223 | 3131 | ), |
| 3224 | 3132 | .opt_type => |child_ty| { |
| 3225 | 3133 | // Must stay in sync with `opt_payload` logic in `lowerPtr`. |
| 3226 | if (!Type.fromInterned(child_ty).hasRuntimeBitsIgnoreComptime(zcu)) return .i8; | |
| 3134 | if (!Type.fromInterned(child_ty).hasRuntimeBits(zcu)) return .i8; | |
| 3227 | 3135 | |
| 3228 | 3136 | const payload_ty = try o.lowerType(pt, Type.fromInterned(child_ty)); |
| 3229 | 3137 | if (t.optionalReprIsPayload(zcu)) return payload_ty; |
| ... | ... | @@ -3245,7 +3153,7 @@ pub const Object = struct { |
| 3245 | 3153 | // Must stay in sync with `codegen.errUnionPayloadOffset`. |
| 3246 | 3154 | // See logic in `lowerPtr`. |
| 3247 | 3155 | const error_type = try o.errorIntType(pt); |
| 3248 | if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBitsIgnoreComptime(zcu)) | |
| 3156 | if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBits(zcu)) | |
| 3249 | 3157 | return error_type; |
| 3250 | 3158 | const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type)); |
| 3251 | 3159 | |
| ... | ... | @@ -3287,7 +3195,7 @@ pub const Object = struct { |
| 3287 | 3195 | const struct_type = ip.loadStructType(t.toIntern()); |
| 3288 | 3196 | |
| 3289 | 3197 | if (struct_type.layout == .@"packed") { |
| 3290 | const int_ty = try o.lowerType(pt, Type.fromInterned(struct_type.backingIntTypeUnordered(ip))); | |
| 3198 | const int_ty = try o.lowerType(pt, .fromInterned(struct_type.packed_backing_int_type)); | |
| 3291 | 3199 | try o.type_map.put(o.gpa, t.toIntern(), int_ty); |
| 3292 | 3200 | return int_ty; |
| 3293 | 3201 | } |
| ... | ... | @@ -3301,18 +3209,20 @@ pub const Object = struct { |
| 3301 | 3209 | |
| 3302 | 3210 | comptime assert(struct_layout_version == 2); |
| 3303 | 3211 | var offset: u64 = 0; |
| 3304 | var big_align: InternPool.Alignment = .@"1"; | |
| 3305 | 3212 | var struct_kind: Builder.Type.Structure.Kind = .normal; |
| 3306 | 3213 | // When we encounter a zero-bit field, we place it here so we know to map it to the next non-zero-bit field (if any). |
| 3307 | 3214 | var it = struct_type.iterateRuntimeOrder(ip); |
| 3215 | var max_field_ty_align: InternPool.Alignment = .@"1"; | |
| 3308 | 3216 | while (it.next()) |field_index| { |
| 3309 | 3217 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 3310 | const field_align = t.fieldAlignment(field_index, zcu); | |
| 3311 | 3218 | const field_ty_align = field_ty.abiAlignment(zcu); |
| 3312 | if (field_align.compare(.lt, field_ty_align)) struct_kind = .@"packed"; | |
| 3313 | big_align = big_align.max(field_align); | |
| 3219 | max_field_ty_align = max_field_ty_align.maxStrict(field_ty_align); | |
| 3220 | ||
| 3314 | 3221 | const prev_offset = offset; |
| 3315 | offset = field_align.forward(offset); | |
| 3222 | offset = struct_type.field_offsets.get(ip)[field_index]; | |
| 3223 | if (@ctz(offset) < field_ty_align.toLog2Units()) { | |
| 3224 | struct_kind = .@"packed"; // prevent unexpected padding before this field | |
| 3225 | } | |
| 3316 | 3226 | |
| 3317 | 3227 | const padding_len = offset - prev_offset; |
| 3318 | 3228 | if (padding_len > 0) try llvm_field_types.append( |
| ... | ... | @@ -3320,11 +3230,11 @@ pub const Object = struct { |
| 3320 | 3230 | try o.builder.arrayType(padding_len, .i8), |
| 3321 | 3231 | ); |
| 3322 | 3232 | |
| 3323 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3233 | if (!field_ty.hasRuntimeBits(zcu)) { | |
| 3324 | 3234 | // This is a zero-bit field. If there are runtime bits after this field, |
| 3325 | 3235 | // map to the next LLVM field (which we know exists): otherwise, don't |
| 3326 | 3236 | // map the field, indicating it's at the end of the struct. |
| 3327 | if (offset != struct_type.sizeUnordered(ip)) { | |
| 3237 | if (offset != struct_type.size) { | |
| 3328 | 3238 | try o.struct_field_map.put(o.gpa, .{ |
| 3329 | 3239 | .struct_ty = t.toIntern(), |
| 3330 | 3240 | .field_index = field_index, |
| ... | ... | @@ -3343,12 +3253,15 @@ pub const Object = struct { |
| 3343 | 3253 | } |
| 3344 | 3254 | { |
| 3345 | 3255 | const prev_offset = offset; |
| 3346 | offset = big_align.forward(offset); | |
| 3256 | offset = struct_type.alignment.forward(offset); | |
| 3347 | 3257 | const padding_len = offset - prev_offset; |
| 3348 | 3258 | if (padding_len > 0) try llvm_field_types.append( |
| 3349 | 3259 | o.gpa, |
| 3350 | 3260 | try o.builder.arrayType(padding_len, .i8), |
| 3351 | 3261 | ); |
| 3262 | if (@ctz(offset) < max_field_ty_align.toLog2Units()) { | |
| 3263 | struct_kind = .@"packed"; // prevent unexpected trailing padding | |
| 3264 | } | |
| 3352 | 3265 | } |
| 3353 | 3266 | |
| 3354 | 3267 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); |
| ... | ... | @@ -3391,7 +3304,7 @@ pub const Object = struct { |
| 3391 | 3304 | o.gpa, |
| 3392 | 3305 | try o.builder.arrayType(padding_len, .i8), |
| 3393 | 3306 | ); |
| 3394 | if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3307 | if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) { | |
| 3395 | 3308 | // This is a zero-bit field. If there are runtime bits after this field, |
| 3396 | 3309 | // map to the next LLVM field (which we know exists): otherwise, don't |
| 3397 | 3310 | // map the field, indicating it's at the end of the struct. |
| ... | ... | @@ -3426,16 +3339,17 @@ pub const Object = struct { |
| 3426 | 3339 | if (o.type_map.get(t.toIntern())) |value| return value; |
| 3427 | 3340 | |
| 3428 | 3341 | const union_obj = ip.loadUnionType(t.toIntern()); |
| 3429 | const layout = Type.getUnionLayout(union_obj, zcu); | |
| 3430 | 3342 | |
| 3431 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | |
| 3432 | const int_ty = try o.builder.intType(@intCast(t.bitSize(zcu))); | |
| 3343 | if (union_obj.layout == .@"packed") { | |
| 3344 | const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type)); | |
| 3433 | 3345 | try o.type_map.put(o.gpa, t.toIntern(), int_ty); |
| 3434 | 3346 | return int_ty; |
| 3435 | 3347 | } |
| 3436 | 3348 | |
| 3349 | const layout = Type.getUnionLayout(union_obj, zcu); | |
| 3350 | ||
| 3437 | 3351 | if (layout.payload_size == 0) { |
| 3438 | const enum_tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); | |
| 3352 | const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); | |
| 3439 | 3353 | try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty); |
| 3440 | 3354 | return enum_tag_ty; |
| 3441 | 3355 | } |
| ... | ... | @@ -3467,7 +3381,7 @@ pub const Object = struct { |
| 3467 | 3381 | ); |
| 3468 | 3382 | return ty; |
| 3469 | 3383 | } |
| 3470 | const enum_tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); | |
| 3384 | const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); | |
| 3471 | 3385 | |
| 3472 | 3386 | // Put the tag before or after the payload depending on which one's |
| 3473 | 3387 | // alignment is greater. |
| ... | ... | @@ -3502,7 +3416,7 @@ pub const Object = struct { |
| 3502 | 3416 | } |
| 3503 | 3417 | return gop.value_ptr.*; |
| 3504 | 3418 | }, |
| 3505 | .enum_type => try o.lowerType(pt, Type.fromInterned(ip.loadEnumType(t.toIntern()).tag_ty)), | |
| 3419 | .enum_type => try o.lowerType(pt, t.intTagType(zcu)), | |
| 3506 | 3420 | .func_type => |func_type| try o.lowerTypeFn(pt, func_type), |
| 3507 | 3421 | .error_set_type, .inferred_error_set_type => try o.errorIntType(pt), |
| 3508 | 3422 | // values, not types |
| ... | ... | @@ -3516,13 +3430,13 @@ pub const Object = struct { |
| 3516 | 3430 | .error_union, |
| 3517 | 3431 | .enum_literal, |
| 3518 | 3432 | .enum_tag, |
| 3519 | .empty_enum_value, | |
| 3520 | 3433 | .float, |
| 3521 | 3434 | .ptr, |
| 3522 | 3435 | .slice, |
| 3523 | 3436 | .opt, |
| 3524 | 3437 | .aggregate, |
| 3525 | 3438 | .un, |
| 3439 | .bitpack, | |
| 3526 | 3440 | // memoization, not types |
| 3527 | 3441 | .memoized_call, |
| 3528 | 3442 | => unreachable, |
| ... | ... | @@ -3530,20 +3444,6 @@ pub const Object = struct { |
| 3530 | 3444 | }; |
| 3531 | 3445 | } |
| 3532 | 3446 | |
| 3533 | /// Use this instead of lowerType when you want to handle correctly the case of elem_ty | |
| 3534 | /// being a zero bit type, but it should still be lowered as an i8 in such case. | |
| 3535 | /// There are other similar cases handled here as well. | |
| 3536 | fn lowerPtrElemTy(o: *Object, pt: Zcu.PerThread, elem_ty: Type) Allocator.Error!Builder.Type { | |
| 3537 | const zcu = pt.zcu; | |
| 3538 | const lower_elem_ty = switch (elem_ty.zigTypeTag(zcu)) { | |
| 3539 | .@"opaque" => true, | |
| 3540 | .@"fn" => !zcu.typeToFunc(elem_ty).?.is_generic, | |
| 3541 | .array => elem_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu), | |
| 3542 | else => elem_ty.hasRuntimeBitsIgnoreComptime(zcu), | |
| 3543 | }; | |
| 3544 | return if (lower_elem_ty) try o.lowerType(pt, elem_ty) else .i8; | |
| 3545 | } | |
| 3546 | ||
| 3547 | 3447 | fn lowerTypeFn(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { |
| 3548 | 3448 | const zcu = pt.zcu; |
| 3549 | 3449 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -3558,9 +3458,9 @@ pub const Object = struct { |
| 3558 | 3458 | } |
| 3559 | 3459 | |
| 3560 | 3460 | if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) { |
| 3561 | const stack_trace_ty = zcu.builtin_decl_values.get(.StackTrace); | |
| 3562 | const ptr_ty = try pt.ptrType(.{ .child = stack_trace_ty }); | |
| 3563 | try llvm_params.append(o.gpa, try o.lowerType(pt, ptr_ty)); | |
| 3461 | // First parameter is a pointer to `std.builtin.StackTrace`. | |
| 3462 | const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(.generic, target)); | |
| 3463 | try llvm_params.append(o.gpa, llvm_ptr_ty); | |
| 3564 | 3464 | } |
| 3565 | 3465 | |
| 3566 | 3466 | var it = iterateParamTypes(o, pt, fn_info); |
| ... | ... | @@ -3610,84 +3510,6 @@ pub const Object = struct { |
| 3610 | 3510 | ); |
| 3611 | 3511 | } |
| 3612 | 3512 | |
| 3613 | fn lowerValueToInt(o: *Object, pt: Zcu.PerThread, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant { | |
| 3614 | const zcu = pt.zcu; | |
| 3615 | const ip = &zcu.intern_pool; | |
| 3616 | const target = zcu.getTarget(); | |
| 3617 | ||
| 3618 | const val = Value.fromInterned(arg_val); | |
| 3619 | const val_key = ip.indexToKey(val.toIntern()); | |
| 3620 | ||
| 3621 | if (val.isUndef(zcu)) return o.builder.undefConst(llvm_int_ty); | |
| 3622 | ||
| 3623 | const ty = Type.fromInterned(val_key.typeOf()); | |
| 3624 | switch (val_key) { | |
| 3625 | .@"extern" => |@"extern"| { | |
| 3626 | const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); | |
| 3627 | const ptr = function_index.ptrConst(&o.builder).global.toConst(); | |
| 3628 | return o.builder.convConst(ptr, llvm_int_ty); | |
| 3629 | }, | |
| 3630 | .func => |func| { | |
| 3631 | const function_index = try o.resolveLlvmFunction(pt, func.owner_nav); | |
| 3632 | const ptr = function_index.ptrConst(&o.builder).global.toConst(); | |
| 3633 | return o.builder.convConst(ptr, llvm_int_ty); | |
| 3634 | }, | |
| 3635 | .ptr => return o.builder.convConst(try o.lowerPtr(pt, arg_val, 0), llvm_int_ty), | |
| 3636 | .aggregate => switch (ip.indexToKey(ty.toIntern())) { | |
| 3637 | .struct_type, .vector_type => {}, | |
| 3638 | else => unreachable, | |
| 3639 | }, | |
| 3640 | .un => |un| { | |
| 3641 | const layout = ty.unionGetLayout(zcu); | |
| 3642 | if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); | |
| 3643 | ||
| 3644 | const union_obj = zcu.typeToUnion(ty).?; | |
| 3645 | const container_layout = union_obj.flagsUnordered(ip).layout; | |
| 3646 | ||
| 3647 | assert(container_layout == .@"packed"); | |
| 3648 | ||
| 3649 | var need_unnamed = false; | |
| 3650 | if (un.tag == .none) { | |
| 3651 | assert(layout.tag_size == 0); | |
| 3652 | const union_val = try o.lowerValueToInt(pt, llvm_int_ty, un.val); | |
| 3653 | ||
| 3654 | need_unnamed = true; | |
| 3655 | return union_val; | |
| 3656 | } | |
| 3657 | const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; | |
| 3658 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 3659 | if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(llvm_int_ty, 0); | |
| 3660 | return o.lowerValueToInt(pt, llvm_int_ty, un.val); | |
| 3661 | }, | |
| 3662 | .simple_value => |simple_value| switch (simple_value) { | |
| 3663 | .false, .true => {}, | |
| 3664 | else => unreachable, | |
| 3665 | }, | |
| 3666 | .int, | |
| 3667 | .float, | |
| 3668 | .enum_tag, | |
| 3669 | => {}, | |
| 3670 | .opt => {}, // pointer like optional expected | |
| 3671 | else => unreachable, | |
| 3672 | } | |
| 3673 | var stack = std.heap.stackFallback(32, o.gpa); | |
| 3674 | const allocator = stack.get(); | |
| 3675 | ||
| 3676 | const bits: usize = @intCast(ty.bitSize(zcu)); | |
| 3677 | ||
| 3678 | const buffer = try allocator.alloc(u8, (bits + 7) / 8); | |
| 3679 | defer allocator.free(buffer); | |
| 3680 | const limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits)); | |
| 3681 | defer allocator.free(limbs); | |
| 3682 | ||
| 3683 | val.writeToPackedMemory(ty, pt, buffer, 0) catch unreachable; | |
| 3684 | ||
| 3685 | var big: std.math.big.int.Mutable = .init(limbs, 0); | |
| 3686 | big.readTwosComplement(buffer, bits, target.cpu.arch.endian(), .unsigned); | |
| 3687 | ||
| 3688 | return o.builder.bigIntConst(llvm_int_ty, big.toConst()); | |
| 3689 | } | |
| 3690 | ||
| 3691 | 3513 | fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant { |
| 3692 | 3514 | const zcu = pt.zcu; |
| 3693 | 3515 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -3700,7 +3522,9 @@ pub const Object = struct { |
| 3700 | 3522 | return o.builder.undefConst(try o.lowerType(pt, Type.fromInterned(val_key.typeOf()))); |
| 3701 | 3523 | } |
| 3702 | 3524 | |
| 3703 | const ty = Type.fromInterned(val_key.typeOf()); | |
| 3525 | const ty: Type = .fromInterned(val_key.typeOf()); | |
| 3526 | ty.assertHasLayout(zcu); | |
| 3527 | ||
| 3704 | 3528 | return switch (val_key) { |
| 3705 | 3529 | .int_type, |
| 3706 | 3530 | .ptr_type, |
| ... | ... | @@ -3722,10 +3546,8 @@ pub const Object = struct { |
| 3722 | 3546 | |
| 3723 | 3547 | .undef => unreachable, // handled above |
| 3724 | 3548 | .simple_value => |simple_value| switch (simple_value) { |
| 3725 | .undefined => unreachable, // non-runtime value | |
| 3726 | 3549 | .void => unreachable, // non-runtime value |
| 3727 | 3550 | .null => unreachable, // non-runtime value |
| 3728 | .empty_tuple => unreachable, // non-runtime value | |
| 3729 | 3551 | .@"unreachable" => unreachable, // non-runtime value |
| 3730 | 3552 | |
| 3731 | 3553 | .false => .false, |
| ... | ... | @@ -3733,7 +3555,6 @@ pub const Object = struct { |
| 3733 | 3555 | }, |
| 3734 | 3556 | .variable, |
| 3735 | 3557 | .enum_literal, |
| 3736 | .empty_enum_value, | |
| 3737 | 3558 | => unreachable, // non-runtime values |
| 3738 | 3559 | .@"extern" => |@"extern"| { |
| 3739 | 3560 | const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); |
| ... | ... | @@ -3763,7 +3584,7 @@ pub const Object = struct { |
| 3763 | 3584 | }; |
| 3764 | 3585 | const err_int_ty = try pt.errorIntType(); |
| 3765 | 3586 | const payload_type = ty.errorUnionPayload(zcu); |
| 3766 | if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3587 | if (!payload_type.hasRuntimeBits(zcu)) { | |
| 3767 | 3588 | // We use the error type directly as the type. |
| 3768 | 3589 | return o.lowerValue(pt, err_val); |
| 3769 | 3590 | } |
| ... | ... | @@ -3825,7 +3646,7 @@ pub const Object = struct { |
| 3825 | 3646 | const payload_ty = ty.optionalChild(zcu); |
| 3826 | 3647 | |
| 3827 | 3648 | const non_null_bit = try o.builder.intConst(.i8, @intFromBool(opt.val != .none)); |
| 3828 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3649 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 3829 | 3650 | return non_null_bit; |
| 3830 | 3651 | } |
| 3831 | 3652 | const llvm_ty = try o.lowerType(pt, ty); |
| ... | ... | @@ -3861,6 +3682,7 @@ pub const Object = struct { |
| 3861 | 3682 | fields[0..llvm_ty_fields.len], |
| 3862 | 3683 | ), vals[0..llvm_ty_fields.len]); |
| 3863 | 3684 | }, |
| 3685 | .bitpack => |bitpack| return o.lowerValue(pt, bitpack.backing_int_val), | |
| 3864 | 3686 | .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { |
| 3865 | 3687 | .array_type => |array_type| switch (aggregate.storage) { |
| 3866 | 3688 | .bytes => |bytes| try o.builder.stringConst(try o.builder.string( |
| ... | ... | @@ -3992,7 +3814,7 @@ pub const Object = struct { |
| 3992 | 3814 | 0.., |
| 3993 | 3815 | ) |field_ty, field_val, field_index| { |
| 3994 | 3816 | if (field_val != .none) continue; |
| 3995 | if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 3817 | if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; | |
| 3996 | 3818 | |
| 3997 | 3819 | const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); |
| 3998 | 3820 | big_align = big_align.max(field_align); |
| ... | ... | @@ -4038,16 +3860,8 @@ pub const Object = struct { |
| 4038 | 3860 | }, |
| 4039 | 3861 | .struct_type => { |
| 4040 | 3862 | const struct_type = ip.loadStructType(ty.toIntern()); |
| 4041 | assert(struct_type.haveLayout(ip)); | |
| 4042 | 3863 | const struct_ty = try o.lowerType(pt, ty); |
| 4043 | if (struct_type.layout == .@"packed") { | |
| 4044 | comptime assert(Type.packed_struct_layout_version == 2); | |
| 4045 | ||
| 4046 | const bits = ty.bitSize(zcu); | |
| 4047 | const llvm_int_ty = try o.builder.intType(@intCast(bits)); | |
| 4048 | ||
| 4049 | return o.lowerValueToInt(pt, llvm_int_ty, arg_val); | |
| 4050 | } | |
| 3864 | assert(struct_type.layout != .@"packed"); | |
| 4051 | 3865 | const llvm_len = struct_ty.aggregateLen(&o.builder); |
| 4052 | 3866 | |
| 4053 | 3867 | const ExpectedContents = extern struct { |
| ... | ... | @@ -4067,15 +3881,12 @@ pub const Object = struct { |
| 4067 | 3881 | comptime assert(struct_layout_version == 2); |
| 4068 | 3882 | var llvm_index: usize = 0; |
| 4069 | 3883 | var offset: u64 = 0; |
| 4070 | var big_align: InternPool.Alignment = .@"1"; | |
| 4071 | 3884 | var need_unnamed = false; |
| 4072 | 3885 | var field_it = struct_type.iterateRuntimeOrder(ip); |
| 4073 | 3886 | while (field_it.next()) |field_index| { |
| 4074 | 3887 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 4075 | const field_align = ty.fieldAlignment(field_index, zcu); | |
| 4076 | big_align = big_align.max(field_align); | |
| 4077 | 3888 | const prev_offset = offset; |
| 4078 | offset = field_align.forward(offset); | |
| 3889 | offset = struct_type.field_offsets.get(ip)[field_index]; | |
| 4079 | 3890 | |
| 4080 | 3891 | const padding_len = offset - prev_offset; |
| 4081 | 3892 | if (padding_len > 0) { |
| ... | ... | @@ -4088,7 +3899,7 @@ pub const Object = struct { |
| 4088 | 3899 | llvm_index += 1; |
| 4089 | 3900 | } |
| 4090 | 3901 | |
| 4091 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3902 | if (!field_ty.hasRuntimeBits(zcu)) { | |
| 4092 | 3903 | // This is a zero-bit field - we only needed it for the alignment. |
| 4093 | 3904 | continue; |
| 4094 | 3905 | } |
| ... | ... | @@ -4106,7 +3917,7 @@ pub const Object = struct { |
| 4106 | 3917 | } |
| 4107 | 3918 | { |
| 4108 | 3919 | const prev_offset = offset; |
| 4109 | offset = big_align.forward(offset); | |
| 3920 | offset = struct_type.alignment.forward(offset); | |
| 4110 | 3921 | const padding_len = offset - prev_offset; |
| 4111 | 3922 | if (padding_len > 0) { |
| 4112 | 3923 | fields[llvm_index] = try o.builder.arrayType(padding_len, .i8); |
| ... | ... | @@ -4130,19 +3941,13 @@ pub const Object = struct { |
| 4130 | 3941 | if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); |
| 4131 | 3942 | |
| 4132 | 3943 | const union_obj = zcu.typeToUnion(ty).?; |
| 4133 | const container_layout = union_obj.flagsUnordered(ip).layout; | |
| 3944 | const container_layout = union_obj.layout; | |
| 3945 | assert(container_layout != .@"packed"); | |
| 4134 | 3946 | |
| 4135 | 3947 | var need_unnamed = false; |
| 4136 | 3948 | const payload = if (un.tag != .none) p: { |
| 4137 | 3949 | const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; |
| 4138 | 3950 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 4139 | if (container_layout == .@"packed") { | |
| 4140 | if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(union_ty, 0); | |
| 4141 | const bits = ty.bitSize(zcu); | |
| 4142 | const llvm_int_ty = try o.builder.intType(@intCast(bits)); | |
| 4143 | ||
| 4144 | return o.lowerValueToInt(pt, llvm_int_ty, arg_val); | |
| 4145 | } | |
| 4146 | 3951 | |
| 4147 | 3952 | // Sometimes we must make an unnamed struct because LLVM does |
| 4148 | 3953 | // not support bitcasting our payload struct to the true union payload type. |
| ... | ... | @@ -4150,14 +3955,14 @@ pub const Object = struct { |
| 4150 | 3955 | // must pointer cast to the expected type before accessing the union. |
| 4151 | 3956 | need_unnamed = layout.most_aligned_field != field_index; |
| 4152 | 3957 | |
| 4153 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3958 | if (!field_ty.hasRuntimeBits(zcu)) { | |
| 4154 | 3959 | const padding_len = layout.payload_size; |
| 4155 | 3960 | break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8)); |
| 4156 | 3961 | } |
| 4157 | 3962 | const payload = try o.lowerValue(pt, un.val); |
| 4158 | 3963 | const payload_ty = payload.typeOf(&o.builder); |
| 4159 | 3964 | if (payload_ty != union_ty.structFields(&o.builder)[ |
| 4160 | @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)) | |
| 3965 | @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) | |
| 4161 | 3966 | ]) need_unnamed = true; |
| 4162 | 3967 | const field_size = field_ty.abiSize(zcu); |
| 4163 | 3968 | if (field_size == layout.payload_size) break :p payload; |
| ... | ... | @@ -4169,13 +3974,6 @@ pub const Object = struct { |
| 4169 | 3974 | ); |
| 4170 | 3975 | } else p: { |
| 4171 | 3976 | assert(layout.tag_size == 0); |
| 4172 | if (container_layout == .@"packed") { | |
| 4173 | const bits = ty.bitSize(zcu); | |
| 4174 | const llvm_int_ty = try o.builder.intType(@intCast(bits)); | |
| 4175 | ||
| 4176 | return o.lowerValueToInt(pt, llvm_int_ty, arg_val); | |
| 4177 | } | |
| 4178 | ||
| 4179 | 3977 | const union_val = try o.lowerValue(pt, un.val); |
| 4180 | 3978 | need_unnamed = true; |
| 4181 | 3979 | break :p union_val; |
| ... | ... | @@ -4277,7 +4075,14 @@ pub const Object = struct { |
| 4277 | 4075 | }; |
| 4278 | 4076 | return o.lowerPtr(pt, field.base, offset + field_off); |
| 4279 | 4077 | }, |
| 4280 | .arr_elem, .comptime_field, .comptime_alloc => unreachable, | |
| 4078 | .arr_elem => |arr_elem| { | |
| 4079 | const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu); | |
| 4080 | assert(base_ptr_ty.ptrSize(zcu) == .many); | |
| 4081 | const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu); | |
| 4082 | return o.lowerPtr(pt, arr_elem.base, offset + elem_size * arr_elem.index); | |
| 4083 | }, | |
| 4084 | .comptime_field => unreachable, | |
| 4085 | .comptime_alloc => unreachable, | |
| 4281 | 4086 | }; |
| 4282 | 4087 | } |
| 4283 | 4088 | |
| ... | ... | @@ -4302,12 +4107,11 @@ pub const Object = struct { |
| 4302 | 4107 | |
| 4303 | 4108 | const ptr_ty = Type.fromInterned(uav.orig_ty); |
| 4304 | 4109 | |
| 4305 | const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn"; | |
| 4306 | if ((!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) or | |
| 4307 | (is_fn_body and zcu.typeToFunc(uav_ty).?.is_generic)) return o.lowerPtrToVoid(pt, ptr_ty); | |
| 4110 | if (!uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 4111 | return o.lowerPtrToVoid(pt, ptr_ty); | |
| 4112 | } | |
| 4308 | 4113 | |
| 4309 | if (is_fn_body) | |
| 4310 | @panic("TODO"); | |
| 4114 | assert(uav_ty.zigTypeTag(zcu) != .@"fn"); // should be using a Nav ref | |
| 4311 | 4115 | |
| 4312 | 4116 | const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(zcu), target); |
| 4313 | 4117 | const alignment = ptr_ty.ptrAlignment(zcu); |
| ... | ... | @@ -4330,14 +4134,11 @@ pub const Object = struct { |
| 4330 | 4134 | const nav_ty = Type.fromInterned(nav.typeOf(ip)); |
| 4331 | 4135 | const ptr_ty = try pt.navPtrType(nav_index); |
| 4332 | 4136 | |
| 4333 | const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; | |
| 4334 | if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or | |
| 4335 | (is_fn_body and zcu.typeToFunc(nav_ty).?.is_generic)) | |
| 4336 | { | |
| 4137 | if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 4337 | 4138 | return o.lowerPtrToVoid(pt, ptr_ty); |
| 4338 | 4139 | } |
| 4339 | 4140 | |
| 4340 | const llvm_global = if (is_fn_body) | |
| 4141 | const llvm_global = if (nav_ty.zigTypeTag(zcu) == .@"fn") | |
| 4341 | 4142 | (try o.resolveLlvmFunction(pt, nav_index)).ptrConst(&o.builder).global |
| 4342 | 4143 | else |
| 4343 | 4144 | (try o.resolveGlobalNav(pt, nav_index)).ptrConst(&o.builder).global; |
| ... | ... | @@ -4380,21 +4181,18 @@ pub const Object = struct { |
| 4380 | 4181 | /// types to work around a LLVM deficiency when targeting ARM/AArch64. |
| 4381 | 4182 | fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type { |
| 4382 | 4183 | const zcu = pt.zcu; |
| 4383 | const ip = &zcu.intern_pool; | |
| 4384 | const int_ty = switch (ty.zigTypeTag(zcu)) { | |
| 4385 | .int => ty, | |
| 4386 | .@"enum" => ty.intTagType(zcu), | |
| 4387 | .@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)), | |
| 4184 | switch (ty.zigTypeTag(zcu)) { | |
| 4185 | .int, .@"enum", .@"struct", .@"union" => {}, | |
| 4388 | 4186 | .float => { |
| 4389 | 4187 | if (!is_rmw_xchg) return .none; |
| 4390 | 4188 | return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); |
| 4391 | 4189 | }, |
| 4392 | 4190 | .bool => return .i8, |
| 4393 | 4191 | else => return .none, |
| 4394 | }; | |
| 4395 | const bit_count = int_ty.intInfo(zcu).bits; | |
| 4192 | } | |
| 4193 | const bit_count = ty.bitSize(zcu); | |
| 4396 | 4194 | if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) { |
| 4397 | return o.builder.intType(@intCast(int_ty.abiSize(zcu) * 8)); | |
| 4195 | return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); | |
| 4398 | 4196 | } else { |
| 4399 | 4197 | return .none; |
| 4400 | 4198 | } |
| ... | ... | @@ -4435,11 +4233,11 @@ pub const Object = struct { |
| 4435 | 4233 | if (ptr_info.flags.is_const) { |
| 4436 | 4234 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4437 | 4235 | } |
| 4438 | const elem_align = if (ptr_info.flags.alignment != .none) | |
| 4439 | ptr_info.flags.alignment | |
| 4440 | else | |
| 4441 | Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1"); | |
| 4442 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align.toLlvm() }, &o.builder); | |
| 4236 | const elem_align: Builder.Alignment.Lazy = switch (ptr_info.flags.alignment) { | |
| 4237 | else => |a| .wrap(a.toLlvm()), | |
| 4238 | .none => try o.lazyAbiAlignment(pt, .fromInterned(ptr_info.child)), | |
| 4239 | }; | |
| 4240 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); | |
| 4443 | 4241 | } else if (ccAbiPromoteInt(fn_info.cc, zcu, param_ty)) |s| switch (s) { |
| 4444 | 4242 | .signed => try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder), |
| 4445 | 4243 | .unsigned => try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder), |
| ... | ... | @@ -4456,7 +4254,7 @@ pub const Object = struct { |
| 4456 | 4254 | ) Allocator.Error!void { |
| 4457 | 4255 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); |
| 4458 | 4256 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4459 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); | |
| 4257 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder); | |
| 4460 | 4258 | if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); |
| 4461 | 4259 | } |
| 4462 | 4260 | |
| ... | ... | @@ -4502,7 +4300,7 @@ pub const Object = struct { |
| 4502 | 4300 | const ret_ty = try o.lowerType(pt, Type.slice_const_u8_sentinel_0); |
| 4503 | 4301 | const target = &zcu.root_mod.resolved_target.result; |
| 4504 | 4302 | const function_index = try o.builder.addFunction( |
| 4505 | try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.tag_ty))}, .normal), | |
| 4303 | try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal), | |
| 4506 | 4304 | try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}), |
| 4507 | 4305 | toLlvmAddressSpace(.generic, target), |
| 4508 | 4306 | ); |
| ... | ... | @@ -4525,12 +4323,16 @@ pub const Object = struct { |
| 4525 | 4323 | |
| 4526 | 4324 | const bad_value_block = try wip.block(1, "BadValue"); |
| 4527 | 4325 | const tag_int_value = wip.arg(0); |
| 4528 | var wip_switch = | |
| 4529 | try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len), .none); | |
| 4326 | var wip_switch = try wip.@"switch"( | |
| 4327 | tag_int_value, | |
| 4328 | bad_value_block, | |
| 4329 | @intCast(enum_type.field_names.len), | |
| 4330 | .none, | |
| 4331 | ); | |
| 4530 | 4332 | defer wip_switch.finish(&wip); |
| 4531 | 4333 | |
| 4532 | for (0..enum_type.names.len) |field_index| { | |
| 4533 | const name = try o.builder.stringNull(enum_type.names.get(ip)[field_index].toSlice(ip)); | |
| 4334 | for (0..enum_type.field_names.len) |field_index| { | |
| 4335 | const name = try o.builder.stringNull(enum_type.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4534 | 4336 | const name_init = try o.builder.stringConst(name); |
| 4535 | 4337 | const name_variable_index = |
| 4536 | 4338 | try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); |
| ... | ... | @@ -4562,6 +4364,11 @@ pub const Object = struct { |
| 4562 | 4364 | try wip.finish(); |
| 4563 | 4365 | return function_index; |
| 4564 | 4366 | } |
| 4367 | ||
| 4368 | fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy { | |
| 4369 | const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); | |
| 4370 | return o.lazy_abi_aligns.items[@intFromEnum(index)]; | |
| 4371 | } | |
| 4565 | 4372 | }; |
| 4566 | 4373 | |
| 4567 | 4374 | pub const NavGen = struct { |
| ... | ... | @@ -4601,10 +4408,44 @@ pub const NavGen = struct { |
| 4601 | 4408 | const ty = Type.fromInterned(nav.typeOf(ip)); |
| 4602 | 4409 | |
| 4603 | 4410 | if (linkage != .internal and ip.isFunctionType(ty.toIntern())) { |
| 4604 | _ = try o.resolveLlvmFunction(pt, owner_nav); | |
| 4411 | const function_index = try o.resolveLlvmFunction(pt, owner_nav); | |
| 4412 | // Add parameter attributes which weren't set by `resolveLlvmFunction` | |
| 4413 | const fn_info = zcu.typeToFunc(ty).?; | |
| 4414 | var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder); | |
| 4415 | defer attributes.deinit(&o.builder); | |
| 4416 | var it = iterateParamTypes(o, pt, fn_info); | |
| 4417 | if (firstParamSRet(fn_info, zcu, zcu.getTarget())) it.llvm_index += 1; | |
| 4418 | if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) it.llvm_index += 1; | |
| 4419 | while (try it.next()) |lowering| switch (lowering) { | |
| 4420 | .byval => { | |
| 4421 | const param_index = it.zig_index - 1; | |
| 4422 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); | |
| 4423 | if (!isByRef(param_ty, zcu)) { | |
| 4424 | try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); | |
| 4425 | } | |
| 4426 | }, | |
| 4427 | .byref => { | |
| 4428 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | |
| 4429 | const param_llvm_ty = try o.lowerType(pt, param_ty); | |
| 4430 | const alignment = param_ty.abiAlignment(zcu); | |
| 4431 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); | |
| 4432 | }, | |
| 4433 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), | |
| 4434 | // No attributes needed for these. | |
| 4435 | .no_bits, | |
| 4436 | .abi_sized_int, | |
| 4437 | .multiple_llvm_types, | |
| 4438 | .float_array, | |
| 4439 | .i32_array, | |
| 4440 | .i64_array, | |
| 4441 | => continue, | |
| 4442 | ||
| 4443 | .slice => unreachable, // extern functions do not support slice types. | |
| 4444 | }; | |
| 4445 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 4605 | 4446 | } else { |
| 4606 | 4447 | const variable_index = try o.resolveGlobalNav(pt, nav_index); |
| 4607 | variable_index.setAlignment(pt.navAlignment(nav_index).toLlvm(), &o.builder); | |
| 4448 | variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder); | |
| 4608 | 4449 | if (resolved.@"linksection".toSlice(ip)) |section| |
| 4609 | 4450 | variable_index.setSection(try o.builder.string(section), &o.builder); |
| 4610 | 4451 | if (is_const) variable_index.setMutability(.constant, &o.builder); |
| ... | ... | @@ -4630,7 +4471,7 @@ pub const NavGen = struct { |
| 4630 | 4471 | debug_file, // File |
| 4631 | 4472 | debug_file, // Scope |
| 4632 | 4473 | line_number, |
| 4633 | try o.lowerDebugType(pt, ty), | |
| 4474 | try o.getDebugType(pt, ty), | |
| 4634 | 4475 | variable_index, |
| 4635 | 4476 | .{ .local = linkage == .internal }, |
| 4636 | 4477 | ); |
| ... | ... | @@ -4752,7 +4593,7 @@ pub const FuncGen = struct { |
| 4752 | 4593 | /// Have we seen loads or stores involving `allowzero` pointers? |
| 4753 | 4594 | allowzero_access: bool = false, |
| 4754 | 4595 | |
| 4755 | pub fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void { | |
| 4596 | fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void { | |
| 4756 | 4597 | // LLVM already considers null pointers to be valid in non-generic address spaces, so avoid |
| 4757 | 4598 | // pessimizing optimization for functions with accesses to such pointers. |
| 4758 | 4599 | if (info.flags.address_space == .generic and info.flags.is_allowzero) self.allowzero_access = true; |
| ... | ... | @@ -5220,7 +5061,7 @@ pub const FuncGen = struct { |
| 5220 | 5061 | try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)), |
| 5221 | 5062 | line_number, |
| 5222 | 5063 | line_number + func.lbrace_line, |
| 5223 | try o.lowerDebugType(pt, fn_ty), | |
| 5064 | try o.getDebugType(pt, fn_ty), | |
| 5224 | 5065 | .{ |
| 5225 | 5066 | .di_flags = .{ .StaticMember = true }, |
| 5226 | 5067 | .sp_flags = .{ |
| ... | ... | @@ -5490,10 +5331,10 @@ pub const FuncGen = struct { |
| 5490 | 5331 | if (ptr_info.flags.is_const) { |
| 5491 | 5332 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 5492 | 5333 | } |
| 5493 | const elem_align = (if (ptr_info.flags.alignment != .none) | |
| 5494 | @as(InternPool.Alignment, ptr_info.flags.alignment) | |
| 5495 | else | |
| 5496 | Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm(); | |
| 5334 | const elem_align: Builder.Alignment.Lazy = switch (ptr_info.flags.alignment) { | |
| 5335 | else => |a| .wrap(a.toLlvm()), | |
| 5336 | .none => try o.lazyAbiAlignment(pt, .fromInterned(ptr_info.child)), | |
| 5337 | }; | |
| 5497 | 5338 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); |
| 5498 | 5339 | }, |
| 5499 | 5340 | }; |
| ... | ... | @@ -5518,7 +5359,7 @@ pub const FuncGen = struct { |
| 5518 | 5359 | return .none; |
| 5519 | 5360 | } |
| 5520 | 5361 | |
| 5521 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5362 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBits(zcu)) { | |
| 5522 | 5363 | return .none; |
| 5523 | 5364 | } |
| 5524 | 5365 | |
| ... | ... | @@ -5637,7 +5478,7 @@ pub const FuncGen = struct { |
| 5637 | 5478 | return; |
| 5638 | 5479 | } |
| 5639 | 5480 | const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; |
| 5640 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5481 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 5641 | 5482 | if (Type.fromInterned(fn_info.return_type).isError(zcu)) { |
| 5642 | 5483 | // Functions with an empty error set are emitted with an error code |
| 5643 | 5484 | // return type and return zero so they can be function pointers coerced |
| ... | ... | @@ -5702,7 +5543,7 @@ pub const FuncGen = struct { |
| 5702 | 5543 | const ptr_ty = self.typeOf(un_op); |
| 5703 | 5544 | const ret_ty = ptr_ty.childType(zcu); |
| 5704 | 5545 | const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; |
| 5705 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5546 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 5706 | 5547 | if (Type.fromInterned(fn_info.return_type).isError(zcu)) { |
| 5707 | 5548 | // Functions with an empty error set are emitted with an error code |
| 5708 | 5549 | // return type and return zero so they can be function pointers coerced |
| ... | ... | @@ -5833,14 +5674,13 @@ pub const FuncGen = struct { |
| 5833 | 5674 | const o = self.ng.object; |
| 5834 | 5675 | const pt = self.ng.pt; |
| 5835 | 5676 | const zcu = pt.zcu; |
| 5836 | const ip = &zcu.intern_pool; | |
| 5837 | 5677 | const scalar_ty = operand_ty.scalarType(zcu); |
| 5838 | 5678 | const int_ty = switch (scalar_ty.zigTypeTag(zcu)) { |
| 5839 | 5679 | .@"enum" => scalar_ty.intTagType(zcu), |
| 5840 | 5680 | .int, .bool, .pointer, .error_set => scalar_ty, |
| 5841 | 5681 | .optional => blk: { |
| 5842 | 5682 | const payload_ty = operand_ty.optionalChild(zcu); |
| 5843 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or | |
| 5683 | if (!payload_ty.hasRuntimeBits(zcu) or | |
| 5844 | 5684 | operand_ty.optionalReprIsPayload(zcu)) |
| 5845 | 5685 | { |
| 5846 | 5686 | break :blk operand_ty; |
| ... | ... | @@ -5912,12 +5752,7 @@ pub const FuncGen = struct { |
| 5912 | 5752 | return phi.toValue(); |
| 5913 | 5753 | }, |
| 5914 | 5754 | .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }), |
| 5915 | .@"struct" => blk: { | |
| 5916 | const struct_obj = ip.loadStructType(scalar_ty.toIntern()); | |
| 5917 | assert(struct_obj.layout == .@"packed"); | |
| 5918 | const backing_index = struct_obj.backingIntTypeUnordered(ip); | |
| 5919 | break :blk Type.fromInterned(backing_index); | |
| 5920 | }, | |
| 5755 | .@"struct" => scalar_ty.bitpackBackingInt(zcu), | |
| 5921 | 5756 | else => unreachable, |
| 5922 | 5757 | }; |
| 5923 | 5758 | const is_signed = int_ty.isSignedInt(zcu); |
| ... | ... | @@ -5953,7 +5788,7 @@ pub const FuncGen = struct { |
| 5953 | 5788 | return .none; |
| 5954 | 5789 | } |
| 5955 | 5790 | |
| 5956 | const have_block_result = inst_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu); | |
| 5791 | const have_block_result = inst_ty.hasRuntimeBits(zcu); | |
| 5957 | 5792 | |
| 5958 | 5793 | var breaks: BreakList = if (have_block_result) .{ .list = .{} } else .{ .len = 0 }; |
| 5959 | 5794 | defer if (have_block_result) breaks.list.deinit(self.gpa); |
| ... | ... | @@ -6000,7 +5835,7 @@ pub const FuncGen = struct { |
| 6000 | 5835 | |
| 6001 | 5836 | // Add the values to the lists only if the break provides a value. |
| 6002 | 5837 | const operand_ty = self.typeOf(branch.operand); |
| 6003 | if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5838 | if (operand_ty.hasRuntimeBits(zcu)) { | |
| 6004 | 5839 | const val = try self.resolveInst(branch.operand); |
| 6005 | 5840 | |
| 6006 | 5841 | // For the phi node, we need the basic blocks and the values of the |
| ... | ... | @@ -6309,7 +6144,7 @@ pub const FuncGen = struct { |
| 6309 | 6144 | const pt = fg.ng.pt; |
| 6310 | 6145 | const zcu = pt.zcu; |
| 6311 | 6146 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 6312 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 6147 | const payload_has_bits = payload_ty.hasRuntimeBits(zcu); | |
| 6313 | 6148 | const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); |
| 6314 | 6149 | const error_type = try o.errorIntType(pt); |
| 6315 | 6150 | |
| ... | ... | @@ -6645,7 +6480,7 @@ pub const FuncGen = struct { |
| 6645 | 6480 | const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu)); |
| 6646 | 6481 | const slice_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst)); |
| 6647 | 6482 | const operand = try self.resolveInst(ty_op.operand); |
| 6648 | if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 6483 | if (!array_ty.hasRuntimeBits(zcu)) | |
| 6649 | 6484 | return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); |
| 6650 | 6485 | const ptr = try self.wip.gep(.inbounds, try o.lowerType(pt, array_ty), operand, &.{ |
| 6651 | 6486 | try o.builder.intValue(llvm_usize, 0), try o.builder.intValue(llvm_usize, 0), |
| ... | ... | @@ -6828,7 +6663,7 @@ pub const FuncGen = struct { |
| 6828 | 6663 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6829 | 6664 | const slice_ptr = try self.resolveInst(ty_op.operand); |
| 6830 | 6665 | const slice_ptr_ty = self.typeOf(ty_op.operand); |
| 6831 | const slice_llvm_ty = try o.lowerPtrElemTy(pt, slice_ptr_ty.childType(zcu)); | |
| 6666 | const slice_llvm_ty = try o.lowerType(pt, slice_ptr_ty.childType(zcu)); | |
| 6832 | 6667 | |
| 6833 | 6668 | return self.wip.gepStruct(slice_llvm_ty, slice_ptr, index, ""); |
| 6834 | 6669 | } |
| ... | ... | @@ -6842,7 +6677,7 @@ pub const FuncGen = struct { |
| 6842 | 6677 | const slice = try self.resolveInst(bin_op.lhs); |
| 6843 | 6678 | const index = try self.resolveInst(bin_op.rhs); |
| 6844 | 6679 | const elem_ty = slice_ty.childType(zcu); |
| 6845 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty); | |
| 6680 | const llvm_elem_ty = try o.lowerType(pt, elem_ty); | |
| 6846 | 6681 | const base_ptr = try self.wip.extractValue(slice, &.{0}, ""); |
| 6847 | 6682 | const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, ""); |
| 6848 | 6683 | if (isByRef(elem_ty, zcu)) { |
| ... | ... | @@ -6867,7 +6702,7 @@ pub const FuncGen = struct { |
| 6867 | 6702 | |
| 6868 | 6703 | const slice = try self.resolveInst(bin_op.lhs); |
| 6869 | 6704 | const index = try self.resolveInst(bin_op.rhs); |
| 6870 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, slice_ty.childType(zcu)); | |
| 6705 | const llvm_elem_ty = try o.lowerType(pt, slice_ty.childType(zcu)); | |
| 6871 | 6706 | const base_ptr = try self.wip.extractValue(slice, &.{0}, ""); |
| 6872 | 6707 | return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, ""); |
| 6873 | 6708 | } |
| ... | ... | @@ -6906,16 +6741,11 @@ pub const FuncGen = struct { |
| 6906 | 6741 | const zcu = pt.zcu; |
| 6907 | 6742 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6908 | 6743 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 6909 | const elem_ty = ptr_ty.childType(zcu); | |
| 6910 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty); | |
| 6744 | const elem_ty = ptr_ty.indexableElem(zcu); | |
| 6745 | const llvm_elem_ty = try o.lowerType(pt, elem_ty); | |
| 6911 | 6746 | const base_ptr = try self.resolveInst(bin_op.lhs); |
| 6912 | 6747 | const rhs = try self.resolveInst(bin_op.rhs); |
| 6913 | // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch | |
| 6914 | const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu)) | |
| 6915 | // If this is a single-item pointer to an array, we need another index in the GEP. | |
| 6916 | &.{ try o.builder.intValue(try o.lowerType(pt, Type.usize), 0), rhs } | |
| 6917 | else | |
| 6918 | &.{rhs}, ""); | |
| 6748 | const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, ""); | |
| 6919 | 6749 | if (isByRef(elem_ty, zcu)) { |
| 6920 | 6750 | self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); |
| 6921 | 6751 | const ptr_align = (ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm(); |
| ... | ... | @@ -6934,8 +6764,8 @@ pub const FuncGen = struct { |
| 6934 | 6764 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6935 | 6765 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 6936 | 6766 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 6937 | const elem_ty = ptr_ty.childType(zcu); | |
| 6938 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return self.resolveInst(bin_op.lhs); | |
| 6767 | const elem_ty = ptr_ty.indexableElem(zcu); | |
| 6768 | assert(elem_ty.hasRuntimeBits(zcu)); | |
| 6939 | 6769 | |
| 6940 | 6770 | const base_ptr = try self.resolveInst(bin_op.lhs); |
| 6941 | 6771 | const rhs = try self.resolveInst(bin_op.rhs); |
| ... | ... | @@ -6943,12 +6773,8 @@ pub const FuncGen = struct { |
| 6943 | 6773 | const elem_ptr = ty_pl.ty.toType(); |
| 6944 | 6774 | if (elem_ptr.ptrInfo(zcu).flags.vector_index != .none) return base_ptr; |
| 6945 | 6775 | |
| 6946 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty); | |
| 6947 | return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu)) | |
| 6948 | // If this is a single-item pointer to an array, we need another index in the GEP. | |
| 6949 | &.{ try o.builder.intValue(try o.lowerType(pt, Type.usize), 0), rhs } | |
| 6950 | else | |
| 6951 | &.{rhs}, ""); | |
| 6776 | const llvm_elem_ty = try o.lowerType(pt, elem_ty); | |
| 6777 | return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, ""); | |
| 6952 | 6778 | } |
| 6953 | 6779 | |
| 6954 | 6780 | fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -6956,7 +6782,7 @@ pub const FuncGen = struct { |
| 6956 | 6782 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 6957 | 6783 | const struct_ptr = try self.resolveInst(struct_field.struct_operand); |
| 6958 | 6784 | const struct_ptr_ty = self.typeOf(struct_field.struct_operand); |
| 6959 | return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, struct_field.field_index); | |
| 6785 | return self.fieldPtr(struct_ptr, struct_ptr_ty, struct_field.field_index); | |
| 6960 | 6786 | } |
| 6961 | 6787 | |
| 6962 | 6788 | fn airStructFieldPtrIndex( |
| ... | ... | @@ -6967,7 +6793,7 @@ pub const FuncGen = struct { |
| 6967 | 6793 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6968 | 6794 | const struct_ptr = try self.resolveInst(ty_op.operand); |
| 6969 | 6795 | const struct_ptr_ty = self.typeOf(ty_op.operand); |
| 6970 | return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, field_index); | |
| 6796 | return self.fieldPtr(struct_ptr, struct_ptr_ty, field_index); | |
| 6971 | 6797 | } |
| 6972 | 6798 | |
| 6973 | 6799 | fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -6980,7 +6806,7 @@ pub const FuncGen = struct { |
| 6980 | 6806 | const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); |
| 6981 | 6807 | const field_index = struct_field.field_index; |
| 6982 | 6808 | const field_ty = struct_ty.fieldType(field_index, zcu); |
| 6983 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; | |
| 6809 | if (!field_ty.hasRuntimeBits(zcu)) return .none; | |
| 6984 | 6810 | |
| 6985 | 6811 | if (!isByRef(struct_ty, zcu)) { |
| 6986 | 6812 | assert(!isByRef(field_ty, zcu)); |
| ... | ... | @@ -6999,11 +6825,6 @@ pub const FuncGen = struct { |
| 6999 | 6825 | const truncated_int = |
| 7000 | 6826 | try self.wip.cast(.trunc, shifted_value, same_size_int, ""); |
| 7001 | 6827 | return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, ""); |
| 7002 | } else if (field_ty.isPtrAtRuntime(zcu)) { | |
| 7003 | const same_size_int = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); | |
| 7004 | const truncated_int = | |
| 7005 | try self.wip.cast(.trunc, shifted_value, same_size_int, ""); | |
| 7006 | return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, ""); | |
| 7007 | 6828 | } |
| 7008 | 6829 | return self.wip.cast(.trunc, shifted_value, elem_llvm_ty, ""); |
| 7009 | 6830 | }, |
| ... | ... | @@ -7021,11 +6842,6 @@ pub const FuncGen = struct { |
| 7021 | 6842 | const truncated_int = |
| 7022 | 6843 | try self.wip.cast(.trunc, containing_int, same_size_int, ""); |
| 7023 | 6844 | return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, ""); |
| 7024 | } else if (field_ty.isPtrAtRuntime(zcu)) { | |
| 7025 | const same_size_int = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); | |
| 7026 | const truncated_int = | |
| 7027 | try self.wip.cast(.trunc, containing_int, same_size_int, ""); | |
| 7028 | return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, ""); | |
| 7029 | 6845 | } |
| 7030 | 6846 | return self.wip.cast(.trunc, containing_int, elem_llvm_ty, ""); |
| 7031 | 6847 | }, |
| ... | ... | @@ -7041,15 +6857,17 @@ pub const FuncGen = struct { |
| 7041 | 6857 | const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?; |
| 7042 | 6858 | const field_ptr = |
| 7043 | 6859 | try self.wip.gepStruct(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); |
| 7044 | const alignment = struct_ty.fieldAlignment(field_index, zcu); | |
| 6860 | const explicit_alignment = struct_ty.explicitFieldAlignment(field_index, zcu); | |
| 7045 | 6861 | const field_ptr_ty = try pt.ptrType(.{ |
| 7046 | 6862 | .child = field_ty.toIntern(), |
| 7047 | .flags = .{ .alignment = alignment }, | |
| 6863 | .flags = .{ .alignment = explicit_alignment }, | |
| 7048 | 6864 | }); |
| 7049 | 6865 | if (isByRef(field_ty, zcu)) { |
| 7050 | assert(alignment != .none); | |
| 7051 | const field_alignment = alignment.toLlvm(); | |
| 7052 | return self.loadByRef(field_ptr, field_ty, field_alignment, .normal); | |
| 6866 | const alignment = switch (explicit_alignment) { | |
| 6867 | .none => field_ty.abiAlignment(zcu), | |
| 6868 | else => |a| a, | |
| 6869 | }; | |
| 6870 | return self.loadByRef(field_ptr, field_ty, alignment.toLlvm(), .normal); | |
| 7053 | 6871 | } else { |
| 7054 | 6872 | return self.load(field_ptr, field_ptr_ty); |
| 7055 | 6873 | } |
| ... | ... | @@ -7057,7 +6875,7 @@ pub const FuncGen = struct { |
| 7057 | 6875 | .@"union" => { |
| 7058 | 6876 | const union_llvm_ty = try o.lowerType(pt, struct_ty); |
| 7059 | 6877 | const layout = struct_ty.unionGetLayout(zcu); |
| 7060 | const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); | |
| 6878 | const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); | |
| 7061 | 6879 | const field_ptr = |
| 7062 | 6880 | try self.wip.gepStruct(union_llvm_ty, struct_llvm_val, payload_index, ""); |
| 7063 | 6881 | const payload_alignment = layout.payload_align.toLlvm(); |
| ... | ... | @@ -7150,7 +6968,7 @@ pub const FuncGen = struct { |
| 7150 | 6968 | self.file, |
| 7151 | 6969 | self.scope, |
| 7152 | 6970 | self.prev_dbg_line, |
| 7153 | try o.lowerDebugType(pt, ptr_ty.childType(zcu)), | |
| 6971 | try o.getDebugType(pt, ptr_ty.childType(zcu)), | |
| 7154 | 6972 | ); |
| 7155 | 6973 | |
| 7156 | 6974 | _ = try self.wip.callIntrinsic( |
| ... | ... | @@ -7183,7 +7001,7 @@ pub const FuncGen = struct { |
| 7183 | 7001 | self.file, |
| 7184 | 7002 | self.scope, |
| 7185 | 7003 | self.prev_dbg_line, |
| 7186 | try o.lowerDebugType(pt, operand_ty), | |
| 7004 | try o.getDebugType(pt, operand_ty), | |
| 7187 | 7005 | arg_no: { |
| 7188 | 7006 | self.arg_inline_index += 1; |
| 7189 | 7007 | break :arg_no self.arg_inline_index; |
| ... | ... | @@ -7193,7 +7011,7 @@ pub const FuncGen = struct { |
| 7193 | 7011 | self.file, |
| 7194 | 7012 | self.scope, |
| 7195 | 7013 | self.prev_dbg_line, |
| 7196 | try o.lowerDebugType(pt, operand_ty), | |
| 7014 | try o.getDebugType(pt, operand_ty), | |
| 7197 | 7015 | ); |
| 7198 | 7016 | |
| 7199 | 7017 | const zcu = pt.zcu; |
| ... | ... | @@ -7284,6 +7102,7 @@ pub const FuncGen = struct { |
| 7284 | 7102 | const llvm_param_attrs = try arena.alloc(Builder.Type, max_param_count); |
| 7285 | 7103 | const pt = self.ng.pt; |
| 7286 | 7104 | const zcu = pt.zcu; |
| 7105 | const ip = &zcu.intern_pool; | |
| 7287 | 7106 | const target = zcu.getTarget(); |
| 7288 | 7107 | |
| 7289 | 7108 | var llvm_ret_i: usize = 0; |
| ... | ... | @@ -7308,7 +7127,7 @@ pub const FuncGen = struct { |
| 7308 | 7127 | const output_inst = try self.resolveInst(output.operand); |
| 7309 | 7128 | const output_ty = self.typeOf(output.operand); |
| 7310 | 7129 | assert(output_ty.zigTypeTag(zcu) == .pointer); |
| 7311 | const elem_llvm_ty = try o.lowerPtrElemTy(pt, output_ty.childType(zcu)); | |
| 7130 | const elem_llvm_ty = try o.lowerType(pt, output_ty.childType(zcu)); | |
| 7312 | 7131 | |
| 7313 | 7132 | switch (constraint[0]) { |
| 7314 | 7133 | '=' => {}, |
| ... | ... | @@ -7426,7 +7245,7 @@ pub const FuncGen = struct { |
| 7426 | 7245 | llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { |
| 7427 | 7246 | if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); |
| 7428 | 7247 | |
| 7429 | break :blk try o.lowerPtrElemTy(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu)); | |
| 7248 | break :blk try o.lowerType(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu)); | |
| 7430 | 7249 | } else .none; |
| 7431 | 7250 | |
| 7432 | 7251 | llvm_param_i += 1; |
| ... | ... | @@ -7440,7 +7259,7 @@ pub const FuncGen = struct { |
| 7440 | 7259 | if (constraint[0] != '+') continue; |
| 7441 | 7260 | |
| 7442 | 7261 | const rw_ty = self.typeOf(output.operand); |
| 7443 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, rw_ty.childType(zcu)); | |
| 7262 | const llvm_elem_ty = try o.lowerType(pt, rw_ty.childType(zcu)); | |
| 7444 | 7263 | if (llvm_ret_indirect[output.index]) { |
| 7445 | 7264 | llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; |
| 7446 | 7265 | llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); |
| ... | ... | @@ -7467,30 +7286,21 @@ pub const FuncGen = struct { |
| 7467 | 7286 | total_i += 1; |
| 7468 | 7287 | } |
| 7469 | 7288 | |
| 7470 | const ip = &zcu.intern_pool; | |
| 7471 | const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; | |
| 7472 | const struct_type: Type = .fromInterned(aggregate.ty); | |
| 7473 | 7289 | if (total_i != 0) try llvm_constraints.append(gpa, ','); |
| 7474 | switch (aggregate.storage) { | |
| 7475 | .elems => |elems| for (elems, 0..) |elem, i| { | |
| 7476 | switch (elem) { | |
| 7477 | .bool_true => { | |
| 7478 | const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 7479 | total_i += try appendConstraints(gpa, &llvm_constraints, name, target); | |
| 7480 | }, | |
| 7481 | .bool_false => continue, | |
| 7482 | else => unreachable, | |
| 7483 | } | |
| 7484 | }, | |
| 7485 | .repeated_elem => |elem| switch (elem) { | |
| 7486 | .bool_true => for (0..struct_type.structFieldCount(zcu)) |i| { | |
| 7487 | const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 7488 | total_i += try appendConstraints(gpa, &llvm_constraints, name, target); | |
| 7489 | }, | |
| 7490 | .bool_false => {}, | |
| 7491 | else => unreachable, | |
| 7492 | }, | |
| 7493 | .bytes => @panic("TODO"), | |
| 7290 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 7291 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 7292 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 7293 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 7294 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 7295 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 7296 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 7297 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 7298 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 7299 | 0 => continue, // field is false | |
| 7300 | 1 => {}, // field is true | |
| 7301 | } | |
| 7302 | const name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 7303 | total_i += try appendConstraints(gpa, &llvm_constraints, name, target); | |
| 7494 | 7304 | } |
| 7495 | 7305 | |
| 7496 | 7306 | // We have finished scanning through all inputs/outputs, so the number of |
| ... | ... | @@ -7676,7 +7486,7 @@ pub const FuncGen = struct { |
| 7676 | 7486 | |
| 7677 | 7487 | comptime assert(optional_layout_version == 3); |
| 7678 | 7488 | |
| 7679 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7489 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7680 | 7490 | const loaded = if (operand_is_ptr) |
| 7681 | 7491 | try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "") |
| 7682 | 7492 | else |
| ... | ... | @@ -7719,7 +7529,7 @@ pub const FuncGen = struct { |
| 7719 | 7529 | |
| 7720 | 7530 | if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); |
| 7721 | 7531 | |
| 7722 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7532 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7723 | 7533 | const loaded = if (operand_is_ptr) |
| 7724 | 7534 | try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "") |
| 7725 | 7535 | else |
| ... | ... | @@ -7746,7 +7556,7 @@ pub const FuncGen = struct { |
| 7746 | 7556 | const operand = try self.resolveInst(ty_op.operand); |
| 7747 | 7557 | const optional_ty = self.typeOf(ty_op.operand).childType(zcu); |
| 7748 | 7558 | const payload_ty = optional_ty.optionalChild(zcu); |
| 7749 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7559 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7750 | 7560 | // We have a pointer to a zero-bit value and we need to return |
| 7751 | 7561 | // a pointer to a zero-bit value. |
| 7752 | 7562 | return operand; |
| ... | ... | @@ -7774,7 +7584,7 @@ pub const FuncGen = struct { |
| 7774 | 7584 | const access_kind: Builder.MemoryAccessKind = |
| 7775 | 7585 | if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 7776 | 7586 | |
| 7777 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7587 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7778 | 7588 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7779 | 7589 | |
| 7780 | 7590 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| ... | ... | @@ -7810,7 +7620,7 @@ pub const FuncGen = struct { |
| 7810 | 7620 | const operand = try self.resolveInst(ty_op.operand); |
| 7811 | 7621 | const optional_ty = self.typeOf(ty_op.operand); |
| 7812 | 7622 | const payload_ty = self.typeOfIndex(inst); |
| 7813 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; | |
| 7623 | if (!payload_ty.hasRuntimeBits(zcu)) return .none; | |
| 7814 | 7624 | |
| 7815 | 7625 | if (optional_ty.optionalReprIsPayload(zcu)) { |
| 7816 | 7626 | // Payload value is the same as the optional value. |
| ... | ... | @@ -7832,7 +7642,7 @@ pub const FuncGen = struct { |
| 7832 | 7642 | const result_ty = self.typeOfIndex(inst); |
| 7833 | 7643 | const payload_ty = if (operand_is_ptr) result_ty.childType(zcu) else result_ty; |
| 7834 | 7644 | |
| 7835 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7645 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7836 | 7646 | return if (operand_is_ptr) operand else .none; |
| 7837 | 7647 | } |
| 7838 | 7648 | const offset = try errUnionPayloadOffset(payload_ty, pt); |
| ... | ... | @@ -7876,7 +7686,7 @@ pub const FuncGen = struct { |
| 7876 | 7686 | if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 7877 | 7687 | |
| 7878 | 7688 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 7879 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7689 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7880 | 7690 | if (!operand_is_ptr) return operand; |
| 7881 | 7691 | |
| 7882 | 7692 | self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); |
| ... | ... | @@ -7912,7 +7722,7 @@ pub const FuncGen = struct { |
| 7912 | 7722 | const access_kind: Builder.MemoryAccessKind = |
| 7913 | 7723 | if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 7914 | 7724 | |
| 7915 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7725 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 7916 | 7726 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7917 | 7727 | |
| 7918 | 7728 | _ = try self.wip.store(access_kind, non_error_val, operand, .default); |
| ... | ... | @@ -7959,9 +7769,8 @@ pub const FuncGen = struct { |
| 7959 | 7769 | const struct_llvm_ty = try o.lowerType(pt, struct_ty); |
| 7960 | 7770 | const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?; |
| 7961 | 7771 | assert(self.err_ret_trace != .none); |
| 7962 | const field_ptr = | |
| 7963 | try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, ""); | |
| 7964 | const field_alignment = struct_ty.fieldAlignment(field_index, zcu); | |
| 7772 | const field_ptr = try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, ""); | |
| 7773 | const field_alignment = struct_ty.explicitFieldAlignment(field_index, zcu); | |
| 7965 | 7774 | const field_ty = struct_ty.fieldType(field_index, zcu); |
| 7966 | 7775 | const field_ptr_ty = try pt.ptrType(.{ |
| 7967 | 7776 | .child = field_ty.toIntern(), |
| ... | ... | @@ -8002,7 +7811,7 @@ pub const FuncGen = struct { |
| 8002 | 7811 | const payload_ty = self.typeOf(ty_op.operand); |
| 8003 | 7812 | const non_null_bit = try o.builder.intValue(.i8, 1); |
| 8004 | 7813 | comptime assert(optional_layout_version == 3); |
| 8005 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return non_null_bit; | |
| 7814 | assert(payload_ty.hasRuntimeBits(zcu)); | |
| 8006 | 7815 | const operand = try self.resolveInst(ty_op.operand); |
| 8007 | 7816 | const optional_ty = self.typeOfIndex(inst); |
| 8008 | 7817 | if (optional_ty.optionalReprIsPayload(zcu)) return operand; |
| ... | ... | @@ -8036,9 +7845,7 @@ pub const FuncGen = struct { |
| 8036 | 7845 | const err_un_ty = self.typeOfIndex(inst); |
| 8037 | 7846 | const operand = try self.resolveInst(ty_op.operand); |
| 8038 | 7847 | const payload_ty = self.typeOf(ty_op.operand); |
| 8039 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 8040 | return operand; | |
| 8041 | } | |
| 7848 | assert(payload_ty.hasRuntimeBits(zcu)); | |
| 8042 | 7849 | const ok_err_code = try o.builder.intValue(try o.errorIntType(pt), 0); |
| 8043 | 7850 | const err_un_llvm_ty = try o.lowerType(pt, err_un_ty); |
| 8044 | 7851 | |
| ... | ... | @@ -8078,7 +7885,7 @@ pub const FuncGen = struct { |
| 8078 | 7885 | const err_un_ty = self.typeOfIndex(inst); |
| 8079 | 7886 | const payload_ty = err_un_ty.errorUnionPayload(zcu); |
| 8080 | 7887 | const operand = try self.resolveInst(ty_op.operand); |
| 8081 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return operand; | |
| 7888 | if (!payload_ty.hasRuntimeBits(zcu)) return operand; | |
| 8082 | 7889 | const err_un_llvm_ty = try o.lowerType(pt, err_un_ty); |
| 8083 | 7890 | |
| 8084 | 7891 | const payload_offset = try errUnionPayloadOffset(payload_ty, pt); |
| ... | ... | @@ -8530,7 +8337,7 @@ pub const FuncGen = struct { |
| 8530 | 8337 | const ptr = try self.resolveInst(bin_op.lhs); |
| 8531 | 8338 | const offset = try self.resolveInst(bin_op.rhs); |
| 8532 | 8339 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 8533 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, ptr_ty.childType(zcu)); | |
| 8340 | const llvm_elem_ty = try o.lowerType(pt, ptr_ty.childType(zcu)); | |
| 8534 | 8341 | switch (ptr_ty.ptrSize(zcu)) { |
| 8535 | 8342 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 8536 | 8343 | .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{ |
| ... | ... | @@ -8554,7 +8361,7 @@ pub const FuncGen = struct { |
| 8554 | 8361 | const offset = try self.resolveInst(bin_op.rhs); |
| 8555 | 8362 | const negative_offset = try self.wip.neg(offset, ""); |
| 8556 | 8363 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 8557 | const llvm_elem_ty = try o.lowerPtrElemTy(pt, ptr_ty.childType(zcu)); | |
| 8364 | const llvm_elem_ty = try o.lowerType(pt, ptr_ty.childType(zcu)); | |
| 8558 | 8365 | switch (ptr_ty.ptrSize(zcu)) { |
| 8559 | 8366 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 8560 | 8367 | .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{ |
| ... | ... | @@ -9515,7 +9322,7 @@ pub const FuncGen = struct { |
| 9515 | 9322 | self.file, |
| 9516 | 9323 | self.scope, |
| 9517 | 9324 | lbrace_line, |
| 9518 | try o.lowerDebugType(pt, inst_ty), | |
| 9325 | try o.getDebugType(pt, inst_ty), | |
| 9519 | 9326 | self.arg_index, |
| 9520 | 9327 | ); |
| 9521 | 9328 | |
| ... | ... | @@ -9581,7 +9388,7 @@ pub const FuncGen = struct { |
| 9581 | 9388 | const zcu = pt.zcu; |
| 9582 | 9389 | const ptr_ty = self.typeOfIndex(inst); |
| 9583 | 9390 | const pointee_type = ptr_ty.childType(zcu); |
| 9584 | if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) | |
| 9391 | if (!pointee_type.hasRuntimeBits(zcu)) | |
| 9585 | 9392 | return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); |
| 9586 | 9393 | |
| 9587 | 9394 | const pointee_llvm_ty = try o.lowerType(pt, pointee_type); |
| ... | ... | @@ -9595,7 +9402,7 @@ pub const FuncGen = struct { |
| 9595 | 9402 | const zcu = pt.zcu; |
| 9596 | 9403 | const ptr_ty = self.typeOfIndex(inst); |
| 9597 | 9404 | const ret_ty = ptr_ty.childType(zcu); |
| 9598 | if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) | |
| 9405 | if (!ret_ty.hasRuntimeBits(zcu)) | |
| 9599 | 9406 | return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); |
| 9600 | 9407 | if (self.ret_ptr != .none) return self.ret_ptr; |
| 9601 | 9408 | const ret_llvm_ty = try o.lowerType(pt, ret_ty); |
| ... | ... | @@ -9849,7 +9656,7 @@ pub const FuncGen = struct { |
| 9849 | 9656 | const ptr_ty = self.typeOf(atomic_load.ptr); |
| 9850 | 9657 | const info = ptr_ty.ptrInfo(zcu); |
| 9851 | 9658 | const elem_ty = Type.fromInterned(info.child); |
| 9852 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; | |
| 9659 | if (!elem_ty.hasRuntimeBits(zcu)) return .none; | |
| 9853 | 9660 | const ordering = toLlvmAtomicOrdering(atomic_load.order); |
| 9854 | 9661 | const llvm_abi_ty = try o.getAtomicAbiType(pt, elem_ty, false); |
| 9855 | 9662 | const ptr_alignment = (if (info.flags.alignment != .none) |
| ... | ... | @@ -9897,7 +9704,7 @@ pub const FuncGen = struct { |
| 9897 | 9704 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 9898 | 9705 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 9899 | 9706 | const operand_ty = ptr_ty.childType(zcu); |
| 9900 | if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .none; | |
| 9707 | if (!operand_ty.hasRuntimeBits(zcu)) return .none; | |
| 9901 | 9708 | const ptr = try self.resolveInst(bin_op.lhs); |
| 9902 | 9709 | var element = try self.resolveInst(bin_op.rhs); |
| 9903 | 9710 | const llvm_abi_ty = try o.getAtomicAbiType(pt, operand_ty, false); |
| ... | ... | @@ -10310,14 +10117,14 @@ pub const FuncGen = struct { |
| 10310 | 10117 | const ip = &zcu.intern_pool; |
| 10311 | 10118 | const enum_type = ip.loadEnumType(enum_ty.toIntern()); |
| 10312 | 10119 | |
| 10313 | // TODO: detect when the type changes and re-emit this function. | |
| 10120 | // TODO: detect when the type changes (`updateContainerType` will be called) and re-emit this function | |
| 10314 | 10121 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); |
| 10315 | 10122 | if (gop.found_existing) return gop.value_ptr.*; |
| 10316 | 10123 | errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); |
| 10317 | 10124 | |
| 10318 | 10125 | const target = &zcu.root_mod.resolved_target.result; |
| 10319 | 10126 | const function_index = try o.builder.addFunction( |
| 10320 | try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.tag_ty))}, .normal), | |
| 10127 | try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal), | |
| 10321 | 10128 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}), |
| 10322 | 10129 | toLlvmAddressSpace(.generic, target), |
| 10323 | 10130 | ); |
| ... | ... | @@ -10338,13 +10145,13 @@ pub const FuncGen = struct { |
| 10338 | 10145 | defer wip.deinit(); |
| 10339 | 10146 | wip.cursor = .{ .block = try wip.block(0, "Entry") }; |
| 10340 | 10147 | |
| 10341 | const named_block = try wip.block(@intCast(enum_type.names.len), "Named"); | |
| 10148 | const named_block = try wip.block(@intCast(enum_type.field_names.len), "Named"); | |
| 10342 | 10149 | const unnamed_block = try wip.block(1, "Unnamed"); |
| 10343 | 10150 | const tag_int_value = wip.arg(0); |
| 10344 | var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.names.len), .none); | |
| 10151 | var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.field_names.len), .none); | |
| 10345 | 10152 | defer wip_switch.finish(&wip); |
| 10346 | 10153 | |
| 10347 | for (0..enum_type.names.len) |field_index| { | |
| 10154 | for (0..enum_type.field_names.len) |field_index| { | |
| 10348 | 10155 | const this_tag_int_value = try o.lowerValue( |
| 10349 | 10156 | pt, |
| 10350 | 10157 | (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), |
| ... | ... | @@ -10813,15 +10620,14 @@ pub const FuncGen = struct { |
| 10813 | 10620 | }, |
| 10814 | 10621 | .@"struct" => { |
| 10815 | 10622 | if (zcu.typeToPackedStruct(result_ty)) |struct_type| { |
| 10816 | const backing_int_ty = struct_type.backingIntTypeUnordered(ip); | |
| 10817 | assert(backing_int_ty != .none); | |
| 10818 | const big_bits = Type.fromInterned(backing_int_ty).bitSize(zcu); | |
| 10623 | const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type); | |
| 10624 | const big_bits = backing_int_ty.bitSize(zcu); | |
| 10819 | 10625 | const int_ty = try o.builder.intType(@intCast(big_bits)); |
| 10820 | 10626 | comptime assert(Type.packed_struct_layout_version == 2); |
| 10821 | 10627 | var running_int = try o.builder.intValue(int_ty, 0); |
| 10822 | 10628 | var running_bits: u16 = 0; |
| 10823 | 10629 | for (elements, struct_type.field_types.get(ip)) |elem, field_ty| { |
| 10824 | if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 10630 | if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; | |
| 10825 | 10631 | |
| 10826 | 10632 | const non_int_val = try self.resolveInst(elem); |
| 10827 | 10633 | const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu)); |
| ... | ... | @@ -10853,12 +10659,12 @@ pub const FuncGen = struct { |
| 10853 | 10659 | |
| 10854 | 10660 | const llvm_elem = try self.resolveInst(elem); |
| 10855 | 10661 | const llvm_i = o.llvmFieldIndex(result_ty, i).?; |
| 10856 | const field_ptr = | |
| 10857 | try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, ""); | |
| 10662 | const field_ptr = try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, ""); | |
| 10663 | ||
| 10858 | 10664 | const field_ptr_ty = try pt.ptrType(.{ |
| 10859 | 10665 | .child = self.typeOf(elem).toIntern(), |
| 10860 | 10666 | .flags = .{ |
| 10861 | .alignment = result_ty.fieldAlignment(i, zcu), | |
| 10667 | .alignment = result_ty.explicitFieldAlignment(i, zcu), | |
| 10862 | 10668 | }, |
| 10863 | 10669 | }); |
| 10864 | 10670 | try self.store(field_ptr, field_ptr_ty, llvm_elem, .none); |
| ... | ... | @@ -10920,28 +10726,16 @@ pub const FuncGen = struct { |
| 10920 | 10726 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 10921 | 10727 | const union_ty = self.typeOfIndex(inst); |
| 10922 | 10728 | const union_llvm_ty = try o.lowerType(pt, union_ty); |
| 10923 | const layout = union_ty.unionGetLayout(zcu); | |
| 10924 | 10729 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 10925 | 10730 | |
| 10926 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | |
| 10927 | const big_bits = union_ty.bitSize(zcu); | |
| 10928 | const int_llvm_ty = try o.builder.intType(@intCast(big_bits)); | |
| 10929 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); | |
| 10930 | const non_int_val = try self.resolveInst(extra.init); | |
| 10931 | const small_int_ty = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); | |
| 10932 | const small_int_val = if (field_ty.isPtrAtRuntime(zcu)) | |
| 10933 | try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "") | |
| 10934 | else | |
| 10935 | try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); | |
| 10936 | return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, ""); | |
| 10937 | } | |
| 10731 | assert(union_obj.layout != .@"packed"); | |
| 10732 | ||
| 10733 | const layout = Type.getUnionLayout(union_obj, zcu); | |
| 10938 | 10734 | |
| 10939 | 10735 | const tag_int_val = blk: { |
| 10940 | 10736 | const tag_ty = union_ty.unionTagTypeHypothetical(zcu); |
| 10941 | const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | |
| 10942 | const enum_field_index = tag_ty.enumFieldIndex(union_field_name, zcu).?; | |
| 10943 | const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index); | |
| 10944 | break :blk try tag_val.intFromEnum(tag_ty, pt); | |
| 10737 | const tag_val = try pt.enumValueFieldIndex(tag_ty, extra.field_index); | |
| 10738 | break :blk tag_val.intFromEnum(zcu); | |
| 10945 | 10739 | }; |
| 10946 | 10740 | if (layout.payload_size == 0) { |
| 10947 | 10741 | if (layout.tag_size == 0) { |
| ... | ... | @@ -10963,16 +10757,14 @@ pub const FuncGen = struct { |
| 10963 | 10757 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); |
| 10964 | 10758 | const field_llvm_ty = try o.lowerType(pt, field_ty); |
| 10965 | 10759 | const field_size = field_ty.abiSize(zcu); |
| 10966 | const field_align = union_ty.fieldAlignment(extra.field_index, zcu); | |
| 10760 | const field_align = union_ty.explicitFieldAlignment(extra.field_index, zcu); | |
| 10967 | 10761 | const llvm_usize = try o.lowerType(pt, Type.usize); |
| 10968 | 10762 | const usize_zero = try o.builder.intValue(llvm_usize, 0); |
| 10969 | 10763 | |
| 10764 | assert(field_ty.hasRuntimeBits(zcu)); | |
| 10765 | ||
| 10970 | 10766 | const llvm_union_ty = t: { |
| 10971 | 10767 | const payload_ty = p: { |
| 10972 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 10973 | const padding_len = layout.payload_size; | |
| 10974 | break :p try o.builder.arrayType(padding_len, .i8); | |
| 10975 | } | |
| 10976 | 10768 | if (field_size == layout.payload_size) { |
| 10977 | 10769 | break :p field_llvm_ty; |
| 10978 | 10770 | } |
| ... | ... | @@ -10982,7 +10774,7 @@ pub const FuncGen = struct { |
| 10982 | 10774 | }); |
| 10983 | 10775 | }; |
| 10984 | 10776 | if (layout.tag_size == 0) break :t try o.builder.structType(.normal, &.{payload_ty}); |
| 10985 | const tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); | |
| 10777 | const tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); | |
| 10986 | 10778 | var fields: [3]Builder.Type = undefined; |
| 10987 | 10779 | var fields_len: usize = 2; |
| 10988 | 10780 | if (layout.tag_align.compare(.gte, layout.payload_align)) { |
| ... | ... | @@ -11023,11 +10815,11 @@ pub const FuncGen = struct { |
| 11023 | 10815 | const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); |
| 11024 | 10816 | const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) }; |
| 11025 | 10817 | const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, &indices, ""); |
| 11026 | const tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); | |
| 10818 | const tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); | |
| 11027 | 10819 | var big_int_space: Value.BigIntSpace = undefined; |
| 11028 | 10820 | const tag_big_int = tag_int_val.toBigInt(&big_int_space, zcu); |
| 11029 | 10821 | const llvm_tag = try o.builder.bigIntValue(tag_ty, tag_big_int); |
| 11030 | const tag_alignment = Type.fromInterned(union_obj.enum_tag_ty).abiAlignment(zcu).toLlvm(); | |
| 10822 | const tag_alignment = Type.fromInterned(union_obj.enum_tag_type).abiAlignment(zcu).toLlvm(); | |
| 11031 | 10823 | _ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment); |
| 11032 | 10824 | } |
| 11033 | 10825 | |
| ... | ... | @@ -11274,63 +11066,45 @@ pub const FuncGen = struct { |
| 11274 | 11066 | |
| 11275 | 11067 | fn fieldPtr( |
| 11276 | 11068 | self: *FuncGen, |
| 11277 | inst: Air.Inst.Index, | |
| 11278 | struct_ptr: Builder.Value, | |
| 11279 | struct_ptr_ty: Type, | |
| 11069 | aggregate_ptr: Builder.Value, | |
| 11070 | aggregate_ptr_ty: Type, | |
| 11280 | 11071 | field_index: u32, |
| 11281 | 11072 | ) !Builder.Value { |
| 11282 | 11073 | const o = self.ng.object; |
| 11283 | 11074 | const pt = self.ng.pt; |
| 11284 | 11075 | const zcu = pt.zcu; |
| 11285 | const struct_ty = struct_ptr_ty.childType(zcu); | |
| 11286 | switch (struct_ty.zigTypeTag(zcu)) { | |
| 11287 | .@"struct" => switch (struct_ty.containerLayout(zcu)) { | |
| 11288 | .@"packed" => { | |
| 11289 | const result_ty = self.typeOfIndex(inst); | |
| 11290 | const result_ty_info = result_ty.ptrInfo(zcu); | |
| 11291 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); | |
| 11292 | const struct_type = zcu.typeToStruct(struct_ty).?; | |
| 11293 | ||
| 11294 | if (result_ty_info.packed_offset.host_size != 0) { | |
| 11295 | // From LLVM's perspective, a pointer to a packed struct and a pointer | |
| 11296 | // to a field of a packed struct are the same. The difference is in the | |
| 11297 | // Zig pointer type which provides information for how to mask and shift | |
| 11298 | // out the relevant bits when accessing the pointee. | |
| 11299 | return struct_ptr; | |
| 11300 | } | |
| 11301 | ||
| 11302 | // We have a pointer to a packed struct field that happens to be byte-aligned. | |
| 11303 | // Offset our operand pointer by the correct number of bytes. | |
| 11304 | const byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8); | |
| 11305 | if (byte_offset == 0) return struct_ptr; | |
| 11306 | const usize_ty = try o.lowerType(pt, Type.usize); | |
| 11307 | const llvm_index = try o.builder.intValue(usize_ty, byte_offset); | |
| 11308 | return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, ""); | |
| 11309 | }, | |
| 11310 | else => { | |
| 11311 | const struct_llvm_ty = try o.lowerPtrElemTy(pt, struct_ty); | |
| 11312 | ||
| 11313 | if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| { | |
| 11314 | return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, ""); | |
| 11315 | } else { | |
| 11316 | // If we found no index then this means this is a zero sized field at the | |
| 11317 | // end of the struct. Treat our struct pointer as an array of two and get | |
| 11318 | // the index to the element at index `1` to get a pointer to the end of | |
| 11319 | // the struct. | |
| 11320 | const llvm_index = try o.builder.intValue( | |
| 11321 | try o.lowerType(pt, Type.usize), | |
| 11322 | @intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(zcu)), | |
| 11323 | ); | |
| 11324 | return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, ""); | |
| 11325 | } | |
| 11326 | }, | |
| 11076 | const aggregate_ty = aggregate_ptr_ty.childType(zcu); | |
| 11077 | if (aggregate_ty.containerLayout(zcu) == .@"packed") { | |
| 11078 | // A pointer to a bitpack field is equivalent to a pointer to the whole bitpack; the | |
| 11079 | // bit offset is represented in the pointer *type*. | |
| 11080 | return aggregate_ptr; | |
| 11081 | } | |
| 11082 | switch (aggregate_ty.zigTypeTag(zcu)) { | |
| 11083 | .@"struct" => { | |
| 11084 | if (!aggregate_ty.hasRuntimeBits(zcu)) { | |
| 11085 | return aggregate_ptr; | |
| 11086 | } | |
| 11087 | const struct_llvm_ty = try o.lowerType(pt, aggregate_ty); | |
| 11088 | if (o.llvmFieldIndex(aggregate_ty, field_index)) |llvm_field_index| { | |
| 11089 | return self.wip.gepStruct(struct_llvm_ty, aggregate_ptr, llvm_field_index, ""); | |
| 11090 | } else { | |
| 11091 | // If we found no index then this means this is a zero sized field at the | |
| 11092 | // end of the struct. Treat our struct pointer as an array of two and get | |
| 11093 | // the index to the element at index `1` to get a pointer to the end of | |
| 11094 | // the struct. | |
| 11095 | const llvm_index = try o.builder.intValue( | |
| 11096 | try o.lowerType(pt, Type.usize), | |
| 11097 | @intFromBool(aggregate_ty.hasRuntimeBits(zcu)), | |
| 11098 | ); | |
| 11099 | return self.wip.gep(.inbounds, struct_llvm_ty, aggregate_ptr, &.{llvm_index}, ""); | |
| 11100 | } | |
| 11327 | 11101 | }, |
| 11328 | 11102 | .@"union" => { |
| 11329 | const layout = struct_ty.unionGetLayout(zcu); | |
| 11330 | if (layout.payload_size == 0 or struct_ty.containerLayout(zcu) == .@"packed") return struct_ptr; | |
| 11331 | const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); | |
| 11332 | const union_llvm_ty = try o.lowerType(pt, struct_ty); | |
| 11333 | return self.wip.gepStruct(union_llvm_ty, struct_ptr, payload_index, ""); | |
| 11103 | const layout = aggregate_ty.unionGetLayout(zcu); | |
| 11104 | if (layout.payload_size == 0) return aggregate_ptr; | |
| 11105 | const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); | |
| 11106 | const union_llvm_ty = try o.lowerType(pt, aggregate_ty); | |
| 11107 | return self.wip.gepStruct(union_llvm_ty, aggregate_ptr, payload_index, ""); | |
| 11334 | 11108 | }, |
| 11335 | 11109 | else => unreachable, |
| 11336 | 11110 | } |
| ... | ... | @@ -11406,7 +11180,7 @@ pub const FuncGen = struct { |
| 11406 | 11180 | const zcu = pt.zcu; |
| 11407 | 11181 | const info = ptr_ty.ptrInfo(zcu); |
| 11408 | 11182 | const elem_ty = Type.fromInterned(info.child); |
| 11409 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; | |
| 11183 | if (!elem_ty.hasRuntimeBits(zcu)) return .none; | |
| 11410 | 11184 | |
| 11411 | 11185 | const ptr_alignment = (if (info.flags.alignment != .none) |
| 11412 | 11186 | @as(InternPool.Alignment, info.flags.alignment) |
| ... | ... | @@ -11478,7 +11252,7 @@ pub const FuncGen = struct { |
| 11478 | 11252 | const zcu = pt.zcu; |
| 11479 | 11253 | const info = ptr_ty.ptrInfo(zcu); |
| 11480 | 11254 | const elem_ty = Type.fromInterned(info.child); |
| 11481 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 11255 | if (!elem_ty.hasRuntimeBits(zcu)) { | |
| 11482 | 11256 | return; |
| 11483 | 11257 | } |
| 11484 | 11258 | const ptr_alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); |
| ... | ... | @@ -12061,7 +11835,7 @@ fn returnTypeByRef(zcu: *Zcu, target: *const std.Target, ty: Type) bool { |
| 12061 | 11835 | |
| 12062 | 11836 | fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const std.Target) bool { |
| 12063 | 11837 | const return_type = Type.fromInterned(fn_info.return_type); |
| 12064 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; | |
| 11838 | if (!return_type.hasRuntimeBits(zcu)) return false; | |
| 12065 | 11839 | |
| 12066 | 11840 | return switch (fn_info.cc) { |
| 12067 | 11841 | .auto => returnTypeByRef(zcu, target, return_type), |
| ... | ... | @@ -12101,11 +11875,9 @@ fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool { |
| 12101 | 11875 | fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { |
| 12102 | 11876 | const zcu = pt.zcu; |
| 12103 | 11877 | const return_type = Type.fromInterned(fn_info.return_type); |
| 12104 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 12105 | // If the return type is an error set or an error union, then we make this | |
| 12106 | // anyerror return type instead, so that it can be coerced into a function | |
| 12107 | // pointer type which has anyerror as the return type. | |
| 12108 | return if (return_type.isError(zcu)) try o.errorIntType(pt) else .void; | |
| 11878 | if (!return_type.hasRuntimeBits(zcu)) { | |
| 11879 | assert(!return_type.isError(zcu)); | |
| 11880 | return .void; | |
| 12109 | 11881 | } |
| 12110 | 11882 | const target = zcu.getTarget(); |
| 12111 | 11883 | switch (fn_info.cc) { |
| ... | ... | @@ -12149,7 +11921,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) |
| 12149 | 11921 | var types: [8]Builder.Type = undefined; |
| 12150 | 11922 | for (0..return_type.structFieldCount(zcu)) |field_index| { |
| 12151 | 11923 | const field_ty = return_type.fieldType(field_index, zcu); |
| 12152 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 11924 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 12153 | 11925 | types[types_len] = try o.lowerType(pt, field_ty); |
| 12154 | 11926 | types_len += 1; |
| 12155 | 11927 | } |
| ... | ... | @@ -12187,6 +11959,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu |
| 12187 | 11959 | const zcu = pt.zcu; |
| 12188 | 11960 | const ip = &zcu.intern_pool; |
| 12189 | 11961 | const return_type = Type.fromInterned(fn_info.return_type); |
| 11962 | return_type.assertHasLayout(zcu); | |
| 12190 | 11963 | if (isScalar(zcu, return_type)) { |
| 12191 | 11964 | return o.lowerType(pt, return_type); |
| 12192 | 11965 | } |
| ... | ... | @@ -12235,9 +12008,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu |
| 12235 | 12008 | assert(first_non_integer orelse classes.len == types_index); |
| 12236 | 12009 | switch (ip.indexToKey(return_type.toIntern())) { |
| 12237 | 12010 | .struct_type => { |
| 12238 | const struct_type = ip.loadStructType(return_type.toIntern()); | |
| 12239 | assert(struct_type.haveLayout(ip)); | |
| 12240 | const size: u64 = struct_type.sizeUnordered(ip); | |
| 12011 | const size = return_type.abiSize(zcu); | |
| 12241 | 12012 | assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); |
| 12242 | 12013 | if (size % 8 > 0) { |
| 12243 | 12014 | types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8)); |
| ... | ... | @@ -12273,7 +12044,7 @@ const ParamTypeIterator = struct { |
| 12273 | 12044 | i64_array: u8, |
| 12274 | 12045 | }; |
| 12275 | 12046 | |
| 12276 | pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { | |
| 12047 | fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { | |
| 12277 | 12048 | if (it.zig_index >= it.fn_info.param_types.len) return null; |
| 12278 | 12049 | const ip = &it.pt.zcu.intern_pool; |
| 12279 | 12050 | const ty = it.fn_info.param_types.get(ip)[it.zig_index]; |
| ... | ... | @@ -12282,7 +12053,7 @@ const ParamTypeIterator = struct { |
| 12282 | 12053 | } |
| 12283 | 12054 | |
| 12284 | 12055 | /// `airCall` uses this instead of `next` so that it can take into account variadic functions. |
| 12285 | pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { | |
| 12056 | fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { | |
| 12286 | 12057 | assert(std.meta.eql(it.pt, fg.ng.pt)); |
| 12287 | 12058 | const ip = &it.pt.zcu.intern_pool; |
| 12288 | 12059 | if (it.zig_index >= it.fn_info.param_types.len) { |
| ... | ... | @@ -12301,7 +12072,7 @@ const ParamTypeIterator = struct { |
| 12301 | 12072 | const zcu = pt.zcu; |
| 12302 | 12073 | const target = zcu.getTarget(); |
| 12303 | 12074 | |
| 12304 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 12075 | if (!ty.hasRuntimeBits(zcu)) { | |
| 12305 | 12076 | it.zig_index += 1; |
| 12306 | 12077 | return .no_bits; |
| 12307 | 12078 | } |
| ... | ... | @@ -12396,7 +12167,7 @@ const ParamTypeIterator = struct { |
| 12396 | 12167 | it.types_len = 0; |
| 12397 | 12168 | for (0..ty.structFieldCount(zcu)) |field_index| { |
| 12398 | 12169 | const field_ty = ty.fieldType(field_index, zcu); |
| 12399 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 12170 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 12400 | 12171 | it.types_buffer[it.types_len] = try it.object.lowerType(pt, field_ty); |
| 12401 | 12172 | it.types_len += 1; |
| 12402 | 12173 | } |
| ... | ... | @@ -12473,6 +12244,7 @@ const ParamTypeIterator = struct { |
| 12473 | 12244 | fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { |
| 12474 | 12245 | const zcu = it.pt.zcu; |
| 12475 | 12246 | const ip = &zcu.intern_pool; |
| 12247 | ty.assertHasLayout(zcu); | |
| 12476 | 12248 | const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg); |
| 12477 | 12249 | if (classes[0] == .memory) { |
| 12478 | 12250 | it.zig_index += 1; |
| ... | ... | @@ -12544,9 +12316,7 @@ const ParamTypeIterator = struct { |
| 12544 | 12316 | } |
| 12545 | 12317 | switch (ip.indexToKey(ty.toIntern())) { |
| 12546 | 12318 | .struct_type => { |
| 12547 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 12548 | assert(struct_type.haveLayout(ip)); | |
| 12549 | const size: u64 = struct_type.sizeUnordered(ip); | |
| 12319 | const size = ty.abiSize(zcu); | |
| 12550 | 12320 | assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); |
| 12551 | 12321 | if (size % 8 > 0) { |
| 12552 | 12322 | types_buffer[types_index - 1] = |
| ... | ... | @@ -12720,14 +12490,14 @@ fn isByRef(ty: Type, zcu: *Zcu) bool { |
| 12720 | 12490 | }, |
| 12721 | 12491 | .error_union => { |
| 12722 | 12492 | const payload_ty = ty.errorUnionPayload(zcu); |
| 12723 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 12493 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 12724 | 12494 | return false; |
| 12725 | 12495 | } |
| 12726 | 12496 | return true; |
| 12727 | 12497 | }, |
| 12728 | 12498 | .optional => { |
| 12729 | 12499 | const payload_ty = ty.optionalChild(zcu); |
| 12730 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 12500 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 12731 | 12501 | return false; |
| 12732 | 12502 | } |
| 12733 | 12503 | if (ty.optionalReprIsPayload(zcu)) { |
src/codegen/mips/abi.zig+2-2| ... | ... | @@ -13,7 +13,7 @@ pub const Context = enum { ret, arg }; |
| 13 | 13 | |
| 14 | 14 | pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 15 | 15 | const target = zcu.getTarget(); |
| 16 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 16 | std.debug.assert(ty.hasRuntimeBits(zcu)); | |
| 17 | 17 | |
| 18 | 18 | const max_direct_size = target.ptrBitWidth() * 2; |
| 19 | 19 | switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -44,7 +44,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 44 | 44 | return .byval; |
| 45 | 45 | }, |
| 46 | 46 | .vector => { |
| 47 | const elem_type = ty.elemType2(zcu); | |
| 47 | const elem_type = ty.childType(zcu); | |
| 48 | 48 | switch (elem_type.zigTypeTag(zcu)) { |
| 49 | 49 | .bool, .int => { |
| 50 | 50 | const bit_size = ty.bitSize(zcu); |
src/codegen/riscv64/CodeGen.zig+45-58| ... | ... | @@ -2673,7 +2673,7 @@ fn genBinOp( |
| 2673 | 2673 | defer func.register_manager.unlockReg(tmp_lock); |
| 2674 | 2674 | |
| 2675 | 2675 | // RISC-V has no immediate mul, so we copy the size to a temporary register |
| 2676 | const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu); | |
| 2676 | const elem_size = lhs_ty.indexableElem(zcu).abiSize(zcu); | |
| 2677 | 2677 | const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size }); |
| 2678 | 2678 | |
| 2679 | 2679 | try func.genBinOp( |
| ... | ... | @@ -3257,7 +3257,7 @@ fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void { |
| 3257 | 3257 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3258 | 3258 | const result: MCValue = result: { |
| 3259 | 3259 | const pl_ty = func.typeOfIndex(inst); |
| 3260 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; | |
| 3260 | if (!pl_ty.hasRuntimeBits(zcu)) break :result .none; | |
| 3261 | 3261 | |
| 3262 | 3262 | const opt_mcv = try func.resolveInst(ty_op.operand); |
| 3263 | 3263 | if (func.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) { |
| ... | ... | @@ -3331,7 +3331,7 @@ fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void { |
| 3331 | 3331 | break :result .{ .immediate = 0 }; |
| 3332 | 3332 | } |
| 3333 | 3333 | |
| 3334 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3334 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 3335 | 3335 | break :result operand; |
| 3336 | 3336 | } |
| 3337 | 3337 | |
| ... | ... | @@ -3384,7 +3384,7 @@ fn genUnwrapErrUnionPayloadMir( |
| 3384 | 3384 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 3385 | 3385 | |
| 3386 | 3386 | const result: MCValue = result: { |
| 3387 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; | |
| 3387 | if (!payload_ty.hasRuntimeBits(zcu)) break :result .none; | |
| 3388 | 3388 | |
| 3389 | 3389 | const payload_off: u31 = @intCast(errUnionPayloadOffset(payload_ty, zcu)); |
| 3390 | 3390 | switch (err_union) { |
| ... | ... | @@ -3547,7 +3547,7 @@ fn airWrapErrUnionPayload(func: *Func, inst: Air.Inst.Index) !void { |
| 3547 | 3547 | const operand = try func.resolveInst(ty_op.operand); |
| 3548 | 3548 | |
| 3549 | 3549 | const result: MCValue = result: { |
| 3550 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 }; | |
| 3550 | if (!pl_ty.hasRuntimeBits(zcu)) break :result .{ .immediate = 0 }; | |
| 3551 | 3551 | |
| 3552 | 3552 | const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); |
| 3553 | 3553 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); |
| ... | ... | @@ -3571,7 +3571,7 @@ fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void { |
| 3571 | 3571 | const err_ty = eu_ty.errorUnionSet(zcu); |
| 3572 | 3572 | |
| 3573 | 3573 | const result: MCValue = result: { |
| 3574 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try func.resolveInst(ty_op.operand); | |
| 3574 | if (!pl_ty.hasRuntimeBits(zcu)) break :result try func.resolveInst(ty_op.operand); | |
| 3575 | 3575 | |
| 3576 | 3576 | const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); |
| 3577 | 3577 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); |
| ... | ... | @@ -3761,7 +3761,7 @@ fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void { |
| 3761 | 3761 | |
| 3762 | 3762 | const result: MCValue = result: { |
| 3763 | 3763 | const elem_ty = func.typeOfIndex(inst); |
| 3764 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; | |
| 3764 | assert(elem_ty.hasRuntimeBits(zcu)); | |
| 3765 | 3765 | |
| 3766 | 3766 | const slice_ty = func.typeOf(bin_op.lhs); |
| 3767 | 3767 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu); |
| ... | ... | @@ -3913,9 +3913,8 @@ fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void { |
| 3913 | 3913 | const base_ptr_ty = func.typeOf(bin_op.lhs); |
| 3914 | 3914 | |
| 3915 | 3915 | const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: { |
| 3916 | const elem_ty = base_ptr_ty.elemType2(zcu); | |
| 3917 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; | |
| 3918 | ||
| 3916 | const elem_ty = base_ptr_ty.indexableElem(zcu); | |
| 3917 | assert(elem_ty.hasRuntimeBits(zcu)); | |
| 3919 | 3918 | const base_ptr_mcv = try func.resolveInst(bin_op.lhs); |
| 3920 | 3919 | const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) { |
| 3921 | 3920 | .register => |reg| func.register_manager.lockRegAssumeUnused(reg), |
| ... | ... | @@ -4618,7 +4617,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { |
| 4618 | 4617 | const src_mcv = try func.resolveInst(operand); |
| 4619 | 4618 | const struct_ty = func.typeOf(operand); |
| 4620 | 4619 | const field_ty = struct_ty.fieldType(index, zcu); |
| 4621 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; | |
| 4620 | assert(field_ty.hasRuntimeBits(zcu)); | |
| 4622 | 4621 | |
| 4623 | 4622 | const field_off: u32 = switch (struct_ty.containerLayout(zcu)) { |
| 4624 | 4623 | .auto, .@"extern" => @intCast(struct_ty.structFieldOffset(index, zcu) * 8), |
| ... | ... | @@ -5127,7 +5126,6 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 5127 | 5126 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 5128 | 5127 | const pt = func.pt; |
| 5129 | 5128 | const zcu = pt.zcu; |
| 5130 | const ip = &zcu.intern_pool; | |
| 5131 | 5129 | |
| 5132 | 5130 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| 5133 | 5131 | const lhs_ty = func.typeOf(bin_op.lhs); |
| ... | ... | @@ -5141,28 +5139,23 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 5141 | 5139 | .optional, |
| 5142 | 5140 | .@"struct", |
| 5143 | 5141 | => { |
| 5144 | const int_ty = switch (lhs_ty.zigTypeTag(zcu)) { | |
| 5142 | const int_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { | |
| 5145 | 5143 | .@"enum" => lhs_ty.intTagType(zcu), |
| 5146 | 5144 | .int => lhs_ty, |
| 5147 | .bool => Type.u1, | |
| 5148 | .pointer => Type.u64, | |
| 5149 | .error_set => Type.anyerror, | |
| 5145 | .bool => .u1, | |
| 5146 | .pointer => .u64, | |
| 5147 | .error_set => .anyerror, | |
| 5150 | 5148 | .optional => blk: { |
| 5151 | 5149 | const payload_ty = lhs_ty.optionalChild(zcu); |
| 5152 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5153 | break :blk Type.u1; | |
| 5150 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 5151 | break :blk .u1; | |
| 5154 | 5152 | } else if (lhs_ty.isPtrLikeOptional(zcu)) { |
| 5155 | break :blk Type.u64; | |
| 5153 | break :blk .u64; | |
| 5156 | 5154 | } else { |
| 5157 | 5155 | return func.fail("TODO riscv cmp non-pointer optionals", .{}); |
| 5158 | 5156 | } |
| 5159 | 5157 | }, |
| 5160 | .@"struct" => blk: { | |
| 5161 | const struct_obj = ip.loadStructType(lhs_ty.toIntern()); | |
| 5162 | assert(struct_obj.layout == .@"packed"); | |
| 5163 | const backing_index = struct_obj.backingIntTypeUnordered(ip); | |
| 5164 | break :blk Type.fromInterned(backing_index); | |
| 5165 | }, | |
| 5158 | .@"struct", .@"union" => lhs_ty.bitpackBackingInt(zcu), | |
| 5166 | 5159 | else => unreachable, |
| 5167 | 5160 | }; |
| 5168 | 5161 | |
| ... | ... | @@ -5926,8 +5919,7 @@ fn airBr(func: *Func, inst: Air.Inst.Index) !void { |
| 5926 | 5919 | const br = func.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 5927 | 5920 | |
| 5928 | 5921 | const block_ty = func.typeOfIndex(br.block_inst); |
| 5929 | const block_unused = | |
| 5930 | !block_ty.hasRuntimeBitsIgnoreComptime(zcu) or func.liveness.isUnused(br.block_inst); | |
| 5922 | const block_unused = !block_ty.hasRuntimeBits(zcu) or func.liveness.isUnused(br.block_inst); | |
| 5931 | 5923 | const block_tracking = func.inst_tracking.getPtr(br.block_inst).?; |
| 5932 | 5924 | const block_data = func.blocks.getPtr(br.block_inst).?; |
| 5933 | 5925 | const first_br = block_data.relocs.items.len == 0; |
| ... | ... | @@ -6150,31 +6142,26 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 6150 | 6142 | |
| 6151 | 6143 | const zcu = func.pt.zcu; |
| 6152 | 6144 | const ip = &zcu.intern_pool; |
| 6153 | const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; | |
| 6154 | const struct_type: Type = .fromInterned(aggregate.ty); | |
| 6155 | switch (aggregate.storage) { | |
| 6156 | .elems => |elems| for (elems, 0..) |elem, i| { | |
| 6157 | switch (elem) { | |
| 6158 | .bool_true => { | |
| 6159 | const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 6160 | assert(clobber.len != 0); | |
| 6161 | if (std.mem.eql(u8, clobber, "memory")) { | |
| 6162 | // nothing really to do | |
| 6163 | } else { | |
| 6164 | try func.register_manager.getReg(parseRegName(clobber) orelse | |
| 6165 | return func.fail("invalid clobber: '{s}'", .{clobber}), null); | |
| 6166 | } | |
| 6167 | }, | |
| 6168 | .bool_false => continue, | |
| 6169 | else => unreachable, | |
| 6170 | } | |
| 6171 | }, | |
| 6172 | .repeated_elem => |elem| switch (elem) { | |
| 6173 | .bool_true => @panic("TODO"), | |
| 6174 | .bool_false => {}, | |
| 6175 | else => unreachable, | |
| 6176 | }, | |
| 6177 | .bytes => @panic("TODO"), | |
| 6145 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 6146 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 6147 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 6148 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 6149 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 6150 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 6151 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 6152 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 6153 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 6154 | 0 => continue, // field is false | |
| 6155 | 1 => {}, // field is true | |
| 6156 | } | |
| 6157 | const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 6158 | assert(clobber.len != 0); | |
| 6159 | if (std.mem.eql(u8, clobber, "memory")) { | |
| 6160 | // nothing really to do | |
| 6161 | } else { | |
| 6162 | try func.register_manager.getReg(parseRegName(clobber) orelse | |
| 6163 | return func.fail("invalid clobber: '{s}'", .{clobber}), null); | |
| 6164 | } | |
| 6178 | 6165 | } |
| 6179 | 6166 | |
| 6180 | 6167 | const Label = struct { |
| ... | ... | @@ -8255,7 +8242,7 @@ fn resolveCallingConventionValues( |
| 8255 | 8242 | // Return values |
| 8256 | 8243 | if (ret_ty.zigTypeTag(zcu) == .noreturn) { |
| 8257 | 8244 | result.return_value = InstTracking.init(.unreach); |
| 8258 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 8245 | } else if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 8259 | 8246 | result.return_value = InstTracking.init(.none); |
| 8260 | 8247 | } else { |
| 8261 | 8248 | var ret_tracking: [2]InstTracking = undefined; |
| ... | ... | @@ -8306,7 +8293,7 @@ fn resolveCallingConventionValues( |
| 8306 | 8293 | var param_float_reg_i: usize = 0; |
| 8307 | 8294 | |
| 8308 | 8295 | for (param_types, result.args) |ty, *arg| { |
| 8309 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 8296 | if (!ty.hasRuntimeBits(zcu)) { | |
| 8310 | 8297 | assert(cc == .auto); |
| 8311 | 8298 | arg.* = .none; |
| 8312 | 8299 | continue; |
| ... | ... | @@ -8421,10 +8408,10 @@ fn hasFeature(func: *Func, feature: Target.riscv.Feature) bool { |
| 8421 | 8408 | } |
| 8422 | 8409 | |
| 8423 | 8410 | pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { |
| 8424 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; | |
| 8411 | if (!payload_ty.hasRuntimeBits(zcu)) return 0; | |
| 8425 | 8412 | const payload_align = payload_ty.abiAlignment(zcu); |
| 8426 | 8413 | const error_align = Type.anyerror.abiAlignment(zcu); |
| 8427 | if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 8414 | if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBits(zcu)) { | |
| 8428 | 8415 | return 0; |
| 8429 | 8416 | } else { |
| 8430 | 8417 | return payload_align.forward(Type.anyerror.abiSize(zcu)); |
| ... | ... | @@ -8432,10 +8419,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { |
| 8432 | 8419 | } |
| 8433 | 8420 | |
| 8434 | 8421 | pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 { |
| 8435 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; | |
| 8422 | if (!payload_ty.hasRuntimeBits(zcu)) return 0; | |
| 8436 | 8423 | const payload_align = payload_ty.abiAlignment(zcu); |
| 8437 | 8424 | const error_align = Type.anyerror.abiAlignment(zcu); |
| 8438 | if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 8425 | if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBits(zcu)) { | |
| 8439 | 8426 | return error_align.forward(payload_ty.abiSize(zcu)); |
| 8440 | 8427 | } else { |
| 8441 | 8428 | return 0; |
src/codegen/riscv64/abi.zig+2-2| ... | ... | @@ -11,7 +11,7 @@ pub const Class = enum { memory, byval, integer, double_integer, fields }; |
| 11 | 11 | |
| 12 | 12 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 13 | 13 | const target = zcu.getTarget(); |
| 14 | std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 14 | std.debug.assert(ty.hasRuntimeBits(zcu)); | |
| 15 | 15 | |
| 16 | 16 | const max_byval_size = target.ptrBitWidth() * 2; |
| 17 | 17 | switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -27,7 +27,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 27 | 27 | var field_count: usize = 0; |
| 28 | 28 | for (0..ty.structFieldCount(zcu)) |field_index| { |
| 29 | 29 | const field_ty = ty.fieldType(field_index, zcu); |
| 30 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 30 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 31 | 31 | if (field_ty.isRuntimeFloat()) |
| 32 | 32 | any_fp = true |
| 33 | 33 | else if (!field_ty.isAbiInt(zcu)) |
src/codegen/sparc64/CodeGen.zig+11-11| ... | ... | @@ -1102,7 +1102,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 1102 | 1102 | fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void { |
| 1103 | 1103 | try self.blocks.putNoClobber(self.gpa, inst, .{ |
| 1104 | 1104 | // A block is a setup to be able to jump to the end. |
| 1105 | .relocs = .{}, | |
| 1105 | .relocs = .empty, | |
| 1106 | 1106 | // It also acts as a receptacle for break operands. |
| 1107 | 1107 | // Here we use `MCValue.none` to represent a null value so that the first |
| 1108 | 1108 | // break instruction will choose a MCValue for the block result and overwrite |
| ... | ... | @@ -1376,19 +1376,19 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1376 | 1376 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1377 | 1377 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 1378 | 1378 | |
| 1379 | const int_ty = switch (lhs_ty.zigTypeTag(zcu)) { | |
| 1379 | const int_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { | |
| 1380 | 1380 | .vector => unreachable, // Handled by cmp_vector. |
| 1381 | 1381 | .@"enum" => lhs_ty.intTagType(zcu), |
| 1382 | 1382 | .int => lhs_ty, |
| 1383 | .bool => Type.u1, | |
| 1384 | .pointer => Type.usize, | |
| 1385 | .error_set => Type.u16, | |
| 1383 | .bool => .u1, | |
| 1384 | .pointer => .usize, | |
| 1385 | .error_set => .u16, | |
| 1386 | 1386 | .optional => blk: { |
| 1387 | 1387 | const payload_ty = lhs_ty.optionalChild(zcu); |
| 1388 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1389 | break :blk Type.u1; | |
| 1388 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 1389 | break :blk .u1; | |
| 1390 | 1390 | } else if (lhs_ty.isPtrLikeOptional(zcu)) { |
| 1391 | break :blk Type.usize; | |
| 1391 | break :blk .usize; | |
| 1392 | 1392 | } else { |
| 1393 | 1393 | return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{}); |
| 1394 | 1394 | } |
| ... | ... | @@ -3452,8 +3452,8 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) |
| 3452 | 3452 | if (err_ty.errorSetIsEmpty(zcu)) { |
| 3453 | 3453 | return error_union_mcv; |
| 3454 | 3454 | } |
| 3455 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3456 | return MCValue.none; | |
| 3455 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 3456 | return .none; | |
| 3457 | 3457 | } |
| 3458 | 3458 | |
| 3459 | 3459 | const payload_offset: u32 = @intCast(errUnionPayloadOffset(payload_ty, zcu)); |
| ... | ... | @@ -4481,7 +4481,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 4481 | 4481 | const ty = self.typeOf(ref); |
| 4482 | 4482 | |
| 4483 | 4483 | // If the type has no codegen bits, no need to store it. |
| 4484 | if (!ty.hasRuntimeBitsIgnoreComptime(pt.zcu)) return .none; | |
| 4484 | if (!ty.hasRuntimeBits(pt.zcu)) return .none; | |
| 4485 | 4485 | |
| 4486 | 4486 | if (ref.toIndex()) |inst| { |
| 4487 | 4487 | return self.getResolvedInstValue(inst); |
src/codegen/spirv/CodeGen.zig+84-122| ... | ... | @@ -208,7 +208,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 208 | 208 | try cg.args.ensureUnusedCapacity(gpa, fn_info.param_types.len); |
| 209 | 209 | for (fn_info.param_types.get(ip)) |param_ty_index| { |
| 210 | 210 | const param_ty: Type = .fromInterned(param_ty_index); |
| 211 | if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 211 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 212 | 212 | |
| 213 | 213 | const param_type_id = try cg.resolveType(param_ty, .direct); |
| 214 | 214 | const arg_result_id = cg.module.allocId(); |
| ... | ... | @@ -689,7 +689,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { |
| 689 | 689 | .comptime_int => if (value < 0) .signed else .unsigned, |
| 690 | 690 | else => unreachable, |
| 691 | 691 | }; |
| 692 | if (@sizeOf(@TypeOf(value)) >= 4 and big_int) { | |
| 692 | if (@TypeOf(value) != comptime_int and @sizeOf(@TypeOf(value)) >= 4 and big_int) { | |
| 693 | 693 | const value64: u64 = switch (signedness) { |
| 694 | 694 | .signed => @bitCast(@as(i64, @intCast(value))), |
| 695 | 695 | .unsigned => @as(u64, @intCast(value)), |
| ... | ... | @@ -814,14 +814,11 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 814 | 814 | .@"extern", |
| 815 | 815 | .func, |
| 816 | 816 | .enum_literal, |
| 817 | .empty_enum_value, | |
| 818 | 817 | => unreachable, // non-runtime values |
| 819 | 818 | |
| 820 | 819 | .simple_value => |simple_value| switch (simple_value) { |
| 821 | .undefined, | |
| 822 | 820 | .void, |
| 823 | 821 | .null, |
| 824 | .empty_tuple, | |
| 825 | 822 | .@"unreachable", |
| 826 | 823 | => unreachable, // non-runtime values |
| 827 | 824 | |
| ... | ... | @@ -887,7 +884,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 887 | 884 | return try cg.constructComposite(comp_ty_id, &constituents); |
| 888 | 885 | }, |
| 889 | 886 | .enum_tag => { |
| 890 | const int_val = try val.intFromEnum(ty, pt); | |
| 887 | const int_val = val.intFromEnum(zcu); | |
| 891 | 888 | const int_ty = ty.intTagType(zcu); |
| 892 | 889 | break :cache try cg.constant(int_ty, int_val, repr); |
| 893 | 890 | }, |
| ... | ... | @@ -962,18 +959,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 962 | 959 | }, |
| 963 | 960 | .struct_type => { |
| 964 | 961 | const struct_type = zcu.typeToStruct(ty).?; |
| 965 | ||
| 966 | if (struct_type.layout == .@"packed") { | |
| 967 | // TODO: composite int | |
| 968 | // TODO: endianness | |
| 969 | const bits: u16 = @intCast(ty.bitSize(zcu)); | |
| 970 | const bytes = std.mem.alignForward(u16, cg.module.backingIntBits(bits).@"0", 8) / 8; | |
| 971 | var limbs: [8]u8 = undefined; | |
| 972 | @memset(&limbs, 0); | |
| 973 | val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable; | |
| 974 | const backing_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); | |
| 975 | return try cg.constInt(backing_ty, @as(u64, @bitCast(limbs))); | |
| 976 | } | |
| 962 | assert(struct_type.layout != .@"packed"); // packed structs use `bitpack` | |
| 977 | 963 | |
| 978 | 964 | var types = std.array_list.Managed(Type).init(gpa); |
| 979 | 965 | defer types.deinit(); |
| ... | ... | @@ -984,7 +970,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 984 | 970 | var it = struct_type.iterateRuntimeOrder(ip); |
| 985 | 971 | while (it.next()) |field_index| { |
| 986 | 972 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 987 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 973 | if (!field_ty.hasRuntimeBits(zcu)) { | |
| 988 | 974 | // This is a zero-bit field - we only needed it for the alignment. |
| 989 | 975 | continue; |
| 990 | 976 | } |
| ... | ... | @@ -1004,20 +990,24 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 1004 | 990 | else => unreachable, |
| 1005 | 991 | }, |
| 1006 | 992 | .un => |un| { |
| 993 | assert(ty.containerLayout(zcu) != .@"packed"); // packed unions use `bitpack` | |
| 1007 | 994 | if (un.tag == .none) { |
| 1008 | assert(ty.containerLayout(zcu) == .@"packed"); // TODO | |
| 1009 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); | |
| 1010 | return try cg.constInt(int_ty, Value.toUnsignedInt(.fromInterned(un.val), zcu)); | |
| 995 | @panic("TODO"); | |
| 1011 | 996 | } |
| 1012 | 997 | const active_field = ty.unionTagFieldIndex(.fromInterned(un.tag), zcu).?; |
| 1013 | 998 | const union_obj = zcu.typeToUnion(ty).?; |
| 1014 | 999 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[active_field]); |
| 1015 | const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 1000 | const payload = if (field_ty.hasRuntimeBits(zcu)) | |
| 1016 | 1001 | try cg.constant(field_ty, .fromInterned(un.val), .direct) |
| 1017 | 1002 | else |
| 1018 | 1003 | null; |
| 1019 | 1004 | return try cg.unionInit(ty, active_field, payload); |
| 1020 | 1005 | }, |
| 1006 | .bitpack => |bitpack| { | |
| 1007 | const int_val: Value = .fromInterned(bitpack.backing_int_val); | |
| 1008 | break :cache try cg.constant(int_val.typeOf(zcu), int_val, repr); | |
| 1009 | }, | |
| 1010 | ||
| 1021 | 1011 | .memoized_call => unreachable, |
| 1022 | 1012 | } |
| 1023 | 1013 | }; |
| ... | ... | @@ -1041,7 +1031,7 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { |
| 1041 | 1031 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 1042 | 1032 | defer arena.deinit(); |
| 1043 | 1033 | |
| 1044 | const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt); | |
| 1034 | const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt, null); | |
| 1045 | 1035 | return cg.derivePtr(derivation); |
| 1046 | 1036 | } |
| 1047 | 1037 | |
| ... | ... | @@ -1150,7 +1140,7 @@ fn constantUavRef( |
| 1150 | 1140 | } |
| 1151 | 1141 | |
| 1152 | 1142 | // const is_fn_body = decl_ty.zigTypeTag(zcu) == .@"fn"; |
| 1153 | if (!uav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1143 | if (!uav_ty.hasRuntimeBits(zcu)) { | |
| 1154 | 1144 | // Pointer to nothing - return undefined |
| 1155 | 1145 | return cg.module.constUndef(ty_id); |
| 1156 | 1146 | } |
| ... | ... | @@ -1196,7 +1186,7 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { |
| 1196 | 1186 | }, |
| 1197 | 1187 | } |
| 1198 | 1188 | |
| 1199 | if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1189 | if (!nav_ty.hasRuntimeBits(zcu)) { | |
| 1200 | 1190 | // Pointer to nothing - return undefined. |
| 1201 | 1191 | return cg.module.constUndef(ty_id); |
| 1202 | 1192 | } |
| ... | ... | @@ -1258,17 +1248,16 @@ fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 { |
| 1258 | 1248 | fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { |
| 1259 | 1249 | const gpa = cg.module.gpa; |
| 1260 | 1250 | const zcu = cg.module.zcu; |
| 1261 | const ip = &zcu.intern_pool; | |
| 1262 | 1251 | const union_obj = zcu.typeToUnion(ty).?; |
| 1263 | 1252 | |
| 1264 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | |
| 1253 | if (union_obj.layout == .@"packed") { | |
| 1265 | 1254 | return try cg.module.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| 1266 | 1255 | } |
| 1267 | 1256 | |
| 1268 | 1257 | const layout = cg.unionLayout(ty); |
| 1269 | 1258 | if (!layout.has_payload) { |
| 1270 | 1259 | // No payload, so represent this as just the tag type. |
| 1271 | return try cg.resolveType(.fromInterned(union_obj.enum_tag_ty), .indirect); | |
| 1260 | return try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect); | |
| 1272 | 1261 | } |
| 1273 | 1262 | |
| 1274 | 1263 | var member_types: [4]Id = undefined; |
| ... | ... | @@ -1277,7 +1266,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { |
| 1277 | 1266 | const u8_ty_id = try cg.resolveType(.u8, .direct); |
| 1278 | 1267 | |
| 1279 | 1268 | if (layout.tag_size != 0) { |
| 1280 | const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_ty), .indirect); | |
| 1269 | const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect); | |
| 1281 | 1270 | member_types[layout.tag_index] = tag_ty_id; |
| 1282 | 1271 | member_names[layout.tag_index] = "(tag)"; |
| 1283 | 1272 | } |
| ... | ... | @@ -1318,7 +1307,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { |
| 1318 | 1307 | |
| 1319 | 1308 | fn resolveFnReturnType(cg: *CodeGen, ret_ty: Type) !Id { |
| 1320 | 1309 | const zcu = cg.module.zcu; |
| 1321 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1310 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 1322 | 1311 | // If the return type is an error set or an error union, then we make this |
| 1323 | 1312 | // anyerror return type instead, so that it can be coerced into a function |
| 1324 | 1313 | // pointer type which has anyerror as the return type. |
| ... | ... | @@ -1392,7 +1381,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1392 | 1381 | return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)}); |
| 1393 | 1382 | }; |
| 1394 | 1383 | |
| 1395 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1384 | if (!elem_ty.hasRuntimeBits(zcu)) { | |
| 1396 | 1385 | assert(repr == .indirect); |
| 1397 | 1386 | if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); |
| 1398 | 1387 | return try cg.module.opaqueType("zero-sized-array"); |
| ... | ... | @@ -1456,7 +1445,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1456 | 1445 | var param_index: usize = 0; |
| 1457 | 1446 | for (fn_info.param_types.get(ip)) |param_ty_index| { |
| 1458 | 1447 | const param_ty: Type = .fromInterned(param_ty_index); |
| 1459 | if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1448 | if (!param_ty.hasRuntimeBits(zcu)) continue; | |
| 1460 | 1449 | |
| 1461 | 1450 | param_ty_ids[param_index] = try cg.resolveType(param_ty, .direct); |
| 1462 | 1451 | param_index += 1; |
| ... | ... | @@ -1521,7 +1510,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1521 | 1510 | }; |
| 1522 | 1511 | |
| 1523 | 1512 | if (struct_type.layout == .@"packed") { |
| 1524 | return try cg.resolveType(.fromInterned(struct_type.backingIntTypeUnordered(ip)), .direct); | |
| 1513 | return try cg.resolveType(.fromInterned(struct_type.packed_backing_int_type), .direct); | |
| 1525 | 1514 | } |
| 1526 | 1515 | |
| 1527 | 1516 | var member_types = std.array_list.Managed(Id).init(gpa); |
| ... | ... | @@ -1536,9 +1525,9 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1536 | 1525 | var it = struct_type.iterateRuntimeOrder(ip); |
| 1537 | 1526 | while (it.next()) |field_index| { |
| 1538 | 1527 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 1539 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1528 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 1540 | 1529 | |
| 1541 | const field_name = struct_type.fieldName(ip, field_index); | |
| 1530 | const field_name = struct_type.field_names.get(ip)[field_index]; | |
| 1542 | 1531 | try member_types.append(try cg.resolveType(field_ty, .indirect)); |
| 1543 | 1532 | try member_names.append(field_name.toSlice(ip)); |
| 1544 | 1533 | try member_offsets.append(@intCast(ty.structFieldOffset(field_index, zcu))); |
| ... | ... | @@ -1559,7 +1548,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 1559 | 1548 | }, |
| 1560 | 1549 | .optional => { |
| 1561 | 1550 | const payload_ty = ty.optionalChild(zcu); |
| 1562 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1551 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 1563 | 1552 | // Just use a bool. |
| 1564 | 1553 | // Note: Always generate the bool with indirect format, to save on some sanity |
| 1565 | 1554 | // Perform the conversion to a direct bool when the field is extracted. |
| ... | ... | @@ -1656,7 +1645,7 @@ fn errorUnionLayout(cg: *CodeGen, payload_ty: Type) ErrorUnionLayout { |
| 1656 | 1645 | |
| 1657 | 1646 | const error_first = error_align.compare(.gt, payload_align); |
| 1658 | 1647 | return .{ |
| 1659 | .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu), | |
| 1648 | .payload_has_bits = payload_ty.hasRuntimeBits(zcu), | |
| 1660 | 1649 | .error_first = error_first, |
| 1661 | 1650 | }; |
| 1662 | 1651 | } |
| ... | ... | @@ -3727,7 +3716,6 @@ fn cmp( |
| 3727 | 3716 | const gpa = cg.module.gpa; |
| 3728 | 3717 | const pt = cg.pt; |
| 3729 | 3718 | const zcu = cg.module.zcu; |
| 3730 | const ip = &zcu.intern_pool; | |
| 3731 | 3719 | const scalar_ty = lhs.ty.scalarType(zcu); |
| 3732 | 3720 | const is_vector = lhs.ty.isVector(zcu); |
| 3733 | 3721 | |
| ... | ... | @@ -3740,7 +3728,7 @@ fn cmp( |
| 3740 | 3728 | }, |
| 3741 | 3729 | .@"struct" => { |
| 3742 | 3730 | const struct_ty = zcu.typeToPackedStruct(scalar_ty).?; |
| 3743 | const ty: Type = .fromInterned(struct_ty.backingIntTypeUnordered(ip)); | |
| 3731 | const ty: Type = .fromInterned(struct_ty.packed_backing_int_type); | |
| 3744 | 3732 | return try cg.cmp(op, lhs.pun(ty), rhs.pun(ty)); |
| 3745 | 3733 | }, |
| 3746 | 3734 | .error_set => { |
| ... | ... | @@ -3781,7 +3769,7 @@ fn cmp( |
| 3781 | 3769 | |
| 3782 | 3770 | const payload_ty = ty.optionalChild(zcu); |
| 3783 | 3771 | if (ty.optionalReprIsPayload(zcu)) { |
| 3784 | assert(payload_ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 3772 | assert(payload_ty.hasRuntimeBits(zcu)); | |
| 3785 | 3773 | assert(!payload_ty.isSlice(zcu)); |
| 3786 | 3774 | |
| 3787 | 3775 | return try cg.cmp(op, lhs.pun(payload_ty), rhs.pun(payload_ty)); |
| ... | ... | @@ -3790,12 +3778,12 @@ fn cmp( |
| 3790 | 3778 | const lhs_id = try lhs.materialize(cg); |
| 3791 | 3779 | const rhs_id = try rhs.materialize(cg); |
| 3792 | 3780 | |
| 3793 | const lhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 3781 | const lhs_valid_id = if (payload_ty.hasRuntimeBits(zcu)) | |
| 3794 | 3782 | try cg.extractField(.bool, lhs_id, 1) |
| 3795 | 3783 | else |
| 3796 | 3784 | try cg.convertToDirect(.bool, lhs_id); |
| 3797 | 3785 | |
| 3798 | const rhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 3786 | const rhs_valid_id = if (payload_ty.hasRuntimeBits(zcu)) | |
| 3799 | 3787 | try cg.extractField(.bool, rhs_id, 1) |
| 3800 | 3788 | else |
| 3801 | 3789 | try cg.convertToDirect(.bool, rhs_id); |
| ... | ... | @@ -3803,7 +3791,7 @@ fn cmp( |
| 3803 | 3791 | const lhs_valid: Temporary = .init(.bool, lhs_valid_id); |
| 3804 | 3792 | const rhs_valid: Temporary = .init(.bool, rhs_valid_id); |
| 3805 | 3793 | |
| 3806 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3794 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 3807 | 3795 | return try cg.cmp(op, lhs_valid, rhs_valid); |
| 3808 | 3796 | } |
| 3809 | 3797 | |
| ... | ... | @@ -4141,7 +4129,7 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4141 | 4129 | const array_ptr_id = try cg.resolve(ty_op.operand); |
| 4142 | 4130 | const len_id = try cg.constInt(.usize, array_ty.arrayLen(zcu)); |
| 4143 | 4131 | |
| 4144 | const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 4132 | const elem_ptr_id = if (!array_ty.hasRuntimeBits(zcu)) | |
| 4145 | 4133 | // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. |
| 4146 | 4134 | try cg.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id) |
| 4147 | 4135 | else |
| ... | ... | @@ -4177,12 +4165,12 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4177 | 4165 | .@"struct" => { |
| 4178 | 4166 | if (zcu.typeToPackedStruct(result_ty)) |struct_type| { |
| 4179 | 4167 | comptime assert(Type.packed_struct_layout_version == 2); |
| 4180 | const backing_int_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); | |
| 4168 | const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type); | |
| 4181 | 4169 | var running_int_id = try cg.constInt(backing_int_ty, 0); |
| 4182 | 4170 | var running_bits: u16 = 0; |
| 4183 | 4171 | for (struct_type.field_types.get(ip), elements) |field_ty_ip, element| { |
| 4184 | 4172 | const field_ty: Type = .fromInterned(field_ty_ip); |
| 4185 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 4173 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 4186 | 4174 | const field_id = try cg.resolve(element); |
| 4187 | 4175 | const ty_bit_size: u16 = @intCast(field_ty.bitSize(zcu)); |
| 4188 | 4176 | const field_int_ty = try cg.pt.intType(.unsigned, ty_bit_size); |
| ... | ... | @@ -4242,7 +4230,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4242 | 4230 | const field_index = it.next().?; |
| 4243 | 4231 | if ((try result_ty.structFieldValueComptime(pt, i)) != null) continue; |
| 4244 | 4232 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 4245 | assert(field_ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 4233 | assert(field_ty.hasRuntimeBits(zcu)); | |
| 4246 | 4234 | |
| 4247 | 4235 | const id = try cg.resolve(element); |
| 4248 | 4236 | types[index] = field_ty; |
| ... | ... | @@ -4381,7 +4369,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4381 | 4369 | fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { |
| 4382 | 4370 | const zcu = cg.module.zcu; |
| 4383 | 4371 | // Construct new pointer type for the resulting pointer |
| 4384 | const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. | |
| 4372 | const elem_ty = ptr_ty.indexableElem(zcu); | |
| 4385 | 4373 | const elem_ty_id = try cg.resolveType(elem_ty, .indirect); |
| 4386 | 4374 | const elem_ptr_ty_id = try cg.module.ptrType(elem_ty_id, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu))); |
| 4387 | 4375 | if (ptr_ty.isSinglePointer(zcu)) { |
| ... | ... | @@ -4402,10 +4390,7 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4402 | 4390 | const elem_ty = src_ptr_ty.childType(zcu); |
| 4403 | 4391 | const ptr_id = try cg.resolve(bin_op.lhs); |
| 4404 | 4392 | |
| 4405 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4406 | const dst_ptr_ty = cg.typeOfIndex(inst); | |
| 4407 | return try cg.bitCast(dst_ptr_ty, src_ptr_ty, ptr_id); | |
| 4408 | } | |
| 4393 | assert(elem_ty.hasRuntimeBits(zcu)); | |
| 4409 | 4394 | |
| 4410 | 4395 | const index_id = try cg.resolve(bin_op.rhs); |
| 4411 | 4396 | return try cg.ptrElemPtr(src_ptr_ty, ptr_id, index_id); |
| ... | ... | @@ -4483,7 +4468,7 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 4483 | 4468 | |
| 4484 | 4469 | if (layout.tag_size == 0) return; |
| 4485 | 4470 | |
| 4486 | const tag_ty = un_ty.unionTagTypeSafety(zcu).?; | |
| 4471 | const tag_ty = un_ty.unionTagTypeRuntime(zcu).?; | |
| 4487 | 4472 | const tag_ty_id = try cg.resolveType(tag_ty, .indirect); |
| 4488 | 4473 | const tag_ptr_ty_id = try cg.module.ptrType(tag_ty_id, cg.module.storageClass(un_ptr_ty.ptrAddressSpace(zcu))); |
| 4489 | 4474 | |
| ... | ... | @@ -4509,7 +4494,7 @@ fn airGetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4509 | 4494 | const union_handle = try cg.resolve(ty_op.operand); |
| 4510 | 4495 | if (!layout.has_payload) return union_handle; |
| 4511 | 4496 | |
| 4512 | const tag_ty = un_ty.unionTagTypeSafety(zcu).?; | |
| 4497 | const tag_ty = un_ty.unionTagTypeRuntime(zcu).?; | |
| 4513 | 4498 | return try cg.extractField(tag_ty, union_handle, layout.tag_index); |
| 4514 | 4499 | } |
| 4515 | 4500 | |
| ... | ... | @@ -4529,39 +4514,16 @@ fn unionInit( |
| 4529 | 4514 | const zcu = cg.module.zcu; |
| 4530 | 4515 | const ip = &zcu.intern_pool; |
| 4531 | 4516 | const union_ty = zcu.typeToUnion(ty).?; |
| 4532 | const tag_ty: Type = .fromInterned(union_ty.enum_tag_ty); | |
| 4517 | const tag_ty: Type = .fromInterned(union_ty.enum_tag_type); | |
| 4533 | 4518 | |
| 4534 | 4519 | const layout = cg.unionLayout(ty); |
| 4535 | 4520 | const payload_ty: Type = .fromInterned(union_ty.field_types.get(ip)[active_field]); |
| 4536 | 4521 | |
| 4537 | if (union_ty.flagsUnordered(ip).layout == .@"packed") { | |
| 4538 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4539 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); | |
| 4540 | return cg.constInt(int_ty, 0); | |
| 4541 | } | |
| 4542 | ||
| 4543 | assert(payload != null); | |
| 4544 | if (payload_ty.isInt(zcu)) { | |
| 4545 | if (ty.bitSize(zcu) == payload_ty.bitSize(zcu)) { | |
| 4546 | return cg.bitCast(ty, payload_ty, payload.?); | |
| 4547 | } | |
| 4548 | ||
| 4549 | const trunc = try cg.buildConvert(ty, .{ .ty = payload_ty, .value = .{ .singleton = payload.? } }); | |
| 4550 | return try trunc.materialize(cg); | |
| 4551 | } | |
| 4552 | ||
| 4553 | const payload_int_ty = try pt.intType(.unsigned, @intCast(payload_ty.bitSize(zcu))); | |
| 4554 | const payload_int = if (payload_ty.ip_index == .bool_type) | |
| 4555 | try cg.convertToIndirect(payload_ty, payload.?) | |
| 4556 | else | |
| 4557 | try cg.bitCast(payload_int_ty, payload_ty, payload.?); | |
| 4558 | const trunc = try cg.buildConvert(ty, .{ .ty = payload_int_ty, .value = .{ .singleton = payload_int } }); | |
| 4559 | return try trunc.materialize(cg); | |
| 4560 | } | |
| 4522 | assert(union_ty.layout != .@"packed"); | |
| 4561 | 4523 | |
| 4562 | 4524 | const tag_int = if (layout.tag_size != 0) blk: { |
| 4563 | 4525 | const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); |
| 4564 | const tag_int_val = try tag_val.intFromEnum(tag_ty, pt); | |
| 4526 | const tag_int_val = tag_val.intFromEnum(zcu); | |
| 4565 | 4527 | break :blk tag_int_val.toUnsignedInt(zcu); |
| 4566 | 4528 | } else 0; |
| 4567 | 4529 | |
| ... | ... | @@ -4580,7 +4542,7 @@ fn unionInit( |
| 4580 | 4542 | try cg.store(tag_ty, ptr_id, tag_id, .{}); |
| 4581 | 4543 | } |
| 4582 | 4544 | |
| 4583 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4545 | if (payload_ty.hasRuntimeBits(zcu)) { | |
| 4584 | 4546 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); |
| 4585 | 4547 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function); |
| 4586 | 4548 | const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| ... | ... | @@ -4616,7 +4578,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4616 | 4578 | |
| 4617 | 4579 | const union_obj = zcu.typeToUnion(ty).?; |
| 4618 | 4580 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[extra.field_index]); |
| 4619 | const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 4581 | const payload = if (field_ty.hasRuntimeBits(zcu)) | |
| 4620 | 4582 | try cg.resolve(extra.init) |
| 4621 | 4583 | else |
| 4622 | 4584 | null; |
| ... | ... | @@ -4634,7 +4596,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4634 | 4596 | const field_index = struct_field.field_index; |
| 4635 | 4597 | const field_ty = object_ty.fieldType(field_index, zcu); |
| 4636 | 4598 | |
| 4637 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; | |
| 4599 | assert(field_ty.hasRuntimeBits(zcu)); | |
| 4638 | 4600 | |
| 4639 | 4601 | switch (object_ty.zigTypeTag(zcu)) { |
| 4640 | 4602 | .@"struct" => switch (object_ty.containerLayout(zcu)) { |
| ... | ... | @@ -4776,33 +4738,36 @@ fn structFieldPtr( |
| 4776 | 4738 | }, |
| 4777 | 4739 | .@"struct" => switch (object_ty.containerLayout(zcu)) { |
| 4778 | 4740 | .@"packed" => return cg.todo("implement field access for packed structs", .{}), |
| 4779 | else => { | |
| 4741 | .auto, .@"extern" => { | |
| 4780 | 4742 | return try cg.accessChain(result_ty_id, object_ptr, &.{field_index}); |
| 4781 | 4743 | }, |
| 4782 | 4744 | }, |
| 4783 | .@"union" => { | |
| 4784 | const layout = cg.unionLayout(object_ty); | |
| 4785 | if (!layout.has_payload) { | |
| 4786 | // Asked to get a pointer to a zero-sized field. Just lower this | |
| 4787 | // to undefined, there is no reason to make it be a valid pointer. | |
| 4788 | return try cg.module.constUndef(result_ty_id); | |
| 4789 | } | |
| 4745 | .@"union" => switch (object_ty.containerLayout(zcu)) { | |
| 4746 | .@"packed" => return cg.todo("implement field access for packed unions", .{}), | |
| 4747 | .auto, .@"extern" => { | |
| 4748 | const layout = cg.unionLayout(object_ty); | |
| 4749 | if (!layout.has_payload) { | |
| 4750 | // Asked to get a pointer to a zero-sized field. Just lower this | |
| 4751 | // to undefined, there is no reason to make it be a valid pointer. | |
| 4752 | return try cg.module.constUndef(result_ty_id); | |
| 4753 | } | |
| 4790 | 4754 | |
| 4791 | const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); | |
| 4792 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); | |
| 4793 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); | |
| 4794 | const pl_ptr_id = blk: { | |
| 4795 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; | |
| 4796 | break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | |
| 4797 | }; | |
| 4755 | const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); | |
| 4756 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); | |
| 4757 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); | |
| 4758 | const pl_ptr_id = blk: { | |
| 4759 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; | |
| 4760 | break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | |
| 4761 | }; | |
| 4798 | 4762 | |
| 4799 | const active_pl_ptr_id = cg.module.allocId(); | |
| 4800 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ | |
| 4801 | .id_result_type = result_ty_id, | |
| 4802 | .id_result = active_pl_ptr_id, | |
| 4803 | .operand = pl_ptr_id, | |
| 4804 | }); | |
| 4805 | return active_pl_ptr_id; | |
| 4763 | const active_pl_ptr_id = cg.module.allocId(); | |
| 4764 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ | |
| 4765 | .id_result_type = result_ty_id, | |
| 4766 | .id_result = active_pl_ptr_id, | |
| 4767 | .operand = pl_ptr_id, | |
| 4768 | }); | |
| 4769 | return active_pl_ptr_id; | |
| 4770 | }, | |
| 4806 | 4771 | }, |
| 4807 | 4772 | else => unreachable, |
| 4808 | 4773 | } |
| ... | ... | @@ -5028,7 +4993,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 5028 | 4993 | const gpa = cg.module.gpa; |
| 5029 | 4994 | const zcu = cg.module.zcu; |
| 5030 | 4995 | const ty = cg.typeOfIndex(inst); |
| 5031 | const have_block_result = ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu); | |
| 4996 | const have_block_result = ty.hasRuntimeBits(zcu); | |
| 5032 | 4997 | |
| 5033 | 4998 | const cf = switch (cg.control_flow) { |
| 5034 | 4999 | .structured => |*cf| cf, |
| ... | ... | @@ -5166,7 +5131,7 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5166 | 5131 | |
| 5167 | 5132 | switch (cg.control_flow) { |
| 5168 | 5133 | .structured => |*cf| { |
| 5169 | if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5134 | if (operand_ty.hasRuntimeBits(zcu)) { | |
| 5170 | 5135 | const operand_id = try cg.resolve(br.operand); |
| 5171 | 5136 | const block_result_var_id = cf.block_results.get(br.block_inst).?; |
| 5172 | 5137 | try cg.store(operand_ty, block_result_var_id, operand_id, .{}); |
| ... | ... | @@ -5177,7 +5142,7 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5177 | 5142 | }, |
| 5178 | 5143 | .unstructured => |cf| { |
| 5179 | 5144 | const block = cf.blocks.get(br.block_inst).?; |
| 5180 | if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5145 | if (operand_ty.hasRuntimeBits(zcu)) { | |
| 5181 | 5146 | const operand_id = try cg.resolve(br.operand); |
| 5182 | 5147 | // block_label should not be undefined here, lest there |
| 5183 | 5148 | // is a br or br_void in the function's body. |
| ... | ... | @@ -5335,7 +5300,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5335 | 5300 | const zcu = cg.module.zcu; |
| 5336 | 5301 | const operand = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5337 | 5302 | const ret_ty = cg.typeOf(operand); |
| 5338 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5303 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 5339 | 5304 | const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; |
| 5340 | 5305 | if (Type.fromInterned(fn_info.return_type).isError(zcu)) { |
| 5341 | 5306 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -5359,7 +5324,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5359 | 5324 | const ptr_ty = cg.typeOf(un_op); |
| 5360 | 5325 | const ret_ty = ptr_ty.childType(zcu); |
| 5361 | 5326 | |
| 5362 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5327 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 5363 | 5328 | const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; |
| 5364 | 5329 | if (Type.fromInterned(fn_info.return_type).isError(zcu)) { |
| 5365 | 5330 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -5576,7 +5541,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { |
| 5576 | 5541 | |
| 5577 | 5542 | const is_non_null_id = blk: { |
| 5578 | 5543 | if (is_pointer) { |
| 5579 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5544 | if (payload_ty.hasRuntimeBits(zcu)) { | |
| 5580 | 5545 | const storage_class = cg.module.storageClass(operand_ty.ptrAddressSpace(zcu)); |
| 5581 | 5546 | const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect); |
| 5582 | 5547 | const bool_ptr_ty_id = try cg.module.ptrType(bool_indirect_ty_id, storage_class); |
| ... | ... | @@ -5587,7 +5552,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { |
| 5587 | 5552 | break :blk try cg.load(.bool, operand_id, .{}); |
| 5588 | 5553 | } |
| 5589 | 5554 | |
| 5590 | break :blk if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 5555 | break :blk if (payload_ty.hasRuntimeBits(zcu)) | |
| 5591 | 5556 | try cg.extractField(.bool, operand_id, 1) |
| 5592 | 5557 | else |
| 5593 | 5558 | // Optional representation is bool indicating whether the optional is set |
| ... | ... | @@ -5656,7 +5621,7 @@ fn airUnwrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5656 | 5621 | const optional_ty = cg.typeOf(ty_op.operand); |
| 5657 | 5622 | const payload_ty = cg.typeOfIndex(inst); |
| 5658 | 5623 | |
| 5659 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; | |
| 5624 | if (!payload_ty.hasRuntimeBits(zcu)) return null; | |
| 5660 | 5625 | |
| 5661 | 5626 | if (optional_ty.optionalReprIsPayload(zcu)) { |
| 5662 | 5627 | return operand_id; |
| ... | ... | @@ -5675,7 +5640,7 @@ fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5675 | 5640 | const result_ty = cg.typeOfIndex(inst); |
| 5676 | 5641 | const result_ty_id = try cg.resolveType(result_ty, .direct); |
| 5677 | 5642 | |
| 5678 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5643 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 5679 | 5644 | // There is no payload, but we still need to return a valid pointer. |
| 5680 | 5645 | // We can just return anything here, so just return a pointer to the operand. |
| 5681 | 5646 | return try cg.bitCast(result_ty, operand_ty, operand_id); |
| ... | ... | @@ -5694,9 +5659,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5694 | 5659 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5695 | 5660 | const payload_ty = cg.typeOf(ty_op.operand); |
| 5696 | 5661 | |
| 5697 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5698 | return try cg.constBool(true, .indirect); | |
| 5699 | } | |
| 5662 | assert(payload_ty.hasRuntimeBits(zcu)); | |
| 5700 | 5663 | |
| 5701 | 5664 | const operand_id = try cg.resolve(ty_op.operand); |
| 5702 | 5665 | |
| ... | ... | @@ -5792,8 +5755,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5792 | 5755 | const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) { |
| 5793 | 5756 | .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu), |
| 5794 | 5757 | .@"enum" => blk: { |
| 5795 | // TODO: figure out of cond_ty is correct (something with enum literals) | |
| 5796 | break :blk (try value.intFromEnum(cond_ty, pt)).toUnsignedInt(zcu); // TODO: composite integer constants | |
| 5758 | break :blk value.intFromEnum(zcu).toUnsignedInt(zcu); // TODO: composite integer constants | |
| 5797 | 5759 | }, |
| 5798 | 5760 | .error_set => value.getErrorInt(zcu), |
| 5799 | 5761 | .pointer => value.toUnsignedInt(zcu), |
| ... | ... | @@ -6070,7 +6032,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 6070 | 6032 | // before starting to emit OpFunctionCall instructions. Hence the |
| 6071 | 6033 | // temporary params buffer. |
| 6072 | 6034 | const arg_ty = cg.typeOf(arg); |
| 6073 | if (!arg_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 6035 | if (!arg_ty.hasRuntimeBits(zcu)) continue; | |
| 6074 | 6036 | const arg_id = try cg.resolve(arg); |
| 6075 | 6037 | |
| 6076 | 6038 | params[n_params] = arg_id; |
| ... | ... | @@ -6084,7 +6046,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 6084 | 6046 | .id_ref_3 = params[0..n_params], |
| 6085 | 6047 | }); |
| 6086 | 6048 | |
| 6087 | if (cg.liveness.isUnused(inst) or !Type.fromInterned(return_type).hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 6049 | if (cg.liveness.isUnused(inst) or !Type.fromInterned(return_type).hasRuntimeBits(zcu)) { | |
| 6088 | 6050 | return null; |
| 6089 | 6051 | } |
| 6090 | 6052 |
src/codegen/wasm/CodeGen.zig+77-151| ... | ... | @@ -759,7 +759,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 759 | 759 | const zcu = pt.zcu; |
| 760 | 760 | const val = (try cg.air.value(ref, pt)).?; |
| 761 | 761 | const ty = cg.typeOf(ref); |
| 762 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { | |
| 762 | if (!ty.hasRuntimeBits(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { | |
| 763 | 763 | gop.value_ptr.* = .none; |
| 764 | 764 | return .none; |
| 765 | 765 | } |
| ... | ... | @@ -773,7 +773,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 773 | 773 | const result: WValue = if (isByRef(ty, zcu, cg.target)) |
| 774 | 774 | .{ .uav_ref = .{ .ip_index = val.toIntern() } } |
| 775 | 775 | else |
| 776 | try cg.lowerConstant(val, ty); | |
| 776 | try cg.lowerConstant(val); | |
| 777 | 777 | |
| 778 | 778 | gop.value_ptr.* = result; |
| 779 | 779 | return result; |
| ... | ... | @@ -786,7 +786,7 @@ fn resolveValue(cg: *CodeGen, val: Value) InnerError!WValue { |
| 786 | 786 | return if (isByRef(ty, zcu, cg.target)) |
| 787 | 787 | .{ .uav_ref = .{ .ip_index = val.toIntern() } } |
| 788 | 788 | else |
| 789 | try cg.lowerConstant(val, ty); | |
| 789 | try cg.lowerConstant(val); | |
| 790 | 790 | } |
| 791 | 791 | |
| 792 | 792 | /// NOTE: if result == .stack, it will be stored in .local |
| ... | ... | @@ -980,7 +980,6 @@ fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { |
| 980 | 980 | |
| 981 | 981 | /// For `std.builtin.CallingConvention.auto`. |
| 982 | 982 | pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.wasm.Valtype { |
| 983 | const ip = &zcu.intern_pool; | |
| 984 | 983 | return switch (ty.zigTypeTag(zcu)) { |
| 985 | 984 | .float => switch (ty.floatBits(target)) { |
| 986 | 985 | 16 => .i32, // stored/loaded as u16 |
| ... | ... | @@ -994,25 +993,13 @@ pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.w |
| 994 | 993 | 33...64 => .i64, |
| 995 | 994 | else => .i32, |
| 996 | 995 | }, |
| 997 | .@"struct" => blk: { | |
| 998 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { | |
| 999 | const backing_int_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); | |
| 1000 | break :blk typeToValtype(backing_int_ty, zcu, target); | |
| 1001 | } else { | |
| 1002 | break :blk .i32; | |
| 1003 | } | |
| 1004 | }, | |
| 1005 | 996 | .vector => switch (CodeGen.determineSimdStoreStrategy(ty, zcu, target)) { |
| 1006 | 997 | .direct => .v128, |
| 1007 | 998 | .unrolled => .i32, |
| 1008 | 999 | }, |
| 1009 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 1010 | .@"packed" => switch (ty.bitSize(zcu)) { | |
| 1011 | 0...32 => .i32, | |
| 1012 | 33...64 => .i64, | |
| 1013 | else => .i32, | |
| 1014 | }, | |
| 1015 | else => .i32, | |
| 1000 | .@"union", .@"struct" => switch (ty.containerLayout(zcu)) { | |
| 1001 | .@"packed" => typeToValtype(ty.bitpackBackingInt(zcu), zcu, target), | |
| 1002 | .auto, .@"extern" => .i32, | |
| 1016 | 1003 | }, |
| 1017 | 1004 | else => .i32, // all represented as reference/immediate |
| 1018 | 1005 | }; |
| ... | ... | @@ -1185,7 +1172,7 @@ pub fn generate( |
| 1185 | 1172 | const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu); |
| 1186 | 1173 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 1187 | 1174 | const ret_ty: Type = .fromInterned(fn_info.return_type); |
| 1188 | const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 1175 | const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBits(zcu); | |
| 1189 | 1176 | |
| 1190 | 1177 | var cc_result = try resolveCallingConventionValues(zcu, fn_ty, target); |
| 1191 | 1178 | defer cc_result.deinit(gpa); |
| ... | ... | @@ -1244,7 +1231,7 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir { |
| 1244 | 1231 | if (any_returns and cg.air.instructions.len > 0) { |
| 1245 | 1232 | const inst: Air.Inst.Index = @enumFromInt(cg.air.instructions.len - 1); |
| 1246 | 1233 | const last_inst_ty = cg.typeOfIndex(inst); |
| 1247 | if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(zcu) or last_inst_ty.isNoReturn(zcu)) { | |
| 1234 | if (!last_inst_ty.hasRuntimeBits(zcu)) { | |
| 1248 | 1235 | try cg.addTag(.@"unreachable"); |
| 1249 | 1236 | } |
| 1250 | 1237 | } |
| ... | ... | @@ -1316,7 +1303,7 @@ fn resolveCallingConventionValues( |
| 1316 | 1303 | switch (cc) { |
| 1317 | 1304 | .auto => { |
| 1318 | 1305 | for (fn_info.param_types.get(ip)) |ty| { |
| 1319 | if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1306 | if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { | |
| 1320 | 1307 | continue; |
| 1321 | 1308 | } |
| 1322 | 1309 | |
| ... | ... | @@ -1326,7 +1313,7 @@ fn resolveCallingConventionValues( |
| 1326 | 1313 | }, |
| 1327 | 1314 | .wasm_mvp => { |
| 1328 | 1315 | for (fn_info.param_types.get(ip)) |ty| { |
| 1329 | if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1316 | if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { | |
| 1330 | 1317 | continue; |
| 1331 | 1318 | } |
| 1332 | 1319 | switch (abi.classifyType(.fromInterned(ty), zcu)) { |
| ... | ... | @@ -1357,7 +1344,7 @@ pub fn firstParamSRet( |
| 1357 | 1344 | zcu: *const Zcu, |
| 1358 | 1345 | target: *const std.Target, |
| 1359 | 1346 | ) bool { |
| 1360 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; | |
| 1347 | if (!return_type.hasRuntimeBits(zcu)) return false; | |
| 1361 | 1348 | switch (cc) { |
| 1362 | 1349 | .@"inline" => unreachable, |
| 1363 | 1350 | .auto => return isByRef(return_type, zcu, target), |
| ... | ... | @@ -1457,7 +1444,7 @@ fn restoreStackPointer(cg: *CodeGen) !void { |
| 1457 | 1444 | fn allocStack(cg: *CodeGen, ty: Type) !WValue { |
| 1458 | 1445 | const pt = cg.pt; |
| 1459 | 1446 | const zcu = pt.zcu; |
| 1460 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 1447 | assert(ty.hasRuntimeBits(zcu)); | |
| 1461 | 1448 | if (cg.initial_stack_value == .none) { |
| 1462 | 1449 | try cg.initializeStack(); |
| 1463 | 1450 | } |
| ... | ... | @@ -1491,7 +1478,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue { |
| 1491 | 1478 | try cg.initializeStack(); |
| 1492 | 1479 | } |
| 1493 | 1480 | |
| 1494 | if (!pointee_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1481 | if (!pointee_ty.hasRuntimeBits(zcu)) { | |
| 1495 | 1482 | return cg.allocStack(Type.usize); // create a value containing just the stack pointer. |
| 1496 | 1483 | } |
| 1497 | 1484 | |
| ... | ... | @@ -1676,7 +1663,6 @@ fn ptrSize(cg: *const CodeGen) u16 { |
| 1676 | 1663 | /// For a given `Type`, will return true when the type will be passed |
| 1677 | 1664 | /// by reference, rather than by value |
| 1678 | 1665 | fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { |
| 1679 | const ip = &zcu.intern_pool; | |
| 1680 | 1666 | switch (ty.zigTypeTag(zcu)) { |
| 1681 | 1667 | .type, |
| 1682 | 1668 | .comptime_int, |
| ... | ... | @@ -1697,20 +1683,10 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { |
| 1697 | 1683 | |
| 1698 | 1684 | .array, |
| 1699 | 1685 | .frame, |
| 1700 | => return ty.hasRuntimeBitsIgnoreComptime(zcu), | |
| 1701 | .@"union" => { | |
| 1702 | if (zcu.typeToUnion(ty)) |union_obj| { | |
| 1703 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | |
| 1704 | return ty.abiSize(zcu) > 8; | |
| 1705 | } | |
| 1706 | } | |
| 1707 | return ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 1708 | }, | |
| 1709 | .@"struct" => { | |
| 1710 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { | |
| 1711 | return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), zcu, target); | |
| 1712 | } | |
| 1713 | return ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 1686 | => return ty.hasRuntimeBits(zcu), | |
| 1687 | .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { | |
| 1688 | .@"packed" => return isByRef(ty.bitpackBackingInt(zcu), zcu, target), | |
| 1689 | .@"extern", .auto => return ty.hasRuntimeBits(zcu), | |
| 1714 | 1690 | }, |
| 1715 | 1691 | .vector => return determineSimdStoreStrategy(ty, zcu, target) == .unrolled, |
| 1716 | 1692 | .int => return ty.intInfo(zcu).bits > 64, |
| ... | ... | @@ -1718,7 +1694,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { |
| 1718 | 1694 | .float => return ty.floatBits(target) > 64, |
| 1719 | 1695 | .error_union => { |
| 1720 | 1696 | const pl_ty = ty.errorUnionPayload(zcu); |
| 1721 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1697 | if (!pl_ty.hasRuntimeBits(zcu)) { | |
| 1722 | 1698 | return false; |
| 1723 | 1699 | } |
| 1724 | 1700 | return true; |
| ... | ... | @@ -1727,7 +1703,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { |
| 1727 | 1703 | if (ty.isPtrLikeOptional(zcu)) return false; |
| 1728 | 1704 | const pl_type = ty.optionalChild(zcu); |
| 1729 | 1705 | if (pl_type.zigTypeTag(zcu) == .error_set) return false; |
| 1730 | return pl_type.hasRuntimeBitsIgnoreComptime(zcu); | |
| 1706 | return pl_type.hasRuntimeBits(zcu); | |
| 1731 | 1707 | }, |
| 1732 | 1708 | .pointer => { |
| 1733 | 1709 | // Slices act like struct and will be passed by reference |
| ... | ... | @@ -2069,7 +2045,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2069 | 2045 | // to the stack instead |
| 2070 | 2046 | if (cg.return_value != .none) { |
| 2071 | 2047 | try cg.store(cg.return_value, operand, ret_ty, 0); |
| 2072 | } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2048 | } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) { | |
| 2073 | 2049 | switch (abi.classifyType(ret_ty, zcu)) { |
| 2074 | 2050 | .direct => |scalar_type| { |
| 2075 | 2051 | assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); |
| ... | ... | @@ -2082,7 +2058,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2082 | 2058 | .indirect => unreachable, |
| 2083 | 2059 | } |
| 2084 | 2060 | } else { |
| 2085 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and ret_ty.isError(zcu)) { | |
| 2061 | if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) { | |
| 2086 | 2062 | try cg.addImm32(0); |
| 2087 | 2063 | } else { |
| 2088 | 2064 | try cg.emitWValue(operand); |
| ... | ... | @@ -2099,7 +2075,7 @@ fn airRetPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2099 | 2075 | const child_type = cg.typeOfIndex(inst).childType(zcu); |
| 2100 | 2076 | |
| 2101 | 2077 | const result = result: { |
| 2102 | if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2078 | if (!child_type.hasRuntimeBits(zcu)) { | |
| 2103 | 2079 | break :result try cg.allocStack(Type.usize); // create pointer to void |
| 2104 | 2080 | } |
| 2105 | 2081 | |
| ... | ... | @@ -2121,7 +2097,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2121 | 2097 | const ret_ty = cg.typeOf(un_op).childType(zcu); |
| 2122 | 2098 | |
| 2123 | 2099 | const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; |
| 2124 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2100 | if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 2125 | 2101 | if (ret_ty.isError(zcu)) { |
| 2126 | 2102 | try cg.addImm32(0); |
| 2127 | 2103 | } |
| ... | ... | @@ -2177,7 +2153,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 2177 | 2153 | const arg_val = try cg.resolveInst(arg); |
| 2178 | 2154 | |
| 2179 | 2155 | const arg_ty = cg.typeOf(arg); |
| 2180 | if (!arg_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 2156 | if (!arg_ty.hasRuntimeBits(zcu)) continue; | |
| 2181 | 2157 | |
| 2182 | 2158 | try cg.lowerArg(zcu.typeToFunc(fn_ty).?.cc, arg_ty, arg_val); |
| 2183 | 2159 | } |
| ... | ... | @@ -2199,10 +2175,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 2199 | 2175 | } |
| 2200 | 2176 | |
| 2201 | 2177 | const result_value = result_value: { |
| 2202 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) { | |
| 2203 | break :result_value .none; | |
| 2204 | } else if (ret_ty.isNoReturn(zcu)) { | |
| 2205 | try cg.addTag(.@"unreachable"); | |
| 2178 | if (!ret_ty.hasRuntimeBits(zcu) and !ret_ty.isError(zcu)) { | |
| 2206 | 2179 | break :result_value .none; |
| 2207 | 2180 | } else if (first_param_sret) { |
| 2208 | 2181 | break :result_value sret; |
| ... | ... | @@ -2323,12 +2296,12 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2323 | 2296 | const zcu = pt.zcu; |
| 2324 | 2297 | const abi_size = ty.abiSize(zcu); |
| 2325 | 2298 | |
| 2326 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return; | |
| 2299 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 2327 | 2300 | |
| 2328 | 2301 | switch (ty.zigTypeTag(zcu)) { |
| 2329 | 2302 | .error_union => { |
| 2330 | 2303 | const pl_ty = ty.errorUnionPayload(zcu); |
| 2331 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2304 | if (!pl_ty.hasRuntimeBits(zcu)) { | |
| 2332 | 2305 | return cg.store(lhs, rhs, Type.anyerror, offset); |
| 2333 | 2306 | } |
| 2334 | 2307 | |
| ... | ... | @@ -2341,7 +2314,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2341 | 2314 | return cg.store(lhs, rhs, Type.usize, offset); |
| 2342 | 2315 | } |
| 2343 | 2316 | const pl_ty = ty.optionalChild(zcu); |
| 2344 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 2317 | if (!pl_ty.hasRuntimeBits(zcu)) { | |
| 2345 | 2318 | return cg.store(lhs, rhs, Type.u8, offset); |
| 2346 | 2319 | } |
| 2347 | 2320 | if (pl_ty.zigTypeTag(zcu) == .error_set) { |
| ... | ... | @@ -2441,7 +2414,7 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2441 | 2414 | const ptr_ty = cg.typeOf(ty_op.operand); |
| 2442 | 2415 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| 2443 | 2416 | |
| 2444 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); | |
| 2417 | if (!ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); | |
| 2445 | 2418 | |
| 2446 | 2419 | const result = result: { |
| 2447 | 2420 | if (isByRef(ty, zcu, cg.target)) { |
| ... | ... | @@ -3092,7 +3065,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro |
| 3092 | 3065 | return switch (ptr.base_addr) { |
| 3093 | 3066 | .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } }, |
| 3094 | 3067 | .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset), .orig_ptr_ty = uav.orig_ty } }, |
| 3095 | .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize), | |
| 3068 | .int => return cg.lowerConstant(try pt.intValue(.usize, offset)), | |
| 3096 | 3069 | .eu_payload => |eu_ptr| try cg.lowerPtr( |
| 3097 | 3070 | eu_ptr, |
| 3098 | 3071 | offset + codegen.errUnionPayloadOffset( |
| ... | ... | @@ -3129,10 +3102,11 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro |
| 3129 | 3102 | }; |
| 3130 | 3103 | } |
| 3131 | 3104 | |
| 3132 | /// Asserts that `isByRef` returns `false` for `ty`. | |
| 3133 | fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { | |
| 3105 | /// Asserts that `isByRef` returns `false` for `val.typeOf(zcu)`. | |
| 3106 | fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue { | |
| 3134 | 3107 | const pt = cg.pt; |
| 3135 | 3108 | const zcu = pt.zcu; |
| 3109 | const ty = val.typeOf(zcu); | |
| 3136 | 3110 | assert(!isByRef(ty, zcu, cg.target)); |
| 3137 | 3111 | const ip = &zcu.intern_pool; |
| 3138 | 3112 | if (val.isUndef(zcu)) return cg.emitUndefined(ty); |
| ... | ... | @@ -3158,10 +3132,8 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3158 | 3132 | |
| 3159 | 3133 | .undef => unreachable, // handled above |
| 3160 | 3134 | .simple_value => |simple_value| switch (simple_value) { |
| 3161 | .undefined, | |
| 3162 | 3135 | .void, |
| 3163 | 3136 | .null, |
| 3164 | .empty_tuple, | |
| 3165 | 3137 | .@"unreachable", |
| 3166 | 3138 | => unreachable, // non-runtime values |
| 3167 | 3139 | .false, .true => return .{ .imm32 = switch (simple_value) { |
| ... | ... | @@ -3174,7 +3146,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3174 | 3146 | .@"extern", |
| 3175 | 3147 | .func, |
| 3176 | 3148 | .enum_literal, |
| 3177 | .empty_enum_value, | |
| 3178 | 3149 | => unreachable, // non-runtime values |
| 3179 | 3150 | .int => { |
| 3180 | 3151 | const int_info = ty.intInfo(zcu); |
| ... | ... | @@ -3197,31 +3168,22 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3197 | 3168 | }, |
| 3198 | 3169 | .error_union => |error_union| { |
| 3199 | 3170 | const err_int_ty = try pt.errorIntType(); |
| 3200 | const err_ty, const err_val = switch (error_union.val) { | |
| 3201 | .err_name => |err_name| .{ | |
| 3202 | ty.errorUnionSet(zcu), | |
| 3203 | Value.fromInterned(try pt.intern(.{ .err = .{ | |
| 3204 | .ty = ty.errorUnionSet(zcu).toIntern(), | |
| 3205 | .name = err_name, | |
| 3206 | } })), | |
| 3207 | }, | |
| 3208 | .payload => .{ | |
| 3209 | err_int_ty, | |
| 3210 | try pt.intValue(err_int_ty, 0), | |
| 3211 | }, | |
| 3171 | const err_val: Value = switch (error_union.val) { | |
| 3172 | .err_name => |err_name| .fromInterned(try pt.intern(.{ .err = .{ | |
| 3173 | .ty = ty.errorUnionSet(zcu).toIntern(), | |
| 3174 | .name = err_name, | |
| 3175 | } })), | |
| 3176 | .payload => try pt.intValue(err_int_ty, 0), | |
| 3212 | 3177 | }; |
| 3213 | 3178 | const payload_type = ty.errorUnionPayload(zcu); |
| 3214 | if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3179 | if (!payload_type.hasRuntimeBits(zcu)) { | |
| 3215 | 3180 | // We use the error type directly as the type. |
| 3216 | return cg.lowerConstant(err_val, err_ty); | |
| 3181 | return cg.lowerConstant(err_val); | |
| 3217 | 3182 | } |
| 3218 | 3183 | |
| 3219 | 3184 | return cg.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{}); |
| 3220 | 3185 | }, |
| 3221 | .enum_tag => |enum_tag| { | |
| 3222 | const int_tag_ty = ip.typeOf(enum_tag.int); | |
| 3223 | return cg.lowerConstant(Value.fromInterned(enum_tag.int), Type.fromInterned(int_tag_ty)); | |
| 3224 | }, | |
| 3186 | .enum_tag => |enum_tag| return cg.lowerConstant(.fromInterned(enum_tag.int)), | |
| 3225 | 3187 | .float => |float| switch (float.storage) { |
| 3226 | 3188 | .f16 => |f16_val| return .{ .imm32 = @as(u16, @bitCast(f16_val)) }, |
| 3227 | 3189 | .f32 => |f32_val| return .{ .float32 = f32_val }, |
| ... | ... | @@ -3231,9 +3193,8 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3231 | 3193 | .slice => unreachable, // isByRef == true |
| 3232 | 3194 | .ptr => return cg.lowerPtr(val.toIntern(), 0), |
| 3233 | 3195 | .opt => if (ty.optionalReprIsPayload(zcu)) { |
| 3234 | const pl_ty = ty.optionalChild(zcu); | |
| 3235 | 3196 | if (val.optionalValue(zcu)) |payload| { |
| 3236 | return cg.lowerConstant(payload, pl_ty); | |
| 3197 | return cg.lowerConstant(payload); | |
| 3237 | 3198 | } else { |
| 3238 | 3199 | return .{ .imm32 = 0 }; |
| 3239 | 3200 | } |
| ... | ... | @@ -3248,33 +3209,11 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3248 | 3209 | val.writeToMemory(pt, &buf) catch unreachable; |
| 3249 | 3210 | return cg.storeSimdImmd(buf); |
| 3250 | 3211 | }, |
| 3251 | .struct_type => { | |
| 3252 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 3253 | // non-packed structs are not handled in this function because they | |
| 3254 | // are by-ref types. | |
| 3255 | assert(struct_type.layout == .@"packed"); | |
| 3256 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer | |
| 3257 | val.writeToPackedMemory(ty, pt, &buf, 0) catch unreachable; | |
| 3258 | const backing_int_ty = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)); | |
| 3259 | const int_val = try pt.intValue( | |
| 3260 | backing_int_ty, | |
| 3261 | mem.readInt(u64, &buf, .little), | |
| 3262 | ); | |
| 3263 | return cg.lowerConstant(int_val, backing_int_ty); | |
| 3264 | }, | |
| 3212 | .struct_type => unreachable, // packed structs use `bitpack` | |
| 3265 | 3213 | else => unreachable, |
| 3266 | 3214 | }, |
| 3267 | .un => { | |
| 3268 | const int_type = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); | |
| 3269 | ||
| 3270 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer | |
| 3271 | val.writeToPackedMemory(ty, pt, &buf, 0) catch unreachable; | |
| 3272 | const int_val = try pt.intValue( | |
| 3273 | int_type, | |
| 3274 | mem.readInt(u64, &buf, .little), | |
| 3275 | ); | |
| 3276 | return cg.lowerConstant(int_val, int_type); | |
| 3277 | }, | |
| 3215 | .un => unreachable, // packed unions use `bitpack` | |
| 3216 | .bitpack => |bitpack| return cg.lowerConstant(.fromInterned(bitpack.backing_int_val)), | |
| 3278 | 3217 | .memoized_call => unreachable, |
| 3279 | 3218 | } |
| 3280 | 3219 | } |
| ... | ... | @@ -3289,7 +3228,6 @@ fn storeSimdImmd(cg: *CodeGen, value: [16]u8) !WValue { |
| 3289 | 3228 | |
| 3290 | 3229 | fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 3291 | 3230 | const zcu = cg.pt.zcu; |
| 3292 | const ip = &zcu.intern_pool; | |
| 3293 | 3231 | switch (ty.zigTypeTag(zcu)) { |
| 3294 | 3232 | .bool, .error_set => return .{ .imm32 = 0xaaaaaaaa }, |
| 3295 | 3233 | .int, .@"enum" => switch (ty.intInfo(zcu).bits) { |
| ... | ... | @@ -3317,17 +3255,9 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 3317 | 3255 | .error_union => { |
| 3318 | 3256 | return .{ .imm32 = 0xaaaaaaaa }; |
| 3319 | 3257 | }, |
| 3320 | .@"struct" => { | |
| 3321 | const packed_struct = zcu.typeToPackedStruct(ty).?; | |
| 3322 | return cg.emitUndefined(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip))); | |
| 3323 | }, | |
| 3324 | .@"union" => switch (ty.containerLayout(zcu)) { | |
| 3325 | .@"packed" => switch (ty.bitSize(zcu)) { | |
| 3326 | 0...32 => return .{ .imm32 = 0xaaaaaaaa }, | |
| 3327 | 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa }, | |
| 3328 | else => unreachable, | |
| 3329 | }, | |
| 3330 | else => unreachable, | |
| 3258 | .@"struct", .@"union" => { | |
| 3259 | const backing_int_ty = ty.bitpackBackingInt(zcu); | |
| 3260 | return cg.emitUndefined(backing_int_ty); | |
| 3331 | 3261 | }, |
| 3332 | 3262 | else => return cg.fail("Wasm TODO: emitUndefined for type: {t}\n", .{ty.zigTypeTag(zcu)}), |
| 3333 | 3263 | } |
| ... | ... | @@ -3341,7 +3271,7 @@ fn airBlock(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3341 | 3271 | fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void { |
| 3342 | 3272 | const zcu = cg.pt.zcu; |
| 3343 | 3273 | // if wasm_block_ty is non-empty, we create a register to store the temporary value |
| 3344 | const block_result: WValue = if (block_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 3274 | const block_result: WValue = if (block_ty.hasRuntimeBits(zcu)) | |
| 3345 | 3275 | try cg.allocLocal(block_ty) |
| 3346 | 3276 | else |
| 3347 | 3277 | .none; |
| ... | ... | @@ -3455,7 +3385,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe |
| 3455 | 3385 | const zcu = cg.pt.zcu; |
| 3456 | 3386 | if (ty.zigTypeTag(zcu) == .optional and !ty.optionalReprIsPayload(zcu)) { |
| 3457 | 3387 | const payload_ty = ty.optionalChild(zcu); |
| 3458 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3388 | if (payload_ty.hasRuntimeBits(zcu)) { | |
| 3459 | 3389 | // When we hit this case, we must check the value of optionals |
| 3460 | 3390 | // that are not pointers. This means first checking against non-null for |
| 3461 | 3391 | // both lhs and rhs, as well as checking the payload are matching of lhs and rhs |
| ... | ... | @@ -3798,7 +3728,6 @@ fn structFieldPtr( |
| 3798 | 3728 | fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3799 | 3729 | const pt = cg.pt; |
| 3800 | 3730 | const zcu = pt.zcu; |
| 3801 | const ip = &zcu.intern_pool; | |
| 3802 | 3731 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3803 | 3732 | const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data; |
| 3804 | 3733 | |
| ... | ... | @@ -3806,14 +3735,14 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3806 | 3735 | const operand = try cg.resolveInst(struct_field.struct_operand); |
| 3807 | 3736 | const field_index = struct_field.field_index; |
| 3808 | 3737 | const field_ty = struct_ty.fieldType(field_index, zcu); |
| 3809 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{struct_field.struct_operand}); | |
| 3738 | if (!field_ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{struct_field.struct_operand}); | |
| 3810 | 3739 | |
| 3811 | 3740 | const result: WValue = switch (struct_ty.containerLayout(zcu)) { |
| 3812 | 3741 | .@"packed" => switch (struct_ty.zigTypeTag(zcu)) { |
| 3813 | 3742 | .@"struct" => result: { |
| 3814 | 3743 | const packed_struct = zcu.typeToPackedStruct(struct_ty).?; |
| 3815 | 3744 | const offset = zcu.structPackedFieldBitOffset(packed_struct, field_index); |
| 3816 | const backing_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); | |
| 3745 | const backing_ty = Type.fromInterned(packed_struct.packed_backing_int_type); | |
| 3817 | 3746 | const host_bits = backing_ty.intInfo(zcu).bits; |
| 3818 | 3747 | |
| 3819 | 3748 | const const_wvalue: WValue = if (33 <= host_bits and host_bits <= 64) |
| ... | ... | @@ -3891,7 +3820,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner |
| 3891 | 3820 | const switch_br = cg.air.unwrapSwitch(inst); |
| 3892 | 3821 | const target_ty = cg.typeOf(switch_br.operand); |
| 3893 | 3822 | |
| 3894 | assert(target_ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 3823 | assert(target_ty.hasRuntimeBits(zcu)); | |
| 3895 | 3824 | |
| 3896 | 3825 | // swap target value with placeholder local, for dispatching |
| 3897 | 3826 | const target = if (is_dispatch_loop) target: { |
| ... | ... | @@ -4125,7 +4054,7 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, opcode: std.wasm.Opcode, op_kind |
| 4125 | 4054 | } |
| 4126 | 4055 | |
| 4127 | 4056 | try cg.emitWValue(operand); |
| 4128 | if (op_kind == .ptr or pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4057 | if (op_kind == .ptr or pl_ty.hasRuntimeBits(zcu)) { | |
| 4129 | 4058 | try cg.addMemArg(.i32_load16_u, .{ |
| 4130 | 4059 | .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, zcu))), |
| 4131 | 4060 | .alignment = @intCast(Type.anyerror.abiAlignment(zcu).toByteUnits().?), |
| ... | ... | @@ -4152,7 +4081,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) |
| 4152 | 4081 | const payload_ty = eu_ty.errorUnionPayload(zcu); |
| 4153 | 4082 | |
| 4154 | 4083 | const result: WValue = result: { |
| 4155 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4084 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 4156 | 4085 | if (op_is_ptr) { |
| 4157 | 4086 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 4158 | 4087 | } else { |
| ... | ... | @@ -4172,7 +4101,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) |
| 4172 | 4101 | } |
| 4173 | 4102 | |
| 4174 | 4103 | /// E!T -> E op_is_ptr == false |
| 4175 | /// *(E!T) -> E op_is_prt == true | |
| 4104 | /// *(E!T) -> E op_is_ptr == true | |
| 4176 | 4105 | /// NOTE: op_is_ptr will not change return type |
| 4177 | 4106 | fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { |
| 4178 | 4107 | const zcu = cg.pt.zcu; |
| ... | ... | @@ -4192,7 +4121,7 @@ fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) I |
| 4192 | 4121 | if (op_is_ptr or isByRef(eu_ty, zcu, cg.target)) { |
| 4193 | 4122 | break :result try cg.load(operand, Type.anyerror, err_offset); |
| 4194 | 4123 | } else { |
| 4195 | assert(!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 4124 | assert(!payload_ty.hasRuntimeBits(zcu)); | |
| 4196 | 4125 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 4197 | 4126 | } |
| 4198 | 4127 | }; |
| ... | ... | @@ -4208,7 +4137,7 @@ fn airWrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4208 | 4137 | |
| 4209 | 4138 | const pl_ty = cg.typeOf(ty_op.operand); |
| 4210 | 4139 | const result = result: { |
| 4211 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4140 | if (!pl_ty.hasRuntimeBits(zcu)) { | |
| 4212 | 4141 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 4213 | 4142 | } |
| 4214 | 4143 | |
| ... | ... | @@ -4238,7 +4167,7 @@ fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4238 | 4167 | const pl_ty = err_ty.errorUnionPayload(zcu); |
| 4239 | 4168 | |
| 4240 | 4169 | const result = result: { |
| 4241 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4170 | if (!pl_ty.hasRuntimeBits(zcu)) { | |
| 4242 | 4171 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 4243 | 4172 | } |
| 4244 | 4173 | |
| ... | ... | @@ -4354,7 +4283,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc |
| 4354 | 4283 | if (!optional_ty.optionalReprIsPayload(zcu)) { |
| 4355 | 4284 | // When payload is zero-bits, we can treat operand as a value, rather than |
| 4356 | 4285 | // a pointer to the stack value |
| 4357 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4286 | if (payload_ty.hasRuntimeBits(zcu)) { | |
| 4358 | 4287 | const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse { |
| 4359 | 4288 | return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)}); |
| 4360 | 4289 | }; |
| ... | ... | @@ -4379,7 +4308,7 @@ fn airOptionalPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4379 | 4308 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4380 | 4309 | const opt_ty = cg.typeOf(ty_op.operand); |
| 4381 | 4310 | const payload_ty = cg.typeOfIndex(inst); |
| 4382 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4311 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 4383 | 4312 | return cg.finishAir(inst, .none, &.{ty_op.operand}); |
| 4384 | 4313 | } |
| 4385 | 4314 | |
| ... | ... | @@ -4404,7 +4333,7 @@ fn airOptionalPayloadPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4404 | 4333 | |
| 4405 | 4334 | const result = result: { |
| 4406 | 4335 | const payload_ty = opt_ty.optionalChild(zcu); |
| 4407 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or opt_ty.optionalReprIsPayload(zcu)) { | |
| 4336 | if (!payload_ty.hasRuntimeBits(zcu) or opt_ty.optionalReprIsPayload(zcu)) { | |
| 4408 | 4337 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 4409 | 4338 | } |
| 4410 | 4339 | |
| ... | ... | @@ -4444,7 +4373,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4444 | 4373 | const zcu = pt.zcu; |
| 4445 | 4374 | |
| 4446 | 4375 | const result = result: { |
| 4447 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4376 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 4448 | 4377 | const non_null_bit = try cg.allocStack(Type.u1); |
| 4449 | 4378 | try cg.emitWValue(non_null_bit); |
| 4450 | 4379 | try cg.addImm32(1); |
| ... | ... | @@ -4612,7 +4541,7 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4612 | 4541 | const slice_local = try cg.allocStack(slice_ty); |
| 4613 | 4542 | |
| 4614 | 4543 | // store the array ptr in the slice |
| 4615 | if (array_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4544 | if (array_ty.hasRuntimeBits(zcu)) { | |
| 4616 | 4545 | try cg.store(slice_local, operand, Type.usize, 0); |
| 4617 | 4546 | } |
| 4618 | 4547 | |
| ... | ... | @@ -5111,7 +5040,7 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5111 | 5040 | try cg.emitWValue(dest_alloc); |
| 5112 | 5041 | const elem_val = switch (mask_elem.unwrap()) { |
| 5113 | 5042 | .elem => |idx| try cg.load(operand, elem_ty, @intCast(elem_size * idx)), |
| 5114 | .value => |val| try cg.lowerConstant(.fromInterned(val), elem_ty), | |
| 5043 | .value => |val| try cg.lowerConstant(.fromInterned(val)), | |
| 5115 | 5044 | }; |
| 5116 | 5045 | try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx)); |
| 5117 | 5046 | } |
| ... | ... | @@ -5252,7 +5181,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5252 | 5181 | } |
| 5253 | 5182 | const packed_struct = zcu.typeToPackedStruct(result_ty).?; |
| 5254 | 5183 | const field_types = packed_struct.field_types; |
| 5255 | const backing_type = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); | |
| 5184 | const backing_type = Type.fromInterned(packed_struct.packed_backing_int_type); | |
| 5256 | 5185 | |
| 5257 | 5186 | // ensure the result is zero'd |
| 5258 | 5187 | const result = try cg.allocLocal(backing_type); |
| ... | ... | @@ -5265,7 +5194,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5265 | 5194 | var current_bit: u16 = 0; |
| 5266 | 5195 | for (elements, 0..) |elem, elem_index| { |
| 5267 | 5196 | const field_ty = Type.fromInterned(field_types.get(ip)[elem_index]); |
| 5268 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 5197 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 5269 | 5198 | |
| 5270 | 5199 | const shift_val: WValue = if (backing_type.bitSize(zcu) <= 32) |
| 5271 | 5200 | .{ .imm32 = current_bit } |
| ... | ... | @@ -5338,13 +5267,13 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5338 | 5267 | const layout = union_ty.unionGetLayout(zcu); |
| 5339 | 5268 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 5340 | 5269 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); |
| 5341 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | |
| 5270 | const field_name = ip.loadEnumType(union_obj.enum_tag_type).field_names.get(ip)[extra.field_index]; | |
| 5342 | 5271 | |
| 5343 | 5272 | const tag_int = blk: { |
| 5344 | 5273 | const tag_ty = union_ty.unionTagTypeHypothetical(zcu); |
| 5345 | 5274 | const enum_field_index = tag_ty.enumFieldIndex(field_name, zcu).?; |
| 5346 | 5275 | const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index); |
| 5347 | break :blk try cg.lowerConstant(tag_val, tag_ty); | |
| 5276 | break :blk try cg.lowerConstant(tag_val); | |
| 5348 | 5277 | }; |
| 5349 | 5278 | if (layout.payload_size == 0) { |
| 5350 | 5279 | if (layout.tag_size == 0) { |
| ... | ... | @@ -5366,7 +5295,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5366 | 5295 | } |
| 5367 | 5296 | |
| 5368 | 5297 | if (layout.tag_size > 0) { |
| 5369 | try cg.store(result_ptr, tag_int, Type.fromInterned(union_obj.enum_tag_ty), 0); | |
| 5298 | try cg.store(result_ptr, tag_int, .fromInterned(union_obj.enum_tag_type), 0); | |
| 5370 | 5299 | } |
| 5371 | 5300 | } else { |
| 5372 | 5301 | try cg.store(result_ptr, payload, field_ty, 0); |
| ... | ... | @@ -5374,7 +5303,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5374 | 5303 | try cg.store( |
| 5375 | 5304 | result_ptr, |
| 5376 | 5305 | tag_int, |
| 5377 | Type.fromInterned(union_obj.enum_tag_ty), | |
| 5306 | .fromInterned(union_obj.enum_tag_type), | |
| 5378 | 5307 | @intCast(layout.payload_size), |
| 5379 | 5308 | ); |
| 5380 | 5309 | } |
| ... | ... | @@ -5421,7 +5350,7 @@ fn airWasmMemoryGrow(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 5421 | 5350 | |
| 5422 | 5351 | fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { |
| 5423 | 5352 | const zcu = cg.pt.zcu; |
| 5424 | assert(operand_ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 5353 | assert(operand_ty.hasRuntimeBits(zcu)); | |
| 5425 | 5354 | assert(op == .eq or op == .neq); |
| 5426 | 5355 | const payload_ty = operand_ty.optionalChild(zcu); |
| 5427 | 5356 | assert(!isByRef(payload_ty, zcu, cg.target)); |
| ... | ... | @@ -5675,7 +5604,7 @@ fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void |
| 5675 | 5604 | ); |
| 5676 | 5605 | |
| 5677 | 5606 | const result = result: { |
| 5678 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 5607 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 5679 | 5608 | break :result cg.reuseOperand(ty_op.operand, operand); |
| 5680 | 5609 | } |
| 5681 | 5610 | |
| ... | ... | @@ -6464,7 +6393,7 @@ fn lowerTry( |
| 6464 | 6393 | const zcu = cg.pt.zcu; |
| 6465 | 6394 | |
| 6466 | 6395 | const pl_ty = err_union_ty.errorUnionPayload(zcu); |
| 6467 | const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(zcu); | |
| 6396 | const pl_has_bits = pl_ty.hasRuntimeBits(zcu); | |
| 6468 | 6397 | |
| 6469 | 6398 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 6470 | 6399 | // Block we can jump out of when error is not set |
| ... | ... | @@ -7102,16 +7031,13 @@ fn callIntrinsic( |
| 7102 | 7031 | // Lower all arguments to the stack before we call our function |
| 7103 | 7032 | for (args, 0..) |arg, arg_i| { |
| 7104 | 7033 | assert(!(want_sret_param and arg == .stack)); |
| 7105 | assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBitsIgnoreComptime(zcu)); | |
| 7034 | assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBits(zcu)); | |
| 7106 | 7035 | try cg.lowerArg(.{ .wasm_mvp = .{} }, Type.fromInterned(param_types[arg_i]), arg); |
| 7107 | 7036 | } |
| 7108 | 7037 | |
| 7109 | 7038 | try cg.addInst(.{ .tag = .call_intrinsic, .data = .{ .intrinsic = intrinsic } }); |
| 7110 | 7039 | |
| 7111 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 7112 | return .none; | |
| 7113 | } else if (return_type.isNoReturn(zcu)) { | |
| 7114 | try cg.addTag(.@"unreachable"); | |
| 7040 | if (!return_type.hasRuntimeBits(zcu)) { | |
| 7115 | 7041 | return .none; |
| 7116 | 7042 | } else if (want_sret_param) { |
| 7117 | 7043 | return sret; |
src/codegen/wasm/abi.zig+3-3| ... | ... | @@ -22,7 +22,7 @@ pub const Class = union(enum) { |
| 22 | 22 | /// or returned as value within a wasm function. |
| 23 | 23 | pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 24 | 24 | const ip = &zcu.intern_pool; |
| 25 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 25 | assert(ty.hasRuntimeBits(zcu)); | |
| 26 | 26 | switch (ty.zigTypeTag(zcu)) { |
| 27 | 27 | .int, .@"enum", .error_set => return .{ .direct = ty }, |
| 28 | 28 | .float => return .{ .direct = ty }, |
| ... | ... | @@ -47,7 +47,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 47 | 47 | return .indirect; |
| 48 | 48 | } |
| 49 | 49 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]); |
| 50 | const explicit_align = struct_type.fieldAlign(ip, 0); | |
| 50 | const explicit_align = struct_type.field_aligns.getOrNone(ip, 0); | |
| 51 | 51 | if (explicit_align != .none) { |
| 52 | 52 | if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) |
| 53 | 53 | return .indirect; |
| ... | ... | @@ -56,7 +56,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 56 | 56 | }, |
| 57 | 57 | .@"union" => { |
| 58 | 58 | const union_obj = zcu.typeToUnion(ty).?; |
| 59 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | |
| 59 | if (union_obj.layout == .@"packed") { | |
| 60 | 60 | return .{ .direct = ty }; |
| 61 | 61 | } |
| 62 | 62 | const layout = ty.unionGetLayout(zcu); |
src/codegen/x86_64/CodeGen.zig+80-86| ... | ... | @@ -43261,7 +43261,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43261 | 43261 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 43262 | 43262 | try ops[0].toSlicePtr(cg); |
| 43263 | 43263 | var res: [1]Temp = undefined; |
| 43264 | if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ | |
| 43264 | if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBits(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ | |
| 43265 | 43265 | .patterns = &.{ |
| 43266 | 43266 | .{ .src = .{ .to_gpr, .simm32, .none } }, |
| 43267 | 43267 | }, |
| ... | ... | @@ -43375,7 +43375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43375 | 43375 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 43376 | 43376 | try ops[0].toSlicePtr(cg); |
| 43377 | 43377 | var res: [1]Temp = undefined; |
| 43378 | if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ | |
| 43378 | if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBits(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ | |
| 43379 | 43379 | .patterns = &.{ |
| 43380 | 43380 | .{ .src = .{ .to_gpr, .simm32, .none } }, |
| 43381 | 43381 | }, |
| ... | ... | @@ -103699,7 +103699,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 103699 | 103699 | .optional_payload => { |
| 103700 | 103700 | const ty_op = air_datas[@intFromEnum(inst)].ty_op; |
| 103701 | 103701 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 103702 | const pl = if (!hack_around_sema_opv_bugs or ty_op.ty.toType().hasRuntimeBitsIgnoreComptime(zcu)) | |
| 103702 | const pl = if (!hack_around_sema_opv_bugs or ty_op.ty.toType().hasRuntimeBits(zcu)) | |
| 103703 | 103703 | try ops[0].read(ty_op.ty.toType(), .{}, cg) |
| 103704 | 103704 | else |
| 103705 | 103705 | try cg.tempInit(ty_op.ty.toType(), .none); |
| ... | ... | @@ -103745,7 +103745,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 103745 | 103745 | const eu_pl_ty = ty_op.ty.toType(); |
| 103746 | 103746 | const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu)); |
| 103747 | 103747 | var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); |
| 103748 | const pl = if (!hack_around_sema_opv_bugs or eu_pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 103748 | const pl = if (!hack_around_sema_opv_bugs or eu_pl_ty.hasRuntimeBits(zcu)) | |
| 103749 | 103749 | try ops[0].read(eu_pl_ty, .{ .disp = eu_pl_off }, cg) |
| 103750 | 103750 | else |
| 103751 | 103751 | try cg.tempInit(eu_pl_ty, .none); |
| ... | ... | @@ -103864,7 +103864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 103864 | 103864 | .@"packed" => unreachable, |
| 103865 | 103865 | }; |
| 103866 | 103866 | var ops = try cg.tempsFromOperands(inst, .{struct_field.struct_operand}); |
| 103867 | var res = if (!hack_around_sema_opv_bugs or field_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 103867 | var res = if (!hack_around_sema_opv_bugs or field_ty.hasRuntimeBits(zcu)) | |
| 103868 | 103868 | try ops[0].read(field_ty, .{ .disp = field_off }, cg) |
| 103869 | 103869 | else |
| 103870 | 103870 | try cg.tempInit(field_ty, .none); |
| ... | ... | @@ -103926,7 +103926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 103926 | 103926 | .array_elem_val, .legalize_vec_elem_val => { |
| 103927 | 103927 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 103928 | 103928 | const array_ty = cg.typeOf(bin_op.lhs); |
| 103929 | const res_ty = array_ty.elemType2(zcu); | |
| 103929 | const res_ty = array_ty.childType(zcu); | |
| 103930 | 103930 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 103931 | 103931 | var res: [1]Temp = undefined; |
| 103932 | 103932 | cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ |
| ... | ... | @@ -104121,11 +104121,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 104121 | 104121 | }, |
| 104122 | 104122 | .slice_elem_val, .ptr_elem_val => { |
| 104123 | 104123 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 104124 | const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu); | |
| 104124 | const res_ty = cg.typeOf(bin_op.lhs).indexableElem(zcu); | |
| 104125 | 104125 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 104126 | 104126 | try ops[0].toSlicePtr(cg); |
| 104127 | 104127 | var res: [1]Temp = undefined; |
| 104128 | if (!hack_around_sema_opv_bugs or res_ty.hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ | |
| 104128 | if (!hack_around_sema_opv_bugs or res_ty.hasRuntimeBits(zcu)) cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ | |
| 104129 | 104129 | .dst_constraints = .{ .{ .int = .byte }, .any }, |
| 104130 | 104130 | .patterns = &.{ |
| 104131 | 104131 | .{ .src = .{ .to_gpr, .simm32, .none } }, |
| ... | ... | @@ -171422,10 +171422,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 171422 | 171422 | .auto, .@"extern" => { |
| 171423 | 171423 | for (elems, 0..) |elem_ref, field_index| { |
| 171424 | 171424 | const elem_dies = bt.feed(); |
| 171425 | if (loaded_struct.fieldIsComptime(ip, field_index)) continue; | |
| 171426 | if (!hack_around_sema_opv_bugs or Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]).hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 171425 | if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; | |
| 171426 | if (!hack_around_sema_opv_bugs or Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]).hasRuntimeBits(zcu)) { | |
| 171427 | 171427 | var elem = try cg.tempFromOperand(elem_ref, elem_dies); |
| 171428 | try res.write(&elem, .{ .disp = @intCast(loaded_struct.offsets.get(ip)[field_index]) }, cg); | |
| 171428 | try res.write(&elem, .{ .disp = @intCast(loaded_struct.field_offsets.get(ip)[field_index]) }, cg); | |
| 171429 | 171429 | try elem.die(cg); |
| 171430 | 171430 | try cg.resetTemps(reset_index); |
| 171431 | 171431 | } |
| ... | ... | @@ -171441,7 +171441,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 171441 | 171441 | const elem_dies = bt.feed(); |
| 171442 | 171442 | if (tuple_type.values.get(ip)[field_index] != .none) continue; |
| 171443 | 171443 | const field_type = Type.fromInterned(tuple_type.types.get(ip)[field_index]); |
| 171444 | if (!hack_around_sema_opv_bugs or field_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 171444 | if (!hack_around_sema_opv_bugs or field_type.hasRuntimeBits(zcu)) { | |
| 171445 | 171445 | elem_disp = @intCast(field_type.abiAlignment(zcu).forward(elem_disp)); |
| 171446 | 171446 | var elem = try cg.tempFromOperand(elem_ref, elem_dies); |
| 171447 | 171447 | try res.write(&elem, .{ .disp = elem_disp }, cg); |
| ... | ... | @@ -171467,7 +171467,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 171467 | 171467 | const union_layout = union_ty.unionGetLayout(zcu); |
| 171468 | 171468 | if (union_layout.tag_size > 0) { |
| 171469 | 171469 | var tag_temp = try cg.tempFromValue(try pt.enumValueFieldIndex( |
| 171470 | union_ty.unionTagTypeSafety(zcu).?, | |
| 171470 | union_ty.unionTagTypeRuntime(zcu).?, | |
| 171471 | 171471 | union_init.field_index, |
| 171472 | 171472 | )); |
| 171473 | 171473 | try res.write(&tag_temp, .{ |
| ... | ... | @@ -173756,7 +173756,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 173756 | 173756 | |
| 173757 | 173757 | var data_off: i32 = 0; |
| 173758 | 173758 | const reset_index = cg.next_temp_index; |
| 173759 | const tag_names = ip.loadEnumType(lazy_sym.ty).names; | |
| 173759 | const tag_names = ip.loadEnumType(lazy_sym.ty).field_names; | |
| 173760 | 173760 | for (0..tag_names.len) |tag_index| { |
| 173761 | 173761 | var enum_temp = try cg.tempInit(enum_ty, if (enum_ty.abiSize(zcu) <= @as(u4, switch (cg.target.cpu.arch) { |
| 173762 | 173762 | else => unreachable, |
| ... | ... | @@ -174334,7 +174334,7 @@ fn genUnwrapErrUnionPayloadMir( |
| 174334 | 174334 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 174335 | 174335 | |
| 174336 | 174336 | const result: MCValue = result: { |
| 174337 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; | |
| 174337 | if (!payload_ty.hasRuntimeBits(zcu)) break :result .none; | |
| 174338 | 174338 | |
| 174339 | 174339 | const payload_off: u31 = @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu)); |
| 174340 | 174340 | switch (err_union) { |
| ... | ... | @@ -174450,7 +174450,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 174450 | 174450 | const pt = self.pt; |
| 174451 | 174451 | const zcu = pt.zcu; |
| 174452 | 174452 | const dst_ty = ptr_ty.childType(zcu); |
| 174453 | if (!dst_ty.hasRuntimeBitsIgnoreComptime(zcu)) return; | |
| 174453 | if (!dst_ty.hasRuntimeBits(zcu)) return; | |
| 174454 | 174454 | switch (ptr_mcv) { |
| 174455 | 174455 | .none, |
| 174456 | 174456 | .unreach, |
| ... | ... | @@ -174503,7 +174503,7 @@ fn store( |
| 174503 | 174503 | const pt = self.pt; |
| 174504 | 174504 | const zcu = pt.zcu; |
| 174505 | 174505 | const src_ty = ptr_ty.childType(zcu); |
| 174506 | if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) return; | |
| 174506 | if (!src_ty.hasRuntimeBits(zcu)) return; | |
| 174507 | 174507 | switch (ptr_mcv) { |
| 174508 | 174508 | .none, |
| 174509 | 174509 | .unreach, |
| ... | ... | @@ -176615,7 +176615,7 @@ fn lowerSwitchBr( |
| 176615 | 176615 | break :condition_index condition_index; |
| 176616 | 176616 | }; |
| 176617 | 176617 | try cg.spillEflagsIfOccupied(); |
| 176618 | if (min.?.orderAgainstZero(zcu).compare(.neq)) try cg.genBinOpMir( | |
| 176618 | if (Value.compareHetero(min.?, .neq, .zero_comptime_int, zcu)) try cg.genBinOpMir( | |
| 176619 | 176619 | .{ ._, .sub }, |
| 176620 | 176620 | condition_ty, |
| 176621 | 176621 | condition_index, |
| ... | ... | @@ -176957,7 +176957,7 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 176957 | 176957 | const unsigned_condition_ty = try self.pt.intType(.unsigned, self.intInfo(condition_ty).?.bits); |
| 176958 | 176958 | const condition_mcv = block_tracking.short; |
| 176959 | 176959 | try self.spillEflagsIfOccupied(); |
| 176960 | if (table.min.orderAgainstZero(self.pt.zcu).compare(.neq)) try self.genBinOpMir( | |
| 176960 | if (Value.compareHetero(table.min, .neq, .zero_comptime_int, self.pt.zcu)) try self.genBinOpMir( | |
| 176961 | 176961 | .{ ._, .sub }, |
| 176962 | 176962 | condition_ty, |
| 176963 | 176963 | condition_mcv, |
| ... | ... | @@ -177054,8 +177054,7 @@ fn airBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177054 | 177054 | const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 177055 | 177055 | |
| 177056 | 177056 | const block_ty = self.typeOfIndex(br.block_inst); |
| 177057 | const block_unused = | |
| 177058 | !block_ty.hasRuntimeBitsIgnoreComptime(zcu) or self.liveness.isUnused(br.block_inst); | |
| 177057 | const block_unused = !block_ty.hasRuntimeBits(zcu) or self.liveness.isUnused(br.block_inst); | |
| 177059 | 177058 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; |
| 177060 | 177059 | const block_data = self.blocks.getPtr(br.block_inst).?; |
| 177061 | 177060 | const first_br = block_data.relocs.items.len == 0; |
| ... | ... | @@ -177295,41 +177294,38 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177295 | 177294 | } |
| 177296 | 177295 | |
| 177297 | 177296 | const ip = &zcu.intern_pool; |
| 177298 | const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; | |
| 177299 | const struct_type: Type = .fromInterned(aggregate.ty); | |
| 177300 | switch (aggregate.storage) { | |
| 177301 | .elems => |elems| for (elems, 0..) |elem, i| switch (elem) { | |
| 177302 | .bool_true => { | |
| 177303 | const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 177304 | assert(clobber.len != 0); | |
| 177305 | ||
| 177306 | if (std.mem.eql(u8, clobber, "memory") or | |
| 177307 | std.mem.eql(u8, clobber, "fpsr") or | |
| 177308 | std.mem.eql(u8, clobber, "fpcr") or | |
| 177309 | std.mem.eql(u8, clobber, "mxcsr") or | |
| 177310 | std.mem.eql(u8, clobber, "dirflag")) | |
| 177311 | { | |
| 177312 | // ok, sure | |
| 177313 | } else if (std.mem.eql(u8, clobber, "cc") or | |
| 177314 | std.mem.eql(u8, clobber, "flags") or | |
| 177315 | std.mem.eql(u8, clobber, "eflags") or | |
| 177316 | std.mem.eql(u8, clobber, "rflags")) | |
| 177317 | { | |
| 177318 | try self.spillEflagsIfOccupied(); | |
| 177319 | } else { | |
| 177320 | try self.register_manager.getReg(parseRegName(clobber) orelse | |
| 177321 | return self.fail("invalid clobber: '{s}'", .{clobber}), null); | |
| 177322 | } | |
| 177323 | }, | |
| 177324 | .bool_false => continue, | |
| 177325 | else => unreachable, | |
| 177326 | }, | |
| 177327 | .repeated_elem => |elem| switch (elem) { | |
| 177328 | .bool_true => @panic("TODO"), | |
| 177329 | .bool_false => {}, | |
| 177330 | else => unreachable, | |
| 177331 | }, | |
| 177332 | .bytes => @panic("TODO"), | |
| 177297 | const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); | |
| 177298 | const clobbers_ty = clobbers_val.typeOf(zcu); | |
| 177299 | var clobbers_bigint_buf: Value.BigIntSpace = undefined; | |
| 177300 | const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); | |
| 177301 | for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { | |
| 177302 | assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); | |
| 177303 | const limb_bits = @bitSizeOf(std.math.big.Limb); | |
| 177304 | if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false | |
| 177305 | switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { | |
| 177306 | 0 => continue, // field is false | |
| 177307 | 1 => {}, // field is true | |
| 177308 | } | |
| 177309 | const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; | |
| 177310 | assert(clobber.len != 0); | |
| 177311 | ||
| 177312 | if (std.mem.eql(u8, clobber, "memory") or | |
| 177313 | std.mem.eql(u8, clobber, "fpsr") or | |
| 177314 | std.mem.eql(u8, clobber, "fpcr") or | |
| 177315 | std.mem.eql(u8, clobber, "mxcsr") or | |
| 177316 | std.mem.eql(u8, clobber, "dirflag")) | |
| 177317 | { | |
| 177318 | // ok, sure | |
| 177319 | } else if (std.mem.eql(u8, clobber, "cc") or | |
| 177320 | std.mem.eql(u8, clobber, "flags") or | |
| 177321 | std.mem.eql(u8, clobber, "eflags") or | |
| 177322 | std.mem.eql(u8, clobber, "rflags")) | |
| 177323 | { | |
| 177324 | try self.spillEflagsIfOccupied(); | |
| 177325 | } else { | |
| 177326 | try self.register_manager.getReg(parseRegName(clobber) orelse | |
| 177327 | return self.fail("invalid clobber: '{s}'", .{clobber}), null); | |
| 177328 | } | |
| 177333 | 177329 | } |
| 177334 | 177330 | |
| 177335 | 177331 | const Label = struct { |
| ... | ... | @@ -180986,7 +180982,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue { |
| 180986 | 180982 | const ty = self.typeOf(ref); |
| 180987 | 180983 | |
| 180988 | 180984 | // If the type has no codegen bits, no need to store it. |
| 180989 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; | |
| 180985 | if (!ty.hasRuntimeBits(zcu)) return .none; | |
| 180990 | 180986 | |
| 180991 | 180987 | const mcv: MCValue = if (ref.toIndex()) |inst| mcv: { |
| 180992 | 180988 | break :mcv self.inst_tracking.getPtr(inst).?.short; |
| ... | ... | @@ -181105,7 +181101,7 @@ fn resolveCallingConventionValues( |
| 181105 | 181101 | // Return values |
| 181106 | 181102 | if (ret_ty.isNoReturn(zcu)) { |
| 181107 | 181103 | result.return_value = .init(.unreach); |
| 181108 | } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 181104 | } else if (!ret_ty.hasRuntimeBits(zcu)) { | |
| 181109 | 181105 | // TODO: is this even possible for C calling convention? |
| 181110 | 181106 | result.return_value = .init(.none); |
| 181111 | 181107 | } else { |
| ... | ... | @@ -181115,7 +181111,7 @@ fn resolveCallingConventionValues( |
| 181115 | 181111 | var ret_sse = abi.getCAbiSseReturnRegs(cc); |
| 181116 | 181112 | var ret_x87 = abi.getCAbiX87ReturnRegs(cc); |
| 181117 | 181113 | |
| 181118 | const classes = switch (cc) { | |
| 181114 | const classes: []const abi.Class = switch (cc) { | |
| 181119 | 181115 | .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, cg.target, .ret), .none), |
| 181120 | 181116 | .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu, cg.target, .ret)}, |
| 181121 | 181117 | else => unreachable, |
| ... | ... | @@ -181182,7 +181178,7 @@ fn resolveCallingConventionValues( |
| 181182 | 181178 | |
| 181183 | 181179 | // Input params |
| 181184 | 181180 | params: for (param_types, result.args) |ty, *arg| { |
| 181185 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | |
| 181181 | assert(ty.hasRuntimeBits(zcu)); | |
| 181186 | 181182 | result.air_arg_count += 1; |
| 181187 | 181183 | switch (cc) { |
| 181188 | 181184 | .x86_64_sysv => {}, |
| ... | ... | @@ -181327,7 +181323,7 @@ fn resolveCallingConventionValues( |
| 181327 | 181323 | // Return values |
| 181328 | 181324 | result.return_value = if (ret_ty.isNoReturn(zcu)) |
| 181329 | 181325 | .init(.unreach) |
| 181330 | else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) | |
| 181326 | else if (!ret_ty.hasRuntimeBits(zcu)) | |
| 181331 | 181327 | .init(.none) |
| 181332 | 181328 | else return_value: { |
| 181333 | 181329 | const ret_gpr = abi.getCAbiIntReturnRegs(cc); |
| ... | ... | @@ -181357,7 +181353,7 @@ fn resolveCallingConventionValues( |
| 181357 | 181353 | |
| 181358 | 181354 | // Input params |
| 181359 | 181355 | for (param_types, result.args) |param_ty, *arg| { |
| 181360 | if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 181356 | if (!param_ty.hasRuntimeBits(zcu)) { | |
| 181361 | 181357 | arg.* = .none; |
| 181362 | 181358 | continue; |
| 181363 | 181359 | } |
| ... | ... | @@ -181721,7 +181717,7 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.builtin.Type.Int { |
| 181721 | 181717 | .one, .many, .c => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, |
| 181722 | 181718 | .slice => null, |
| 181723 | 181719 | }, |
| 181724 | .opt_type => |opt_child| return if (!Type.fromInterned(opt_child).hasRuntimeBitsIgnoreComptime(zcu)) | |
| 181720 | .opt_type => |opt_child| return if (!Type.fromInterned(opt_child).hasRuntimeBits(zcu)) | |
| 181725 | 181721 | .{ .signedness = .unsigned, .bits = 1 } |
| 181726 | 181722 | else switch (ip.indexToKey(opt_child)) { |
| 181727 | 181723 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| ... | ... | @@ -181734,7 +181730,7 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.builtin.Type.Int { |
| 181734 | 181730 | else => null, |
| 181735 | 181731 | }, |
| 181736 | 181732 | .error_union_type => |error_union_type| return if (!Type.fromInterned(error_union_type.payload_type) |
| 181737 | .hasRuntimeBitsIgnoreComptime(zcu)) .{ .signedness = .unsigned, .bits = zcu.errorSetBits() } else null, | |
| 181733 | .hasRuntimeBits(zcu)) .{ .signedness = .unsigned, .bits = zcu.errorSetBits() } else null, | |
| 181738 | 181734 | .simple_type => |simple_type| return switch (simple_type) { |
| 181739 | 181735 | .bool => .{ .signedness = .unsigned, .bits = 1 }, |
| 181740 | 181736 | .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, |
| ... | ... | @@ -181767,14 +181763,17 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.builtin.Type.Int { |
| 181767 | 181763 | const loaded_struct = ip.loadStructType(ty_index); |
| 181768 | 181764 | switch (loaded_struct.layout) { |
| 181769 | 181765 | .auto, .@"extern" => return null, |
| 181770 | .@"packed" => ty_index = loaded_struct.backingIntTypeUnordered(ip), | |
| 181766 | .@"packed" => ty_index = loaded_struct.packed_backing_int_type, | |
| 181771 | 181767 | } |
| 181772 | 181768 | }, |
| 181773 | .union_type => return switch (ip.loadUnionType(ty_index).flagsUnordered(ip).layout) { | |
| 181774 | .auto, .@"extern" => null, | |
| 181775 | .@"packed" => .{ .signedness = .unsigned, .bits = @intCast(ty.bitSize(zcu)) }, | |
| 181769 | .union_type => { | |
| 181770 | const loaded_union = ip.loadUnionType(ty_index); | |
| 181771 | switch (loaded_union.layout) { | |
| 181772 | .auto, .@"extern" => return null, | |
| 181773 | .@"packed" => ty_index = loaded_union.packed_backing_int_type, | |
| 181774 | } | |
| 181776 | 181775 | }, |
| 181777 | .enum_type => ty_index = ip.loadEnumType(ty_index).tag_ty, | |
| 181776 | .enum_type => ty_index = ip.loadEnumType(ty_index).int_tag_type, | |
| 181778 | 181777 | .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, |
| 181779 | 181778 | else => return null, |
| 181780 | 181779 | }; |
| ... | ... | @@ -187919,7 +187918,6 @@ const Select = struct { |
| 187919 | 187918 | unsigned_int: Memory.Size, |
| 187920 | 187919 | elem_size_is: u8, |
| 187921 | 187920 | po2_elem_size, |
| 187922 | elem_int: Memory.Size, | |
| 187923 | 187921 | |
| 187924 | 187922 | const OfIsSizes = struct { of: Memory.Size, is: Memory.Size }; |
| 187925 | 187923 | |
| ... | ... | @@ -188178,12 +188176,8 @@ const Select = struct { |
| 188178 | 188176 | .signed => false, |
| 188179 | 188177 | .unsigned => size.bitSize(cg.target) >= int_info.bits, |
| 188180 | 188178 | } else false, |
| 188181 | .elem_size_is => |size| size == ty.elemType2(zcu).abiSize(zcu), | |
| 188182 | .po2_elem_size => std.math.isPowerOfTwo(ty.elemType2(zcu).abiSize(zcu)), | |
| 188183 | .elem_int => |size| if (cg.intInfo(ty.elemType2(zcu))) |elem_int_info| | |
| 188184 | size.bitSize(cg.target) >= elem_int_info.bits | |
| 188185 | else | |
| 188186 | false, | |
| 188179 | .elem_size_is => |size| size == ty.indexableElem(zcu).abiSize(zcu), | |
| 188180 | .po2_elem_size => std.math.isPowerOfTwo(ty.indexableElem(zcu).abiSize(zcu)), | |
| 188187 | 188181 | }; |
| 188188 | 188182 | } |
| 188189 | 188183 | }; |
| ... | ... | @@ -189918,20 +189912,20 @@ const Select = struct { |
| 189918 | 189912 | .dst0_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).abiSize(s.cg.pt.zcu)), |
| 189919 | 189913 | .delta_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).abiSize(s.cg.pt.zcu))) - |
| 189920 | 189914 | @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).abiSize(s.cg.pt.zcu)))), |
| 189921 | .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) - | |
| 189922 | @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)))), | |
| 189915 | .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) - | |
| 189916 | @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)))), | |
| 189923 | 189917 | .unaligned_size => @intCast(s.cg.unalignedSize(op.flags.base.ref.typeOf(s))), |
| 189924 | 189918 | .unaligned_size_add_elem_size => { |
| 189925 | 189919 | const ty = op.flags.base.ref.typeOf(s); |
| 189926 | break :lhs @intCast(s.cg.unalignedSize(ty) + ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); | |
| 189920 | break :lhs @intCast(s.cg.unalignedSize(ty) + ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); | |
| 189927 | 189921 | }, |
| 189928 | 189922 | .unaligned_size_sub_elem_size => { |
| 189929 | 189923 | const ty = op.flags.base.ref.typeOf(s); |
| 189930 | break :lhs @intCast(s.cg.unalignedSize(ty) - ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); | |
| 189924 | break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); | |
| 189931 | 189925 | }, |
| 189932 | 189926 | .unaligned_size_sub_2_elem_size => { |
| 189933 | 189927 | const ty = op.flags.base.ref.typeOf(s); |
| 189934 | break :lhs @intCast(s.cg.unalignedSize(ty) - ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2); | |
| 189928 | break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2); | |
| 189935 | 189929 | }, |
| 189936 | 189930 | .bit_size => @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s))), |
| 189937 | 189931 | .src0_bit_size => @intCast(s.cg.nonBoolScalarBitSize(Select.Operand.Ref.src0.typeOf(s))), |
| ... | ... | @@ -189944,10 +189938,10 @@ const Select = struct { |
| 189944 | 189938 | op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu), |
| 189945 | 189939 | @divExact(op.flags.base.size.bitSize(s.cg.target), 8), |
| 189946 | 189940 | )), |
| 189947 | .elem_size => @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), | |
| 189948 | .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), | |
| 189949 | .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), | |
| 189950 | .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * | |
| 189941 | .elem_size => @intCast(op.flags.base.ref.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), | |
| 189942 | .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), | |
| 189943 | .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), | |
| 189944 | .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * | |
| 189951 | 189945 | Select.Operand.Ref.src1.valueOf(s).immediate), |
| 189952 | 189946 | .vector_index => switch (op.flags.base.ref.typeOf(s).ptrInfo(s.cg.pt.zcu).flags.vector_index) { |
| 189953 | 189947 | .none => unreachable, |
| ... | ... | @@ -189956,7 +189950,7 @@ const Select = struct { |
| 189956 | 189950 | .src1 => @intCast(Select.Operand.Ref.src1.valueOf(s).immediate), |
| 189957 | 189951 | .src1_sub_bit_size => @as(SignedImm, @intCast(Select.Operand.Ref.src1.valueOf(s).immediate)) - |
| 189958 | 189952 | @as(SignedImm, @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s)))), |
| 189959 | .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), | |
| 189953 | .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), | |
| 189960 | 189954 | .elem_mask => @as(u8, std.math.maxInt(u8)) >> @intCast( |
| 189961 | 189955 | 8 - ((s.cg.unalignedSize(op.flags.base.ref.typeOf(s)) - 1) % |
| 189962 | 189956 | @divExact(op.flags.base.size.bitSize(s.cg.target), 8) + 1 >> |
src/codegen/x86_64/abi.zig+6-6| ... | ... | @@ -339,7 +339,7 @@ fn classifySystemVStruct( |
| 339 | 339 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 340 | 340 | while (field_it.next()) |field_index| { |
| 341 | 341 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 342 | const field_align = loaded_struct.fieldAlign(ip, field_index); | |
| 342 | const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index); | |
| 343 | 343 | byte_offset = std.mem.alignForward( |
| 344 | 344 | u64, |
| 345 | 345 | byte_offset, |
| ... | ... | @@ -355,7 +355,7 @@ fn classifySystemVStruct( |
| 355 | 355 | .@"packed" => {}, |
| 356 | 356 | } |
| 357 | 357 | } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| { |
| 358 | switch (field_loaded_union.flagsUnordered(ip).layout) { | |
| 358 | switch (field_loaded_union.layout) { | |
| 359 | 359 | .auto => unreachable, |
| 360 | 360 | .@"extern" => { |
| 361 | 361 | byte_offset = classifySystemVUnion(result, byte_offset, field_loaded_union, zcu, target); |
| ... | ... | @@ -369,11 +369,11 @@ fn classifySystemVStruct( |
| 369 | 369 | result_class.* = result_class.combineSystemV(field_class); |
| 370 | 370 | byte_offset += field_ty.abiSize(zcu); |
| 371 | 371 | } |
| 372 | const final_byte_offset = starting_byte_offset + loaded_struct.sizeUnordered(ip); | |
| 372 | const final_byte_offset = starting_byte_offset + loaded_struct.size; | |
| 373 | 373 | std.debug.assert(final_byte_offset == std.mem.alignForward( |
| 374 | 374 | u64, |
| 375 | 375 | byte_offset, |
| 376 | loaded_struct.flagsUnordered(ip).alignment.toByteUnits().?, | |
| 376 | loaded_struct.alignment.toByteUnits().?, | |
| 377 | 377 | )); |
| 378 | 378 | return final_byte_offset; |
| 379 | 379 | } |
| ... | ... | @@ -398,7 +398,7 @@ fn classifySystemVUnion( |
| 398 | 398 | .@"packed" => {}, |
| 399 | 399 | } |
| 400 | 400 | } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| { |
| 401 | switch (field_loaded_union.flagsUnordered(ip).layout) { | |
| 401 | switch (field_loaded_union.layout) { | |
| 402 | 402 | .auto => unreachable, |
| 403 | 403 | .@"extern" => { |
| 404 | 404 | _ = classifySystemVUnion(result, starting_byte_offset, field_loaded_union, zcu, target); |
| ... | ... | @@ -411,7 +411,7 @@ fn classifySystemVUnion( |
| 411 | 411 | for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| |
| 412 | 412 | result_class.* = result_class.combineSystemV(field_class); |
| 413 | 413 | } |
| 414 | return starting_byte_offset + loaded_union.sizeUnordered(ip); | |
| 414 | return starting_byte_offset + loaded_union.size; | |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | 417 | pub const zigcc = struct { |
src/link.zig+40-13| ... | ... | @@ -29,6 +29,7 @@ const codegen = @import("codegen.zig"); |
| 29 | 29 | pub const aarch64 = @import("link/aarch64.zig"); |
| 30 | 30 | pub const LdScript = @import("link/LdScript.zig"); |
| 31 | 31 | pub const Queue = @import("link/Queue.zig"); |
| 32 | pub const ConstPool = @import("link/ConstPool.zig"); | |
| 32 | 33 | |
| 33 | 34 | pub const Diags = struct { |
| 34 | 35 | /// Stored here so that function definitions can distinguish between |
| ... | ... | @@ -798,14 +799,27 @@ pub const File = struct { |
| 798 | 799 | }; |
| 799 | 800 | |
| 800 | 801 | /// Never called when LLVM is codegenning the ZCU. |
| 801 | fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void { | |
| 802 | fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) UpdateContainerTypeError!void { | |
| 803 | assert(base.comp.zcu.?.llvm_object == null); | |
| 804 | switch (base.tag) { | |
| 805 | .lld => unreachable, | |
| 806 | else => {}, | |
| 807 | inline .elf, .c => |tag| { | |
| 808 | dev.check(tag.devFeature()); | |
| 809 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty, success); | |
| 810 | }, | |
| 811 | } | |
| 812 | } | |
| 813 | ||
| 814 | /// Never called when LLVM is codegenning the ZCU. | |
| 815 | fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void { | |
| 802 | 816 | assert(base.comp.zcu.?.llvm_object == null); |
| 803 | 817 | switch (base.tag) { |
| 804 | 818 | .lld => unreachable, |
| 805 | 819 | else => {}, |
| 806 | 820 | inline .elf => |tag| { |
| 807 | 821 | dev.check(tag.devFeature()); |
| 808 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty); | |
| 822 | return @as(*tag.Type(), @fieldParentPtr("base", base)).clearContainerType(pt, ty); | |
| 809 | 823 | }, |
| 810 | 824 | } |
| 811 | 825 | } |
| ... | ... | @@ -1375,8 +1389,14 @@ pub const ZcuTask = union(enum) { |
| 1375 | 1389 | link_nav: InternPool.Nav.Index, |
| 1376 | 1390 | /// Write the machine code for a function to the output file. |
| 1377 | 1391 | link_func: Zcu.CodegenTaskPool.Index, |
| 1378 | link_type: InternPool.Index, | |
| 1379 | update_line_number: InternPool.TrackedInst.Index, | |
| 1392 | /// This struct/union/enum type has finished type resolution (successfully or otherwise), so the | |
| 1393 | /// linker can now lower debug information for this type (and any structural types which depend | |
| 1394 | /// on it, such as `?T`, `struct { T }`, `[2]T`, etc). | |
| 1395 | debug_update_container_type: struct { | |
| 1396 | ty: InternPool.Index, | |
| 1397 | success: bool, | |
| 1398 | }, | |
| 1399 | debug_update_line_number: InternPool.TrackedInst.Index, | |
| 1380 | 1400 | }; |
| 1381 | 1401 | |
| 1382 | 1402 | pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| ... | ... | @@ -1537,7 +1557,10 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1537 | 1557 | .link_func => |codegen_task| nav: { |
| 1538 | 1558 | timer.pause(io); |
| 1539 | 1559 | const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) { |
| 1540 | error.Canceled, error.AlreadyReported => return, | |
| 1560 | error.Canceled, error.AlreadyReported => { | |
| 1561 | comp.link_prog_node.completeOne(); | |
| 1562 | return; | |
| 1563 | }, | |
| 1541 | 1564 | }; |
| 1542 | 1565 | defer mir.deinit(zcu); |
| 1543 | 1566 | timer.@"resume"(io); |
| ... | ... | @@ -1563,21 +1586,25 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void |
| 1563 | 1586 | } |
| 1564 | 1587 | break :nav ip.indexToKey(func).func.owner_nav; |
| 1565 | 1588 | }, |
| 1566 | .link_type => |ty| nav: { | |
| 1567 | const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip); | |
| 1568 | const nav_prog_node = comp.link_prog_node.start(name, 0); | |
| 1569 | defer nav_prog_node.end(); | |
| 1570 | if (zcu.llvm_object == null) { | |
| 1589 | .debug_update_container_type => |container_update| nav: { | |
| 1590 | const name = Type.fromInterned(container_update.ty).containerTypeName(ip).toSlice(ip); | |
| 1591 | const ty_prog_node = comp.link_prog_node.start(name, 0); | |
| 1592 | defer ty_prog_node.end(); | |
| 1593 | if (zcu.llvm_object) |llvm_object| { | |
| 1594 | llvm_object.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { | |
| 1595 | error.OutOfMemory => diags.setAllocFailure(), | |
| 1596 | }; | |
| 1597 | } else { | |
| 1571 | 1598 | if (comp.bin_file) |lf| { |
| 1572 | lf.updateContainerType(pt, ty) catch |err| switch (err) { | |
| 1599 | lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { | |
| 1573 | 1600 | error.OutOfMemory => diags.setAllocFailure(), |
| 1574 | error.TypeFailureReported => assert(zcu.failed_types.contains(ty)), | |
| 1601 | error.TypeFailureReported => assert(zcu.failed_types.contains(container_update.ty)), | |
| 1575 | 1602 | }; |
| 1576 | 1603 | } |
| 1577 | 1604 | } |
| 1578 | 1605 | break :nav null; |
| 1579 | 1606 | }, |
| 1580 | .update_line_number => |ti| nav: { | |
| 1607 | .debug_update_line_number => |ti| nav: { | |
| 1581 | 1608 | const nav_prog_node = comp.link_prog_node.start("Update line number", 0); |
| 1582 | 1609 | defer nav_prog_node.end(); |
| 1583 | 1610 | if (pt.zcu.llvm_object == null) { |
src/link/C.zig+1272-627| ... | ... | @@ -1,3 +1,9 @@ |
| 1 | /// Unlike other linker implementations, `link.C` does not attempt to incrementally link its output, | |
| 2 | /// because C has many language rules which make that impractical. Instead, we individually generate | |
| 3 | /// each declaration (NAV), and the output is stitched together (alongside types and UAVs) in an | |
| 4 | /// appropriate order in `flush`. | |
| 5 | const C = @This(); | |
| 6 | ||
| 1 | 7 | const std = @import("std"); |
| 2 | 8 | const mem = std.mem; |
| 3 | 9 | const assert = std.debug.assert; |
| ... | ... | @@ -5,7 +11,6 @@ const Allocator = std.mem.Allocator; |
| 5 | 11 | const fs = std.fs; |
| 6 | 12 | const Path = std.Build.Cache.Path; |
| 7 | 13 | |
| 8 | const C = @This(); | |
| 9 | 14 | const build_options = @import("build_options"); |
| 10 | 15 | const Zcu = @import("../Zcu.zig"); |
| 11 | 16 | const Module = @import("../Package/Module.zig"); |
| ... | ... | @@ -19,40 +24,45 @@ const Type = @import("../Type.zig"); |
| 19 | 24 | const Value = @import("../Value.zig"); |
| 20 | 25 | const AnyMir = @import("../codegen.zig").AnyMir; |
| 21 | 26 | |
| 22 | pub const zig_h = "#include \"zig.h\"\n"; | |
| 23 | ||
| 24 | 27 | base: link.File, |
| 25 | /// This linker backend does not try to incrementally link output C source code. | |
| 26 | /// Instead, it tracks all declarations in this table, and iterates over it | |
| 27 | /// in the flush function, stitching pre-rendered pieces of C code together. | |
| 28 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock), | |
| 29 | /// All the string bytes of rendered C code, all squished into one array. | |
| 30 | /// While in progress, a separate buffer is used, and then when finished, the | |
| 31 | /// buffer is copied into this one. | |
| 28 | ||
| 29 | /// All the string bytes of rendered C code, all squished into one array. `String` is used to refer | |
| 30 | /// to specific slices of this array, used for the rendered C code of an individual UAV/NAV/type. | |
| 31 | /// | |
| 32 | /// During code generation for functions, a separate buffer is used, and the contents of that buffer | |
| 33 | /// are copied into `string_bytes` when the function is emitted by `updateFunc`. | |
| 32 | 34 | string_bytes: std.ArrayList(u8), |
| 33 | /// Tracks all the anonymous decls that are used by all the decls so they can | |
| 34 | /// be rendered during flush(). | |
| 35 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock), | |
| 36 | /// Sparse set of uavs that are overaligned. Underaligned anon decls are | |
| 37 | /// lowered the same as ABI-aligned anon decls. The keys here are a subset of | |
| 38 | /// the keys of `uavs`. | |
| 39 | aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 40 | ||
| 41 | exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock), | |
| 42 | exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock), | |
| 43 | ||
| 44 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | |
| 45 | /// one with every call. | |
| 46 | fwd_decl_buf: []u8, | |
| 47 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | |
| 48 | /// one with every call. | |
| 49 | code_header_buf: []u8, | |
| 50 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | |
| 51 | /// one with every call. | |
| 52 | code_buf: []u8, | |
| 53 | /// Optimization, `flush` reuses this buffer rather than creating a new | |
| 54 | /// one with every call. | |
| 55 | scratch_buf: []u32, | |
| 35 | ||
| 36 | /// Like with `string_bytes`, we concatenate all type dependencies into one array, and slice into it | |
| 37 | /// for specific groups of dependencies. These values are indices into `type_pool`, and thus also | |
| 38 | /// into `types`. We store these instead of `InternPool.Index` because it lets us avoid some hash | |
| 39 | /// map lookups in `flush`. | |
| 40 | type_dependencies: std.ArrayList(link.ConstPool.Index), | |
| 41 | /// For storing dependencies on "aligned" versions of types, we must associate each type with a | |
| 42 | /// bitmask of required alignments. As with `type_dependencies`, we concatenate all such masks into | |
| 43 | /// one array. | |
| 44 | align_dependency_masks: std.ArrayList(u64), | |
| 45 | ||
| 46 | /// All NAVs, regardless of whether they are functions or simple constants, are put in this map. | |
| 47 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, RenderedDecl), | |
| 48 | /// All UAVs which may be referenced are in this map. The UAV alignment is not included in the | |
| 49 | /// rendered C code stored here, because we don't know the alignment a UAV needs until `flush`. | |
| 50 | uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, RenderedDecl), | |
| 51 | /// Contains all types which are needed by some other rendered code. Does not contain any constants | |
| 52 | /// other than types. | |
| 53 | type_pool: link.ConstPool, | |
| 54 | /// Indices are `link.ConstPool.Index` from `type_pool`. Contains rendered C code for every type | |
| 55 | /// which may be referenced. Logic in `flush` will perform the appropriate topological sort to emit | |
| 56 | /// these type definitions in an order which C allows. | |
| 57 | types: std.ArrayList(RenderedType), | |
| 58 | ||
| 59 | /// The set of big int types required by *any* generated code so far. These are always safe to emit, | |
| 60 | /// so they do not participate in the dependency graph traversal in `flush`. Therefore, redundant | |
| 61 | /// big-int types may be emitted under incremental compilation. | |
| 62 | bigint_types: std.AutoArrayHashMapUnmanaged(codegen.CType.BigInt, void), | |
| 63 | ||
| 64 | exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, String), | |
| 65 | exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, String), | |
| 56 | 66 | |
| 57 | 67 | /// A reference into `string_bytes`. |
| 58 | 68 | const String = extern struct { |
| ... | ... | @@ -64,50 +74,320 @@ const String = extern struct { |
| 64 | 74 | .len = 0, |
| 65 | 75 | }; |
| 66 | 76 | |
| 67 | fn concat(lhs: String, rhs: String) String { | |
| 68 | assert(lhs.start + lhs.len == rhs.start); | |
| 77 | fn get(s: String, c: *C) []const u8 { | |
| 78 | return c.string_bytes.items[s.start..][0..s.len]; | |
| 79 | } | |
| 80 | }; | |
| 81 | ||
| 82 | const CTypeDependencies = struct { | |
| 83 | len: u32, | |
| 84 | errunion_len: u32, | |
| 85 | fwd_len: u32, | |
| 86 | errunion_fwd_len: u32, | |
| 87 | aligned_fwd_len: u32, | |
| 88 | ||
| 89 | /// Index into `C.type_dependencies`. Starting at this index are: | |
| 90 | /// * `len` dependencies on complete types | |
| 91 | /// * `errunion_len` dependencies on complete error union types | |
| 92 | /// * `fwd_len` dependencies on forward-declared types | |
| 93 | /// * `errunion_fwd_len` dependencies on forward-declared error union types | |
| 94 | /// * `aligned_fwd_len` dependencies on aligned types | |
| 95 | type_start: u32, | |
| 96 | /// Index into `C.align_dependency_masks`. Starting at this index are `aligned_type_fwd_len` | |
| 97 | /// items containing the bitmasks for each aligned type (in `C.type_dependencies`). | |
| 98 | align_mask_start: u32, | |
| 99 | ||
| 100 | const Resolved = struct { | |
| 101 | type: []const link.ConstPool.Index, | |
| 102 | errunion_type: []const link.ConstPool.Index, | |
| 103 | type_fwd: []const link.ConstPool.Index, | |
| 104 | errunion_type_fwd: []const link.ConstPool.Index, | |
| 105 | aligned_type_fwd: []const link.ConstPool.Index, | |
| 106 | aligned_type_masks: []const u64, | |
| 107 | }; | |
| 108 | ||
| 109 | fn get(td: *const CTypeDependencies, c: *const C) Resolved { | |
| 110 | const types_overlong = c.type_dependencies.items[td.type_start..]; | |
| 69 | 111 | return .{ |
| 70 | .start = lhs.start, | |
| 71 | .len = lhs.len + rhs.len, | |
| 112 | .type = types_overlong[0..td.len], | |
| 113 | .errunion_type = types_overlong[td.len..][0..td.errunion_len], | |
| 114 | .type_fwd = types_overlong[td.len + td.errunion_len ..][0..td.fwd_len], | |
| 115 | .errunion_type_fwd = types_overlong[td.len + td.errunion_len + td.fwd_len ..][0..td.errunion_fwd_len], | |
| 116 | .aligned_type_fwd = types_overlong[td.len + td.errunion_len + td.fwd_len + td.errunion_fwd_len ..][0..td.aligned_fwd_len], | |
| 117 | .aligned_type_masks = c.align_dependency_masks.items[td.align_mask_start..][0..td.aligned_fwd_len], | |
| 72 | 118 | }; |
| 73 | 119 | } |
| 120 | ||
| 121 | const empty: CTypeDependencies = .{ | |
| 122 | .len = 0, | |
| 123 | .errunion_len = 0, | |
| 124 | .fwd_len = 0, | |
| 125 | .errunion_fwd_len = 0, | |
| 126 | .aligned_fwd_len = 0, | |
| 127 | .type_start = 0, | |
| 128 | .align_mask_start = 0, | |
| 129 | }; | |
| 74 | 130 | }; |
| 75 | 131 | |
| 76 | /// Per-declaration data. | |
| 77 | pub const AvBlock = struct { | |
| 78 | fwd_decl: String = .empty, | |
| 79 | code: String = .empty, | |
| 80 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate | |
| 81 | /// over each `Decl` and generate the definition for each used `CType` once. | |
| 82 | ctype_pool: codegen.CType.Pool = .empty, | |
| 83 | /// May contain string references to ctype_pool | |
| 84 | lazy_fns: codegen.LazyFnMap = .{}, | |
| 85 | ||
| 86 | fn deinit(ab: *AvBlock, gpa: Allocator) void { | |
| 87 | ab.lazy_fns.deinit(gpa); | |
| 88 | ab.ctype_pool.deinit(gpa); | |
| 89 | ab.* = undefined; | |
| 132 | const RenderedDecl = struct { | |
| 133 | fwd_decl: String, | |
| 134 | code: String, | |
| 135 | ctype_deps: CTypeDependencies, | |
| 136 | need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 137 | need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 138 | need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), | |
| 139 | need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), | |
| 140 | ||
| 141 | const init: RenderedDecl = .{ | |
| 142 | .fwd_decl = .empty, | |
| 143 | .code = .empty, | |
| 144 | .ctype_deps = .empty, | |
| 145 | .need_uavs = .empty, | |
| 146 | .need_tag_name_funcs = .empty, | |
| 147 | .need_never_tail_funcs = .empty, | |
| 148 | .need_never_inline_funcs = .empty, | |
| 149 | }; | |
| 150 | ||
| 151 | fn deinit(rd: *RenderedDecl, gpa: Allocator) void { | |
| 152 | rd.need_uavs.deinit(gpa); | |
| 153 | rd.need_tag_name_funcs.deinit(gpa); | |
| 154 | rd.need_never_tail_funcs.deinit(gpa); | |
| 155 | rd.need_never_inline_funcs.deinit(gpa); | |
| 156 | rd.* = undefined; | |
| 157 | } | |
| 158 | ||
| 159 | /// We are about to re-render this declaration, but we want to reuse the existing buffers, so | |
| 160 | /// call `clearRetainCapacity` on the containers. Sets `fwd_decl` and `code` to `undefined`, | |
| 161 | /// because we shouldn't be using the old values any longer. | |
| 162 | fn clearRetainingCapacity(rd: *RenderedDecl) void { | |
| 163 | rd.fwd_decl = undefined; | |
| 164 | rd.code = undefined; | |
| 165 | rd.need_uavs.clearRetainingCapacity(); | |
| 166 | rd.need_tag_name_funcs.clearRetainingCapacity(); | |
| 167 | rd.need_never_tail_funcs.clearRetainingCapacity(); | |
| 168 | rd.need_never_inline_funcs.clearRetainingCapacity(); | |
| 90 | 169 | } |
| 91 | 170 | }; |
| 92 | 171 | |
| 93 | /// Per-exported-symbol data. | |
| 94 | pub const ExportedBlock = struct { | |
| 95 | fwd_decl: String = .empty, | |
| 172 | const RenderedType = struct { | |
| 173 | /// If this type lowers to an aggregate, this is a forward declaration of its struct/union tag. | |
| 174 | /// Otherwise, this is `.empty`. | |
| 175 | /// | |
| 176 | /// Populated immediately and never changes. | |
| 177 | fwd_decl: String, | |
| 178 | ||
| 179 | /// A forward declaration of an error union type with this type as its *payload*. | |
| 180 | /// | |
| 181 | /// Populated immediately and never changes. | |
| 182 | errunion_fwd_decl: String, | |
| 183 | ||
| 184 | /// If this type lowers to an aggregate, this is the struct/union definition. | |
| 185 | /// If this type lowers to a typedef, this is that typedef. | |
| 186 | /// Otherwise, this is `.empty`. | |
| 187 | definition: String, | |
| 188 | /// The `struct` definition for an error union type with this type as its *payload*. | |
| 189 | /// | |
| 190 | /// This string is empty iff the payload type does not have a resolved layout. If the layout is | |
| 191 | /// resolved, the error union struct is defined, even if the payload type lacks runtime bits. | |
| 192 | errunion_definition: String, | |
| 193 | ||
| 194 | /// Dependencies which must be satisfied before emitting the name of this type. As such, they | |
| 195 | /// must be satisfied before emitting `errunion_definition` or any aligned typedef. | |
| 196 | /// | |
| 197 | /// Populated immediately and never changes. | |
| 198 | deps: CTypeDependencies, | |
| 199 | ||
| 200 | /// Dependencies which must be satisfied before emitting `definition`. | |
| 201 | definition_deps: CTypeDependencies, | |
| 96 | 202 | }; |
| 97 | 203 | |
| 98 | pub fn getString(this: C, s: String) []const u8 { | |
| 99 | return this.string_bytes.items[s.start..][0..s.len]; | |
| 204 | /// Only called by `link.ConstPool` due to `c.type_pool`, so `val` is always a type. | |
| 205 | pub fn addConst( | |
| 206 | c: *C, | |
| 207 | pt: Zcu.PerThread, | |
| 208 | pool_index: link.ConstPool.Index, | |
| 209 | val: InternPool.Index, | |
| 210 | ) Allocator.Error!void { | |
| 211 | const zcu = pt.zcu; | |
| 212 | const gpa = zcu.comp.gpa; | |
| 213 | assert(zcu.intern_pool.typeOf(val) == .type_type); | |
| 214 | assert(@intFromEnum(pool_index) == c.types.items.len); | |
| 215 | ||
| 216 | const ty: Type = .fromInterned(val); | |
| 217 | ||
| 218 | const fwd_decl: String = fwd_decl: { | |
| 219 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 220 | defer c.string_bytes = aw.toArrayList(); | |
| 221 | const start = aw.written().len; | |
| 222 | codegen.CType.render_defs.fwdDecl(ty, &aw.writer, zcu) catch |err| switch (err) { | |
| 223 | error.WriteFailed => return error.OutOfMemory, | |
| 224 | }; | |
| 225 | break :fwd_decl .{ | |
| 226 | .start = @intCast(start), | |
| 227 | .len = @intCast(aw.written().len - start), | |
| 228 | }; | |
| 229 | }; | |
| 230 | ||
| 231 | const errunion_fwd_decl: String = errunion_fwd_decl: { | |
| 232 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 233 | defer c.string_bytes = aw.toArrayList(); | |
| 234 | const start = aw.written().len; | |
| 235 | codegen.CType.render_defs.errunionFwdDecl(ty, &aw.writer, zcu) catch |err| switch (err) { | |
| 236 | error.WriteFailed => return error.OutOfMemory, | |
| 237 | }; | |
| 238 | break :errunion_fwd_decl .{ | |
| 239 | .start = @intCast(start), | |
| 240 | .len = @intCast(aw.written().len - start), | |
| 241 | }; | |
| 242 | }; | |
| 243 | ||
| 244 | try c.types.append(gpa, .{ | |
| 245 | .fwd_decl = fwd_decl, | |
| 246 | .errunion_fwd_decl = errunion_fwd_decl, | |
| 247 | // This field will be populated just below. | |
| 248 | .deps = undefined, | |
| 249 | // The remaining fields will be populated later by either `updateConstIncomplete` or | |
| 250 | // `updateConstComplete` (it is guaranteed that at least one will be called). | |
| 251 | .definition = undefined, | |
| 252 | .errunion_definition = undefined, | |
| 253 | .definition_deps = undefined, | |
| 254 | }); | |
| 255 | ||
| 256 | { | |
| 257 | // Find the dependencies required to just render the type `ty`. | |
| 258 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 259 | defer arena.deinit(); | |
| 260 | var deps: codegen.CType.Dependencies = .empty; | |
| 261 | defer deps.deinit(gpa); | |
| 262 | _ = try codegen.CType.lower(ty, &deps, arena.allocator(), zcu); | |
| 263 | // This call may add more items to `c.types`. | |
| 264 | const type_deps = try c.addCTypeDependencies(pt, &deps); | |
| 265 | c.types.items[@intFromEnum(pool_index)].deps = type_deps; | |
| 266 | } | |
| 100 | 267 | } |
| 101 | 268 | |
| 102 | pub fn addString(this: *C, s: []const u8) Allocator.Error!String { | |
| 103 | const comp = this.base.comp; | |
| 104 | const gpa = comp.gpa; | |
| 105 | try this.string_bytes.appendSlice(gpa, s); | |
| 106 | return .{ | |
| 107 | .start = @intCast(this.string_bytes.items.len - s.len), | |
| 108 | .len = @intCast(s.len), | |
| 269 | /// Only called by `link.ConstPool` due to `c.type_pool`, so `val` is always a type. | |
| 270 | pub fn updateConstIncomplete( | |
| 271 | c: *C, | |
| 272 | pt: Zcu.PerThread, | |
| 273 | index: link.ConstPool.Index, | |
| 274 | val: InternPool.Index, | |
| 275 | ) Allocator.Error!void { | |
| 276 | const zcu = pt.zcu; | |
| 277 | const gpa = zcu.comp.gpa; | |
| 278 | ||
| 279 | assert(zcu.intern_pool.typeOf(val) == .type_type); | |
| 280 | const ty: Type = .fromInterned(val); | |
| 281 | ||
| 282 | const rendered: *RenderedType = &c.types.items[@intFromEnum(index)]; | |
| 283 | ||
| 284 | rendered.errunion_definition = .empty; | |
| 285 | rendered.definition_deps = .empty; | |
| 286 | rendered.definition = definition: { | |
| 287 | if (rendered.fwd_decl.len != 0) { | |
| 288 | // This is a struct or union type. We will never complete it, but we must forward | |
| 289 | // declare it to ensure that its first usage does not appear in a different scope. | |
| 290 | break :definition rendered.fwd_decl; | |
| 291 | } | |
| 292 | // Otherwise, we might need to `typedef` to `void`. | |
| 293 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 294 | defer c.string_bytes = aw.toArrayList(); | |
| 295 | const start = aw.written().len; | |
| 296 | codegen.CType.render_defs.defineIncomplete(ty, &aw.writer, pt) catch |err| switch (err) { | |
| 297 | error.WriteFailed => return error.OutOfMemory, | |
| 298 | }; | |
| 299 | break :definition .{ | |
| 300 | .start = @intCast(start), | |
| 301 | .len = @intCast(aw.written().len - start), | |
| 302 | }; | |
| 109 | 303 | }; |
| 110 | 304 | } |
| 305 | /// Only called by `link.ConstPool` due to `c.type_pool`, so `val` is always a type. | |
| 306 | pub fn updateConst( | |
| 307 | c: *C, | |
| 308 | pt: Zcu.PerThread, | |
| 309 | index: link.ConstPool.Index, | |
| 310 | val: InternPool.Index, | |
| 311 | ) Allocator.Error!void { | |
| 312 | const zcu = pt.zcu; | |
| 313 | const gpa = zcu.comp.gpa; | |
| 314 | ||
| 315 | assert(zcu.intern_pool.typeOf(val) == .type_type); | |
| 316 | const ty: Type = .fromInterned(val); | |
| 317 | ||
| 318 | const rendered: *RenderedType = &c.types.items[@intFromEnum(index)]; | |
| 319 | ||
| 320 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 321 | defer arena.deinit(); | |
| 322 | ||
| 323 | var deps: codegen.CType.Dependencies = .empty; | |
| 324 | defer deps.deinit(gpa); | |
| 325 | ||
| 326 | { | |
| 327 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 328 | defer c.string_bytes = aw.toArrayList(); | |
| 329 | const start = aw.written().len; | |
| 330 | codegen.CType.render_defs.errunionDefineComplete( | |
| 331 | ty, | |
| 332 | &deps, | |
| 333 | arena.allocator(), | |
| 334 | &aw.writer, | |
| 335 | pt, | |
| 336 | ) catch |err| switch (err) { | |
| 337 | error.WriteFailed => return error.OutOfMemory, | |
| 338 | error.OutOfMemory => |e| return e, | |
| 339 | }; | |
| 340 | rendered.errunion_definition = .{ | |
| 341 | .start = @intCast(start), | |
| 342 | .len = @intCast(aw.written().len - start), | |
| 343 | }; | |
| 344 | } | |
| 345 | ||
| 346 | deps.clearRetainingCapacity(); | |
| 347 | ||
| 348 | { | |
| 349 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 350 | defer c.string_bytes = aw.toArrayList(); | |
| 351 | const start = aw.written().len; | |
| 352 | codegen.CType.render_defs.defineComplete( | |
| 353 | ty, | |
| 354 | &deps, | |
| 355 | arena.allocator(), | |
| 356 | &aw.writer, | |
| 357 | pt, | |
| 358 | ) catch |err| switch (err) { | |
| 359 | error.WriteFailed => return error.OutOfMemory, | |
| 360 | error.OutOfMemory => |e| return e, | |
| 361 | }; | |
| 362 | // Remove dependency on a forward declaration of ourselves; we're defining this type so that | |
| 363 | // forward declaration obviously exists! | |
| 364 | _ = deps.type_fwd.swapRemove(ty.toIntern()); | |
| 365 | rendered.definition = .{ | |
| 366 | .start = @intCast(start), | |
| 367 | .len = @intCast(aw.written().len - start), | |
| 368 | }; | |
| 369 | } | |
| 370 | ||
| 371 | { | |
| 372 | // This call invalidates `rendered`. | |
| 373 | const definition_deps = try c.addCTypeDependencies(pt, &deps); | |
| 374 | c.types.items[@intFromEnum(index)].definition_deps = definition_deps; | |
| 375 | } | |
| 376 | } | |
| 377 | ||
| 378 | fn addString(c: *C, vec: []const []const u8) Allocator.Error!String { | |
| 379 | const gpa = c.base.comp.gpa; | |
| 380 | ||
| 381 | var len: u32 = 0; | |
| 382 | for (vec) |s| len += @intCast(s.len); | |
| 383 | try c.string_bytes.ensureUnusedCapacity(gpa, len); | |
| 384 | ||
| 385 | const start: u32 = @intCast(c.string_bytes.items.len); | |
| 386 | for (vec) |s| c.string_bytes.appendSliceAssumeCapacity(s); | |
| 387 | assert(c.string_bytes.items.len == start + len); | |
| 388 | ||
| 389 | return .{ .start = start, .len = len }; | |
| 390 | } | |
| 111 | 391 | |
| 112 | 392 | pub fn open( |
| 113 | 393 | arena: Allocator, |
| ... | ... | @@ -156,267 +436,622 @@ pub fn createEmpty( |
| 156 | 436 | .file = file, |
| 157 | 437 | .build_id = options.build_id, |
| 158 | 438 | }, |
| 159 | .navs = .empty, | |
| 160 | 439 | .string_bytes = .empty, |
| 440 | .type_dependencies = .empty, | |
| 441 | .align_dependency_masks = .empty, | |
| 442 | .navs = .empty, | |
| 161 | 443 | .uavs = .empty, |
| 162 | .aligned_uavs = .empty, | |
| 444 | .type_pool = .empty, | |
| 445 | .types = .empty, | |
| 446 | .bigint_types = .empty, | |
| 163 | 447 | .exported_navs = .empty, |
| 164 | 448 | .exported_uavs = .empty, |
| 165 | .fwd_decl_buf = &.{}, | |
| 166 | .code_header_buf = &.{}, | |
| 167 | .code_buf = &.{}, | |
| 168 | .scratch_buf = &.{}, | |
| 169 | 449 | }; |
| 170 | 450 | |
| 171 | 451 | return c_file; |
| 172 | 452 | } |
| 173 | 453 | |
| 174 | pub fn deinit(self: *C) void { | |
| 175 | const gpa = self.base.comp.gpa; | |
| 176 | ||
| 177 | for (self.navs.values()) |*db| { | |
| 178 | db.deinit(gpa); | |
| 179 | } | |
| 180 | self.navs.deinit(gpa); | |
| 181 | ||
| 182 | for (self.uavs.values()) |*db| { | |
| 183 | db.deinit(gpa); | |
| 184 | } | |
| 185 | self.uavs.deinit(gpa); | |
| 186 | self.aligned_uavs.deinit(gpa); | |
| 454 | pub fn deinit(c: *C) void { | |
| 455 | const gpa = c.base.comp.gpa; | |
| 187 | 456 | |
| 188 | self.exported_navs.deinit(gpa); | |
| 189 | self.exported_uavs.deinit(gpa); | |
| 457 | for (c.navs.values()) |*r| r.deinit(gpa); | |
| 458 | for (c.uavs.values()) |*r| r.deinit(gpa); | |
| 459 | ||
| 460 | c.string_bytes.deinit(gpa); | |
| 461 | c.type_dependencies.deinit(gpa); | |
| 462 | c.align_dependency_masks.deinit(gpa); | |
| 463 | c.navs.deinit(gpa); | |
| 464 | c.uavs.deinit(gpa); | |
| 465 | c.type_pool.deinit(gpa); | |
| 466 | c.types.deinit(gpa); | |
| 467 | c.bigint_types.deinit(gpa); | |
| 468 | c.exported_navs.deinit(gpa); | |
| 469 | c.exported_uavs.deinit(gpa); | |
| 470 | } | |
| 190 | 471 | |
| 191 | self.string_bytes.deinit(gpa); | |
| 192 | gpa.free(self.fwd_decl_buf); | |
| 193 | gpa.free(self.code_header_buf); | |
| 194 | gpa.free(self.code_buf); | |
| 195 | gpa.free(self.scratch_buf); | |
| 472 | pub fn updateContainerType( | |
| 473 | c: *C, | |
| 474 | pt: Zcu.PerThread, | |
| 475 | ty: InternPool.Index, | |
| 476 | success: bool, | |
| 477 | ) link.File.UpdateContainerTypeError!void { | |
| 478 | try c.type_pool.updateContainerType(pt, .{ .c = c }, ty, success); | |
| 196 | 479 | } |
| 197 | 480 | |
| 198 | 481 | pub fn updateFunc( |
| 199 | self: *C, | |
| 482 | c: *C, | |
| 200 | 483 | pt: Zcu.PerThread, |
| 201 | 484 | func_index: InternPool.Index, |
| 202 | 485 | mir: *AnyMir, |
| 203 | ) link.File.UpdateNavError!void { | |
| 486 | ) Allocator.Error!void { | |
| 204 | 487 | const zcu = pt.zcu; |
| 205 | 488 | const gpa = zcu.gpa; |
| 206 | const func = zcu.funcInfo(func_index); | |
| 489 | const nav = zcu.funcInfo(func_index).owner_nav; | |
| 207 | 490 | |
| 208 | const gop = try self.navs.getOrPut(gpa, func.owner_nav); | |
| 209 | if (gop.found_existing) gop.value_ptr.deinit(gpa); | |
| 210 | gop.value_ptr.* = .{ | |
| 211 | .code = .empty, | |
| 212 | .fwd_decl = .empty, | |
| 213 | .ctype_pool = mir.c.ctype_pool.move(), | |
| 214 | .lazy_fns = mir.c.lazy_fns.move(), | |
| 491 | const rendered_decl: *RenderedDecl = rd: { | |
| 492 | const gop = try c.navs.getOrPut(gpa, nav); | |
| 493 | if (gop.found_existing) gop.value_ptr.deinit(gpa); | |
| 494 | break :rd gop.value_ptr; | |
| 215 | 495 | }; |
| 216 | gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl); | |
| 217 | const code_header = try self.addString(mir.c.code_header); | |
| 218 | const code = try self.addString(mir.c.code); | |
| 219 | gop.value_ptr.code = code_header.concat(code); | |
| 220 | try self.addUavsFromCodegen(&mir.c.uavs); | |
| 221 | } | |
| 222 | ||
| 223 | fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) link.File.FlushError!void { | |
| 224 | const gpa = self.base.comp.gpa; | |
| 225 | const uav = self.uavs.keys()[i]; | |
| 226 | ||
| 227 | var object: codegen.Object = .{ | |
| 228 | .dg = .{ | |
| 229 | .gpa = gpa, | |
| 230 | .pt = pt, | |
| 231 | .mod = pt.zcu.root_mod, | |
| 232 | .error_msg = null, | |
| 233 | .pass = .{ .uav = uav }, | |
| 234 | .is_naked_fn = false, | |
| 235 | .expected_block = null, | |
| 236 | .fwd_decl = undefined, | |
| 237 | .ctype_pool = .empty, | |
| 238 | .scratch = .initBuffer(self.scratch_buf), | |
| 239 | .uavs = .empty, | |
| 240 | }, | |
| 241 | .code_header = undefined, | |
| 242 | .code = undefined, | |
| 243 | .indent_counter = 0, | |
| 244 | }; | |
| 245 | object.dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); | |
| 246 | object.code = .initOwnedSlice(gpa, self.code_buf); | |
| 247 | defer { | |
| 248 | object.dg.uavs.deinit(gpa); | |
| 249 | object.dg.ctype_pool.deinit(object.dg.gpa); | |
| 250 | ||
| 251 | self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice(); | |
| 252 | self.code_buf = object.code.toArrayList().allocatedSlice(); | |
| 253 | self.scratch_buf = object.dg.scratch.allocatedSlice(); | |
| 254 | } | |
| 255 | try object.dg.ctype_pool.init(gpa); | |
| 256 | ||
| 257 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(uav) }; | |
| 258 | const alignment: Alignment = self.aligned_uavs.get(uav) orelse .none; | |
| 259 | codegen.genDeclValue(&object, c_value.constant, c_value, alignment, .none) catch |err| switch (err) { | |
| 260 | error.AnalysisFail => { | |
| 261 | @panic("TODO: C backend AnalysisFail on anonymous decl"); | |
| 262 | //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); | |
| 263 | //return; | |
| 264 | }, | |
| 265 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 496 | c.navs.lockPointers(); | |
| 497 | defer c.navs.unlockPointers(); | |
| 498 | ||
| 499 | rendered_decl.* = .{ | |
| 500 | .fwd_decl = try c.addString(&.{mir.c.fwd_decl}), | |
| 501 | .code = try c.addString(&.{ mir.c.code_header, mir.c.code }), | |
| 502 | .ctype_deps = try c.addCTypeDependencies(pt, &mir.c.ctype_deps), | |
| 503 | .need_uavs = mir.c.need_uavs.move(), | |
| 504 | .need_tag_name_funcs = mir.c.need_tag_name_funcs.move(), | |
| 505 | .need_never_tail_funcs = mir.c.need_never_tail_funcs.move(), | |
| 506 | .need_never_inline_funcs = mir.c.need_never_inline_funcs.move(), | |
| 266 | 507 | }; |
| 267 | 508 | |
| 268 | try self.addUavsFromCodegen(&object.dg.uavs); | |
| 509 | const old_uavs_len = c.uavs.count(); | |
| 510 | try c.uavs.ensureUnusedCapacity(gpa, rendered_decl.need_uavs.count()); | |
| 511 | for (rendered_decl.need_uavs.keys()) |val| { | |
| 512 | const gop = c.uavs.getOrPutAssumeCapacity(val); | |
| 513 | if (gop.found_existing) { | |
| 514 | assert(gop.index < old_uavs_len); | |
| 515 | } else { | |
| 516 | assert(gop.index >= old_uavs_len); | |
| 517 | } | |
| 518 | } | |
| 519 | try c.updateNewUavs(pt, old_uavs_len); | |
| 269 | 520 | |
| 270 | object.dg.ctype_pool.freeUnusedCapacity(gpa); | |
| 271 | self.uavs.values()[i] = .{ | |
| 272 | .fwd_decl = try self.addString(object.dg.fwd_decl.written()), | |
| 273 | .code = try self.addString(object.code.written()), | |
| 274 | .ctype_pool = object.dg.ctype_pool.move(), | |
| 275 | }; | |
| 521 | try c.type_pool.flushPending(pt, .{ .c = c }); | |
| 276 | 522 | } |
| 277 | 523 | |
| 278 | pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.File.UpdateNavError!void { | |
| 524 | pub fn updateNav( | |
| 525 | c: *C, | |
| 526 | pt: Zcu.PerThread, | |
| 527 | nav_index: InternPool.Nav.Index, | |
| 528 | ) Allocator.Error!void { | |
| 279 | 529 | const tracy = trace(@src()); |
| 280 | 530 | defer tracy.end(); |
| 281 | 531 | |
| 282 | const gpa = self.base.comp.gpa; | |
| 532 | const gpa = c.base.comp.gpa; | |
| 283 | 533 | const zcu = pt.zcu; |
| 284 | 534 | const ip = &zcu.intern_pool; |
| 285 | 535 | |
| 286 | 536 | const nav = ip.getNav(nav_index); |
| 287 | const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 537 | switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 288 | 538 | .func => return, |
| 289 | .@"extern" => .none, | |
| 290 | .variable => |variable| variable.init, | |
| 291 | else => nav.status.fully_resolved.val, | |
| 539 | .@"extern" => {}, | |
| 540 | else => { | |
| 541 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 542 | if (!nav_ty.hasRuntimeBits(zcu)) { | |
| 543 | if (c.navs.fetchSwapRemove(nav_index)) |kv| { | |
| 544 | var old_rendered = kv.value; | |
| 545 | old_rendered.deinit(gpa); | |
| 546 | } | |
| 547 | return; | |
| 548 | } | |
| 549 | }, | |
| 550 | } | |
| 551 | ||
| 552 | const rendered_decl: *RenderedDecl = rd: { | |
| 553 | const gop = try c.navs.getOrPut(gpa, nav_index); | |
| 554 | if (gop.found_existing) { | |
| 555 | gop.value_ptr.clearRetainingCapacity(); | |
| 556 | } else { | |
| 557 | gop.value_ptr.* = .init; | |
| 558 | } | |
| 559 | break :rd gop.value_ptr; | |
| 292 | 560 | }; |
| 293 | if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) return; | |
| 561 | c.navs.lockPointers(); | |
| 562 | defer c.navs.unlockPointers(); | |
| 294 | 563 | |
| 295 | const gop = try self.navs.getOrPut(gpa, nav_index); | |
| 296 | errdefer _ = self.navs.pop(); | |
| 297 | if (!gop.found_existing) gop.value_ptr.* = .{}; | |
| 298 | const ctype_pool = &gop.value_ptr.ctype_pool; | |
| 299 | try ctype_pool.init(gpa); | |
| 300 | ctype_pool.clearRetainingCapacity(); | |
| 564 | { | |
| 565 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 566 | defer arena.deinit(); | |
| 301 | 567 | |
| 302 | var object: codegen.Object = .{ | |
| 303 | .dg = .{ | |
| 568 | var dg: codegen.DeclGen = .{ | |
| 304 | 569 | .gpa = gpa, |
| 570 | .arena = arena.allocator(), | |
| 305 | 571 | .pt = pt, |
| 306 | 572 | .mod = zcu.navFileScope(nav_index).mod.?, |
| 307 | 573 | .error_msg = null, |
| 308 | .pass = .{ .nav = nav_index }, | |
| 574 | .owner_nav = nav_index.toOptional(), | |
| 309 | 575 | .is_naked_fn = false, |
| 310 | 576 | .expected_block = null, |
| 311 | .fwd_decl = undefined, | |
| 312 | .ctype_pool = ctype_pool.*, | |
| 313 | .scratch = .initBuffer(self.scratch_buf), | |
| 314 | .uavs = .empty, | |
| 315 | }, | |
| 316 | .code_header = undefined, | |
| 317 | .code = undefined, | |
| 318 | .indent_counter = 0, | |
| 577 | .ctype_deps = .empty, | |
| 578 | .uavs = rendered_decl.need_uavs.move(), | |
| 579 | }; | |
| 580 | ||
| 581 | defer { | |
| 582 | rendered_decl.need_uavs = dg.uavs.move(); | |
| 583 | dg.ctype_deps.deinit(gpa); | |
| 584 | } | |
| 585 | ||
| 586 | rendered_decl.fwd_decl = fwd_decl: { | |
| 587 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 588 | defer c.string_bytes = aw.toArrayList(); | |
| 589 | const start = aw.written().len; | |
| 590 | codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) { | |
| 591 | error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) { | |
| 592 | error.CodegenFail => return, | |
| 593 | error.OutOfMemory => |e| return e, | |
| 594 | }, | |
| 595 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 596 | }; | |
| 597 | break :fwd_decl .{ | |
| 598 | .start = @intCast(start), | |
| 599 | .len = @intCast(aw.written().len - start), | |
| 600 | }; | |
| 601 | }; | |
| 602 | ||
| 603 | rendered_decl.code = code: { | |
| 604 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 605 | defer c.string_bytes = aw.toArrayList(); | |
| 606 | const start = aw.written().len; | |
| 607 | codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) { | |
| 608 | error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) { | |
| 609 | error.CodegenFail => return, | |
| 610 | error.OutOfMemory => |e| return e, | |
| 611 | }, | |
| 612 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 613 | }; | |
| 614 | break :code .{ | |
| 615 | .start = @intCast(start), | |
| 616 | .len = @intCast(aw.written().len - start), | |
| 617 | }; | |
| 618 | }; | |
| 619 | ||
| 620 | rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps); | |
| 621 | } | |
| 622 | ||
| 623 | const old_uavs_len = c.uavs.count(); | |
| 624 | try c.uavs.ensureUnusedCapacity(gpa, rendered_decl.need_uavs.count()); | |
| 625 | for (rendered_decl.need_uavs.keys()) |val| { | |
| 626 | const gop = c.uavs.getOrPutAssumeCapacity(val); | |
| 627 | if (gop.found_existing) { | |
| 628 | assert(gop.index < old_uavs_len); | |
| 629 | } else { | |
| 630 | assert(gop.index >= old_uavs_len); | |
| 631 | } | |
| 632 | } | |
| 633 | try c.updateNewUavs(pt, old_uavs_len); | |
| 634 | ||
| 635 | try c.type_pool.flushPending(pt, .{ .c = c }); | |
| 636 | } | |
| 637 | ||
| 638 | /// Unlike `updateNav` and `updateFunc`, this does *not* add newly-discovered UAVs to `c.uavs`. The | |
| 639 | /// caller is instead responsible for doing that (by iterating `rendered_decl.need_uavs`). However, | |
| 640 | /// this function *does* still add newly-discovered *types* to `c.type_pool`. | |
| 641 | /// | |
| 642 | /// This function does not accept an alignment for the UAV, because the alignment needed on a UAV is | |
| 643 | /// not known until `flush` (since we need to have seen all uses of the UAV first). Instead, `flush` | |
| 644 | /// will prefix the UAV definition with an appropriate alignment annotation if necessary. | |
| 645 | fn updateUav( | |
| 646 | c: *C, | |
| 647 | pt: Zcu.PerThread, | |
| 648 | val: Value, | |
| 649 | rendered_decl: *RenderedDecl, | |
| 650 | ) Allocator.Error!void { | |
| 651 | const tracy = trace(@src()); | |
| 652 | defer tracy.end(); | |
| 653 | ||
| 654 | const gpa = c.base.comp.gpa; | |
| 655 | ||
| 656 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 657 | defer arena.deinit(); | |
| 658 | ||
| 659 | var dg: codegen.DeclGen = .{ | |
| 660 | .gpa = gpa, | |
| 661 | .arena = arena.allocator(), | |
| 662 | .pt = pt, | |
| 663 | .mod = pt.zcu.root_mod, | |
| 664 | .error_msg = null, | |
| 665 | .owner_nav = .none, | |
| 666 | .is_naked_fn = false, | |
| 667 | .expected_block = null, | |
| 668 | .ctype_deps = .empty, | |
| 669 | .uavs = .empty, | |
| 319 | 670 | }; |
| 320 | object.dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); | |
| 321 | object.code = .initOwnedSlice(gpa, self.code_buf); | |
| 322 | 671 | defer { |
| 323 | object.dg.uavs.deinit(gpa); | |
| 324 | ctype_pool.* = object.dg.ctype_pool.move(); | |
| 325 | ctype_pool.freeUnusedCapacity(gpa); | |
| 326 | ||
| 327 | self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice(); | |
| 328 | self.code_buf = object.code.toArrayList().allocatedSlice(); | |
| 329 | self.scratch_buf = object.dg.scratch.allocatedSlice(); | |
| 672 | rendered_decl.need_uavs = dg.uavs.move(); | |
| 673 | dg.ctype_deps.deinit(gpa); | |
| 330 | 674 | } |
| 331 | 675 | |
| 332 | codegen.genDecl(&object) catch |err| switch (err) { | |
| 333 | error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, object.dg.error_msg.?)) { | |
| 334 | error.CodegenFail => return, | |
| 335 | error.OutOfMemory => |e| return e, | |
| 336 | }, | |
| 337 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 676 | rendered_decl.fwd_decl = fwd_decl: { | |
| 677 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 678 | defer c.string_bytes = aw.toArrayList(); | |
| 679 | const start = aw.written().len; | |
| 680 | codegen.genDeclValueFwd(&dg, &aw.writer, .{ | |
| 681 | .name = .{ .constant = val }, | |
| 682 | .@"const" = true, | |
| 683 | .@"threadlocal" = false, | |
| 684 | .init_val = val, | |
| 685 | }) catch |err| switch (err) { | |
| 686 | error.AnalysisFail => { | |
| 687 | @panic("TODO: CBE error.AnalysisFail on uav"); | |
| 688 | }, | |
| 689 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 690 | }; | |
| 691 | break :fwd_decl .{ | |
| 692 | .start = @intCast(start), | |
| 693 | .len = @intCast(aw.written().len - start), | |
| 694 | }; | |
| 695 | }; | |
| 696 | ||
| 697 | rendered_decl.code = code: { | |
| 698 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 699 | defer c.string_bytes = aw.toArrayList(); | |
| 700 | const start = aw.written().len; | |
| 701 | codegen.genDeclValue(&dg, &aw.writer, .{ | |
| 702 | .name = .{ .constant = val }, | |
| 703 | .@"const" = true, | |
| 704 | .@"threadlocal" = false, | |
| 705 | .init_val = val, | |
| 706 | }) catch |err| switch (err) { | |
| 707 | error.AnalysisFail => { | |
| 708 | @panic("TODO: CBE error.AnalysisFail on uav"); | |
| 709 | }, | |
| 710 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 711 | }; | |
| 712 | break :code .{ | |
| 713 | .start = @intCast(start), | |
| 714 | .len = @intCast(aw.written().len - start), | |
| 715 | }; | |
| 338 | 716 | }; |
| 339 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.written()); | |
| 340 | gop.value_ptr.code = try self.addString(object.code.written()); | |
| 341 | try self.addUavsFromCodegen(&object.dg.uavs); | |
| 717 | ||
| 718 | rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps); | |
| 342 | 719 | } |
| 343 | 720 | |
| 344 | pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { | |
| 345 | // The C backend does not have the ability to fix line numbers without re-generating | |
| 346 | // the entire Decl. | |
| 347 | _ = self; | |
| 721 | pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) error{}!void { | |
| 722 | // The C backend does not currently emit "#line" directives. Even if it did, it would not be | |
| 723 | // capable of updating those line numbers without re-generating the entire declaration. | |
| 724 | _ = c; | |
| 348 | 725 | _ = pt; |
| 349 | 726 | _ = ti_id; |
| 350 | 727 | } |
| 351 | 728 | |
| 352 | fn abiDefines(w: *std.Io.Writer, target: *const std.Target) !void { | |
| 353 | switch (target.abi) { | |
| 354 | .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"), | |
| 355 | else => {}, | |
| 356 | } | |
| 357 | try w.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{ | |
| 358 | target.cMaxIntAlignment(), | |
| 359 | }); | |
| 360 | } | |
| 361 | ||
| 362 | pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { | |
| 363 | _ = arena; // Has the same lifetime as the call to Compilation.update. | |
| 364 | ||
| 729 | pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { | |
| 365 | 730 | const tracy = trace(@src()); |
| 366 | 731 | defer tracy.end(); |
| 367 | 732 | |
| 368 | 733 | const sub_prog_node = prog_node.start("Flush Module", 0); |
| 369 | 734 | defer sub_prog_node.end(); |
| 370 | 735 | |
| 371 | const comp = self.base.comp; | |
| 736 | const comp = c.base.comp; | |
| 372 | 737 | const diags = &comp.link_diags; |
| 373 | 738 | const gpa = comp.gpa; |
| 374 | 739 | const io = comp.io; |
| 375 | const zcu = self.base.comp.zcu.?; | |
| 740 | const zcu = c.base.comp.zcu.?; | |
| 376 | 741 | const ip = &zcu.intern_pool; |
| 742 | const target = zcu.getTarget(); | |
| 377 | 743 | const pt: Zcu.PerThread = .activate(zcu, tid); |
| 378 | 744 | defer pt.deactivate(); |
| 379 | 745 | |
| 746 | // If it's somehow not made it into the pool, we need to generate the type `[:0]const u8` for | |
| 747 | // error names. | |
| 748 | const slice_const_u8_sentinel_0_pool_index = try c.type_pool.get( | |
| 749 | pt, | |
| 750 | .{ .c = c }, | |
| 751 | .slice_const_u8_sentinel_0_type, | |
| 752 | ); | |
| 753 | try c.type_pool.flushPending(pt, .{ .c = c }); | |
| 754 | ||
| 755 | // Find the set of referenced NAVs; these are the ones we'll emit. It is important in this | |
| 756 | // backend that we only emit referenced NAVs, because other ones may contain code from past | |
| 757 | // incremental updates which is invalid C (due to e.g. types changing). Machine code backends | |
| 758 | // don't have this problem because there are, of course, no type checking performed when you | |
| 759 | // *execute* a binary! | |
| 760 | var need_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty; | |
| 761 | defer need_navs.deinit(gpa); | |
| 762 | { | |
| 763 | const unit_references = try zcu.resolveReferences(); | |
| 764 | for (c.navs.keys()) |nav| { | |
| 765 | const nav_val = ip.getNav(nav).status.fully_resolved.val; | |
| 766 | const check_unit: ?InternPool.AnalUnit = switch (ip.indexToKey(nav_val)) { | |
| 767 | else => .wrap(.{ .nav_val = nav }), | |
| 768 | .func => .wrap(.{ .func = nav_val }), | |
| 769 | // TODO: this is a hack to deal with the fact that there's currently no good way to | |
| 770 | // know which `extern`s are alive. This can and will break in certain patterns of | |
| 771 | // incremental update. We kind of need to think a bit more about how the frontend | |
| 772 | // actually represents `extern`, it's a bit awkward right now. | |
| 773 | .@"extern" => null, | |
| 774 | }; | |
| 775 | if (check_unit) |u| { | |
| 776 | if (!unit_references.contains(u)) continue; | |
| 777 | } | |
| 778 | try need_navs.putNoClobber(gpa, nav, {}); | |
| 779 | } | |
| 780 | } | |
| 781 | ||
| 782 | // Using our knowledge of which NAVs are referenced, we now need to discover the set of UAVs and | |
| 783 | // C types which are referenced (and hence must be emitted). As above, this is necessary to make | |
| 784 | // sure we only emit valid C code. | |
| 785 | // | |
| 786 | // At the same time, we will discover the set of lazy functions which are referenced. | |
| 787 | ||
| 788 | var need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty; | |
| 789 | defer need_uavs.deinit(gpa); | |
| 790 | ||
| 791 | var need_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void) = .empty; | |
| 792 | defer need_types.deinit(gpa); | |
| 793 | var need_errunion_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void) = .empty; | |
| 794 | defer need_errunion_types.deinit(gpa); | |
| 795 | var need_aligned_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64) = .empty; | |
| 796 | defer need_aligned_types.deinit(gpa); | |
| 797 | ||
| 798 | var need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty; | |
| 799 | defer need_tag_name_funcs.deinit(gpa); | |
| 800 | ||
| 801 | var need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty; | |
| 802 | defer need_never_tail_funcs.deinit(gpa); | |
| 803 | ||
| 804 | var need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty; | |
| 805 | defer need_never_inline_funcs.deinit(gpa); | |
| 806 | ||
| 807 | // As mentioned above, we need this type for error names. | |
| 808 | try need_types.put(gpa, slice_const_u8_sentinel_0_pool_index, {}); | |
| 809 | ||
| 810 | // Every exported NAV should have been discovered via `zcu.resolveReferences`... | |
| 811 | for (c.exported_navs.keys()) |nav| assert(need_navs.contains(nav)); | |
| 812 | // ...but we *do* need to add exported UAVs to the set. | |
| 813 | try need_uavs.ensureUnusedCapacity(gpa, c.exported_uavs.count()); | |
| 814 | for (c.exported_uavs.keys()) |uav| { | |
| 815 | const gop = need_uavs.getOrPutAssumeCapacity(uav); | |
| 816 | if (!gop.found_existing) gop.value_ptr.* = .none; | |
| 817 | } | |
| 818 | ||
| 819 | // For every referenced NAV, some UAVs, C types, and lazy functions may be referenced. | |
| 820 | for (need_navs.keys()) |nav| { | |
| 821 | const rendered = c.navs.getPtr(nav).?; | |
| 822 | try mergeNeededCTypes( | |
| 823 | c, | |
| 824 | &need_types, | |
| 825 | &need_errunion_types, | |
| 826 | &need_aligned_types, | |
| 827 | &rendered.ctype_deps, | |
| 828 | ); | |
| 829 | try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs); | |
| 830 | ||
| 831 | try need_tag_name_funcs.ensureUnusedCapacity(gpa, rendered.need_tag_name_funcs.count()); | |
| 832 | for (rendered.need_tag_name_funcs.keys()) |enum_type| { | |
| 833 | need_tag_name_funcs.putAssumeCapacity(enum_type, {}); | |
| 834 | } | |
| 835 | ||
| 836 | try need_never_tail_funcs.ensureUnusedCapacity(gpa, rendered.need_never_tail_funcs.count()); | |
| 837 | for (rendered.need_never_tail_funcs.keys()) |fn_nav| { | |
| 838 | need_never_tail_funcs.putAssumeCapacity(fn_nav, {}); | |
| 839 | } | |
| 840 | ||
| 841 | try need_never_inline_funcs.ensureUnusedCapacity(gpa, rendered.need_never_inline_funcs.count()); | |
| 842 | for (rendered.need_never_inline_funcs.keys()) |fn_nav| { | |
| 843 | need_never_inline_funcs.putAssumeCapacity(fn_nav, {}); | |
| 844 | } | |
| 845 | } | |
| 846 | ||
| 847 | // UAVs may reference other UAVs or C types. | |
| 380 | 848 | { |
| 381 | var i: usize = 0; | |
| 382 | while (i < self.uavs.count()) : (i += 1) { | |
| 383 | try self.updateUav(pt, i); | |
| 849 | var index: usize = 0; | |
| 850 | while (need_uavs.count() > index) : (index += 1) { | |
| 851 | const val = need_uavs.keys()[index]; | |
| 852 | const rendered = c.uavs.getPtr(val).?; | |
| 853 | try mergeNeededCTypes( | |
| 854 | c, | |
| 855 | &need_types, | |
| 856 | &need_errunion_types, | |
| 857 | &need_aligned_types, | |
| 858 | &rendered.ctype_deps, | |
| 859 | ); | |
| 860 | try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs); | |
| 384 | 861 | } |
| 385 | 862 | } |
| 386 | 863 | |
| 387 | // This code path happens exclusively with -ofmt=c. The flush logic for | |
| 388 | // emit-h is in `flushEmitH` below. | |
| 864 | // Finally, C types may reference other C types. | |
| 865 | { | |
| 866 | var index: usize = 0; | |
| 867 | var errunion_index: usize = 0; | |
| 868 | var aligned_index: usize = 0; | |
| 869 | while (true) { | |
| 870 | if (index < need_types.count()) { | |
| 871 | const pool_index = need_types.keys()[index]; | |
| 872 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 873 | try mergeNeededCTypes( | |
| 874 | c, | |
| 875 | &need_types, | |
| 876 | &need_errunion_types, | |
| 877 | &need_aligned_types, | |
| 878 | &rendered.definition_deps, // we're tasked with emitting the *definition* of this type | |
| 879 | ); | |
| 880 | index += 1; | |
| 881 | continue; | |
| 882 | } | |
| 389 | 883 | |
| 390 | var f: Flush = .{ | |
| 391 | .ctype_pool = .empty, | |
| 392 | .ctype_global_from_decl_map = .empty, | |
| 393 | .ctypes = .empty, | |
| 884 | if (errunion_index < need_errunion_types.count()) { | |
| 885 | const payload_pool_index = need_errunion_types.keys()[errunion_index]; | |
| 886 | const rendered = &c.types.items[@intFromEnum(payload_pool_index)]; | |
| 887 | try mergeNeededCTypes( | |
| 888 | c, | |
| 889 | &need_types, | |
| 890 | &need_errunion_types, | |
| 891 | &need_aligned_types, | |
| 892 | &rendered.deps, // the error union type requires emitting this type's *name* | |
| 893 | ); | |
| 894 | errunion_index += 1; | |
| 895 | continue; | |
| 896 | } | |
| 394 | 897 | |
| 395 | .lazy_ctype_pool = .empty, | |
| 396 | .lazy_fns = .empty, | |
| 397 | .lazy_fwd_decl = .empty, | |
| 398 | .lazy_code = .empty, | |
| 898 | if (aligned_index < need_aligned_types.count()) { | |
| 899 | const pool_index = need_aligned_types.keys()[aligned_index]; | |
| 900 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 901 | try mergeNeededCTypes( | |
| 902 | c, | |
| 903 | &need_types, | |
| 904 | &need_errunion_types, | |
| 905 | &need_aligned_types, | |
| 906 | &rendered.deps, // an aligned typedef requires emitting this type's *name* | |
| 907 | ); | |
| 908 | aligned_index += 1; | |
| 909 | continue; | |
| 910 | } | |
| 399 | 911 | |
| 400 | .all_buffers = .empty, | |
| 401 | .file_size = 0, | |
| 402 | }; | |
| 912 | break; | |
| 913 | } | |
| 914 | } | |
| 915 | ||
| 916 | // Now that we know which types are required, generate aligned typedefs. One buffer per aligned | |
| 917 | // type, with *all* aligned typedefs for that type. | |
| 918 | const aligned_type_strings = try arena.alloc([]const u8, need_aligned_types.count()); | |
| 919 | { | |
| 920 | var aw: std.Io.Writer.Allocating = .init(gpa); | |
| 921 | defer aw.deinit(); | |
| 922 | var unused_deps: codegen.CType.Dependencies = .empty; | |
| 923 | defer unused_deps.deinit(gpa); | |
| 924 | for ( | |
| 925 | need_aligned_types.keys(), | |
| 926 | need_aligned_types.values(), | |
| 927 | aligned_type_strings, | |
| 928 | ) |pool_index, align_mask, *str_out| { | |
| 929 | const ty: Type = .fromInterned(pool_index.val(&c.type_pool)); | |
| 930 | const has_layout = c.types.items[@intFromEnum(pool_index)].errunion_definition.len > 0; | |
| 931 | for (0..@bitSizeOf(@TypeOf(align_mask))) |bit_index| { | |
| 932 | switch (@as(u1, @truncate(align_mask >> @intCast(bit_index)))) { | |
| 933 | 0 => continue, | |
| 934 | 1 => {}, | |
| 935 | } | |
| 936 | codegen.CType.render_defs.defineAligned( | |
| 937 | ty, | |
| 938 | .fromLog2Units(@intCast(bit_index)), | |
| 939 | has_layout, | |
| 940 | &unused_deps, | |
| 941 | arena, | |
| 942 | &aw.writer, | |
| 943 | pt, | |
| 944 | ) catch |err| switch (err) { | |
| 945 | error.WriteFailed => return error.OutOfMemory, | |
| 946 | error.OutOfMemory => |e| return e, | |
| 947 | }; | |
| 948 | } | |
| 949 | str_out.* = try arena.dupe(u8, aw.written()); | |
| 950 | aw.clearRetainingCapacity(); | |
| 951 | } | |
| 952 | } | |
| 953 | ||
| 954 | // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin | |
| 955 | // to build the output buffer. Our strategy is to emit the C source in this order: | |
| 956 | // | |
| 957 | // * ABI defines and `#include "zig.h"` | |
| 958 | // * Big-int type definitions | |
| 959 | // * Other CType definitions (traversing the dependency graph to sort topologically) | |
| 960 | // * Global assembly | |
| 961 | // * UAV exports | |
| 962 | // * NAV exports | |
| 963 | // * UAV forward declarations | |
| 964 | // * NAV forward declarations | |
| 965 | // * Lazy declarations (error names; @tagName functions; never_tail/never_inline wrappers) | |
| 966 | // * UAV definitions | |
| 967 | // * NAV definitions | |
| 968 | // | |
| 969 | // Most of these sections are order-independent within themselves, with the exception of the | |
| 970 | // type definitions, which must be ordered to avoid a struct/union from embedding a type which | |
| 971 | // is currently incomplete. | |
| 972 | // | |
| 973 | // When emitting UAV forward declarations, if the UAV requires alignment, we must prefix it with | |
| 974 | // an alignment annotation. We couldn't emit the alignment into the UAV's `RenderedDecl` because | |
| 975 | // we couldn't have known the required alignment until now! | |
| 976 | ||
| 977 | var f: Flush = .{ .all_buffers = .empty, .file_size = 0 }; | |
| 403 | 978 | defer f.deinit(gpa); |
| 404 | 979 | |
| 405 | var abi_defines_aw: std.Io.Writer.Allocating = .init(gpa); | |
| 406 | defer abi_defines_aw.deinit(); | |
| 407 | abiDefines(&abi_defines_aw.writer, zcu.getTarget()) catch |err| switch (err) { | |
| 408 | error.WriteFailed => return error.OutOfMemory, | |
| 409 | }; | |
| 980 | // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers! | |
| 981 | ||
| 982 | try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"` | |
| 983 | 1 + // Big-int type definitions | |
| 984 | need_types.count() + // `RenderedType.fwd_decl` (worst-case) | |
| 985 | need_types.count() + // `RenderedType.definition` | |
| 986 | need_errunion_types.count() + // `RenderedType.errunion_fwd_decl` (worst-case) | |
| 987 | need_errunion_types.count() + // `RenderedType.errunion_definition` | |
| 988 | need_aligned_types.count() + // `aligned_type_strings` | |
| 989 | 1 + // Global assembly | |
| 990 | c.exported_uavs.count() + // UAV export block | |
| 991 | c.exported_navs.count() + // NAV export block | |
| 992 | need_uavs.count() + // UAV forward declarations | |
| 993 | need_navs.count() + // NAV forward declarations | |
| 994 | 1 + // Lazy declarations | |
| 995 | need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "<definition body>") | |
| 996 | need_navs.count() * 2); // NAV definitions ("static ", "<definition body>") | |
| 997 | ||
| 998 | // ABI defines and `#include "zig.h"` | |
| 999 | switch (target.abi) { | |
| 1000 | .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"), | |
| 1001 | else => {}, | |
| 1002 | } | |
| 1003 | f.appendBufAssumeCapacity(try std.fmt.allocPrint( | |
| 1004 | arena, | |
| 1005 | "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", | |
| 1006 | .{target.cMaxIntAlignment()}, | |
| 1007 | )); | |
| 1008 | f.appendBufAssumeCapacity( | |
| 1009 | \\#include "zig.h" | |
| 1010 | \\ | |
| 1011 | ); | |
| 410 | 1012 | |
| 411 | // Covers defines, zig.h, ctypes, asm, lazy fwd. | |
| 412 | try f.all_buffers.ensureUnusedCapacity(gpa, 5); | |
| 1013 | // Big-int type definitions | |
| 1014 | var bigint_aw: std.Io.Writer.Allocating = .init(gpa); | |
| 1015 | defer bigint_aw.deinit(); | |
| 1016 | for (c.bigint_types.keys()) |bigint| { | |
| 1017 | codegen.CType.render_defs.defineBigInt(bigint, &bigint_aw.writer, zcu) catch |err| switch (err) { | |
| 1018 | error.WriteFailed => return error.OutOfMemory, | |
| 1019 | }; | |
| 1020 | } | |
| 1021 | f.appendBufAssumeCapacity(bigint_aw.written()); | |
| 413 | 1022 | |
| 414 | f.appendBufAssumeCapacity(abi_defines_aw.written()); | |
| 415 | f.appendBufAssumeCapacity(zig_h); | |
| 1023 | // CType definitions | |
| 1024 | { | |
| 1025 | var ft: FlushTypes = .{ | |
| 1026 | .c = c, | |
| 1027 | .f = &f, | |
| 1028 | .aligned_types = &need_aligned_types, | |
| 1029 | .aligned_type_strings = aligned_type_strings, | |
| 1030 | .status = .empty, | |
| 1031 | .errunion_status = .empty, | |
| 1032 | .aligned_status = .empty, | |
| 1033 | }; | |
| 1034 | defer { | |
| 1035 | ft.status.deinit(gpa); | |
| 1036 | ft.errunion_status.deinit(gpa); | |
| 1037 | ft.aligned_status.deinit(gpa); | |
| 1038 | } | |
| 1039 | try ft.status.ensureUnusedCapacity(gpa, need_types.count()); | |
| 1040 | try ft.errunion_status.ensureUnusedCapacity(gpa, need_errunion_types.count()); | |
| 1041 | try ft.aligned_status.ensureUnusedCapacity(gpa, need_aligned_types.count()); | |
| 416 | 1042 | |
| 417 | const ctypes_index = f.all_buffers.items.len; | |
| 418 | f.all_buffers.items.len += 1; | |
| 1043 | for (need_types.keys()) |pool_index| { | |
| 1044 | ft.doType(pool_index); | |
| 1045 | } | |
| 1046 | for (need_errunion_types.keys()) |pool_index| { | |
| 1047 | ft.doErrunionType(pool_index); | |
| 1048 | } | |
| 1049 | for (need_aligned_types.keys()) |pool_index| { | |
| 1050 | ft.doAlignedTypeFwd(pool_index); | |
| 1051 | } | |
| 1052 | } | |
| 419 | 1053 | |
| 1054 | // Global assembly | |
| 420 | 1055 | var asm_aw: std.Io.Writer.Allocating = .init(gpa); |
| 421 | 1056 | defer asm_aw.deinit(); |
| 422 | 1057 | codegen.genGlobalAsm(zcu, &asm_aw.writer) catch |err| switch (err) { |
| ... | ... | @@ -424,462 +1059,472 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P |
| 424 | 1059 | }; |
| 425 | 1060 | f.appendBufAssumeCapacity(asm_aw.written()); |
| 426 | 1061 | |
| 427 | const lazy_index = f.all_buffers.items.len; | |
| 428 | f.all_buffers.items.len += 1; | |
| 1062 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; | |
| 1063 | defer export_names.deinit(gpa); | |
| 1064 | try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count())); | |
| 1065 | for (zcu.single_exports.values()) |export_index| { | |
| 1066 | export_names.putAssumeCapacity(export_index.ptr(zcu).opts.name, {}); | |
| 1067 | } | |
| 1068 | for (zcu.multi_exports.values()) |info| { | |
| 1069 | try export_names.ensureUnusedCapacity(gpa, info.len); | |
| 1070 | for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| { | |
| 1071 | export_names.putAssumeCapacity(@"export".opts.name, {}); | |
| 1072 | } | |
| 1073 | } | |
| 429 | 1074 | |
| 430 | try f.lazy_ctype_pool.init(gpa); | |
| 431 | try self.flushErrDecls(pt, &f); | |
| 1075 | // UAV export block | |
| 1076 | for (c.exported_uavs.values()) |code| { | |
| 1077 | f.appendBufAssumeCapacity(code.get(c)); | |
| 1078 | } | |
| 432 | 1079 | |
| 433 | // Unlike other backends, the .c code we are emitting has order-dependent decls. | |
| 434 | // `CType`s, forward decls, and non-functions first. | |
| 1080 | // NAV export block | |
| 1081 | for (c.exported_navs.values()) |code| { | |
| 1082 | f.appendBufAssumeCapacity(code.get(c)); | |
| 1083 | } | |
| 435 | 1084 | |
| 436 | { | |
| 437 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; | |
| 438 | defer export_names.deinit(gpa); | |
| 439 | try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count())); | |
| 440 | for (zcu.single_exports.values()) |export_index| { | |
| 441 | export_names.putAssumeCapacity(export_index.ptr(zcu).opts.name, {}); | |
| 442 | } | |
| 443 | for (zcu.multi_exports.values()) |info| { | |
| 444 | try export_names.ensureUnusedCapacity(gpa, info.len); | |
| 445 | for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| { | |
| 446 | export_names.putAssumeCapacity(@"export".opts.name, {}); | |
| 447 | } | |
| 1085 | // UAV forward declarations | |
| 1086 | for (need_uavs.keys()) |val| { | |
| 1087 | if (c.exported_uavs.contains(val)) continue; // the export was the declaration | |
| 1088 | const fwd_decl = c.uavs.getPtr(val).?.fwd_decl; | |
| 1089 | f.appendBufAssumeCapacity(fwd_decl.get(c)); | |
| 1090 | } | |
| 1091 | ||
| 1092 | // NAV forward declarations | |
| 1093 | for (need_navs.keys()) |nav| { | |
| 1094 | if (c.exported_navs.contains(nav)) continue; // the export was the declaration | |
| 1095 | if (ip.getNav(nav).getExtern(ip)) |e| { | |
| 1096 | if (export_names.contains(e.name)) continue; | |
| 448 | 1097 | } |
| 1098 | const fwd_decl = c.navs.getPtr(nav).?.fwd_decl; | |
| 1099 | f.appendBufAssumeCapacity(fwd_decl.get(c)); | |
| 1100 | } | |
| 449 | 1101 | |
| 450 | for (self.uavs.keys(), self.uavs.values()) |uav, *av_block| try self.flushAvBlock( | |
| 451 | pt, | |
| 452 | zcu.root_mod, | |
| 453 | &f, | |
| 454 | av_block, | |
| 455 | self.exported_uavs.getPtr(uav), | |
| 456 | export_names, | |
| 457 | .none, | |
| 1102 | // Lazy declarations | |
| 1103 | var lazy_decls_aw: std.Io.Writer.Allocating = .init(gpa); | |
| 1104 | defer lazy_decls_aw.deinit(); | |
| 1105 | { | |
| 1106 | var lazy_dg: codegen.DeclGen = .{ | |
| 1107 | .gpa = gpa, | |
| 1108 | .arena = arena, | |
| 1109 | .pt = pt, | |
| 1110 | .mod = pt.zcu.root_mod, | |
| 1111 | .owner_nav = .none, | |
| 1112 | .is_naked_fn = false, | |
| 1113 | .expected_block = null, | |
| 1114 | .error_msg = null, | |
| 1115 | .ctype_deps = .empty, | |
| 1116 | .uavs = .empty, | |
| 1117 | }; | |
| 1118 | defer { | |
| 1119 | assert(lazy_dg.uavs.count() == 0); | |
| 1120 | lazy_dg.ctype_deps.deinit(gpa); | |
| 1121 | } | |
| 1122 | const slice_const_u8_sentinel_0_cty: codegen.CType = try .lower( | |
| 1123 | .slice_const_u8_sentinel_0, | |
| 1124 | &lazy_dg.ctype_deps, | |
| 1125 | arena, | |
| 1126 | zcu, | |
| 458 | 1127 | ); |
| 459 | ||
| 460 | for (self.navs.keys(), self.navs.values()) |nav, *av_block| try self.flushAvBlock( | |
| 461 | pt, | |
| 462 | zcu.navFileScope(nav).mod.?, | |
| 463 | &f, | |
| 464 | av_block, | |
| 465 | self.exported_navs.getPtr(nav), | |
| 466 | export_names, | |
| 467 | if (ip.getNav(nav).getExtern(ip) != null) | |
| 468 | ip.getNav(nav).name.toOptional() | |
| 469 | else | |
| 470 | .none, | |
| 1128 | const slice_const_u8_sentinel_0_name = try std.fmt.allocPrint( | |
| 1129 | arena, | |
| 1130 | "{f}", | |
| 1131 | .{slice_const_u8_sentinel_0_cty.fmtTypeName(zcu)}, | |
| 471 | 1132 | ); |
| 1133 | codegen.genErrDecls(zcu, &lazy_decls_aw.writer, slice_const_u8_sentinel_0_name) catch |err| switch (err) { | |
| 1134 | error.WriteFailed => return error.OutOfMemory, | |
| 1135 | }; | |
| 1136 | for (need_tag_name_funcs.keys()) |enum_ty_ip| { | |
| 1137 | const enum_ty: Type = .fromInterned(enum_ty_ip); | |
| 1138 | const enum_cty: codegen.CType = try .lower( | |
| 1139 | enum_ty, | |
| 1140 | &lazy_dg.ctype_deps, | |
| 1141 | arena, | |
| 1142 | zcu, | |
| 1143 | ); | |
| 1144 | codegen.genTagNameFn( | |
| 1145 | zcu, | |
| 1146 | &lazy_decls_aw.writer, | |
| 1147 | slice_const_u8_sentinel_0_name, | |
| 1148 | enum_ty, | |
| 1149 | try std.fmt.allocPrint(arena, "{f}", .{enum_cty.fmtTypeName(zcu)}), | |
| 1150 | ) catch |err| switch (err) { | |
| 1151 | error.WriteFailed => return error.OutOfMemory, | |
| 1152 | }; | |
| 1153 | } | |
| 1154 | for (need_never_tail_funcs.keys()) |fn_nav| { | |
| 1155 | codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) { | |
| 1156 | error.WriteFailed => return error.OutOfMemory, | |
| 1157 | error.OutOfMemory => |e| return e, | |
| 1158 | error.AnalysisFail => unreachable, | |
| 1159 | }; | |
| 1160 | } | |
| 1161 | for (need_never_inline_funcs.keys()) |fn_nav| { | |
| 1162 | codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) { | |
| 1163 | error.WriteFailed => return error.OutOfMemory, | |
| 1164 | error.OutOfMemory => |e| return e, | |
| 1165 | error.AnalysisFail => unreachable, | |
| 1166 | }; | |
| 1167 | } | |
| 472 | 1168 | } |
| 473 | ||
| 474 | { | |
| 475 | // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. | |
| 476 | // This ensures that every lazy CType.Index exactly matches the global CType.Index. | |
| 477 | try f.ctype_pool.init(gpa); | |
| 478 | try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool); | |
| 479 | ||
| 480 | for (self.uavs.keys(), self.uavs.values()) |uav, av_block| { | |
| 481 | try self.flushCTypes(zcu, &f, .{ .uav = uav }, &av_block.ctype_pool); | |
| 1169 | f.appendBufAssumeCapacity(lazy_decls_aw.written()); | |
| 1170 | ||
| 1171 | // UAV definitions | |
| 1172 | for (need_uavs.keys(), need_uavs.values()) |val, overalign| { | |
| 1173 | const code = c.uavs.getPtr(val).?.code; | |
| 1174 | if (code.len == 0) continue; | |
| 1175 | if (!c.exported_uavs.contains(val)) { | |
| 1176 | f.appendBufAssumeCapacity("static "); | |
| 482 | 1177 | } |
| 483 | ||
| 484 | for (self.navs.keys(), self.navs.values()) |nav, av_block| { | |
| 485 | try self.flushCTypes(zcu, &f, .{ .nav = nav }, &av_block.ctype_pool); | |
| 1178 | if (overalign != .none) { | |
| 1179 | // As long as `Alignment` isn't too big, it's reasonable to just generate all possible | |
| 1180 | // alignment annotations statically into a LUT, which avoids allocating strings on this | |
| 1181 | // path. | |
| 1182 | comptime assert(@bitSizeOf(Alignment) < 8); | |
| 1183 | const table_len = (1 << @bitSizeOf(Alignment)) - 1; | |
| 1184 | const table: [table_len][]const u8 = comptime table: { | |
| 1185 | @setEvalBranchQuota(16_000); | |
| 1186 | var table: [table_len][]const u8 = undefined; | |
| 1187 | for (&table, 0..) |*str, log2_align| { | |
| 1188 | const byte_align = Alignment.fromLog2Units(log2_align).toByteUnits().?; | |
| 1189 | str.* = std.fmt.comptimePrint("zig_align({d}) ", .{byte_align}); | |
| 1190 | } | |
| 1191 | break :table table; | |
| 1192 | }; | |
| 1193 | f.appendBufAssumeCapacity(table[overalign.toLog2Units()]); | |
| 486 | 1194 | } |
| 1195 | f.appendBufAssumeCapacity(code.get(c)); | |
| 487 | 1196 | } |
| 488 | 1197 | |
| 489 | f.all_buffers.items[ctypes_index] = f.ctypes.items; | |
| 490 | f.file_size += f.ctypes.items.len; | |
| 491 | ||
| 492 | f.all_buffers.items[lazy_index] = f.lazy_fwd_decl.items; | |
| 493 | f.file_size += f.lazy_fwd_decl.items.len; | |
| 494 | ||
| 495 | // Now the code. | |
| 496 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2); | |
| 497 | f.appendBufAssumeCapacity(f.lazy_code.items); | |
| 498 | for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity( | |
| 499 | if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) { | |
| 500 | .@"extern" => .zig_extern, | |
| 501 | else => .static, | |
| 502 | }, | |
| 503 | self.getString(av_block.code), | |
| 504 | ); | |
| 505 | for (self.navs.keys(), self.navs.values()) |nav, av_block| f.appendCodeAssumeCapacity(storage: { | |
| 506 | if (self.exported_navs.contains(nav)) break :storage .default; | |
| 507 | if (ip.getNav(nav).getExtern(ip) != null) break :storage .zig_extern; | |
| 508 | break :storage .static; | |
| 509 | }, self.getString(av_block.code)); | |
| 1198 | // NAV definitions | |
| 1199 | for (need_navs.keys()) |nav| { | |
| 1200 | const code = c.navs.getPtr(nav).?.code; | |
| 1201 | if (code.len == 0) continue; | |
| 1202 | if (!c.exported_navs.contains(nav)) { | |
| 1203 | const is_extern = ip.getNav(nav).getExtern(ip) != null; | |
| 1204 | f.appendBufAssumeCapacity(if (is_extern) "zig_extern " else "static "); | |
| 1205 | } | |
| 1206 | f.appendBufAssumeCapacity(code.get(c)); | |
| 1207 | } | |
| 510 | 1208 | |
| 511 | const file = self.base.file.?; | |
| 1209 | // We've collected all of our buffers; it's now time to actually write the file! | |
| 1210 | const file = c.base.file.?; | |
| 512 | 1211 | file.setLength(io, f.file_size) catch |err| return diags.fail("failed to allocate file: {t}", .{err}); |
| 513 | 1212 | var fw = file.writer(io, &.{}); |
| 514 | 1213 | var w = &fw.interface; |
| 515 | 1214 | w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { |
| 516 | 1215 | error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{ |
| 517 | std.fmt.alt(self.base.emit, .formatEscapeChar), @errorName(fw.err.?), | |
| 1216 | std.fmt.alt(c.base.emit, .formatEscapeChar), @errorName(fw.err.?), | |
| 518 | 1217 | }), |
| 519 | 1218 | }; |
| 520 | 1219 | } |
| 521 | 1220 | |
| 522 | 1221 | const Flush = struct { |
| 523 | ctype_pool: codegen.CType.Pool, | |
| 524 | ctype_global_from_decl_map: std.ArrayList(codegen.CType), | |
| 525 | ctypes: std.ArrayList(u8), | |
| 526 | ||
| 527 | lazy_ctype_pool: codegen.CType.Pool, | |
| 528 | lazy_fns: LazyFns, | |
| 529 | lazy_fwd_decl: std.ArrayList(u8), | |
| 530 | lazy_code: std.ArrayList(u8), | |
| 531 | ||
| 532 | 1222 | /// We collect a list of buffers to write, and write them all at once with pwritev 😎 |
| 533 | 1223 | all_buffers: std.ArrayList([]const u8), |
| 534 | 1224 | /// Keeps track of the total bytes of `all_buffers`. |
| 535 | 1225 | file_size: u64, |
| 536 | 1226 | |
| 537 | const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void); | |
| 538 | ||
| 539 | 1227 | fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void { |
| 540 | 1228 | if (buf.len == 0) return; |
| 541 | 1229 | f.all_buffers.appendAssumeCapacity(buf); |
| 542 | 1230 | f.file_size += buf.len; |
| 543 | 1231 | } |
| 544 | 1232 | |
| 545 | fn appendCodeAssumeCapacity(f: *Flush, storage: enum { default, zig_extern, static }, code: []const u8) void { | |
| 546 | if (code.len == 0) return; | |
| 547 | f.appendBufAssumeCapacity(switch (storage) { | |
| 548 | .default => "\n", | |
| 549 | .zig_extern => "\nzig_extern ", | |
| 550 | .static => "\nstatic ", | |
| 551 | }); | |
| 552 | f.appendBufAssumeCapacity(code); | |
| 553 | } | |
| 554 | ||
| 555 | 1233 | fn deinit(f: *Flush, gpa: Allocator) void { |
| 556 | f.ctype_pool.deinit(gpa); | |
| 557 | assert(f.ctype_global_from_decl_map.items.len == 0); | |
| 558 | f.ctype_global_from_decl_map.deinit(gpa); | |
| 559 | f.ctypes.deinit(gpa); | |
| 560 | f.lazy_ctype_pool.deinit(gpa); | |
| 561 | f.lazy_fns.deinit(gpa); | |
| 562 | f.lazy_fwd_decl.deinit(gpa); | |
| 563 | f.lazy_code.deinit(gpa); | |
| 564 | 1234 | f.all_buffers.deinit(gpa); |
| 565 | 1235 | } |
| 566 | 1236 | }; |
| 567 | 1237 | |
| 568 | const FlushDeclError = error{ | |
| 569 | OutOfMemory, | |
| 570 | }; | |
| 571 | ||
| 572 | fn flushCTypes( | |
| 573 | self: *C, | |
| 574 | zcu: *Zcu, | |
| 575 | f: *Flush, | |
| 576 | pass: codegen.DeclGen.Pass, | |
| 577 | decl_ctype_pool: *const codegen.CType.Pool, | |
| 578 | ) FlushDeclError!void { | |
| 579 | const gpa = self.base.comp.gpa; | |
| 580 | const global_ctype_pool = &f.ctype_pool; | |
| 581 | ||
| 582 | const global_from_decl_map = &f.ctype_global_from_decl_map; | |
| 583 | assert(global_from_decl_map.items.len == 0); | |
| 584 | try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len); | |
| 585 | defer global_from_decl_map.clearRetainingCapacity(); | |
| 586 | ||
| 587 | var ctypes_aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &f.ctypes); | |
| 588 | const ctypes_bw = &ctypes_aw.writer; | |
| 589 | defer f.ctypes = ctypes_aw.toArrayList(); | |
| 590 | ||
| 591 | for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| { | |
| 592 | const PoolAdapter = struct { | |
| 593 | global_from_decl_map: []const codegen.CType, | |
| 594 | pub fn eql(pool_adapter: @This(), decl_ctype: codegen.CType, global_ctype: codegen.CType) bool { | |
| 595 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| | |
| 596 | decl_pool_index < pool_adapter.global_from_decl_map.len and | |
| 597 | pool_adapter.global_from_decl_map[decl_pool_index].eql(global_ctype) | |
| 598 | else | |
| 599 | decl_ctype.index == global_ctype.index; | |
| 600 | } | |
| 601 | pub fn copy(pool_adapter: @This(), decl_ctype: codegen.CType) codegen.CType { | |
| 602 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| | |
| 603 | pool_adapter.global_from_decl_map[decl_pool_index] | |
| 604 | else | |
| 605 | decl_ctype; | |
| 606 | } | |
| 607 | }; | |
| 608 | const decl_ctype = codegen.CType.fromPoolIndex(decl_ctype_pool_index); | |
| 609 | const global_ctype, const found_existing = try global_ctype_pool.getOrPutAdapted( | |
| 610 | gpa, | |
| 611 | decl_ctype_pool, | |
| 612 | decl_ctype, | |
| 613 | PoolAdapter{ .global_from_decl_map = global_from_decl_map.items }, | |
| 614 | ); | |
| 615 | global_from_decl_map.appendAssumeCapacity(global_ctype); | |
| 616 | codegen.genTypeDecl( | |
| 617 | zcu, | |
| 618 | ctypes_bw, | |
| 619 | global_ctype_pool, | |
| 620 | global_ctype, | |
| 621 | pass, | |
| 622 | decl_ctype_pool, | |
| 623 | decl_ctype, | |
| 624 | found_existing, | |
| 625 | ) catch |err| switch (err) { | |
| 626 | error.WriteFailed => return error.OutOfMemory, | |
| 627 | }; | |
| 628 | } | |
| 629 | } | |
| 1238 | pub fn updateExports( | |
| 1239 | c: *C, | |
| 1240 | pt: Zcu.PerThread, | |
| 1241 | exported: Zcu.Exported, | |
| 1242 | export_indices: []const Zcu.Export.Index, | |
| 1243 | ) Allocator.Error!void { | |
| 1244 | const zcu = pt.zcu; | |
| 1245 | const gpa = zcu.gpa; | |
| 630 | 1246 | |
| 631 | fn flushErrDecls(self: *C, pt: Zcu.PerThread, f: *Flush) FlushDeclError!void { | |
| 632 | const gpa = self.base.comp.gpa; | |
| 1247 | var arena: std.heap.ArenaAllocator = .init(gpa); | |
| 1248 | defer arena.deinit(); | |
| 633 | 1249 | |
| 634 | var object: codegen.Object = .{ | |
| 635 | .dg = .{ | |
| 636 | .gpa = gpa, | |
| 637 | .pt = pt, | |
| 638 | .mod = pt.zcu.root_mod, | |
| 639 | .error_msg = null, | |
| 640 | .pass = .flush, | |
| 641 | .is_naked_fn = false, | |
| 642 | .expected_block = null, | |
| 643 | .fwd_decl = undefined, | |
| 644 | .ctype_pool = f.lazy_ctype_pool, | |
| 645 | .scratch = .initBuffer(self.scratch_buf), | |
| 646 | .uavs = .empty, | |
| 647 | }, | |
| 648 | .code_header = undefined, | |
| 649 | .code = undefined, | |
| 650 | .indent_counter = 0, | |
| 1250 | var dg: codegen.DeclGen = .{ | |
| 1251 | .gpa = gpa, | |
| 1252 | .arena = arena.allocator(), | |
| 1253 | .pt = pt, | |
| 1254 | .mod = zcu.root_mod, | |
| 1255 | .owner_nav = .none, | |
| 1256 | .is_naked_fn = false, | |
| 1257 | .expected_block = null, | |
| 1258 | .error_msg = null, | |
| 1259 | .ctype_deps = .empty, | |
| 1260 | .uavs = .empty, | |
| 651 | 1261 | }; |
| 652 | object.dg.fwd_decl = .fromArrayList(gpa, &f.lazy_fwd_decl); | |
| 653 | object.code = .fromArrayList(gpa, &f.lazy_code); | |
| 654 | 1262 | defer { |
| 655 | object.dg.uavs.deinit(gpa); | |
| 656 | f.lazy_ctype_pool = object.dg.ctype_pool.move(); | |
| 657 | f.lazy_ctype_pool.freeUnusedCapacity(gpa); | |
| 658 | ||
| 659 | f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList(); | |
| 660 | f.lazy_code = object.code.toArrayList(); | |
| 661 | self.scratch_buf = object.dg.scratch.allocatedSlice(); | |
| 1263 | assert(dg.uavs.count() == 0); | |
| 1264 | dg.ctype_deps.deinit(gpa); | |
| 662 | 1265 | } |
| 663 | 1266 | |
| 664 | codegen.genErrDecls(&object) catch |err| switch (err) { | |
| 665 | error.AnalysisFail => unreachable, | |
| 666 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 667 | }; | |
| 668 | ||
| 669 | try self.addUavsFromCodegen(&object.dg.uavs); | |
| 670 | } | |
| 671 | ||
| 672 | fn flushLazyFn( | |
| 673 | self: *C, | |
| 674 | pt: Zcu.PerThread, | |
| 675 | mod: *Module, | |
| 676 | f: *Flush, | |
| 677 | lazy_ctype_pool: *const codegen.CType.Pool, | |
| 678 | lazy_fn: codegen.LazyFnMap.Entry, | |
| 679 | ) FlushDeclError!void { | |
| 680 | const gpa = self.base.comp.gpa; | |
| 681 | ||
| 682 | var object: codegen.Object = .{ | |
| 683 | .dg = .{ | |
| 684 | .gpa = gpa, | |
| 685 | .pt = pt, | |
| 686 | .mod = mod, | |
| 687 | .error_msg = null, | |
| 688 | .pass = .flush, | |
| 689 | .is_naked_fn = false, | |
| 690 | .expected_block = null, | |
| 691 | .fwd_decl = undefined, | |
| 692 | .ctype_pool = f.lazy_ctype_pool, | |
| 693 | .scratch = .initBuffer(self.scratch_buf), | |
| 694 | .uavs = .empty, | |
| 695 | }, | |
| 696 | .code_header = undefined, | |
| 697 | .code = undefined, | |
| 698 | .indent_counter = 0, | |
| 1267 | const code: String = code: { | |
| 1268 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); | |
| 1269 | defer c.string_bytes = aw.toArrayList(); | |
| 1270 | const start = aw.written().len; | |
| 1271 | codegen.genExports(&dg, &aw.writer, exported, export_indices) catch |err| switch (err) { | |
| 1272 | error.WriteFailed => return error.OutOfMemory, | |
| 1273 | error.OutOfMemory => |e| return e, | |
| 1274 | }; | |
| 1275 | break :code .{ | |
| 1276 | .start = @intCast(start), | |
| 1277 | .len = @intCast(aw.written().len - start), | |
| 1278 | }; | |
| 699 | 1279 | }; |
| 700 | object.dg.fwd_decl = .fromArrayList(gpa, &f.lazy_fwd_decl); | |
| 701 | object.code = .fromArrayList(gpa, &f.lazy_code); | |
| 702 | defer { | |
| 703 | // If this assert trips just handle the anon_decl_deps the same as | |
| 704 | // `updateFunc()` does. | |
| 705 | assert(object.dg.uavs.count() == 0); | |
| 706 | f.lazy_ctype_pool = object.dg.ctype_pool.move(); | |
| 707 | f.lazy_ctype_pool.freeUnusedCapacity(gpa); | |
| 708 | ||
| 709 | f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList(); | |
| 710 | f.lazy_code = object.code.toArrayList(); | |
| 711 | self.scratch_buf = object.dg.scratch.allocatedSlice(); | |
| 1280 | switch (exported) { | |
| 1281 | .nav => |nav| try c.exported_navs.put(gpa, nav, code), | |
| 1282 | .uav => |uav| try c.exported_uavs.put(gpa, uav, code), | |
| 712 | 1283 | } |
| 713 | ||
| 714 | codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) { | |
| 715 | error.AnalysisFail => unreachable, | |
| 716 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 717 | }; | |
| 718 | 1284 | } |
| 719 | 1285 | |
| 720 | fn flushLazyFns( | |
| 1286 | pub fn deleteExport( | |
| 721 | 1287 | self: *C, |
| 722 | pt: Zcu.PerThread, | |
| 723 | mod: *Module, | |
| 724 | f: *Flush, | |
| 725 | lazy_ctype_pool: *const codegen.CType.Pool, | |
| 726 | lazy_fns: codegen.LazyFnMap, | |
| 727 | ) FlushDeclError!void { | |
| 728 | const gpa = self.base.comp.gpa; | |
| 729 | try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count())); | |
| 730 | ||
| 731 | var it = lazy_fns.iterator(); | |
| 732 | while (it.next()) |entry| { | |
| 733 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); | |
| 734 | if (gop.found_existing) continue; | |
| 735 | gop.value_ptr.* = {}; | |
| 736 | try self.flushLazyFn(pt, mod, f, lazy_ctype_pool, entry); | |
| 1288 | exported: Zcu.Exported, | |
| 1289 | _: InternPool.NullTerminatedString, | |
| 1290 | ) void { | |
| 1291 | switch (exported) { | |
| 1292 | .nav => |nav| _ = self.exported_navs.swapRemove(nav), | |
| 1293 | .uav => |uav| _ = self.exported_uavs.swapRemove(uav), | |
| 737 | 1294 | } |
| 738 | 1295 | } |
| 739 | 1296 | |
| 740 | fn flushAvBlock( | |
| 741 | self: *C, | |
| 742 | pt: Zcu.PerThread, | |
| 743 | mod: *Module, | |
| 744 | f: *Flush, | |
| 745 | av_block: *const AvBlock, | |
| 746 | exported_block: ?*const ExportedBlock, | |
| 747 | export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), | |
| 748 | extern_name: InternPool.OptionalNullTerminatedString, | |
| 749 | ) FlushDeclError!void { | |
| 750 | const gpa = self.base.comp.gpa; | |
| 751 | try self.flushLazyFns(pt, mod, f, &av_block.ctype_pool, av_block.lazy_fns); | |
| 752 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); | |
| 753 | // avoid emitting extern decls that are already exported | |
| 754 | if (extern_name.unwrap()) |name| if (export_names.contains(name)) return; | |
| 755 | f.appendBufAssumeCapacity(self.getString(if (exported_block) |exported| | |
| 756 | exported.fwd_decl | |
| 757 | else | |
| 758 | av_block.fwd_decl)); | |
| 759 | } | |
| 1297 | fn mergeNeededCTypes( | |
| 1298 | c: *C, | |
| 1299 | need_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void), | |
| 1300 | need_errunion_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void), | |
| 1301 | need_aligned_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64), | |
| 1302 | deps: *const CTypeDependencies, | |
| 1303 | ) Allocator.Error!void { | |
| 1304 | const gpa = c.base.comp.gpa; | |
| 760 | 1305 | |
| 761 | pub fn flushEmitH(zcu: *Zcu) !void { | |
| 762 | const tracy = trace(@src()); | |
| 763 | defer tracy.end(); | |
| 1306 | const resolved = deps.get(c); | |
| 764 | 1307 | |
| 765 | if (true) return; // emit-h is regressed | |
| 1308 | try need_types.ensureUnusedCapacity(gpa, resolved.type.len + resolved.type_fwd.len); | |
| 1309 | try need_errunion_types.ensureUnusedCapacity(gpa, resolved.errunion_type.len + resolved.errunion_type_fwd.len); | |
| 1310 | try need_aligned_types.ensureUnusedCapacity(gpa, resolved.aligned_type_fwd.len); | |
| 766 | 1311 | |
| 767 | const emit_h = zcu.emit_h orelse return; | |
| 768 | const io = zcu.comp.io; | |
| 1312 | for (resolved.type) |index| need_types.putAssumeCapacity(index, {}); | |
| 1313 | for (resolved.type_fwd) |index| need_types.putAssumeCapacity(index, {}); | |
| 769 | 1314 | |
| 770 | // We collect a list of buffers to write, and write them all at once with pwritev 😎 | |
| 771 | const num_buffers = emit_h.decl_table.count() + 1; | |
| 772 | var all_buffers = try std.array_list.Managed(std.posix.iovec_const).initCapacity(zcu.gpa, num_buffers); | |
| 773 | defer all_buffers.deinit(); | |
| 1315 | for (resolved.errunion_type) |index| need_errunion_types.putAssumeCapacity(index, {}); | |
| 1316 | for (resolved.errunion_type_fwd) |index| need_errunion_types.putAssumeCapacity(index, {}); | |
| 774 | 1317 | |
| 775 | var file_size: u64 = zig_h.len; | |
| 776 | if (zig_h.len != 0) { | |
| 777 | all_buffers.appendAssumeCapacity(.{ | |
| 778 | .base = zig_h, | |
| 779 | .len = zig_h.len, | |
| 780 | }); | |
| 1318 | for (resolved.aligned_type_fwd, resolved.aligned_type_masks) |ty_index, align_mask| { | |
| 1319 | const gop = need_aligned_types.getOrPutAssumeCapacity(ty_index); | |
| 1320 | if (!gop.found_existing) gop.value_ptr.* = 0; | |
| 1321 | gop.value_ptr.* |= align_mask; | |
| 781 | 1322 | } |
| 1323 | } | |
| 782 | 1324 | |
| 783 | for (emit_h.decl_table.keys()) |decl_index| { | |
| 784 | const decl_emit_h = emit_h.declPtr(decl_index); | |
| 785 | const buf = decl_emit_h.fwd_decl.items; | |
| 786 | if (buf.len != 0) { | |
| 787 | all_buffers.appendAssumeCapacity(.{ | |
| 788 | .base = buf.ptr, | |
| 789 | .len = buf.len, | |
| 790 | }); | |
| 791 | file_size += buf.len; | |
| 1325 | fn mergeNeededUavs( | |
| 1326 | zcu: *const Zcu, | |
| 1327 | global: *std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 1328 | new: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 1329 | ) Allocator.Error!void { | |
| 1330 | const gpa = zcu.comp.gpa; | |
| 1331 | ||
| 1332 | try global.ensureUnusedCapacity(gpa, new.count()); | |
| 1333 | for (new.keys(), new.values()) |uav_val, need_align| { | |
| 1334 | const gop = global.getOrPutAssumeCapacity(uav_val); | |
| 1335 | if (!gop.found_existing) gop.value_ptr.* = .none; | |
| 1336 | ||
| 1337 | if (need_align != .none) { | |
| 1338 | const cur_align = switch (gop.value_ptr.*) { | |
| 1339 | .none => Value.fromInterned(uav_val).typeOf(zcu).abiAlignment(zcu), | |
| 1340 | else => |a| a, | |
| 1341 | }; | |
| 1342 | if (need_align.compareStrict(.gt, cur_align)) { | |
| 1343 | gop.value_ptr.* = need_align; | |
| 1344 | } | |
| 792 | 1345 | } |
| 793 | 1346 | } |
| 794 | ||
| 795 | const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory; | |
| 796 | const file = try directory.handle.createFile(io, emit_h.loc.basename, .{ | |
| 797 | // We set the end position explicitly below; by not truncating the file, we possibly | |
| 798 | // make it easier on the file system by doing 1 reallocation instead of two. | |
| 799 | .truncate = false, | |
| 800 | }); | |
| 801 | defer file.close(io); | |
| 802 | ||
| 803 | try file.setLength(io, file_size); | |
| 804 | try file.pwritevAll(all_buffers.items, 0); | |
| 805 | 1347 | } |
| 806 | 1348 | |
| 807 | pub fn updateExports( | |
| 808 | self: *C, | |
| 1349 | fn addCTypeDependencies( | |
| 1350 | c: *C, | |
| 809 | 1351 | pt: Zcu.PerThread, |
| 810 | exported: Zcu.Exported, | |
| 811 | export_indices: []const Zcu.Export.Index, | |
| 812 | ) !void { | |
| 813 | const zcu = pt.zcu; | |
| 814 | const gpa = zcu.gpa; | |
| 815 | const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) { | |
| 816 | .nav => |nav| .{ | |
| 817 | zcu.navFileScope(nav).mod.?, | |
| 818 | .{ .nav = nav }, | |
| 819 | self.navs.getPtr(nav).?, | |
| 820 | (try self.exported_navs.getOrPut(gpa, nav)).value_ptr, | |
| 821 | }, | |
| 822 | .uav => |uav| .{ | |
| 823 | zcu.root_mod, | |
| 824 | .{ .uav = uav }, | |
| 825 | self.uavs.getPtr(uav).?, | |
| 826 | (try self.exported_uavs.getOrPut(gpa, uav)).value_ptr, | |
| 827 | }, | |
| 828 | }; | |
| 829 | const ctype_pool = &decl_block.ctype_pool; | |
| 830 | var dg: codegen.DeclGen = .{ | |
| 831 | .gpa = gpa, | |
| 832 | .pt = pt, | |
| 833 | .mod = mod, | |
| 834 | .error_msg = null, | |
| 835 | .pass = pass, | |
| 836 | .is_naked_fn = false, | |
| 837 | .expected_block = null, | |
| 838 | .fwd_decl = undefined, | |
| 839 | .ctype_pool = decl_block.ctype_pool, | |
| 840 | .scratch = .initBuffer(self.scratch_buf), | |
| 841 | .uavs = .empty, | |
| 842 | }; | |
| 843 | dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); | |
| 844 | defer { | |
| 845 | assert(dg.uavs.count() == 0); | |
| 846 | ctype_pool.* = dg.ctype_pool.move(); | |
| 847 | ctype_pool.freeUnusedCapacity(gpa); | |
| 1352 | deps: *const codegen.CType.Dependencies, | |
| 1353 | ) Allocator.Error!CTypeDependencies { | |
| 1354 | const gpa = pt.zcu.comp.gpa; | |
| 1355 | ||
| 1356 | try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count()); | |
| 1357 | for (deps.bigint.keys()) |bigint| c.bigint_types.putAssumeCapacity(bigint, {}); | |
| 1358 | ||
| 1359 | const type_start = c.type_dependencies.items.len; | |
| 1360 | const errunion_type_start = type_start + deps.type.count(); | |
| 1361 | const type_fwd_start = errunion_type_start + deps.errunion_type.count(); | |
| 1362 | const errunion_type_fwd_start = type_fwd_start + deps.type_fwd.count(); | |
| 1363 | const aligned_type_fwd_start = errunion_type_fwd_start + deps.errunion_type_fwd.count(); | |
| 1364 | try c.type_dependencies.appendNTimes(gpa, undefined, deps.type.count() + | |
| 1365 | deps.errunion_type.count() + | |
| 1366 | deps.type_fwd.count() + | |
| 1367 | deps.errunion_type_fwd.count() + | |
| 1368 | deps.aligned_type_fwd.count()); | |
| 1369 | ||
| 1370 | const align_mask_start = c.align_dependency_masks.items.len; | |
| 1371 | try c.align_dependency_masks.appendSlice(gpa, deps.aligned_type_fwd.values()); | |
| 1372 | ||
| 1373 | for (deps.type.keys(), type_start..) |ty, i| { | |
| 1374 | const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); | |
| 1375 | c.type_dependencies.items[i] = pool_index; | |
| 1376 | } | |
| 848 | 1377 | |
| 849 | self.fwd_decl_buf = dg.fwd_decl.toArrayList().allocatedSlice(); | |
| 850 | self.scratch_buf = dg.scratch.allocatedSlice(); | |
| 1378 | for (deps.errunion_type.keys(), errunion_type_start..) |ty, i| { | |
| 1379 | const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); | |
| 1380 | c.type_dependencies.items[i] = pool_index; | |
| 851 | 1381 | } |
| 852 | codegen.genExports(&dg, exported, export_indices) catch |err| switch (err) { | |
| 853 | error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, | |
| 1382 | ||
| 1383 | for (deps.type_fwd.keys(), type_fwd_start..) |ty, i| { | |
| 1384 | const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); | |
| 1385 | c.type_dependencies.items[i] = pool_index; | |
| 1386 | } | |
| 1387 | ||
| 1388 | for (deps.errunion_type_fwd.keys(), errunion_type_fwd_start..) |ty, i| { | |
| 1389 | const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); | |
| 1390 | c.type_dependencies.items[i] = pool_index; | |
| 1391 | } | |
| 1392 | ||
| 1393 | for (deps.aligned_type_fwd.keys(), aligned_type_fwd_start..) |ty, i| { | |
| 1394 | const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); | |
| 1395 | c.type_dependencies.items[i] = pool_index; | |
| 1396 | } | |
| 1397 | ||
| 1398 | return .{ | |
| 1399 | .len = @intCast(deps.type.count()), | |
| 1400 | .errunion_len = @intCast(deps.errunion_type.count()), | |
| 1401 | .fwd_len = @intCast(deps.type_fwd.count()), | |
| 1402 | .errunion_fwd_len = @intCast(deps.errunion_type_fwd.count()), | |
| 1403 | .aligned_fwd_len = @intCast(deps.aligned_type_fwd.count()), | |
| 1404 | .type_start = @intCast(type_start), | |
| 1405 | .align_mask_start = @intCast(align_mask_start), | |
| 854 | 1406 | }; |
| 855 | exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.written()) }; | |
| 856 | 1407 | } |
| 857 | 1408 | |
| 858 | pub fn deleteExport( | |
| 859 | self: *C, | |
| 860 | exported: Zcu.Exported, | |
| 861 | _: InternPool.NullTerminatedString, | |
| 862 | ) void { | |
| 863 | switch (exported) { | |
| 864 | .nav => |nav| _ = self.exported_navs.swapRemove(nav), | |
| 865 | .uav => |uav| _ = self.exported_uavs.swapRemove(uav), | |
| 1409 | fn updateNewUavs(c: *C, pt: Zcu.PerThread, old_uavs_len: usize) Allocator.Error!void { | |
| 1410 | const gpa = pt.zcu.comp.gpa; | |
| 1411 | var index = old_uavs_len; | |
| 1412 | while (index < c.uavs.count()) : (index += 1) { | |
| 1413 | // `new_uavs` is UAVs discovered while lowering *this* UAV. | |
| 1414 | const new_uavs: []const InternPool.Index = new: { | |
| 1415 | c.uavs.lockPointers(); | |
| 1416 | defer c.uavs.unlockPointers(); | |
| 1417 | const val: Value = .fromInterned(c.uavs.keys()[index]); | |
| 1418 | const rendered_decl = &c.uavs.values()[index]; | |
| 1419 | rendered_decl.* = .init; | |
| 1420 | try c.updateUav(pt, val, rendered_decl); | |
| 1421 | break :new rendered_decl.need_uavs.keys(); | |
| 1422 | }; | |
| 1423 | try c.uavs.ensureUnusedCapacity(gpa, new_uavs.len); | |
| 1424 | for (new_uavs) |val| { | |
| 1425 | const gop = c.uavs.getOrPutAssumeCapacity(val); | |
| 1426 | if (!gop.found_existing) { | |
| 1427 | assert(gop.index > index); | |
| 1428 | } | |
| 1429 | } | |
| 866 | 1430 | } |
| 867 | 1431 | } |
| 868 | 1432 | |
| 869 | fn addUavsFromCodegen(c: *C, uavs: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment)) Allocator.Error!void { | |
| 870 | const gpa = c.base.comp.gpa; | |
| 871 | try c.uavs.ensureUnusedCapacity(gpa, uavs.count()); | |
| 872 | try c.aligned_uavs.ensureUnusedCapacity(gpa, uavs.count()); | |
| 873 | for (uavs.keys(), uavs.values()) |uav_val, uav_align| { | |
| 874 | { | |
| 875 | const gop = c.uavs.getOrPutAssumeCapacity(uav_val); | |
| 876 | if (!gop.found_existing) gop.value_ptr.* = .{}; | |
| 1433 | const FlushTypes = struct { | |
| 1434 | c: *C, | |
| 1435 | f: *Flush, | |
| 1436 | ||
| 1437 | aligned_types: *const std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64), | |
| 1438 | aligned_type_strings: []const []const u8, | |
| 1439 | ||
| 1440 | status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, bool), | |
| 1441 | errunion_status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, bool), | |
| 1442 | aligned_status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void), | |
| 1443 | ||
| 1444 | fn processDeps(ft: *FlushTypes, deps: *const CTypeDependencies) void { | |
| 1445 | const resolved = deps.get(ft.c); | |
| 1446 | for (resolved.type) |pool_index| ft.doType(pool_index); | |
| 1447 | for (resolved.type_fwd) |pool_index| ft.doTypeFwd(pool_index); | |
| 1448 | for (resolved.errunion_type) |pool_index| ft.doErrunionType(pool_index); | |
| 1449 | for (resolved.errunion_type_fwd) |pool_index| ft.doErrunionTypeFwd(pool_index); | |
| 1450 | for (resolved.aligned_type_fwd) |pool_index| ft.doAlignedTypeFwd(pool_index); | |
| 1451 | } | |
| 1452 | fn processDepsAsFwd(ft: *FlushTypes, deps: *const CTypeDependencies) void { | |
| 1453 | const resolved = deps.get(ft.c); | |
| 1454 | for (resolved.type) |pool_index| ft.doTypeFwd(pool_index); | |
| 1455 | for (resolved.type_fwd) |pool_index| ft.doTypeFwd(pool_index); | |
| 1456 | for (resolved.errunion_type) |pool_index| ft.doErrunionTypeFwd(pool_index); | |
| 1457 | for (resolved.errunion_type_fwd) |pool_index| ft.doErrunionTypeFwd(pool_index); | |
| 1458 | for (resolved.aligned_type_fwd) |pool_index| ft.doAlignedTypeFwd(pool_index); | |
| 1459 | } | |
| 1460 | ||
| 1461 | fn doAlignedTypeFwd(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { | |
| 1462 | const c = ft.c; | |
| 1463 | if (ft.aligned_status.contains(pool_index)) return; | |
| 1464 | if (ft.aligned_types.getIndex(pool_index)) |i| { | |
| 1465 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 1466 | ft.processDepsAsFwd(&rendered.deps); | |
| 1467 | ft.f.appendBufAssumeCapacity(ft.aligned_type_strings[i]); | |
| 877 | 1468 | } |
| 878 | if (uav_align != .none) { | |
| 879 | const gop = c.aligned_uavs.getOrPutAssumeCapacity(uav_val); | |
| 880 | gop.value_ptr.* = if (gop.found_existing) max: { | |
| 881 | break :max gop.value_ptr.*.maxStrict(uav_align); | |
| 882 | } else uav_align; | |
| 1469 | ft.aligned_status.putAssumeCapacity(pool_index, {}); | |
| 1470 | } | |
| 1471 | fn doTypeFwd(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { | |
| 1472 | const c = ft.c; | |
| 1473 | if (ft.status.contains(pool_index)) return; | |
| 1474 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 1475 | if (rendered.fwd_decl.len > 0) { | |
| 1476 | ft.f.appendBufAssumeCapacity(rendered.fwd_decl.get(c)); | |
| 1477 | ft.status.putAssumeCapacityNoClobber(pool_index, false); | |
| 1478 | } else { | |
| 1479 | ft.processDepsAsFwd(&rendered.definition_deps); | |
| 1480 | const gop = ft.status.getOrPutAssumeCapacity(pool_index); | |
| 1481 | if (!gop.found_existing) { | |
| 1482 | gop.value_ptr.* = false; | |
| 1483 | ft.f.appendBufAssumeCapacity(rendered.definition.get(c)); | |
| 1484 | } | |
| 883 | 1485 | } |
| 884 | 1486 | } |
| 885 | } | |
| 1487 | fn doType(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { | |
| 1488 | const c = ft.c; | |
| 1489 | if (ft.status.get(pool_index)) |completed| { | |
| 1490 | if (completed) return; | |
| 1491 | } | |
| 1492 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 1493 | ft.processDeps(&rendered.definition_deps); | |
| 1494 | if (rendered.fwd_decl.len == 0 and ft.status.contains(pool_index)) { | |
| 1495 | // `doTypeFwd` already rendered the defintion, we just had to complete the type by | |
| 1496 | // fully resolving its dependencies. | |
| 1497 | } else if (rendered.definition.len > 0) { | |
| 1498 | ft.f.appendBufAssumeCapacity(rendered.definition.get(c)); | |
| 1499 | } else if (!ft.status.contains(pool_index)) { | |
| 1500 | // The type will never be completed, but it must be forward declared to avoid it being | |
| 1501 | // declared in the wrong scope. | |
| 1502 | ft.f.appendBufAssumeCapacity(rendered.fwd_decl.get(c)); | |
| 1503 | } | |
| 1504 | ft.status.putAssumeCapacity(pool_index, true); | |
| 1505 | } | |
| 1506 | fn doErrunionTypeFwd(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { | |
| 1507 | const c = ft.c; | |
| 1508 | const gop = ft.errunion_status.getOrPutAssumeCapacity(pool_index); | |
| 1509 | if (gop.found_existing) return; | |
| 1510 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 1511 | ft.f.appendBufAssumeCapacity(rendered.errunion_fwd_decl.get(c)); | |
| 1512 | gop.value_ptr.* = false; | |
| 1513 | } | |
| 1514 | fn doErrunionType(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { | |
| 1515 | const c = ft.c; | |
| 1516 | if (ft.errunion_status.get(pool_index)) |completed| { | |
| 1517 | if (completed) return; | |
| 1518 | } | |
| 1519 | const rendered = &c.types.items[@intFromEnum(pool_index)]; | |
| 1520 | ft.processDeps(&rendered.deps); | |
| 1521 | if (rendered.errunion_definition.len > 0) { | |
| 1522 | ft.f.appendBufAssumeCapacity(rendered.errunion_definition.get(c)); | |
| 1523 | } else { | |
| 1524 | // The error union type will never be completed, but forward declare it to avoid the | |
| 1525 | // type being first declared in a different scope. | |
| 1526 | ft.f.appendBufAssumeCapacity(rendered.errunion_fwd_decl.get(c)); | |
| 1527 | } | |
| 1528 | ft.errunion_status.putAssumeCapacity(pool_index, true); | |
| 1529 | } | |
| 1530 | }; |
src/link/Coff.zig+1-1| ... | ... | @@ -1552,7 +1552,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 1552 | 1552 | const sec_si = try coff.navSection(zcu, nav.status.fully_resolved); |
| 1553 | 1553 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 1554 | 1554 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| 1555 | .alignment = pt.navAlignment(nav_index).toStdMem(), | |
| 1555 | .alignment = zcu.navAlignment(nav_index).toStdMem(), | |
| 1556 | 1556 | .moved = true, |
| 1557 | 1557 | }); |
| 1558 | 1558 | coff.nodes.appendAssumeCapacity(.{ .nav = nmi }); |
src/link/ConstPool.zig created+288| ... | ... | @@ -0,0 +1,288 @@ |
| 1 | /// Helper type for debug information implementations (such as `link.Dwarf`) to help them emit | |
| 2 | /// information about comptime-known values (constants), including types. | |
| 3 | /// | |
| 4 | /// Every constant with associated debug information is assigned an `Index` by calling `get`. The | |
| 5 | /// pool will track which container types do and do not have a resolved layout, as well as which | |
| 6 | /// constants in the pool depend on which types, and call into the implementation to emit debug | |
| 7 | /// information for a constant only when all information is available. | |
| 8 | /// | |
| 9 | /// Indices into the pool are dense, and constants are never removed from the pool, so the debug | |
| 10 | /// info implementation can store information for each one with a simple `ArrayList`. | |
| 11 | /// | |
| 12 | /// To use `ConstPool`, the debug info implementation is required to: | |
| 13 | /// * forward `updateContainerType` calls to its `ConstPool` | |
| 14 | /// * expose some callback functions---see functions in `User` | |
| 15 | /// * ensure that any `get` call is eventually followed by a `flushPending` call | |
| 16 | const ConstPool = @This(); | |
| 17 | ||
| 18 | values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 19 | pending: std.ArrayList(Index), | |
| 20 | complete_containers: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 21 | container_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, ContainerDepEntry.Index), | |
| 22 | container_dep_entries: std.ArrayList(ContainerDepEntry), | |
| 23 | ||
| 24 | pub const empty: ConstPool = .{ | |
| 25 | .values = .empty, | |
| 26 | .pending = .empty, | |
| 27 | .complete_containers = .empty, | |
| 28 | .container_deps = .empty, | |
| 29 | .container_dep_entries = .empty, | |
| 30 | }; | |
| 31 | ||
| 32 | pub fn deinit(pool: *ConstPool, gpa: Allocator) void { | |
| 33 | pool.values.deinit(gpa); | |
| 34 | pool.pending.deinit(gpa); | |
| 35 | pool.complete_containers.deinit(gpa); | |
| 36 | pool.container_deps.deinit(gpa); | |
| 37 | pool.container_dep_entries.deinit(gpa); | |
| 38 | } | |
| 39 | ||
| 40 | pub const Index = enum(u32) { | |
| 41 | _, | |
| 42 | pub fn val(i: Index, pool: *const ConstPool) InternPool.Index { | |
| 43 | return pool.values.keys()[@intFromEnum(i)]; | |
| 44 | } | |
| 45 | }; | |
| 46 | ||
| 47 | pub const User = union(enum) { | |
| 48 | dwarf: *@import("Dwarf.zig"), | |
| 49 | c: *@import("C.zig"), | |
| 50 | llvm: @import("../codegen/llvm.zig").Object.Ptr, | |
| 51 | ||
| 52 | /// Inform the debug info implementation that the new constant `val` was added to the pool at | |
| 53 | /// the given index (which equals the current pool length) due to a `get` call. It is guaranteed | |
| 54 | /// that there will eventually be a call to either `updateConst` or `updateConstIncomplete` | |
| 55 | /// following the `addConst` call, to actually populate the constant's debug info. | |
| 56 | fn addConst( | |
| 57 | user: User, | |
| 58 | pt: Zcu.PerThread, | |
| 59 | index: Index, | |
| 60 | val: InternPool.Index, | |
| 61 | ) Allocator.Error!void { | |
| 62 | switch (user) { | |
| 63 | inline else => |impl| return impl.addConst(pt, index, val), | |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 67 | /// Tell the debug info implementation to emit information for the constant `val`, which is in | |
| 68 | /// the pool at the given index. `val` is "complete", which means: | |
| 69 | /// * If it is a type, its layout is known. | |
| 70 | /// * Otherwise, the layout of its type is known. | |
| 71 | fn updateConst( | |
| 72 | user: User, | |
| 73 | pt: Zcu.PerThread, | |
| 74 | index: Index, | |
| 75 | val: InternPool.Index, | |
| 76 | ) Allocator.Error!void { | |
| 77 | switch (user) { | |
| 78 | inline else => |impl| return impl.updateConst(pt, index, val), | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | /// Tell the debug info implementation to emit information for the constant `val`, which is in | |
| 83 | /// the pool at the given index. `val` is "incomplete", meaning the implementation cannot emit | |
| 84 | /// full information for it (for instance, perhaps it is a struct type which was never actually | |
| 85 | /// initialized so never had its layout resolved). Instead, the implementation must emit some | |
| 86 | /// form of placeholder entry representing an incomplete/unknown constant. | |
| 87 | fn updateConstIncomplete( | |
| 88 | user: User, | |
| 89 | pt: Zcu.PerThread, | |
| 90 | index: Index, | |
| 91 | val: InternPool.Index, | |
| 92 | ) Allocator.Error!void { | |
| 93 | switch (user) { | |
| 94 | inline else => |impl| return impl.updateConstIncomplete(pt, index, val), | |
| 95 | } | |
| 96 | } | |
| 97 | }; | |
| 98 | ||
| 99 | const ContainerDepEntry = extern struct { | |
| 100 | next: ContainerDepEntry.Index.Optional, | |
| 101 | depender: ConstPool.Index, | |
| 102 | const Index = enum(u32) { | |
| 103 | _, | |
| 104 | const Optional = enum(u32) { | |
| 105 | none = std.math.maxInt(u32), | |
| 106 | _, | |
| 107 | fn unwrap(o: Optional) ?ContainerDepEntry.Index { | |
| 108 | return switch (o) { | |
| 109 | .none => null, | |
| 110 | else => @enumFromInt(@intFromEnum(o)), | |
| 111 | }; | |
| 112 | } | |
| 113 | }; | |
| 114 | fn toOptional(i: ContainerDepEntry.Index) Optional { | |
| 115 | return @enumFromInt(@intFromEnum(i)); | |
| 116 | } | |
| 117 | fn ptr(i: ContainerDepEntry.Index, pool: *ConstPool) *ContainerDepEntry { | |
| 118 | return &pool.container_dep_entries.items[@intFromEnum(i)]; | |
| 119 | } | |
| 120 | }; | |
| 121 | }; | |
| 122 | ||
| 123 | /// Calls to `link.File.updateContainerType` must be forwarded to this function so that the debug | |
| 124 | /// constant pool has up-to-date information about the resolution status of types. | |
| 125 | pub fn updateContainerType( | |
| 126 | pool: *ConstPool, | |
| 127 | pt: Zcu.PerThread, | |
| 128 | user: User, | |
| 129 | container_ty: InternPool.Index, | |
| 130 | success: bool, | |
| 131 | ) Allocator.Error!void { | |
| 132 | if (success) { | |
| 133 | const gpa = pt.zcu.comp.gpa; | |
| 134 | try pool.complete_containers.put(gpa, container_ty, {}); | |
| 135 | } else { | |
| 136 | _ = pool.complete_containers.fetchSwapRemove(container_ty); | |
| 137 | } | |
| 138 | var opt_dep = pool.container_deps.get(container_ty); | |
| 139 | while (opt_dep) |dep| : (opt_dep = dep.ptr(pool).next.unwrap()) { | |
| 140 | try pool.update(pt, user, dep.ptr(pool).depender); | |
| 141 | } | |
| 142 | } | |
| 143 | ||
| 144 | /// After this is called, there may be a constant for which debug information (complete or not) has | |
| 145 | /// not yet been emitted, so the user must call `flushPending` at some point after this call. | |
| 146 | pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) Allocator.Error!ConstPool.Index { | |
| 147 | const zcu = pt.zcu; | |
| 148 | const ip = &zcu.intern_pool; | |
| 149 | const gpa = zcu.comp.gpa; | |
| 150 | const gop = try pool.values.getOrPut(gpa, val); | |
| 151 | const index: ConstPool.Index = @enumFromInt(gop.index); | |
| 152 | if (!gop.found_existing) { | |
| 153 | const ty: Type = switch (ip.typeOf(val)) { | |
| 154 | .type_type => if (ip.isUndef(val)) .type else .fromInterned(val), | |
| 155 | else => |ty| .fromInterned(ty), | |
| 156 | }; | |
| 157 | try pool.registerTypeDeps(index, ty, zcu); | |
| 158 | try pool.pending.append(gpa, index); | |
| 159 | try user.addConst(pt, index, val); | |
| 160 | } | |
| 161 | return index; | |
| 162 | } | |
| 163 | pub fn flushPending(pool: *ConstPool, pt: Zcu.PerThread, user: User) Allocator.Error!void { | |
| 164 | while (pool.pending.pop()) |pending_ty| { | |
| 165 | try pool.update(pt, user, pending_ty); | |
| 166 | } | |
| 167 | } | |
| 168 | ||
| 169 | fn update(pool: *ConstPool, pt: Zcu.PerThread, user: User, index: ConstPool.Index) Allocator.Error!void { | |
| 170 | const zcu = pt.zcu; | |
| 171 | const ip = &zcu.intern_pool; | |
| 172 | const val = index.val(pool); | |
| 173 | const ty: Type = switch (ip.typeOf(val)) { | |
| 174 | .type_type => if (ip.isUndef(val)) .type else .fromInterned(val), | |
| 175 | else => |ty| .fromInterned(ty), | |
| 176 | }; | |
| 177 | if (pool.checkType(ty, zcu)) { | |
| 178 | try user.updateConst(pt, index, val); | |
| 179 | } else { | |
| 180 | try user.updateConstIncomplete(pt, index, val); | |
| 181 | } | |
| 182 | } | |
| 183 | fn checkType(pool: *const ConstPool, ty: Type, zcu: *const Zcu) bool { | |
| 184 | if (ty.isGenericPoison()) return true; | |
| 185 | return switch (ty.zigTypeTag(zcu)) { | |
| 186 | .type, | |
| 187 | .void, | |
| 188 | .bool, | |
| 189 | .noreturn, | |
| 190 | .int, | |
| 191 | .float, | |
| 192 | .pointer, | |
| 193 | .comptime_float, | |
| 194 | .comptime_int, | |
| 195 | .undefined, | |
| 196 | .null, | |
| 197 | .error_set, | |
| 198 | .@"opaque", | |
| 199 | .frame, | |
| 200 | .@"anyframe", | |
| 201 | .enum_literal, | |
| 202 | => true, | |
| 203 | ||
| 204 | .array, .vector => pool.checkType(ty.childType(zcu), zcu), | |
| 205 | .optional => pool.checkType(ty.optionalChild(zcu), zcu), | |
| 206 | .error_union => pool.checkType(ty.errorUnionPayload(zcu), zcu), | |
| 207 | .@"fn" => { | |
| 208 | const ip = &zcu.intern_pool; | |
| 209 | const func = ip.indexToKey(ty.toIntern()).func_type; | |
| 210 | for (func.param_types.get(ip)) |param_ty_ip| { | |
| 211 | if (!pool.checkType(.fromInterned(param_ty_ip), zcu)) return false; | |
| 212 | } | |
| 213 | return pool.checkType(.fromInterned(func.return_type), zcu); | |
| 214 | }, | |
| 215 | .@"struct" => if (ty.isTuple(zcu)) { | |
| 216 | for (0..ty.structFieldCount(zcu)) |field_index| { | |
| 217 | if (!pool.checkType(ty.fieldType(field_index, zcu), zcu)) return false; | |
| 218 | } | |
| 219 | return true; | |
| 220 | } else { | |
| 221 | return pool.complete_containers.contains(ty.toIntern()); | |
| 222 | }, | |
| 223 | .@"union", .@"enum" => { | |
| 224 | return pool.complete_containers.contains(ty.toIntern()); | |
| 225 | }, | |
| 226 | }; | |
| 227 | } | |
| 228 | fn registerTypeDeps(pool: *ConstPool, root: Index, ty: Type, zcu: *const Zcu) Allocator.Error!void { | |
| 229 | if (ty.isGenericPoison()) return; | |
| 230 | switch (ty.zigTypeTag(zcu)) { | |
| 231 | .type, | |
| 232 | .void, | |
| 233 | .bool, | |
| 234 | .noreturn, | |
| 235 | .int, | |
| 236 | .float, | |
| 237 | .pointer, | |
| 238 | .comptime_float, | |
| 239 | .comptime_int, | |
| 240 | .undefined, | |
| 241 | .null, | |
| 242 | .error_set, | |
| 243 | .@"opaque", | |
| 244 | .frame, | |
| 245 | .@"anyframe", | |
| 246 | .enum_literal, | |
| 247 | => {}, | |
| 248 | ||
| 249 | .array, .vector => try pool.registerTypeDeps(root, ty.childType(zcu), zcu), | |
| 250 | .optional => try pool.registerTypeDeps(root, ty.optionalChild(zcu), zcu), | |
| 251 | .error_union => try pool.registerTypeDeps(root, ty.errorUnionPayload(zcu), zcu), | |
| 252 | .@"fn" => { | |
| 253 | const ip = &zcu.intern_pool; | |
| 254 | const func = ip.indexToKey(ty.toIntern()).func_type; | |
| 255 | for (func.param_types.get(ip)) |param_ty_ip| { | |
| 256 | try pool.registerTypeDeps(root, .fromInterned(param_ty_ip), zcu); | |
| 257 | } | |
| 258 | try pool.registerTypeDeps(root, .fromInterned(func.return_type), zcu); | |
| 259 | }, | |
| 260 | .@"struct", .@"union", .@"enum" => if (ty.isTuple(zcu)) { | |
| 261 | for (0..ty.structFieldCount(zcu)) |field_index| { | |
| 262 | try pool.registerTypeDeps(root, ty.fieldType(field_index, zcu), zcu); | |
| 263 | } | |
| 264 | } else { | |
| 265 | // `ty` is a container; register the dependency. | |
| 266 | ||
| 267 | const gpa = zcu.comp.gpa; | |
| 268 | try pool.container_deps.ensureUnusedCapacity(gpa, 1); | |
| 269 | try pool.container_dep_entries.ensureUnusedCapacity(gpa, 1); | |
| 270 | errdefer comptime unreachable; | |
| 271 | ||
| 272 | const gop = pool.container_deps.getOrPutAssumeCapacity(ty.toIntern()); | |
| 273 | const entry: ContainerDepEntry.Index = @enumFromInt(pool.container_dep_entries.items.len); | |
| 274 | pool.container_dep_entries.appendAssumeCapacity(.{ | |
| 275 | .next = if (gop.found_existing) gop.value_ptr.toOptional() else .none, | |
| 276 | .depender = root, | |
| 277 | }); | |
| 278 | gop.value_ptr.* = entry; | |
| 279 | }, | |
| 280 | } | |
| 281 | } | |
| 282 | ||
| 283 | const std = @import("std"); | |
| 284 | const Allocator = std.mem.Allocator; | |
| 285 | ||
| 286 | const InternPool = @import("../InternPool.zig"); | |
| 287 | const Type = @import("../Type.zig"); | |
| 288 | const Zcu = @import("../Zcu.zig"); |
src/link/Dwarf.zig+828-918| ... | ... | @@ -25,9 +25,11 @@ format: DW.Format, |
| 25 | 25 | endian: std.builtin.Endian, |
| 26 | 26 | address_size: AddressSize, |
| 27 | 27 | |
| 28 | const_pool: link.ConstPool, | |
| 29 | ||
| 28 | 30 | mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo), |
| 29 | types: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), | |
| 30 | values: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), | |
| 31 | /// Indices are `link.ConstPool.Index`. | |
| 32 | values: std.ArrayList(struct { Unit.Index, Entry.Index }), | |
| 31 | 33 | navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), |
| 32 | 34 | decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index), |
| 33 | 35 | |
| ... | ... | @@ -1034,15 +1036,14 @@ const Entry = struct { |
| 1034 | 1036 | }); |
| 1035 | 1037 | const zcu = dwarf.bin_file.comp.zcu.?; |
| 1036 | 1038 | const ip = &zcu.intern_pool; |
| 1037 | for (dwarf.types.keys(), dwarf.types.values()) |ty, other_entry| { | |
| 1038 | const ty_unit: Unit.Index = if (Type.fromInterned(ty).typeDeclInst(zcu)) |inst_index| | |
| 1039 | dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?) catch unreachable | |
| 1040 | else | |
| 1041 | .main; | |
| 1042 | if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry) | |
| 1043 | log.err("missing Type({f}({d}))", .{ | |
| 1044 | Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }), | |
| 1045 | @intFromEnum(ty), | |
| 1039 | for (0.., dwarf.values.items) |raw_index, unit_and_entry| { | |
| 1040 | const index: link.ConstPool.Index = @enumFromInt(raw_index); | |
| 1041 | const val = index.val(&dwarf.const_pool); | |
| 1042 | const val_unit, const val_entry = unit_and_entry; | |
| 1043 | if (sec.getUnit(val_unit) == unit and unit.getEntry(val_entry) == entry) | |
| 1044 | log.err("missing Value({f}({d}))", .{ | |
| 1045 | Value.fromInterned(val).fmtValue(.{ .tid = .main, .zcu = zcu }), | |
| 1046 | @intFromEnum(val), | |
| 1046 | 1047 | }); |
| 1047 | 1048 | } |
| 1048 | 1049 | for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| { |
| ... | ... | @@ -1520,7 +1521,6 @@ pub const WipNav = struct { |
| 1520 | 1521 | debug_info: Writer.Allocating, |
| 1521 | 1522 | debug_line: Writer.Allocating, |
| 1522 | 1523 | debug_loclists: Writer.Allocating, |
| 1523 | pending_lazy: PendingLazy, | |
| 1524 | 1524 | |
| 1525 | 1525 | pub fn deinit(wip_nav: *WipNav) void { |
| 1526 | 1526 | const gpa = wip_nav.dwarf.gpa; |
| ... | ... | @@ -1529,8 +1529,6 @@ pub const WipNav = struct { |
| 1529 | 1529 | wip_nav.debug_info.deinit(); |
| 1530 | 1530 | wip_nav.debug_line.deinit(); |
| 1531 | 1531 | wip_nav.debug_loclists.deinit(); |
| 1532 | wip_nav.pending_lazy.types.deinit(gpa); | |
| 1533 | wip_nav.pending_lazy.values.deinit(gpa); | |
| 1534 | 1532 | } |
| 1535 | 1533 | |
| 1536 | 1534 | pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void { |
| ... | ... | @@ -1603,7 +1601,7 @@ pub const WipNav = struct { |
| 1603 | 1601 | const zcu = pt.zcu; |
| 1604 | 1602 | const ty = val.typeOf(zcu); |
| 1605 | 1603 | const has_runtime_bits = ty.hasRuntimeBits(zcu); |
| 1606 | const has_comptime_state = ty.comptimeOnly(zcu) and try ty.onePossibleValue(pt) == null; | |
| 1604 | const has_comptime_state = ty.comptimeOnly(zcu); | |
| 1607 | 1605 | try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) switch (tag) { |
| 1608 | 1606 | .comptime_arg => if (opt_name) |_| .comptime_arg_runtime_bits_comptime_state else .unnamed_comptime_arg_runtime_bits_comptime_state, |
| 1609 | 1607 | .local_const => if (opt_name) |_| .local_const_runtime_bits_comptime_state else unreachable, |
| ... | ... | @@ -1945,6 +1943,12 @@ pub const WipNav = struct { |
| 1945 | 1943 | try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0); |
| 1946 | 1944 | } |
| 1947 | 1945 | |
| 1946 | fn strpFmt(wip_nav: *WipNav, comptime fmt: []const u8, args: anytype) (UpdateError || Writer.Error)!void { | |
| 1947 | const str = try std.fmt.allocPrint(wip_nav.dwarf.gpa, fmt, args); | |
| 1948 | defer wip_nav.dwarf.gpa.free(str); | |
| 1949 | return wip_nav.strp(str); | |
| 1950 | } | |
| 1951 | ||
| 1948 | 1952 | const ExprLocCounter = struct { |
| 1949 | 1953 | dw: Writer.Discarding, |
| 1950 | 1954 | section_offset_bytes: u32, |
| ... | ... | @@ -2054,74 +2058,16 @@ pub const WipNav = struct { |
| 2054 | 2058 | try dfw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size)); |
| 2055 | 2059 | } |
| 2056 | 2060 | |
| 2057 | fn getNavEntry( | |
| 2058 | wip_nav: *WipNav, | |
| 2059 | nav_index: InternPool.Nav.Index, | |
| 2060 | ) UpdateError!struct { Unit.Index, Entry.Index } { | |
| 2061 | const zcu = wip_nav.pt.zcu; | |
| 2062 | const ip = &zcu.intern_pool; | |
| 2063 | const nav = ip.getNav(nav_index); | |
| 2064 | const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?); | |
| 2065 | const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index); | |
| 2066 | if (gop.found_existing) return .{ unit, gop.value_ptr.* }; | |
| 2067 | const entry = try wip_nav.dwarf.addCommonEntry(unit); | |
| 2068 | gop.value_ptr.* = entry; | |
| 2069 | return .{ unit, entry }; | |
| 2070 | } | |
| 2071 | ||
| 2072 | 2061 | fn refNav( |
| 2073 | 2062 | wip_nav: *WipNav, |
| 2074 | 2063 | nav_index: InternPool.Nav.Index, |
| 2075 | 2064 | ) (UpdateError || Writer.Error)!void { |
| 2076 | const unit, const entry = try wip_nav.getNavEntry(nav_index); | |
| 2065 | const unit, const entry = try wip_nav.dwarf.getNavEntry(nav_index); | |
| 2077 | 2066 | try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); |
| 2078 | 2067 | } |
| 2079 | 2068 | |
| 2080 | fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } { | |
| 2081 | const zcu = wip_nav.pt.zcu; | |
| 2082 | const ip = &zcu.intern_pool; | |
| 2083 | const maybe_inst_index = ty.typeDeclInst(zcu); | |
| 2084 | const unit = if (maybe_inst_index) |inst_index| switch (switch (ip.indexToKey(ty.toIntern())) { | |
| 2085 | else => unreachable, | |
| 2086 | .struct_type => ip.loadStructType(ty.toIntern()).name_nav, | |
| 2087 | .union_type => ip.loadUnionType(ty.toIntern()).name_nav, | |
| 2088 | .enum_type => ip.loadEnumType(ty.toIntern()).name_nav, | |
| 2089 | .opaque_type => ip.loadOpaqueType(ty.toIntern()).name_nav, | |
| 2090 | }) { | |
| 2091 | .none => try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?), | |
| 2092 | else => |name_nav| return wip_nav.getNavEntry(name_nav.unwrap().?), | |
| 2093 | } else .main; | |
| 2094 | const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern()); | |
| 2095 | if (gop.found_existing) return .{ unit, gop.value_ptr.* }; | |
| 2096 | const entry = try wip_nav.dwarf.addCommonEntry(unit); | |
| 2097 | gop.value_ptr.* = entry; | |
| 2098 | if (maybe_inst_index == null) try wip_nav.pending_lazy.types.append(wip_nav.dwarf.gpa, ty.toIntern()); | |
| 2099 | return .{ unit, entry }; | |
| 2100 | } | |
| 2101 | ||
| 2102 | 2069 | fn refType(wip_nav: *WipNav, ty: Type) (UpdateError || Writer.Error)!void { |
| 2103 | const unit, const entry = try wip_nav.getTypeEntry(ty); | |
| 2104 | try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); | |
| 2105 | } | |
| 2106 | ||
| 2107 | fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } { | |
| 2108 | const zcu = wip_nav.pt.zcu; | |
| 2109 | const ip = &zcu.intern_pool; | |
| 2110 | const ty = value.typeOf(zcu); | |
| 2111 | if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu) and try ty.onePossibleValue(wip_nav.pt) == null); | |
| 2112 | if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType()); | |
| 2113 | if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(switch (ip.indexToKey(value.toIntern())) { | |
| 2114 | else => unreachable, | |
| 2115 | .func => |func| func.owner_nav, | |
| 2116 | .@"extern" => |@"extern"| @"extern".owner_nav, | |
| 2117 | }); | |
| 2118 | const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern()); | |
| 2119 | const unit: Unit.Index = .main; | |
| 2120 | if (gop.found_existing) return .{ unit, gop.value_ptr.* }; | |
| 2121 | const entry = try wip_nav.dwarf.addCommonEntry(unit); | |
| 2122 | gop.value_ptr.* = entry; | |
| 2123 | try wip_nav.pending_lazy.values.append(wip_nav.dwarf.gpa, value.toIntern()); | |
| 2124 | return .{ unit, entry }; | |
| 2070 | return wip_nav.refValue(ty.toValue()); | |
| 2125 | 2071 | } |
| 2126 | 2072 | |
| 2127 | 2073 | fn refValue(wip_nav: *WipNav, value: Value) (UpdateError || Writer.Error)!void { |
| ... | ... | @@ -2129,6 +2075,15 @@ pub const WipNav = struct { |
| 2129 | 2075 | try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); |
| 2130 | 2076 | } |
| 2131 | 2077 | |
| 2078 | fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } { | |
| 2079 | if (value.typeOf(wip_nav.pt.zcu).toIntern() != .type_type) { | |
| 2080 | assert(value.typeOf(wip_nav.pt.zcu).comptimeOnly(wip_nav.pt.zcu)); | |
| 2081 | } | |
| 2082 | const dwarf = wip_nav.dwarf; | |
| 2083 | const index = try dwarf.const_pool.get(wip_nav.pt, .{ .dwarf = dwarf }, value.toIntern()); | |
| 2084 | return dwarf.values.items[@intFromEnum(index)]; | |
| 2085 | } | |
| 2086 | ||
| 2132 | 2087 | fn refForward(wip_nav: *WipNav) (Allocator.Error || Writer.Error)!u32 { |
| 2133 | 2088 | const dwarf = wip_nav.dwarf; |
| 2134 | 2089 | const diw = &wip_nav.debug_info.writer; |
| ... | ... | @@ -2156,7 +2111,7 @@ pub const WipNav = struct { |
| 2156 | 2111 | ) (UpdateError || Writer.Error)!void { |
| 2157 | 2112 | const ty = val.typeOf(wip_nav.pt.zcu); |
| 2158 | 2113 | const diw = &wip_nav.debug_info.writer; |
| 2159 | const size = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0; | |
| 2114 | const size = ty.abiSize(wip_nav.pt.zcu); | |
| 2160 | 2115 | try diw.writeUleb128(size); |
| 2161 | 2116 | if (size == 0) return; |
| 2162 | 2117 | const old_end = wip_nav.debug_info.writer.end; |
| ... | ... | @@ -2243,8 +2198,8 @@ pub const WipNav = struct { |
| 2243 | 2198 | const zcu = wip_nav.pt.zcu; |
| 2244 | 2199 | const ip = &zcu.intern_pool; |
| 2245 | 2200 | var big_int_space: Value.BigIntSpace = undefined; |
| 2246 | try wip_nav.bigIntConstValue(abbrev_code, .fromInterned(loaded_enum.tag_ty), if (loaded_enum.values.len > 0) | |
| 2247 | Value.fromInterned(loaded_enum.values.get(ip)[field_index]).toBigInt(&big_int_space, zcu) | |
| 2201 | try wip_nav.bigIntConstValue(abbrev_code, .fromInterned(loaded_enum.int_tag_type), if (loaded_enum.field_values.len > 0) | |
| 2202 | Value.fromInterned(loaded_enum.field_values.get(ip)[field_index]).toBigInt(&big_int_space, zcu) | |
| 2248 | 2203 | else |
| 2249 | 2204 | std.math.big.int.Mutable.init(&big_int_space.limbs, field_index).toConst()); |
| 2250 | 2205 | } |
| ... | ... | @@ -2297,6 +2252,12 @@ pub const WipNav = struct { |
| 2297 | 2252 | .generic_decl_const, |
| 2298 | 2253 | .generic_decl_func, |
| 2299 | 2254 | => true, |
| 2255 | ||
| 2256 | // This comes from a decl which was previously generated as an incomplete value | |
| 2257 | // (I think that must mean either a function or an extern which previously had | |
| 2258 | // incomplete types). | |
| 2259 | .undefined_comptime_value => false, | |
| 2260 | ||
| 2300 | 2261 | else => |t| std.debug.panic("bad decl abbrev code: {t}", .{t}), |
| 2301 | 2262 | }; |
| 2302 | 2263 | if (parent_type.getCaptures(zcu).len == 0) { |
| ... | ... | @@ -2331,22 +2292,6 @@ pub const WipNav = struct { |
| 2331 | 2292 | try wip_nav.refType(parent_type.?); |
| 2332 | 2293 | try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0); |
| 2333 | 2294 | } |
| 2334 | ||
| 2335 | const PendingLazy = struct { | |
| 2336 | types: std.ArrayList(InternPool.Index), | |
| 2337 | values: std.ArrayList(InternPool.Index), | |
| 2338 | ||
| 2339 | const empty: PendingLazy = .{ .types = .empty, .values = .empty }; | |
| 2340 | }; | |
| 2341 | ||
| 2342 | fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) (UpdateError || Writer.Error)!void { | |
| 2343 | while (true) if (wip_nav.pending_lazy.types.pop()) |pending_ty| | |
| 2344 | try wip_nav.dwarf.updateLazyType(wip_nav.pt, src_loc, pending_ty, &wip_nav.pending_lazy) | |
| 2345 | else if (wip_nav.pending_lazy.values.pop()) |pending_val| | |
| 2346 | try wip_nav.dwarf.updateLazyValue(wip_nav.pt, src_loc, pending_val, &wip_nav.pending_lazy) | |
| 2347 | else | |
| 2348 | break; | |
| 2349 | } | |
| 2350 | 2295 | }; |
| 2351 | 2296 | |
| 2352 | 2297 | /// When allocating, the ideal_capacity is calculated by |
| ... | ... | @@ -2372,8 +2317,9 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { |
| 2372 | 2317 | }, |
| 2373 | 2318 | .endian = target.cpu.arch.endian(), |
| 2374 | 2319 | |
| 2320 | .const_pool = .empty, | |
| 2321 | ||
| 2375 | 2322 | .mods = .empty, |
| 2376 | .types = .empty, | |
| 2377 | 2323 | .values = .empty, |
| 2378 | 2324 | .navs = .empty, |
| 2379 | 2325 | .decls = .empty, |
| ... | ... | @@ -2544,9 +2490,9 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void { |
| 2544 | 2490 | |
| 2545 | 2491 | pub fn deinit(dwarf: *Dwarf) void { |
| 2546 | 2492 | const gpa = dwarf.gpa; |
| 2493 | dwarf.const_pool.deinit(gpa); | |
| 2547 | 2494 | for (dwarf.mods.values()) |*mod_info| mod_info.deinit(gpa); |
| 2548 | 2495 | dwarf.mods.deinit(gpa); |
| 2549 | dwarf.types.deinit(gpa); | |
| 2550 | 2496 | dwarf.values.deinit(gpa); |
| 2551 | 2497 | dwarf.navs.deinit(gpa); |
| 2552 | 2498 | dwarf.decls.deinit(gpa); |
| ... | ... | @@ -2562,6 +2508,21 @@ pub fn deinit(dwarf: *Dwarf) void { |
| 2562 | 2508 | dwarf.* = undefined; |
| 2563 | 2509 | } |
| 2564 | 2510 | |
| 2511 | fn getNavEntry( | |
| 2512 | dwarf: *Dwarf, | |
| 2513 | nav_index: InternPool.Nav.Index, | |
| 2514 | ) UpdateError!struct { Unit.Index, Entry.Index } { | |
| 2515 | const zcu = dwarf.bin_file.comp.zcu.?; | |
| 2516 | const ip = &zcu.intern_pool; | |
| 2517 | const nav = ip.getNav(nav_index); | |
| 2518 | const unit = try dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?); | |
| 2519 | const gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); | |
| 2520 | if (gop.found_existing) return .{ unit, gop.value_ptr.* }; | |
| 2521 | const entry = try dwarf.addCommonEntry(unit); | |
| 2522 | gop.value_ptr.* = entry; | |
| 2523 | return .{ unit, entry }; | |
| 2524 | } | |
| 2525 | ||
| 2565 | 2526 | fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index { |
| 2566 | 2527 | const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); |
| 2567 | 2528 | const unit: Unit.Index = @enumFromInt(mod_gop.index); |
| ... | ... | @@ -2622,6 +2583,10 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo { |
| 2622 | 2583 | return &dwarf.mods.values()[@intFromEnum(unit)]; |
| 2623 | 2584 | } |
| 2624 | 2585 | |
| 2586 | fn getUnitModule(dwarf: *Dwarf, unit: Unit.Index) *Module { | |
| 2587 | return dwarf.mods.keys()[@intFromEnum(unit)]; | |
| 2588 | } | |
| 2589 | ||
| 2625 | 2590 | pub fn initWipNav( |
| 2626 | 2591 | dwarf: *Dwarf, |
| 2627 | 2592 | pt: Zcu.PerThread, |
| ... | ... | @@ -2683,7 +2648,6 @@ fn initWipNavInner( |
| 2683 | 2648 | .debug_info = .init(dwarf.gpa), |
| 2684 | 2649 | .debug_line = .init(dwarf.gpa), |
| 2685 | 2650 | .debug_loclists = .init(dwarf.gpa), |
| 2686 | .pending_lazy = .empty, | |
| 2687 | 2651 | }; |
| 2688 | 2652 | errdefer wip_nav.deinit(); |
| 2689 | 2653 | |
| ... | ... | @@ -2705,7 +2669,7 @@ fn initWipNavInner( |
| 2705 | 2669 | try wip_nav.refType(.fromInterned(if (maybe_func_type) |func_type| func_type.return_type else @"extern".ty)); |
| 2706 | 2670 | if (maybe_func_type) |func_type| { |
| 2707 | 2671 | try wip_nav.infoAddrSym(sym_index, 0); |
| 2708 | try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type))); | |
| 2672 | try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); | |
| 2709 | 2673 | if (func_type.param_types.len > 0 or func_type.is_var_args) { |
| 2710 | 2674 | for (func_type.param_types.get(ip)) |param_type| { |
| 2711 | 2675 | try wip_nav.abbrevCode(.extern_param); |
| ... | ... | @@ -2733,7 +2697,7 @@ fn initWipNavInner( |
| 2733 | 2697 | try wip_nav.strp(@"extern".name.toSlice(ip)); |
| 2734 | 2698 | try wip_nav.refType(.fromInterned(func_type.return_type)); |
| 2735 | 2699 | try wip_nav.infoAddrSym(sym_index, 0); |
| 2736 | try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type))); | |
| 2700 | try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); | |
| 2737 | 2701 | if (func_type.param_types.len > 0 or func_type.is_var_args) { |
| 2738 | 2702 | for (func_type.param_types.get(ip)) |param_type| { |
| 2739 | 2703 | try wip_nav.abbrevCode(.extern_param); |
| ... | ... | @@ -2818,7 +2782,7 @@ fn initWipNavInner( |
| 2818 | 2782 | else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), |
| 2819 | 2783 | }.toByteUnits().?); |
| 2820 | 2784 | try diw.writeByte(@intFromBool(decl.linkage != .normal)); |
| 2821 | try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type))); | |
| 2785 | try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); | |
| 2822 | 2786 | |
| 2823 | 2787 | const dlw = &wip_nav.debug_line.writer; |
| 2824 | 2788 | try dlw.writeByte(DW.LNS.extended_op); |
| ... | ... | @@ -3050,7 +3014,7 @@ fn finishWipNavWriterError( |
| 3050 | 3014 | } |
| 3051 | 3015 | try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written()); |
| 3052 | 3016 | |
| 3053 | try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); | |
| 3017 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 3054 | 3018 | } |
| 3055 | 3019 | |
| 3056 | 3020 | pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void { |
| ... | ... | @@ -3087,34 +3051,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3087 | 3051 | return; |
| 3088 | 3052 | } |
| 3089 | 3053 | |
| 3090 | var wip_nav: WipNav = .{ | |
| 3091 | .dwarf = dwarf, | |
| 3092 | .pt = pt, | |
| 3093 | .unit = try dwarf.getUnit(file.mod.?), | |
| 3094 | .entry = undefined, | |
| 3095 | .any_children = false, | |
| 3096 | .func = .none, | |
| 3097 | .func_sym_index = undefined, | |
| 3098 | .func_high_pc = undefined, | |
| 3099 | .blocks = undefined, | |
| 3100 | .cfi = undefined, | |
| 3101 | .debug_frame = .init(dwarf.gpa), | |
| 3102 | .debug_info = .init(dwarf.gpa), | |
| 3103 | .debug_line = .init(dwarf.gpa), | |
| 3104 | .debug_loclists = .init(dwarf.gpa), | |
| 3105 | .pending_lazy = .empty, | |
| 3106 | }; | |
| 3107 | defer wip_nav.deinit(); | |
| 3108 | ||
| 3109 | const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); | |
| 3110 | errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop(); | |
| 3111 | ||
| 3112 | 3054 | const tag: union(enum) { |
| 3113 | done, | |
| 3114 | decl_alias, | |
| 3115 | decl_var, | |
| 3116 | decl_const, | |
| 3117 | decl_func_alias: InternPool.Nav.Index, | |
| 3055 | alias, | |
| 3056 | @"var", | |
| 3057 | @"const", | |
| 3058 | func: Type, | |
| 3059 | func_alias: InternPool.Nav.Index, | |
| 3118 | 3060 | } = switch (ip.indexToKey(nav_val.toIntern())) { |
| 3119 | 3061 | .int_type, |
| 3120 | 3062 | .ptr_type, |
| ... | ... | @@ -3128,242 +3070,49 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3128 | 3070 | .func_type, |
| 3129 | 3071 | .error_set_type, |
| 3130 | 3072 | .inferred_error_set_type, |
| 3131 | => .decl_alias, | |
| 3073 | => .alias, | |
| 3074 | ||
| 3132 | 3075 | .struct_type => tag: { |
| 3133 | 3076 | const loaded_struct = ip.loadStructType(nav_val.toIntern()); |
| 3134 | if (loaded_struct.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; | |
| 3135 | ||
| 3136 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); | |
| 3137 | if (type_gop.found_existing) { | |
| 3138 | if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; | |
| 3139 | assert(!nav_gop.found_existing); | |
| 3140 | nav_gop.value_ptr.* = type_gop.value_ptr.*; | |
| 3141 | } else { | |
| 3142 | if (nav_gop.found_existing) | |
| 3143 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() | |
| 3144 | else | |
| 3145 | nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | |
| 3146 | type_gop.value_ptr.* = nav_gop.value_ptr.*; | |
| 3147 | } | |
| 3148 | wip_nav.entry = nav_gop.value_ptr.*; | |
| 3149 | ||
| 3150 | const diw = &wip_nav.debug_info.writer; | |
| 3151 | ||
| 3152 | switch (loaded_struct.layout) { | |
| 3153 | .auto, .@"extern" => { | |
| 3154 | try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ | |
| 3155 | .decl = .decl_namespace_struct, | |
| 3156 | .generic_decl = .generic_decl_const, | |
| 3157 | .decl_instance = .decl_instance_namespace_struct, | |
| 3158 | } else .{ | |
| 3159 | .decl = .decl_struct, | |
| 3160 | .generic_decl = .generic_decl_const, | |
| 3161 | .decl_instance = .decl_instance_struct, | |
| 3162 | }, &nav, inst_info.file, &decl); | |
| 3163 | if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { | |
| 3164 | try diw.writeUleb128(nav_val.toType().abiSize(zcu)); | |
| 3165 | try diw.writeUleb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3166 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 3167 | const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); | |
| 3168 | const field_init = loaded_struct.fieldInit(ip, field_index); | |
| 3169 | assert(!(is_comptime and field_init == .none)); | |
| 3170 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 3171 | const has_runtime_bits, const has_comptime_state = switch (field_init) { | |
| 3172 | .none => .{ false, false }, | |
| 3173 | else => .{ | |
| 3174 | field_type.hasRuntimeBits(zcu), | |
| 3175 | field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, | |
| 3176 | }, | |
| 3177 | }; | |
| 3178 | try wip_nav.abbrevCode(if (is_comptime) | |
| 3179 | if (has_comptime_state) | |
| 3180 | .struct_field_comptime_comptime_state | |
| 3181 | else if (has_runtime_bits) | |
| 3182 | .struct_field_comptime_runtime_bits | |
| 3183 | else | |
| 3184 | .struct_field_comptime | |
| 3185 | else if (field_init != .none) | |
| 3186 | if (has_comptime_state) | |
| 3187 | .struct_field_default_comptime_state | |
| 3188 | else if (has_runtime_bits) | |
| 3189 | .struct_field_default_runtime_bits | |
| 3190 | else | |
| 3191 | .struct_field | |
| 3192 | else | |
| 3193 | .struct_field); | |
| 3194 | try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); | |
| 3195 | try wip_nav.refType(field_type); | |
| 3196 | if (!is_comptime) { | |
| 3197 | try diw.writeUleb128(loaded_struct.offsets.get(ip)[field_index]); | |
| 3198 | try diw.writeUleb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 3199 | field_type.abiAlignment(zcu).toByteUnits().?); | |
| 3200 | } | |
| 3201 | if (has_comptime_state) | |
| 3202 | try wip_nav.refValue(.fromInterned(field_init)) | |
| 3203 | else if (has_runtime_bits) | |
| 3204 | try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init)); | |
| 3205 | } | |
| 3206 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3207 | } | |
| 3208 | }, | |
| 3209 | .@"packed" => { | |
| 3210 | try wip_nav.declCommon(.{ | |
| 3211 | .decl = .decl_packed_struct, | |
| 3212 | .generic_decl = .generic_decl_const, | |
| 3213 | .decl_instance = .decl_instance_packed_struct, | |
| 3214 | }, &nav, inst_info.file, &decl); | |
| 3215 | try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); | |
| 3216 | var field_bit_offset: u16 = 0; | |
| 3217 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 3218 | try wip_nav.abbrevCode(.packed_struct_field); | |
| 3219 | try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); | |
| 3220 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 3221 | try wip_nav.refType(field_type); | |
| 3222 | try diw.writeUleb128(field_bit_offset); | |
| 3223 | field_bit_offset += @intCast(field_type.bitSize(zcu)); | |
| 3224 | } | |
| 3225 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3226 | }, | |
| 3077 | if (nav_index.toOptional() == loaded_struct.name_nav) { | |
| 3078 | // This Nav's entry is populated by the type, not the actual Nav. | |
| 3079 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | |
| 3080 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 3081 | return; | |
| 3227 | 3082 | } |
| 3228 | break :tag .done; | |
| 3083 | break :tag .alias; | |
| 3229 | 3084 | }, |
| 3230 | 3085 | .enum_type => tag: { |
| 3231 | 3086 | const loaded_enum = ip.loadEnumType(nav_val.toIntern()); |
| 3232 | const type_zir_index = loaded_enum.zir_index.unwrap() orelse break :tag .decl_alias; | |
| 3233 | if (type_zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; | |
| 3234 | ||
| 3235 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); | |
| 3236 | if (type_gop.found_existing) { | |
| 3237 | if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; | |
| 3238 | assert(!nav_gop.found_existing); | |
| 3239 | nav_gop.value_ptr.* = type_gop.value_ptr.*; | |
| 3240 | } else { | |
| 3241 | if (nav_gop.found_existing) | |
| 3242 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() | |
| 3243 | else | |
| 3244 | nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | |
| 3245 | type_gop.value_ptr.* = nav_gop.value_ptr.*; | |
| 3246 | } | |
| 3247 | wip_nav.entry = nav_gop.value_ptr.*; | |
| 3248 | const diw = &wip_nav.debug_info.writer; | |
| 3249 | try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{ | |
| 3250 | .decl = .decl_enum, | |
| 3251 | .generic_decl = .generic_decl_const, | |
| 3252 | .decl_instance = .decl_instance_enum, | |
| 3253 | } else .{ | |
| 3254 | .decl = .decl_empty_enum, | |
| 3255 | .generic_decl = .generic_decl_const, | |
| 3256 | .decl_instance = .decl_instance_empty_enum, | |
| 3257 | }, &nav, inst_info.file, &decl); | |
| 3258 | try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); | |
| 3259 | for (0..loaded_enum.names.len) |field_index| { | |
| 3260 | try wip_nav.enumConstValue(loaded_enum, .{ | |
| 3261 | .sdata = .signed_enum_field, | |
| 3262 | .udata = .unsigned_enum_field, | |
| 3263 | .block = .big_enum_field, | |
| 3264 | }, field_index); | |
| 3265 | try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); | |
| 3087 | if (nav_index.toOptional() == loaded_enum.name_nav) { | |
| 3088 | // This Nav's entry is populated by the type, not the actual Nav. | |
| 3089 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | |
| 3090 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 3091 | return; | |
| 3266 | 3092 | } |
| 3267 | if (loaded_enum.names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3268 | break :tag .done; | |
| 3093 | break :tag .alias; | |
| 3269 | 3094 | }, |
| 3270 | 3095 | .union_type => tag: { |
| 3271 | 3096 | const loaded_union = ip.loadUnionType(nav_val.toIntern()); |
| 3272 | if (loaded_union.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; | |
| 3273 | ||
| 3274 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); | |
| 3275 | if (type_gop.found_existing) { | |
| 3276 | if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; | |
| 3277 | assert(!nav_gop.found_existing); | |
| 3278 | nav_gop.value_ptr.* = type_gop.value_ptr.*; | |
| 3279 | } else { | |
| 3280 | if (nav_gop.found_existing) | |
| 3281 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() | |
| 3282 | else | |
| 3283 | nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | |
| 3284 | type_gop.value_ptr.* = nav_gop.value_ptr.*; | |
| 3285 | } | |
| 3286 | wip_nav.entry = nav_gop.value_ptr.*; | |
| 3287 | const diw = &wip_nav.debug_info.writer; | |
| 3288 | try wip_nav.declCommon(.{ | |
| 3289 | .decl = .decl_union, | |
| 3290 | .generic_decl = .generic_decl_const, | |
| 3291 | .decl_instance = .decl_instance_union, | |
| 3292 | }, &nav, inst_info.file, &decl); | |
| 3293 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | |
| 3294 | try diw.writeUleb128(union_layout.abi_size); | |
| 3295 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); | |
| 3296 | const loaded_tag = loaded_union.loadTagType(ip); | |
| 3297 | if (loaded_union.hasTag(ip)) { | |
| 3298 | try wip_nav.abbrevCode(.tagged_union); | |
| 3299 | try wip_nav.infoSectionOffset( | |
| 3300 | .debug_info, | |
| 3301 | wip_nav.unit, | |
| 3302 | wip_nav.entry, | |
| 3303 | @intCast(diw.end + dwarf.sectionOffsetBytes()), | |
| 3304 | ); | |
| 3305 | { | |
| 3306 | try wip_nav.abbrevCode(.generated_field); | |
| 3307 | try wip_nav.strp("tag"); | |
| 3308 | try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); | |
| 3309 | try diw.writeUleb128(union_layout.tagOffset()); | |
| 3310 | ||
| 3311 | for (0..loaded_union.field_types.len) |field_index| { | |
| 3312 | try wip_nav.enumConstValue(loaded_tag, .{ | |
| 3313 | .sdata = .signed_tagged_union_field, | |
| 3314 | .udata = .unsigned_tagged_union_field, | |
| 3315 | .block = .big_tagged_union_field, | |
| 3316 | }, field_index); | |
| 3317 | { | |
| 3318 | try wip_nav.abbrevCode(.struct_field); | |
| 3319 | try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); | |
| 3320 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 3321 | try wip_nav.refType(field_type); | |
| 3322 | try diw.writeUleb128(union_layout.payloadOffset()); | |
| 3323 | try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 3324 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 3325 | } | |
| 3326 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3327 | } | |
| 3328 | } | |
| 3329 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3330 | } else for (0..loaded_union.field_types.len) |field_index| { | |
| 3331 | try wip_nav.abbrevCode(.untagged_union_field); | |
| 3332 | try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); | |
| 3333 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 3334 | try wip_nav.refType(field_type); | |
| 3335 | try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 3336 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 3097 | if (nav_index.toOptional() == loaded_union.name_nav) { | |
| 3098 | // This Nav's entry is populated by the type, not the actual Nav. | |
| 3099 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | |
| 3100 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 3101 | return; | |
| 3337 | 3102 | } |
| 3338 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3339 | break :tag .done; | |
| 3103 | break :tag .alias; | |
| 3340 | 3104 | }, |
| 3341 | 3105 | .opaque_type => tag: { |
| 3342 | 3106 | const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); |
| 3343 | if (loaded_opaque.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; | |
| 3344 | ||
| 3345 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); | |
| 3346 | if (type_gop.found_existing) { | |
| 3347 | if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; | |
| 3348 | assert(!nav_gop.found_existing); | |
| 3349 | nav_gop.value_ptr.* = type_gop.value_ptr.*; | |
| 3350 | } else { | |
| 3351 | if (nav_gop.found_existing) | |
| 3352 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() | |
| 3353 | else | |
| 3354 | nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | |
| 3355 | type_gop.value_ptr.* = nav_gop.value_ptr.*; | |
| 3107 | if (nav_index.toOptional() == loaded_opaque.name_nav) { | |
| 3108 | // This Nav's entry is populated by the type, not the actual Nav. | |
| 3109 | _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); | |
| 3110 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 3111 | return; | |
| 3356 | 3112 | } |
| 3357 | wip_nav.entry = nav_gop.value_ptr.*; | |
| 3358 | const diw = &wip_nav.debug_info.writer; | |
| 3359 | try wip_nav.declCommon(.{ | |
| 3360 | .decl = .decl_namespace_struct, | |
| 3361 | .generic_decl = .generic_decl_const, | |
| 3362 | .decl_instance = .decl_instance_namespace_struct, | |
| 3363 | }, &nav, inst_info.file, &decl); | |
| 3364 | try diw.writeByte(@intFromBool(true)); | |
| 3365 | break :tag .done; | |
| 3113 | break :tag .alias; | |
| 3366 | 3114 | }, |
| 3115 | ||
| 3367 | 3116 | .undef, |
| 3368 | 3117 | .simple_value, |
| 3369 | 3118 | .int, |
| ... | ... | @@ -3371,70 +3120,76 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3371 | 3120 | .error_union, |
| 3372 | 3121 | .enum_literal, |
| 3373 | 3122 | .enum_tag, |
| 3374 | .empty_enum_value, | |
| 3375 | 3123 | .float, |
| 3376 | 3124 | .ptr, |
| 3377 | 3125 | .slice, |
| 3378 | 3126 | .opt, |
| 3379 | 3127 | .aggregate, |
| 3380 | 3128 | .un, |
| 3381 | => .decl_const, | |
| 3382 | .variable => .decl_var, | |
| 3129 | .bitpack, | |
| 3130 | => .@"const", | |
| 3131 | ||
| 3132 | .variable => .@"var", | |
| 3133 | ||
| 3383 | 3134 | .@"extern" => unreachable, |
| 3384 | .func => |func| tag: { | |
| 3385 | if (func.owner_nav != nav_index) break :tag .{ .decl_func_alias = func.owner_nav }; | |
| 3386 | if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) { | |
| 3387 | .null => {}, | |
| 3388 | else => unreachable, | |
| 3389 | .decl_nullary_func, .decl_func, .decl_instance_nullary_func, .decl_instance_func => return, | |
| 3390 | .decl_nullary_func_generic, | |
| 3391 | .decl_func_generic, | |
| 3392 | .decl_instance_nullary_func_generic, | |
| 3393 | .decl_instance_func_generic, | |
| 3394 | => dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear(), | |
| 3395 | } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | |
| 3396 | wip_nav.entry = nav_gop.value_ptr.*; | |
| 3397 | 3135 | |
| 3398 | const func_type = ip.indexToKey(func.ty).func_type; | |
| 3399 | const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| { | |
| 3400 | if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false; | |
| 3401 | } else true; | |
| 3402 | const diw = &wip_nav.debug_info.writer; | |
| 3403 | try wip_nav.declCommon(if (is_nullary) .{ | |
| 3404 | .decl = .decl_nullary_func_generic, | |
| 3405 | .generic_decl = .generic_decl_func, | |
| 3406 | .decl_instance = .decl_instance_nullary_func_generic, | |
| 3407 | } else .{ | |
| 3408 | .decl = .decl_func_generic, | |
| 3409 | .generic_decl = .generic_decl_func, | |
| 3410 | .decl_instance = .decl_instance_func_generic, | |
| 3411 | }, &nav, inst_info.file, &decl); | |
| 3412 | try wip_nav.refType(.fromInterned(func_type.return_type)); | |
| 3413 | if (!is_nullary) { | |
| 3414 | for (0..func_type.param_types.len) |param_index| { | |
| 3415 | if (std.math.cast(u5, param_index)) |small_param_index| | |
| 3416 | if (func_type.paramIsComptime(small_param_index)) continue; | |
| 3417 | try wip_nav.abbrevCode(.func_type_param); | |
| 3418 | try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); | |
| 3419 | } | |
| 3420 | if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); | |
| 3421 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3422 | } | |
| 3423 | break :tag .done; | |
| 3136 | .func => |func| tag: { | |
| 3137 | if (func.owner_nav != nav_index) break :tag .{ .func_alias = func.owner_nav }; | |
| 3138 | break :tag .{ .func = .fromInterned(func.ty) }; | |
| 3424 | 3139 | }, |
| 3140 | ||
| 3425 | 3141 | // memoization, not types |
| 3426 | 3142 | .memoized_call => unreachable, |
| 3427 | 3143 | }; |
| 3428 | if (tag != .done) { | |
| 3429 | if (nav_gop.found_existing) | |
| 3430 | dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() | |
| 3431 | else | |
| 3432 | nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); | |
| 3433 | wip_nav.entry = nav_gop.value_ptr.*; | |
| 3144 | ||
| 3145 | const unit = try dwarf.getUnit(file.mod.?); | |
| 3146 | ||
| 3147 | const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); | |
| 3148 | errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop(); | |
| 3149 | ||
| 3150 | if (nav_gop.found_existing) { | |
| 3151 | if (tag == .func) switch (try dwarf.debug_info.declAbbrevCode(unit, nav_gop.value_ptr.*)) { | |
| 3152 | else => unreachable, | |
| 3153 | ||
| 3154 | .decl_nullary_func, | |
| 3155 | .decl_func, | |
| 3156 | .decl_instance_nullary_func, | |
| 3157 | .decl_instance_func, | |
| 3158 | => return, | |
| 3159 | ||
| 3160 | .null, | |
| 3161 | .decl_nullary_func_generic, | |
| 3162 | .decl_func_generic, | |
| 3163 | .decl_instance_nullary_func_generic, | |
| 3164 | .decl_instance_func_generic, | |
| 3165 | => {}, | |
| 3166 | }; | |
| 3167 | dwarf.debug_info.section.getUnit(unit).getEntry(nav_gop.value_ptr.*).clear(); | |
| 3168 | } else { | |
| 3169 | nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit); | |
| 3434 | 3170 | } |
| 3171 | ||
| 3172 | var wip_nav: WipNav = .{ | |
| 3173 | .dwarf = dwarf, | |
| 3174 | .pt = pt, | |
| 3175 | .unit = unit, | |
| 3176 | .entry = nav_gop.value_ptr.*, | |
| 3177 | .any_children = false, | |
| 3178 | .func = .none, | |
| 3179 | .func_sym_index = undefined, | |
| 3180 | .func_high_pc = undefined, | |
| 3181 | .blocks = undefined, | |
| 3182 | .cfi = undefined, | |
| 3183 | .debug_frame = .init(dwarf.gpa), | |
| 3184 | .debug_info = .init(dwarf.gpa), | |
| 3185 | .debug_line = .init(dwarf.gpa), | |
| 3186 | .debug_loclists = .init(dwarf.gpa), | |
| 3187 | }; | |
| 3188 | defer wip_nav.deinit(); | |
| 3189 | const diw = &wip_nav.debug_info.writer; | |
| 3190 | ||
| 3435 | 3191 | switch (tag) { |
| 3436 | .done => {}, | |
| 3437 | .decl_alias => { | |
| 3192 | .alias => { | |
| 3438 | 3193 | try wip_nav.declCommon(.{ |
| 3439 | 3194 | .decl = .decl_alias, |
| 3440 | 3195 | .generic_decl = .generic_decl_const, |
| ... | ... | @@ -3442,8 +3197,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3442 | 3197 | }, &nav, inst_info.file, &decl); |
| 3443 | 3198 | try wip_nav.refType(nav_val.toType()); |
| 3444 | 3199 | }, |
| 3445 | .decl_var => { | |
| 3446 | const diw = &wip_nav.debug_info.writer; | |
| 3200 | .@"var" => { | |
| 3447 | 3201 | try wip_nav.declCommon(.{ |
| 3448 | 3202 | .decl = .decl_var, |
| 3449 | 3203 | .generic_decl = .generic_decl_var, |
| ... | ... | @@ -3460,11 +3214,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3460 | 3214 | nav_ty.abiAlignment(zcu).toByteUnits().?); |
| 3461 | 3215 | try diw.writeByte(@intFromBool(decl.linkage != .normal)); |
| 3462 | 3216 | }, |
| 3463 | .decl_const => { | |
| 3464 | const diw = &wip_nav.debug_info.writer; | |
| 3217 | .@"const" => { | |
| 3465 | 3218 | const nav_ty = nav_val.typeOf(zcu); |
| 3466 | 3219 | const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); |
| 3467 | const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null; | |
| 3220 | const has_comptime_state = nav_ty.comptimeOnly(zcu); | |
| 3468 | 3221 | try wip_nav.declCommon(if (has_runtime_bits and has_comptime_state) .{ |
| 3469 | 3222 | .decl = .decl_const_runtime_bits_comptime_state, |
| 3470 | 3223 | .generic_decl = .generic_decl_const, |
| ... | ... | @@ -3496,40 +3249,129 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3496 | 3249 | try wip_nav.abbrevCode(.is_const); |
| 3497 | 3250 | try wip_nav.refType(nav_ty); |
| 3498 | 3251 | }, |
| 3499 | .decl_func_alias => |owner_nav| { | |
| 3500 | try wip_nav.declCommon(.{ | |
| 3501 | .decl = .decl_alias, | |
| 3502 | .generic_decl = .generic_decl_const, | |
| 3503 | .decl_instance = .decl_instance_alias, | |
| 3252 | .func => |func_ty| { | |
| 3253 | const func_type = ip.indexToKey(func_ty.toIntern()).func_type; | |
| 3254 | const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| { | |
| 3255 | if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false; | |
| 3256 | } else true; | |
| 3257 | try wip_nav.declCommon(if (is_nullary) .{ | |
| 3258 | .decl = .decl_nullary_func_generic, | |
| 3259 | .generic_decl = .generic_decl_func, | |
| 3260 | .decl_instance = .decl_instance_nullary_func_generic, | |
| 3261 | } else .{ | |
| 3262 | .decl = .decl_func_generic, | |
| 3263 | .generic_decl = .generic_decl_func, | |
| 3264 | .decl_instance = .decl_instance_func_generic, | |
| 3504 | 3265 | }, &nav, inst_info.file, &decl); |
| 3505 | try wip_nav.refNav(owner_nav); | |
| 3506 | }, | |
| 3507 | } | |
| 3508 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | |
| 3509 | try wip_nav.updateLazy(nav_src_loc); | |
| 3266 | try wip_nav.refType(.fromInterned(func_type.return_type)); | |
| 3267 | if (!is_nullary) { | |
| 3268 | for (0..func_type.param_types.len) |param_index| { | |
| 3269 | if (std.math.cast(u5, param_index)) |small_param_index| | |
| 3270 | if (func_type.paramIsComptime(small_param_index)) continue; | |
| 3271 | try wip_nav.abbrevCode(.func_type_param); | |
| 3272 | try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); | |
| 3273 | } | |
| 3274 | if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); | |
| 3275 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3276 | } | |
| 3277 | }, | |
| 3278 | .func_alias => |owner_nav| { | |
| 3279 | try wip_nav.declCommon(.{ | |
| 3280 | .decl = .decl_alias, | |
| 3281 | .generic_decl = .generic_decl_const, | |
| 3282 | .decl_instance = .decl_instance_alias, | |
| 3283 | }, &nav, inst_info.file, &decl); | |
| 3284 | try wip_nav.refNav(owner_nav); | |
| 3285 | }, | |
| 3286 | } | |
| 3287 | try dwarf.debug_info.section.replaceEntry(unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | |
| 3288 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 3510 | 3289 | } |
| 3511 | 3290 | |
| 3512 | fn updateLazyType( | |
| 3291 | pub fn updateContainerType( | |
| 3513 | 3292 | dwarf: *Dwarf, |
| 3514 | 3293 | pt: Zcu.PerThread, |
| 3515 | src_loc: Zcu.LazySrcLoc, | |
| 3516 | type_index: InternPool.Index, | |
| 3517 | pending_lazy: *WipNav.PendingLazy, | |
| 3518 | ) (UpdateError || Writer.Error)!void { | |
| 3294 | ty: InternPool.Index, | |
| 3295 | success: bool, | |
| 3296 | ) !void { | |
| 3297 | try dwarf.const_pool.updateContainerType(pt, .{ .dwarf = dwarf }, ty, success); | |
| 3298 | } | |
| 3299 | /// Should only be called by the `link.ConstPool` implementation. | |
| 3300 | pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { | |
| 3301 | addConstInner(dwarf, pt, index, val) catch |err| switch (err) { | |
| 3302 | error.OutOfMemory => |e| return e, | |
| 3303 | else => |e| std.debug.panic("DWARF TODO: '{t}' while registering constant\n", .{e}), | |
| 3304 | }; | |
| 3305 | } | |
| 3306 | fn addConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) !void { | |
| 3519 | 3307 | const zcu = pt.zcu; |
| 3520 | 3308 | const ip = &zcu.intern_pool; |
| 3521 | assert(ip.typeOf(type_index) == .type_type); | |
| 3522 | const ty: Type = .fromInterned(type_index); | |
| 3523 | switch (type_index) { | |
| 3524 | .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}), | |
| 3525 | else => log.debug("updateLazyType({f})", .{ty.fmt(pt)}), | |
| 3309 | ||
| 3310 | const unit: Unit.Index, const entry: Entry.Index = switch (ip.indexToKey(val)) { | |
| 3311 | else => .{ .main, try dwarf.addCommonEntry(.main) }, | |
| 3312 | .func => |func| try dwarf.getNavEntry(func.owner_nav), | |
| 3313 | .@"extern" => |@"extern"| try dwarf.getNavEntry(@"extern".owner_nav), | |
| 3314 | .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| entry: { | |
| 3315 | const name_nav = switch (tag) { | |
| 3316 | .struct_type => ip.loadStructType(val).name_nav, | |
| 3317 | .union_type => ip.loadUnionType(val).name_nav, | |
| 3318 | .enum_type => ip.loadEnumType(val).name_nav, | |
| 3319 | .opaque_type => ip.loadOpaqueType(val).name_nav, | |
| 3320 | else => unreachable, | |
| 3321 | }; | |
| 3322 | if (name_nav.unwrap()) |nav| { | |
| 3323 | break :entry try dwarf.getNavEntry(nav); | |
| 3324 | } else { | |
| 3325 | const zir_index = Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?; | |
| 3326 | const unit = try dwarf.getUnit(zcu.fileByIndex(zir_index.resolveFile(ip)).mod.?); | |
| 3327 | break :entry .{ unit, try dwarf.addCommonEntry(unit) }; | |
| 3328 | } | |
| 3329 | }, | |
| 3330 | }; | |
| 3331 | ||
| 3332 | assert(@intFromEnum(index) == dwarf.values.items.len); | |
| 3333 | try dwarf.values.append(dwarf.gpa, .{ unit, entry }); | |
| 3334 | } | |
| 3335 | /// Should only be called by the `link.ConstPool` implementation. | |
| 3336 | /// | |
| 3337 | /// Emits a "dummy" DIE for the given comptime-only value (which may be a type). For types, this is | |
| 3338 | /// an opaque type. Otherwise, it is an undefined value of the value's type. | |
| 3339 | pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) Allocator.Error!void { | |
| 3340 | updateConstIncompleteInner(dwarf, pt, debug_const_index, value_index) catch |err| switch (err) { | |
| 3341 | error.OutOfMemory => |e| return e, | |
| 3342 | else => |e| std.debug.panic("DWARF TODO: '{t}' while updating incomplete constant\n", .{e}), | |
| 3343 | }; | |
| 3344 | } | |
| 3345 | fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void { | |
| 3346 | const zcu = pt.zcu; | |
| 3347 | const ip = &zcu.intern_pool; | |
| 3348 | ||
| 3349 | const val: Value = .fromInterned(value_index); | |
| 3350 | ||
| 3351 | switch (value_index) { | |
| 3352 | .generic_poison_type => log.debug("updateValueIncomplete(anytype)", .{}), | |
| 3353 | else => log.debug("updateValueIncomplete(@as({f}, {f}))", .{ | |
| 3354 | val.typeOf(zcu).fmt(pt), | |
| 3355 | val.fmtValue(pt), | |
| 3356 | }), | |
| 3526 | 3357 | } |
| 3527 | 3358 | |
| 3359 | const unit, const entry = dwarf.values.items[@intFromEnum(debug_const_index)]; | |
| 3360 | ||
| 3361 | for ([_]*Section{ | |
| 3362 | &dwarf.debug_aranges.section, | |
| 3363 | &dwarf.debug_aranges.section, | |
| 3364 | &dwarf.debug_info.section, | |
| 3365 | &dwarf.debug_line.section, | |
| 3366 | &dwarf.debug_loclists.section, | |
| 3367 | &dwarf.debug_rnglists.section, | |
| 3368 | }) |sec| sec.getUnit(unit).getEntry(entry).clear(); | |
| 3369 | ||
| 3528 | 3370 | var wip_nav: WipNav = .{ |
| 3529 | 3371 | .dwarf = dwarf, |
| 3530 | 3372 | .pt = pt, |
| 3531 | .unit = .main, | |
| 3532 | .entry = dwarf.types.get(type_index).?, | |
| 3373 | .unit = unit, | |
| 3374 | .entry = entry, | |
| 3533 | 3375 | .any_children = false, |
| 3534 | 3376 | .func = .none, |
| 3535 | 3377 | .func_sym_index = undefined, |
| ... | ... | @@ -3540,43 +3382,216 @@ fn updateLazyType( |
| 3540 | 3382 | .debug_info = .init(dwarf.gpa), |
| 3541 | 3383 | .debug_line = .init(dwarf.gpa), |
| 3542 | 3384 | .debug_loclists = .init(dwarf.gpa), |
| 3543 | .pending_lazy = pending_lazy.*, | |
| 3544 | 3385 | }; |
| 3545 | defer { | |
| 3546 | pending_lazy.* = wip_nav.pending_lazy; | |
| 3547 | wip_nav.pending_lazy = .empty; | |
| 3548 | wip_nav.deinit(); | |
| 3386 | defer wip_nav.deinit(); | |
| 3387 | ||
| 3388 | switch (ip.indexToKey(value_index)) { | |
| 3389 | // Container types still need to be valid namespaces. | |
| 3390 | .struct_type => { | |
| 3391 | const loaded_struct = ip.loadStructType(value_index); | |
| 3392 | const root_of_file: ?Zcu.File.Index = if (loaded_struct.zir_index.resolveFull(ip)) |r| f: { | |
| 3393 | if (r.inst != .main_struct_inst) break :f null; | |
| 3394 | break :f r.file; | |
| 3395 | } else null; | |
| 3396 | if (root_of_file) |file_index| { | |
| 3397 | assert(loaded_struct.name_nav == .none); | |
| 3398 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index); | |
| 3399 | try wip_nav.abbrevCode(.empty_file); | |
| 3400 | try wip_nav.debug_info.writer.writeUleb128(file_gop.index); | |
| 3401 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | |
| 3402 | } else { | |
| 3403 | try dwarf.emitIncompleteContainerType( | |
| 3404 | &wip_nav, | |
| 3405 | loaded_struct.zir_index, | |
| 3406 | loaded_struct.name, | |
| 3407 | loaded_struct.name_nav, | |
| 3408 | ); | |
| 3409 | } | |
| 3410 | }, | |
| 3411 | .union_type => { | |
| 3412 | const loaded_union = ip.loadUnionType(value_index); | |
| 3413 | try dwarf.emitIncompleteContainerType( | |
| 3414 | &wip_nav, | |
| 3415 | loaded_union.zir_index, | |
| 3416 | loaded_union.name, | |
| 3417 | loaded_union.name_nav, | |
| 3418 | ); | |
| 3419 | }, | |
| 3420 | .enum_type => { | |
| 3421 | const loaded_enum = ip.loadEnumType(value_index); | |
| 3422 | if (loaded_enum.zir_index.unwrap()) |zir_index| { | |
| 3423 | try dwarf.emitIncompleteContainerType( | |
| 3424 | &wip_nav, | |
| 3425 | zir_index, | |
| 3426 | loaded_enum.name, | |
| 3427 | loaded_enum.name_nav, | |
| 3428 | ); | |
| 3429 | } else { | |
| 3430 | try wip_nav.abbrevCode(.generated_empty_struct_type); | |
| 3431 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | |
| 3432 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3433 | } | |
| 3434 | }, | |
| 3435 | .opaque_type => { | |
| 3436 | const loaded_opaque = ip.loadOpaqueType(value_index); | |
| 3437 | try dwarf.emitIncompleteContainerType( | |
| 3438 | &wip_nav, | |
| 3439 | loaded_opaque.zir_index, | |
| 3440 | loaded_opaque.name, | |
| 3441 | loaded_opaque.name_nav, | |
| 3442 | ); | |
| 3443 | }, | |
| 3444 | // Not a container type, so just emit a dummy entry. If `val` happens to be a type, we'll | |
| 3445 | // emit it as if it were an opaque type so that we can name it. | |
| 3446 | else => |val_key| switch (val_key.typeOf()) { | |
| 3447 | .type_type => { | |
| 3448 | try wip_nav.abbrevCode(.generated_empty_struct_type); | |
| 3449 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3450 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3451 | }, | |
| 3452 | else => |ty| { | |
| 3453 | try wip_nav.abbrevCode(.undefined_comptime_value); | |
| 3454 | try wip_nav.refType(.fromInterned(ty)); | |
| 3455 | }, | |
| 3456 | }, | |
| 3549 | 3457 | } |
| 3550 | const diw = &wip_nav.debug_info.writer; | |
| 3551 | const name = switch (type_index) { | |
| 3552 | .generic_poison_type => "", | |
| 3553 | else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}), | |
| 3458 | try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); | |
| 3459 | try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); | |
| 3460 | } | |
| 3461 | fn emitIncompleteContainerType( | |
| 3462 | dwarf: *Dwarf, | |
| 3463 | wip_nav: *WipNav, | |
| 3464 | zir_index: InternPool.TrackedInst.Index, | |
| 3465 | name: InternPool.NullTerminatedString, | |
| 3466 | name_nav: InternPool.Nav.Index.Optional, | |
| 3467 | ) !void { | |
| 3468 | const zcu = wip_nav.pt.zcu; | |
| 3469 | const ip = &zcu.intern_pool; | |
| 3470 | const file = zir_index.resolveFile(ip); | |
| 3471 | if (name_nav.unwrap()) |nav_index| { | |
| 3472 | const nav = ip.getNav(nav_index); | |
| 3473 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 3474 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 3475 | try wip_nav.declCommon(.{ | |
| 3476 | .decl = .decl_namespace_struct, | |
| 3477 | .generic_decl = .generic_decl_const, | |
| 3478 | .decl_instance = .decl_instance_namespace_struct, | |
| 3479 | }, &nav, file, &decl); | |
| 3480 | try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); | |
| 3481 | } else { | |
| 3482 | const diw = &wip_nav.debug_info.writer; | |
| 3483 | const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file); | |
| 3484 | try wip_nav.abbrevCode(.empty_struct_type); | |
| 3485 | try diw.writeUleb128(file_gop.index); | |
| 3486 | try wip_nav.strp(name.toSlice(ip)); | |
| 3487 | try diw.writeByte(@intFromBool(true)); | |
| 3488 | } | |
| 3489 | } | |
| 3490 | /// Should only be called by the `link.ConstPool` implementation. | |
| 3491 | /// | |
| 3492 | /// Emits a DIE for the given comptime-only value (which may be a type). | |
| 3493 | pub fn updateConst(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) Allocator.Error!void { | |
| 3494 | updateConstInner(dwarf, pt, debug_const_index, value_index) catch |err| switch (err) { | |
| 3495 | error.OutOfMemory => |e| return e, | |
| 3496 | else => |e| std.debug.panic("DWARF TODO: '{t}' while updating constant\n", .{e}), | |
| 3554 | 3497 | }; |
| 3555 | defer dwarf.gpa.free(name); | |
| 3498 | } | |
| 3499 | fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void { | |
| 3500 | const zcu = pt.zcu; | |
| 3501 | const ip = &zcu.intern_pool; | |
| 3502 | ||
| 3503 | const val: Value = .fromInterned(value_index); | |
| 3504 | ||
| 3505 | if (val.typeOf(zcu).toIntern() == .type_type and !val.isUndef(zcu)) { | |
| 3506 | val.toType().assertHasLayout(zcu); | |
| 3507 | } else { | |
| 3508 | val.typeOf(zcu).assertHasLayout(zcu); | |
| 3509 | } | |
| 3510 | ||
| 3511 | if (value_index == .anyerror_type) return; // handled in `flush` instead | |
| 3512 | ||
| 3513 | const value_ip_key = ip.indexToKey(value_index); | |
| 3514 | switch (value_ip_key) { | |
| 3515 | .func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`) | |
| 3516 | .@"extern" => return, // populated by the Nav instead (`initWipNav`) | |
| 3517 | else => {}, | |
| 3518 | } | |
| 3519 | ||
| 3520 | switch (value_index) { | |
| 3521 | .generic_poison_type => log.debug("updateValue(anytype)", .{}), | |
| 3522 | else => log.debug("updateValue(@as({f}, {f}))", .{ | |
| 3523 | val.typeOf(zcu).fmt(pt), | |
| 3524 | val.fmtValue(pt), | |
| 3525 | }), | |
| 3526 | } | |
| 3527 | ||
| 3528 | const unit, const entry = dwarf.values.items[@intFromEnum(debug_const_index)]; | |
| 3529 | ||
| 3530 | for ([_]*Section{ | |
| 3531 | &dwarf.debug_aranges.section, | |
| 3532 | &dwarf.debug_info.section, | |
| 3533 | &dwarf.debug_line.section, | |
| 3534 | &dwarf.debug_loclists.section, | |
| 3535 | &dwarf.debug_rnglists.section, | |
| 3536 | }) |sec| sec.getUnit(unit).getEntry(entry).clear(); | |
| 3537 | ||
| 3538 | var wip_nav: WipNav = .{ | |
| 3539 | .dwarf = dwarf, | |
| 3540 | .pt = pt, | |
| 3541 | .unit = unit, | |
| 3542 | .entry = entry, | |
| 3543 | .any_children = false, | |
| 3544 | .func = .none, | |
| 3545 | .func_sym_index = undefined, | |
| 3546 | .func_high_pc = undefined, | |
| 3547 | .blocks = undefined, | |
| 3548 | .cfi = undefined, | |
| 3549 | .debug_frame = .init(dwarf.gpa), | |
| 3550 | .debug_info = .init(dwarf.gpa), | |
| 3551 | .debug_line = .init(dwarf.gpa), | |
| 3552 | .debug_loclists = .init(dwarf.gpa), | |
| 3553 | }; | |
| 3554 | defer wip_nav.deinit(); | |
| 3555 | ||
| 3556 | // TODO: we really shouldn't need source locations at this point in the pipeline: we've lost | |
| 3557 | // that information by now. If the linker fundamentally cannot lower certain values, that needs | |
| 3558 | // to be caught in the frontend; if it can only hit transient failures, they should be reported | |
| 3559 | // without trying to tie them to a bogus source location. | |
| 3560 | const src_loc: Zcu.LazySrcLoc = .{ | |
| 3561 | .base_node_inst = inst: { | |
| 3562 | const mod_root_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; | |
| 3563 | const mod_root_type_index = zcu.fileRootType(mod_root_file_index); | |
| 3564 | break :inst ip.loadStructType(mod_root_type_index).zir_index; | |
| 3565 | }, | |
| 3566 | .offset = .{ .byte_abs = 0 }, | |
| 3567 | }; | |
| 3568 | ||
| 3569 | const diw = &wip_nav.debug_info.writer; | |
| 3570 | var big_int_space: Value.BigIntSpace = undefined; | |
| 3571 | switch (value_ip_key) { | |
| 3572 | .func => unreachable, // handled above | |
| 3573 | .@"extern" => unreachable, // handled above | |
| 3556 | 3574 | |
| 3557 | switch (ip.indexToKey(type_index)) { | |
| 3558 | .undef => { | |
| 3559 | try wip_nav.abbrevCode(.undefined_comptime_value); | |
| 3560 | try wip_nav.refType(.type); | |
| 3561 | }, | |
| 3562 | 3575 | .int_type => |int_type| { |
| 3563 | 3576 | try wip_nav.abbrevCode(.numeric_type); |
| 3564 | try wip_nav.strp(name); | |
| 3577 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3565 | 3578 | try diw.writeByte(switch (int_type.signedness) { |
| 3566 | 3579 | inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), |
| 3567 | 3580 | }); |
| 3568 | 3581 | try diw.writeUleb128(int_type.bits); |
| 3569 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3570 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3582 | try diw.writeUleb128(val.toType().abiSize(zcu)); | |
| 3583 | try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3571 | 3584 | }, |
| 3572 | 3585 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 3573 | 3586 | .one, .many, .c => { |
| 3574 | 3587 | const ptr_child_type: Type = .fromInterned(ptr_type.child); |
| 3575 | try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type); | |
| 3576 | try wip_nav.strp(name); | |
| 3588 | try wip_nav.abbrevCode(switch (ptr_type.flags.alignment) { | |
| 3589 | .none => if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type, | |
| 3590 | else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type, | |
| 3591 | }); | |
| 3592 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3577 | 3593 | if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel)); |
| 3578 | try diw.writeUleb128(ptr_type.flags.alignment.toByteUnits() orelse | |
| 3579 | ptr_child_type.abiAlignment(zcu).toByteUnits().?); | |
| 3594 | if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a); | |
| 3580 | 3595 | try diw.writeByte(@intFromEnum(ptr_type.flags.address_space)); |
| 3581 | 3596 | if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset( |
| 3582 | 3597 | .debug_info, |
| ... | ... | @@ -3600,12 +3615,12 @@ fn updateLazyType( |
| 3600 | 3615 | }, |
| 3601 | 3616 | .slice => { |
| 3602 | 3617 | try wip_nav.abbrevCode(.generated_struct_type); |
| 3603 | try wip_nav.strp(name); | |
| 3604 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3605 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3618 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3619 | try diw.writeUleb128(val.toType().abiSize(zcu)); | |
| 3620 | try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3606 | 3621 | try wip_nav.abbrevCode(.generated_field); |
| 3607 | 3622 | try wip_nav.strp("ptr"); |
| 3608 | const ptr_field_type = ty.slicePtrFieldType(zcu); | |
| 3623 | const ptr_field_type = val.toType().slicePtrFieldType(zcu); | |
| 3609 | 3624 | try wip_nav.refType(ptr_field_type); |
| 3610 | 3625 | try diw.writeUleb128(0); |
| 3611 | 3626 | try wip_nav.abbrevCode(.generated_field); |
| ... | ... | @@ -3619,7 +3634,7 @@ fn updateLazyType( |
| 3619 | 3634 | .array_type => |array_type| { |
| 3620 | 3635 | const array_child_type: Type = .fromInterned(array_type.child); |
| 3621 | 3636 | try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type); |
| 3622 | try wip_nav.strp(name); | |
| 3637 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3623 | 3638 | if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel)); |
| 3624 | 3639 | try wip_nav.refType(array_child_type); |
| 3625 | 3640 | try wip_nav.abbrevCode(.array_len); |
| ... | ... | @@ -3629,7 +3644,7 @@ fn updateLazyType( |
| 3629 | 3644 | }, |
| 3630 | 3645 | .vector_type => |vector_type| { |
| 3631 | 3646 | try wip_nav.abbrevCode(.vector_type); |
| 3632 | try wip_nav.strp(name); | |
| 3647 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3633 | 3648 | try wip_nav.refType(.fromInterned(vector_type.child)); |
| 3634 | 3649 | try wip_nav.abbrevCode(.array_len); |
| 3635 | 3650 | try wip_nav.refType(.usize); |
| ... | ... | @@ -3640,9 +3655,9 @@ fn updateLazyType( |
| 3640 | 3655 | const opt_child_type: Type = .fromInterned(opt_child_type_index); |
| 3641 | 3656 | const opt_repr = optRepr(opt_child_type, zcu); |
| 3642 | 3657 | try wip_nav.abbrevCode(.generated_union_type); |
| 3643 | try wip_nav.strp(name); | |
| 3644 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3645 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3658 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3659 | try diw.writeUleb128(val.toType().abiSize(zcu)); | |
| 3660 | try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3646 | 3661 | switch (opt_repr) { |
| 3647 | 3662 | .opv_null => { |
| 3648 | 3663 | try wip_nav.abbrevCode(.generated_field); |
| ... | ... | @@ -3720,12 +3735,12 @@ fn updateLazyType( |
| 3720 | 3735 | }; |
| 3721 | 3736 | |
| 3722 | 3737 | try wip_nav.abbrevCode(.generated_union_type); |
| 3723 | try wip_nav.strp(name); | |
| 3738 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3724 | 3739 | if (error_union_type.error_set_type != .generic_poison_type and |
| 3725 | 3740 | error_union_type.payload_type != .generic_poison_type) |
| 3726 | 3741 | { |
| 3727 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3728 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3742 | try diw.writeUleb128(val.toType().abiSize(zcu)); | |
| 3743 | try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3729 | 3744 | } else { |
| 3730 | 3745 | try diw.writeUleb128(0); |
| 3731 | 3746 | try diw.writeUleb128(1); |
| ... | ... | @@ -3791,20 +3806,24 @@ fn updateLazyType( |
| 3791 | 3806 | .bool, |
| 3792 | 3807 | => { |
| 3793 | 3808 | try wip_nav.abbrevCode(.numeric_type); |
| 3794 | try wip_nav.strp(name); | |
| 3795 | try diw.writeByte(if (type_index == .bool_type) | |
| 3809 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3810 | try diw.writeByte(if (value_index == .bool_type) | |
| 3796 | 3811 | DW.ATE.boolean |
| 3797 | else if (ty.isRuntimeFloat()) | |
| 3812 | else if (val.toType().isRuntimeFloat()) | |
| 3798 | 3813 | DW.ATE.float |
| 3799 | else if (ty.isSignedInt(zcu)) | |
| 3814 | else if (val.toType().isSignedInt(zcu)) | |
| 3800 | 3815 | DW.ATE.signed |
| 3801 | else if (ty.isUnsignedInt(zcu)) | |
| 3816 | else if (val.toType().isUnsignedInt(zcu)) | |
| 3802 | 3817 | DW.ATE.unsigned |
| 3803 | 3818 | else |
| 3804 | 3819 | unreachable); |
| 3805 | try diw.writeUleb128(ty.bitSize(zcu)); | |
| 3806 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3807 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3820 | try diw.writeUleb128(val.toType().bitSize(zcu)); | |
| 3821 | try diw.writeUleb128(val.toType().abiSize(zcu)); | |
| 3822 | try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3823 | }, | |
| 3824 | .generic_poison => { | |
| 3825 | try wip_nav.abbrevCode(.void_type); | |
| 3826 | try wip_nav.strp("anytype"); | |
| 3808 | 3827 | }, |
| 3809 | 3828 | .anyopaque, |
| 3810 | 3829 | .void, |
| ... | ... | @@ -3815,37 +3834,29 @@ fn updateLazyType( |
| 3815 | 3834 | .null, |
| 3816 | 3835 | .undefined, |
| 3817 | 3836 | .enum_literal, |
| 3818 | .generic_poison, | |
| 3819 | 3837 | => { |
| 3820 | 3838 | try wip_nav.abbrevCode(.void_type); |
| 3821 | try wip_nav.strp(if (type_index == .generic_poison_type) "anytype" else name); | |
| 3839 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3822 | 3840 | }, |
| 3823 | .anyerror => return, // delay until flush | |
| 3841 | .anyerror => unreachable, // already did early return above | |
| 3824 | 3842 | .adhoc_inferred_error_set => unreachable, |
| 3825 | 3843 | }, |
| 3826 | .struct_type, | |
| 3827 | .union_type, | |
| 3828 | .opaque_type, | |
| 3829 | => unreachable, | |
| 3830 | 3844 | .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { |
| 3831 | 3845 | try wip_nav.abbrevCode(.generated_empty_struct_type); |
| 3832 | try wip_nav.strp(name); | |
| 3846 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3833 | 3847 | try diw.writeByte(@intFromBool(false)); |
| 3834 | 3848 | } else { |
| 3835 | 3849 | try wip_nav.abbrevCode(.generated_struct_type); |
| 3836 | try wip_nav.strp(name); | |
| 3837 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3838 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3850 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3851 | try diw.writeUleb128(val.toType().abiSize(zcu)); | |
| 3852 | try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); | |
| 3839 | 3853 | var field_byte_offset: u64 = 0; |
| 3840 | 3854 | for (0..tuple_type.types.len) |field_index| { |
| 3841 | 3855 | const comptime_value = tuple_type.values.get(ip)[field_index]; |
| 3842 | 3856 | const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); |
| 3843 | 3857 | const has_runtime_bits, const has_comptime_state = switch (comptime_value) { |
| 3844 | 3858 | .none => .{ false, false }, |
| 3845 | else => .{ | |
| 3846 | field_type.hasRuntimeBits(zcu), | |
| 3847 | field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, | |
| 3848 | }, | |
| 3859 | else => .{ field_type.hasRuntimeBits(zcu), field_type.comptimeOnly(zcu) }, | |
| 3849 | 3860 | }; |
| 3850 | 3861 | try wip_nav.abbrevCode(if (has_comptime_state) |
| 3851 | 3862 | .struct_field_comptime_comptime_state |
| ... | ... | @@ -3875,25 +3886,284 @@ fn updateLazyType( |
| 3875 | 3886 | } |
| 3876 | 3887 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); |
| 3877 | 3888 | }, |
| 3889 | .struct_type => { | |
| 3890 | const loaded_struct = ip.loadStructType(value_index); | |
| 3891 | const ty = val.toType(); | |
| 3892 | const file = loaded_struct.zir_index.resolveFile(ip); | |
| 3893 | switch (loaded_struct.layout) { | |
| 3894 | .auto, .@"extern" => { | |
| 3895 | const struct_is_file: bool = if (loaded_struct.zir_index.resolve(ip)) |inst| f: { | |
| 3896 | break :f inst == .main_struct_inst; | |
| 3897 | } else false; | |
| 3898 | if (loaded_struct.name_nav.unwrap()) |nav_index| { | |
| 3899 | assert(!struct_is_file); | |
| 3900 | const nav = ip.getNav(nav_index); | |
| 3901 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 3902 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 3903 | try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ | |
| 3904 | .decl = .decl_namespace_struct, | |
| 3905 | .generic_decl = .generic_decl_const, | |
| 3906 | .decl_instance = .decl_instance_namespace_struct, | |
| 3907 | } else .{ | |
| 3908 | .decl = .decl_struct, | |
| 3909 | .generic_decl = .generic_decl_const, | |
| 3910 | .decl_instance = .decl_instance_struct, | |
| 3911 | }, &nav, file, &decl); | |
| 3912 | } else { | |
| 3913 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 3914 | try wip_nav.abbrevCode(switch (loaded_struct.field_types.len) { | |
| 3915 | 0 => if (struct_is_file) .empty_file else .empty_struct_type, | |
| 3916 | else => if (struct_is_file) .file else .struct_type, | |
| 3917 | }); | |
| 3918 | try diw.writeUleb128(file_gop.index); | |
| 3919 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | |
| 3920 | } | |
| 3921 | if (loaded_struct.field_types.len == 0) { | |
| 3922 | if (!struct_is_file) try diw.writeByte(@intFromBool(false)); | |
| 3923 | } else { | |
| 3924 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 3925 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 3926 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 3927 | const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); | |
| 3928 | // TODO: we currently don't emit information about default values for | |
| 3929 | // non-`comptime` fields, because these default values are resolved at a | |
| 3930 | // separate time in the compiler frontend. To emit this information, the | |
| 3931 | // frontend needs to tell us when the default values are available: like | |
| 3932 | // how `Zcu.PerThread.ensureTypeLayoutUpToDate` enqueues a link task to | |
| 3933 | // indicate completion of the type's layout, a task should be enqueued | |
| 3934 | // by `Zcu.PerThread.ensureStructDefaultsUpToDate`, and upon receiving | |
| 3935 | // it we should patch the correct default field values in. | |
| 3936 | const field_init: InternPool.Index = if (is_comptime) loaded_struct.field_defaults.getOrNone(ip, field_index) else .none; | |
| 3937 | assert(!(is_comptime and field_init == .none)); | |
| 3938 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 3939 | const has_runtime_bits, const has_comptime_state = switch (field_init) { | |
| 3940 | .none => .{ false, false }, | |
| 3941 | else => .{ | |
| 3942 | field_type.hasRuntimeBits(zcu), | |
| 3943 | field_type.comptimeOnly(zcu), | |
| 3944 | }, | |
| 3945 | }; | |
| 3946 | try wip_nav.abbrevCode(if (is_comptime) | |
| 3947 | if (has_comptime_state) | |
| 3948 | .struct_field_comptime_comptime_state | |
| 3949 | else if (has_runtime_bits) | |
| 3950 | .struct_field_comptime_runtime_bits | |
| 3951 | else | |
| 3952 | .struct_field_comptime | |
| 3953 | else if (field_init != .none) | |
| 3954 | if (has_comptime_state) | |
| 3955 | .struct_field_default_comptime_state | |
| 3956 | else if (has_runtime_bits) | |
| 3957 | .struct_field_default_runtime_bits | |
| 3958 | else | |
| 3959 | .struct_field | |
| 3960 | else | |
| 3961 | .struct_field); | |
| 3962 | try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); | |
| 3963 | try wip_nav.refType(field_type); | |
| 3964 | if (!is_comptime) { | |
| 3965 | try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); | |
| 3966 | try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 3967 | field_type.abiAlignment(zcu).toByteUnits().?); | |
| 3968 | } | |
| 3969 | if (has_comptime_state) | |
| 3970 | try wip_nav.refValue(.fromInterned(field_init)) | |
| 3971 | else if (has_runtime_bits) | |
| 3972 | try wip_nav.blockValue(ty.srcLoc(zcu), .fromInterned(field_init)); | |
| 3973 | } | |
| 3974 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 3975 | } | |
| 3976 | }, | |
| 3977 | .@"packed" => { | |
| 3978 | const need_terminator: bool = if (loaded_struct.name_nav.unwrap()) |nav_index| t: { | |
| 3979 | const nav = ip.getNav(nav_index); | |
| 3980 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 3981 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 3982 | try wip_nav.declCommon(.{ | |
| 3983 | .decl = .decl_packed_struct, | |
| 3984 | .generic_decl = .generic_decl_const, | |
| 3985 | .decl_instance = .decl_instance_packed_struct, | |
| 3986 | }, &nav, file, &decl); | |
| 3987 | break :t true; | |
| 3988 | } else t: { | |
| 3989 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 3990 | try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); | |
| 3991 | try diw.writeUleb128(file_gop.index); | |
| 3992 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | |
| 3993 | break :t loaded_struct.field_types.len > 0; | |
| 3994 | }; | |
| 3995 | try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); | |
| 3996 | var field_bit_offset: u16 = 0; | |
| 3997 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 3998 | try wip_nav.abbrevCode(.packed_struct_field); | |
| 3999 | try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4000 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 4001 | try wip_nav.refType(field_type); | |
| 4002 | try diw.writeUleb128(field_bit_offset); | |
| 4003 | field_bit_offset += @intCast(field_type.bitSize(zcu)); | |
| 4004 | } | |
| 4005 | if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4006 | }, | |
| 4007 | } | |
| 4008 | }, | |
| 4009 | .union_type => { | |
| 4010 | const loaded_union = ip.loadUnionType(value_index); | |
| 4011 | const file = loaded_union.zir_index.resolveFile(ip); | |
| 4012 | switch (loaded_union.layout) { | |
| 4013 | .auto, .@"extern" => { | |
| 4014 | const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: { | |
| 4015 | const nav = ip.getNav(nav_index); | |
| 4016 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 4017 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 4018 | try wip_nav.declCommon(.{ | |
| 4019 | .decl = .decl_union, | |
| 4020 | .generic_decl = .generic_decl_const, | |
| 4021 | .decl_instance = .decl_instance_union, | |
| 4022 | }, &nav, file, &decl); | |
| 4023 | break :t true; | |
| 4024 | } else t: { | |
| 4025 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 4026 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); | |
| 4027 | try diw.writeUleb128(file_gop.index); | |
| 4028 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | |
| 4029 | break :t loaded_union.field_types.len > 0; | |
| 4030 | }; | |
| 4031 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | |
| 4032 | try diw.writeUleb128(union_layout.abi_size); | |
| 4033 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); | |
| 4034 | const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 4035 | if (loaded_union.has_runtime_tag) { | |
| 4036 | try wip_nav.abbrevCode(.tagged_union); | |
| 4037 | try wip_nav.infoSectionOffset( | |
| 4038 | .debug_info, | |
| 4039 | wip_nav.unit, | |
| 4040 | wip_nav.entry, | |
| 4041 | @intCast(diw.end + dwarf.sectionOffsetBytes()), | |
| 4042 | ); | |
| 4043 | { | |
| 4044 | try wip_nav.abbrevCode(.generated_field); | |
| 4045 | try wip_nav.strp("tag"); | |
| 4046 | try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); | |
| 4047 | try diw.writeUleb128(union_layout.tagOffset()); | |
| 4048 | ||
| 4049 | for (0..loaded_union.field_types.len) |field_index| { | |
| 4050 | try wip_nav.enumConstValue(loaded_tag, .{ | |
| 4051 | .sdata = .signed_tagged_union_field, | |
| 4052 | .udata = .unsigned_tagged_union_field, | |
| 4053 | .block = .big_tagged_union_field, | |
| 4054 | }, field_index); | |
| 4055 | { | |
| 4056 | try wip_nav.abbrevCode(.struct_field); | |
| 4057 | try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4058 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4059 | try wip_nav.refType(field_type); | |
| 4060 | try diw.writeUleb128(union_layout.payloadOffset()); | |
| 4061 | try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 4062 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4063 | } | |
| 4064 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4065 | } | |
| 4066 | } | |
| 4067 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4068 | } else for (0..loaded_union.field_types.len) |field_index| { | |
| 4069 | try wip_nav.abbrevCode(.untagged_union_field); | |
| 4070 | try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4071 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4072 | try wip_nav.refType(field_type); | |
| 4073 | try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 4074 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4075 | } | |
| 4076 | if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4077 | }, | |
| 4078 | .@"packed" => { | |
| 4079 | // TODO: debug info for packed unions | |
| 4080 | try wip_nav.abbrevCode(.numeric_type); | |
| 4081 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | |
| 4082 | const backing_int_ty: Type = .fromInterned(loaded_union.packed_backing_int_type); | |
| 4083 | const int_info = backing_int_ty.intInfo(zcu); | |
| 4084 | try diw.writeByte(switch (int_info.signedness) { | |
| 4085 | inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), | |
| 4086 | }); | |
| 4087 | try diw.writeUleb128(int_info.bits); | |
| 4088 | try diw.writeUleb128(backing_int_ty.abiSize(zcu)); | |
| 4089 | try diw.writeUleb128(backing_int_ty.abiAlignment(zcu).toByteUnits().?); | |
| 4090 | }, | |
| 4091 | } | |
| 4092 | }, | |
| 3878 | 4093 | .enum_type => { |
| 3879 | const loaded_enum = ip.loadEnumType(type_index); | |
| 3880 | try wip_nav.abbrevCode(if (loaded_enum.names.len == 0) .generated_empty_enum_type else .generated_enum_type); | |
| 3881 | try wip_nav.strp(name); | |
| 3882 | try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); | |
| 3883 | for (0..loaded_enum.names.len) |field_index| { | |
| 3884 | try wip_nav.enumConstValue(loaded_enum, .{ | |
| 3885 | .sdata = .signed_enum_field, | |
| 3886 | .udata = .unsigned_enum_field, | |
| 3887 | .block = .big_enum_field, | |
| 3888 | }, field_index); | |
| 3889 | try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); | |
| 4094 | const loaded_enum = ip.loadEnumType(value_index); | |
| 4095 | if (loaded_enum.zir_index.unwrap()) |zir_index| { | |
| 4096 | assert(loaded_enum.owner_union == .none); | |
| 4097 | const file = zir_index.resolveFile(ip); | |
| 4098 | if (loaded_enum.name_nav.unwrap()) |nav_index| { | |
| 4099 | const nav = ip.getNav(nav_index); | |
| 4100 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 4101 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 4102 | try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{ | |
| 4103 | .decl = .decl_enum, | |
| 4104 | .generic_decl = .generic_decl_const, | |
| 4105 | .decl_instance = .decl_instance_enum, | |
| 4106 | } else .{ | |
| 4107 | .decl = .decl_empty_enum, | |
| 4108 | .generic_decl = .generic_decl_const, | |
| 4109 | .decl_instance = .decl_instance_empty_enum, | |
| 4110 | }, &nav, file, &decl); | |
| 4111 | } else { | |
| 4112 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 4113 | try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type); | |
| 4114 | try diw.writeUleb128(file_gop.index); | |
| 4115 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | |
| 4116 | } | |
| 4117 | try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); | |
| 4118 | for (0..loaded_enum.field_names.len) |field_index| { | |
| 4119 | try wip_nav.enumConstValue(loaded_enum, .{ | |
| 4120 | .sdata = .signed_enum_field, | |
| 4121 | .udata = .unsigned_enum_field, | |
| 4122 | .block = .big_enum_field, | |
| 4123 | }, field_index); | |
| 4124 | try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4125 | } | |
| 4126 | if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4127 | } else { | |
| 4128 | assert(loaded_enum.owner_union != .none); | |
| 4129 | try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type); | |
| 4130 | try wip_nav.strp(loaded_enum.name.toSlice(ip)); | |
| 4131 | try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); | |
| 4132 | for (0..loaded_enum.field_names.len) |field_index| { | |
| 4133 | try wip_nav.enumConstValue(loaded_enum, .{ | |
| 4134 | .sdata = .signed_enum_field, | |
| 4135 | .udata = .unsigned_enum_field, | |
| 4136 | .block = .big_enum_field, | |
| 4137 | }, field_index); | |
| 4138 | try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4139 | } | |
| 4140 | if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4141 | } | |
| 4142 | }, | |
| 4143 | .opaque_type => { | |
| 4144 | const loaded_opaque = ip.loadOpaqueType(value_index); | |
| 4145 | const file = loaded_opaque.zir_index.resolveFile(ip); | |
| 4146 | if (loaded_opaque.name_nav.unwrap()) |nav_index| { | |
| 4147 | const nav = ip.getNav(nav_index); | |
| 4148 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 4149 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 4150 | try wip_nav.declCommon(.{ | |
| 4151 | .decl = .decl_namespace_struct, | |
| 4152 | .generic_decl = .generic_decl_const, | |
| 4153 | .decl_instance = .decl_instance_namespace_struct, | |
| 4154 | }, &nav, file, &decl); | |
| 4155 | } else { | |
| 4156 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 4157 | try wip_nav.abbrevCode(.empty_struct_type); | |
| 4158 | try diw.writeUleb128(file_gop.index); | |
| 4159 | try wip_nav.strp(loaded_opaque.name.toSlice(ip)); | |
| 3890 | 4160 | } |
| 3891 | if (loaded_enum.names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4161 | try diw.writeByte(@intFromBool(true)); | |
| 3892 | 4162 | }, |
| 3893 | 4163 | .func_type => |func_type| { |
| 3894 | 4164 | const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; |
| 3895 | 4165 | try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type); |
| 3896 | try wip_nav.strp(name); | |
| 4166 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3897 | 4167 | const cc: DW.CC = cc: { |
| 3898 | 4168 | if (zcu.getTarget().cCallingConvention()) |cc| { |
| 3899 | 4169 | if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) { |
| ... | ... | @@ -3975,7 +4245,7 @@ fn updateLazyType( |
| 3975 | 4245 | }, |
| 3976 | 4246 | .error_set_type => |error_set_type| { |
| 3977 | 4247 | try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type); |
| 3978 | try wip_nav.strp(name); | |
| 4248 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3979 | 4249 | try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ |
| 3980 | 4250 | .signedness = .unsigned, |
| 3981 | 4251 | .bits = zcu.errorSetBits(), |
| ... | ... | @@ -3990,100 +4260,28 @@ fn updateLazyType( |
| 3990 | 4260 | }, |
| 3991 | 4261 | .inferred_error_set_type => |func| { |
| 3992 | 4262 | try wip_nav.abbrevCode(.inferred_error_set_type); |
| 3993 | try wip_nav.strp(name); | |
| 4263 | try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); | |
| 3994 | 4264 | try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) { |
| 3995 | 4265 | .none => .anyerror_type, |
| 3996 | 4266 | else => |ies| ies, |
| 3997 | 4267 | })); |
| 3998 | 4268 | }, |
| 3999 | 4269 | |
| 4000 | // values, not types | |
| 4001 | .simple_value, | |
| 4002 | .variable, | |
| 4003 | .@"extern", | |
| 4004 | .func, | |
| 4005 | .int, | |
| 4006 | .err, | |
| 4007 | .error_union, | |
| 4008 | .enum_literal, | |
| 4009 | .enum_tag, | |
| 4010 | .empty_enum_value, | |
| 4011 | .float, | |
| 4012 | .ptr, | |
| 4013 | .slice, | |
| 4014 | .opt, | |
| 4015 | .aggregate, | |
| 4016 | .un, | |
| 4017 | // memoization, not types | |
| 4018 | .memoized_call, | |
| 4019 | => unreachable, | |
| 4020 | } | |
| 4021 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | |
| 4022 | } | |
| 4023 | ||
| 4024 | fn updateLazyValue( | |
| 4025 | dwarf: *Dwarf, | |
| 4026 | pt: Zcu.PerThread, | |
| 4027 | src_loc: Zcu.LazySrcLoc, | |
| 4028 | value_index: InternPool.Index, | |
| 4029 | pending_lazy: *WipNav.PendingLazy, | |
| 4030 | ) (UpdateError || Writer.Error)!void { | |
| 4031 | const zcu = pt.zcu; | |
| 4032 | const ip = &zcu.intern_pool; | |
| 4033 | assert(ip.typeOf(value_index) != .type_type); | |
| 4034 | log.debug("updateLazyValue(@as({f}, {f}))", .{ | |
| 4035 | Value.fromInterned(value_index).typeOf(zcu).fmt(pt), | |
| 4036 | Value.fromInterned(value_index).fmtValue(pt), | |
| 4037 | }); | |
| 4038 | var wip_nav: WipNav = .{ | |
| 4039 | .dwarf = dwarf, | |
| 4040 | .pt = pt, | |
| 4041 | .unit = .main, | |
| 4042 | .entry = dwarf.values.get(value_index).?, | |
| 4043 | .any_children = false, | |
| 4044 | .func = .none, | |
| 4045 | .func_sym_index = undefined, | |
| 4046 | .func_high_pc = undefined, | |
| 4047 | .blocks = undefined, | |
| 4048 | .cfi = undefined, | |
| 4049 | .debug_frame = .init(dwarf.gpa), | |
| 4050 | .debug_info = .init(dwarf.gpa), | |
| 4051 | .debug_line = .init(dwarf.gpa), | |
| 4052 | .debug_loclists = .init(dwarf.gpa), | |
| 4053 | .pending_lazy = pending_lazy.*, | |
| 4054 | }; | |
| 4055 | defer { | |
| 4056 | pending_lazy.* = wip_nav.pending_lazy; | |
| 4057 | wip_nav.pending_lazy = .empty; | |
| 4058 | wip_nav.deinit(); | |
| 4059 | } | |
| 4060 | const diw = &wip_nav.debug_info.writer; | |
| 4061 | var big_int_space: Value.BigIntSpace = undefined; | |
| 4062 | switch (ip.indexToKey(value_index)) { | |
| 4063 | .int_type, | |
| 4064 | .ptr_type, | |
| 4065 | .array_type, | |
| 4066 | .vector_type, | |
| 4067 | .opt_type, | |
| 4068 | .anyframe_type, | |
| 4069 | .error_union_type, | |
| 4070 | .simple_type, | |
| 4071 | .struct_type, | |
| 4072 | .tuple_type, | |
| 4073 | .union_type, | |
| 4074 | .opaque_type, | |
| 4075 | .enum_type, | |
| 4076 | .func_type, | |
| 4077 | .error_set_type, | |
| 4078 | .inferred_error_set_type, | |
| 4079 | => unreachable, // already handled | |
| 4080 | 4270 | .undef => |ty| { |
| 4081 | 4271 | try wip_nav.abbrevCode(.undefined_comptime_value); |
| 4082 | 4272 | try wip_nav.refType(.fromInterned(ty)); |
| 4083 | 4273 | }, |
| 4084 | .simple_value => unreachable, // opv state | |
| 4085 | .variable, .@"extern" => unreachable, // not a value | |
| 4086 | .func => unreachable, // already handled | |
| 4274 | .simple_value => |simple_value| switch (simple_value) { | |
| 4275 | .void => unreachable, // opv state | |
| 4276 | .true, .false => unreachable, // runtime bits | |
| 4277 | .@"unreachable" => unreachable, // not a value | |
| 4278 | .null => { | |
| 4279 | // TODO: proper representation for this | |
| 4280 | try wip_nav.abbrevCode(.undefined_comptime_value); | |
| 4281 | try wip_nav.refType(.null); | |
| 4282 | }, | |
| 4283 | }, | |
| 4284 | .variable => unreachable, // not a value | |
| 4087 | 4285 | .int => |int| { |
| 4088 | 4286 | try wip_nav.bigIntConstValue(.{ |
| 4089 | 4287 | .sdata = .sdata_comptime_value, |
| ... | ... | @@ -4092,6 +4290,15 @@ fn updateLazyValue( |
| 4092 | 4290 | }, .fromInterned(int.ty), Value.fromInterned(value_index).toBigInt(&big_int_space, zcu)); |
| 4093 | 4291 | try wip_nav.refType(.fromInterned(int.ty)); |
| 4094 | 4292 | }, |
| 4293 | .bitpack => |bitpack| { | |
| 4294 | const backing_int_val: Value = .fromInterned(bitpack.backing_int_val); | |
| 4295 | try wip_nav.bigIntConstValue(.{ | |
| 4296 | .sdata = .sdata_comptime_value, | |
| 4297 | .udata = .udata_comptime_value, | |
| 4298 | .block = .block_comptime_value, | |
| 4299 | }, backing_int_val.typeOf(zcu), backing_int_val.toBigInt(&big_int_space, zcu)); | |
| 4300 | try wip_nav.refType(.fromInterned(bitpack.ty)); | |
| 4301 | }, | |
| 4095 | 4302 | .err => |err| { |
| 4096 | 4303 | try wip_nav.abbrevCode(.udata_comptime_value); |
| 4097 | 4304 | try wip_nav.refType(.fromInterned(err.ty)); |
| ... | ... | @@ -4117,7 +4324,7 @@ fn updateLazyValue( |
| 4117 | 4324 | .payload => |payload_val| { |
| 4118 | 4325 | const payload_type: Type = .fromInterned(ip.typeOf(payload_val)); |
| 4119 | 4326 | const has_runtime_bits = payload_type.hasRuntimeBits(zcu); |
| 4120 | const has_comptime_state = payload_type.comptimeOnly(zcu) and try payload_type.onePossibleValue(pt) == null; | |
| 4327 | const has_comptime_state = payload_type.comptimeOnly(zcu); | |
| 4121 | 4328 | try wip_nav.abbrevCode(if (has_comptime_state) |
| 4122 | 4329 | .comptime_value_field_comptime_state |
| 4123 | 4330 | else if (has_runtime_bits) |
| ... | ... | @@ -4153,7 +4360,6 @@ fn updateLazyValue( |
| 4153 | 4360 | }, .fromInterned(int.ty), Value.fromInterned(value_index).toBigInt(&big_int_space, zcu)); |
| 4154 | 4361 | try wip_nav.refType(.fromInterned(enum_tag.ty)); |
| 4155 | 4362 | }, |
| 4156 | .empty_enum_value => unreachable, | |
| 4157 | 4363 | .float => |float| { |
| 4158 | 4364 | switch (float.storage) { |
| 4159 | 4365 | .f16 => |f16_val| { |
| ... | ... | @@ -4194,11 +4400,11 @@ fn updateLazyValue( |
| 4194 | 4400 | var byte_offset = ptr.byte_offset; |
| 4195 | 4401 | const base_unit, const base_entry = while (true) { |
| 4196 | 4402 | const base_ptr, const access: Access = base_ptr_access: switch (base_addr) { |
| 4197 | .nav => |nav_index| break try wip_nav.getNavEntry(nav_index), | |
| 4403 | .nav => |nav_index| break try dwarf.getNavEntry(nav_index), | |
| 4198 | 4404 | .comptime_alloc, .comptime_field => unreachable, |
| 4199 | 4405 | .uav => |uav| { |
| 4200 | 4406 | const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); |
| 4201 | if (try uav_ty.onePossibleValue(pt)) |_| { | |
| 4407 | if (uav_ty.classify(zcu) == .one_possible_value) { | |
| 4202 | 4408 | try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0) |
| 4203 | 4409 | .aggregate_udata_comptime_value |
| 4204 | 4410 | else |
| ... | ... | @@ -4311,22 +4517,12 @@ fn updateLazyValue( |
| 4311 | 4517 | switch (optRepr(opt_child_type, zcu)) { |
| 4312 | 4518 | .opv_null => try diw.writeUleb128(0), |
| 4313 | 4519 | .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)), |
| 4314 | .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)), | |
| 4315 | .pointer => if (opt_child_type.comptimeOnly(zcu)) { | |
| 4316 | var buf: [8]u8 = undefined; | |
| 4317 | const bytes = buf[0..@divExact(zcu.getTarget().ptrBitWidth(), 8)]; | |
| 4318 | dwarf.writeInt(bytes, switch (opt.val) { | |
| 4319 | .none => 0, | |
| 4320 | else => opt_child_type.ptrAlignment(zcu).toByteUnits().?, | |
| 4321 | }); | |
| 4322 | try diw.writeUleb128(bytes.len); | |
| 4323 | try diw.writeAll(bytes); | |
| 4324 | } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)), | |
| 4520 | .error_set, .pointer => try wip_nav.blockValue(src_loc, .fromInterned(value_index)), | |
| 4325 | 4521 | } |
| 4326 | 4522 | } |
| 4327 | 4523 | if (opt.val != .none) child_field: { |
| 4328 | 4524 | const has_runtime_bits = opt_child_type.hasRuntimeBits(zcu); |
| 4329 | const has_comptime_state = opt_child_type.comptimeOnly(zcu) and try opt_child_type.onePossibleValue(pt) == null; | |
| 4525 | const has_comptime_state = opt_child_type.comptimeOnly(zcu); | |
| 4330 | 4526 | try wip_nav.abbrevCode(if (has_comptime_state) |
| 4331 | 4527 | .comptime_value_field_comptime_state |
| 4332 | 4528 | else if (has_runtime_bits) |
| ... | ... | @@ -4349,17 +4545,17 @@ fn updateLazyValue( |
| 4349 | 4545 | const loaded_struct_type = ip.loadStructType(aggregate.ty); |
| 4350 | 4546 | assert(loaded_struct_type.layout == .auto); |
| 4351 | 4547 | for (0..loaded_struct_type.field_types.len) |field_index| { |
| 4352 | if (loaded_struct_type.fieldIsComptime(ip, field_index)) continue; | |
| 4548 | if (loaded_struct_type.field_is_comptime_bits.get(ip, field_index)) continue; | |
| 4353 | 4549 | const field_type: Type = .fromInterned(loaded_struct_type.field_types.get(ip)[field_index]); |
| 4354 | 4550 | const has_runtime_bits = field_type.hasRuntimeBits(zcu); |
| 4355 | const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; | |
| 4551 | const has_comptime_state = field_type.comptimeOnly(zcu); | |
| 4356 | 4552 | try wip_nav.abbrevCode(if (has_comptime_state) |
| 4357 | 4553 | .comptime_value_field_comptime_state |
| 4358 | 4554 | else if (has_runtime_bits) |
| 4359 | 4555 | .comptime_value_field_runtime_bits |
| 4360 | 4556 | else |
| 4361 | 4557 | continue); |
| 4362 | try wip_nav.strp(loaded_struct_type.fieldName(ip, field_index).toSlice(ip)); | |
| 4558 | try wip_nav.strp(loaded_struct_type.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4363 | 4559 | const field_value: Value = .fromInterned(switch (aggregate.storage) { |
| 4364 | 4560 | .bytes => unreachable, |
| 4365 | 4561 | .elems => |elems| elems[field_index], |
| ... | ... | @@ -4375,7 +4571,7 @@ fn updateLazyValue( |
| 4375 | 4571 | if (tuple_type.values.get(ip)[field_index] != .none) continue; |
| 4376 | 4572 | const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); |
| 4377 | 4573 | const has_runtime_bits = field_type.hasRuntimeBits(zcu); |
| 4378 | const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; | |
| 4574 | const has_comptime_state = field_type.comptimeOnly(zcu); | |
| 4379 | 4575 | try wip_nav.abbrevCode(if (has_comptime_state) |
| 4380 | 4576 | .comptime_value_field_comptime_state |
| 4381 | 4577 | else if (has_runtime_bits) |
| ... | ... | @@ -4400,7 +4596,7 @@ fn updateLazyValue( |
| 4400 | 4596 | inline .array_type, .vector_type => |sequence_type| { |
| 4401 | 4597 | const child_type: Type = .fromInterned(sequence_type.child); |
| 4402 | 4598 | const has_runtime_bits = child_type.hasRuntimeBits(zcu); |
| 4403 | const has_comptime_state = child_type.comptimeOnly(zcu) and try child_type.onePossibleValue(pt) == null; | |
| 4599 | const has_comptime_state = child_type.comptimeOnly(zcu); | |
| 4404 | 4600 | for (switch (aggregate.storage) { |
| 4405 | 4601 | .bytes => unreachable, |
| 4406 | 4602 | .elems => |elems| elems, |
| ... | ... | @@ -4427,12 +4623,12 @@ fn updateLazyValue( |
| 4427 | 4623 | try wip_nav.refType(.fromInterned(un.ty)); |
| 4428 | 4624 | field: { |
| 4429 | 4625 | const loaded_union_type = ip.loadUnionType(un.ty); |
| 4430 | assert(loaded_union_type.flagsUnordered(ip).layout == .auto); | |
| 4626 | assert(loaded_union_type.layout == .auto); | |
| 4431 | 4627 | const field_index = zcu.unionTagFieldIndex(loaded_union_type, Value.fromInterned(un.tag)).?; |
| 4432 | 4628 | const field_ty: Type = .fromInterned(loaded_union_type.field_types.get(ip)[field_index]); |
| 4433 | const field_name = loaded_union_type.loadTagType(ip).names.get(ip)[field_index]; | |
| 4629 | const field_name = ip.loadEnumType(loaded_union_type.enum_tag_type).field_names.get(ip)[field_index]; | |
| 4434 | 4630 | const has_runtime_bits = field_ty.hasRuntimeBits(zcu); |
| 4435 | const has_comptime_state = field_ty.comptimeOnly(zcu) and try field_ty.onePossibleValue(pt) == null; | |
| 4631 | const has_comptime_state = field_ty.comptimeOnly(zcu); | |
| 4436 | 4632 | try wip_nav.abbrevCode(if (has_comptime_state) |
| 4437 | 4633 | .comptime_value_field_comptime_state |
| 4438 | 4634 | else if (has_runtime_bits) |
| ... | ... | @@ -4449,7 +4645,8 @@ fn updateLazyValue( |
| 4449 | 4645 | }, |
| 4450 | 4646 | .memoized_call => unreachable, // not a value |
| 4451 | 4647 | } |
| 4452 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | |
| 4648 | try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); | |
| 4649 | try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); | |
| 4453 | 4650 | } |
| 4454 | 4651 | |
| 4455 | 4652 | fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } { |
| ... | ... | @@ -4464,312 +4661,6 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, err |
| 4464 | 4661 | }; |
| 4465 | 4662 | } |
| 4466 | 4663 | |
| 4467 | pub fn updateContainerType( | |
| 4468 | dwarf: *Dwarf, | |
| 4469 | pt: Zcu.PerThread, | |
| 4470 | type_index: InternPool.Index, | |
| 4471 | ) UpdateError!void { | |
| 4472 | return dwarf.updateContainerTypeWriterError(pt, type_index) catch |err| switch (err) { | |
| 4473 | error.WriteFailed => error.OutOfMemory, | |
| 4474 | else => |e| e, | |
| 4475 | }; | |
| 4476 | } | |
| 4477 | fn updateContainerTypeWriterError( | |
| 4478 | dwarf: *Dwarf, | |
| 4479 | pt: Zcu.PerThread, | |
| 4480 | type_index: InternPool.Index, | |
| 4481 | ) (UpdateError || Writer.Error)!void { | |
| 4482 | const zcu = pt.zcu; | |
| 4483 | const ip = &zcu.intern_pool; | |
| 4484 | const ty: Type = .fromInterned(type_index); | |
| 4485 | const ty_src_loc = ty.srcLoc(zcu); | |
| 4486 | log.debug("updateContainerType({f})", .{ty.fmt(pt)}); | |
| 4487 | ||
| 4488 | const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?; | |
| 4489 | const file = zcu.fileByIndex(inst_info.file); | |
| 4490 | const unit = try dwarf.getUnit(file.mod.?); | |
| 4491 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file); | |
| 4492 | if (inst_info.inst == .main_struct_inst) { | |
| 4493 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index); | |
| 4494 | if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit); | |
| 4495 | var wip_nav: WipNav = .{ | |
| 4496 | .dwarf = dwarf, | |
| 4497 | .pt = pt, | |
| 4498 | .unit = unit, | |
| 4499 | .entry = type_gop.value_ptr.*, | |
| 4500 | .any_children = false, | |
| 4501 | .func = .none, | |
| 4502 | .func_sym_index = undefined, | |
| 4503 | .func_high_pc = undefined, | |
| 4504 | .blocks = undefined, | |
| 4505 | .cfi = undefined, | |
| 4506 | .debug_frame = .init(dwarf.gpa), | |
| 4507 | .debug_info = .init(dwarf.gpa), | |
| 4508 | .debug_line = .init(dwarf.gpa), | |
| 4509 | .debug_loclists = .init(dwarf.gpa), | |
| 4510 | .pending_lazy = .empty, | |
| 4511 | }; | |
| 4512 | defer wip_nav.deinit(); | |
| 4513 | ||
| 4514 | const loaded_struct = ip.loadStructType(type_index); | |
| 4515 | ||
| 4516 | const diw = &wip_nav.debug_info.writer; | |
| 4517 | try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_file else .file); | |
| 4518 | try diw.writeUleb128(file_gop.index); | |
| 4519 | try wip_nav.strp(loaded_struct.name.toSlice(ip)); | |
| 4520 | if (loaded_struct.field_types.len > 0) { | |
| 4521 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 4522 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 4523 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 4524 | const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); | |
| 4525 | const field_init = loaded_struct.fieldInit(ip, field_index); | |
| 4526 | assert(!(is_comptime and field_init == .none)); | |
| 4527 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 4528 | const has_runtime_bits, const has_comptime_state = switch (field_init) { | |
| 4529 | .none => .{ false, false }, | |
| 4530 | else => .{ | |
| 4531 | field_type.hasRuntimeBits(zcu), | |
| 4532 | field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, | |
| 4533 | }, | |
| 4534 | }; | |
| 4535 | try wip_nav.abbrevCode(if (is_comptime) | |
| 4536 | if (has_comptime_state) | |
| 4537 | .struct_field_comptime_comptime_state | |
| 4538 | else if (has_runtime_bits) | |
| 4539 | .struct_field_comptime_runtime_bits | |
| 4540 | else | |
| 4541 | .struct_field_comptime | |
| 4542 | else if (field_init != .none) | |
| 4543 | if (has_comptime_state) | |
| 4544 | .struct_field_default_comptime_state | |
| 4545 | else if (has_runtime_bits) | |
| 4546 | .struct_field_default_runtime_bits | |
| 4547 | else | |
| 4548 | .struct_field | |
| 4549 | else | |
| 4550 | .struct_field); | |
| 4551 | try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); | |
| 4552 | try wip_nav.refType(field_type); | |
| 4553 | if (!is_comptime) { | |
| 4554 | try diw.writeUleb128(loaded_struct.offsets.get(ip)[field_index]); | |
| 4555 | try diw.writeUleb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 4556 | field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4557 | } | |
| 4558 | if (has_comptime_state) | |
| 4559 | try wip_nav.refValue(.fromInterned(field_init)) | |
| 4560 | else if (has_runtime_bits) | |
| 4561 | try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init)); | |
| 4562 | } | |
| 4563 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4564 | } | |
| 4565 | ||
| 4566 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | |
| 4567 | try wip_nav.updateLazy(ty_src_loc); | |
| 4568 | } else { | |
| 4569 | { | |
| 4570 | // Note that changes to ZIR instruction tracking only need to update this code | |
| 4571 | // if a newly-tracked instruction can be a type's owner `zir_index`. | |
| 4572 | comptime assert(Zir.inst_tracking_version == 0); | |
| 4573 | ||
| 4574 | const decl_inst = file.zir.?.instructions.get(@intFromEnum(inst_info.inst)); | |
| 4575 | const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) { | |
| 4576 | .struct_init, .struct_init_ref, .struct_init_anon => .anon, | |
| 4577 | .extended => switch (decl_inst.data.extended.opcode) { | |
| 4578 | .struct_decl => @as(Zir.Inst.StructDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, | |
| 4579 | .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, | |
| 4580 | .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, | |
| 4581 | .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, | |
| 4582 | ||
| 4583 | .reify_enum, | |
| 4584 | .reify_struct, | |
| 4585 | .reify_union, | |
| 4586 | => @enumFromInt(decl_inst.data.extended.small), | |
| 4587 | ||
| 4588 | else => unreachable, | |
| 4589 | }, | |
| 4590 | else => unreachable, | |
| 4591 | }; | |
| 4592 | if (name_strat == .parent) return; | |
| 4593 | } | |
| 4594 | ||
| 4595 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index); | |
| 4596 | if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit); | |
| 4597 | var wip_nav: WipNav = .{ | |
| 4598 | .dwarf = dwarf, | |
| 4599 | .pt = pt, | |
| 4600 | .unit = unit, | |
| 4601 | .entry = type_gop.value_ptr.*, | |
| 4602 | .any_children = false, | |
| 4603 | .func = .none, | |
| 4604 | .func_sym_index = undefined, | |
| 4605 | .func_high_pc = undefined, | |
| 4606 | .blocks = undefined, | |
| 4607 | .cfi = undefined, | |
| 4608 | .debug_frame = .init(dwarf.gpa), | |
| 4609 | .debug_info = .init(dwarf.gpa), | |
| 4610 | .debug_line = .init(dwarf.gpa), | |
| 4611 | .debug_loclists = .init(dwarf.gpa), | |
| 4612 | .pending_lazy = .empty, | |
| 4613 | }; | |
| 4614 | defer wip_nav.deinit(); | |
| 4615 | const diw = &wip_nav.debug_info.writer; | |
| 4616 | const name = try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}); | |
| 4617 | defer dwarf.gpa.free(name); | |
| 4618 | ||
| 4619 | switch (ip.indexToKey(type_index)) { | |
| 4620 | .struct_type => { | |
| 4621 | const loaded_struct = ip.loadStructType(type_index); | |
| 4622 | switch (loaded_struct.layout) { | |
| 4623 | .auto, .@"extern" => { | |
| 4624 | try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_struct_type else .struct_type); | |
| 4625 | try diw.writeUleb128(file_gop.index); | |
| 4626 | try wip_nav.strp(name); | |
| 4627 | if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { | |
| 4628 | try diw.writeUleb128(ty.abiSize(zcu)); | |
| 4629 | try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); | |
| 4630 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 4631 | const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); | |
| 4632 | const field_init = loaded_struct.fieldInit(ip, field_index); | |
| 4633 | assert(!(is_comptime and field_init == .none)); | |
| 4634 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 4635 | const has_runtime_bits, const has_comptime_state = switch (field_init) { | |
| 4636 | .none => .{ false, false }, | |
| 4637 | else => .{ | |
| 4638 | field_type.hasRuntimeBits(zcu), | |
| 4639 | field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, | |
| 4640 | }, | |
| 4641 | }; | |
| 4642 | try wip_nav.abbrevCode(if (is_comptime) | |
| 4643 | if (has_comptime_state) | |
| 4644 | .struct_field_comptime_comptime_state | |
| 4645 | else if (has_runtime_bits) | |
| 4646 | .struct_field_comptime_runtime_bits | |
| 4647 | else | |
| 4648 | .struct_field_comptime | |
| 4649 | else if (field_init != .none) | |
| 4650 | if (has_comptime_state) | |
| 4651 | .struct_field_default_comptime_state | |
| 4652 | else if (has_runtime_bits) | |
| 4653 | .struct_field_default_runtime_bits | |
| 4654 | else | |
| 4655 | .struct_field | |
| 4656 | else | |
| 4657 | .struct_field); | |
| 4658 | try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); | |
| 4659 | try wip_nav.refType(field_type); | |
| 4660 | if (!is_comptime) { | |
| 4661 | try diw.writeUleb128(loaded_struct.offsets.get(ip)[field_index]); | |
| 4662 | try diw.writeUleb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 4663 | field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4664 | } | |
| 4665 | if (has_comptime_state) | |
| 4666 | try wip_nav.refValue(.fromInterned(field_init)) | |
| 4667 | else if (has_runtime_bits) | |
| 4668 | try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init)); | |
| 4669 | } | |
| 4670 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4671 | } | |
| 4672 | }, | |
| 4673 | .@"packed" => { | |
| 4674 | try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); | |
| 4675 | try diw.writeUleb128(file_gop.index); | |
| 4676 | try wip_nav.strp(name); | |
| 4677 | try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); | |
| 4678 | var field_bit_offset: u16 = 0; | |
| 4679 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 4680 | try wip_nav.abbrevCode(.packed_struct_field); | |
| 4681 | try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); | |
| 4682 | const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 4683 | try wip_nav.refType(field_type); | |
| 4684 | try diw.writeUleb128(field_bit_offset); | |
| 4685 | field_bit_offset += @intCast(field_type.bitSize(zcu)); | |
| 4686 | } | |
| 4687 | if (loaded_struct.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4688 | }, | |
| 4689 | } | |
| 4690 | }, | |
| 4691 | .enum_type => { | |
| 4692 | const loaded_enum = ip.loadEnumType(type_index); | |
| 4693 | try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .enum_type else .empty_enum_type); | |
| 4694 | try diw.writeUleb128(file_gop.index); | |
| 4695 | try wip_nav.strp(name); | |
| 4696 | try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); | |
| 4697 | for (0..loaded_enum.names.len) |field_index| { | |
| 4698 | try wip_nav.enumConstValue(loaded_enum, .{ | |
| 4699 | .sdata = .signed_enum_field, | |
| 4700 | .udata = .unsigned_enum_field, | |
| 4701 | .block = .big_enum_field, | |
| 4702 | }, field_index); | |
| 4703 | try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); | |
| 4704 | } | |
| 4705 | if (loaded_enum.names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4706 | }, | |
| 4707 | .union_type => { | |
| 4708 | const loaded_union = ip.loadUnionType(type_index); | |
| 4709 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); | |
| 4710 | try diw.writeUleb128(file_gop.index); | |
| 4711 | try wip_nav.strp(name); | |
| 4712 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | |
| 4713 | try diw.writeUleb128(union_layout.abi_size); | |
| 4714 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); | |
| 4715 | const loaded_tag = loaded_union.loadTagType(ip); | |
| 4716 | if (loaded_union.hasTag(ip)) { | |
| 4717 | try wip_nav.abbrevCode(.tagged_union); | |
| 4718 | try wip_nav.infoSectionOffset( | |
| 4719 | .debug_info, | |
| 4720 | wip_nav.unit, | |
| 4721 | wip_nav.entry, | |
| 4722 | @intCast(diw.end + dwarf.sectionOffsetBytes()), | |
| 4723 | ); | |
| 4724 | { | |
| 4725 | try wip_nav.abbrevCode(.generated_field); | |
| 4726 | try wip_nav.strp("tag"); | |
| 4727 | try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); | |
| 4728 | try diw.writeUleb128(union_layout.tagOffset()); | |
| 4729 | ||
| 4730 | for (0..loaded_union.field_types.len) |field_index| { | |
| 4731 | try wip_nav.enumConstValue(loaded_tag, .{ | |
| 4732 | .sdata = .signed_tagged_union_field, | |
| 4733 | .udata = .unsigned_tagged_union_field, | |
| 4734 | .block = .big_tagged_union_field, | |
| 4735 | }, field_index); | |
| 4736 | { | |
| 4737 | try wip_nav.abbrevCode(.struct_field); | |
| 4738 | try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); | |
| 4739 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4740 | try wip_nav.refType(field_type); | |
| 4741 | try diw.writeUleb128(union_layout.payloadOffset()); | |
| 4742 | try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 4743 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4744 | } | |
| 4745 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4746 | } | |
| 4747 | } | |
| 4748 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4749 | } else for (0..loaded_union.field_types.len) |field_index| { | |
| 4750 | try wip_nav.abbrevCode(.untagged_union_field); | |
| 4751 | try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); | |
| 4752 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4753 | try wip_nav.refType(field_type); | |
| 4754 | try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse | |
| 4755 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4756 | } | |
| 4757 | if (loaded_union.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4758 | }, | |
| 4759 | .opaque_type => { | |
| 4760 | try wip_nav.abbrevCode(.empty_struct_type); | |
| 4761 | try diw.writeUleb128(file_gop.index); | |
| 4762 | try wip_nav.strp(name); | |
| 4763 | try diw.writeByte(@intFromBool(true)); | |
| 4764 | }, | |
| 4765 | else => unreachable, | |
| 4766 | } | |
| 4767 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); | |
| 4768 | try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written()); | |
| 4769 | try wip_nav.updateLazy(ty_src_loc); | |
| 4770 | } | |
| 4771 | } | |
| 4772 | ||
| 4773 | 4664 | pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void { |
| 4774 | 4665 | const comp = dwarf.bin_file.comp; |
| 4775 | 4666 | const io = comp.io; |
| ... | ... | @@ -4832,14 +4723,15 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro |
| 4832 | 4723 | const comp = dwarf.bin_file.comp; |
| 4833 | 4724 | const io = comp.io; |
| 4834 | 4725 | |
| 4726 | // Update `anyerror` based on the finished global error set. | |
| 4835 | 4727 | { |
| 4836 | const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type); | |
| 4837 | if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main); | |
| 4728 | const index = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, .anyerror_type); | |
| 4729 | const unit, const entry = dwarf.values.items[@intFromEnum(index)]; | |
| 4838 | 4730 | var wip_nav: WipNav = .{ |
| 4839 | 4731 | .dwarf = dwarf, |
| 4840 | 4732 | .pt = pt, |
| 4841 | .unit = .main, | |
| 4842 | .entry = type_gop.value_ptr.*, | |
| 4733 | .unit = unit, | |
| 4734 | .entry = entry, | |
| 4843 | 4735 | .any_children = false, |
| 4844 | 4736 | .func = .none, |
| 4845 | 4737 | .func_sym_index = undefined, |
| ... | ... | @@ -4850,7 +4742,6 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro |
| 4850 | 4742 | .debug_info = .init(dwarf.gpa), |
| 4851 | 4743 | .debug_line = .init(dwarf.gpa), |
| 4852 | 4744 | .debug_loclists = .init(dwarf.gpa), |
| 4853 | .pending_lazy = .empty, | |
| 4854 | 4745 | }; |
| 4855 | 4746 | defer wip_nav.deinit(); |
| 4856 | 4747 | const diw = &wip_nav.debug_info.writer; |
| ... | ... | @@ -4868,7 +4759,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro |
| 4868 | 4759 | } |
| 4869 | 4760 | if (global_error_set_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); |
| 4870 | 4761 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); |
| 4871 | try wip_nav.updateLazy(.unneeded); | |
| 4762 | try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); | |
| 4872 | 4763 | } |
| 4873 | 4764 | |
| 4874 | 4765 | for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { |
| ... | ... | @@ -5316,6 +5207,8 @@ const AbbrevCode = enum { |
| 5316 | 5207 | inferred_error_set_type, |
| 5317 | 5208 | ptr_type, |
| 5318 | 5209 | ptr_sentinel_type, |
| 5210 | ptr_aligned_type, | |
| 5211 | ptr_aligned_sentinel_type, | |
| 5319 | 5212 | is_const, |
| 5320 | 5213 | is_volatile, |
| 5321 | 5214 | array_type, |
| ... | ... | @@ -5952,12 +5845,29 @@ const AbbrevCode = enum { |
| 5952 | 5845 | .tag = .pointer_type, |
| 5953 | 5846 | .attrs = &.{ |
| 5954 | 5847 | .{ .name, .strp }, |
| 5955 | .{ .alignment, .udata }, | |
| 5956 | 5848 | .{ .address_class, .data1 }, |
| 5957 | 5849 | .{ .type, .ref_addr }, |
| 5958 | 5850 | }, |
| 5959 | 5851 | }, |
| 5960 | 5852 | .ptr_sentinel_type = .{ |
| 5853 | .tag = .pointer_type, | |
| 5854 | .attrs = &.{ | |
| 5855 | .{ .name, .strp }, | |
| 5856 | .{ .ZIG_sentinel, .block }, | |
| 5857 | .{ .address_class, .data1 }, | |
| 5858 | .{ .type, .ref_addr }, | |
| 5859 | }, | |
| 5860 | }, | |
| 5861 | .ptr_aligned_type = .{ | |
| 5862 | .tag = .pointer_type, | |
| 5863 | .attrs = &.{ | |
| 5864 | .{ .name, .strp }, | |
| 5865 | .{ .alignment, .udata }, | |
| 5866 | .{ .address_class, .data1 }, | |
| 5867 | .{ .type, .ref_addr }, | |
| 5868 | }, | |
| 5869 | }, | |
| 5870 | .ptr_aligned_sentinel_type = .{ | |
| 5961 | 5871 | .tag = .pointer_type, |
| 5962 | 5872 | .attrs = &.{ |
| 5963 | 5873 | .{ .name, .strp }, |
src/link/Elf.zig+2-12| ... | ... | @@ -1711,23 +1711,13 @@ pub fn updateContainerType( |
| 1711 | 1711 | self: *Elf, |
| 1712 | 1712 | pt: Zcu.PerThread, |
| 1713 | 1713 | ty: InternPool.Index, |
| 1714 | success: bool, | |
| 1714 | 1715 | ) link.File.UpdateContainerTypeError!void { |
| 1715 | 1716 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 1716 | 1717 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1717 | 1718 | } |
| 1718 | const zcu = pt.zcu; | |
| 1719 | const gpa = zcu.gpa; | |
| 1720 | return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) { | |
| 1719 | return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) { | |
| 1721 | 1720 | error.OutOfMemory => return error.OutOfMemory, |
| 1722 | else => |e| { | |
| 1723 | try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create( | |
| 1724 | gpa, | |
| 1725 | zcu.typeSrcLoc(ty), | |
| 1726 | "failed to update container type: {s}", | |
| 1727 | .{@errorName(e)}, | |
| 1728 | )); | |
| 1729 | return error.TypeFailureReported; | |
| 1730 | }, | |
| 1731 | 1721 | }; |
| 1732 | 1722 | } |
| 1733 | 1723 |
src/link/Elf/Object.zig+1-1| ... | ... | @@ -775,7 +775,7 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO |
| 775 | 775 | |
| 776 | 776 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); |
| 777 | 777 | if (!gop.found_existing) { |
| 778 | gop.value_ptr.* = .{}; | |
| 778 | gop.value_ptr.* = .empty; | |
| 779 | 779 | } |
| 780 | 780 | try gop.value_ptr.append(elf_file.base.comp.gpa, self.index); |
| 781 | 781 | } |
src/link/Elf/ZigObject.zig+6-5| ... | ... | @@ -84,7 +84,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 84 | 84 | const ptr_size = elf_file.ptrWidthBytes(); |
| 85 | 85 | |
| 86 | 86 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section |
| 87 | try self.relocs.append(gpa, .{}); // null relocs section | |
| 87 | try self.relocs.append(gpa, .empty); // null relocs section | |
| 88 | 88 | try self.strtab.buffer.append(gpa, 0); |
| 89 | 89 | |
| 90 | 90 | { |
| ... | ... | @@ -546,7 +546,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index { |
| 546 | 546 | atom_ptr.name_offset = name_off; |
| 547 | 547 | |
| 548 | 548 | const relocs_index: u32 = @intCast(self.relocs.items.len); |
| 549 | self.relocs.addOneAssumeCapacity().* = .{}; | |
| 549 | self.relocs.addOneAssumeCapacity().* = .empty; | |
| 550 | 550 | atom_ptr.relocs_section_index = relocs_index; |
| 551 | 551 | |
| 552 | 552 | return index; |
| ... | ... | @@ -730,7 +730,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O |
| 730 | 730 | |
| 731 | 731 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); |
| 732 | 732 | if (!gop.found_existing) { |
| 733 | gop.value_ptr.* = .{}; | |
| 733 | gop.value_ptr.* = .empty; | |
| 734 | 734 | } |
| 735 | 735 | try gop.value_ptr.append(elf_file.base.comp.gpa, self.index); |
| 736 | 736 | } |
| ... | ... | @@ -1479,7 +1479,7 @@ fn updateTlv( |
| 1479 | 1479 | |
| 1480 | 1480 | log.debug("updateTlv {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); |
| 1481 | 1481 | |
| 1482 | const required_alignment = pt.navAlignment(nav_index); | |
| 1482 | const required_alignment = zcu.navAlignment(nav_index); | |
| 1483 | 1483 | |
| 1484 | 1484 | const sym = self.symbol(sym_index); |
| 1485 | 1485 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| ... | ... | @@ -1719,11 +1719,12 @@ pub fn updateContainerType( |
| 1719 | 1719 | self: *ZigObject, |
| 1720 | 1720 | pt: Zcu.PerThread, |
| 1721 | 1721 | ty: InternPool.Index, |
| 1722 | success: bool, | |
| 1722 | 1723 | ) !void { |
| 1723 | 1724 | const tracy = trace(@src()); |
| 1724 | 1725 | defer tracy.end(); |
| 1725 | 1726 | |
| 1726 | if (self.dwarf) |*dwarf| try dwarf.updateContainerType(pt, ty); | |
| 1727 | if (self.dwarf) |*dwarf| try dwarf.updateContainerType(pt, ty, success); | |
| 1727 | 1728 | } |
| 1728 | 1729 | |
| 1729 | 1730 | fn updateLazySymbol( |
src/link/Elf2.zig+1-1| ... | ... | @@ -2906,7 +2906,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 2906 | 2906 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 2907 | 2907 | const sec_si = elf.navSection(ip, nav.status.fully_resolved); |
| 2908 | 2908 | const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ |
| 2909 | .alignment = pt.navAlignment(nav_index).toStdMem(), | |
| 2909 | .alignment = zcu.navAlignment(nav_index).toStdMem(), | |
| 2910 | 2910 | .moved = true, |
| 2911 | 2911 | }); |
| 2912 | 2912 | elf.nodes.appendAssumeCapacity(.{ .nav = nmi }); |
src/link/MachO/Atom.zig+1-1| ... | ... | @@ -561,7 +561,7 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { |
| 561 | 561 | defer macho_file.undefs_mutex.unlock(io); |
| 562 | 562 | const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]); |
| 563 | 563 | if (!gop.found_existing) { |
| 564 | gop.value_ptr.* = .{ .refs = .{} }; | |
| 564 | gop.value_ptr.* = .{ .refs = .empty }; | |
| 565 | 565 | } |
| 566 | 566 | try gop.value_ptr.refs.append(gpa, .{ .index = self.atom_index, .file = self.file }); |
| 567 | 567 | return true; |
src/link/MachO/ZigObject.zig+7-7| ... | ... | @@ -3,7 +3,7 @@ data: std.ArrayList(u8) = .empty, |
| 3 | 3 | basename: []const u8, |
| 4 | 4 | index: File.Index, |
| 5 | 5 | |
| 6 | symtab: std.MultiArrayList(Nlist) = .{}, | |
| 6 | symtab: std.MultiArrayList(Nlist) = .empty, | |
| 7 | 7 | strtab: StringTable = .{}, |
| 8 | 8 | |
| 9 | 9 | symbols: std.ArrayList(Symbol) = .empty, |
| ... | ... | @@ -29,7 +29,7 @@ uavs: UavTable = .{}, |
| 29 | 29 | tlv_initializers: TlvInitializerTable = .{}, |
| 30 | 30 | |
| 31 | 31 | /// A table of relocations. |
| 32 | relocs: RelocationTable = .{}, | |
| 32 | relocs: RelocationTable = .empty, | |
| 33 | 33 | |
| 34 | 34 | dwarf: ?Dwarf = null, |
| 35 | 35 | |
| ... | ... | @@ -150,7 +150,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name: MachO.String, macho_fil |
| 150 | 150 | atom.name = name; |
| 151 | 151 | |
| 152 | 152 | const relocs_index = @as(u32, @intCast(self.relocs.items.len)); |
| 153 | self.relocs.addOneAssumeCapacity().* = .{}; | |
| 153 | self.relocs.addOneAssumeCapacity().* = .empty; | |
| 154 | 154 | atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file); |
| 155 | 155 | |
| 156 | 156 | return index; |
| ... | ... | @@ -925,7 +925,7 @@ pub fn updateNav( |
| 925 | 925 | |
| 926 | 926 | const sect_index = try self.getNavOutputSection(macho_file, zcu, nav_index, code); |
| 927 | 927 | if (isThreadlocal(macho_file, nav_index)) |
| 928 | try self.updateTlv(macho_file, pt, nav_index, sym_index, sect_index, code) | |
| 928 | try self.updateTlv(macho_file, zcu, nav_index, sym_index, sect_index, code) | |
| 929 | 929 | else |
| 930 | 930 | try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code); |
| 931 | 931 | |
| ... | ... | @@ -1030,13 +1030,13 @@ fn updateNavCode( |
| 1030 | 1030 | fn updateTlv( |
| 1031 | 1031 | self: *ZigObject, |
| 1032 | 1032 | macho_file: *MachO, |
| 1033 | pt: Zcu.PerThread, | |
| 1033 | zcu: *Zcu, | |
| 1034 | 1034 | nav_index: InternPool.Nav.Index, |
| 1035 | 1035 | sym_index: Symbol.Index, |
| 1036 | 1036 | sect_index: u8, |
| 1037 | 1037 | code: []const u8, |
| 1038 | 1038 | ) !void { |
| 1039 | const ip = &pt.zcu.intern_pool; | |
| 1039 | const ip = &zcu.intern_pool; | |
| 1040 | 1040 | const nav = ip.getNav(nav_index); |
| 1041 | 1041 | |
| 1042 | 1042 | log.debug("updateTlv {f} (0x{x})", .{ nav.fqn.fmt(ip), nav_index }); |
| ... | ... | @@ -1045,7 +1045,7 @@ fn updateTlv( |
| 1045 | 1045 | const init_sym_index = try self.createTlvInitializer( |
| 1046 | 1046 | macho_file, |
| 1047 | 1047 | nav.fqn.toSlice(ip), |
| 1048 | pt.navAlignment(nav_index), | |
| 1048 | zcu.navAlignment(nav_index), | |
| 1049 | 1049 | sect_index, |
| 1050 | 1050 | code, |
| 1051 | 1051 | ); |
src/link/MachO/file.zig+1-1| ... | ... | @@ -258,7 +258,7 @@ pub const File = union(enum) { |
| 258 | 258 | |
| 259 | 259 | const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]); |
| 260 | 260 | if (!gop.found_existing) { |
| 261 | gop.value_ptr.* = .{}; | |
| 261 | gop.value_ptr.* = .empty; | |
| 262 | 262 | } |
| 263 | 263 | try gop.value_ptr.append(gpa, file.getIndex()); |
| 264 | 264 | } |
src/link/Wasm.zig+4-4| ... | ... | @@ -78,7 +78,7 @@ export_table: bool, |
| 78 | 78 | /// Output name of the file |
| 79 | 79 | name: []const u8, |
| 80 | 80 | /// List of relocatable files to be linked into the final binary. |
| 81 | objects: std.ArrayList(Object) = .{}, | |
| 81 | objects: std.ArrayList(Object) = .empty, | |
| 82 | 82 | |
| 83 | 83 | func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty, |
| 84 | 84 | /// Provides a mapping of both imports and provided functions to symbol name. |
| ... | ... | @@ -278,7 +278,7 @@ any_tls_relocs: bool = false, |
| 278 | 278 | any_passive_inits: bool = false, |
| 279 | 279 | |
| 280 | 280 | /// All MIR instructions for all Zcu functions. |
| 281 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, | |
| 281 | mir_instructions: std.MultiArrayList(Mir.Inst) = .empty, | |
| 282 | 282 | /// Corresponds to `mir_instructions`. |
| 283 | 283 | mir_extra: std.ArrayList(u32) = .empty, |
| 284 | 284 | /// All local types for all Zcu functions. |
| ... | ... | @@ -4226,7 +4226,7 @@ fn convertZcuFnType( |
| 4226 | 4226 | |
| 4227 | 4227 | if (CodeGen.firstParamSRet(cc, return_type, zcu, target)) { |
| 4228 | 4228 | try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle |
| 4229 | } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4229 | } else if (return_type.hasRuntimeBits(zcu)) { | |
| 4230 | 4230 | if (cc == .wasm_mvp) { |
| 4231 | 4231 | switch (abi.classifyType(return_type, zcu)) { |
| 4232 | 4232 | .direct => |scalar_ty| { |
| ... | ... | @@ -4245,7 +4245,7 @@ fn convertZcuFnType( |
| 4245 | 4245 | // param types |
| 4246 | 4246 | for (params) |param_type_ip| { |
| 4247 | 4247 | const param_type = Zcu.Type.fromInterned(param_type_ip); |
| 4248 | if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 4248 | if (!param_type.hasRuntimeBits(zcu)) continue; | |
| 4249 | 4249 | |
| 4250 | 4250 | switch (cc) { |
| 4251 | 4251 | .wasm_mvp => { |
src/link/Wasm/Flush.zig+3-3| ... | ... | @@ -154,7 +154,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 154 | 154 | .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .slice_const_u8_sentinel_0, target), |
| 155 | 155 | .table_index = @intCast(wasm.tag_name_offs.items.len), |
| 156 | 156 | } }; |
| 157 | const tag_names = ip.loadEnumType(data.ip_index).names; | |
| 157 | const tag_names = ip.loadEnumType(data.ip_index).field_names; | |
| 158 | 158 | for (tag_names.get(ip)) |tag_name| { |
| 159 | 159 | const slice = tag_name.toSlice(ip); |
| 160 | 160 | try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); |
| ... | ... | @@ -1869,7 +1869,7 @@ fn emitTagNameFunction( |
| 1869 | 1869 | const zcu = comp.zcu.?; |
| 1870 | 1870 | const ip = &zcu.intern_pool; |
| 1871 | 1871 | const enum_type = ip.loadEnumType(enum_type_ip); |
| 1872 | const tag_values = enum_type.values.get(ip); | |
| 1872 | const tag_values = enum_type.field_values.get(ip); | |
| 1873 | 1873 | |
| 1874 | 1874 | const slice_abi_size = 8; |
| 1875 | 1875 | const encoded_alignment = @ctz(@as(u32, 4)); |
| ... | ... | @@ -1908,7 +1908,7 @@ fn emitTagNameFunction( |
| 1908 | 1908 | return; |
| 1909 | 1909 | } |
| 1910 | 1910 | |
| 1911 | const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); | |
| 1911 | const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.int_tag_type), zcu); | |
| 1912 | 1912 | const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { |
| 1913 | 1913 | 0...32 => .i32, |
| 1914 | 1914 | 33...64 => .i64, |
src/link/tapi/parse.zig+1-1| ... | ... | @@ -530,7 +530,7 @@ const Parser = struct { |
| 530 | 530 | fn leaf_value(self: *Parser) ParseError!*Node { |
| 531 | 531 | const node = try self.allocator.create(Node.Value); |
| 532 | 532 | errdefer self.allocator.destroy(node); |
| 533 | node.* = .{ .string_value = .{} }; | |
| 533 | node.* = .{ .string_value = .empty }; | |
| 534 | 534 | node.base.tree = self.tree; |
| 535 | 535 | node.base.start = self.token_it.pos; |
| 536 | 536 | errdefer node.string_value.deinit(self.allocator); |
src/main.zig+9-9| ... | ... | @@ -979,7 +979,7 @@ fn buildOutputType( |
| 979 | 979 | .dirs = undefined, |
| 980 | 980 | .object_format = null, |
| 981 | 981 | .dynamic_linker = null, |
| 982 | .modules = .{}, | |
| 982 | .modules = .empty, | |
| 983 | 983 | .opts = .{ |
| 984 | 984 | .is_test = switch (arg_mode) { |
| 985 | 985 | .zig_test, .zig_test_obj => true, |
| ... | ... | @@ -1006,18 +1006,18 @@ fn buildOutputType( |
| 1006 | 1006 | .windows_libs = .empty, |
| 1007 | 1007 | .link_inputs = .empty, |
| 1008 | 1008 | |
| 1009 | .c_source_files = .{}, | |
| 1010 | .rc_source_files = .{}, | |
| 1009 | .c_source_files = .empty, | |
| 1010 | .rc_source_files = .empty, | |
| 1011 | 1011 | |
| 1012 | .llvm_m_args = .{}, | |
| 1012 | .llvm_m_args = .empty, | |
| 1013 | 1013 | .sysroot = null, |
| 1014 | .lib_directories = .{}, // populated by createModule() | |
| 1015 | .lib_dir_args = .{}, // populated from CLI arg parsing | |
| 1014 | .lib_directories = .empty, // populated by createModule() | |
| 1015 | .lib_dir_args = .empty, // populated from CLI arg parsing | |
| 1016 | 1016 | .libc_installation = null, |
| 1017 | 1017 | .want_native_include_dirs = false, |
| 1018 | .frameworks = .{}, | |
| 1019 | .framework_dirs = .{}, | |
| 1020 | .rpath_list = .{}, | |
| 1018 | .frameworks = .empty, | |
| 1019 | .framework_dirs = .empty, | |
| 1020 | .rpath_list = .empty, | |
| 1021 | 1021 | .each_lib_rpath = null, |
| 1022 | 1022 | .libc_paths_file = EnvVar.ZIG_LIBC.get(environ_map), |
| 1023 | 1023 | .native_system_include_paths = &.{}, |
src/mutable_value.zig+18-26| ... | ... | @@ -18,7 +18,7 @@ pub const MutableValue = union(enum) { |
| 18 | 18 | opt_payload: SubValue, |
| 19 | 19 | /// An aggregate consisting of a single repeated value. |
| 20 | 20 | repeated: SubValue, |
| 21 | /// An aggregate of `u8` consisting of "plain" bytes (no lazy or undefined elements). | |
| 21 | /// An aggregate of `u8` consisting of "plain" bytes (no undefined elements). | |
| 22 | 22 | bytes: Bytes, |
| 23 | 23 | /// An aggregate with arbitrary sub-values. |
| 24 | 24 | aggregate: Aggregate, |
| ... | ... | @@ -97,8 +97,8 @@ pub const MutableValue = union(enum) { |
| 97 | 97 | /// * Non-error error unions use `eu_payload` |
| 98 | 98 | /// * Non-null optionals use `eu_payload |
| 99 | 99 | /// * Slices use `slice` |
| 100 | /// * Unions use `un` | |
| 101 | /// * Aggregates use `repeated` or `bytes` or `aggregate` | |
| 100 | /// * Unions use `un` (excluding packed unions) | |
| 101 | /// * Aggregates use `repeated` or `bytes` or `aggregate` (excluding packed structs) | |
| 102 | 102 | /// If `!allow_bytes`, the `bytes` representation will not be used. |
| 103 | 103 | /// If `!allow_repeated`, the `repeated` representation will not be used. |
| 104 | 104 | pub fn unintern( |
| ... | ... | @@ -209,6 +209,7 @@ pub const MutableValue = union(enum) { |
| 209 | 209 | .undef => |ty_ip| switch (Type.fromInterned(ty_ip).zigTypeTag(zcu)) { |
| 210 | 210 | .@"struct", .array, .vector => |type_tag| { |
| 211 | 211 | const ty = Type.fromInterned(ty_ip); |
| 212 | if (type_tag == .@"struct" and ty.containerLayout(zcu) == .@"packed") return; | |
| 212 | 213 | const opt_sent = ty.sentinel(zcu); |
| 213 | 214 | if (type_tag == .@"struct" or opt_sent != null or !allow_repeated) { |
| 214 | 215 | const len_no_sent = ip.aggregateTypeLen(ty_ip); |
| ... | ... | @@ -241,15 +242,18 @@ pub const MutableValue = union(enum) { |
| 241 | 242 | } }; |
| 242 | 243 | } |
| 243 | 244 | }, |
| 244 | .@"union" => { | |
| 245 | const payload = try arena.create(MutableValue); | |
| 246 | const backing_ty = try Type.fromInterned(ty_ip).unionBackingType(pt); | |
| 247 | payload.* = .{ .interned = try pt.intern(.{ .undef = backing_ty.toIntern() }) }; | |
| 248 | mv.* = .{ .un = .{ | |
| 249 | .ty = ty_ip, | |
| 250 | .tag = .none, | |
| 251 | .payload = payload, | |
| 252 | } }; | |
| 245 | .@"union" => switch (Type.fromInterned(ty_ip).containerLayout(zcu)) { | |
| 246 | .auto, .@"packed" => {}, | |
| 247 | .@"extern" => { | |
| 248 | const payload = try arena.create(MutableValue); | |
| 249 | const backing_ty = try Type.fromInterned(ty_ip).externUnionBackingType(pt); | |
| 250 | payload.* = .{ .interned = try pt.intern(.{ .undef = backing_ty.toIntern() }) }; | |
| 251 | mv.* = .{ .un = .{ | |
| 252 | .ty = ty_ip, | |
| 253 | .tag = .none, | |
| 254 | .payload = payload, | |
| 255 | } }; | |
| 256 | }, | |
| 253 | 257 | }, |
| 254 | 258 | .pointer => { |
| 255 | 259 | const ptr_ty = ip.indexToKey(ty_ip).ptr_type; |
| ... | ... | @@ -415,16 +419,7 @@ pub const MutableValue = union(enum) { |
| 415 | 419 | } else if (!is_struct and is_trivial_int and Type.fromInterned(a.ty).childType(zcu).toIntern() == .u8_type) { |
| 416 | 420 | // See if we can switch to `bytes` repr |
| 417 | 421 | for (a.elems) |e| { |
| 418 | switch (e) { | |
| 419 | else => break, | |
| 420 | .interned => |ip_index| switch (ip.indexToKey(ip_index)) { | |
| 421 | else => break, | |
| 422 | .int => |int| switch (int.storage) { | |
| 423 | .u64, .i64, .big_int => {}, | |
| 424 | .lazy_align, .lazy_size => break, | |
| 425 | }, | |
| 426 | }, | |
| 427 | } | |
| 422 | if (!e.isTrivialInt(zcu)) break; | |
| 428 | 423 | } else { |
| 429 | 424 | const bytes = try arena.alloc(u8, a.elems.len); |
| 430 | 425 | for (a.elems, bytes) |elem_val, *b| { |
| ... | ... | @@ -494,10 +489,7 @@ pub const MutableValue = union(enum) { |
| 494 | 489 | else => false, |
| 495 | 490 | .interned => |ip_index| switch (zcu.intern_pool.indexToKey(ip_index)) { |
| 496 | 491 | else => false, |
| 497 | .int => |int| switch (int.storage) { | |
| 498 | .u64, .i64, .big_int => true, | |
| 499 | .lazy_align, .lazy_size => false, | |
| 500 | }, | |
| 492 | .int => true, | |
| 501 | 493 | }, |
| 502 | 494 | }; |
| 503 | 495 | } |
src/print_value.zig+79-42| ... | ... | @@ -25,10 +25,7 @@ pub fn formatSema(ctx: FormatContext, writer: *Writer) Writer.Error!void { |
| 25 | 25 | const sema = ctx.opt_sema.?; |
| 26 | 26 | return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) { |
| 27 | 27 | error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function |
| 28 | error.ComptimeBreak, error.ComptimeReturn => unreachable, | |
| 29 | error.AnalysisFail => unreachable, // TODO: re-evaluate when we use `sema` more fully | |
| 30 | error.Canceled => @panic("TODO"), // pls stop returning this error mlugg | |
| 31 | else => |e| return e, | |
| 28 | error.WriteFailed => |e| return e, | |
| 32 | 29 | }; |
| 33 | 30 | } |
| 34 | 31 | |
| ... | ... | @@ -36,9 +33,7 @@ pub fn format(ctx: FormatContext, writer: *Writer) Writer.Error!void { |
| 36 | 33 | std.debug.assert(ctx.opt_sema == null); |
| 37 | 34 | return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) { |
| 38 | 35 | error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function |
| 39 | error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable, | |
| 40 | error.Canceled => @panic("TODO"), // pls stop returning this error mlugg | |
| 41 | else => |e| return e, | |
| 36 | error.WriteFailed => |e| return e, | |
| 42 | 37 | }; |
| 43 | 38 | } |
| 44 | 39 | |
| ... | ... | @@ -48,7 +43,7 @@ pub fn print( |
| 48 | 43 | level: u8, |
| 49 | 44 | pt: Zcu.PerThread, |
| 50 | 45 | opt_sema: ?*Sema, |
| 51 | ) (Writer.Error || Zcu.CompileError)!void { | |
| 46 | ) (Writer.Error || Allocator.Error)!void { | |
| 52 | 47 | const zcu = pt.zcu; |
| 53 | 48 | const ip = &zcu.intern_pool; |
| 54 | 49 | switch (ip.indexToKey(val.toIntern())) { |
| ... | ... | @@ -72,8 +67,12 @@ pub fn print( |
| 72 | 67 | .undef => try writer.writeAll("undefined"), |
| 73 | 68 | .simple_value => |simple_value| switch (simple_value) { |
| 74 | 69 | .void => try writer.writeAll("{}"), |
| 75 | .empty_tuple => try writer.writeAll(".{}"), | |
| 76 | else => try writer.writeAll(@tagName(simple_value)), | |
| 70 | ||
| 71 | .null, | |
| 72 | .true, | |
| 73 | .false, | |
| 74 | .@"unreachable", | |
| 75 | => try writer.writeAll(@tagName(simple_value)), | |
| 77 | 76 | }, |
| 78 | 77 | .variable => try writer.writeAll("(variable)"), |
| 79 | 78 | .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}), |
| ... | ... | @@ -81,14 +80,6 @@ pub fn print( |
| 81 | 80 | .int => |int| switch (int.storage) { |
| 82 | 81 | inline .u64, .i64 => |x| try writer.print("{d}", .{x}), |
| 83 | 82 | .big_int => |x| try writer.print("{d}", .{x}), |
| 84 | .lazy_align => |ty| if (opt_sema != null) { | |
| 85 | const a = try Type.fromInterned(ty).abiAlignmentSema(pt); | |
| 86 | try writer.print("{d}", .{a.toByteUnits() orelse 0}); | |
| 87 | } else try writer.print("@alignOf({f})", .{Type.fromInterned(ty).fmt(pt)}), | |
| 88 | .lazy_size => |ty| if (opt_sema != null) { | |
| 89 | const s = try Type.fromInterned(ty).abiSizeSema(pt); | |
| 90 | try writer.print("{d}", .{s}); | |
| 91 | } else try writer.print("@sizeOf({f})", .{Type.fromInterned(ty).fmt(pt)}), | |
| 92 | 83 | }, |
| 93 | 84 | .err => |err| try writer.print("error.{f}", .{ |
| 94 | 85 | err.name.fmt(ip), |
| ... | ... | @@ -104,8 +95,8 @@ pub fn print( |
| 104 | 95 | }), |
| 105 | 96 | .enum_tag => |enum_tag| { |
| 106 | 97 | const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern()); |
| 107 | if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { | |
| 108 | return writer.print(".{f}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); | |
| 98 | if (enum_type.tagValueIndex(ip, enum_tag.int)) |tag_index| { | |
| 99 | return writer.print(".{f}", .{enum_type.field_names.get(ip)[tag_index].fmt(ip)}); | |
| 109 | 100 | } |
| 110 | 101 | if (level == 0) { |
| 111 | 102 | return writer.writeAll("@enumFromInt(...)"); |
| ... | ... | @@ -114,7 +105,6 @@ pub fn print( |
| 114 | 105 | try print(Value.fromInterned(enum_tag.int), writer, level - 1, pt, opt_sema); |
| 115 | 106 | try writer.writeAll(")"); |
| 116 | 107 | }, |
| 117 | .empty_enum_value => try writer.writeAll("(empty enum value)"), | |
| 118 | 108 | .float => |float| switch (float.storage) { |
| 119 | 109 | inline else => |x| try writer.print("{d}", .{@as(f64, @floatCast(x))}), |
| 120 | 110 | }, |
| ... | ... | @@ -123,7 +113,7 @@ pub fn print( |
| 123 | 113 | if (slice.len == .zero_usize) { |
| 124 | 114 | return writer.writeAll("&.{}"); |
| 125 | 115 | } |
| 126 | try print(.fromInterned(slice.ptr), writer, level - 1, pt, opt_sema); | |
| 116 | try print(.fromInterned(slice.ptr), writer, level, pt, opt_sema); | |
| 127 | 117 | } else { |
| 128 | 118 | const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) { |
| 129 | 119 | .field, .arr_elem, .eu_payload, .opt_payload => unreachable, |
| ... | ... | @@ -167,7 +157,7 @@ pub fn print( |
| 167 | 157 | return; |
| 168 | 158 | } |
| 169 | 159 | if (un.tag == .none) { |
| 170 | const backing_ty = try val.typeOf(zcu).unionBackingType(pt); | |
| 160 | const backing_ty = try val.typeOf(zcu).externUnionBackingType(pt); | |
| 171 | 161 | try writer.print("@bitCast(@as({f}, ", .{backing_ty.fmt(pt)}); |
| 172 | 162 | try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema); |
| 173 | 163 | try writer.writeAll("))"); |
| ... | ... | @@ -179,6 +169,35 @@ pub fn print( |
| 179 | 169 | try writer.writeAll(" }"); |
| 180 | 170 | } |
| 181 | 171 | }, |
| 172 | .bitpack => |bitpack| { | |
| 173 | if (level == 0) { | |
| 174 | return writer.writeAll(".{ ... }"); | |
| 175 | } | |
| 176 | const ty: Type = .fromInterned(bitpack.ty); | |
| 177 | switch (ty.zigTypeTag(zcu)) { | |
| 178 | .@"struct" => { | |
| 179 | if (ty.structFieldCount(zcu) == 0) { | |
| 180 | return writer.writeAll(".{}"); | |
| 181 | } | |
| 182 | try writer.writeAll(".{ "); | |
| 183 | const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items); | |
| 184 | for (0..max_len) |i| { | |
| 185 | if (i != 0) try writer.writeAll(", "); | |
| 186 | const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?; | |
| 187 | try writer.print(".{f} = ", .{field_name.fmt(ip)}); | |
| 188 | try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); | |
| 189 | } | |
| 190 | try writer.writeAll(" }"); | |
| 191 | return; | |
| 192 | }, | |
| 193 | .@"union" => { | |
| 194 | try writer.print("@bitCast(@as({f}, ", .{ty.bitpackBackingInt(zcu).fmt(pt)}); | |
| 195 | try print(.fromInterned(bitpack.backing_int_val), writer, level - 1, pt, opt_sema); | |
| 196 | try writer.writeAll("))"); | |
| 197 | }, | |
| 198 | else => unreachable, | |
| 199 | } | |
| 200 | }, | |
| 182 | 201 | .memoized_call => unreachable, |
| 183 | 202 | } |
| 184 | 203 | } |
| ... | ... | @@ -191,7 +210,7 @@ fn printAggregate( |
| 191 | 210 | level: u8, |
| 192 | 211 | pt: Zcu.PerThread, |
| 193 | 212 | opt_sema: ?*Sema, |
| 194 | ) (Writer.Error || Zcu.CompileError)!void { | |
| 213 | ) (Writer.Error || Allocator.Error)!void { | |
| 195 | 214 | if (level == 0) { |
| 196 | 215 | if (is_ref) try writer.writeByte('&'); |
| 197 | 216 | return writer.writeAll(".{ ... }"); |
| ... | ... | @@ -256,17 +275,26 @@ fn printAggregate( |
| 256 | 275 | const len = ty.arrayLen(zcu); |
| 257 | 276 | |
| 258 | 277 | if (is_ref) try writer.writeByte('&'); |
| 259 | try writer.writeAll(".{ "); | |
| 260 | ||
| 261 | const max_len = @min(len, max_aggregate_items); | |
| 262 | for (0..max_len) |i| { | |
| 263 | if (i != 0) try writer.writeAll(", "); | |
| 264 | try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); | |
| 265 | } | |
| 266 | if (len > max_aggregate_items) { | |
| 267 | try writer.writeAll(", ..."); | |
| 278 | switch (len) { | |
| 279 | 0 => try writer.writeAll(".{}"), | |
| 280 | 1 => { | |
| 281 | try writer.writeAll(".{"); | |
| 282 | try print(try val.fieldValue(pt, 0), writer, level - 1, pt, opt_sema); | |
| 283 | try writer.writeByte('}'); | |
| 284 | }, | |
| 285 | else => { | |
| 286 | try writer.writeAll(".{ "); | |
| 287 | const max_len = @min(len, max_aggregate_items); | |
| 288 | for (0..max_len) |i| { | |
| 289 | if (i != 0) try writer.writeAll(", "); | |
| 290 | try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); | |
| 291 | } | |
| 292 | if (len > max_aggregate_items) { | |
| 293 | try writer.writeAll(", ..."); | |
| 294 | } | |
| 295 | try writer.writeAll(" }"); | |
| 296 | }, | |
| 268 | 297 | } |
| 269 | return writer.writeAll(" }"); | |
| 270 | 298 | } |
| 271 | 299 | |
| 272 | 300 | fn printPtr( |
| ... | ... | @@ -277,7 +305,7 @@ fn printPtr( |
| 277 | 305 | level: u8, |
| 278 | 306 | pt: Zcu.PerThread, |
| 279 | 307 | opt_sema: ?*Sema, |
| 280 | ) (Writer.Error || Zcu.CompileError)!void { | |
| 308 | ) (Writer.Error || Allocator.Error)!void { | |
| 281 | 309 | const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) { |
| 282 | 310 | .undef => return writer.writeAll("undefined"), |
| 283 | 311 | .ptr => |ptr| ptr, |
| ... | ... | @@ -302,10 +330,7 @@ fn printPtr( |
| 302 | 330 | |
| 303 | 331 | var arena = std.heap.ArenaAllocator.init(pt.zcu.gpa); |
| 304 | 332 | defer arena.deinit(); |
| 305 | const derivation = if (opt_sema) |sema| | |
| 306 | try ptr_val.pointerDerivationAdvanced(arena.allocator(), pt, true, sema) | |
| 307 | else | |
| 308 | try ptr_val.pointerDerivationAdvanced(arena.allocator(), pt, false, null); | |
| 333 | const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt, opt_sema); | |
| 309 | 334 | |
| 310 | 335 | _ = try printPtrDerivation(derivation, writer, pt, want_kind, .{ .print_val = .{ |
| 311 | 336 | .level = level, |
| ... | ... | @@ -442,18 +467,30 @@ pub fn printPtrDerivation( |
| 442 | 467 | .uav_ptr => |uav| { |
| 443 | 468 | const ty = Value.fromInterned(uav.val).typeOf(zcu); |
| 444 | 469 | try writer.print("@as({f}, ", .{ty.fmt(pt)}); |
| 445 | try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema); | |
| 470 | if (x.level == 0) { | |
| 471 | try writer.writeAll("..."); | |
| 472 | } else { | |
| 473 | try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema); | |
| 474 | } | |
| 446 | 475 | try writer.writeByte(')'); |
| 447 | 476 | }, |
| 448 | 477 | .comptime_alloc_ptr => |info| { |
| 449 | 478 | try writer.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)}); |
| 450 | try print(info.val, writer, x.level - 1, pt, x.opt_sema); | |
| 479 | if (x.level == 0) { | |
| 480 | try writer.writeAll("..."); | |
| 481 | } else { | |
| 482 | try print(info.val, writer, x.level - 1, pt, x.opt_sema); | |
| 483 | } | |
| 451 | 484 | try writer.writeByte(')'); |
| 452 | 485 | }, |
| 453 | 486 | .comptime_field_ptr => |val| { |
| 454 | 487 | const ty = val.typeOf(zcu); |
| 455 | 488 | try writer.print("@as({f}, ", .{ty.fmt(pt)}); |
| 456 | try print(val, writer, x.level - 1, pt, x.opt_sema); | |
| 489 | if (x.level == 0) { | |
| 490 | try writer.writeAll("..."); | |
| 491 | } else { | |
| 492 | try print(val, writer, x.level - 1, pt, x.opt_sema); | |
| 493 | } | |
| 457 | 494 | try writer.writeByte(')'); |
| 458 | 495 | }, |
| 459 | 496 | else => unreachable, |
src/print_zir.zig+115-426| ... | ... | @@ -548,10 +548,10 @@ const Writer = struct { |
| 548 | 548 | .shl_with_overflow, |
| 549 | 549 | => try self.writeOverflowArithmetic(stream, extended), |
| 550 | 550 | |
| 551 | .struct_decl => try self.writeStructDecl(stream, extended), | |
| 552 | .union_decl => try self.writeUnionDecl(stream, extended), | |
| 553 | .enum_decl => try self.writeEnumDecl(stream, extended), | |
| 554 | .opaque_decl => try self.writeOpaqueDecl(stream, extended), | |
| 551 | .struct_decl => try self.writeStructDecl(stream, inst), | |
| 552 | .union_decl => try self.writeUnionDecl(stream, inst), | |
| 553 | .enum_decl => try self.writeEnumDecl(stream, inst), | |
| 554 | .opaque_decl => try self.writeOpaqueDecl(stream, inst), | |
| 555 | 555 | |
| 556 | 556 | .tuple_decl => try self.writeTupleDecl(stream, extended), |
| 557 | 557 | |
| ... | ... | @@ -1427,187 +1427,57 @@ const Writer = struct { |
| 1427 | 1427 | try self.writeSrcNode(stream, inst_data.src_node); |
| 1428 | 1428 | } |
| 1429 | 1429 | |
| 1430 | fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { | |
| 1431 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | |
| 1432 | ||
| 1433 | const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); | |
| 1430 | fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { | |
| 1431 | const struct_decl = self.code.getStructDecl(inst); | |
| 1434 | 1432 | |
| 1435 | 1433 | const prev_parent_decl_node = self.parent_decl_node; |
| 1436 | self.parent_decl_node = extra.data.src_node; | |
| 1434 | self.parent_decl_node = struct_decl.src_node; | |
| 1437 | 1435 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1438 | 1436 | |
| 1439 | const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ | |
| 1440 | extra.data.fields_hash_0, | |
| 1441 | extra.data.fields_hash_1, | |
| 1442 | extra.data.fields_hash_2, | |
| 1443 | extra.data.fields_hash_3, | |
| 1444 | }); | |
| 1445 | ||
| 1437 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; | |
| 1446 | 1438 | try stream.print("hash({x}) ", .{&fields_hash}); |
| 1447 | 1439 | |
| 1448 | var extra_index: usize = extra.end; | |
| 1449 | ||
| 1450 | const captures_len = if (small.has_captures_len) blk: { | |
| 1451 | const captures_len = self.code.extra[extra_index]; | |
| 1452 | extra_index += 1; | |
| 1453 | break :blk captures_len; | |
| 1454 | } else 0; | |
| 1455 | ||
| 1456 | const fields_len = if (small.has_fields_len) blk: { | |
| 1457 | const fields_len = self.code.extra[extra_index]; | |
| 1458 | extra_index += 1; | |
| 1459 | break :blk fields_len; | |
| 1460 | } else 0; | |
| 1461 | ||
| 1462 | const decls_len = if (small.has_decls_len) blk: { | |
| 1463 | const decls_len = self.code.extra[extra_index]; | |
| 1464 | extra_index += 1; | |
| 1465 | break :blk decls_len; | |
| 1466 | } else 0; | |
| 1440 | try stream.print("{s}, ", .{@tagName(struct_decl.name_strategy)}); | |
| 1467 | 1441 | |
| 1468 | try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv); | |
| 1469 | try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only); | |
| 1470 | ||
| 1471 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | |
| 1472 | ||
| 1473 | extra_index = try self.writeCaptures(stream, extra_index, captures_len); | |
| 1474 | try stream.writeAll(", "); | |
| 1475 | ||
| 1476 | if (small.has_backing_int) { | |
| 1477 | const backing_int_body_len = self.code.extra[extra_index]; | |
| 1478 | extra_index += 1; | |
| 1442 | if (struct_decl.backing_int_type_body) |backing_int_type_body| { | |
| 1443 | assert(struct_decl.layout == .@"packed"); | |
| 1479 | 1444 | try stream.writeAll("packed("); |
| 1480 | if (backing_int_body_len == 0) { | |
| 1481 | const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); | |
| 1482 | extra_index += 1; | |
| 1483 | try self.writeInstRef(stream, backing_int_ref); | |
| 1484 | } else { | |
| 1485 | const body = self.code.bodySlice(extra_index, backing_int_body_len); | |
| 1486 | extra_index += backing_int_body_len; | |
| 1487 | self.indent += 2; | |
| 1488 | try self.writeBracedDecl(stream, body); | |
| 1489 | self.indent -= 2; | |
| 1490 | } | |
| 1445 | try self.writeBracedDecl(stream, backing_int_type_body); | |
| 1491 | 1446 | try stream.writeAll("), "); |
| 1492 | 1447 | } else { |
| 1493 | try stream.print("{s}, ", .{@tagName(small.layout)}); | |
| 1448 | try stream.print("{s}, ", .{@tagName(struct_decl.layout)}); | |
| 1494 | 1449 | } |
| 1495 | 1450 | |
| 1496 | if (decls_len == 0) { | |
| 1497 | try stream.writeAll("{}, "); | |
| 1498 | } else { | |
| 1499 | try stream.writeAll("{\n"); | |
| 1500 | self.indent += 2; | |
| 1501 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); | |
| 1502 | self.indent -= 2; | |
| 1503 | extra_index += decls_len; | |
| 1504 | try stream.splatByteAll(' ', self.indent); | |
| 1505 | try stream.writeAll("}, "); | |
| 1506 | } | |
| 1451 | try self.writeCaptures(stream, struct_decl.captures, struct_decl.capture_names); | |
| 1452 | try stream.writeAll(", "); | |
| 1453 | try self.writeBracedDecl(stream, struct_decl.decls); | |
| 1454 | try stream.writeAll(", "); | |
| 1507 | 1455 | |
| 1508 | if (fields_len == 0) { | |
| 1509 | try stream.writeAll("{}, {}) "); | |
| 1456 | if (struct_decl.field_names.len == 0) { | |
| 1457 | try stream.writeAll("{}) "); | |
| 1510 | 1458 | } else { |
| 1511 | const bits_per_field = 4; | |
| 1512 | const fields_per_u32 = 32 / bits_per_field; | |
| 1513 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 1514 | const Field = struct { | |
| 1515 | type_len: u32 = 0, | |
| 1516 | align_len: u32 = 0, | |
| 1517 | init_len: u32 = 0, | |
| 1518 | type: Zir.Inst.Ref = .none, | |
| 1519 | name: Zir.NullTerminatedString, | |
| 1520 | is_comptime: bool, | |
| 1521 | }; | |
| 1522 | const fields = try self.arena.alloc(Field, fields_len); | |
| 1523 | { | |
| 1524 | var bit_bag_index: usize = extra_index; | |
| 1525 | extra_index += bit_bags_count; | |
| 1526 | var cur_bit_bag: u32 = undefined; | |
| 1527 | var field_i: u32 = 0; | |
| 1528 | while (field_i < fields_len) : (field_i += 1) { | |
| 1529 | if (field_i % fields_per_u32 == 0) { | |
| 1530 | cur_bit_bag = self.code.extra[bit_bag_index]; | |
| 1531 | bit_bag_index += 1; | |
| 1532 | } | |
| 1533 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1534 | cur_bit_bag >>= 1; | |
| 1535 | const has_default = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1536 | cur_bit_bag >>= 1; | |
| 1537 | const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1538 | cur_bit_bag >>= 1; | |
| 1539 | const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1540 | cur_bit_bag >>= 1; | |
| 1541 | ||
| 1542 | const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); | |
| 1543 | extra_index += 1; | |
| 1544 | ||
| 1545 | fields[field_i] = .{ | |
| 1546 | .is_comptime = is_comptime, | |
| 1547 | .name = field_name_index, | |
| 1548 | }; | |
| 1549 | ||
| 1550 | if (has_type_body) { | |
| 1551 | fields[field_i].type_len = self.code.extra[extra_index]; | |
| 1552 | } else { | |
| 1553 | fields[field_i].type = @enumFromInt(self.code.extra[extra_index]); | |
| 1554 | } | |
| 1555 | extra_index += 1; | |
| 1556 | ||
| 1557 | if (has_align) { | |
| 1558 | fields[field_i].align_len = self.code.extra[extra_index]; | |
| 1559 | extra_index += 1; | |
| 1560 | } | |
| 1561 | ||
| 1562 | if (has_default) { | |
| 1563 | fields[field_i].init_len = self.code.extra[extra_index]; | |
| 1564 | extra_index += 1; | |
| 1565 | } | |
| 1566 | } | |
| 1567 | } | |
| 1568 | ||
| 1569 | 1459 | try stream.writeAll("{\n"); |
| 1570 | 1460 | self.indent += 2; |
| 1571 | 1461 | |
| 1572 | for (fields, 0..) |field, i| { | |
| 1462 | var it = struct_decl.iterateFields(); | |
| 1463 | while (it.next()) |field| { | |
| 1573 | 1464 | try stream.splatByteAll(' ', self.indent); |
| 1574 | 1465 | try self.writeFlag(stream, "comptime ", field.is_comptime); |
| 1575 | if (field.name != .empty) { | |
| 1576 | const field_name = self.code.nullTerminatedString(field.name); | |
| 1577 | try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)}); | |
| 1578 | } else { | |
| 1579 | try stream.print("@\"{d}\": ", .{i}); | |
| 1580 | } | |
| 1581 | if (field.type != .none) { | |
| 1582 | try self.writeInstRef(stream, field.type); | |
| 1583 | } | |
| 1584 | ||
| 1585 | if (field.type_len > 0) { | |
| 1586 | const body = self.code.bodySlice(extra_index, field.type_len); | |
| 1587 | extra_index += body.len; | |
| 1588 | self.indent += 2; | |
| 1589 | try self.writeBracedDecl(stream, body); | |
| 1590 | self.indent -= 2; | |
| 1591 | } | |
| 1466 | const field_name = self.code.nullTerminatedString(field.name); | |
| 1467 | try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)}); | |
| 1592 | 1468 | |
| 1593 | if (field.align_len > 0) { | |
| 1594 | const body = self.code.bodySlice(extra_index, field.align_len); | |
| 1595 | extra_index += body.len; | |
| 1596 | self.indent += 2; | |
| 1469 | self.indent += 2; | |
| 1470 | try self.writeBracedDecl(stream, field.type_body); | |
| 1471 | if (field.align_body) |body| { | |
| 1597 | 1472 | try stream.writeAll(" align("); |
| 1598 | 1473 | try self.writeBracedDecl(stream, body); |
| 1599 | try stream.writeAll(")"); | |
| 1600 | self.indent -= 2; | |
| 1474 | try stream.writeByte(')'); | |
| 1601 | 1475 | } |
| 1602 | ||
| 1603 | if (field.init_len > 0) { | |
| 1604 | const body = self.code.bodySlice(extra_index, field.init_len); | |
| 1605 | extra_index += body.len; | |
| 1606 | self.indent += 2; | |
| 1476 | if (field.default_body) |body| { | |
| 1607 | 1477 | try stream.writeAll(" = "); |
| 1608 | 1478 | try self.writeBracedDecl(stream, body); |
| 1609 | self.indent -= 2; | |
| 1610 | 1479 | } |
| 1480 | self.indent -= 2; | |
| 1611 | 1481 | |
| 1612 | 1482 | try stream.writeAll(",\n"); |
| 1613 | 1483 | } |
| ... | ... | @@ -1619,266 +1489,119 @@ const Writer = struct { |
| 1619 | 1489 | try self.writeSrcNode(stream, .zero); |
| 1620 | 1490 | } |
| 1621 | 1491 | |
| 1622 | fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { | |
| 1623 | const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); | |
| 1624 | ||
| 1625 | const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); | |
| 1492 | fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { | |
| 1493 | const union_decl = self.code.getUnionDecl(inst); | |
| 1626 | 1494 | |
| 1627 | 1495 | const prev_parent_decl_node = self.parent_decl_node; |
| 1628 | self.parent_decl_node = extra.data.src_node; | |
| 1496 | self.parent_decl_node = union_decl.src_node; | |
| 1629 | 1497 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1630 | 1498 | |
| 1631 | const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ | |
| 1632 | extra.data.fields_hash_0, | |
| 1633 | extra.data.fields_hash_1, | |
| 1634 | extra.data.fields_hash_2, | |
| 1635 | extra.data.fields_hash_3, | |
| 1636 | }); | |
| 1637 | ||
| 1499 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; | |
| 1638 | 1500 | try stream.print("hash({x}) ", .{&fields_hash}); |
| 1639 | 1501 | |
| 1640 | var extra_index: usize = extra.end; | |
| 1641 | ||
| 1642 | const tag_type_ref = if (small.has_tag_type) blk: { | |
| 1643 | const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | |
| 1644 | extra_index += 1; | |
| 1645 | break :blk tag_type_ref; | |
| 1646 | } else .none; | |
| 1647 | ||
| 1648 | const captures_len = if (small.has_captures_len) blk: { | |
| 1649 | const captures_len = self.code.extra[extra_index]; | |
| 1650 | extra_index += 1; | |
| 1651 | break :blk captures_len; | |
| 1652 | } else 0; | |
| 1653 | ||
| 1654 | const body_len = if (small.has_body_len) blk: { | |
| 1655 | const body_len = self.code.extra[extra_index]; | |
| 1656 | extra_index += 1; | |
| 1657 | break :blk body_len; | |
| 1658 | } else 0; | |
| 1659 | ||
| 1660 | const fields_len = if (small.has_fields_len) blk: { | |
| 1661 | const fields_len = self.code.extra[extra_index]; | |
| 1662 | extra_index += 1; | |
| 1663 | break :blk fields_len; | |
| 1664 | } else 0; | |
| 1665 | ||
| 1666 | const decls_len = if (small.has_decls_len) blk: { | |
| 1667 | const decls_len = self.code.extra[extra_index]; | |
| 1668 | extra_index += 1; | |
| 1669 | break :blk decls_len; | |
| 1670 | } else 0; | |
| 1502 | try stream.print("{s}, ", .{@tagName(union_decl.name_strategy)}); | |
| 1671 | 1503 | |
| 1672 | try stream.print("{s}, {s}, ", .{ | |
| 1673 | @tagName(small.name_strategy), @tagName(small.layout), | |
| 1674 | }); | |
| 1675 | try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); | |
| 1504 | switch (union_decl.kind) { | |
| 1505 | .auto => try stream.writeAll("auto, "), | |
| 1506 | .@"extern" => try stream.writeAll("extern, "), | |
| 1507 | .@"packed" => try stream.writeAll("packed, "), | |
| 1508 | .packed_explicit => { | |
| 1509 | try stream.writeAll("packed("); | |
| 1510 | try self.writeBracedDecl(stream, union_decl.arg_type_body.?); | |
| 1511 | try stream.writeAll("), "); | |
| 1512 | }, | |
| 1513 | .tagged_explicit => { | |
| 1514 | try stream.writeAll("tagged("); | |
| 1515 | try self.writeBracedDecl(stream, union_decl.arg_type_body.?); | |
| 1516 | try stream.writeAll("), "); | |
| 1517 | }, | |
| 1518 | .tagged_enum => try stream.writeAll("tagged(enum), "), | |
| 1519 | .tagged_enum_explicit => { | |
| 1520 | try stream.writeAll("tagged(enum("); | |
| 1521 | try self.writeBracedDecl(stream, union_decl.arg_type_body.?); | |
| 1522 | try stream.writeAll(")), "); | |
| 1523 | }, | |
| 1524 | } | |
| 1676 | 1525 | |
| 1677 | extra_index = try self.writeCaptures(stream, extra_index, captures_len); | |
| 1526 | try self.writeCaptures(stream, union_decl.captures, union_decl.capture_names); | |
| 1527 | try stream.writeAll(", "); | |
| 1528 | try self.writeBracedDecl(stream, union_decl.decls); | |
| 1678 | 1529 | try stream.writeAll(", "); |
| 1679 | 1530 | |
| 1680 | if (decls_len == 0) { | |
| 1681 | try stream.writeAll("{}"); | |
| 1531 | if (union_decl.field_names.len == 0) { | |
| 1532 | try stream.writeAll("}) "); | |
| 1682 | 1533 | } else { |
| 1683 | 1534 | try stream.writeAll("{\n"); |
| 1684 | 1535 | self.indent += 2; |
| 1685 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); | |
| 1686 | self.indent -= 2; | |
| 1687 | extra_index += decls_len; | |
| 1688 | try stream.splatByteAll(' ', self.indent); | |
| 1689 | try stream.writeAll("}"); | |
| 1690 | } | |
| 1691 | ||
| 1692 | if (tag_type_ref != .none) { | |
| 1693 | try stream.writeAll(", "); | |
| 1694 | try self.writeInstRef(stream, tag_type_ref); | |
| 1695 | } | |
| 1696 | ||
| 1697 | if (fields_len == 0) { | |
| 1698 | try stream.writeAll("}) "); | |
| 1699 | try self.writeSrcNode(stream, .zero); | |
| 1700 | return; | |
| 1701 | } | |
| 1702 | try stream.writeAll(", "); | |
| 1703 | 1536 | |
| 1704 | const body = self.code.bodySlice(extra_index, body_len); | |
| 1705 | extra_index += body.len; | |
| 1537 | var it = union_decl.iterateFields(); | |
| 1538 | while (it.next()) |field| { | |
| 1539 | try stream.splatByteAll(' ', self.indent); | |
| 1540 | const field_name = self.code.nullTerminatedString(field.name); | |
| 1541 | try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); | |
| 1706 | 1542 | |
| 1707 | try self.writeBracedDecl(stream, body); | |
| 1708 | try stream.writeAll(", {\n"); | |
| 1543 | self.indent += 2; | |
| 1544 | if (field.type_body) |body| { | |
| 1545 | try stream.writeAll(": "); | |
| 1546 | try self.writeBracedDecl(stream, body); | |
| 1547 | } | |
| 1548 | if (field.align_body) |body| { | |
| 1549 | try stream.writeAll(" align("); | |
| 1550 | try self.writeBracedDecl(stream, body); | |
| 1551 | try stream.writeByte(')'); | |
| 1552 | } | |
| 1553 | if (field.value_body) |body| { | |
| 1554 | try stream.writeAll(" = "); | |
| 1555 | try self.writeBracedDecl(stream, body); | |
| 1556 | } | |
| 1557 | self.indent -= 2; | |
| 1709 | 1558 | |
| 1710 | self.indent += 2; | |
| 1711 | const bits_per_field = 4; | |
| 1712 | const fields_per_u32 = 32 / bits_per_field; | |
| 1713 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 1714 | const body_end = extra_index; | |
| 1715 | extra_index += bit_bags_count; | |
| 1716 | var bit_bag_index: usize = body_end; | |
| 1717 | var cur_bit_bag: u32 = undefined; | |
| 1718 | var field_i: u32 = 0; | |
| 1719 | while (field_i < fields_len) : (field_i += 1) { | |
| 1720 | if (field_i % fields_per_u32 == 0) { | |
| 1721 | cur_bit_bag = self.code.extra[bit_bag_index]; | |
| 1722 | bit_bag_index += 1; | |
| 1559 | try stream.writeAll(",\n"); | |
| 1723 | 1560 | } |
| 1724 | const has_type = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1725 | cur_bit_bag >>= 1; | |
| 1726 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1727 | cur_bit_bag >>= 1; | |
| 1728 | const has_value = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1729 | cur_bit_bag >>= 1; | |
| 1730 | const unused = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1731 | cur_bit_bag >>= 1; | |
| 1732 | ||
| 1733 | _ = unused; | |
| 1734 | ||
| 1735 | const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); | |
| 1736 | const field_name = self.code.nullTerminatedString(field_name_index); | |
| 1737 | extra_index += 1; | |
| 1738 | ||
| 1561 | self.indent -= 2; | |
| 1739 | 1562 | try stream.splatByteAll(' ', self.indent); |
| 1740 | try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); | |
| 1741 | ||
| 1742 | if (has_type) { | |
| 1743 | const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | |
| 1744 | extra_index += 1; | |
| 1745 | ||
| 1746 | try stream.writeAll(": "); | |
| 1747 | try self.writeInstRef(stream, field_type); | |
| 1748 | } | |
| 1749 | if (has_align) { | |
| 1750 | const align_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | |
| 1751 | extra_index += 1; | |
| 1752 | ||
| 1753 | try stream.writeAll(" align("); | |
| 1754 | try self.writeInstRef(stream, align_ref); | |
| 1755 | try stream.writeAll(")"); | |
| 1756 | } | |
| 1757 | if (has_value) { | |
| 1758 | const default_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | |
| 1759 | extra_index += 1; | |
| 1760 | ||
| 1761 | try stream.writeAll(" = "); | |
| 1762 | try self.writeInstRef(stream, default_ref); | |
| 1763 | } | |
| 1764 | try stream.writeAll(",\n"); | |
| 1563 | try stream.writeAll("}) "); | |
| 1765 | 1564 | } |
| 1766 | ||
| 1767 | self.indent -= 2; | |
| 1768 | try stream.splatByteAll(' ', self.indent); | |
| 1769 | try stream.writeAll("}) "); | |
| 1770 | 1565 | try self.writeSrcNode(stream, .zero); |
| 1771 | 1566 | } |
| 1772 | 1567 | |
| 1773 | fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { | |
| 1774 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); | |
| 1775 | ||
| 1776 | const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); | |
| 1568 | fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { | |
| 1569 | const enum_decl = self.code.getEnumDecl(inst); | |
| 1777 | 1570 | |
| 1778 | 1571 | const prev_parent_decl_node = self.parent_decl_node; |
| 1779 | self.parent_decl_node = extra.data.src_node; | |
| 1572 | self.parent_decl_node = enum_decl.src_node; | |
| 1780 | 1573 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1781 | 1574 | |
| 1782 | const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ | |
| 1783 | extra.data.fields_hash_0, | |
| 1784 | extra.data.fields_hash_1, | |
| 1785 | extra.data.fields_hash_2, | |
| 1786 | extra.data.fields_hash_3, | |
| 1787 | }); | |
| 1788 | ||
| 1575 | const fields_hash = self.code.getAssociatedSrcHash(inst).?; | |
| 1789 | 1576 | try stream.print("hash({x}) ", .{&fields_hash}); |
| 1790 | 1577 | |
| 1791 | var extra_index: usize = extra.end; | |
| 1792 | ||
| 1793 | const tag_type_ref = if (small.has_tag_type) blk: { | |
| 1794 | const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | |
| 1795 | extra_index += 1; | |
| 1796 | break :blk tag_type_ref; | |
| 1797 | } else .none; | |
| 1798 | ||
| 1799 | const captures_len = if (small.has_captures_len) blk: { | |
| 1800 | const captures_len = self.code.extra[extra_index]; | |
| 1801 | extra_index += 1; | |
| 1802 | break :blk captures_len; | |
| 1803 | } else 0; | |
| 1804 | ||
| 1805 | const body_len = if (small.has_body_len) blk: { | |
| 1806 | const body_len = self.code.extra[extra_index]; | |
| 1807 | extra_index += 1; | |
| 1808 | break :blk body_len; | |
| 1809 | } else 0; | |
| 1810 | ||
| 1811 | const fields_len = if (small.has_fields_len) blk: { | |
| 1812 | const fields_len = self.code.extra[extra_index]; | |
| 1813 | extra_index += 1; | |
| 1814 | break :blk fields_len; | |
| 1815 | } else 0; | |
| 1816 | ||
| 1817 | const decls_len = if (small.has_decls_len) blk: { | |
| 1818 | const decls_len = self.code.extra[extra_index]; | |
| 1819 | extra_index += 1; | |
| 1820 | break :blk decls_len; | |
| 1821 | } else 0; | |
| 1822 | ||
| 1823 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | |
| 1824 | try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); | |
| 1578 | try stream.print("{s}, ", .{@tagName(enum_decl.name_strategy)}); | |
| 1579 | try self.writeFlag(stream, "nonexhaustive, ", enum_decl.nonexhaustive); | |
| 1580 | if (enum_decl.tag_type_body) |tag_type_body| { | |
| 1581 | try stream.writeAll("tag("); | |
| 1582 | try self.writeBracedDecl(stream, tag_type_body); | |
| 1583 | try stream.writeAll("), "); | |
| 1584 | } | |
| 1825 | 1585 | |
| 1826 | extra_index = try self.writeCaptures(stream, extra_index, captures_len); | |
| 1586 | try self.writeCaptures(stream, enum_decl.captures, enum_decl.capture_names); | |
| 1587 | try stream.writeAll(", "); | |
| 1588 | try self.writeBracedDecl(stream, enum_decl.decls); | |
| 1827 | 1589 | try stream.writeAll(", "); |
| 1828 | 1590 | |
| 1829 | if (decls_len == 0) { | |
| 1830 | try stream.writeAll("{}, "); | |
| 1591 | if (enum_decl.field_names.len == 0) { | |
| 1592 | try stream.writeAll("{}) "); | |
| 1831 | 1593 | } else { |
| 1832 | 1594 | try stream.writeAll("{\n"); |
| 1833 | 1595 | self.indent += 2; |
| 1834 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); | |
| 1835 | self.indent -= 2; | |
| 1836 | extra_index += decls_len; | |
| 1837 | try stream.splatByteAll(' ', self.indent); | |
| 1838 | try stream.writeAll("}, "); | |
| 1839 | } | |
| 1840 | ||
| 1841 | if (tag_type_ref != .none) { | |
| 1842 | try self.writeInstRef(stream, tag_type_ref); | |
| 1843 | try stream.writeAll(", "); | |
| 1844 | } | |
| 1845 | ||
| 1846 | const body = self.code.bodySlice(extra_index, body_len); | |
| 1847 | extra_index += body.len; | |
| 1848 | ||
| 1849 | try self.writeBracedDecl(stream, body); | |
| 1850 | if (fields_len == 0) { | |
| 1851 | try stream.writeAll(", {}) "); | |
| 1852 | } else { | |
| 1853 | try stream.writeAll(", {\n"); | |
| 1854 | ||
| 1855 | self.indent += 2; | |
| 1856 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; | |
| 1857 | const body_end = extra_index; | |
| 1858 | extra_index += bit_bags_count; | |
| 1859 | var bit_bag_index: usize = body_end; | |
| 1860 | var cur_bit_bag: u32 = undefined; | |
| 1861 | var field_i: u32 = 0; | |
| 1862 | while (field_i < fields_len) : (field_i += 1) { | |
| 1863 | if (field_i % 32 == 0) { | |
| 1864 | cur_bit_bag = self.code.extra[bit_bag_index]; | |
| 1865 | bit_bag_index += 1; | |
| 1866 | } | |
| 1867 | const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0; | |
| 1868 | cur_bit_bag >>= 1; | |
| 1869 | ||
| 1870 | const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index])); | |
| 1871 | extra_index += 1; | |
| 1872 | 1596 | |
| 1597 | var it = enum_decl.iterateFields(); | |
| 1598 | while (it.next()) |field| { | |
| 1873 | 1599 | try stream.splatByteAll(' ', self.indent); |
| 1600 | const field_name = self.code.nullTerminatedString(field.name); | |
| 1874 | 1601 | try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); |
| 1875 | ||
| 1876 | if (has_tag_value) { | |
| 1877 | const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | |
| 1878 | extra_index += 1; | |
| 1879 | ||
| 1602 | if (field.value_body) |body| { | |
| 1880 | 1603 | try stream.writeAll(" = "); |
| 1881 | try self.writeInstRef(stream, tag_value_ref); | |
| 1604 | try self.writeBracedDecl(stream, body); | |
| 1882 | 1605 | } |
| 1883 | 1606 | try stream.writeAll(",\n"); |
| 1884 | 1607 | } |
| ... | ... | @@ -1889,47 +1612,18 @@ const Writer = struct { |
| 1889 | 1612 | try self.writeSrcNode(stream, .zero); |
| 1890 | 1613 | } |
| 1891 | 1614 | |
| 1892 | fn writeOpaqueDecl( | |
| 1893 | self: *Writer, | |
| 1894 | stream: *std.Io.Writer, | |
| 1895 | extended: Zir.Inst.Extended.InstData, | |
| 1896 | ) !void { | |
| 1897 | const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small)); | |
| 1898 | const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); | |
| 1615 | fn writeOpaqueDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { | |
| 1616 | const opaque_decl = self.code.getOpaqueDecl(inst); | |
| 1899 | 1617 | |
| 1900 | 1618 | const prev_parent_decl_node = self.parent_decl_node; |
| 1901 | self.parent_decl_node = extra.data.src_node; | |
| 1619 | self.parent_decl_node = opaque_decl.src_node; | |
| 1902 | 1620 | defer self.parent_decl_node = prev_parent_decl_node; |
| 1903 | 1621 | |
| 1904 | var extra_index: usize = extra.end; | |
| 1905 | ||
| 1906 | const captures_len = if (small.has_captures_len) blk: { | |
| 1907 | const captures_len = self.code.extra[extra_index]; | |
| 1908 | extra_index += 1; | |
| 1909 | break :blk captures_len; | |
| 1910 | } else 0; | |
| 1911 | ||
| 1912 | const decls_len = if (small.has_decls_len) blk: { | |
| 1913 | const decls_len = self.code.extra[extra_index]; | |
| 1914 | extra_index += 1; | |
| 1915 | break :blk decls_len; | |
| 1916 | } else 0; | |
| 1917 | ||
| 1918 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | |
| 1919 | ||
| 1920 | extra_index = try self.writeCaptures(stream, extra_index, captures_len); | |
| 1622 | try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)}); | |
| 1623 | try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names); | |
| 1921 | 1624 | try stream.writeAll(", "); |
| 1922 | ||
| 1923 | if (decls_len == 0) { | |
| 1924 | try stream.writeAll("{}) "); | |
| 1925 | } else { | |
| 1926 | try stream.writeAll("{\n"); | |
| 1927 | self.indent += 2; | |
| 1928 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); | |
| 1929 | self.indent -= 2; | |
| 1930 | try stream.splatByteAll(' ', self.indent); | |
| 1931 | try stream.writeAll("}) "); | |
| 1932 | } | |
| 1625 | try self.writeBracedDecl(stream, opaque_decl.decls); | |
| 1626 | try stream.writeAll(") "); | |
| 1933 | 1627 | try self.writeSrcNode(stream, .zero); |
| 1934 | 1628 | } |
| 1935 | 1629 | |
| ... | ... | @@ -2588,14 +2282,11 @@ const Writer = struct { |
| 2588 | 2282 | return stream.print("%{d}", .{@intFromEnum(inst)}); |
| 2589 | 2283 | } |
| 2590 | 2284 | |
| 2591 | fn writeCaptures(self: *Writer, stream: *std.Io.Writer, extra_index: usize, captures_len: u32) !usize { | |
| 2592 | if (captures_len == 0) { | |
| 2593 | try stream.writeAll("{}"); | |
| 2594 | return extra_index; | |
| 2285 | fn writeCaptures(self: *Writer, stream: *std.Io.Writer, captures: []const Zir.Inst.Capture, capture_names: []const Zir.NullTerminatedString) !void { | |
| 2286 | if (captures.len == 0) { | |
| 2287 | assert(capture_names.len == 0); | |
| 2288 | return stream.writeAll("{}"); | |
| 2595 | 2289 | } |
| 2596 | ||
| 2597 | const captures: []const Zir.Inst.Capture = @ptrCast(self.code.extra[extra_index..][0..captures_len]); | |
| 2598 | const capture_names: []const Zir.NullTerminatedString = @ptrCast(self.code.extra[extra_index + captures_len ..][0..captures_len]); | |
| 2599 | 2290 | for (captures, capture_names) |capture, name| { |
| 2600 | 2291 | try stream.writeAll("{ "); |
| 2601 | 2292 | if (name != .empty) { |
| ... | ... | @@ -2604,8 +2295,6 @@ const Writer = struct { |
| 2604 | 2295 | } |
| 2605 | 2296 | try self.writeCapture(stream, capture); |
| 2606 | 2297 | } |
| 2607 | ||
| 2608 | return extra_index + 2 * captures_len; | |
| 2609 | 2298 | } |
| 2610 | 2299 | |
| 2611 | 2300 | fn writeCapture(self: *Writer, stream: *std.Io.Writer, capture: Zir.Inst.Capture) !void { |
stage1/zig.h+9-1| ... | ... | @@ -151,6 +151,14 @@ |
| 151 | 151 | #define zig_has_attribute(attribute) 0 |
| 152 | 152 | #endif |
| 153 | 153 | |
| 154 | #if __STDC_VERSION__ >= 201112L | |
| 155 | #define zig_static_assert(cond, msg) _Static_assert(cond, msg) | |
| 156 | #elif zig_has_attribute(unused) | |
| 157 | #define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) | |
| 158 | #else | |
| 159 | #define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] | |
| 160 | #endif | |
| 161 | ||
| 154 | 162 | #if __STDC_VERSION__ >= 202311L |
| 155 | 163 | #define zig_threadlocal thread_local |
| 156 | 164 | #elif __STDC_VERSION__ >= 201112L |
| ... | ... | @@ -259,7 +267,7 @@ |
| 259 | 267 | #endif |
| 260 | 268 | |
| 261 | 269 | #if zig_has_attribute(packed) || defined(zig_tinyc) |
| 262 | #define zig_packed(definition) __attribute__((packed)) definition | |
| 270 | #define zig_packed(definition) definition __attribute__((packed)) | |
| 263 | 271 | #elif defined(zig_msvc) |
| 264 | 272 | #define zig_packed(definition) __pragma(pack(1)) definition __pragma(pack()) |
| 265 | 273 | #else |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ |
test/behavior.zig-1| ... | ... | @@ -24,7 +24,6 @@ test { |
| 24 | 24 | _ = @import("behavior/duplicated_test_names.zig"); |
| 25 | 25 | _ = @import("behavior/defer.zig"); |
| 26 | 26 | _ = @import("behavior/destructure.zig"); |
| 27 | _ = @import("behavior/empty_union.zig"); | |
| 28 | 27 | _ = @import("behavior/enum.zig"); |
| 29 | 28 | _ = @import("behavior/error.zig"); |
| 30 | 29 | _ = @import("behavior/eval.zig"); |
test/behavior/align.zig+47-10| ... | ... | @@ -18,6 +18,7 @@ test "global variable alignment" { |
| 18 | 18 | test "large alignment of local constant" { |
| 19 | 19 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 20 | 20 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky |
| 21 | if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; | |
| 21 | 22 | |
| 22 | 23 | const x: f32 align(128) = 12.34; |
| 23 | 24 | try std.testing.expect(@intFromPtr(&x) % 128 == 0); |
| ... | ... | @@ -30,13 +31,41 @@ test "slicing array of length 1 can not assume runtime index is always zero" { |
| 30 | 31 | var runtime_index: usize = 1; |
| 31 | 32 | _ = &runtime_index; |
| 32 | 33 | const slice = @as(*align(4) [1]u8, &foo)[runtime_index..]; |
| 33 | try expect(@TypeOf(slice) == []u8); | |
| 34 | try expect(@TypeOf(slice) == []align(1) u8); | |
| 34 | 35 | try expect(slice.len == 0); |
| 35 | 36 | try expect(@as(u2, @truncate(@intFromPtr(slice.ptr) - 1)) == 0); |
| 36 | 37 | } |
| 37 | 38 | |
| 38 | test "default alignment allows unspecified in type syntax" { | |
| 39 | try expect(*u32 == *align(@alignOf(u32)) u32); | |
| 39 | test "implicitly-aligned pointer is coercible to equivalent explicitly-aligned pointer" { | |
| 40 | const A = *u32; | |
| 41 | const B = *align(@alignOf(u32)) u32; | |
| 42 | ||
| 43 | comptime assert(A != B); | |
| 44 | ||
| 45 | const static = struct { | |
| 46 | fn doTheTest() !void { | |
| 47 | var buf: u32 = 123; | |
| 48 | ||
| 49 | const ptr: A = &buf; | |
| 50 | const coerced_ptr: B = ptr; | |
| 51 | ||
| 52 | try expect(ptr == coerced_ptr); | |
| 53 | try expect(ptr.* == 123); | |
| 54 | try expect(coerced_ptr.* == 123); | |
| 55 | ||
| 56 | const ptr_ptr: *const A = &ptr; | |
| 57 | const coerced_ptr_ptr: *const B = ptr_ptr; | |
| 58 | ||
| 59 | try expect(ptr_ptr == coerced_ptr_ptr); | |
| 60 | try expect(ptr_ptr.* == &buf); | |
| 61 | try expect(coerced_ptr_ptr.* == &buf); | |
| 62 | try expect(ptr_ptr.*.* == 123); | |
| 63 | try expect(coerced_ptr_ptr.*.* == 123); | |
| 64 | } | |
| 65 | }; | |
| 66 | ||
| 67 | try static.doTheTest(); | |
| 68 | try comptime static.doTheTest(); | |
| 40 | 69 | } |
| 41 | 70 | |
| 42 | 71 | test "implicitly decreasing pointer alignment" { |
| ... | ... | @@ -307,11 +336,15 @@ test "runtime-known array index has best alignment possible" { |
| 307 | 336 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 308 | 337 | |
| 309 | 338 | // take full advantage of over-alignment |
| 310 | var array align(4) = [_]u8{ 1, 2, 3, 4 }; | |
| 339 | var array align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; | |
| 311 | 340 | comptime assert(@TypeOf(&array[0]) == *align(4) u8); |
| 312 | comptime assert(@TypeOf(&array[1]) == *u8); | |
| 341 | comptime assert(@TypeOf(&array[1]) == *align(1) u8); | |
| 313 | 342 | comptime assert(@TypeOf(&array[2]) == *align(2) u8); |
| 314 | comptime assert(@TypeOf(&array[3]) == *u8); | |
| 343 | comptime assert(@TypeOf(&array[3]) == *align(1) u8); | |
| 344 | comptime assert(@TypeOf(&array[4]) == *align(4) u8); | |
| 345 | comptime assert(@TypeOf(&array[5]) == *align(1) u8); | |
| 346 | comptime assert(@TypeOf(&array[6]) == *align(2) u8); | |
| 347 | comptime assert(@TypeOf(&array[7]) == *align(1) u8); | |
| 315 | 348 | |
| 316 | 349 | // because align is too small but we still figure out to use 2 |
| 317 | 350 | var bigger align(2) = [_]u64{ 1, 2, 3, 4 }; |
| ... | ... | @@ -332,10 +365,14 @@ test "runtime-known array index has best alignment possible" { |
| 332 | 365 | try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32); |
| 333 | 366 | |
| 334 | 367 | // has to use ABI alignment because index known at runtime only |
| 335 | try testIndex2(&array, 0, *u8); | |
| 336 | try testIndex2(&array, 1, *u8); | |
| 337 | try testIndex2(&array, 2, *u8); | |
| 338 | try testIndex2(&array, 3, *u8); | |
| 368 | try testIndex2(&array, 0, *align(1) u8); | |
| 369 | try testIndex2(&array, 1, *align(1) u8); | |
| 370 | try testIndex2(&array, 2, *align(1) u8); | |
| 371 | try testIndex2(&array, 3, *align(1) u8); | |
| 372 | try testIndex2(&array, 4, *align(1) u8); | |
| 373 | try testIndex2(&array, 5, *align(1) u8); | |
| 374 | try testIndex2(&array, 6, *align(1) u8); | |
| 375 | try testIndex2(&array, 7, *align(1) u8); | |
| 339 | 376 | } |
| 340 | 377 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void { |
| 341 | 378 | comptime assert(@TypeOf(&smaller[index]) == T); |
test/behavior/alignof.zig+5| ... | ... | @@ -39,3 +39,8 @@ test "correct alignment for elements and slices of aligned array" { |
| 39 | 39 | try expect(@alignOf(@TypeOf(&buf[start..end])) == @alignOf(*u8)); |
| 40 | 40 | try expect(@alignOf(@TypeOf(&buf[start])) == @alignOf(*u8)); |
| 41 | 41 | } |
| 42 | ||
| 43 | test "@alignOf(anyerror!noreturn)" { | |
| 44 | try expect(@alignOf(anyerror!noreturn) == @alignOf(anyerror)); | |
| 45 | try expect(@alignOf(anyerror!anyerror!noreturn) == @alignOf(anyerror)); | |
| 46 | } |
test/behavior/array.zig-22| ... | ... | @@ -539,28 +539,6 @@ test "sentinel element count towards the ABI size calculation" { |
| 539 | 539 | try comptime S.doTheTest(); |
| 540 | 540 | } |
| 541 | 541 | |
| 542 | test "zero-sized array with recursive type definition" { | |
| 543 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 544 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 545 | ||
| 546 | const U = struct { | |
| 547 | fn foo(comptime T: type, comptime n: usize) type { | |
| 548 | return struct { | |
| 549 | s: [n]T, | |
| 550 | x: usize = n, | |
| 551 | }; | |
| 552 | } | |
| 553 | }; | |
| 554 | ||
| 555 | const S = struct { | |
| 556 | list: U.foo(@This(), 0), | |
| 557 | }; | |
| 558 | ||
| 559 | var t: S = .{ .list = .{ .s = undefined } }; | |
| 560 | _ = &t; | |
| 561 | try expect(@as(usize, 0) == t.list.x); | |
| 562 | } | |
| 563 | ||
| 564 | 542 | test "type coercion of anon struct literal to array" { |
| 565 | 543 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 566 | 544 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/bitcast.zig-32| ... | ... | @@ -350,9 +350,6 @@ test "comptime @bitCast packed struct to int and back" { |
| 350 | 350 | iint_neg2: i3 = -2, |
| 351 | 351 | float: f32 = 3.14, |
| 352 | 352 | @"enum": enum(u2) { A, B = 1, C, D } = .B, |
| 353 | vectorb: @Vector(3, bool) = .{ true, false, true }, | |
| 354 | vectori: @Vector(2, u8) = .{ 127, 42 }, | |
| 355 | vectorf: @Vector(2, f16) = .{ 3.14, 2.71 }, | |
| 356 | 353 | }; |
| 357 | 354 | const Int = @typeInfo(S).@"struct".backing_integer.?; |
| 358 | 355 | |
| ... | ... | @@ -511,35 +508,6 @@ test "@bitCast of packed struct of bools all false" { |
| 511 | 508 | try expect(@as(u8, @as(u4, @bitCast(p))) == 0); |
| 512 | 509 | } |
| 513 | 510 | |
| 514 | test "@bitCast of packed struct containing pointer" { | |
| 515 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 516 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 517 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 518 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO | |
| 519 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179 | |
| 520 | ||
| 521 | const S = struct { | |
| 522 | const A = packed struct { | |
| 523 | ptr: *const u32, | |
| 524 | }; | |
| 525 | ||
| 526 | const B = packed struct { | |
| 527 | ptr: *const i32, | |
| 528 | }; | |
| 529 | ||
| 530 | fn doTheTest() !void { | |
| 531 | const x: u32 = 123; | |
| 532 | var a: A = undefined; | |
| 533 | a = .{ .ptr = &x }; | |
| 534 | const b: B = @bitCast(a); | |
| 535 | try expect(b.ptr.* == 123); | |
| 536 | } | |
| 537 | }; | |
| 538 | ||
| 539 | try S.doTheTest(); | |
| 540 | try comptime S.doTheTest(); | |
| 541 | } | |
| 542 | ||
| 543 | 511 | test "@bitCast of extern struct containing pointer" { |
| 544 | 512 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 545 | 513 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
test/behavior/call.zig+5-6| ... | ... | @@ -551,19 +551,18 @@ test "generic function pointer can be called" { |
| 551 | 551 | |
| 552 | 552 | test "value returned from comptime function is comptime known" { |
| 553 | 553 | const S = struct { |
| 554 | fn fields(comptime T: type) switch (@typeInfo(T)) { | |
| 555 | .@"struct" => []const std.builtin.Type.StructField, | |
| 554 | fn fieldCount(comptime T: type) switch (@typeInfo(T)) { | |
| 555 | .@"struct" => comptime_int, | |
| 556 | 556 | else => unreachable, |
| 557 | 557 | } { |
| 558 | 558 | return switch (@typeInfo(T)) { |
| 559 | .@"struct" => |info| info.fields, | |
| 559 | .@"struct" => |info| info.fields.len, | |
| 560 | 560 | else => unreachable, |
| 561 | 561 | }; |
| 562 | 562 | } |
| 563 | 563 | }; |
| 564 | const fields_list = S.fields(@TypeOf(.{})); | |
| 565 | if (fields_list.len != 0) | |
| 566 | @compileError("Argument count mismatch"); | |
| 564 | const fields_len = S.fieldCount(@TypeOf(.{})); | |
| 565 | comptime assert(fields_len == 0); | |
| 567 | 566 | } |
| 568 | 567 | |
| 569 | 568 | test "registers get overwritten when ignoring return" { |
test/behavior/empty_union.zig deleted-66| ... | ... | @@ -1,66 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const expect = std.testing.expect; | |
| 4 | ||
| 5 | test "switch on empty enum" { | |
| 6 | const E = enum {}; | |
| 7 | var e: E = undefined; | |
| 8 | _ = &e; | |
| 9 | switch (e) {} | |
| 10 | } | |
| 11 | ||
| 12 | test "switch on empty enum with a specified tag type" { | |
| 13 | const E = enum(u8) {}; | |
| 14 | var e: E = undefined; | |
| 15 | _ = &e; | |
| 16 | switch (e) {} | |
| 17 | } | |
| 18 | ||
| 19 | test "switch on empty auto numbered tagged union" { | |
| 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 21 | ||
| 22 | const U = union(enum(u8)) {}; | |
| 23 | var u: U = undefined; | |
| 24 | _ = &u; | |
| 25 | switch (u) {} | |
| 26 | } | |
| 27 | ||
| 28 | test "switch on empty tagged union" { | |
| 29 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 30 | ||
| 31 | const E = enum {}; | |
| 32 | const U = union(E) {}; | |
| 33 | var u: U = undefined; | |
| 34 | _ = &u; | |
| 35 | switch (u) {} | |
| 36 | } | |
| 37 | ||
| 38 | test "empty union" { | |
| 39 | const U = union {}; | |
| 40 | try expect(@sizeOf(U) == 0); | |
| 41 | try expect(@alignOf(U) == 1); | |
| 42 | } | |
| 43 | ||
| 44 | test "empty extern union" { | |
| 45 | const U = extern union {}; | |
| 46 | try expect(@sizeOf(U) == 0); | |
| 47 | try expect(@alignOf(U) == 1); | |
| 48 | } | |
| 49 | ||
| 50 | test "empty union passed as argument" { | |
| 51 | const U = union(enum) { | |
| 52 | fn f(u: @This()) void { | |
| 53 | switch (u) {} | |
| 54 | } | |
| 55 | }; | |
| 56 | U.f(@as(U, undefined)); | |
| 57 | } | |
| 58 | ||
| 59 | test "empty enum passed as argument" { | |
| 60 | const E = enum { | |
| 61 | fn f(e: @This()) void { | |
| 62 | switch (e) {} | |
| 63 | } | |
| 64 | }; | |
| 65 | E.f(@as(E, undefined)); | |
| 66 | } |
test/behavior/enum.zig+38-16| ... | ... | @@ -823,15 +823,6 @@ test "enum with one member and u1 tag type @intFromEnum" { |
| 823 | 823 | try expect(@intFromEnum(Enum.Test) == 0); |
| 824 | 824 | } |
| 825 | 825 | |
| 826 | test "enum with comptime_int tag type" { | |
| 827 | const Enum = enum(comptime_int) { | |
| 828 | One = 3, | |
| 829 | Two = 2, | |
| 830 | Three = 1, | |
| 831 | }; | |
| 832 | comptime assert(Tag(Enum) == comptime_int); | |
| 833 | } | |
| 834 | ||
| 835 | 826 | test "enum with one member default to u0 tag type" { |
| 836 | 827 | const E0 = enum { X }; |
| 837 | 828 | comptime assert(Tag(E0) == u0); |
| ... | ... | @@ -1274,13 +1265,6 @@ fn getLazyInitialized(param: enum(u8) { |
| 1274 | 1265 | return @intFromEnum(param); |
| 1275 | 1266 | } |
| 1276 | 1267 | |
| 1277 | test "Non-exhaustive enum backed by comptime_int" { | |
| 1278 | const E = enum(comptime_int) { a, b, c, _ }; | |
| 1279 | comptime var e: E = .a; | |
| 1280 | e = @as(E, @enumFromInt(378089457309184723749)); | |
| 1281 | try expect(@intFromEnum(e) == 378089457309184723749); | |
| 1282 | } | |
| 1283 | ||
| 1284 | 1268 | test "matching captures causes enum equivalence" { |
| 1285 | 1269 | const S = struct { |
| 1286 | 1270 | fn Nonexhaustive(comptime I: type) type { |
| ... | ... | @@ -1347,3 +1331,41 @@ test "comptime @enumFromInt with signed arithmetic" { |
| 1347 | 1331 | comptime assert(x == .bar); |
| 1348 | 1332 | comptime assert(@intFromEnum(x) == 0); |
| 1349 | 1333 | } |
| 1334 | ||
| 1335 | test "switch on empty enum" { | |
| 1336 | const E = enum {}; | |
| 1337 | var e: E = undefined; | |
| 1338 | _ = &e; | |
| 1339 | switch (e) {} | |
| 1340 | } | |
| 1341 | ||
| 1342 | test "switch on empty enum with a specified tag type" { | |
| 1343 | const E = enum(u8) {}; | |
| 1344 | var e: E = undefined; | |
| 1345 | _ = &e; | |
| 1346 | switch (e) {} | |
| 1347 | } | |
| 1348 | ||
| 1349 | test "empty enum passed as argument" { | |
| 1350 | const E = enum { | |
| 1351 | fn f(e: @This()) void { | |
| 1352 | switch (e) {} | |
| 1353 | } | |
| 1354 | }; | |
| 1355 | E.f(@as(E, undefined)); | |
| 1356 | } | |
| 1357 | ||
| 1358 | test "enum int tag type uses declaration inside the enum" { | |
| 1359 | const static = struct { | |
| 1360 | const E = enum(E.IntTag) { | |
| 1361 | const IntTag = u8; | |
| 1362 | a, | |
| 1363 | b, | |
| 1364 | c, | |
| 1365 | }; | |
| 1366 | }; | |
| 1367 | try expect(@sizeOf(static.E) == @sizeOf(u8)); | |
| 1368 | const val: static.E = .b; | |
| 1369 | try expect(val == .b); | |
| 1370 | try expect(@intFromEnum(val) == 1); | |
| 1371 | } |
test/behavior/error.zig+33| ... | ... | @@ -1109,3 +1109,36 @@ test "'if' ignores error via local while 'else' ignores error directly" { |
| 1109 | 1109 | try S.testOne(false); |
| 1110 | 1110 | try S.testOne(true); |
| 1111 | 1111 | } |
| 1112 | ||
| 1113 | test "@errorCast into own inferred error set" { | |
| 1114 | const static = struct { | |
| 1115 | fn foo(b: bool) !void { | |
| 1116 | if (b) { | |
| 1117 | return @errorCast(error.Bad); | |
| 1118 | } | |
| 1119 | } | |
| 1120 | }; | |
| 1121 | try static.foo(false); | |
| 1122 | if (static.foo(true)) { | |
| 1123 | return error.ExpectedError; | |
| 1124 | } else |err| { | |
| 1125 | try expect(err == error.Bad); | |
| 1126 | } | |
| 1127 | ||
| 1128 | const errors = @typeInfo(@typeInfo(@TypeOf(static.foo(false))).error_union.error_set).error_set.?; | |
| 1129 | comptime assert(errors.len == 1); | |
| 1130 | comptime assert(std.mem.eql(u8, errors[0].name, "Bad")); | |
| 1131 | } | |
| 1132 | ||
| 1133 | test "@errorCast into other inferred error set" { | |
| 1134 | const static = struct { | |
| 1135 | fn foo() !void { | |
| 1136 | return error.Bad; | |
| 1137 | } | |
| 1138 | }; | |
| 1139 | const Ies = @typeInfo(@TypeOf(static.foo())).error_union.error_set; | |
| 1140 | const err: Ies = @errorCast(error.Bad); | |
| 1141 | try expect(err == error.Bad); | |
| 1142 | const non_err: Ies!u32 = @errorCast(@as(error{}!u32, 123)); | |
| 1143 | try expect(try non_err == 123); | |
| 1144 | } |
test/behavior/eval.zig-121| ... | ... | @@ -719,13 +719,6 @@ fn testVarInsideInlineLoop(args: anytype) !void { |
| 719 | 719 | } |
| 720 | 720 | } |
| 721 | 721 | |
| 722 | test "*align(1) u16 is the same as *align(1:0:2) u16" { | |
| 723 | comptime { | |
| 724 | try expect(*align(1:0:2) u16 == *align(1) u16); | |
| 725 | try expect(*align(2:0:2) u16 == *u16); | |
| 726 | } | |
| 727 | } | |
| 728 | ||
| 729 | 722 | test "array concatenation of function calls" { |
| 730 | 723 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 731 | 724 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1081,120 +1074,6 @@ test "comptime break operand passing through runtime switch converted to runtime |
| 1081 | 1074 | try comptime S.doTheTest('b'); |
| 1082 | 1075 | } |
| 1083 | 1076 | |
| 1084 | test "no dependency loop for alignment of self struct" { | |
| 1085 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 1086 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1087 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 1088 | ||
| 1089 | const S = struct { | |
| 1090 | fn doTheTest() !void { | |
| 1091 | var a: namespace.A = undefined; | |
| 1092 | a.d = .{ .g = &buf }; | |
| 1093 | a.d.g[3] = 42; | |
| 1094 | a.d.g[3] += 1; | |
| 1095 | try expect(a.d.g[3] == 43); | |
| 1096 | } | |
| 1097 | ||
| 1098 | var buf: [10]u8 align(@alignOf([*]u8)) = undefined; | |
| 1099 | ||
| 1100 | const namespace = struct { | |
| 1101 | const B = struct { a: A }; | |
| 1102 | const A = C(B); | |
| 1103 | }; | |
| 1104 | ||
| 1105 | pub fn C(comptime B: type) type { | |
| 1106 | return struct { | |
| 1107 | d: D(F) = .{}, | |
| 1108 | ||
| 1109 | const F = struct { b: B }; | |
| 1110 | }; | |
| 1111 | } | |
| 1112 | ||
| 1113 | pub fn D(comptime F: type) type { | |
| 1114 | return struct { | |
| 1115 | g: [*]align(@alignOf(F)) u8 = undefined, | |
| 1116 | }; | |
| 1117 | } | |
| 1118 | }; | |
| 1119 | try S.doTheTest(); | |
| 1120 | } | |
| 1121 | ||
| 1122 | test "no dependency loop for alignment of self bare union" { | |
| 1123 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 1124 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1125 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 1126 | ||
| 1127 | const S = struct { | |
| 1128 | fn doTheTest() !void { | |
| 1129 | var a: namespace.A = undefined; | |
| 1130 | a.d = .{ .g = &buf }; | |
| 1131 | a.d.g[3] = 42; | |
| 1132 | a.d.g[3] += 1; | |
| 1133 | try expect(a.d.g[3] == 43); | |
| 1134 | } | |
| 1135 | ||
| 1136 | var buf: [10]u8 align(@alignOf([*]u8)) = undefined; | |
| 1137 | ||
| 1138 | const namespace = struct { | |
| 1139 | const B = union { a: A, b: void }; | |
| 1140 | const A = C(B); | |
| 1141 | }; | |
| 1142 | ||
| 1143 | pub fn C(comptime B: type) type { | |
| 1144 | return struct { | |
| 1145 | d: D(F) = .{}, | |
| 1146 | ||
| 1147 | const F = struct { b: B }; | |
| 1148 | }; | |
| 1149 | } | |
| 1150 | ||
| 1151 | pub fn D(comptime F: type) type { | |
| 1152 | return struct { | |
| 1153 | g: [*]align(@alignOf(F)) u8 = undefined, | |
| 1154 | }; | |
| 1155 | } | |
| 1156 | }; | |
| 1157 | try S.doTheTest(); | |
| 1158 | } | |
| 1159 | ||
| 1160 | test "no dependency loop for alignment of self tagged union" { | |
| 1161 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 1162 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1163 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 1164 | ||
| 1165 | const S = struct { | |
| 1166 | fn doTheTest() !void { | |
| 1167 | var a: namespace.A = undefined; | |
| 1168 | a.d = .{ .g = &buf }; | |
| 1169 | a.d.g[3] = 42; | |
| 1170 | a.d.g[3] += 1; | |
| 1171 | try expect(a.d.g[3] == 43); | |
| 1172 | } | |
| 1173 | ||
| 1174 | var buf: [10]u8 align(@alignOf([*]u8)) = undefined; | |
| 1175 | ||
| 1176 | const namespace = struct { | |
| 1177 | const B = union(enum) { a: A, b: void }; | |
| 1178 | const A = C(B); | |
| 1179 | }; | |
| 1180 | ||
| 1181 | pub fn C(comptime B: type) type { | |
| 1182 | return struct { | |
| 1183 | d: D(F) = .{}, | |
| 1184 | ||
| 1185 | const F = struct { b: B }; | |
| 1186 | }; | |
| 1187 | } | |
| 1188 | ||
| 1189 | pub fn D(comptime F: type) type { | |
| 1190 | return struct { | |
| 1191 | g: [*]align(@alignOf(F)) u8 = undefined, | |
| 1192 | }; | |
| 1193 | } | |
| 1194 | }; | |
| 1195 | try S.doTheTest(); | |
| 1196 | } | |
| 1197 | ||
| 1198 | 1077 | test "equality of pointers to comptime const" { |
| 1199 | 1078 | const a: i32 = undefined; |
| 1200 | 1079 | comptime assert(&a == &a); |
test/behavior/generics.zig+1-4| ... | ... | @@ -339,7 +339,7 @@ test "generic instantiation of tagged union with only one field" { |
| 339 | 339 | try expect(S.foo(.{ .s = "ab" }) == 2); |
| 340 | 340 | } |
| 341 | 341 | |
| 342 | test "nested generic function" { | |
| 342 | test "generic parameter type is function type" { | |
| 343 | 343 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 344 | 344 | |
| 345 | 345 | const S = struct { |
| ... | ... | @@ -349,10 +349,7 @@ test "nested generic function" { |
| 349 | 349 | fn bar(a: u32) anyerror!void { |
| 350 | 350 | try expect(a == 123); |
| 351 | 351 | } |
| 352 | ||
| 353 | fn g(_: *const fn (anytype) void) void {} | |
| 354 | 352 | }; |
| 355 | try expect(@typeInfo(@TypeOf(S.g)).@"fn".is_generic); | |
| 356 | 353 | try S.foo(u32, S.bar, 123); |
| 357 | 354 | } |
| 358 | 355 |
test/behavior/packed-struct.zig+1-99| ... | ... | @@ -438,27 +438,6 @@ test "nested packed struct field pointers" { |
| 438 | 438 | try expectEqual(6, ptr_p1_b.*); |
| 439 | 439 | } |
| 440 | 440 | |
| 441 | test "load pointer from packed struct" { | |
| 442 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 443 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 444 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 445 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 446 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 447 | ||
| 448 | const A = struct { | |
| 449 | index: u16, | |
| 450 | }; | |
| 451 | const B = packed struct { | |
| 452 | x: *A, | |
| 453 | y: u32, | |
| 454 | }; | |
| 455 | var a: A = .{ .index = 123 }; | |
| 456 | const b_list: []const B = &.{.{ .x = &a, .y = 99 }}; | |
| 457 | for (b_list) |b| { | |
| 458 | try expect(b.x.index == 123); | |
| 459 | } | |
| 460 | } | |
| 461 | ||
| 462 | 441 | test "@intFromPtr on a packed struct field" { |
| 463 | 442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 464 | 443 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -601,19 +580,6 @@ test "packed struct fields modification" { |
| 601 | 580 | try expect(@as(u16, @bitCast(Small.p)) == 0x1313); |
| 602 | 581 | } |
| 603 | 582 | |
| 604 | test "optional pointer in packed struct" { | |
| 605 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 606 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 607 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 608 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 609 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 610 | ||
| 611 | const T = packed struct { ptr: ?*const u8 }; | |
| 612 | var n: u8 = 0; | |
| 613 | const x = T{ .ptr = &n }; | |
| 614 | try expect(x.ptr.? == &n); | |
| 615 | } | |
| 616 | ||
| 617 | 583 | test "nested packed struct field access test" { |
| 618 | 584 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 619 | 585 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits |
| ... | ... | @@ -854,7 +820,7 @@ test "packed struct passed to callconv(.c) function" { |
| 854 | 820 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 855 | 821 | |
| 856 | 822 | const S = struct { |
| 857 | const Packed = packed struct { | |
| 823 | const Packed = packed struct(u64) { | |
| 858 | 824 | a: u16, |
| 859 | 825 | b: bool = true, |
| 860 | 826 | c: bool = true, |
| ... | ... | @@ -1042,48 +1008,6 @@ test "packed struct acts as a namespace" { |
| 1042 | 1008 | try expect(foo == .fizz); |
| 1043 | 1009 | } |
| 1044 | 1010 | |
| 1045 | test "pointer loaded correctly from packed struct" { | |
| 1046 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 1047 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 1048 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1049 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | |
| 1050 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 1051 | ||
| 1052 | if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC | |
| 1053 | ||
| 1054 | const RAM = struct { | |
| 1055 | data: [0xFFFF + 1]u8, | |
| 1056 | fn new() !@This() { | |
| 1057 | return .{ .data = [_]u8{0} ** 0x10000 }; | |
| 1058 | } | |
| 1059 | fn get(self: *@This(), addr: u16) u8 { | |
| 1060 | return self.data[addr]; | |
| 1061 | } | |
| 1062 | }; | |
| 1063 | ||
| 1064 | const CPU = packed struct { | |
| 1065 | interrupts: bool, | |
| 1066 | ram: *RAM, | |
| 1067 | fn new(ram: *RAM) !@This() { | |
| 1068 | return .{ | |
| 1069 | .ram = ram, | |
| 1070 | .interrupts = false, | |
| 1071 | }; | |
| 1072 | } | |
| 1073 | fn tick(self: *@This()) !void { | |
| 1074 | const queued_interrupts = self.ram.get(0xFFFF) & self.ram.get(0xFF0F); | |
| 1075 | if (self.interrupts and queued_interrupts != 0) { | |
| 1076 | self.interrupts = false; | |
| 1077 | } | |
| 1078 | } | |
| 1079 | }; | |
| 1080 | ||
| 1081 | var ram = try RAM.new(); | |
| 1082 | var cpu = try CPU.new(&ram); | |
| 1083 | try cpu.tick(); | |
| 1084 | try std.testing.expect(cpu.interrupts == false); | |
| 1085 | } | |
| 1086 | ||
| 1087 | 1011 | test "assignment to non-byte-aligned field in packed struct" { |
| 1088 | 1012 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1089 | 1013 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1227,13 +1151,6 @@ test "2-byte packed struct argument in C calling convention" { |
| 1227 | 1151 | } |
| 1228 | 1152 | } |
| 1229 | 1153 | |
| 1230 | test "packed struct contains optional pointer" { | |
| 1231 | const foo: packed struct { | |
| 1232 | a: ?*@This() = null, | |
| 1233 | } = .{}; | |
| 1234 | try expect(foo.a == null); | |
| 1235 | } | |
| 1236 | ||
| 1237 | 1154 | test "packed struct equality" { |
| 1238 | 1155 | const Foo = packed struct { |
| 1239 | 1156 | a: u4, |
| ... | ... | @@ -1297,21 +1214,6 @@ test "assign packed struct initialized with RLS to packed struct literal field" |
| 1297 | 1214 | try expect(outer.x == x); |
| 1298 | 1215 | } |
| 1299 | 1216 | |
| 1300 | test "byte-aligned packed relocation" { | |
| 1301 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1302 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | |
| 1303 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 1304 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 1305 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 1306 | ||
| 1307 | const S = struct { | |
| 1308 | var global: u8 align(2) = 0; | |
| 1309 | var packed_value: packed struct { x: u8, y: *align(2) u8 } = .{ .x = 111, .y = &global }; | |
| 1310 | }; | |
| 1311 | try expect(S.packed_value.x == 111); | |
| 1312 | try expect(S.packed_value.y == &S.global); | |
| 1313 | } | |
| 1314 | ||
| 1315 | 1217 | test "packed struct store of comparison result" { |
| 1316 | 1218 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1317 | 1219 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/packed-union.zig+18-8| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | const expect = std.testing.expect; | |
| 4 | 5 | const expectEqual = std.testing.expectEqual; |
| 5 | 6 | |
| 6 | 7 | test "flags in packed union" { |
| ... | ... | @@ -178,14 +179,23 @@ test "assigning to non-active field at comptime" { |
| 178 | 179 | } |
| 179 | 180 | } |
| 180 | 181 | |
| 181 | test "comptime packed union of pointers" { | |
| 182 | const U = packed union { | |
| 183 | a: *const u32, | |
| 184 | b: *const [1]u32, | |
| 185 | }; | |
| 182 | test "packed union with explicit backing integer" { | |
| 183 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 184 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 185 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 186 | 186 | |
| 187 | const x: u32 = 123; | |
| 188 | const u: U = .{ .a = &x }; | |
| 187 | const U = packed union(i32) { | |
| 188 | raw: i32, | |
| 189 | unsigned_halves: packed struct { low: u16, high: u16 }, | |
| 189 | 190 | |
| 190 | comptime assert(u.b[0] == 123); | |
| 191 | fn check(val: @This()) !void { | |
| 192 | try expect(@as(i32, @bitCast(val)) == -2); | |
| 193 | try expect(@as(u32, @bitCast(val)) == 0xFFFFFFFE); | |
| 194 | try expect(val.raw == -2); | |
| 195 | try expect(val.unsigned_halves.low == 0xFFFE); | |
| 196 | try expect(val.unsigned_halves.high == 0xFFFF); | |
| 197 | } | |
| 198 | }; | |
| 199 | try U.check(.{ .raw = -2 }); | |
| 200 | try comptime U.check(.{ .raw = -2 }); | |
| 191 | 201 | } |
test/behavior/sizeof_and_typeof.zig+1-41| ... | ... | @@ -11,13 +11,6 @@ test "@sizeOf and @TypeOf" { |
| 11 | 11 | const x: u16 = 13; |
| 12 | 12 | const z: @TypeOf(x) = 19; |
| 13 | 13 | |
| 14 | test "@sizeOf on compile-time types" { | |
| 15 | try expect(@sizeOf(comptime_int) == 0); | |
| 16 | try expect(@sizeOf(comptime_float) == 0); | |
| 17 | try expect(@sizeOf(@TypeOf(.hi)) == 0); | |
| 18 | try expect(@sizeOf(@TypeOf(type)) == 0); | |
| 19 | } | |
| 20 | ||
| 21 | 14 | test "@TypeOf() with multiple arguments" { |
| 22 | 15 | { |
| 23 | 16 | var var_1: u32 = undefined; |
| ... | ... | @@ -127,21 +120,6 @@ test "@bitOffsetOf" { |
| 127 | 120 | try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); |
| 128 | 121 | } |
| 129 | 122 | |
| 130 | test "@sizeOf(T) == 0 doesn't force resolving struct size" { | |
| 131 | const S = struct { | |
| 132 | const Foo = struct { | |
| 133 | y: if (@sizeOf(Foo) == 0) u64 else u32, | |
| 134 | }; | |
| 135 | const Bar = struct { | |
| 136 | x: i32, | |
| 137 | y: if (0 == @sizeOf(Bar)) u64 else u32, | |
| 138 | }; | |
| 139 | }; | |
| 140 | ||
| 141 | try expect(@sizeOf(S.Foo) == 4); | |
| 142 | try expect(@sizeOf(S.Bar) == 8); | |
| 143 | } | |
| 144 | ||
| 145 | 123 | test "@TypeOf() has no runtime side effects" { |
| 146 | 124 | const S = struct { |
| 147 | 125 | fn foo(comptime T: type, ptr: *T) T { |
| ... | ... | @@ -265,10 +243,6 @@ test "lazy size cast to float" { |
| 265 | 243 | } |
| 266 | 244 | } |
| 267 | 245 | |
| 268 | test "bitSizeOf comptime_int" { | |
| 269 | try expect(@bitSizeOf(comptime_int) == 0); | |
| 270 | } | |
| 271 | ||
| 272 | 246 | test "runtime instructions inside typeof in comptime only scope" { |
| 273 | 247 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 274 | 248 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -336,20 +310,6 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" { |
| 336 | 310 | try std.testing.expect(t.next == null); |
| 337 | 311 | } |
| 338 | 312 | |
| 339 | test "@sizeOf reified union zero-size payload fields" { | |
| 340 | comptime { | |
| 341 | try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{}, &.{}, &.{}))); | |
| 342 | try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{"a"}, &.{void}, &.{.{}}))); | |
| 343 | if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) { | |
| 344 | try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} }))); | |
| 345 | try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} }))); | |
| 346 | } else { | |
| 347 | try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} }))); | |
| 348 | try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} }))); | |
| 349 | } | |
| 350 | } | |
| 351 | } | |
| 352 | ||
| 353 | 313 | const FILE = extern struct { |
| 354 | 314 | dummy_field: u8, |
| 355 | 315 | }; |
| ... | ... | @@ -391,7 +351,7 @@ test "Extern function calls in @TypeOf" { |
| 391 | 351 | |
| 392 | 352 | extern fn s_do_thing([*c]const @This(), b: c_int) c_short; |
| 393 | 353 | }; |
| 394 | const E = struct { | |
| 354 | const E = extern struct { | |
| 395 | 355 | export fn s_do_thing(a: [*c]const @This(), b: c_int) c_short { |
| 396 | 356 | _ = a; |
| 397 | 357 | _ = b; |
test/behavior/slice.zig+1-1| ... | ... | @@ -160,7 +160,7 @@ test "slice of type" { |
| 160 | 160 | |
| 161 | 161 | test "pass a slice of types to a function" { |
| 162 | 162 | const S = struct { |
| 163 | fn checkTypesSlice(types_slice: []const type) !void { | |
| 163 | fn checkTypesSlice(comptime types_slice: []const type) !void { | |
| 164 | 164 | try expect(types_slice.len == 2); |
| 165 | 165 | try expect(types_slice[0] == anyerror); |
| 166 | 166 | try expect(types_slice[1] == bool); |
test/behavior/struct.zig+73-1| ... | ... | @@ -2177,7 +2177,7 @@ test "avoid unused field function body compile error" { |
| 2177 | 2177 | |
| 2178 | 2178 | test "pass a pointer to a comptime-only struct field to a function" { |
| 2179 | 2179 | const S = struct { |
| 2180 | fn checkField(field_ptr: *const type) !void { | |
| 2180 | fn checkField(comptime field_ptr: *const type) !void { | |
| 2181 | 2181 | try expect(field_ptr.* == u42); |
| 2182 | 2182 | } |
| 2183 | 2183 | }; |
| ... | ... | @@ -2233,3 +2233,75 @@ test "overaligned extern struct fields" { |
| 2233 | 2233 | try expect(std.mem.isAligned(@intFromPtr(&e.c), @alignOf(u32))); |
| 2234 | 2234 | try expect(std.mem.isAligned(@intFromPtr(&e.d), @alignOf(B))); |
| 2235 | 2235 | } |
| 2236 | ||
| 2237 | test "runtime-known slice of comptime-only struct" { | |
| 2238 | const Mixed = struct { index: u32, T: type }; | |
| 2239 | ||
| 2240 | const static = struct { | |
| 2241 | fn doTheTest(index_offset: usize, s: []const Mixed) !void { | |
| 2242 | for (s, index_offset..) |*mixed, index| { | |
| 2243 | try expect(mixed.index == index); | |
| 2244 | } | |
| 2245 | } | |
| 2246 | }; | |
| 2247 | ||
| 2248 | try static.doTheTest(10, &.{ | |
| 2249 | .{ .index = 10, .T = u8 }, | |
| 2250 | .{ .index = 11, .T = noreturn }, | |
| 2251 | .{ .index = 12, .T = *opaque {} }, | |
| 2252 | .{ .index = 13, .T = undefined }, | |
| 2253 | .{ .index = 14, .T = @TypeOf(undefined) }, | |
| 2254 | .{ .index = 15, .T = Mixed }, | |
| 2255 | }); | |
| 2256 | } | |
| 2257 | ||
| 2258 | test "struct contains aligned pointer to itself through type decl" { | |
| 2259 | const Slab = struct { | |
| 2260 | const Ptr = *align(64) const @This(); | |
| 2261 | next: Ptr, | |
| 2262 | }; | |
| 2263 | // We intentionally use `Slab.Ptr` before `Slab`. | |
| 2264 | var ptr: Slab.Ptr = undefined; | |
| 2265 | var slab: Slab align(64) = undefined; | |
| 2266 | ptr = &slab; | |
| 2267 | slab.next = ptr; | |
| 2268 | ||
| 2269 | try expect(ptr == &slab); | |
| 2270 | try expect(slab.next == &slab); | |
| 2271 | try expect(slab.next.next == &slab); | |
| 2272 | try expect(slab.next.next.next == &slab); | |
| 2273 | } | |
| 2274 | ||
| 2275 | test "struct contains underaligned field with overaligned pointer to itself" { | |
| 2276 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 2277 | const S = struct { | |
| 2278 | ptr: *align(8) @This() align(1), | |
| 2279 | }; | |
| 2280 | var val: S align(8) = undefined; | |
| 2281 | val.ptr = &val; | |
| 2282 | try expect(val.ptr == &val); | |
| 2283 | try expect(val.ptr.ptr == &val); | |
| 2284 | try expect(val.ptr.ptr.ptr == &val); | |
| 2285 | } | |
| 2286 | ||
| 2287 | test "struct contains pointer to function accepting that struct" { | |
| 2288 | const S = struct { | |
| 2289 | const FnPtr = ?*const fn (@This()) void; | |
| 2290 | fn_ptr: FnPtr, | |
| 2291 | }; | |
| 2292 | const dummy_fn_ptr: S.FnPtr = @ptrFromInt(0x100000); | |
| 2293 | const dummy_s: S = .{ .fn_ptr = dummy_fn_ptr }; | |
| 2294 | try expect(dummy_s.fn_ptr == dummy_fn_ptr); | |
| 2295 | try expect(@TypeOf(dummy_s.fn_ptr.?) == *const fn (S) void); | |
| 2296 | } | |
| 2297 | ||
| 2298 | test "struct queries typeinfo of struct containing pointer back to first struct" { | |
| 2299 | const static = struct { | |
| 2300 | const A = struct { b: *B }; | |
| 2301 | const B = struct { a: T: { | |
| 2302 | _ = @typeInfo(A); | |
| 2303 | break :T u32; | |
| 2304 | } }; | |
| 2305 | }; | |
| 2306 | _ = @as(static.A, undefined); | |
| 2307 | } |
test/behavior/struct_contains_slice_of_itself.zig+1-1| ... | ... | @@ -8,7 +8,7 @@ const Node = struct { |
| 8 | 8 | |
| 9 | 9 | const NodeAligned = struct { |
| 10 | 10 | payload: i32, |
| 11 | children: []align(@alignOf(NodeAligned)) NodeAligned, | |
| 11 | children: []align(1) NodeAligned, | |
| 12 | 12 | }; |
| 13 | 13 | |
| 14 | 14 | test "struct contains slice of itself" { |
test/behavior/switch.zig+5-6| ... | ... | @@ -645,7 +645,7 @@ test "switch prong pointer capture alignment" { |
| 645 | 645 | } |
| 646 | 646 | |
| 647 | 647 | switch (u) { |
| 648 | .a, .c => |*p| comptime assert(@TypeOf(p) == *const u8), | |
| 648 | .a, .c => |*p| comptime assert(@TypeOf(p) == *align(1) const u8), | |
| 649 | 649 | .b => |*p| { |
| 650 | 650 | _ = p; |
| 651 | 651 | return error.TestFailed; |
| ... | ... | @@ -1141,24 +1141,23 @@ test "decl literals as switch cases" { |
| 1141 | 1141 | try comptime E.doTheTest(.foo); |
| 1142 | 1142 | } |
| 1143 | 1143 | |
| 1144 | // TODO audit after #15909 and/or #19855 are decided/implemented | |
| 1144 | // TODO audit after #15909 and/or #19855 are decided/implemented. | |
| 1145 | // When we do that, consider adding an 'error{}' case if possible. | |
| 1145 | 1146 | test "switch with uninstantiable union fields" { |
| 1146 | 1147 | const U = union(enum) { |
| 1147 | 1148 | ok: void, |
| 1148 | 1149 | a: noreturn, |
| 1149 | 1150 | b: noreturn, |
| 1150 | c: error{}, | |
| 1151 | 1151 | |
| 1152 | 1152 | fn doTheTest(u: @This()) void { |
| 1153 | 1153 | switch (u) { |
| 1154 | 1154 | .ok => {}, |
| 1155 | 1155 | .a => comptime unreachable, |
| 1156 | 1156 | .b => comptime unreachable, |
| 1157 | .c => comptime unreachable, | |
| 1158 | 1157 | } |
| 1159 | 1158 | switch (u) { |
| 1160 | 1159 | .ok => {}, |
| 1161 | .a, .b, .c => comptime unreachable, | |
| 1160 | .a, .b => comptime unreachable, | |
| 1162 | 1161 | } |
| 1163 | 1162 | switch (u) { |
| 1164 | 1163 | .ok => {}, |
| ... | ... | @@ -1166,7 +1165,7 @@ test "switch with uninstantiable union fields" { |
| 1166 | 1165 | } |
| 1167 | 1166 | switch (u) { |
| 1168 | 1167 | .a => comptime unreachable, |
| 1169 | .ok, .b, .c => {}, | |
| 1168 | .ok, .b => {}, | |
| 1170 | 1169 | } |
| 1171 | 1170 | } |
| 1172 | 1171 | }; |
test/behavior/tuple.zig+11| ... | ... | @@ -592,3 +592,14 @@ test "array of tuples that end with a zero-bit field followed by padding" { |
| 592 | 592 | try expect(S.foo[1][1] == 4); |
| 593 | 593 | try expect(S.foo[1][2] == {}); |
| 594 | 594 | } |
| 595 | ||
| 596 | test "call function at comptime through container-level const tuple" { | |
| 597 | const static = struct { | |
| 598 | const MyTuple = struct { (fn () u32) }; | |
| 599 | const val: MyTuple = .{foo}; | |
| 600 | fn foo() u32 { | |
| 601 | return 1234; | |
| 602 | } | |
| 603 | }; | |
| 604 | comptime assert(static.val[0]() == 1234); | |
| 605 | } |
test/behavior/tuple_declarations.zig+2-2| ... | ... | @@ -22,13 +22,13 @@ test "tuple declaration type info" { |
| 22 | 22 | try expect(info.fields[0].type == u32); |
| 23 | 23 | try expect(info.fields[0].defaultValue() == 1); |
| 24 | 24 | try expect(info.fields[0].is_comptime); |
| 25 | try expect(info.fields[0].alignment == @alignOf(u32)); | |
| 25 | try expect(info.fields[0].alignment == null); | |
| 26 | 26 | |
| 27 | 27 | try expectEqualStrings(info.fields[1].name, "1"); |
| 28 | 28 | try expect(info.fields[1].type == []const u8); |
| 29 | 29 | try expect(info.fields[1].defaultValue() == null); |
| 30 | 30 | try expect(!info.fields[1].is_comptime); |
| 31 | try expect(info.fields[1].alignment == @alignOf([]const u8)); | |
| 31 | try expect(info.fields[1].alignment == null); | |
| 32 | 32 | } |
| 33 | 33 | } |
| 34 | 34 |
test/behavior/type.zig+2-2| ... | ... | @@ -278,13 +278,13 @@ test "Type.Union from regular enum" { |
| 278 | 278 | test "Type.Union from empty regular enum" { |
| 279 | 279 | const E = enum {}; |
| 280 | 280 | const U = @Union(.auto, E, &.{}, &.{}, &.{}); |
| 281 | try testing.expectEqual(@sizeOf(U), 0); | |
| 281 | try testing.expectEqual(@typeInfo(U).@"union".fields.len, 0); | |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | 284 | test "Type.Union from empty Type.Enum" { |
| 285 | 285 | const E = @Enum(u0, .exhaustive, &.{}, &.{}); |
| 286 | 286 | const U = @Union(.auto, E, &.{}, &.{}, &.{}); |
| 287 | try testing.expectEqual(@sizeOf(U), 0); | |
| 287 | try testing.expectEqual(@typeInfo(U).@"union".fields.len, 0); | |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | test "Type.Fn" { |
test/behavior/type_info.zig+8-8| ... | ... | @@ -82,7 +82,7 @@ fn testPointer() !void { |
| 82 | 82 | try expect(u32_ptr_info.pointer.size == .one); |
| 83 | 83 | try expect(u32_ptr_info.pointer.is_const == false); |
| 84 | 84 | try expect(u32_ptr_info.pointer.is_volatile == false); |
| 85 | try expect(u32_ptr_info.pointer.alignment == @alignOf(u32)); | |
| 85 | try expect(u32_ptr_info.pointer.alignment == null); | |
| 86 | 86 | try expect(u32_ptr_info.pointer.child == u32); |
| 87 | 87 | try expect(u32_ptr_info.pointer.sentinel() == null); |
| 88 | 88 | } |
| ... | ... | @@ -99,7 +99,7 @@ fn testUnknownLenPtr() !void { |
| 99 | 99 | try expect(u32_ptr_info.pointer.is_const == true); |
| 100 | 100 | try expect(u32_ptr_info.pointer.is_volatile == true); |
| 101 | 101 | try expect(u32_ptr_info.pointer.sentinel() == null); |
| 102 | try expect(u32_ptr_info.pointer.alignment == @alignOf(f64)); | |
| 102 | try expect(u32_ptr_info.pointer.alignment == null); | |
| 103 | 103 | try expect(u32_ptr_info.pointer.child == f64); |
| 104 | 104 | } |
| 105 | 105 | |
| ... | ... | @@ -130,7 +130,7 @@ fn testSlice() !void { |
| 130 | 130 | try expect(u32_slice_info.pointer.size == .slice); |
| 131 | 131 | try expect(u32_slice_info.pointer.is_const == false); |
| 132 | 132 | try expect(u32_slice_info.pointer.is_volatile == false); |
| 133 | try expect(u32_slice_info.pointer.alignment == 4); | |
| 133 | try expect(u32_slice_info.pointer.alignment == null); | |
| 134 | 134 | try expect(u32_slice_info.pointer.child == u32); |
| 135 | 135 | } |
| 136 | 136 | |
| ... | ... | @@ -266,9 +266,9 @@ fn testUnion() !void { |
| 266 | 266 | try expect(notag_union_info.@"union".tag_type == null); |
| 267 | 267 | try expect(notag_union_info.@"union".layout == .auto); |
| 268 | 268 | try expect(notag_union_info.@"union".fields.len == 2); |
| 269 | try expect(notag_union_info.@"union".fields[0].alignment == @alignOf(void)); | |
| 269 | try expect(notag_union_info.@"union".fields[0].alignment == null); | |
| 270 | 270 | try expect(notag_union_info.@"union".fields[1].type == u32); |
| 271 | try expect(notag_union_info.@"union".fields[1].alignment == @alignOf(u32)); | |
| 271 | try expect(notag_union_info.@"union".fields[1].alignment == null); | |
| 272 | 272 | |
| 273 | 273 | const TestExternUnion = extern union { |
| 274 | 274 | foo: *anyopaque, |
| ... | ... | @@ -292,7 +292,7 @@ fn testStruct() !void { |
| 292 | 292 | const unpacked_struct_info = @typeInfo(TestStruct); |
| 293 | 293 | try expect(unpacked_struct_info.@"struct".is_tuple == false); |
| 294 | 294 | try expect(unpacked_struct_info.@"struct".backing_integer == null); |
| 295 | try expect(unpacked_struct_info.@"struct".fields[0].alignment == @alignOf(u32)); | |
| 295 | try expect(unpacked_struct_info.@"struct".fields[0].alignment == null); | |
| 296 | 296 | try expect(unpacked_struct_info.@"struct".fields[0].defaultValue().? == 4); |
| 297 | 297 | try expect(mem.eql(u8, "foobar", unpacked_struct_info.@"struct".fields[1].defaultValue().?)); |
| 298 | 298 | } |
| ... | ... | @@ -314,11 +314,11 @@ fn testPackedStruct() !void { |
| 314 | 314 | try expect(struct_info.@"struct".layout == .@"packed"); |
| 315 | 315 | try expect(struct_info.@"struct".backing_integer == u128); |
| 316 | 316 | try expect(struct_info.@"struct".fields.len == 4); |
| 317 | try expect(struct_info.@"struct".fields[0].alignment == 0); | |
| 317 | try expect(struct_info.@"struct".fields[0].alignment == null); | |
| 318 | 318 | try expect(struct_info.@"struct".fields[2].type == f32); |
| 319 | 319 | try expect(struct_info.@"struct".fields[2].defaultValue() == null); |
| 320 | 320 | try expect(struct_info.@"struct".fields[3].defaultValue().? == 4); |
| 321 | try expect(struct_info.@"struct".fields[3].alignment == 0); | |
| 321 | try expect(struct_info.@"struct".fields[3].alignment == null); | |
| 322 | 322 | try expect(struct_info.@"struct".decls.len == 1); |
| 323 | 323 | } |
| 324 | 324 |
test/behavior/union.zig+20-53| ... | ... | @@ -148,6 +148,7 @@ const err = @as(anyerror!Agg, Agg{ |
| 148 | 148 | const array = [_]Value{ v1, v2, v1, v2 }; |
| 149 | 149 | |
| 150 | 150 | test "unions embedded in aggregate types" { |
| 151 | if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; | |
| 151 | 152 | switch (array[1]) { |
| 152 | 153 | Value.Array => |arr| try expect(arr[4] == 3), |
| 153 | 154 | else => unreachable, |
| ... | ... | @@ -217,26 +218,6 @@ test "union with specified enum tag" { |
| 217 | 218 | try comptime doTest(); |
| 218 | 219 | } |
| 219 | 220 | |
| 220 | test "packed union generates correctly aligned type" { | |
| 221 | // This test will be removed after the following accepted proposal is implemented: | |
| 222 | // https://github.com/ziglang/zig/issues/24657 | |
| 223 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 224 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 225 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 226 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 227 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 228 | ||
| 229 | const U = packed union { | |
| 230 | f1: *const fn () error{TestUnexpectedResult}!void, | |
| 231 | f2: usize, | |
| 232 | }; | |
| 233 | var foo = [_]U{ | |
| 234 | U{ .f1 = doTest }, | |
| 235 | U{ .f2 = 0 }, | |
| 236 | }; | |
| 237 | try foo[0].f1(); | |
| 238 | } | |
| 239 | ||
| 240 | 221 | fn doTest() error{TestUnexpectedResult}!void { |
| 241 | 222 | try expect((try bar(Payload{ .A = 1234 })) == -10); |
| 242 | 223 | } |
| ... | ... | @@ -359,12 +340,12 @@ test "simple union(enum(u32))" { |
| 359 | 340 | try expect(@intFromEnum(@as(Tag(MultipleChoice), x)) == 60); |
| 360 | 341 | } |
| 361 | 342 | |
| 362 | const PackedPtrOrInt = packed union { | |
| 363 | ptr: *u8, | |
| 364 | int: usize, | |
| 365 | }; | |
| 366 | 343 | test "packed union size" { |
| 367 | comptime assert(@sizeOf(PackedPtrOrInt) == @sizeOf(usize)); | |
| 344 | const U = packed union { | |
| 345 | signed: isize, | |
| 346 | unsigned: usize, | |
| 347 | }; | |
| 348 | comptime assert(@sizeOf(U) == @sizeOf(usize)); | |
| 368 | 349 | } |
| 369 | 350 | |
| 370 | 351 | const ZeroBits = union { |
| ... | ... | @@ -703,25 +684,23 @@ test "union with only 1 field casted to its enum type which has enum value speci |
| 703 | 684 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 704 | 685 | |
| 705 | 686 | const Literal = union(enum) { |
| 706 | Number: f64, | |
| 707 | Bool: bool, | |
| 687 | number: f64, | |
| 688 | bool: bool, | |
| 708 | 689 | }; |
| 709 | 690 | |
| 710 | const ExprTag = enum(comptime_int) { | |
| 711 | Literal = 33, | |
| 712 | }; | |
| 691 | const ExprTag = enum(u32) { literal = 33 }; | |
| 692 | const Expr = union(ExprTag) { literal: Literal }; | |
| 713 | 693 | |
| 714 | const Expr = union(ExprTag) { | |
| 715 | Literal: Literal, | |
| 716 | }; | |
| 694 | comptime assert(Tag(ExprTag) == u32); | |
| 717 | 695 | |
| 718 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | |
| 719 | _ = &e; | |
| 720 | comptime assert(Tag(ExprTag) == comptime_int); | |
| 721 | const t = comptime @as(ExprTag, e); | |
| 722 | try expect(t == Expr.Literal); | |
| 723 | try expect(@intFromEnum(t) == 33); | |
| 696 | var e: Expr = undefined; | |
| 697 | e = .{ .literal = .{ .bool = true } }; | |
| 698 | ||
| 699 | const t: ExprTag = e; | |
| 700 | comptime assert(t == Expr.literal); | |
| 724 | 701 | comptime assert(@intFromEnum(t) == 33); |
| 702 | try expect(t == Expr.literal); | |
| 703 | try expect(@intFromEnum(t) == 33); | |
| 725 | 704 | } |
| 726 | 705 | |
| 727 | 706 | test "@intFromEnum works on unions" { |
| ... | ... | @@ -893,15 +872,6 @@ test "union no tag with struct member" { |
| 893 | 872 | u.foo(); |
| 894 | 873 | } |
| 895 | 874 | |
| 896 | test "union with comptime_int tag" { | |
| 897 | const Union = union(enum(comptime_int)) { | |
| 898 | X: u32, | |
| 899 | Y: u16, | |
| 900 | Z: u8, | |
| 901 | }; | |
| 902 | comptime assert(Tag(Tag(Union)) == comptime_int); | |
| 903 | } | |
| 904 | ||
| 905 | 875 | test "extern union doesn't trigger field check at comptime" { |
| 906 | 876 | const U = extern union { |
| 907 | 877 | x: u32, |
| ... | ... | @@ -1031,7 +1001,7 @@ test "containers with single-field enums" { |
| 1031 | 1001 | try comptime S.doTheTest(); |
| 1032 | 1002 | } |
| 1033 | 1003 | |
| 1034 | test "@unionInit on union with tag but no fields" { | |
| 1004 | test "@unionInit on union with u8 tag but no fields" { | |
| 1035 | 1005 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1036 | 1006 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1037 | 1007 | |
| ... | ... | @@ -1047,10 +1017,6 @@ test "@unionInit on union with tag but no fields" { |
| 1047 | 1017 | } |
| 1048 | 1018 | }; |
| 1049 | 1019 | |
| 1050 | comptime { | |
| 1051 | assert(@sizeOf(Data) == 1); | |
| 1052 | } | |
| 1053 | ||
| 1054 | 1020 | fn doTheTest() !void { |
| 1055 | 1021 | var data: Data = .{ .no_op = {} }; |
| 1056 | 1022 | _ = &data; |
| ... | ... | @@ -2057,6 +2023,7 @@ test "runtime union init, most-aligned field != largest" { |
| 2057 | 2023 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2058 | 2024 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 2059 | 2025 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2026 | if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; | |
| 2060 | 2027 | |
| 2061 | 2028 | const U = union(enum) { |
| 2062 | 2029 | x: u128, |
test/c_abi/main.zig+2-2| ... | ... | @@ -718,7 +718,7 @@ export fn zig_med_struct_ints(s: MedStructInts) void { |
| 718 | 718 | expect(s.z == 3) catch @panic("test failure"); |
| 719 | 719 | } |
| 720 | 720 | |
| 721 | const SmallPackedStruct = packed struct { | |
| 721 | const SmallPackedStruct = packed struct(u8) { | |
| 722 | 722 | a: u2, |
| 723 | 723 | b: u2, |
| 724 | 724 | c: u2, |
| ... | ... | @@ -744,7 +744,7 @@ test "C ABI small packed struct" { |
| 744 | 744 | try expect(s2.d == 3); |
| 745 | 745 | } |
| 746 | 746 | |
| 747 | const BigPackedStruct = packed struct { | |
| 747 | const BigPackedStruct = packed struct(u128) { | |
| 748 | 748 | a: u64, |
| 749 | 749 | b: u64, |
| 750 | 750 | }; |
test/cases/compile_errors/@import_zon_bad_type.zig+4-4| ... | ... | @@ -116,13 +116,13 @@ export fn testMutablePointer() void { |
| 116 | 116 | // tmp.zig:85:26: note: ZON does not allow nested optionals |
| 117 | 117 | // tmp.zig:90:29: error: type '*i32' is not available in ZON |
| 118 | 118 | // tmp.zig:90:29: note: ZON does not allow mutable pointers |
| 119 | // neg_inf.zon:1:1: error: expected type '@EnumLiteral()' | |
| 120 | // tmp.zig:37:38: note: imported here | |
| 121 | 119 | // neg_inf.zon:1:1: error: expected type '?u8' |
| 122 | 120 | // tmp.zig:57:28: note: imported here |
| 121 | // neg_inf.zon:1:1: error: expected type '@EnumLiteral()' | |
| 122 | // tmp.zig:37:38: note: imported here | |
| 123 | 123 | // neg_inf.zon:1:1: error: expected type 'tmp.E' |
| 124 | 124 | // tmp.zig:63:26: note: imported here |
| 125 | // neg_inf.zon:1:1: error: expected type 'tmp.U' | |
| 126 | // tmp.zig:69:26: note: imported here | |
| 127 | 125 | // neg_inf.zon:1:1: error: expected type 'tmp.EU' |
| 128 | 126 | // tmp.zig:75:27: note: imported here |
| 127 | // neg_inf.zon:1:1: error: expected type 'tmp.U' | |
| 128 | // tmp.zig:69:26: note: imported here |
test/cases/compile_errors/@import_zon_opt_in_err.zig+10-10| ... | ... | @@ -58,25 +58,25 @@ export fn testVector() void { |
| 58 | 58 | // error |
| 59 | 59 | // imports=zon/vec2.zon |
| 60 | 60 | // |
| 61 | // vec2.zon:1:2: error: expected type '?f32' | |
| 62 | // tmp.zig:2:29: note: imported here | |
| 63 | 61 | // vec2.zon:1:2: error: expected type '*const ?f32' |
| 64 | 62 | // tmp.zig:7:36: note: imported here |
| 65 | 63 | // vec2.zon:1:2: error: expected type '?*const f32' |
| 66 | 64 | // tmp.zig:12:36: note: imported here |
| 65 | // vec2.zon:1:2: error: expected type '?@EnumLiteral()' | |
| 66 | // tmp.zig:33:39: note: imported here | |
| 67 | // vec2.zon:1:2: error: expected type '?@Vector(3, f32)' | |
| 68 | // tmp.zig:54:41: note: imported here | |
| 69 | // vec2.zon:1:2: error: expected type '?[1]u8' | |
| 70 | // tmp.zig:38:31: note: imported here | |
| 71 | // vec2.zon:1:2: error: expected type '?[]const u8' | |
| 72 | // tmp.zig:49:36: note: imported here | |
| 67 | 73 | // vec2.zon:1:2: error: expected type '?bool' |
| 68 | 74 | // tmp.zig:17:30: note: imported here |
| 75 | // vec2.zon:1:2: error: expected type '?f32' | |
| 76 | // tmp.zig:2:29: note: imported here | |
| 69 | 77 | // vec2.zon:1:2: error: expected type '?i32' |
| 70 | 78 | // tmp.zig:22:29: note: imported here |
| 71 | 79 | // vec2.zon:1:2: error: expected type '?tmp.Enum' |
| 72 | 80 | // tmp.zig:28:30: note: imported here |
| 73 | // vec2.zon:1:2: error: expected type '?@EnumLiteral()' | |
| 74 | // tmp.zig:33:39: note: imported here | |
| 75 | // vec2.zon:1:2: error: expected type '?[1]u8' | |
| 76 | // tmp.zig:38:31: note: imported here | |
| 77 | 81 | // vec2.zon:1:2: error: expected type '?tmp.Union' |
| 78 | 82 | // tmp.zig:44:31: note: imported here |
| 79 | // vec2.zon:1:2: error: expected type '?[]const u8' | |
| 80 | // tmp.zig:49:36: note: imported here | |
| 81 | // vec2.zon:1:2: error: expected type '?@Vector(3, f32)' | |
| 82 | // tmp.zig:54:41: note: imported here |
test/cases/compile_errors/@import_zon_opt_in_err_struct.zig+4-4| ... | ... | @@ -13,7 +13,7 @@ export fn testTuple() void { |
| 13 | 13 | // error |
| 14 | 14 | // imports=zon/nan.zon |
| 15 | 15 | // |
| 16 | //nan.zon:1:1: error: expected type '?tmp.Struct' | |
| 17 | //tmp.zig:3:32: note: imported here | |
| 18 | //nan.zon:1:1: error: expected type '?struct { bool }' | |
| 19 | //tmp.zig:9:31: note: imported here | |
| 16 | // nan.zon:1:1: error: expected type '?struct { bool }' | |
| 17 | // tmp.zig:9:31: note: imported here | |
| 18 | // nan.zon:1:1: error: expected type '?tmp.Struct' | |
| 19 | // tmp.zig:3:32: note: imported here |
test/cases/compile_errors/@intFromPtr_with_bad_type.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | const x = 42; | |
| 2 | const y = @intFromPtr(&x); | |
| 3 | pub export fn entry() void { | |
| 4 | _ = y; | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // | |
| 9 | // :2:23: error: comptime-only type 'comptime_int' has no pointer address |
test/cases/compile_errors/AstGen_comptime_known_struct_is_resolved_before_error.zig deleted-17| ... | ... | @@ -1,17 +0,0 @@ |
| 1 | const S1 = struct { | |
| 2 | a: S2, | |
| 3 | }; | |
| 4 | const S2 = struct { | |
| 5 | b: fn () void, | |
| 6 | }; | |
| 7 | pub export fn entry() void { | |
| 8 | var s: S1 = undefined; | |
| 9 | _ = &s; | |
| 10 | } | |
| 11 | ||
| 12 | // error | |
| 13 | // | |
| 14 | // :8:12: error: variable of type 'tmp.S1' must be const or comptime | |
| 15 | // :2:8: note: struct requires comptime because of this field | |
| 16 | // :5:8: note: struct requires comptime because of this field | |
| 17 | // :5:8: note: use '*const fn () void' for a function pointer type |
test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const Foo = struct { a: u32 }; | |
| 2 | export fn a() void { | |
| 3 | const T = [*c]Foo; | |
| 4 | const t: T = undefined; | |
| 5 | _ = t; | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // | |
| 10 | // :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo' | |
| 11 | // :3:19: note: only extern structs and ABI sized packed structs are extern compatible | |
| 12 | // :1:13: note: struct declared here |
test/cases/compile_errors/aggregate_too_large.zig+7-9| ... | ... | @@ -12,16 +12,14 @@ const U = union { |
| 12 | 12 | b: [1 << 32]u8, |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | const V = union { | |
| 16 | a: u32, | |
| 17 | b: T, | |
| 18 | }; | |
| 19 | ||
| 20 | 15 | comptime { |
| 21 | _ = S; | |
| 22 | _ = T; | |
| 23 | _ = U; | |
| 24 | _ = V; | |
| 16 | _ = @as(S, undefined); | |
| 17 | } | |
| 18 | comptime { | |
| 19 | _ = @as(T, undefined); | |
| 20 | } | |
| 21 | comptime { | |
| 22 | _ = @as(U, undefined); | |
| 25 | 23 | } |
| 26 | 24 | |
| 27 | 25 | // error |
test/cases/compile_errors/alignOf_bad_type.zig+8-2| ... | ... | @@ -1,7 +1,13 @@ |
| 1 | export fn entry() usize { | |
| 1 | export fn entry0() usize { | |
| 2 | 2 | return @alignOf(noreturn); |
| 3 | 3 | } |
| 4 | const S = struct { a: u32, b: noreturn }; | |
| 5 | export fn entry1() usize { | |
| 6 | return @alignOf(S); | |
| 7 | } | |
| 4 | 8 | |
| 5 | 9 | // error |
| 6 | 10 | // |
| 7 | // :2:21: error: no align available for type 'noreturn' | |
| 11 | // :2:21: error: no align available for uninstantiable type 'noreturn' | |
| 12 | // :6:21: error: no align available for uninstantiable type 'tmp.S' | |
| 13 | // :4:11: note: struct declared here |
test/cases/compile_errors/align_zero.zig+4-4| ... | ... | @@ -30,11 +30,11 @@ export fn g() void { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | export fn h() void { |
| 33 | _ = struct { field: i32 align(0) }; | |
| 33 | _ = @as(struct { field: i32 align(0) }, undefined); | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | export fn i() void { |
| 37 | _ = union { field: i32 align(0) }; | |
| 37 | _ = @as(union { field: i32 align(0) }, undefined); | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | export fn j() void { |
| ... | ... | @@ -54,7 +54,7 @@ export fn k() void { |
| 54 | 54 | // :20:30: error: alignment must be >= 1 |
| 55 | 55 | // :25:16: error: alignment must be >= 1 |
| 56 | 56 | // :29:17: error: alignment must be >= 1 |
| 57 | // :33:35: error: alignment must be >= 1 | |
| 58 | // :37:34: error: alignment must be >= 1 | |
| 57 | // :33:39: error: alignment must be >= 1 | |
| 58 | // :37:38: error: alignment must be >= 1 | |
| 59 | 59 | // :41:51: error: alignment must be >= 1 |
| 60 | 60 | // :45:25: error: alignment must be >= 1 |
test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | var a = &b; | |
| 3 | _ = &a; | |
| 4 | } | |
| 5 | inline fn b() void {} | |
| 6 | ||
| 7 | // error | |
| 8 | // | |
| 9 | // :2:9: error: variable of type '*const fn () callconv(.@"inline") void' must be const or comptime | |
| 10 | // :2:9: note: function has inline calling convention |
test/cases/compile_errors/bit_ptr_non_packed.zig+6-2| ... | ... | @@ -16,7 +16,11 @@ export fn entry3() void { |
| 16 | 16 | // error |
| 17 | 17 | // |
| 18 | 18 | // :3:23: error: bit-pointer cannot refer to value of type 'tmp.entry1.S' |
| 19 | // :3:23: note: only packed structs layout are allowed in packed types | |
| 19 | // :3:23: note: non-packed structs do not have a bit-packed representation | |
| 20 | // :2:22: note: struct declared here | |
| 20 | 21 | // :8:36: error: bit-pointer cannot refer to value of type 'tmp.entry2.S' |
| 21 | // :8:36: note: only packed structs layout are allowed in packed types | |
| 22 | // :8:36: note: non-packed structs do not have a bit-packed representation | |
| 23 | // :7:15: note: struct declared here | |
| 22 | 24 | // :13:23: error: bit-pointer cannot refer to value of type 'tmp.entry3.E' |
| 25 | // :12:15: note: integer tag type of enum is inferred | |
| 26 | // :12:15: note: consider explicitly specifying the integer tag type |
test/cases/compile_errors/bitsize_of_packed_struct_checks_backing_int_ty.zig+3-1| ... | ... | @@ -8,4 +8,6 @@ pub export fn entry() void { |
| 8 | 8 | |
| 9 | 9 | // error |
| 10 | 10 | // |
| 11 | // :1:27: error: backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 1 | |
| 11 | // :1:20: error: backing integer bit width does not match total bit width of fields | |
| 12 | // :1:27: note: backing integer 'u32' has bit width '32' | |
| 13 | // :1:20: note: struct fields have total bit width '1' |
test/cases/compile_errors/c_pointer_to_void.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | const a: [*c]void = undefined; | |
| 3 | _ = a; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :2:18: error: C pointers cannot point to non-C-ABI-compatible type 'void' | |
| 9 | // :2:18: note: 'void' is a zero bit type; for C 'void' use 'anyopaque' |
test/cases/compile_errors/call_runtime_known_inline_fn_ptr.zig created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | export fn entry() void { | |
| 2 | var a = &b; | |
| 3 | a = a; | |
| 4 | a(); | |
| 5 | } | |
| 6 | inline fn b() void {} | |
| 7 | ||
| 8 | // error | |
| 9 | // | |
| 10 | // :4:5: error: unable to resolve comptime value | |
| 11 | // :4:5: note: function being called inline must be comptime-known |
test/cases/compile_errors/coerce_int_to_float.zig+6-6| ... | ... | @@ -40,13 +40,13 @@ export fn entry() void { |
| 40 | 40 | |
| 41 | 41 | // error |
| 42 | 42 | // |
| 43 | // :6:20: error: expected type 'f16', found 'u12' | |
| 43 | // :6:20: error: expected type 'f128', found 'i115' | |
| 44 | // :6:20: error: expected type 'f128', found 'u114' | |
| 44 | 45 | // :6:20: error: expected type 'f16', found 'i13' |
| 45 | // :6:20: error: expected type 'f32', found 'u25' | |
| 46 | // :6:20: error: expected type 'f16', found 'u12' | |
| 46 | 47 | // :6:20: error: expected type 'f32', found 'i26' |
| 47 | // :6:20: error: expected type 'f64', found 'u54' | |
| 48 | // :6:20: error: expected type 'f32', found 'u25' | |
| 48 | 49 | // :6:20: error: expected type 'f64', found 'i55' |
| 49 | // :6:20: error: expected type 'f80', found 'u65' | |
| 50 | // :6:20: error: expected type 'f64', found 'u54' | |
| 50 | 51 | // :6:20: error: expected type 'f80', found 'i66' |
| 51 | // :6:20: error: expected type 'f128', found 'u114' | |
| 52 | // :6:20: error: expected type 'f128', found 'i115' | |
| 52 | // :6:20: error: expected type 'f80', found 'u65' |
test/cases/compile_errors/comptime_var_referenced_by_type.zig+1-1| ... | ... | @@ -21,6 +21,6 @@ comptime { |
| 21 | 21 | // error |
| 22 | 22 | // |
| 23 | 23 | // :7:16: error: captured value contains reference to comptime var |
| 24 | // :7:16: note: 'wrapper' points to '@as(*const tmp.Wrapper, @ptrCast(&v0)).*', where | |
| 24 | // :7:16: note: 'wrapper' points to 'v0', where | |
| 25 | 25 | // :16:5: note: 'v0.ptr' points to comptime var declared here |
| 26 | 26 | // :17:29: note: called at comptime here |
test/cases/compile_errors/direct_struct_loop.zig+1-1| ... | ... | @@ -7,4 +7,4 @@ export fn entry() usize { |
| 7 | 7 | |
| 8 | 8 | // error |
| 9 | 9 | // |
| 10 | // :1:11: error: struct 'tmp.A' depends on itself | |
| 10 | // :2:8: error: type 'tmp.A' depends on itself for field declared here |
test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig+4-2| ... | ... | @@ -26,9 +26,11 @@ export fn d() void { |
| 26 | 26 | |
| 27 | 27 | // error |
| 28 | 28 | // |
| 29 | // :3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs | |
| 29 | // :3:8: error: cannot directly embed opaque type 'tmp.O' in struct | |
| 30 | // :3:8: note: opaque types have unknown size | |
| 30 | 31 | // :1:11: note: opaque declared here |
| 31 | // :7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions | |
| 32 | // :7:10: error: cannot directly embed opaque type 'tmp.O' in union | |
| 33 | // :7:10: note: opaque types have unknown size | |
| 32 | 34 | // :1:11: note: opaque declared here |
| 33 | 35 | // :18:24: error: cannot cast to opaque type 'tmp.O' |
| 34 | 36 | // :1:11: note: opaque declared here |
test/cases/compile_errors/empty_extern_union.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | export fn foo() void { | |
| 2 | const U = extern union {}; | |
| 3 | _ = @as(U, undefined); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :2:22: error: extern union has no fields |
test/cases/compile_errors/empty_packed_union.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | export fn foo() void { | |
| 2 | const U = packed union {}; | |
| 3 | _ = @as(U, undefined); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :2:22: error: packed union has no fields |
test/cases/compile_errors/enum_backed_by_comptime_int.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | const E = enum(comptime_int) { a }; | |
| 2 | comptime { | |
| 3 | _ = E.a; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :1:16: error: expected integer tag type, found 'comptime_int' |
test/cases/compile_errors/enum_backed_by_comptime_int_must_be_casted_from_comptime_value.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | const Tag = enum(comptime_int) { a, b }; | |
| 3 | ||
| 4 | var v: u32 = 0; | |
| 5 | _ = &v; | |
| 6 | _ = @as(Tag, @enumFromInt(v)); | |
| 7 | } | |
| 8 | ||
| 9 | // error | |
| 10 | // | |
| 11 | // :6:31: error: unable to resolve comptime value | |
| 12 | // :6:31: note: value casted to enum with 'comptime_int' tag type must be comptime-known |
test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | pub export fn entry() void { | |
| 2 | const E = enum(comptime_int) { a, b, c, _ }; | |
| 3 | var e: E = .a; | |
| 4 | _ = &e; | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // | |
| 9 | // :3:12: error: variable of type 'tmp.entry.E' must be const or comptime |
test/cases/compile_errors/enum_field_value_references_enum.zig+4-8| ... | ... | @@ -1,15 +1,11 @@ |
| 1 | 1 | pub const Foo = enum(c_int) { |
| 2 | A = Foo.B, | |
| 3 | C = D, | |
| 4 | ||
| 5 | pub const B = 0; | |
| 2 | a = 10, | |
| 3 | b = @intFromEnum(Foo.a) - 1, | |
| 6 | 4 | }; |
| 7 | 5 | export fn entry() void { |
| 8 | const s: Foo = Foo.E; | |
| 9 | _ = s; | |
| 6 | _ = @as(Foo, .a); | |
| 10 | 7 | } |
| 11 | const D = 1; | |
| 12 | 8 | |
| 13 | 9 | // error |
| 14 | 10 | // |
| 15 | // :1:5: error: dependency loop detected | |
| 11 | // :3:25: error: type 'tmp.Foo' depends on itself for field usage here |
test/cases/compile_errors/enum_field_value_references_nonexistent_circular.zig+1-1| ... | ... | @@ -10,4 +10,4 @@ const D = 1; |
| 10 | 10 | |
| 11 | 11 | // error |
| 12 | 12 | // |
| 13 | // :1:5: error: dependency loop detected | |
| 13 | // :2:12: error: type 'tmp.Foo' depends on itself for field usage here |
test/cases/compile_errors/enum_uses_own_typeinfo.zig created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | const E = enum(u9) { | |
| 2 | const a_val: @typeInfo(E).@"enum".tag_type = 0; | |
| 3 | a = a_val, | |
| 4 | }; | |
| 5 | comptime { | |
| 6 | _ = E.a; | |
| 7 | } | |
| 8 | ||
| 9 | // error | |
| 10 | // | |
| 11 | // error: dependency loop with length 3 | |
| 12 | // :3:9: note: type 'tmp.E' uses value of declaration 'tmp.E.a_val' here | |
| 13 | // :2:50: note: value of declaration 'tmp.E.a_val' uses type of declaration 'tmp.E.a_val' here | |
| 14 | // :2:18: note: type of declaration 'tmp.E.a_val' depends on type 'tmp.E' for type information query here | |
| 15 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/enum_value_already_taken.zig+2-2| ... | ... | @@ -12,5 +12,5 @@ export fn entry() void { |
| 12 | 12 | |
| 13 | 13 | // error |
| 14 | 14 | // |
| 15 | // :6:9: error: enum tag value 60 already taken | |
| 16 | // :4:9: note: other occurrence here | |
| 15 | // :6:9: error: enum tag value '60' for field 'E' already taken | |
| 16 | // :4:9: note: previous occurrence in field 'C' |
test/cases/compile_errors/error_set_membership.zig+2-1| ... | ... | @@ -26,5 +26,6 @@ pub fn main() Error!void { |
| 26 | 26 | // error |
| 27 | 27 | // target=x86_64-linux |
| 28 | 28 | // |
| 29 | // :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' | |
| 29 | // :23:29: error: expected type 'error{InvalidCharacter}!void', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' | |
| 30 | 30 | // :23:29: note: 'error.InvalidDirection' not a member of destination error set |
| 31 | // :22:20: note: function return type declared here |
test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig+2-2| ... | ... | @@ -11,6 +11,6 @@ comptime { |
| 11 | 11 | // |
| 12 | 12 | // :3:5: error: unable to export type 'type' |
| 13 | 13 | // :7:5: error: unable to export type 'tmp.E' |
| 14 | // :7:5: note: enum tag type 'u1' is not extern compatible | |
| 15 | // :7:5: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible | |
| 14 | // :1:11: note: integer tag type of enum is inferred | |
| 15 | // :1:11: note: consider explicitly specifying the integer tag type | |
| 16 | 16 | // :1:11: note: enum declared here |
test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig deleted-45| ... | ... | @@ -1,45 +0,0 @@ |
| 1 | // zig fmt: off | |
| 2 | pub const E = enum { | |
| 3 | @"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12", | |
| 4 | @"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20",@"21",@"22",@"23", | |
| 5 | @"24",@"25",@"26",@"27",@"28",@"29",@"30",@"31",@"32",@"33",@"34", | |
| 6 | @"35",@"36",@"37",@"38",@"39",@"40",@"41",@"42",@"43",@"44",@"45", | |
| 7 | @"46",@"47",@"48",@"49",@"50",@"51",@"52",@"53",@"54",@"55",@"56", | |
| 8 | @"57",@"58",@"59",@"60",@"61",@"62",@"63",@"64",@"65",@"66",@"67", | |
| 9 | @"68",@"69",@"70",@"71",@"72",@"73",@"74",@"75",@"76",@"77",@"78", | |
| 10 | @"79",@"80",@"81",@"82",@"83",@"84",@"85",@"86",@"87",@"88",@"89", | |
| 11 | @"90",@"91",@"92",@"93",@"94",@"95",@"96",@"97",@"98",@"99",@"100", | |
| 12 | @"101",@"102",@"103",@"104",@"105",@"106",@"107",@"108",@"109", | |
| 13 | @"110",@"111",@"112",@"113",@"114",@"115",@"116",@"117",@"118", | |
| 14 | @"119",@"120",@"121",@"122",@"123",@"124",@"125",@"126",@"127", | |
| 15 | @"128",@"129",@"130",@"131",@"132",@"133",@"134",@"135",@"136", | |
| 16 | @"137",@"138",@"139",@"140",@"141",@"142",@"143",@"144",@"145", | |
| 17 | @"146",@"147",@"148",@"149",@"150",@"151",@"152",@"153",@"154", | |
| 18 | @"155",@"156",@"157",@"158",@"159",@"160",@"161",@"162",@"163", | |
| 19 | @"164",@"165",@"166",@"167",@"168",@"169",@"170",@"171",@"172", | |
| 20 | @"173",@"174",@"175",@"176",@"177",@"178",@"179",@"180",@"181", | |
| 21 | @"182",@"183",@"184",@"185",@"186",@"187",@"188",@"189",@"190", | |
| 22 | @"191",@"192",@"193",@"194",@"195",@"196",@"197",@"198",@"199", | |
| 23 | @"200",@"201",@"202",@"203",@"204",@"205",@"206",@"207",@"208", | |
| 24 | @"209",@"210",@"211",@"212",@"213",@"214",@"215",@"216",@"217", | |
| 25 | @"218",@"219",@"220",@"221",@"222",@"223",@"224",@"225",@"226", | |
| 26 | @"227",@"228",@"229",@"230",@"231",@"232",@"233",@"234",@"235", | |
| 27 | @"236",@"237",@"238",@"239",@"240",@"241",@"242",@"243",@"244", | |
| 28 | @"245",@"246",@"247",@"248",@"249",@"250",@"251",@"252",@"253", | |
| 29 | @"254",@"255", @"256" | |
| 30 | }; | |
| 31 | // zig fmt: on | |
| 32 | pub const S = extern struct { | |
| 33 | e: E, | |
| 34 | }; | |
| 35 | export fn entry() void { | |
| 36 | const s: S = undefined; | |
| 37 | _ = s; | |
| 38 | } | |
| 39 | ||
| 40 | // error | |
| 41 | // | |
| 42 | // :33:8: error: extern structs cannot contain fields of type 'tmp.E' | |
| 43 | // :33:8: note: enum tag type 'u9' is not extern compatible | |
| 44 | // :33:8: note: only integers with 0 or power of two bits are extern compatible | |
| 45 | // :2:15: note: enum declared here |
test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig+2-2| ... | ... | @@ -10,6 +10,6 @@ export fn entry() void { |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | 12 | // :3:8: error: extern structs cannot contain fields of type 'tmp.E' |
| 13 | // :3:8: note: enum tag type 'u31' is not extern compatible | |
| 14 | // :3:8: note: only integers with 0 or power of two bits are extern compatible | |
| 13 | // :1:15: note: enum tag type 'u31' is not extern compatible | |
| 14 | // :1:15: note: only integers with 0 or power of two bits are extern compatible | |
| 15 | 15 | // :1:15: note: enum declared here |
test/cases/compile_errors/fn_body_in_struct_runtime_known.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | const S1 = struct { | |
| 2 | a: S2, | |
| 3 | }; | |
| 4 | const S2 = struct { | |
| 5 | b: fn () void, | |
| 6 | }; | |
| 7 | pub export fn entry() void { | |
| 8 | var s: S1 = undefined; | |
| 9 | _ = &s; | |
| 10 | } | |
| 11 | ||
| 12 | // error | |
| 13 | // | |
| 14 | // :8:12: error: variable of type 'tmp.S1' must be const or comptime | |
| 15 | // :2:8: note: struct requires comptime because of this field | |
| 16 | // :5:8: note: struct requires comptime because of this field | |
| 17 | // :5:8: note: use '*const fn () void' for a function pointer type |
test/cases/compile_errors/fn_type_returning_pointer_to_itself.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | const MyFn = fn () ?*const MyFn; | |
| 2 | comptime { | |
| 3 | _ = MyFn; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :1:28: error: value of declaration 'tmp.MyFn' depends on itself here |
test/cases/compile_errors/function_ptr_alignment.zig+1-1| ... | ... | @@ -11,5 +11,5 @@ comptime { |
| 11 | 11 | // error |
| 12 | 12 | // target=x86_64-linux |
| 13 | 13 | // |
| 14 | // :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void' | |
| 14 | // :8:41: error: expected type '*align(2) const fn () void', found '*align(1) const fn () void' | |
| 15 | 15 | // :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2' |
test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig+2-2| ... | ... | @@ -7,6 +7,6 @@ export fn entry(foo: Foo) void { |
| 7 | 7 | // target=x86_64-linux |
| 8 | 8 | // |
| 9 | 9 | // :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv' |
| 10 | // :2:17: note: enum tag type 'u2' is not extern compatible | |
| 11 | // :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible | |
| 10 | // :1:13: note: integer tag type of enum is inferred | |
| 11 | // :1:13: note: consider explicitly specifying the integer tag type | |
| 12 | 12 | // :1:13: note: enum declared here |
test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig+1-1| ... | ... | @@ -11,5 +11,5 @@ export fn entry(foo: Foo) void { |
| 11 | 11 | // target=x86_64-linux |
| 12 | 12 | // |
| 13 | 13 | // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv' |
| 14 | // :6:17: note: only extern structs and ABI sized packed structs are extern compatible | |
| 14 | // :6:17: note: struct with automatic layout has no guaranteed in-memory representation | |
| 15 | 15 | // :1:13: note: struct declared here |
test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig+1-1| ... | ... | @@ -11,5 +11,5 @@ export fn entry(foo: Foo) void { |
| 11 | 11 | // target=x86_64-linux |
| 12 | 12 | // |
| 13 | 13 | // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv' |
| 14 | // :6:17: note: only extern unions and ABI sized packed unions are extern compatible | |
| 14 | // :6:17: note: union with automatic layout has no guaranteed in-memory representation | |
| 15 | 15 | // :1:13: note: union declared here |
test/cases/compile_errors/generic_function_returning_opaque_type.zig+1-1| ... | ... | @@ -11,6 +11,6 @@ export fn bar() void { |
| 11 | 11 | |
| 12 | 12 | // error |
| 13 | 13 | // |
| 14 | // :1:30: error: opaque return type 'anyopaque' not allowed | |
| 14 | 15 | // :1:30: error: opaque return type 'tmp.MyOpaque' not allowed |
| 15 | 16 | // :4:18: note: opaque declared here |
| 16 | // :1:30: error: opaque return type 'anyopaque' not allowed |
test/cases/compile_errors/implicit_backing_type_in_extern_context.zig created+51| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | const PackedStruct = packed struct { x: u32 }; | |
| 2 | const PackedUnion = packed union { x: u32 }; | |
| 3 | ||
| 4 | /// This enum has 256 fields, so `u8` will be its inferred tag type. | |
| 5 | const Enum = enum { | |
| 6 | // zig fmt: off | |
| 7 | _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0a, _0b, _0c, _0d, _0e, _0f, | |
| 8 | _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1a, _1b, _1c, _1d, _1e, _1f, | |
| 9 | _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2a, _2b, _2c, _2d, _2e, _2f, | |
| 10 | _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3a, _3b, _3c, _3d, _3e, _3f, | |
| 11 | _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4a, _4b, _4c, _4d, _4e, _4f, | |
| 12 | _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5a, _5b, _5c, _5d, _5e, _5f, | |
| 13 | _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6a, _6b, _6c, _6d, _6e, _6f, | |
| 14 | _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7a, _7b, _7c, _7d, _7e, _7f, | |
| 15 | _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8a, _8b, _8c, _8d, _8e, _8f, | |
| 16 | _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9a, _9b, _9c, _9d, _9e, _9f, | |
| 17 | _a0, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8, _a9, _aa, _ab, _ac, _ad, _ae, _af, | |
| 18 | _b0, _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8, _b9, _ba, _bb, _bc, _bd, _be, _bf, | |
| 19 | _c0, _c1, _c2, _c3, _c4, _c5, _c6, _c7, _c8, _c9, _ca, _cb, _cc, _cd, _ce, _cf, | |
| 20 | _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7, _d8, _d9, _da, _db, _dc, _dd, _de, _df, | |
| 21 | _e0, _e1, _e2, _e3, _e4, _e5, _e6, _e7, _e8, _e9, _ea, _eb, _ec, _ed, _ee, _ef, | |
| 22 | _f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _fa, _fb, _fc, _fd, _fe, _ff, | |
| 23 | // zig fmt: on | |
| 24 | }; | |
| 25 | ||
| 26 | const Extern0 = extern struct { val: PackedStruct }; | |
| 27 | const Extern1 = extern struct { val: PackedUnion }; | |
| 28 | const Extern2 = extern struct { val: Enum }; | |
| 29 | ||
| 30 | comptime { | |
| 31 | _ = @as(Extern0, undefined); | |
| 32 | } | |
| 33 | comptime { | |
| 34 | _ = @as(Extern1, undefined); | |
| 35 | } | |
| 36 | comptime { | |
| 37 | _ = @as(Extern2, undefined); | |
| 38 | } | |
| 39 | ||
| 40 | // error | |
| 41 | // | |
| 42 | // :26:38: error: extern structs cannot contain fields of type 'tmp.PackedStruct' | |
| 43 | // :26:38: note: inferred backing integer of packed struct has unspecified signedness | |
| 44 | // :1:29: note: struct declared here | |
| 45 | // :27:38: error: extern structs cannot contain fields of type 'tmp.PackedUnion' | |
| 46 | // :27:38: note: inferred backing integer of packed union has unspecified signedness | |
| 47 | // :2:28: note: union declared here | |
| 48 | // :28:38: error: extern structs cannot contain fields of type 'tmp.Enum' | |
| 49 | // :5:14: note: integer tag type of enum is inferred | |
| 50 | // :5:14: note: consider explicitly specifying the integer tag type | |
| 51 | // :5:14: note: enum declared here |
test/cases/compile_errors/indexing_an_array_of_size_zero.zig+1-1| ... | ... | @@ -6,4 +6,4 @@ export fn foo() void { |
| 6 | 6 | |
| 7 | 7 | // error |
| 8 | 8 | // |
| 9 | // :3:27: error: indexing into empty array is not allowed | |
| 9 | // :3:27: error: cannot index into empty array |
test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig+1-1| ... | ... | @@ -8,4 +8,4 @@ export fn foo() void { |
| 8 | 8 | |
| 9 | 9 | // error |
| 10 | 10 | // |
| 11 | // :5:27: error: indexing into empty array is not allowed | |
| 11 | // :5:27: error: cannot index into empty array |
test/cases/compile_errors/indirect_struct_loop.zig+5-1| ... | ... | @@ -13,4 +13,8 @@ export fn entry() usize { |
| 13 | 13 | |
| 14 | 14 | // error |
| 15 | 15 | // |
| 16 | // :1:11: error: struct 'tmp.A' depends on itself | |
| 16 | // error: dependency loop with length 3 | |
| 17 | // :2:8: note: type 'tmp.A' depends on type 'tmp.B' for field declared here | |
| 18 | // :5:8: note: type 'tmp.B' depends on type 'tmp.C' for field declared here | |
| 19 | // :8:8: note: type 'tmp.C' depends on type 'tmp.A' for field declared here | |
| 20 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/initialize_empty_union.zig created+81| ... | ... | @@ -0,0 +1,81 @@ |
| 1 | const EnumInferred = enum {}; | |
| 2 | const EnumExplicit = enum(u8) {}; | |
| 3 | const EnumNonexhaustive = enum(u8) { _ }; | |
| 4 | ||
| 5 | const U0 = union {}; | |
| 6 | const U1 = union(enum) {}; | |
| 7 | const U2 = union(enum(u8)) {}; | |
| 8 | const U3 = union(EnumInferred) {}; | |
| 9 | const U4 = union(EnumExplicit) {}; | |
| 10 | const U5 = union(EnumNonexhaustive) {}; | |
| 11 | ||
| 12 | export fn init0() void { | |
| 13 | _ = @as(U0, undefined); | |
| 14 | } | |
| 15 | export fn init1() void { | |
| 16 | _ = @as(U1, undefined); | |
| 17 | } | |
| 18 | export fn init2() void { | |
| 19 | _ = @as(U2, undefined); | |
| 20 | } | |
| 21 | export fn init3() void { | |
| 22 | _ = @as(U3, undefined); | |
| 23 | } | |
| 24 | export fn init4() void { | |
| 25 | _ = @as(U4, undefined); | |
| 26 | } | |
| 27 | export fn init5() void { | |
| 28 | _ = @as(U5, undefined); | |
| 29 | } | |
| 30 | ||
| 31 | export fn deref0(ptr: *const U0) void { | |
| 32 | _ = ptr.*; | |
| 33 | } | |
| 34 | export fn deref1(ptr: *const U1) void { | |
| 35 | _ = ptr.*; | |
| 36 | } | |
| 37 | export fn deref2(ptr: *const U2) void { | |
| 38 | _ = ptr.*; | |
| 39 | } | |
| 40 | export fn deref3(ptr: *const U3) void { | |
| 41 | _ = ptr.*; | |
| 42 | } | |
| 43 | export fn deref4(ptr: *const U4) void { | |
| 44 | _ = ptr.*; | |
| 45 | } | |
| 46 | export fn deref5(ptr: *const U5) void { | |
| 47 | _ = ptr.*; | |
| 48 | } | |
| 49 | ||
| 50 | // error | |
| 51 | // | |
| 52 | // :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)' | |
| 53 | // :13:17: note: cannot coerce to uninstantiable type 'tmp.U0' | |
| 54 | // :5:12: note: union declared here | |
| 55 | // :16:17: error: expected type 'tmp.U1', found '@TypeOf(undefined)' | |
| 56 | // :16:17: note: cannot coerce to uninstantiable type 'tmp.U1' | |
| 57 | // :6:12: note: union declared here | |
| 58 | // :19:17: error: expected type 'tmp.U2', found '@TypeOf(undefined)' | |
| 59 | // :19:17: note: cannot coerce to uninstantiable type 'tmp.U2' | |
| 60 | // :7:12: note: union declared here | |
| 61 | // :22:17: error: expected type 'tmp.U3', found '@TypeOf(undefined)' | |
| 62 | // :22:17: note: cannot coerce to uninstantiable type 'tmp.U3' | |
| 63 | // :8:12: note: union declared here | |
| 64 | // :25:17: error: expected type 'tmp.U4', found '@TypeOf(undefined)' | |
| 65 | // :25:17: note: cannot coerce to uninstantiable type 'tmp.U4' | |
| 66 | // :9:12: note: union declared here | |
| 67 | // :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)' | |
| 68 | // :28:17: note: cannot coerce to uninstantiable type 'tmp.U5' | |
| 69 | // :10:12: note: union declared here | |
| 70 | // :32:12: error: cannot load uninstantiable type 'tmp.U0' | |
| 71 | // :5:12: note: union declared here | |
| 72 | // :35:12: error: cannot load uninstantiable type 'tmp.U1' | |
| 73 | // :6:12: note: union declared here | |
| 74 | // :38:12: error: cannot load uninstantiable type 'tmp.U2' | |
| 75 | // :7:12: note: union declared here | |
| 76 | // :41:12: error: cannot load uninstantiable type 'tmp.U3' | |
| 77 | // :8:12: note: union declared here | |
| 78 | // :44:12: error: cannot load uninstantiable type 'tmp.U4' | |
| 79 | // :9:12: note: union declared here | |
| 80 | // :47:12: error: cannot load uninstantiable type 'tmp.U5' | |
| 81 | // :10:12: note: union declared here |
test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig+1-1| ... | ... | @@ -10,4 +10,4 @@ export fn entry() usize { |
| 10 | 10 | |
| 11 | 11 | // error |
| 12 | 12 | // |
| 13 | // :1:13: error: struct 'tmp.Foo' depends on itself | |
| 13 | // :2:8: error: type 'tmp.Foo' depends on itself for field declared here |
test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig+1-1| ... | ... | @@ -10,4 +10,4 @@ export fn entry() usize { |
| 10 | 10 | |
| 11 | 11 | // error |
| 12 | 12 | // |
| 13 | // :1:13: error: union 'tmp.Foo' depends on itself | |
| 13 | // :2:8: error: type 'tmp.Foo' depends on itself for field declared here |
test/cases/compile_errors/invalid_dependency_on_struct_size.zig+12-10| ... | ... | @@ -1,16 +1,18 @@ |
| 1 | comptime { | |
| 2 | const S = struct { | |
| 3 | const Foo = struct { | |
| 4 | y: Bar, | |
| 5 | }; | |
| 6 | const Bar = struct { | |
| 7 | y: if (@sizeOf(Foo) == 0) u64 else void, | |
| 8 | }; | |
| 1 | const S = struct { | |
| 2 | const Foo = struct { | |
| 3 | y: Bar, | |
| 9 | 4 | }; |
| 10 | ||
| 5 | const Bar = struct { | |
| 6 | y: if (@sizeOf(Foo) == 0) u64 else void, | |
| 7 | }; | |
| 8 | }; | |
| 9 | comptime { | |
| 11 | 10 | _ = @sizeOf(S.Foo) + 1; |
| 12 | 11 | } |
| 13 | 12 | |
| 14 | 13 | // error |
| 15 | 14 | // |
| 16 | // :6:21: error: struct layout depends on it having runtime bits | |
| 15 | // error: dependency loop with length 2 | |
| 16 | // :3:12: note: type 'tmp.S.Foo' depends on type 'tmp.S.Bar' for field declared here | |
| 17 | // :6:24: note: type 'tmp.S.Bar' depends on type 'tmp.S.Foo' for size query here | |
| 18 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig+2-2| ... | ... | @@ -2,10 +2,10 @@ const stroo = extern struct { |
| 2 | 2 | moo: ?[*c]u8, |
| 3 | 3 | }; |
| 4 | 4 | export fn testf(fluff: *stroo) void { |
| 5 | _ = fluff; | |
| 5 | _ = fluff.*; | |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | 8 | // error |
| 9 | 9 | // |
| 10 | 10 | // :2:10: error: extern structs cannot contain fields of type '?[*c]u8' |
| 11 | // :2:10: note: only pointer like optionals are extern compatible | |
| 11 | // :2:10: note: non-pointer optionals have no guaranteed in-memory representation |
test/cases/compile_errors/invalid_pointer_arithmetic.zig+1-7| ... | ... | @@ -26,11 +26,6 @@ comptime { |
| 26 | 26 | _ = x - y; |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | comptime { | |
| 30 | const x: [*]u0 = @ptrFromInt(1); | |
| 31 | _ = x + 1; | |
| 32 | } | |
| 33 | ||
| 34 | 29 | comptime { |
| 35 | 30 | const x: *u0 = @ptrFromInt(1); |
| 36 | 31 | const y: *u0 = @ptrFromInt(2); |
| ... | ... | @@ -46,5 +41,4 @@ comptime { |
| 46 | 41 | // :12:11: error: invalid operands to binary expression: 'pointer' and 'pointer' |
| 47 | 42 | // :20:11: error: incompatible pointer arithmetic operands '[*]u8' and '[*]u16' |
| 48 | 43 | // :26:11: error: incompatible pointer arithmetic operands '*u8' and '*u16' |
| 49 | // :31:11: error: pointer arithmetic requires element type 'u0' to have runtime bits | |
| 50 | // :37:11: error: pointer arithmetic requires element type 'u0' to have runtime bits | |
| 44 | // :32:11: error: pointer subtraction requires element type 'u0' to have runtime bits |
test/cases/compile_errors/invalid_type_in_builtin_extern.zig+10-4| ... | ... | @@ -1,16 +1,22 @@ |
| 1 | 1 | const x = @extern(*comptime_int, .{ .name = "foo" }); |
| 2 | 2 | const y = @extern(*fn (u8) u8, .{ .name = "bar" }); |
| 3 | pub export fn entry() void { | |
| 3 | const z = @extern(*fn (u8) callconv(.c) u8, .{ .name = "bar" }); | |
| 4 | comptime { | |
| 4 | 5 | _ = x; |
| 5 | 6 | } |
| 6 | pub export fn entry2() void { | |
| 7 | comptime { | |
| 7 | 8 | _ = y; |
| 8 | 9 | } |
| 10 | comptime { | |
| 11 | _ = z; | |
| 12 | } | |
| 9 | 13 | |
| 10 | 14 | // error |
| 11 | 15 | // |
| 12 | 16 | // :1:19: error: extern symbol cannot have type '*comptime_int' |
| 13 | // :1:19: note: pointer to comptime-only type 'comptime_int' | |
| 17 | // :1:19: note: pointer element type 'comptime_int' is not extern compatible | |
| 14 | 18 | // :2:19: error: extern symbol cannot have type '*fn (u8) u8' |
| 15 | // :2:19: note: pointer to extern function must be 'const' | |
| 19 | // :2:19: note: pointer element type 'fn (u8) u8' is not extern compatible | |
| 16 | 20 | // :2:19: note: extern function must specify calling convention |
| 21 | // :3:19: error: extern symbol cannot have type '*fn (u8) callconv(.c) u8' | |
| 22 | // :3:19: note: pointer to extern function must be 'const' |
test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig+18-23| ... | ... | @@ -1,49 +1,44 @@ |
| 1 | export fn entry1() void { | |
| 2 | var m2 = &2; | |
| 3 | _ = &m2; | |
| 4 | } | |
| 5 | export fn entry2() void { | |
| 1 | export fn entry0() void { | |
| 6 | 2 | var a = undefined; |
| 7 | 3 | _ = &a; |
| 8 | 4 | } |
| 9 | export fn entry3() void { | |
| 5 | export fn entry1() void { | |
| 10 | 6 | var b = 1; |
| 11 | 7 | _ = &b; |
| 12 | 8 | } |
| 13 | export fn entry4() void { | |
| 9 | export fn entry2() void { | |
| 14 | 10 | var c = 1.0; |
| 15 | 11 | _ = &c; |
| 16 | 12 | } |
| 17 | export fn entry5() void { | |
| 13 | export fn entry3() void { | |
| 18 | 14 | var d = null; |
| 19 | 15 | _ = &d; |
| 20 | 16 | } |
| 21 | export fn entry6(opaque_: *Opaque) void { | |
| 17 | export fn entry4(opaque_: *Opaque) void { | |
| 22 | 18 | var e = opaque_.*; |
| 23 | 19 | _ = &e; |
| 24 | 20 | } |
| 25 | export fn entry7() void { | |
| 21 | export fn entry5() void { | |
| 26 | 22 | var f = i32; |
| 27 | 23 | _ = &f; |
| 28 | 24 | } |
| 29 | 25 | const Opaque = opaque {}; |
| 30 | export fn entry8() void { | |
| 26 | export fn entry6() void { | |
| 31 | 27 | var e: Opaque = undefined; |
| 32 | 28 | _ = &e; |
| 33 | 29 | } |
| 34 | 30 | |
| 35 | 31 | // error |
| 36 | 32 | // |
| 37 | // :2:9: error: variable of type '*const comptime_int' must be const or comptime | |
| 38 | // :6:9: error: variable of type '@TypeOf(undefined)' must be const or comptime | |
| 39 | // :10:9: error: variable of type 'comptime_int' must be const or comptime | |
| 33 | // :2:9: error: variable of type '@TypeOf(undefined)' must be const or comptime | |
| 34 | // :6:9: error: variable of type 'comptime_int' must be const or comptime | |
| 35 | // :6:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type | |
| 36 | // :10:9: error: variable of type 'comptime_float' must be const or comptime | |
| 40 | 37 | // :10:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type |
| 41 | // :14:9: error: variable of type 'comptime_float' must be const or comptime | |
| 42 | // :14:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type | |
| 43 | // :18:9: error: variable of type '@TypeOf(null)' must be const or comptime | |
| 44 | // :22:20: error: cannot load opaque type 'tmp.Opaque' | |
| 45 | // :29:16: note: opaque declared here | |
| 46 | // :26:9: error: variable of type 'type' must be const or comptime | |
| 47 | // :26:9: note: types are not available at runtime | |
| 48 | // :31:12: error: non-extern variable with opaque type 'tmp.Opaque' | |
| 49 | // :29:16: note: opaque declared here | |
| 38 | // :14:9: error: variable of type '@TypeOf(null)' must be const or comptime | |
| 39 | // :18:20: error: cannot load opaque type 'tmp.Opaque' | |
| 40 | // :25:16: note: opaque declared here | |
| 41 | // :22:9: error: variable of type 'type' must be const or comptime | |
| 42 | // :22:9: note: types are not available at runtime | |
| 43 | // :27:12: error: non-extern variable with opaque type 'tmp.Opaque' | |
| 44 | // :25:16: note: opaque declared here |
test/cases/compile_errors/non-exhaustive_enum_marker_assigned_a_value.zig-11| ... | ... | @@ -3,18 +3,7 @@ const A = enum { |
| 3 | 3 | b, |
| 4 | 4 | _ = 1, |
| 5 | 5 | }; |
| 6 | const B = enum { | |
| 7 | a, | |
| 8 | b, | |
| 9 | _, | |
| 10 | }; | |
| 11 | comptime { | |
| 12 | _ = A; | |
| 13 | _ = B; | |
| 14 | } | |
| 15 | 6 | |
| 16 | 7 | // error |
| 17 | 8 | // |
| 18 | 9 | // :4:9: error: '_' is used to mark an enum as non-exhaustive and cannot be assigned a value |
| 19 | // :6:11: error: non-exhaustive enum missing integer tag type | |
| 20 | // :9:5: note: marked non-exhaustive here |
test/cases/compile_errors/non-exhaustive_enum_missing_tag_type.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | const E = enum { | |
| 2 | a, | |
| 3 | b, | |
| 4 | _, | |
| 5 | }; | |
| 6 | ||
| 7 | // error | |
| 8 | // | |
| 9 | // :1:11: error: non-exhaustive enum missing integer tag type | |
| 10 | // :4:5: note: marked non-exhaustive here |
test/cases/compile_errors/non-exhaustive_enum_specifies_every_value.zig+1-1| ... | ... | @@ -4,7 +4,7 @@ const C = enum(u1) { |
| 4 | 4 | _, |
| 5 | 5 | }; |
| 6 | 6 | pub export fn entry() void { |
| 7 | _ = C; | |
| 7 | _ = C.a; | |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | 10 | // error |
test/cases/compile_errors/non-inline_for_loop_on_a_type_that_requires_comptime.zig+1-1| ... | ... | @@ -11,6 +11,6 @@ export fn entry() void { |
| 11 | 11 | |
| 12 | 12 | // error |
| 13 | 13 | // |
| 14 | // :7:10: error: values of type '[2]tmp.Foo' must be comptime-known, but index value is runtime-known | |
| 14 | // :7:10: error: values of type 'tmp.Foo' must be comptime-known, but index value is runtime-known | |
| 15 | 15 | // :3:8: note: struct requires comptime because of this field |
| 16 | 16 | // :3:8: note: types are not available at runtime |
test/cases/compile_errors/non_constant_expression_in_array_size.zig+1-1| ... | ... | @@ -14,4 +14,4 @@ export fn entry() usize { |
| 14 | 14 | // |
| 15 | 15 | // :6:12: error: unable to resolve comptime value |
| 16 | 16 | // :2:12: note: called at comptime from here |
| 17 | // :1:13: note: types must be comptime-known | |
| 17 | // :2:8: note: struct field types must be comptime-known |
test/cases/compile_errors/noreturn_struct_field.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | const S = struct { | |
| 2 | s: noreturn, | |
| 3 | }; | |
| 4 | comptime { | |
| 5 | _ = @typeInfo(S); | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // | |
| 10 | // :2:8: error: struct fields cannot be 'noreturn' |
test/cases/compile_errors/old_fn_ptr_in_extern_context.zig-6| ... | ... | @@ -4,15 +4,9 @@ const S = extern struct { |
| 4 | 4 | comptime { |
| 5 | 5 | _ = @sizeOf(S) == 1; |
| 6 | 6 | } |
| 7 | comptime { | |
| 8 | _ = [*c][4]fn () callconv(.c) void; | |
| 9 | } | |
| 10 | 7 | |
| 11 | 8 | // error |
| 12 | 9 | // |
| 13 | 10 | // :2:8: error: extern structs cannot contain fields of type 'fn () callconv(.c) void' |
| 14 | 11 | // :2:8: note: type has no guaranteed in-memory representation |
| 15 | 12 | // :2:8: note: use '*const ' to make a function pointer type |
| 16 | // :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn () callconv(.c) void' | |
| 17 | // :8:13: note: type has no guaranteed in-memory representation | |
| 18 | // :8:13: note: use '*const ' to make a function pointer type |
test/cases/compile_errors/overflow_in_enum_value_allocation.zig+1-1| ... | ... | @@ -9,4 +9,4 @@ pub export fn entry() void { |
| 9 | 9 | |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | // :3:5: error: enumeration value '256' too large for type 'u8' | |
| 12 | // :3:5: error: enum tag value '256' too large for type 'u8' |
test/cases/compile_errors/packed_struct_backing_int_wrong.zig+6-2| ... | ... | @@ -44,8 +44,12 @@ export fn entry7() void { |
| 44 | 44 | |
| 45 | 45 | // error |
| 46 | 46 | // |
| 47 | // :2:31: error: backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 29 | |
| 48 | // :9:31: error: backing integer type 'i31' has bit size 31 but the struct fields have a total bit size of 32 | |
| 47 | // :2:24: error: backing integer bit width does not match total bit width of fields | |
| 48 | // :2:31: note: backing integer 'u32' has bit width '32' | |
| 49 | // :2:24: note: struct fields have total bit width '29' | |
| 50 | // :9:24: error: backing integer bit width does not match total bit width of fields | |
| 51 | // :9:31: note: backing integer 'i31' has bit width '31' | |
| 52 | // :9:24: note: struct fields have total bit width '32' | |
| 49 | 53 | // :17:31: error: expected backing integer type, found 'void' |
| 50 | 54 | // :23:31: error: expected backing integer type, found 'void' |
| 51 | 55 | // :27:31: error: expected backing integer type, found 'noreturn' |
test/cases/compile_errors/packed_struct_uses_own_size.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | const S = packed struct { | |
| 2 | x: @Int(.unsigned, @sizeOf(S)), | |
| 3 | }; | |
| 4 | comptime { | |
| 5 | _ = @as(S, undefined); | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // | |
| 10 | // :2:32: error: type 'tmp.S' depends on itself for size query here |
test/cases/compile_errors/packed_struct_uses_own_typeinfo.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | const S = packed struct(u16) { | |
| 2 | a: bool, | |
| 3 | b: bool, | |
| 4 | _padding: @Int(.unsigned, 17 - @typeInfo(S).Struct.fields.len) = 0, | |
| 5 | }; | |
| 6 | ||
| 7 | comptime { | |
| 8 | _ = @as(S, .{ .a = true, .b = true }); | |
| 9 | } | |
| 10 | ||
| 11 | // error | |
| 12 | // | |
| 13 | // :4:36: error: type 'tmp.S' depends on itself for type information query here |
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig+23-12| ... | ... | @@ -76,30 +76,41 @@ export fn entry14() void { |
| 76 | 76 | x: E, |
| 77 | 77 | }); |
| 78 | 78 | } |
| 79 | export fn entry15() void { | |
| 80 | _ = @sizeOf(packed struct { | |
| 81 | x: *const u32, | |
| 82 | }); | |
| 83 | } | |
| 79 | 84 | |
| 80 | 85 | // error |
| 81 | 86 | // |
| 82 | 87 | // :3:12: error: packed structs cannot contain fields of type 'anyerror' |
| 83 | // :3:12: note: type has no guaranteed in-memory representation | |
| 88 | // :3:12: note: type does not have a bit-packed representation | |
| 84 | 89 | // :8:12: error: packed structs cannot contain fields of type '[2]u24' |
| 85 | // :8:12: note: type has no guaranteed in-memory representation | |
| 90 | // :8:12: note: type does not have a bit-packed representation | |
| 86 | 91 | // :13:20: error: packed structs cannot contain fields of type 'anyerror!u32' |
| 87 | // :13:20: note: type has no guaranteed in-memory representation | |
| 92 | // :13:20: note: type does not have a bit-packed representation | |
| 88 | 93 | // :18:12: error: packed structs cannot contain fields of type 'tmp.S' |
| 89 | // :18:12: note: only packed structs layout are allowed in packed types | |
| 94 | // :18:12: note: non-packed structs do not have a bit-packed representation | |
| 90 | 95 | // :56:11: note: struct declared here |
| 91 | 96 | // :23:12: error: packed structs cannot contain fields of type 'tmp.U' |
| 92 | // :23:12: note: only packed unions layout are allowed in packed types | |
| 97 | // :23:12: note: non-packed unions do not have a bit-packed representation | |
| 93 | 98 | // :59:18: note: union declared here |
| 94 | 99 | // :28:12: error: packed structs cannot contain fields of type '?anyerror' |
| 95 | // :28:12: note: type has no guaranteed in-memory representation | |
| 100 | // :28:12: note: type does not have a bit-packed representation | |
| 96 | 101 | // :38:12: error: packed structs cannot contain fields of type 'fn () void' |
| 97 | // :38:12: note: type has no guaranteed in-memory representation | |
| 98 | // :38:12: note: use '*const ' to make a function pointer type | |
| 102 | // :38:12: note: type does not have a bit-packed representation | |
| 103 | // :43:12: error: packed structs cannot contain fields of type '*const fn () void' | |
| 104 | // :43:12: note: pointers cannot be directly bitpacked | |
| 105 | // :43:12: note: consider using 'usize' and '@intFromPtr' | |
| 99 | 106 | // :65:31: error: packed structs cannot contain fields of type '[]u8' |
| 100 | // :65:31: note: slices have no guaranteed in-memory representation | |
| 107 | // :65:31: note: slices do not have a bit-packed representation | |
| 101 | 108 | // :70:12: error: packed structs cannot contain fields of type '*type' |
| 102 | // :70:12: note: comptime-only pointer has no guaranteed in-memory representation | |
| 103 | // :70:12: note: types are not available at runtime | |
| 109 | // :70:12: note: pointers cannot be directly bitpacked | |
| 110 | // :70:12: note: consider using 'usize' and '@intFromPtr' | |
| 104 | 111 | // :76:12: error: packed structs cannot contain fields of type 'tmp.entry14.E' |
| 105 | // :74:15: note: enum declared here | |
| 112 | // :74:15: note: integer tag type of enum is inferred | |
| 113 | // :74:15: note: consider explicitly specifying the integer tag type | |
| 114 | // :81:12: error: packed structs cannot contain fields of type '*const u32' | |
| 115 | // :81:12: note: pointers cannot be directly bitpacked | |
| 116 | // :81:12: note: consider using 'usize' and '@intFromPtr' |
test/cases/compile_errors/packed_union_fields_mismatch.zig+6-4| ... | ... | @@ -1,12 +1,14 @@ |
| 1 | 1 | export fn entry1() void { |
| 2 | _ = packed union { | |
| 2 | const U = packed union { | |
| 3 | 3 | a: u1, |
| 4 | 4 | b: u2, |
| 5 | 5 | }; |
| 6 | _ = @as(U, undefined); | |
| 6 | 7 | } |
| 7 | 8 | |
| 8 | 9 | // error |
| 9 | 10 | // |
| 10 | // :2:16: error: packed union has fields with mismatching bit sizes | |
| 11 | // :3:12: note: 1 bits here | |
| 12 | // :4:12: note: 2 bits here | |
| 11 | // :4:12: error: field bit width does not match earlier field | |
| 12 | // :4:12: note: field type 'u2' has bit width '2' | |
| 13 | // :3:12: note: other field type 'u1' has bit width '1' | |
| 14 | // :4:12: note: all fields in a packed union must have the same bit width |
test/cases/compile_errors/packed_union_given_enum_tag_type.zig deleted-18| ... | ... | @@ -1,18 +0,0 @@ |
| 1 | const Letter = enum { | |
| 2 | A, | |
| 3 | B, | |
| 4 | C, | |
| 5 | }; | |
| 6 | const Payload = packed union(Letter) { | |
| 7 | A: i32, | |
| 8 | B: f64, | |
| 9 | C: bool, | |
| 10 | }; | |
| 11 | export fn entry() void { | |
| 12 | const a: Payload = .{ .A = 1234 }; | |
| 13 | _ = a; | |
| 14 | } | |
| 15 | ||
| 16 | // error | |
| 17 | // | |
| 18 | // :6:30: error: packed union does not support enum tag type |
test/cases/compile_errors/packed_union_with_automatic_layout_field.zig deleted-18| ... | ... | @@ -1,18 +0,0 @@ |
| 1 | const Foo = struct { | |
| 2 | a: u32, | |
| 3 | b: f32, | |
| 4 | }; | |
| 5 | const Payload = packed union { | |
| 6 | A: Foo, | |
| 7 | B: bool, | |
| 8 | }; | |
| 9 | export fn entry() void { | |
| 10 | const a: Payload = .{ .B = true }; | |
| 11 | _ = a; | |
| 12 | } | |
| 13 | ||
| 14 | // error | |
| 15 | // | |
| 16 | // :6:8: error: packed unions cannot contain fields of type 'tmp.Foo' | |
| 17 | // :6:8: note: only packed structs layout are allowed in packed types | |
| 18 | // :1:13: note: struct declared here |
test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const S = struct { a: u32 }; | |
| 2 | export fn entry0() void { | |
| 3 | _ = @sizeOf(packed union { | |
| 4 | foo: S, | |
| 5 | bar: bool, | |
| 6 | }); | |
| 7 | } | |
| 8 | export fn entry1() void { | |
| 9 | _ = @sizeOf(packed union { | |
| 10 | x: *const u32, | |
| 11 | }); | |
| 12 | } | |
| 13 | ||
| 14 | // error | |
| 15 | // | |
| 16 | // :4:14: error: packed unions cannot contain fields of type 'tmp.S' | |
| 17 | // :4:14: note: non-packed structs do not have a bit-packed representation | |
| 18 | // :1:11: note: struct declared here | |
| 19 | // :10:12: error: packed unions cannot contain fields of type '*const u32' | |
| 20 | // :10:12: note: pointers cannot be directly bitpacked | |
| 21 | // :10:12: note: consider using 'usize' and '@intFromPtr' |
test/cases/compile_errors/pointer_in_bitpack.zig created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | const S = packed struct { | |
| 2 | ptr: *u32, | |
| 3 | }; | |
| 4 | export fn foo() void { | |
| 5 | _ = @as(S, undefined); | |
| 6 | } | |
| 7 | ||
| 8 | const U = packed union { | |
| 9 | ptr: *u32, | |
| 10 | }; | |
| 11 | export fn bar() void { | |
| 12 | _ = @as(U, undefined); | |
| 13 | } | |
| 14 | ||
| 15 | // error | |
| 16 | // | |
| 17 | // :2:10: error: packed structs cannot contain fields of type '*u32' | |
| 18 | // :2:10: note: pointers cannot be directly bitpacked | |
| 19 | // :2:10: note: consider using 'usize' and '@intFromPtr' | |
| 20 | // :9:10: error: packed unions cannot contain fields of type '*u32' | |
| 21 | // :9:10: note: pointers cannot be directly bitpacked | |
| 22 | // :9:10: note: consider using 'usize' and '@intFromPtr' |
test/cases/compile_errors/reify_enum_with_duplicate_field.zig+4-3| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | 1 | export fn entry() void { |
| 2 | _ = @Enum(u32, .nonexhaustive, &.{ "A", "A" }, &.{ 0, 1 }); | |
| 2 | const E = @Enum(u32, .nonexhaustive, &.{ "A", "A" }, &.{ 0, 1 }); | |
| 3 | _ = @as(E, undefined); | |
| 3 | 4 | } |
| 4 | 5 | |
| 5 | 6 | // error |
| 6 | 7 | // |
| 7 | // :2:36: error: duplicate enum field 'A' | |
| 8 | // :2:36: note: other field here | |
| 8 | // :2:42: error: duplicate enum field 'A' at index '1' | |
| 9 | // :2:42: note: previous field at index '0' |
test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig+4-3| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | 1 | export fn entry() void { |
| 2 | _ = @Enum(u32, .nonexhaustive, &.{ "A", "B" }, &.{ 10, 10 }); | |
| 2 | const E = @Enum(u32, .nonexhaustive, &.{ "a", "b" }, &.{ 10, 10 }); | |
| 3 | _ = E.a; | |
| 3 | 4 | } |
| 4 | 5 | |
| 5 | 6 | // error |
| 6 | 7 | // |
| 7 | // :2:52: error: enum tag value 10 already taken | |
| 8 | // :2:52: note: other enum tag value here | |
| 8 | // :2:58: error: enum tag value '10' for field 'b' already taken | |
| 9 | // :2:58: note: previous occurrence in field 'a' |
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig+1-1| ... | ... | @@ -5,4 +5,4 @@ export fn entry() void { |
| 5 | 5 | |
| 6 | 6 | // error |
| 7 | 7 | // |
| 8 | // :1:19: error: tag type must be an integer type | |
| 8 | // :1:19: error: expected integer tag type, found 'bool' |
test/cases/compile_errors/reify_type_for_tagged_packed_union.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 }); | |
| 2 | const Packed = @Union(.@"packed", Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{})); | |
| 3 | ||
| 4 | export fn entry() void { | |
| 5 | const tagged: Packed = .{ .signed = -1 }; | |
| 6 | _ = tagged; | |
| 7 | } | |
| 8 | ||
| 9 | // error | |
| 10 | // | |
| 11 | // :2:35: error: packed union does not support enum tag type |
test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig+2-3| ... | ... | @@ -7,6 +7,5 @@ export fn entry() void { |
| 7 | 7 | |
| 8 | 8 | // error |
| 9 | 9 | // |
| 10 | // :2:35: error: 1 enum fields missing in union | |
| 11 | // :1:13: note: field 'arst' missing, declared here | |
| 12 | // :1:13: note: enum declared here | |
| 10 | // :2:16: error: enum field 'arst' missing from union | |
| 11 | // :1:36: note: enum field here |
test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig+2-4| ... | ... | @@ -7,7 +7,5 @@ export fn entry() void { |
| 7 | 7 | |
| 8 | 8 | // error |
| 9 | 9 | // |
| 10 | // :2:35: error: 2 enum fields missing in union | |
| 11 | // :1:13: note: field 'signed' missing, declared here | |
| 12 | // :1:13: note: field 'unsigned' missing, declared here | |
| 13 | // :1:13: note: enum declared here | |
| 10 | // :2:16: error: enum field 'signed' missing from union | |
| 11 | // :1:36: note: enum field here |
test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig+5-3| ... | ... | @@ -1,9 +1,11 @@ |
| 1 | const Untagged = @Union(.auto, null, &.{"foo"}, &.{opaque {}}, &.{.{}}); | |
| 1 | const Opaque = opaque {}; | |
| 2 | const Untagged = @Union(.auto, null, &.{"foo"}, &.{Opaque}, &.{.{}}); | |
| 2 | 3 | export fn entry() usize { |
| 3 | 4 | return @sizeOf(Untagged); |
| 4 | 5 | } |
| 5 | 6 | |
| 6 | 7 | // error |
| 7 | 8 | // |
| 8 | // :1:49: error: opaque types have unknown size and therefore cannot be directly embedded in unions | |
| 9 | // :1:52: note: opaque declared here | |
| 9 | // :2:49: error: cannot directly embed opaque type 'tmp.Opaque' in union | |
| 10 | // :2:49: note: opaque types have unknown size | |
| 11 | // :1:16: note: opaque declared here |
test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig+6-2| ... | ... | @@ -2,7 +2,11 @@ comptime { |
| 2 | 2 | _ = @Union(.auto, null, &.{"foo"}, &.{usize}, &.{.{ .@"align" = 3 }}); |
| 3 | 3 | } |
| 4 | 4 | comptime { |
| 5 | _ = @Struct(.auto, null, &.{"a"}, &.{u32}, &.{.{ .@"comptime" = true, .@"align" = 5 }}); | |
| 5 | _ = @Struct(.auto, null, &.{"a"}, &.{u32}, &.{.{ | |
| 6 | .@"comptime" = true, | |
| 7 | .@"align" = 5, | |
| 8 | .default_value_ptr = &@as(u32, 0), | |
| 9 | }}); | |
| 6 | 10 | } |
| 7 | 11 | comptime { |
| 8 | 12 | _ = @Pointer(.many, .{ .@"align" = 7 }, u8, null); |
| ... | ... | @@ -12,4 +16,4 @@ comptime { |
| 12 | 16 | // |
| 13 | 17 | // :2:51: error: alignment value '3' is not a power of two |
| 14 | 18 | // :5:48: error: alignment value '5' is not a power of two |
| 15 | // :8:26: error: alignment value '7' is not a power of two | |
| 19 | // :12:26: error: alignment value '7' is not a power of two |
test/cases/compile_errors/resolve_inferred_error_set_of_generic_fn.zig+1-2| ... | ... | @@ -12,5 +12,4 @@ export fn entry() void { |
| 12 | 12 | |
| 13 | 13 | // error |
| 14 | 14 | // |
| 15 | // :10:15: error: unable to resolve inferred error set of generic function | |
| 16 | // :1:1: note: generic function declared here | |
| 15 | // :1:1: error: cannot resolve inferred error set of generic function type 'fn (anytype) @typeInfo(@typeInfo(@TypeOf(tmp.foo)).@"fn".return_type.?).error_union.error_set!void' |
test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig+2-3| ... | ... | @@ -10,6 +10,5 @@ pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void { |
| 10 | 10 | |
| 11 | 11 | // error |
| 12 | 12 | // |
| 13 | // :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known | |
| 14 | // :2:10: note: struct requires comptime because of this field | |
| 15 | // :2:10: note: use '*const fn (c_int) callconv(.c) void' for a function pointer type | |
| 13 | // :6:19: error: cannot load comptime-only type '?fn (c_int) callconv(.c) void' | |
| 14 | // :6:20: note: pointer of type '*?fn (c_int) callconv(.c) void' is runtime-known |
test/cases/compile_errors/runtime_index_into_comptime_only_many_ptr.zig+3-3| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | 1 | var rt: usize = 0; |
| 2 | 2 | export fn foo() void { |
| 3 | 3 | const x: [*]const type = &.{ u8, u16 }; |
| 4 | _ = &x[rt]; | |
| 4 | _ = x[rt]; | |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | 7 | // error |
| 8 | 8 | // |
| 9 | // :4:12: error: values of type '[*]const type' must be comptime-known, but index value is runtime-known | |
| 10 | // :4:11: note: types are not available at runtime | |
| 9 | // :4:11: error: values of type 'type' must be comptime-known, but index value is runtime-known | |
| 10 | // :4:10: note: types are not available at runtime |
test/cases/compile_errors/runtime_index_into_comptime_type_slice.zig+1-2| ... | ... | @@ -12,7 +12,6 @@ export fn entry() void { |
| 12 | 12 | |
| 13 | 13 | // error |
| 14 | 14 | // |
| 15 | // :9:54: error: values of type '[]const builtin.Type.StructField' must be comptime-known, but index value is runtime-known | |
| 15 | // :9:54: error: values of type 'builtin.Type.StructField' must be comptime-known, but index value is runtime-known | |
| 16 | 16 | // : note: struct requires comptime because of this field |
| 17 | 17 | // : note: types are not available at runtime |
| 18 | // : struct requires comptime because of this field |
test/cases/compile_errors/runtime_indexing_comptime_array.zig+3-3| ... | ... | @@ -24,9 +24,9 @@ pub export fn entry3() void { |
| 24 | 24 | } |
| 25 | 25 | // error |
| 26 | 26 | // |
| 27 | // :7:10: error: values of type '[2]fn () void' must be comptime-known, but index value is runtime-known | |
| 27 | // :7:10: error: values of type 'fn () void' must be comptime-known, but index value is runtime-known | |
| 28 | 28 | // :7:10: note: use '*const fn () void' for a function pointer type |
| 29 | // :15:18: error: values of type '[2]fn () void' must be comptime-known, but index value is runtime-known | |
| 29 | // :15:18: error: values of type 'fn () void' must be comptime-known, but index value is runtime-known | |
| 30 | 30 | // :15:17: note: use '*const fn () void' for a function pointer type |
| 31 | // :22:19: error: values of type '[2]fn () void' must be comptime-known, but index value is runtime-known | |
| 31 | // :22:19: error: values of type 'fn () void' must be comptime-known, but index value is runtime-known | |
| 32 | 32 | // :22:18: note: use '*const fn () void' for a function pointer type |
test/cases/compile_errors/runtime_operation_in_comptime_scope.zig+4-4| ... | ... | @@ -25,13 +25,13 @@ var rt: u32 = undefined; |
| 25 | 25 | // |
| 26 | 26 | // :19:8: error: unable to evaluate comptime expression |
| 27 | 27 | // :19:5: note: operation is runtime due to this operand |
| 28 | // :6:8: note: called at comptime from here | |
| 29 | // :5:1: note: 'comptime' keyword forces comptime evaluation | |
| 30 | // :19:8: error: unable to evaluate comptime expression | |
| 31 | // :19:5: note: operation is runtime due to this operand | |
| 28 | 32 | // :14:8: note: called at comptime from here |
| 29 | 33 | // :10:12: note: called at comptime from here |
| 30 | 34 | // :10:12: note: call to function with comptime-only return type 'type' is evaluated at comptime |
| 31 | 35 | // :13:10: note: return type declared here |
| 32 | 36 | // :10:12: note: types are not available at runtime |
| 33 | 37 | // :2:8: note: called inline here |
| 34 | // :19:8: error: unable to evaluate comptime expression | |
| 35 | // :19:5: note: operation is runtime due to this operand | |
| 36 | // :6:8: note: called at comptime from here | |
| 37 | // :5:1: note: 'comptime' keyword forces comptime evaluation |
test/cases/compile_errors/self_referential_struct_requires_comptime.zig-1| ... | ... | @@ -12,4 +12,3 @@ pub export fn entry() void { |
| 12 | 12 | // :6:12: error: variable of type 'tmp.S' must be const or comptime |
| 13 | 13 | // :2:8: note: struct requires comptime because of this field |
| 14 | 14 | // :2:8: note: use '*const fn () void' for a function pointer type |
| 15 | // :3:8: note: struct requires comptime because of this field |
test/cases/compile_errors/self_referential_union_requires_comptime.zig-1| ... | ... | @@ -12,4 +12,3 @@ pub export fn entry() void { |
| 12 | 12 | // :6:12: error: variable of type 'tmp.U' must be const or comptime |
| 13 | 13 | // :2:8: note: union requires comptime because of this field |
| 14 | 14 | // :2:8: note: use '*const fn () void' for a function pointer type |
| 15 | // :3:8: note: union requires comptime because of this field |
test/cases/compile_errors/simple_struct_loop.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const A = struct { | |
| 2 | b: B, | |
| 3 | }; | |
| 4 | const B = struct { | |
| 5 | a: A, | |
| 6 | }; | |
| 7 | comptime { | |
| 8 | _ = @as(A, undefined); | |
| 9 | } | |
| 10 | ||
| 11 | // error | |
| 12 | // | |
| 13 | // error: dependency loop with length 2 | |
| 14 | // :2:8: note: type 'tmp.A' depends on type 'tmp.B' for field declared here | |
| 15 | // :5:8: note: type 'tmp.B' depends on type 'tmp.A' for field declared here | |
| 16 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/sizeOf_bad_type.zig+26-2| ... | ... | @@ -1,7 +1,31 @@ |
| 1 | export fn entry() usize { | |
| 1 | export fn entry0() usize { | |
| 2 | 2 | return @sizeOf(@TypeOf(null)); |
| 3 | 3 | } |
| 4 | export fn entry1() usize { | |
| 5 | return @sizeOf(comptime_int); | |
| 6 | } | |
| 7 | export fn entry2() usize { | |
| 8 | return @sizeOf(noreturn); | |
| 9 | } | |
| 10 | const S3 = struct { a: u32, b: comptime_int }; | |
| 11 | export fn entry3() usize { | |
| 12 | return @sizeOf(S3); | |
| 13 | } | |
| 14 | const S4 = struct { a: u32, b: noreturn }; | |
| 15 | export fn entry4() usize { | |
| 16 | return @sizeOf(S4); | |
| 17 | } | |
| 18 | export fn entry5() usize { | |
| 19 | return @sizeOf([1]fn () void); | |
| 20 | } | |
| 4 | 21 | |
| 5 | 22 | // error |
| 6 | 23 | // |
| 7 | // :2:20: error: no size available for type '@TypeOf(null)' | |
| 24 | // :2:20: error: no size available for comptime-only type '@TypeOf(null)' | |
| 25 | // :5:20: error: no size available for comptime-only type 'comptime_int' | |
| 26 | // :8:20: error: no size available for uninstantiable type 'noreturn' | |
| 27 | // :12:20: error: no size available for comptime-only type 'tmp.S3' | |
| 28 | // :10:12: note: struct declared here | |
| 29 | // :16:20: error: no size available for uninstantiable type 'tmp.S4' | |
| 30 | // :14:12: note: struct declared here | |
| 31 | // :19:20: error: no size available for comptime-only type '[1]fn () void' |
test/cases/compile_errors/sizeof_alignof_empty_union.zig created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | const EnumInferred = enum {}; | |
| 2 | const EnumExplicit = enum(u8) {}; | |
| 3 | const EnumNonexhaustive = enum(u8) { _ }; | |
| 4 | ||
| 5 | const U0 = union {}; | |
| 6 | const U1 = union(enum) {}; | |
| 7 | const U2 = union(enum(u8)) {}; | |
| 8 | const U3 = union(EnumInferred) {}; | |
| 9 | const U4 = union(EnumExplicit) {}; | |
| 10 | const U5 = union(EnumNonexhaustive) {}; | |
| 11 | ||
| 12 | export fn size0() void { | |
| 13 | _ = @sizeOf(U0); | |
| 14 | } | |
| 15 | export fn size1() void { | |
| 16 | _ = @sizeOf(U1); | |
| 17 | } | |
| 18 | export fn size2() void { | |
| 19 | _ = @sizeOf(U2); | |
| 20 | } | |
| 21 | export fn size3() void { | |
| 22 | _ = @sizeOf(U3); | |
| 23 | } | |
| 24 | export fn size4() void { | |
| 25 | _ = @sizeOf(U4); | |
| 26 | } | |
| 27 | export fn size5() void { | |
| 28 | _ = @sizeOf(U5); | |
| 29 | } | |
| 30 | ||
| 31 | export fn align0() void { | |
| 32 | _ = @alignOf(U0); | |
| 33 | } | |
| 34 | export fn align1() void { | |
| 35 | _ = @alignOf(U1); | |
| 36 | } | |
| 37 | export fn align2() void { | |
| 38 | _ = @alignOf(U2); | |
| 39 | } | |
| 40 | export fn align3() void { | |
| 41 | _ = @alignOf(U3); | |
| 42 | } | |
| 43 | export fn align4() void { | |
| 44 | _ = @alignOf(U4); | |
| 45 | } | |
| 46 | export fn align5() void { | |
| 47 | _ = @alignOf(U5); | |
| 48 | } | |
| 49 | ||
| 50 | // error | |
| 51 | // | |
| 52 | // :13:17: error: no size available for uninstantiable type 'tmp.U0' | |
| 53 | // :5:12: note: union declared here | |
| 54 | // :16:17: error: no size available for uninstantiable type 'tmp.U1' | |
| 55 | // :6:12: note: union declared here | |
| 56 | // :19:17: error: no size available for uninstantiable type 'tmp.U2' | |
| 57 | // :7:12: note: union declared here | |
| 58 | // :22:17: error: no size available for uninstantiable type 'tmp.U3' | |
| 59 | // :8:12: note: union declared here | |
| 60 | // :25:17: error: no size available for uninstantiable type 'tmp.U4' | |
| 61 | // :9:12: note: union declared here | |
| 62 | // :28:17: error: no size available for uninstantiable type 'tmp.U5' | |
| 63 | // :10:12: note: union declared here | |
| 64 | // :32:18: error: no align available for uninstantiable type 'tmp.U0' | |
| 65 | // :5:12: note: union declared here | |
| 66 | // :35:18: error: no align available for uninstantiable type 'tmp.U1' | |
| 67 | // :6:12: note: union declared here | |
| 68 | // :38:18: error: no align available for uninstantiable type 'tmp.U2' | |
| 69 | // :7:12: note: union declared here | |
| 70 | // :41:18: error: no align available for uninstantiable type 'tmp.U3' | |
| 71 | // :8:12: note: union declared here | |
| 72 | // :44:18: error: no align available for uninstantiable type 'tmp.U4' | |
| 73 | // :9:12: note: union declared here | |
| 74 | // :47:18: error: no align available for uninstantiable type 'tmp.U5' | |
| 75 | // :10:12: note: union declared here |
test/cases/compile_errors/slice_used_as_extern_fn_param.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | extern fn Text(str: []const u8, num: i32) callconv(.c) void; |
| 2 | 2 | export fn entry() void { |
| 3 | _ = Text; | |
| 3 | Text(undefined, undefined); | |
| 4 | 4 | } |
| 5 | 5 | |
| 6 | 6 | // error |
test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig+9-9| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | 1 | const Small = enum(u2) { |
| 2 | One, | |
| 3 | Two, | |
| 4 | Three, | |
| 5 | Four, | |
| 6 | Five, | |
| 2 | one, | |
| 3 | two, | |
| 4 | three, | |
| 5 | four, | |
| 6 | five, | |
| 7 | 7 | }; |
| 8 | 8 | |
| 9 | 9 | const SmallUnion = union(enum(u2)) { |
| ... | ... | @@ -14,13 +14,13 @@ const SmallUnion = union(enum(u2)) { |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | 16 | comptime { |
| 17 | _ = Small; | |
| 17 | _ = Small.one; | |
| 18 | 18 | } |
| 19 | 19 | comptime { |
| 20 | _ = SmallUnion; | |
| 20 | _ = SmallUnion.one; | |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | // error |
| 24 | 24 | // |
| 25 | // :6:5: error: enumeration value '4' too large for type 'u2' | |
| 26 | // :13:5: error: enumeration value '4' too large for type 'u2' | |
| 25 | // :6:5: error: enum tag value '4' too large for type 'u2' | |
| 26 | // :13:5: error: enum tag value '4' too large for type 'u2' |
test/cases/compile_errors/store_comptime_only_type_to_runtime_pointer.zig+2-9| ... | ... | @@ -21,22 +21,15 @@ export fn e() void { |
| 21 | 21 | p.* = undefined; |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | export fn f() void { | |
| 25 | const p: **comptime_int = @ptrFromInt(16); // double pointer ('*comptime_int' is comptime-only) | |
| 26 | p.* = undefined; | |
| 27 | } | |
| 28 | ||
| 29 | 24 | // error |
| 30 | 25 | // |
| 31 | 26 | // :3:9: error: cannot store comptime-only type 'fn () void' at runtime |
| 32 | 27 | // :3:6: note: operation is runtime due to this pointer |
| 33 | 28 | // :7:11: error: expected type 'anyopaque', found '@TypeOf(undefined)' |
| 34 | // :7:11: note: cannot coerce to 'anyopaque' | |
| 29 | // :7:11: note: cannot coerce to uninstantiable type 'anyopaque' | |
| 35 | 30 | // :11:12: error: cannot load opaque type 'anyopaque' |
| 36 | 31 | // :16:11: error: expected type 'tmp.Opaque', found '@TypeOf(undefined)' |
| 37 | // :16:11: note: cannot coerce to 'tmp.Opaque' | |
| 32 | // :16:11: note: cannot coerce to uninstantiable type 'tmp.Opaque' | |
| 38 | 33 | // :14:16: note: opaque declared here |
| 39 | 34 | // :21:9: error: cannot store comptime-only type 'comptime_int' at runtime |
| 40 | 35 | // :21:6: note: operation is runtime due to this pointer |
| 41 | // :26:9: error: cannot store comptime-only type '*comptime_int' at runtime | |
| 42 | // :26:6: note: operation is runtime due to this pointer |
test/cases/compile_errors/struct_depends_on_itself_via_non_initial_field.zig+2-2| ... | ... | @@ -4,9 +4,9 @@ const A = struct { |
| 4 | 4 | }; |
| 5 | 5 | |
| 6 | 6 | comptime { |
| 7 | _ = A; | |
| 7 | _ = @as(A, undefined); | |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | // :1:11: error: struct 'tmp.A' depends on itself | |
| 12 | // :3:21: error: type 'tmp.A' depends on itself for size query here |
test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig+4-1| ... | ... | @@ -12,4 +12,7 @@ export fn entry() void { |
| 12 | 12 | |
| 13 | 13 | // error |
| 14 | 14 | // |
| 15 | // :1:17: error: struct 'tmp.LhsExpr' depends on itself | |
| 15 | // error: dependency loop with length 2 | |
| 16 | // :2:14: note: type 'tmp.LhsExpr' depends on type 'tmp.AstObject' for field declared here | |
| 17 | // :5:14: note: type 'tmp.AstObject' depends on type 'tmp.LhsExpr' for field declared here | |
| 18 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/struct_depends_on_pointer_alignment.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const S = struct { | |
| 2 | next: ?*align(1) S align(128), | |
| 3 | }; | |
| 4 | ||
| 5 | export fn entry() usize { | |
| 6 | return @alignOf(S); | |
| 7 | } | |
| 8 | ||
| 9 | // error | |
| 10 | // | |
| 11 | // :1:11: error: struct layout depends on being pointer aligned |
test/cases/compile_errors/struct_field_queries_hasfield_of_itself.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const Foo = packed struct { | |
| 2 | bar: (T: { | |
| 3 | _ = @hasField(Foo, "bar"); | |
| 4 | break :T void; | |
| 5 | }), | |
| 6 | }; | |
| 7 | ||
| 8 | comptime { | |
| 9 | _ = @as(Foo, undefined); | |
| 10 | } | |
| 11 | ||
| 12 | // error | |
| 13 | // | |
| 14 | // :3:23: error: type 'tmp.Foo' depends on itself for field query here |
test/cases/compile_errors/struct_uses_reified_type_which_queries_struct_alignment.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | const A = struct { b: *B }; | |
| 2 | const B = @Struct(.auto, null, &.{"x"}, &.{A}, &.{.{ .@"align" = @alignOf(A) }}); | |
| 3 | comptime { | |
| 4 | _ = @as(A, undefined); | |
| 5 | _ = @as(B, undefined); | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // | |
| 10 | // error: dependency loop with length 2 | |
| 11 | // :1:24: note: type 'tmp.A' uses value of declaration 'tmp.B' here | |
| 12 | // :2:75: note: value of declaration 'tmp.B' depends on type 'tmp.A' for alignment query here | |
| 13 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/struct_uses_sizeof_self_as_array_len.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | const S = struct { | |
| 2 | a: *[@sizeOf(S)]u8, | |
| 3 | }; | |
| 4 | comptime { | |
| 5 | _ = @as(S, undefined); | |
| 6 | } | |
| 7 | ||
| 8 | // error | |
| 9 | // | |
| 10 | // :2:18: error: type 'tmp.S' depends on itself for size query here |
test/cases/compile_errors/too_big_packed_struct.zig+1-1| ... | ... | @@ -8,4 +8,4 @@ pub export fn entry() void { |
| 8 | 8 | |
| 9 | 9 | // error |
| 10 | 10 | // |
| 11 | // :2:22: error: size of packed struct '131070' exceeds maximum bit width of 65535 | |
| 11 | // :2:22: error: packed struct bit width '131070' exceeds maximum bit width of 65535 |
test/cases/compile_errors/top_level_decl_dependency_loop.zig+6-1| ... | ... | @@ -7,4 +7,9 @@ export fn entry() void { |
| 7 | 7 | |
| 8 | 8 | // error |
| 9 | 9 | // |
| 10 | // :1:1: error: dependency loop detected | |
| 10 | // error: dependency loop with length 4 | |
| 11 | // :1:23: note: value of declaration 'tmp.a' uses type of declaration 'tmp.a' here | |
| 12 | // :1:18: note: type of declaration 'tmp.a' uses value of declaration 'tmp.b' here | |
| 13 | // :2:23: note: value of declaration 'tmp.b' uses type of declaration 'tmp.b' here | |
| 14 | // :2:18: note: type of declaration 'tmp.b' uses value of declaration 'tmp.a' here | |
| 15 | // note: eliminate any one of these dependencies to break the loop |
test/cases/compile_errors/unable_to_evaluate_comptime_expr.zig-19| ... | ... | @@ -16,22 +16,6 @@ pub export fn entry2() void { |
| 16 | 16 | _ = b; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | const Int = @typeInfo(bar).@"struct".backing_integer.?; | |
| 20 | ||
| 21 | const foo = enum(Int) { | |
| 22 | c = @bitCast(bar{ | |
| 23 | .name = "test", | |
| 24 | }), | |
| 25 | }; | |
| 26 | ||
| 27 | const bar = packed struct { | |
| 28 | name: [*:0]const u8, | |
| 29 | }; | |
| 30 | ||
| 31 | pub export fn entry3() void { | |
| 32 | _ = @field(foo, "c"); | |
| 33 | } | |
| 34 | ||
| 35 | 19 | // error |
| 36 | 20 | // |
| 37 | 21 | // :7:13: error: unable to evaluate comptime expression |
| ... | ... | @@ -40,6 +24,3 @@ pub export fn entry3() void { |
| 40 | 24 | // :13:13: error: unable to evaluate comptime expression |
| 41 | 25 | // :13:16: note: operation is runtime due to this operand |
| 42 | 26 | // :13:13: note: initializer of container-level variable must be comptime-known |
| 43 | // :22:9: error: unable to evaluate comptime expression | |
| 44 | // :22:21: note: operation is runtime due to this operand | |
| 45 | // :21:13: note: enum field values must be comptime-known |
test/cases/compile_errors/undef_arith_is_illegal.zig+1508-1508| ... | ... | @@ -192,50 +192,30 @@ const std = @import("std"); |
| 192 | 192 | // :65:17: error: use of undefined value here causes illegal behavior |
| 193 | 193 | // :65:17: error: use of undefined value here causes illegal behavior |
| 194 | 194 | // :65:17: error: use of undefined value here causes illegal behavior |
| 195 | // :65:17: note: when computing vector element at index '0' | |
| 196 | 195 | // :65:17: error: use of undefined value here causes illegal behavior |
| 197 | // :65:17: note: when computing vector element at index '0' | |
| 198 | 196 | // :65:17: error: use of undefined value here causes illegal behavior |
| 199 | // :65:17: note: when computing vector element at index '0' | |
| 200 | 197 | // :65:17: error: use of undefined value here causes illegal behavior |
| 201 | // :65:17: note: when computing vector element at index '0' | |
| 202 | 198 | // :65:17: error: use of undefined value here causes illegal behavior |
| 203 | // :65:17: note: when computing vector element at index '1' | |
| 204 | 199 | // :65:17: error: use of undefined value here causes illegal behavior |
| 205 | // :65:17: note: when computing vector element at index '1' | |
| 206 | 200 | // :65:17: error: use of undefined value here causes illegal behavior |
| 207 | // :65:17: note: when computing vector element at index '0' | |
| 208 | 201 | // :65:17: error: use of undefined value here causes illegal behavior |
| 209 | // :65:17: note: when computing vector element at index '0' | |
| 210 | 202 | // :65:17: error: use of undefined value here causes illegal behavior |
| 211 | // :65:17: note: when computing vector element at index '0' | |
| 212 | 203 | // :65:17: error: use of undefined value here causes illegal behavior |
| 213 | // :65:17: note: when computing vector element at index '0' | |
| 214 | 204 | // :65:17: error: use of undefined value here causes illegal behavior |
| 215 | 205 | // :65:17: error: use of undefined value here causes illegal behavior |
| 216 | 206 | // :65:17: error: use of undefined value here causes illegal behavior |
| 217 | // :65:17: note: when computing vector element at index '0' | |
| 218 | 207 | // :65:17: error: use of undefined value here causes illegal behavior |
| 219 | // :65:17: note: when computing vector element at index '0' | |
| 220 | 208 | // :65:17: error: use of undefined value here causes illegal behavior |
| 221 | // :65:17: note: when computing vector element at index '0' | |
| 222 | 209 | // :65:17: error: use of undefined value here causes illegal behavior |
| 223 | // :65:17: note: when computing vector element at index '0' | |
| 224 | 210 | // :65:17: error: use of undefined value here causes illegal behavior |
| 225 | // :65:17: note: when computing vector element at index '1' | |
| 226 | 211 | // :65:17: error: use of undefined value here causes illegal behavior |
| 227 | // :65:17: note: when computing vector element at index '1' | |
| 228 | 212 | // :65:17: error: use of undefined value here causes illegal behavior |
| 229 | // :65:17: note: when computing vector element at index '0' | |
| 230 | 213 | // :65:17: error: use of undefined value here causes illegal behavior |
| 231 | // :65:17: note: when computing vector element at index '0' | |
| 232 | 214 | // :65:17: error: use of undefined value here causes illegal behavior |
| 233 | 215 | // :65:17: note: when computing vector element at index '0' |
| 234 | 216 | // :65:17: error: use of undefined value here causes illegal behavior |
| 235 | 217 | // :65:17: note: when computing vector element at index '0' |
| 236 | 218 | // :65:17: error: use of undefined value here causes illegal behavior |
| 237 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 238 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 239 | 219 | // :65:17: note: when computing vector element at index '0' |
| 240 | 220 | // :65:17: error: use of undefined value here causes illegal behavior |
| 241 | 221 | // :65:17: note: when computing vector element at index '0' |
| ... | ... | @@ -244,10 +224,6 @@ const std = @import("std"); |
| 244 | 224 | // :65:17: error: use of undefined value here causes illegal behavior |
| 245 | 225 | // :65:17: note: when computing vector element at index '0' |
| 246 | 226 | // :65:17: error: use of undefined value here causes illegal behavior |
| 247 | // :65:17: note: when computing vector element at index '1' | |
| 248 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 249 | // :65:17: note: when computing vector element at index '1' | |
| 250 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 251 | 227 | // :65:17: note: when computing vector element at index '0' |
| 252 | 228 | // :65:17: error: use of undefined value here causes illegal behavior |
| 253 | 229 | // :65:17: note: when computing vector element at index '0' |
| ... | ... | @@ -256,7 +232,9 @@ const std = @import("std"); |
| 256 | 232 | // :65:17: error: use of undefined value here causes illegal behavior |
| 257 | 233 | // :65:17: note: when computing vector element at index '0' |
| 258 | 234 | // :65:17: error: use of undefined value here causes illegal behavior |
| 235 | // :65:17: note: when computing vector element at index '0' | |
| 259 | 236 | // :65:17: error: use of undefined value here causes illegal behavior |
| 237 | // :65:17: note: when computing vector element at index '0' | |
| 260 | 238 | // :65:17: error: use of undefined value here causes illegal behavior |
| 261 | 239 | // :65:17: note: when computing vector element at index '0' |
| 262 | 240 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -266,9 +244,9 @@ const std = @import("std"); |
| 266 | 244 | // :65:17: error: use of undefined value here causes illegal behavior |
| 267 | 245 | // :65:17: note: when computing vector element at index '0' |
| 268 | 246 | // :65:17: error: use of undefined value here causes illegal behavior |
| 269 | // :65:17: note: when computing vector element at index '1' | |
| 247 | // :65:17: note: when computing vector element at index '0' | |
| 270 | 248 | // :65:17: error: use of undefined value here causes illegal behavior |
| 271 | // :65:17: note: when computing vector element at index '1' | |
| 249 | // :65:17: note: when computing vector element at index '0' | |
| 272 | 250 | // :65:17: error: use of undefined value here causes illegal behavior |
| 273 | 251 | // :65:17: note: when computing vector element at index '0' |
| 274 | 252 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -278,7 +256,9 @@ const std = @import("std"); |
| 278 | 256 | // :65:17: error: use of undefined value here causes illegal behavior |
| 279 | 257 | // :65:17: note: when computing vector element at index '0' |
| 280 | 258 | // :65:17: error: use of undefined value here causes illegal behavior |
| 259 | // :65:17: note: when computing vector element at index '0' | |
| 281 | 260 | // :65:17: error: use of undefined value here causes illegal behavior |
| 261 | // :65:17: note: when computing vector element at index '0' | |
| 282 | 262 | // :65:17: error: use of undefined value here causes illegal behavior |
| 283 | 263 | // :65:17: note: when computing vector element at index '0' |
| 284 | 264 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -288,9 +268,9 @@ const std = @import("std"); |
| 288 | 268 | // :65:17: error: use of undefined value here causes illegal behavior |
| 289 | 269 | // :65:17: note: when computing vector element at index '0' |
| 290 | 270 | // :65:17: error: use of undefined value here causes illegal behavior |
| 291 | // :65:17: note: when computing vector element at index '1' | |
| 271 | // :65:17: note: when computing vector element at index '0' | |
| 292 | 272 | // :65:17: error: use of undefined value here causes illegal behavior |
| 293 | // :65:17: note: when computing vector element at index '1' | |
| 273 | // :65:17: note: when computing vector element at index '0' | |
| 294 | 274 | // :65:17: error: use of undefined value here causes illegal behavior |
| 295 | 275 | // :65:17: note: when computing vector element at index '0' |
| 296 | 276 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -300,7 +280,9 @@ const std = @import("std"); |
| 300 | 280 | // :65:17: error: use of undefined value here causes illegal behavior |
| 301 | 281 | // :65:17: note: when computing vector element at index '0' |
| 302 | 282 | // :65:17: error: use of undefined value here causes illegal behavior |
| 283 | // :65:17: note: when computing vector element at index '0' | |
| 303 | 284 | // :65:17: error: use of undefined value here causes illegal behavior |
| 285 | // :65:17: note: when computing vector element at index '0' | |
| 304 | 286 | // :65:17: error: use of undefined value here causes illegal behavior |
| 305 | 287 | // :65:17: note: when computing vector element at index '0' |
| 306 | 288 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -310,9 +292,9 @@ const std = @import("std"); |
| 310 | 292 | // :65:17: error: use of undefined value here causes illegal behavior |
| 311 | 293 | // :65:17: note: when computing vector element at index '0' |
| 312 | 294 | // :65:17: error: use of undefined value here causes illegal behavior |
| 313 | // :65:17: note: when computing vector element at index '1' | |
| 295 | // :65:17: note: when computing vector element at index '0' | |
| 314 | 296 | // :65:17: error: use of undefined value here causes illegal behavior |
| 315 | // :65:17: note: when computing vector element at index '1' | |
| 297 | // :65:17: note: when computing vector element at index '0' | |
| 316 | 298 | // :65:17: error: use of undefined value here causes illegal behavior |
| 317 | 299 | // :65:17: note: when computing vector element at index '0' |
| 318 | 300 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -322,7 +304,9 @@ const std = @import("std"); |
| 322 | 304 | // :65:17: error: use of undefined value here causes illegal behavior |
| 323 | 305 | // :65:17: note: when computing vector element at index '0' |
| 324 | 306 | // :65:17: error: use of undefined value here causes illegal behavior |
| 307 | // :65:17: note: when computing vector element at index '0' | |
| 325 | 308 | // :65:17: error: use of undefined value here causes illegal behavior |
| 309 | // :65:17: note: when computing vector element at index '0' | |
| 326 | 310 | // :65:17: error: use of undefined value here causes illegal behavior |
| 327 | 311 | // :65:17: note: when computing vector element at index '0' |
| 328 | 312 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -332,9 +316,9 @@ const std = @import("std"); |
| 332 | 316 | // :65:17: error: use of undefined value here causes illegal behavior |
| 333 | 317 | // :65:17: note: when computing vector element at index '0' |
| 334 | 318 | // :65:17: error: use of undefined value here causes illegal behavior |
| 335 | // :65:17: note: when computing vector element at index '1' | |
| 319 | // :65:17: note: when computing vector element at index '0' | |
| 336 | 320 | // :65:17: error: use of undefined value here causes illegal behavior |
| 337 | // :65:17: note: when computing vector element at index '1' | |
| 321 | // :65:17: note: when computing vector element at index '0' | |
| 338 | 322 | // :65:17: error: use of undefined value here causes illegal behavior |
| 339 | 323 | // :65:17: note: when computing vector element at index '0' |
| 340 | 324 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -344,7 +328,9 @@ const std = @import("std"); |
| 344 | 328 | // :65:17: error: use of undefined value here causes illegal behavior |
| 345 | 329 | // :65:17: note: when computing vector element at index '0' |
| 346 | 330 | // :65:17: error: use of undefined value here causes illegal behavior |
| 331 | // :65:17: note: when computing vector element at index '0' | |
| 347 | 332 | // :65:17: error: use of undefined value here causes illegal behavior |
| 333 | // :65:17: note: when computing vector element at index '0' | |
| 348 | 334 | // :65:17: error: use of undefined value here causes illegal behavior |
| 349 | 335 | // :65:17: note: when computing vector element at index '0' |
| 350 | 336 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -354,9 +340,9 @@ const std = @import("std"); |
| 354 | 340 | // :65:17: error: use of undefined value here causes illegal behavior |
| 355 | 341 | // :65:17: note: when computing vector element at index '0' |
| 356 | 342 | // :65:17: error: use of undefined value here causes illegal behavior |
| 357 | // :65:17: note: when computing vector element at index '1' | |
| 343 | // :65:17: note: when computing vector element at index '0' | |
| 358 | 344 | // :65:17: error: use of undefined value here causes illegal behavior |
| 359 | // :65:17: note: when computing vector element at index '1' | |
| 345 | // :65:17: note: when computing vector element at index '0' | |
| 360 | 346 | // :65:17: error: use of undefined value here causes illegal behavior |
| 361 | 347 | // :65:17: note: when computing vector element at index '0' |
| 362 | 348 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -366,7 +352,9 @@ const std = @import("std"); |
| 366 | 352 | // :65:17: error: use of undefined value here causes illegal behavior |
| 367 | 353 | // :65:17: note: when computing vector element at index '0' |
| 368 | 354 | // :65:17: error: use of undefined value here causes illegal behavior |
| 355 | // :65:17: note: when computing vector element at index '0' | |
| 369 | 356 | // :65:17: error: use of undefined value here causes illegal behavior |
| 357 | // :65:17: note: when computing vector element at index '0' | |
| 370 | 358 | // :65:17: error: use of undefined value here causes illegal behavior |
| 371 | 359 | // :65:17: note: when computing vector element at index '0' |
| 372 | 360 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -376,9 +364,9 @@ const std = @import("std"); |
| 376 | 364 | // :65:17: error: use of undefined value here causes illegal behavior |
| 377 | 365 | // :65:17: note: when computing vector element at index '0' |
| 378 | 366 | // :65:17: error: use of undefined value here causes illegal behavior |
| 379 | // :65:17: note: when computing vector element at index '1' | |
| 367 | // :65:17: note: when computing vector element at index '0' | |
| 380 | 368 | // :65:17: error: use of undefined value here causes illegal behavior |
| 381 | // :65:17: note: when computing vector element at index '1' | |
| 369 | // :65:17: note: when computing vector element at index '0' | |
| 382 | 370 | // :65:17: error: use of undefined value here causes illegal behavior |
| 383 | 371 | // :65:17: note: when computing vector element at index '0' |
| 384 | 372 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -388,7 +376,9 @@ const std = @import("std"); |
| 388 | 376 | // :65:17: error: use of undefined value here causes illegal behavior |
| 389 | 377 | // :65:17: note: when computing vector element at index '0' |
| 390 | 378 | // :65:17: error: use of undefined value here causes illegal behavior |
| 379 | // :65:17: note: when computing vector element at index '0' | |
| 391 | 380 | // :65:17: error: use of undefined value here causes illegal behavior |
| 381 | // :65:17: note: when computing vector element at index '0' | |
| 392 | 382 | // :65:17: error: use of undefined value here causes illegal behavior |
| 393 | 383 | // :65:17: note: when computing vector element at index '0' |
| 394 | 384 | // :65:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -402,35 +392,45 @@ const std = @import("std"); |
| 402 | 392 | // :65:17: error: use of undefined value here causes illegal behavior |
| 403 | 393 | // :65:17: note: when computing vector element at index '1' |
| 404 | 394 | // :65:17: error: use of undefined value here causes illegal behavior |
| 405 | // :65:17: note: when computing vector element at index '0' | |
| 395 | // :65:17: note: when computing vector element at index '1' | |
| 406 | 396 | // :65:17: error: use of undefined value here causes illegal behavior |
| 407 | // :65:17: note: when computing vector element at index '0' | |
| 397 | // :65:17: note: when computing vector element at index '1' | |
| 408 | 398 | // :65:17: error: use of undefined value here causes illegal behavior |
| 409 | // :65:17: note: when computing vector element at index '0' | |
| 399 | // :65:17: note: when computing vector element at index '1' | |
| 410 | 400 | // :65:17: error: use of undefined value here causes illegal behavior |
| 411 | // :65:17: note: when computing vector element at index '0' | |
| 401 | // :65:17: note: when computing vector element at index '1' | |
| 412 | 402 | // :65:17: error: use of undefined value here causes illegal behavior |
| 403 | // :65:17: note: when computing vector element at index '1' | |
| 413 | 404 | // :65:17: error: use of undefined value here causes illegal behavior |
| 405 | // :65:17: note: when computing vector element at index '1' | |
| 414 | 406 | // :65:17: error: use of undefined value here causes illegal behavior |
| 415 | // :65:17: note: when computing vector element at index '0' | |
| 407 | // :65:17: note: when computing vector element at index '1' | |
| 416 | 408 | // :65:17: error: use of undefined value here causes illegal behavior |
| 417 | // :65:17: note: when computing vector element at index '0' | |
| 409 | // :65:17: note: when computing vector element at index '1' | |
| 418 | 410 | // :65:17: error: use of undefined value here causes illegal behavior |
| 419 | // :65:17: note: when computing vector element at index '0' | |
| 411 | // :65:17: note: when computing vector element at index '1' | |
| 420 | 412 | // :65:17: error: use of undefined value here causes illegal behavior |
| 421 | // :65:17: note: when computing vector element at index '0' | |
| 413 | // :65:17: note: when computing vector element at index '1' | |
| 422 | 414 | // :65:17: error: use of undefined value here causes illegal behavior |
| 423 | 415 | // :65:17: note: when computing vector element at index '1' |
| 424 | 416 | // :65:17: error: use of undefined value here causes illegal behavior |
| 425 | 417 | // :65:17: note: when computing vector element at index '1' |
| 426 | 418 | // :65:17: error: use of undefined value here causes illegal behavior |
| 427 | // :65:17: note: when computing vector element at index '0' | |
| 419 | // :65:17: note: when computing vector element at index '1' | |
| 428 | 420 | // :65:17: error: use of undefined value here causes illegal behavior |
| 429 | // :65:17: note: when computing vector element at index '0' | |
| 421 | // :65:17: note: when computing vector element at index '1' | |
| 430 | 422 | // :65:17: error: use of undefined value here causes illegal behavior |
| 431 | // :65:17: note: when computing vector element at index '0' | |
| 423 | // :65:17: note: when computing vector element at index '1' | |
| 432 | 424 | // :65:17: error: use of undefined value here causes illegal behavior |
| 433 | // :65:17: note: when computing vector element at index '0' | |
| 425 | // :65:17: note: when computing vector element at index '1' | |
| 426 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 427 | // :65:17: note: when computing vector element at index '1' | |
| 428 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 429 | // :65:17: note: when computing vector element at index '1' | |
| 430 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 431 | // :65:17: note: when computing vector element at index '1' | |
| 432 | // :65:17: error: use of undefined value here causes illegal behavior | |
| 433 | // :65:17: note: when computing vector element at index '1' | |
| 434 | 434 | // :65:21: error: use of undefined value here causes illegal behavior |
| 435 | 435 | // :65:21: note: when computing vector element at index '0' |
| 436 | 436 | // :65:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -478,50 +478,30 @@ const std = @import("std"); |
| 478 | 478 | // :69:27: error: use of undefined value here causes illegal behavior |
| 479 | 479 | // :69:27: error: use of undefined value here causes illegal behavior |
| 480 | 480 | // :69:27: error: use of undefined value here causes illegal behavior |
| 481 | // :69:27: note: when computing vector element at index '0' | |
| 482 | 481 | // :69:27: error: use of undefined value here causes illegal behavior |
| 483 | // :69:27: note: when computing vector element at index '0' | |
| 484 | 482 | // :69:27: error: use of undefined value here causes illegal behavior |
| 485 | // :69:27: note: when computing vector element at index '0' | |
| 486 | 483 | // :69:27: error: use of undefined value here causes illegal behavior |
| 487 | // :69:27: note: when computing vector element at index '0' | |
| 488 | 484 | // :69:27: error: use of undefined value here causes illegal behavior |
| 489 | // :69:27: note: when computing vector element at index '1' | |
| 490 | 485 | // :69:27: error: use of undefined value here causes illegal behavior |
| 491 | // :69:27: note: when computing vector element at index '1' | |
| 492 | 486 | // :69:27: error: use of undefined value here causes illegal behavior |
| 493 | // :69:27: note: when computing vector element at index '0' | |
| 494 | 487 | // :69:27: error: use of undefined value here causes illegal behavior |
| 495 | // :69:27: note: when computing vector element at index '0' | |
| 496 | 488 | // :69:27: error: use of undefined value here causes illegal behavior |
| 497 | // :69:27: note: when computing vector element at index '0' | |
| 498 | 489 | // :69:27: error: use of undefined value here causes illegal behavior |
| 499 | // :69:27: note: when computing vector element at index '0' | |
| 500 | 490 | // :69:27: error: use of undefined value here causes illegal behavior |
| 501 | 491 | // :69:27: error: use of undefined value here causes illegal behavior |
| 502 | 492 | // :69:27: error: use of undefined value here causes illegal behavior |
| 503 | // :69:27: note: when computing vector element at index '0' | |
| 504 | 493 | // :69:27: error: use of undefined value here causes illegal behavior |
| 505 | // :69:27: note: when computing vector element at index '0' | |
| 506 | 494 | // :69:27: error: use of undefined value here causes illegal behavior |
| 507 | // :69:27: note: when computing vector element at index '0' | |
| 508 | 495 | // :69:27: error: use of undefined value here causes illegal behavior |
| 509 | // :69:27: note: when computing vector element at index '0' | |
| 510 | 496 | // :69:27: error: use of undefined value here causes illegal behavior |
| 511 | // :69:27: note: when computing vector element at index '1' | |
| 512 | 497 | // :69:27: error: use of undefined value here causes illegal behavior |
| 513 | // :69:27: note: when computing vector element at index '1' | |
| 514 | 498 | // :69:27: error: use of undefined value here causes illegal behavior |
| 515 | // :69:27: note: when computing vector element at index '0' | |
| 516 | 499 | // :69:27: error: use of undefined value here causes illegal behavior |
| 517 | // :69:27: note: when computing vector element at index '0' | |
| 518 | 500 | // :69:27: error: use of undefined value here causes illegal behavior |
| 519 | 501 | // :69:27: note: when computing vector element at index '0' |
| 520 | 502 | // :69:27: error: use of undefined value here causes illegal behavior |
| 521 | 503 | // :69:27: note: when computing vector element at index '0' |
| 522 | 504 | // :69:27: error: use of undefined value here causes illegal behavior |
| 523 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 524 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 525 | 505 | // :69:27: note: when computing vector element at index '0' |
| 526 | 506 | // :69:27: error: use of undefined value here causes illegal behavior |
| 527 | 507 | // :69:27: note: when computing vector element at index '0' |
| ... | ... | @@ -530,10 +510,6 @@ const std = @import("std"); |
| 530 | 510 | // :69:27: error: use of undefined value here causes illegal behavior |
| 531 | 511 | // :69:27: note: when computing vector element at index '0' |
| 532 | 512 | // :69:27: error: use of undefined value here causes illegal behavior |
| 533 | // :69:27: note: when computing vector element at index '1' | |
| 534 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 535 | // :69:27: note: when computing vector element at index '1' | |
| 536 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 537 | 513 | // :69:27: note: when computing vector element at index '0' |
| 538 | 514 | // :69:27: error: use of undefined value here causes illegal behavior |
| 539 | 515 | // :69:27: note: when computing vector element at index '0' |
| ... | ... | @@ -542,7 +518,9 @@ const std = @import("std"); |
| 542 | 518 | // :69:27: error: use of undefined value here causes illegal behavior |
| 543 | 519 | // :69:27: note: when computing vector element at index '0' |
| 544 | 520 | // :69:27: error: use of undefined value here causes illegal behavior |
| 521 | // :69:27: note: when computing vector element at index '0' | |
| 545 | 522 | // :69:27: error: use of undefined value here causes illegal behavior |
| 523 | // :69:27: note: when computing vector element at index '0' | |
| 546 | 524 | // :69:27: error: use of undefined value here causes illegal behavior |
| 547 | 525 | // :69:27: note: when computing vector element at index '0' |
| 548 | 526 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -552,9 +530,9 @@ const std = @import("std"); |
| 552 | 530 | // :69:27: error: use of undefined value here causes illegal behavior |
| 553 | 531 | // :69:27: note: when computing vector element at index '0' |
| 554 | 532 | // :69:27: error: use of undefined value here causes illegal behavior |
| 555 | // :69:27: note: when computing vector element at index '1' | |
| 533 | // :69:27: note: when computing vector element at index '0' | |
| 556 | 534 | // :69:27: error: use of undefined value here causes illegal behavior |
| 557 | // :69:27: note: when computing vector element at index '1' | |
| 535 | // :69:27: note: when computing vector element at index '0' | |
| 558 | 536 | // :69:27: error: use of undefined value here causes illegal behavior |
| 559 | 537 | // :69:27: note: when computing vector element at index '0' |
| 560 | 538 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -564,7 +542,9 @@ const std = @import("std"); |
| 564 | 542 | // :69:27: error: use of undefined value here causes illegal behavior |
| 565 | 543 | // :69:27: note: when computing vector element at index '0' |
| 566 | 544 | // :69:27: error: use of undefined value here causes illegal behavior |
| 545 | // :69:27: note: when computing vector element at index '0' | |
| 567 | 546 | // :69:27: error: use of undefined value here causes illegal behavior |
| 547 | // :69:27: note: when computing vector element at index '0' | |
| 568 | 548 | // :69:27: error: use of undefined value here causes illegal behavior |
| 569 | 549 | // :69:27: note: when computing vector element at index '0' |
| 570 | 550 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -574,9 +554,9 @@ const std = @import("std"); |
| 574 | 554 | // :69:27: error: use of undefined value here causes illegal behavior |
| 575 | 555 | // :69:27: note: when computing vector element at index '0' |
| 576 | 556 | // :69:27: error: use of undefined value here causes illegal behavior |
| 577 | // :69:27: note: when computing vector element at index '1' | |
| 557 | // :69:27: note: when computing vector element at index '0' | |
| 578 | 558 | // :69:27: error: use of undefined value here causes illegal behavior |
| 579 | // :69:27: note: when computing vector element at index '1' | |
| 559 | // :69:27: note: when computing vector element at index '0' | |
| 580 | 560 | // :69:27: error: use of undefined value here causes illegal behavior |
| 581 | 561 | // :69:27: note: when computing vector element at index '0' |
| 582 | 562 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -586,7 +566,9 @@ const std = @import("std"); |
| 586 | 566 | // :69:27: error: use of undefined value here causes illegal behavior |
| 587 | 567 | // :69:27: note: when computing vector element at index '0' |
| 588 | 568 | // :69:27: error: use of undefined value here causes illegal behavior |
| 569 | // :69:27: note: when computing vector element at index '0' | |
| 589 | 570 | // :69:27: error: use of undefined value here causes illegal behavior |
| 571 | // :69:27: note: when computing vector element at index '0' | |
| 590 | 572 | // :69:27: error: use of undefined value here causes illegal behavior |
| 591 | 573 | // :69:27: note: when computing vector element at index '0' |
| 592 | 574 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -596,9 +578,9 @@ const std = @import("std"); |
| 596 | 578 | // :69:27: error: use of undefined value here causes illegal behavior |
| 597 | 579 | // :69:27: note: when computing vector element at index '0' |
| 598 | 580 | // :69:27: error: use of undefined value here causes illegal behavior |
| 599 | // :69:27: note: when computing vector element at index '1' | |
| 581 | // :69:27: note: when computing vector element at index '0' | |
| 600 | 582 | // :69:27: error: use of undefined value here causes illegal behavior |
| 601 | // :69:27: note: when computing vector element at index '1' | |
| 583 | // :69:27: note: when computing vector element at index '0' | |
| 602 | 584 | // :69:27: error: use of undefined value here causes illegal behavior |
| 603 | 585 | // :69:27: note: when computing vector element at index '0' |
| 604 | 586 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -608,7 +590,9 @@ const std = @import("std"); |
| 608 | 590 | // :69:27: error: use of undefined value here causes illegal behavior |
| 609 | 591 | // :69:27: note: when computing vector element at index '0' |
| 610 | 592 | // :69:27: error: use of undefined value here causes illegal behavior |
| 593 | // :69:27: note: when computing vector element at index '0' | |
| 611 | 594 | // :69:27: error: use of undefined value here causes illegal behavior |
| 595 | // :69:27: note: when computing vector element at index '0' | |
| 612 | 596 | // :69:27: error: use of undefined value here causes illegal behavior |
| 613 | 597 | // :69:27: note: when computing vector element at index '0' |
| 614 | 598 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -618,9 +602,9 @@ const std = @import("std"); |
| 618 | 602 | // :69:27: error: use of undefined value here causes illegal behavior |
| 619 | 603 | // :69:27: note: when computing vector element at index '0' |
| 620 | 604 | // :69:27: error: use of undefined value here causes illegal behavior |
| 621 | // :69:27: note: when computing vector element at index '1' | |
| 605 | // :69:27: note: when computing vector element at index '0' | |
| 622 | 606 | // :69:27: error: use of undefined value here causes illegal behavior |
| 623 | // :69:27: note: when computing vector element at index '1' | |
| 607 | // :69:27: note: when computing vector element at index '0' | |
| 624 | 608 | // :69:27: error: use of undefined value here causes illegal behavior |
| 625 | 609 | // :69:27: note: when computing vector element at index '0' |
| 626 | 610 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -630,7 +614,9 @@ const std = @import("std"); |
| 630 | 614 | // :69:27: error: use of undefined value here causes illegal behavior |
| 631 | 615 | // :69:27: note: when computing vector element at index '0' |
| 632 | 616 | // :69:27: error: use of undefined value here causes illegal behavior |
| 617 | // :69:27: note: when computing vector element at index '0' | |
| 633 | 618 | // :69:27: error: use of undefined value here causes illegal behavior |
| 619 | // :69:27: note: when computing vector element at index '0' | |
| 634 | 620 | // :69:27: error: use of undefined value here causes illegal behavior |
| 635 | 621 | // :69:27: note: when computing vector element at index '0' |
| 636 | 622 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -640,9 +626,9 @@ const std = @import("std"); |
| 640 | 626 | // :69:27: error: use of undefined value here causes illegal behavior |
| 641 | 627 | // :69:27: note: when computing vector element at index '0' |
| 642 | 628 | // :69:27: error: use of undefined value here causes illegal behavior |
| 643 | // :69:27: note: when computing vector element at index '1' | |
| 629 | // :69:27: note: when computing vector element at index '0' | |
| 644 | 630 | // :69:27: error: use of undefined value here causes illegal behavior |
| 645 | // :69:27: note: when computing vector element at index '1' | |
| 631 | // :69:27: note: when computing vector element at index '0' | |
| 646 | 632 | // :69:27: error: use of undefined value here causes illegal behavior |
| 647 | 633 | // :69:27: note: when computing vector element at index '0' |
| 648 | 634 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -652,7 +638,9 @@ const std = @import("std"); |
| 652 | 638 | // :69:27: error: use of undefined value here causes illegal behavior |
| 653 | 639 | // :69:27: note: when computing vector element at index '0' |
| 654 | 640 | // :69:27: error: use of undefined value here causes illegal behavior |
| 641 | // :69:27: note: when computing vector element at index '0' | |
| 655 | 642 | // :69:27: error: use of undefined value here causes illegal behavior |
| 643 | // :69:27: note: when computing vector element at index '0' | |
| 656 | 644 | // :69:27: error: use of undefined value here causes illegal behavior |
| 657 | 645 | // :69:27: note: when computing vector element at index '0' |
| 658 | 646 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -662,9 +650,9 @@ const std = @import("std"); |
| 662 | 650 | // :69:27: error: use of undefined value here causes illegal behavior |
| 663 | 651 | // :69:27: note: when computing vector element at index '0' |
| 664 | 652 | // :69:27: error: use of undefined value here causes illegal behavior |
| 665 | // :69:27: note: when computing vector element at index '1' | |
| 653 | // :69:27: note: when computing vector element at index '0' | |
| 666 | 654 | // :69:27: error: use of undefined value here causes illegal behavior |
| 667 | // :69:27: note: when computing vector element at index '1' | |
| 655 | // :69:27: note: when computing vector element at index '0' | |
| 668 | 656 | // :69:27: error: use of undefined value here causes illegal behavior |
| 669 | 657 | // :69:27: note: when computing vector element at index '0' |
| 670 | 658 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -674,7 +662,9 @@ const std = @import("std"); |
| 674 | 662 | // :69:27: error: use of undefined value here causes illegal behavior |
| 675 | 663 | // :69:27: note: when computing vector element at index '0' |
| 676 | 664 | // :69:27: error: use of undefined value here causes illegal behavior |
| 665 | // :69:27: note: when computing vector element at index '0' | |
| 677 | 666 | // :69:27: error: use of undefined value here causes illegal behavior |
| 667 | // :69:27: note: when computing vector element at index '0' | |
| 678 | 668 | // :69:27: error: use of undefined value here causes illegal behavior |
| 679 | 669 | // :69:27: note: when computing vector element at index '0' |
| 680 | 670 | // :69:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -688,35 +678,45 @@ const std = @import("std"); |
| 688 | 678 | // :69:27: error: use of undefined value here causes illegal behavior |
| 689 | 679 | // :69:27: note: when computing vector element at index '1' |
| 690 | 680 | // :69:27: error: use of undefined value here causes illegal behavior |
| 691 | // :69:27: note: when computing vector element at index '0' | |
| 681 | // :69:27: note: when computing vector element at index '1' | |
| 692 | 682 | // :69:27: error: use of undefined value here causes illegal behavior |
| 693 | // :69:27: note: when computing vector element at index '0' | |
| 683 | // :69:27: note: when computing vector element at index '1' | |
| 694 | 684 | // :69:27: error: use of undefined value here causes illegal behavior |
| 695 | // :69:27: note: when computing vector element at index '0' | |
| 685 | // :69:27: note: when computing vector element at index '1' | |
| 696 | 686 | // :69:27: error: use of undefined value here causes illegal behavior |
| 697 | // :69:27: note: when computing vector element at index '0' | |
| 687 | // :69:27: note: when computing vector element at index '1' | |
| 698 | 688 | // :69:27: error: use of undefined value here causes illegal behavior |
| 689 | // :69:27: note: when computing vector element at index '1' | |
| 699 | 690 | // :69:27: error: use of undefined value here causes illegal behavior |
| 691 | // :69:27: note: when computing vector element at index '1' | |
| 700 | 692 | // :69:27: error: use of undefined value here causes illegal behavior |
| 701 | // :69:27: note: when computing vector element at index '0' | |
| 693 | // :69:27: note: when computing vector element at index '1' | |
| 702 | 694 | // :69:27: error: use of undefined value here causes illegal behavior |
| 703 | // :69:27: note: when computing vector element at index '0' | |
| 695 | // :69:27: note: when computing vector element at index '1' | |
| 704 | 696 | // :69:27: error: use of undefined value here causes illegal behavior |
| 705 | // :69:27: note: when computing vector element at index '0' | |
| 697 | // :69:27: note: when computing vector element at index '1' | |
| 706 | 698 | // :69:27: error: use of undefined value here causes illegal behavior |
| 707 | // :69:27: note: when computing vector element at index '0' | |
| 699 | // :69:27: note: when computing vector element at index '1' | |
| 708 | 700 | // :69:27: error: use of undefined value here causes illegal behavior |
| 709 | 701 | // :69:27: note: when computing vector element at index '1' |
| 710 | 702 | // :69:27: error: use of undefined value here causes illegal behavior |
| 711 | 703 | // :69:27: note: when computing vector element at index '1' |
| 712 | 704 | // :69:27: error: use of undefined value here causes illegal behavior |
| 713 | // :69:27: note: when computing vector element at index '0' | |
| 705 | // :69:27: note: when computing vector element at index '1' | |
| 714 | 706 | // :69:27: error: use of undefined value here causes illegal behavior |
| 715 | // :69:27: note: when computing vector element at index '0' | |
| 707 | // :69:27: note: when computing vector element at index '1' | |
| 716 | 708 | // :69:27: error: use of undefined value here causes illegal behavior |
| 717 | // :69:27: note: when computing vector element at index '0' | |
| 709 | // :69:27: note: when computing vector element at index '1' | |
| 718 | 710 | // :69:27: error: use of undefined value here causes illegal behavior |
| 719 | // :69:27: note: when computing vector element at index '0' | |
| 711 | // :69:27: note: when computing vector element at index '1' | |
| 712 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 713 | // :69:27: note: when computing vector element at index '1' | |
| 714 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 715 | // :69:27: note: when computing vector element at index '1' | |
| 716 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 717 | // :69:27: note: when computing vector element at index '1' | |
| 718 | // :69:27: error: use of undefined value here causes illegal behavior | |
| 719 | // :69:27: note: when computing vector element at index '1' | |
| 720 | 720 | // :69:30: error: use of undefined value here causes illegal behavior |
| 721 | 721 | // :69:30: note: when computing vector element at index '0' |
| 722 | 722 | // :69:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -764,50 +764,30 @@ const std = @import("std"); |
| 764 | 764 | // :73:27: error: use of undefined value here causes illegal behavior |
| 765 | 765 | // :73:27: error: use of undefined value here causes illegal behavior |
| 766 | 766 | // :73:27: error: use of undefined value here causes illegal behavior |
| 767 | // :73:27: note: when computing vector element at index '0' | |
| 768 | 767 | // :73:27: error: use of undefined value here causes illegal behavior |
| 769 | // :73:27: note: when computing vector element at index '0' | |
| 770 | 768 | // :73:27: error: use of undefined value here causes illegal behavior |
| 771 | // :73:27: note: when computing vector element at index '0' | |
| 772 | 769 | // :73:27: error: use of undefined value here causes illegal behavior |
| 773 | // :73:27: note: when computing vector element at index '0' | |
| 774 | 770 | // :73:27: error: use of undefined value here causes illegal behavior |
| 775 | // :73:27: note: when computing vector element at index '1' | |
| 776 | 771 | // :73:27: error: use of undefined value here causes illegal behavior |
| 777 | // :73:27: note: when computing vector element at index '1' | |
| 778 | 772 | // :73:27: error: use of undefined value here causes illegal behavior |
| 779 | // :73:27: note: when computing vector element at index '0' | |
| 780 | 773 | // :73:27: error: use of undefined value here causes illegal behavior |
| 781 | // :73:27: note: when computing vector element at index '0' | |
| 782 | 774 | // :73:27: error: use of undefined value here causes illegal behavior |
| 783 | // :73:27: note: when computing vector element at index '0' | |
| 784 | 775 | // :73:27: error: use of undefined value here causes illegal behavior |
| 785 | // :73:27: note: when computing vector element at index '0' | |
| 786 | 776 | // :73:27: error: use of undefined value here causes illegal behavior |
| 787 | 777 | // :73:27: error: use of undefined value here causes illegal behavior |
| 788 | 778 | // :73:27: error: use of undefined value here causes illegal behavior |
| 789 | // :73:27: note: when computing vector element at index '0' | |
| 790 | 779 | // :73:27: error: use of undefined value here causes illegal behavior |
| 791 | // :73:27: note: when computing vector element at index '0' | |
| 792 | 780 | // :73:27: error: use of undefined value here causes illegal behavior |
| 793 | // :73:27: note: when computing vector element at index '0' | |
| 794 | 781 | // :73:27: error: use of undefined value here causes illegal behavior |
| 795 | // :73:27: note: when computing vector element at index '0' | |
| 796 | 782 | // :73:27: error: use of undefined value here causes illegal behavior |
| 797 | // :73:27: note: when computing vector element at index '1' | |
| 798 | 783 | // :73:27: error: use of undefined value here causes illegal behavior |
| 799 | // :73:27: note: when computing vector element at index '1' | |
| 800 | 784 | // :73:27: error: use of undefined value here causes illegal behavior |
| 801 | // :73:27: note: when computing vector element at index '0' | |
| 802 | 785 | // :73:27: error: use of undefined value here causes illegal behavior |
| 803 | // :73:27: note: when computing vector element at index '0' | |
| 804 | 786 | // :73:27: error: use of undefined value here causes illegal behavior |
| 805 | 787 | // :73:27: note: when computing vector element at index '0' |
| 806 | 788 | // :73:27: error: use of undefined value here causes illegal behavior |
| 807 | 789 | // :73:27: note: when computing vector element at index '0' |
| 808 | 790 | // :73:27: error: use of undefined value here causes illegal behavior |
| 809 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 810 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 811 | 791 | // :73:27: note: when computing vector element at index '0' |
| 812 | 792 | // :73:27: error: use of undefined value here causes illegal behavior |
| 813 | 793 | // :73:27: note: when computing vector element at index '0' |
| ... | ... | @@ -816,10 +796,6 @@ const std = @import("std"); |
| 816 | 796 | // :73:27: error: use of undefined value here causes illegal behavior |
| 817 | 797 | // :73:27: note: when computing vector element at index '0' |
| 818 | 798 | // :73:27: error: use of undefined value here causes illegal behavior |
| 819 | // :73:27: note: when computing vector element at index '1' | |
| 820 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 821 | // :73:27: note: when computing vector element at index '1' | |
| 822 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 823 | 799 | // :73:27: note: when computing vector element at index '0' |
| 824 | 800 | // :73:27: error: use of undefined value here causes illegal behavior |
| 825 | 801 | // :73:27: note: when computing vector element at index '0' |
| ... | ... | @@ -828,7 +804,9 @@ const std = @import("std"); |
| 828 | 804 | // :73:27: error: use of undefined value here causes illegal behavior |
| 829 | 805 | // :73:27: note: when computing vector element at index '0' |
| 830 | 806 | // :73:27: error: use of undefined value here causes illegal behavior |
| 807 | // :73:27: note: when computing vector element at index '0' | |
| 831 | 808 | // :73:27: error: use of undefined value here causes illegal behavior |
| 809 | // :73:27: note: when computing vector element at index '0' | |
| 832 | 810 | // :73:27: error: use of undefined value here causes illegal behavior |
| 833 | 811 | // :73:27: note: when computing vector element at index '0' |
| 834 | 812 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -838,9 +816,9 @@ const std = @import("std"); |
| 838 | 816 | // :73:27: error: use of undefined value here causes illegal behavior |
| 839 | 817 | // :73:27: note: when computing vector element at index '0' |
| 840 | 818 | // :73:27: error: use of undefined value here causes illegal behavior |
| 841 | // :73:27: note: when computing vector element at index '1' | |
| 819 | // :73:27: note: when computing vector element at index '0' | |
| 842 | 820 | // :73:27: error: use of undefined value here causes illegal behavior |
| 843 | // :73:27: note: when computing vector element at index '1' | |
| 821 | // :73:27: note: when computing vector element at index '0' | |
| 844 | 822 | // :73:27: error: use of undefined value here causes illegal behavior |
| 845 | 823 | // :73:27: note: when computing vector element at index '0' |
| 846 | 824 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -850,7 +828,9 @@ const std = @import("std"); |
| 850 | 828 | // :73:27: error: use of undefined value here causes illegal behavior |
| 851 | 829 | // :73:27: note: when computing vector element at index '0' |
| 852 | 830 | // :73:27: error: use of undefined value here causes illegal behavior |
| 831 | // :73:27: note: when computing vector element at index '0' | |
| 853 | 832 | // :73:27: error: use of undefined value here causes illegal behavior |
| 833 | // :73:27: note: when computing vector element at index '0' | |
| 854 | 834 | // :73:27: error: use of undefined value here causes illegal behavior |
| 855 | 835 | // :73:27: note: when computing vector element at index '0' |
| 856 | 836 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -860,9 +840,9 @@ const std = @import("std"); |
| 860 | 840 | // :73:27: error: use of undefined value here causes illegal behavior |
| 861 | 841 | // :73:27: note: when computing vector element at index '0' |
| 862 | 842 | // :73:27: error: use of undefined value here causes illegal behavior |
| 863 | // :73:27: note: when computing vector element at index '1' | |
| 843 | // :73:27: note: when computing vector element at index '0' | |
| 864 | 844 | // :73:27: error: use of undefined value here causes illegal behavior |
| 865 | // :73:27: note: when computing vector element at index '1' | |
| 845 | // :73:27: note: when computing vector element at index '0' | |
| 866 | 846 | // :73:27: error: use of undefined value here causes illegal behavior |
| 867 | 847 | // :73:27: note: when computing vector element at index '0' |
| 868 | 848 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -872,7 +852,9 @@ const std = @import("std"); |
| 872 | 852 | // :73:27: error: use of undefined value here causes illegal behavior |
| 873 | 853 | // :73:27: note: when computing vector element at index '0' |
| 874 | 854 | // :73:27: error: use of undefined value here causes illegal behavior |
| 855 | // :73:27: note: when computing vector element at index '0' | |
| 875 | 856 | // :73:27: error: use of undefined value here causes illegal behavior |
| 857 | // :73:27: note: when computing vector element at index '0' | |
| 876 | 858 | // :73:27: error: use of undefined value here causes illegal behavior |
| 877 | 859 | // :73:27: note: when computing vector element at index '0' |
| 878 | 860 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -882,9 +864,9 @@ const std = @import("std"); |
| 882 | 864 | // :73:27: error: use of undefined value here causes illegal behavior |
| 883 | 865 | // :73:27: note: when computing vector element at index '0' |
| 884 | 866 | // :73:27: error: use of undefined value here causes illegal behavior |
| 885 | // :73:27: note: when computing vector element at index '1' | |
| 867 | // :73:27: note: when computing vector element at index '0' | |
| 886 | 868 | // :73:27: error: use of undefined value here causes illegal behavior |
| 887 | // :73:27: note: when computing vector element at index '1' | |
| 869 | // :73:27: note: when computing vector element at index '0' | |
| 888 | 870 | // :73:27: error: use of undefined value here causes illegal behavior |
| 889 | 871 | // :73:27: note: when computing vector element at index '0' |
| 890 | 872 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -894,7 +876,9 @@ const std = @import("std"); |
| 894 | 876 | // :73:27: error: use of undefined value here causes illegal behavior |
| 895 | 877 | // :73:27: note: when computing vector element at index '0' |
| 896 | 878 | // :73:27: error: use of undefined value here causes illegal behavior |
| 879 | // :73:27: note: when computing vector element at index '0' | |
| 897 | 880 | // :73:27: error: use of undefined value here causes illegal behavior |
| 881 | // :73:27: note: when computing vector element at index '0' | |
| 898 | 882 | // :73:27: error: use of undefined value here causes illegal behavior |
| 899 | 883 | // :73:27: note: when computing vector element at index '0' |
| 900 | 884 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -904,9 +888,9 @@ const std = @import("std"); |
| 904 | 888 | // :73:27: error: use of undefined value here causes illegal behavior |
| 905 | 889 | // :73:27: note: when computing vector element at index '0' |
| 906 | 890 | // :73:27: error: use of undefined value here causes illegal behavior |
| 907 | // :73:27: note: when computing vector element at index '1' | |
| 891 | // :73:27: note: when computing vector element at index '0' | |
| 908 | 892 | // :73:27: error: use of undefined value here causes illegal behavior |
| 909 | // :73:27: note: when computing vector element at index '1' | |
| 893 | // :73:27: note: when computing vector element at index '0' | |
| 910 | 894 | // :73:27: error: use of undefined value here causes illegal behavior |
| 911 | 895 | // :73:27: note: when computing vector element at index '0' |
| 912 | 896 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -916,7 +900,9 @@ const std = @import("std"); |
| 916 | 900 | // :73:27: error: use of undefined value here causes illegal behavior |
| 917 | 901 | // :73:27: note: when computing vector element at index '0' |
| 918 | 902 | // :73:27: error: use of undefined value here causes illegal behavior |
| 903 | // :73:27: note: when computing vector element at index '0' | |
| 919 | 904 | // :73:27: error: use of undefined value here causes illegal behavior |
| 905 | // :73:27: note: when computing vector element at index '0' | |
| 920 | 906 | // :73:27: error: use of undefined value here causes illegal behavior |
| 921 | 907 | // :73:27: note: when computing vector element at index '0' |
| 922 | 908 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -926,9 +912,9 @@ const std = @import("std"); |
| 926 | 912 | // :73:27: error: use of undefined value here causes illegal behavior |
| 927 | 913 | // :73:27: note: when computing vector element at index '0' |
| 928 | 914 | // :73:27: error: use of undefined value here causes illegal behavior |
| 929 | // :73:27: note: when computing vector element at index '1' | |
| 915 | // :73:27: note: when computing vector element at index '0' | |
| 930 | 916 | // :73:27: error: use of undefined value here causes illegal behavior |
| 931 | // :73:27: note: when computing vector element at index '1' | |
| 917 | // :73:27: note: when computing vector element at index '0' | |
| 932 | 918 | // :73:27: error: use of undefined value here causes illegal behavior |
| 933 | 919 | // :73:27: note: when computing vector element at index '0' |
| 934 | 920 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -938,7 +924,9 @@ const std = @import("std"); |
| 938 | 924 | // :73:27: error: use of undefined value here causes illegal behavior |
| 939 | 925 | // :73:27: note: when computing vector element at index '0' |
| 940 | 926 | // :73:27: error: use of undefined value here causes illegal behavior |
| 927 | // :73:27: note: when computing vector element at index '0' | |
| 941 | 928 | // :73:27: error: use of undefined value here causes illegal behavior |
| 929 | // :73:27: note: when computing vector element at index '0' | |
| 942 | 930 | // :73:27: error: use of undefined value here causes illegal behavior |
| 943 | 931 | // :73:27: note: when computing vector element at index '0' |
| 944 | 932 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -948,9 +936,9 @@ const std = @import("std"); |
| 948 | 936 | // :73:27: error: use of undefined value here causes illegal behavior |
| 949 | 937 | // :73:27: note: when computing vector element at index '0' |
| 950 | 938 | // :73:27: error: use of undefined value here causes illegal behavior |
| 951 | // :73:27: note: when computing vector element at index '1' | |
| 939 | // :73:27: note: when computing vector element at index '0' | |
| 952 | 940 | // :73:27: error: use of undefined value here causes illegal behavior |
| 953 | // :73:27: note: when computing vector element at index '1' | |
| 941 | // :73:27: note: when computing vector element at index '0' | |
| 954 | 942 | // :73:27: error: use of undefined value here causes illegal behavior |
| 955 | 943 | // :73:27: note: when computing vector element at index '0' |
| 956 | 944 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -960,7 +948,9 @@ const std = @import("std"); |
| 960 | 948 | // :73:27: error: use of undefined value here causes illegal behavior |
| 961 | 949 | // :73:27: note: when computing vector element at index '0' |
| 962 | 950 | // :73:27: error: use of undefined value here causes illegal behavior |
| 951 | // :73:27: note: when computing vector element at index '0' | |
| 963 | 952 | // :73:27: error: use of undefined value here causes illegal behavior |
| 953 | // :73:27: note: when computing vector element at index '0' | |
| 964 | 954 | // :73:27: error: use of undefined value here causes illegal behavior |
| 965 | 955 | // :73:27: note: when computing vector element at index '0' |
| 966 | 956 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -974,35 +964,45 @@ const std = @import("std"); |
| 974 | 964 | // :73:27: error: use of undefined value here causes illegal behavior |
| 975 | 965 | // :73:27: note: when computing vector element at index '1' |
| 976 | 966 | // :73:27: error: use of undefined value here causes illegal behavior |
| 977 | // :73:27: note: when computing vector element at index '0' | |
| 967 | // :73:27: note: when computing vector element at index '1' | |
| 978 | 968 | // :73:27: error: use of undefined value here causes illegal behavior |
| 979 | // :73:27: note: when computing vector element at index '0' | |
| 969 | // :73:27: note: when computing vector element at index '1' | |
| 980 | 970 | // :73:27: error: use of undefined value here causes illegal behavior |
| 981 | // :73:27: note: when computing vector element at index '0' | |
| 971 | // :73:27: note: when computing vector element at index '1' | |
| 982 | 972 | // :73:27: error: use of undefined value here causes illegal behavior |
| 983 | // :73:27: note: when computing vector element at index '0' | |
| 973 | // :73:27: note: when computing vector element at index '1' | |
| 984 | 974 | // :73:27: error: use of undefined value here causes illegal behavior |
| 975 | // :73:27: note: when computing vector element at index '1' | |
| 985 | 976 | // :73:27: error: use of undefined value here causes illegal behavior |
| 977 | // :73:27: note: when computing vector element at index '1' | |
| 986 | 978 | // :73:27: error: use of undefined value here causes illegal behavior |
| 987 | // :73:27: note: when computing vector element at index '0' | |
| 979 | // :73:27: note: when computing vector element at index '1' | |
| 988 | 980 | // :73:27: error: use of undefined value here causes illegal behavior |
| 989 | // :73:27: note: when computing vector element at index '0' | |
| 981 | // :73:27: note: when computing vector element at index '1' | |
| 990 | 982 | // :73:27: error: use of undefined value here causes illegal behavior |
| 991 | // :73:27: note: when computing vector element at index '0' | |
| 983 | // :73:27: note: when computing vector element at index '1' | |
| 992 | 984 | // :73:27: error: use of undefined value here causes illegal behavior |
| 993 | // :73:27: note: when computing vector element at index '0' | |
| 985 | // :73:27: note: when computing vector element at index '1' | |
| 994 | 986 | // :73:27: error: use of undefined value here causes illegal behavior |
| 995 | 987 | // :73:27: note: when computing vector element at index '1' |
| 996 | 988 | // :73:27: error: use of undefined value here causes illegal behavior |
| 997 | 989 | // :73:27: note: when computing vector element at index '1' |
| 998 | 990 | // :73:27: error: use of undefined value here causes illegal behavior |
| 999 | // :73:27: note: when computing vector element at index '0' | |
| 991 | // :73:27: note: when computing vector element at index '1' | |
| 1000 | 992 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1001 | // :73:27: note: when computing vector element at index '0' | |
| 993 | // :73:27: note: when computing vector element at index '1' | |
| 1002 | 994 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1003 | // :73:27: note: when computing vector element at index '0' | |
| 995 | // :73:27: note: when computing vector element at index '1' | |
| 1004 | 996 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1005 | // :73:27: note: when computing vector element at index '0' | |
| 997 | // :73:27: note: when computing vector element at index '1' | |
| 998 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 999 | // :73:27: note: when computing vector element at index '1' | |
| 1000 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 1001 | // :73:27: note: when computing vector element at index '1' | |
| 1002 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 1003 | // :73:27: note: when computing vector element at index '1' | |
| 1004 | // :73:27: error: use of undefined value here causes illegal behavior | |
| 1005 | // :73:27: note: when computing vector element at index '1' | |
| 1006 | 1006 | // :73:30: error: use of undefined value here causes illegal behavior |
| 1007 | 1007 | // :73:30: note: when computing vector element at index '0' |
| 1008 | 1008 | // :73:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1050,50 +1050,30 @@ const std = @import("std"); |
| 1050 | 1050 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1051 | 1051 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1052 | 1052 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1053 | // :77:27: note: when computing vector element at index '0' | |
| 1054 | 1053 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1055 | // :77:27: note: when computing vector element at index '0' | |
| 1056 | 1054 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1057 | // :77:27: note: when computing vector element at index '0' | |
| 1058 | 1055 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1059 | // :77:27: note: when computing vector element at index '0' | |
| 1060 | 1056 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1061 | // :77:27: note: when computing vector element at index '1' | |
| 1062 | 1057 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1063 | // :77:27: note: when computing vector element at index '1' | |
| 1064 | 1058 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1065 | // :77:27: note: when computing vector element at index '0' | |
| 1066 | 1059 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1067 | // :77:27: note: when computing vector element at index '0' | |
| 1068 | 1060 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1069 | // :77:27: note: when computing vector element at index '0' | |
| 1070 | 1061 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1071 | // :77:27: note: when computing vector element at index '0' | |
| 1072 | 1062 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1073 | 1063 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1074 | 1064 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1075 | // :77:27: note: when computing vector element at index '0' | |
| 1076 | 1065 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1077 | // :77:27: note: when computing vector element at index '0' | |
| 1078 | 1066 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1079 | // :77:27: note: when computing vector element at index '0' | |
| 1080 | 1067 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1081 | // :77:27: note: when computing vector element at index '0' | |
| 1082 | 1068 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1083 | // :77:27: note: when computing vector element at index '1' | |
| 1084 | 1069 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1085 | // :77:27: note: when computing vector element at index '1' | |
| 1086 | 1070 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1087 | // :77:27: note: when computing vector element at index '0' | |
| 1088 | 1071 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1089 | // :77:27: note: when computing vector element at index '0' | |
| 1090 | 1072 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1091 | 1073 | // :77:27: note: when computing vector element at index '0' |
| 1092 | 1074 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1093 | 1075 | // :77:27: note: when computing vector element at index '0' |
| 1094 | 1076 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1095 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1096 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1097 | 1077 | // :77:27: note: when computing vector element at index '0' |
| 1098 | 1078 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1099 | 1079 | // :77:27: note: when computing vector element at index '0' |
| ... | ... | @@ -1102,10 +1082,6 @@ const std = @import("std"); |
| 1102 | 1082 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1103 | 1083 | // :77:27: note: when computing vector element at index '0' |
| 1104 | 1084 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1105 | // :77:27: note: when computing vector element at index '1' | |
| 1106 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1107 | // :77:27: note: when computing vector element at index '1' | |
| 1108 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1109 | 1085 | // :77:27: note: when computing vector element at index '0' |
| 1110 | 1086 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1111 | 1087 | // :77:27: note: when computing vector element at index '0' |
| ... | ... | @@ -1114,7 +1090,9 @@ const std = @import("std"); |
| 1114 | 1090 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1115 | 1091 | // :77:27: note: when computing vector element at index '0' |
| 1116 | 1092 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1093 | // :77:27: note: when computing vector element at index '0' | |
| 1117 | 1094 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1095 | // :77:27: note: when computing vector element at index '0' | |
| 1118 | 1096 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1119 | 1097 | // :77:27: note: when computing vector element at index '0' |
| 1120 | 1098 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1124,9 +1102,9 @@ const std = @import("std"); |
| 1124 | 1102 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1125 | 1103 | // :77:27: note: when computing vector element at index '0' |
| 1126 | 1104 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1127 | // :77:27: note: when computing vector element at index '1' | |
| 1105 | // :77:27: note: when computing vector element at index '0' | |
| 1128 | 1106 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1129 | // :77:27: note: when computing vector element at index '1' | |
| 1107 | // :77:27: note: when computing vector element at index '0' | |
| 1130 | 1108 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1131 | 1109 | // :77:27: note: when computing vector element at index '0' |
| 1132 | 1110 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1136,7 +1114,9 @@ const std = @import("std"); |
| 1136 | 1114 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1137 | 1115 | // :77:27: note: when computing vector element at index '0' |
| 1138 | 1116 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1117 | // :77:27: note: when computing vector element at index '0' | |
| 1139 | 1118 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1119 | // :77:27: note: when computing vector element at index '0' | |
| 1140 | 1120 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1141 | 1121 | // :77:27: note: when computing vector element at index '0' |
| 1142 | 1122 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1146,9 +1126,9 @@ const std = @import("std"); |
| 1146 | 1126 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1147 | 1127 | // :77:27: note: when computing vector element at index '0' |
| 1148 | 1128 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1149 | // :77:27: note: when computing vector element at index '1' | |
| 1129 | // :77:27: note: when computing vector element at index '0' | |
| 1150 | 1130 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1151 | // :77:27: note: when computing vector element at index '1' | |
| 1131 | // :77:27: note: when computing vector element at index '0' | |
| 1152 | 1132 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1153 | 1133 | // :77:27: note: when computing vector element at index '0' |
| 1154 | 1134 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1158,7 +1138,9 @@ const std = @import("std"); |
| 1158 | 1138 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1159 | 1139 | // :77:27: note: when computing vector element at index '0' |
| 1160 | 1140 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1141 | // :77:27: note: when computing vector element at index '0' | |
| 1161 | 1142 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1143 | // :77:27: note: when computing vector element at index '0' | |
| 1162 | 1144 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1163 | 1145 | // :77:27: note: when computing vector element at index '0' |
| 1164 | 1146 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1168,9 +1150,9 @@ const std = @import("std"); |
| 1168 | 1150 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1169 | 1151 | // :77:27: note: when computing vector element at index '0' |
| 1170 | 1152 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1171 | // :77:27: note: when computing vector element at index '1' | |
| 1153 | // :77:27: note: when computing vector element at index '0' | |
| 1172 | 1154 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1173 | // :77:27: note: when computing vector element at index '1' | |
| 1155 | // :77:27: note: when computing vector element at index '0' | |
| 1174 | 1156 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1175 | 1157 | // :77:27: note: when computing vector element at index '0' |
| 1176 | 1158 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1180,7 +1162,9 @@ const std = @import("std"); |
| 1180 | 1162 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1181 | 1163 | // :77:27: note: when computing vector element at index '0' |
| 1182 | 1164 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1165 | // :77:27: note: when computing vector element at index '0' | |
| 1183 | 1166 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1167 | // :77:27: note: when computing vector element at index '0' | |
| 1184 | 1168 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1185 | 1169 | // :77:27: note: when computing vector element at index '0' |
| 1186 | 1170 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1190,9 +1174,9 @@ const std = @import("std"); |
| 1190 | 1174 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1191 | 1175 | // :77:27: note: when computing vector element at index '0' |
| 1192 | 1176 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1193 | // :77:27: note: when computing vector element at index '1' | |
| 1177 | // :77:27: note: when computing vector element at index '0' | |
| 1194 | 1178 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1195 | // :77:27: note: when computing vector element at index '1' | |
| 1179 | // :77:27: note: when computing vector element at index '0' | |
| 1196 | 1180 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1197 | 1181 | // :77:27: note: when computing vector element at index '0' |
| 1198 | 1182 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1202,7 +1186,9 @@ const std = @import("std"); |
| 1202 | 1186 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1203 | 1187 | // :77:27: note: when computing vector element at index '0' |
| 1204 | 1188 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1189 | // :77:27: note: when computing vector element at index '0' | |
| 1205 | 1190 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1191 | // :77:27: note: when computing vector element at index '0' | |
| 1206 | 1192 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1207 | 1193 | // :77:27: note: when computing vector element at index '0' |
| 1208 | 1194 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1212,9 +1198,9 @@ const std = @import("std"); |
| 1212 | 1198 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1213 | 1199 | // :77:27: note: when computing vector element at index '0' |
| 1214 | 1200 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1215 | // :77:27: note: when computing vector element at index '1' | |
| 1201 | // :77:27: note: when computing vector element at index '0' | |
| 1216 | 1202 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1217 | // :77:27: note: when computing vector element at index '1' | |
| 1203 | // :77:27: note: when computing vector element at index '0' | |
| 1218 | 1204 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1219 | 1205 | // :77:27: note: when computing vector element at index '0' |
| 1220 | 1206 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1224,7 +1210,9 @@ const std = @import("std"); |
| 1224 | 1210 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1225 | 1211 | // :77:27: note: when computing vector element at index '0' |
| 1226 | 1212 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1213 | // :77:27: note: when computing vector element at index '0' | |
| 1227 | 1214 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1215 | // :77:27: note: when computing vector element at index '0' | |
| 1228 | 1216 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1229 | 1217 | // :77:27: note: when computing vector element at index '0' |
| 1230 | 1218 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1234,9 +1222,9 @@ const std = @import("std"); |
| 1234 | 1222 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1235 | 1223 | // :77:27: note: when computing vector element at index '0' |
| 1236 | 1224 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1237 | // :77:27: note: when computing vector element at index '1' | |
| 1225 | // :77:27: note: when computing vector element at index '0' | |
| 1238 | 1226 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1239 | // :77:27: note: when computing vector element at index '1' | |
| 1227 | // :77:27: note: when computing vector element at index '0' | |
| 1240 | 1228 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1241 | 1229 | // :77:27: note: when computing vector element at index '0' |
| 1242 | 1230 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1246,7 +1234,9 @@ const std = @import("std"); |
| 1246 | 1234 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1247 | 1235 | // :77:27: note: when computing vector element at index '0' |
| 1248 | 1236 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1237 | // :77:27: note: when computing vector element at index '0' | |
| 1249 | 1238 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1239 | // :77:27: note: when computing vector element at index '0' | |
| 1250 | 1240 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1251 | 1241 | // :77:27: note: when computing vector element at index '0' |
| 1252 | 1242 | // :77:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1260,35 +1250,45 @@ const std = @import("std"); |
| 1260 | 1250 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1261 | 1251 | // :77:27: note: when computing vector element at index '1' |
| 1262 | 1252 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1263 | // :77:27: note: when computing vector element at index '0' | |
| 1253 | // :77:27: note: when computing vector element at index '1' | |
| 1264 | 1254 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1265 | // :77:27: note: when computing vector element at index '0' | |
| 1255 | // :77:27: note: when computing vector element at index '1' | |
| 1266 | 1256 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1267 | // :77:27: note: when computing vector element at index '0' | |
| 1257 | // :77:27: note: when computing vector element at index '1' | |
| 1268 | 1258 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1269 | // :77:27: note: when computing vector element at index '0' | |
| 1259 | // :77:27: note: when computing vector element at index '1' | |
| 1270 | 1260 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1261 | // :77:27: note: when computing vector element at index '1' | |
| 1271 | 1262 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1263 | // :77:27: note: when computing vector element at index '1' | |
| 1272 | 1264 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1273 | // :77:27: note: when computing vector element at index '0' | |
| 1265 | // :77:27: note: when computing vector element at index '1' | |
| 1274 | 1266 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1275 | // :77:27: note: when computing vector element at index '0' | |
| 1267 | // :77:27: note: when computing vector element at index '1' | |
| 1276 | 1268 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1277 | // :77:27: note: when computing vector element at index '0' | |
| 1269 | // :77:27: note: when computing vector element at index '1' | |
| 1278 | 1270 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1279 | // :77:27: note: when computing vector element at index '0' | |
| 1271 | // :77:27: note: when computing vector element at index '1' | |
| 1280 | 1272 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1281 | 1273 | // :77:27: note: when computing vector element at index '1' |
| 1282 | 1274 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1283 | 1275 | // :77:27: note: when computing vector element at index '1' |
| 1284 | 1276 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1285 | // :77:27: note: when computing vector element at index '0' | |
| 1277 | // :77:27: note: when computing vector element at index '1' | |
| 1286 | 1278 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1287 | // :77:27: note: when computing vector element at index '0' | |
| 1279 | // :77:27: note: when computing vector element at index '1' | |
| 1288 | 1280 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1289 | // :77:27: note: when computing vector element at index '0' | |
| 1281 | // :77:27: note: when computing vector element at index '1' | |
| 1290 | 1282 | // :77:27: error: use of undefined value here causes illegal behavior |
| 1291 | // :77:27: note: when computing vector element at index '0' | |
| 1283 | // :77:27: note: when computing vector element at index '1' | |
| 1284 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1285 | // :77:27: note: when computing vector element at index '1' | |
| 1286 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1287 | // :77:27: note: when computing vector element at index '1' | |
| 1288 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1289 | // :77:27: note: when computing vector element at index '1' | |
| 1290 | // :77:27: error: use of undefined value here causes illegal behavior | |
| 1291 | // :77:27: note: when computing vector element at index '1' | |
| 1292 | 1292 | // :77:30: error: use of undefined value here causes illegal behavior |
| 1293 | 1293 | // :77:30: note: when computing vector element at index '0' |
| 1294 | 1294 | // :77:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1336,50 +1336,30 @@ const std = @import("std"); |
| 1336 | 1336 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1337 | 1337 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1338 | 1338 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1339 | // :81:17: note: when computing vector element at index '0' | |
| 1340 | 1339 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1341 | // :81:17: note: when computing vector element at index '0' | |
| 1342 | 1340 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1343 | // :81:17: note: when computing vector element at index '0' | |
| 1344 | 1341 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1345 | // :81:17: note: when computing vector element at index '0' | |
| 1346 | 1342 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1347 | // :81:17: note: when computing vector element at index '1' | |
| 1348 | 1343 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1349 | // :81:17: note: when computing vector element at index '1' | |
| 1350 | 1344 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1351 | // :81:17: note: when computing vector element at index '0' | |
| 1352 | 1345 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1353 | // :81:17: note: when computing vector element at index '0' | |
| 1354 | 1346 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1355 | // :81:17: note: when computing vector element at index '0' | |
| 1356 | 1347 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1357 | // :81:17: note: when computing vector element at index '0' | |
| 1358 | 1348 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1359 | 1349 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1360 | 1350 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1361 | // :81:17: note: when computing vector element at index '0' | |
| 1362 | 1351 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1363 | // :81:17: note: when computing vector element at index '0' | |
| 1364 | 1352 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1365 | // :81:17: note: when computing vector element at index '0' | |
| 1366 | 1353 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1367 | // :81:17: note: when computing vector element at index '0' | |
| 1368 | 1354 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1369 | // :81:17: note: when computing vector element at index '1' | |
| 1370 | 1355 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1371 | // :81:17: note: when computing vector element at index '1' | |
| 1372 | 1356 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1373 | // :81:17: note: when computing vector element at index '0' | |
| 1374 | 1357 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1375 | // :81:17: note: when computing vector element at index '0' | |
| 1376 | 1358 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1377 | 1359 | // :81:17: note: when computing vector element at index '0' |
| 1378 | 1360 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1379 | 1361 | // :81:17: note: when computing vector element at index '0' |
| 1380 | 1362 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1381 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1382 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1383 | 1363 | // :81:17: note: when computing vector element at index '0' |
| 1384 | 1364 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1385 | 1365 | // :81:17: note: when computing vector element at index '0' |
| ... | ... | @@ -1388,10 +1368,6 @@ const std = @import("std"); |
| 1388 | 1368 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1389 | 1369 | // :81:17: note: when computing vector element at index '0' |
| 1390 | 1370 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1391 | // :81:17: note: when computing vector element at index '1' | |
| 1392 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1393 | // :81:17: note: when computing vector element at index '1' | |
| 1394 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1395 | 1371 | // :81:17: note: when computing vector element at index '0' |
| 1396 | 1372 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1397 | 1373 | // :81:17: note: when computing vector element at index '0' |
| ... | ... | @@ -1400,7 +1376,9 @@ const std = @import("std"); |
| 1400 | 1376 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1401 | 1377 | // :81:17: note: when computing vector element at index '0' |
| 1402 | 1378 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1379 | // :81:17: note: when computing vector element at index '0' | |
| 1403 | 1380 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1381 | // :81:17: note: when computing vector element at index '0' | |
| 1404 | 1382 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1405 | 1383 | // :81:17: note: when computing vector element at index '0' |
| 1406 | 1384 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1410,9 +1388,9 @@ const std = @import("std"); |
| 1410 | 1388 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1411 | 1389 | // :81:17: note: when computing vector element at index '0' |
| 1412 | 1390 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1413 | // :81:17: note: when computing vector element at index '1' | |
| 1391 | // :81:17: note: when computing vector element at index '0' | |
| 1414 | 1392 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1415 | // :81:17: note: when computing vector element at index '1' | |
| 1393 | // :81:17: note: when computing vector element at index '0' | |
| 1416 | 1394 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1417 | 1395 | // :81:17: note: when computing vector element at index '0' |
| 1418 | 1396 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1422,7 +1400,9 @@ const std = @import("std"); |
| 1422 | 1400 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1423 | 1401 | // :81:17: note: when computing vector element at index '0' |
| 1424 | 1402 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1403 | // :81:17: note: when computing vector element at index '0' | |
| 1425 | 1404 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1405 | // :81:17: note: when computing vector element at index '0' | |
| 1426 | 1406 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1427 | 1407 | // :81:17: note: when computing vector element at index '0' |
| 1428 | 1408 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1432,9 +1412,9 @@ const std = @import("std"); |
| 1432 | 1412 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1433 | 1413 | // :81:17: note: when computing vector element at index '0' |
| 1434 | 1414 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1435 | // :81:17: note: when computing vector element at index '1' | |
| 1415 | // :81:17: note: when computing vector element at index '0' | |
| 1436 | 1416 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1437 | // :81:17: note: when computing vector element at index '1' | |
| 1417 | // :81:17: note: when computing vector element at index '0' | |
| 1438 | 1418 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1439 | 1419 | // :81:17: note: when computing vector element at index '0' |
| 1440 | 1420 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1444,7 +1424,9 @@ const std = @import("std"); |
| 1444 | 1424 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1445 | 1425 | // :81:17: note: when computing vector element at index '0' |
| 1446 | 1426 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1427 | // :81:17: note: when computing vector element at index '0' | |
| 1447 | 1428 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1429 | // :81:17: note: when computing vector element at index '0' | |
| 1448 | 1430 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1449 | 1431 | // :81:17: note: when computing vector element at index '0' |
| 1450 | 1432 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1454,9 +1436,9 @@ const std = @import("std"); |
| 1454 | 1436 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1455 | 1437 | // :81:17: note: when computing vector element at index '0' |
| 1456 | 1438 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1457 | // :81:17: note: when computing vector element at index '1' | |
| 1439 | // :81:17: note: when computing vector element at index '0' | |
| 1458 | 1440 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1459 | // :81:17: note: when computing vector element at index '1' | |
| 1441 | // :81:17: note: when computing vector element at index '0' | |
| 1460 | 1442 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1461 | 1443 | // :81:17: note: when computing vector element at index '0' |
| 1462 | 1444 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1466,7 +1448,9 @@ const std = @import("std"); |
| 1466 | 1448 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1467 | 1449 | // :81:17: note: when computing vector element at index '0' |
| 1468 | 1450 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1451 | // :81:17: note: when computing vector element at index '0' | |
| 1469 | 1452 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1453 | // :81:17: note: when computing vector element at index '0' | |
| 1470 | 1454 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1471 | 1455 | // :81:17: note: when computing vector element at index '0' |
| 1472 | 1456 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1476,9 +1460,9 @@ const std = @import("std"); |
| 1476 | 1460 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1477 | 1461 | // :81:17: note: when computing vector element at index '0' |
| 1478 | 1462 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1479 | // :81:17: note: when computing vector element at index '1' | |
| 1463 | // :81:17: note: when computing vector element at index '0' | |
| 1480 | 1464 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1481 | // :81:17: note: when computing vector element at index '1' | |
| 1465 | // :81:17: note: when computing vector element at index '0' | |
| 1482 | 1466 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1483 | 1467 | // :81:17: note: when computing vector element at index '0' |
| 1484 | 1468 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1488,7 +1472,9 @@ const std = @import("std"); |
| 1488 | 1472 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1489 | 1473 | // :81:17: note: when computing vector element at index '0' |
| 1490 | 1474 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1475 | // :81:17: note: when computing vector element at index '0' | |
| 1491 | 1476 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1477 | // :81:17: note: when computing vector element at index '0' | |
| 1492 | 1478 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1493 | 1479 | // :81:17: note: when computing vector element at index '0' |
| 1494 | 1480 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1498,9 +1484,9 @@ const std = @import("std"); |
| 1498 | 1484 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1499 | 1485 | // :81:17: note: when computing vector element at index '0' |
| 1500 | 1486 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1501 | // :81:17: note: when computing vector element at index '1' | |
| 1487 | // :81:17: note: when computing vector element at index '0' | |
| 1502 | 1488 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1503 | // :81:17: note: when computing vector element at index '1' | |
| 1489 | // :81:17: note: when computing vector element at index '0' | |
| 1504 | 1490 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1505 | 1491 | // :81:17: note: when computing vector element at index '0' |
| 1506 | 1492 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1510,7 +1496,9 @@ const std = @import("std"); |
| 1510 | 1496 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1511 | 1497 | // :81:17: note: when computing vector element at index '0' |
| 1512 | 1498 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1499 | // :81:17: note: when computing vector element at index '0' | |
| 1513 | 1500 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1501 | // :81:17: note: when computing vector element at index '0' | |
| 1514 | 1502 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1515 | 1503 | // :81:17: note: when computing vector element at index '0' |
| 1516 | 1504 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1520,9 +1508,9 @@ const std = @import("std"); |
| 1520 | 1508 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1521 | 1509 | // :81:17: note: when computing vector element at index '0' |
| 1522 | 1510 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1523 | // :81:17: note: when computing vector element at index '1' | |
| 1511 | // :81:17: note: when computing vector element at index '0' | |
| 1524 | 1512 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1525 | // :81:17: note: when computing vector element at index '1' | |
| 1513 | // :81:17: note: when computing vector element at index '0' | |
| 1526 | 1514 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1527 | 1515 | // :81:17: note: when computing vector element at index '0' |
| 1528 | 1516 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1532,7 +1520,9 @@ const std = @import("std"); |
| 1532 | 1520 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1533 | 1521 | // :81:17: note: when computing vector element at index '0' |
| 1534 | 1522 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1523 | // :81:17: note: when computing vector element at index '0' | |
| 1535 | 1524 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1525 | // :81:17: note: when computing vector element at index '0' | |
| 1536 | 1526 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1537 | 1527 | // :81:17: note: when computing vector element at index '0' |
| 1538 | 1528 | // :81:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1546,35 +1536,45 @@ const std = @import("std"); |
| 1546 | 1536 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1547 | 1537 | // :81:17: note: when computing vector element at index '1' |
| 1548 | 1538 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1549 | // :81:17: note: when computing vector element at index '0' | |
| 1539 | // :81:17: note: when computing vector element at index '1' | |
| 1550 | 1540 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1551 | // :81:17: note: when computing vector element at index '0' | |
| 1541 | // :81:17: note: when computing vector element at index '1' | |
| 1552 | 1542 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1553 | // :81:17: note: when computing vector element at index '0' | |
| 1543 | // :81:17: note: when computing vector element at index '1' | |
| 1554 | 1544 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1555 | // :81:17: note: when computing vector element at index '0' | |
| 1545 | // :81:17: note: when computing vector element at index '1' | |
| 1556 | 1546 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1547 | // :81:17: note: when computing vector element at index '1' | |
| 1557 | 1548 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1549 | // :81:17: note: when computing vector element at index '1' | |
| 1558 | 1550 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1559 | // :81:17: note: when computing vector element at index '0' | |
| 1551 | // :81:17: note: when computing vector element at index '1' | |
| 1560 | 1552 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1561 | // :81:17: note: when computing vector element at index '0' | |
| 1553 | // :81:17: note: when computing vector element at index '1' | |
| 1562 | 1554 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1563 | // :81:17: note: when computing vector element at index '0' | |
| 1555 | // :81:17: note: when computing vector element at index '1' | |
| 1564 | 1556 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1565 | // :81:17: note: when computing vector element at index '0' | |
| 1557 | // :81:17: note: when computing vector element at index '1' | |
| 1566 | 1558 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1567 | 1559 | // :81:17: note: when computing vector element at index '1' |
| 1568 | 1560 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1569 | 1561 | // :81:17: note: when computing vector element at index '1' |
| 1570 | 1562 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1571 | // :81:17: note: when computing vector element at index '0' | |
| 1563 | // :81:17: note: when computing vector element at index '1' | |
| 1572 | 1564 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1573 | // :81:17: note: when computing vector element at index '0' | |
| 1565 | // :81:17: note: when computing vector element at index '1' | |
| 1574 | 1566 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1575 | // :81:17: note: when computing vector element at index '0' | |
| 1567 | // :81:17: note: when computing vector element at index '1' | |
| 1576 | 1568 | // :81:17: error: use of undefined value here causes illegal behavior |
| 1577 | // :81:17: note: when computing vector element at index '0' | |
| 1569 | // :81:17: note: when computing vector element at index '1' | |
| 1570 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1571 | // :81:17: note: when computing vector element at index '1' | |
| 1572 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1573 | // :81:17: note: when computing vector element at index '1' | |
| 1574 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1575 | // :81:17: note: when computing vector element at index '1' | |
| 1576 | // :81:17: error: use of undefined value here causes illegal behavior | |
| 1577 | // :81:17: note: when computing vector element at index '1' | |
| 1578 | 1578 | // :81:21: error: use of undefined value here causes illegal behavior |
| 1579 | 1579 | // :81:21: note: when computing vector element at index '0' |
| 1580 | 1580 | // :81:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1622,39 +1622,25 @@ const std = @import("std"); |
| 1622 | 1622 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1623 | 1623 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1624 | 1624 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1625 | // :85:22: note: when computing vector element at index '0' | |
| 1626 | 1625 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1627 | // :85:22: note: when computing vector element at index '0' | |
| 1628 | 1626 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1629 | // :85:22: note: when computing vector element at index '0' | |
| 1630 | 1627 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1631 | // :85:22: note: when computing vector element at index '0' | |
| 1632 | 1628 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1633 | // :85:22: note: when computing vector element at index '1' | |
| 1634 | 1629 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1635 | // :85:22: note: when computing vector element at index '1' | |
| 1636 | 1630 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1637 | // :85:22: note: when computing vector element at index '0' | |
| 1638 | 1631 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1639 | // :85:22: note: when computing vector element at index '0' | |
| 1640 | 1632 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1641 | // :85:22: note: when computing vector element at index '0' | |
| 1642 | 1633 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1643 | // :85:22: note: when computing vector element at index '0' | |
| 1644 | 1634 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1645 | 1635 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1646 | 1636 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1647 | // :85:22: note: when computing vector element at index '0' | |
| 1648 | 1637 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1649 | // :85:22: note: when computing vector element at index '0' | |
| 1650 | 1638 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1651 | // :85:22: note: when computing vector element at index '0' | |
| 1652 | 1639 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1653 | // :85:22: note: when computing vector element at index '0' | |
| 1654 | 1640 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1655 | // :85:22: note: when computing vector element at index '1' | |
| 1656 | 1641 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1657 | // :85:22: note: when computing vector element at index '1' | |
| 1642 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1643 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1658 | 1644 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1659 | 1645 | // :85:22: note: when computing vector element at index '0' |
| 1660 | 1646 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1664,7 +1650,9 @@ const std = @import("std"); |
| 1664 | 1650 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1665 | 1651 | // :85:22: note: when computing vector element at index '0' |
| 1666 | 1652 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1653 | // :85:22: note: when computing vector element at index '0' | |
| 1667 | 1654 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1655 | // :85:22: note: when computing vector element at index '0' | |
| 1668 | 1656 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1669 | 1657 | // :85:22: note: when computing vector element at index '0' |
| 1670 | 1658 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1674,9 +1662,9 @@ const std = @import("std"); |
| 1674 | 1662 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1675 | 1663 | // :85:22: note: when computing vector element at index '0' |
| 1676 | 1664 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1677 | // :85:22: note: when computing vector element at index '1' | |
| 1665 | // :85:22: note: when computing vector element at index '0' | |
| 1678 | 1666 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1679 | // :85:22: note: when computing vector element at index '1' | |
| 1667 | // :85:22: note: when computing vector element at index '0' | |
| 1680 | 1668 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1681 | 1669 | // :85:22: note: when computing vector element at index '0' |
| 1682 | 1670 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1686,7 +1674,9 @@ const std = @import("std"); |
| 1686 | 1674 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1687 | 1675 | // :85:22: note: when computing vector element at index '0' |
| 1688 | 1676 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1677 | // :85:22: note: when computing vector element at index '0' | |
| 1689 | 1678 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1679 | // :85:22: note: when computing vector element at index '0' | |
| 1690 | 1680 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1691 | 1681 | // :85:22: note: when computing vector element at index '0' |
| 1692 | 1682 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1696,9 +1686,9 @@ const std = @import("std"); |
| 1696 | 1686 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1697 | 1687 | // :85:22: note: when computing vector element at index '0' |
| 1698 | 1688 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1699 | // :85:22: note: when computing vector element at index '1' | |
| 1689 | // :85:22: note: when computing vector element at index '0' | |
| 1700 | 1690 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1701 | // :85:22: note: when computing vector element at index '1' | |
| 1691 | // :85:22: note: when computing vector element at index '0' | |
| 1702 | 1692 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1703 | 1693 | // :85:22: note: when computing vector element at index '0' |
| 1704 | 1694 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1708,7 +1698,9 @@ const std = @import("std"); |
| 1708 | 1698 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1709 | 1699 | // :85:22: note: when computing vector element at index '0' |
| 1710 | 1700 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1701 | // :85:22: note: when computing vector element at index '0' | |
| 1711 | 1702 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1703 | // :85:22: note: when computing vector element at index '0' | |
| 1712 | 1704 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1713 | 1705 | // :85:22: note: when computing vector element at index '0' |
| 1714 | 1706 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1718,10 +1710,6 @@ const std = @import("std"); |
| 1718 | 1710 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1719 | 1711 | // :85:22: note: when computing vector element at index '0' |
| 1720 | 1712 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1721 | // :85:22: note: when computing vector element at index '1' | |
| 1722 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1723 | // :85:22: note: when computing vector element at index '1' | |
| 1724 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1725 | 1713 | // :85:22: note: when computing vector element at index '0' |
| 1726 | 1714 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1727 | 1715 | // :85:22: note: when computing vector element at index '0' |
| ... | ... | @@ -1730,8 +1718,6 @@ const std = @import("std"); |
| 1730 | 1718 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1731 | 1719 | // :85:22: note: when computing vector element at index '0' |
| 1732 | 1720 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1733 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1734 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1735 | 1721 | // :85:22: note: when computing vector element at index '0' |
| 1736 | 1722 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1737 | 1723 | // :85:22: note: when computing vector element at index '0' |
| ... | ... | @@ -1740,10 +1726,6 @@ const std = @import("std"); |
| 1740 | 1726 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1741 | 1727 | // :85:22: note: when computing vector element at index '0' |
| 1742 | 1728 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1743 | // :85:22: note: when computing vector element at index '1' | |
| 1744 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1745 | // :85:22: note: when computing vector element at index '1' | |
| 1746 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1747 | 1729 | // :85:22: note: when computing vector element at index '0' |
| 1748 | 1730 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1749 | 1731 | // :85:22: note: when computing vector element at index '0' |
| ... | ... | @@ -1752,7 +1734,9 @@ const std = @import("std"); |
| 1752 | 1734 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1753 | 1735 | // :85:22: note: when computing vector element at index '0' |
| 1754 | 1736 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1737 | // :85:22: note: when computing vector element at index '0' | |
| 1755 | 1738 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1739 | // :85:22: note: when computing vector element at index '0' | |
| 1756 | 1740 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1757 | 1741 | // :85:22: note: when computing vector element at index '0' |
| 1758 | 1742 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1762,9 +1746,9 @@ const std = @import("std"); |
| 1762 | 1746 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1763 | 1747 | // :85:22: note: when computing vector element at index '0' |
| 1764 | 1748 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1765 | // :85:22: note: when computing vector element at index '1' | |
| 1749 | // :85:22: note: when computing vector element at index '0' | |
| 1766 | 1750 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1767 | // :85:22: note: when computing vector element at index '1' | |
| 1751 | // :85:22: note: when computing vector element at index '0' | |
| 1768 | 1752 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1769 | 1753 | // :85:22: note: when computing vector element at index '0' |
| 1770 | 1754 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1774,7 +1758,9 @@ const std = @import("std"); |
| 1774 | 1758 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1775 | 1759 | // :85:22: note: when computing vector element at index '0' |
| 1776 | 1760 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1761 | // :85:22: note: when computing vector element at index '0' | |
| 1777 | 1762 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1763 | // :85:22: note: when computing vector element at index '0' | |
| 1778 | 1764 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1779 | 1765 | // :85:22: note: when computing vector element at index '0' |
| 1780 | 1766 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1784,9 +1770,9 @@ const std = @import("std"); |
| 1784 | 1770 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1785 | 1771 | // :85:22: note: when computing vector element at index '0' |
| 1786 | 1772 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1787 | // :85:22: note: when computing vector element at index '1' | |
| 1773 | // :85:22: note: when computing vector element at index '0' | |
| 1788 | 1774 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1789 | // :85:22: note: when computing vector element at index '1' | |
| 1775 | // :85:22: note: when computing vector element at index '0' | |
| 1790 | 1776 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1791 | 1777 | // :85:22: note: when computing vector element at index '0' |
| 1792 | 1778 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1796,7 +1782,9 @@ const std = @import("std"); |
| 1796 | 1782 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1797 | 1783 | // :85:22: note: when computing vector element at index '0' |
| 1798 | 1784 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1785 | // :85:22: note: when computing vector element at index '0' | |
| 1799 | 1786 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1787 | // :85:22: note: when computing vector element at index '0' | |
| 1800 | 1788 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1801 | 1789 | // :85:22: note: when computing vector element at index '0' |
| 1802 | 1790 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1806,9 +1794,9 @@ const std = @import("std"); |
| 1806 | 1794 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1807 | 1795 | // :85:22: note: when computing vector element at index '0' |
| 1808 | 1796 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1809 | // :85:22: note: when computing vector element at index '1' | |
| 1797 | // :85:22: note: when computing vector element at index '0' | |
| 1810 | 1798 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1811 | // :85:22: note: when computing vector element at index '1' | |
| 1799 | // :85:22: note: when computing vector element at index '0' | |
| 1812 | 1800 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1813 | 1801 | // :85:22: note: when computing vector element at index '0' |
| 1814 | 1802 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1818,7 +1806,9 @@ const std = @import("std"); |
| 1818 | 1806 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1819 | 1807 | // :85:22: note: when computing vector element at index '0' |
| 1820 | 1808 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1809 | // :85:22: note: when computing vector element at index '0' | |
| 1821 | 1810 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1811 | // :85:22: note: when computing vector element at index '0' | |
| 1822 | 1812 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1823 | 1813 | // :85:22: note: when computing vector element at index '0' |
| 1824 | 1814 | // :85:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1832,35 +1822,45 @@ const std = @import("std"); |
| 1832 | 1822 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1833 | 1823 | // :85:22: note: when computing vector element at index '1' |
| 1834 | 1824 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1835 | // :85:22: note: when computing vector element at index '0' | |
| 1825 | // :85:22: note: when computing vector element at index '1' | |
| 1836 | 1826 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1837 | // :85:22: note: when computing vector element at index '0' | |
| 1827 | // :85:22: note: when computing vector element at index '1' | |
| 1838 | 1828 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1839 | // :85:22: note: when computing vector element at index '0' | |
| 1829 | // :85:22: note: when computing vector element at index '1' | |
| 1840 | 1830 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1841 | // :85:22: note: when computing vector element at index '0' | |
| 1831 | // :85:22: note: when computing vector element at index '1' | |
| 1842 | 1832 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1833 | // :85:22: note: when computing vector element at index '1' | |
| 1843 | 1834 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1835 | // :85:22: note: when computing vector element at index '1' | |
| 1844 | 1836 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1845 | // :85:22: note: when computing vector element at index '0' | |
| 1837 | // :85:22: note: when computing vector element at index '1' | |
| 1846 | 1838 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1847 | // :85:22: note: when computing vector element at index '0' | |
| 1839 | // :85:22: note: when computing vector element at index '1' | |
| 1848 | 1840 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1849 | // :85:22: note: when computing vector element at index '0' | |
| 1841 | // :85:22: note: when computing vector element at index '1' | |
| 1850 | 1842 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1851 | // :85:22: note: when computing vector element at index '0' | |
| 1843 | // :85:22: note: when computing vector element at index '1' | |
| 1852 | 1844 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1853 | 1845 | // :85:22: note: when computing vector element at index '1' |
| 1854 | 1846 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1855 | 1847 | // :85:22: note: when computing vector element at index '1' |
| 1856 | 1848 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1857 | // :85:22: note: when computing vector element at index '0' | |
| 1849 | // :85:22: note: when computing vector element at index '1' | |
| 1858 | 1850 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1859 | // :85:22: note: when computing vector element at index '0' | |
| 1851 | // :85:22: note: when computing vector element at index '1' | |
| 1860 | 1852 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1861 | // :85:22: note: when computing vector element at index '0' | |
| 1853 | // :85:22: note: when computing vector element at index '1' | |
| 1862 | 1854 | // :85:22: error: use of undefined value here causes illegal behavior |
| 1863 | // :85:22: note: when computing vector element at index '0' | |
| 1855 | // :85:22: note: when computing vector element at index '1' | |
| 1856 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1857 | // :85:22: note: when computing vector element at index '1' | |
| 1858 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1859 | // :85:22: note: when computing vector element at index '1' | |
| 1860 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1861 | // :85:22: note: when computing vector element at index '1' | |
| 1862 | // :85:22: error: use of undefined value here causes illegal behavior | |
| 1863 | // :85:22: note: when computing vector element at index '1' | |
| 1864 | 1864 | // :85:25: error: use of undefined value here causes illegal behavior |
| 1865 | 1865 | // :85:25: note: when computing vector element at index '0' |
| 1866 | 1866 | // :85:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1908,50 +1908,30 @@ const std = @import("std"); |
| 1908 | 1908 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1909 | 1909 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1910 | 1910 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1911 | // :89:22: note: when computing vector element at index '0' | |
| 1912 | 1911 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1913 | // :89:22: note: when computing vector element at index '0' | |
| 1914 | 1912 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1915 | // :89:22: note: when computing vector element at index '0' | |
| 1916 | 1913 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1917 | // :89:22: note: when computing vector element at index '0' | |
| 1918 | 1914 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1919 | // :89:22: note: when computing vector element at index '1' | |
| 1920 | 1915 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1921 | // :89:22: note: when computing vector element at index '1' | |
| 1922 | 1916 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1923 | // :89:22: note: when computing vector element at index '0' | |
| 1924 | 1917 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1925 | // :89:22: note: when computing vector element at index '0' | |
| 1926 | 1918 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1927 | // :89:22: note: when computing vector element at index '0' | |
| 1928 | 1919 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1929 | // :89:22: note: when computing vector element at index '0' | |
| 1930 | 1920 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1931 | 1921 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1932 | 1922 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1933 | // :89:22: note: when computing vector element at index '0' | |
| 1934 | 1923 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1935 | // :89:22: note: when computing vector element at index '0' | |
| 1936 | 1924 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1937 | // :89:22: note: when computing vector element at index '0' | |
| 1938 | 1925 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1939 | // :89:22: note: when computing vector element at index '0' | |
| 1940 | 1926 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1941 | // :89:22: note: when computing vector element at index '1' | |
| 1942 | 1927 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1943 | // :89:22: note: when computing vector element at index '1' | |
| 1944 | 1928 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1945 | // :89:22: note: when computing vector element at index '0' | |
| 1946 | 1929 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1947 | // :89:22: note: when computing vector element at index '0' | |
| 1948 | 1930 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1949 | 1931 | // :89:22: note: when computing vector element at index '0' |
| 1950 | 1932 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1951 | 1933 | // :89:22: note: when computing vector element at index '0' |
| 1952 | 1934 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1953 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 1954 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 1955 | 1935 | // :89:22: note: when computing vector element at index '0' |
| 1956 | 1936 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1957 | 1937 | // :89:22: note: when computing vector element at index '0' |
| ... | ... | @@ -1960,10 +1940,6 @@ const std = @import("std"); |
| 1960 | 1940 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1961 | 1941 | // :89:22: note: when computing vector element at index '0' |
| 1962 | 1942 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1963 | // :89:22: note: when computing vector element at index '1' | |
| 1964 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 1965 | // :89:22: note: when computing vector element at index '1' | |
| 1966 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 1967 | 1943 | // :89:22: note: when computing vector element at index '0' |
| 1968 | 1944 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1969 | 1945 | // :89:22: note: when computing vector element at index '0' |
| ... | ... | @@ -1972,7 +1948,9 @@ const std = @import("std"); |
| 1972 | 1948 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1973 | 1949 | // :89:22: note: when computing vector element at index '0' |
| 1974 | 1950 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1951 | // :89:22: note: when computing vector element at index '0' | |
| 1975 | 1952 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1953 | // :89:22: note: when computing vector element at index '0' | |
| 1976 | 1954 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1977 | 1955 | // :89:22: note: when computing vector element at index '0' |
| 1978 | 1956 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1982,9 +1960,9 @@ const std = @import("std"); |
| 1982 | 1960 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1983 | 1961 | // :89:22: note: when computing vector element at index '0' |
| 1984 | 1962 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1985 | // :89:22: note: when computing vector element at index '1' | |
| 1963 | // :89:22: note: when computing vector element at index '0' | |
| 1986 | 1964 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1987 | // :89:22: note: when computing vector element at index '1' | |
| 1965 | // :89:22: note: when computing vector element at index '0' | |
| 1988 | 1966 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1989 | 1967 | // :89:22: note: when computing vector element at index '0' |
| 1990 | 1968 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1994,7 +1972,9 @@ const std = @import("std"); |
| 1994 | 1972 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1995 | 1973 | // :89:22: note: when computing vector element at index '0' |
| 1996 | 1974 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1975 | // :89:22: note: when computing vector element at index '0' | |
| 1997 | 1976 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1977 | // :89:22: note: when computing vector element at index '0' | |
| 1998 | 1978 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1999 | 1979 | // :89:22: note: when computing vector element at index '0' |
| 2000 | 1980 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2004,9 +1984,9 @@ const std = @import("std"); |
| 2004 | 1984 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2005 | 1985 | // :89:22: note: when computing vector element at index '0' |
| 2006 | 1986 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2007 | // :89:22: note: when computing vector element at index '1' | |
| 1987 | // :89:22: note: when computing vector element at index '0' | |
| 2008 | 1988 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2009 | // :89:22: note: when computing vector element at index '1' | |
| 1989 | // :89:22: note: when computing vector element at index '0' | |
| 2010 | 1990 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2011 | 1991 | // :89:22: note: when computing vector element at index '0' |
| 2012 | 1992 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2016,7 +1996,9 @@ const std = @import("std"); |
| 2016 | 1996 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2017 | 1997 | // :89:22: note: when computing vector element at index '0' |
| 2018 | 1998 | // :89:22: error: use of undefined value here causes illegal behavior |
| 1999 | // :89:22: note: when computing vector element at index '0' | |
| 2019 | 2000 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2001 | // :89:22: note: when computing vector element at index '0' | |
| 2020 | 2002 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2021 | 2003 | // :89:22: note: when computing vector element at index '0' |
| 2022 | 2004 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2026,9 +2008,9 @@ const std = @import("std"); |
| 2026 | 2008 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2027 | 2009 | // :89:22: note: when computing vector element at index '0' |
| 2028 | 2010 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2029 | // :89:22: note: when computing vector element at index '1' | |
| 2011 | // :89:22: note: when computing vector element at index '0' | |
| 2030 | 2012 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2031 | // :89:22: note: when computing vector element at index '1' | |
| 2013 | // :89:22: note: when computing vector element at index '0' | |
| 2032 | 2014 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2033 | 2015 | // :89:22: note: when computing vector element at index '0' |
| 2034 | 2016 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2038,7 +2020,9 @@ const std = @import("std"); |
| 2038 | 2020 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2039 | 2021 | // :89:22: note: when computing vector element at index '0' |
| 2040 | 2022 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2023 | // :89:22: note: when computing vector element at index '0' | |
| 2041 | 2024 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2025 | // :89:22: note: when computing vector element at index '0' | |
| 2042 | 2026 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2043 | 2027 | // :89:22: note: when computing vector element at index '0' |
| 2044 | 2028 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2048,9 +2032,9 @@ const std = @import("std"); |
| 2048 | 2032 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2049 | 2033 | // :89:22: note: when computing vector element at index '0' |
| 2050 | 2034 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2051 | // :89:22: note: when computing vector element at index '1' | |
| 2035 | // :89:22: note: when computing vector element at index '0' | |
| 2052 | 2036 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2053 | // :89:22: note: when computing vector element at index '1' | |
| 2037 | // :89:22: note: when computing vector element at index '0' | |
| 2054 | 2038 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2055 | 2039 | // :89:22: note: when computing vector element at index '0' |
| 2056 | 2040 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2060,7 +2044,9 @@ const std = @import("std"); |
| 2060 | 2044 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2061 | 2045 | // :89:22: note: when computing vector element at index '0' |
| 2062 | 2046 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2047 | // :89:22: note: when computing vector element at index '0' | |
| 2063 | 2048 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2049 | // :89:22: note: when computing vector element at index '0' | |
| 2064 | 2050 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2065 | 2051 | // :89:22: note: when computing vector element at index '0' |
| 2066 | 2052 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2070,9 +2056,9 @@ const std = @import("std"); |
| 2070 | 2056 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2071 | 2057 | // :89:22: note: when computing vector element at index '0' |
| 2072 | 2058 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2073 | // :89:22: note: when computing vector element at index '1' | |
| 2059 | // :89:22: note: when computing vector element at index '0' | |
| 2074 | 2060 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2075 | // :89:22: note: when computing vector element at index '1' | |
| 2061 | // :89:22: note: when computing vector element at index '0' | |
| 2076 | 2062 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2077 | 2063 | // :89:22: note: when computing vector element at index '0' |
| 2078 | 2064 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2082,7 +2068,9 @@ const std = @import("std"); |
| 2082 | 2068 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2083 | 2069 | // :89:22: note: when computing vector element at index '0' |
| 2084 | 2070 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2071 | // :89:22: note: when computing vector element at index '0' | |
| 2085 | 2072 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2073 | // :89:22: note: when computing vector element at index '0' | |
| 2086 | 2074 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2087 | 2075 | // :89:22: note: when computing vector element at index '0' |
| 2088 | 2076 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2092,9 +2080,9 @@ const std = @import("std"); |
| 2092 | 2080 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2093 | 2081 | // :89:22: note: when computing vector element at index '0' |
| 2094 | 2082 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2095 | // :89:22: note: when computing vector element at index '1' | |
| 2083 | // :89:22: note: when computing vector element at index '0' | |
| 2096 | 2084 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2097 | // :89:22: note: when computing vector element at index '1' | |
| 2085 | // :89:22: note: when computing vector element at index '0' | |
| 2098 | 2086 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2099 | 2087 | // :89:22: note: when computing vector element at index '0' |
| 2100 | 2088 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2104,7 +2092,9 @@ const std = @import("std"); |
| 2104 | 2092 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2105 | 2093 | // :89:22: note: when computing vector element at index '0' |
| 2106 | 2094 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2095 | // :89:22: note: when computing vector element at index '0' | |
| 2107 | 2096 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2097 | // :89:22: note: when computing vector element at index '0' | |
| 2108 | 2098 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2109 | 2099 | // :89:22: note: when computing vector element at index '0' |
| 2110 | 2100 | // :89:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2118,35 +2108,45 @@ const std = @import("std"); |
| 2118 | 2108 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2119 | 2109 | // :89:22: note: when computing vector element at index '1' |
| 2120 | 2110 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2121 | // :89:22: note: when computing vector element at index '0' | |
| 2111 | // :89:22: note: when computing vector element at index '1' | |
| 2122 | 2112 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2123 | // :89:22: note: when computing vector element at index '0' | |
| 2113 | // :89:22: note: when computing vector element at index '1' | |
| 2124 | 2114 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2125 | // :89:22: note: when computing vector element at index '0' | |
| 2115 | // :89:22: note: when computing vector element at index '1' | |
| 2126 | 2116 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2127 | // :89:22: note: when computing vector element at index '0' | |
| 2117 | // :89:22: note: when computing vector element at index '1' | |
| 2128 | 2118 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2119 | // :89:22: note: when computing vector element at index '1' | |
| 2129 | 2120 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2121 | // :89:22: note: when computing vector element at index '1' | |
| 2130 | 2122 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2131 | // :89:22: note: when computing vector element at index '0' | |
| 2123 | // :89:22: note: when computing vector element at index '1' | |
| 2132 | 2124 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2133 | // :89:22: note: when computing vector element at index '0' | |
| 2125 | // :89:22: note: when computing vector element at index '1' | |
| 2134 | 2126 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2135 | // :89:22: note: when computing vector element at index '0' | |
| 2127 | // :89:22: note: when computing vector element at index '1' | |
| 2136 | 2128 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2137 | // :89:22: note: when computing vector element at index '0' | |
| 2129 | // :89:22: note: when computing vector element at index '1' | |
| 2138 | 2130 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2139 | 2131 | // :89:22: note: when computing vector element at index '1' |
| 2140 | 2132 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2141 | 2133 | // :89:22: note: when computing vector element at index '1' |
| 2142 | 2134 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2143 | // :89:22: note: when computing vector element at index '0' | |
| 2135 | // :89:22: note: when computing vector element at index '1' | |
| 2144 | 2136 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2145 | // :89:22: note: when computing vector element at index '0' | |
| 2137 | // :89:22: note: when computing vector element at index '1' | |
| 2146 | 2138 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2147 | // :89:22: note: when computing vector element at index '0' | |
| 2139 | // :89:22: note: when computing vector element at index '1' | |
| 2148 | 2140 | // :89:22: error: use of undefined value here causes illegal behavior |
| 2149 | // :89:22: note: when computing vector element at index '0' | |
| 2141 | // :89:22: note: when computing vector element at index '1' | |
| 2142 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 2143 | // :89:22: note: when computing vector element at index '1' | |
| 2144 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 2145 | // :89:22: note: when computing vector element at index '1' | |
| 2146 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 2147 | // :89:22: note: when computing vector element at index '1' | |
| 2148 | // :89:22: error: use of undefined value here causes illegal behavior | |
| 2149 | // :89:22: note: when computing vector element at index '1' | |
| 2150 | 2150 | // :89:25: error: use of undefined value here causes illegal behavior |
| 2151 | 2151 | // :89:25: note: when computing vector element at index '0' |
| 2152 | 2152 | // :89:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2198,21 +2198,13 @@ const std = @import("std"); |
| 2198 | 2198 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2199 | 2199 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2200 | 2200 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2201 | // :95:17: note: when computing vector element at index '1' | |
| 2202 | 2201 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2203 | // :95:17: note: when computing vector element at index '1' | |
| 2204 | 2202 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2205 | // :95:17: note: when computing vector element at index '1' | |
| 2206 | 2203 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2207 | // :95:17: note: when computing vector element at index '1' | |
| 2208 | 2204 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2209 | // :95:17: note: when computing vector element at index '0' | |
| 2210 | 2205 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2211 | // :95:17: note: when computing vector element at index '0' | |
| 2212 | 2206 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2213 | // :95:17: note: when computing vector element at index '0' | |
| 2214 | 2207 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2215 | // :95:17: note: when computing vector element at index '0' | |
| 2216 | 2208 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2217 | 2209 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2218 | 2210 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2220,21 +2212,13 @@ const std = @import("std"); |
| 2220 | 2212 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2221 | 2213 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2222 | 2214 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2223 | // :95:17: note: when computing vector element at index '1' | |
| 2224 | 2215 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2225 | // :95:17: note: when computing vector element at index '1' | |
| 2226 | 2216 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2227 | // :95:17: note: when computing vector element at index '1' | |
| 2228 | 2217 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2229 | // :95:17: note: when computing vector element at index '1' | |
| 2230 | 2218 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2231 | // :95:17: note: when computing vector element at index '0' | |
| 2232 | 2219 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2233 | // :95:17: note: when computing vector element at index '0' | |
| 2234 | 2220 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2235 | // :95:17: note: when computing vector element at index '0' | |
| 2236 | 2221 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2237 | // :95:17: note: when computing vector element at index '0' | |
| 2238 | 2222 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2239 | 2223 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2240 | 2224 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2242,21 +2226,13 @@ const std = @import("std"); |
| 2242 | 2226 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2243 | 2227 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2244 | 2228 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2245 | // :95:17: note: when computing vector element at index '1' | |
| 2246 | 2229 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2247 | // :95:17: note: when computing vector element at index '1' | |
| 2248 | 2230 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2249 | // :95:17: note: when computing vector element at index '1' | |
| 2250 | 2231 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2251 | // :95:17: note: when computing vector element at index '1' | |
| 2252 | 2232 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2253 | // :95:17: note: when computing vector element at index '0' | |
| 2254 | 2233 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2255 | // :95:17: note: when computing vector element at index '0' | |
| 2256 | 2234 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2257 | // :95:17: note: when computing vector element at index '0' | |
| 2258 | 2235 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2259 | // :95:17: note: when computing vector element at index '0' | |
| 2260 | 2236 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2261 | 2237 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2262 | 2238 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2264,21 +2240,13 @@ const std = @import("std"); |
| 2264 | 2240 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2265 | 2241 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2266 | 2242 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2267 | // :95:17: note: when computing vector element at index '1' | |
| 2268 | 2243 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2269 | // :95:17: note: when computing vector element at index '1' | |
| 2270 | 2244 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2271 | // :95:17: note: when computing vector element at index '1' | |
| 2272 | 2245 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2273 | // :95:17: note: when computing vector element at index '1' | |
| 2274 | 2246 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2275 | // :95:17: note: when computing vector element at index '0' | |
| 2276 | 2247 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2277 | // :95:17: note: when computing vector element at index '0' | |
| 2278 | 2248 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2279 | // :95:17: note: when computing vector element at index '0' | |
| 2280 | 2249 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2281 | // :95:17: note: when computing vector element at index '0' | |
| 2282 | 2250 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2283 | 2251 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2284 | 2252 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2286,13 +2254,9 @@ const std = @import("std"); |
| 2286 | 2254 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2287 | 2255 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2288 | 2256 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2289 | // :95:17: note: when computing vector element at index '1' | |
| 2290 | 2257 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2291 | // :95:17: note: when computing vector element at index '1' | |
| 2292 | 2258 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2293 | // :95:17: note: when computing vector element at index '1' | |
| 2294 | 2259 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2295 | // :95:17: note: when computing vector element at index '1' | |
| 2296 | 2260 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2297 | 2261 | // :95:17: note: when computing vector element at index '0' |
| 2298 | 2262 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2302,19 +2266,21 @@ const std = @import("std"); |
| 2302 | 2266 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2303 | 2267 | // :95:17: note: when computing vector element at index '0' |
| 2304 | 2268 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2269 | // :95:17: note: when computing vector element at index '0' | |
| 2305 | 2270 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2271 | // :95:17: note: when computing vector element at index '0' | |
| 2306 | 2272 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2273 | // :95:17: note: when computing vector element at index '0' | |
| 2307 | 2274 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2275 | // :95:17: note: when computing vector element at index '0' | |
| 2308 | 2276 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2277 | // :95:17: note: when computing vector element at index '0' | |
| 2309 | 2278 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2279 | // :95:17: note: when computing vector element at index '0' | |
| 2310 | 2280 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2311 | // :95:17: note: when computing vector element at index '1' | |
| 2312 | // :95:17: error: use of undefined value here causes illegal behavior | |
| 2313 | // :95:17: note: when computing vector element at index '1' | |
| 2314 | // :95:17: error: use of undefined value here causes illegal behavior | |
| 2315 | // :95:17: note: when computing vector element at index '1' | |
| 2281 | // :95:17: note: when computing vector element at index '0' | |
| 2316 | 2282 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2317 | // :95:17: note: when computing vector element at index '1' | |
| 2283 | // :95:17: note: when computing vector element at index '0' | |
| 2318 | 2284 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2319 | 2285 | // :95:17: note: when computing vector element at index '0' |
| 2320 | 2286 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2324,19 +2290,25 @@ const std = @import("std"); |
| 2324 | 2290 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2325 | 2291 | // :95:17: note: when computing vector element at index '0' |
| 2326 | 2292 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2293 | // :95:17: note: when computing vector element at index '0' | |
| 2327 | 2294 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2295 | // :95:17: note: when computing vector element at index '0' | |
| 2328 | 2296 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2297 | // :95:17: note: when computing vector element at index '0' | |
| 2329 | 2298 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2299 | // :95:17: note: when computing vector element at index '0' | |
| 2330 | 2300 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2301 | // :95:17: note: when computing vector element at index '0' | |
| 2331 | 2302 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2303 | // :95:17: note: when computing vector element at index '0' | |
| 2332 | 2304 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2333 | // :95:17: note: when computing vector element at index '1' | |
| 2305 | // :95:17: note: when computing vector element at index '0' | |
| 2334 | 2306 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2335 | // :95:17: note: when computing vector element at index '1' | |
| 2307 | // :95:17: note: when computing vector element at index '0' | |
| 2336 | 2308 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2337 | // :95:17: note: when computing vector element at index '1' | |
| 2309 | // :95:17: note: when computing vector element at index '0' | |
| 2338 | 2310 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2339 | // :95:17: note: when computing vector element at index '1' | |
| 2311 | // :95:17: note: when computing vector element at index '0' | |
| 2340 | 2312 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2341 | 2313 | // :95:17: note: when computing vector element at index '0' |
| 2342 | 2314 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2346,19 +2318,25 @@ const std = @import("std"); |
| 2346 | 2318 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2347 | 2319 | // :95:17: note: when computing vector element at index '0' |
| 2348 | 2320 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2321 | // :95:17: note: when computing vector element at index '0' | |
| 2349 | 2322 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2323 | // :95:17: note: when computing vector element at index '0' | |
| 2350 | 2324 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2325 | // :95:17: note: when computing vector element at index '0' | |
| 2351 | 2326 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2327 | // :95:17: note: when computing vector element at index '0' | |
| 2352 | 2328 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2329 | // :95:17: note: when computing vector element at index '0' | |
| 2353 | 2330 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2331 | // :95:17: note: when computing vector element at index '0' | |
| 2354 | 2332 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2355 | // :95:17: note: when computing vector element at index '1' | |
| 2333 | // :95:17: note: when computing vector element at index '0' | |
| 2356 | 2334 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2357 | // :95:17: note: when computing vector element at index '1' | |
| 2335 | // :95:17: note: when computing vector element at index '0' | |
| 2358 | 2336 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2359 | // :95:17: note: when computing vector element at index '1' | |
| 2337 | // :95:17: note: when computing vector element at index '0' | |
| 2360 | 2338 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2361 | // :95:17: note: when computing vector element at index '1' | |
| 2339 | // :95:17: note: when computing vector element at index '0' | |
| 2362 | 2340 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2363 | 2341 | // :95:17: note: when computing vector element at index '0' |
| 2364 | 2342 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2368,11 +2346,17 @@ const std = @import("std"); |
| 2368 | 2346 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2369 | 2347 | // :95:17: note: when computing vector element at index '0' |
| 2370 | 2348 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2349 | // :95:17: note: when computing vector element at index '1' | |
| 2371 | 2350 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2351 | // :95:17: note: when computing vector element at index '1' | |
| 2372 | 2352 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2353 | // :95:17: note: when computing vector element at index '1' | |
| 2373 | 2354 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2355 | // :95:17: note: when computing vector element at index '1' | |
| 2374 | 2356 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2357 | // :95:17: note: when computing vector element at index '1' | |
| 2375 | 2358 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2359 | // :95:17: note: when computing vector element at index '1' | |
| 2376 | 2360 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2377 | 2361 | // :95:17: note: when computing vector element at index '1' |
| 2378 | 2362 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2382,19 +2366,25 @@ const std = @import("std"); |
| 2382 | 2366 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2383 | 2367 | // :95:17: note: when computing vector element at index '1' |
| 2384 | 2368 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2385 | // :95:17: note: when computing vector element at index '0' | |
| 2369 | // :95:17: note: when computing vector element at index '1' | |
| 2386 | 2370 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2387 | // :95:17: note: when computing vector element at index '0' | |
| 2371 | // :95:17: note: when computing vector element at index '1' | |
| 2388 | 2372 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2389 | // :95:17: note: when computing vector element at index '0' | |
| 2373 | // :95:17: note: when computing vector element at index '1' | |
| 2390 | 2374 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2391 | // :95:17: note: when computing vector element at index '0' | |
| 2375 | // :95:17: note: when computing vector element at index '1' | |
| 2392 | 2376 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2377 | // :95:17: note: when computing vector element at index '1' | |
| 2393 | 2378 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2379 | // :95:17: note: when computing vector element at index '1' | |
| 2394 | 2380 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2381 | // :95:17: note: when computing vector element at index '1' | |
| 2395 | 2382 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2383 | // :95:17: note: when computing vector element at index '1' | |
| 2396 | 2384 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2385 | // :95:17: note: when computing vector element at index '1' | |
| 2397 | 2386 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2387 | // :95:17: note: when computing vector element at index '1' | |
| 2398 | 2388 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2399 | 2389 | // :95:17: note: when computing vector element at index '1' |
| 2400 | 2390 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2404,19 +2394,25 @@ const std = @import("std"); |
| 2404 | 2394 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2405 | 2395 | // :95:17: note: when computing vector element at index '1' |
| 2406 | 2396 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2407 | // :95:17: note: when computing vector element at index '0' | |
| 2397 | // :95:17: note: when computing vector element at index '1' | |
| 2408 | 2398 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2409 | // :95:17: note: when computing vector element at index '0' | |
| 2399 | // :95:17: note: when computing vector element at index '1' | |
| 2410 | 2400 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2411 | // :95:17: note: when computing vector element at index '0' | |
| 2401 | // :95:17: note: when computing vector element at index '1' | |
| 2412 | 2402 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2413 | // :95:17: note: when computing vector element at index '0' | |
| 2403 | // :95:17: note: when computing vector element at index '1' | |
| 2414 | 2404 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2405 | // :95:17: note: when computing vector element at index '1' | |
| 2415 | 2406 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2407 | // :95:17: note: when computing vector element at index '1' | |
| 2416 | 2408 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2409 | // :95:17: note: when computing vector element at index '1' | |
| 2417 | 2410 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2411 | // :95:17: note: when computing vector element at index '1' | |
| 2418 | 2412 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2413 | // :95:17: note: when computing vector element at index '1' | |
| 2419 | 2414 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2415 | // :95:17: note: when computing vector element at index '1' | |
| 2420 | 2416 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2421 | 2417 | // :95:17: note: when computing vector element at index '1' |
| 2422 | 2418 | // :95:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2426,13 +2422,17 @@ const std = @import("std"); |
| 2426 | 2422 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2427 | 2423 | // :95:17: note: when computing vector element at index '1' |
| 2428 | 2424 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2429 | // :95:17: note: when computing vector element at index '0' | |
| 2425 | // :95:17: note: when computing vector element at index '1' | |
| 2430 | 2426 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2431 | // :95:17: note: when computing vector element at index '0' | |
| 2427 | // :95:17: note: when computing vector element at index '1' | |
| 2432 | 2428 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2433 | // :95:17: note: when computing vector element at index '0' | |
| 2429 | // :95:17: note: when computing vector element at index '1' | |
| 2434 | 2430 | // :95:17: error: use of undefined value here causes illegal behavior |
| 2435 | // :95:17: note: when computing vector element at index '0' | |
| 2431 | // :95:17: note: when computing vector element at index '1' | |
| 2432 | // :95:17: error: use of undefined value here causes illegal behavior | |
| 2433 | // :95:17: note: when computing vector element at index '1' | |
| 2434 | // :95:17: error: use of undefined value here causes illegal behavior | |
| 2435 | // :95:17: note: when computing vector element at index '1' | |
| 2436 | 2436 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2437 | 2437 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2438 | 2438 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2440,21 +2440,13 @@ const std = @import("std"); |
| 2440 | 2440 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2441 | 2441 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2442 | 2442 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2443 | // :99:27: note: when computing vector element at index '1' | |
| 2444 | 2443 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2445 | // :99:27: note: when computing vector element at index '1' | |
| 2446 | 2444 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2447 | // :99:27: note: when computing vector element at index '1' | |
| 2448 | 2445 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2449 | // :99:27: note: when computing vector element at index '1' | |
| 2450 | 2446 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2451 | // :99:27: note: when computing vector element at index '0' | |
| 2452 | 2447 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2453 | // :99:27: note: when computing vector element at index '0' | |
| 2454 | 2448 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2455 | // :99:27: note: when computing vector element at index '0' | |
| 2456 | 2449 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2457 | // :99:27: note: when computing vector element at index '0' | |
| 2458 | 2450 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2459 | 2451 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2460 | 2452 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2462,21 +2454,13 @@ const std = @import("std"); |
| 2462 | 2454 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2463 | 2455 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2464 | 2456 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2465 | // :99:27: note: when computing vector element at index '1' | |
| 2466 | 2457 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2467 | // :99:27: note: when computing vector element at index '1' | |
| 2468 | 2458 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2469 | // :99:27: note: when computing vector element at index '1' | |
| 2470 | 2459 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2471 | // :99:27: note: when computing vector element at index '1' | |
| 2472 | 2460 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2473 | // :99:27: note: when computing vector element at index '0' | |
| 2474 | 2461 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2475 | // :99:27: note: when computing vector element at index '0' | |
| 2476 | 2462 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2477 | // :99:27: note: when computing vector element at index '0' | |
| 2478 | 2463 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2479 | // :99:27: note: when computing vector element at index '0' | |
| 2480 | 2464 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2481 | 2465 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2482 | 2466 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2484,21 +2468,13 @@ const std = @import("std"); |
| 2484 | 2468 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2485 | 2469 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2486 | 2470 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2487 | // :99:27: note: when computing vector element at index '1' | |
| 2488 | 2471 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2489 | // :99:27: note: when computing vector element at index '1' | |
| 2490 | 2472 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2491 | // :99:27: note: when computing vector element at index '1' | |
| 2492 | 2473 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2493 | // :99:27: note: when computing vector element at index '1' | |
| 2494 | 2474 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2495 | // :99:27: note: when computing vector element at index '0' | |
| 2496 | 2475 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2497 | // :99:27: note: when computing vector element at index '0' | |
| 2498 | 2476 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2499 | // :99:27: note: when computing vector element at index '0' | |
| 2500 | 2477 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2501 | // :99:27: note: when computing vector element at index '0' | |
| 2502 | 2478 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2503 | 2479 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2504 | 2480 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2506,21 +2482,13 @@ const std = @import("std"); |
| 2506 | 2482 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2507 | 2483 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2508 | 2484 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2509 | // :99:27: note: when computing vector element at index '1' | |
| 2510 | 2485 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2511 | // :99:27: note: when computing vector element at index '1' | |
| 2512 | 2486 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2513 | // :99:27: note: when computing vector element at index '1' | |
| 2514 | 2487 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2515 | // :99:27: note: when computing vector element at index '1' | |
| 2516 | 2488 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2517 | // :99:27: note: when computing vector element at index '0' | |
| 2518 | 2489 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2519 | // :99:27: note: when computing vector element at index '0' | |
| 2520 | 2490 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2521 | // :99:27: note: when computing vector element at index '0' | |
| 2522 | 2491 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2523 | // :99:27: note: when computing vector element at index '0' | |
| 2524 | 2492 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2525 | 2493 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2526 | 2494 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2528,13 +2496,9 @@ const std = @import("std"); |
| 2528 | 2496 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2529 | 2497 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2530 | 2498 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2531 | // :99:27: note: when computing vector element at index '1' | |
| 2532 | 2499 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2533 | // :99:27: note: when computing vector element at index '1' | |
| 2534 | 2500 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2535 | // :99:27: note: when computing vector element at index '1' | |
| 2536 | 2501 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2537 | // :99:27: note: when computing vector element at index '1' | |
| 2538 | 2502 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2539 | 2503 | // :99:27: note: when computing vector element at index '0' |
| 2540 | 2504 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2544,19 +2508,21 @@ const std = @import("std"); |
| 2544 | 2508 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2545 | 2509 | // :99:27: note: when computing vector element at index '0' |
| 2546 | 2510 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2511 | // :99:27: note: when computing vector element at index '0' | |
| 2547 | 2512 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2513 | // :99:27: note: when computing vector element at index '0' | |
| 2548 | 2514 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2515 | // :99:27: note: when computing vector element at index '0' | |
| 2549 | 2516 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2517 | // :99:27: note: when computing vector element at index '0' | |
| 2550 | 2518 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2519 | // :99:27: note: when computing vector element at index '0' | |
| 2551 | 2520 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2521 | // :99:27: note: when computing vector element at index '0' | |
| 2552 | 2522 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2553 | // :99:27: note: when computing vector element at index '1' | |
| 2554 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2555 | // :99:27: note: when computing vector element at index '1' | |
| 2556 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2557 | // :99:27: note: when computing vector element at index '1' | |
| 2523 | // :99:27: note: when computing vector element at index '0' | |
| 2558 | 2524 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2559 | // :99:27: note: when computing vector element at index '1' | |
| 2525 | // :99:27: note: when computing vector element at index '0' | |
| 2560 | 2526 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2561 | 2527 | // :99:27: note: when computing vector element at index '0' |
| 2562 | 2528 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2566,19 +2532,25 @@ const std = @import("std"); |
| 2566 | 2532 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2567 | 2533 | // :99:27: note: when computing vector element at index '0' |
| 2568 | 2534 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2535 | // :99:27: note: when computing vector element at index '0' | |
| 2569 | 2536 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2537 | // :99:27: note: when computing vector element at index '0' | |
| 2570 | 2538 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2539 | // :99:27: note: when computing vector element at index '0' | |
| 2571 | 2540 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2541 | // :99:27: note: when computing vector element at index '0' | |
| 2572 | 2542 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2543 | // :99:27: note: when computing vector element at index '0' | |
| 2573 | 2544 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2545 | // :99:27: note: when computing vector element at index '0' | |
| 2574 | 2546 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2575 | // :99:27: note: when computing vector element at index '1' | |
| 2547 | // :99:27: note: when computing vector element at index '0' | |
| 2576 | 2548 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2577 | // :99:27: note: when computing vector element at index '1' | |
| 2549 | // :99:27: note: when computing vector element at index '0' | |
| 2578 | 2550 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2579 | // :99:27: note: when computing vector element at index '1' | |
| 2551 | // :99:27: note: when computing vector element at index '0' | |
| 2580 | 2552 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2581 | // :99:27: note: when computing vector element at index '1' | |
| 2553 | // :99:27: note: when computing vector element at index '0' | |
| 2582 | 2554 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2583 | 2555 | // :99:27: note: when computing vector element at index '0' |
| 2584 | 2556 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2588,19 +2560,25 @@ const std = @import("std"); |
| 2588 | 2560 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2589 | 2561 | // :99:27: note: when computing vector element at index '0' |
| 2590 | 2562 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2563 | // :99:27: note: when computing vector element at index '0' | |
| 2591 | 2564 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2565 | // :99:27: note: when computing vector element at index '0' | |
| 2592 | 2566 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2567 | // :99:27: note: when computing vector element at index '0' | |
| 2593 | 2568 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2569 | // :99:27: note: when computing vector element at index '0' | |
| 2594 | 2570 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2571 | // :99:27: note: when computing vector element at index '0' | |
| 2595 | 2572 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2573 | // :99:27: note: when computing vector element at index '0' | |
| 2596 | 2574 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2597 | // :99:27: note: when computing vector element at index '1' | |
| 2575 | // :99:27: note: when computing vector element at index '0' | |
| 2598 | 2576 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2599 | // :99:27: note: when computing vector element at index '1' | |
| 2577 | // :99:27: note: when computing vector element at index '0' | |
| 2600 | 2578 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2601 | // :99:27: note: when computing vector element at index '1' | |
| 2579 | // :99:27: note: when computing vector element at index '0' | |
| 2602 | 2580 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2603 | // :99:27: note: when computing vector element at index '1' | |
| 2581 | // :99:27: note: when computing vector element at index '0' | |
| 2604 | 2582 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2605 | 2583 | // :99:27: note: when computing vector element at index '0' |
| 2606 | 2584 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2610,11 +2588,17 @@ const std = @import("std"); |
| 2610 | 2588 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2611 | 2589 | // :99:27: note: when computing vector element at index '0' |
| 2612 | 2590 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2591 | // :99:27: note: when computing vector element at index '1' | |
| 2613 | 2592 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2593 | // :99:27: note: when computing vector element at index '1' | |
| 2614 | 2594 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2595 | // :99:27: note: when computing vector element at index '1' | |
| 2615 | 2596 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2597 | // :99:27: note: when computing vector element at index '1' | |
| 2616 | 2598 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2599 | // :99:27: note: when computing vector element at index '1' | |
| 2617 | 2600 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2601 | // :99:27: note: when computing vector element at index '1' | |
| 2618 | 2602 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2619 | 2603 | // :99:27: note: when computing vector element at index '1' |
| 2620 | 2604 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2624,19 +2608,25 @@ const std = @import("std"); |
| 2624 | 2608 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2625 | 2609 | // :99:27: note: when computing vector element at index '1' |
| 2626 | 2610 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2627 | // :99:27: note: when computing vector element at index '0' | |
| 2611 | // :99:27: note: when computing vector element at index '1' | |
| 2628 | 2612 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2629 | // :99:27: note: when computing vector element at index '0' | |
| 2613 | // :99:27: note: when computing vector element at index '1' | |
| 2630 | 2614 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2631 | // :99:27: note: when computing vector element at index '0' | |
| 2615 | // :99:27: note: when computing vector element at index '1' | |
| 2632 | 2616 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2633 | // :99:27: note: when computing vector element at index '0' | |
| 2617 | // :99:27: note: when computing vector element at index '1' | |
| 2634 | 2618 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2619 | // :99:27: note: when computing vector element at index '1' | |
| 2635 | 2620 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2621 | // :99:27: note: when computing vector element at index '1' | |
| 2636 | 2622 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2623 | // :99:27: note: when computing vector element at index '1' | |
| 2637 | 2624 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2625 | // :99:27: note: when computing vector element at index '1' | |
| 2638 | 2626 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2627 | // :99:27: note: when computing vector element at index '1' | |
| 2639 | 2628 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2629 | // :99:27: note: when computing vector element at index '1' | |
| 2640 | 2630 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2641 | 2631 | // :99:27: note: when computing vector element at index '1' |
| 2642 | 2632 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2646,19 +2636,25 @@ const std = @import("std"); |
| 2646 | 2636 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2647 | 2637 | // :99:27: note: when computing vector element at index '1' |
| 2648 | 2638 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2649 | // :99:27: note: when computing vector element at index '0' | |
| 2639 | // :99:27: note: when computing vector element at index '1' | |
| 2650 | 2640 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2651 | // :99:27: note: when computing vector element at index '0' | |
| 2641 | // :99:27: note: when computing vector element at index '1' | |
| 2652 | 2642 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2653 | // :99:27: note: when computing vector element at index '0' | |
| 2643 | // :99:27: note: when computing vector element at index '1' | |
| 2654 | 2644 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2655 | // :99:27: note: when computing vector element at index '0' | |
| 2645 | // :99:27: note: when computing vector element at index '1' | |
| 2656 | 2646 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2647 | // :99:27: note: when computing vector element at index '1' | |
| 2657 | 2648 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2649 | // :99:27: note: when computing vector element at index '1' | |
| 2658 | 2650 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2651 | // :99:27: note: when computing vector element at index '1' | |
| 2659 | 2652 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2653 | // :99:27: note: when computing vector element at index '1' | |
| 2660 | 2654 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2655 | // :99:27: note: when computing vector element at index '1' | |
| 2661 | 2656 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2657 | // :99:27: note: when computing vector element at index '1' | |
| 2662 | 2658 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2663 | 2659 | // :99:27: note: when computing vector element at index '1' |
| 2664 | 2660 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2668,13 +2664,17 @@ const std = @import("std"); |
| 2668 | 2664 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2669 | 2665 | // :99:27: note: when computing vector element at index '1' |
| 2670 | 2666 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2671 | // :99:27: note: when computing vector element at index '0' | |
| 2667 | // :99:27: note: when computing vector element at index '1' | |
| 2672 | 2668 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2673 | // :99:27: note: when computing vector element at index '0' | |
| 2669 | // :99:27: note: when computing vector element at index '1' | |
| 2674 | 2670 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2675 | // :99:27: note: when computing vector element at index '0' | |
| 2671 | // :99:27: note: when computing vector element at index '1' | |
| 2676 | 2672 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2677 | // :99:27: note: when computing vector element at index '0' | |
| 2673 | // :99:27: note: when computing vector element at index '1' | |
| 2674 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2675 | // :99:27: note: when computing vector element at index '1' | |
| 2676 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2677 | // :99:27: note: when computing vector element at index '1' | |
| 2678 | 2678 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2679 | 2679 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2680 | 2680 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2682,21 +2682,13 @@ const std = @import("std"); |
| 2682 | 2682 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2683 | 2683 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2684 | 2684 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2685 | // :103:27: note: when computing vector element at index '1' | |
| 2686 | 2685 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2687 | // :103:27: note: when computing vector element at index '1' | |
| 2688 | 2686 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2689 | // :103:27: note: when computing vector element at index '1' | |
| 2690 | 2687 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2691 | // :103:27: note: when computing vector element at index '1' | |
| 2692 | 2688 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2693 | // :103:27: note: when computing vector element at index '0' | |
| 2694 | 2689 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2695 | // :103:27: note: when computing vector element at index '0' | |
| 2696 | 2690 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2697 | // :103:27: note: when computing vector element at index '0' | |
| 2698 | 2691 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2699 | // :103:27: note: when computing vector element at index '0' | |
| 2700 | 2692 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2701 | 2693 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2702 | 2694 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2704,21 +2696,13 @@ const std = @import("std"); |
| 2704 | 2696 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2705 | 2697 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2706 | 2698 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2707 | // :103:27: note: when computing vector element at index '1' | |
| 2708 | 2699 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2709 | // :103:27: note: when computing vector element at index '1' | |
| 2710 | 2700 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2711 | // :103:27: note: when computing vector element at index '1' | |
| 2712 | 2701 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2713 | // :103:27: note: when computing vector element at index '1' | |
| 2714 | 2702 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2715 | // :103:27: note: when computing vector element at index '0' | |
| 2716 | 2703 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2717 | // :103:27: note: when computing vector element at index '0' | |
| 2718 | 2704 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2719 | // :103:27: note: when computing vector element at index '0' | |
| 2720 | 2705 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2721 | // :103:27: note: when computing vector element at index '0' | |
| 2722 | 2706 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2723 | 2707 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2724 | 2708 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2726,21 +2710,13 @@ const std = @import("std"); |
| 2726 | 2710 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2727 | 2711 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2728 | 2712 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2729 | // :103:27: note: when computing vector element at index '1' | |
| 2730 | 2713 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2731 | // :103:27: note: when computing vector element at index '1' | |
| 2732 | 2714 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2733 | // :103:27: note: when computing vector element at index '1' | |
| 2734 | 2715 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2735 | // :103:27: note: when computing vector element at index '1' | |
| 2736 | 2716 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2737 | // :103:27: note: when computing vector element at index '0' | |
| 2738 | 2717 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2739 | // :103:27: note: when computing vector element at index '0' | |
| 2740 | 2718 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2741 | // :103:27: note: when computing vector element at index '0' | |
| 2742 | 2719 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2743 | // :103:27: note: when computing vector element at index '0' | |
| 2744 | 2720 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2745 | 2721 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2746 | 2722 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2748,21 +2724,13 @@ const std = @import("std"); |
| 2748 | 2724 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2749 | 2725 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2750 | 2726 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2751 | // :103:27: note: when computing vector element at index '1' | |
| 2752 | 2727 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2753 | // :103:27: note: when computing vector element at index '1' | |
| 2754 | 2728 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2755 | // :103:27: note: when computing vector element at index '1' | |
| 2756 | 2729 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2757 | // :103:27: note: when computing vector element at index '1' | |
| 2758 | 2730 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2759 | // :103:27: note: when computing vector element at index '0' | |
| 2760 | 2731 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2761 | // :103:27: note: when computing vector element at index '0' | |
| 2762 | 2732 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2763 | // :103:27: note: when computing vector element at index '0' | |
| 2764 | 2733 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2765 | // :103:27: note: when computing vector element at index '0' | |
| 2766 | 2734 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2767 | 2735 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2768 | 2736 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2770,13 +2738,9 @@ const std = @import("std"); |
| 2770 | 2738 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2771 | 2739 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2772 | 2740 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2773 | // :103:27: note: when computing vector element at index '1' | |
| 2774 | 2741 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2775 | // :103:27: note: when computing vector element at index '1' | |
| 2776 | 2742 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2777 | // :103:27: note: when computing vector element at index '1' | |
| 2778 | 2743 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2779 | // :103:27: note: when computing vector element at index '1' | |
| 2780 | 2744 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2781 | 2745 | // :103:27: note: when computing vector element at index '0' |
| 2782 | 2746 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2786,19 +2750,21 @@ const std = @import("std"); |
| 2786 | 2750 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2787 | 2751 | // :103:27: note: when computing vector element at index '0' |
| 2788 | 2752 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2753 | // :103:27: note: when computing vector element at index '0' | |
| 2789 | 2754 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2755 | // :103:27: note: when computing vector element at index '0' | |
| 2790 | 2756 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2757 | // :103:27: note: when computing vector element at index '0' | |
| 2791 | 2758 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2759 | // :103:27: note: when computing vector element at index '0' | |
| 2792 | 2760 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2761 | // :103:27: note: when computing vector element at index '0' | |
| 2793 | 2762 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2763 | // :103:27: note: when computing vector element at index '0' | |
| 2794 | 2764 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2795 | // :103:27: note: when computing vector element at index '1' | |
| 2796 | // :103:27: error: use of undefined value here causes illegal behavior | |
| 2797 | // :103:27: note: when computing vector element at index '1' | |
| 2798 | // :103:27: error: use of undefined value here causes illegal behavior | |
| 2799 | // :103:27: note: when computing vector element at index '1' | |
| 2765 | // :103:27: note: when computing vector element at index '0' | |
| 2800 | 2766 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2801 | // :103:27: note: when computing vector element at index '1' | |
| 2767 | // :103:27: note: when computing vector element at index '0' | |
| 2802 | 2768 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2803 | 2769 | // :103:27: note: when computing vector element at index '0' |
| 2804 | 2770 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2808,19 +2774,25 @@ const std = @import("std"); |
| 2808 | 2774 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2809 | 2775 | // :103:27: note: when computing vector element at index '0' |
| 2810 | 2776 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2777 | // :103:27: note: when computing vector element at index '0' | |
| 2811 | 2778 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2779 | // :103:27: note: when computing vector element at index '0' | |
| 2812 | 2780 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2781 | // :103:27: note: when computing vector element at index '0' | |
| 2813 | 2782 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2783 | // :103:27: note: when computing vector element at index '0' | |
| 2814 | 2784 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2785 | // :103:27: note: when computing vector element at index '0' | |
| 2815 | 2786 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2787 | // :103:27: note: when computing vector element at index '0' | |
| 2816 | 2788 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2817 | // :103:27: note: when computing vector element at index '1' | |
| 2789 | // :103:27: note: when computing vector element at index '0' | |
| 2818 | 2790 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2819 | // :103:27: note: when computing vector element at index '1' | |
| 2791 | // :103:27: note: when computing vector element at index '0' | |
| 2820 | 2792 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2821 | // :103:27: note: when computing vector element at index '1' | |
| 2793 | // :103:27: note: when computing vector element at index '0' | |
| 2822 | 2794 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2823 | // :103:27: note: when computing vector element at index '1' | |
| 2795 | // :103:27: note: when computing vector element at index '0' | |
| 2824 | 2796 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2825 | 2797 | // :103:27: note: when computing vector element at index '0' |
| 2826 | 2798 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2830,19 +2802,25 @@ const std = @import("std"); |
| 2830 | 2802 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2831 | 2803 | // :103:27: note: when computing vector element at index '0' |
| 2832 | 2804 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2805 | // :103:27: note: when computing vector element at index '0' | |
| 2833 | 2806 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2807 | // :103:27: note: when computing vector element at index '0' | |
| 2834 | 2808 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2809 | // :103:27: note: when computing vector element at index '0' | |
| 2835 | 2810 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2811 | // :103:27: note: when computing vector element at index '0' | |
| 2836 | 2812 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2813 | // :103:27: note: when computing vector element at index '0' | |
| 2837 | 2814 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2815 | // :103:27: note: when computing vector element at index '0' | |
| 2838 | 2816 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2839 | // :103:27: note: when computing vector element at index '1' | |
| 2817 | // :103:27: note: when computing vector element at index '0' | |
| 2840 | 2818 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2841 | // :103:27: note: when computing vector element at index '1' | |
| 2819 | // :103:27: note: when computing vector element at index '0' | |
| 2842 | 2820 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2843 | // :103:27: note: when computing vector element at index '1' | |
| 2821 | // :103:27: note: when computing vector element at index '0' | |
| 2844 | 2822 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2845 | // :103:27: note: when computing vector element at index '1' | |
| 2823 | // :103:27: note: when computing vector element at index '0' | |
| 2846 | 2824 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2847 | 2825 | // :103:27: note: when computing vector element at index '0' |
| 2848 | 2826 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2852,11 +2830,17 @@ const std = @import("std"); |
| 2852 | 2830 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2853 | 2831 | // :103:27: note: when computing vector element at index '0' |
| 2854 | 2832 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2833 | // :103:27: note: when computing vector element at index '1' | |
| 2855 | 2834 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2835 | // :103:27: note: when computing vector element at index '1' | |
| 2856 | 2836 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2837 | // :103:27: note: when computing vector element at index '1' | |
| 2857 | 2838 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2839 | // :103:27: note: when computing vector element at index '1' | |
| 2858 | 2840 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2841 | // :103:27: note: when computing vector element at index '1' | |
| 2859 | 2842 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2843 | // :103:27: note: when computing vector element at index '1' | |
| 2860 | 2844 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2861 | 2845 | // :103:27: note: when computing vector element at index '1' |
| 2862 | 2846 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2866,19 +2850,25 @@ const std = @import("std"); |
| 2866 | 2850 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2867 | 2851 | // :103:27: note: when computing vector element at index '1' |
| 2868 | 2852 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2869 | // :103:27: note: when computing vector element at index '0' | |
| 2853 | // :103:27: note: when computing vector element at index '1' | |
| 2870 | 2854 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2871 | // :103:27: note: when computing vector element at index '0' | |
| 2855 | // :103:27: note: when computing vector element at index '1' | |
| 2872 | 2856 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2873 | // :103:27: note: when computing vector element at index '0' | |
| 2857 | // :103:27: note: when computing vector element at index '1' | |
| 2874 | 2858 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2875 | // :103:27: note: when computing vector element at index '0' | |
| 2859 | // :103:27: note: when computing vector element at index '1' | |
| 2876 | 2860 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2861 | // :103:27: note: when computing vector element at index '1' | |
| 2877 | 2862 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2863 | // :103:27: note: when computing vector element at index '1' | |
| 2878 | 2864 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2865 | // :103:27: note: when computing vector element at index '1' | |
| 2879 | 2866 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2867 | // :103:27: note: when computing vector element at index '1' | |
| 2880 | 2868 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2869 | // :103:27: note: when computing vector element at index '1' | |
| 2881 | 2870 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2871 | // :103:27: note: when computing vector element at index '1' | |
| 2882 | 2872 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2883 | 2873 | // :103:27: note: when computing vector element at index '1' |
| 2884 | 2874 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2888,19 +2878,25 @@ const std = @import("std"); |
| 2888 | 2878 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2889 | 2879 | // :103:27: note: when computing vector element at index '1' |
| 2890 | 2880 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2891 | // :103:27: note: when computing vector element at index '0' | |
| 2881 | // :103:27: note: when computing vector element at index '1' | |
| 2892 | 2882 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2893 | // :103:27: note: when computing vector element at index '0' | |
| 2883 | // :103:27: note: when computing vector element at index '1' | |
| 2894 | 2884 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2895 | // :103:27: note: when computing vector element at index '0' | |
| 2885 | // :103:27: note: when computing vector element at index '1' | |
| 2896 | 2886 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2897 | // :103:27: note: when computing vector element at index '0' | |
| 2887 | // :103:27: note: when computing vector element at index '1' | |
| 2898 | 2888 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2889 | // :103:27: note: when computing vector element at index '1' | |
| 2899 | 2890 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2891 | // :103:27: note: when computing vector element at index '1' | |
| 2900 | 2892 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2893 | // :103:27: note: when computing vector element at index '1' | |
| 2901 | 2894 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2895 | // :103:27: note: when computing vector element at index '1' | |
| 2902 | 2896 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2897 | // :103:27: note: when computing vector element at index '1' | |
| 2903 | 2898 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2899 | // :103:27: note: when computing vector element at index '1' | |
| 2904 | 2900 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2905 | 2901 | // :103:27: note: when computing vector element at index '1' |
| 2906 | 2902 | // :103:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2910,13 +2906,17 @@ const std = @import("std"); |
| 2910 | 2906 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2911 | 2907 | // :103:27: note: when computing vector element at index '1' |
| 2912 | 2908 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2913 | // :103:27: note: when computing vector element at index '0' | |
| 2909 | // :103:27: note: when computing vector element at index '1' | |
| 2914 | 2910 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2915 | // :103:27: note: when computing vector element at index '0' | |
| 2911 | // :103:27: note: when computing vector element at index '1' | |
| 2916 | 2912 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2917 | // :103:27: note: when computing vector element at index '0' | |
| 2913 | // :103:27: note: when computing vector element at index '1' | |
| 2918 | 2914 | // :103:27: error: use of undefined value here causes illegal behavior |
| 2919 | // :103:27: note: when computing vector element at index '0' | |
| 2915 | // :103:27: note: when computing vector element at index '1' | |
| 2916 | // :103:27: error: use of undefined value here causes illegal behavior | |
| 2917 | // :103:27: note: when computing vector element at index '1' | |
| 2918 | // :103:27: error: use of undefined value here causes illegal behavior | |
| 2919 | // :103:27: note: when computing vector element at index '1' | |
| 2920 | 2920 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2921 | 2921 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2922 | 2922 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2924,21 +2924,13 @@ const std = @import("std"); |
| 2924 | 2924 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2925 | 2925 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2926 | 2926 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2927 | // :107:27: note: when computing vector element at index '1' | |
| 2928 | 2927 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2929 | // :107:27: note: when computing vector element at index '1' | |
| 2930 | 2928 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2931 | // :107:27: note: when computing vector element at index '1' | |
| 2932 | 2929 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2933 | // :107:27: note: when computing vector element at index '1' | |
| 2934 | 2930 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2935 | // :107:27: note: when computing vector element at index '0' | |
| 2936 | 2931 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2937 | // :107:27: note: when computing vector element at index '0' | |
| 2938 | 2932 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2939 | // :107:27: note: when computing vector element at index '0' | |
| 2940 | 2933 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2941 | // :107:27: note: when computing vector element at index '0' | |
| 2942 | 2934 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2943 | 2935 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2944 | 2936 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2946,21 +2938,13 @@ const std = @import("std"); |
| 2946 | 2938 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2947 | 2939 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2948 | 2940 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2949 | // :107:27: note: when computing vector element at index '1' | |
| 2950 | 2941 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2951 | // :107:27: note: when computing vector element at index '1' | |
| 2952 | 2942 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2953 | // :107:27: note: when computing vector element at index '1' | |
| 2954 | 2943 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2955 | // :107:27: note: when computing vector element at index '1' | |
| 2956 | 2944 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2957 | // :107:27: note: when computing vector element at index '0' | |
| 2958 | 2945 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2959 | // :107:27: note: when computing vector element at index '0' | |
| 2960 | 2946 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2961 | // :107:27: note: when computing vector element at index '0' | |
| 2962 | 2947 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2963 | // :107:27: note: when computing vector element at index '0' | |
| 2964 | 2948 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2965 | 2949 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2966 | 2950 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2968,21 +2952,13 @@ const std = @import("std"); |
| 2968 | 2952 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2969 | 2953 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2970 | 2954 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2971 | // :107:27: note: when computing vector element at index '1' | |
| 2972 | 2955 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2973 | // :107:27: note: when computing vector element at index '1' | |
| 2974 | 2956 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2975 | // :107:27: note: when computing vector element at index '1' | |
| 2976 | 2957 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2977 | // :107:27: note: when computing vector element at index '1' | |
| 2978 | 2958 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2979 | // :107:27: note: when computing vector element at index '0' | |
| 2980 | 2959 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2981 | // :107:27: note: when computing vector element at index '0' | |
| 2982 | 2960 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2983 | // :107:27: note: when computing vector element at index '0' | |
| 2984 | 2961 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2985 | // :107:27: note: when computing vector element at index '0' | |
| 2986 | 2962 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2987 | 2963 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2988 | 2964 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2990,21 +2966,13 @@ const std = @import("std"); |
| 2990 | 2966 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2991 | 2967 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2992 | 2968 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2993 | // :107:27: note: when computing vector element at index '1' | |
| 2994 | 2969 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2995 | // :107:27: note: when computing vector element at index '1' | |
| 2996 | 2970 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2997 | // :107:27: note: when computing vector element at index '1' | |
| 2998 | 2971 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2999 | // :107:27: note: when computing vector element at index '1' | |
| 3000 | 2972 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3001 | // :107:27: note: when computing vector element at index '0' | |
| 3002 | 2973 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3003 | // :107:27: note: when computing vector element at index '0' | |
| 3004 | 2974 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3005 | // :107:27: note: when computing vector element at index '0' | |
| 3006 | 2975 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3007 | // :107:27: note: when computing vector element at index '0' | |
| 3008 | 2976 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3009 | 2977 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3010 | 2978 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3012,13 +2980,9 @@ const std = @import("std"); |
| 3012 | 2980 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3013 | 2981 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3014 | 2982 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3015 | // :107:27: note: when computing vector element at index '1' | |
| 3016 | 2983 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3017 | // :107:27: note: when computing vector element at index '1' | |
| 3018 | 2984 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3019 | // :107:27: note: when computing vector element at index '1' | |
| 3020 | 2985 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3021 | // :107:27: note: when computing vector element at index '1' | |
| 3022 | 2986 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3023 | 2987 | // :107:27: note: when computing vector element at index '0' |
| 3024 | 2988 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3028,19 +2992,21 @@ const std = @import("std"); |
| 3028 | 2992 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3029 | 2993 | // :107:27: note: when computing vector element at index '0' |
| 3030 | 2994 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2995 | // :107:27: note: when computing vector element at index '0' | |
| 3031 | 2996 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2997 | // :107:27: note: when computing vector element at index '0' | |
| 3032 | 2998 | // :107:27: error: use of undefined value here causes illegal behavior |
| 2999 | // :107:27: note: when computing vector element at index '0' | |
| 3033 | 3000 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3001 | // :107:27: note: when computing vector element at index '0' | |
| 3034 | 3002 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3003 | // :107:27: note: when computing vector element at index '0' | |
| 3035 | 3004 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3005 | // :107:27: note: when computing vector element at index '0' | |
| 3036 | 3006 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3037 | // :107:27: note: when computing vector element at index '1' | |
| 3038 | // :107:27: error: use of undefined value here causes illegal behavior | |
| 3039 | // :107:27: note: when computing vector element at index '1' | |
| 3040 | // :107:27: error: use of undefined value here causes illegal behavior | |
| 3041 | // :107:27: note: when computing vector element at index '1' | |
| 3007 | // :107:27: note: when computing vector element at index '0' | |
| 3042 | 3008 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3043 | // :107:27: note: when computing vector element at index '1' | |
| 3009 | // :107:27: note: when computing vector element at index '0' | |
| 3044 | 3010 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3045 | 3011 | // :107:27: note: when computing vector element at index '0' |
| 3046 | 3012 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3050,19 +3016,25 @@ const std = @import("std"); |
| 3050 | 3016 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3051 | 3017 | // :107:27: note: when computing vector element at index '0' |
| 3052 | 3018 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3019 | // :107:27: note: when computing vector element at index '0' | |
| 3053 | 3020 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3021 | // :107:27: note: when computing vector element at index '0' | |
| 3054 | 3022 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3023 | // :107:27: note: when computing vector element at index '0' | |
| 3055 | 3024 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3025 | // :107:27: note: when computing vector element at index '0' | |
| 3056 | 3026 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3027 | // :107:27: note: when computing vector element at index '0' | |
| 3057 | 3028 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3029 | // :107:27: note: when computing vector element at index '0' | |
| 3058 | 3030 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3059 | // :107:27: note: when computing vector element at index '1' | |
| 3031 | // :107:27: note: when computing vector element at index '0' | |
| 3060 | 3032 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3061 | // :107:27: note: when computing vector element at index '1' | |
| 3033 | // :107:27: note: when computing vector element at index '0' | |
| 3062 | 3034 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3063 | // :107:27: note: when computing vector element at index '1' | |
| 3035 | // :107:27: note: when computing vector element at index '0' | |
| 3064 | 3036 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3065 | // :107:27: note: when computing vector element at index '1' | |
| 3037 | // :107:27: note: when computing vector element at index '0' | |
| 3066 | 3038 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3067 | 3039 | // :107:27: note: when computing vector element at index '0' |
| 3068 | 3040 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3072,19 +3044,25 @@ const std = @import("std"); |
| 3072 | 3044 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3073 | 3045 | // :107:27: note: when computing vector element at index '0' |
| 3074 | 3046 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3047 | // :107:27: note: when computing vector element at index '0' | |
| 3075 | 3048 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3049 | // :107:27: note: when computing vector element at index '0' | |
| 3076 | 3050 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3051 | // :107:27: note: when computing vector element at index '0' | |
| 3077 | 3052 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3053 | // :107:27: note: when computing vector element at index '0' | |
| 3078 | 3054 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3055 | // :107:27: note: when computing vector element at index '0' | |
| 3079 | 3056 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3057 | // :107:27: note: when computing vector element at index '0' | |
| 3080 | 3058 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3081 | // :107:27: note: when computing vector element at index '1' | |
| 3059 | // :107:27: note: when computing vector element at index '0' | |
| 3082 | 3060 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3083 | // :107:27: note: when computing vector element at index '1' | |
| 3061 | // :107:27: note: when computing vector element at index '0' | |
| 3084 | 3062 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3085 | // :107:27: note: when computing vector element at index '1' | |
| 3063 | // :107:27: note: when computing vector element at index '0' | |
| 3086 | 3064 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3087 | // :107:27: note: when computing vector element at index '1' | |
| 3065 | // :107:27: note: when computing vector element at index '0' | |
| 3088 | 3066 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3089 | 3067 | // :107:27: note: when computing vector element at index '0' |
| 3090 | 3068 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3094,11 +3072,17 @@ const std = @import("std"); |
| 3094 | 3072 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3095 | 3073 | // :107:27: note: when computing vector element at index '0' |
| 3096 | 3074 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3075 | // :107:27: note: when computing vector element at index '1' | |
| 3097 | 3076 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3077 | // :107:27: note: when computing vector element at index '1' | |
| 3098 | 3078 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3079 | // :107:27: note: when computing vector element at index '1' | |
| 3099 | 3080 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3081 | // :107:27: note: when computing vector element at index '1' | |
| 3100 | 3082 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3083 | // :107:27: note: when computing vector element at index '1' | |
| 3101 | 3084 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3085 | // :107:27: note: when computing vector element at index '1' | |
| 3102 | 3086 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3103 | 3087 | // :107:27: note: when computing vector element at index '1' |
| 3104 | 3088 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3108,19 +3092,25 @@ const std = @import("std"); |
| 3108 | 3092 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3109 | 3093 | // :107:27: note: when computing vector element at index '1' |
| 3110 | 3094 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3111 | // :107:27: note: when computing vector element at index '0' | |
| 3095 | // :107:27: note: when computing vector element at index '1' | |
| 3112 | 3096 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3113 | // :107:27: note: when computing vector element at index '0' | |
| 3097 | // :107:27: note: when computing vector element at index '1' | |
| 3114 | 3098 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3115 | // :107:27: note: when computing vector element at index '0' | |
| 3099 | // :107:27: note: when computing vector element at index '1' | |
| 3116 | 3100 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3117 | // :107:27: note: when computing vector element at index '0' | |
| 3101 | // :107:27: note: when computing vector element at index '1' | |
| 3118 | 3102 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3103 | // :107:27: note: when computing vector element at index '1' | |
| 3119 | 3104 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3105 | // :107:27: note: when computing vector element at index '1' | |
| 3120 | 3106 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3107 | // :107:27: note: when computing vector element at index '1' | |
| 3121 | 3108 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3109 | // :107:27: note: when computing vector element at index '1' | |
| 3122 | 3110 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3111 | // :107:27: note: when computing vector element at index '1' | |
| 3123 | 3112 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3113 | // :107:27: note: when computing vector element at index '1' | |
| 3124 | 3114 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3125 | 3115 | // :107:27: note: when computing vector element at index '1' |
| 3126 | 3116 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3130,19 +3120,29 @@ const std = @import("std"); |
| 3130 | 3120 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3131 | 3121 | // :107:27: note: when computing vector element at index '1' |
| 3132 | 3122 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3133 | // :107:27: note: when computing vector element at index '0' | |
| 3123 | // :107:27: note: when computing vector element at index '1' | |
| 3134 | 3124 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3135 | // :107:27: note: when computing vector element at index '0' | |
| 3125 | // :107:27: note: when computing vector element at index '1' | |
| 3136 | 3126 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3137 | // :107:27: note: when computing vector element at index '0' | |
| 3127 | // :107:27: note: when computing vector element at index '1' | |
| 3138 | 3128 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3139 | // :107:27: note: when computing vector element at index '0' | |
| 3129 | // :107:27: note: when computing vector element at index '1' | |
| 3130 | // :107:27: error: use of undefined value here causes illegal behavior | |
| 3131 | // :107:27: note: when computing vector element at index '1' | |
| 3132 | // :107:27: error: use of undefined value here causes illegal behavior | |
| 3133 | // :107:27: note: when computing vector element at index '1' | |
| 3140 | 3134 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3135 | // :107:27: note: when computing vector element at index '1' | |
| 3141 | 3136 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3137 | // :107:27: note: when computing vector element at index '1' | |
| 3142 | 3138 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3139 | // :107:27: note: when computing vector element at index '1' | |
| 3143 | 3140 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3141 | // :107:27: note: when computing vector element at index '1' | |
| 3144 | 3142 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3143 | // :107:27: note: when computing vector element at index '1' | |
| 3145 | 3144 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3145 | // :107:27: note: when computing vector element at index '1' | |
| 3146 | 3146 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3147 | 3147 | // :107:27: note: when computing vector element at index '1' |
| 3148 | 3148 | // :107:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3152,13 +3152,13 @@ const std = @import("std"); |
| 3152 | 3152 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3153 | 3153 | // :107:27: note: when computing vector element at index '1' |
| 3154 | 3154 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3155 | // :107:27: note: when computing vector element at index '0' | |
| 3155 | // :107:27: note: when computing vector element at index '1' | |
| 3156 | 3156 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3157 | // :107:27: note: when computing vector element at index '0' | |
| 3157 | // :107:27: note: when computing vector element at index '1' | |
| 3158 | 3158 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3159 | // :107:27: note: when computing vector element at index '0' | |
| 3159 | // :107:27: note: when computing vector element at index '1' | |
| 3160 | 3160 | // :107:27: error: use of undefined value here causes illegal behavior |
| 3161 | // :107:27: note: when computing vector element at index '0' | |
| 3161 | // :107:27: note: when computing vector element at index '1' | |
| 3162 | 3162 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3163 | 3163 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3164 | 3164 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3166,21 +3166,13 @@ const std = @import("std"); |
| 3166 | 3166 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3167 | 3167 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3168 | 3168 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3169 | // :111:22: note: when computing vector element at index '1' | |
| 3170 | 3169 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3171 | // :111:22: note: when computing vector element at index '1' | |
| 3172 | 3170 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3173 | // :111:22: note: when computing vector element at index '1' | |
| 3174 | 3171 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3175 | // :111:22: note: when computing vector element at index '1' | |
| 3176 | 3172 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3177 | // :111:22: note: when computing vector element at index '0' | |
| 3178 | 3173 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3179 | // :111:22: note: when computing vector element at index '0' | |
| 3180 | 3174 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3181 | // :111:22: note: when computing vector element at index '0' | |
| 3182 | 3175 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3183 | // :111:22: note: when computing vector element at index '0' | |
| 3184 | 3176 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3185 | 3177 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3186 | 3178 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3188,21 +3180,13 @@ const std = @import("std"); |
| 3188 | 3180 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3189 | 3181 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3190 | 3182 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3191 | // :111:22: note: when computing vector element at index '1' | |
| 3192 | 3183 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3193 | // :111:22: note: when computing vector element at index '1' | |
| 3194 | 3184 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3195 | // :111:22: note: when computing vector element at index '1' | |
| 3196 | 3185 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3197 | // :111:22: note: when computing vector element at index '1' | |
| 3198 | 3186 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3199 | // :111:22: note: when computing vector element at index '0' | |
| 3200 | 3187 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3201 | // :111:22: note: when computing vector element at index '0' | |
| 3202 | 3188 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3203 | // :111:22: note: when computing vector element at index '0' | |
| 3204 | 3189 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3205 | // :111:22: note: when computing vector element at index '0' | |
| 3206 | 3190 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3207 | 3191 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3208 | 3192 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3210,21 +3194,13 @@ const std = @import("std"); |
| 3210 | 3194 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3211 | 3195 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3212 | 3196 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3213 | // :111:22: note: when computing vector element at index '1' | |
| 3214 | 3197 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3215 | // :111:22: note: when computing vector element at index '1' | |
| 3216 | 3198 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3217 | // :111:22: note: when computing vector element at index '1' | |
| 3218 | 3199 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3219 | // :111:22: note: when computing vector element at index '1' | |
| 3220 | 3200 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3221 | // :111:22: note: when computing vector element at index '0' | |
| 3222 | 3201 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3223 | // :111:22: note: when computing vector element at index '0' | |
| 3224 | 3202 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3225 | // :111:22: note: when computing vector element at index '0' | |
| 3226 | 3203 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3227 | // :111:22: note: when computing vector element at index '0' | |
| 3228 | 3204 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3229 | 3205 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3230 | 3206 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3232,21 +3208,13 @@ const std = @import("std"); |
| 3232 | 3208 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3233 | 3209 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3234 | 3210 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3235 | // :111:22: note: when computing vector element at index '1' | |
| 3236 | 3211 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3237 | // :111:22: note: when computing vector element at index '1' | |
| 3238 | 3212 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3239 | // :111:22: note: when computing vector element at index '1' | |
| 3240 | 3213 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3241 | // :111:22: note: when computing vector element at index '1' | |
| 3242 | 3214 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3243 | // :111:22: note: when computing vector element at index '0' | |
| 3244 | 3215 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3245 | // :111:22: note: when computing vector element at index '0' | |
| 3246 | 3216 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3247 | // :111:22: note: when computing vector element at index '0' | |
| 3248 | 3217 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3249 | // :111:22: note: when computing vector element at index '0' | |
| 3250 | 3218 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3251 | 3219 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3252 | 3220 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3254,13 +3222,9 @@ const std = @import("std"); |
| 3254 | 3222 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3255 | 3223 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3256 | 3224 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3257 | // :111:22: note: when computing vector element at index '1' | |
| 3258 | 3225 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3259 | // :111:22: note: when computing vector element at index '1' | |
| 3260 | 3226 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3261 | // :111:22: note: when computing vector element at index '1' | |
| 3262 | 3227 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3263 | // :111:22: note: when computing vector element at index '1' | |
| 3264 | 3228 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3265 | 3229 | // :111:22: note: when computing vector element at index '0' |
| 3266 | 3230 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3270,19 +3234,21 @@ const std = @import("std"); |
| 3270 | 3234 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3271 | 3235 | // :111:22: note: when computing vector element at index '0' |
| 3272 | 3236 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3237 | // :111:22: note: when computing vector element at index '0' | |
| 3273 | 3238 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3239 | // :111:22: note: when computing vector element at index '0' | |
| 3274 | 3240 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3241 | // :111:22: note: when computing vector element at index '0' | |
| 3275 | 3242 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3243 | // :111:22: note: when computing vector element at index '0' | |
| 3276 | 3244 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3245 | // :111:22: note: when computing vector element at index '0' | |
| 3277 | 3246 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3247 | // :111:22: note: when computing vector element at index '0' | |
| 3278 | 3248 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3279 | // :111:22: note: when computing vector element at index '1' | |
| 3280 | // :111:22: error: use of undefined value here causes illegal behavior | |
| 3281 | // :111:22: note: when computing vector element at index '1' | |
| 3282 | // :111:22: error: use of undefined value here causes illegal behavior | |
| 3283 | // :111:22: note: when computing vector element at index '1' | |
| 3249 | // :111:22: note: when computing vector element at index '0' | |
| 3284 | 3250 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3285 | // :111:22: note: when computing vector element at index '1' | |
| 3251 | // :111:22: note: when computing vector element at index '0' | |
| 3286 | 3252 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3287 | 3253 | // :111:22: note: when computing vector element at index '0' |
| 3288 | 3254 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3292,19 +3258,25 @@ const std = @import("std"); |
| 3292 | 3258 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3293 | 3259 | // :111:22: note: when computing vector element at index '0' |
| 3294 | 3260 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3261 | // :111:22: note: when computing vector element at index '0' | |
| 3295 | 3262 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3263 | // :111:22: note: when computing vector element at index '0' | |
| 3296 | 3264 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3265 | // :111:22: note: when computing vector element at index '0' | |
| 3297 | 3266 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3267 | // :111:22: note: when computing vector element at index '0' | |
| 3298 | 3268 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3269 | // :111:22: note: when computing vector element at index '0' | |
| 3299 | 3270 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3271 | // :111:22: note: when computing vector element at index '0' | |
| 3300 | 3272 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3301 | // :111:22: note: when computing vector element at index '1' | |
| 3273 | // :111:22: note: when computing vector element at index '0' | |
| 3302 | 3274 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3303 | // :111:22: note: when computing vector element at index '1' | |
| 3275 | // :111:22: note: when computing vector element at index '0' | |
| 3304 | 3276 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3305 | // :111:22: note: when computing vector element at index '1' | |
| 3277 | // :111:22: note: when computing vector element at index '0' | |
| 3306 | 3278 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3307 | // :111:22: note: when computing vector element at index '1' | |
| 3279 | // :111:22: note: when computing vector element at index '0' | |
| 3308 | 3280 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3309 | 3281 | // :111:22: note: when computing vector element at index '0' |
| 3310 | 3282 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3314,19 +3286,25 @@ const std = @import("std"); |
| 3314 | 3286 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3315 | 3287 | // :111:22: note: when computing vector element at index '0' |
| 3316 | 3288 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3289 | // :111:22: note: when computing vector element at index '0' | |
| 3317 | 3290 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3291 | // :111:22: note: when computing vector element at index '0' | |
| 3318 | 3292 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3293 | // :111:22: note: when computing vector element at index '0' | |
| 3319 | 3294 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3295 | // :111:22: note: when computing vector element at index '0' | |
| 3320 | 3296 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3297 | // :111:22: note: when computing vector element at index '0' | |
| 3321 | 3298 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3299 | // :111:22: note: when computing vector element at index '0' | |
| 3322 | 3300 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3323 | // :111:22: note: when computing vector element at index '1' | |
| 3301 | // :111:22: note: when computing vector element at index '0' | |
| 3324 | 3302 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3325 | // :111:22: note: when computing vector element at index '1' | |
| 3303 | // :111:22: note: when computing vector element at index '0' | |
| 3326 | 3304 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3327 | // :111:22: note: when computing vector element at index '1' | |
| 3305 | // :111:22: note: when computing vector element at index '0' | |
| 3328 | 3306 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3329 | // :111:22: note: when computing vector element at index '1' | |
| 3307 | // :111:22: note: when computing vector element at index '0' | |
| 3330 | 3308 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3331 | 3309 | // :111:22: note: when computing vector element at index '0' |
| 3332 | 3310 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3336,11 +3314,17 @@ const std = @import("std"); |
| 3336 | 3314 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3337 | 3315 | // :111:22: note: when computing vector element at index '0' |
| 3338 | 3316 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3317 | // :111:22: note: when computing vector element at index '1' | |
| 3339 | 3318 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3319 | // :111:22: note: when computing vector element at index '1' | |
| 3340 | 3320 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3321 | // :111:22: note: when computing vector element at index '1' | |
| 3341 | 3322 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3323 | // :111:22: note: when computing vector element at index '1' | |
| 3342 | 3324 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3325 | // :111:22: note: when computing vector element at index '1' | |
| 3343 | 3326 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3327 | // :111:22: note: when computing vector element at index '1' | |
| 3344 | 3328 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3345 | 3329 | // :111:22: note: when computing vector element at index '1' |
| 3346 | 3330 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3350,19 +3334,25 @@ const std = @import("std"); |
| 3350 | 3334 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3351 | 3335 | // :111:22: note: when computing vector element at index '1' |
| 3352 | 3336 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3353 | // :111:22: note: when computing vector element at index '0' | |
| 3337 | // :111:22: note: when computing vector element at index '1' | |
| 3354 | 3338 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3355 | // :111:22: note: when computing vector element at index '0' | |
| 3339 | // :111:22: note: when computing vector element at index '1' | |
| 3356 | 3340 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3357 | // :111:22: note: when computing vector element at index '0' | |
| 3341 | // :111:22: note: when computing vector element at index '1' | |
| 3358 | 3342 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3359 | // :111:22: note: when computing vector element at index '0' | |
| 3343 | // :111:22: note: when computing vector element at index '1' | |
| 3360 | 3344 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3345 | // :111:22: note: when computing vector element at index '1' | |
| 3361 | 3346 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3347 | // :111:22: note: when computing vector element at index '1' | |
| 3362 | 3348 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3349 | // :111:22: note: when computing vector element at index '1' | |
| 3363 | 3350 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3351 | // :111:22: note: when computing vector element at index '1' | |
| 3364 | 3352 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3353 | // :111:22: note: when computing vector element at index '1' | |
| 3365 | 3354 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3355 | // :111:22: note: when computing vector element at index '1' | |
| 3366 | 3356 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3367 | 3357 | // :111:22: note: when computing vector element at index '1' |
| 3368 | 3358 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3372,19 +3362,25 @@ const std = @import("std"); |
| 3372 | 3362 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3373 | 3363 | // :111:22: note: when computing vector element at index '1' |
| 3374 | 3364 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3375 | // :111:22: note: when computing vector element at index '0' | |
| 3365 | // :111:22: note: when computing vector element at index '1' | |
| 3376 | 3366 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3377 | // :111:22: note: when computing vector element at index '0' | |
| 3367 | // :111:22: note: when computing vector element at index '1' | |
| 3378 | 3368 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3379 | // :111:22: note: when computing vector element at index '0' | |
| 3369 | // :111:22: note: when computing vector element at index '1' | |
| 3380 | 3370 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3381 | // :111:22: note: when computing vector element at index '0' | |
| 3371 | // :111:22: note: when computing vector element at index '1' | |
| 3382 | 3372 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3373 | // :111:22: note: when computing vector element at index '1' | |
| 3383 | 3374 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3375 | // :111:22: note: when computing vector element at index '1' | |
| 3384 | 3376 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3377 | // :111:22: note: when computing vector element at index '1' | |
| 3385 | 3378 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3379 | // :111:22: note: when computing vector element at index '1' | |
| 3386 | 3380 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3381 | // :111:22: note: when computing vector element at index '1' | |
| 3387 | 3382 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3383 | // :111:22: note: when computing vector element at index '1' | |
| 3388 | 3384 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3389 | 3385 | // :111:22: note: when computing vector element at index '1' |
| 3390 | 3386 | // :111:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3394,13 +3390,17 @@ const std = @import("std"); |
| 3394 | 3390 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3395 | 3391 | // :111:22: note: when computing vector element at index '1' |
| 3396 | 3392 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3397 | // :111:22: note: when computing vector element at index '0' | |
| 3393 | // :111:22: note: when computing vector element at index '1' | |
| 3398 | 3394 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3399 | // :111:22: note: when computing vector element at index '0' | |
| 3395 | // :111:22: note: when computing vector element at index '1' | |
| 3400 | 3396 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3401 | // :111:22: note: when computing vector element at index '0' | |
| 3397 | // :111:22: note: when computing vector element at index '1' | |
| 3402 | 3398 | // :111:22: error: use of undefined value here causes illegal behavior |
| 3403 | // :111:22: note: when computing vector element at index '0' | |
| 3399 | // :111:22: note: when computing vector element at index '1' | |
| 3400 | // :111:22: error: use of undefined value here causes illegal behavior | |
| 3401 | // :111:22: note: when computing vector element at index '1' | |
| 3402 | // :111:22: error: use of undefined value here causes illegal behavior | |
| 3403 | // :111:22: note: when computing vector element at index '1' | |
| 3404 | 3404 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3405 | 3405 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3406 | 3406 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3408,21 +3408,13 @@ const std = @import("std"); |
| 3408 | 3408 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3409 | 3409 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3410 | 3410 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3411 | // :115:22: note: when computing vector element at index '1' | |
| 3412 | 3411 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3413 | // :115:22: note: when computing vector element at index '1' | |
| 3414 | 3412 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3415 | // :115:22: note: when computing vector element at index '1' | |
| 3416 | 3413 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3417 | // :115:22: note: when computing vector element at index '1' | |
| 3418 | 3414 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3419 | // :115:22: note: when computing vector element at index '0' | |
| 3420 | 3415 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3421 | // :115:22: note: when computing vector element at index '0' | |
| 3422 | 3416 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3423 | // :115:22: note: when computing vector element at index '0' | |
| 3424 | 3417 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3425 | // :115:22: note: when computing vector element at index '0' | |
| 3426 | 3418 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3427 | 3419 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3428 | 3420 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3430,21 +3422,13 @@ const std = @import("std"); |
| 3430 | 3422 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3431 | 3423 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3432 | 3424 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3433 | // :115:22: note: when computing vector element at index '1' | |
| 3434 | 3425 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3435 | // :115:22: note: when computing vector element at index '1' | |
| 3436 | 3426 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3437 | // :115:22: note: when computing vector element at index '1' | |
| 3438 | 3427 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3439 | // :115:22: note: when computing vector element at index '1' | |
| 3440 | 3428 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3441 | // :115:22: note: when computing vector element at index '0' | |
| 3442 | 3429 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3443 | // :115:22: note: when computing vector element at index '0' | |
| 3444 | 3430 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3445 | // :115:22: note: when computing vector element at index '0' | |
| 3446 | 3431 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3447 | // :115:22: note: when computing vector element at index '0' | |
| 3448 | 3432 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3449 | 3433 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3450 | 3434 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3452,21 +3436,13 @@ const std = @import("std"); |
| 3452 | 3436 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3453 | 3437 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3454 | 3438 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3455 | // :115:22: note: when computing vector element at index '1' | |
| 3456 | 3439 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3457 | // :115:22: note: when computing vector element at index '1' | |
| 3458 | 3440 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3459 | // :115:22: note: when computing vector element at index '1' | |
| 3460 | 3441 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3461 | // :115:22: note: when computing vector element at index '1' | |
| 3462 | 3442 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3463 | // :115:22: note: when computing vector element at index '0' | |
| 3464 | 3443 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3465 | // :115:22: note: when computing vector element at index '0' | |
| 3466 | 3444 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3467 | // :115:22: note: when computing vector element at index '0' | |
| 3468 | 3445 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3469 | // :115:22: note: when computing vector element at index '0' | |
| 3470 | 3446 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3471 | 3447 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3472 | 3448 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3474,21 +3450,13 @@ const std = @import("std"); |
| 3474 | 3450 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3475 | 3451 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3476 | 3452 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3477 | // :115:22: note: when computing vector element at index '1' | |
| 3478 | 3453 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3479 | // :115:22: note: when computing vector element at index '1' | |
| 3480 | 3454 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3481 | // :115:22: note: when computing vector element at index '1' | |
| 3482 | 3455 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3483 | // :115:22: note: when computing vector element at index '1' | |
| 3484 | 3456 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3485 | // :115:22: note: when computing vector element at index '0' | |
| 3486 | 3457 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3487 | // :115:22: note: when computing vector element at index '0' | |
| 3488 | 3458 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3489 | // :115:22: note: when computing vector element at index '0' | |
| 3490 | 3459 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3491 | // :115:22: note: when computing vector element at index '0' | |
| 3492 | 3460 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3493 | 3461 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3494 | 3462 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3496,13 +3464,9 @@ const std = @import("std"); |
| 3496 | 3464 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3497 | 3465 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3498 | 3466 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3499 | // :115:22: note: when computing vector element at index '1' | |
| 3500 | 3467 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3501 | // :115:22: note: when computing vector element at index '1' | |
| 3502 | 3468 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3503 | // :115:22: note: when computing vector element at index '1' | |
| 3504 | 3469 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3505 | // :115:22: note: when computing vector element at index '1' | |
| 3506 | 3470 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3507 | 3471 | // :115:22: note: when computing vector element at index '0' |
| 3508 | 3472 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3512,19 +3476,21 @@ const std = @import("std"); |
| 3512 | 3476 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3513 | 3477 | // :115:22: note: when computing vector element at index '0' |
| 3514 | 3478 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3479 | // :115:22: note: when computing vector element at index '0' | |
| 3515 | 3480 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3481 | // :115:22: note: when computing vector element at index '0' | |
| 3516 | 3482 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3483 | // :115:22: note: when computing vector element at index '0' | |
| 3517 | 3484 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3485 | // :115:22: note: when computing vector element at index '0' | |
| 3518 | 3486 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3487 | // :115:22: note: when computing vector element at index '0' | |
| 3519 | 3488 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3489 | // :115:22: note: when computing vector element at index '0' | |
| 3520 | 3490 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3521 | // :115:22: note: when computing vector element at index '1' | |
| 3522 | // :115:22: error: use of undefined value here causes illegal behavior | |
| 3523 | // :115:22: note: when computing vector element at index '1' | |
| 3524 | // :115:22: error: use of undefined value here causes illegal behavior | |
| 3525 | // :115:22: note: when computing vector element at index '1' | |
| 3491 | // :115:22: note: when computing vector element at index '0' | |
| 3526 | 3492 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3527 | // :115:22: note: when computing vector element at index '1' | |
| 3493 | // :115:22: note: when computing vector element at index '0' | |
| 3528 | 3494 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3529 | 3495 | // :115:22: note: when computing vector element at index '0' |
| 3530 | 3496 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3534,19 +3500,25 @@ const std = @import("std"); |
| 3534 | 3500 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3535 | 3501 | // :115:22: note: when computing vector element at index '0' |
| 3536 | 3502 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3503 | // :115:22: note: when computing vector element at index '0' | |
| 3537 | 3504 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3505 | // :115:22: note: when computing vector element at index '0' | |
| 3538 | 3506 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3507 | // :115:22: note: when computing vector element at index '0' | |
| 3539 | 3508 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3509 | // :115:22: note: when computing vector element at index '0' | |
| 3540 | 3510 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3511 | // :115:22: note: when computing vector element at index '0' | |
| 3541 | 3512 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3513 | // :115:22: note: when computing vector element at index '0' | |
| 3542 | 3514 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3543 | // :115:22: note: when computing vector element at index '1' | |
| 3515 | // :115:22: note: when computing vector element at index '0' | |
| 3544 | 3516 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3545 | // :115:22: note: when computing vector element at index '1' | |
| 3517 | // :115:22: note: when computing vector element at index '0' | |
| 3546 | 3518 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3547 | // :115:22: note: when computing vector element at index '1' | |
| 3519 | // :115:22: note: when computing vector element at index '0' | |
| 3548 | 3520 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3549 | // :115:22: note: when computing vector element at index '1' | |
| 3521 | // :115:22: note: when computing vector element at index '0' | |
| 3550 | 3522 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3551 | 3523 | // :115:22: note: when computing vector element at index '0' |
| 3552 | 3524 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3556,19 +3528,25 @@ const std = @import("std"); |
| 3556 | 3528 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3557 | 3529 | // :115:22: note: when computing vector element at index '0' |
| 3558 | 3530 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3531 | // :115:22: note: when computing vector element at index '0' | |
| 3559 | 3532 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3533 | // :115:22: note: when computing vector element at index '0' | |
| 3560 | 3534 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3535 | // :115:22: note: when computing vector element at index '0' | |
| 3561 | 3536 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3537 | // :115:22: note: when computing vector element at index '0' | |
| 3562 | 3538 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3539 | // :115:22: note: when computing vector element at index '0' | |
| 3563 | 3540 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3541 | // :115:22: note: when computing vector element at index '0' | |
| 3564 | 3542 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3565 | // :115:22: note: when computing vector element at index '1' | |
| 3543 | // :115:22: note: when computing vector element at index '0' | |
| 3566 | 3544 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3567 | // :115:22: note: when computing vector element at index '1' | |
| 3545 | // :115:22: note: when computing vector element at index '0' | |
| 3568 | 3546 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3569 | // :115:22: note: when computing vector element at index '1' | |
| 3547 | // :115:22: note: when computing vector element at index '0' | |
| 3570 | 3548 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3571 | // :115:22: note: when computing vector element at index '1' | |
| 3549 | // :115:22: note: when computing vector element at index '0' | |
| 3572 | 3550 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3573 | 3551 | // :115:22: note: when computing vector element at index '0' |
| 3574 | 3552 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3578,11 +3556,17 @@ const std = @import("std"); |
| 3578 | 3556 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3579 | 3557 | // :115:22: note: when computing vector element at index '0' |
| 3580 | 3558 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3559 | // :115:22: note: when computing vector element at index '1' | |
| 3581 | 3560 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3561 | // :115:22: note: when computing vector element at index '1' | |
| 3582 | 3562 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3563 | // :115:22: note: when computing vector element at index '1' | |
| 3583 | 3564 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3565 | // :115:22: note: when computing vector element at index '1' | |
| 3584 | 3566 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3567 | // :115:22: note: when computing vector element at index '1' | |
| 3585 | 3568 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3569 | // :115:22: note: when computing vector element at index '1' | |
| 3586 | 3570 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3587 | 3571 | // :115:22: note: when computing vector element at index '1' |
| 3588 | 3572 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3592,19 +3576,25 @@ const std = @import("std"); |
| 3592 | 3576 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3593 | 3577 | // :115:22: note: when computing vector element at index '1' |
| 3594 | 3578 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3595 | // :115:22: note: when computing vector element at index '0' | |
| 3579 | // :115:22: note: when computing vector element at index '1' | |
| 3596 | 3580 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3597 | // :115:22: note: when computing vector element at index '0' | |
| 3581 | // :115:22: note: when computing vector element at index '1' | |
| 3598 | 3582 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3599 | // :115:22: note: when computing vector element at index '0' | |
| 3583 | // :115:22: note: when computing vector element at index '1' | |
| 3600 | 3584 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3601 | // :115:22: note: when computing vector element at index '0' | |
| 3585 | // :115:22: note: when computing vector element at index '1' | |
| 3602 | 3586 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3587 | // :115:22: note: when computing vector element at index '1' | |
| 3603 | 3588 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3589 | // :115:22: note: when computing vector element at index '1' | |
| 3604 | 3590 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3591 | // :115:22: note: when computing vector element at index '1' | |
| 3605 | 3592 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3593 | // :115:22: note: when computing vector element at index '1' | |
| 3606 | 3594 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3595 | // :115:22: note: when computing vector element at index '1' | |
| 3607 | 3596 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3597 | // :115:22: note: when computing vector element at index '1' | |
| 3608 | 3598 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3609 | 3599 | // :115:22: note: when computing vector element at index '1' |
| 3610 | 3600 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3614,19 +3604,27 @@ const std = @import("std"); |
| 3614 | 3604 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3615 | 3605 | // :115:22: note: when computing vector element at index '1' |
| 3616 | 3606 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3617 | // :115:22: note: when computing vector element at index '0' | |
| 3607 | // :115:22: note: when computing vector element at index '1' | |
| 3618 | 3608 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3619 | // :115:22: note: when computing vector element at index '0' | |
| 3609 | // :115:22: note: when computing vector element at index '1' | |
| 3620 | 3610 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3621 | // :115:22: note: when computing vector element at index '0' | |
| 3611 | // :115:22: note: when computing vector element at index '1' | |
| 3622 | 3612 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3623 | // :115:22: note: when computing vector element at index '0' | |
| 3613 | // :115:22: note: when computing vector element at index '1' | |
| 3614 | // :115:22: error: use of undefined value here causes illegal behavior | |
| 3615 | // :115:22: note: when computing vector element at index '1' | |
| 3624 | 3616 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3617 | // :115:22: note: when computing vector element at index '1' | |
| 3625 | 3618 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3619 | // :115:22: note: when computing vector element at index '1' | |
| 3626 | 3620 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3621 | // :115:22: note: when computing vector element at index '1' | |
| 3627 | 3622 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3623 | // :115:22: note: when computing vector element at index '1' | |
| 3628 | 3624 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3625 | // :115:22: note: when computing vector element at index '1' | |
| 3629 | 3626 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3627 | // :115:22: note: when computing vector element at index '1' | |
| 3630 | 3628 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3631 | 3629 | // :115:22: note: when computing vector element at index '1' |
| 3632 | 3630 | // :115:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3636,37 +3634,32 @@ const std = @import("std"); |
| 3636 | 3634 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3637 | 3635 | // :115:22: note: when computing vector element at index '1' |
| 3638 | 3636 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3639 | // :115:22: note: when computing vector element at index '0' | |
| 3637 | // :115:22: note: when computing vector element at index '1' | |
| 3640 | 3638 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3641 | // :115:22: note: when computing vector element at index '0' | |
| 3639 | // :115:22: note: when computing vector element at index '1' | |
| 3642 | 3640 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3643 | // :115:22: note: when computing vector element at index '0' | |
| 3641 | // :115:22: note: when computing vector element at index '1' | |
| 3644 | 3642 | // :115:22: error: use of undefined value here causes illegal behavior |
| 3645 | // :115:22: note: when computing vector element at index '0' | |
| 3643 | // :115:22: note: when computing vector element at index '1' | |
| 3644 | // :115:22: error: use of undefined value here causes illegal behavior | |
| 3645 | // :115:22: note: when computing vector element at index '1' | |
| 3646 | // :121:17: error: use of undefined value here causes illegal behavior | |
| 3646 | 3647 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3647 | 3648 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3648 | // :121:17: note: when computing vector element at index '0' | |
| 3649 | 3649 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3650 | // :121:17: note: when computing vector element at index '0' | |
| 3651 | 3650 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3652 | // :121:17: note: when computing vector element at index '0' | |
| 3653 | 3651 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3654 | // :121:17: note: when computing vector element at index '1' | |
| 3655 | 3652 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3656 | // :121:17: note: when computing vector element at index '0' | |
| 3657 | 3653 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3658 | // :121:17: note: when computing vector element at index '0' | |
| 3659 | 3654 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3660 | // :121:17: note: when computing vector element at index '0' | |
| 3661 | 3655 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3662 | 3656 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3663 | // :121:17: note: when computing vector element at index '0' | |
| 3664 | 3657 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3665 | 3658 | // :121:17: note: when computing vector element at index '0' |
| 3666 | 3659 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3667 | 3660 | // :121:17: note: when computing vector element at index '0' |
| 3668 | 3661 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3669 | // :121:17: note: when computing vector element at index '1' | |
| 3662 | // :121:17: note: when computing vector element at index '0' | |
| 3670 | 3663 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3671 | 3664 | // :121:17: note: when computing vector element at index '0' |
| 3672 | 3665 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3674,6 +3667,7 @@ const std = @import("std"); |
| 3674 | 3667 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3675 | 3668 | // :121:17: note: when computing vector element at index '0' |
| 3676 | 3669 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3670 | // :121:17: note: when computing vector element at index '0' | |
| 3677 | 3671 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3678 | 3672 | // :121:17: note: when computing vector element at index '0' |
| 3679 | 3673 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3681,7 +3675,7 @@ const std = @import("std"); |
| 3681 | 3675 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3682 | 3676 | // :121:17: note: when computing vector element at index '0' |
| 3683 | 3677 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3684 | // :121:17: note: when computing vector element at index '1' | |
| 3678 | // :121:17: note: when computing vector element at index '0' | |
| 3685 | 3679 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3686 | 3680 | // :121:17: note: when computing vector element at index '0' |
| 3687 | 3681 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3689,6 +3683,7 @@ const std = @import("std"); |
| 3689 | 3683 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3690 | 3684 | // :121:17: note: when computing vector element at index '0' |
| 3691 | 3685 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3686 | // :121:17: note: when computing vector element at index '0' | |
| 3692 | 3687 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3693 | 3688 | // :121:17: note: when computing vector element at index '0' |
| 3694 | 3689 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3696,7 +3691,7 @@ const std = @import("std"); |
| 3696 | 3691 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3697 | 3692 | // :121:17: note: when computing vector element at index '0' |
| 3698 | 3693 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3699 | // :121:17: note: when computing vector element at index '1' | |
| 3694 | // :121:17: note: when computing vector element at index '0' | |
| 3700 | 3695 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3701 | 3696 | // :121:17: note: when computing vector element at index '0' |
| 3702 | 3697 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3704,6 +3699,7 @@ const std = @import("std"); |
| 3704 | 3699 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3705 | 3700 | // :121:17: note: when computing vector element at index '0' |
| 3706 | 3701 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3702 | // :121:17: note: when computing vector element at index '0' | |
| 3707 | 3703 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3708 | 3704 | // :121:17: note: when computing vector element at index '0' |
| 3709 | 3705 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3711,7 +3707,7 @@ const std = @import("std"); |
| 3711 | 3707 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3712 | 3708 | // :121:17: note: when computing vector element at index '0' |
| 3713 | 3709 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3714 | // :121:17: note: when computing vector element at index '1' | |
| 3710 | // :121:17: note: when computing vector element at index '0' | |
| 3715 | 3711 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3716 | 3712 | // :121:17: note: when computing vector element at index '0' |
| 3717 | 3713 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3719,6 +3715,7 @@ const std = @import("std"); |
| 3719 | 3715 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3720 | 3716 | // :121:17: note: when computing vector element at index '0' |
| 3721 | 3717 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3718 | // :121:17: note: when computing vector element at index '0' | |
| 3722 | 3719 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3723 | 3720 | // :121:17: note: when computing vector element at index '0' |
| 3724 | 3721 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3726,7 +3723,7 @@ const std = @import("std"); |
| 3726 | 3723 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3727 | 3724 | // :121:17: note: when computing vector element at index '0' |
| 3728 | 3725 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3729 | // :121:17: note: when computing vector element at index '1' | |
| 3726 | // :121:17: note: when computing vector element at index '0' | |
| 3730 | 3727 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3731 | 3728 | // :121:17: note: when computing vector element at index '0' |
| 3732 | 3729 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3734,6 +3731,7 @@ const std = @import("std"); |
| 3734 | 3731 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3735 | 3732 | // :121:17: note: when computing vector element at index '0' |
| 3736 | 3733 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3734 | // :121:17: note: when computing vector element at index '0' | |
| 3737 | 3735 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3738 | 3736 | // :121:17: note: when computing vector element at index '0' |
| 3739 | 3737 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3741,7 +3739,7 @@ const std = @import("std"); |
| 3741 | 3739 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3742 | 3740 | // :121:17: note: when computing vector element at index '0' |
| 3743 | 3741 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3744 | // :121:17: note: when computing vector element at index '1' | |
| 3742 | // :121:17: note: when computing vector element at index '0' | |
| 3745 | 3743 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3746 | 3744 | // :121:17: note: when computing vector element at index '0' |
| 3747 | 3745 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3749,6 +3747,7 @@ const std = @import("std"); |
| 3749 | 3747 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3750 | 3748 | // :121:17: note: when computing vector element at index '0' |
| 3751 | 3749 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3750 | // :121:17: note: when computing vector element at index '0' | |
| 3752 | 3751 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3753 | 3752 | // :121:17: note: when computing vector element at index '0' |
| 3754 | 3753 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3756,7 +3755,7 @@ const std = @import("std"); |
| 3756 | 3755 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3757 | 3756 | // :121:17: note: when computing vector element at index '0' |
| 3758 | 3757 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3759 | // :121:17: note: when computing vector element at index '1' | |
| 3758 | // :121:17: note: when computing vector element at index '0' | |
| 3760 | 3759 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3761 | 3760 | // :121:17: note: when computing vector element at index '0' |
| 3762 | 3761 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3764,6 +3763,7 @@ const std = @import("std"); |
| 3764 | 3763 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3765 | 3764 | // :121:17: note: when computing vector element at index '0' |
| 3766 | 3765 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3766 | // :121:17: note: when computing vector element at index '0' | |
| 3767 | 3767 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3768 | 3768 | // :121:17: note: when computing vector element at index '0' |
| 3769 | 3769 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3771,7 +3771,7 @@ const std = @import("std"); |
| 3771 | 3771 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3772 | 3772 | // :121:17: note: when computing vector element at index '0' |
| 3773 | 3773 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3774 | // :121:17: note: when computing vector element at index '1' | |
| 3774 | // :121:17: note: when computing vector element at index '0' | |
| 3775 | 3775 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3776 | 3776 | // :121:17: note: when computing vector element at index '0' |
| 3777 | 3777 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3779,6 +3779,7 @@ const std = @import("std"); |
| 3779 | 3779 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3780 | 3780 | // :121:17: note: when computing vector element at index '0' |
| 3781 | 3781 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3782 | // :121:17: note: when computing vector element at index '0' | |
| 3782 | 3783 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3783 | 3784 | // :121:17: note: when computing vector element at index '0' |
| 3784 | 3785 | // :121:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3788,126 +3789,120 @@ const std = @import("std"); |
| 3788 | 3789 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3789 | 3790 | // :121:17: note: when computing vector element at index '1' |
| 3790 | 3791 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3791 | // :121:17: note: when computing vector element at index '0' | |
| 3792 | // :121:17: error: use of undefined value here causes illegal behavior | |
| 3793 | // :121:17: note: when computing vector element at index '0' | |
| 3792 | // :121:17: note: when computing vector element at index '1' | |
| 3794 | 3793 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3795 | // :121:17: note: when computing vector element at index '0' | |
| 3794 | // :121:17: note: when computing vector element at index '1' | |
| 3796 | 3795 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3796 | // :121:17: note: when computing vector element at index '1' | |
| 3797 | 3797 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3798 | // :121:17: note: when computing vector element at index '0' | |
| 3798 | // :121:17: note: when computing vector element at index '1' | |
| 3799 | 3799 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3800 | // :121:17: note: when computing vector element at index '0' | |
| 3800 | // :121:17: note: when computing vector element at index '1' | |
| 3801 | 3801 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3802 | // :121:17: note: when computing vector element at index '0' | |
| 3802 | // :121:17: note: when computing vector element at index '1' | |
| 3803 | 3803 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3804 | 3804 | // :121:17: note: when computing vector element at index '1' |
| 3805 | 3805 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3806 | // :121:17: note: when computing vector element at index '0' | |
| 3806 | // :121:17: note: when computing vector element at index '1' | |
| 3807 | 3807 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3808 | // :121:17: note: when computing vector element at index '0' | |
| 3808 | // :121:17: note: when computing vector element at index '1' | |
| 3809 | 3809 | // :121:17: error: use of undefined value here causes illegal behavior |
| 3810 | // :121:17: note: when computing vector element at index '0' | |
| 3810 | // :121:17: note: when computing vector element at index '1' | |
| 3811 | 3811 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3812 | 3812 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3813 | // :121:21: note: when computing vector element at index '0' | |
| 3814 | 3813 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3815 | // :121:21: note: when computing vector element at index '0' | |
| 3816 | 3814 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3817 | // :121:21: note: when computing vector element at index '1' | |
| 3818 | 3815 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3819 | // :121:21: note: when computing vector element at index '0' | |
| 3820 | 3816 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3821 | // :121:21: note: when computing vector element at index '0' | |
| 3822 | 3817 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3823 | 3818 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3824 | // :121:21: note: when computing vector element at index '0' | |
| 3825 | 3819 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3826 | // :121:21: note: when computing vector element at index '0' | |
| 3827 | 3820 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3828 | // :121:21: note: when computing vector element at index '1' | |
| 3829 | 3821 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3830 | // :121:21: note: when computing vector element at index '0' | |
| 3831 | 3822 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3832 | 3823 | // :121:21: note: when computing vector element at index '0' |
| 3833 | 3824 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3834 | // :121:21: error: use of undefined value here causes illegal behavior | |
| 3835 | 3825 | // :121:21: note: when computing vector element at index '0' |
| 3836 | 3826 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3837 | 3827 | // :121:21: note: when computing vector element at index '0' |
| 3838 | 3828 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3839 | // :121:21: note: when computing vector element at index '1' | |
| 3840 | // :121:21: error: use of undefined value here causes illegal behavior | |
| 3841 | 3829 | // :121:21: note: when computing vector element at index '0' |
| 3842 | 3830 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3843 | 3831 | // :121:21: note: when computing vector element at index '0' |
| 3844 | 3832 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3833 | // :121:21: note: when computing vector element at index '0' | |
| 3845 | 3834 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3846 | 3835 | // :121:21: note: when computing vector element at index '0' |
| 3847 | 3836 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3848 | 3837 | // :121:21: note: when computing vector element at index '0' |
| 3849 | 3838 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3850 | // :121:21: note: when computing vector element at index '1' | |
| 3839 | // :121:21: note: when computing vector element at index '0' | |
| 3851 | 3840 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3852 | 3841 | // :121:21: note: when computing vector element at index '0' |
| 3853 | 3842 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3854 | 3843 | // :121:21: note: when computing vector element at index '0' |
| 3855 | 3844 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3845 | // :121:21: note: when computing vector element at index '0' | |
| 3856 | 3846 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3857 | 3847 | // :121:21: note: when computing vector element at index '0' |
| 3858 | 3848 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3859 | 3849 | // :121:21: note: when computing vector element at index '0' |
| 3860 | 3850 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3861 | // :121:21: note: when computing vector element at index '1' | |
| 3851 | // :121:21: note: when computing vector element at index '0' | |
| 3862 | 3852 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3863 | 3853 | // :121:21: note: when computing vector element at index '0' |
| 3864 | 3854 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3865 | 3855 | // :121:21: note: when computing vector element at index '0' |
| 3866 | 3856 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3857 | // :121:21: note: when computing vector element at index '0' | |
| 3867 | 3858 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3868 | 3859 | // :121:21: note: when computing vector element at index '0' |
| 3869 | 3860 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3870 | 3861 | // :121:21: note: when computing vector element at index '0' |
| 3871 | 3862 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3872 | // :121:21: note: when computing vector element at index '1' | |
| 3863 | // :121:21: note: when computing vector element at index '0' | |
| 3873 | 3864 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3874 | 3865 | // :121:21: note: when computing vector element at index '0' |
| 3875 | 3866 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3876 | 3867 | // :121:21: note: when computing vector element at index '0' |
| 3877 | 3868 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3869 | // :121:21: note: when computing vector element at index '0' | |
| 3878 | 3870 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3879 | 3871 | // :121:21: note: when computing vector element at index '0' |
| 3880 | 3872 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3881 | 3873 | // :121:21: note: when computing vector element at index '0' |
| 3882 | 3874 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3883 | // :121:21: note: when computing vector element at index '1' | |
| 3875 | // :121:21: note: when computing vector element at index '0' | |
| 3884 | 3876 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3885 | 3877 | // :121:21: note: when computing vector element at index '0' |
| 3886 | 3878 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3887 | 3879 | // :121:21: note: when computing vector element at index '0' |
| 3888 | 3880 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3881 | // :121:21: note: when computing vector element at index '0' | |
| 3889 | 3882 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3890 | 3883 | // :121:21: note: when computing vector element at index '0' |
| 3891 | 3884 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3892 | 3885 | // :121:21: note: when computing vector element at index '0' |
| 3893 | 3886 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3894 | // :121:21: note: when computing vector element at index '1' | |
| 3887 | // :121:21: note: when computing vector element at index '0' | |
| 3895 | 3888 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3896 | 3889 | // :121:21: note: when computing vector element at index '0' |
| 3897 | 3890 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3898 | 3891 | // :121:21: note: when computing vector element at index '0' |
| 3899 | 3892 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3893 | // :121:21: note: when computing vector element at index '0' | |
| 3900 | 3894 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3901 | 3895 | // :121:21: note: when computing vector element at index '0' |
| 3902 | 3896 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3903 | 3897 | // :121:21: note: when computing vector element at index '0' |
| 3904 | 3898 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3905 | // :121:21: note: when computing vector element at index '1' | |
| 3899 | // :121:21: note: when computing vector element at index '0' | |
| 3906 | 3900 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3907 | 3901 | // :121:21: note: when computing vector element at index '0' |
| 3908 | 3902 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3909 | 3903 | // :121:21: note: when computing vector element at index '0' |
| 3910 | 3904 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3905 | // :121:21: note: when computing vector element at index '0' | |
| 3911 | 3906 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3912 | 3907 | // :121:21: note: when computing vector element at index '0' |
| 3913 | 3908 | // :121:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3915,44 +3910,42 @@ const std = @import("std"); |
| 3915 | 3910 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3916 | 3911 | // :121:21: note: when computing vector element at index '1' |
| 3917 | 3912 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3918 | // :121:21: note: when computing vector element at index '0' | |
| 3913 | // :121:21: note: when computing vector element at index '1' | |
| 3919 | 3914 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3920 | // :121:21: note: when computing vector element at index '0' | |
| 3915 | // :121:21: note: when computing vector element at index '1' | |
| 3921 | 3916 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3917 | // :121:21: note: when computing vector element at index '1' | |
| 3922 | 3918 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3923 | // :121:21: note: when computing vector element at index '0' | |
| 3919 | // :121:21: note: when computing vector element at index '1' | |
| 3924 | 3920 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3925 | // :121:21: note: when computing vector element at index '0' | |
| 3921 | // :121:21: note: when computing vector element at index '1' | |
| 3926 | 3922 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3927 | 3923 | // :121:21: note: when computing vector element at index '1' |
| 3928 | 3924 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3929 | // :121:21: note: when computing vector element at index '0' | |
| 3925 | // :121:21: note: when computing vector element at index '1' | |
| 3930 | 3926 | // :121:21: error: use of undefined value here causes illegal behavior |
| 3931 | // :121:21: note: when computing vector element at index '0' | |
| 3927 | // :121:21: note: when computing vector element at index '1' | |
| 3928 | // :121:21: error: use of undefined value here causes illegal behavior | |
| 3929 | // :121:21: note: when computing vector element at index '1' | |
| 3930 | // :121:21: error: use of undefined value here causes illegal behavior | |
| 3931 | // :121:21: note: when computing vector element at index '1' | |
| 3932 | // :125:27: error: use of undefined value here causes illegal behavior | |
| 3932 | 3933 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3933 | 3934 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3934 | // :125:27: note: when computing vector element at index '0' | |
| 3935 | 3935 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3936 | // :125:27: note: when computing vector element at index '0' | |
| 3937 | 3936 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3938 | // :125:27: note: when computing vector element at index '0' | |
| 3939 | 3937 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3940 | // :125:27: note: when computing vector element at index '1' | |
| 3941 | 3938 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3942 | // :125:27: note: when computing vector element at index '0' | |
| 3943 | 3939 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3944 | // :125:27: note: when computing vector element at index '0' | |
| 3945 | 3940 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3946 | // :125:27: note: when computing vector element at index '0' | |
| 3947 | 3941 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3948 | 3942 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3949 | // :125:27: note: when computing vector element at index '0' | |
| 3950 | 3943 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3951 | 3944 | // :125:27: note: when computing vector element at index '0' |
| 3952 | 3945 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3953 | 3946 | // :125:27: note: when computing vector element at index '0' |
| 3954 | 3947 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3955 | // :125:27: note: when computing vector element at index '1' | |
| 3948 | // :125:27: note: when computing vector element at index '0' | |
| 3956 | 3949 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3957 | 3950 | // :125:27: note: when computing vector element at index '0' |
| 3958 | 3951 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3960,6 +3953,7 @@ const std = @import("std"); |
| 3960 | 3953 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3961 | 3954 | // :125:27: note: when computing vector element at index '0' |
| 3962 | 3955 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3956 | // :125:27: note: when computing vector element at index '0' | |
| 3963 | 3957 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3964 | 3958 | // :125:27: note: when computing vector element at index '0' |
| 3965 | 3959 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3967,7 +3961,7 @@ const std = @import("std"); |
| 3967 | 3961 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3968 | 3962 | // :125:27: note: when computing vector element at index '0' |
| 3969 | 3963 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3970 | // :125:27: note: when computing vector element at index '1' | |
| 3964 | // :125:27: note: when computing vector element at index '0' | |
| 3971 | 3965 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3972 | 3966 | // :125:27: note: when computing vector element at index '0' |
| 3973 | 3967 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3975,6 +3969,7 @@ const std = @import("std"); |
| 3975 | 3969 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3976 | 3970 | // :125:27: note: when computing vector element at index '0' |
| 3977 | 3971 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3972 | // :125:27: note: when computing vector element at index '0' | |
| 3978 | 3973 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3979 | 3974 | // :125:27: note: when computing vector element at index '0' |
| 3980 | 3975 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3982,7 +3977,7 @@ const std = @import("std"); |
| 3982 | 3977 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3983 | 3978 | // :125:27: note: when computing vector element at index '0' |
| 3984 | 3979 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3985 | // :125:27: note: when computing vector element at index '1' | |
| 3980 | // :125:27: note: when computing vector element at index '0' | |
| 3986 | 3981 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3987 | 3982 | // :125:27: note: when computing vector element at index '0' |
| 3988 | 3983 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3990,6 +3985,7 @@ const std = @import("std"); |
| 3990 | 3985 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3991 | 3986 | // :125:27: note: when computing vector element at index '0' |
| 3992 | 3987 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3988 | // :125:27: note: when computing vector element at index '0' | |
| 3993 | 3989 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3994 | 3990 | // :125:27: note: when computing vector element at index '0' |
| 3995 | 3991 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -3997,7 +3993,7 @@ const std = @import("std"); |
| 3997 | 3993 | // :125:27: error: use of undefined value here causes illegal behavior |
| 3998 | 3994 | // :125:27: note: when computing vector element at index '0' |
| 3999 | 3995 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4000 | // :125:27: note: when computing vector element at index '1' | |
| 3996 | // :125:27: note: when computing vector element at index '0' | |
| 4001 | 3997 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4002 | 3998 | // :125:27: note: when computing vector element at index '0' |
| 4003 | 3999 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4005,6 +4001,7 @@ const std = @import("std"); |
| 4005 | 4001 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4006 | 4002 | // :125:27: note: when computing vector element at index '0' |
| 4007 | 4003 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4004 | // :125:27: note: when computing vector element at index '0' | |
| 4008 | 4005 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4009 | 4006 | // :125:27: note: when computing vector element at index '0' |
| 4010 | 4007 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4012,7 +4009,7 @@ const std = @import("std"); |
| 4012 | 4009 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4013 | 4010 | // :125:27: note: when computing vector element at index '0' |
| 4014 | 4011 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4015 | // :125:27: note: when computing vector element at index '1' | |
| 4012 | // :125:27: note: when computing vector element at index '0' | |
| 4016 | 4013 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4017 | 4014 | // :125:27: note: when computing vector element at index '0' |
| 4018 | 4015 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4020,6 +4017,7 @@ const std = @import("std"); |
| 4020 | 4017 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4021 | 4018 | // :125:27: note: when computing vector element at index '0' |
| 4022 | 4019 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4020 | // :125:27: note: when computing vector element at index '0' | |
| 4023 | 4021 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4024 | 4022 | // :125:27: note: when computing vector element at index '0' |
| 4025 | 4023 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4027,7 +4025,7 @@ const std = @import("std"); |
| 4027 | 4025 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4028 | 4026 | // :125:27: note: when computing vector element at index '0' |
| 4029 | 4027 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4030 | // :125:27: note: when computing vector element at index '1' | |
| 4028 | // :125:27: note: when computing vector element at index '0' | |
| 4031 | 4029 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4032 | 4030 | // :125:27: note: when computing vector element at index '0' |
| 4033 | 4031 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4035,6 +4033,7 @@ const std = @import("std"); |
| 4035 | 4033 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4036 | 4034 | // :125:27: note: when computing vector element at index '0' |
| 4037 | 4035 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4036 | // :125:27: note: when computing vector element at index '0' | |
| 4038 | 4037 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4039 | 4038 | // :125:27: note: when computing vector element at index '0' |
| 4040 | 4039 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4042,7 +4041,7 @@ const std = @import("std"); |
| 4042 | 4041 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4043 | 4042 | // :125:27: note: when computing vector element at index '0' |
| 4044 | 4043 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4045 | // :125:27: note: when computing vector element at index '1' | |
| 4044 | // :125:27: note: when computing vector element at index '0' | |
| 4046 | 4045 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4047 | 4046 | // :125:27: note: when computing vector element at index '0' |
| 4048 | 4047 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4050,6 +4049,7 @@ const std = @import("std"); |
| 4050 | 4049 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4051 | 4050 | // :125:27: note: when computing vector element at index '0' |
| 4052 | 4051 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4052 | // :125:27: note: when computing vector element at index '0' | |
| 4053 | 4053 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4054 | 4054 | // :125:27: note: when computing vector element at index '0' |
| 4055 | 4055 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4057,7 +4057,7 @@ const std = @import("std"); |
| 4057 | 4057 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4058 | 4058 | // :125:27: note: when computing vector element at index '0' |
| 4059 | 4059 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4060 | // :125:27: note: when computing vector element at index '1' | |
| 4060 | // :125:27: note: when computing vector element at index '0' | |
| 4061 | 4061 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4062 | 4062 | // :125:27: note: when computing vector element at index '0' |
| 4063 | 4063 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4065,6 +4065,7 @@ const std = @import("std"); |
| 4065 | 4065 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4066 | 4066 | // :125:27: note: when computing vector element at index '0' |
| 4067 | 4067 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4068 | // :125:27: note: when computing vector element at index '0' | |
| 4068 | 4069 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4069 | 4070 | // :125:27: note: when computing vector element at index '0' |
| 4070 | 4071 | // :125:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4074,126 +4075,120 @@ const std = @import("std"); |
| 4074 | 4075 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4075 | 4076 | // :125:27: note: when computing vector element at index '1' |
| 4076 | 4077 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4077 | // :125:27: note: when computing vector element at index '0' | |
| 4078 | // :125:27: error: use of undefined value here causes illegal behavior | |
| 4079 | // :125:27: note: when computing vector element at index '0' | |
| 4078 | // :125:27: note: when computing vector element at index '1' | |
| 4080 | 4079 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4081 | // :125:27: note: when computing vector element at index '0' | |
| 4080 | // :125:27: note: when computing vector element at index '1' | |
| 4082 | 4081 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4082 | // :125:27: note: when computing vector element at index '1' | |
| 4083 | 4083 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4084 | // :125:27: note: when computing vector element at index '0' | |
| 4084 | // :125:27: note: when computing vector element at index '1' | |
| 4085 | 4085 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4086 | // :125:27: note: when computing vector element at index '0' | |
| 4086 | // :125:27: note: when computing vector element at index '1' | |
| 4087 | 4087 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4088 | // :125:27: note: when computing vector element at index '0' | |
| 4088 | // :125:27: note: when computing vector element at index '1' | |
| 4089 | 4089 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4090 | 4090 | // :125:27: note: when computing vector element at index '1' |
| 4091 | 4091 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4092 | // :125:27: note: when computing vector element at index '0' | |
| 4092 | // :125:27: note: when computing vector element at index '1' | |
| 4093 | 4093 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4094 | // :125:27: note: when computing vector element at index '0' | |
| 4094 | // :125:27: note: when computing vector element at index '1' | |
| 4095 | 4095 | // :125:27: error: use of undefined value here causes illegal behavior |
| 4096 | // :125:27: note: when computing vector element at index '0' | |
| 4096 | // :125:27: note: when computing vector element at index '1' | |
| 4097 | 4097 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4098 | 4098 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4099 | // :125:30: note: when computing vector element at index '0' | |
| 4100 | 4099 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4101 | // :125:30: note: when computing vector element at index '0' | |
| 4102 | 4100 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4103 | // :125:30: note: when computing vector element at index '1' | |
| 4104 | 4101 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4105 | // :125:30: note: when computing vector element at index '0' | |
| 4106 | 4102 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4107 | // :125:30: note: when computing vector element at index '0' | |
| 4108 | 4103 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4109 | 4104 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4110 | // :125:30: note: when computing vector element at index '0' | |
| 4111 | 4105 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4112 | // :125:30: note: when computing vector element at index '0' | |
| 4113 | 4106 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4114 | // :125:30: note: when computing vector element at index '1' | |
| 4115 | 4107 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4116 | // :125:30: note: when computing vector element at index '0' | |
| 4117 | 4108 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4118 | 4109 | // :125:30: note: when computing vector element at index '0' |
| 4119 | 4110 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4120 | // :125:30: error: use of undefined value here causes illegal behavior | |
| 4121 | 4111 | // :125:30: note: when computing vector element at index '0' |
| 4122 | 4112 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4123 | 4113 | // :125:30: note: when computing vector element at index '0' |
| 4124 | 4114 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4125 | // :125:30: note: when computing vector element at index '1' | |
| 4126 | // :125:30: error: use of undefined value here causes illegal behavior | |
| 4127 | 4115 | // :125:30: note: when computing vector element at index '0' |
| 4128 | 4116 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4129 | 4117 | // :125:30: note: when computing vector element at index '0' |
| 4130 | 4118 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4119 | // :125:30: note: when computing vector element at index '0' | |
| 4131 | 4120 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4132 | 4121 | // :125:30: note: when computing vector element at index '0' |
| 4133 | 4122 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4134 | 4123 | // :125:30: note: when computing vector element at index '0' |
| 4135 | 4124 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4136 | // :125:30: note: when computing vector element at index '1' | |
| 4125 | // :125:30: note: when computing vector element at index '0' | |
| 4137 | 4126 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4138 | 4127 | // :125:30: note: when computing vector element at index '0' |
| 4139 | 4128 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4140 | 4129 | // :125:30: note: when computing vector element at index '0' |
| 4141 | 4130 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4131 | // :125:30: note: when computing vector element at index '0' | |
| 4142 | 4132 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4143 | 4133 | // :125:30: note: when computing vector element at index '0' |
| 4144 | 4134 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4145 | 4135 | // :125:30: note: when computing vector element at index '0' |
| 4146 | 4136 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4147 | // :125:30: note: when computing vector element at index '1' | |
| 4137 | // :125:30: note: when computing vector element at index '0' | |
| 4148 | 4138 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4149 | 4139 | // :125:30: note: when computing vector element at index '0' |
| 4150 | 4140 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4151 | 4141 | // :125:30: note: when computing vector element at index '0' |
| 4152 | 4142 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4143 | // :125:30: note: when computing vector element at index '0' | |
| 4153 | 4144 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4154 | 4145 | // :125:30: note: when computing vector element at index '0' |
| 4155 | 4146 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4156 | 4147 | // :125:30: note: when computing vector element at index '0' |
| 4157 | 4148 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4158 | // :125:30: note: when computing vector element at index '1' | |
| 4149 | // :125:30: note: when computing vector element at index '0' | |
| 4159 | 4150 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4160 | 4151 | // :125:30: note: when computing vector element at index '0' |
| 4161 | 4152 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4162 | 4153 | // :125:30: note: when computing vector element at index '0' |
| 4163 | 4154 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4155 | // :125:30: note: when computing vector element at index '0' | |
| 4164 | 4156 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4165 | 4157 | // :125:30: note: when computing vector element at index '0' |
| 4166 | 4158 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4167 | 4159 | // :125:30: note: when computing vector element at index '0' |
| 4168 | 4160 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4169 | // :125:30: note: when computing vector element at index '1' | |
| 4161 | // :125:30: note: when computing vector element at index '0' | |
| 4170 | 4162 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4171 | 4163 | // :125:30: note: when computing vector element at index '0' |
| 4172 | 4164 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4173 | 4165 | // :125:30: note: when computing vector element at index '0' |
| 4174 | 4166 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4167 | // :125:30: note: when computing vector element at index '0' | |
| 4175 | 4168 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4176 | 4169 | // :125:30: note: when computing vector element at index '0' |
| 4177 | 4170 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4178 | 4171 | // :125:30: note: when computing vector element at index '0' |
| 4179 | 4172 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4180 | // :125:30: note: when computing vector element at index '1' | |
| 4173 | // :125:30: note: when computing vector element at index '0' | |
| 4181 | 4174 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4182 | 4175 | // :125:30: note: when computing vector element at index '0' |
| 4183 | 4176 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4184 | 4177 | // :125:30: note: when computing vector element at index '0' |
| 4185 | 4178 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4179 | // :125:30: note: when computing vector element at index '0' | |
| 4186 | 4180 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4187 | 4181 | // :125:30: note: when computing vector element at index '0' |
| 4188 | 4182 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4189 | 4183 | // :125:30: note: when computing vector element at index '0' |
| 4190 | 4184 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4191 | // :125:30: note: when computing vector element at index '1' | |
| 4185 | // :125:30: note: when computing vector element at index '0' | |
| 4192 | 4186 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4193 | 4187 | // :125:30: note: when computing vector element at index '0' |
| 4194 | 4188 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4195 | 4189 | // :125:30: note: when computing vector element at index '0' |
| 4196 | 4190 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4191 | // :125:30: note: when computing vector element at index '0' | |
| 4197 | 4192 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4198 | 4193 | // :125:30: note: when computing vector element at index '0' |
| 4199 | 4194 | // :125:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4201,44 +4196,42 @@ const std = @import("std"); |
| 4201 | 4196 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4202 | 4197 | // :125:30: note: when computing vector element at index '1' |
| 4203 | 4198 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4204 | // :125:30: note: when computing vector element at index '0' | |
| 4199 | // :125:30: note: when computing vector element at index '1' | |
| 4205 | 4200 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4206 | // :125:30: note: when computing vector element at index '0' | |
| 4201 | // :125:30: note: when computing vector element at index '1' | |
| 4207 | 4202 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4203 | // :125:30: note: when computing vector element at index '1' | |
| 4208 | 4204 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4209 | // :125:30: note: when computing vector element at index '0' | |
| 4205 | // :125:30: note: when computing vector element at index '1' | |
| 4210 | 4206 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4211 | // :125:30: note: when computing vector element at index '0' | |
| 4207 | // :125:30: note: when computing vector element at index '1' | |
| 4212 | 4208 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4213 | 4209 | // :125:30: note: when computing vector element at index '1' |
| 4214 | 4210 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4215 | // :125:30: note: when computing vector element at index '0' | |
| 4211 | // :125:30: note: when computing vector element at index '1' | |
| 4216 | 4212 | // :125:30: error: use of undefined value here causes illegal behavior |
| 4217 | // :125:30: note: when computing vector element at index '0' | |
| 4213 | // :125:30: note: when computing vector element at index '1' | |
| 4214 | // :125:30: error: use of undefined value here causes illegal behavior | |
| 4215 | // :125:30: note: when computing vector element at index '1' | |
| 4216 | // :125:30: error: use of undefined value here causes illegal behavior | |
| 4217 | // :125:30: note: when computing vector element at index '1' | |
| 4218 | // :129:27: error: use of undefined value here causes illegal behavior | |
| 4218 | 4219 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4219 | 4220 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4220 | // :129:27: note: when computing vector element at index '0' | |
| 4221 | 4221 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4222 | // :129:27: note: when computing vector element at index '0' | |
| 4223 | 4222 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4224 | // :129:27: note: when computing vector element at index '0' | |
| 4225 | 4223 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4226 | // :129:27: note: when computing vector element at index '1' | |
| 4227 | 4224 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4228 | // :129:27: note: when computing vector element at index '0' | |
| 4229 | 4225 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4230 | // :129:27: note: when computing vector element at index '0' | |
| 4231 | 4226 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4232 | // :129:27: note: when computing vector element at index '0' | |
| 4233 | 4227 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4234 | 4228 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4235 | // :129:27: note: when computing vector element at index '0' | |
| 4236 | 4229 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4237 | 4230 | // :129:27: note: when computing vector element at index '0' |
| 4238 | 4231 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4239 | 4232 | // :129:27: note: when computing vector element at index '0' |
| 4240 | 4233 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4241 | // :129:27: note: when computing vector element at index '1' | |
| 4234 | // :129:27: note: when computing vector element at index '0' | |
| 4242 | 4235 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4243 | 4236 | // :129:27: note: when computing vector element at index '0' |
| 4244 | 4237 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4246,6 +4239,7 @@ const std = @import("std"); |
| 4246 | 4239 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4247 | 4240 | // :129:27: note: when computing vector element at index '0' |
| 4248 | 4241 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4242 | // :129:27: note: when computing vector element at index '0' | |
| 4249 | 4243 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4250 | 4244 | // :129:27: note: when computing vector element at index '0' |
| 4251 | 4245 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4253,7 +4247,7 @@ const std = @import("std"); |
| 4253 | 4247 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4254 | 4248 | // :129:27: note: when computing vector element at index '0' |
| 4255 | 4249 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4256 | // :129:27: note: when computing vector element at index '1' | |
| 4250 | // :129:27: note: when computing vector element at index '0' | |
| 4257 | 4251 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4258 | 4252 | // :129:27: note: when computing vector element at index '0' |
| 4259 | 4253 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4261,6 +4255,7 @@ const std = @import("std"); |
| 4261 | 4255 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4262 | 4256 | // :129:27: note: when computing vector element at index '0' |
| 4263 | 4257 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4258 | // :129:27: note: when computing vector element at index '0' | |
| 4264 | 4259 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4265 | 4260 | // :129:27: note: when computing vector element at index '0' |
| 4266 | 4261 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4268,7 +4263,7 @@ const std = @import("std"); |
| 4268 | 4263 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4269 | 4264 | // :129:27: note: when computing vector element at index '0' |
| 4270 | 4265 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4271 | // :129:27: note: when computing vector element at index '1' | |
| 4266 | // :129:27: note: when computing vector element at index '0' | |
| 4272 | 4267 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4273 | 4268 | // :129:27: note: when computing vector element at index '0' |
| 4274 | 4269 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4276,6 +4271,7 @@ const std = @import("std"); |
| 4276 | 4271 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4277 | 4272 | // :129:27: note: when computing vector element at index '0' |
| 4278 | 4273 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4274 | // :129:27: note: when computing vector element at index '0' | |
| 4279 | 4275 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4280 | 4276 | // :129:27: note: when computing vector element at index '0' |
| 4281 | 4277 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4283,7 +4279,7 @@ const std = @import("std"); |
| 4283 | 4279 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4284 | 4280 | // :129:27: note: when computing vector element at index '0' |
| 4285 | 4281 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4286 | // :129:27: note: when computing vector element at index '1' | |
| 4282 | // :129:27: note: when computing vector element at index '0' | |
| 4287 | 4283 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4288 | 4284 | // :129:27: note: when computing vector element at index '0' |
| 4289 | 4285 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4291,6 +4287,7 @@ const std = @import("std"); |
| 4291 | 4287 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4292 | 4288 | // :129:27: note: when computing vector element at index '0' |
| 4293 | 4289 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4290 | // :129:27: note: when computing vector element at index '0' | |
| 4294 | 4291 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4295 | 4292 | // :129:27: note: when computing vector element at index '0' |
| 4296 | 4293 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4298,7 +4295,7 @@ const std = @import("std"); |
| 4298 | 4295 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4299 | 4296 | // :129:27: note: when computing vector element at index '0' |
| 4300 | 4297 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4301 | // :129:27: note: when computing vector element at index '1' | |
| 4298 | // :129:27: note: when computing vector element at index '0' | |
| 4302 | 4299 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4303 | 4300 | // :129:27: note: when computing vector element at index '0' |
| 4304 | 4301 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4306,6 +4303,7 @@ const std = @import("std"); |
| 4306 | 4303 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4307 | 4304 | // :129:27: note: when computing vector element at index '0' |
| 4308 | 4305 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4306 | // :129:27: note: when computing vector element at index '0' | |
| 4309 | 4307 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4310 | 4308 | // :129:27: note: when computing vector element at index '0' |
| 4311 | 4309 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4313,7 +4311,7 @@ const std = @import("std"); |
| 4313 | 4311 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4314 | 4312 | // :129:27: note: when computing vector element at index '0' |
| 4315 | 4313 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4316 | // :129:27: note: when computing vector element at index '1' | |
| 4314 | // :129:27: note: when computing vector element at index '0' | |
| 4317 | 4315 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4318 | 4316 | // :129:27: note: when computing vector element at index '0' |
| 4319 | 4317 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4321,6 +4319,7 @@ const std = @import("std"); |
| 4321 | 4319 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4322 | 4320 | // :129:27: note: when computing vector element at index '0' |
| 4323 | 4321 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4322 | // :129:27: note: when computing vector element at index '0' | |
| 4324 | 4323 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4325 | 4324 | // :129:27: note: when computing vector element at index '0' |
| 4326 | 4325 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4328,7 +4327,7 @@ const std = @import("std"); |
| 4328 | 4327 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4329 | 4328 | // :129:27: note: when computing vector element at index '0' |
| 4330 | 4329 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4331 | // :129:27: note: when computing vector element at index '1' | |
| 4330 | // :129:27: note: when computing vector element at index '0' | |
| 4332 | 4331 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4333 | 4332 | // :129:27: note: when computing vector element at index '0' |
| 4334 | 4333 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4336,6 +4335,7 @@ const std = @import("std"); |
| 4336 | 4335 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4337 | 4336 | // :129:27: note: when computing vector element at index '0' |
| 4338 | 4337 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4338 | // :129:27: note: when computing vector element at index '0' | |
| 4339 | 4339 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4340 | 4340 | // :129:27: note: when computing vector element at index '0' |
| 4341 | 4341 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4343,7 +4343,7 @@ const std = @import("std"); |
| 4343 | 4343 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4344 | 4344 | // :129:27: note: when computing vector element at index '0' |
| 4345 | 4345 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4346 | // :129:27: note: when computing vector element at index '1' | |
| 4346 | // :129:27: note: when computing vector element at index '0' | |
| 4347 | 4347 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4348 | 4348 | // :129:27: note: when computing vector element at index '0' |
| 4349 | 4349 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4351,6 +4351,7 @@ const std = @import("std"); |
| 4351 | 4351 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4352 | 4352 | // :129:27: note: when computing vector element at index '0' |
| 4353 | 4353 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4354 | // :129:27: note: when computing vector element at index '0' | |
| 4354 | 4355 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4355 | 4356 | // :129:27: note: when computing vector element at index '0' |
| 4356 | 4357 | // :129:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4360,126 +4361,120 @@ const std = @import("std"); |
| 4360 | 4361 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4361 | 4362 | // :129:27: note: when computing vector element at index '1' |
| 4362 | 4363 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4363 | // :129:27: note: when computing vector element at index '0' | |
| 4364 | // :129:27: error: use of undefined value here causes illegal behavior | |
| 4365 | // :129:27: note: when computing vector element at index '0' | |
| 4364 | // :129:27: note: when computing vector element at index '1' | |
| 4366 | 4365 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4367 | // :129:27: note: when computing vector element at index '0' | |
| 4366 | // :129:27: note: when computing vector element at index '1' | |
| 4368 | 4367 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4368 | // :129:27: note: when computing vector element at index '1' | |
| 4369 | 4369 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4370 | // :129:27: note: when computing vector element at index '0' | |
| 4370 | // :129:27: note: when computing vector element at index '1' | |
| 4371 | 4371 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4372 | // :129:27: note: when computing vector element at index '0' | |
| 4372 | // :129:27: note: when computing vector element at index '1' | |
| 4373 | 4373 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4374 | // :129:27: note: when computing vector element at index '0' | |
| 4374 | // :129:27: note: when computing vector element at index '1' | |
| 4375 | 4375 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4376 | 4376 | // :129:27: note: when computing vector element at index '1' |
| 4377 | 4377 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4378 | // :129:27: note: when computing vector element at index '0' | |
| 4378 | // :129:27: note: when computing vector element at index '1' | |
| 4379 | 4379 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4380 | // :129:27: note: when computing vector element at index '0' | |
| 4380 | // :129:27: note: when computing vector element at index '1' | |
| 4381 | 4381 | // :129:27: error: use of undefined value here causes illegal behavior |
| 4382 | // :129:27: note: when computing vector element at index '0' | |
| 4382 | // :129:27: note: when computing vector element at index '1' | |
| 4383 | 4383 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4384 | 4384 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4385 | // :129:30: note: when computing vector element at index '0' | |
| 4386 | 4385 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4387 | // :129:30: note: when computing vector element at index '0' | |
| 4388 | 4386 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4389 | // :129:30: note: when computing vector element at index '1' | |
| 4390 | 4387 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4391 | // :129:30: note: when computing vector element at index '0' | |
| 4392 | 4388 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4393 | // :129:30: note: when computing vector element at index '0' | |
| 4394 | 4389 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4395 | 4390 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4396 | // :129:30: note: when computing vector element at index '0' | |
| 4397 | 4391 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4398 | // :129:30: note: when computing vector element at index '0' | |
| 4399 | 4392 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4400 | // :129:30: note: when computing vector element at index '1' | |
| 4401 | 4393 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4402 | // :129:30: note: when computing vector element at index '0' | |
| 4403 | 4394 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4404 | 4395 | // :129:30: note: when computing vector element at index '0' |
| 4405 | 4396 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4406 | // :129:30: error: use of undefined value here causes illegal behavior | |
| 4407 | 4397 | // :129:30: note: when computing vector element at index '0' |
| 4408 | 4398 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4409 | 4399 | // :129:30: note: when computing vector element at index '0' |
| 4410 | 4400 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4411 | // :129:30: note: when computing vector element at index '1' | |
| 4412 | // :129:30: error: use of undefined value here causes illegal behavior | |
| 4413 | 4401 | // :129:30: note: when computing vector element at index '0' |
| 4414 | 4402 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4415 | 4403 | // :129:30: note: when computing vector element at index '0' |
| 4416 | 4404 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4405 | // :129:30: note: when computing vector element at index '0' | |
| 4417 | 4406 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4418 | 4407 | // :129:30: note: when computing vector element at index '0' |
| 4419 | 4408 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4420 | 4409 | // :129:30: note: when computing vector element at index '0' |
| 4421 | 4410 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4422 | // :129:30: note: when computing vector element at index '1' | |
| 4411 | // :129:30: note: when computing vector element at index '0' | |
| 4423 | 4412 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4424 | 4413 | // :129:30: note: when computing vector element at index '0' |
| 4425 | 4414 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4426 | 4415 | // :129:30: note: when computing vector element at index '0' |
| 4427 | 4416 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4417 | // :129:30: note: when computing vector element at index '0' | |
| 4428 | 4418 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4429 | 4419 | // :129:30: note: when computing vector element at index '0' |
| 4430 | 4420 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4431 | 4421 | // :129:30: note: when computing vector element at index '0' |
| 4432 | 4422 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4433 | // :129:30: note: when computing vector element at index '1' | |
| 4423 | // :129:30: note: when computing vector element at index '0' | |
| 4434 | 4424 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4435 | 4425 | // :129:30: note: when computing vector element at index '0' |
| 4436 | 4426 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4437 | 4427 | // :129:30: note: when computing vector element at index '0' |
| 4438 | 4428 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4429 | // :129:30: note: when computing vector element at index '0' | |
| 4439 | 4430 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4440 | 4431 | // :129:30: note: when computing vector element at index '0' |
| 4441 | 4432 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4442 | 4433 | // :129:30: note: when computing vector element at index '0' |
| 4443 | 4434 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4444 | // :129:30: note: when computing vector element at index '1' | |
| 4435 | // :129:30: note: when computing vector element at index '0' | |
| 4445 | 4436 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4446 | 4437 | // :129:30: note: when computing vector element at index '0' |
| 4447 | 4438 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4448 | 4439 | // :129:30: note: when computing vector element at index '0' |
| 4449 | 4440 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4441 | // :129:30: note: when computing vector element at index '0' | |
| 4450 | 4442 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4451 | 4443 | // :129:30: note: when computing vector element at index '0' |
| 4452 | 4444 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4453 | 4445 | // :129:30: note: when computing vector element at index '0' |
| 4454 | 4446 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4455 | // :129:30: note: when computing vector element at index '1' | |
| 4447 | // :129:30: note: when computing vector element at index '0' | |
| 4456 | 4448 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4457 | 4449 | // :129:30: note: when computing vector element at index '0' |
| 4458 | 4450 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4459 | 4451 | // :129:30: note: when computing vector element at index '0' |
| 4460 | 4452 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4453 | // :129:30: note: when computing vector element at index '0' | |
| 4461 | 4454 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4462 | 4455 | // :129:30: note: when computing vector element at index '0' |
| 4463 | 4456 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4464 | 4457 | // :129:30: note: when computing vector element at index '0' |
| 4465 | 4458 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4466 | // :129:30: note: when computing vector element at index '1' | |
| 4459 | // :129:30: note: when computing vector element at index '0' | |
| 4467 | 4460 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4468 | 4461 | // :129:30: note: when computing vector element at index '0' |
| 4469 | 4462 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4470 | 4463 | // :129:30: note: when computing vector element at index '0' |
| 4471 | 4464 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4465 | // :129:30: note: when computing vector element at index '0' | |
| 4472 | 4466 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4473 | 4467 | // :129:30: note: when computing vector element at index '0' |
| 4474 | 4468 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4475 | 4469 | // :129:30: note: when computing vector element at index '0' |
| 4476 | 4470 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4477 | // :129:30: note: when computing vector element at index '1' | |
| 4471 | // :129:30: note: when computing vector element at index '0' | |
| 4478 | 4472 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4479 | 4473 | // :129:30: note: when computing vector element at index '0' |
| 4480 | 4474 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4481 | 4475 | // :129:30: note: when computing vector element at index '0' |
| 4482 | 4476 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4477 | // :129:30: note: when computing vector element at index '0' | |
| 4483 | 4478 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4484 | 4479 | // :129:30: note: when computing vector element at index '0' |
| 4485 | 4480 | // :129:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4487,44 +4482,42 @@ const std = @import("std"); |
| 4487 | 4482 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4488 | 4483 | // :129:30: note: when computing vector element at index '1' |
| 4489 | 4484 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4490 | // :129:30: note: when computing vector element at index '0' | |
| 4485 | // :129:30: note: when computing vector element at index '1' | |
| 4491 | 4486 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4492 | // :129:30: note: when computing vector element at index '0' | |
| 4487 | // :129:30: note: when computing vector element at index '1' | |
| 4488 | // :129:30: error: use of undefined value here causes illegal behavior | |
| 4489 | // :129:30: note: when computing vector element at index '1' | |
| 4493 | 4490 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4491 | // :129:30: note: when computing vector element at index '1' | |
| 4494 | 4492 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4495 | // :129:30: note: when computing vector element at index '0' | |
| 4493 | // :129:30: note: when computing vector element at index '1' | |
| 4496 | 4494 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4497 | // :129:30: note: when computing vector element at index '0' | |
| 4495 | // :129:30: note: when computing vector element at index '1' | |
| 4498 | 4496 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4499 | 4497 | // :129:30: note: when computing vector element at index '1' |
| 4500 | 4498 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4501 | // :129:30: note: when computing vector element at index '0' | |
| 4499 | // :129:30: note: when computing vector element at index '1' | |
| 4502 | 4500 | // :129:30: error: use of undefined value here causes illegal behavior |
| 4503 | // :129:30: note: when computing vector element at index '0' | |
| 4501 | // :129:30: note: when computing vector element at index '1' | |
| 4502 | // :129:30: error: use of undefined value here causes illegal behavior | |
| 4503 | // :129:30: note: when computing vector element at index '1' | |
| 4504 | // :133:27: error: use of undefined value here causes illegal behavior | |
| 4504 | 4505 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4505 | 4506 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4506 | // :133:27: note: when computing vector element at index '0' | |
| 4507 | 4507 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4508 | // :133:27: note: when computing vector element at index '0' | |
| 4509 | 4508 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4510 | // :133:27: note: when computing vector element at index '0' | |
| 4511 | 4509 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4512 | // :133:27: note: when computing vector element at index '1' | |
| 4513 | 4510 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4514 | // :133:27: note: when computing vector element at index '0' | |
| 4515 | 4511 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4516 | // :133:27: note: when computing vector element at index '0' | |
| 4517 | 4512 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4518 | // :133:27: note: when computing vector element at index '0' | |
| 4519 | 4513 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4520 | 4514 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4521 | // :133:27: note: when computing vector element at index '0' | |
| 4522 | 4515 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4523 | 4516 | // :133:27: note: when computing vector element at index '0' |
| 4524 | 4517 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4525 | 4518 | // :133:27: note: when computing vector element at index '0' |
| 4526 | 4519 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4527 | // :133:27: note: when computing vector element at index '1' | |
| 4520 | // :133:27: note: when computing vector element at index '0' | |
| 4528 | 4521 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4529 | 4522 | // :133:27: note: when computing vector element at index '0' |
| 4530 | 4523 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4532,6 +4525,7 @@ const std = @import("std"); |
| 4532 | 4525 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4533 | 4526 | // :133:27: note: when computing vector element at index '0' |
| 4534 | 4527 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4528 | // :133:27: note: when computing vector element at index '0' | |
| 4535 | 4529 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4536 | 4530 | // :133:27: note: when computing vector element at index '0' |
| 4537 | 4531 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4539,7 +4533,7 @@ const std = @import("std"); |
| 4539 | 4533 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4540 | 4534 | // :133:27: note: when computing vector element at index '0' |
| 4541 | 4535 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4542 | // :133:27: note: when computing vector element at index '1' | |
| 4536 | // :133:27: note: when computing vector element at index '0' | |
| 4543 | 4537 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4544 | 4538 | // :133:27: note: when computing vector element at index '0' |
| 4545 | 4539 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4547,6 +4541,7 @@ const std = @import("std"); |
| 4547 | 4541 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4548 | 4542 | // :133:27: note: when computing vector element at index '0' |
| 4549 | 4543 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4544 | // :133:27: note: when computing vector element at index '0' | |
| 4550 | 4545 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4551 | 4546 | // :133:27: note: when computing vector element at index '0' |
| 4552 | 4547 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4554,7 +4549,7 @@ const std = @import("std"); |
| 4554 | 4549 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4555 | 4550 | // :133:27: note: when computing vector element at index '0' |
| 4556 | 4551 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4557 | // :133:27: note: when computing vector element at index '1' | |
| 4552 | // :133:27: note: when computing vector element at index '0' | |
| 4558 | 4553 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4559 | 4554 | // :133:27: note: when computing vector element at index '0' |
| 4560 | 4555 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4562,6 +4557,7 @@ const std = @import("std"); |
| 4562 | 4557 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4563 | 4558 | // :133:27: note: when computing vector element at index '0' |
| 4564 | 4559 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4560 | // :133:27: note: when computing vector element at index '0' | |
| 4565 | 4561 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4566 | 4562 | // :133:27: note: when computing vector element at index '0' |
| 4567 | 4563 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4569,7 +4565,7 @@ const std = @import("std"); |
| 4569 | 4565 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4570 | 4566 | // :133:27: note: when computing vector element at index '0' |
| 4571 | 4567 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4572 | // :133:27: note: when computing vector element at index '1' | |
| 4568 | // :133:27: note: when computing vector element at index '0' | |
| 4573 | 4569 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4574 | 4570 | // :133:27: note: when computing vector element at index '0' |
| 4575 | 4571 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4577,6 +4573,7 @@ const std = @import("std"); |
| 4577 | 4573 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4578 | 4574 | // :133:27: note: when computing vector element at index '0' |
| 4579 | 4575 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4576 | // :133:27: note: when computing vector element at index '0' | |
| 4580 | 4577 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4581 | 4578 | // :133:27: note: when computing vector element at index '0' |
| 4582 | 4579 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4584,7 +4581,7 @@ const std = @import("std"); |
| 4584 | 4581 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4585 | 4582 | // :133:27: note: when computing vector element at index '0' |
| 4586 | 4583 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4587 | // :133:27: note: when computing vector element at index '1' | |
| 4584 | // :133:27: note: when computing vector element at index '0' | |
| 4588 | 4585 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4589 | 4586 | // :133:27: note: when computing vector element at index '0' |
| 4590 | 4587 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4592,6 +4589,7 @@ const std = @import("std"); |
| 4592 | 4589 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4593 | 4590 | // :133:27: note: when computing vector element at index '0' |
| 4594 | 4591 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4592 | // :133:27: note: when computing vector element at index '0' | |
| 4595 | 4593 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4596 | 4594 | // :133:27: note: when computing vector element at index '0' |
| 4597 | 4595 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4599,7 +4597,7 @@ const std = @import("std"); |
| 4599 | 4597 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4600 | 4598 | // :133:27: note: when computing vector element at index '0' |
| 4601 | 4599 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4602 | // :133:27: note: when computing vector element at index '1' | |
| 4600 | // :133:27: note: when computing vector element at index '0' | |
| 4603 | 4601 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4604 | 4602 | // :133:27: note: when computing vector element at index '0' |
| 4605 | 4603 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4607,6 +4605,7 @@ const std = @import("std"); |
| 4607 | 4605 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4608 | 4606 | // :133:27: note: when computing vector element at index '0' |
| 4609 | 4607 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4608 | // :133:27: note: when computing vector element at index '0' | |
| 4610 | 4609 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4611 | 4610 | // :133:27: note: when computing vector element at index '0' |
| 4612 | 4611 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4614,7 +4613,7 @@ const std = @import("std"); |
| 4614 | 4613 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4615 | 4614 | // :133:27: note: when computing vector element at index '0' |
| 4616 | 4615 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4617 | // :133:27: note: when computing vector element at index '1' | |
| 4616 | // :133:27: note: when computing vector element at index '0' | |
| 4618 | 4617 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4619 | 4618 | // :133:27: note: when computing vector element at index '0' |
| 4620 | 4619 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4622,6 +4621,7 @@ const std = @import("std"); |
| 4622 | 4621 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4623 | 4622 | // :133:27: note: when computing vector element at index '0' |
| 4624 | 4623 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4624 | // :133:27: note: when computing vector element at index '0' | |
| 4625 | 4625 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4626 | 4626 | // :133:27: note: when computing vector element at index '0' |
| 4627 | 4627 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4629,7 +4629,7 @@ const std = @import("std"); |
| 4629 | 4629 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4630 | 4630 | // :133:27: note: when computing vector element at index '0' |
| 4631 | 4631 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4632 | // :133:27: note: when computing vector element at index '1' | |
| 4632 | // :133:27: note: when computing vector element at index '0' | |
| 4633 | 4633 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4634 | 4634 | // :133:27: note: when computing vector element at index '0' |
| 4635 | 4635 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4637,6 +4637,7 @@ const std = @import("std"); |
| 4637 | 4637 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4638 | 4638 | // :133:27: note: when computing vector element at index '0' |
| 4639 | 4639 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4640 | // :133:27: note: when computing vector element at index '0' | |
| 4640 | 4641 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4641 | 4642 | // :133:27: note: when computing vector element at index '0' |
| 4642 | 4643 | // :133:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4646,126 +4647,120 @@ const std = @import("std"); |
| 4646 | 4647 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4647 | 4648 | // :133:27: note: when computing vector element at index '1' |
| 4648 | 4649 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4649 | // :133:27: note: when computing vector element at index '0' | |
| 4650 | // :133:27: error: use of undefined value here causes illegal behavior | |
| 4651 | // :133:27: note: when computing vector element at index '0' | |
| 4650 | // :133:27: note: when computing vector element at index '1' | |
| 4652 | 4651 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4653 | // :133:27: note: when computing vector element at index '0' | |
| 4652 | // :133:27: note: when computing vector element at index '1' | |
| 4654 | 4653 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4654 | // :133:27: note: when computing vector element at index '1' | |
| 4655 | 4655 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4656 | // :133:27: note: when computing vector element at index '0' | |
| 4656 | // :133:27: note: when computing vector element at index '1' | |
| 4657 | 4657 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4658 | // :133:27: note: when computing vector element at index '0' | |
| 4658 | // :133:27: note: when computing vector element at index '1' | |
| 4659 | 4659 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4660 | // :133:27: note: when computing vector element at index '0' | |
| 4660 | // :133:27: note: when computing vector element at index '1' | |
| 4661 | 4661 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4662 | 4662 | // :133:27: note: when computing vector element at index '1' |
| 4663 | 4663 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4664 | // :133:27: note: when computing vector element at index '0' | |
| 4664 | // :133:27: note: when computing vector element at index '1' | |
| 4665 | 4665 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4666 | // :133:27: note: when computing vector element at index '0' | |
| 4666 | // :133:27: note: when computing vector element at index '1' | |
| 4667 | 4667 | // :133:27: error: use of undefined value here causes illegal behavior |
| 4668 | // :133:27: note: when computing vector element at index '0' | |
| 4668 | // :133:27: note: when computing vector element at index '1' | |
| 4669 | 4669 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4670 | 4670 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4671 | // :133:30: note: when computing vector element at index '0' | |
| 4672 | 4671 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4673 | // :133:30: note: when computing vector element at index '0' | |
| 4674 | 4672 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4675 | // :133:30: note: when computing vector element at index '1' | |
| 4676 | 4673 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4677 | // :133:30: note: when computing vector element at index '0' | |
| 4678 | 4674 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4679 | // :133:30: note: when computing vector element at index '0' | |
| 4680 | 4675 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4681 | 4676 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4682 | // :133:30: note: when computing vector element at index '0' | |
| 4683 | 4677 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4684 | // :133:30: note: when computing vector element at index '0' | |
| 4685 | 4678 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4686 | // :133:30: note: when computing vector element at index '1' | |
| 4687 | 4679 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4688 | // :133:30: note: when computing vector element at index '0' | |
| 4689 | 4680 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4690 | 4681 | // :133:30: note: when computing vector element at index '0' |
| 4691 | 4682 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4692 | // :133:30: error: use of undefined value here causes illegal behavior | |
| 4693 | 4683 | // :133:30: note: when computing vector element at index '0' |
| 4694 | 4684 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4695 | 4685 | // :133:30: note: when computing vector element at index '0' |
| 4696 | 4686 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4697 | // :133:30: note: when computing vector element at index '1' | |
| 4698 | // :133:30: error: use of undefined value here causes illegal behavior | |
| 4699 | 4687 | // :133:30: note: when computing vector element at index '0' |
| 4700 | 4688 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4701 | 4689 | // :133:30: note: when computing vector element at index '0' |
| 4702 | 4690 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4691 | // :133:30: note: when computing vector element at index '0' | |
| 4703 | 4692 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4704 | 4693 | // :133:30: note: when computing vector element at index '0' |
| 4705 | 4694 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4706 | 4695 | // :133:30: note: when computing vector element at index '0' |
| 4707 | 4696 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4708 | // :133:30: note: when computing vector element at index '1' | |
| 4697 | // :133:30: note: when computing vector element at index '0' | |
| 4709 | 4698 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4710 | 4699 | // :133:30: note: when computing vector element at index '0' |
| 4711 | 4700 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4712 | 4701 | // :133:30: note: when computing vector element at index '0' |
| 4713 | 4702 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4703 | // :133:30: note: when computing vector element at index '0' | |
| 4714 | 4704 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4715 | 4705 | // :133:30: note: when computing vector element at index '0' |
| 4716 | 4706 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4717 | 4707 | // :133:30: note: when computing vector element at index '0' |
| 4718 | 4708 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4719 | // :133:30: note: when computing vector element at index '1' | |
| 4709 | // :133:30: note: when computing vector element at index '0' | |
| 4720 | 4710 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4721 | 4711 | // :133:30: note: when computing vector element at index '0' |
| 4722 | 4712 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4723 | 4713 | // :133:30: note: when computing vector element at index '0' |
| 4724 | 4714 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4715 | // :133:30: note: when computing vector element at index '0' | |
| 4725 | 4716 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4726 | 4717 | // :133:30: note: when computing vector element at index '0' |
| 4727 | 4718 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4728 | 4719 | // :133:30: note: when computing vector element at index '0' |
| 4729 | 4720 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4730 | // :133:30: note: when computing vector element at index '1' | |
| 4721 | // :133:30: note: when computing vector element at index '0' | |
| 4731 | 4722 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4732 | 4723 | // :133:30: note: when computing vector element at index '0' |
| 4733 | 4724 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4734 | 4725 | // :133:30: note: when computing vector element at index '0' |
| 4735 | 4726 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4727 | // :133:30: note: when computing vector element at index '0' | |
| 4736 | 4728 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4737 | 4729 | // :133:30: note: when computing vector element at index '0' |
| 4738 | 4730 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4739 | 4731 | // :133:30: note: when computing vector element at index '0' |
| 4740 | 4732 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4741 | // :133:30: note: when computing vector element at index '1' | |
| 4733 | // :133:30: note: when computing vector element at index '0' | |
| 4742 | 4734 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4743 | 4735 | // :133:30: note: when computing vector element at index '0' |
| 4744 | 4736 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4745 | 4737 | // :133:30: note: when computing vector element at index '0' |
| 4746 | 4738 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4739 | // :133:30: note: when computing vector element at index '0' | |
| 4747 | 4740 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4748 | 4741 | // :133:30: note: when computing vector element at index '0' |
| 4749 | 4742 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4750 | 4743 | // :133:30: note: when computing vector element at index '0' |
| 4751 | 4744 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4752 | // :133:30: note: when computing vector element at index '1' | |
| 4745 | // :133:30: note: when computing vector element at index '0' | |
| 4753 | 4746 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4754 | 4747 | // :133:30: note: when computing vector element at index '0' |
| 4755 | 4748 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4756 | 4749 | // :133:30: note: when computing vector element at index '0' |
| 4757 | 4750 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4751 | // :133:30: note: when computing vector element at index '0' | |
| 4758 | 4752 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4759 | 4753 | // :133:30: note: when computing vector element at index '0' |
| 4760 | 4754 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4761 | 4755 | // :133:30: note: when computing vector element at index '0' |
| 4762 | 4756 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4763 | // :133:30: note: when computing vector element at index '1' | |
| 4757 | // :133:30: note: when computing vector element at index '0' | |
| 4764 | 4758 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4765 | 4759 | // :133:30: note: when computing vector element at index '0' |
| 4766 | 4760 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4767 | 4761 | // :133:30: note: when computing vector element at index '0' |
| 4768 | 4762 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4763 | // :133:30: note: when computing vector element at index '0' | |
| 4769 | 4764 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4770 | 4765 | // :133:30: note: when computing vector element at index '0' |
| 4771 | 4766 | // :133:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4773,44 +4768,42 @@ const std = @import("std"); |
| 4773 | 4768 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4774 | 4769 | // :133:30: note: when computing vector element at index '1' |
| 4775 | 4770 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4776 | // :133:30: note: when computing vector element at index '0' | |
| 4771 | // :133:30: note: when computing vector element at index '1' | |
| 4777 | 4772 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4778 | // :133:30: note: when computing vector element at index '0' | |
| 4773 | // :133:30: note: when computing vector element at index '1' | |
| 4779 | 4774 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4775 | // :133:30: note: when computing vector element at index '1' | |
| 4780 | 4776 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4781 | // :133:30: note: when computing vector element at index '0' | |
| 4777 | // :133:30: note: when computing vector element at index '1' | |
| 4782 | 4778 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4783 | // :133:30: note: when computing vector element at index '0' | |
| 4779 | // :133:30: note: when computing vector element at index '1' | |
| 4784 | 4780 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4785 | 4781 | // :133:30: note: when computing vector element at index '1' |
| 4786 | 4782 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4787 | // :133:30: note: when computing vector element at index '0' | |
| 4783 | // :133:30: note: when computing vector element at index '1' | |
| 4788 | 4784 | // :133:30: error: use of undefined value here causes illegal behavior |
| 4789 | // :133:30: note: when computing vector element at index '0' | |
| 4785 | // :133:30: note: when computing vector element at index '1' | |
| 4786 | // :133:30: error: use of undefined value here causes illegal behavior | |
| 4787 | // :133:30: note: when computing vector element at index '1' | |
| 4788 | // :133:30: error: use of undefined value here causes illegal behavior | |
| 4789 | // :133:30: note: when computing vector element at index '1' | |
| 4790 | // :137:17: error: use of undefined value here causes illegal behavior | |
| 4790 | 4791 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4791 | 4792 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4792 | // :137:17: note: when computing vector element at index '0' | |
| 4793 | 4793 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4794 | // :137:17: note: when computing vector element at index '0' | |
| 4795 | 4794 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4796 | // :137:17: note: when computing vector element at index '0' | |
| 4797 | 4795 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4798 | // :137:17: note: when computing vector element at index '1' | |
| 4799 | 4796 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4800 | // :137:17: note: when computing vector element at index '0' | |
| 4801 | 4797 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4802 | // :137:17: note: when computing vector element at index '0' | |
| 4803 | 4798 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4804 | // :137:17: note: when computing vector element at index '0' | |
| 4805 | 4799 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4806 | 4800 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4807 | // :137:17: note: when computing vector element at index '0' | |
| 4808 | 4801 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4809 | 4802 | // :137:17: note: when computing vector element at index '0' |
| 4810 | 4803 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4811 | 4804 | // :137:17: note: when computing vector element at index '0' |
| 4812 | 4805 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4813 | // :137:17: note: when computing vector element at index '1' | |
| 4806 | // :137:17: note: when computing vector element at index '0' | |
| 4814 | 4807 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4815 | 4808 | // :137:17: note: when computing vector element at index '0' |
| 4816 | 4809 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4818,6 +4811,7 @@ const std = @import("std"); |
| 4818 | 4811 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4819 | 4812 | // :137:17: note: when computing vector element at index '0' |
| 4820 | 4813 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4814 | // :137:17: note: when computing vector element at index '0' | |
| 4821 | 4815 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4822 | 4816 | // :137:17: note: when computing vector element at index '0' |
| 4823 | 4817 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4825,7 +4819,7 @@ const std = @import("std"); |
| 4825 | 4819 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4826 | 4820 | // :137:17: note: when computing vector element at index '0' |
| 4827 | 4821 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4828 | // :137:17: note: when computing vector element at index '1' | |
| 4822 | // :137:17: note: when computing vector element at index '0' | |
| 4829 | 4823 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4830 | 4824 | // :137:17: note: when computing vector element at index '0' |
| 4831 | 4825 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4833,6 +4827,7 @@ const std = @import("std"); |
| 4833 | 4827 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4834 | 4828 | // :137:17: note: when computing vector element at index '0' |
| 4835 | 4829 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4830 | // :137:17: note: when computing vector element at index '0' | |
| 4836 | 4831 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4837 | 4832 | // :137:17: note: when computing vector element at index '0' |
| 4838 | 4833 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4840,7 +4835,7 @@ const std = @import("std"); |
| 4840 | 4835 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4841 | 4836 | // :137:17: note: when computing vector element at index '0' |
| 4842 | 4837 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4843 | // :137:17: note: when computing vector element at index '1' | |
| 4838 | // :137:17: note: when computing vector element at index '0' | |
| 4844 | 4839 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4845 | 4840 | // :137:17: note: when computing vector element at index '0' |
| 4846 | 4841 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4848,6 +4843,7 @@ const std = @import("std"); |
| 4848 | 4843 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4849 | 4844 | // :137:17: note: when computing vector element at index '0' |
| 4850 | 4845 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4846 | // :137:17: note: when computing vector element at index '0' | |
| 4851 | 4847 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4852 | 4848 | // :137:17: note: when computing vector element at index '0' |
| 4853 | 4849 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4855,7 +4851,7 @@ const std = @import("std"); |
| 4855 | 4851 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4856 | 4852 | // :137:17: note: when computing vector element at index '0' |
| 4857 | 4853 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4858 | // :137:17: note: when computing vector element at index '1' | |
| 4854 | // :137:17: note: when computing vector element at index '0' | |
| 4859 | 4855 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4860 | 4856 | // :137:17: note: when computing vector element at index '0' |
| 4861 | 4857 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4863,6 +4859,7 @@ const std = @import("std"); |
| 4863 | 4859 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4864 | 4860 | // :137:17: note: when computing vector element at index '0' |
| 4865 | 4861 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4862 | // :137:17: note: when computing vector element at index '0' | |
| 4866 | 4863 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4867 | 4864 | // :137:17: note: when computing vector element at index '0' |
| 4868 | 4865 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4870,7 +4867,7 @@ const std = @import("std"); |
| 4870 | 4867 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4871 | 4868 | // :137:17: note: when computing vector element at index '0' |
| 4872 | 4869 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4873 | // :137:17: note: when computing vector element at index '1' | |
| 4870 | // :137:17: note: when computing vector element at index '0' | |
| 4874 | 4871 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4875 | 4872 | // :137:17: note: when computing vector element at index '0' |
| 4876 | 4873 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4878,6 +4875,7 @@ const std = @import("std"); |
| 4878 | 4875 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4879 | 4876 | // :137:17: note: when computing vector element at index '0' |
| 4880 | 4877 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4878 | // :137:17: note: when computing vector element at index '0' | |
| 4881 | 4879 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4882 | 4880 | // :137:17: note: when computing vector element at index '0' |
| 4883 | 4881 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4885,7 +4883,7 @@ const std = @import("std"); |
| 4885 | 4883 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4886 | 4884 | // :137:17: note: when computing vector element at index '0' |
| 4887 | 4885 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4888 | // :137:17: note: when computing vector element at index '1' | |
| 4886 | // :137:17: note: when computing vector element at index '0' | |
| 4889 | 4887 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4890 | 4888 | // :137:17: note: when computing vector element at index '0' |
| 4891 | 4889 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4893,6 +4891,7 @@ const std = @import("std"); |
| 4893 | 4891 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4894 | 4892 | // :137:17: note: when computing vector element at index '0' |
| 4895 | 4893 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4894 | // :137:17: note: when computing vector element at index '0' | |
| 4896 | 4895 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4897 | 4896 | // :137:17: note: when computing vector element at index '0' |
| 4898 | 4897 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4900,7 +4899,7 @@ const std = @import("std"); |
| 4900 | 4899 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4901 | 4900 | // :137:17: note: when computing vector element at index '0' |
| 4902 | 4901 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4903 | // :137:17: note: when computing vector element at index '1' | |
| 4902 | // :137:17: note: when computing vector element at index '0' | |
| 4904 | 4903 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4905 | 4904 | // :137:17: note: when computing vector element at index '0' |
| 4906 | 4905 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4908,6 +4907,7 @@ const std = @import("std"); |
| 4908 | 4907 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4909 | 4908 | // :137:17: note: when computing vector element at index '0' |
| 4910 | 4909 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4910 | // :137:17: note: when computing vector element at index '0' | |
| 4911 | 4911 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4912 | 4912 | // :137:17: note: when computing vector element at index '0' |
| 4913 | 4913 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4915,7 +4915,7 @@ const std = @import("std"); |
| 4915 | 4915 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4916 | 4916 | // :137:17: note: when computing vector element at index '0' |
| 4917 | 4917 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4918 | // :137:17: note: when computing vector element at index '1' | |
| 4918 | // :137:17: note: when computing vector element at index '0' | |
| 4919 | 4919 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4920 | 4920 | // :137:17: note: when computing vector element at index '0' |
| 4921 | 4921 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4923,6 +4923,7 @@ const std = @import("std"); |
| 4923 | 4923 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4924 | 4924 | // :137:17: note: when computing vector element at index '0' |
| 4925 | 4925 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4926 | // :137:17: note: when computing vector element at index '0' | |
| 4926 | 4927 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4927 | 4928 | // :137:17: note: when computing vector element at index '0' |
| 4928 | 4929 | // :137:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -4932,126 +4933,120 @@ const std = @import("std"); |
| 4932 | 4933 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4933 | 4934 | // :137:17: note: when computing vector element at index '1' |
| 4934 | 4935 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4935 | // :137:17: note: when computing vector element at index '0' | |
| 4936 | // :137:17: error: use of undefined value here causes illegal behavior | |
| 4937 | // :137:17: note: when computing vector element at index '0' | |
| 4936 | // :137:17: note: when computing vector element at index '1' | |
| 4938 | 4937 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4939 | // :137:17: note: when computing vector element at index '0' | |
| 4938 | // :137:17: note: when computing vector element at index '1' | |
| 4940 | 4939 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4940 | // :137:17: note: when computing vector element at index '1' | |
| 4941 | 4941 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4942 | // :137:17: note: when computing vector element at index '0' | |
| 4942 | // :137:17: note: when computing vector element at index '1' | |
| 4943 | 4943 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4944 | // :137:17: note: when computing vector element at index '0' | |
| 4944 | // :137:17: note: when computing vector element at index '1' | |
| 4945 | 4945 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4946 | // :137:17: note: when computing vector element at index '0' | |
| 4946 | // :137:17: note: when computing vector element at index '1' | |
| 4947 | 4947 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4948 | 4948 | // :137:17: note: when computing vector element at index '1' |
| 4949 | 4949 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4950 | // :137:17: note: when computing vector element at index '0' | |
| 4950 | // :137:17: note: when computing vector element at index '1' | |
| 4951 | 4951 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4952 | // :137:17: note: when computing vector element at index '0' | |
| 4952 | // :137:17: note: when computing vector element at index '1' | |
| 4953 | 4953 | // :137:17: error: use of undefined value here causes illegal behavior |
| 4954 | // :137:17: note: when computing vector element at index '0' | |
| 4954 | // :137:17: note: when computing vector element at index '1' | |
| 4955 | 4955 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4956 | 4956 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4957 | // :137:21: note: when computing vector element at index '0' | |
| 4958 | 4957 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4959 | // :137:21: note: when computing vector element at index '0' | |
| 4960 | 4958 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4961 | // :137:21: note: when computing vector element at index '1' | |
| 4962 | 4959 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4963 | // :137:21: note: when computing vector element at index '0' | |
| 4964 | 4960 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4965 | // :137:21: note: when computing vector element at index '0' | |
| 4966 | 4961 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4967 | 4962 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4968 | // :137:21: note: when computing vector element at index '0' | |
| 4969 | 4963 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4970 | // :137:21: note: when computing vector element at index '0' | |
| 4971 | 4964 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4972 | // :137:21: note: when computing vector element at index '1' | |
| 4973 | 4965 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4974 | // :137:21: note: when computing vector element at index '0' | |
| 4975 | 4966 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4976 | 4967 | // :137:21: note: when computing vector element at index '0' |
| 4977 | 4968 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4978 | // :137:21: error: use of undefined value here causes illegal behavior | |
| 4979 | 4969 | // :137:21: note: when computing vector element at index '0' |
| 4980 | 4970 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4981 | 4971 | // :137:21: note: when computing vector element at index '0' |
| 4982 | 4972 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4983 | // :137:21: note: when computing vector element at index '1' | |
| 4984 | // :137:21: error: use of undefined value here causes illegal behavior | |
| 4985 | 4973 | // :137:21: note: when computing vector element at index '0' |
| 4986 | 4974 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4987 | 4975 | // :137:21: note: when computing vector element at index '0' |
| 4988 | 4976 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4977 | // :137:21: note: when computing vector element at index '0' | |
| 4989 | 4978 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4990 | 4979 | // :137:21: note: when computing vector element at index '0' |
| 4991 | 4980 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4992 | 4981 | // :137:21: note: when computing vector element at index '0' |
| 4993 | 4982 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4994 | // :137:21: note: when computing vector element at index '1' | |
| 4983 | // :137:21: note: when computing vector element at index '0' | |
| 4995 | 4984 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4996 | 4985 | // :137:21: note: when computing vector element at index '0' |
| 4997 | 4986 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4998 | 4987 | // :137:21: note: when computing vector element at index '0' |
| 4999 | 4988 | // :137:21: error: use of undefined value here causes illegal behavior |
| 4989 | // :137:21: note: when computing vector element at index '0' | |
| 5000 | 4990 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5001 | 4991 | // :137:21: note: when computing vector element at index '0' |
| 5002 | 4992 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5003 | 4993 | // :137:21: note: when computing vector element at index '0' |
| 5004 | 4994 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5005 | // :137:21: note: when computing vector element at index '1' | |
| 4995 | // :137:21: note: when computing vector element at index '0' | |
| 5006 | 4996 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5007 | 4997 | // :137:21: note: when computing vector element at index '0' |
| 5008 | 4998 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5009 | 4999 | // :137:21: note: when computing vector element at index '0' |
| 5010 | 5000 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5001 | // :137:21: note: when computing vector element at index '0' | |
| 5011 | 5002 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5012 | 5003 | // :137:21: note: when computing vector element at index '0' |
| 5013 | 5004 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5014 | 5005 | // :137:21: note: when computing vector element at index '0' |
| 5015 | 5006 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5016 | // :137:21: note: when computing vector element at index '1' | |
| 5007 | // :137:21: note: when computing vector element at index '0' | |
| 5017 | 5008 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5018 | 5009 | // :137:21: note: when computing vector element at index '0' |
| 5019 | 5010 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5020 | 5011 | // :137:21: note: when computing vector element at index '0' |
| 5021 | 5012 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5013 | // :137:21: note: when computing vector element at index '0' | |
| 5022 | 5014 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5023 | 5015 | // :137:21: note: when computing vector element at index '0' |
| 5024 | 5016 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5025 | 5017 | // :137:21: note: when computing vector element at index '0' |
| 5026 | 5018 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5027 | // :137:21: note: when computing vector element at index '1' | |
| 5019 | // :137:21: note: when computing vector element at index '0' | |
| 5028 | 5020 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5029 | 5021 | // :137:21: note: when computing vector element at index '0' |
| 5030 | 5022 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5031 | 5023 | // :137:21: note: when computing vector element at index '0' |
| 5032 | 5024 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5025 | // :137:21: note: when computing vector element at index '0' | |
| 5033 | 5026 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5034 | 5027 | // :137:21: note: when computing vector element at index '0' |
| 5035 | 5028 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5036 | 5029 | // :137:21: note: when computing vector element at index '0' |
| 5037 | 5030 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5038 | // :137:21: note: when computing vector element at index '1' | |
| 5031 | // :137:21: note: when computing vector element at index '0' | |
| 5039 | 5032 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5040 | 5033 | // :137:21: note: when computing vector element at index '0' |
| 5041 | 5034 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5042 | 5035 | // :137:21: note: when computing vector element at index '0' |
| 5043 | 5036 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5037 | // :137:21: note: when computing vector element at index '0' | |
| 5044 | 5038 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5045 | 5039 | // :137:21: note: when computing vector element at index '0' |
| 5046 | 5040 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5047 | 5041 | // :137:21: note: when computing vector element at index '0' |
| 5048 | 5042 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5049 | // :137:21: note: when computing vector element at index '1' | |
| 5043 | // :137:21: note: when computing vector element at index '0' | |
| 5050 | 5044 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5051 | 5045 | // :137:21: note: when computing vector element at index '0' |
| 5052 | 5046 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5053 | 5047 | // :137:21: note: when computing vector element at index '0' |
| 5054 | 5048 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5049 | // :137:21: note: when computing vector element at index '0' | |
| 5055 | 5050 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5056 | 5051 | // :137:21: note: when computing vector element at index '0' |
| 5057 | 5052 | // :137:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5059,44 +5054,42 @@ const std = @import("std"); |
| 5059 | 5054 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5060 | 5055 | // :137:21: note: when computing vector element at index '1' |
| 5061 | 5056 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5062 | // :137:21: note: when computing vector element at index '0' | |
| 5057 | // :137:21: note: when computing vector element at index '1' | |
| 5063 | 5058 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5064 | // :137:21: note: when computing vector element at index '0' | |
| 5059 | // :137:21: note: when computing vector element at index '1' | |
| 5065 | 5060 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5061 | // :137:21: note: when computing vector element at index '1' | |
| 5066 | 5062 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5067 | // :137:21: note: when computing vector element at index '0' | |
| 5063 | // :137:21: note: when computing vector element at index '1' | |
| 5068 | 5064 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5069 | // :137:21: note: when computing vector element at index '0' | |
| 5065 | // :137:21: note: when computing vector element at index '1' | |
| 5070 | 5066 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5071 | 5067 | // :137:21: note: when computing vector element at index '1' |
| 5072 | 5068 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5073 | // :137:21: note: when computing vector element at index '0' | |
| 5069 | // :137:21: note: when computing vector element at index '1' | |
| 5074 | 5070 | // :137:21: error: use of undefined value here causes illegal behavior |
| 5075 | // :137:21: note: when computing vector element at index '0' | |
| 5071 | // :137:21: note: when computing vector element at index '1' | |
| 5072 | // :137:21: error: use of undefined value here causes illegal behavior | |
| 5073 | // :137:21: note: when computing vector element at index '1' | |
| 5074 | // :137:21: error: use of undefined value here causes illegal behavior | |
| 5075 | // :137:21: note: when computing vector element at index '1' | |
| 5076 | // :141:22: error: use of undefined value here causes illegal behavior | |
| 5076 | 5077 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5077 | 5078 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5078 | // :141:22: note: when computing vector element at index '0' | |
| 5079 | 5079 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5080 | // :141:22: note: when computing vector element at index '0' | |
| 5081 | 5080 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5082 | // :141:22: note: when computing vector element at index '0' | |
| 5083 | 5081 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5084 | // :141:22: note: when computing vector element at index '1' | |
| 5085 | 5082 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5086 | // :141:22: note: when computing vector element at index '0' | |
| 5087 | 5083 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5088 | // :141:22: note: when computing vector element at index '0' | |
| 5089 | 5084 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5090 | // :141:22: note: when computing vector element at index '0' | |
| 5091 | 5085 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5092 | 5086 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5093 | // :141:22: note: when computing vector element at index '0' | |
| 5094 | 5087 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5095 | 5088 | // :141:22: note: when computing vector element at index '0' |
| 5096 | 5089 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5097 | 5090 | // :141:22: note: when computing vector element at index '0' |
| 5098 | 5091 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5099 | // :141:22: note: when computing vector element at index '1' | |
| 5092 | // :141:22: note: when computing vector element at index '0' | |
| 5100 | 5093 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5101 | 5094 | // :141:22: note: when computing vector element at index '0' |
| 5102 | 5095 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5104,6 +5097,7 @@ const std = @import("std"); |
| 5104 | 5097 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5105 | 5098 | // :141:22: note: when computing vector element at index '0' |
| 5106 | 5099 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5100 | // :141:22: note: when computing vector element at index '0' | |
| 5107 | 5101 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5108 | 5102 | // :141:22: note: when computing vector element at index '0' |
| 5109 | 5103 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5111,7 +5105,7 @@ const std = @import("std"); |
| 5111 | 5105 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5112 | 5106 | // :141:22: note: when computing vector element at index '0' |
| 5113 | 5107 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5114 | // :141:22: note: when computing vector element at index '1' | |
| 5108 | // :141:22: note: when computing vector element at index '0' | |
| 5115 | 5109 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5116 | 5110 | // :141:22: note: when computing vector element at index '0' |
| 5117 | 5111 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5119,6 +5113,7 @@ const std = @import("std"); |
| 5119 | 5113 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5120 | 5114 | // :141:22: note: when computing vector element at index '0' |
| 5121 | 5115 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5116 | // :141:22: note: when computing vector element at index '0' | |
| 5122 | 5117 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5123 | 5118 | // :141:22: note: when computing vector element at index '0' |
| 5124 | 5119 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5126,7 +5121,7 @@ const std = @import("std"); |
| 5126 | 5121 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5127 | 5122 | // :141:22: note: when computing vector element at index '0' |
| 5128 | 5123 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5129 | // :141:22: note: when computing vector element at index '1' | |
| 5124 | // :141:22: note: when computing vector element at index '0' | |
| 5130 | 5125 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5131 | 5126 | // :141:22: note: when computing vector element at index '0' |
| 5132 | 5127 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5134,6 +5129,7 @@ const std = @import("std"); |
| 5134 | 5129 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5135 | 5130 | // :141:22: note: when computing vector element at index '0' |
| 5136 | 5131 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5132 | // :141:22: note: when computing vector element at index '0' | |
| 5137 | 5133 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5138 | 5134 | // :141:22: note: when computing vector element at index '0' |
| 5139 | 5135 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5141,7 +5137,7 @@ const std = @import("std"); |
| 5141 | 5137 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5142 | 5138 | // :141:22: note: when computing vector element at index '0' |
| 5143 | 5139 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5144 | // :141:22: note: when computing vector element at index '1' | |
| 5140 | // :141:22: note: when computing vector element at index '0' | |
| 5145 | 5141 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5146 | 5142 | // :141:22: note: when computing vector element at index '0' |
| 5147 | 5143 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5149,6 +5145,7 @@ const std = @import("std"); |
| 5149 | 5145 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5150 | 5146 | // :141:22: note: when computing vector element at index '0' |
| 5151 | 5147 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5148 | // :141:22: note: when computing vector element at index '0' | |
| 5152 | 5149 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5153 | 5150 | // :141:22: note: when computing vector element at index '0' |
| 5154 | 5151 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5156,7 +5153,7 @@ const std = @import("std"); |
| 5156 | 5153 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5157 | 5154 | // :141:22: note: when computing vector element at index '0' |
| 5158 | 5155 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5159 | // :141:22: note: when computing vector element at index '1' | |
| 5156 | // :141:22: note: when computing vector element at index '0' | |
| 5160 | 5157 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5161 | 5158 | // :141:22: note: when computing vector element at index '0' |
| 5162 | 5159 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5164,6 +5161,7 @@ const std = @import("std"); |
| 5164 | 5161 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5165 | 5162 | // :141:22: note: when computing vector element at index '0' |
| 5166 | 5163 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5164 | // :141:22: note: when computing vector element at index '0' | |
| 5167 | 5165 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5168 | 5166 | // :141:22: note: when computing vector element at index '0' |
| 5169 | 5167 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5171,7 +5169,7 @@ const std = @import("std"); |
| 5171 | 5169 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5172 | 5170 | // :141:22: note: when computing vector element at index '0' |
| 5173 | 5171 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5174 | // :141:22: note: when computing vector element at index '1' | |
| 5172 | // :141:22: note: when computing vector element at index '0' | |
| 5175 | 5173 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5176 | 5174 | // :141:22: note: when computing vector element at index '0' |
| 5177 | 5175 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5179,6 +5177,7 @@ const std = @import("std"); |
| 5179 | 5177 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5180 | 5178 | // :141:22: note: when computing vector element at index '0' |
| 5181 | 5179 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5180 | // :141:22: note: when computing vector element at index '0' | |
| 5182 | 5181 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5183 | 5182 | // :141:22: note: when computing vector element at index '0' |
| 5184 | 5183 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5186,7 +5185,7 @@ const std = @import("std"); |
| 5186 | 5185 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5187 | 5186 | // :141:22: note: when computing vector element at index '0' |
| 5188 | 5187 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5189 | // :141:22: note: when computing vector element at index '1' | |
| 5188 | // :141:22: note: when computing vector element at index '0' | |
| 5190 | 5189 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5191 | 5190 | // :141:22: note: when computing vector element at index '0' |
| 5192 | 5191 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5194,6 +5193,7 @@ const std = @import("std"); |
| 5194 | 5193 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5195 | 5194 | // :141:22: note: when computing vector element at index '0' |
| 5196 | 5195 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5196 | // :141:22: note: when computing vector element at index '0' | |
| 5197 | 5197 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5198 | 5198 | // :141:22: note: when computing vector element at index '0' |
| 5199 | 5199 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5201,7 +5201,7 @@ const std = @import("std"); |
| 5201 | 5201 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5202 | 5202 | // :141:22: note: when computing vector element at index '0' |
| 5203 | 5203 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5204 | // :141:22: note: when computing vector element at index '1' | |
| 5204 | // :141:22: note: when computing vector element at index '0' | |
| 5205 | 5205 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5206 | 5206 | // :141:22: note: when computing vector element at index '0' |
| 5207 | 5207 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5209,6 +5209,7 @@ const std = @import("std"); |
| 5209 | 5209 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5210 | 5210 | // :141:22: note: when computing vector element at index '0' |
| 5211 | 5211 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5212 | // :141:22: note: when computing vector element at index '0' | |
| 5212 | 5213 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5213 | 5214 | // :141:22: note: when computing vector element at index '0' |
| 5214 | 5215 | // :141:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5218,126 +5219,120 @@ const std = @import("std"); |
| 5218 | 5219 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5219 | 5220 | // :141:22: note: when computing vector element at index '1' |
| 5220 | 5221 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5221 | // :141:22: note: when computing vector element at index '0' | |
| 5222 | // :141:22: error: use of undefined value here causes illegal behavior | |
| 5223 | // :141:22: note: when computing vector element at index '0' | |
| 5222 | // :141:22: note: when computing vector element at index '1' | |
| 5224 | 5223 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5225 | // :141:22: note: when computing vector element at index '0' | |
| 5224 | // :141:22: note: when computing vector element at index '1' | |
| 5226 | 5225 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5226 | // :141:22: note: when computing vector element at index '1' | |
| 5227 | 5227 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5228 | // :141:22: note: when computing vector element at index '0' | |
| 5228 | // :141:22: note: when computing vector element at index '1' | |
| 5229 | 5229 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5230 | // :141:22: note: when computing vector element at index '0' | |
| 5230 | // :141:22: note: when computing vector element at index '1' | |
| 5231 | 5231 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5232 | // :141:22: note: when computing vector element at index '0' | |
| 5232 | // :141:22: note: when computing vector element at index '1' | |
| 5233 | 5233 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5234 | 5234 | // :141:22: note: when computing vector element at index '1' |
| 5235 | 5235 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5236 | // :141:22: note: when computing vector element at index '0' | |
| 5236 | // :141:22: note: when computing vector element at index '1' | |
| 5237 | 5237 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5238 | // :141:22: note: when computing vector element at index '0' | |
| 5238 | // :141:22: note: when computing vector element at index '1' | |
| 5239 | 5239 | // :141:22: error: use of undefined value here causes illegal behavior |
| 5240 | // :141:22: note: when computing vector element at index '0' | |
| 5240 | // :141:22: note: when computing vector element at index '1' | |
| 5241 | 5241 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5242 | 5242 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5243 | // :141:25: note: when computing vector element at index '0' | |
| 5244 | 5243 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5245 | // :141:25: note: when computing vector element at index '0' | |
| 5246 | 5244 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5247 | // :141:25: note: when computing vector element at index '1' | |
| 5248 | 5245 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5249 | // :141:25: note: when computing vector element at index '0' | |
| 5250 | 5246 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5251 | // :141:25: note: when computing vector element at index '0' | |
| 5252 | 5247 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5253 | 5248 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5254 | // :141:25: note: when computing vector element at index '0' | |
| 5255 | 5249 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5256 | // :141:25: note: when computing vector element at index '0' | |
| 5257 | 5250 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5258 | // :141:25: note: when computing vector element at index '1' | |
| 5259 | 5251 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5260 | // :141:25: note: when computing vector element at index '0' | |
| 5261 | 5252 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5262 | 5253 | // :141:25: note: when computing vector element at index '0' |
| 5263 | 5254 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5264 | // :141:25: error: use of undefined value here causes illegal behavior | |
| 5265 | 5255 | // :141:25: note: when computing vector element at index '0' |
| 5266 | 5256 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5267 | 5257 | // :141:25: note: when computing vector element at index '0' |
| 5268 | 5258 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5269 | // :141:25: note: when computing vector element at index '1' | |
| 5270 | // :141:25: error: use of undefined value here causes illegal behavior | |
| 5271 | 5259 | // :141:25: note: when computing vector element at index '0' |
| 5272 | 5260 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5273 | 5261 | // :141:25: note: when computing vector element at index '0' |
| 5274 | 5262 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5263 | // :141:25: note: when computing vector element at index '0' | |
| 5275 | 5264 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5276 | 5265 | // :141:25: note: when computing vector element at index '0' |
| 5277 | 5266 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5278 | 5267 | // :141:25: note: when computing vector element at index '0' |
| 5279 | 5268 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5280 | // :141:25: note: when computing vector element at index '1' | |
| 5269 | // :141:25: note: when computing vector element at index '0' | |
| 5281 | 5270 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5282 | 5271 | // :141:25: note: when computing vector element at index '0' |
| 5283 | 5272 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5284 | 5273 | // :141:25: note: when computing vector element at index '0' |
| 5285 | 5274 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5275 | // :141:25: note: when computing vector element at index '0' | |
| 5286 | 5276 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5287 | 5277 | // :141:25: note: when computing vector element at index '0' |
| 5288 | 5278 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5289 | 5279 | // :141:25: note: when computing vector element at index '0' |
| 5290 | 5280 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5291 | // :141:25: note: when computing vector element at index '1' | |
| 5281 | // :141:25: note: when computing vector element at index '0' | |
| 5292 | 5282 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5293 | 5283 | // :141:25: note: when computing vector element at index '0' |
| 5294 | 5284 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5295 | 5285 | // :141:25: note: when computing vector element at index '0' |
| 5296 | 5286 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5287 | // :141:25: note: when computing vector element at index '0' | |
| 5297 | 5288 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5298 | 5289 | // :141:25: note: when computing vector element at index '0' |
| 5299 | 5290 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5300 | 5291 | // :141:25: note: when computing vector element at index '0' |
| 5301 | 5292 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5302 | // :141:25: note: when computing vector element at index '1' | |
| 5293 | // :141:25: note: when computing vector element at index '0' | |
| 5303 | 5294 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5304 | 5295 | // :141:25: note: when computing vector element at index '0' |
| 5305 | 5296 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5306 | 5297 | // :141:25: note: when computing vector element at index '0' |
| 5307 | 5298 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5299 | // :141:25: note: when computing vector element at index '0' | |
| 5308 | 5300 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5309 | 5301 | // :141:25: note: when computing vector element at index '0' |
| 5310 | 5302 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5311 | 5303 | // :141:25: note: when computing vector element at index '0' |
| 5312 | 5304 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5313 | // :141:25: note: when computing vector element at index '1' | |
| 5305 | // :141:25: note: when computing vector element at index '0' | |
| 5314 | 5306 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5315 | 5307 | // :141:25: note: when computing vector element at index '0' |
| 5316 | 5308 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5317 | 5309 | // :141:25: note: when computing vector element at index '0' |
| 5318 | 5310 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5311 | // :141:25: note: when computing vector element at index '0' | |
| 5319 | 5312 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5320 | 5313 | // :141:25: note: when computing vector element at index '0' |
| 5321 | 5314 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5322 | 5315 | // :141:25: note: when computing vector element at index '0' |
| 5323 | 5316 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5324 | // :141:25: note: when computing vector element at index '1' | |
| 5317 | // :141:25: note: when computing vector element at index '0' | |
| 5325 | 5318 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5326 | 5319 | // :141:25: note: when computing vector element at index '0' |
| 5327 | 5320 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5328 | 5321 | // :141:25: note: when computing vector element at index '0' |
| 5329 | 5322 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5323 | // :141:25: note: when computing vector element at index '0' | |
| 5330 | 5324 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5331 | 5325 | // :141:25: note: when computing vector element at index '0' |
| 5332 | 5326 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5333 | 5327 | // :141:25: note: when computing vector element at index '0' |
| 5334 | 5328 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5335 | // :141:25: note: when computing vector element at index '1' | |
| 5329 | // :141:25: note: when computing vector element at index '0' | |
| 5336 | 5330 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5337 | 5331 | // :141:25: note: when computing vector element at index '0' |
| 5338 | 5332 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5339 | 5333 | // :141:25: note: when computing vector element at index '0' |
| 5340 | 5334 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5335 | // :141:25: note: when computing vector element at index '0' | |
| 5341 | 5336 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5342 | 5337 | // :141:25: note: when computing vector element at index '0' |
| 5343 | 5338 | // :141:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5345,44 +5340,42 @@ const std = @import("std"); |
| 5345 | 5340 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5346 | 5341 | // :141:25: note: when computing vector element at index '1' |
| 5347 | 5342 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5348 | // :141:25: note: when computing vector element at index '0' | |
| 5343 | // :141:25: note: when computing vector element at index '1' | |
| 5349 | 5344 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5350 | // :141:25: note: when computing vector element at index '0' | |
| 5345 | // :141:25: note: when computing vector element at index '1' | |
| 5351 | 5346 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5347 | // :141:25: note: when computing vector element at index '1' | |
| 5352 | 5348 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5353 | // :141:25: note: when computing vector element at index '0' | |
| 5349 | // :141:25: note: when computing vector element at index '1' | |
| 5354 | 5350 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5355 | // :141:25: note: when computing vector element at index '0' | |
| 5351 | // :141:25: note: when computing vector element at index '1' | |
| 5356 | 5352 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5357 | 5353 | // :141:25: note: when computing vector element at index '1' |
| 5358 | 5354 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5359 | // :141:25: note: when computing vector element at index '0' | |
| 5355 | // :141:25: note: when computing vector element at index '1' | |
| 5360 | 5356 | // :141:25: error: use of undefined value here causes illegal behavior |
| 5361 | // :141:25: note: when computing vector element at index '0' | |
| 5357 | // :141:25: note: when computing vector element at index '1' | |
| 5358 | // :141:25: error: use of undefined value here causes illegal behavior | |
| 5359 | // :141:25: note: when computing vector element at index '1' | |
| 5360 | // :141:25: error: use of undefined value here causes illegal behavior | |
| 5361 | // :141:25: note: when computing vector element at index '1' | |
| 5362 | // :145:22: error: use of undefined value here causes illegal behavior | |
| 5362 | 5363 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5363 | 5364 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5364 | // :145:22: note: when computing vector element at index '0' | |
| 5365 | 5365 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5366 | // :145:22: note: when computing vector element at index '0' | |
| 5367 | 5366 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5368 | // :145:22: note: when computing vector element at index '0' | |
| 5369 | 5367 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5370 | // :145:22: note: when computing vector element at index '1' | |
| 5371 | 5368 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5372 | // :145:22: note: when computing vector element at index '0' | |
| 5373 | 5369 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5374 | // :145:22: note: when computing vector element at index '0' | |
| 5375 | 5370 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5376 | // :145:22: note: when computing vector element at index '0' | |
| 5377 | 5371 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5378 | 5372 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5379 | // :145:22: note: when computing vector element at index '0' | |
| 5380 | 5373 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5381 | 5374 | // :145:22: note: when computing vector element at index '0' |
| 5382 | 5375 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5383 | 5376 | // :145:22: note: when computing vector element at index '0' |
| 5384 | 5377 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5385 | // :145:22: note: when computing vector element at index '1' | |
| 5378 | // :145:22: note: when computing vector element at index '0' | |
| 5386 | 5379 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5387 | 5380 | // :145:22: note: when computing vector element at index '0' |
| 5388 | 5381 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5390,6 +5383,7 @@ const std = @import("std"); |
| 5390 | 5383 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5391 | 5384 | // :145:22: note: when computing vector element at index '0' |
| 5392 | 5385 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5386 | // :145:22: note: when computing vector element at index '0' | |
| 5393 | 5387 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5394 | 5388 | // :145:22: note: when computing vector element at index '0' |
| 5395 | 5389 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5397,7 +5391,7 @@ const std = @import("std"); |
| 5397 | 5391 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5398 | 5392 | // :145:22: note: when computing vector element at index '0' |
| 5399 | 5393 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5400 | // :145:22: note: when computing vector element at index '1' | |
| 5394 | // :145:22: note: when computing vector element at index '0' | |
| 5401 | 5395 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5402 | 5396 | // :145:22: note: when computing vector element at index '0' |
| 5403 | 5397 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5405,6 +5399,7 @@ const std = @import("std"); |
| 5405 | 5399 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5406 | 5400 | // :145:22: note: when computing vector element at index '0' |
| 5407 | 5401 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5402 | // :145:22: note: when computing vector element at index '0' | |
| 5408 | 5403 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5409 | 5404 | // :145:22: note: when computing vector element at index '0' |
| 5410 | 5405 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5412,7 +5407,7 @@ const std = @import("std"); |
| 5412 | 5407 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5413 | 5408 | // :145:22: note: when computing vector element at index '0' |
| 5414 | 5409 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5415 | // :145:22: note: when computing vector element at index '1' | |
| 5410 | // :145:22: note: when computing vector element at index '0' | |
| 5416 | 5411 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5417 | 5412 | // :145:22: note: when computing vector element at index '0' |
| 5418 | 5413 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5420,6 +5415,7 @@ const std = @import("std"); |
| 5420 | 5415 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5421 | 5416 | // :145:22: note: when computing vector element at index '0' |
| 5422 | 5417 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5418 | // :145:22: note: when computing vector element at index '0' | |
| 5423 | 5419 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5424 | 5420 | // :145:22: note: when computing vector element at index '0' |
| 5425 | 5421 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5427,7 +5423,7 @@ const std = @import("std"); |
| 5427 | 5423 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5428 | 5424 | // :145:22: note: when computing vector element at index '0' |
| 5429 | 5425 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5430 | // :145:22: note: when computing vector element at index '1' | |
| 5426 | // :145:22: note: when computing vector element at index '0' | |
| 5431 | 5427 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5432 | 5428 | // :145:22: note: when computing vector element at index '0' |
| 5433 | 5429 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5435,6 +5431,7 @@ const std = @import("std"); |
| 5435 | 5431 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5436 | 5432 | // :145:22: note: when computing vector element at index '0' |
| 5437 | 5433 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5434 | // :145:22: note: when computing vector element at index '0' | |
| 5438 | 5435 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5439 | 5436 | // :145:22: note: when computing vector element at index '0' |
| 5440 | 5437 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5442,7 +5439,7 @@ const std = @import("std"); |
| 5442 | 5439 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5443 | 5440 | // :145:22: note: when computing vector element at index '0' |
| 5444 | 5441 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5445 | // :145:22: note: when computing vector element at index '1' | |
| 5442 | // :145:22: note: when computing vector element at index '0' | |
| 5446 | 5443 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5447 | 5444 | // :145:22: note: when computing vector element at index '0' |
| 5448 | 5445 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5450,6 +5447,7 @@ const std = @import("std"); |
| 5450 | 5447 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5451 | 5448 | // :145:22: note: when computing vector element at index '0' |
| 5452 | 5449 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5450 | // :145:22: note: when computing vector element at index '0' | |
| 5453 | 5451 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5454 | 5452 | // :145:22: note: when computing vector element at index '0' |
| 5455 | 5453 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5457,7 +5455,7 @@ const std = @import("std"); |
| 5457 | 5455 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5458 | 5456 | // :145:22: note: when computing vector element at index '0' |
| 5459 | 5457 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5460 | // :145:22: note: when computing vector element at index '1' | |
| 5458 | // :145:22: note: when computing vector element at index '0' | |
| 5461 | 5459 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5462 | 5460 | // :145:22: note: when computing vector element at index '0' |
| 5463 | 5461 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5465,6 +5463,7 @@ const std = @import("std"); |
| 5465 | 5463 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5466 | 5464 | // :145:22: note: when computing vector element at index '0' |
| 5467 | 5465 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5466 | // :145:22: note: when computing vector element at index '0' | |
| 5468 | 5467 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5469 | 5468 | // :145:22: note: when computing vector element at index '0' |
| 5470 | 5469 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5472,7 +5471,7 @@ const std = @import("std"); |
| 5472 | 5471 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5473 | 5472 | // :145:22: note: when computing vector element at index '0' |
| 5474 | 5473 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5475 | // :145:22: note: when computing vector element at index '1' | |
| 5474 | // :145:22: note: when computing vector element at index '0' | |
| 5476 | 5475 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5477 | 5476 | // :145:22: note: when computing vector element at index '0' |
| 5478 | 5477 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5480,6 +5479,7 @@ const std = @import("std"); |
| 5480 | 5479 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5481 | 5480 | // :145:22: note: when computing vector element at index '0' |
| 5482 | 5481 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5482 | // :145:22: note: when computing vector element at index '0' | |
| 5483 | 5483 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5484 | 5484 | // :145:22: note: when computing vector element at index '0' |
| 5485 | 5485 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5487,7 +5487,7 @@ const std = @import("std"); |
| 5487 | 5487 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5488 | 5488 | // :145:22: note: when computing vector element at index '0' |
| 5489 | 5489 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5490 | // :145:22: note: when computing vector element at index '1' | |
| 5490 | // :145:22: note: when computing vector element at index '0' | |
| 5491 | 5491 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5492 | 5492 | // :145:22: note: when computing vector element at index '0' |
| 5493 | 5493 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5495,6 +5495,7 @@ const std = @import("std"); |
| 5495 | 5495 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5496 | 5496 | // :145:22: note: when computing vector element at index '0' |
| 5497 | 5497 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5498 | // :145:22: note: when computing vector element at index '0' | |
| 5498 | 5499 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5499 | 5500 | // :145:22: note: when computing vector element at index '0' |
| 5500 | 5501 | // :145:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5504,126 +5505,120 @@ const std = @import("std"); |
| 5504 | 5505 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5505 | 5506 | // :145:22: note: when computing vector element at index '1' |
| 5506 | 5507 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5507 | // :145:22: note: when computing vector element at index '0' | |
| 5508 | // :145:22: error: use of undefined value here causes illegal behavior | |
| 5509 | // :145:22: note: when computing vector element at index '0' | |
| 5508 | // :145:22: note: when computing vector element at index '1' | |
| 5510 | 5509 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5511 | // :145:22: note: when computing vector element at index '0' | |
| 5510 | // :145:22: note: when computing vector element at index '1' | |
| 5512 | 5511 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5512 | // :145:22: note: when computing vector element at index '1' | |
| 5513 | 5513 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5514 | // :145:22: note: when computing vector element at index '0' | |
| 5514 | // :145:22: note: when computing vector element at index '1' | |
| 5515 | 5515 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5516 | // :145:22: note: when computing vector element at index '0' | |
| 5516 | // :145:22: note: when computing vector element at index '1' | |
| 5517 | 5517 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5518 | // :145:22: note: when computing vector element at index '0' | |
| 5518 | // :145:22: note: when computing vector element at index '1' | |
| 5519 | 5519 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5520 | 5520 | // :145:22: note: when computing vector element at index '1' |
| 5521 | 5521 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5522 | // :145:22: note: when computing vector element at index '0' | |
| 5522 | // :145:22: note: when computing vector element at index '1' | |
| 5523 | 5523 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5524 | // :145:22: note: when computing vector element at index '0' | |
| 5524 | // :145:22: note: when computing vector element at index '1' | |
| 5525 | 5525 | // :145:22: error: use of undefined value here causes illegal behavior |
| 5526 | // :145:22: note: when computing vector element at index '0' | |
| 5526 | // :145:22: note: when computing vector element at index '1' | |
| 5527 | 5527 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5528 | 5528 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5529 | // :145:25: note: when computing vector element at index '0' | |
| 5530 | 5529 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5531 | // :145:25: note: when computing vector element at index '0' | |
| 5532 | 5530 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5533 | // :145:25: note: when computing vector element at index '1' | |
| 5534 | 5531 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5535 | // :145:25: note: when computing vector element at index '0' | |
| 5536 | 5532 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5537 | // :145:25: note: when computing vector element at index '0' | |
| 5538 | 5533 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5539 | 5534 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5540 | // :145:25: note: when computing vector element at index '0' | |
| 5541 | 5535 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5542 | // :145:25: note: when computing vector element at index '0' | |
| 5543 | 5536 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5544 | // :145:25: note: when computing vector element at index '1' | |
| 5545 | 5537 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5546 | // :145:25: note: when computing vector element at index '0' | |
| 5547 | 5538 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5548 | 5539 | // :145:25: note: when computing vector element at index '0' |
| 5549 | 5540 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5550 | // :145:25: error: use of undefined value here causes illegal behavior | |
| 5551 | 5541 | // :145:25: note: when computing vector element at index '0' |
| 5552 | 5542 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5553 | 5543 | // :145:25: note: when computing vector element at index '0' |
| 5554 | 5544 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5555 | // :145:25: note: when computing vector element at index '1' | |
| 5556 | // :145:25: error: use of undefined value here causes illegal behavior | |
| 5557 | 5545 | // :145:25: note: when computing vector element at index '0' |
| 5558 | 5546 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5559 | 5547 | // :145:25: note: when computing vector element at index '0' |
| 5560 | 5548 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5549 | // :145:25: note: when computing vector element at index '0' | |
| 5561 | 5550 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5562 | 5551 | // :145:25: note: when computing vector element at index '0' |
| 5563 | 5552 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5564 | 5553 | // :145:25: note: when computing vector element at index '0' |
| 5565 | 5554 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5566 | // :145:25: note: when computing vector element at index '1' | |
| 5555 | // :145:25: note: when computing vector element at index '0' | |
| 5567 | 5556 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5568 | 5557 | // :145:25: note: when computing vector element at index '0' |
| 5569 | 5558 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5570 | 5559 | // :145:25: note: when computing vector element at index '0' |
| 5571 | 5560 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5561 | // :145:25: note: when computing vector element at index '0' | |
| 5572 | 5562 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5573 | 5563 | // :145:25: note: when computing vector element at index '0' |
| 5574 | 5564 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5575 | 5565 | // :145:25: note: when computing vector element at index '0' |
| 5576 | 5566 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5577 | // :145:25: note: when computing vector element at index '1' | |
| 5567 | // :145:25: note: when computing vector element at index '0' | |
| 5578 | 5568 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5579 | 5569 | // :145:25: note: when computing vector element at index '0' |
| 5580 | 5570 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5581 | 5571 | // :145:25: note: when computing vector element at index '0' |
| 5582 | 5572 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5573 | // :145:25: note: when computing vector element at index '0' | |
| 5583 | 5574 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5584 | 5575 | // :145:25: note: when computing vector element at index '0' |
| 5585 | 5576 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5586 | 5577 | // :145:25: note: when computing vector element at index '0' |
| 5587 | 5578 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5588 | // :145:25: note: when computing vector element at index '1' | |
| 5579 | // :145:25: note: when computing vector element at index '0' | |
| 5589 | 5580 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5590 | 5581 | // :145:25: note: when computing vector element at index '0' |
| 5591 | 5582 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5592 | 5583 | // :145:25: note: when computing vector element at index '0' |
| 5593 | 5584 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5585 | // :145:25: note: when computing vector element at index '0' | |
| 5594 | 5586 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5595 | 5587 | // :145:25: note: when computing vector element at index '0' |
| 5596 | 5588 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5597 | 5589 | // :145:25: note: when computing vector element at index '0' |
| 5598 | 5590 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5599 | // :145:25: note: when computing vector element at index '1' | |
| 5591 | // :145:25: note: when computing vector element at index '0' | |
| 5600 | 5592 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5601 | 5593 | // :145:25: note: when computing vector element at index '0' |
| 5602 | 5594 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5603 | 5595 | // :145:25: note: when computing vector element at index '0' |
| 5604 | 5596 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5597 | // :145:25: note: when computing vector element at index '0' | |
| 5605 | 5598 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5606 | 5599 | // :145:25: note: when computing vector element at index '0' |
| 5607 | 5600 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5608 | 5601 | // :145:25: note: when computing vector element at index '0' |
| 5609 | 5602 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5610 | // :145:25: note: when computing vector element at index '1' | |
| 5603 | // :145:25: note: when computing vector element at index '0' | |
| 5611 | 5604 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5612 | 5605 | // :145:25: note: when computing vector element at index '0' |
| 5613 | 5606 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5614 | 5607 | // :145:25: note: when computing vector element at index '0' |
| 5615 | 5608 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5609 | // :145:25: note: when computing vector element at index '0' | |
| 5616 | 5610 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5617 | 5611 | // :145:25: note: when computing vector element at index '0' |
| 5618 | 5612 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5619 | 5613 | // :145:25: note: when computing vector element at index '0' |
| 5620 | 5614 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5621 | // :145:25: note: when computing vector element at index '1' | |
| 5615 | // :145:25: note: when computing vector element at index '0' | |
| 5622 | 5616 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5623 | 5617 | // :145:25: note: when computing vector element at index '0' |
| 5624 | 5618 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5625 | 5619 | // :145:25: note: when computing vector element at index '0' |
| 5626 | 5620 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5621 | // :145:25: note: when computing vector element at index '0' | |
| 5627 | 5622 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5628 | 5623 | // :145:25: note: when computing vector element at index '0' |
| 5629 | 5624 | // :145:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5631,20 +5626,25 @@ const std = @import("std"); |
| 5631 | 5626 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5632 | 5627 | // :145:25: note: when computing vector element at index '1' |
| 5633 | 5628 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5634 | // :145:25: note: when computing vector element at index '0' | |
| 5629 | // :145:25: note: when computing vector element at index '1' | |
| 5635 | 5630 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5636 | // :145:25: note: when computing vector element at index '0' | |
| 5631 | // :145:25: note: when computing vector element at index '1' | |
| 5632 | // :145:25: error: use of undefined value here causes illegal behavior | |
| 5633 | // :145:25: note: when computing vector element at index '1' | |
| 5637 | 5634 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5635 | // :145:25: note: when computing vector element at index '1' | |
| 5638 | 5636 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5639 | // :145:25: note: when computing vector element at index '0' | |
| 5637 | // :145:25: note: when computing vector element at index '1' | |
| 5640 | 5638 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5641 | // :145:25: note: when computing vector element at index '0' | |
| 5639 | // :145:25: note: when computing vector element at index '1' | |
| 5642 | 5640 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5643 | 5641 | // :145:25: note: when computing vector element at index '1' |
| 5644 | 5642 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5645 | // :145:25: note: when computing vector element at index '0' | |
| 5643 | // :145:25: note: when computing vector element at index '1' | |
| 5646 | 5644 | // :145:25: error: use of undefined value here causes illegal behavior |
| 5647 | // :145:25: note: when computing vector element at index '0' | |
| 5645 | // :145:25: note: when computing vector element at index '1' | |
| 5646 | // :145:25: error: use of undefined value here causes illegal behavior | |
| 5647 | // :145:25: note: when computing vector element at index '1' | |
| 5648 | 5648 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5649 | 5649 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5650 | 5650 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5652,21 +5652,13 @@ const std = @import("std"); |
| 5652 | 5652 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5653 | 5653 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5654 | 5654 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5655 | // :151:21: note: when computing vector element at index '1' | |
| 5656 | 5655 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5657 | // :151:21: note: when computing vector element at index '1' | |
| 5658 | 5656 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5659 | // :151:21: note: when computing vector element at index '1' | |
| 5660 | 5657 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5661 | // :151:21: note: when computing vector element at index '1' | |
| 5662 | 5658 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5663 | // :151:21: note: when computing vector element at index '0' | |
| 5664 | 5659 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5665 | // :151:21: note: when computing vector element at index '0' | |
| 5666 | 5660 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5667 | // :151:21: note: when computing vector element at index '0' | |
| 5668 | 5661 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5669 | // :151:21: note: when computing vector element at index '0' | |
| 5670 | 5662 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5671 | 5663 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5672 | 5664 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5674,21 +5666,13 @@ const std = @import("std"); |
| 5674 | 5666 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5675 | 5667 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5676 | 5668 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5677 | // :151:21: note: when computing vector element at index '1' | |
| 5678 | 5669 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5679 | // :151:21: note: when computing vector element at index '1' | |
| 5680 | 5670 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5681 | // :151:21: note: when computing vector element at index '1' | |
| 5682 | 5671 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5683 | // :151:21: note: when computing vector element at index '1' | |
| 5684 | 5672 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5685 | // :151:21: note: when computing vector element at index '0' | |
| 5686 | 5673 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5687 | // :151:21: note: when computing vector element at index '0' | |
| 5688 | 5674 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5689 | // :151:21: note: when computing vector element at index '0' | |
| 5690 | 5675 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5691 | // :151:21: note: when computing vector element at index '0' | |
| 5692 | 5676 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5693 | 5677 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5694 | 5678 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5696,21 +5680,13 @@ const std = @import("std"); |
| 5696 | 5680 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5697 | 5681 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5698 | 5682 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5699 | // :151:21: note: when computing vector element at index '1' | |
| 5700 | 5683 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5701 | // :151:21: note: when computing vector element at index '1' | |
| 5702 | 5684 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5703 | // :151:21: note: when computing vector element at index '1' | |
| 5704 | 5685 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5705 | // :151:21: note: when computing vector element at index '1' | |
| 5706 | 5686 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5707 | // :151:21: note: when computing vector element at index '0' | |
| 5708 | 5687 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5709 | // :151:21: note: when computing vector element at index '0' | |
| 5710 | 5688 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5711 | // :151:21: note: when computing vector element at index '0' | |
| 5712 | 5689 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5713 | // :151:21: note: when computing vector element at index '0' | |
| 5714 | 5690 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5715 | 5691 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5716 | 5692 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5718,21 +5694,13 @@ const std = @import("std"); |
| 5718 | 5694 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5719 | 5695 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5720 | 5696 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5721 | // :151:21: note: when computing vector element at index '1' | |
| 5722 | 5697 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5723 | // :151:21: note: when computing vector element at index '1' | |
| 5724 | 5698 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5725 | // :151:21: note: when computing vector element at index '1' | |
| 5726 | 5699 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5727 | // :151:21: note: when computing vector element at index '1' | |
| 5728 | 5700 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5729 | // :151:21: note: when computing vector element at index '0' | |
| 5730 | 5701 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5731 | // :151:21: note: when computing vector element at index '0' | |
| 5732 | 5702 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5733 | // :151:21: note: when computing vector element at index '0' | |
| 5734 | 5703 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5735 | // :151:21: note: when computing vector element at index '0' | |
| 5736 | 5704 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5737 | 5705 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5738 | 5706 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5740,13 +5708,9 @@ const std = @import("std"); |
| 5740 | 5708 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5741 | 5709 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5742 | 5710 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5743 | // :151:21: note: when computing vector element at index '1' | |
| 5744 | 5711 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5745 | // :151:21: note: when computing vector element at index '1' | |
| 5746 | 5712 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5747 | // :151:21: note: when computing vector element at index '1' | |
| 5748 | 5713 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5749 | // :151:21: note: when computing vector element at index '1' | |
| 5750 | 5714 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5751 | 5715 | // :151:21: note: when computing vector element at index '0' |
| 5752 | 5716 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5756,19 +5720,21 @@ const std = @import("std"); |
| 5756 | 5720 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5757 | 5721 | // :151:21: note: when computing vector element at index '0' |
| 5758 | 5722 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5723 | // :151:21: note: when computing vector element at index '0' | |
| 5759 | 5724 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5725 | // :151:21: note: when computing vector element at index '0' | |
| 5760 | 5726 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5727 | // :151:21: note: when computing vector element at index '0' | |
| 5761 | 5728 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5729 | // :151:21: note: when computing vector element at index '0' | |
| 5762 | 5730 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5731 | // :151:21: note: when computing vector element at index '0' | |
| 5763 | 5732 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5733 | // :151:21: note: when computing vector element at index '0' | |
| 5764 | 5734 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5765 | // :151:21: note: when computing vector element at index '1' | |
| 5766 | // :151:21: error: use of undefined value here causes illegal behavior | |
| 5767 | // :151:21: note: when computing vector element at index '1' | |
| 5768 | // :151:21: error: use of undefined value here causes illegal behavior | |
| 5769 | // :151:21: note: when computing vector element at index '1' | |
| 5735 | // :151:21: note: when computing vector element at index '0' | |
| 5770 | 5736 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5771 | // :151:21: note: when computing vector element at index '1' | |
| 5737 | // :151:21: note: when computing vector element at index '0' | |
| 5772 | 5738 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5773 | 5739 | // :151:21: note: when computing vector element at index '0' |
| 5774 | 5740 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5778,19 +5744,25 @@ const std = @import("std"); |
| 5778 | 5744 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5779 | 5745 | // :151:21: note: when computing vector element at index '0' |
| 5780 | 5746 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5747 | // :151:21: note: when computing vector element at index '0' | |
| 5781 | 5748 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5749 | // :151:21: note: when computing vector element at index '0' | |
| 5782 | 5750 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5751 | // :151:21: note: when computing vector element at index '0' | |
| 5783 | 5752 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5753 | // :151:21: note: when computing vector element at index '0' | |
| 5784 | 5754 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5755 | // :151:21: note: when computing vector element at index '0' | |
| 5785 | 5756 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5757 | // :151:21: note: when computing vector element at index '0' | |
| 5786 | 5758 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5787 | // :151:21: note: when computing vector element at index '1' | |
| 5759 | // :151:21: note: when computing vector element at index '0' | |
| 5788 | 5760 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5789 | // :151:21: note: when computing vector element at index '1' | |
| 5761 | // :151:21: note: when computing vector element at index '0' | |
| 5790 | 5762 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5791 | // :151:21: note: when computing vector element at index '1' | |
| 5763 | // :151:21: note: when computing vector element at index '0' | |
| 5792 | 5764 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5793 | // :151:21: note: when computing vector element at index '1' | |
| 5765 | // :151:21: note: when computing vector element at index '0' | |
| 5794 | 5766 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5795 | 5767 | // :151:21: note: when computing vector element at index '0' |
| 5796 | 5768 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5800,19 +5772,25 @@ const std = @import("std"); |
| 5800 | 5772 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5801 | 5773 | // :151:21: note: when computing vector element at index '0' |
| 5802 | 5774 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5775 | // :151:21: note: when computing vector element at index '0' | |
| 5803 | 5776 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5777 | // :151:21: note: when computing vector element at index '0' | |
| 5804 | 5778 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5779 | // :151:21: note: when computing vector element at index '0' | |
| 5805 | 5780 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5781 | // :151:21: note: when computing vector element at index '0' | |
| 5806 | 5782 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5783 | // :151:21: note: when computing vector element at index '0' | |
| 5807 | 5784 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5785 | // :151:21: note: when computing vector element at index '0' | |
| 5808 | 5786 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5809 | // :151:21: note: when computing vector element at index '1' | |
| 5787 | // :151:21: note: when computing vector element at index '0' | |
| 5810 | 5788 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5811 | // :151:21: note: when computing vector element at index '1' | |
| 5789 | // :151:21: note: when computing vector element at index '0' | |
| 5812 | 5790 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5813 | // :151:21: note: when computing vector element at index '1' | |
| 5791 | // :151:21: note: when computing vector element at index '0' | |
| 5814 | 5792 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5815 | // :151:21: note: when computing vector element at index '1' | |
| 5793 | // :151:21: note: when computing vector element at index '0' | |
| 5816 | 5794 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5817 | 5795 | // :151:21: note: when computing vector element at index '0' |
| 5818 | 5796 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5822,11 +5800,17 @@ const std = @import("std"); |
| 5822 | 5800 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5823 | 5801 | // :151:21: note: when computing vector element at index '0' |
| 5824 | 5802 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5803 | // :151:21: note: when computing vector element at index '1' | |
| 5825 | 5804 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5805 | // :151:21: note: when computing vector element at index '1' | |
| 5826 | 5806 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5807 | // :151:21: note: when computing vector element at index '1' | |
| 5827 | 5808 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5809 | // :151:21: note: when computing vector element at index '1' | |
| 5828 | 5810 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5811 | // :151:21: note: when computing vector element at index '1' | |
| 5829 | 5812 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5813 | // :151:21: note: when computing vector element at index '1' | |
| 5830 | 5814 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5831 | 5815 | // :151:21: note: when computing vector element at index '1' |
| 5832 | 5816 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5836,19 +5820,25 @@ const std = @import("std"); |
| 5836 | 5820 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5837 | 5821 | // :151:21: note: when computing vector element at index '1' |
| 5838 | 5822 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5839 | // :151:21: note: when computing vector element at index '0' | |
| 5823 | // :151:21: note: when computing vector element at index '1' | |
| 5840 | 5824 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5841 | // :151:21: note: when computing vector element at index '0' | |
| 5825 | // :151:21: note: when computing vector element at index '1' | |
| 5842 | 5826 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5843 | // :151:21: note: when computing vector element at index '0' | |
| 5827 | // :151:21: note: when computing vector element at index '1' | |
| 5844 | 5828 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5845 | // :151:21: note: when computing vector element at index '0' | |
| 5829 | // :151:21: note: when computing vector element at index '1' | |
| 5846 | 5830 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5831 | // :151:21: note: when computing vector element at index '1' | |
| 5847 | 5832 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5833 | // :151:21: note: when computing vector element at index '1' | |
| 5848 | 5834 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5835 | // :151:21: note: when computing vector element at index '1' | |
| 5849 | 5836 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5837 | // :151:21: note: when computing vector element at index '1' | |
| 5850 | 5838 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5839 | // :151:21: note: when computing vector element at index '1' | |
| 5851 | 5840 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5841 | // :151:21: note: when computing vector element at index '1' | |
| 5852 | 5842 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5853 | 5843 | // :151:21: note: when computing vector element at index '1' |
| 5854 | 5844 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5858,19 +5848,25 @@ const std = @import("std"); |
| 5858 | 5848 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5859 | 5849 | // :151:21: note: when computing vector element at index '1' |
| 5860 | 5850 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5861 | // :151:21: note: when computing vector element at index '0' | |
| 5851 | // :151:21: note: when computing vector element at index '1' | |
| 5862 | 5852 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5863 | // :151:21: note: when computing vector element at index '0' | |
| 5853 | // :151:21: note: when computing vector element at index '1' | |
| 5864 | 5854 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5865 | // :151:21: note: when computing vector element at index '0' | |
| 5855 | // :151:21: note: when computing vector element at index '1' | |
| 5866 | 5856 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5867 | // :151:21: note: when computing vector element at index '0' | |
| 5857 | // :151:21: note: when computing vector element at index '1' | |
| 5868 | 5858 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5859 | // :151:21: note: when computing vector element at index '1' | |
| 5869 | 5860 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5861 | // :151:21: note: when computing vector element at index '1' | |
| 5870 | 5862 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5863 | // :151:21: note: when computing vector element at index '1' | |
| 5871 | 5864 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5865 | // :151:21: note: when computing vector element at index '1' | |
| 5872 | 5866 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5867 | // :151:21: note: when computing vector element at index '1' | |
| 5873 | 5868 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5869 | // :151:21: note: when computing vector element at index '1' | |
| 5874 | 5870 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5875 | 5871 | // :151:21: note: when computing vector element at index '1' |
| 5876 | 5872 | // :151:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5880,13 +5876,17 @@ const std = @import("std"); |
| 5880 | 5876 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5881 | 5877 | // :151:21: note: when computing vector element at index '1' |
| 5882 | 5878 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5883 | // :151:21: note: when computing vector element at index '0' | |
| 5879 | // :151:21: note: when computing vector element at index '1' | |
| 5884 | 5880 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5885 | // :151:21: note: when computing vector element at index '0' | |
| 5881 | // :151:21: note: when computing vector element at index '1' | |
| 5886 | 5882 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5887 | // :151:21: note: when computing vector element at index '0' | |
| 5883 | // :151:21: note: when computing vector element at index '1' | |
| 5888 | 5884 | // :151:21: error: use of undefined value here causes illegal behavior |
| 5889 | // :151:21: note: when computing vector element at index '0' | |
| 5885 | // :151:21: note: when computing vector element at index '1' | |
| 5886 | // :151:21: error: use of undefined value here causes illegal behavior | |
| 5887 | // :151:21: note: when computing vector element at index '1' | |
| 5888 | // :151:21: error: use of undefined value here causes illegal behavior | |
| 5889 | // :151:21: note: when computing vector element at index '1' | |
| 5890 | 5890 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5891 | 5891 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5892 | 5892 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5894,21 +5894,13 @@ const std = @import("std"); |
| 5894 | 5894 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5895 | 5895 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5896 | 5896 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5897 | // :155:30: note: when computing vector element at index '1' | |
| 5898 | 5897 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5899 | // :155:30: note: when computing vector element at index '1' | |
| 5900 | 5898 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5901 | // :155:30: note: when computing vector element at index '1' | |
| 5902 | 5899 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5903 | // :155:30: note: when computing vector element at index '1' | |
| 5904 | 5900 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5905 | // :155:30: note: when computing vector element at index '0' | |
| 5906 | 5901 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5907 | // :155:30: note: when computing vector element at index '0' | |
| 5908 | 5902 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5909 | // :155:30: note: when computing vector element at index '0' | |
| 5910 | 5903 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5911 | // :155:30: note: when computing vector element at index '0' | |
| 5912 | 5904 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5913 | 5905 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5914 | 5906 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5916,21 +5908,13 @@ const std = @import("std"); |
| 5916 | 5908 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5917 | 5909 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5918 | 5910 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5919 | // :155:30: note: when computing vector element at index '1' | |
| 5920 | 5911 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5921 | // :155:30: note: when computing vector element at index '1' | |
| 5922 | 5912 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5923 | // :155:30: note: when computing vector element at index '1' | |
| 5924 | 5913 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5925 | // :155:30: note: when computing vector element at index '1' | |
| 5926 | 5914 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5927 | // :155:30: note: when computing vector element at index '0' | |
| 5928 | 5915 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5929 | // :155:30: note: when computing vector element at index '0' | |
| 5930 | 5916 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5931 | // :155:30: note: when computing vector element at index '0' | |
| 5932 | 5917 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5933 | // :155:30: note: when computing vector element at index '0' | |
| 5934 | 5918 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5935 | 5919 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5936 | 5920 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5938,21 +5922,13 @@ const std = @import("std"); |
| 5938 | 5922 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5939 | 5923 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5940 | 5924 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5941 | // :155:30: note: when computing vector element at index '1' | |
| 5942 | 5925 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5943 | // :155:30: note: when computing vector element at index '1' | |
| 5944 | 5926 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5945 | // :155:30: note: when computing vector element at index '1' | |
| 5946 | 5927 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5947 | // :155:30: note: when computing vector element at index '1' | |
| 5948 | 5928 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5949 | // :155:30: note: when computing vector element at index '0' | |
| 5950 | 5929 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5951 | // :155:30: note: when computing vector element at index '0' | |
| 5952 | 5930 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5953 | // :155:30: note: when computing vector element at index '0' | |
| 5954 | 5931 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5955 | // :155:30: note: when computing vector element at index '0' | |
| 5956 | 5932 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5957 | 5933 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5958 | 5934 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5960,21 +5936,13 @@ const std = @import("std"); |
| 5960 | 5936 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5961 | 5937 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5962 | 5938 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5963 | // :155:30: note: when computing vector element at index '1' | |
| 5964 | 5939 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5965 | // :155:30: note: when computing vector element at index '1' | |
| 5966 | 5940 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5967 | // :155:30: note: when computing vector element at index '1' | |
| 5968 | 5941 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5969 | // :155:30: note: when computing vector element at index '1' | |
| 5970 | 5942 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5971 | // :155:30: note: when computing vector element at index '0' | |
| 5972 | 5943 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5973 | // :155:30: note: when computing vector element at index '0' | |
| 5974 | 5944 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5975 | // :155:30: note: when computing vector element at index '0' | |
| 5976 | 5945 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5977 | // :155:30: note: when computing vector element at index '0' | |
| 5978 | 5946 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5979 | 5947 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5980 | 5948 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5982,13 +5950,9 @@ const std = @import("std"); |
| 5982 | 5950 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5983 | 5951 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5984 | 5952 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5985 | // :155:30: note: when computing vector element at index '1' | |
| 5986 | 5953 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5987 | // :155:30: note: when computing vector element at index '1' | |
| 5988 | 5954 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5989 | // :155:30: note: when computing vector element at index '1' | |
| 5990 | 5955 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5991 | // :155:30: note: when computing vector element at index '1' | |
| 5992 | 5956 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5993 | 5957 | // :155:30: note: when computing vector element at index '0' |
| 5994 | 5958 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -5998,19 +5962,21 @@ const std = @import("std"); |
| 5998 | 5962 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5999 | 5963 | // :155:30: note: when computing vector element at index '0' |
| 6000 | 5964 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5965 | // :155:30: note: when computing vector element at index '0' | |
| 6001 | 5966 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5967 | // :155:30: note: when computing vector element at index '0' | |
| 6002 | 5968 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5969 | // :155:30: note: when computing vector element at index '0' | |
| 6003 | 5970 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5971 | // :155:30: note: when computing vector element at index '0' | |
| 6004 | 5972 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5973 | // :155:30: note: when computing vector element at index '0' | |
| 6005 | 5974 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5975 | // :155:30: note: when computing vector element at index '0' | |
| 6006 | 5976 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6007 | // :155:30: note: when computing vector element at index '1' | |
| 6008 | // :155:30: error: use of undefined value here causes illegal behavior | |
| 6009 | // :155:30: note: when computing vector element at index '1' | |
| 6010 | // :155:30: error: use of undefined value here causes illegal behavior | |
| 6011 | // :155:30: note: when computing vector element at index '1' | |
| 5977 | // :155:30: note: when computing vector element at index '0' | |
| 6012 | 5978 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6013 | // :155:30: note: when computing vector element at index '1' | |
| 5979 | // :155:30: note: when computing vector element at index '0' | |
| 6014 | 5980 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6015 | 5981 | // :155:30: note: when computing vector element at index '0' |
| 6016 | 5982 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6020,19 +5986,25 @@ const std = @import("std"); |
| 6020 | 5986 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6021 | 5987 | // :155:30: note: when computing vector element at index '0' |
| 6022 | 5988 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5989 | // :155:30: note: when computing vector element at index '0' | |
| 6023 | 5990 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5991 | // :155:30: note: when computing vector element at index '0' | |
| 6024 | 5992 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5993 | // :155:30: note: when computing vector element at index '0' | |
| 6025 | 5994 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5995 | // :155:30: note: when computing vector element at index '0' | |
| 6026 | 5996 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5997 | // :155:30: note: when computing vector element at index '0' | |
| 6027 | 5998 | // :155:30: error: use of undefined value here causes illegal behavior |
| 5999 | // :155:30: note: when computing vector element at index '0' | |
| 6028 | 6000 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6029 | // :155:30: note: when computing vector element at index '1' | |
| 6001 | // :155:30: note: when computing vector element at index '0' | |
| 6030 | 6002 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6031 | // :155:30: note: when computing vector element at index '1' | |
| 6003 | // :155:30: note: when computing vector element at index '0' | |
| 6032 | 6004 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6033 | // :155:30: note: when computing vector element at index '1' | |
| 6005 | // :155:30: note: when computing vector element at index '0' | |
| 6034 | 6006 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6035 | // :155:30: note: when computing vector element at index '1' | |
| 6007 | // :155:30: note: when computing vector element at index '0' | |
| 6036 | 6008 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6037 | 6009 | // :155:30: note: when computing vector element at index '0' |
| 6038 | 6010 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6042,19 +6014,25 @@ const std = @import("std"); |
| 6042 | 6014 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6043 | 6015 | // :155:30: note: when computing vector element at index '0' |
| 6044 | 6016 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6017 | // :155:30: note: when computing vector element at index '0' | |
| 6045 | 6018 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6019 | // :155:30: note: when computing vector element at index '0' | |
| 6046 | 6020 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6021 | // :155:30: note: when computing vector element at index '0' | |
| 6047 | 6022 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6023 | // :155:30: note: when computing vector element at index '0' | |
| 6048 | 6024 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6025 | // :155:30: note: when computing vector element at index '0' | |
| 6049 | 6026 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6027 | // :155:30: note: when computing vector element at index '0' | |
| 6050 | 6028 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6051 | // :155:30: note: when computing vector element at index '1' | |
| 6029 | // :155:30: note: when computing vector element at index '0' | |
| 6052 | 6030 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6053 | // :155:30: note: when computing vector element at index '1' | |
| 6031 | // :155:30: note: when computing vector element at index '0' | |
| 6054 | 6032 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6055 | // :155:30: note: when computing vector element at index '1' | |
| 6033 | // :155:30: note: when computing vector element at index '0' | |
| 6056 | 6034 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6057 | // :155:30: note: when computing vector element at index '1' | |
| 6035 | // :155:30: note: when computing vector element at index '0' | |
| 6058 | 6036 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6059 | 6037 | // :155:30: note: when computing vector element at index '0' |
| 6060 | 6038 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6064,11 +6042,17 @@ const std = @import("std"); |
| 6064 | 6042 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6065 | 6043 | // :155:30: note: when computing vector element at index '0' |
| 6066 | 6044 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6045 | // :155:30: note: when computing vector element at index '1' | |
| 6067 | 6046 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6047 | // :155:30: note: when computing vector element at index '1' | |
| 6068 | 6048 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6049 | // :155:30: note: when computing vector element at index '1' | |
| 6069 | 6050 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6051 | // :155:30: note: when computing vector element at index '1' | |
| 6070 | 6052 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6053 | // :155:30: note: when computing vector element at index '1' | |
| 6071 | 6054 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6055 | // :155:30: note: when computing vector element at index '1' | |
| 6072 | 6056 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6073 | 6057 | // :155:30: note: when computing vector element at index '1' |
| 6074 | 6058 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6078,19 +6062,25 @@ const std = @import("std"); |
| 6078 | 6062 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6079 | 6063 | // :155:30: note: when computing vector element at index '1' |
| 6080 | 6064 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6081 | // :155:30: note: when computing vector element at index '0' | |
| 6065 | // :155:30: note: when computing vector element at index '1' | |
| 6082 | 6066 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6083 | // :155:30: note: when computing vector element at index '0' | |
| 6067 | // :155:30: note: when computing vector element at index '1' | |
| 6084 | 6068 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6085 | // :155:30: note: when computing vector element at index '0' | |
| 6069 | // :155:30: note: when computing vector element at index '1' | |
| 6086 | 6070 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6087 | // :155:30: note: when computing vector element at index '0' | |
| 6071 | // :155:30: note: when computing vector element at index '1' | |
| 6088 | 6072 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6073 | // :155:30: note: when computing vector element at index '1' | |
| 6089 | 6074 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6075 | // :155:30: note: when computing vector element at index '1' | |
| 6090 | 6076 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6077 | // :155:30: note: when computing vector element at index '1' | |
| 6091 | 6078 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6079 | // :155:30: note: when computing vector element at index '1' | |
| 6092 | 6080 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6081 | // :155:30: note: when computing vector element at index '1' | |
| 6093 | 6082 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6083 | // :155:30: note: when computing vector element at index '1' | |
| 6094 | 6084 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6095 | 6085 | // :155:30: note: when computing vector element at index '1' |
| 6096 | 6086 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6100,19 +6090,25 @@ const std = @import("std"); |
| 6100 | 6090 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6101 | 6091 | // :155:30: note: when computing vector element at index '1' |
| 6102 | 6092 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6103 | // :155:30: note: when computing vector element at index '0' | |
| 6093 | // :155:30: note: when computing vector element at index '1' | |
| 6104 | 6094 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6105 | // :155:30: note: when computing vector element at index '0' | |
| 6095 | // :155:30: note: when computing vector element at index '1' | |
| 6106 | 6096 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6107 | // :155:30: note: when computing vector element at index '0' | |
| 6097 | // :155:30: note: when computing vector element at index '1' | |
| 6108 | 6098 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6109 | // :155:30: note: when computing vector element at index '0' | |
| 6099 | // :155:30: note: when computing vector element at index '1' | |
| 6110 | 6100 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6101 | // :155:30: note: when computing vector element at index '1' | |
| 6111 | 6102 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6103 | // :155:30: note: when computing vector element at index '1' | |
| 6112 | 6104 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6105 | // :155:30: note: when computing vector element at index '1' | |
| 6113 | 6106 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6107 | // :155:30: note: when computing vector element at index '1' | |
| 6114 | 6108 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6109 | // :155:30: note: when computing vector element at index '1' | |
| 6115 | 6110 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6111 | // :155:30: note: when computing vector element at index '1' | |
| 6116 | 6112 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6117 | 6113 | // :155:30: note: when computing vector element at index '1' |
| 6118 | 6114 | // :155:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6122,13 +6118,17 @@ const std = @import("std"); |
| 6122 | 6118 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6123 | 6119 | // :155:30: note: when computing vector element at index '1' |
| 6124 | 6120 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6125 | // :155:30: note: when computing vector element at index '0' | |
| 6121 | // :155:30: note: when computing vector element at index '1' | |
| 6126 | 6122 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6127 | // :155:30: note: when computing vector element at index '0' | |
| 6123 | // :155:30: note: when computing vector element at index '1' | |
| 6128 | 6124 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6129 | // :155:30: note: when computing vector element at index '0' | |
| 6125 | // :155:30: note: when computing vector element at index '1' | |
| 6130 | 6126 | // :155:30: error: use of undefined value here causes illegal behavior |
| 6131 | // :155:30: note: when computing vector element at index '0' | |
| 6127 | // :155:30: note: when computing vector element at index '1' | |
| 6128 | // :155:30: error: use of undefined value here causes illegal behavior | |
| 6129 | // :155:30: note: when computing vector element at index '1' | |
| 6130 | // :155:30: error: use of undefined value here causes illegal behavior | |
| 6131 | // :155:30: note: when computing vector element at index '1' | |
| 6132 | 6132 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6133 | 6133 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6134 | 6134 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6136,21 +6136,13 @@ const std = @import("std"); |
| 6136 | 6136 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6137 | 6137 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6138 | 6138 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6139 | // :159:30: note: when computing vector element at index '1' | |
| 6140 | 6139 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6141 | // :159:30: note: when computing vector element at index '1' | |
| 6142 | 6140 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6143 | // :159:30: note: when computing vector element at index '1' | |
| 6144 | 6141 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6145 | // :159:30: note: when computing vector element at index '1' | |
| 6146 | 6142 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6147 | // :159:30: note: when computing vector element at index '0' | |
| 6148 | 6143 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6149 | // :159:30: note: when computing vector element at index '0' | |
| 6150 | 6144 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6151 | // :159:30: note: when computing vector element at index '0' | |
| 6152 | 6145 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6153 | // :159:30: note: when computing vector element at index '0' | |
| 6154 | 6146 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6155 | 6147 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6156 | 6148 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6158,21 +6150,13 @@ const std = @import("std"); |
| 6158 | 6150 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6159 | 6151 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6160 | 6152 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6161 | // :159:30: note: when computing vector element at index '1' | |
| 6162 | 6153 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6163 | // :159:30: note: when computing vector element at index '1' | |
| 6164 | 6154 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6165 | // :159:30: note: when computing vector element at index '1' | |
| 6166 | 6155 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6167 | // :159:30: note: when computing vector element at index '1' | |
| 6168 | 6156 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6169 | // :159:30: note: when computing vector element at index '0' | |
| 6170 | 6157 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6171 | // :159:30: note: when computing vector element at index '0' | |
| 6172 | 6158 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6173 | // :159:30: note: when computing vector element at index '0' | |
| 6174 | 6159 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6175 | // :159:30: note: when computing vector element at index '0' | |
| 6176 | 6160 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6177 | 6161 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6178 | 6162 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6180,21 +6164,13 @@ const std = @import("std"); |
| 6180 | 6164 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6181 | 6165 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6182 | 6166 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6183 | // :159:30: note: when computing vector element at index '1' | |
| 6184 | 6167 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6185 | // :159:30: note: when computing vector element at index '1' | |
| 6186 | 6168 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6187 | // :159:30: note: when computing vector element at index '1' | |
| 6188 | 6169 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6189 | // :159:30: note: when computing vector element at index '1' | |
| 6190 | 6170 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6191 | // :159:30: note: when computing vector element at index '0' | |
| 6192 | 6171 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6193 | // :159:30: note: when computing vector element at index '0' | |
| 6194 | 6172 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6195 | // :159:30: note: when computing vector element at index '0' | |
| 6196 | 6173 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6197 | // :159:30: note: when computing vector element at index '0' | |
| 6198 | 6174 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6199 | 6175 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6200 | 6176 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6202,21 +6178,13 @@ const std = @import("std"); |
| 6202 | 6178 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6203 | 6179 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6204 | 6180 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6205 | // :159:30: note: when computing vector element at index '1' | |
| 6206 | 6181 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6207 | // :159:30: note: when computing vector element at index '1' | |
| 6208 | 6182 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6209 | // :159:30: note: when computing vector element at index '1' | |
| 6210 | 6183 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6211 | // :159:30: note: when computing vector element at index '1' | |
| 6212 | 6184 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6213 | // :159:30: note: when computing vector element at index '0' | |
| 6214 | 6185 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6215 | // :159:30: note: when computing vector element at index '0' | |
| 6216 | 6186 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6217 | // :159:30: note: when computing vector element at index '0' | |
| 6218 | 6187 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6219 | // :159:30: note: when computing vector element at index '0' | |
| 6220 | 6188 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6221 | 6189 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6222 | 6190 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6224,13 +6192,9 @@ const std = @import("std"); |
| 6224 | 6192 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6225 | 6193 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6226 | 6194 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6227 | // :159:30: note: when computing vector element at index '1' | |
| 6228 | 6195 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6229 | // :159:30: note: when computing vector element at index '1' | |
| 6230 | 6196 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6231 | // :159:30: note: when computing vector element at index '1' | |
| 6232 | 6197 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6233 | // :159:30: note: when computing vector element at index '1' | |
| 6234 | 6198 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6235 | 6199 | // :159:30: note: when computing vector element at index '0' |
| 6236 | 6200 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6240,19 +6204,21 @@ const std = @import("std"); |
| 6240 | 6204 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6241 | 6205 | // :159:30: note: when computing vector element at index '0' |
| 6242 | 6206 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6207 | // :159:30: note: when computing vector element at index '0' | |
| 6243 | 6208 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6209 | // :159:30: note: when computing vector element at index '0' | |
| 6244 | 6210 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6211 | // :159:30: note: when computing vector element at index '0' | |
| 6245 | 6212 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6213 | // :159:30: note: when computing vector element at index '0' | |
| 6246 | 6214 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6215 | // :159:30: note: when computing vector element at index '0' | |
| 6247 | 6216 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6217 | // :159:30: note: when computing vector element at index '0' | |
| 6248 | 6218 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6249 | // :159:30: note: when computing vector element at index '1' | |
| 6250 | // :159:30: error: use of undefined value here causes illegal behavior | |
| 6251 | // :159:30: note: when computing vector element at index '1' | |
| 6252 | // :159:30: error: use of undefined value here causes illegal behavior | |
| 6253 | // :159:30: note: when computing vector element at index '1' | |
| 6219 | // :159:30: note: when computing vector element at index '0' | |
| 6254 | 6220 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6255 | // :159:30: note: when computing vector element at index '1' | |
| 6221 | // :159:30: note: when computing vector element at index '0' | |
| 6256 | 6222 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6257 | 6223 | // :159:30: note: when computing vector element at index '0' |
| 6258 | 6224 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6262,19 +6228,25 @@ const std = @import("std"); |
| 6262 | 6228 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6263 | 6229 | // :159:30: note: when computing vector element at index '0' |
| 6264 | 6230 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6231 | // :159:30: note: when computing vector element at index '0' | |
| 6265 | 6232 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6233 | // :159:30: note: when computing vector element at index '0' | |
| 6266 | 6234 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6235 | // :159:30: note: when computing vector element at index '0' | |
| 6267 | 6236 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6237 | // :159:30: note: when computing vector element at index '0' | |
| 6268 | 6238 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6239 | // :159:30: note: when computing vector element at index '0' | |
| 6269 | 6240 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6241 | // :159:30: note: when computing vector element at index '0' | |
| 6270 | 6242 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6271 | // :159:30: note: when computing vector element at index '1' | |
| 6243 | // :159:30: note: when computing vector element at index '0' | |
| 6272 | 6244 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6273 | // :159:30: note: when computing vector element at index '1' | |
| 6245 | // :159:30: note: when computing vector element at index '0' | |
| 6274 | 6246 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6275 | // :159:30: note: when computing vector element at index '1' | |
| 6247 | // :159:30: note: when computing vector element at index '0' | |
| 6276 | 6248 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6277 | // :159:30: note: when computing vector element at index '1' | |
| 6249 | // :159:30: note: when computing vector element at index '0' | |
| 6278 | 6250 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6279 | 6251 | // :159:30: note: when computing vector element at index '0' |
| 6280 | 6252 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6284,19 +6256,25 @@ const std = @import("std"); |
| 6284 | 6256 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6285 | 6257 | // :159:30: note: when computing vector element at index '0' |
| 6286 | 6258 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6259 | // :159:30: note: when computing vector element at index '0' | |
| 6287 | 6260 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6261 | // :159:30: note: when computing vector element at index '0' | |
| 6288 | 6262 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6263 | // :159:30: note: when computing vector element at index '0' | |
| 6289 | 6264 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6265 | // :159:30: note: when computing vector element at index '0' | |
| 6290 | 6266 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6267 | // :159:30: note: when computing vector element at index '0' | |
| 6291 | 6268 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6269 | // :159:30: note: when computing vector element at index '0' | |
| 6292 | 6270 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6293 | // :159:30: note: when computing vector element at index '1' | |
| 6271 | // :159:30: note: when computing vector element at index '0' | |
| 6294 | 6272 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6295 | // :159:30: note: when computing vector element at index '1' | |
| 6273 | // :159:30: note: when computing vector element at index '0' | |
| 6296 | 6274 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6297 | // :159:30: note: when computing vector element at index '1' | |
| 6275 | // :159:30: note: when computing vector element at index '0' | |
| 6298 | 6276 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6299 | // :159:30: note: when computing vector element at index '1' | |
| 6277 | // :159:30: note: when computing vector element at index '0' | |
| 6300 | 6278 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6301 | 6279 | // :159:30: note: when computing vector element at index '0' |
| 6302 | 6280 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6306,11 +6284,17 @@ const std = @import("std"); |
| 6306 | 6284 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6307 | 6285 | // :159:30: note: when computing vector element at index '0' |
| 6308 | 6286 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6287 | // :159:30: note: when computing vector element at index '1' | |
| 6309 | 6288 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6289 | // :159:30: note: when computing vector element at index '1' | |
| 6310 | 6290 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6291 | // :159:30: note: when computing vector element at index '1' | |
| 6311 | 6292 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6293 | // :159:30: note: when computing vector element at index '1' | |
| 6312 | 6294 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6295 | // :159:30: note: when computing vector element at index '1' | |
| 6313 | 6296 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6297 | // :159:30: note: when computing vector element at index '1' | |
| 6314 | 6298 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6315 | 6299 | // :159:30: note: when computing vector element at index '1' |
| 6316 | 6300 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6320,19 +6304,25 @@ const std = @import("std"); |
| 6320 | 6304 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6321 | 6305 | // :159:30: note: when computing vector element at index '1' |
| 6322 | 6306 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6323 | // :159:30: note: when computing vector element at index '0' | |
| 6307 | // :159:30: note: when computing vector element at index '1' | |
| 6324 | 6308 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6325 | // :159:30: note: when computing vector element at index '0' | |
| 6309 | // :159:30: note: when computing vector element at index '1' | |
| 6326 | 6310 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6327 | // :159:30: note: when computing vector element at index '0' | |
| 6311 | // :159:30: note: when computing vector element at index '1' | |
| 6328 | 6312 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6329 | // :159:30: note: when computing vector element at index '0' | |
| 6313 | // :159:30: note: when computing vector element at index '1' | |
| 6330 | 6314 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6315 | // :159:30: note: when computing vector element at index '1' | |
| 6331 | 6316 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6317 | // :159:30: note: when computing vector element at index '1' | |
| 6332 | 6318 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6319 | // :159:30: note: when computing vector element at index '1' | |
| 6333 | 6320 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6321 | // :159:30: note: when computing vector element at index '1' | |
| 6334 | 6322 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6323 | // :159:30: note: when computing vector element at index '1' | |
| 6335 | 6324 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6325 | // :159:30: note: when computing vector element at index '1' | |
| 6336 | 6326 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6337 | 6327 | // :159:30: note: when computing vector element at index '1' |
| 6338 | 6328 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6342,19 +6332,27 @@ const std = @import("std"); |
| 6342 | 6332 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6343 | 6333 | // :159:30: note: when computing vector element at index '1' |
| 6344 | 6334 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6345 | // :159:30: note: when computing vector element at index '0' | |
| 6335 | // :159:30: note: when computing vector element at index '1' | |
| 6346 | 6336 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6347 | // :159:30: note: when computing vector element at index '0' | |
| 6337 | // :159:30: note: when computing vector element at index '1' | |
| 6348 | 6338 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6349 | // :159:30: note: when computing vector element at index '0' | |
| 6339 | // :159:30: note: when computing vector element at index '1' | |
| 6350 | 6340 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6351 | // :159:30: note: when computing vector element at index '0' | |
| 6341 | // :159:30: note: when computing vector element at index '1' | |
| 6342 | // :159:30: error: use of undefined value here causes illegal behavior | |
| 6343 | // :159:30: note: when computing vector element at index '1' | |
| 6352 | 6344 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6345 | // :159:30: note: when computing vector element at index '1' | |
| 6353 | 6346 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6347 | // :159:30: note: when computing vector element at index '1' | |
| 6354 | 6348 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6349 | // :159:30: note: when computing vector element at index '1' | |
| 6355 | 6350 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6351 | // :159:30: note: when computing vector element at index '1' | |
| 6356 | 6352 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6353 | // :159:30: note: when computing vector element at index '1' | |
| 6357 | 6354 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6355 | // :159:30: note: when computing vector element at index '1' | |
| 6358 | 6356 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6359 | 6357 | // :159:30: note: when computing vector element at index '1' |
| 6360 | 6358 | // :159:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6364,13 +6362,15 @@ const std = @import("std"); |
| 6364 | 6362 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6365 | 6363 | // :159:30: note: when computing vector element at index '1' |
| 6366 | 6364 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6367 | // :159:30: note: when computing vector element at index '0' | |
| 6365 | // :159:30: note: when computing vector element at index '1' | |
| 6368 | 6366 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6369 | // :159:30: note: when computing vector element at index '0' | |
| 6367 | // :159:30: note: when computing vector element at index '1' | |
| 6370 | 6368 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6371 | // :159:30: note: when computing vector element at index '0' | |
| 6369 | // :159:30: note: when computing vector element at index '1' | |
| 6372 | 6370 | // :159:30: error: use of undefined value here causes illegal behavior |
| 6373 | // :159:30: note: when computing vector element at index '0' | |
| 6371 | // :159:30: note: when computing vector element at index '1' | |
| 6372 | // :159:30: error: use of undefined value here causes illegal behavior | |
| 6373 | // :159:30: note: when computing vector element at index '1' | |
| 6374 | 6374 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6375 | 6375 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6376 | 6376 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6378,21 +6378,13 @@ const std = @import("std"); |
| 6378 | 6378 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6379 | 6379 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6380 | 6380 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6381 | // :163:30: note: when computing vector element at index '1' | |
| 6382 | 6381 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6383 | // :163:30: note: when computing vector element at index '1' | |
| 6384 | 6382 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6385 | // :163:30: note: when computing vector element at index '1' | |
| 6386 | 6383 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6387 | // :163:30: note: when computing vector element at index '1' | |
| 6388 | 6384 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6389 | // :163:30: note: when computing vector element at index '0' | |
| 6390 | 6385 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6391 | // :163:30: note: when computing vector element at index '0' | |
| 6392 | 6386 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6393 | // :163:30: note: when computing vector element at index '0' | |
| 6394 | 6387 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6395 | // :163:30: note: when computing vector element at index '0' | |
| 6396 | 6388 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6397 | 6389 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6398 | 6390 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6400,21 +6392,13 @@ const std = @import("std"); |
| 6400 | 6392 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6401 | 6393 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6402 | 6394 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6403 | // :163:30: note: when computing vector element at index '1' | |
| 6404 | 6395 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6405 | // :163:30: note: when computing vector element at index '1' | |
| 6406 | 6396 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6407 | // :163:30: note: when computing vector element at index '1' | |
| 6408 | 6397 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6409 | // :163:30: note: when computing vector element at index '1' | |
| 6410 | 6398 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6411 | // :163:30: note: when computing vector element at index '0' | |
| 6412 | 6399 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6413 | // :163:30: note: when computing vector element at index '0' | |
| 6414 | 6400 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6415 | // :163:30: note: when computing vector element at index '0' | |
| 6416 | 6401 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6417 | // :163:30: note: when computing vector element at index '0' | |
| 6418 | 6402 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6419 | 6403 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6420 | 6404 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6422,21 +6406,13 @@ const std = @import("std"); |
| 6422 | 6406 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6423 | 6407 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6424 | 6408 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6425 | // :163:30: note: when computing vector element at index '1' | |
| 6426 | 6409 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6427 | // :163:30: note: when computing vector element at index '1' | |
| 6428 | 6410 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6429 | // :163:30: note: when computing vector element at index '1' | |
| 6430 | 6411 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6431 | // :163:30: note: when computing vector element at index '1' | |
| 6432 | 6412 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6433 | // :163:30: note: when computing vector element at index '0' | |
| 6434 | 6413 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6435 | // :163:30: note: when computing vector element at index '0' | |
| 6436 | 6414 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6437 | // :163:30: note: when computing vector element at index '0' | |
| 6438 | 6415 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6439 | // :163:30: note: when computing vector element at index '0' | |
| 6440 | 6416 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6441 | 6417 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6442 | 6418 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6444,21 +6420,13 @@ const std = @import("std"); |
| 6444 | 6420 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6445 | 6421 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6446 | 6422 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6447 | // :163:30: note: when computing vector element at index '1' | |
| 6448 | 6423 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6449 | // :163:30: note: when computing vector element at index '1' | |
| 6450 | 6424 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6451 | // :163:30: note: when computing vector element at index '1' | |
| 6452 | 6425 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6453 | // :163:30: note: when computing vector element at index '1' | |
| 6454 | 6426 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6455 | // :163:30: note: when computing vector element at index '0' | |
| 6456 | 6427 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6457 | // :163:30: note: when computing vector element at index '0' | |
| 6458 | 6428 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6459 | // :163:30: note: when computing vector element at index '0' | |
| 6460 | 6429 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6461 | // :163:30: note: when computing vector element at index '0' | |
| 6462 | 6430 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6463 | 6431 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6464 | 6432 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6466,13 +6434,9 @@ const std = @import("std"); |
| 6466 | 6434 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6467 | 6435 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6468 | 6436 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6469 | // :163:30: note: when computing vector element at index '1' | |
| 6470 | 6437 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6471 | // :163:30: note: when computing vector element at index '1' | |
| 6472 | 6438 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6473 | // :163:30: note: when computing vector element at index '1' | |
| 6474 | 6439 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6475 | // :163:30: note: when computing vector element at index '1' | |
| 6476 | 6440 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6477 | 6441 | // :163:30: note: when computing vector element at index '0' |
| 6478 | 6442 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6482,19 +6446,21 @@ const std = @import("std"); |
| 6482 | 6446 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6483 | 6447 | // :163:30: note: when computing vector element at index '0' |
| 6484 | 6448 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6449 | // :163:30: note: when computing vector element at index '0' | |
| 6485 | 6450 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6451 | // :163:30: note: when computing vector element at index '0' | |
| 6486 | 6452 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6453 | // :163:30: note: when computing vector element at index '0' | |
| 6487 | 6454 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6455 | // :163:30: note: when computing vector element at index '0' | |
| 6488 | 6456 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6457 | // :163:30: note: when computing vector element at index '0' | |
| 6489 | 6458 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6459 | // :163:30: note: when computing vector element at index '0' | |
| 6490 | 6460 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6491 | // :163:30: note: when computing vector element at index '1' | |
| 6492 | // :163:30: error: use of undefined value here causes illegal behavior | |
| 6493 | // :163:30: note: when computing vector element at index '1' | |
| 6494 | // :163:30: error: use of undefined value here causes illegal behavior | |
| 6495 | // :163:30: note: when computing vector element at index '1' | |
| 6461 | // :163:30: note: when computing vector element at index '0' | |
| 6496 | 6462 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6497 | // :163:30: note: when computing vector element at index '1' | |
| 6463 | // :163:30: note: when computing vector element at index '0' | |
| 6498 | 6464 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6499 | 6465 | // :163:30: note: when computing vector element at index '0' |
| 6500 | 6466 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6504,19 +6470,25 @@ const std = @import("std"); |
| 6504 | 6470 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6505 | 6471 | // :163:30: note: when computing vector element at index '0' |
| 6506 | 6472 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6473 | // :163:30: note: when computing vector element at index '0' | |
| 6507 | 6474 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6475 | // :163:30: note: when computing vector element at index '0' | |
| 6508 | 6476 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6477 | // :163:30: note: when computing vector element at index '0' | |
| 6509 | 6478 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6479 | // :163:30: note: when computing vector element at index '0' | |
| 6510 | 6480 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6481 | // :163:30: note: when computing vector element at index '0' | |
| 6511 | 6482 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6483 | // :163:30: note: when computing vector element at index '0' | |
| 6512 | 6484 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6513 | // :163:30: note: when computing vector element at index '1' | |
| 6485 | // :163:30: note: when computing vector element at index '0' | |
| 6514 | 6486 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6515 | // :163:30: note: when computing vector element at index '1' | |
| 6487 | // :163:30: note: when computing vector element at index '0' | |
| 6516 | 6488 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6517 | // :163:30: note: when computing vector element at index '1' | |
| 6489 | // :163:30: note: when computing vector element at index '0' | |
| 6518 | 6490 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6519 | // :163:30: note: when computing vector element at index '1' | |
| 6491 | // :163:30: note: when computing vector element at index '0' | |
| 6520 | 6492 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6521 | 6493 | // :163:30: note: when computing vector element at index '0' |
| 6522 | 6494 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6526,19 +6498,25 @@ const std = @import("std"); |
| 6526 | 6498 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6527 | 6499 | // :163:30: note: when computing vector element at index '0' |
| 6528 | 6500 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6501 | // :163:30: note: when computing vector element at index '0' | |
| 6529 | 6502 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6503 | // :163:30: note: when computing vector element at index '0' | |
| 6530 | 6504 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6505 | // :163:30: note: when computing vector element at index '0' | |
| 6531 | 6506 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6507 | // :163:30: note: when computing vector element at index '0' | |
| 6532 | 6508 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6509 | // :163:30: note: when computing vector element at index '0' | |
| 6533 | 6510 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6511 | // :163:30: note: when computing vector element at index '0' | |
| 6534 | 6512 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6535 | // :163:30: note: when computing vector element at index '1' | |
| 6513 | // :163:30: note: when computing vector element at index '0' | |
| 6536 | 6514 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6537 | // :163:30: note: when computing vector element at index '1' | |
| 6515 | // :163:30: note: when computing vector element at index '0' | |
| 6538 | 6516 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6539 | // :163:30: note: when computing vector element at index '1' | |
| 6517 | // :163:30: note: when computing vector element at index '0' | |
| 6540 | 6518 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6541 | // :163:30: note: when computing vector element at index '1' | |
| 6519 | // :163:30: note: when computing vector element at index '0' | |
| 6542 | 6520 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6543 | 6521 | // :163:30: note: when computing vector element at index '0' |
| 6544 | 6522 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6548,11 +6526,19 @@ const std = @import("std"); |
| 6548 | 6526 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6549 | 6527 | // :163:30: note: when computing vector element at index '0' |
| 6550 | 6528 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6529 | // :163:30: note: when computing vector element at index '1' | |
| 6530 | // :163:30: error: use of undefined value here causes illegal behavior | |
| 6531 | // :163:30: note: when computing vector element at index '1' | |
| 6551 | 6532 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6533 | // :163:30: note: when computing vector element at index '1' | |
| 6552 | 6534 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6535 | // :163:30: note: when computing vector element at index '1' | |
| 6553 | 6536 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6537 | // :163:30: note: when computing vector element at index '1' | |
| 6554 | 6538 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6539 | // :163:30: note: when computing vector element at index '1' | |
| 6555 | 6540 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6541 | // :163:30: note: when computing vector element at index '1' | |
| 6556 | 6542 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6557 | 6543 | // :163:30: note: when computing vector element at index '1' |
| 6558 | 6544 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6562,19 +6548,27 @@ const std = @import("std"); |
| 6562 | 6548 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6563 | 6549 | // :163:30: note: when computing vector element at index '1' |
| 6564 | 6550 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6565 | // :163:30: note: when computing vector element at index '0' | |
| 6551 | // :163:30: note: when computing vector element at index '1' | |
| 6566 | 6552 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6567 | // :163:30: note: when computing vector element at index '0' | |
| 6553 | // :163:30: note: when computing vector element at index '1' | |
| 6568 | 6554 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6569 | // :163:30: note: when computing vector element at index '0' | |
| 6555 | // :163:30: note: when computing vector element at index '1' | |
| 6570 | 6556 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6571 | // :163:30: note: when computing vector element at index '0' | |
| 6557 | // :163:30: note: when computing vector element at index '1' | |
| 6558 | // :163:30: error: use of undefined value here causes illegal behavior | |
| 6559 | // :163:30: note: when computing vector element at index '1' | |
| 6572 | 6560 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6561 | // :163:30: note: when computing vector element at index '1' | |
| 6573 | 6562 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6563 | // :163:30: note: when computing vector element at index '1' | |
| 6574 | 6564 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6565 | // :163:30: note: when computing vector element at index '1' | |
| 6575 | 6566 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6567 | // :163:30: note: when computing vector element at index '1' | |
| 6576 | 6568 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6569 | // :163:30: note: when computing vector element at index '1' | |
| 6577 | 6570 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6571 | // :163:30: note: when computing vector element at index '1' | |
| 6578 | 6572 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6579 | 6573 | // :163:30: note: when computing vector element at index '1' |
| 6580 | 6574 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6584,19 +6578,25 @@ const std = @import("std"); |
| 6584 | 6578 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6585 | 6579 | // :163:30: note: when computing vector element at index '1' |
| 6586 | 6580 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6587 | // :163:30: note: when computing vector element at index '0' | |
| 6581 | // :163:30: note: when computing vector element at index '1' | |
| 6588 | 6582 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6589 | // :163:30: note: when computing vector element at index '0' | |
| 6583 | // :163:30: note: when computing vector element at index '1' | |
| 6590 | 6584 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6591 | // :163:30: note: when computing vector element at index '0' | |
| 6585 | // :163:30: note: when computing vector element at index '1' | |
| 6592 | 6586 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6593 | // :163:30: note: when computing vector element at index '0' | |
| 6587 | // :163:30: note: when computing vector element at index '1' | |
| 6594 | 6588 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6589 | // :163:30: note: when computing vector element at index '1' | |
| 6595 | 6590 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6591 | // :163:30: note: when computing vector element at index '1' | |
| 6596 | 6592 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6593 | // :163:30: note: when computing vector element at index '1' | |
| 6597 | 6594 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6595 | // :163:30: note: when computing vector element at index '1' | |
| 6598 | 6596 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6597 | // :163:30: note: when computing vector element at index '1' | |
| 6599 | 6598 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6599 | // :163:30: note: when computing vector element at index '1' | |
| 6600 | 6600 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6601 | 6601 | // :163:30: note: when computing vector element at index '1' |
| 6602 | 6602 | // :163:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6606,13 +6606,13 @@ const std = @import("std"); |
| 6606 | 6606 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6607 | 6607 | // :163:30: note: when computing vector element at index '1' |
| 6608 | 6608 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6609 | // :163:30: note: when computing vector element at index '0' | |
| 6609 | // :163:30: note: when computing vector element at index '1' | |
| 6610 | 6610 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6611 | // :163:30: note: when computing vector element at index '0' | |
| 6611 | // :163:30: note: when computing vector element at index '1' | |
| 6612 | 6612 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6613 | // :163:30: note: when computing vector element at index '0' | |
| 6613 | // :163:30: note: when computing vector element at index '1' | |
| 6614 | 6614 | // :163:30: error: use of undefined value here causes illegal behavior |
| 6615 | // :163:30: note: when computing vector element at index '0' | |
| 6615 | // :163:30: note: when computing vector element at index '1' | |
| 6616 | 6616 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6617 | 6617 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6618 | 6618 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6620,21 +6620,13 @@ const std = @import("std"); |
| 6620 | 6620 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6621 | 6621 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6622 | 6622 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6623 | // :167:25: note: when computing vector element at index '1' | |
| 6624 | 6623 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6625 | // :167:25: note: when computing vector element at index '1' | |
| 6626 | 6624 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6627 | // :167:25: note: when computing vector element at index '1' | |
| 6628 | 6625 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6629 | // :167:25: note: when computing vector element at index '1' | |
| 6630 | 6626 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6631 | // :167:25: note: when computing vector element at index '0' | |
| 6632 | 6627 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6633 | // :167:25: note: when computing vector element at index '0' | |
| 6634 | 6628 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6635 | // :167:25: note: when computing vector element at index '0' | |
| 6636 | 6629 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6637 | // :167:25: note: when computing vector element at index '0' | |
| 6638 | 6630 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6639 | 6631 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6640 | 6632 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6642,21 +6634,13 @@ const std = @import("std"); |
| 6642 | 6634 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6643 | 6635 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6644 | 6636 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6645 | // :167:25: note: when computing vector element at index '1' | |
| 6646 | 6637 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6647 | // :167:25: note: when computing vector element at index '1' | |
| 6648 | 6638 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6649 | // :167:25: note: when computing vector element at index '1' | |
| 6650 | 6639 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6651 | // :167:25: note: when computing vector element at index '1' | |
| 6652 | 6640 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6653 | // :167:25: note: when computing vector element at index '0' | |
| 6654 | 6641 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6655 | // :167:25: note: when computing vector element at index '0' | |
| 6656 | 6642 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6657 | // :167:25: note: when computing vector element at index '0' | |
| 6658 | 6643 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6659 | // :167:25: note: when computing vector element at index '0' | |
| 6660 | 6644 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6661 | 6645 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6662 | 6646 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6664,21 +6648,13 @@ const std = @import("std"); |
| 6664 | 6648 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6665 | 6649 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6666 | 6650 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6667 | // :167:25: note: when computing vector element at index '1' | |
| 6668 | 6651 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6669 | // :167:25: note: when computing vector element at index '1' | |
| 6670 | 6652 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6671 | // :167:25: note: when computing vector element at index '1' | |
| 6672 | 6653 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6673 | // :167:25: note: when computing vector element at index '1' | |
| 6674 | 6654 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6675 | // :167:25: note: when computing vector element at index '0' | |
| 6676 | 6655 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6677 | // :167:25: note: when computing vector element at index '0' | |
| 6678 | 6656 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6679 | // :167:25: note: when computing vector element at index '0' | |
| 6680 | 6657 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6681 | // :167:25: note: when computing vector element at index '0' | |
| 6682 | 6658 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6683 | 6659 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6684 | 6660 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6686,21 +6662,13 @@ const std = @import("std"); |
| 6686 | 6662 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6687 | 6663 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6688 | 6664 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6689 | // :167:25: note: when computing vector element at index '1' | |
| 6690 | 6665 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6691 | // :167:25: note: when computing vector element at index '1' | |
| 6692 | 6666 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6693 | // :167:25: note: when computing vector element at index '1' | |
| 6694 | 6667 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6695 | // :167:25: note: when computing vector element at index '1' | |
| 6696 | 6668 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6697 | // :167:25: note: when computing vector element at index '0' | |
| 6698 | 6669 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6699 | // :167:25: note: when computing vector element at index '0' | |
| 6700 | 6670 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6701 | // :167:25: note: when computing vector element at index '0' | |
| 6702 | 6671 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6703 | // :167:25: note: when computing vector element at index '0' | |
| 6704 | 6672 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6705 | 6673 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6706 | 6674 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6708,13 +6676,9 @@ const std = @import("std"); |
| 6708 | 6676 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6709 | 6677 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6710 | 6678 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6711 | // :167:25: note: when computing vector element at index '1' | |
| 6712 | 6679 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6713 | // :167:25: note: when computing vector element at index '1' | |
| 6714 | 6680 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6715 | // :167:25: note: when computing vector element at index '1' | |
| 6716 | 6681 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6717 | // :167:25: note: when computing vector element at index '1' | |
| 6718 | 6682 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6719 | 6683 | // :167:25: note: when computing vector element at index '0' |
| 6720 | 6684 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6724,19 +6688,21 @@ const std = @import("std"); |
| 6724 | 6688 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6725 | 6689 | // :167:25: note: when computing vector element at index '0' |
| 6726 | 6690 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6691 | // :167:25: note: when computing vector element at index '0' | |
| 6727 | 6692 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6693 | // :167:25: note: when computing vector element at index '0' | |
| 6728 | 6694 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6695 | // :167:25: note: when computing vector element at index '0' | |
| 6729 | 6696 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6697 | // :167:25: note: when computing vector element at index '0' | |
| 6730 | 6698 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6699 | // :167:25: note: when computing vector element at index '0' | |
| 6731 | 6700 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6701 | // :167:25: note: when computing vector element at index '0' | |
| 6732 | 6702 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6733 | // :167:25: note: when computing vector element at index '1' | |
| 6734 | // :167:25: error: use of undefined value here causes illegal behavior | |
| 6735 | // :167:25: note: when computing vector element at index '1' | |
| 6736 | // :167:25: error: use of undefined value here causes illegal behavior | |
| 6737 | // :167:25: note: when computing vector element at index '1' | |
| 6703 | // :167:25: note: when computing vector element at index '0' | |
| 6738 | 6704 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6739 | // :167:25: note: when computing vector element at index '1' | |
| 6705 | // :167:25: note: when computing vector element at index '0' | |
| 6740 | 6706 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6741 | 6707 | // :167:25: note: when computing vector element at index '0' |
| 6742 | 6708 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6746,19 +6712,25 @@ const std = @import("std"); |
| 6746 | 6712 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6747 | 6713 | // :167:25: note: when computing vector element at index '0' |
| 6748 | 6714 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6715 | // :167:25: note: when computing vector element at index '0' | |
| 6749 | 6716 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6717 | // :167:25: note: when computing vector element at index '0' | |
| 6750 | 6718 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6719 | // :167:25: note: when computing vector element at index '0' | |
| 6751 | 6720 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6721 | // :167:25: note: when computing vector element at index '0' | |
| 6752 | 6722 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6723 | // :167:25: note: when computing vector element at index '0' | |
| 6753 | 6724 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6725 | // :167:25: note: when computing vector element at index '0' | |
| 6754 | 6726 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6755 | // :167:25: note: when computing vector element at index '1' | |
| 6727 | // :167:25: note: when computing vector element at index '0' | |
| 6756 | 6728 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6757 | // :167:25: note: when computing vector element at index '1' | |
| 6729 | // :167:25: note: when computing vector element at index '0' | |
| 6758 | 6730 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6759 | // :167:25: note: when computing vector element at index '1' | |
| 6731 | // :167:25: note: when computing vector element at index '0' | |
| 6760 | 6732 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6761 | // :167:25: note: when computing vector element at index '1' | |
| 6733 | // :167:25: note: when computing vector element at index '0' | |
| 6762 | 6734 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6763 | 6735 | // :167:25: note: when computing vector element at index '0' |
| 6764 | 6736 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6768,19 +6740,25 @@ const std = @import("std"); |
| 6768 | 6740 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6769 | 6741 | // :167:25: note: when computing vector element at index '0' |
| 6770 | 6742 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6743 | // :167:25: note: when computing vector element at index '0' | |
| 6771 | 6744 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6745 | // :167:25: note: when computing vector element at index '0' | |
| 6772 | 6746 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6747 | // :167:25: note: when computing vector element at index '0' | |
| 6773 | 6748 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6749 | // :167:25: note: when computing vector element at index '0' | |
| 6774 | 6750 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6751 | // :167:25: note: when computing vector element at index '0' | |
| 6775 | 6752 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6753 | // :167:25: note: when computing vector element at index '0' | |
| 6776 | 6754 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6777 | // :167:25: note: when computing vector element at index '1' | |
| 6755 | // :167:25: note: when computing vector element at index '0' | |
| 6778 | 6756 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6779 | // :167:25: note: when computing vector element at index '1' | |
| 6757 | // :167:25: note: when computing vector element at index '0' | |
| 6780 | 6758 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6781 | // :167:25: note: when computing vector element at index '1' | |
| 6759 | // :167:25: note: when computing vector element at index '0' | |
| 6782 | 6760 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6783 | // :167:25: note: when computing vector element at index '1' | |
| 6761 | // :167:25: note: when computing vector element at index '0' | |
| 6784 | 6762 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6785 | 6763 | // :167:25: note: when computing vector element at index '0' |
| 6786 | 6764 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6790,11 +6768,21 @@ const std = @import("std"); |
| 6790 | 6768 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6791 | 6769 | // :167:25: note: when computing vector element at index '0' |
| 6792 | 6770 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6771 | // :167:25: note: when computing vector element at index '1' | |
| 6772 | // :167:25: error: use of undefined value here causes illegal behavior | |
| 6773 | // :167:25: note: when computing vector element at index '1' | |
| 6774 | // :167:25: error: use of undefined value here causes illegal behavior | |
| 6775 | // :167:25: note: when computing vector element at index '1' | |
| 6793 | 6776 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6777 | // :167:25: note: when computing vector element at index '1' | |
| 6794 | 6778 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6779 | // :167:25: note: when computing vector element at index '1' | |
| 6795 | 6780 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6781 | // :167:25: note: when computing vector element at index '1' | |
| 6796 | 6782 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6783 | // :167:25: note: when computing vector element at index '1' | |
| 6797 | 6784 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6785 | // :167:25: note: when computing vector element at index '1' | |
| 6798 | 6786 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6799 | 6787 | // :167:25: note: when computing vector element at index '1' |
| 6800 | 6788 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6804,19 +6792,25 @@ const std = @import("std"); |
| 6804 | 6792 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6805 | 6793 | // :167:25: note: when computing vector element at index '1' |
| 6806 | 6794 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6807 | // :167:25: note: when computing vector element at index '0' | |
| 6795 | // :167:25: note: when computing vector element at index '1' | |
| 6808 | 6796 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6809 | // :167:25: note: when computing vector element at index '0' | |
| 6797 | // :167:25: note: when computing vector element at index '1' | |
| 6810 | 6798 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6811 | // :167:25: note: when computing vector element at index '0' | |
| 6799 | // :167:25: note: when computing vector element at index '1' | |
| 6812 | 6800 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6813 | // :167:25: note: when computing vector element at index '0' | |
| 6801 | // :167:25: note: when computing vector element at index '1' | |
| 6814 | 6802 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6803 | // :167:25: note: when computing vector element at index '1' | |
| 6815 | 6804 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6805 | // :167:25: note: when computing vector element at index '1' | |
| 6816 | 6806 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6807 | // :167:25: note: when computing vector element at index '1' | |
| 6817 | 6808 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6809 | // :167:25: note: when computing vector element at index '1' | |
| 6818 | 6810 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6811 | // :167:25: note: when computing vector element at index '1' | |
| 6819 | 6812 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6813 | // :167:25: note: when computing vector element at index '1' | |
| 6820 | 6814 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6821 | 6815 | // :167:25: note: when computing vector element at index '1' |
| 6822 | 6816 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6826,19 +6820,25 @@ const std = @import("std"); |
| 6826 | 6820 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6827 | 6821 | // :167:25: note: when computing vector element at index '1' |
| 6828 | 6822 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6829 | // :167:25: note: when computing vector element at index '0' | |
| 6823 | // :167:25: note: when computing vector element at index '1' | |
| 6830 | 6824 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6831 | // :167:25: note: when computing vector element at index '0' | |
| 6825 | // :167:25: note: when computing vector element at index '1' | |
| 6832 | 6826 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6833 | // :167:25: note: when computing vector element at index '0' | |
| 6827 | // :167:25: note: when computing vector element at index '1' | |
| 6834 | 6828 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6835 | // :167:25: note: when computing vector element at index '0' | |
| 6829 | // :167:25: note: when computing vector element at index '1' | |
| 6836 | 6830 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6831 | // :167:25: note: when computing vector element at index '1' | |
| 6837 | 6832 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6833 | // :167:25: note: when computing vector element at index '1' | |
| 6838 | 6834 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6835 | // :167:25: note: when computing vector element at index '1' | |
| 6839 | 6836 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6837 | // :167:25: note: when computing vector element at index '1' | |
| 6840 | 6838 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6839 | // :167:25: note: when computing vector element at index '1' | |
| 6841 | 6840 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6841 | // :167:25: note: when computing vector element at index '1' | |
| 6842 | 6842 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6843 | 6843 | // :167:25: note: when computing vector element at index '1' |
| 6844 | 6844 | // :167:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6848,13 +6848,13 @@ const std = @import("std"); |
| 6848 | 6848 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6849 | 6849 | // :167:25: note: when computing vector element at index '1' |
| 6850 | 6850 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6851 | // :167:25: note: when computing vector element at index '0' | |
| 6851 | // :167:25: note: when computing vector element at index '1' | |
| 6852 | 6852 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6853 | // :167:25: note: when computing vector element at index '0' | |
| 6853 | // :167:25: note: when computing vector element at index '1' | |
| 6854 | 6854 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6855 | // :167:25: note: when computing vector element at index '0' | |
| 6855 | // :167:25: note: when computing vector element at index '1' | |
| 6856 | 6856 | // :167:25: error: use of undefined value here causes illegal behavior |
| 6857 | // :167:25: note: when computing vector element at index '0' | |
| 6857 | // :167:25: note: when computing vector element at index '1' | |
| 6858 | 6858 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6859 | 6859 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6860 | 6860 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6862,21 +6862,13 @@ const std = @import("std"); |
| 6862 | 6862 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6863 | 6863 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6864 | 6864 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6865 | // :171:25: note: when computing vector element at index '1' | |
| 6866 | 6865 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6867 | // :171:25: note: when computing vector element at index '1' | |
| 6868 | 6866 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6869 | // :171:25: note: when computing vector element at index '1' | |
| 6870 | 6867 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6871 | // :171:25: note: when computing vector element at index '1' | |
| 6872 | 6868 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6873 | // :171:25: note: when computing vector element at index '0' | |
| 6874 | 6869 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6875 | // :171:25: note: when computing vector element at index '0' | |
| 6876 | 6870 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6877 | // :171:25: note: when computing vector element at index '0' | |
| 6878 | 6871 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6879 | // :171:25: note: when computing vector element at index '0' | |
| 6880 | 6872 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6881 | 6873 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6882 | 6874 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6884,21 +6876,13 @@ const std = @import("std"); |
| 6884 | 6876 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6885 | 6877 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6886 | 6878 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6887 | // :171:25: note: when computing vector element at index '1' | |
| 6888 | 6879 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6889 | // :171:25: note: when computing vector element at index '1' | |
| 6890 | 6880 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6891 | // :171:25: note: when computing vector element at index '1' | |
| 6892 | 6881 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6893 | // :171:25: note: when computing vector element at index '1' | |
| 6894 | 6882 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6895 | // :171:25: note: when computing vector element at index '0' | |
| 6896 | 6883 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6897 | // :171:25: note: when computing vector element at index '0' | |
| 6898 | 6884 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6899 | // :171:25: note: when computing vector element at index '0' | |
| 6900 | 6885 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6901 | // :171:25: note: when computing vector element at index '0' | |
| 6902 | 6886 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6903 | 6887 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6904 | 6888 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6906,21 +6890,13 @@ const std = @import("std"); |
| 6906 | 6890 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6907 | 6891 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6908 | 6892 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6909 | // :171:25: note: when computing vector element at index '1' | |
| 6910 | 6893 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6911 | // :171:25: note: when computing vector element at index '1' | |
| 6912 | 6894 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6913 | // :171:25: note: when computing vector element at index '1' | |
| 6914 | 6895 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6915 | // :171:25: note: when computing vector element at index '1' | |
| 6916 | 6896 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6917 | // :171:25: note: when computing vector element at index '0' | |
| 6918 | 6897 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6919 | // :171:25: note: when computing vector element at index '0' | |
| 6920 | 6898 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6921 | // :171:25: note: when computing vector element at index '0' | |
| 6922 | 6899 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6923 | // :171:25: note: when computing vector element at index '0' | |
| 6924 | 6900 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6925 | 6901 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6926 | 6902 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6928,21 +6904,13 @@ const std = @import("std"); |
| 6928 | 6904 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6929 | 6905 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6930 | 6906 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6931 | // :171:25: note: when computing vector element at index '1' | |
| 6932 | 6907 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6933 | // :171:25: note: when computing vector element at index '1' | |
| 6934 | 6908 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6935 | // :171:25: note: when computing vector element at index '1' | |
| 6936 | 6909 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6937 | // :171:25: note: when computing vector element at index '1' | |
| 6938 | 6910 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6939 | // :171:25: note: when computing vector element at index '0' | |
| 6940 | 6911 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6941 | // :171:25: note: when computing vector element at index '0' | |
| 6942 | 6912 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6943 | // :171:25: note: when computing vector element at index '0' | |
| 6944 | 6913 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6945 | // :171:25: note: when computing vector element at index '0' | |
| 6946 | 6914 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6947 | 6915 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6948 | 6916 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6950,13 +6918,9 @@ const std = @import("std"); |
| 6950 | 6918 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6951 | 6919 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6952 | 6920 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6953 | // :171:25: note: when computing vector element at index '1' | |
| 6954 | 6921 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6955 | // :171:25: note: when computing vector element at index '1' | |
| 6956 | 6922 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6957 | // :171:25: note: when computing vector element at index '1' | |
| 6958 | 6923 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6959 | // :171:25: note: when computing vector element at index '1' | |
| 6960 | 6924 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6961 | 6925 | // :171:25: note: when computing vector element at index '0' |
| 6962 | 6926 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6966,19 +6930,21 @@ const std = @import("std"); |
| 6966 | 6930 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6967 | 6931 | // :171:25: note: when computing vector element at index '0' |
| 6968 | 6932 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6933 | // :171:25: note: when computing vector element at index '0' | |
| 6969 | 6934 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6935 | // :171:25: note: when computing vector element at index '0' | |
| 6970 | 6936 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6937 | // :171:25: note: when computing vector element at index '0' | |
| 6971 | 6938 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6939 | // :171:25: note: when computing vector element at index '0' | |
| 6972 | 6940 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6941 | // :171:25: note: when computing vector element at index '0' | |
| 6973 | 6942 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6943 | // :171:25: note: when computing vector element at index '0' | |
| 6974 | 6944 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6975 | // :171:25: note: when computing vector element at index '1' | |
| 6976 | // :171:25: error: use of undefined value here causes illegal behavior | |
| 6977 | // :171:25: note: when computing vector element at index '1' | |
| 6978 | // :171:25: error: use of undefined value here causes illegal behavior | |
| 6979 | // :171:25: note: when computing vector element at index '1' | |
| 6945 | // :171:25: note: when computing vector element at index '0' | |
| 6980 | 6946 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6981 | // :171:25: note: when computing vector element at index '1' | |
| 6947 | // :171:25: note: when computing vector element at index '0' | |
| 6982 | 6948 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6983 | 6949 | // :171:25: note: when computing vector element at index '0' |
| 6984 | 6950 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -6988,19 +6954,25 @@ const std = @import("std"); |
| 6988 | 6954 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6989 | 6955 | // :171:25: note: when computing vector element at index '0' |
| 6990 | 6956 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6957 | // :171:25: note: when computing vector element at index '0' | |
| 6991 | 6958 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6959 | // :171:25: note: when computing vector element at index '0' | |
| 6992 | 6960 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6961 | // :171:25: note: when computing vector element at index '0' | |
| 6993 | 6962 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6963 | // :171:25: note: when computing vector element at index '0' | |
| 6994 | 6964 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6965 | // :171:25: note: when computing vector element at index '0' | |
| 6995 | 6966 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6967 | // :171:25: note: when computing vector element at index '0' | |
| 6996 | 6968 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6997 | // :171:25: note: when computing vector element at index '1' | |
| 6969 | // :171:25: note: when computing vector element at index '0' | |
| 6998 | 6970 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6999 | // :171:25: note: when computing vector element at index '1' | |
| 6971 | // :171:25: note: when computing vector element at index '0' | |
| 7000 | 6972 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7001 | // :171:25: note: when computing vector element at index '1' | |
| 6973 | // :171:25: note: when computing vector element at index '0' | |
| 7002 | 6974 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7003 | // :171:25: note: when computing vector element at index '1' | |
| 6975 | // :171:25: note: when computing vector element at index '0' | |
| 7004 | 6976 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7005 | 6977 | // :171:25: note: when computing vector element at index '0' |
| 7006 | 6978 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7010,19 +6982,25 @@ const std = @import("std"); |
| 7010 | 6982 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7011 | 6983 | // :171:25: note: when computing vector element at index '0' |
| 7012 | 6984 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6985 | // :171:25: note: when computing vector element at index '0' | |
| 7013 | 6986 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6987 | // :171:25: note: when computing vector element at index '0' | |
| 7014 | 6988 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6989 | // :171:25: note: when computing vector element at index '0' | |
| 7015 | 6990 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6991 | // :171:25: note: when computing vector element at index '0' | |
| 7016 | 6992 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6993 | // :171:25: note: when computing vector element at index '0' | |
| 7017 | 6994 | // :171:25: error: use of undefined value here causes illegal behavior |
| 6995 | // :171:25: note: when computing vector element at index '0' | |
| 7018 | 6996 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7019 | // :171:25: note: when computing vector element at index '1' | |
| 6997 | // :171:25: note: when computing vector element at index '0' | |
| 7020 | 6998 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7021 | // :171:25: note: when computing vector element at index '1' | |
| 6999 | // :171:25: note: when computing vector element at index '0' | |
| 7022 | 7000 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7023 | // :171:25: note: when computing vector element at index '1' | |
| 7001 | // :171:25: note: when computing vector element at index '0' | |
| 7024 | 7002 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7025 | // :171:25: note: when computing vector element at index '1' | |
| 7003 | // :171:25: note: when computing vector element at index '0' | |
| 7026 | 7004 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7027 | 7005 | // :171:25: note: when computing vector element at index '0' |
| 7028 | 7006 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7032,11 +7010,17 @@ const std = @import("std"); |
| 7032 | 7010 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7033 | 7011 | // :171:25: note: when computing vector element at index '0' |
| 7034 | 7012 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7013 | // :171:25: note: when computing vector element at index '1' | |
| 7035 | 7014 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7015 | // :171:25: note: when computing vector element at index '1' | |
| 7036 | 7016 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7017 | // :171:25: note: when computing vector element at index '1' | |
| 7037 | 7018 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7019 | // :171:25: note: when computing vector element at index '1' | |
| 7038 | 7020 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7021 | // :171:25: note: when computing vector element at index '1' | |
| 7039 | 7022 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7023 | // :171:25: note: when computing vector element at index '1' | |
| 7040 | 7024 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7041 | 7025 | // :171:25: note: when computing vector element at index '1' |
| 7042 | 7026 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7046,19 +7030,25 @@ const std = @import("std"); |
| 7046 | 7030 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7047 | 7031 | // :171:25: note: when computing vector element at index '1' |
| 7048 | 7032 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7049 | // :171:25: note: when computing vector element at index '0' | |
| 7033 | // :171:25: note: when computing vector element at index '1' | |
| 7050 | 7034 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7051 | // :171:25: note: when computing vector element at index '0' | |
| 7035 | // :171:25: note: when computing vector element at index '1' | |
| 7052 | 7036 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7053 | // :171:25: note: when computing vector element at index '0' | |
| 7037 | // :171:25: note: when computing vector element at index '1' | |
| 7054 | 7038 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7055 | // :171:25: note: when computing vector element at index '0' | |
| 7039 | // :171:25: note: when computing vector element at index '1' | |
| 7056 | 7040 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7041 | // :171:25: note: when computing vector element at index '1' | |
| 7057 | 7042 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7043 | // :171:25: note: when computing vector element at index '1' | |
| 7058 | 7044 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7045 | // :171:25: note: when computing vector element at index '1' | |
| 7059 | 7046 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7047 | // :171:25: note: when computing vector element at index '1' | |
| 7060 | 7048 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7049 | // :171:25: note: when computing vector element at index '1' | |
| 7061 | 7050 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7051 | // :171:25: note: when computing vector element at index '1' | |
| 7062 | 7052 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7063 | 7053 | // :171:25: note: when computing vector element at index '1' |
| 7064 | 7054 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7068,19 +7058,25 @@ const std = @import("std"); |
| 7068 | 7058 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7069 | 7059 | // :171:25: note: when computing vector element at index '1' |
| 7070 | 7060 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7071 | // :171:25: note: when computing vector element at index '0' | |
| 7061 | // :171:25: note: when computing vector element at index '1' | |
| 7072 | 7062 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7073 | // :171:25: note: when computing vector element at index '0' | |
| 7063 | // :171:25: note: when computing vector element at index '1' | |
| 7074 | 7064 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7075 | // :171:25: note: when computing vector element at index '0' | |
| 7065 | // :171:25: note: when computing vector element at index '1' | |
| 7076 | 7066 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7077 | // :171:25: note: when computing vector element at index '0' | |
| 7067 | // :171:25: note: when computing vector element at index '1' | |
| 7078 | 7068 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7069 | // :171:25: note: when computing vector element at index '1' | |
| 7079 | 7070 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7071 | // :171:25: note: when computing vector element at index '1' | |
| 7080 | 7072 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7073 | // :171:25: note: when computing vector element at index '1' | |
| 7081 | 7074 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7075 | // :171:25: note: when computing vector element at index '1' | |
| 7082 | 7076 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7077 | // :171:25: note: when computing vector element at index '1' | |
| 7083 | 7078 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7079 | // :171:25: note: when computing vector element at index '1' | |
| 7084 | 7080 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7085 | 7081 | // :171:25: note: when computing vector element at index '1' |
| 7086 | 7082 | // :171:25: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7090,37 +7086,33 @@ const std = @import("std"); |
| 7090 | 7086 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7091 | 7087 | // :171:25: note: when computing vector element at index '1' |
| 7092 | 7088 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7093 | // :171:25: note: when computing vector element at index '0' | |
| 7089 | // :171:25: note: when computing vector element at index '1' | |
| 7094 | 7090 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7095 | // :171:25: note: when computing vector element at index '0' | |
| 7091 | // :171:25: note: when computing vector element at index '1' | |
| 7096 | 7092 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7097 | // :171:25: note: when computing vector element at index '0' | |
| 7093 | // :171:25: note: when computing vector element at index '1' | |
| 7098 | 7094 | // :171:25: error: use of undefined value here causes illegal behavior |
| 7099 | // :171:25: note: when computing vector element at index '0' | |
| 7095 | // :171:25: note: when computing vector element at index '1' | |
| 7096 | // :171:25: error: use of undefined value here causes illegal behavior | |
| 7097 | // :171:25: note: when computing vector element at index '1' | |
| 7098 | // :171:25: error: use of undefined value here causes illegal behavior | |
| 7099 | // :171:25: note: when computing vector element at index '1' | |
| 7100 | 7100 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7101 | 7101 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7102 | 7102 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7103 | // :177:17: note: when computing vector element at index '0' | |
| 7104 | 7103 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7105 | // :177:17: note: when computing vector element at index '0' | |
| 7106 | 7104 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7107 | // :177:17: note: when computing vector element at index '0' | |
| 7108 | 7105 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7109 | // :177:17: note: when computing vector element at index '0' | |
| 7110 | 7106 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7111 | // :177:17: note: when computing vector element at index '1' | |
| 7112 | 7107 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7113 | // :177:17: note: when computing vector element at index '1' | |
| 7114 | 7108 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7115 | // :177:17: note: when computing vector element at index '0' | |
| 7116 | 7109 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7117 | // :177:17: note: when computing vector element at index '0' | |
| 7118 | 7110 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7119 | // :177:17: note: when computing vector element at index '0' | |
| 7120 | 7111 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7121 | // :177:17: note: when computing vector element at index '0' | |
| 7122 | 7112 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7113 | // :177:17: note: when computing vector element at index '0' | |
| 7123 | 7114 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7115 | // :177:17: note: when computing vector element at index '0' | |
| 7124 | 7116 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7125 | 7117 | // :177:17: note: when computing vector element at index '0' |
| 7126 | 7118 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7130,9 +7122,9 @@ const std = @import("std"); |
| 7130 | 7122 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7131 | 7123 | // :177:17: note: when computing vector element at index '0' |
| 7132 | 7124 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7133 | // :177:17: note: when computing vector element at index '1' | |
| 7125 | // :177:17: note: when computing vector element at index '0' | |
| 7134 | 7126 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7135 | // :177:17: note: when computing vector element at index '1' | |
| 7127 | // :177:17: note: when computing vector element at index '0' | |
| 7136 | 7128 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7137 | 7129 | // :177:17: note: when computing vector element at index '0' |
| 7138 | 7130 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7142,7 +7134,9 @@ const std = @import("std"); |
| 7142 | 7134 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7143 | 7135 | // :177:17: note: when computing vector element at index '0' |
| 7144 | 7136 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7137 | // :177:17: note: when computing vector element at index '0' | |
| 7145 | 7138 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7139 | // :177:17: note: when computing vector element at index '0' | |
| 7146 | 7140 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7147 | 7141 | // :177:17: note: when computing vector element at index '0' |
| 7148 | 7142 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7152,9 +7146,9 @@ const std = @import("std"); |
| 7152 | 7146 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7153 | 7147 | // :177:17: note: when computing vector element at index '0' |
| 7154 | 7148 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7155 | // :177:17: note: when computing vector element at index '1' | |
| 7149 | // :177:17: note: when computing vector element at index '0' | |
| 7156 | 7150 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7157 | // :177:17: note: when computing vector element at index '1' | |
| 7151 | // :177:17: note: when computing vector element at index '0' | |
| 7158 | 7152 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7159 | 7153 | // :177:17: note: when computing vector element at index '0' |
| 7160 | 7154 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7164,7 +7158,9 @@ const std = @import("std"); |
| 7164 | 7158 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7165 | 7159 | // :177:17: note: when computing vector element at index '0' |
| 7166 | 7160 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7161 | // :177:17: note: when computing vector element at index '0' | |
| 7167 | 7162 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7163 | // :177:17: note: when computing vector element at index '0' | |
| 7168 | 7164 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7169 | 7165 | // :177:17: note: when computing vector element at index '0' |
| 7170 | 7166 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7174,9 +7170,9 @@ const std = @import("std"); |
| 7174 | 7170 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7175 | 7171 | // :177:17: note: when computing vector element at index '0' |
| 7176 | 7172 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7177 | // :177:17: note: when computing vector element at index '1' | |
| 7173 | // :177:17: note: when computing vector element at index '0' | |
| 7178 | 7174 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7179 | // :177:17: note: when computing vector element at index '1' | |
| 7175 | // :177:17: note: when computing vector element at index '0' | |
| 7180 | 7176 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7181 | 7177 | // :177:17: note: when computing vector element at index '0' |
| 7182 | 7178 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7186,7 +7182,9 @@ const std = @import("std"); |
| 7186 | 7182 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7187 | 7183 | // :177:17: note: when computing vector element at index '0' |
| 7188 | 7184 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7185 | // :177:17: note: when computing vector element at index '0' | |
| 7189 | 7186 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7187 | // :177:17: note: when computing vector element at index '0' | |
| 7190 | 7188 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7191 | 7189 | // :177:17: note: when computing vector element at index '0' |
| 7192 | 7190 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7196,9 +7194,9 @@ const std = @import("std"); |
| 7196 | 7194 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7197 | 7195 | // :177:17: note: when computing vector element at index '0' |
| 7198 | 7196 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7199 | // :177:17: note: when computing vector element at index '1' | |
| 7197 | // :177:17: note: when computing vector element at index '0' | |
| 7200 | 7198 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7201 | // :177:17: note: when computing vector element at index '1' | |
| 7199 | // :177:17: note: when computing vector element at index '0' | |
| 7202 | 7200 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7203 | 7201 | // :177:17: note: when computing vector element at index '0' |
| 7204 | 7202 | // :177:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7208,27 +7206,29 @@ const std = @import("std"); |
| 7208 | 7206 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7209 | 7207 | // :177:17: note: when computing vector element at index '0' |
| 7210 | 7208 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7209 | // :177:17: note: when computing vector element at index '1' | |
| 7211 | 7210 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7211 | // :177:17: note: when computing vector element at index '1' | |
| 7212 | 7212 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7213 | // :177:17: note: when computing vector element at index '0' | |
| 7213 | // :177:17: note: when computing vector element at index '1' | |
| 7214 | 7214 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7215 | // :177:17: note: when computing vector element at index '0' | |
| 7215 | // :177:17: note: when computing vector element at index '1' | |
| 7216 | 7216 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7217 | // :177:17: note: when computing vector element at index '0' | |
| 7217 | // :177:17: note: when computing vector element at index '1' | |
| 7218 | 7218 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7219 | // :177:17: note: when computing vector element at index '0' | |
| 7219 | // :177:17: note: when computing vector element at index '1' | |
| 7220 | 7220 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7221 | 7221 | // :177:17: note: when computing vector element at index '1' |
| 7222 | 7222 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7223 | 7223 | // :177:17: note: when computing vector element at index '1' |
| 7224 | 7224 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7225 | // :177:17: note: when computing vector element at index '0' | |
| 7225 | // :177:17: note: when computing vector element at index '1' | |
| 7226 | 7226 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7227 | // :177:17: note: when computing vector element at index '0' | |
| 7227 | // :177:17: note: when computing vector element at index '1' | |
| 7228 | 7228 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7229 | // :177:17: note: when computing vector element at index '0' | |
| 7229 | // :177:17: note: when computing vector element at index '1' | |
| 7230 | 7230 | // :177:17: error: use of undefined value here causes illegal behavior |
| 7231 | // :177:17: note: when computing vector element at index '0' | |
| 7231 | // :177:17: note: when computing vector element at index '1' | |
| 7232 | 7232 | // :177:21: error: use of undefined value here causes illegal behavior |
| 7233 | 7233 | // :177:21: note: when computing vector element at index '0' |
| 7234 | 7234 | // :177:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7256,27 +7256,19 @@ const std = @import("std"); |
| 7256 | 7256 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7257 | 7257 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7258 | 7258 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7259 | // :180:17: note: when computing vector element at index '0' | |
| 7260 | 7259 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7261 | // :180:17: note: when computing vector element at index '0' | |
| 7262 | 7260 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7263 | // :180:17: note: when computing vector element at index '0' | |
| 7264 | 7261 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7265 | // :180:17: note: when computing vector element at index '0' | |
| 7266 | 7262 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7267 | // :180:17: note: when computing vector element at index '1' | |
| 7268 | 7263 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7269 | // :180:17: note: when computing vector element at index '1' | |
| 7270 | 7264 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7271 | // :180:17: note: when computing vector element at index '0' | |
| 7272 | 7265 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7273 | // :180:17: note: when computing vector element at index '0' | |
| 7274 | 7266 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7275 | // :180:17: note: when computing vector element at index '0' | |
| 7276 | 7267 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7277 | // :180:17: note: when computing vector element at index '0' | |
| 7278 | 7268 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7269 | // :180:17: note: when computing vector element at index '0' | |
| 7279 | 7270 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7271 | // :180:17: note: when computing vector element at index '0' | |
| 7280 | 7272 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7281 | 7273 | // :180:17: note: when computing vector element at index '0' |
| 7282 | 7274 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7286,9 +7278,9 @@ const std = @import("std"); |
| 7286 | 7278 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7287 | 7279 | // :180:17: note: when computing vector element at index '0' |
| 7288 | 7280 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7289 | // :180:17: note: when computing vector element at index '1' | |
| 7281 | // :180:17: note: when computing vector element at index '0' | |
| 7290 | 7282 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7291 | // :180:17: note: when computing vector element at index '1' | |
| 7283 | // :180:17: note: when computing vector element at index '0' | |
| 7292 | 7284 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7293 | 7285 | // :180:17: note: when computing vector element at index '0' |
| 7294 | 7286 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7298,7 +7290,9 @@ const std = @import("std"); |
| 7298 | 7290 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7299 | 7291 | // :180:17: note: when computing vector element at index '0' |
| 7300 | 7292 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7293 | // :180:17: note: when computing vector element at index '0' | |
| 7301 | 7294 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7295 | // :180:17: note: when computing vector element at index '0' | |
| 7302 | 7296 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7303 | 7297 | // :180:17: note: when computing vector element at index '0' |
| 7304 | 7298 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7308,9 +7302,9 @@ const std = @import("std"); |
| 7308 | 7302 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7309 | 7303 | // :180:17: note: when computing vector element at index '0' |
| 7310 | 7304 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7311 | // :180:17: note: when computing vector element at index '1' | |
| 7305 | // :180:17: note: when computing vector element at index '0' | |
| 7312 | 7306 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7313 | // :180:17: note: when computing vector element at index '1' | |
| 7307 | // :180:17: note: when computing vector element at index '0' | |
| 7314 | 7308 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7315 | 7309 | // :180:17: note: when computing vector element at index '0' |
| 7316 | 7310 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7320,7 +7314,9 @@ const std = @import("std"); |
| 7320 | 7314 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7321 | 7315 | // :180:17: note: when computing vector element at index '0' |
| 7322 | 7316 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7317 | // :180:17: note: when computing vector element at index '0' | |
| 7323 | 7318 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7319 | // :180:17: note: when computing vector element at index '0' | |
| 7324 | 7320 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7325 | 7321 | // :180:17: note: when computing vector element at index '0' |
| 7326 | 7322 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7330,9 +7326,9 @@ const std = @import("std"); |
| 7330 | 7326 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7331 | 7327 | // :180:17: note: when computing vector element at index '0' |
| 7332 | 7328 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7333 | // :180:17: note: when computing vector element at index '1' | |
| 7329 | // :180:17: note: when computing vector element at index '0' | |
| 7334 | 7330 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7335 | // :180:17: note: when computing vector element at index '1' | |
| 7331 | // :180:17: note: when computing vector element at index '0' | |
| 7336 | 7332 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7337 | 7333 | // :180:17: note: when computing vector element at index '0' |
| 7338 | 7334 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7342,7 +7338,9 @@ const std = @import("std"); |
| 7342 | 7338 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7343 | 7339 | // :180:17: note: when computing vector element at index '0' |
| 7344 | 7340 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7341 | // :180:17: note: when computing vector element at index '0' | |
| 7345 | 7342 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7343 | // :180:17: note: when computing vector element at index '0' | |
| 7346 | 7344 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7347 | 7345 | // :180:17: note: when computing vector element at index '0' |
| 7348 | 7346 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7352,9 +7350,9 @@ const std = @import("std"); |
| 7352 | 7350 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7353 | 7351 | // :180:17: note: when computing vector element at index '0' |
| 7354 | 7352 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7355 | // :180:17: note: when computing vector element at index '1' | |
| 7353 | // :180:17: note: when computing vector element at index '0' | |
| 7356 | 7354 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7357 | // :180:17: note: when computing vector element at index '1' | |
| 7355 | // :180:17: note: when computing vector element at index '0' | |
| 7358 | 7356 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7359 | 7357 | // :180:17: note: when computing vector element at index '0' |
| 7360 | 7358 | // :180:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7364,27 +7362,29 @@ const std = @import("std"); |
| 7364 | 7362 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7365 | 7363 | // :180:17: note: when computing vector element at index '0' |
| 7366 | 7364 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7365 | // :180:17: note: when computing vector element at index '1' | |
| 7367 | 7366 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7367 | // :180:17: note: when computing vector element at index '1' | |
| 7368 | 7368 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7369 | // :180:17: note: when computing vector element at index '0' | |
| 7369 | // :180:17: note: when computing vector element at index '1' | |
| 7370 | 7370 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7371 | // :180:17: note: when computing vector element at index '0' | |
| 7371 | // :180:17: note: when computing vector element at index '1' | |
| 7372 | 7372 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7373 | // :180:17: note: when computing vector element at index '0' | |
| 7373 | // :180:17: note: when computing vector element at index '1' | |
| 7374 | 7374 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7375 | // :180:17: note: when computing vector element at index '0' | |
| 7375 | // :180:17: note: when computing vector element at index '1' | |
| 7376 | 7376 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7377 | 7377 | // :180:17: note: when computing vector element at index '1' |
| 7378 | 7378 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7379 | 7379 | // :180:17: note: when computing vector element at index '1' |
| 7380 | 7380 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7381 | // :180:17: note: when computing vector element at index '0' | |
| 7381 | // :180:17: note: when computing vector element at index '1' | |
| 7382 | 7382 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7383 | // :180:17: note: when computing vector element at index '0' | |
| 7383 | // :180:17: note: when computing vector element at index '1' | |
| 7384 | 7384 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7385 | // :180:17: note: when computing vector element at index '0' | |
| 7385 | // :180:17: note: when computing vector element at index '1' | |
| 7386 | 7386 | // :180:17: error: use of undefined value here causes illegal behavior |
| 7387 | // :180:17: note: when computing vector element at index '0' | |
| 7387 | // :180:17: note: when computing vector element at index '1' | |
| 7388 | 7388 | // :180:21: error: use of undefined value here causes illegal behavior |
| 7389 | 7389 | // :180:21: note: when computing vector element at index '0' |
| 7390 | 7390 | // :180:21: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7412,27 +7412,19 @@ const std = @import("std"); |
| 7412 | 7412 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7413 | 7413 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7414 | 7414 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7415 | // :183:17: note: when computing vector element at index '0' | |
| 7416 | 7415 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7417 | // :183:17: note: when computing vector element at index '0' | |
| 7418 | 7416 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7419 | // :183:17: note: when computing vector element at index '0' | |
| 7420 | 7417 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7421 | // :183:17: note: when computing vector element at index '0' | |
| 7422 | 7418 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7423 | // :183:17: note: when computing vector element at index '1' | |
| 7424 | 7419 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7425 | // :183:17: note: when computing vector element at index '1' | |
| 7426 | 7420 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7427 | // :183:17: note: when computing vector element at index '0' | |
| 7428 | 7421 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7429 | // :183:17: note: when computing vector element at index '0' | |
| 7430 | 7422 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7431 | // :183:17: note: when computing vector element at index '0' | |
| 7432 | 7423 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7433 | // :183:17: note: when computing vector element at index '0' | |
| 7434 | 7424 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7425 | // :183:17: note: when computing vector element at index '0' | |
| 7435 | 7426 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7427 | // :183:17: note: when computing vector element at index '0' | |
| 7436 | 7428 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7437 | 7429 | // :183:17: note: when computing vector element at index '0' |
| 7438 | 7430 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7442,9 +7434,9 @@ const std = @import("std"); |
| 7442 | 7434 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7443 | 7435 | // :183:17: note: when computing vector element at index '0' |
| 7444 | 7436 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7445 | // :183:17: note: when computing vector element at index '1' | |
| 7437 | // :183:17: note: when computing vector element at index '0' | |
| 7446 | 7438 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7447 | // :183:17: note: when computing vector element at index '1' | |
| 7439 | // :183:17: note: when computing vector element at index '0' | |
| 7448 | 7440 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7449 | 7441 | // :183:17: note: when computing vector element at index '0' |
| 7450 | 7442 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7454,7 +7446,9 @@ const std = @import("std"); |
| 7454 | 7446 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7455 | 7447 | // :183:17: note: when computing vector element at index '0' |
| 7456 | 7448 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7449 | // :183:17: note: when computing vector element at index '0' | |
| 7457 | 7450 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7451 | // :183:17: note: when computing vector element at index '0' | |
| 7458 | 7452 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7459 | 7453 | // :183:17: note: when computing vector element at index '0' |
| 7460 | 7454 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7464,9 +7458,9 @@ const std = @import("std"); |
| 7464 | 7458 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7465 | 7459 | // :183:17: note: when computing vector element at index '0' |
| 7466 | 7460 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7467 | // :183:17: note: when computing vector element at index '1' | |
| 7461 | // :183:17: note: when computing vector element at index '0' | |
| 7468 | 7462 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7469 | // :183:17: note: when computing vector element at index '1' | |
| 7463 | // :183:17: note: when computing vector element at index '0' | |
| 7470 | 7464 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7471 | 7465 | // :183:17: note: when computing vector element at index '0' |
| 7472 | 7466 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7476,7 +7470,9 @@ const std = @import("std"); |
| 7476 | 7470 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7477 | 7471 | // :183:17: note: when computing vector element at index '0' |
| 7478 | 7472 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7473 | // :183:17: note: when computing vector element at index '0' | |
| 7479 | 7474 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7475 | // :183:17: note: when computing vector element at index '0' | |
| 7480 | 7476 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7481 | 7477 | // :183:17: note: when computing vector element at index '0' |
| 7482 | 7478 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7486,9 +7482,9 @@ const std = @import("std"); |
| 7486 | 7482 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7487 | 7483 | // :183:17: note: when computing vector element at index '0' |
| 7488 | 7484 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7489 | // :183:17: note: when computing vector element at index '1' | |
| 7485 | // :183:17: note: when computing vector element at index '0' | |
| 7490 | 7486 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7491 | // :183:17: note: when computing vector element at index '1' | |
| 7487 | // :183:17: note: when computing vector element at index '0' | |
| 7492 | 7488 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7493 | 7489 | // :183:17: note: when computing vector element at index '0' |
| 7494 | 7490 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7498,7 +7494,9 @@ const std = @import("std"); |
| 7498 | 7494 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7499 | 7495 | // :183:17: note: when computing vector element at index '0' |
| 7500 | 7496 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7497 | // :183:17: note: when computing vector element at index '0' | |
| 7501 | 7498 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7499 | // :183:17: note: when computing vector element at index '0' | |
| 7502 | 7500 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7503 | 7501 | // :183:17: note: when computing vector element at index '0' |
| 7504 | 7502 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7508,9 +7506,9 @@ const std = @import("std"); |
| 7508 | 7506 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7509 | 7507 | // :183:17: note: when computing vector element at index '0' |
| 7510 | 7508 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7511 | // :183:17: note: when computing vector element at index '1' | |
| 7509 | // :183:17: note: when computing vector element at index '0' | |
| 7512 | 7510 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7513 | // :183:17: note: when computing vector element at index '1' | |
| 7511 | // :183:17: note: when computing vector element at index '0' | |
| 7514 | 7512 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7515 | 7513 | // :183:17: note: when computing vector element at index '0' |
| 7516 | 7514 | // :183:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -7520,27 +7518,29 @@ const std = @import("std"); |
| 7520 | 7518 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7521 | 7519 | // :183:17: note: when computing vector element at index '0' |
| 7522 | 7520 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7521 | // :183:17: note: when computing vector element at index '1' | |
| 7523 | 7522 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7523 | // :183:17: note: when computing vector element at index '1' | |
| 7524 | 7524 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7525 | // :183:17: note: when computing vector element at index '0' | |
| 7525 | // :183:17: note: when computing vector element at index '1' | |
| 7526 | 7526 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7527 | // :183:17: note: when computing vector element at index '0' | |
| 7527 | // :183:17: note: when computing vector element at index '1' | |
| 7528 | 7528 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7529 | // :183:17: note: when computing vector element at index '0' | |
| 7529 | // :183:17: note: when computing vector element at index '1' | |
| 7530 | 7530 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7531 | // :183:17: note: when computing vector element at index '0' | |
| 7531 | // :183:17: note: when computing vector element at index '1' | |
| 7532 | 7532 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7533 | 7533 | // :183:17: note: when computing vector element at index '1' |
| 7534 | 7534 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7535 | 7535 | // :183:17: note: when computing vector element at index '1' |
| 7536 | 7536 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7537 | // :183:17: note: when computing vector element at index '0' | |
| 7537 | // :183:17: note: when computing vector element at index '1' | |
| 7538 | 7538 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7539 | // :183:17: note: when computing vector element at index '0' | |
| 7539 | // :183:17: note: when computing vector element at index '1' | |
| 7540 | 7540 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7541 | // :183:17: note: when computing vector element at index '0' | |
| 7541 | // :183:17: note: when computing vector element at index '1' | |
| 7542 | 7542 | // :183:17: error: use of undefined value here causes illegal behavior |
| 7543 | // :183:17: note: when computing vector element at index '0' | |
| 7543 | // :183:17: note: when computing vector element at index '1' | |
| 7544 | 7544 | // :183:21: error: use of undefined value here causes illegal behavior |
| 7545 | 7545 | // :183:21: note: when computing vector element at index '0' |
| 7546 | 7546 | // :183:21: error: use of undefined value here causes illegal behavior |
test/cases/compile_errors/undef_arith_returns_undef.zig+1794-1794| ... | ... | @@ -681,1800 +681,1360 @@ inline fn testFloatWithValue(comptime Float: type, x: Float) void { |
| 681 | 681 | // @as(@Vector(2, u8), undefined) |
| 682 | 682 | // @as(@Vector(2, u8), [runtime value]) |
| 683 | 683 | // @as(@Vector(2, u8), [runtime value]) |
| 684 | // @as(i8, undefined) | |
| 685 | // @as(i8, undefined) | |
| 686 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 687 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 688 | // @as(@Vector(2, i8), undefined) | |
| 689 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 690 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 691 | // @as(@Vector(2, i8), undefined) | |
| 692 | // @as(@Vector(2, i8), undefined) | |
| 693 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 694 | // @as(@Vector(2, i8), undefined) | |
| 695 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 696 | // @as(@Vector(2, i8), undefined) | |
| 697 | // @as(@Vector(2, i8), undefined) | |
| 698 | // @as(@Vector(2, i8), undefined) | |
| 699 | // @as(@Vector(2, i8), undefined) | |
| 700 | // @as(@Vector(2, i8), undefined) | |
| 701 | // @as(i8, undefined) | |
| 702 | // @as(i8, undefined) | |
| 703 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 704 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 705 | // @as(@Vector(2, i8), undefined) | |
| 706 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 707 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 708 | // @as(@Vector(2, i8), undefined) | |
| 709 | // @as(@Vector(2, i8), undefined) | |
| 710 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 711 | // @as(@Vector(2, i8), undefined) | |
| 712 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 713 | // @as(@Vector(2, i8), undefined) | |
| 714 | // @as(@Vector(2, i8), undefined) | |
| 715 | // @as(@Vector(2, i8), undefined) | |
| 716 | // @as(@Vector(2, i8), undefined) | |
| 717 | // @as(@Vector(2, i8), undefined) | |
| 718 | // @as(i8, undefined) | |
| 719 | // @as(i8, undefined) | |
| 720 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 721 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 722 | // @as(@Vector(2, i8), undefined) | |
| 723 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 724 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 725 | // @as(@Vector(2, i8), undefined) | |
| 726 | // @as(@Vector(2, i8), undefined) | |
| 727 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 728 | // @as(@Vector(2, i8), undefined) | |
| 729 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 730 | // @as(@Vector(2, i8), undefined) | |
| 731 | // @as(@Vector(2, i8), undefined) | |
| 732 | // @as(@Vector(2, i8), undefined) | |
| 733 | // @as(@Vector(2, i8), undefined) | |
| 734 | // @as(@Vector(2, i8), undefined) | |
| 735 | // @as(i8, undefined) | |
| 736 | // @as(i8, undefined) | |
| 737 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 738 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 739 | // @as(@Vector(2, i8), undefined) | |
| 740 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 741 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 742 | // @as(@Vector(2, i8), undefined) | |
| 743 | // @as(@Vector(2, i8), undefined) | |
| 744 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 745 | // @as(@Vector(2, i8), undefined) | |
| 746 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 747 | // @as(@Vector(2, i8), undefined) | |
| 748 | // @as(@Vector(2, i8), undefined) | |
| 749 | // @as(@Vector(2, i8), undefined) | |
| 750 | // @as(@Vector(2, i8), undefined) | |
| 751 | // @as(@Vector(2, i8), undefined) | |
| 752 | // @as(i8, undefined) | |
| 753 | // @as(i8, undefined) | |
| 754 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 755 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 756 | // @as(@Vector(2, i8), undefined) | |
| 757 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 758 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 759 | // @as(@Vector(2, i8), undefined) | |
| 760 | // @as(@Vector(2, i8), undefined) | |
| 761 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 762 | // @as(@Vector(2, i8), undefined) | |
| 763 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 764 | // @as(@Vector(2, i8), undefined) | |
| 765 | // @as(@Vector(2, i8), undefined) | |
| 766 | // @as(@Vector(2, i8), undefined) | |
| 767 | // @as(@Vector(2, i8), undefined) | |
| 768 | // @as(@Vector(2, i8), undefined) | |
| 769 | // @as(i8, undefined) | |
| 770 | // @as(i8, undefined) | |
| 771 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 772 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 773 | // @as(@Vector(2, i8), undefined) | |
| 774 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 775 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 776 | // @as(@Vector(2, i8), undefined) | |
| 777 | // @as(@Vector(2, i8), undefined) | |
| 778 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 779 | // @as(@Vector(2, i8), undefined) | |
| 780 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 781 | // @as(@Vector(2, i8), undefined) | |
| 782 | // @as(@Vector(2, i8), undefined) | |
| 783 | // @as(@Vector(2, i8), undefined) | |
| 784 | // @as(@Vector(2, i8), undefined) | |
| 785 | // @as(@Vector(2, i8), undefined) | |
| 786 | // @as(i8, undefined) | |
| 787 | // @as(i8, undefined) | |
| 788 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 789 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 790 | // @as(@Vector(2, i8), undefined) | |
| 791 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 792 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 793 | // @as(@Vector(2, i8), undefined) | |
| 794 | // @as(@Vector(2, i8), undefined) | |
| 795 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 796 | // @as(@Vector(2, i8), undefined) | |
| 797 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 798 | // @as(@Vector(2, i8), undefined) | |
| 799 | // @as(@Vector(2, i8), undefined) | |
| 800 | // @as(@Vector(2, i8), undefined) | |
| 801 | // @as(@Vector(2, i8), undefined) | |
| 802 | // @as(@Vector(2, i8), undefined) | |
| 803 | // @as(i8, undefined) | |
| 804 | // @as(@Vector(2, i8), undefined) | |
| 805 | // @as(i8, undefined) | |
| 806 | // @as(i8, undefined) | |
| 807 | // @as(@Vector(2, i8), undefined) | |
| 808 | // @as(@Vector(2, i8), undefined) | |
| 809 | // @as(i8, undefined) | |
| 810 | // @as(@Vector(2, i8), undefined) | |
| 811 | // @as(i8, undefined) | |
| 812 | // @as(i8, undefined) | |
| 813 | // @as(@Vector(2, i8), [runtime value]) | |
| 814 | // @as(@Vector(2, i8), [runtime value]) | |
| 815 | // @as(@Vector(2, i8), undefined) | |
| 816 | // @as(@Vector(2, i8), [runtime value]) | |
| 817 | // @as(@Vector(2, i8), [runtime value]) | |
| 818 | // @as(@Vector(2, i8), [runtime value]) | |
| 819 | // @as(@Vector(2, i8), undefined) | |
| 820 | // @as(@Vector(2, i8), [runtime value]) | |
| 821 | // @as(@Vector(2, i8), [runtime value]) | |
| 822 | // @as(@Vector(2, i8), [runtime value]) | |
| 823 | // @as(@Vector(2, i8), undefined) | |
| 824 | // @as(@Vector(2, i8), undefined) | |
| 825 | // @as(@Vector(2, i8), undefined) | |
| 826 | // @as(@Vector(2, i8), undefined) | |
| 827 | // @as(@Vector(2, i8), undefined) | |
| 828 | // @as(i8, undefined) | |
| 829 | // @as(i8, undefined) | |
| 830 | // @as(@Vector(2, i8), [runtime value]) | |
| 831 | // @as(@Vector(2, i8), [runtime value]) | |
| 832 | // @as(@Vector(2, i8), undefined) | |
| 833 | // @as(@Vector(2, i8), [runtime value]) | |
| 834 | // @as(@Vector(2, i8), [runtime value]) | |
| 835 | // @as(@Vector(2, i8), [runtime value]) | |
| 836 | // @as(@Vector(2, i8), undefined) | |
| 837 | // @as(@Vector(2, i8), [runtime value]) | |
| 838 | // @as(@Vector(2, i8), [runtime value]) | |
| 839 | // @as(@Vector(2, i8), [runtime value]) | |
| 840 | // @as(@Vector(2, i8), undefined) | |
| 841 | // @as(@Vector(2, i8), undefined) | |
| 842 | // @as(@Vector(2, i8), undefined) | |
| 843 | // @as(@Vector(2, i8), undefined) | |
| 844 | // @as(@Vector(2, i8), undefined) | |
| 845 | // @as(i8, undefined) | |
| 846 | // @as(i8, undefined) | |
| 847 | // @as(@Vector(2, i8), [runtime value]) | |
| 848 | // @as(@Vector(2, i8), [runtime value]) | |
| 849 | // @as(@Vector(2, i8), undefined) | |
| 850 | // @as(@Vector(2, i8), [runtime value]) | |
| 851 | // @as(@Vector(2, i8), [runtime value]) | |
| 852 | // @as(@Vector(2, i8), [runtime value]) | |
| 853 | // @as(@Vector(2, i8), undefined) | |
| 854 | // @as(@Vector(2, i8), [runtime value]) | |
| 855 | // @as(@Vector(2, i8), [runtime value]) | |
| 856 | // @as(@Vector(2, i8), [runtime value]) | |
| 857 | // @as(@Vector(2, i8), undefined) | |
| 858 | // @as(@Vector(2, i8), undefined) | |
| 859 | // @as(@Vector(2, i8), undefined) | |
| 860 | // @as(@Vector(2, i8), undefined) | |
| 861 | // @as(@Vector(2, i8), undefined) | |
| 862 | // @as(i8, undefined) | |
| 863 | // @as(i8, undefined) | |
| 864 | // @as(@Vector(2, i8), [runtime value]) | |
| 865 | // @as(@Vector(2, i8), [runtime value]) | |
| 866 | // @as(@Vector(2, i8), undefined) | |
| 867 | // @as(@Vector(2, i8), [runtime value]) | |
| 868 | // @as(@Vector(2, i8), [runtime value]) | |
| 869 | // @as(@Vector(2, i8), [runtime value]) | |
| 870 | // @as(@Vector(2, i8), undefined) | |
| 871 | // @as(@Vector(2, i8), [runtime value]) | |
| 872 | // @as(@Vector(2, i8), [runtime value]) | |
| 873 | // @as(@Vector(2, i8), [runtime value]) | |
| 874 | // @as(@Vector(2, i8), undefined) | |
| 875 | // @as(@Vector(2, i8), undefined) | |
| 876 | // @as(@Vector(2, i8), undefined) | |
| 877 | // @as(@Vector(2, i8), undefined) | |
| 878 | // @as(@Vector(2, i8), undefined) | |
| 879 | // @as(i8, undefined) | |
| 880 | // @as(i8, undefined) | |
| 881 | // @as(@Vector(2, i8), [runtime value]) | |
| 882 | // @as(@Vector(2, i8), [runtime value]) | |
| 883 | // @as(@Vector(2, i8), undefined) | |
| 884 | // @as(@Vector(2, i8), [runtime value]) | |
| 885 | // @as(@Vector(2, i8), [runtime value]) | |
| 886 | // @as(@Vector(2, i8), [runtime value]) | |
| 887 | // @as(@Vector(2, i8), undefined) | |
| 888 | // @as(@Vector(2, i8), [runtime value]) | |
| 889 | // @as(@Vector(2, i8), [runtime value]) | |
| 890 | // @as(@Vector(2, i8), [runtime value]) | |
| 891 | // @as(@Vector(2, i8), undefined) | |
| 892 | // @as(@Vector(2, i8), undefined) | |
| 893 | // @as(@Vector(2, i8), undefined) | |
| 894 | // @as(@Vector(2, i8), undefined) | |
| 895 | // @as(@Vector(2, i8), undefined) | |
| 896 | // @as(i8, undefined) | |
| 897 | // @as(i8, undefined) | |
| 898 | // @as(@Vector(2, i8), [runtime value]) | |
| 899 | // @as(@Vector(2, i8), [runtime value]) | |
| 900 | // @as(@Vector(2, i8), undefined) | |
| 901 | // @as(@Vector(2, i8), [runtime value]) | |
| 902 | // @as(@Vector(2, i8), [runtime value]) | |
| 903 | // @as(@Vector(2, i8), [runtime value]) | |
| 904 | // @as(@Vector(2, i8), undefined) | |
| 905 | // @as(@Vector(2, i8), [runtime value]) | |
| 906 | // @as(@Vector(2, i8), [runtime value]) | |
| 907 | // @as(@Vector(2, i8), [runtime value]) | |
| 908 | // @as(@Vector(2, i8), undefined) | |
| 909 | // @as(@Vector(2, i8), undefined) | |
| 910 | // @as(@Vector(2, i8), undefined) | |
| 911 | // @as(@Vector(2, i8), undefined) | |
| 912 | // @as(@Vector(2, i8), undefined) | |
| 913 | // @as(i8, [runtime value]) | |
| 914 | // @as(i8, [runtime value]) | |
| 915 | // @as(@Vector(2, i8), [runtime value]) | |
| 916 | // @as(@Vector(2, i8), [runtime value]) | |
| 917 | // @as(@Vector(2, i8), [runtime value]) | |
| 918 | // @as(@Vector(2, i8), [runtime value]) | |
| 919 | // @as(@Vector(2, i8), [runtime value]) | |
| 920 | // @as(@Vector(2, i8), [runtime value]) | |
| 921 | // @as(@Vector(2, i8), [runtime value]) | |
| 922 | // @as(@Vector(2, i8), [runtime value]) | |
| 923 | // @as(@Vector(2, i8), [runtime value]) | |
| 924 | // @as(@Vector(2, i8), [runtime value]) | |
| 925 | // @as(@Vector(2, i8), [runtime value]) | |
| 926 | // @as(@Vector(2, i8), [runtime value]) | |
| 927 | // @as(@Vector(2, i8), [runtime value]) | |
| 928 | // @as(@Vector(2, i8), [runtime value]) | |
| 929 | // @as(@Vector(2, i8), undefined) | |
| 930 | // @as(i8, undefined) | |
| 931 | // @as(@Vector(2, i8), undefined) | |
| 932 | // @as(i8, undefined) | |
| 933 | // @as(i8, undefined) | |
| 934 | // @as(@Vector(2, i8), undefined) | |
| 935 | // @as(@Vector(2, i8), undefined) | |
| 936 | // @as(i8, undefined) | |
| 937 | // @as(@Vector(2, i8), undefined) | |
| 938 | // @as(u32, undefined) | |
| 939 | // @as(u32, undefined) | |
| 940 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 941 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 942 | // @as(@Vector(2, u32), undefined) | |
| 943 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 944 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 945 | // @as(@Vector(2, u32), undefined) | |
| 946 | // @as(@Vector(2, u32), undefined) | |
| 947 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 948 | // @as(@Vector(2, u32), undefined) | |
| 949 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 950 | // @as(@Vector(2, u32), undefined) | |
| 951 | // @as(@Vector(2, u32), undefined) | |
| 952 | // @as(@Vector(2, u32), undefined) | |
| 953 | // @as(@Vector(2, u32), undefined) | |
| 954 | // @as(@Vector(2, u32), undefined) | |
| 955 | // @as(u32, undefined) | |
| 956 | // @as(u32, undefined) | |
| 957 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 958 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 959 | // @as(@Vector(2, u32), undefined) | |
| 960 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 961 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 962 | // @as(@Vector(2, u32), undefined) | |
| 963 | // @as(@Vector(2, u32), undefined) | |
| 964 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 965 | // @as(@Vector(2, u32), undefined) | |
| 966 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 967 | // @as(@Vector(2, u32), undefined) | |
| 968 | // @as(@Vector(2, u32), undefined) | |
| 969 | // @as(@Vector(2, u32), undefined) | |
| 970 | // @as(@Vector(2, u32), undefined) | |
| 971 | // @as(@Vector(2, u32), undefined) | |
| 972 | // @as(u32, undefined) | |
| 973 | // @as(u32, undefined) | |
| 974 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 975 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 976 | // @as(@Vector(2, u32), undefined) | |
| 977 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 978 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 979 | // @as(@Vector(2, u32), undefined) | |
| 980 | // @as(@Vector(2, u32), undefined) | |
| 981 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 982 | // @as(@Vector(2, u32), undefined) | |
| 983 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 984 | // @as(@Vector(2, u32), undefined) | |
| 985 | // @as(@Vector(2, u32), undefined) | |
| 986 | // @as(@Vector(2, u32), undefined) | |
| 987 | // @as(@Vector(2, u32), undefined) | |
| 988 | // @as(@Vector(2, u32), undefined) | |
| 989 | // @as(u32, undefined) | |
| 990 | // @as(u32, undefined) | |
| 991 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 992 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 993 | // @as(@Vector(2, u32), undefined) | |
| 994 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 995 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 996 | // @as(@Vector(2, u32), undefined) | |
| 997 | // @as(@Vector(2, u32), undefined) | |
| 998 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 999 | // @as(@Vector(2, u32), undefined) | |
| 1000 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1001 | // @as(@Vector(2, u32), undefined) | |
| 1002 | // @as(@Vector(2, u32), undefined) | |
| 1003 | // @as(@Vector(2, u32), undefined) | |
| 1004 | // @as(@Vector(2, u32), undefined) | |
| 1005 | // @as(@Vector(2, u32), undefined) | |
| 1006 | // @as(u32, undefined) | |
| 1007 | // @as(u32, undefined) | |
| 1008 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1009 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1010 | // @as(@Vector(2, u32), undefined) | |
| 1011 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1012 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1013 | // @as(@Vector(2, u32), undefined) | |
| 1014 | // @as(@Vector(2, u32), undefined) | |
| 1015 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1016 | // @as(@Vector(2, u32), undefined) | |
| 1017 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1018 | // @as(@Vector(2, u32), undefined) | |
| 1019 | // @as(@Vector(2, u32), undefined) | |
| 1020 | // @as(@Vector(2, u32), undefined) | |
| 1021 | // @as(@Vector(2, u32), undefined) | |
| 1022 | // @as(@Vector(2, u32), undefined) | |
| 1023 | // @as(u32, undefined) | |
| 1024 | // @as(u32, undefined) | |
| 1025 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1026 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1027 | // @as(@Vector(2, u32), undefined) | |
| 1028 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1029 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1030 | // @as(@Vector(2, u32), undefined) | |
| 1031 | // @as(@Vector(2, u32), undefined) | |
| 1032 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1033 | // @as(@Vector(2, u32), undefined) | |
| 1034 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1035 | // @as(@Vector(2, u32), undefined) | |
| 1036 | // @as(@Vector(2, u32), undefined) | |
| 1037 | // @as(@Vector(2, u32), undefined) | |
| 1038 | // @as(@Vector(2, u32), undefined) | |
| 1039 | // @as(@Vector(2, u32), undefined) | |
| 1040 | // @as(u32, undefined) | |
| 1041 | // @as(u32, undefined) | |
| 1042 | // @as(@Vector(2, u32), .{ 24, undefined }) | |
| 1043 | // @as(@Vector(2, u32), .{ undefined, 24 }) | |
| 1044 | // @as(@Vector(2, u32), undefined) | |
| 1045 | // @as(@Vector(2, u32), .{ 24, undefined }) | |
| 1046 | // @as(@Vector(2, u32), .{ 24, undefined }) | |
| 1047 | // @as(@Vector(2, u32), undefined) | |
| 1048 | // @as(@Vector(2, u32), undefined) | |
| 1049 | // @as(@Vector(2, u32), .{ undefined, 24 }) | |
| 1050 | // @as(@Vector(2, u32), undefined) | |
| 1051 | // @as(@Vector(2, u32), .{ undefined, 24 }) | |
| 1052 | // @as(@Vector(2, u32), undefined) | |
| 1053 | // @as(@Vector(2, u32), undefined) | |
| 1054 | // @as(@Vector(2, u32), undefined) | |
| 1055 | // @as(@Vector(2, u32), undefined) | |
| 1056 | // @as(@Vector(2, u32), undefined) | |
| 1057 | // @as(u32, undefined) | |
| 1058 | // @as(u32, undefined) | |
| 1059 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1060 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1061 | // @as(@Vector(2, u32), undefined) | |
| 1062 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1063 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1064 | // @as(@Vector(2, u32), undefined) | |
| 1065 | // @as(@Vector(2, u32), undefined) | |
| 1066 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1067 | // @as(@Vector(2, u32), undefined) | |
| 1068 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1069 | // @as(@Vector(2, u32), undefined) | |
| 1070 | // @as(@Vector(2, u32), undefined) | |
| 1071 | // @as(@Vector(2, u32), undefined) | |
| 1072 | // @as(@Vector(2, u32), undefined) | |
| 1073 | // @as(@Vector(2, u32), undefined) | |
| 1074 | // @as(u32, undefined) | |
| 1075 | // @as(@Vector(2, u32), undefined) | |
| 1076 | // @as(u32, undefined) | |
| 1077 | // @as(u32, undefined) | |
| 1078 | // @as(@Vector(2, u32), undefined) | |
| 1079 | // @as(@Vector(2, u32), undefined) | |
| 1080 | // @as(u1, undefined) | |
| 1081 | // @as(@Vector(2, u1), .{ 1, undefined }) | |
| 1082 | // @as(@Vector(2, u1), .{ undefined, 1 }) | |
| 1083 | // @as(@Vector(2, u1), undefined) | |
| 1084 | // @as(u32, undefined) | |
| 1085 | // @as(@Vector(2, u32), undefined) | |
| 1086 | // @as(u32, undefined) | |
| 1087 | // @as(u32, undefined) | |
| 1088 | // @as(@Vector(2, u32), [runtime value]) | |
| 1089 | // @as(@Vector(2, u32), [runtime value]) | |
| 1090 | // @as(@Vector(2, u32), undefined) | |
| 1091 | // @as(@Vector(2, u32), [runtime value]) | |
| 1092 | // @as(@Vector(2, u32), [runtime value]) | |
| 1093 | // @as(@Vector(2, u32), [runtime value]) | |
| 1094 | // @as(@Vector(2, u32), undefined) | |
| 1095 | // @as(@Vector(2, u32), [runtime value]) | |
| 1096 | // @as(@Vector(2, u32), [runtime value]) | |
| 1097 | // @as(@Vector(2, u32), [runtime value]) | |
| 1098 | // @as(@Vector(2, u32), undefined) | |
| 1099 | // @as(@Vector(2, u32), undefined) | |
| 1100 | // @as(@Vector(2, u32), undefined) | |
| 1101 | // @as(@Vector(2, u32), undefined) | |
| 1102 | // @as(@Vector(2, u32), undefined) | |
| 1103 | // @as(u32, undefined) | |
| 1104 | // @as(u32, undefined) | |
| 1105 | // @as(@Vector(2, u32), [runtime value]) | |
| 1106 | // @as(@Vector(2, u32), [runtime value]) | |
| 1107 | // @as(@Vector(2, u32), undefined) | |
| 1108 | // @as(@Vector(2, u32), [runtime value]) | |
| 1109 | // @as(@Vector(2, u32), [runtime value]) | |
| 1110 | // @as(@Vector(2, u32), [runtime value]) | |
| 1111 | // @as(@Vector(2, u32), undefined) | |
| 1112 | // @as(@Vector(2, u32), [runtime value]) | |
| 1113 | // @as(@Vector(2, u32), [runtime value]) | |
| 1114 | // @as(@Vector(2, u32), [runtime value]) | |
| 1115 | // @as(@Vector(2, u32), undefined) | |
| 1116 | // @as(@Vector(2, u32), undefined) | |
| 1117 | // @as(@Vector(2, u32), undefined) | |
| 1118 | // @as(@Vector(2, u32), undefined) | |
| 1119 | // @as(@Vector(2, u32), undefined) | |
| 1120 | // @as(u32, undefined) | |
| 1121 | // @as(u32, undefined) | |
| 1122 | // @as(@Vector(2, u32), [runtime value]) | |
| 1123 | // @as(@Vector(2, u32), [runtime value]) | |
| 1124 | // @as(@Vector(2, u32), undefined) | |
| 1125 | // @as(@Vector(2, u32), [runtime value]) | |
| 1126 | // @as(@Vector(2, u32), [runtime value]) | |
| 1127 | // @as(@Vector(2, u32), [runtime value]) | |
| 1128 | // @as(@Vector(2, u32), undefined) | |
| 1129 | // @as(@Vector(2, u32), [runtime value]) | |
| 1130 | // @as(@Vector(2, u32), [runtime value]) | |
| 1131 | // @as(@Vector(2, u32), [runtime value]) | |
| 1132 | // @as(@Vector(2, u32), undefined) | |
| 1133 | // @as(@Vector(2, u32), undefined) | |
| 1134 | // @as(@Vector(2, u32), undefined) | |
| 1135 | // @as(@Vector(2, u32), undefined) | |
| 1136 | // @as(@Vector(2, u32), undefined) | |
| 1137 | // @as(u32, undefined) | |
| 1138 | // @as(u32, undefined) | |
| 1139 | // @as(@Vector(2, u32), [runtime value]) | |
| 1140 | // @as(@Vector(2, u32), [runtime value]) | |
| 1141 | // @as(@Vector(2, u32), undefined) | |
| 1142 | // @as(@Vector(2, u32), [runtime value]) | |
| 1143 | // @as(@Vector(2, u32), [runtime value]) | |
| 1144 | // @as(@Vector(2, u32), [runtime value]) | |
| 1145 | // @as(@Vector(2, u32), undefined) | |
| 1146 | // @as(@Vector(2, u32), [runtime value]) | |
| 1147 | // @as(@Vector(2, u32), [runtime value]) | |
| 1148 | // @as(@Vector(2, u32), [runtime value]) | |
| 1149 | // @as(@Vector(2, u32), undefined) | |
| 1150 | // @as(@Vector(2, u32), undefined) | |
| 1151 | // @as(@Vector(2, u32), undefined) | |
| 1152 | // @as(@Vector(2, u32), undefined) | |
| 1153 | // @as(@Vector(2, u32), undefined) | |
| 1154 | // @as(u32, undefined) | |
| 1155 | // @as(u32, undefined) | |
| 1156 | // @as(@Vector(2, u32), [runtime value]) | |
| 1157 | // @as(@Vector(2, u32), [runtime value]) | |
| 1158 | // @as(@Vector(2, u32), undefined) | |
| 1159 | // @as(@Vector(2, u32), [runtime value]) | |
| 1160 | // @as(@Vector(2, u32), [runtime value]) | |
| 1161 | // @as(@Vector(2, u32), [runtime value]) | |
| 1162 | // @as(@Vector(2, u32), undefined) | |
| 1163 | // @as(@Vector(2, u32), [runtime value]) | |
| 1164 | // @as(@Vector(2, u32), [runtime value]) | |
| 1165 | // @as(@Vector(2, u32), [runtime value]) | |
| 1166 | // @as(@Vector(2, u32), undefined) | |
| 1167 | // @as(@Vector(2, u32), undefined) | |
| 1168 | // @as(@Vector(2, u32), undefined) | |
| 1169 | // @as(@Vector(2, u32), undefined) | |
| 1170 | // @as(@Vector(2, u32), undefined) | |
| 1171 | // @as(u32, undefined) | |
| 1172 | // @as(u32, undefined) | |
| 1173 | // @as(@Vector(2, u32), [runtime value]) | |
| 1174 | // @as(@Vector(2, u32), [runtime value]) | |
| 1175 | // @as(@Vector(2, u32), undefined) | |
| 1176 | // @as(@Vector(2, u32), [runtime value]) | |
| 1177 | // @as(@Vector(2, u32), [runtime value]) | |
| 1178 | // @as(@Vector(2, u32), [runtime value]) | |
| 1179 | // @as(@Vector(2, u32), undefined) | |
| 1180 | // @as(@Vector(2, u32), [runtime value]) | |
| 1181 | // @as(@Vector(2, u32), [runtime value]) | |
| 1182 | // @as(@Vector(2, u32), [runtime value]) | |
| 1183 | // @as(@Vector(2, u32), undefined) | |
| 1184 | // @as(@Vector(2, u32), undefined) | |
| 1185 | // @as(@Vector(2, u32), undefined) | |
| 1186 | // @as(@Vector(2, u32), undefined) | |
| 1187 | // @as(@Vector(2, u32), undefined) | |
| 1188 | // @as(u32, undefined) | |
| 1189 | // @as(u32, undefined) | |
| 1190 | // @as(@Vector(2, u32), [runtime value]) | |
| 1191 | // @as(@Vector(2, u32), [runtime value]) | |
| 1192 | // @as(@Vector(2, u32), undefined) | |
| 1193 | // @as(@Vector(2, u32), [runtime value]) | |
| 1194 | // @as(@Vector(2, u32), [runtime value]) | |
| 1195 | // @as(@Vector(2, u32), [runtime value]) | |
| 1196 | // @as(@Vector(2, u32), undefined) | |
| 1197 | // @as(@Vector(2, u32), [runtime value]) | |
| 1198 | // @as(@Vector(2, u32), [runtime value]) | |
| 1199 | // @as(@Vector(2, u32), [runtime value]) | |
| 1200 | // @as(@Vector(2, u32), undefined) | |
| 1201 | // @as(@Vector(2, u32), undefined) | |
| 1202 | // @as(@Vector(2, u32), undefined) | |
| 1203 | // @as(@Vector(2, u32), undefined) | |
| 1204 | // @as(@Vector(2, u32), undefined) | |
| 1205 | // @as(u32, [runtime value]) | |
| 1206 | // @as(u32, [runtime value]) | |
| 1207 | // @as(@Vector(2, u32), [runtime value]) | |
| 1208 | // @as(@Vector(2, u32), [runtime value]) | |
| 1209 | // @as(@Vector(2, u32), [runtime value]) | |
| 1210 | // @as(@Vector(2, u32), [runtime value]) | |
| 1211 | // @as(@Vector(2, u32), [runtime value]) | |
| 1212 | // @as(@Vector(2, u32), [runtime value]) | |
| 1213 | // @as(@Vector(2, u32), [runtime value]) | |
| 1214 | // @as(@Vector(2, u32), [runtime value]) | |
| 1215 | // @as(@Vector(2, u32), [runtime value]) | |
| 1216 | // @as(@Vector(2, u32), [runtime value]) | |
| 1217 | // @as(@Vector(2, u32), [runtime value]) | |
| 1218 | // @as(@Vector(2, u32), [runtime value]) | |
| 1219 | // @as(@Vector(2, u32), [runtime value]) | |
| 1220 | // @as(@Vector(2, u32), [runtime value]) | |
| 1221 | // @as(@Vector(2, u32), undefined) | |
| 1222 | // @as(u32, undefined) | |
| 1223 | // @as(@Vector(2, u32), undefined) | |
| 1224 | // @as(u32, undefined) | |
| 1225 | // @as(u32, undefined) | |
| 1226 | // @as(@Vector(2, u32), undefined) | |
| 1227 | // @as(@Vector(2, u32), undefined) | |
| 1228 | // @as(u1, undefined) | |
| 1229 | // @as(@Vector(2, u1), [runtime value]) | |
| 1230 | // @as(@Vector(2, u1), [runtime value]) | |
| 1231 | // @as(@Vector(2, u1), undefined) | |
| 1232 | // @as(u32, undefined) | |
| 1233 | // @as(@Vector(2, u32), undefined) | |
| 1234 | // @as(i32, undefined) | |
| 1235 | // @as(i32, undefined) | |
| 1236 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1237 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1238 | // @as(@Vector(2, i32), undefined) | |
| 1239 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1240 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1241 | // @as(@Vector(2, i32), undefined) | |
| 1242 | // @as(@Vector(2, i32), undefined) | |
| 1243 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1244 | // @as(@Vector(2, i32), undefined) | |
| 1245 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1246 | // @as(@Vector(2, i32), undefined) | |
| 1247 | // @as(@Vector(2, i32), undefined) | |
| 1248 | // @as(@Vector(2, i32), undefined) | |
| 1249 | // @as(@Vector(2, i32), undefined) | |
| 1250 | // @as(@Vector(2, i32), undefined) | |
| 1251 | // @as(i32, undefined) | |
| 1252 | // @as(i32, undefined) | |
| 1253 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1254 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1255 | // @as(@Vector(2, i32), undefined) | |
| 1256 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1257 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1258 | // @as(@Vector(2, i32), undefined) | |
| 1259 | // @as(@Vector(2, i32), undefined) | |
| 1260 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1261 | // @as(@Vector(2, i32), undefined) | |
| 1262 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1263 | // @as(@Vector(2, i32), undefined) | |
| 1264 | // @as(@Vector(2, i32), undefined) | |
| 1265 | // @as(@Vector(2, i32), undefined) | |
| 1266 | // @as(@Vector(2, i32), undefined) | |
| 1267 | // @as(@Vector(2, i32), undefined) | |
| 1268 | // @as(i32, undefined) | |
| 1269 | // @as(i32, undefined) | |
| 1270 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1271 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1272 | // @as(@Vector(2, i32), undefined) | |
| 1273 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1274 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1275 | // @as(@Vector(2, i32), undefined) | |
| 1276 | // @as(@Vector(2, i32), undefined) | |
| 1277 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1278 | // @as(@Vector(2, i32), undefined) | |
| 1279 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1280 | // @as(@Vector(2, i32), undefined) | |
| 1281 | // @as(@Vector(2, i32), undefined) | |
| 1282 | // @as(@Vector(2, i32), undefined) | |
| 1283 | // @as(@Vector(2, i32), undefined) | |
| 1284 | // @as(@Vector(2, i32), undefined) | |
| 1285 | // @as(i32, undefined) | |
| 1286 | // @as(i32, undefined) | |
| 1287 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1288 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1289 | // @as(@Vector(2, i32), undefined) | |
| 1290 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1291 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1292 | // @as(@Vector(2, i32), undefined) | |
| 1293 | // @as(@Vector(2, i32), undefined) | |
| 1294 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1295 | // @as(@Vector(2, i32), undefined) | |
| 1296 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1297 | // @as(@Vector(2, i32), undefined) | |
| 1298 | // @as(@Vector(2, i32), undefined) | |
| 1299 | // @as(@Vector(2, i32), undefined) | |
| 1300 | // @as(@Vector(2, i32), undefined) | |
| 1301 | // @as(@Vector(2, i32), undefined) | |
| 1302 | // @as(i32, undefined) | |
| 1303 | // @as(i32, undefined) | |
| 1304 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1305 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1306 | // @as(@Vector(2, i32), undefined) | |
| 1307 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1308 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1309 | // @as(@Vector(2, i32), undefined) | |
| 1310 | // @as(@Vector(2, i32), undefined) | |
| 1311 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1312 | // @as(@Vector(2, i32), undefined) | |
| 1313 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1314 | // @as(@Vector(2, i32), undefined) | |
| 1315 | // @as(@Vector(2, i32), undefined) | |
| 1316 | // @as(@Vector(2, i32), undefined) | |
| 1317 | // @as(@Vector(2, i32), undefined) | |
| 1318 | // @as(@Vector(2, i32), undefined) | |
| 1319 | // @as(i32, undefined) | |
| 1320 | // @as(i32, undefined) | |
| 1321 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1322 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1323 | // @as(@Vector(2, i32), undefined) | |
| 1324 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1325 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1326 | // @as(@Vector(2, i32), undefined) | |
| 1327 | // @as(@Vector(2, i32), undefined) | |
| 1328 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1329 | // @as(@Vector(2, i32), undefined) | |
| 1330 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1331 | // @as(@Vector(2, i32), undefined) | |
| 1332 | // @as(@Vector(2, i32), undefined) | |
| 1333 | // @as(@Vector(2, i32), undefined) | |
| 1334 | // @as(@Vector(2, i32), undefined) | |
| 1335 | // @as(@Vector(2, i32), undefined) | |
| 1336 | // @as(i32, undefined) | |
| 1337 | // @as(i32, undefined) | |
| 1338 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1339 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1340 | // @as(@Vector(2, i32), undefined) | |
| 1341 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1342 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1343 | // @as(@Vector(2, i32), undefined) | |
| 1344 | // @as(@Vector(2, i32), undefined) | |
| 1345 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1346 | // @as(@Vector(2, i32), undefined) | |
| 1347 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1348 | // @as(@Vector(2, i32), undefined) | |
| 1349 | // @as(@Vector(2, i32), undefined) | |
| 1350 | // @as(@Vector(2, i32), undefined) | |
| 1351 | // @as(@Vector(2, i32), undefined) | |
| 1352 | // @as(@Vector(2, i32), undefined) | |
| 1353 | // @as(i32, undefined) | |
| 1354 | // @as(@Vector(2, i32), undefined) | |
| 1355 | // @as(i32, undefined) | |
| 1356 | // @as(i32, undefined) | |
| 1357 | // @as(@Vector(2, i32), undefined) | |
| 1358 | // @as(@Vector(2, i32), undefined) | |
| 1359 | // @as(i32, undefined) | |
| 1360 | // @as(@Vector(2, i32), undefined) | |
| 1361 | // @as(i32, undefined) | |
| 1362 | // @as(i32, undefined) | |
| 1363 | // @as(@Vector(2, i32), [runtime value]) | |
| 1364 | // @as(@Vector(2, i32), [runtime value]) | |
| 1365 | // @as(@Vector(2, i32), undefined) | |
| 1366 | // @as(@Vector(2, i32), [runtime value]) | |
| 1367 | // @as(@Vector(2, i32), [runtime value]) | |
| 1368 | // @as(@Vector(2, i32), [runtime value]) | |
| 1369 | // @as(@Vector(2, i32), undefined) | |
| 1370 | // @as(@Vector(2, i32), [runtime value]) | |
| 1371 | // @as(@Vector(2, i32), [runtime value]) | |
| 1372 | // @as(@Vector(2, i32), [runtime value]) | |
| 1373 | // @as(@Vector(2, i32), undefined) | |
| 1374 | // @as(@Vector(2, i32), undefined) | |
| 1375 | // @as(@Vector(2, i32), undefined) | |
| 1376 | // @as(@Vector(2, i32), undefined) | |
| 1377 | // @as(@Vector(2, i32), undefined) | |
| 1378 | // @as(i32, undefined) | |
| 1379 | // @as(i32, undefined) | |
| 1380 | // @as(@Vector(2, i32), [runtime value]) | |
| 1381 | // @as(@Vector(2, i32), [runtime value]) | |
| 1382 | // @as(@Vector(2, i32), undefined) | |
| 1383 | // @as(@Vector(2, i32), [runtime value]) | |
| 1384 | // @as(@Vector(2, i32), [runtime value]) | |
| 1385 | // @as(@Vector(2, i32), [runtime value]) | |
| 1386 | // @as(@Vector(2, i32), undefined) | |
| 1387 | // @as(@Vector(2, i32), [runtime value]) | |
| 1388 | // @as(@Vector(2, i32), [runtime value]) | |
| 1389 | // @as(@Vector(2, i32), [runtime value]) | |
| 1390 | // @as(@Vector(2, i32), undefined) | |
| 1391 | // @as(@Vector(2, i32), undefined) | |
| 1392 | // @as(@Vector(2, i32), undefined) | |
| 1393 | // @as(@Vector(2, i32), undefined) | |
| 1394 | // @as(@Vector(2, i32), undefined) | |
| 1395 | // @as(i32, undefined) | |
| 1396 | // @as(i32, undefined) | |
| 1397 | // @as(@Vector(2, i32), [runtime value]) | |
| 1398 | // @as(@Vector(2, i32), [runtime value]) | |
| 1399 | // @as(@Vector(2, i32), undefined) | |
| 1400 | // @as(@Vector(2, i32), [runtime value]) | |
| 1401 | // @as(@Vector(2, i32), [runtime value]) | |
| 1402 | // @as(@Vector(2, i32), [runtime value]) | |
| 1403 | // @as(@Vector(2, i32), undefined) | |
| 1404 | // @as(@Vector(2, i32), [runtime value]) | |
| 1405 | // @as(@Vector(2, i32), [runtime value]) | |
| 1406 | // @as(@Vector(2, i32), [runtime value]) | |
| 1407 | // @as(@Vector(2, i32), undefined) | |
| 1408 | // @as(@Vector(2, i32), undefined) | |
| 1409 | // @as(@Vector(2, i32), undefined) | |
| 1410 | // @as(@Vector(2, i32), undefined) | |
| 1411 | // @as(@Vector(2, i32), undefined) | |
| 1412 | // @as(i32, undefined) | |
| 1413 | // @as(i32, undefined) | |
| 1414 | // @as(@Vector(2, i32), [runtime value]) | |
| 1415 | // @as(@Vector(2, i32), [runtime value]) | |
| 1416 | // @as(@Vector(2, i32), undefined) | |
| 1417 | // @as(@Vector(2, i32), [runtime value]) | |
| 1418 | // @as(@Vector(2, i32), [runtime value]) | |
| 1419 | // @as(@Vector(2, i32), [runtime value]) | |
| 1420 | // @as(@Vector(2, i32), undefined) | |
| 1421 | // @as(@Vector(2, i32), [runtime value]) | |
| 1422 | // @as(@Vector(2, i32), [runtime value]) | |
| 1423 | // @as(@Vector(2, i32), [runtime value]) | |
| 1424 | // @as(@Vector(2, i32), undefined) | |
| 1425 | // @as(@Vector(2, i32), undefined) | |
| 1426 | // @as(@Vector(2, i32), undefined) | |
| 1427 | // @as(@Vector(2, i32), undefined) | |
| 1428 | // @as(@Vector(2, i32), undefined) | |
| 1429 | // @as(i32, undefined) | |
| 1430 | // @as(i32, undefined) | |
| 1431 | // @as(@Vector(2, i32), [runtime value]) | |
| 1432 | // @as(@Vector(2, i32), [runtime value]) | |
| 1433 | // @as(@Vector(2, i32), undefined) | |
| 1434 | // @as(@Vector(2, i32), [runtime value]) | |
| 1435 | // @as(@Vector(2, i32), [runtime value]) | |
| 1436 | // @as(@Vector(2, i32), [runtime value]) | |
| 1437 | // @as(@Vector(2, i32), undefined) | |
| 1438 | // @as(@Vector(2, i32), [runtime value]) | |
| 1439 | // @as(@Vector(2, i32), [runtime value]) | |
| 1440 | // @as(@Vector(2, i32), [runtime value]) | |
| 1441 | // @as(@Vector(2, i32), undefined) | |
| 1442 | // @as(@Vector(2, i32), undefined) | |
| 1443 | // @as(@Vector(2, i32), undefined) | |
| 1444 | // @as(@Vector(2, i32), undefined) | |
| 1445 | // @as(@Vector(2, i32), undefined) | |
| 1446 | // @as(i32, undefined) | |
| 1447 | // @as(i32, undefined) | |
| 1448 | // @as(@Vector(2, i32), [runtime value]) | |
| 1449 | // @as(@Vector(2, i32), [runtime value]) | |
| 1450 | // @as(@Vector(2, i32), undefined) | |
| 1451 | // @as(@Vector(2, i32), [runtime value]) | |
| 1452 | // @as(@Vector(2, i32), [runtime value]) | |
| 1453 | // @as(@Vector(2, i32), [runtime value]) | |
| 1454 | // @as(@Vector(2, i32), undefined) | |
| 1455 | // @as(@Vector(2, i32), [runtime value]) | |
| 1456 | // @as(@Vector(2, i32), [runtime value]) | |
| 1457 | // @as(@Vector(2, i32), [runtime value]) | |
| 1458 | // @as(@Vector(2, i32), undefined) | |
| 1459 | // @as(@Vector(2, i32), undefined) | |
| 1460 | // @as(@Vector(2, i32), undefined) | |
| 1461 | // @as(@Vector(2, i32), undefined) | |
| 1462 | // @as(@Vector(2, i32), undefined) | |
| 1463 | // @as(i32, [runtime value]) | |
| 1464 | // @as(i32, [runtime value]) | |
| 1465 | // @as(@Vector(2, i32), [runtime value]) | |
| 1466 | // @as(@Vector(2, i32), [runtime value]) | |
| 1467 | // @as(@Vector(2, i32), [runtime value]) | |
| 1468 | // @as(@Vector(2, i32), [runtime value]) | |
| 1469 | // @as(@Vector(2, i32), [runtime value]) | |
| 1470 | // @as(@Vector(2, i32), [runtime value]) | |
| 1471 | // @as(@Vector(2, i32), [runtime value]) | |
| 1472 | // @as(@Vector(2, i32), [runtime value]) | |
| 1473 | // @as(@Vector(2, i32), [runtime value]) | |
| 1474 | // @as(@Vector(2, i32), [runtime value]) | |
| 1475 | // @as(@Vector(2, i32), [runtime value]) | |
| 1476 | // @as(@Vector(2, i32), [runtime value]) | |
| 1477 | // @as(@Vector(2, i32), [runtime value]) | |
| 1478 | // @as(@Vector(2, i32), [runtime value]) | |
| 1479 | // @as(@Vector(2, i32), undefined) | |
| 1480 | // @as(i32, undefined) | |
| 1481 | // @as(@Vector(2, i32), undefined) | |
| 1482 | // @as(i32, undefined) | |
| 1483 | // @as(i32, undefined) | |
| 1484 | // @as(@Vector(2, i32), undefined) | |
| 1485 | // @as(@Vector(2, i32), undefined) | |
| 1486 | // @as(i32, undefined) | |
| 1487 | // @as(@Vector(2, i32), undefined) | |
| 1488 | // @as(u500, undefined) | |
| 1489 | // @as(u500, undefined) | |
| 1490 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 1491 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 1492 | // @as(@Vector(2, u500), undefined) | |
| 1493 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 1494 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 1495 | // @as(@Vector(2, u500), undefined) | |
| 1496 | // @as(@Vector(2, u500), undefined) | |
| 1497 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 1498 | // @as(@Vector(2, u500), undefined) | |
| 1499 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 1500 | // @as(@Vector(2, u500), undefined) | |
| 1501 | // @as(@Vector(2, u500), undefined) | |
| 1502 | // @as(@Vector(2, u500), undefined) | |
| 1503 | // @as(@Vector(2, u500), undefined) | |
| 1504 | // @as(@Vector(2, u500), undefined) | |
| 1505 | // @as(u500, undefined) | |
| 1506 | // @as(u500, undefined) | |
| 1507 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 1508 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 1509 | // @as(@Vector(2, u500), undefined) | |
| 1510 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 1511 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 1512 | // @as(@Vector(2, u500), undefined) | |
| 1513 | // @as(@Vector(2, u500), undefined) | |
| 1514 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 1515 | // @as(@Vector(2, u500), undefined) | |
| 1516 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 1517 | // @as(@Vector(2, u500), undefined) | |
| 1518 | // @as(@Vector(2, u500), undefined) | |
| 1519 | // @as(@Vector(2, u500), undefined) | |
| 1520 | // @as(@Vector(2, u500), undefined) | |
| 1521 | // @as(@Vector(2, u500), undefined) | |
| 1522 | // @as(u500, undefined) | |
| 1523 | // @as(u500, undefined) | |
| 1524 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1525 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1526 | // @as(@Vector(2, u500), undefined) | |
| 1527 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1528 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1529 | // @as(@Vector(2, u500), undefined) | |
| 1530 | // @as(@Vector(2, u500), undefined) | |
| 1531 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1532 | // @as(@Vector(2, u500), undefined) | |
| 1533 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1534 | // @as(@Vector(2, u500), undefined) | |
| 1535 | // @as(@Vector(2, u500), undefined) | |
| 1536 | // @as(@Vector(2, u500), undefined) | |
| 1537 | // @as(@Vector(2, u500), undefined) | |
| 1538 | // @as(@Vector(2, u500), undefined) | |
| 1539 | // @as(u500, undefined) | |
| 1540 | // @as(u500, undefined) | |
| 1541 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1542 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1543 | // @as(@Vector(2, u500), undefined) | |
| 1544 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1545 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1546 | // @as(@Vector(2, u500), undefined) | |
| 1547 | // @as(@Vector(2, u500), undefined) | |
| 1548 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1549 | // @as(@Vector(2, u500), undefined) | |
| 1550 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1551 | // @as(@Vector(2, u500), undefined) | |
| 1552 | // @as(@Vector(2, u500), undefined) | |
| 1553 | // @as(@Vector(2, u500), undefined) | |
| 1554 | // @as(@Vector(2, u500), undefined) | |
| 1555 | // @as(@Vector(2, u500), undefined) | |
| 1556 | // @as(u500, undefined) | |
| 1557 | // @as(u500, undefined) | |
| 1558 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1559 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1560 | // @as(@Vector(2, u500), undefined) | |
| 1561 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1562 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1563 | // @as(@Vector(2, u500), undefined) | |
| 1564 | // @as(@Vector(2, u500), undefined) | |
| 1565 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1566 | // @as(@Vector(2, u500), undefined) | |
| 1567 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1568 | // @as(@Vector(2, u500), undefined) | |
| 1569 | // @as(@Vector(2, u500), undefined) | |
| 1570 | // @as(@Vector(2, u500), undefined) | |
| 1571 | // @as(@Vector(2, u500), undefined) | |
| 1572 | // @as(@Vector(2, u500), undefined) | |
| 1573 | // @as(u500, undefined) | |
| 1574 | // @as(u500, undefined) | |
| 1575 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1576 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1577 | // @as(@Vector(2, u500), undefined) | |
| 1578 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1579 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1580 | // @as(@Vector(2, u500), undefined) | |
| 1581 | // @as(@Vector(2, u500), undefined) | |
| 1582 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1583 | // @as(@Vector(2, u500), undefined) | |
| 1584 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1585 | // @as(@Vector(2, u500), undefined) | |
| 1586 | // @as(@Vector(2, u500), undefined) | |
| 1587 | // @as(@Vector(2, u500), undefined) | |
| 1588 | // @as(@Vector(2, u500), undefined) | |
| 1589 | // @as(@Vector(2, u500), undefined) | |
| 1590 | // @as(u500, undefined) | |
| 1591 | // @as(u500, undefined) | |
| 1592 | // @as(@Vector(2, u500), .{ 24, undefined }) | |
| 1593 | // @as(@Vector(2, u500), .{ undefined, 24 }) | |
| 1594 | // @as(@Vector(2, u500), undefined) | |
| 1595 | // @as(@Vector(2, u500), .{ 24, undefined }) | |
| 1596 | // @as(@Vector(2, u500), .{ 24, undefined }) | |
| 1597 | // @as(@Vector(2, u500), undefined) | |
| 1598 | // @as(@Vector(2, u500), undefined) | |
| 1599 | // @as(@Vector(2, u500), .{ undefined, 24 }) | |
| 1600 | // @as(@Vector(2, u500), undefined) | |
| 1601 | // @as(@Vector(2, u500), .{ undefined, 24 }) | |
| 1602 | // @as(@Vector(2, u500), undefined) | |
| 1603 | // @as(@Vector(2, u500), undefined) | |
| 1604 | // @as(@Vector(2, u500), undefined) | |
| 1605 | // @as(@Vector(2, u500), undefined) | |
| 1606 | // @as(@Vector(2, u500), undefined) | |
| 1607 | // @as(u500, undefined) | |
| 1608 | // @as(u500, undefined) | |
| 1609 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1610 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1611 | // @as(@Vector(2, u500), undefined) | |
| 1612 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1613 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1614 | // @as(@Vector(2, u500), undefined) | |
| 1615 | // @as(@Vector(2, u500), undefined) | |
| 1616 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1617 | // @as(@Vector(2, u500), undefined) | |
| 1618 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1619 | // @as(@Vector(2, u500), undefined) | |
| 1620 | // @as(@Vector(2, u500), undefined) | |
| 1621 | // @as(@Vector(2, u500), undefined) | |
| 1622 | // @as(@Vector(2, u500), undefined) | |
| 1623 | // @as(@Vector(2, u500), undefined) | |
| 1624 | // @as(u500, undefined) | |
| 1625 | // @as(@Vector(2, u500), undefined) | |
| 1626 | // @as(u500, undefined) | |
| 1627 | // @as(u500, undefined) | |
| 1628 | // @as(@Vector(2, u500), undefined) | |
| 1629 | // @as(@Vector(2, u500), undefined) | |
| 1630 | // @as(u1, undefined) | |
| 1631 | // @as(@Vector(2, u1), .{ 1, undefined }) | |
| 1632 | // @as(@Vector(2, u1), .{ undefined, 1 }) | |
| 1633 | // @as(@Vector(2, u1), undefined) | |
| 1634 | // @as(u500, undefined) | |
| 1635 | // @as(@Vector(2, u500), undefined) | |
| 1636 | // @as(u500, undefined) | |
| 1637 | // @as(u500, undefined) | |
| 1638 | // @as(@Vector(2, u500), [runtime value]) | |
| 1639 | // @as(@Vector(2, u500), [runtime value]) | |
| 1640 | // @as(@Vector(2, u500), undefined) | |
| 1641 | // @as(@Vector(2, u500), [runtime value]) | |
| 1642 | // @as(@Vector(2, u500), [runtime value]) | |
| 1643 | // @as(@Vector(2, u500), [runtime value]) | |
| 1644 | // @as(@Vector(2, u500), undefined) | |
| 1645 | // @as(@Vector(2, u500), [runtime value]) | |
| 1646 | // @as(@Vector(2, u500), [runtime value]) | |
| 1647 | // @as(@Vector(2, u500), [runtime value]) | |
| 1648 | // @as(@Vector(2, u500), undefined) | |
| 1649 | // @as(@Vector(2, u500), undefined) | |
| 1650 | // @as(@Vector(2, u500), undefined) | |
| 1651 | // @as(@Vector(2, u500), undefined) | |
| 1652 | // @as(@Vector(2, u500), undefined) | |
| 1653 | // @as(u500, undefined) | |
| 1654 | // @as(u500, undefined) | |
| 1655 | // @as(@Vector(2, u500), [runtime value]) | |
| 1656 | // @as(@Vector(2, u500), [runtime value]) | |
| 1657 | // @as(@Vector(2, u500), undefined) | |
| 1658 | // @as(@Vector(2, u500), [runtime value]) | |
| 1659 | // @as(@Vector(2, u500), [runtime value]) | |
| 1660 | // @as(@Vector(2, u500), [runtime value]) | |
| 1661 | // @as(@Vector(2, u500), undefined) | |
| 1662 | // @as(@Vector(2, u500), [runtime value]) | |
| 1663 | // @as(@Vector(2, u500), [runtime value]) | |
| 1664 | // @as(@Vector(2, u500), [runtime value]) | |
| 1665 | // @as(@Vector(2, u500), undefined) | |
| 1666 | // @as(@Vector(2, u500), undefined) | |
| 1667 | // @as(@Vector(2, u500), undefined) | |
| 1668 | // @as(@Vector(2, u500), undefined) | |
| 1669 | // @as(@Vector(2, u500), undefined) | |
| 1670 | // @as(u500, undefined) | |
| 1671 | // @as(u500, undefined) | |
| 1672 | // @as(@Vector(2, u500), [runtime value]) | |
| 1673 | // @as(@Vector(2, u500), [runtime value]) | |
| 1674 | // @as(@Vector(2, u500), undefined) | |
| 1675 | // @as(@Vector(2, u500), [runtime value]) | |
| 1676 | // @as(@Vector(2, u500), [runtime value]) | |
| 1677 | // @as(@Vector(2, u500), [runtime value]) | |
| 1678 | // @as(@Vector(2, u500), undefined) | |
| 1679 | // @as(@Vector(2, u500), [runtime value]) | |
| 1680 | // @as(@Vector(2, u500), [runtime value]) | |
| 1681 | // @as(@Vector(2, u500), [runtime value]) | |
| 1682 | // @as(@Vector(2, u500), undefined) | |
| 1683 | // @as(@Vector(2, u500), undefined) | |
| 1684 | // @as(@Vector(2, u500), undefined) | |
| 1685 | // @as(@Vector(2, u500), undefined) | |
| 1686 | // @as(@Vector(2, u500), undefined) | |
| 1687 | // @as(u500, undefined) | |
| 1688 | // @as(u500, undefined) | |
| 1689 | // @as(@Vector(2, u500), [runtime value]) | |
| 1690 | // @as(@Vector(2, u500), [runtime value]) | |
| 1691 | // @as(@Vector(2, u500), undefined) | |
| 1692 | // @as(@Vector(2, u500), [runtime value]) | |
| 1693 | // @as(@Vector(2, u500), [runtime value]) | |
| 1694 | // @as(@Vector(2, u500), [runtime value]) | |
| 1695 | // @as(@Vector(2, u500), undefined) | |
| 1696 | // @as(@Vector(2, u500), [runtime value]) | |
| 1697 | // @as(@Vector(2, u500), [runtime value]) | |
| 1698 | // @as(@Vector(2, u500), [runtime value]) | |
| 1699 | // @as(@Vector(2, u500), undefined) | |
| 1700 | // @as(@Vector(2, u500), undefined) | |
| 1701 | // @as(@Vector(2, u500), undefined) | |
| 1702 | // @as(@Vector(2, u500), undefined) | |
| 1703 | // @as(@Vector(2, u500), undefined) | |
| 1704 | // @as(u500, undefined) | |
| 1705 | // @as(u500, undefined) | |
| 1706 | // @as(@Vector(2, u500), [runtime value]) | |
| 1707 | // @as(@Vector(2, u500), [runtime value]) | |
| 1708 | // @as(@Vector(2, u500), undefined) | |
| 1709 | // @as(@Vector(2, u500), [runtime value]) | |
| 1710 | // @as(@Vector(2, u500), [runtime value]) | |
| 1711 | // @as(@Vector(2, u500), [runtime value]) | |
| 1712 | // @as(@Vector(2, u500), undefined) | |
| 1713 | // @as(@Vector(2, u500), [runtime value]) | |
| 1714 | // @as(@Vector(2, u500), [runtime value]) | |
| 1715 | // @as(@Vector(2, u500), [runtime value]) | |
| 1716 | // @as(@Vector(2, u500), undefined) | |
| 1717 | // @as(@Vector(2, u500), undefined) | |
| 1718 | // @as(@Vector(2, u500), undefined) | |
| 1719 | // @as(@Vector(2, u500), undefined) | |
| 1720 | // @as(@Vector(2, u500), undefined) | |
| 1721 | // @as(u500, undefined) | |
| 1722 | // @as(u500, undefined) | |
| 1723 | // @as(@Vector(2, u500), [runtime value]) | |
| 1724 | // @as(@Vector(2, u500), [runtime value]) | |
| 1725 | // @as(@Vector(2, u500), undefined) | |
| 1726 | // @as(@Vector(2, u500), [runtime value]) | |
| 1727 | // @as(@Vector(2, u500), [runtime value]) | |
| 1728 | // @as(@Vector(2, u500), [runtime value]) | |
| 1729 | // @as(@Vector(2, u500), undefined) | |
| 1730 | // @as(@Vector(2, u500), [runtime value]) | |
| 1731 | // @as(@Vector(2, u500), [runtime value]) | |
| 1732 | // @as(@Vector(2, u500), [runtime value]) | |
| 1733 | // @as(@Vector(2, u500), undefined) | |
| 1734 | // @as(@Vector(2, u500), undefined) | |
| 1735 | // @as(@Vector(2, u500), undefined) | |
| 1736 | // @as(@Vector(2, u500), undefined) | |
| 1737 | // @as(@Vector(2, u500), undefined) | |
| 1738 | // @as(u500, undefined) | |
| 1739 | // @as(u500, undefined) | |
| 1740 | // @as(@Vector(2, u500), [runtime value]) | |
| 1741 | // @as(@Vector(2, u500), [runtime value]) | |
| 1742 | // @as(@Vector(2, u500), undefined) | |
| 1743 | // @as(@Vector(2, u500), [runtime value]) | |
| 1744 | // @as(@Vector(2, u500), [runtime value]) | |
| 1745 | // @as(@Vector(2, u500), [runtime value]) | |
| 1746 | // @as(@Vector(2, u500), undefined) | |
| 1747 | // @as(@Vector(2, u500), [runtime value]) | |
| 1748 | // @as(@Vector(2, u500), [runtime value]) | |
| 1749 | // @as(@Vector(2, u500), [runtime value]) | |
| 1750 | // @as(@Vector(2, u500), undefined) | |
| 1751 | // @as(@Vector(2, u500), undefined) | |
| 1752 | // @as(@Vector(2, u500), undefined) | |
| 1753 | // @as(@Vector(2, u500), undefined) | |
| 1754 | // @as(@Vector(2, u500), undefined) | |
| 1755 | // @as(u500, [runtime value]) | |
| 1756 | // @as(u500, [runtime value]) | |
| 1757 | // @as(@Vector(2, u500), [runtime value]) | |
| 1758 | // @as(@Vector(2, u500), [runtime value]) | |
| 1759 | // @as(@Vector(2, u500), [runtime value]) | |
| 1760 | // @as(@Vector(2, u500), [runtime value]) | |
| 1761 | // @as(@Vector(2, u500), [runtime value]) | |
| 1762 | // @as(@Vector(2, u500), [runtime value]) | |
| 1763 | // @as(@Vector(2, u500), [runtime value]) | |
| 1764 | // @as(@Vector(2, u500), [runtime value]) | |
| 1765 | // @as(@Vector(2, u500), [runtime value]) | |
| 1766 | // @as(@Vector(2, u500), [runtime value]) | |
| 1767 | // @as(@Vector(2, u500), [runtime value]) | |
| 1768 | // @as(@Vector(2, u500), [runtime value]) | |
| 1769 | // @as(@Vector(2, u500), [runtime value]) | |
| 1770 | // @as(@Vector(2, u500), [runtime value]) | |
| 1771 | // @as(@Vector(2, u500), undefined) | |
| 1772 | // @as(u500, undefined) | |
| 1773 | // @as(@Vector(2, u500), undefined) | |
| 1774 | // @as(u500, undefined) | |
| 1775 | // @as(u500, undefined) | |
| 1776 | // @as(@Vector(2, u500), undefined) | |
| 1777 | // @as(@Vector(2, u500), undefined) | |
| 1778 | // @as(u1, undefined) | |
| 1779 | // @as(@Vector(2, u1), [runtime value]) | |
| 1780 | // @as(@Vector(2, u1), [runtime value]) | |
| 1781 | // @as(@Vector(2, u1), undefined) | |
| 1782 | // @as(u500, undefined) | |
| 1783 | // @as(@Vector(2, u500), undefined) | |
| 1784 | // @as(i500, undefined) | |
| 1785 | // @as(i500, undefined) | |
| 1786 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 1787 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 1788 | // @as(@Vector(2, i500), undefined) | |
| 1789 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 1790 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 1791 | // @as(@Vector(2, i500), undefined) | |
| 1792 | // @as(@Vector(2, i500), undefined) | |
| 1793 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 1794 | // @as(@Vector(2, i500), undefined) | |
| 1795 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 1796 | // @as(@Vector(2, i500), undefined) | |
| 1797 | // @as(@Vector(2, i500), undefined) | |
| 1798 | // @as(@Vector(2, i500), undefined) | |
| 1799 | // @as(@Vector(2, i500), undefined) | |
| 1800 | // @as(@Vector(2, i500), undefined) | |
| 1801 | // @as(i500, undefined) | |
| 1802 | // @as(i500, undefined) | |
| 1803 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 1804 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 1805 | // @as(@Vector(2, i500), undefined) | |
| 1806 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 1807 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 1808 | // @as(@Vector(2, i500), undefined) | |
| 1809 | // @as(@Vector(2, i500), undefined) | |
| 1810 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 1811 | // @as(@Vector(2, i500), undefined) | |
| 1812 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 1813 | // @as(@Vector(2, i500), undefined) | |
| 1814 | // @as(@Vector(2, i500), undefined) | |
| 1815 | // @as(@Vector(2, i500), undefined) | |
| 1816 | // @as(@Vector(2, i500), undefined) | |
| 1817 | // @as(@Vector(2, i500), undefined) | |
| 1818 | // @as(i500, undefined) | |
| 1819 | // @as(i500, undefined) | |
| 1820 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1821 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1822 | // @as(@Vector(2, i500), undefined) | |
| 1823 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1824 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1825 | // @as(@Vector(2, i500), undefined) | |
| 1826 | // @as(@Vector(2, i500), undefined) | |
| 1827 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1828 | // @as(@Vector(2, i500), undefined) | |
| 1829 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1830 | // @as(@Vector(2, i500), undefined) | |
| 1831 | // @as(@Vector(2, i500), undefined) | |
| 1832 | // @as(@Vector(2, i500), undefined) | |
| 1833 | // @as(@Vector(2, i500), undefined) | |
| 1834 | // @as(@Vector(2, i500), undefined) | |
| 1835 | // @as(i500, undefined) | |
| 1836 | // @as(i500, undefined) | |
| 1837 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1838 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1839 | // @as(@Vector(2, i500), undefined) | |
| 1840 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1841 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1842 | // @as(@Vector(2, i500), undefined) | |
| 1843 | // @as(@Vector(2, i500), undefined) | |
| 1844 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1845 | // @as(@Vector(2, i500), undefined) | |
| 1846 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1847 | // @as(@Vector(2, i500), undefined) | |
| 1848 | // @as(@Vector(2, i500), undefined) | |
| 1849 | // @as(@Vector(2, i500), undefined) | |
| 1850 | // @as(@Vector(2, i500), undefined) | |
| 1851 | // @as(@Vector(2, i500), undefined) | |
| 1852 | // @as(i500, undefined) | |
| 1853 | // @as(i500, undefined) | |
| 1854 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 1855 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 1856 | // @as(@Vector(2, i500), undefined) | |
| 1857 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 1858 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 1859 | // @as(@Vector(2, i500), undefined) | |
| 1860 | // @as(@Vector(2, i500), undefined) | |
| 1861 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 1862 | // @as(@Vector(2, i500), undefined) | |
| 1863 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 1864 | // @as(@Vector(2, i500), undefined) | |
| 1865 | // @as(@Vector(2, i500), undefined) | |
| 1866 | // @as(@Vector(2, i500), undefined) | |
| 1867 | // @as(@Vector(2, i500), undefined) | |
| 1868 | // @as(@Vector(2, i500), undefined) | |
| 1869 | // @as(i500, undefined) | |
| 1870 | // @as(i500, undefined) | |
| 1871 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 1872 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 1873 | // @as(@Vector(2, i500), undefined) | |
| 1874 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 1875 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 1876 | // @as(@Vector(2, i500), undefined) | |
| 1877 | // @as(@Vector(2, i500), undefined) | |
| 1878 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 1879 | // @as(@Vector(2, i500), undefined) | |
| 1880 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 1881 | // @as(@Vector(2, i500), undefined) | |
| 1882 | // @as(@Vector(2, i500), undefined) | |
| 1883 | // @as(@Vector(2, i500), undefined) | |
| 1884 | // @as(@Vector(2, i500), undefined) | |
| 1885 | // @as(@Vector(2, i500), undefined) | |
| 1886 | // @as(i500, undefined) | |
| 1887 | // @as(i500, undefined) | |
| 1888 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1889 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1890 | // @as(@Vector(2, i500), undefined) | |
| 1891 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1892 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 1893 | // @as(@Vector(2, i500), undefined) | |
| 1894 | // @as(@Vector(2, i500), undefined) | |
| 1895 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1896 | // @as(@Vector(2, i500), undefined) | |
| 1897 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 1898 | // @as(@Vector(2, i500), undefined) | |
| 1899 | // @as(@Vector(2, i500), undefined) | |
| 1900 | // @as(@Vector(2, i500), undefined) | |
| 1901 | // @as(@Vector(2, i500), undefined) | |
| 1902 | // @as(@Vector(2, i500), undefined) | |
| 1903 | // @as(i500, undefined) | |
| 1904 | // @as(@Vector(2, i500), undefined) | |
| 1905 | // @as(i500, undefined) | |
| 1906 | // @as(i500, undefined) | |
| 1907 | // @as(@Vector(2, i500), undefined) | |
| 1908 | // @as(@Vector(2, i500), undefined) | |
| 1909 | // @as(i500, undefined) | |
| 1910 | // @as(@Vector(2, i500), undefined) | |
| 1911 | // @as(i500, undefined) | |
| 1912 | // @as(i500, undefined) | |
| 1913 | // @as(@Vector(2, i500), [runtime value]) | |
| 1914 | // @as(@Vector(2, i500), [runtime value]) | |
| 1915 | // @as(@Vector(2, i500), undefined) | |
| 1916 | // @as(@Vector(2, i500), [runtime value]) | |
| 1917 | // @as(@Vector(2, i500), [runtime value]) | |
| 1918 | // @as(@Vector(2, i500), [runtime value]) | |
| 1919 | // @as(@Vector(2, i500), undefined) | |
| 1920 | // @as(@Vector(2, i500), [runtime value]) | |
| 1921 | // @as(@Vector(2, i500), [runtime value]) | |
| 1922 | // @as(@Vector(2, i500), [runtime value]) | |
| 1923 | // @as(@Vector(2, i500), undefined) | |
| 1924 | // @as(@Vector(2, i500), undefined) | |
| 1925 | // @as(@Vector(2, i500), undefined) | |
| 1926 | // @as(@Vector(2, i500), undefined) | |
| 1927 | // @as(@Vector(2, i500), undefined) | |
| 1928 | // @as(i500, undefined) | |
| 1929 | // @as(i500, undefined) | |
| 1930 | // @as(@Vector(2, i500), [runtime value]) | |
| 1931 | // @as(@Vector(2, i500), [runtime value]) | |
| 1932 | // @as(@Vector(2, i500), undefined) | |
| 1933 | // @as(@Vector(2, i500), [runtime value]) | |
| 1934 | // @as(@Vector(2, i500), [runtime value]) | |
| 1935 | // @as(@Vector(2, i500), [runtime value]) | |
| 1936 | // @as(@Vector(2, i500), undefined) | |
| 1937 | // @as(@Vector(2, i500), [runtime value]) | |
| 1938 | // @as(@Vector(2, i500), [runtime value]) | |
| 1939 | // @as(@Vector(2, i500), [runtime value]) | |
| 1940 | // @as(@Vector(2, i500), undefined) | |
| 1941 | // @as(@Vector(2, i500), undefined) | |
| 1942 | // @as(@Vector(2, i500), undefined) | |
| 1943 | // @as(@Vector(2, i500), undefined) | |
| 1944 | // @as(@Vector(2, i500), undefined) | |
| 1945 | // @as(i500, undefined) | |
| 1946 | // @as(i500, undefined) | |
| 1947 | // @as(@Vector(2, i500), [runtime value]) | |
| 1948 | // @as(@Vector(2, i500), [runtime value]) | |
| 1949 | // @as(@Vector(2, i500), undefined) | |
| 1950 | // @as(@Vector(2, i500), [runtime value]) | |
| 1951 | // @as(@Vector(2, i500), [runtime value]) | |
| 1952 | // @as(@Vector(2, i500), [runtime value]) | |
| 1953 | // @as(@Vector(2, i500), undefined) | |
| 1954 | // @as(@Vector(2, i500), [runtime value]) | |
| 1955 | // @as(@Vector(2, i500), [runtime value]) | |
| 1956 | // @as(@Vector(2, i500), [runtime value]) | |
| 1957 | // @as(@Vector(2, i500), undefined) | |
| 1958 | // @as(@Vector(2, i500), undefined) | |
| 1959 | // @as(@Vector(2, i500), undefined) | |
| 1960 | // @as(@Vector(2, i500), undefined) | |
| 1961 | // @as(@Vector(2, i500), undefined) | |
| 1962 | // @as(i500, undefined) | |
| 1963 | // @as(i500, undefined) | |
| 1964 | // @as(@Vector(2, i500), [runtime value]) | |
| 1965 | // @as(@Vector(2, i500), [runtime value]) | |
| 1966 | // @as(@Vector(2, i500), undefined) | |
| 1967 | // @as(@Vector(2, i500), [runtime value]) | |
| 1968 | // @as(@Vector(2, i500), [runtime value]) | |
| 1969 | // @as(@Vector(2, i500), [runtime value]) | |
| 1970 | // @as(@Vector(2, i500), undefined) | |
| 1971 | // @as(@Vector(2, i500), [runtime value]) | |
| 1972 | // @as(@Vector(2, i500), [runtime value]) | |
| 1973 | // @as(@Vector(2, i500), [runtime value]) | |
| 1974 | // @as(@Vector(2, i500), undefined) | |
| 1975 | // @as(@Vector(2, i500), undefined) | |
| 1976 | // @as(@Vector(2, i500), undefined) | |
| 1977 | // @as(@Vector(2, i500), undefined) | |
| 1978 | // @as(@Vector(2, i500), undefined) | |
| 1979 | // @as(i500, undefined) | |
| 1980 | // @as(i500, undefined) | |
| 1981 | // @as(@Vector(2, i500), [runtime value]) | |
| 1982 | // @as(@Vector(2, i500), [runtime value]) | |
| 1983 | // @as(@Vector(2, i500), undefined) | |
| 1984 | // @as(@Vector(2, i500), [runtime value]) | |
| 1985 | // @as(@Vector(2, i500), [runtime value]) | |
| 1986 | // @as(@Vector(2, i500), [runtime value]) | |
| 1987 | // @as(@Vector(2, i500), undefined) | |
| 1988 | // @as(@Vector(2, i500), [runtime value]) | |
| 1989 | // @as(@Vector(2, i500), [runtime value]) | |
| 1990 | // @as(@Vector(2, i500), [runtime value]) | |
| 1991 | // @as(@Vector(2, i500), undefined) | |
| 1992 | // @as(@Vector(2, i500), undefined) | |
| 1993 | // @as(@Vector(2, i500), undefined) | |
| 1994 | // @as(@Vector(2, i500), undefined) | |
| 1995 | // @as(@Vector(2, i500), undefined) | |
| 1996 | // @as(i500, undefined) | |
| 1997 | // @as(i500, undefined) | |
| 1998 | // @as(@Vector(2, i500), [runtime value]) | |
| 1999 | // @as(@Vector(2, i500), [runtime value]) | |
| 2000 | // @as(@Vector(2, i500), undefined) | |
| 2001 | // @as(@Vector(2, i500), [runtime value]) | |
| 2002 | // @as(@Vector(2, i500), [runtime value]) | |
| 2003 | // @as(@Vector(2, i500), [runtime value]) | |
| 2004 | // @as(@Vector(2, i500), undefined) | |
| 2005 | // @as(@Vector(2, i500), [runtime value]) | |
| 2006 | // @as(@Vector(2, i500), [runtime value]) | |
| 2007 | // @as(@Vector(2, i500), [runtime value]) | |
| 2008 | // @as(@Vector(2, i500), undefined) | |
| 2009 | // @as(@Vector(2, i500), undefined) | |
| 2010 | // @as(@Vector(2, i500), undefined) | |
| 2011 | // @as(@Vector(2, i500), undefined) | |
| 2012 | // @as(@Vector(2, i500), undefined) | |
| 2013 | // @as(i500, [runtime value]) | |
| 2014 | // @as(i500, [runtime value]) | |
| 2015 | // @as(@Vector(2, i500), [runtime value]) | |
| 2016 | // @as(@Vector(2, i500), [runtime value]) | |
| 2017 | // @as(@Vector(2, i500), [runtime value]) | |
| 2018 | // @as(@Vector(2, i500), [runtime value]) | |
| 2019 | // @as(@Vector(2, i500), [runtime value]) | |
| 2020 | // @as(@Vector(2, i500), [runtime value]) | |
| 2021 | // @as(@Vector(2, i500), [runtime value]) | |
| 2022 | // @as(@Vector(2, i500), [runtime value]) | |
| 2023 | // @as(@Vector(2, i500), [runtime value]) | |
| 2024 | // @as(@Vector(2, i500), [runtime value]) | |
| 2025 | // @as(@Vector(2, i500), [runtime value]) | |
| 2026 | // @as(@Vector(2, i500), [runtime value]) | |
| 2027 | // @as(@Vector(2, i500), [runtime value]) | |
| 2028 | // @as(@Vector(2, i500), [runtime value]) | |
| 2029 | // @as(@Vector(2, i500), undefined) | |
| 2030 | // @as(i500, undefined) | |
| 2031 | // @as(@Vector(2, i500), undefined) | |
| 2032 | // @as(i500, undefined) | |
| 2033 | // @as(i500, undefined) | |
| 2034 | // @as(@Vector(2, i500), undefined) | |
| 2035 | // @as(@Vector(2, i500), undefined) | |
| 2036 | // @as(i500, undefined) | |
| 2037 | // @as(@Vector(2, i500), undefined) | |
| 2038 | // @as(f16, undefined) | |
| 2039 | // @as(f16, undefined) | |
| 2040 | // @as(@Vector(2, f16), .{ 6, undefined }) | |
| 2041 | // @as(@Vector(2, f16), .{ undefined, 6 }) | |
| 2042 | // @as(@Vector(2, f16), undefined) | |
| 2043 | // @as(@Vector(2, f16), .{ 6, undefined }) | |
| 2044 | // @as(@Vector(2, f16), .{ 6, undefined }) | |
| 2045 | // @as(@Vector(2, f16), undefined) | |
| 2046 | // @as(@Vector(2, f16), undefined) | |
| 2047 | // @as(@Vector(2, f16), .{ undefined, 6 }) | |
| 2048 | // @as(@Vector(2, f16), undefined) | |
| 2049 | // @as(@Vector(2, f16), .{ undefined, 6 }) | |
| 2050 | // @as(@Vector(2, f16), undefined) | |
| 2051 | // @as(@Vector(2, f16), undefined) | |
| 2052 | // @as(@Vector(2, f16), undefined) | |
| 2053 | // @as(@Vector(2, f16), undefined) | |
| 2054 | // @as(@Vector(2, f16), undefined) | |
| 2055 | // @as(f16, undefined) | |
| 2056 | // @as(f16, undefined) | |
| 2057 | // @as(@Vector(2, f16), .{ 0, undefined }) | |
| 2058 | // @as(@Vector(2, f16), .{ undefined, 0 }) | |
| 2059 | // @as(@Vector(2, f16), undefined) | |
| 2060 | // @as(@Vector(2, f16), .{ 0, undefined }) | |
| 2061 | // @as(@Vector(2, f16), .{ 0, undefined }) | |
| 2062 | // @as(@Vector(2, f16), undefined) | |
| 2063 | // @as(@Vector(2, f16), undefined) | |
| 2064 | // @as(@Vector(2, f16), .{ undefined, 0 }) | |
| 2065 | // @as(@Vector(2, f16), undefined) | |
| 2066 | // @as(@Vector(2, f16), .{ undefined, 0 }) | |
| 2067 | // @as(@Vector(2, f16), undefined) | |
| 2068 | // @as(@Vector(2, f16), undefined) | |
| 2069 | // @as(@Vector(2, f16), undefined) | |
| 2070 | // @as(@Vector(2, f16), undefined) | |
| 2071 | // @as(@Vector(2, f16), undefined) | |
| 2072 | // @as(f16, undefined) | |
| 2073 | // @as(f16, undefined) | |
| 2074 | // @as(@Vector(2, f16), .{ 9, undefined }) | |
| 2075 | // @as(@Vector(2, f16), .{ undefined, 9 }) | |
| 2076 | // @as(@Vector(2, f16), undefined) | |
| 2077 | // @as(@Vector(2, f16), .{ 9, undefined }) | |
| 2078 | // @as(@Vector(2, f16), .{ 9, undefined }) | |
| 2079 | // @as(@Vector(2, f16), undefined) | |
| 2080 | // @as(@Vector(2, f16), undefined) | |
| 2081 | // @as(@Vector(2, f16), .{ undefined, 9 }) | |
| 2082 | // @as(@Vector(2, f16), undefined) | |
| 2083 | // @as(@Vector(2, f16), .{ undefined, 9 }) | |
| 2084 | // @as(@Vector(2, f16), undefined) | |
| 2085 | // @as(@Vector(2, f16), undefined) | |
| 2086 | // @as(@Vector(2, f16), undefined) | |
| 2087 | // @as(@Vector(2, f16), undefined) | |
| 2088 | // @as(@Vector(2, f16), undefined) | |
| 2089 | // @as(f16, undefined) | |
| 2090 | // @as(@Vector(2, f16), .{ -3, undefined }) | |
| 2091 | // @as(@Vector(2, f16), .{ undefined, -3 }) | |
| 2092 | // @as(@Vector(2, f16), undefined) | |
| 2093 | // @as(f16, undefined) | |
| 2094 | // @as(f16, undefined) | |
| 2095 | // @as(@Vector(2, f16), [runtime value]) | |
| 2096 | // @as(@Vector(2, f16), [runtime value]) | |
| 2097 | // @as(@Vector(2, f16), undefined) | |
| 2098 | // @as(@Vector(2, f16), [runtime value]) | |
| 2099 | // @as(@Vector(2, f16), [runtime value]) | |
| 2100 | // @as(@Vector(2, f16), [runtime value]) | |
| 2101 | // @as(@Vector(2, f16), undefined) | |
| 2102 | // @as(@Vector(2, f16), [runtime value]) | |
| 2103 | // @as(@Vector(2, f16), [runtime value]) | |
| 2104 | // @as(@Vector(2, f16), [runtime value]) | |
| 2105 | // @as(@Vector(2, f16), undefined) | |
| 2106 | // @as(@Vector(2, f16), undefined) | |
| 2107 | // @as(@Vector(2, f16), undefined) | |
| 2108 | // @as(@Vector(2, f16), undefined) | |
| 2109 | // @as(@Vector(2, f16), undefined) | |
| 2110 | // @as(f16, undefined) | |
| 2111 | // @as(f16, undefined) | |
| 2112 | // @as(@Vector(2, f16), [runtime value]) | |
| 2113 | // @as(@Vector(2, f16), [runtime value]) | |
| 2114 | // @as(@Vector(2, f16), undefined) | |
| 2115 | // @as(@Vector(2, f16), [runtime value]) | |
| 2116 | // @as(@Vector(2, f16), [runtime value]) | |
| 2117 | // @as(@Vector(2, f16), [runtime value]) | |
| 2118 | // @as(@Vector(2, f16), undefined) | |
| 2119 | // @as(@Vector(2, f16), [runtime value]) | |
| 2120 | // @as(@Vector(2, f16), [runtime value]) | |
| 2121 | // @as(@Vector(2, f16), [runtime value]) | |
| 2122 | // @as(@Vector(2, f16), undefined) | |
| 2123 | // @as(@Vector(2, f16), undefined) | |
| 2124 | // @as(@Vector(2, f16), undefined) | |
| 2125 | // @as(@Vector(2, f16), undefined) | |
| 2126 | // @as(@Vector(2, f16), undefined) | |
| 2127 | // @as(f16, undefined) | |
| 2128 | // @as(f16, undefined) | |
| 2129 | // @as(@Vector(2, f16), [runtime value]) | |
| 2130 | // @as(@Vector(2, f16), [runtime value]) | |
| 2131 | // @as(@Vector(2, f16), undefined) | |
| 2132 | // @as(@Vector(2, f16), [runtime value]) | |
| 2133 | // @as(@Vector(2, f16), [runtime value]) | |
| 2134 | // @as(@Vector(2, f16), [runtime value]) | |
| 2135 | // @as(@Vector(2, f16), undefined) | |
| 2136 | // @as(@Vector(2, f16), [runtime value]) | |
| 2137 | // @as(@Vector(2, f16), [runtime value]) | |
| 2138 | // @as(@Vector(2, f16), [runtime value]) | |
| 2139 | // @as(@Vector(2, f16), undefined) | |
| 2140 | // @as(@Vector(2, f16), undefined) | |
| 2141 | // @as(@Vector(2, f16), undefined) | |
| 2142 | // @as(@Vector(2, f16), undefined) | |
| 2143 | // @as(@Vector(2, f16), undefined) | |
| 2144 | // @as(f16, undefined) | |
| 2145 | // @as(@Vector(2, f16), [runtime value]) | |
| 2146 | // @as(@Vector(2, f16), [runtime value]) | |
| 2147 | // @as(@Vector(2, f16), undefined) | |
| 2148 | // @as(f32, undefined) | |
| 2149 | // @as(f32, undefined) | |
| 2150 | // @as(@Vector(2, f32), .{ 6, undefined }) | |
| 2151 | // @as(@Vector(2, f32), .{ undefined, 6 }) | |
| 2152 | // @as(@Vector(2, f32), undefined) | |
| 2153 | // @as(@Vector(2, f32), .{ 6, undefined }) | |
| 2154 | // @as(@Vector(2, f32), .{ 6, undefined }) | |
| 2155 | // @as(@Vector(2, f32), undefined) | |
| 2156 | // @as(@Vector(2, f32), undefined) | |
| 2157 | // @as(@Vector(2, f32), .{ undefined, 6 }) | |
| 2158 | // @as(@Vector(2, f32), undefined) | |
| 2159 | // @as(@Vector(2, f32), .{ undefined, 6 }) | |
| 2160 | // @as(@Vector(2, f32), undefined) | |
| 2161 | // @as(@Vector(2, f32), undefined) | |
| 2162 | // @as(@Vector(2, f32), undefined) | |
| 2163 | // @as(@Vector(2, f32), undefined) | |
| 2164 | // @as(@Vector(2, f32), undefined) | |
| 2165 | // @as(f32, undefined) | |
| 2166 | // @as(f32, undefined) | |
| 2167 | // @as(@Vector(2, f32), .{ 0, undefined }) | |
| 2168 | // @as(@Vector(2, f32), .{ undefined, 0 }) | |
| 2169 | // @as(@Vector(2, f32), undefined) | |
| 2170 | // @as(@Vector(2, f32), .{ 0, undefined }) | |
| 2171 | // @as(@Vector(2, f32), .{ 0, undefined }) | |
| 2172 | // @as(@Vector(2, f32), undefined) | |
| 2173 | // @as(@Vector(2, f32), undefined) | |
| 2174 | // @as(@Vector(2, f32), .{ undefined, 0 }) | |
| 2175 | // @as(@Vector(2, f32), undefined) | |
| 2176 | // @as(@Vector(2, f32), .{ undefined, 0 }) | |
| 2177 | // @as(@Vector(2, f32), undefined) | |
| 2178 | // @as(@Vector(2, f32), undefined) | |
| 2179 | // @as(@Vector(2, f32), undefined) | |
| 2180 | // @as(@Vector(2, f32), undefined) | |
| 2181 | // @as(@Vector(2, f32), undefined) | |
| 2182 | // @as(f32, undefined) | |
| 2183 | // @as(f32, undefined) | |
| 2184 | // @as(@Vector(2, f32), .{ 9, undefined }) | |
| 2185 | // @as(@Vector(2, f32), .{ undefined, 9 }) | |
| 2186 | // @as(@Vector(2, f32), undefined) | |
| 2187 | // @as(@Vector(2, f32), .{ 9, undefined }) | |
| 2188 | // @as(@Vector(2, f32), .{ 9, undefined }) | |
| 2189 | // @as(@Vector(2, f32), undefined) | |
| 2190 | // @as(@Vector(2, f32), undefined) | |
| 2191 | // @as(@Vector(2, f32), .{ undefined, 9 }) | |
| 2192 | // @as(@Vector(2, f32), undefined) | |
| 2193 | // @as(@Vector(2, f32), .{ undefined, 9 }) | |
| 2194 | // @as(@Vector(2, f32), undefined) | |
| 2195 | // @as(@Vector(2, f32), undefined) | |
| 2196 | // @as(@Vector(2, f32), undefined) | |
| 2197 | // @as(@Vector(2, f32), undefined) | |
| 2198 | // @as(@Vector(2, f32), undefined) | |
| 2199 | // @as(f32, undefined) | |
| 2200 | // @as(@Vector(2, f32), .{ -3, undefined }) | |
| 2201 | // @as(@Vector(2, f32), .{ undefined, -3 }) | |
| 2202 | // @as(@Vector(2, f32), undefined) | |
| 2203 | // @as(f32, undefined) | |
| 2204 | // @as(f32, undefined) | |
| 2205 | // @as(@Vector(2, f32), [runtime value]) | |
| 2206 | // @as(@Vector(2, f32), [runtime value]) | |
| 2207 | // @as(@Vector(2, f32), undefined) | |
| 2208 | // @as(@Vector(2, f32), [runtime value]) | |
| 2209 | // @as(@Vector(2, f32), [runtime value]) | |
| 2210 | // @as(@Vector(2, f32), [runtime value]) | |
| 2211 | // @as(@Vector(2, f32), undefined) | |
| 2212 | // @as(@Vector(2, f32), [runtime value]) | |
| 2213 | // @as(@Vector(2, f32), [runtime value]) | |
| 2214 | // @as(@Vector(2, f32), [runtime value]) | |
| 2215 | // @as(@Vector(2, f32), undefined) | |
| 2216 | // @as(@Vector(2, f32), undefined) | |
| 2217 | // @as(@Vector(2, f32), undefined) | |
| 2218 | // @as(@Vector(2, f32), undefined) | |
| 2219 | // @as(@Vector(2, f32), undefined) | |
| 2220 | // @as(f32, undefined) | |
| 2221 | // @as(f32, undefined) | |
| 2222 | // @as(@Vector(2, f32), [runtime value]) | |
| 2223 | // @as(@Vector(2, f32), [runtime value]) | |
| 2224 | // @as(@Vector(2, f32), undefined) | |
| 2225 | // @as(@Vector(2, f32), [runtime value]) | |
| 2226 | // @as(@Vector(2, f32), [runtime value]) | |
| 2227 | // @as(@Vector(2, f32), [runtime value]) | |
| 2228 | // @as(@Vector(2, f32), undefined) | |
| 2229 | // @as(@Vector(2, f32), [runtime value]) | |
| 2230 | // @as(@Vector(2, f32), [runtime value]) | |
| 2231 | // @as(@Vector(2, f32), [runtime value]) | |
| 2232 | // @as(@Vector(2, f32), undefined) | |
| 2233 | // @as(@Vector(2, f32), undefined) | |
| 2234 | // @as(@Vector(2, f32), undefined) | |
| 2235 | // @as(@Vector(2, f32), undefined) | |
| 2236 | // @as(@Vector(2, f32), undefined) | |
| 2237 | // @as(f32, undefined) | |
| 2238 | // @as(f32, undefined) | |
| 2239 | // @as(@Vector(2, f32), [runtime value]) | |
| 2240 | // @as(@Vector(2, f32), [runtime value]) | |
| 2241 | // @as(@Vector(2, f32), undefined) | |
| 2242 | // @as(@Vector(2, f32), [runtime value]) | |
| 2243 | // @as(@Vector(2, f32), [runtime value]) | |
| 2244 | // @as(@Vector(2, f32), [runtime value]) | |
| 2245 | // @as(@Vector(2, f32), undefined) | |
| 2246 | // @as(@Vector(2, f32), [runtime value]) | |
| 2247 | // @as(@Vector(2, f32), [runtime value]) | |
| 2248 | // @as(@Vector(2, f32), [runtime value]) | |
| 2249 | // @as(@Vector(2, f32), undefined) | |
| 2250 | // @as(@Vector(2, f32), undefined) | |
| 2251 | // @as(@Vector(2, f32), undefined) | |
| 2252 | // @as(@Vector(2, f32), undefined) | |
| 2253 | // @as(@Vector(2, f32), undefined) | |
| 2254 | // @as(f32, undefined) | |
| 2255 | // @as(@Vector(2, f32), [runtime value]) | |
| 2256 | // @as(@Vector(2, f32), [runtime value]) | |
| 2257 | // @as(@Vector(2, f32), undefined) | |
| 2258 | // @as(f64, undefined) | |
| 2259 | // @as(f64, undefined) | |
| 2260 | // @as(@Vector(2, f64), .{ 6, undefined }) | |
| 2261 | // @as(@Vector(2, f64), .{ undefined, 6 }) | |
| 2262 | // @as(@Vector(2, f64), undefined) | |
| 2263 | // @as(@Vector(2, f64), .{ 6, undefined }) | |
| 2264 | // @as(@Vector(2, f64), .{ 6, undefined }) | |
| 2265 | // @as(@Vector(2, f64), undefined) | |
| 2266 | // @as(@Vector(2, f64), undefined) | |
| 2267 | // @as(@Vector(2, f64), .{ undefined, 6 }) | |
| 2268 | // @as(@Vector(2, f64), undefined) | |
| 2269 | // @as(@Vector(2, f64), .{ undefined, 6 }) | |
| 2270 | // @as(@Vector(2, f64), undefined) | |
| 2271 | // @as(@Vector(2, f64), undefined) | |
| 2272 | // @as(@Vector(2, f64), undefined) | |
| 2273 | // @as(@Vector(2, f64), undefined) | |
| 2274 | // @as(@Vector(2, f64), undefined) | |
| 2275 | // @as(f64, undefined) | |
| 2276 | // @as(f64, undefined) | |
| 2277 | // @as(@Vector(2, f64), .{ 0, undefined }) | |
| 2278 | // @as(@Vector(2, f64), .{ undefined, 0 }) | |
| 2279 | // @as(@Vector(2, f64), undefined) | |
| 2280 | // @as(@Vector(2, f64), .{ 0, undefined }) | |
| 2281 | // @as(@Vector(2, f64), .{ 0, undefined }) | |
| 2282 | // @as(@Vector(2, f64), undefined) | |
| 2283 | // @as(@Vector(2, f64), undefined) | |
| 2284 | // @as(@Vector(2, f64), .{ undefined, 0 }) | |
| 2285 | // @as(@Vector(2, f64), undefined) | |
| 2286 | // @as(@Vector(2, f64), .{ undefined, 0 }) | |
| 2287 | // @as(@Vector(2, f64), undefined) | |
| 2288 | // @as(@Vector(2, f64), undefined) | |
| 2289 | // @as(@Vector(2, f64), undefined) | |
| 2290 | // @as(@Vector(2, f64), undefined) | |
| 2291 | // @as(@Vector(2, f64), undefined) | |
| 2292 | // @as(f64, undefined) | |
| 2293 | // @as(f64, undefined) | |
| 2294 | // @as(@Vector(2, f64), .{ 9, undefined }) | |
| 2295 | // @as(@Vector(2, f64), .{ undefined, 9 }) | |
| 2296 | // @as(@Vector(2, f64), undefined) | |
| 2297 | // @as(@Vector(2, f64), .{ 9, undefined }) | |
| 2298 | // @as(@Vector(2, f64), .{ 9, undefined }) | |
| 2299 | // @as(@Vector(2, f64), undefined) | |
| 2300 | // @as(@Vector(2, f64), undefined) | |
| 2301 | // @as(@Vector(2, f64), .{ undefined, 9 }) | |
| 2302 | // @as(@Vector(2, f64), undefined) | |
| 2303 | // @as(@Vector(2, f64), .{ undefined, 9 }) | |
| 2304 | // @as(@Vector(2, f64), undefined) | |
| 2305 | // @as(@Vector(2, f64), undefined) | |
| 2306 | // @as(@Vector(2, f64), undefined) | |
| 2307 | // @as(@Vector(2, f64), undefined) | |
| 2308 | // @as(@Vector(2, f64), undefined) | |
| 2309 | // @as(f64, undefined) | |
| 2310 | // @as(@Vector(2, f64), .{ -3, undefined }) | |
| 2311 | // @as(@Vector(2, f64), .{ undefined, -3 }) | |
| 2312 | // @as(@Vector(2, f64), undefined) | |
| 2313 | // @as(f64, undefined) | |
| 2314 | // @as(f64, undefined) | |
| 2315 | // @as(@Vector(2, f64), [runtime value]) | |
| 2316 | // @as(@Vector(2, f64), [runtime value]) | |
| 2317 | // @as(@Vector(2, f64), undefined) | |
| 2318 | // @as(@Vector(2, f64), [runtime value]) | |
| 2319 | // @as(@Vector(2, f64), [runtime value]) | |
| 2320 | // @as(@Vector(2, f64), [runtime value]) | |
| 2321 | // @as(@Vector(2, f64), undefined) | |
| 2322 | // @as(@Vector(2, f64), [runtime value]) | |
| 2323 | // @as(@Vector(2, f64), [runtime value]) | |
| 2324 | // @as(@Vector(2, f64), [runtime value]) | |
| 2325 | // @as(@Vector(2, f64), undefined) | |
| 2326 | // @as(@Vector(2, f64), undefined) | |
| 2327 | // @as(@Vector(2, f64), undefined) | |
| 2328 | // @as(@Vector(2, f64), undefined) | |
| 2329 | // @as(@Vector(2, f64), undefined) | |
| 2330 | // @as(f64, undefined) | |
| 2331 | // @as(f64, undefined) | |
| 2332 | // @as(@Vector(2, f64), [runtime value]) | |
| 2333 | // @as(@Vector(2, f64), [runtime value]) | |
| 2334 | // @as(@Vector(2, f64), undefined) | |
| 2335 | // @as(@Vector(2, f64), [runtime value]) | |
| 2336 | // @as(@Vector(2, f64), [runtime value]) | |
| 2337 | // @as(@Vector(2, f64), [runtime value]) | |
| 2338 | // @as(@Vector(2, f64), undefined) | |
| 2339 | // @as(@Vector(2, f64), [runtime value]) | |
| 2340 | // @as(@Vector(2, f64), [runtime value]) | |
| 2341 | // @as(@Vector(2, f64), [runtime value]) | |
| 2342 | // @as(@Vector(2, f64), undefined) | |
| 2343 | // @as(@Vector(2, f64), undefined) | |
| 2344 | // @as(@Vector(2, f64), undefined) | |
| 2345 | // @as(@Vector(2, f64), undefined) | |
| 2346 | // @as(@Vector(2, f64), undefined) | |
| 2347 | // @as(f64, undefined) | |
| 2348 | // @as(f64, undefined) | |
| 2349 | // @as(@Vector(2, f64), [runtime value]) | |
| 2350 | // @as(@Vector(2, f64), [runtime value]) | |
| 2351 | // @as(@Vector(2, f64), undefined) | |
| 2352 | // @as(@Vector(2, f64), [runtime value]) | |
| 2353 | // @as(@Vector(2, f64), [runtime value]) | |
| 2354 | // @as(@Vector(2, f64), [runtime value]) | |
| 2355 | // @as(@Vector(2, f64), undefined) | |
| 2356 | // @as(@Vector(2, f64), [runtime value]) | |
| 2357 | // @as(@Vector(2, f64), [runtime value]) | |
| 2358 | // @as(@Vector(2, f64), [runtime value]) | |
| 2359 | // @as(@Vector(2, f64), undefined) | |
| 2360 | // @as(@Vector(2, f64), undefined) | |
| 2361 | // @as(@Vector(2, f64), undefined) | |
| 2362 | // @as(@Vector(2, f64), undefined) | |
| 2363 | // @as(@Vector(2, f64), undefined) | |
| 2364 | // @as(f64, undefined) | |
| 2365 | // @as(@Vector(2, f64), [runtime value]) | |
| 2366 | // @as(@Vector(2, f64), [runtime value]) | |
| 2367 | // @as(@Vector(2, f64), undefined) | |
| 2368 | // @as(f80, undefined) | |
| 2369 | // @as(f80, undefined) | |
| 2370 | // @as(@Vector(2, f80), .{ 6, undefined }) | |
| 2371 | // @as(@Vector(2, f80), .{ undefined, 6 }) | |
| 2372 | // @as(@Vector(2, f80), undefined) | |
| 2373 | // @as(@Vector(2, f80), .{ 6, undefined }) | |
| 2374 | // @as(@Vector(2, f80), .{ 6, undefined }) | |
| 2375 | // @as(@Vector(2, f80), undefined) | |
| 2376 | // @as(@Vector(2, f80), undefined) | |
| 2377 | // @as(@Vector(2, f80), .{ undefined, 6 }) | |
| 2378 | // @as(@Vector(2, f80), undefined) | |
| 2379 | // @as(@Vector(2, f80), .{ undefined, 6 }) | |
| 2380 | // @as(@Vector(2, f80), undefined) | |
| 2381 | // @as(@Vector(2, f80), undefined) | |
| 2382 | // @as(@Vector(2, f80), undefined) | |
| 2383 | // @as(@Vector(2, f80), undefined) | |
| 2384 | // @as(@Vector(2, f80), undefined) | |
| 2385 | // @as(f80, undefined) | |
| 2386 | // @as(f80, undefined) | |
| 2387 | // @as(@Vector(2, f80), .{ 0, undefined }) | |
| 2388 | // @as(@Vector(2, f80), .{ undefined, 0 }) | |
| 2389 | // @as(@Vector(2, f80), undefined) | |
| 2390 | // @as(@Vector(2, f80), .{ 0, undefined }) | |
| 2391 | // @as(@Vector(2, f80), .{ 0, undefined }) | |
| 2392 | // @as(@Vector(2, f80), undefined) | |
| 2393 | // @as(@Vector(2, f80), undefined) | |
| 2394 | // @as(@Vector(2, f80), .{ undefined, 0 }) | |
| 2395 | // @as(@Vector(2, f80), undefined) | |
| 2396 | // @as(@Vector(2, f80), .{ undefined, 0 }) | |
| 2397 | // @as(@Vector(2, f80), undefined) | |
| 2398 | // @as(@Vector(2, f80), undefined) | |
| 2399 | // @as(@Vector(2, f80), undefined) | |
| 2400 | // @as(@Vector(2, f80), undefined) | |
| 2401 | // @as(@Vector(2, f80), undefined) | |
| 2402 | // @as(f80, undefined) | |
| 2403 | // @as(f80, undefined) | |
| 2404 | // @as(@Vector(2, f80), .{ 9, undefined }) | |
| 2405 | // @as(@Vector(2, f80), .{ undefined, 9 }) | |
| 2406 | // @as(@Vector(2, f80), undefined) | |
| 2407 | // @as(@Vector(2, f80), .{ 9, undefined }) | |
| 2408 | // @as(@Vector(2, f80), .{ 9, undefined }) | |
| 2409 | // @as(@Vector(2, f80), undefined) | |
| 2410 | // @as(@Vector(2, f80), undefined) | |
| 2411 | // @as(@Vector(2, f80), .{ undefined, 9 }) | |
| 2412 | // @as(@Vector(2, f80), undefined) | |
| 2413 | // @as(@Vector(2, f80), .{ undefined, 9 }) | |
| 2414 | // @as(@Vector(2, f80), undefined) | |
| 2415 | // @as(@Vector(2, f80), undefined) | |
| 2416 | // @as(@Vector(2, f80), undefined) | |
| 2417 | // @as(@Vector(2, f80), undefined) | |
| 2418 | // @as(@Vector(2, f80), undefined) | |
| 2419 | // @as(f80, undefined) | |
| 2420 | // @as(@Vector(2, f80), .{ -3, undefined }) | |
| 2421 | // @as(@Vector(2, f80), .{ undefined, -3 }) | |
| 2422 | // @as(@Vector(2, f80), undefined) | |
| 2423 | // @as(f80, undefined) | |
| 2424 | // @as(f80, undefined) | |
| 2425 | // @as(@Vector(2, f80), [runtime value]) | |
| 2426 | // @as(@Vector(2, f80), [runtime value]) | |
| 2427 | // @as(@Vector(2, f80), undefined) | |
| 2428 | // @as(@Vector(2, f80), [runtime value]) | |
| 2429 | // @as(@Vector(2, f80), [runtime value]) | |
| 2430 | // @as(@Vector(2, f80), [runtime value]) | |
| 2431 | // @as(@Vector(2, f80), undefined) | |
| 2432 | // @as(@Vector(2, f80), [runtime value]) | |
| 2433 | // @as(@Vector(2, f80), [runtime value]) | |
| 2434 | // @as(@Vector(2, f80), [runtime value]) | |
| 2435 | // @as(@Vector(2, f80), undefined) | |
| 2436 | // @as(@Vector(2, f80), undefined) | |
| 2437 | // @as(@Vector(2, f80), undefined) | |
| 2438 | // @as(@Vector(2, f80), undefined) | |
| 2439 | // @as(@Vector(2, f80), undefined) | |
| 2440 | // @as(f80, undefined) | |
| 2441 | // @as(f80, undefined) | |
| 2442 | // @as(@Vector(2, f80), [runtime value]) | |
| 2443 | // @as(@Vector(2, f80), [runtime value]) | |
| 2444 | // @as(@Vector(2, f80), undefined) | |
| 2445 | // @as(@Vector(2, f80), [runtime value]) | |
| 2446 | // @as(@Vector(2, f80), [runtime value]) | |
| 2447 | // @as(@Vector(2, f80), [runtime value]) | |
| 2448 | // @as(@Vector(2, f80), undefined) | |
| 2449 | // @as(@Vector(2, f80), [runtime value]) | |
| 2450 | // @as(@Vector(2, f80), [runtime value]) | |
| 2451 | // @as(@Vector(2, f80), [runtime value]) | |
| 2452 | // @as(@Vector(2, f80), undefined) | |
| 2453 | // @as(@Vector(2, f80), undefined) | |
| 2454 | // @as(@Vector(2, f80), undefined) | |
| 2455 | // @as(@Vector(2, f80), undefined) | |
| 2456 | // @as(@Vector(2, f80), undefined) | |
| 2457 | // @as(f80, undefined) | |
| 2458 | // @as(f80, undefined) | |
| 2459 | // @as(@Vector(2, f80), [runtime value]) | |
| 2460 | // @as(@Vector(2, f80), [runtime value]) | |
| 2461 | // @as(@Vector(2, f80), undefined) | |
| 2462 | // @as(@Vector(2, f80), [runtime value]) | |
| 2463 | // @as(@Vector(2, f80), [runtime value]) | |
| 2464 | // @as(@Vector(2, f80), [runtime value]) | |
| 2465 | // @as(@Vector(2, f80), undefined) | |
| 2466 | // @as(@Vector(2, f80), [runtime value]) | |
| 2467 | // @as(@Vector(2, f80), [runtime value]) | |
| 2468 | // @as(@Vector(2, f80), [runtime value]) | |
| 2469 | // @as(@Vector(2, f80), undefined) | |
| 2470 | // @as(@Vector(2, f80), undefined) | |
| 2471 | // @as(@Vector(2, f80), undefined) | |
| 2472 | // @as(@Vector(2, f80), undefined) | |
| 2473 | // @as(@Vector(2, f80), undefined) | |
| 2474 | // @as(f80, undefined) | |
| 2475 | // @as(@Vector(2, f80), [runtime value]) | |
| 2476 | // @as(@Vector(2, f80), [runtime value]) | |
| 2477 | // @as(@Vector(2, f80), undefined) | |
| 684 | // @as(i500, undefined) | |
| 685 | // @as(i500, undefined) | |
| 686 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 687 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 688 | // @as(@Vector(2, i500), undefined) | |
| 689 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 690 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 691 | // @as(@Vector(2, i500), undefined) | |
| 692 | // @as(@Vector(2, i500), undefined) | |
| 693 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 694 | // @as(@Vector(2, i500), undefined) | |
| 695 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 696 | // @as(@Vector(2, i500), undefined) | |
| 697 | // @as(@Vector(2, i500), undefined) | |
| 698 | // @as(@Vector(2, i500), undefined) | |
| 699 | // @as(@Vector(2, i500), undefined) | |
| 700 | // @as(@Vector(2, i500), undefined) | |
| 701 | // @as(i500, undefined) | |
| 702 | // @as(i500, undefined) | |
| 703 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 704 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 705 | // @as(@Vector(2, i500), undefined) | |
| 706 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 707 | // @as(@Vector(2, i500), .{ 6, undefined }) | |
| 708 | // @as(@Vector(2, i500), undefined) | |
| 709 | // @as(@Vector(2, i500), undefined) | |
| 710 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 711 | // @as(@Vector(2, i500), undefined) | |
| 712 | // @as(@Vector(2, i500), .{ undefined, 6 }) | |
| 713 | // @as(@Vector(2, i500), undefined) | |
| 714 | // @as(@Vector(2, i500), undefined) | |
| 715 | // @as(@Vector(2, i500), undefined) | |
| 716 | // @as(@Vector(2, i500), undefined) | |
| 717 | // @as(@Vector(2, i500), undefined) | |
| 718 | // @as(i500, undefined) | |
| 719 | // @as(i500, undefined) | |
| 720 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 721 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 722 | // @as(@Vector(2, i500), undefined) | |
| 723 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 724 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 725 | // @as(@Vector(2, i500), undefined) | |
| 726 | // @as(@Vector(2, i500), undefined) | |
| 727 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 728 | // @as(@Vector(2, i500), undefined) | |
| 729 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 730 | // @as(@Vector(2, i500), undefined) | |
| 731 | // @as(@Vector(2, i500), undefined) | |
| 732 | // @as(@Vector(2, i500), undefined) | |
| 733 | // @as(@Vector(2, i500), undefined) | |
| 734 | // @as(@Vector(2, i500), undefined) | |
| 735 | // @as(i500, undefined) | |
| 736 | // @as(i500, undefined) | |
| 737 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 738 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 739 | // @as(@Vector(2, i500), undefined) | |
| 740 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 741 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 742 | // @as(@Vector(2, i500), undefined) | |
| 743 | // @as(@Vector(2, i500), undefined) | |
| 744 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 745 | // @as(@Vector(2, i500), undefined) | |
| 746 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 747 | // @as(@Vector(2, i500), undefined) | |
| 748 | // @as(@Vector(2, i500), undefined) | |
| 749 | // @as(@Vector(2, i500), undefined) | |
| 750 | // @as(@Vector(2, i500), undefined) | |
| 751 | // @as(@Vector(2, i500), undefined) | |
| 752 | // @as(i500, undefined) | |
| 753 | // @as(i500, undefined) | |
| 754 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 755 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 756 | // @as(@Vector(2, i500), undefined) | |
| 757 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 758 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 759 | // @as(@Vector(2, i500), undefined) | |
| 760 | // @as(@Vector(2, i500), undefined) | |
| 761 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 762 | // @as(@Vector(2, i500), undefined) | |
| 763 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 764 | // @as(@Vector(2, i500), undefined) | |
| 765 | // @as(@Vector(2, i500), undefined) | |
| 766 | // @as(@Vector(2, i500), undefined) | |
| 767 | // @as(@Vector(2, i500), undefined) | |
| 768 | // @as(@Vector(2, i500), undefined) | |
| 769 | // @as(i500, undefined) | |
| 770 | // @as(i500, undefined) | |
| 771 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 772 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 773 | // @as(@Vector(2, i500), undefined) | |
| 774 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 775 | // @as(@Vector(2, i500), .{ 9, undefined }) | |
| 776 | // @as(@Vector(2, i500), undefined) | |
| 777 | // @as(@Vector(2, i500), undefined) | |
| 778 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 779 | // @as(@Vector(2, i500), undefined) | |
| 780 | // @as(@Vector(2, i500), .{ undefined, 9 }) | |
| 781 | // @as(@Vector(2, i500), undefined) | |
| 782 | // @as(@Vector(2, i500), undefined) | |
| 783 | // @as(@Vector(2, i500), undefined) | |
| 784 | // @as(@Vector(2, i500), undefined) | |
| 785 | // @as(@Vector(2, i500), undefined) | |
| 786 | // @as(i500, undefined) | |
| 787 | // @as(i500, undefined) | |
| 788 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 789 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 790 | // @as(@Vector(2, i500), undefined) | |
| 791 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 792 | // @as(@Vector(2, i500), .{ 0, undefined }) | |
| 793 | // @as(@Vector(2, i500), undefined) | |
| 794 | // @as(@Vector(2, i500), undefined) | |
| 795 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 796 | // @as(@Vector(2, i500), undefined) | |
| 797 | // @as(@Vector(2, i500), .{ undefined, 0 }) | |
| 798 | // @as(@Vector(2, i500), undefined) | |
| 799 | // @as(@Vector(2, i500), undefined) | |
| 800 | // @as(@Vector(2, i500), undefined) | |
| 801 | // @as(@Vector(2, i500), undefined) | |
| 802 | // @as(@Vector(2, i500), undefined) | |
| 803 | // @as(i500, undefined) | |
| 804 | // @as(@Vector(2, i500), undefined) | |
| 805 | // @as(i500, undefined) | |
| 806 | // @as(i500, undefined) | |
| 807 | // @as(@Vector(2, i500), undefined) | |
| 808 | // @as(@Vector(2, i500), undefined) | |
| 809 | // @as(i500, undefined) | |
| 810 | // @as(@Vector(2, i500), undefined) | |
| 811 | // @as(i500, undefined) | |
| 812 | // @as(i500, undefined) | |
| 813 | // @as(@Vector(2, i500), [runtime value]) | |
| 814 | // @as(@Vector(2, i500), [runtime value]) | |
| 815 | // @as(@Vector(2, i500), undefined) | |
| 816 | // @as(@Vector(2, i500), [runtime value]) | |
| 817 | // @as(@Vector(2, i500), [runtime value]) | |
| 818 | // @as(@Vector(2, i500), [runtime value]) | |
| 819 | // @as(@Vector(2, i500), undefined) | |
| 820 | // @as(@Vector(2, i500), [runtime value]) | |
| 821 | // @as(@Vector(2, i500), [runtime value]) | |
| 822 | // @as(@Vector(2, i500), [runtime value]) | |
| 823 | // @as(@Vector(2, i500), undefined) | |
| 824 | // @as(@Vector(2, i500), undefined) | |
| 825 | // @as(@Vector(2, i500), undefined) | |
| 826 | // @as(@Vector(2, i500), undefined) | |
| 827 | // @as(@Vector(2, i500), undefined) | |
| 828 | // @as(i500, undefined) | |
| 829 | // @as(i500, undefined) | |
| 830 | // @as(@Vector(2, i500), [runtime value]) | |
| 831 | // @as(@Vector(2, i500), [runtime value]) | |
| 832 | // @as(@Vector(2, i500), undefined) | |
| 833 | // @as(@Vector(2, i500), [runtime value]) | |
| 834 | // @as(@Vector(2, i500), [runtime value]) | |
| 835 | // @as(@Vector(2, i500), [runtime value]) | |
| 836 | // @as(@Vector(2, i500), undefined) | |
| 837 | // @as(@Vector(2, i500), [runtime value]) | |
| 838 | // @as(@Vector(2, i500), [runtime value]) | |
| 839 | // @as(@Vector(2, i500), [runtime value]) | |
| 840 | // @as(@Vector(2, i500), undefined) | |
| 841 | // @as(@Vector(2, i500), undefined) | |
| 842 | // @as(@Vector(2, i500), undefined) | |
| 843 | // @as(@Vector(2, i500), undefined) | |
| 844 | // @as(@Vector(2, i500), undefined) | |
| 845 | // @as(i500, undefined) | |
| 846 | // @as(i500, undefined) | |
| 847 | // @as(@Vector(2, i500), [runtime value]) | |
| 848 | // @as(@Vector(2, i500), [runtime value]) | |
| 849 | // @as(@Vector(2, i500), undefined) | |
| 850 | // @as(@Vector(2, i500), [runtime value]) | |
| 851 | // @as(@Vector(2, i500), [runtime value]) | |
| 852 | // @as(@Vector(2, i500), [runtime value]) | |
| 853 | // @as(@Vector(2, i500), undefined) | |
| 854 | // @as(@Vector(2, i500), [runtime value]) | |
| 855 | // @as(@Vector(2, i500), [runtime value]) | |
| 856 | // @as(@Vector(2, i500), [runtime value]) | |
| 857 | // @as(@Vector(2, i500), undefined) | |
| 858 | // @as(@Vector(2, i500), undefined) | |
| 859 | // @as(@Vector(2, i500), undefined) | |
| 860 | // @as(@Vector(2, i500), undefined) | |
| 861 | // @as(@Vector(2, i500), undefined) | |
| 862 | // @as(i500, undefined) | |
| 863 | // @as(i500, undefined) | |
| 864 | // @as(@Vector(2, i500), [runtime value]) | |
| 865 | // @as(@Vector(2, i500), [runtime value]) | |
| 866 | // @as(@Vector(2, i500), undefined) | |
| 867 | // @as(@Vector(2, i500), [runtime value]) | |
| 868 | // @as(@Vector(2, i500), [runtime value]) | |
| 869 | // @as(@Vector(2, i500), [runtime value]) | |
| 870 | // @as(@Vector(2, i500), undefined) | |
| 871 | // @as(@Vector(2, i500), [runtime value]) | |
| 872 | // @as(@Vector(2, i500), [runtime value]) | |
| 873 | // @as(@Vector(2, i500), [runtime value]) | |
| 874 | // @as(@Vector(2, i500), undefined) | |
| 875 | // @as(@Vector(2, i500), undefined) | |
| 876 | // @as(@Vector(2, i500), undefined) | |
| 877 | // @as(@Vector(2, i500), undefined) | |
| 878 | // @as(@Vector(2, i500), undefined) | |
| 879 | // @as(i500, undefined) | |
| 880 | // @as(i500, undefined) | |
| 881 | // @as(@Vector(2, i500), [runtime value]) | |
| 882 | // @as(@Vector(2, i500), [runtime value]) | |
| 883 | // @as(@Vector(2, i500), undefined) | |
| 884 | // @as(@Vector(2, i500), [runtime value]) | |
| 885 | // @as(@Vector(2, i500), [runtime value]) | |
| 886 | // @as(@Vector(2, i500), [runtime value]) | |
| 887 | // @as(@Vector(2, i500), undefined) | |
| 888 | // @as(@Vector(2, i500), [runtime value]) | |
| 889 | // @as(@Vector(2, i500), [runtime value]) | |
| 890 | // @as(@Vector(2, i500), [runtime value]) | |
| 891 | // @as(@Vector(2, i500), undefined) | |
| 892 | // @as(@Vector(2, i500), undefined) | |
| 893 | // @as(@Vector(2, i500), undefined) | |
| 894 | // @as(@Vector(2, i500), undefined) | |
| 895 | // @as(@Vector(2, i500), undefined) | |
| 896 | // @as(i500, undefined) | |
| 897 | // @as(i500, undefined) | |
| 898 | // @as(@Vector(2, i500), [runtime value]) | |
| 899 | // @as(@Vector(2, i500), [runtime value]) | |
| 900 | // @as(@Vector(2, i500), undefined) | |
| 901 | // @as(@Vector(2, i500), [runtime value]) | |
| 902 | // @as(@Vector(2, i500), [runtime value]) | |
| 903 | // @as(@Vector(2, i500), [runtime value]) | |
| 904 | // @as(@Vector(2, i500), undefined) | |
| 905 | // @as(@Vector(2, i500), [runtime value]) | |
| 906 | // @as(@Vector(2, i500), [runtime value]) | |
| 907 | // @as(@Vector(2, i500), [runtime value]) | |
| 908 | // @as(@Vector(2, i500), undefined) | |
| 909 | // @as(@Vector(2, i500), undefined) | |
| 910 | // @as(@Vector(2, i500), undefined) | |
| 911 | // @as(@Vector(2, i500), undefined) | |
| 912 | // @as(@Vector(2, i500), undefined) | |
| 913 | // @as(i500, [runtime value]) | |
| 914 | // @as(i500, [runtime value]) | |
| 915 | // @as(@Vector(2, i500), [runtime value]) | |
| 916 | // @as(@Vector(2, i500), [runtime value]) | |
| 917 | // @as(@Vector(2, i500), [runtime value]) | |
| 918 | // @as(@Vector(2, i500), [runtime value]) | |
| 919 | // @as(@Vector(2, i500), [runtime value]) | |
| 920 | // @as(@Vector(2, i500), [runtime value]) | |
| 921 | // @as(@Vector(2, i500), [runtime value]) | |
| 922 | // @as(@Vector(2, i500), [runtime value]) | |
| 923 | // @as(@Vector(2, i500), [runtime value]) | |
| 924 | // @as(@Vector(2, i500), [runtime value]) | |
| 925 | // @as(@Vector(2, i500), [runtime value]) | |
| 926 | // @as(@Vector(2, i500), [runtime value]) | |
| 927 | // @as(@Vector(2, i500), [runtime value]) | |
| 928 | // @as(@Vector(2, i500), [runtime value]) | |
| 929 | // @as(@Vector(2, i500), undefined) | |
| 930 | // @as(i500, undefined) | |
| 931 | // @as(@Vector(2, i500), undefined) | |
| 932 | // @as(i500, undefined) | |
| 933 | // @as(i500, undefined) | |
| 934 | // @as(@Vector(2, i500), undefined) | |
| 935 | // @as(@Vector(2, i500), undefined) | |
| 936 | // @as(i500, undefined) | |
| 937 | // @as(@Vector(2, i500), undefined) | |
| 938 | // @as(u500, undefined) | |
| 939 | // @as(u500, undefined) | |
| 940 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 941 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 942 | // @as(@Vector(2, u500), undefined) | |
| 943 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 944 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 945 | // @as(@Vector(2, u500), undefined) | |
| 946 | // @as(@Vector(2, u500), undefined) | |
| 947 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 948 | // @as(@Vector(2, u500), undefined) | |
| 949 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 950 | // @as(@Vector(2, u500), undefined) | |
| 951 | // @as(@Vector(2, u500), undefined) | |
| 952 | // @as(@Vector(2, u500), undefined) | |
| 953 | // @as(@Vector(2, u500), undefined) | |
| 954 | // @as(@Vector(2, u500), undefined) | |
| 955 | // @as(u500, undefined) | |
| 956 | // @as(u500, undefined) | |
| 957 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 958 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 959 | // @as(@Vector(2, u500), undefined) | |
| 960 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 961 | // @as(@Vector(2, u500), .{ 6, undefined }) | |
| 962 | // @as(@Vector(2, u500), undefined) | |
| 963 | // @as(@Vector(2, u500), undefined) | |
| 964 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 965 | // @as(@Vector(2, u500), undefined) | |
| 966 | // @as(@Vector(2, u500), .{ undefined, 6 }) | |
| 967 | // @as(@Vector(2, u500), undefined) | |
| 968 | // @as(@Vector(2, u500), undefined) | |
| 969 | // @as(@Vector(2, u500), undefined) | |
| 970 | // @as(@Vector(2, u500), undefined) | |
| 971 | // @as(@Vector(2, u500), undefined) | |
| 972 | // @as(u500, undefined) | |
| 973 | // @as(u500, undefined) | |
| 974 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 975 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 976 | // @as(@Vector(2, u500), undefined) | |
| 977 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 978 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 979 | // @as(@Vector(2, u500), undefined) | |
| 980 | // @as(@Vector(2, u500), undefined) | |
| 981 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 982 | // @as(@Vector(2, u500), undefined) | |
| 983 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 984 | // @as(@Vector(2, u500), undefined) | |
| 985 | // @as(@Vector(2, u500), undefined) | |
| 986 | // @as(@Vector(2, u500), undefined) | |
| 987 | // @as(@Vector(2, u500), undefined) | |
| 988 | // @as(@Vector(2, u500), undefined) | |
| 989 | // @as(u500, undefined) | |
| 990 | // @as(u500, undefined) | |
| 991 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 992 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 993 | // @as(@Vector(2, u500), undefined) | |
| 994 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 995 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 996 | // @as(@Vector(2, u500), undefined) | |
| 997 | // @as(@Vector(2, u500), undefined) | |
| 998 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 999 | // @as(@Vector(2, u500), undefined) | |
| 1000 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1001 | // @as(@Vector(2, u500), undefined) | |
| 1002 | // @as(@Vector(2, u500), undefined) | |
| 1003 | // @as(@Vector(2, u500), undefined) | |
| 1004 | // @as(@Vector(2, u500), undefined) | |
| 1005 | // @as(@Vector(2, u500), undefined) | |
| 1006 | // @as(u500, undefined) | |
| 1007 | // @as(u500, undefined) | |
| 1008 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1009 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1010 | // @as(@Vector(2, u500), undefined) | |
| 1011 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1012 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1013 | // @as(@Vector(2, u500), undefined) | |
| 1014 | // @as(@Vector(2, u500), undefined) | |
| 1015 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1016 | // @as(@Vector(2, u500), undefined) | |
| 1017 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1018 | // @as(@Vector(2, u500), undefined) | |
| 1019 | // @as(@Vector(2, u500), undefined) | |
| 1020 | // @as(@Vector(2, u500), undefined) | |
| 1021 | // @as(@Vector(2, u500), undefined) | |
| 1022 | // @as(@Vector(2, u500), undefined) | |
| 1023 | // @as(u500, undefined) | |
| 1024 | // @as(u500, undefined) | |
| 1025 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1026 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1027 | // @as(@Vector(2, u500), undefined) | |
| 1028 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1029 | // @as(@Vector(2, u500), .{ 9, undefined }) | |
| 1030 | // @as(@Vector(2, u500), undefined) | |
| 1031 | // @as(@Vector(2, u500), undefined) | |
| 1032 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1033 | // @as(@Vector(2, u500), undefined) | |
| 1034 | // @as(@Vector(2, u500), .{ undefined, 9 }) | |
| 1035 | // @as(@Vector(2, u500), undefined) | |
| 1036 | // @as(@Vector(2, u500), undefined) | |
| 1037 | // @as(@Vector(2, u500), undefined) | |
| 1038 | // @as(@Vector(2, u500), undefined) | |
| 1039 | // @as(@Vector(2, u500), undefined) | |
| 1040 | // @as(u500, undefined) | |
| 1041 | // @as(u500, undefined) | |
| 1042 | // @as(@Vector(2, u500), .{ 24, undefined }) | |
| 1043 | // @as(@Vector(2, u500), .{ undefined, 24 }) | |
| 1044 | // @as(@Vector(2, u500), undefined) | |
| 1045 | // @as(@Vector(2, u500), .{ 24, undefined }) | |
| 1046 | // @as(@Vector(2, u500), .{ 24, undefined }) | |
| 1047 | // @as(@Vector(2, u500), undefined) | |
| 1048 | // @as(@Vector(2, u500), undefined) | |
| 1049 | // @as(@Vector(2, u500), .{ undefined, 24 }) | |
| 1050 | // @as(@Vector(2, u500), undefined) | |
| 1051 | // @as(@Vector(2, u500), .{ undefined, 24 }) | |
| 1052 | // @as(@Vector(2, u500), undefined) | |
| 1053 | // @as(@Vector(2, u500), undefined) | |
| 1054 | // @as(@Vector(2, u500), undefined) | |
| 1055 | // @as(@Vector(2, u500), undefined) | |
| 1056 | // @as(@Vector(2, u500), undefined) | |
| 1057 | // @as(u500, undefined) | |
| 1058 | // @as(u500, undefined) | |
| 1059 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1060 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1061 | // @as(@Vector(2, u500), undefined) | |
| 1062 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1063 | // @as(@Vector(2, u500), .{ 0, undefined }) | |
| 1064 | // @as(@Vector(2, u500), undefined) | |
| 1065 | // @as(@Vector(2, u500), undefined) | |
| 1066 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1067 | // @as(@Vector(2, u500), undefined) | |
| 1068 | // @as(@Vector(2, u500), .{ undefined, 0 }) | |
| 1069 | // @as(@Vector(2, u500), undefined) | |
| 1070 | // @as(@Vector(2, u500), undefined) | |
| 1071 | // @as(@Vector(2, u500), undefined) | |
| 1072 | // @as(@Vector(2, u500), undefined) | |
| 1073 | // @as(@Vector(2, u500), undefined) | |
| 1074 | // @as(u500, undefined) | |
| 1075 | // @as(@Vector(2, u500), undefined) | |
| 1076 | // @as(u500, undefined) | |
| 1077 | // @as(u500, undefined) | |
| 1078 | // @as(@Vector(2, u500), undefined) | |
| 1079 | // @as(@Vector(2, u500), undefined) | |
| 1080 | // @as(u1, undefined) | |
| 1081 | // @as(@Vector(2, u1), .{ 1, undefined }) | |
| 1082 | // @as(@Vector(2, u1), .{ undefined, 1 }) | |
| 1083 | // @as(@Vector(2, u1), undefined) | |
| 1084 | // @as(u500, undefined) | |
| 1085 | // @as(@Vector(2, u500), undefined) | |
| 1086 | // @as(u500, undefined) | |
| 1087 | // @as(u500, undefined) | |
| 1088 | // @as(@Vector(2, u500), [runtime value]) | |
| 1089 | // @as(@Vector(2, u500), [runtime value]) | |
| 1090 | // @as(@Vector(2, u500), undefined) | |
| 1091 | // @as(@Vector(2, u500), [runtime value]) | |
| 1092 | // @as(@Vector(2, u500), [runtime value]) | |
| 1093 | // @as(@Vector(2, u500), [runtime value]) | |
| 1094 | // @as(@Vector(2, u500), undefined) | |
| 1095 | // @as(@Vector(2, u500), [runtime value]) | |
| 1096 | // @as(@Vector(2, u500), [runtime value]) | |
| 1097 | // @as(@Vector(2, u500), [runtime value]) | |
| 1098 | // @as(@Vector(2, u500), undefined) | |
| 1099 | // @as(@Vector(2, u500), undefined) | |
| 1100 | // @as(@Vector(2, u500), undefined) | |
| 1101 | // @as(@Vector(2, u500), undefined) | |
| 1102 | // @as(@Vector(2, u500), undefined) | |
| 1103 | // @as(u500, undefined) | |
| 1104 | // @as(u500, undefined) | |
| 1105 | // @as(@Vector(2, u500), [runtime value]) | |
| 1106 | // @as(@Vector(2, u500), [runtime value]) | |
| 1107 | // @as(@Vector(2, u500), undefined) | |
| 1108 | // @as(@Vector(2, u500), [runtime value]) | |
| 1109 | // @as(@Vector(2, u500), [runtime value]) | |
| 1110 | // @as(@Vector(2, u500), [runtime value]) | |
| 1111 | // @as(@Vector(2, u500), undefined) | |
| 1112 | // @as(@Vector(2, u500), [runtime value]) | |
| 1113 | // @as(@Vector(2, u500), [runtime value]) | |
| 1114 | // @as(@Vector(2, u500), [runtime value]) | |
| 1115 | // @as(@Vector(2, u500), undefined) | |
| 1116 | // @as(@Vector(2, u500), undefined) | |
| 1117 | // @as(@Vector(2, u500), undefined) | |
| 1118 | // @as(@Vector(2, u500), undefined) | |
| 1119 | // @as(@Vector(2, u500), undefined) | |
| 1120 | // @as(u500, undefined) | |
| 1121 | // @as(u500, undefined) | |
| 1122 | // @as(@Vector(2, u500), [runtime value]) | |
| 1123 | // @as(@Vector(2, u500), [runtime value]) | |
| 1124 | // @as(@Vector(2, u500), undefined) | |
| 1125 | // @as(@Vector(2, u500), [runtime value]) | |
| 1126 | // @as(@Vector(2, u500), [runtime value]) | |
| 1127 | // @as(@Vector(2, u500), [runtime value]) | |
| 1128 | // @as(@Vector(2, u500), undefined) | |
| 1129 | // @as(@Vector(2, u500), [runtime value]) | |
| 1130 | // @as(@Vector(2, u500), [runtime value]) | |
| 1131 | // @as(@Vector(2, u500), [runtime value]) | |
| 1132 | // @as(@Vector(2, u500), undefined) | |
| 1133 | // @as(@Vector(2, u500), undefined) | |
| 1134 | // @as(@Vector(2, u500), undefined) | |
| 1135 | // @as(@Vector(2, u500), undefined) | |
| 1136 | // @as(@Vector(2, u500), undefined) | |
| 1137 | // @as(u500, undefined) | |
| 1138 | // @as(u500, undefined) | |
| 1139 | // @as(@Vector(2, u500), [runtime value]) | |
| 1140 | // @as(@Vector(2, u500), [runtime value]) | |
| 1141 | // @as(@Vector(2, u500), undefined) | |
| 1142 | // @as(@Vector(2, u500), [runtime value]) | |
| 1143 | // @as(@Vector(2, u500), [runtime value]) | |
| 1144 | // @as(@Vector(2, u500), [runtime value]) | |
| 1145 | // @as(@Vector(2, u500), undefined) | |
| 1146 | // @as(@Vector(2, u500), [runtime value]) | |
| 1147 | // @as(@Vector(2, u500), [runtime value]) | |
| 1148 | // @as(@Vector(2, u500), [runtime value]) | |
| 1149 | // @as(@Vector(2, u500), undefined) | |
| 1150 | // @as(@Vector(2, u500), undefined) | |
| 1151 | // @as(@Vector(2, u500), undefined) | |
| 1152 | // @as(@Vector(2, u500), undefined) | |
| 1153 | // @as(@Vector(2, u500), undefined) | |
| 1154 | // @as(u500, undefined) | |
| 1155 | // @as(u500, undefined) | |
| 1156 | // @as(@Vector(2, u500), [runtime value]) | |
| 1157 | // @as(@Vector(2, u500), [runtime value]) | |
| 1158 | // @as(@Vector(2, u500), undefined) | |
| 1159 | // @as(@Vector(2, u500), [runtime value]) | |
| 1160 | // @as(@Vector(2, u500), [runtime value]) | |
| 1161 | // @as(@Vector(2, u500), [runtime value]) | |
| 1162 | // @as(@Vector(2, u500), undefined) | |
| 1163 | // @as(@Vector(2, u500), [runtime value]) | |
| 1164 | // @as(@Vector(2, u500), [runtime value]) | |
| 1165 | // @as(@Vector(2, u500), [runtime value]) | |
| 1166 | // @as(@Vector(2, u500), undefined) | |
| 1167 | // @as(@Vector(2, u500), undefined) | |
| 1168 | // @as(@Vector(2, u500), undefined) | |
| 1169 | // @as(@Vector(2, u500), undefined) | |
| 1170 | // @as(@Vector(2, u500), undefined) | |
| 1171 | // @as(u500, undefined) | |
| 1172 | // @as(u500, undefined) | |
| 1173 | // @as(@Vector(2, u500), [runtime value]) | |
| 1174 | // @as(@Vector(2, u500), [runtime value]) | |
| 1175 | // @as(@Vector(2, u500), undefined) | |
| 1176 | // @as(@Vector(2, u500), [runtime value]) | |
| 1177 | // @as(@Vector(2, u500), [runtime value]) | |
| 1178 | // @as(@Vector(2, u500), [runtime value]) | |
| 1179 | // @as(@Vector(2, u500), undefined) | |
| 1180 | // @as(@Vector(2, u500), [runtime value]) | |
| 1181 | // @as(@Vector(2, u500), [runtime value]) | |
| 1182 | // @as(@Vector(2, u500), [runtime value]) | |
| 1183 | // @as(@Vector(2, u500), undefined) | |
| 1184 | // @as(@Vector(2, u500), undefined) | |
| 1185 | // @as(@Vector(2, u500), undefined) | |
| 1186 | // @as(@Vector(2, u500), undefined) | |
| 1187 | // @as(@Vector(2, u500), undefined) | |
| 1188 | // @as(u500, undefined) | |
| 1189 | // @as(u500, undefined) | |
| 1190 | // @as(@Vector(2, u500), [runtime value]) | |
| 1191 | // @as(@Vector(2, u500), [runtime value]) | |
| 1192 | // @as(@Vector(2, u500), undefined) | |
| 1193 | // @as(@Vector(2, u500), [runtime value]) | |
| 1194 | // @as(@Vector(2, u500), [runtime value]) | |
| 1195 | // @as(@Vector(2, u500), [runtime value]) | |
| 1196 | // @as(@Vector(2, u500), undefined) | |
| 1197 | // @as(@Vector(2, u500), [runtime value]) | |
| 1198 | // @as(@Vector(2, u500), [runtime value]) | |
| 1199 | // @as(@Vector(2, u500), [runtime value]) | |
| 1200 | // @as(@Vector(2, u500), undefined) | |
| 1201 | // @as(@Vector(2, u500), undefined) | |
| 1202 | // @as(@Vector(2, u500), undefined) | |
| 1203 | // @as(@Vector(2, u500), undefined) | |
| 1204 | // @as(@Vector(2, u500), undefined) | |
| 1205 | // @as(u500, [runtime value]) | |
| 1206 | // @as(u500, [runtime value]) | |
| 1207 | // @as(@Vector(2, u500), [runtime value]) | |
| 1208 | // @as(@Vector(2, u500), [runtime value]) | |
| 1209 | // @as(@Vector(2, u500), [runtime value]) | |
| 1210 | // @as(@Vector(2, u500), [runtime value]) | |
| 1211 | // @as(@Vector(2, u500), [runtime value]) | |
| 1212 | // @as(@Vector(2, u500), [runtime value]) | |
| 1213 | // @as(@Vector(2, u500), [runtime value]) | |
| 1214 | // @as(@Vector(2, u500), [runtime value]) | |
| 1215 | // @as(@Vector(2, u500), [runtime value]) | |
| 1216 | // @as(@Vector(2, u500), [runtime value]) | |
| 1217 | // @as(@Vector(2, u500), [runtime value]) | |
| 1218 | // @as(@Vector(2, u500), [runtime value]) | |
| 1219 | // @as(@Vector(2, u500), [runtime value]) | |
| 1220 | // @as(@Vector(2, u500), [runtime value]) | |
| 1221 | // @as(@Vector(2, u500), undefined) | |
| 1222 | // @as(u500, undefined) | |
| 1223 | // @as(@Vector(2, u500), undefined) | |
| 1224 | // @as(u500, undefined) | |
| 1225 | // @as(u500, undefined) | |
| 1226 | // @as(@Vector(2, u500), undefined) | |
| 1227 | // @as(@Vector(2, u500), undefined) | |
| 1228 | // @as(u1, undefined) | |
| 1229 | // @as(@Vector(2, u1), [runtime value]) | |
| 1230 | // @as(@Vector(2, u1), [runtime value]) | |
| 1231 | // @as(@Vector(2, u1), undefined) | |
| 1232 | // @as(u500, undefined) | |
| 1233 | // @as(@Vector(2, u500), undefined) | |
| 1234 | // @as(i32, undefined) | |
| 1235 | // @as(i32, undefined) | |
| 1236 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1237 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1238 | // @as(@Vector(2, i32), undefined) | |
| 1239 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1240 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1241 | // @as(@Vector(2, i32), undefined) | |
| 1242 | // @as(@Vector(2, i32), undefined) | |
| 1243 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1244 | // @as(@Vector(2, i32), undefined) | |
| 1245 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1246 | // @as(@Vector(2, i32), undefined) | |
| 1247 | // @as(@Vector(2, i32), undefined) | |
| 1248 | // @as(@Vector(2, i32), undefined) | |
| 1249 | // @as(@Vector(2, i32), undefined) | |
| 1250 | // @as(@Vector(2, i32), undefined) | |
| 1251 | // @as(i32, undefined) | |
| 1252 | // @as(i32, undefined) | |
| 1253 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1254 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1255 | // @as(@Vector(2, i32), undefined) | |
| 1256 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1257 | // @as(@Vector(2, i32), .{ 6, undefined }) | |
| 1258 | // @as(@Vector(2, i32), undefined) | |
| 1259 | // @as(@Vector(2, i32), undefined) | |
| 1260 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1261 | // @as(@Vector(2, i32), undefined) | |
| 1262 | // @as(@Vector(2, i32), .{ undefined, 6 }) | |
| 1263 | // @as(@Vector(2, i32), undefined) | |
| 1264 | // @as(@Vector(2, i32), undefined) | |
| 1265 | // @as(@Vector(2, i32), undefined) | |
| 1266 | // @as(@Vector(2, i32), undefined) | |
| 1267 | // @as(@Vector(2, i32), undefined) | |
| 1268 | // @as(i32, undefined) | |
| 1269 | // @as(i32, undefined) | |
| 1270 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1271 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1272 | // @as(@Vector(2, i32), undefined) | |
| 1273 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1274 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1275 | // @as(@Vector(2, i32), undefined) | |
| 1276 | // @as(@Vector(2, i32), undefined) | |
| 1277 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1278 | // @as(@Vector(2, i32), undefined) | |
| 1279 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1280 | // @as(@Vector(2, i32), undefined) | |
| 1281 | // @as(@Vector(2, i32), undefined) | |
| 1282 | // @as(@Vector(2, i32), undefined) | |
| 1283 | // @as(@Vector(2, i32), undefined) | |
| 1284 | // @as(@Vector(2, i32), undefined) | |
| 1285 | // @as(i32, undefined) | |
| 1286 | // @as(i32, undefined) | |
| 1287 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1288 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1289 | // @as(@Vector(2, i32), undefined) | |
| 1290 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1291 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1292 | // @as(@Vector(2, i32), undefined) | |
| 1293 | // @as(@Vector(2, i32), undefined) | |
| 1294 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1295 | // @as(@Vector(2, i32), undefined) | |
| 1296 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1297 | // @as(@Vector(2, i32), undefined) | |
| 1298 | // @as(@Vector(2, i32), undefined) | |
| 1299 | // @as(@Vector(2, i32), undefined) | |
| 1300 | // @as(@Vector(2, i32), undefined) | |
| 1301 | // @as(@Vector(2, i32), undefined) | |
| 1302 | // @as(i32, undefined) | |
| 1303 | // @as(i32, undefined) | |
| 1304 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1305 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1306 | // @as(@Vector(2, i32), undefined) | |
| 1307 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1308 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1309 | // @as(@Vector(2, i32), undefined) | |
| 1310 | // @as(@Vector(2, i32), undefined) | |
| 1311 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1312 | // @as(@Vector(2, i32), undefined) | |
| 1313 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1314 | // @as(@Vector(2, i32), undefined) | |
| 1315 | // @as(@Vector(2, i32), undefined) | |
| 1316 | // @as(@Vector(2, i32), undefined) | |
| 1317 | // @as(@Vector(2, i32), undefined) | |
| 1318 | // @as(@Vector(2, i32), undefined) | |
| 1319 | // @as(i32, undefined) | |
| 1320 | // @as(i32, undefined) | |
| 1321 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1322 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1323 | // @as(@Vector(2, i32), undefined) | |
| 1324 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1325 | // @as(@Vector(2, i32), .{ 9, undefined }) | |
| 1326 | // @as(@Vector(2, i32), undefined) | |
| 1327 | // @as(@Vector(2, i32), undefined) | |
| 1328 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1329 | // @as(@Vector(2, i32), undefined) | |
| 1330 | // @as(@Vector(2, i32), .{ undefined, 9 }) | |
| 1331 | // @as(@Vector(2, i32), undefined) | |
| 1332 | // @as(@Vector(2, i32), undefined) | |
| 1333 | // @as(@Vector(2, i32), undefined) | |
| 1334 | // @as(@Vector(2, i32), undefined) | |
| 1335 | // @as(@Vector(2, i32), undefined) | |
| 1336 | // @as(i32, undefined) | |
| 1337 | // @as(i32, undefined) | |
| 1338 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1339 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1340 | // @as(@Vector(2, i32), undefined) | |
| 1341 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1342 | // @as(@Vector(2, i32), .{ 0, undefined }) | |
| 1343 | // @as(@Vector(2, i32), undefined) | |
| 1344 | // @as(@Vector(2, i32), undefined) | |
| 1345 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1346 | // @as(@Vector(2, i32), undefined) | |
| 1347 | // @as(@Vector(2, i32), .{ undefined, 0 }) | |
| 1348 | // @as(@Vector(2, i32), undefined) | |
| 1349 | // @as(@Vector(2, i32), undefined) | |
| 1350 | // @as(@Vector(2, i32), undefined) | |
| 1351 | // @as(@Vector(2, i32), undefined) | |
| 1352 | // @as(@Vector(2, i32), undefined) | |
| 1353 | // @as(i32, undefined) | |
| 1354 | // @as(@Vector(2, i32), undefined) | |
| 1355 | // @as(i32, undefined) | |
| 1356 | // @as(i32, undefined) | |
| 1357 | // @as(@Vector(2, i32), undefined) | |
| 1358 | // @as(@Vector(2, i32), undefined) | |
| 1359 | // @as(i32, undefined) | |
| 1360 | // @as(@Vector(2, i32), undefined) | |
| 1361 | // @as(i32, undefined) | |
| 1362 | // @as(i32, undefined) | |
| 1363 | // @as(@Vector(2, i32), [runtime value]) | |
| 1364 | // @as(@Vector(2, i32), [runtime value]) | |
| 1365 | // @as(@Vector(2, i32), undefined) | |
| 1366 | // @as(@Vector(2, i32), [runtime value]) | |
| 1367 | // @as(@Vector(2, i32), [runtime value]) | |
| 1368 | // @as(@Vector(2, i32), [runtime value]) | |
| 1369 | // @as(@Vector(2, i32), undefined) | |
| 1370 | // @as(@Vector(2, i32), [runtime value]) | |
| 1371 | // @as(@Vector(2, i32), [runtime value]) | |
| 1372 | // @as(@Vector(2, i32), [runtime value]) | |
| 1373 | // @as(@Vector(2, i32), undefined) | |
| 1374 | // @as(@Vector(2, i32), undefined) | |
| 1375 | // @as(@Vector(2, i32), undefined) | |
| 1376 | // @as(@Vector(2, i32), undefined) | |
| 1377 | // @as(@Vector(2, i32), undefined) | |
| 1378 | // @as(i32, undefined) | |
| 1379 | // @as(i32, undefined) | |
| 1380 | // @as(@Vector(2, i32), [runtime value]) | |
| 1381 | // @as(@Vector(2, i32), [runtime value]) | |
| 1382 | // @as(@Vector(2, i32), undefined) | |
| 1383 | // @as(@Vector(2, i32), [runtime value]) | |
| 1384 | // @as(@Vector(2, i32), [runtime value]) | |
| 1385 | // @as(@Vector(2, i32), [runtime value]) | |
| 1386 | // @as(@Vector(2, i32), undefined) | |
| 1387 | // @as(@Vector(2, i32), [runtime value]) | |
| 1388 | // @as(@Vector(2, i32), [runtime value]) | |
| 1389 | // @as(@Vector(2, i32), [runtime value]) | |
| 1390 | // @as(@Vector(2, i32), undefined) | |
| 1391 | // @as(@Vector(2, i32), undefined) | |
| 1392 | // @as(@Vector(2, i32), undefined) | |
| 1393 | // @as(@Vector(2, i32), undefined) | |
| 1394 | // @as(@Vector(2, i32), undefined) | |
| 1395 | // @as(i32, undefined) | |
| 1396 | // @as(i32, undefined) | |
| 1397 | // @as(@Vector(2, i32), [runtime value]) | |
| 1398 | // @as(@Vector(2, i32), [runtime value]) | |
| 1399 | // @as(@Vector(2, i32), undefined) | |
| 1400 | // @as(@Vector(2, i32), [runtime value]) | |
| 1401 | // @as(@Vector(2, i32), [runtime value]) | |
| 1402 | // @as(@Vector(2, i32), [runtime value]) | |
| 1403 | // @as(@Vector(2, i32), undefined) | |
| 1404 | // @as(@Vector(2, i32), [runtime value]) | |
| 1405 | // @as(@Vector(2, i32), [runtime value]) | |
| 1406 | // @as(@Vector(2, i32), [runtime value]) | |
| 1407 | // @as(@Vector(2, i32), undefined) | |
| 1408 | // @as(@Vector(2, i32), undefined) | |
| 1409 | // @as(@Vector(2, i32), undefined) | |
| 1410 | // @as(@Vector(2, i32), undefined) | |
| 1411 | // @as(@Vector(2, i32), undefined) | |
| 1412 | // @as(i32, undefined) | |
| 1413 | // @as(i32, undefined) | |
| 1414 | // @as(@Vector(2, i32), [runtime value]) | |
| 1415 | // @as(@Vector(2, i32), [runtime value]) | |
| 1416 | // @as(@Vector(2, i32), undefined) | |
| 1417 | // @as(@Vector(2, i32), [runtime value]) | |
| 1418 | // @as(@Vector(2, i32), [runtime value]) | |
| 1419 | // @as(@Vector(2, i32), [runtime value]) | |
| 1420 | // @as(@Vector(2, i32), undefined) | |
| 1421 | // @as(@Vector(2, i32), [runtime value]) | |
| 1422 | // @as(@Vector(2, i32), [runtime value]) | |
| 1423 | // @as(@Vector(2, i32), [runtime value]) | |
| 1424 | // @as(@Vector(2, i32), undefined) | |
| 1425 | // @as(@Vector(2, i32), undefined) | |
| 1426 | // @as(@Vector(2, i32), undefined) | |
| 1427 | // @as(@Vector(2, i32), undefined) | |
| 1428 | // @as(@Vector(2, i32), undefined) | |
| 1429 | // @as(i32, undefined) | |
| 1430 | // @as(i32, undefined) | |
| 1431 | // @as(@Vector(2, i32), [runtime value]) | |
| 1432 | // @as(@Vector(2, i32), [runtime value]) | |
| 1433 | // @as(@Vector(2, i32), undefined) | |
| 1434 | // @as(@Vector(2, i32), [runtime value]) | |
| 1435 | // @as(@Vector(2, i32), [runtime value]) | |
| 1436 | // @as(@Vector(2, i32), [runtime value]) | |
| 1437 | // @as(@Vector(2, i32), undefined) | |
| 1438 | // @as(@Vector(2, i32), [runtime value]) | |
| 1439 | // @as(@Vector(2, i32), [runtime value]) | |
| 1440 | // @as(@Vector(2, i32), [runtime value]) | |
| 1441 | // @as(@Vector(2, i32), undefined) | |
| 1442 | // @as(@Vector(2, i32), undefined) | |
| 1443 | // @as(@Vector(2, i32), undefined) | |
| 1444 | // @as(@Vector(2, i32), undefined) | |
| 1445 | // @as(@Vector(2, i32), undefined) | |
| 1446 | // @as(i32, undefined) | |
| 1447 | // @as(i32, undefined) | |
| 1448 | // @as(@Vector(2, i32), [runtime value]) | |
| 1449 | // @as(@Vector(2, i32), [runtime value]) | |
| 1450 | // @as(@Vector(2, i32), undefined) | |
| 1451 | // @as(@Vector(2, i32), [runtime value]) | |
| 1452 | // @as(@Vector(2, i32), [runtime value]) | |
| 1453 | // @as(@Vector(2, i32), [runtime value]) | |
| 1454 | // @as(@Vector(2, i32), undefined) | |
| 1455 | // @as(@Vector(2, i32), [runtime value]) | |
| 1456 | // @as(@Vector(2, i32), [runtime value]) | |
| 1457 | // @as(@Vector(2, i32), [runtime value]) | |
| 1458 | // @as(@Vector(2, i32), undefined) | |
| 1459 | // @as(@Vector(2, i32), undefined) | |
| 1460 | // @as(@Vector(2, i32), undefined) | |
| 1461 | // @as(@Vector(2, i32), undefined) | |
| 1462 | // @as(@Vector(2, i32), undefined) | |
| 1463 | // @as(i32, [runtime value]) | |
| 1464 | // @as(i32, [runtime value]) | |
| 1465 | // @as(@Vector(2, i32), [runtime value]) | |
| 1466 | // @as(@Vector(2, i32), [runtime value]) | |
| 1467 | // @as(@Vector(2, i32), [runtime value]) | |
| 1468 | // @as(@Vector(2, i32), [runtime value]) | |
| 1469 | // @as(@Vector(2, i32), [runtime value]) | |
| 1470 | // @as(@Vector(2, i32), [runtime value]) | |
| 1471 | // @as(@Vector(2, i32), [runtime value]) | |
| 1472 | // @as(@Vector(2, i32), [runtime value]) | |
| 1473 | // @as(@Vector(2, i32), [runtime value]) | |
| 1474 | // @as(@Vector(2, i32), [runtime value]) | |
| 1475 | // @as(@Vector(2, i32), [runtime value]) | |
| 1476 | // @as(@Vector(2, i32), [runtime value]) | |
| 1477 | // @as(@Vector(2, i32), [runtime value]) | |
| 1478 | // @as(@Vector(2, i32), [runtime value]) | |
| 1479 | // @as(@Vector(2, i32), undefined) | |
| 1480 | // @as(i32, undefined) | |
| 1481 | // @as(@Vector(2, i32), undefined) | |
| 1482 | // @as(i32, undefined) | |
| 1483 | // @as(i32, undefined) | |
| 1484 | // @as(@Vector(2, i32), undefined) | |
| 1485 | // @as(@Vector(2, i32), undefined) | |
| 1486 | // @as(i32, undefined) | |
| 1487 | // @as(@Vector(2, i32), undefined) | |
| 1488 | // @as(u32, undefined) | |
| 1489 | // @as(u32, undefined) | |
| 1490 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 1491 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 1492 | // @as(@Vector(2, u32), undefined) | |
| 1493 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 1494 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 1495 | // @as(@Vector(2, u32), undefined) | |
| 1496 | // @as(@Vector(2, u32), undefined) | |
| 1497 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 1498 | // @as(@Vector(2, u32), undefined) | |
| 1499 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 1500 | // @as(@Vector(2, u32), undefined) | |
| 1501 | // @as(@Vector(2, u32), undefined) | |
| 1502 | // @as(@Vector(2, u32), undefined) | |
| 1503 | // @as(@Vector(2, u32), undefined) | |
| 1504 | // @as(@Vector(2, u32), undefined) | |
| 1505 | // @as(u32, undefined) | |
| 1506 | // @as(u32, undefined) | |
| 1507 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 1508 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 1509 | // @as(@Vector(2, u32), undefined) | |
| 1510 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 1511 | // @as(@Vector(2, u32), .{ 6, undefined }) | |
| 1512 | // @as(@Vector(2, u32), undefined) | |
| 1513 | // @as(@Vector(2, u32), undefined) | |
| 1514 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 1515 | // @as(@Vector(2, u32), undefined) | |
| 1516 | // @as(@Vector(2, u32), .{ undefined, 6 }) | |
| 1517 | // @as(@Vector(2, u32), undefined) | |
| 1518 | // @as(@Vector(2, u32), undefined) | |
| 1519 | // @as(@Vector(2, u32), undefined) | |
| 1520 | // @as(@Vector(2, u32), undefined) | |
| 1521 | // @as(@Vector(2, u32), undefined) | |
| 1522 | // @as(u32, undefined) | |
| 1523 | // @as(u32, undefined) | |
| 1524 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1525 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1526 | // @as(@Vector(2, u32), undefined) | |
| 1527 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1528 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1529 | // @as(@Vector(2, u32), undefined) | |
| 1530 | // @as(@Vector(2, u32), undefined) | |
| 1531 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1532 | // @as(@Vector(2, u32), undefined) | |
| 1533 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1534 | // @as(@Vector(2, u32), undefined) | |
| 1535 | // @as(@Vector(2, u32), undefined) | |
| 1536 | // @as(@Vector(2, u32), undefined) | |
| 1537 | // @as(@Vector(2, u32), undefined) | |
| 1538 | // @as(@Vector(2, u32), undefined) | |
| 1539 | // @as(u32, undefined) | |
| 1540 | // @as(u32, undefined) | |
| 1541 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1542 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1543 | // @as(@Vector(2, u32), undefined) | |
| 1544 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1545 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1546 | // @as(@Vector(2, u32), undefined) | |
| 1547 | // @as(@Vector(2, u32), undefined) | |
| 1548 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1549 | // @as(@Vector(2, u32), undefined) | |
| 1550 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1551 | // @as(@Vector(2, u32), undefined) | |
| 1552 | // @as(@Vector(2, u32), undefined) | |
| 1553 | // @as(@Vector(2, u32), undefined) | |
| 1554 | // @as(@Vector(2, u32), undefined) | |
| 1555 | // @as(@Vector(2, u32), undefined) | |
| 1556 | // @as(u32, undefined) | |
| 1557 | // @as(u32, undefined) | |
| 1558 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1559 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1560 | // @as(@Vector(2, u32), undefined) | |
| 1561 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1562 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1563 | // @as(@Vector(2, u32), undefined) | |
| 1564 | // @as(@Vector(2, u32), undefined) | |
| 1565 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1566 | // @as(@Vector(2, u32), undefined) | |
| 1567 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1568 | // @as(@Vector(2, u32), undefined) | |
| 1569 | // @as(@Vector(2, u32), undefined) | |
| 1570 | // @as(@Vector(2, u32), undefined) | |
| 1571 | // @as(@Vector(2, u32), undefined) | |
| 1572 | // @as(@Vector(2, u32), undefined) | |
| 1573 | // @as(u32, undefined) | |
| 1574 | // @as(u32, undefined) | |
| 1575 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1576 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1577 | // @as(@Vector(2, u32), undefined) | |
| 1578 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1579 | // @as(@Vector(2, u32), .{ 9, undefined }) | |
| 1580 | // @as(@Vector(2, u32), undefined) | |
| 1581 | // @as(@Vector(2, u32), undefined) | |
| 1582 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1583 | // @as(@Vector(2, u32), undefined) | |
| 1584 | // @as(@Vector(2, u32), .{ undefined, 9 }) | |
| 1585 | // @as(@Vector(2, u32), undefined) | |
| 1586 | // @as(@Vector(2, u32), undefined) | |
| 1587 | // @as(@Vector(2, u32), undefined) | |
| 1588 | // @as(@Vector(2, u32), undefined) | |
| 1589 | // @as(@Vector(2, u32), undefined) | |
| 1590 | // @as(u32, undefined) | |
| 1591 | // @as(u32, undefined) | |
| 1592 | // @as(@Vector(2, u32), .{ 24, undefined }) | |
| 1593 | // @as(@Vector(2, u32), .{ undefined, 24 }) | |
| 1594 | // @as(@Vector(2, u32), undefined) | |
| 1595 | // @as(@Vector(2, u32), .{ 24, undefined }) | |
| 1596 | // @as(@Vector(2, u32), .{ 24, undefined }) | |
| 1597 | // @as(@Vector(2, u32), undefined) | |
| 1598 | // @as(@Vector(2, u32), undefined) | |
| 1599 | // @as(@Vector(2, u32), .{ undefined, 24 }) | |
| 1600 | // @as(@Vector(2, u32), undefined) | |
| 1601 | // @as(@Vector(2, u32), .{ undefined, 24 }) | |
| 1602 | // @as(@Vector(2, u32), undefined) | |
| 1603 | // @as(@Vector(2, u32), undefined) | |
| 1604 | // @as(@Vector(2, u32), undefined) | |
| 1605 | // @as(@Vector(2, u32), undefined) | |
| 1606 | // @as(@Vector(2, u32), undefined) | |
| 1607 | // @as(u32, undefined) | |
| 1608 | // @as(u32, undefined) | |
| 1609 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1610 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1611 | // @as(@Vector(2, u32), undefined) | |
| 1612 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1613 | // @as(@Vector(2, u32), .{ 0, undefined }) | |
| 1614 | // @as(@Vector(2, u32), undefined) | |
| 1615 | // @as(@Vector(2, u32), undefined) | |
| 1616 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1617 | // @as(@Vector(2, u32), undefined) | |
| 1618 | // @as(@Vector(2, u32), .{ undefined, 0 }) | |
| 1619 | // @as(@Vector(2, u32), undefined) | |
| 1620 | // @as(@Vector(2, u32), undefined) | |
| 1621 | // @as(@Vector(2, u32), undefined) | |
| 1622 | // @as(@Vector(2, u32), undefined) | |
| 1623 | // @as(@Vector(2, u32), undefined) | |
| 1624 | // @as(u32, undefined) | |
| 1625 | // @as(@Vector(2, u32), undefined) | |
| 1626 | // @as(u32, undefined) | |
| 1627 | // @as(u32, undefined) | |
| 1628 | // @as(@Vector(2, u32), undefined) | |
| 1629 | // @as(@Vector(2, u32), undefined) | |
| 1630 | // @as(u1, undefined) | |
| 1631 | // @as(@Vector(2, u1), .{ 1, undefined }) | |
| 1632 | // @as(@Vector(2, u1), .{ undefined, 1 }) | |
| 1633 | // @as(@Vector(2, u1), undefined) | |
| 1634 | // @as(u32, undefined) | |
| 1635 | // @as(@Vector(2, u32), undefined) | |
| 1636 | // @as(u32, undefined) | |
| 1637 | // @as(u32, undefined) | |
| 1638 | // @as(@Vector(2, u32), [runtime value]) | |
| 1639 | // @as(@Vector(2, u32), [runtime value]) | |
| 1640 | // @as(@Vector(2, u32), undefined) | |
| 1641 | // @as(@Vector(2, u32), [runtime value]) | |
| 1642 | // @as(@Vector(2, u32), [runtime value]) | |
| 1643 | // @as(@Vector(2, u32), [runtime value]) | |
| 1644 | // @as(@Vector(2, u32), undefined) | |
| 1645 | // @as(@Vector(2, u32), [runtime value]) | |
| 1646 | // @as(@Vector(2, u32), [runtime value]) | |
| 1647 | // @as(@Vector(2, u32), [runtime value]) | |
| 1648 | // @as(@Vector(2, u32), undefined) | |
| 1649 | // @as(@Vector(2, u32), undefined) | |
| 1650 | // @as(@Vector(2, u32), undefined) | |
| 1651 | // @as(@Vector(2, u32), undefined) | |
| 1652 | // @as(@Vector(2, u32), undefined) | |
| 1653 | // @as(u32, undefined) | |
| 1654 | // @as(u32, undefined) | |
| 1655 | // @as(@Vector(2, u32), [runtime value]) | |
| 1656 | // @as(@Vector(2, u32), [runtime value]) | |
| 1657 | // @as(@Vector(2, u32), undefined) | |
| 1658 | // @as(@Vector(2, u32), [runtime value]) | |
| 1659 | // @as(@Vector(2, u32), [runtime value]) | |
| 1660 | // @as(@Vector(2, u32), [runtime value]) | |
| 1661 | // @as(@Vector(2, u32), undefined) | |
| 1662 | // @as(@Vector(2, u32), [runtime value]) | |
| 1663 | // @as(@Vector(2, u32), [runtime value]) | |
| 1664 | // @as(@Vector(2, u32), [runtime value]) | |
| 1665 | // @as(@Vector(2, u32), undefined) | |
| 1666 | // @as(@Vector(2, u32), undefined) | |
| 1667 | // @as(@Vector(2, u32), undefined) | |
| 1668 | // @as(@Vector(2, u32), undefined) | |
| 1669 | // @as(@Vector(2, u32), undefined) | |
| 1670 | // @as(u32, undefined) | |
| 1671 | // @as(u32, undefined) | |
| 1672 | // @as(@Vector(2, u32), [runtime value]) | |
| 1673 | // @as(@Vector(2, u32), [runtime value]) | |
| 1674 | // @as(@Vector(2, u32), undefined) | |
| 1675 | // @as(@Vector(2, u32), [runtime value]) | |
| 1676 | // @as(@Vector(2, u32), [runtime value]) | |
| 1677 | // @as(@Vector(2, u32), [runtime value]) | |
| 1678 | // @as(@Vector(2, u32), undefined) | |
| 1679 | // @as(@Vector(2, u32), [runtime value]) | |
| 1680 | // @as(@Vector(2, u32), [runtime value]) | |
| 1681 | // @as(@Vector(2, u32), [runtime value]) | |
| 1682 | // @as(@Vector(2, u32), undefined) | |
| 1683 | // @as(@Vector(2, u32), undefined) | |
| 1684 | // @as(@Vector(2, u32), undefined) | |
| 1685 | // @as(@Vector(2, u32), undefined) | |
| 1686 | // @as(@Vector(2, u32), undefined) | |
| 1687 | // @as(u32, undefined) | |
| 1688 | // @as(u32, undefined) | |
| 1689 | // @as(@Vector(2, u32), [runtime value]) | |
| 1690 | // @as(@Vector(2, u32), [runtime value]) | |
| 1691 | // @as(@Vector(2, u32), undefined) | |
| 1692 | // @as(@Vector(2, u32), [runtime value]) | |
| 1693 | // @as(@Vector(2, u32), [runtime value]) | |
| 1694 | // @as(@Vector(2, u32), [runtime value]) | |
| 1695 | // @as(@Vector(2, u32), undefined) | |
| 1696 | // @as(@Vector(2, u32), [runtime value]) | |
| 1697 | // @as(@Vector(2, u32), [runtime value]) | |
| 1698 | // @as(@Vector(2, u32), [runtime value]) | |
| 1699 | // @as(@Vector(2, u32), undefined) | |
| 1700 | // @as(@Vector(2, u32), undefined) | |
| 1701 | // @as(@Vector(2, u32), undefined) | |
| 1702 | // @as(@Vector(2, u32), undefined) | |
| 1703 | // @as(@Vector(2, u32), undefined) | |
| 1704 | // @as(u32, undefined) | |
| 1705 | // @as(u32, undefined) | |
| 1706 | // @as(@Vector(2, u32), [runtime value]) | |
| 1707 | // @as(@Vector(2, u32), [runtime value]) | |
| 1708 | // @as(@Vector(2, u32), undefined) | |
| 1709 | // @as(@Vector(2, u32), [runtime value]) | |
| 1710 | // @as(@Vector(2, u32), [runtime value]) | |
| 1711 | // @as(@Vector(2, u32), [runtime value]) | |
| 1712 | // @as(@Vector(2, u32), undefined) | |
| 1713 | // @as(@Vector(2, u32), [runtime value]) | |
| 1714 | // @as(@Vector(2, u32), [runtime value]) | |
| 1715 | // @as(@Vector(2, u32), [runtime value]) | |
| 1716 | // @as(@Vector(2, u32), undefined) | |
| 1717 | // @as(@Vector(2, u32), undefined) | |
| 1718 | // @as(@Vector(2, u32), undefined) | |
| 1719 | // @as(@Vector(2, u32), undefined) | |
| 1720 | // @as(@Vector(2, u32), undefined) | |
| 1721 | // @as(u32, undefined) | |
| 1722 | // @as(u32, undefined) | |
| 1723 | // @as(@Vector(2, u32), [runtime value]) | |
| 1724 | // @as(@Vector(2, u32), [runtime value]) | |
| 1725 | // @as(@Vector(2, u32), undefined) | |
| 1726 | // @as(@Vector(2, u32), [runtime value]) | |
| 1727 | // @as(@Vector(2, u32), [runtime value]) | |
| 1728 | // @as(@Vector(2, u32), [runtime value]) | |
| 1729 | // @as(@Vector(2, u32), undefined) | |
| 1730 | // @as(@Vector(2, u32), [runtime value]) | |
| 1731 | // @as(@Vector(2, u32), [runtime value]) | |
| 1732 | // @as(@Vector(2, u32), [runtime value]) | |
| 1733 | // @as(@Vector(2, u32), undefined) | |
| 1734 | // @as(@Vector(2, u32), undefined) | |
| 1735 | // @as(@Vector(2, u32), undefined) | |
| 1736 | // @as(@Vector(2, u32), undefined) | |
| 1737 | // @as(@Vector(2, u32), undefined) | |
| 1738 | // @as(u32, undefined) | |
| 1739 | // @as(u32, undefined) | |
| 1740 | // @as(@Vector(2, u32), [runtime value]) | |
| 1741 | // @as(@Vector(2, u32), [runtime value]) | |
| 1742 | // @as(@Vector(2, u32), undefined) | |
| 1743 | // @as(@Vector(2, u32), [runtime value]) | |
| 1744 | // @as(@Vector(2, u32), [runtime value]) | |
| 1745 | // @as(@Vector(2, u32), [runtime value]) | |
| 1746 | // @as(@Vector(2, u32), undefined) | |
| 1747 | // @as(@Vector(2, u32), [runtime value]) | |
| 1748 | // @as(@Vector(2, u32), [runtime value]) | |
| 1749 | // @as(@Vector(2, u32), [runtime value]) | |
| 1750 | // @as(@Vector(2, u32), undefined) | |
| 1751 | // @as(@Vector(2, u32), undefined) | |
| 1752 | // @as(@Vector(2, u32), undefined) | |
| 1753 | // @as(@Vector(2, u32), undefined) | |
| 1754 | // @as(@Vector(2, u32), undefined) | |
| 1755 | // @as(u32, [runtime value]) | |
| 1756 | // @as(u32, [runtime value]) | |
| 1757 | // @as(@Vector(2, u32), [runtime value]) | |
| 1758 | // @as(@Vector(2, u32), [runtime value]) | |
| 1759 | // @as(@Vector(2, u32), [runtime value]) | |
| 1760 | // @as(@Vector(2, u32), [runtime value]) | |
| 1761 | // @as(@Vector(2, u32), [runtime value]) | |
| 1762 | // @as(@Vector(2, u32), [runtime value]) | |
| 1763 | // @as(@Vector(2, u32), [runtime value]) | |
| 1764 | // @as(@Vector(2, u32), [runtime value]) | |
| 1765 | // @as(@Vector(2, u32), [runtime value]) | |
| 1766 | // @as(@Vector(2, u32), [runtime value]) | |
| 1767 | // @as(@Vector(2, u32), [runtime value]) | |
| 1768 | // @as(@Vector(2, u32), [runtime value]) | |
| 1769 | // @as(@Vector(2, u32), [runtime value]) | |
| 1770 | // @as(@Vector(2, u32), [runtime value]) | |
| 1771 | // @as(@Vector(2, u32), undefined) | |
| 1772 | // @as(u32, undefined) | |
| 1773 | // @as(@Vector(2, u32), undefined) | |
| 1774 | // @as(u32, undefined) | |
| 1775 | // @as(u32, undefined) | |
| 1776 | // @as(@Vector(2, u32), undefined) | |
| 1777 | // @as(@Vector(2, u32), undefined) | |
| 1778 | // @as(u1, undefined) | |
| 1779 | // @as(@Vector(2, u1), [runtime value]) | |
| 1780 | // @as(@Vector(2, u1), [runtime value]) | |
| 1781 | // @as(@Vector(2, u1), undefined) | |
| 1782 | // @as(u32, undefined) | |
| 1783 | // @as(@Vector(2, u32), undefined) | |
| 1784 | // @as(i8, undefined) | |
| 1785 | // @as(i8, undefined) | |
| 1786 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 1787 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 1788 | // @as(@Vector(2, i8), undefined) | |
| 1789 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 1790 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 1791 | // @as(@Vector(2, i8), undefined) | |
| 1792 | // @as(@Vector(2, i8), undefined) | |
| 1793 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 1794 | // @as(@Vector(2, i8), undefined) | |
| 1795 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 1796 | // @as(@Vector(2, i8), undefined) | |
| 1797 | // @as(@Vector(2, i8), undefined) | |
| 1798 | // @as(@Vector(2, i8), undefined) | |
| 1799 | // @as(@Vector(2, i8), undefined) | |
| 1800 | // @as(@Vector(2, i8), undefined) | |
| 1801 | // @as(i8, undefined) | |
| 1802 | // @as(i8, undefined) | |
| 1803 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 1804 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 1805 | // @as(@Vector(2, i8), undefined) | |
| 1806 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 1807 | // @as(@Vector(2, i8), .{ 6, undefined }) | |
| 1808 | // @as(@Vector(2, i8), undefined) | |
| 1809 | // @as(@Vector(2, i8), undefined) | |
| 1810 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 1811 | // @as(@Vector(2, i8), undefined) | |
| 1812 | // @as(@Vector(2, i8), .{ undefined, 6 }) | |
| 1813 | // @as(@Vector(2, i8), undefined) | |
| 1814 | // @as(@Vector(2, i8), undefined) | |
| 1815 | // @as(@Vector(2, i8), undefined) | |
| 1816 | // @as(@Vector(2, i8), undefined) | |
| 1817 | // @as(@Vector(2, i8), undefined) | |
| 1818 | // @as(i8, undefined) | |
| 1819 | // @as(i8, undefined) | |
| 1820 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1821 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1822 | // @as(@Vector(2, i8), undefined) | |
| 1823 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1824 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1825 | // @as(@Vector(2, i8), undefined) | |
| 1826 | // @as(@Vector(2, i8), undefined) | |
| 1827 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1828 | // @as(@Vector(2, i8), undefined) | |
| 1829 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1830 | // @as(@Vector(2, i8), undefined) | |
| 1831 | // @as(@Vector(2, i8), undefined) | |
| 1832 | // @as(@Vector(2, i8), undefined) | |
| 1833 | // @as(@Vector(2, i8), undefined) | |
| 1834 | // @as(@Vector(2, i8), undefined) | |
| 1835 | // @as(i8, undefined) | |
| 1836 | // @as(i8, undefined) | |
| 1837 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1838 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1839 | // @as(@Vector(2, i8), undefined) | |
| 1840 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1841 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1842 | // @as(@Vector(2, i8), undefined) | |
| 1843 | // @as(@Vector(2, i8), undefined) | |
| 1844 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1845 | // @as(@Vector(2, i8), undefined) | |
| 1846 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1847 | // @as(@Vector(2, i8), undefined) | |
| 1848 | // @as(@Vector(2, i8), undefined) | |
| 1849 | // @as(@Vector(2, i8), undefined) | |
| 1850 | // @as(@Vector(2, i8), undefined) | |
| 1851 | // @as(@Vector(2, i8), undefined) | |
| 1852 | // @as(i8, undefined) | |
| 1853 | // @as(i8, undefined) | |
| 1854 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 1855 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 1856 | // @as(@Vector(2, i8), undefined) | |
| 1857 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 1858 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 1859 | // @as(@Vector(2, i8), undefined) | |
| 1860 | // @as(@Vector(2, i8), undefined) | |
| 1861 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 1862 | // @as(@Vector(2, i8), undefined) | |
| 1863 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 1864 | // @as(@Vector(2, i8), undefined) | |
| 1865 | // @as(@Vector(2, i8), undefined) | |
| 1866 | // @as(@Vector(2, i8), undefined) | |
| 1867 | // @as(@Vector(2, i8), undefined) | |
| 1868 | // @as(@Vector(2, i8), undefined) | |
| 1869 | // @as(i8, undefined) | |
| 1870 | // @as(i8, undefined) | |
| 1871 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 1872 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 1873 | // @as(@Vector(2, i8), undefined) | |
| 1874 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 1875 | // @as(@Vector(2, i8), .{ 9, undefined }) | |
| 1876 | // @as(@Vector(2, i8), undefined) | |
| 1877 | // @as(@Vector(2, i8), undefined) | |
| 1878 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 1879 | // @as(@Vector(2, i8), undefined) | |
| 1880 | // @as(@Vector(2, i8), .{ undefined, 9 }) | |
| 1881 | // @as(@Vector(2, i8), undefined) | |
| 1882 | // @as(@Vector(2, i8), undefined) | |
| 1883 | // @as(@Vector(2, i8), undefined) | |
| 1884 | // @as(@Vector(2, i8), undefined) | |
| 1885 | // @as(@Vector(2, i8), undefined) | |
| 1886 | // @as(i8, undefined) | |
| 1887 | // @as(i8, undefined) | |
| 1888 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1889 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1890 | // @as(@Vector(2, i8), undefined) | |
| 1891 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1892 | // @as(@Vector(2, i8), .{ 0, undefined }) | |
| 1893 | // @as(@Vector(2, i8), undefined) | |
| 1894 | // @as(@Vector(2, i8), undefined) | |
| 1895 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1896 | // @as(@Vector(2, i8), undefined) | |
| 1897 | // @as(@Vector(2, i8), .{ undefined, 0 }) | |
| 1898 | // @as(@Vector(2, i8), undefined) | |
| 1899 | // @as(@Vector(2, i8), undefined) | |
| 1900 | // @as(@Vector(2, i8), undefined) | |
| 1901 | // @as(@Vector(2, i8), undefined) | |
| 1902 | // @as(@Vector(2, i8), undefined) | |
| 1903 | // @as(i8, undefined) | |
| 1904 | // @as(@Vector(2, i8), undefined) | |
| 1905 | // @as(i8, undefined) | |
| 1906 | // @as(i8, undefined) | |
| 1907 | // @as(@Vector(2, i8), undefined) | |
| 1908 | // @as(@Vector(2, i8), undefined) | |
| 1909 | // @as(i8, undefined) | |
| 1910 | // @as(@Vector(2, i8), undefined) | |
| 1911 | // @as(i8, undefined) | |
| 1912 | // @as(i8, undefined) | |
| 1913 | // @as(@Vector(2, i8), [runtime value]) | |
| 1914 | // @as(@Vector(2, i8), [runtime value]) | |
| 1915 | // @as(@Vector(2, i8), undefined) | |
| 1916 | // @as(@Vector(2, i8), [runtime value]) | |
| 1917 | // @as(@Vector(2, i8), [runtime value]) | |
| 1918 | // @as(@Vector(2, i8), [runtime value]) | |
| 1919 | // @as(@Vector(2, i8), undefined) | |
| 1920 | // @as(@Vector(2, i8), [runtime value]) | |
| 1921 | // @as(@Vector(2, i8), [runtime value]) | |
| 1922 | // @as(@Vector(2, i8), [runtime value]) | |
| 1923 | // @as(@Vector(2, i8), undefined) | |
| 1924 | // @as(@Vector(2, i8), undefined) | |
| 1925 | // @as(@Vector(2, i8), undefined) | |
| 1926 | // @as(@Vector(2, i8), undefined) | |
| 1927 | // @as(@Vector(2, i8), undefined) | |
| 1928 | // @as(i8, undefined) | |
| 1929 | // @as(i8, undefined) | |
| 1930 | // @as(@Vector(2, i8), [runtime value]) | |
| 1931 | // @as(@Vector(2, i8), [runtime value]) | |
| 1932 | // @as(@Vector(2, i8), undefined) | |
| 1933 | // @as(@Vector(2, i8), [runtime value]) | |
| 1934 | // @as(@Vector(2, i8), [runtime value]) | |
| 1935 | // @as(@Vector(2, i8), [runtime value]) | |
| 1936 | // @as(@Vector(2, i8), undefined) | |
| 1937 | // @as(@Vector(2, i8), [runtime value]) | |
| 1938 | // @as(@Vector(2, i8), [runtime value]) | |
| 1939 | // @as(@Vector(2, i8), [runtime value]) | |
| 1940 | // @as(@Vector(2, i8), undefined) | |
| 1941 | // @as(@Vector(2, i8), undefined) | |
| 1942 | // @as(@Vector(2, i8), undefined) | |
| 1943 | // @as(@Vector(2, i8), undefined) | |
| 1944 | // @as(@Vector(2, i8), undefined) | |
| 1945 | // @as(i8, undefined) | |
| 1946 | // @as(i8, undefined) | |
| 1947 | // @as(@Vector(2, i8), [runtime value]) | |
| 1948 | // @as(@Vector(2, i8), [runtime value]) | |
| 1949 | // @as(@Vector(2, i8), undefined) | |
| 1950 | // @as(@Vector(2, i8), [runtime value]) | |
| 1951 | // @as(@Vector(2, i8), [runtime value]) | |
| 1952 | // @as(@Vector(2, i8), [runtime value]) | |
| 1953 | // @as(@Vector(2, i8), undefined) | |
| 1954 | // @as(@Vector(2, i8), [runtime value]) | |
| 1955 | // @as(@Vector(2, i8), [runtime value]) | |
| 1956 | // @as(@Vector(2, i8), [runtime value]) | |
| 1957 | // @as(@Vector(2, i8), undefined) | |
| 1958 | // @as(@Vector(2, i8), undefined) | |
| 1959 | // @as(@Vector(2, i8), undefined) | |
| 1960 | // @as(@Vector(2, i8), undefined) | |
| 1961 | // @as(@Vector(2, i8), undefined) | |
| 1962 | // @as(i8, undefined) | |
| 1963 | // @as(i8, undefined) | |
| 1964 | // @as(@Vector(2, i8), [runtime value]) | |
| 1965 | // @as(@Vector(2, i8), [runtime value]) | |
| 1966 | // @as(@Vector(2, i8), undefined) | |
| 1967 | // @as(@Vector(2, i8), [runtime value]) | |
| 1968 | // @as(@Vector(2, i8), [runtime value]) | |
| 1969 | // @as(@Vector(2, i8), [runtime value]) | |
| 1970 | // @as(@Vector(2, i8), undefined) | |
| 1971 | // @as(@Vector(2, i8), [runtime value]) | |
| 1972 | // @as(@Vector(2, i8), [runtime value]) | |
| 1973 | // @as(@Vector(2, i8), [runtime value]) | |
| 1974 | // @as(@Vector(2, i8), undefined) | |
| 1975 | // @as(@Vector(2, i8), undefined) | |
| 1976 | // @as(@Vector(2, i8), undefined) | |
| 1977 | // @as(@Vector(2, i8), undefined) | |
| 1978 | // @as(@Vector(2, i8), undefined) | |
| 1979 | // @as(i8, undefined) | |
| 1980 | // @as(i8, undefined) | |
| 1981 | // @as(@Vector(2, i8), [runtime value]) | |
| 1982 | // @as(@Vector(2, i8), [runtime value]) | |
| 1983 | // @as(@Vector(2, i8), undefined) | |
| 1984 | // @as(@Vector(2, i8), [runtime value]) | |
| 1985 | // @as(@Vector(2, i8), [runtime value]) | |
| 1986 | // @as(@Vector(2, i8), [runtime value]) | |
| 1987 | // @as(@Vector(2, i8), undefined) | |
| 1988 | // @as(@Vector(2, i8), [runtime value]) | |
| 1989 | // @as(@Vector(2, i8), [runtime value]) | |
| 1990 | // @as(@Vector(2, i8), [runtime value]) | |
| 1991 | // @as(@Vector(2, i8), undefined) | |
| 1992 | // @as(@Vector(2, i8), undefined) | |
| 1993 | // @as(@Vector(2, i8), undefined) | |
| 1994 | // @as(@Vector(2, i8), undefined) | |
| 1995 | // @as(@Vector(2, i8), undefined) | |
| 1996 | // @as(i8, undefined) | |
| 1997 | // @as(i8, undefined) | |
| 1998 | // @as(@Vector(2, i8), [runtime value]) | |
| 1999 | // @as(@Vector(2, i8), [runtime value]) | |
| 2000 | // @as(@Vector(2, i8), undefined) | |
| 2001 | // @as(@Vector(2, i8), [runtime value]) | |
| 2002 | // @as(@Vector(2, i8), [runtime value]) | |
| 2003 | // @as(@Vector(2, i8), [runtime value]) | |
| 2004 | // @as(@Vector(2, i8), undefined) | |
| 2005 | // @as(@Vector(2, i8), [runtime value]) | |
| 2006 | // @as(@Vector(2, i8), [runtime value]) | |
| 2007 | // @as(@Vector(2, i8), [runtime value]) | |
| 2008 | // @as(@Vector(2, i8), undefined) | |
| 2009 | // @as(@Vector(2, i8), undefined) | |
| 2010 | // @as(@Vector(2, i8), undefined) | |
| 2011 | // @as(@Vector(2, i8), undefined) | |
| 2012 | // @as(@Vector(2, i8), undefined) | |
| 2013 | // @as(i8, [runtime value]) | |
| 2014 | // @as(i8, [runtime value]) | |
| 2015 | // @as(@Vector(2, i8), [runtime value]) | |
| 2016 | // @as(@Vector(2, i8), [runtime value]) | |
| 2017 | // @as(@Vector(2, i8), [runtime value]) | |
| 2018 | // @as(@Vector(2, i8), [runtime value]) | |
| 2019 | // @as(@Vector(2, i8), [runtime value]) | |
| 2020 | // @as(@Vector(2, i8), [runtime value]) | |
| 2021 | // @as(@Vector(2, i8), [runtime value]) | |
| 2022 | // @as(@Vector(2, i8), [runtime value]) | |
| 2023 | // @as(@Vector(2, i8), [runtime value]) | |
| 2024 | // @as(@Vector(2, i8), [runtime value]) | |
| 2025 | // @as(@Vector(2, i8), [runtime value]) | |
| 2026 | // @as(@Vector(2, i8), [runtime value]) | |
| 2027 | // @as(@Vector(2, i8), [runtime value]) | |
| 2028 | // @as(@Vector(2, i8), [runtime value]) | |
| 2029 | // @as(@Vector(2, i8), undefined) | |
| 2030 | // @as(i8, undefined) | |
| 2031 | // @as(@Vector(2, i8), undefined) | |
| 2032 | // @as(i8, undefined) | |
| 2033 | // @as(i8, undefined) | |
| 2034 | // @as(@Vector(2, i8), undefined) | |
| 2035 | // @as(@Vector(2, i8), undefined) | |
| 2036 | // @as(i8, undefined) | |
| 2037 | // @as(@Vector(2, i8), undefined) | |
| 2478 | 2038 | // @as(f128, undefined) |
| 2479 | 2039 | // @as(f128, undefined) |
| 2480 | 2040 | // @as(@Vector(2, f128), .{ 6, undefined }) |
| ... | ... | @@ -2585,3 +2145,443 @@ inline fn testFloatWithValue(comptime Float: type, x: Float) void { |
| 2585 | 2145 | // @as(@Vector(2, f128), [runtime value]) |
| 2586 | 2146 | // @as(@Vector(2, f128), [runtime value]) |
| 2587 | 2147 | // @as(@Vector(2, f128), undefined) |
| 2148 | // @as(f80, undefined) | |
| 2149 | // @as(f80, undefined) | |
| 2150 | // @as(@Vector(2, f80), .{ 6, undefined }) | |
| 2151 | // @as(@Vector(2, f80), .{ undefined, 6 }) | |
| 2152 | // @as(@Vector(2, f80), undefined) | |
| 2153 | // @as(@Vector(2, f80), .{ 6, undefined }) | |
| 2154 | // @as(@Vector(2, f80), .{ 6, undefined }) | |
| 2155 | // @as(@Vector(2, f80), undefined) | |
| 2156 | // @as(@Vector(2, f80), undefined) | |
| 2157 | // @as(@Vector(2, f80), .{ undefined, 6 }) | |
| 2158 | // @as(@Vector(2, f80), undefined) | |
| 2159 | // @as(@Vector(2, f80), .{ undefined, 6 }) | |
| 2160 | // @as(@Vector(2, f80), undefined) | |
| 2161 | // @as(@Vector(2, f80), undefined) | |
| 2162 | // @as(@Vector(2, f80), undefined) | |
| 2163 | // @as(@Vector(2, f80), undefined) | |
| 2164 | // @as(@Vector(2, f80), undefined) | |
| 2165 | // @as(f80, undefined) | |
| 2166 | // @as(f80, undefined) | |
| 2167 | // @as(@Vector(2, f80), .{ 0, undefined }) | |
| 2168 | // @as(@Vector(2, f80), .{ undefined, 0 }) | |
| 2169 | // @as(@Vector(2, f80), undefined) | |
| 2170 | // @as(@Vector(2, f80), .{ 0, undefined }) | |
| 2171 | // @as(@Vector(2, f80), .{ 0, undefined }) | |
| 2172 | // @as(@Vector(2, f80), undefined) | |
| 2173 | // @as(@Vector(2, f80), undefined) | |
| 2174 | // @as(@Vector(2, f80), .{ undefined, 0 }) | |
| 2175 | // @as(@Vector(2, f80), undefined) | |
| 2176 | // @as(@Vector(2, f80), .{ undefined, 0 }) | |
| 2177 | // @as(@Vector(2, f80), undefined) | |
| 2178 | // @as(@Vector(2, f80), undefined) | |
| 2179 | // @as(@Vector(2, f80), undefined) | |
| 2180 | // @as(@Vector(2, f80), undefined) | |
| 2181 | // @as(@Vector(2, f80), undefined) | |
| 2182 | // @as(f80, undefined) | |
| 2183 | // @as(f80, undefined) | |
| 2184 | // @as(@Vector(2, f80), .{ 9, undefined }) | |
| 2185 | // @as(@Vector(2, f80), .{ undefined, 9 }) | |
| 2186 | // @as(@Vector(2, f80), undefined) | |
| 2187 | // @as(@Vector(2, f80), .{ 9, undefined }) | |
| 2188 | // @as(@Vector(2, f80), .{ 9, undefined }) | |
| 2189 | // @as(@Vector(2, f80), undefined) | |
| 2190 | // @as(@Vector(2, f80), undefined) | |
| 2191 | // @as(@Vector(2, f80), .{ undefined, 9 }) | |
| 2192 | // @as(@Vector(2, f80), undefined) | |
| 2193 | // @as(@Vector(2, f80), .{ undefined, 9 }) | |
| 2194 | // @as(@Vector(2, f80), undefined) | |
| 2195 | // @as(@Vector(2, f80), undefined) | |
| 2196 | // @as(@Vector(2, f80), undefined) | |
| 2197 | // @as(@Vector(2, f80), undefined) | |
| 2198 | // @as(@Vector(2, f80), undefined) | |
| 2199 | // @as(f80, undefined) | |
| 2200 | // @as(@Vector(2, f80), .{ -3, undefined }) | |
| 2201 | // @as(@Vector(2, f80), .{ undefined, -3 }) | |
| 2202 | // @as(@Vector(2, f80), undefined) | |
| 2203 | // @as(f80, undefined) | |
| 2204 | // @as(f80, undefined) | |
| 2205 | // @as(@Vector(2, f80), [runtime value]) | |
| 2206 | // @as(@Vector(2, f80), [runtime value]) | |
| 2207 | // @as(@Vector(2, f80), undefined) | |
| 2208 | // @as(@Vector(2, f80), [runtime value]) | |
| 2209 | // @as(@Vector(2, f80), [runtime value]) | |
| 2210 | // @as(@Vector(2, f80), [runtime value]) | |
| 2211 | // @as(@Vector(2, f80), undefined) | |
| 2212 | // @as(@Vector(2, f80), [runtime value]) | |
| 2213 | // @as(@Vector(2, f80), [runtime value]) | |
| 2214 | // @as(@Vector(2, f80), [runtime value]) | |
| 2215 | // @as(@Vector(2, f80), undefined) | |
| 2216 | // @as(@Vector(2, f80), undefined) | |
| 2217 | // @as(@Vector(2, f80), undefined) | |
| 2218 | // @as(@Vector(2, f80), undefined) | |
| 2219 | // @as(@Vector(2, f80), undefined) | |
| 2220 | // @as(f80, undefined) | |
| 2221 | // @as(f80, undefined) | |
| 2222 | // @as(@Vector(2, f80), [runtime value]) | |
| 2223 | // @as(@Vector(2, f80), [runtime value]) | |
| 2224 | // @as(@Vector(2, f80), undefined) | |
| 2225 | // @as(@Vector(2, f80), [runtime value]) | |
| 2226 | // @as(@Vector(2, f80), [runtime value]) | |
| 2227 | // @as(@Vector(2, f80), [runtime value]) | |
| 2228 | // @as(@Vector(2, f80), undefined) | |
| 2229 | // @as(@Vector(2, f80), [runtime value]) | |
| 2230 | // @as(@Vector(2, f80), [runtime value]) | |
| 2231 | // @as(@Vector(2, f80), [runtime value]) | |
| 2232 | // @as(@Vector(2, f80), undefined) | |
| 2233 | // @as(@Vector(2, f80), undefined) | |
| 2234 | // @as(@Vector(2, f80), undefined) | |
| 2235 | // @as(@Vector(2, f80), undefined) | |
| 2236 | // @as(@Vector(2, f80), undefined) | |
| 2237 | // @as(f80, undefined) | |
| 2238 | // @as(f80, undefined) | |
| 2239 | // @as(@Vector(2, f80), [runtime value]) | |
| 2240 | // @as(@Vector(2, f80), [runtime value]) | |
| 2241 | // @as(@Vector(2, f80), undefined) | |
| 2242 | // @as(@Vector(2, f80), [runtime value]) | |
| 2243 | // @as(@Vector(2, f80), [runtime value]) | |
| 2244 | // @as(@Vector(2, f80), [runtime value]) | |
| 2245 | // @as(@Vector(2, f80), undefined) | |
| 2246 | // @as(@Vector(2, f80), [runtime value]) | |
| 2247 | // @as(@Vector(2, f80), [runtime value]) | |
| 2248 | // @as(@Vector(2, f80), [runtime value]) | |
| 2249 | // @as(@Vector(2, f80), undefined) | |
| 2250 | // @as(@Vector(2, f80), undefined) | |
| 2251 | // @as(@Vector(2, f80), undefined) | |
| 2252 | // @as(@Vector(2, f80), undefined) | |
| 2253 | // @as(@Vector(2, f80), undefined) | |
| 2254 | // @as(f80, undefined) | |
| 2255 | // @as(@Vector(2, f80), [runtime value]) | |
| 2256 | // @as(@Vector(2, f80), [runtime value]) | |
| 2257 | // @as(@Vector(2, f80), undefined) | |
| 2258 | // @as(f64, undefined) | |
| 2259 | // @as(f64, undefined) | |
| 2260 | // @as(@Vector(2, f64), .{ 6, undefined }) | |
| 2261 | // @as(@Vector(2, f64), .{ undefined, 6 }) | |
| 2262 | // @as(@Vector(2, f64), undefined) | |
| 2263 | // @as(@Vector(2, f64), .{ 6, undefined }) | |
| 2264 | // @as(@Vector(2, f64), .{ 6, undefined }) | |
| 2265 | // @as(@Vector(2, f64), undefined) | |
| 2266 | // @as(@Vector(2, f64), undefined) | |
| 2267 | // @as(@Vector(2, f64), .{ undefined, 6 }) | |
| 2268 | // @as(@Vector(2, f64), undefined) | |
| 2269 | // @as(@Vector(2, f64), .{ undefined, 6 }) | |
| 2270 | // @as(@Vector(2, f64), undefined) | |
| 2271 | // @as(@Vector(2, f64), undefined) | |
| 2272 | // @as(@Vector(2, f64), undefined) | |
| 2273 | // @as(@Vector(2, f64), undefined) | |
| 2274 | // @as(@Vector(2, f64), undefined) | |
| 2275 | // @as(f64, undefined) | |
| 2276 | // @as(f64, undefined) | |
| 2277 | // @as(@Vector(2, f64), .{ 0, undefined }) | |
| 2278 | // @as(@Vector(2, f64), .{ undefined, 0 }) | |
| 2279 | // @as(@Vector(2, f64), undefined) | |
| 2280 | // @as(@Vector(2, f64), .{ 0, undefined }) | |
| 2281 | // @as(@Vector(2, f64), .{ 0, undefined }) | |
| 2282 | // @as(@Vector(2, f64), undefined) | |
| 2283 | // @as(@Vector(2, f64), undefined) | |
| 2284 | // @as(@Vector(2, f64), .{ undefined, 0 }) | |
| 2285 | // @as(@Vector(2, f64), undefined) | |
| 2286 | // @as(@Vector(2, f64), .{ undefined, 0 }) | |
| 2287 | // @as(@Vector(2, f64), undefined) | |
| 2288 | // @as(@Vector(2, f64), undefined) | |
| 2289 | // @as(@Vector(2, f64), undefined) | |
| 2290 | // @as(@Vector(2, f64), undefined) | |
| 2291 | // @as(@Vector(2, f64), undefined) | |
| 2292 | // @as(f64, undefined) | |
| 2293 | // @as(f64, undefined) | |
| 2294 | // @as(@Vector(2, f64), .{ 9, undefined }) | |
| 2295 | // @as(@Vector(2, f64), .{ undefined, 9 }) | |
| 2296 | // @as(@Vector(2, f64), undefined) | |
| 2297 | // @as(@Vector(2, f64), .{ 9, undefined }) | |
| 2298 | // @as(@Vector(2, f64), .{ 9, undefined }) | |
| 2299 | // @as(@Vector(2, f64), undefined) | |
| 2300 | // @as(@Vector(2, f64), undefined) | |
| 2301 | // @as(@Vector(2, f64), .{ undefined, 9 }) | |
| 2302 | // @as(@Vector(2, f64), undefined) | |
| 2303 | // @as(@Vector(2, f64), .{ undefined, 9 }) | |
| 2304 | // @as(@Vector(2, f64), undefined) | |
| 2305 | // @as(@Vector(2, f64), undefined) | |
| 2306 | // @as(@Vector(2, f64), undefined) | |
| 2307 | // @as(@Vector(2, f64), undefined) | |
| 2308 | // @as(@Vector(2, f64), undefined) | |
| 2309 | // @as(f64, undefined) | |
| 2310 | // @as(@Vector(2, f64), .{ -3, undefined }) | |
| 2311 | // @as(@Vector(2, f64), .{ undefined, -3 }) | |
| 2312 | // @as(@Vector(2, f64), undefined) | |
| 2313 | // @as(f64, undefined) | |
| 2314 | // @as(f64, undefined) | |
| 2315 | // @as(@Vector(2, f64), [runtime value]) | |
| 2316 | // @as(@Vector(2, f64), [runtime value]) | |
| 2317 | // @as(@Vector(2, f64), undefined) | |
| 2318 | // @as(@Vector(2, f64), [runtime value]) | |
| 2319 | // @as(@Vector(2, f64), [runtime value]) | |
| 2320 | // @as(@Vector(2, f64), [runtime value]) | |
| 2321 | // @as(@Vector(2, f64), undefined) | |
| 2322 | // @as(@Vector(2, f64), [runtime value]) | |
| 2323 | // @as(@Vector(2, f64), [runtime value]) | |
| 2324 | // @as(@Vector(2, f64), [runtime value]) | |
| 2325 | // @as(@Vector(2, f64), undefined) | |
| 2326 | // @as(@Vector(2, f64), undefined) | |
| 2327 | // @as(@Vector(2, f64), undefined) | |
| 2328 | // @as(@Vector(2, f64), undefined) | |
| 2329 | // @as(@Vector(2, f64), undefined) | |
| 2330 | // @as(f64, undefined) | |
| 2331 | // @as(f64, undefined) | |
| 2332 | // @as(@Vector(2, f64), [runtime value]) | |
| 2333 | // @as(@Vector(2, f64), [runtime value]) | |
| 2334 | // @as(@Vector(2, f64), undefined) | |
| 2335 | // @as(@Vector(2, f64), [runtime value]) | |
| 2336 | // @as(@Vector(2, f64), [runtime value]) | |
| 2337 | // @as(@Vector(2, f64), [runtime value]) | |
| 2338 | // @as(@Vector(2, f64), undefined) | |
| 2339 | // @as(@Vector(2, f64), [runtime value]) | |
| 2340 | // @as(@Vector(2, f64), [runtime value]) | |
| 2341 | // @as(@Vector(2, f64), [runtime value]) | |
| 2342 | // @as(@Vector(2, f64), undefined) | |
| 2343 | // @as(@Vector(2, f64), undefined) | |
| 2344 | // @as(@Vector(2, f64), undefined) | |
| 2345 | // @as(@Vector(2, f64), undefined) | |
| 2346 | // @as(@Vector(2, f64), undefined) | |
| 2347 | // @as(f64, undefined) | |
| 2348 | // @as(f64, undefined) | |
| 2349 | // @as(@Vector(2, f64), [runtime value]) | |
| 2350 | // @as(@Vector(2, f64), [runtime value]) | |
| 2351 | // @as(@Vector(2, f64), undefined) | |
| 2352 | // @as(@Vector(2, f64), [runtime value]) | |
| 2353 | // @as(@Vector(2, f64), [runtime value]) | |
| 2354 | // @as(@Vector(2, f64), [runtime value]) | |
| 2355 | // @as(@Vector(2, f64), undefined) | |
| 2356 | // @as(@Vector(2, f64), [runtime value]) | |
| 2357 | // @as(@Vector(2, f64), [runtime value]) | |
| 2358 | // @as(@Vector(2, f64), [runtime value]) | |
| 2359 | // @as(@Vector(2, f64), undefined) | |
| 2360 | // @as(@Vector(2, f64), undefined) | |
| 2361 | // @as(@Vector(2, f64), undefined) | |
| 2362 | // @as(@Vector(2, f64), undefined) | |
| 2363 | // @as(@Vector(2, f64), undefined) | |
| 2364 | // @as(f64, undefined) | |
| 2365 | // @as(@Vector(2, f64), [runtime value]) | |
| 2366 | // @as(@Vector(2, f64), [runtime value]) | |
| 2367 | // @as(@Vector(2, f64), undefined) | |
| 2368 | // @as(f32, undefined) | |
| 2369 | // @as(f32, undefined) | |
| 2370 | // @as(@Vector(2, f32), .{ 6, undefined }) | |
| 2371 | // @as(@Vector(2, f32), .{ undefined, 6 }) | |
| 2372 | // @as(@Vector(2, f32), undefined) | |
| 2373 | // @as(@Vector(2, f32), .{ 6, undefined }) | |
| 2374 | // @as(@Vector(2, f32), .{ 6, undefined }) | |
| 2375 | // @as(@Vector(2, f32), undefined) | |
| 2376 | // @as(@Vector(2, f32), undefined) | |
| 2377 | // @as(@Vector(2, f32), .{ undefined, 6 }) | |
| 2378 | // @as(@Vector(2, f32), undefined) | |
| 2379 | // @as(@Vector(2, f32), .{ undefined, 6 }) | |
| 2380 | // @as(@Vector(2, f32), undefined) | |
| 2381 | // @as(@Vector(2, f32), undefined) | |
| 2382 | // @as(@Vector(2, f32), undefined) | |
| 2383 | // @as(@Vector(2, f32), undefined) | |
| 2384 | // @as(@Vector(2, f32), undefined) | |
| 2385 | // @as(f32, undefined) | |
| 2386 | // @as(f32, undefined) | |
| 2387 | // @as(@Vector(2, f32), .{ 0, undefined }) | |
| 2388 | // @as(@Vector(2, f32), .{ undefined, 0 }) | |
| 2389 | // @as(@Vector(2, f32), undefined) | |
| 2390 | // @as(@Vector(2, f32), .{ 0, undefined }) | |
| 2391 | // @as(@Vector(2, f32), .{ 0, undefined }) | |
| 2392 | // @as(@Vector(2, f32), undefined) | |
| 2393 | // @as(@Vector(2, f32), undefined) | |
| 2394 | // @as(@Vector(2, f32), .{ undefined, 0 }) | |
| 2395 | // @as(@Vector(2, f32), undefined) | |
| 2396 | // @as(@Vector(2, f32), .{ undefined, 0 }) | |
| 2397 | // @as(@Vector(2, f32), undefined) | |
| 2398 | // @as(@Vector(2, f32), undefined) | |
| 2399 | // @as(@Vector(2, f32), undefined) | |
| 2400 | // @as(@Vector(2, f32), undefined) | |
| 2401 | // @as(@Vector(2, f32), undefined) | |
| 2402 | // @as(f32, undefined) | |
| 2403 | // @as(f32, undefined) | |
| 2404 | // @as(@Vector(2, f32), .{ 9, undefined }) | |
| 2405 | // @as(@Vector(2, f32), .{ undefined, 9 }) | |
| 2406 | // @as(@Vector(2, f32), undefined) | |
| 2407 | // @as(@Vector(2, f32), .{ 9, undefined }) | |
| 2408 | // @as(@Vector(2, f32), .{ 9, undefined }) | |
| 2409 | // @as(@Vector(2, f32), undefined) | |
| 2410 | // @as(@Vector(2, f32), undefined) | |
| 2411 | // @as(@Vector(2, f32), .{ undefined, 9 }) | |
| 2412 | // @as(@Vector(2, f32), undefined) | |
| 2413 | // @as(@Vector(2, f32), .{ undefined, 9 }) | |
| 2414 | // @as(@Vector(2, f32), undefined) | |
| 2415 | // @as(@Vector(2, f32), undefined) | |
| 2416 | // @as(@Vector(2, f32), undefined) | |
| 2417 | // @as(@Vector(2, f32), undefined) | |
| 2418 | // @as(@Vector(2, f32), undefined) | |
| 2419 | // @as(f32, undefined) | |
| 2420 | // @as(@Vector(2, f32), .{ -3, undefined }) | |
| 2421 | // @as(@Vector(2, f32), .{ undefined, -3 }) | |
| 2422 | // @as(@Vector(2, f32), undefined) | |
| 2423 | // @as(f32, undefined) | |
| 2424 | // @as(f32, undefined) | |
| 2425 | // @as(@Vector(2, f32), [runtime value]) | |
| 2426 | // @as(@Vector(2, f32), [runtime value]) | |
| 2427 | // @as(@Vector(2, f32), undefined) | |
| 2428 | // @as(@Vector(2, f32), [runtime value]) | |
| 2429 | // @as(@Vector(2, f32), [runtime value]) | |
| 2430 | // @as(@Vector(2, f32), [runtime value]) | |
| 2431 | // @as(@Vector(2, f32), undefined) | |
| 2432 | // @as(@Vector(2, f32), [runtime value]) | |
| 2433 | // @as(@Vector(2, f32), [runtime value]) | |
| 2434 | // @as(@Vector(2, f32), [runtime value]) | |
| 2435 | // @as(@Vector(2, f32), undefined) | |
| 2436 | // @as(@Vector(2, f32), undefined) | |
| 2437 | // @as(@Vector(2, f32), undefined) | |
| 2438 | // @as(@Vector(2, f32), undefined) | |
| 2439 | // @as(@Vector(2, f32), undefined) | |
| 2440 | // @as(f32, undefined) | |
| 2441 | // @as(f32, undefined) | |
| 2442 | // @as(@Vector(2, f32), [runtime value]) | |
| 2443 | // @as(@Vector(2, f32), [runtime value]) | |
| 2444 | // @as(@Vector(2, f32), undefined) | |
| 2445 | // @as(@Vector(2, f32), [runtime value]) | |
| 2446 | // @as(@Vector(2, f32), [runtime value]) | |
| 2447 | // @as(@Vector(2, f32), [runtime value]) | |
| 2448 | // @as(@Vector(2, f32), undefined) | |
| 2449 | // @as(@Vector(2, f32), [runtime value]) | |
| 2450 | // @as(@Vector(2, f32), [runtime value]) | |
| 2451 | // @as(@Vector(2, f32), [runtime value]) | |
| 2452 | // @as(@Vector(2, f32), undefined) | |
| 2453 | // @as(@Vector(2, f32), undefined) | |
| 2454 | // @as(@Vector(2, f32), undefined) | |
| 2455 | // @as(@Vector(2, f32), undefined) | |
| 2456 | // @as(@Vector(2, f32), undefined) | |
| 2457 | // @as(f32, undefined) | |
| 2458 | // @as(f32, undefined) | |
| 2459 | // @as(@Vector(2, f32), [runtime value]) | |
| 2460 | // @as(@Vector(2, f32), [runtime value]) | |
| 2461 | // @as(@Vector(2, f32), undefined) | |
| 2462 | // @as(@Vector(2, f32), [runtime value]) | |
| 2463 | // @as(@Vector(2, f32), [runtime value]) | |
| 2464 | // @as(@Vector(2, f32), [runtime value]) | |
| 2465 | // @as(@Vector(2, f32), undefined) | |
| 2466 | // @as(@Vector(2, f32), [runtime value]) | |
| 2467 | // @as(@Vector(2, f32), [runtime value]) | |
| 2468 | // @as(@Vector(2, f32), [runtime value]) | |
| 2469 | // @as(@Vector(2, f32), undefined) | |
| 2470 | // @as(@Vector(2, f32), undefined) | |
| 2471 | // @as(@Vector(2, f32), undefined) | |
| 2472 | // @as(@Vector(2, f32), undefined) | |
| 2473 | // @as(@Vector(2, f32), undefined) | |
| 2474 | // @as(f32, undefined) | |
| 2475 | // @as(@Vector(2, f32), [runtime value]) | |
| 2476 | // @as(@Vector(2, f32), [runtime value]) | |
| 2477 | // @as(@Vector(2, f32), undefined) | |
| 2478 | // @as(f16, undefined) | |
| 2479 | // @as(f16, undefined) | |
| 2480 | // @as(@Vector(2, f16), .{ 6, undefined }) | |
| 2481 | // @as(@Vector(2, f16), .{ undefined, 6 }) | |
| 2482 | // @as(@Vector(2, f16), undefined) | |
| 2483 | // @as(@Vector(2, f16), .{ 6, undefined }) | |
| 2484 | // @as(@Vector(2, f16), .{ 6, undefined }) | |
| 2485 | // @as(@Vector(2, f16), undefined) | |
| 2486 | // @as(@Vector(2, f16), undefined) | |
| 2487 | // @as(@Vector(2, f16), .{ undefined, 6 }) | |
| 2488 | // @as(@Vector(2, f16), undefined) | |
| 2489 | // @as(@Vector(2, f16), .{ undefined, 6 }) | |
| 2490 | // @as(@Vector(2, f16), undefined) | |
| 2491 | // @as(@Vector(2, f16), undefined) | |
| 2492 | // @as(@Vector(2, f16), undefined) | |
| 2493 | // @as(@Vector(2, f16), undefined) | |
| 2494 | // @as(@Vector(2, f16), undefined) | |
| 2495 | // @as(f16, undefined) | |
| 2496 | // @as(f16, undefined) | |
| 2497 | // @as(@Vector(2, f16), .{ 0, undefined }) | |
| 2498 | // @as(@Vector(2, f16), .{ undefined, 0 }) | |
| 2499 | // @as(@Vector(2, f16), undefined) | |
| 2500 | // @as(@Vector(2, f16), .{ 0, undefined }) | |
| 2501 | // @as(@Vector(2, f16), .{ 0, undefined }) | |
| 2502 | // @as(@Vector(2, f16), undefined) | |
| 2503 | // @as(@Vector(2, f16), undefined) | |
| 2504 | // @as(@Vector(2, f16), .{ undefined, 0 }) | |
| 2505 | // @as(@Vector(2, f16), undefined) | |
| 2506 | // @as(@Vector(2, f16), .{ undefined, 0 }) | |
| 2507 | // @as(@Vector(2, f16), undefined) | |
| 2508 | // @as(@Vector(2, f16), undefined) | |
| 2509 | // @as(@Vector(2, f16), undefined) | |
| 2510 | // @as(@Vector(2, f16), undefined) | |
| 2511 | // @as(@Vector(2, f16), undefined) | |
| 2512 | // @as(f16, undefined) | |
| 2513 | // @as(f16, undefined) | |
| 2514 | // @as(@Vector(2, f16), .{ 9, undefined }) | |
| 2515 | // @as(@Vector(2, f16), .{ undefined, 9 }) | |
| 2516 | // @as(@Vector(2, f16), undefined) | |
| 2517 | // @as(@Vector(2, f16), .{ 9, undefined }) | |
| 2518 | // @as(@Vector(2, f16), .{ 9, undefined }) | |
| 2519 | // @as(@Vector(2, f16), undefined) | |
| 2520 | // @as(@Vector(2, f16), undefined) | |
| 2521 | // @as(@Vector(2, f16), .{ undefined, 9 }) | |
| 2522 | // @as(@Vector(2, f16), undefined) | |
| 2523 | // @as(@Vector(2, f16), .{ undefined, 9 }) | |
| 2524 | // @as(@Vector(2, f16), undefined) | |
| 2525 | // @as(@Vector(2, f16), undefined) | |
| 2526 | // @as(@Vector(2, f16), undefined) | |
| 2527 | // @as(@Vector(2, f16), undefined) | |
| 2528 | // @as(@Vector(2, f16), undefined) | |
| 2529 | // @as(f16, undefined) | |
| 2530 | // @as(@Vector(2, f16), .{ -3, undefined }) | |
| 2531 | // @as(@Vector(2, f16), .{ undefined, -3 }) | |
| 2532 | // @as(@Vector(2, f16), undefined) | |
| 2533 | // @as(f16, undefined) | |
| 2534 | // @as(f16, undefined) | |
| 2535 | // @as(@Vector(2, f16), [runtime value]) | |
| 2536 | // @as(@Vector(2, f16), [runtime value]) | |
| 2537 | // @as(@Vector(2, f16), undefined) | |
| 2538 | // @as(@Vector(2, f16), [runtime value]) | |
| 2539 | // @as(@Vector(2, f16), [runtime value]) | |
| 2540 | // @as(@Vector(2, f16), [runtime value]) | |
| 2541 | // @as(@Vector(2, f16), undefined) | |
| 2542 | // @as(@Vector(2, f16), [runtime value]) | |
| 2543 | // @as(@Vector(2, f16), [runtime value]) | |
| 2544 | // @as(@Vector(2, f16), [runtime value]) | |
| 2545 | // @as(@Vector(2, f16), undefined) | |
| 2546 | // @as(@Vector(2, f16), undefined) | |
| 2547 | // @as(@Vector(2, f16), undefined) | |
| 2548 | // @as(@Vector(2, f16), undefined) | |
| 2549 | // @as(@Vector(2, f16), undefined) | |
| 2550 | // @as(f16, undefined) | |
| 2551 | // @as(f16, undefined) | |
| 2552 | // @as(@Vector(2, f16), [runtime value]) | |
| 2553 | // @as(@Vector(2, f16), [runtime value]) | |
| 2554 | // @as(@Vector(2, f16), undefined) | |
| 2555 | // @as(@Vector(2, f16), [runtime value]) | |
| 2556 | // @as(@Vector(2, f16), [runtime value]) | |
| 2557 | // @as(@Vector(2, f16), [runtime value]) | |
| 2558 | // @as(@Vector(2, f16), undefined) | |
| 2559 | // @as(@Vector(2, f16), [runtime value]) | |
| 2560 | // @as(@Vector(2, f16), [runtime value]) | |
| 2561 | // @as(@Vector(2, f16), [runtime value]) | |
| 2562 | // @as(@Vector(2, f16), undefined) | |
| 2563 | // @as(@Vector(2, f16), undefined) | |
| 2564 | // @as(@Vector(2, f16), undefined) | |
| 2565 | // @as(@Vector(2, f16), undefined) | |
| 2566 | // @as(@Vector(2, f16), undefined) | |
| 2567 | // @as(f16, undefined) | |
| 2568 | // @as(f16, undefined) | |
| 2569 | // @as(@Vector(2, f16), [runtime value]) | |
| 2570 | // @as(@Vector(2, f16), [runtime value]) | |
| 2571 | // @as(@Vector(2, f16), undefined) | |
| 2572 | // @as(@Vector(2, f16), [runtime value]) | |
| 2573 | // @as(@Vector(2, f16), [runtime value]) | |
| 2574 | // @as(@Vector(2, f16), [runtime value]) | |
| 2575 | // @as(@Vector(2, f16), undefined) | |
| 2576 | // @as(@Vector(2, f16), [runtime value]) | |
| 2577 | // @as(@Vector(2, f16), [runtime value]) | |
| 2578 | // @as(@Vector(2, f16), [runtime value]) | |
| 2579 | // @as(@Vector(2, f16), undefined) | |
| 2580 | // @as(@Vector(2, f16), undefined) | |
| 2581 | // @as(@Vector(2, f16), undefined) | |
| 2582 | // @as(@Vector(2, f16), undefined) | |
| 2583 | // @as(@Vector(2, f16), undefined) | |
| 2584 | // @as(f16, undefined) | |
| 2585 | // @as(@Vector(2, f16), [runtime value]) | |
| 2586 | // @as(@Vector(2, f16), [runtime value]) | |
| 2587 | // @as(@Vector(2, f16), undefined) |
test/cases/compile_errors/undef_shifts_are_illegal.zig+587-587| ... | ... | @@ -125,27 +125,19 @@ const std = @import("std"); |
| 125 | 125 | // :53:17: error: use of undefined value here causes illegal behavior |
| 126 | 126 | // :53:17: error: use of undefined value here causes illegal behavior |
| 127 | 127 | // :53:17: error: use of undefined value here causes illegal behavior |
| 128 | // :53:17: note: when computing vector element at index '0' | |
| 129 | 128 | // :53:17: error: use of undefined value here causes illegal behavior |
| 130 | // :53:17: note: when computing vector element at index '0' | |
| 131 | 129 | // :53:17: error: use of undefined value here causes illegal behavior |
| 132 | // :53:17: note: when computing vector element at index '0' | |
| 133 | 130 | // :53:17: error: use of undefined value here causes illegal behavior |
| 134 | // :53:17: note: when computing vector element at index '0' | |
| 135 | 131 | // :53:17: error: use of undefined value here causes illegal behavior |
| 136 | // :53:17: note: when computing vector element at index '1' | |
| 137 | 132 | // :53:17: error: use of undefined value here causes illegal behavior |
| 138 | // :53:17: note: when computing vector element at index '1' | |
| 139 | 133 | // :53:17: error: use of undefined value here causes illegal behavior |
| 140 | // :53:17: note: when computing vector element at index '0' | |
| 141 | 134 | // :53:17: error: use of undefined value here causes illegal behavior |
| 142 | // :53:17: note: when computing vector element at index '0' | |
| 143 | 135 | // :53:17: error: use of undefined value here causes illegal behavior |
| 144 | // :53:17: note: when computing vector element at index '0' | |
| 145 | 136 | // :53:17: error: use of undefined value here causes illegal behavior |
| 146 | // :53:17: note: when computing vector element at index '0' | |
| 147 | 137 | // :53:17: error: use of undefined value here causes illegal behavior |
| 138 | // :53:17: note: when computing vector element at index '0' | |
| 148 | 139 | // :53:17: error: use of undefined value here causes illegal behavior |
| 140 | // :53:17: note: when computing vector element at index '0' | |
| 149 | 141 | // :53:17: error: use of undefined value here causes illegal behavior |
| 150 | 142 | // :53:17: note: when computing vector element at index '0' |
| 151 | 143 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -155,9 +147,9 @@ const std = @import("std"); |
| 155 | 147 | // :53:17: error: use of undefined value here causes illegal behavior |
| 156 | 148 | // :53:17: note: when computing vector element at index '0' |
| 157 | 149 | // :53:17: error: use of undefined value here causes illegal behavior |
| 158 | // :53:17: note: when computing vector element at index '1' | |
| 150 | // :53:17: note: when computing vector element at index '0' | |
| 159 | 151 | // :53:17: error: use of undefined value here causes illegal behavior |
| 160 | // :53:17: note: when computing vector element at index '1' | |
| 152 | // :53:17: note: when computing vector element at index '0' | |
| 161 | 153 | // :53:17: error: use of undefined value here causes illegal behavior |
| 162 | 154 | // :53:17: note: when computing vector element at index '0' |
| 163 | 155 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -167,7 +159,9 @@ const std = @import("std"); |
| 167 | 159 | // :53:17: error: use of undefined value here causes illegal behavior |
| 168 | 160 | // :53:17: note: when computing vector element at index '0' |
| 169 | 161 | // :53:17: error: use of undefined value here causes illegal behavior |
| 162 | // :53:17: note: when computing vector element at index '0' | |
| 170 | 163 | // :53:17: error: use of undefined value here causes illegal behavior |
| 164 | // :53:17: note: when computing vector element at index '0' | |
| 171 | 165 | // :53:17: error: use of undefined value here causes illegal behavior |
| 172 | 166 | // :53:17: note: when computing vector element at index '0' |
| 173 | 167 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -177,9 +171,9 @@ const std = @import("std"); |
| 177 | 171 | // :53:17: error: use of undefined value here causes illegal behavior |
| 178 | 172 | // :53:17: note: when computing vector element at index '0' |
| 179 | 173 | // :53:17: error: use of undefined value here causes illegal behavior |
| 180 | // :53:17: note: when computing vector element at index '1' | |
| 174 | // :53:17: note: when computing vector element at index '0' | |
| 181 | 175 | // :53:17: error: use of undefined value here causes illegal behavior |
| 182 | // :53:17: note: when computing vector element at index '1' | |
| 176 | // :53:17: note: when computing vector element at index '0' | |
| 183 | 177 | // :53:17: error: use of undefined value here causes illegal behavior |
| 184 | 178 | // :53:17: note: when computing vector element at index '0' |
| 185 | 179 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -189,7 +183,9 @@ const std = @import("std"); |
| 189 | 183 | // :53:17: error: use of undefined value here causes illegal behavior |
| 190 | 184 | // :53:17: note: when computing vector element at index '0' |
| 191 | 185 | // :53:17: error: use of undefined value here causes illegal behavior |
| 186 | // :53:17: note: when computing vector element at index '0' | |
| 192 | 187 | // :53:17: error: use of undefined value here causes illegal behavior |
| 188 | // :53:17: note: when computing vector element at index '0' | |
| 193 | 189 | // :53:17: error: use of undefined value here causes illegal behavior |
| 194 | 190 | // :53:17: note: when computing vector element at index '0' |
| 195 | 191 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -199,9 +195,9 @@ const std = @import("std"); |
| 199 | 195 | // :53:17: error: use of undefined value here causes illegal behavior |
| 200 | 196 | // :53:17: note: when computing vector element at index '0' |
| 201 | 197 | // :53:17: error: use of undefined value here causes illegal behavior |
| 202 | // :53:17: note: when computing vector element at index '1' | |
| 198 | // :53:17: note: when computing vector element at index '0' | |
| 203 | 199 | // :53:17: error: use of undefined value here causes illegal behavior |
| 204 | // :53:17: note: when computing vector element at index '1' | |
| 200 | // :53:17: note: when computing vector element at index '0' | |
| 205 | 201 | // :53:17: error: use of undefined value here causes illegal behavior |
| 206 | 202 | // :53:17: note: when computing vector element at index '0' |
| 207 | 203 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -211,7 +207,9 @@ const std = @import("std"); |
| 211 | 207 | // :53:17: error: use of undefined value here causes illegal behavior |
| 212 | 208 | // :53:17: note: when computing vector element at index '0' |
| 213 | 209 | // :53:17: error: use of undefined value here causes illegal behavior |
| 210 | // :53:17: note: when computing vector element at index '0' | |
| 214 | 211 | // :53:17: error: use of undefined value here causes illegal behavior |
| 212 | // :53:17: note: when computing vector element at index '0' | |
| 215 | 213 | // :53:17: error: use of undefined value here causes illegal behavior |
| 216 | 214 | // :53:17: note: when computing vector element at index '0' |
| 217 | 215 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -221,9 +219,9 @@ const std = @import("std"); |
| 221 | 219 | // :53:17: error: use of undefined value here causes illegal behavior |
| 222 | 220 | // :53:17: note: when computing vector element at index '0' |
| 223 | 221 | // :53:17: error: use of undefined value here causes illegal behavior |
| 224 | // :53:17: note: when computing vector element at index '1' | |
| 222 | // :53:17: note: when computing vector element at index '0' | |
| 225 | 223 | // :53:17: error: use of undefined value here causes illegal behavior |
| 226 | // :53:17: note: when computing vector element at index '1' | |
| 224 | // :53:17: note: when computing vector element at index '0' | |
| 227 | 225 | // :53:17: error: use of undefined value here causes illegal behavior |
| 228 | 226 | // :53:17: note: when computing vector element at index '0' |
| 229 | 227 | // :53:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -233,27 +231,29 @@ const std = @import("std"); |
| 233 | 231 | // :53:17: error: use of undefined value here causes illegal behavior |
| 234 | 232 | // :53:17: note: when computing vector element at index '0' |
| 235 | 233 | // :53:17: error: use of undefined value here causes illegal behavior |
| 234 | // :53:17: note: when computing vector element at index '1' | |
| 236 | 235 | // :53:17: error: use of undefined value here causes illegal behavior |
| 236 | // :53:17: note: when computing vector element at index '1' | |
| 237 | 237 | // :53:17: error: use of undefined value here causes illegal behavior |
| 238 | // :53:17: note: when computing vector element at index '0' | |
| 238 | // :53:17: note: when computing vector element at index '1' | |
| 239 | 239 | // :53:17: error: use of undefined value here causes illegal behavior |
| 240 | // :53:17: note: when computing vector element at index '0' | |
| 240 | // :53:17: note: when computing vector element at index '1' | |
| 241 | 241 | // :53:17: error: use of undefined value here causes illegal behavior |
| 242 | // :53:17: note: when computing vector element at index '0' | |
| 242 | // :53:17: note: when computing vector element at index '1' | |
| 243 | 243 | // :53:17: error: use of undefined value here causes illegal behavior |
| 244 | // :53:17: note: when computing vector element at index '0' | |
| 244 | // :53:17: note: when computing vector element at index '1' | |
| 245 | 245 | // :53:17: error: use of undefined value here causes illegal behavior |
| 246 | 246 | // :53:17: note: when computing vector element at index '1' |
| 247 | 247 | // :53:17: error: use of undefined value here causes illegal behavior |
| 248 | 248 | // :53:17: note: when computing vector element at index '1' |
| 249 | 249 | // :53:17: error: use of undefined value here causes illegal behavior |
| 250 | // :53:17: note: when computing vector element at index '0' | |
| 250 | // :53:17: note: when computing vector element at index '1' | |
| 251 | 251 | // :53:17: error: use of undefined value here causes illegal behavior |
| 252 | // :53:17: note: when computing vector element at index '0' | |
| 252 | // :53:17: note: when computing vector element at index '1' | |
| 253 | 253 | // :53:17: error: use of undefined value here causes illegal behavior |
| 254 | // :53:17: note: when computing vector element at index '0' | |
| 254 | // :53:17: note: when computing vector element at index '1' | |
| 255 | 255 | // :53:17: error: use of undefined value here causes illegal behavior |
| 256 | // :53:17: note: when computing vector element at index '0' | |
| 256 | // :53:17: note: when computing vector element at index '1' | |
| 257 | 257 | // :53:22: error: use of undefined value here causes illegal behavior |
| 258 | 258 | // :53:22: note: when computing vector element at index '0' |
| 259 | 259 | // :53:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -281,27 +281,19 @@ const std = @import("std"); |
| 281 | 281 | // :56:27: error: use of undefined value here causes illegal behavior |
| 282 | 282 | // :56:27: error: use of undefined value here causes illegal behavior |
| 283 | 283 | // :56:27: error: use of undefined value here causes illegal behavior |
| 284 | // :56:27: note: when computing vector element at index '0' | |
| 285 | 284 | // :56:27: error: use of undefined value here causes illegal behavior |
| 286 | // :56:27: note: when computing vector element at index '0' | |
| 287 | 285 | // :56:27: error: use of undefined value here causes illegal behavior |
| 288 | // :56:27: note: when computing vector element at index '0' | |
| 289 | 286 | // :56:27: error: use of undefined value here causes illegal behavior |
| 290 | // :56:27: note: when computing vector element at index '0' | |
| 291 | 287 | // :56:27: error: use of undefined value here causes illegal behavior |
| 292 | // :56:27: note: when computing vector element at index '1' | |
| 293 | 288 | // :56:27: error: use of undefined value here causes illegal behavior |
| 294 | // :56:27: note: when computing vector element at index '1' | |
| 295 | 289 | // :56:27: error: use of undefined value here causes illegal behavior |
| 296 | // :56:27: note: when computing vector element at index '0' | |
| 297 | 290 | // :56:27: error: use of undefined value here causes illegal behavior |
| 298 | // :56:27: note: when computing vector element at index '0' | |
| 299 | 291 | // :56:27: error: use of undefined value here causes illegal behavior |
| 300 | // :56:27: note: when computing vector element at index '0' | |
| 301 | 292 | // :56:27: error: use of undefined value here causes illegal behavior |
| 302 | // :56:27: note: when computing vector element at index '0' | |
| 303 | 293 | // :56:27: error: use of undefined value here causes illegal behavior |
| 294 | // :56:27: note: when computing vector element at index '0' | |
| 304 | 295 | // :56:27: error: use of undefined value here causes illegal behavior |
| 296 | // :56:27: note: when computing vector element at index '0' | |
| 305 | 297 | // :56:27: error: use of undefined value here causes illegal behavior |
| 306 | 298 | // :56:27: note: when computing vector element at index '0' |
| 307 | 299 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -311,9 +303,9 @@ const std = @import("std"); |
| 311 | 303 | // :56:27: error: use of undefined value here causes illegal behavior |
| 312 | 304 | // :56:27: note: when computing vector element at index '0' |
| 313 | 305 | // :56:27: error: use of undefined value here causes illegal behavior |
| 314 | // :56:27: note: when computing vector element at index '1' | |
| 306 | // :56:27: note: when computing vector element at index '0' | |
| 315 | 307 | // :56:27: error: use of undefined value here causes illegal behavior |
| 316 | // :56:27: note: when computing vector element at index '1' | |
| 308 | // :56:27: note: when computing vector element at index '0' | |
| 317 | 309 | // :56:27: error: use of undefined value here causes illegal behavior |
| 318 | 310 | // :56:27: note: when computing vector element at index '0' |
| 319 | 311 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -323,7 +315,9 @@ const std = @import("std"); |
| 323 | 315 | // :56:27: error: use of undefined value here causes illegal behavior |
| 324 | 316 | // :56:27: note: when computing vector element at index '0' |
| 325 | 317 | // :56:27: error: use of undefined value here causes illegal behavior |
| 318 | // :56:27: note: when computing vector element at index '0' | |
| 326 | 319 | // :56:27: error: use of undefined value here causes illegal behavior |
| 320 | // :56:27: note: when computing vector element at index '0' | |
| 327 | 321 | // :56:27: error: use of undefined value here causes illegal behavior |
| 328 | 322 | // :56:27: note: when computing vector element at index '0' |
| 329 | 323 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -333,9 +327,9 @@ const std = @import("std"); |
| 333 | 327 | // :56:27: error: use of undefined value here causes illegal behavior |
| 334 | 328 | // :56:27: note: when computing vector element at index '0' |
| 335 | 329 | // :56:27: error: use of undefined value here causes illegal behavior |
| 336 | // :56:27: note: when computing vector element at index '1' | |
| 330 | // :56:27: note: when computing vector element at index '0' | |
| 337 | 331 | // :56:27: error: use of undefined value here causes illegal behavior |
| 338 | // :56:27: note: when computing vector element at index '1' | |
| 332 | // :56:27: note: when computing vector element at index '0' | |
| 339 | 333 | // :56:27: error: use of undefined value here causes illegal behavior |
| 340 | 334 | // :56:27: note: when computing vector element at index '0' |
| 341 | 335 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -345,7 +339,9 @@ const std = @import("std"); |
| 345 | 339 | // :56:27: error: use of undefined value here causes illegal behavior |
| 346 | 340 | // :56:27: note: when computing vector element at index '0' |
| 347 | 341 | // :56:27: error: use of undefined value here causes illegal behavior |
| 342 | // :56:27: note: when computing vector element at index '0' | |
| 348 | 343 | // :56:27: error: use of undefined value here causes illegal behavior |
| 344 | // :56:27: note: when computing vector element at index '0' | |
| 349 | 345 | // :56:27: error: use of undefined value here causes illegal behavior |
| 350 | 346 | // :56:27: note: when computing vector element at index '0' |
| 351 | 347 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -355,9 +351,9 @@ const std = @import("std"); |
| 355 | 351 | // :56:27: error: use of undefined value here causes illegal behavior |
| 356 | 352 | // :56:27: note: when computing vector element at index '0' |
| 357 | 353 | // :56:27: error: use of undefined value here causes illegal behavior |
| 358 | // :56:27: note: when computing vector element at index '1' | |
| 354 | // :56:27: note: when computing vector element at index '0' | |
| 359 | 355 | // :56:27: error: use of undefined value here causes illegal behavior |
| 360 | // :56:27: note: when computing vector element at index '1' | |
| 356 | // :56:27: note: when computing vector element at index '0' | |
| 361 | 357 | // :56:27: error: use of undefined value here causes illegal behavior |
| 362 | 358 | // :56:27: note: when computing vector element at index '0' |
| 363 | 359 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -367,7 +363,9 @@ const std = @import("std"); |
| 367 | 363 | // :56:27: error: use of undefined value here causes illegal behavior |
| 368 | 364 | // :56:27: note: when computing vector element at index '0' |
| 369 | 365 | // :56:27: error: use of undefined value here causes illegal behavior |
| 366 | // :56:27: note: when computing vector element at index '0' | |
| 370 | 367 | // :56:27: error: use of undefined value here causes illegal behavior |
| 368 | // :56:27: note: when computing vector element at index '0' | |
| 371 | 369 | // :56:27: error: use of undefined value here causes illegal behavior |
| 372 | 370 | // :56:27: note: when computing vector element at index '0' |
| 373 | 371 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -377,9 +375,9 @@ const std = @import("std"); |
| 377 | 375 | // :56:27: error: use of undefined value here causes illegal behavior |
| 378 | 376 | // :56:27: note: when computing vector element at index '0' |
| 379 | 377 | // :56:27: error: use of undefined value here causes illegal behavior |
| 380 | // :56:27: note: when computing vector element at index '1' | |
| 378 | // :56:27: note: when computing vector element at index '0' | |
| 381 | 379 | // :56:27: error: use of undefined value here causes illegal behavior |
| 382 | // :56:27: note: when computing vector element at index '1' | |
| 380 | // :56:27: note: when computing vector element at index '0' | |
| 383 | 381 | // :56:27: error: use of undefined value here causes illegal behavior |
| 384 | 382 | // :56:27: note: when computing vector element at index '0' |
| 385 | 383 | // :56:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -389,27 +387,29 @@ const std = @import("std"); |
| 389 | 387 | // :56:27: error: use of undefined value here causes illegal behavior |
| 390 | 388 | // :56:27: note: when computing vector element at index '0' |
| 391 | 389 | // :56:27: error: use of undefined value here causes illegal behavior |
| 390 | // :56:27: note: when computing vector element at index '1' | |
| 392 | 391 | // :56:27: error: use of undefined value here causes illegal behavior |
| 392 | // :56:27: note: when computing vector element at index '1' | |
| 393 | 393 | // :56:27: error: use of undefined value here causes illegal behavior |
| 394 | // :56:27: note: when computing vector element at index '0' | |
| 394 | // :56:27: note: when computing vector element at index '1' | |
| 395 | 395 | // :56:27: error: use of undefined value here causes illegal behavior |
| 396 | // :56:27: note: when computing vector element at index '0' | |
| 396 | // :56:27: note: when computing vector element at index '1' | |
| 397 | 397 | // :56:27: error: use of undefined value here causes illegal behavior |
| 398 | // :56:27: note: when computing vector element at index '0' | |
| 398 | // :56:27: note: when computing vector element at index '1' | |
| 399 | 399 | // :56:27: error: use of undefined value here causes illegal behavior |
| 400 | // :56:27: note: when computing vector element at index '0' | |
| 400 | // :56:27: note: when computing vector element at index '1' | |
| 401 | 401 | // :56:27: error: use of undefined value here causes illegal behavior |
| 402 | 402 | // :56:27: note: when computing vector element at index '1' |
| 403 | 403 | // :56:27: error: use of undefined value here causes illegal behavior |
| 404 | 404 | // :56:27: note: when computing vector element at index '1' |
| 405 | 405 | // :56:27: error: use of undefined value here causes illegal behavior |
| 406 | // :56:27: note: when computing vector element at index '0' | |
| 406 | // :56:27: note: when computing vector element at index '1' | |
| 407 | 407 | // :56:27: error: use of undefined value here causes illegal behavior |
| 408 | // :56:27: note: when computing vector element at index '0' | |
| 408 | // :56:27: note: when computing vector element at index '1' | |
| 409 | 409 | // :56:27: error: use of undefined value here causes illegal behavior |
| 410 | // :56:27: note: when computing vector element at index '0' | |
| 410 | // :56:27: note: when computing vector element at index '1' | |
| 411 | 411 | // :56:27: error: use of undefined value here causes illegal behavior |
| 412 | // :56:27: note: when computing vector element at index '0' | |
| 412 | // :56:27: note: when computing vector element at index '1' | |
| 413 | 413 | // :56:30: error: use of undefined value here causes illegal behavior |
| 414 | 414 | // :56:30: note: when computing vector element at index '0' |
| 415 | 415 | // :56:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -437,27 +437,19 @@ const std = @import("std"); |
| 437 | 437 | // :59:34: error: use of undefined value here causes illegal behavior |
| 438 | 438 | // :59:34: error: use of undefined value here causes illegal behavior |
| 439 | 439 | // :59:34: error: use of undefined value here causes illegal behavior |
| 440 | // :59:34: note: when computing vector element at index '0' | |
| 441 | 440 | // :59:34: error: use of undefined value here causes illegal behavior |
| 442 | // :59:34: note: when computing vector element at index '0' | |
| 443 | 441 | // :59:34: error: use of undefined value here causes illegal behavior |
| 444 | // :59:34: note: when computing vector element at index '0' | |
| 445 | 442 | // :59:34: error: use of undefined value here causes illegal behavior |
| 446 | // :59:34: note: when computing vector element at index '0' | |
| 447 | 443 | // :59:34: error: use of undefined value here causes illegal behavior |
| 448 | // :59:34: note: when computing vector element at index '1' | |
| 449 | 444 | // :59:34: error: use of undefined value here causes illegal behavior |
| 450 | // :59:34: note: when computing vector element at index '1' | |
| 451 | 445 | // :59:34: error: use of undefined value here causes illegal behavior |
| 452 | // :59:34: note: when computing vector element at index '0' | |
| 453 | 446 | // :59:34: error: use of undefined value here causes illegal behavior |
| 454 | // :59:34: note: when computing vector element at index '0' | |
| 455 | 447 | // :59:34: error: use of undefined value here causes illegal behavior |
| 456 | // :59:34: note: when computing vector element at index '0' | |
| 457 | 448 | // :59:34: error: use of undefined value here causes illegal behavior |
| 458 | // :59:34: note: when computing vector element at index '0' | |
| 459 | 449 | // :59:34: error: use of undefined value here causes illegal behavior |
| 450 | // :59:34: note: when computing vector element at index '0' | |
| 460 | 451 | // :59:34: error: use of undefined value here causes illegal behavior |
| 452 | // :59:34: note: when computing vector element at index '0' | |
| 461 | 453 | // :59:34: error: use of undefined value here causes illegal behavior |
| 462 | 454 | // :59:34: note: when computing vector element at index '0' |
| 463 | 455 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -467,9 +459,9 @@ const std = @import("std"); |
| 467 | 459 | // :59:34: error: use of undefined value here causes illegal behavior |
| 468 | 460 | // :59:34: note: when computing vector element at index '0' |
| 469 | 461 | // :59:34: error: use of undefined value here causes illegal behavior |
| 470 | // :59:34: note: when computing vector element at index '1' | |
| 462 | // :59:34: note: when computing vector element at index '0' | |
| 471 | 463 | // :59:34: error: use of undefined value here causes illegal behavior |
| 472 | // :59:34: note: when computing vector element at index '1' | |
| 464 | // :59:34: note: when computing vector element at index '0' | |
| 473 | 465 | // :59:34: error: use of undefined value here causes illegal behavior |
| 474 | 466 | // :59:34: note: when computing vector element at index '0' |
| 475 | 467 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -479,7 +471,9 @@ const std = @import("std"); |
| 479 | 471 | // :59:34: error: use of undefined value here causes illegal behavior |
| 480 | 472 | // :59:34: note: when computing vector element at index '0' |
| 481 | 473 | // :59:34: error: use of undefined value here causes illegal behavior |
| 474 | // :59:34: note: when computing vector element at index '0' | |
| 482 | 475 | // :59:34: error: use of undefined value here causes illegal behavior |
| 476 | // :59:34: note: when computing vector element at index '0' | |
| 483 | 477 | // :59:34: error: use of undefined value here causes illegal behavior |
| 484 | 478 | // :59:34: note: when computing vector element at index '0' |
| 485 | 479 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -489,9 +483,9 @@ const std = @import("std"); |
| 489 | 483 | // :59:34: error: use of undefined value here causes illegal behavior |
| 490 | 484 | // :59:34: note: when computing vector element at index '0' |
| 491 | 485 | // :59:34: error: use of undefined value here causes illegal behavior |
| 492 | // :59:34: note: when computing vector element at index '1' | |
| 486 | // :59:34: note: when computing vector element at index '0' | |
| 493 | 487 | // :59:34: error: use of undefined value here causes illegal behavior |
| 494 | // :59:34: note: when computing vector element at index '1' | |
| 488 | // :59:34: note: when computing vector element at index '0' | |
| 495 | 489 | // :59:34: error: use of undefined value here causes illegal behavior |
| 496 | 490 | // :59:34: note: when computing vector element at index '0' |
| 497 | 491 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -501,7 +495,9 @@ const std = @import("std"); |
| 501 | 495 | // :59:34: error: use of undefined value here causes illegal behavior |
| 502 | 496 | // :59:34: note: when computing vector element at index '0' |
| 503 | 497 | // :59:34: error: use of undefined value here causes illegal behavior |
| 498 | // :59:34: note: when computing vector element at index '0' | |
| 504 | 499 | // :59:34: error: use of undefined value here causes illegal behavior |
| 500 | // :59:34: note: when computing vector element at index '0' | |
| 505 | 501 | // :59:34: error: use of undefined value here causes illegal behavior |
| 506 | 502 | // :59:34: note: when computing vector element at index '0' |
| 507 | 503 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -511,9 +507,9 @@ const std = @import("std"); |
| 511 | 507 | // :59:34: error: use of undefined value here causes illegal behavior |
| 512 | 508 | // :59:34: note: when computing vector element at index '0' |
| 513 | 509 | // :59:34: error: use of undefined value here causes illegal behavior |
| 514 | // :59:34: note: when computing vector element at index '1' | |
| 510 | // :59:34: note: when computing vector element at index '0' | |
| 515 | 511 | // :59:34: error: use of undefined value here causes illegal behavior |
| 516 | // :59:34: note: when computing vector element at index '1' | |
| 512 | // :59:34: note: when computing vector element at index '0' | |
| 517 | 513 | // :59:34: error: use of undefined value here causes illegal behavior |
| 518 | 514 | // :59:34: note: when computing vector element at index '0' |
| 519 | 515 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -523,7 +519,9 @@ const std = @import("std"); |
| 523 | 519 | // :59:34: error: use of undefined value here causes illegal behavior |
| 524 | 520 | // :59:34: note: when computing vector element at index '0' |
| 525 | 521 | // :59:34: error: use of undefined value here causes illegal behavior |
| 522 | // :59:34: note: when computing vector element at index '0' | |
| 526 | 523 | // :59:34: error: use of undefined value here causes illegal behavior |
| 524 | // :59:34: note: when computing vector element at index '0' | |
| 527 | 525 | // :59:34: error: use of undefined value here causes illegal behavior |
| 528 | 526 | // :59:34: note: when computing vector element at index '0' |
| 529 | 527 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -533,9 +531,9 @@ const std = @import("std"); |
| 533 | 531 | // :59:34: error: use of undefined value here causes illegal behavior |
| 534 | 532 | // :59:34: note: when computing vector element at index '0' |
| 535 | 533 | // :59:34: error: use of undefined value here causes illegal behavior |
| 536 | // :59:34: note: when computing vector element at index '1' | |
| 534 | // :59:34: note: when computing vector element at index '0' | |
| 537 | 535 | // :59:34: error: use of undefined value here causes illegal behavior |
| 538 | // :59:34: note: when computing vector element at index '1' | |
| 536 | // :59:34: note: when computing vector element at index '0' | |
| 539 | 537 | // :59:34: error: use of undefined value here causes illegal behavior |
| 540 | 538 | // :59:34: note: when computing vector element at index '0' |
| 541 | 539 | // :59:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -545,27 +543,29 @@ const std = @import("std"); |
| 545 | 543 | // :59:34: error: use of undefined value here causes illegal behavior |
| 546 | 544 | // :59:34: note: when computing vector element at index '0' |
| 547 | 545 | // :59:34: error: use of undefined value here causes illegal behavior |
| 546 | // :59:34: note: when computing vector element at index '1' | |
| 548 | 547 | // :59:34: error: use of undefined value here causes illegal behavior |
| 548 | // :59:34: note: when computing vector element at index '1' | |
| 549 | 549 | // :59:34: error: use of undefined value here causes illegal behavior |
| 550 | // :59:34: note: when computing vector element at index '0' | |
| 550 | // :59:34: note: when computing vector element at index '1' | |
| 551 | 551 | // :59:34: error: use of undefined value here causes illegal behavior |
| 552 | // :59:34: note: when computing vector element at index '0' | |
| 552 | // :59:34: note: when computing vector element at index '1' | |
| 553 | 553 | // :59:34: error: use of undefined value here causes illegal behavior |
| 554 | // :59:34: note: when computing vector element at index '0' | |
| 554 | // :59:34: note: when computing vector element at index '1' | |
| 555 | 555 | // :59:34: error: use of undefined value here causes illegal behavior |
| 556 | // :59:34: note: when computing vector element at index '0' | |
| 556 | // :59:34: note: when computing vector element at index '1' | |
| 557 | 557 | // :59:34: error: use of undefined value here causes illegal behavior |
| 558 | 558 | // :59:34: note: when computing vector element at index '1' |
| 559 | 559 | // :59:34: error: use of undefined value here causes illegal behavior |
| 560 | 560 | // :59:34: note: when computing vector element at index '1' |
| 561 | 561 | // :59:34: error: use of undefined value here causes illegal behavior |
| 562 | // :59:34: note: when computing vector element at index '0' | |
| 562 | // :59:34: note: when computing vector element at index '1' | |
| 563 | 563 | // :59:34: error: use of undefined value here causes illegal behavior |
| 564 | // :59:34: note: when computing vector element at index '0' | |
| 564 | // :59:34: note: when computing vector element at index '1' | |
| 565 | 565 | // :59:34: error: use of undefined value here causes illegal behavior |
| 566 | // :59:34: note: when computing vector element at index '0' | |
| 566 | // :59:34: note: when computing vector element at index '1' | |
| 567 | 567 | // :59:34: error: use of undefined value here causes illegal behavior |
| 568 | // :59:34: note: when computing vector element at index '0' | |
| 568 | // :59:34: note: when computing vector element at index '1' | |
| 569 | 569 | // :59:37: error: use of undefined value here causes illegal behavior |
| 570 | 570 | // :59:37: note: when computing vector element at index '0' |
| 571 | 571 | // :59:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -593,27 +593,19 @@ const std = @import("std"); |
| 593 | 593 | // :62:17: error: use of undefined value here causes illegal behavior |
| 594 | 594 | // :62:17: error: use of undefined value here causes illegal behavior |
| 595 | 595 | // :62:17: error: use of undefined value here causes illegal behavior |
| 596 | // :62:17: note: when computing vector element at index '0' | |
| 597 | 596 | // :62:17: error: use of undefined value here causes illegal behavior |
| 598 | // :62:17: note: when computing vector element at index '0' | |
| 599 | 597 | // :62:17: error: use of undefined value here causes illegal behavior |
| 600 | // :62:17: note: when computing vector element at index '0' | |
| 601 | 598 | // :62:17: error: use of undefined value here causes illegal behavior |
| 602 | // :62:17: note: when computing vector element at index '0' | |
| 603 | 599 | // :62:17: error: use of undefined value here causes illegal behavior |
| 604 | // :62:17: note: when computing vector element at index '1' | |
| 605 | 600 | // :62:17: error: use of undefined value here causes illegal behavior |
| 606 | // :62:17: note: when computing vector element at index '1' | |
| 607 | 601 | // :62:17: error: use of undefined value here causes illegal behavior |
| 608 | // :62:17: note: when computing vector element at index '0' | |
| 609 | 602 | // :62:17: error: use of undefined value here causes illegal behavior |
| 610 | // :62:17: note: when computing vector element at index '0' | |
| 611 | 603 | // :62:17: error: use of undefined value here causes illegal behavior |
| 612 | // :62:17: note: when computing vector element at index '0' | |
| 613 | 604 | // :62:17: error: use of undefined value here causes illegal behavior |
| 614 | // :62:17: note: when computing vector element at index '0' | |
| 615 | 605 | // :62:17: error: use of undefined value here causes illegal behavior |
| 606 | // :62:17: note: when computing vector element at index '0' | |
| 616 | 607 | // :62:17: error: use of undefined value here causes illegal behavior |
| 608 | // :62:17: note: when computing vector element at index '0' | |
| 617 | 609 | // :62:17: error: use of undefined value here causes illegal behavior |
| 618 | 610 | // :62:17: note: when computing vector element at index '0' |
| 619 | 611 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -623,9 +615,9 @@ const std = @import("std"); |
| 623 | 615 | // :62:17: error: use of undefined value here causes illegal behavior |
| 624 | 616 | // :62:17: note: when computing vector element at index '0' |
| 625 | 617 | // :62:17: error: use of undefined value here causes illegal behavior |
| 626 | // :62:17: note: when computing vector element at index '1' | |
| 618 | // :62:17: note: when computing vector element at index '0' | |
| 627 | 619 | // :62:17: error: use of undefined value here causes illegal behavior |
| 628 | // :62:17: note: when computing vector element at index '1' | |
| 620 | // :62:17: note: when computing vector element at index '0' | |
| 629 | 621 | // :62:17: error: use of undefined value here causes illegal behavior |
| 630 | 622 | // :62:17: note: when computing vector element at index '0' |
| 631 | 623 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -635,7 +627,9 @@ const std = @import("std"); |
| 635 | 627 | // :62:17: error: use of undefined value here causes illegal behavior |
| 636 | 628 | // :62:17: note: when computing vector element at index '0' |
| 637 | 629 | // :62:17: error: use of undefined value here causes illegal behavior |
| 630 | // :62:17: note: when computing vector element at index '0' | |
| 638 | 631 | // :62:17: error: use of undefined value here causes illegal behavior |
| 632 | // :62:17: note: when computing vector element at index '0' | |
| 639 | 633 | // :62:17: error: use of undefined value here causes illegal behavior |
| 640 | 634 | // :62:17: note: when computing vector element at index '0' |
| 641 | 635 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -645,9 +639,9 @@ const std = @import("std"); |
| 645 | 639 | // :62:17: error: use of undefined value here causes illegal behavior |
| 646 | 640 | // :62:17: note: when computing vector element at index '0' |
| 647 | 641 | // :62:17: error: use of undefined value here causes illegal behavior |
| 648 | // :62:17: note: when computing vector element at index '1' | |
| 642 | // :62:17: note: when computing vector element at index '0' | |
| 649 | 643 | // :62:17: error: use of undefined value here causes illegal behavior |
| 650 | // :62:17: note: when computing vector element at index '1' | |
| 644 | // :62:17: note: when computing vector element at index '0' | |
| 651 | 645 | // :62:17: error: use of undefined value here causes illegal behavior |
| 652 | 646 | // :62:17: note: when computing vector element at index '0' |
| 653 | 647 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -657,7 +651,9 @@ const std = @import("std"); |
| 657 | 651 | // :62:17: error: use of undefined value here causes illegal behavior |
| 658 | 652 | // :62:17: note: when computing vector element at index '0' |
| 659 | 653 | // :62:17: error: use of undefined value here causes illegal behavior |
| 654 | // :62:17: note: when computing vector element at index '0' | |
| 660 | 655 | // :62:17: error: use of undefined value here causes illegal behavior |
| 656 | // :62:17: note: when computing vector element at index '0' | |
| 661 | 657 | // :62:17: error: use of undefined value here causes illegal behavior |
| 662 | 658 | // :62:17: note: when computing vector element at index '0' |
| 663 | 659 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -667,9 +663,9 @@ const std = @import("std"); |
| 667 | 663 | // :62:17: error: use of undefined value here causes illegal behavior |
| 668 | 664 | // :62:17: note: when computing vector element at index '0' |
| 669 | 665 | // :62:17: error: use of undefined value here causes illegal behavior |
| 670 | // :62:17: note: when computing vector element at index '1' | |
| 666 | // :62:17: note: when computing vector element at index '0' | |
| 671 | 667 | // :62:17: error: use of undefined value here causes illegal behavior |
| 672 | // :62:17: note: when computing vector element at index '1' | |
| 668 | // :62:17: note: when computing vector element at index '0' | |
| 673 | 669 | // :62:17: error: use of undefined value here causes illegal behavior |
| 674 | 670 | // :62:17: note: when computing vector element at index '0' |
| 675 | 671 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -679,7 +675,9 @@ const std = @import("std"); |
| 679 | 675 | // :62:17: error: use of undefined value here causes illegal behavior |
| 680 | 676 | // :62:17: note: when computing vector element at index '0' |
| 681 | 677 | // :62:17: error: use of undefined value here causes illegal behavior |
| 678 | // :62:17: note: when computing vector element at index '0' | |
| 682 | 679 | // :62:17: error: use of undefined value here causes illegal behavior |
| 680 | // :62:17: note: when computing vector element at index '0' | |
| 683 | 681 | // :62:17: error: use of undefined value here causes illegal behavior |
| 684 | 682 | // :62:17: note: when computing vector element at index '0' |
| 685 | 683 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -689,9 +687,9 @@ const std = @import("std"); |
| 689 | 687 | // :62:17: error: use of undefined value here causes illegal behavior |
| 690 | 688 | // :62:17: note: when computing vector element at index '0' |
| 691 | 689 | // :62:17: error: use of undefined value here causes illegal behavior |
| 692 | // :62:17: note: when computing vector element at index '1' | |
| 690 | // :62:17: note: when computing vector element at index '0' | |
| 693 | 691 | // :62:17: error: use of undefined value here causes illegal behavior |
| 694 | // :62:17: note: when computing vector element at index '1' | |
| 692 | // :62:17: note: when computing vector element at index '0' | |
| 695 | 693 | // :62:17: error: use of undefined value here causes illegal behavior |
| 696 | 694 | // :62:17: note: when computing vector element at index '0' |
| 697 | 695 | // :62:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -701,27 +699,29 @@ const std = @import("std"); |
| 701 | 699 | // :62:17: error: use of undefined value here causes illegal behavior |
| 702 | 700 | // :62:17: note: when computing vector element at index '0' |
| 703 | 701 | // :62:17: error: use of undefined value here causes illegal behavior |
| 702 | // :62:17: note: when computing vector element at index '1' | |
| 704 | 703 | // :62:17: error: use of undefined value here causes illegal behavior |
| 704 | // :62:17: note: when computing vector element at index '1' | |
| 705 | 705 | // :62:17: error: use of undefined value here causes illegal behavior |
| 706 | // :62:17: note: when computing vector element at index '0' | |
| 706 | // :62:17: note: when computing vector element at index '1' | |
| 707 | 707 | // :62:17: error: use of undefined value here causes illegal behavior |
| 708 | // :62:17: note: when computing vector element at index '0' | |
| 708 | // :62:17: note: when computing vector element at index '1' | |
| 709 | 709 | // :62:17: error: use of undefined value here causes illegal behavior |
| 710 | // :62:17: note: when computing vector element at index '0' | |
| 710 | // :62:17: note: when computing vector element at index '1' | |
| 711 | 711 | // :62:17: error: use of undefined value here causes illegal behavior |
| 712 | // :62:17: note: when computing vector element at index '0' | |
| 712 | // :62:17: note: when computing vector element at index '1' | |
| 713 | 713 | // :62:17: error: use of undefined value here causes illegal behavior |
| 714 | 714 | // :62:17: note: when computing vector element at index '1' |
| 715 | 715 | // :62:17: error: use of undefined value here causes illegal behavior |
| 716 | 716 | // :62:17: note: when computing vector element at index '1' |
| 717 | 717 | // :62:17: error: use of undefined value here causes illegal behavior |
| 718 | // :62:17: note: when computing vector element at index '0' | |
| 718 | // :62:17: note: when computing vector element at index '1' | |
| 719 | 719 | // :62:17: error: use of undefined value here causes illegal behavior |
| 720 | // :62:17: note: when computing vector element at index '0' | |
| 720 | // :62:17: note: when computing vector element at index '1' | |
| 721 | 721 | // :62:17: error: use of undefined value here causes illegal behavior |
| 722 | // :62:17: note: when computing vector element at index '0' | |
| 722 | // :62:17: note: when computing vector element at index '1' | |
| 723 | 723 | // :62:17: error: use of undefined value here causes illegal behavior |
| 724 | // :62:17: note: when computing vector element at index '0' | |
| 724 | // :62:17: note: when computing vector element at index '1' | |
| 725 | 725 | // :62:22: error: use of undefined value here causes illegal behavior |
| 726 | 726 | // :62:22: note: when computing vector element at index '0' |
| 727 | 727 | // :62:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -749,27 +749,19 @@ const std = @import("std"); |
| 749 | 749 | // :65:27: error: use of undefined value here causes illegal behavior |
| 750 | 750 | // :65:27: error: use of undefined value here causes illegal behavior |
| 751 | 751 | // :65:27: error: use of undefined value here causes illegal behavior |
| 752 | // :65:27: note: when computing vector element at index '0' | |
| 753 | 752 | // :65:27: error: use of undefined value here causes illegal behavior |
| 754 | // :65:27: note: when computing vector element at index '0' | |
| 755 | 753 | // :65:27: error: use of undefined value here causes illegal behavior |
| 756 | // :65:27: note: when computing vector element at index '0' | |
| 757 | 754 | // :65:27: error: use of undefined value here causes illegal behavior |
| 758 | // :65:27: note: when computing vector element at index '0' | |
| 759 | 755 | // :65:27: error: use of undefined value here causes illegal behavior |
| 760 | // :65:27: note: when computing vector element at index '1' | |
| 761 | 756 | // :65:27: error: use of undefined value here causes illegal behavior |
| 762 | // :65:27: note: when computing vector element at index '1' | |
| 763 | 757 | // :65:27: error: use of undefined value here causes illegal behavior |
| 764 | // :65:27: note: when computing vector element at index '0' | |
| 765 | 758 | // :65:27: error: use of undefined value here causes illegal behavior |
| 766 | // :65:27: note: when computing vector element at index '0' | |
| 767 | 759 | // :65:27: error: use of undefined value here causes illegal behavior |
| 768 | // :65:27: note: when computing vector element at index '0' | |
| 769 | 760 | // :65:27: error: use of undefined value here causes illegal behavior |
| 770 | // :65:27: note: when computing vector element at index '0' | |
| 771 | 761 | // :65:27: error: use of undefined value here causes illegal behavior |
| 762 | // :65:27: note: when computing vector element at index '0' | |
| 772 | 763 | // :65:27: error: use of undefined value here causes illegal behavior |
| 764 | // :65:27: note: when computing vector element at index '0' | |
| 773 | 765 | // :65:27: error: use of undefined value here causes illegal behavior |
| 774 | 766 | // :65:27: note: when computing vector element at index '0' |
| 775 | 767 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -779,9 +771,9 @@ const std = @import("std"); |
| 779 | 771 | // :65:27: error: use of undefined value here causes illegal behavior |
| 780 | 772 | // :65:27: note: when computing vector element at index '0' |
| 781 | 773 | // :65:27: error: use of undefined value here causes illegal behavior |
| 782 | // :65:27: note: when computing vector element at index '1' | |
| 774 | // :65:27: note: when computing vector element at index '0' | |
| 783 | 775 | // :65:27: error: use of undefined value here causes illegal behavior |
| 784 | // :65:27: note: when computing vector element at index '1' | |
| 776 | // :65:27: note: when computing vector element at index '0' | |
| 785 | 777 | // :65:27: error: use of undefined value here causes illegal behavior |
| 786 | 778 | // :65:27: note: when computing vector element at index '0' |
| 787 | 779 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -791,7 +783,9 @@ const std = @import("std"); |
| 791 | 783 | // :65:27: error: use of undefined value here causes illegal behavior |
| 792 | 784 | // :65:27: note: when computing vector element at index '0' |
| 793 | 785 | // :65:27: error: use of undefined value here causes illegal behavior |
| 786 | // :65:27: note: when computing vector element at index '0' | |
| 794 | 787 | // :65:27: error: use of undefined value here causes illegal behavior |
| 788 | // :65:27: note: when computing vector element at index '0' | |
| 795 | 789 | // :65:27: error: use of undefined value here causes illegal behavior |
| 796 | 790 | // :65:27: note: when computing vector element at index '0' |
| 797 | 791 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -801,9 +795,9 @@ const std = @import("std"); |
| 801 | 795 | // :65:27: error: use of undefined value here causes illegal behavior |
| 802 | 796 | // :65:27: note: when computing vector element at index '0' |
| 803 | 797 | // :65:27: error: use of undefined value here causes illegal behavior |
| 804 | // :65:27: note: when computing vector element at index '1' | |
| 798 | // :65:27: note: when computing vector element at index '0' | |
| 805 | 799 | // :65:27: error: use of undefined value here causes illegal behavior |
| 806 | // :65:27: note: when computing vector element at index '1' | |
| 800 | // :65:27: note: when computing vector element at index '0' | |
| 807 | 801 | // :65:27: error: use of undefined value here causes illegal behavior |
| 808 | 802 | // :65:27: note: when computing vector element at index '0' |
| 809 | 803 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -813,7 +807,9 @@ const std = @import("std"); |
| 813 | 807 | // :65:27: error: use of undefined value here causes illegal behavior |
| 814 | 808 | // :65:27: note: when computing vector element at index '0' |
| 815 | 809 | // :65:27: error: use of undefined value here causes illegal behavior |
| 810 | // :65:27: note: when computing vector element at index '0' | |
| 816 | 811 | // :65:27: error: use of undefined value here causes illegal behavior |
| 812 | // :65:27: note: when computing vector element at index '0' | |
| 817 | 813 | // :65:27: error: use of undefined value here causes illegal behavior |
| 818 | 814 | // :65:27: note: when computing vector element at index '0' |
| 819 | 815 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -823,9 +819,9 @@ const std = @import("std"); |
| 823 | 819 | // :65:27: error: use of undefined value here causes illegal behavior |
| 824 | 820 | // :65:27: note: when computing vector element at index '0' |
| 825 | 821 | // :65:27: error: use of undefined value here causes illegal behavior |
| 826 | // :65:27: note: when computing vector element at index '1' | |
| 822 | // :65:27: note: when computing vector element at index '0' | |
| 827 | 823 | // :65:27: error: use of undefined value here causes illegal behavior |
| 828 | // :65:27: note: when computing vector element at index '1' | |
| 824 | // :65:27: note: when computing vector element at index '0' | |
| 829 | 825 | // :65:27: error: use of undefined value here causes illegal behavior |
| 830 | 826 | // :65:27: note: when computing vector element at index '0' |
| 831 | 827 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -835,7 +831,9 @@ const std = @import("std"); |
| 835 | 831 | // :65:27: error: use of undefined value here causes illegal behavior |
| 836 | 832 | // :65:27: note: when computing vector element at index '0' |
| 837 | 833 | // :65:27: error: use of undefined value here causes illegal behavior |
| 834 | // :65:27: note: when computing vector element at index '0' | |
| 838 | 835 | // :65:27: error: use of undefined value here causes illegal behavior |
| 836 | // :65:27: note: when computing vector element at index '0' | |
| 839 | 837 | // :65:27: error: use of undefined value here causes illegal behavior |
| 840 | 838 | // :65:27: note: when computing vector element at index '0' |
| 841 | 839 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -845,9 +843,9 @@ const std = @import("std"); |
| 845 | 843 | // :65:27: error: use of undefined value here causes illegal behavior |
| 846 | 844 | // :65:27: note: when computing vector element at index '0' |
| 847 | 845 | // :65:27: error: use of undefined value here causes illegal behavior |
| 848 | // :65:27: note: when computing vector element at index '1' | |
| 846 | // :65:27: note: when computing vector element at index '0' | |
| 849 | 847 | // :65:27: error: use of undefined value here causes illegal behavior |
| 850 | // :65:27: note: when computing vector element at index '1' | |
| 848 | // :65:27: note: when computing vector element at index '0' | |
| 851 | 849 | // :65:27: error: use of undefined value here causes illegal behavior |
| 852 | 850 | // :65:27: note: when computing vector element at index '0' |
| 853 | 851 | // :65:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -857,27 +855,29 @@ const std = @import("std"); |
| 857 | 855 | // :65:27: error: use of undefined value here causes illegal behavior |
| 858 | 856 | // :65:27: note: when computing vector element at index '0' |
| 859 | 857 | // :65:27: error: use of undefined value here causes illegal behavior |
| 858 | // :65:27: note: when computing vector element at index '1' | |
| 860 | 859 | // :65:27: error: use of undefined value here causes illegal behavior |
| 860 | // :65:27: note: when computing vector element at index '1' | |
| 861 | 861 | // :65:27: error: use of undefined value here causes illegal behavior |
| 862 | // :65:27: note: when computing vector element at index '0' | |
| 862 | // :65:27: note: when computing vector element at index '1' | |
| 863 | 863 | // :65:27: error: use of undefined value here causes illegal behavior |
| 864 | // :65:27: note: when computing vector element at index '0' | |
| 864 | // :65:27: note: when computing vector element at index '1' | |
| 865 | 865 | // :65:27: error: use of undefined value here causes illegal behavior |
| 866 | // :65:27: note: when computing vector element at index '0' | |
| 866 | // :65:27: note: when computing vector element at index '1' | |
| 867 | 867 | // :65:27: error: use of undefined value here causes illegal behavior |
| 868 | // :65:27: note: when computing vector element at index '0' | |
| 868 | // :65:27: note: when computing vector element at index '1' | |
| 869 | 869 | // :65:27: error: use of undefined value here causes illegal behavior |
| 870 | 870 | // :65:27: note: when computing vector element at index '1' |
| 871 | 871 | // :65:27: error: use of undefined value here causes illegal behavior |
| 872 | 872 | // :65:27: note: when computing vector element at index '1' |
| 873 | 873 | // :65:27: error: use of undefined value here causes illegal behavior |
| 874 | // :65:27: note: when computing vector element at index '0' | |
| 874 | // :65:27: note: when computing vector element at index '1' | |
| 875 | 875 | // :65:27: error: use of undefined value here causes illegal behavior |
| 876 | // :65:27: note: when computing vector element at index '0' | |
| 876 | // :65:27: note: when computing vector element at index '1' | |
| 877 | 877 | // :65:27: error: use of undefined value here causes illegal behavior |
| 878 | // :65:27: note: when computing vector element at index '0' | |
| 878 | // :65:27: note: when computing vector element at index '1' | |
| 879 | 879 | // :65:27: error: use of undefined value here causes illegal behavior |
| 880 | // :65:27: note: when computing vector element at index '0' | |
| 880 | // :65:27: note: when computing vector element at index '1' | |
| 881 | 881 | // :65:30: error: use of undefined value here causes illegal behavior |
| 882 | 882 | // :65:30: note: when computing vector element at index '0' |
| 883 | 883 | // :65:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -909,21 +909,13 @@ const std = @import("std"); |
| 909 | 909 | // :70:17: error: use of undefined value here causes illegal behavior |
| 910 | 910 | // :70:17: error: use of undefined value here causes illegal behavior |
| 911 | 911 | // :70:17: error: use of undefined value here causes illegal behavior |
| 912 | // :70:17: note: when computing vector element at index '1' | |
| 913 | 912 | // :70:17: error: use of undefined value here causes illegal behavior |
| 914 | // :70:17: note: when computing vector element at index '1' | |
| 915 | 913 | // :70:17: error: use of undefined value here causes illegal behavior |
| 916 | // :70:17: note: when computing vector element at index '1' | |
| 917 | 914 | // :70:17: error: use of undefined value here causes illegal behavior |
| 918 | // :70:17: note: when computing vector element at index '1' | |
| 919 | 915 | // :70:17: error: use of undefined value here causes illegal behavior |
| 920 | // :70:17: note: when computing vector element at index '0' | |
| 921 | 916 | // :70:17: error: use of undefined value here causes illegal behavior |
| 922 | // :70:17: note: when computing vector element at index '0' | |
| 923 | 917 | // :70:17: error: use of undefined value here causes illegal behavior |
| 924 | // :70:17: note: when computing vector element at index '0' | |
| 925 | 918 | // :70:17: error: use of undefined value here causes illegal behavior |
| 926 | // :70:17: note: when computing vector element at index '0' | |
| 927 | 919 | // :70:17: error: use of undefined value here causes illegal behavior |
| 928 | 920 | // :70:17: error: use of undefined value here causes illegal behavior |
| 929 | 921 | // :70:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -931,21 +923,13 @@ const std = @import("std"); |
| 931 | 923 | // :70:17: error: use of undefined value here causes illegal behavior |
| 932 | 924 | // :70:17: error: use of undefined value here causes illegal behavior |
| 933 | 925 | // :70:17: error: use of undefined value here causes illegal behavior |
| 934 | // :70:17: note: when computing vector element at index '1' | |
| 935 | 926 | // :70:17: error: use of undefined value here causes illegal behavior |
| 936 | // :70:17: note: when computing vector element at index '1' | |
| 937 | 927 | // :70:17: error: use of undefined value here causes illegal behavior |
| 938 | // :70:17: note: when computing vector element at index '1' | |
| 939 | 928 | // :70:17: error: use of undefined value here causes illegal behavior |
| 940 | // :70:17: note: when computing vector element at index '1' | |
| 941 | 929 | // :70:17: error: use of undefined value here causes illegal behavior |
| 942 | // :70:17: note: when computing vector element at index '0' | |
| 943 | 930 | // :70:17: error: use of undefined value here causes illegal behavior |
| 944 | // :70:17: note: when computing vector element at index '0' | |
| 945 | 931 | // :70:17: error: use of undefined value here causes illegal behavior |
| 946 | // :70:17: note: when computing vector element at index '0' | |
| 947 | 932 | // :70:17: error: use of undefined value here causes illegal behavior |
| 948 | // :70:17: note: when computing vector element at index '0' | |
| 949 | 933 | // :70:17: error: use of undefined value here causes illegal behavior |
| 950 | 934 | // :70:17: error: use of undefined value here causes illegal behavior |
| 951 | 935 | // :70:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -953,13 +937,11 @@ const std = @import("std"); |
| 953 | 937 | // :70:17: error: use of undefined value here causes illegal behavior |
| 954 | 938 | // :70:17: error: use of undefined value here causes illegal behavior |
| 955 | 939 | // :70:17: error: use of undefined value here causes illegal behavior |
| 956 | // :70:17: note: when computing vector element at index '1' | |
| 957 | 940 | // :70:17: error: use of undefined value here causes illegal behavior |
| 958 | // :70:17: note: when computing vector element at index '1' | |
| 959 | 941 | // :70:17: error: use of undefined value here causes illegal behavior |
| 960 | // :70:17: note: when computing vector element at index '1' | |
| 942 | // :70:17: note: when computing vector element at index '0' | |
| 961 | 943 | // :70:17: error: use of undefined value here causes illegal behavior |
| 962 | // :70:17: note: when computing vector element at index '1' | |
| 944 | // :70:17: note: when computing vector element at index '0' | |
| 963 | 945 | // :70:17: error: use of undefined value here causes illegal behavior |
| 964 | 946 | // :70:17: note: when computing vector element at index '0' |
| 965 | 947 | // :70:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -969,19 +951,25 @@ const std = @import("std"); |
| 969 | 951 | // :70:17: error: use of undefined value here causes illegal behavior |
| 970 | 952 | // :70:17: note: when computing vector element at index '0' |
| 971 | 953 | // :70:17: error: use of undefined value here causes illegal behavior |
| 954 | // :70:17: note: when computing vector element at index '0' | |
| 972 | 955 | // :70:17: error: use of undefined value here causes illegal behavior |
| 956 | // :70:17: note: when computing vector element at index '0' | |
| 973 | 957 | // :70:17: error: use of undefined value here causes illegal behavior |
| 958 | // :70:17: note: when computing vector element at index '0' | |
| 974 | 959 | // :70:17: error: use of undefined value here causes illegal behavior |
| 960 | // :70:17: note: when computing vector element at index '0' | |
| 975 | 961 | // :70:17: error: use of undefined value here causes illegal behavior |
| 962 | // :70:17: note: when computing vector element at index '0' | |
| 976 | 963 | // :70:17: error: use of undefined value here causes illegal behavior |
| 964 | // :70:17: note: when computing vector element at index '0' | |
| 977 | 965 | // :70:17: error: use of undefined value here causes illegal behavior |
| 978 | // :70:17: note: when computing vector element at index '1' | |
| 966 | // :70:17: note: when computing vector element at index '0' | |
| 979 | 967 | // :70:17: error: use of undefined value here causes illegal behavior |
| 980 | // :70:17: note: when computing vector element at index '1' | |
| 968 | // :70:17: note: when computing vector element at index '0' | |
| 981 | 969 | // :70:17: error: use of undefined value here causes illegal behavior |
| 982 | // :70:17: note: when computing vector element at index '1' | |
| 970 | // :70:17: note: when computing vector element at index '0' | |
| 983 | 971 | // :70:17: error: use of undefined value here causes illegal behavior |
| 984 | // :70:17: note: when computing vector element at index '1' | |
| 972 | // :70:17: note: when computing vector element at index '0' | |
| 985 | 973 | // :70:17: error: use of undefined value here causes illegal behavior |
| 986 | 974 | // :70:17: note: when computing vector element at index '0' |
| 987 | 975 | // :70:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -991,11 +979,17 @@ const std = @import("std"); |
| 991 | 979 | // :70:17: error: use of undefined value here causes illegal behavior |
| 992 | 980 | // :70:17: note: when computing vector element at index '0' |
| 993 | 981 | // :70:17: error: use of undefined value here causes illegal behavior |
| 982 | // :70:17: note: when computing vector element at index '0' | |
| 994 | 983 | // :70:17: error: use of undefined value here causes illegal behavior |
| 984 | // :70:17: note: when computing vector element at index '0' | |
| 995 | 985 | // :70:17: error: use of undefined value here causes illegal behavior |
| 986 | // :70:17: note: when computing vector element at index '0' | |
| 996 | 987 | // :70:17: error: use of undefined value here causes illegal behavior |
| 988 | // :70:17: note: when computing vector element at index '0' | |
| 997 | 989 | // :70:17: error: use of undefined value here causes illegal behavior |
| 990 | // :70:17: note: when computing vector element at index '1' | |
| 998 | 991 | // :70:17: error: use of undefined value here causes illegal behavior |
| 992 | // :70:17: note: when computing vector element at index '1' | |
| 999 | 993 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1000 | 994 | // :70:17: note: when computing vector element at index '1' |
| 1001 | 995 | // :70:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1005,19 +999,25 @@ const std = @import("std"); |
| 1005 | 999 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1006 | 1000 | // :70:17: note: when computing vector element at index '1' |
| 1007 | 1001 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1008 | // :70:17: note: when computing vector element at index '0' | |
| 1002 | // :70:17: note: when computing vector element at index '1' | |
| 1009 | 1003 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1010 | // :70:17: note: when computing vector element at index '0' | |
| 1004 | // :70:17: note: when computing vector element at index '1' | |
| 1011 | 1005 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1012 | // :70:17: note: when computing vector element at index '0' | |
| 1006 | // :70:17: note: when computing vector element at index '1' | |
| 1013 | 1007 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1014 | // :70:17: note: when computing vector element at index '0' | |
| 1008 | // :70:17: note: when computing vector element at index '1' | |
| 1015 | 1009 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1010 | // :70:17: note: when computing vector element at index '1' | |
| 1016 | 1011 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1012 | // :70:17: note: when computing vector element at index '1' | |
| 1017 | 1013 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1014 | // :70:17: note: when computing vector element at index '1' | |
| 1018 | 1015 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1016 | // :70:17: note: when computing vector element at index '1' | |
| 1019 | 1017 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1018 | // :70:17: note: when computing vector element at index '1' | |
| 1020 | 1019 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1020 | // :70:17: note: when computing vector element at index '1' | |
| 1021 | 1021 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1022 | 1022 | // :70:17: note: when computing vector element at index '1' |
| 1023 | 1023 | // :70:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1027,13 +1027,13 @@ const std = @import("std"); |
| 1027 | 1027 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1028 | 1028 | // :70:17: note: when computing vector element at index '1' |
| 1029 | 1029 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1030 | // :70:17: note: when computing vector element at index '0' | |
| 1030 | // :70:17: note: when computing vector element at index '1' | |
| 1031 | 1031 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1032 | // :70:17: note: when computing vector element at index '0' | |
| 1032 | // :70:17: note: when computing vector element at index '1' | |
| 1033 | 1033 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1034 | // :70:17: note: when computing vector element at index '0' | |
| 1034 | // :70:17: note: when computing vector element at index '1' | |
| 1035 | 1035 | // :70:17: error: use of undefined value here causes illegal behavior |
| 1036 | // :70:17: note: when computing vector element at index '0' | |
| 1036 | // :70:17: note: when computing vector element at index '1' | |
| 1037 | 1037 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1038 | 1038 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1039 | 1039 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1041,21 +1041,13 @@ const std = @import("std"); |
| 1041 | 1041 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1042 | 1042 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1043 | 1043 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1044 | // :73:27: note: when computing vector element at index '1' | |
| 1045 | 1044 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1046 | // :73:27: note: when computing vector element at index '1' | |
| 1047 | 1045 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1048 | // :73:27: note: when computing vector element at index '1' | |
| 1049 | 1046 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1050 | // :73:27: note: when computing vector element at index '1' | |
| 1051 | 1047 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1052 | // :73:27: note: when computing vector element at index '0' | |
| 1053 | 1048 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1054 | // :73:27: note: when computing vector element at index '0' | |
| 1055 | 1049 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1056 | // :73:27: note: when computing vector element at index '0' | |
| 1057 | 1050 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1058 | // :73:27: note: when computing vector element at index '0' | |
| 1059 | 1051 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1060 | 1052 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1061 | 1053 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1063,21 +1055,13 @@ const std = @import("std"); |
| 1063 | 1055 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1064 | 1056 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1065 | 1057 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1066 | // :73:27: note: when computing vector element at index '1' | |
| 1067 | 1058 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1068 | // :73:27: note: when computing vector element at index '1' | |
| 1069 | 1059 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1070 | // :73:27: note: when computing vector element at index '1' | |
| 1071 | 1060 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1072 | // :73:27: note: when computing vector element at index '1' | |
| 1073 | 1061 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1074 | // :73:27: note: when computing vector element at index '0' | |
| 1075 | 1062 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1076 | // :73:27: note: when computing vector element at index '0' | |
| 1077 | 1063 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1078 | // :73:27: note: when computing vector element at index '0' | |
| 1079 | 1064 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1080 | // :73:27: note: when computing vector element at index '0' | |
| 1081 | 1065 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1082 | 1066 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1083 | 1067 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1085,13 +1069,11 @@ const std = @import("std"); |
| 1085 | 1069 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1086 | 1070 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1087 | 1071 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1088 | // :73:27: note: when computing vector element at index '1' | |
| 1089 | 1072 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1090 | // :73:27: note: when computing vector element at index '1' | |
| 1091 | 1073 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1092 | // :73:27: note: when computing vector element at index '1' | |
| 1074 | // :73:27: note: when computing vector element at index '0' | |
| 1093 | 1075 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1094 | // :73:27: note: when computing vector element at index '1' | |
| 1076 | // :73:27: note: when computing vector element at index '0' | |
| 1095 | 1077 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1096 | 1078 | // :73:27: note: when computing vector element at index '0' |
| 1097 | 1079 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1101,19 +1083,25 @@ const std = @import("std"); |
| 1101 | 1083 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1102 | 1084 | // :73:27: note: when computing vector element at index '0' |
| 1103 | 1085 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1086 | // :73:27: note: when computing vector element at index '0' | |
| 1104 | 1087 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1088 | // :73:27: note: when computing vector element at index '0' | |
| 1105 | 1089 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1090 | // :73:27: note: when computing vector element at index '0' | |
| 1106 | 1091 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1092 | // :73:27: note: when computing vector element at index '0' | |
| 1107 | 1093 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1094 | // :73:27: note: when computing vector element at index '0' | |
| 1108 | 1095 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1096 | // :73:27: note: when computing vector element at index '0' | |
| 1109 | 1097 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1110 | // :73:27: note: when computing vector element at index '1' | |
| 1098 | // :73:27: note: when computing vector element at index '0' | |
| 1111 | 1099 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1112 | // :73:27: note: when computing vector element at index '1' | |
| 1100 | // :73:27: note: when computing vector element at index '0' | |
| 1113 | 1101 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1114 | // :73:27: note: when computing vector element at index '1' | |
| 1102 | // :73:27: note: when computing vector element at index '0' | |
| 1115 | 1103 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1116 | // :73:27: note: when computing vector element at index '1' | |
| 1104 | // :73:27: note: when computing vector element at index '0' | |
| 1117 | 1105 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1118 | 1106 | // :73:27: note: when computing vector element at index '0' |
| 1119 | 1107 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1123,11 +1111,17 @@ const std = @import("std"); |
| 1123 | 1111 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1124 | 1112 | // :73:27: note: when computing vector element at index '0' |
| 1125 | 1113 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1114 | // :73:27: note: when computing vector element at index '0' | |
| 1126 | 1115 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1116 | // :73:27: note: when computing vector element at index '0' | |
| 1127 | 1117 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1118 | // :73:27: note: when computing vector element at index '0' | |
| 1128 | 1119 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1120 | // :73:27: note: when computing vector element at index '0' | |
| 1129 | 1121 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1122 | // :73:27: note: when computing vector element at index '1' | |
| 1130 | 1123 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1124 | // :73:27: note: when computing vector element at index '1' | |
| 1131 | 1125 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1132 | 1126 | // :73:27: note: when computing vector element at index '1' |
| 1133 | 1127 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1137,19 +1131,25 @@ const std = @import("std"); |
| 1137 | 1131 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1138 | 1132 | // :73:27: note: when computing vector element at index '1' |
| 1139 | 1133 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1140 | // :73:27: note: when computing vector element at index '0' | |
| 1134 | // :73:27: note: when computing vector element at index '1' | |
| 1141 | 1135 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1142 | // :73:27: note: when computing vector element at index '0' | |
| 1136 | // :73:27: note: when computing vector element at index '1' | |
| 1143 | 1137 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1144 | // :73:27: note: when computing vector element at index '0' | |
| 1138 | // :73:27: note: when computing vector element at index '1' | |
| 1145 | 1139 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1146 | // :73:27: note: when computing vector element at index '0' | |
| 1140 | // :73:27: note: when computing vector element at index '1' | |
| 1147 | 1141 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1142 | // :73:27: note: when computing vector element at index '1' | |
| 1148 | 1143 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1144 | // :73:27: note: when computing vector element at index '1' | |
| 1149 | 1145 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1146 | // :73:27: note: when computing vector element at index '1' | |
| 1150 | 1147 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1148 | // :73:27: note: when computing vector element at index '1' | |
| 1151 | 1149 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1150 | // :73:27: note: when computing vector element at index '1' | |
| 1152 | 1151 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1152 | // :73:27: note: when computing vector element at index '1' | |
| 1153 | 1153 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1154 | 1154 | // :73:27: note: when computing vector element at index '1' |
| 1155 | 1155 | // :73:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1159,13 +1159,13 @@ const std = @import("std"); |
| 1159 | 1159 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1160 | 1160 | // :73:27: note: when computing vector element at index '1' |
| 1161 | 1161 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1162 | // :73:27: note: when computing vector element at index '0' | |
| 1162 | // :73:27: note: when computing vector element at index '1' | |
| 1163 | 1163 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1164 | // :73:27: note: when computing vector element at index '0' | |
| 1164 | // :73:27: note: when computing vector element at index '1' | |
| 1165 | 1165 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1166 | // :73:27: note: when computing vector element at index '0' | |
| 1166 | // :73:27: note: when computing vector element at index '1' | |
| 1167 | 1167 | // :73:27: error: use of undefined value here causes illegal behavior |
| 1168 | // :73:27: note: when computing vector element at index '0' | |
| 1168 | // :73:27: note: when computing vector element at index '1' | |
| 1169 | 1169 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1170 | 1170 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1171 | 1171 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1173,21 +1173,13 @@ const std = @import("std"); |
| 1173 | 1173 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1174 | 1174 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1175 | 1175 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1176 | // :76:34: note: when computing vector element at index '1' | |
| 1177 | 1176 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1178 | // :76:34: note: when computing vector element at index '1' | |
| 1179 | 1177 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1180 | // :76:34: note: when computing vector element at index '1' | |
| 1181 | 1178 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1182 | // :76:34: note: when computing vector element at index '1' | |
| 1183 | 1179 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1184 | // :76:34: note: when computing vector element at index '0' | |
| 1185 | 1180 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1186 | // :76:34: note: when computing vector element at index '0' | |
| 1187 | 1181 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1188 | // :76:34: note: when computing vector element at index '0' | |
| 1189 | 1182 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1190 | // :76:34: note: when computing vector element at index '0' | |
| 1191 | 1183 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1192 | 1184 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1193 | 1185 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1195,21 +1187,13 @@ const std = @import("std"); |
| 1195 | 1187 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1196 | 1188 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1197 | 1189 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1198 | // :76:34: note: when computing vector element at index '1' | |
| 1199 | 1190 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1200 | // :76:34: note: when computing vector element at index '1' | |
| 1201 | 1191 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1202 | // :76:34: note: when computing vector element at index '1' | |
| 1203 | 1192 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1204 | // :76:34: note: when computing vector element at index '1' | |
| 1205 | 1193 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1206 | // :76:34: note: when computing vector element at index '0' | |
| 1207 | 1194 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1208 | // :76:34: note: when computing vector element at index '0' | |
| 1209 | 1195 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1210 | // :76:34: note: when computing vector element at index '0' | |
| 1211 | 1196 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1212 | // :76:34: note: when computing vector element at index '0' | |
| 1213 | 1197 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1214 | 1198 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1215 | 1199 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1217,13 +1201,11 @@ const std = @import("std"); |
| 1217 | 1201 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1218 | 1202 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1219 | 1203 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1220 | // :76:34: note: when computing vector element at index '1' | |
| 1221 | 1204 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1222 | // :76:34: note: when computing vector element at index '1' | |
| 1223 | 1205 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1224 | // :76:34: note: when computing vector element at index '1' | |
| 1206 | // :76:34: note: when computing vector element at index '0' | |
| 1225 | 1207 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1226 | // :76:34: note: when computing vector element at index '1' | |
| 1208 | // :76:34: note: when computing vector element at index '0' | |
| 1227 | 1209 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1228 | 1210 | // :76:34: note: when computing vector element at index '0' |
| 1229 | 1211 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1233,19 +1215,25 @@ const std = @import("std"); |
| 1233 | 1215 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1234 | 1216 | // :76:34: note: when computing vector element at index '0' |
| 1235 | 1217 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1218 | // :76:34: note: when computing vector element at index '0' | |
| 1236 | 1219 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1220 | // :76:34: note: when computing vector element at index '0' | |
| 1237 | 1221 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1222 | // :76:34: note: when computing vector element at index '0' | |
| 1238 | 1223 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1224 | // :76:34: note: when computing vector element at index '0' | |
| 1239 | 1225 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1226 | // :76:34: note: when computing vector element at index '0' | |
| 1240 | 1227 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1228 | // :76:34: note: when computing vector element at index '0' | |
| 1241 | 1229 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1242 | // :76:34: note: when computing vector element at index '1' | |
| 1230 | // :76:34: note: when computing vector element at index '0' | |
| 1243 | 1231 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1244 | // :76:34: note: when computing vector element at index '1' | |
| 1232 | // :76:34: note: when computing vector element at index '0' | |
| 1245 | 1233 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1246 | // :76:34: note: when computing vector element at index '1' | |
| 1234 | // :76:34: note: when computing vector element at index '0' | |
| 1247 | 1235 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1248 | // :76:34: note: when computing vector element at index '1' | |
| 1236 | // :76:34: note: when computing vector element at index '0' | |
| 1249 | 1237 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1250 | 1238 | // :76:34: note: when computing vector element at index '0' |
| 1251 | 1239 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1255,11 +1243,17 @@ const std = @import("std"); |
| 1255 | 1243 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1256 | 1244 | // :76:34: note: when computing vector element at index '0' |
| 1257 | 1245 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1246 | // :76:34: note: when computing vector element at index '0' | |
| 1258 | 1247 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1248 | // :76:34: note: when computing vector element at index '0' | |
| 1259 | 1249 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1250 | // :76:34: note: when computing vector element at index '0' | |
| 1260 | 1251 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1252 | // :76:34: note: when computing vector element at index '0' | |
| 1261 | 1253 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1254 | // :76:34: note: when computing vector element at index '1' | |
| 1262 | 1255 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1256 | // :76:34: note: when computing vector element at index '1' | |
| 1263 | 1257 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1264 | 1258 | // :76:34: note: when computing vector element at index '1' |
| 1265 | 1259 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1269,19 +1263,25 @@ const std = @import("std"); |
| 1269 | 1263 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1270 | 1264 | // :76:34: note: when computing vector element at index '1' |
| 1271 | 1265 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1272 | // :76:34: note: when computing vector element at index '0' | |
| 1266 | // :76:34: note: when computing vector element at index '1' | |
| 1273 | 1267 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1274 | // :76:34: note: when computing vector element at index '0' | |
| 1268 | // :76:34: note: when computing vector element at index '1' | |
| 1275 | 1269 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1276 | // :76:34: note: when computing vector element at index '0' | |
| 1270 | // :76:34: note: when computing vector element at index '1' | |
| 1277 | 1271 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1278 | // :76:34: note: when computing vector element at index '0' | |
| 1272 | // :76:34: note: when computing vector element at index '1' | |
| 1279 | 1273 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1274 | // :76:34: note: when computing vector element at index '1' | |
| 1280 | 1275 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1276 | // :76:34: note: when computing vector element at index '1' | |
| 1281 | 1277 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1278 | // :76:34: note: when computing vector element at index '1' | |
| 1282 | 1279 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1280 | // :76:34: note: when computing vector element at index '1' | |
| 1283 | 1281 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1282 | // :76:34: note: when computing vector element at index '1' | |
| 1284 | 1283 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1284 | // :76:34: note: when computing vector element at index '1' | |
| 1285 | 1285 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1286 | 1286 | // :76:34: note: when computing vector element at index '1' |
| 1287 | 1287 | // :76:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1291,13 +1291,13 @@ const std = @import("std"); |
| 1291 | 1291 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1292 | 1292 | // :76:34: note: when computing vector element at index '1' |
| 1293 | 1293 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1294 | // :76:34: note: when computing vector element at index '0' | |
| 1294 | // :76:34: note: when computing vector element at index '1' | |
| 1295 | 1295 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1296 | // :76:34: note: when computing vector element at index '0' | |
| 1296 | // :76:34: note: when computing vector element at index '1' | |
| 1297 | 1297 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1298 | // :76:34: note: when computing vector element at index '0' | |
| 1298 | // :76:34: note: when computing vector element at index '1' | |
| 1299 | 1299 | // :76:34: error: use of undefined value here causes illegal behavior |
| 1300 | // :76:34: note: when computing vector element at index '0' | |
| 1300 | // :76:34: note: when computing vector element at index '1' | |
| 1301 | 1301 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1302 | 1302 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1303 | 1303 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1305,21 +1305,13 @@ const std = @import("std"); |
| 1305 | 1305 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1306 | 1306 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1307 | 1307 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1308 | // :79:17: note: when computing vector element at index '1' | |
| 1309 | 1308 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1310 | // :79:17: note: when computing vector element at index '1' | |
| 1311 | 1309 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1312 | // :79:17: note: when computing vector element at index '1' | |
| 1313 | 1310 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1314 | // :79:17: note: when computing vector element at index '1' | |
| 1315 | 1311 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1316 | // :79:17: note: when computing vector element at index '0' | |
| 1317 | 1312 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1318 | // :79:17: note: when computing vector element at index '0' | |
| 1319 | 1313 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1320 | // :79:17: note: when computing vector element at index '0' | |
| 1321 | 1314 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1322 | // :79:17: note: when computing vector element at index '0' | |
| 1323 | 1315 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1324 | 1316 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1325 | 1317 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1327,21 +1319,13 @@ const std = @import("std"); |
| 1327 | 1319 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1328 | 1320 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1329 | 1321 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1330 | // :79:17: note: when computing vector element at index '1' | |
| 1331 | 1322 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1332 | // :79:17: note: when computing vector element at index '1' | |
| 1333 | 1323 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1334 | // :79:17: note: when computing vector element at index '1' | |
| 1335 | 1324 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1336 | // :79:17: note: when computing vector element at index '1' | |
| 1337 | 1325 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1338 | // :79:17: note: when computing vector element at index '0' | |
| 1339 | 1326 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1340 | // :79:17: note: when computing vector element at index '0' | |
| 1341 | 1327 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1342 | // :79:17: note: when computing vector element at index '0' | |
| 1343 | 1328 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1344 | // :79:17: note: when computing vector element at index '0' | |
| 1345 | 1329 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1346 | 1330 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1347 | 1331 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1349,13 +1333,11 @@ const std = @import("std"); |
| 1349 | 1333 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1350 | 1334 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1351 | 1335 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1352 | // :79:17: note: when computing vector element at index '1' | |
| 1353 | 1336 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1354 | // :79:17: note: when computing vector element at index '1' | |
| 1355 | 1337 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1356 | // :79:17: note: when computing vector element at index '1' | |
| 1338 | // :79:17: note: when computing vector element at index '0' | |
| 1357 | 1339 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1358 | // :79:17: note: when computing vector element at index '1' | |
| 1340 | // :79:17: note: when computing vector element at index '0' | |
| 1359 | 1341 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1360 | 1342 | // :79:17: note: when computing vector element at index '0' |
| 1361 | 1343 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1365,19 +1347,25 @@ const std = @import("std"); |
| 1365 | 1347 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1366 | 1348 | // :79:17: note: when computing vector element at index '0' |
| 1367 | 1349 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1350 | // :79:17: note: when computing vector element at index '0' | |
| 1368 | 1351 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1352 | // :79:17: note: when computing vector element at index '0' | |
| 1369 | 1353 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1354 | // :79:17: note: when computing vector element at index '0' | |
| 1370 | 1355 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1356 | // :79:17: note: when computing vector element at index '0' | |
| 1371 | 1357 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1358 | // :79:17: note: when computing vector element at index '0' | |
| 1372 | 1359 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1360 | // :79:17: note: when computing vector element at index '0' | |
| 1373 | 1361 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1374 | // :79:17: note: when computing vector element at index '1' | |
| 1362 | // :79:17: note: when computing vector element at index '0' | |
| 1375 | 1363 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1376 | // :79:17: note: when computing vector element at index '1' | |
| 1364 | // :79:17: note: when computing vector element at index '0' | |
| 1377 | 1365 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1378 | // :79:17: note: when computing vector element at index '1' | |
| 1366 | // :79:17: note: when computing vector element at index '0' | |
| 1379 | 1367 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1380 | // :79:17: note: when computing vector element at index '1' | |
| 1368 | // :79:17: note: when computing vector element at index '0' | |
| 1381 | 1369 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1382 | 1370 | // :79:17: note: when computing vector element at index '0' |
| 1383 | 1371 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1387,11 +1375,17 @@ const std = @import("std"); |
| 1387 | 1375 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1388 | 1376 | // :79:17: note: when computing vector element at index '0' |
| 1389 | 1377 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1378 | // :79:17: note: when computing vector element at index '0' | |
| 1390 | 1379 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1380 | // :79:17: note: when computing vector element at index '0' | |
| 1391 | 1381 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1382 | // :79:17: note: when computing vector element at index '0' | |
| 1392 | 1383 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1384 | // :79:17: note: when computing vector element at index '0' | |
| 1393 | 1385 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1386 | // :79:17: note: when computing vector element at index '1' | |
| 1394 | 1387 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1388 | // :79:17: note: when computing vector element at index '1' | |
| 1395 | 1389 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1396 | 1390 | // :79:17: note: when computing vector element at index '1' |
| 1397 | 1391 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1401,19 +1395,25 @@ const std = @import("std"); |
| 1401 | 1395 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1402 | 1396 | // :79:17: note: when computing vector element at index '1' |
| 1403 | 1397 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1404 | // :79:17: note: when computing vector element at index '0' | |
| 1398 | // :79:17: note: when computing vector element at index '1' | |
| 1405 | 1399 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1406 | // :79:17: note: when computing vector element at index '0' | |
| 1400 | // :79:17: note: when computing vector element at index '1' | |
| 1407 | 1401 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1408 | // :79:17: note: when computing vector element at index '0' | |
| 1402 | // :79:17: note: when computing vector element at index '1' | |
| 1409 | 1403 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1410 | // :79:17: note: when computing vector element at index '0' | |
| 1404 | // :79:17: note: when computing vector element at index '1' | |
| 1411 | 1405 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1406 | // :79:17: note: when computing vector element at index '1' | |
| 1412 | 1407 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1408 | // :79:17: note: when computing vector element at index '1' | |
| 1413 | 1409 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1410 | // :79:17: note: when computing vector element at index '1' | |
| 1414 | 1411 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1412 | // :79:17: note: when computing vector element at index '1' | |
| 1415 | 1413 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1414 | // :79:17: note: when computing vector element at index '1' | |
| 1416 | 1415 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1416 | // :79:17: note: when computing vector element at index '1' | |
| 1417 | 1417 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1418 | 1418 | // :79:17: note: when computing vector element at index '1' |
| 1419 | 1419 | // :79:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1423,13 +1423,13 @@ const std = @import("std"); |
| 1423 | 1423 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1424 | 1424 | // :79:17: note: when computing vector element at index '1' |
| 1425 | 1425 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1426 | // :79:17: note: when computing vector element at index '0' | |
| 1426 | // :79:17: note: when computing vector element at index '1' | |
| 1427 | 1427 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1428 | // :79:17: note: when computing vector element at index '0' | |
| 1428 | // :79:17: note: when computing vector element at index '1' | |
| 1429 | 1429 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1430 | // :79:17: note: when computing vector element at index '0' | |
| 1430 | // :79:17: note: when computing vector element at index '1' | |
| 1431 | 1431 | // :79:17: error: use of undefined value here causes illegal behavior |
| 1432 | // :79:17: note: when computing vector element at index '0' | |
| 1432 | // :79:17: note: when computing vector element at index '1' | |
| 1433 | 1433 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1434 | 1434 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1435 | 1435 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1437,21 +1437,13 @@ const std = @import("std"); |
| 1437 | 1437 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1438 | 1438 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1439 | 1439 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1440 | // :82:27: note: when computing vector element at index '1' | |
| 1441 | 1440 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1442 | // :82:27: note: when computing vector element at index '1' | |
| 1443 | 1441 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1444 | // :82:27: note: when computing vector element at index '1' | |
| 1445 | 1442 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1446 | // :82:27: note: when computing vector element at index '1' | |
| 1447 | 1443 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1448 | // :82:27: note: when computing vector element at index '0' | |
| 1449 | 1444 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1450 | // :82:27: note: when computing vector element at index '0' | |
| 1451 | 1445 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1452 | // :82:27: note: when computing vector element at index '0' | |
| 1453 | 1446 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1454 | // :82:27: note: when computing vector element at index '0' | |
| 1455 | 1447 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1456 | 1448 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1457 | 1449 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1459,21 +1451,13 @@ const std = @import("std"); |
| 1459 | 1451 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1460 | 1452 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1461 | 1453 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1462 | // :82:27: note: when computing vector element at index '1' | |
| 1463 | 1454 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1464 | // :82:27: note: when computing vector element at index '1' | |
| 1465 | 1455 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1466 | // :82:27: note: when computing vector element at index '1' | |
| 1467 | 1456 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1468 | // :82:27: note: when computing vector element at index '1' | |
| 1469 | 1457 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1470 | // :82:27: note: when computing vector element at index '0' | |
| 1471 | 1458 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1472 | // :82:27: note: when computing vector element at index '0' | |
| 1473 | 1459 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1474 | // :82:27: note: when computing vector element at index '0' | |
| 1475 | 1460 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1476 | // :82:27: note: when computing vector element at index '0' | |
| 1477 | 1461 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1478 | 1462 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1479 | 1463 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1481,13 +1465,11 @@ const std = @import("std"); |
| 1481 | 1465 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1482 | 1466 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1483 | 1467 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1484 | // :82:27: note: when computing vector element at index '1' | |
| 1485 | 1468 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1486 | // :82:27: note: when computing vector element at index '1' | |
| 1487 | 1469 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1488 | // :82:27: note: when computing vector element at index '1' | |
| 1470 | // :82:27: note: when computing vector element at index '0' | |
| 1489 | 1471 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1490 | // :82:27: note: when computing vector element at index '1' | |
| 1472 | // :82:27: note: when computing vector element at index '0' | |
| 1491 | 1473 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1492 | 1474 | // :82:27: note: when computing vector element at index '0' |
| 1493 | 1475 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1497,19 +1479,25 @@ const std = @import("std"); |
| 1497 | 1479 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1498 | 1480 | // :82:27: note: when computing vector element at index '0' |
| 1499 | 1481 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1482 | // :82:27: note: when computing vector element at index '0' | |
| 1500 | 1483 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1484 | // :82:27: note: when computing vector element at index '0' | |
| 1501 | 1485 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1486 | // :82:27: note: when computing vector element at index '0' | |
| 1502 | 1487 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1488 | // :82:27: note: when computing vector element at index '0' | |
| 1503 | 1489 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1490 | // :82:27: note: when computing vector element at index '0' | |
| 1504 | 1491 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1492 | // :82:27: note: when computing vector element at index '0' | |
| 1505 | 1493 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1506 | // :82:27: note: when computing vector element at index '1' | |
| 1494 | // :82:27: note: when computing vector element at index '0' | |
| 1507 | 1495 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1508 | // :82:27: note: when computing vector element at index '1' | |
| 1496 | // :82:27: note: when computing vector element at index '0' | |
| 1509 | 1497 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1510 | // :82:27: note: when computing vector element at index '1' | |
| 1498 | // :82:27: note: when computing vector element at index '0' | |
| 1511 | 1499 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1512 | // :82:27: note: when computing vector element at index '1' | |
| 1500 | // :82:27: note: when computing vector element at index '0' | |
| 1513 | 1501 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1514 | 1502 | // :82:27: note: when computing vector element at index '0' |
| 1515 | 1503 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1519,11 +1507,17 @@ const std = @import("std"); |
| 1519 | 1507 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1520 | 1508 | // :82:27: note: when computing vector element at index '0' |
| 1521 | 1509 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1510 | // :82:27: note: when computing vector element at index '0' | |
| 1522 | 1511 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1512 | // :82:27: note: when computing vector element at index '0' | |
| 1523 | 1513 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1514 | // :82:27: note: when computing vector element at index '0' | |
| 1524 | 1515 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1516 | // :82:27: note: when computing vector element at index '0' | |
| 1525 | 1517 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1518 | // :82:27: note: when computing vector element at index '1' | |
| 1526 | 1519 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1520 | // :82:27: note: when computing vector element at index '1' | |
| 1527 | 1521 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1528 | 1522 | // :82:27: note: when computing vector element at index '1' |
| 1529 | 1523 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1533,19 +1527,25 @@ const std = @import("std"); |
| 1533 | 1527 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1534 | 1528 | // :82:27: note: when computing vector element at index '1' |
| 1535 | 1529 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1536 | // :82:27: note: when computing vector element at index '0' | |
| 1530 | // :82:27: note: when computing vector element at index '1' | |
| 1537 | 1531 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1538 | // :82:27: note: when computing vector element at index '0' | |
| 1532 | // :82:27: note: when computing vector element at index '1' | |
| 1539 | 1533 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1540 | // :82:27: note: when computing vector element at index '0' | |
| 1534 | // :82:27: note: when computing vector element at index '1' | |
| 1541 | 1535 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1542 | // :82:27: note: when computing vector element at index '0' | |
| 1536 | // :82:27: note: when computing vector element at index '1' | |
| 1543 | 1537 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1538 | // :82:27: note: when computing vector element at index '1' | |
| 1544 | 1539 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1540 | // :82:27: note: when computing vector element at index '1' | |
| 1545 | 1541 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1542 | // :82:27: note: when computing vector element at index '1' | |
| 1546 | 1543 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1544 | // :82:27: note: when computing vector element at index '1' | |
| 1547 | 1545 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1546 | // :82:27: note: when computing vector element at index '1' | |
| 1548 | 1547 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1548 | // :82:27: note: when computing vector element at index '1' | |
| 1549 | 1549 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1550 | 1550 | // :82:27: note: when computing vector element at index '1' |
| 1551 | 1551 | // :82:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1555,44 +1555,37 @@ const std = @import("std"); |
| 1555 | 1555 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1556 | 1556 | // :82:27: note: when computing vector element at index '1' |
| 1557 | 1557 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1558 | // :82:27: note: when computing vector element at index '0' | |
| 1558 | // :82:27: note: when computing vector element at index '1' | |
| 1559 | 1559 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1560 | // :82:27: note: when computing vector element at index '0' | |
| 1560 | // :82:27: note: when computing vector element at index '1' | |
| 1561 | 1561 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1562 | // :82:27: note: when computing vector element at index '0' | |
| 1562 | // :82:27: note: when computing vector element at index '1' | |
| 1563 | 1563 | // :82:27: error: use of undefined value here causes illegal behavior |
| 1564 | // :82:27: note: when computing vector element at index '0' | |
| 1564 | // :82:27: note: when computing vector element at index '1' | |
| 1565 | 1565 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1566 | 1566 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1567 | // :87:17: note: when computing vector element at index '0' | |
| 1568 | 1567 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1569 | // :87:17: note: when computing vector element at index '0' | |
| 1570 | 1568 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1571 | // :87:17: note: when computing vector element at index '0' | |
| 1572 | 1569 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1573 | // :87:17: note: when computing vector element at index '1' | |
| 1574 | 1570 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1575 | // :87:17: note: when computing vector element at index '0' | |
| 1576 | 1571 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1577 | 1572 | // :87:17: note: when computing vector element at index '0' |
| 1578 | 1573 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1579 | 1574 | // :87:17: note: when computing vector element at index '0' |
| 1580 | 1575 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1581 | // :87:17: error: use of undefined value here causes illegal behavior | |
| 1582 | 1576 | // :87:17: note: when computing vector element at index '0' |
| 1583 | 1577 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1584 | 1578 | // :87:17: note: when computing vector element at index '0' |
| 1585 | 1579 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1586 | 1580 | // :87:17: note: when computing vector element at index '0' |
| 1587 | 1581 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1588 | // :87:17: note: when computing vector element at index '1' | |
| 1589 | // :87:17: error: use of undefined value here causes illegal behavior | |
| 1590 | 1582 | // :87:17: note: when computing vector element at index '0' |
| 1591 | 1583 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1592 | 1584 | // :87:17: note: when computing vector element at index '0' |
| 1593 | 1585 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1594 | 1586 | // :87:17: note: when computing vector element at index '0' |
| 1595 | 1587 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1588 | // :87:17: note: when computing vector element at index '0' | |
| 1596 | 1589 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1597 | 1590 | // :87:17: note: when computing vector element at index '0' |
| 1598 | 1591 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1600,7 +1593,7 @@ const std = @import("std"); |
| 1600 | 1593 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1601 | 1594 | // :87:17: note: when computing vector element at index '0' |
| 1602 | 1595 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1603 | // :87:17: note: when computing vector element at index '1' | |
| 1596 | // :87:17: note: when computing vector element at index '0' | |
| 1604 | 1597 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1605 | 1598 | // :87:17: note: when computing vector element at index '0' |
| 1606 | 1599 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1608,6 +1601,7 @@ const std = @import("std"); |
| 1608 | 1601 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1609 | 1602 | // :87:17: note: when computing vector element at index '0' |
| 1610 | 1603 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1604 | // :87:17: note: when computing vector element at index '0' | |
| 1611 | 1605 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1612 | 1606 | // :87:17: note: when computing vector element at index '0' |
| 1613 | 1607 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1615,7 +1609,7 @@ const std = @import("std"); |
| 1615 | 1609 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1616 | 1610 | // :87:17: note: when computing vector element at index '0' |
| 1617 | 1611 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1618 | // :87:17: note: when computing vector element at index '1' | |
| 1612 | // :87:17: note: when computing vector element at index '0' | |
| 1619 | 1613 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1620 | 1614 | // :87:17: note: when computing vector element at index '0' |
| 1621 | 1615 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1623,6 +1617,7 @@ const std = @import("std"); |
| 1623 | 1617 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1624 | 1618 | // :87:17: note: when computing vector element at index '0' |
| 1625 | 1619 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1620 | // :87:17: note: when computing vector element at index '0' | |
| 1626 | 1621 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1627 | 1622 | // :87:17: note: when computing vector element at index '0' |
| 1628 | 1623 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1630,7 +1625,7 @@ const std = @import("std"); |
| 1630 | 1625 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1631 | 1626 | // :87:17: note: when computing vector element at index '0' |
| 1632 | 1627 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1633 | // :87:17: note: when computing vector element at index '1' | |
| 1628 | // :87:17: note: when computing vector element at index '0' | |
| 1634 | 1629 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1635 | 1630 | // :87:17: note: when computing vector element at index '0' |
| 1636 | 1631 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1638,6 +1633,7 @@ const std = @import("std"); |
| 1638 | 1633 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1639 | 1634 | // :87:17: note: when computing vector element at index '0' |
| 1640 | 1635 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1636 | // :87:17: note: when computing vector element at index '0' | |
| 1641 | 1637 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1642 | 1638 | // :87:17: note: when computing vector element at index '0' |
| 1643 | 1639 | // :87:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1647,108 +1643,105 @@ const std = @import("std"); |
| 1647 | 1643 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1648 | 1644 | // :87:17: note: when computing vector element at index '1' |
| 1649 | 1645 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1650 | // :87:17: note: when computing vector element at index '0' | |
| 1646 | // :87:17: note: when computing vector element at index '1' | |
| 1651 | 1647 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1652 | // :87:17: note: when computing vector element at index '0' | |
| 1648 | // :87:17: note: when computing vector element at index '1' | |
| 1653 | 1649 | // :87:17: error: use of undefined value here causes illegal behavior |
| 1654 | // :87:17: note: when computing vector element at index '0' | |
| 1650 | // :87:17: note: when computing vector element at index '1' | |
| 1651 | // :87:17: error: use of undefined value here causes illegal behavior | |
| 1652 | // :87:17: note: when computing vector element at index '1' | |
| 1653 | // :87:17: error: use of undefined value here causes illegal behavior | |
| 1654 | // :87:17: note: when computing vector element at index '1' | |
| 1655 | 1655 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1656 | 1656 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1657 | // :87:22: note: when computing vector element at index '0' | |
| 1658 | 1657 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1659 | // :87:22: note: when computing vector element at index '0' | |
| 1660 | 1658 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1661 | // :87:22: note: when computing vector element at index '1' | |
| 1662 | 1659 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1663 | // :87:22: note: when computing vector element at index '0' | |
| 1664 | 1660 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1665 | // :87:22: note: when computing vector element at index '0' | |
| 1666 | 1661 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1662 | // :87:22: note: when computing vector element at index '0' | |
| 1667 | 1663 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1668 | 1664 | // :87:22: note: when computing vector element at index '0' |
| 1669 | 1665 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1670 | 1666 | // :87:22: note: when computing vector element at index '0' |
| 1671 | 1667 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1672 | // :87:22: note: when computing vector element at index '1' | |
| 1668 | // :87:22: note: when computing vector element at index '0' | |
| 1673 | 1669 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1674 | 1670 | // :87:22: note: when computing vector element at index '0' |
| 1675 | 1671 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1676 | 1672 | // :87:22: note: when computing vector element at index '0' |
| 1677 | 1673 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1674 | // :87:22: note: when computing vector element at index '0' | |
| 1678 | 1675 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1679 | 1676 | // :87:22: note: when computing vector element at index '0' |
| 1680 | 1677 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1681 | 1678 | // :87:22: note: when computing vector element at index '0' |
| 1682 | 1679 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1683 | // :87:22: note: when computing vector element at index '1' | |
| 1680 | // :87:22: note: when computing vector element at index '0' | |
| 1684 | 1681 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1685 | 1682 | // :87:22: note: when computing vector element at index '0' |
| 1686 | 1683 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1687 | 1684 | // :87:22: note: when computing vector element at index '0' |
| 1688 | 1685 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1686 | // :87:22: note: when computing vector element at index '0' | |
| 1689 | 1687 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1690 | 1688 | // :87:22: note: when computing vector element at index '0' |
| 1691 | 1689 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1692 | 1690 | // :87:22: note: when computing vector element at index '0' |
| 1693 | 1691 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1694 | // :87:22: note: when computing vector element at index '1' | |
| 1692 | // :87:22: note: when computing vector element at index '0' | |
| 1695 | 1693 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1696 | 1694 | // :87:22: note: when computing vector element at index '0' |
| 1697 | 1695 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1698 | 1696 | // :87:22: note: when computing vector element at index '0' |
| 1699 | 1697 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1698 | // :87:22: note: when computing vector element at index '0' | |
| 1700 | 1699 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1701 | 1700 | // :87:22: note: when computing vector element at index '0' |
| 1702 | 1701 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1703 | 1702 | // :87:22: note: when computing vector element at index '0' |
| 1704 | 1703 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1705 | // :87:22: note: when computing vector element at index '1' | |
| 1704 | // :87:22: note: when computing vector element at index '0' | |
| 1706 | 1705 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1707 | 1706 | // :87:22: note: when computing vector element at index '0' |
| 1708 | 1707 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1709 | 1708 | // :87:22: note: when computing vector element at index '0' |
| 1710 | 1709 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1710 | // :87:22: note: when computing vector element at index '1' | |
| 1711 | 1711 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1712 | // :87:22: note: when computing vector element at index '0' | |
| 1712 | // :87:22: note: when computing vector element at index '1' | |
| 1713 | 1713 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1714 | // :87:22: note: when computing vector element at index '0' | |
| 1714 | // :87:22: note: when computing vector element at index '1' | |
| 1715 | 1715 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1716 | 1716 | // :87:22: note: when computing vector element at index '1' |
| 1717 | 1717 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1718 | // :87:22: note: when computing vector element at index '0' | |
| 1718 | // :87:22: note: when computing vector element at index '1' | |
| 1719 | 1719 | // :87:22: error: use of undefined value here causes illegal behavior |
| 1720 | // :87:22: note: when computing vector element at index '0' | |
| 1720 | // :87:22: note: when computing vector element at index '1' | |
| 1721 | 1721 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1722 | 1722 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1723 | // :90:27: note: when computing vector element at index '0' | |
| 1724 | 1723 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1725 | // :90:27: note: when computing vector element at index '0' | |
| 1726 | 1724 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1727 | // :90:27: note: when computing vector element at index '0' | |
| 1728 | 1725 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1729 | // :90:27: note: when computing vector element at index '1' | |
| 1730 | 1726 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1731 | // :90:27: note: when computing vector element at index '0' | |
| 1732 | 1727 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1733 | 1728 | // :90:27: note: when computing vector element at index '0' |
| 1734 | 1729 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1735 | 1730 | // :90:27: note: when computing vector element at index '0' |
| 1736 | 1731 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1737 | // :90:27: error: use of undefined value here causes illegal behavior | |
| 1738 | 1732 | // :90:27: note: when computing vector element at index '0' |
| 1739 | 1733 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1740 | 1734 | // :90:27: note: when computing vector element at index '0' |
| 1741 | 1735 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1742 | 1736 | // :90:27: note: when computing vector element at index '0' |
| 1743 | 1737 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1744 | // :90:27: note: when computing vector element at index '1' | |
| 1745 | // :90:27: error: use of undefined value here causes illegal behavior | |
| 1746 | 1738 | // :90:27: note: when computing vector element at index '0' |
| 1747 | 1739 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1748 | 1740 | // :90:27: note: when computing vector element at index '0' |
| 1749 | 1741 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1750 | 1742 | // :90:27: note: when computing vector element at index '0' |
| 1751 | 1743 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1744 | // :90:27: note: when computing vector element at index '0' | |
| 1752 | 1745 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1753 | 1746 | // :90:27: note: when computing vector element at index '0' |
| 1754 | 1747 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1756,7 +1749,7 @@ const std = @import("std"); |
| 1756 | 1749 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1757 | 1750 | // :90:27: note: when computing vector element at index '0' |
| 1758 | 1751 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1759 | // :90:27: note: when computing vector element at index '1' | |
| 1752 | // :90:27: note: when computing vector element at index '0' | |
| 1760 | 1753 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1761 | 1754 | // :90:27: note: when computing vector element at index '0' |
| 1762 | 1755 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1764,6 +1757,7 @@ const std = @import("std"); |
| 1764 | 1757 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1765 | 1758 | // :90:27: note: when computing vector element at index '0' |
| 1766 | 1759 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1760 | // :90:27: note: when computing vector element at index '0' | |
| 1767 | 1761 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1768 | 1762 | // :90:27: note: when computing vector element at index '0' |
| 1769 | 1763 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1771,7 +1765,7 @@ const std = @import("std"); |
| 1771 | 1765 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1772 | 1766 | // :90:27: note: when computing vector element at index '0' |
| 1773 | 1767 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1774 | // :90:27: note: when computing vector element at index '1' | |
| 1768 | // :90:27: note: when computing vector element at index '0' | |
| 1775 | 1769 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1776 | 1770 | // :90:27: note: when computing vector element at index '0' |
| 1777 | 1771 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1779,6 +1773,7 @@ const std = @import("std"); |
| 1779 | 1773 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1780 | 1774 | // :90:27: note: when computing vector element at index '0' |
| 1781 | 1775 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1776 | // :90:27: note: when computing vector element at index '0' | |
| 1782 | 1777 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1783 | 1778 | // :90:27: note: when computing vector element at index '0' |
| 1784 | 1779 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1786,7 +1781,7 @@ const std = @import("std"); |
| 1786 | 1781 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1787 | 1782 | // :90:27: note: when computing vector element at index '0' |
| 1788 | 1783 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1789 | // :90:27: note: when computing vector element at index '1' | |
| 1784 | // :90:27: note: when computing vector element at index '0' | |
| 1790 | 1785 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1791 | 1786 | // :90:27: note: when computing vector element at index '0' |
| 1792 | 1787 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1794,6 +1789,7 @@ const std = @import("std"); |
| 1794 | 1789 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1795 | 1790 | // :90:27: note: when computing vector element at index '0' |
| 1796 | 1791 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1792 | // :90:27: note: when computing vector element at index '0' | |
| 1797 | 1793 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1798 | 1794 | // :90:27: note: when computing vector element at index '0' |
| 1799 | 1795 | // :90:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1803,108 +1799,105 @@ const std = @import("std"); |
| 1803 | 1799 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1804 | 1800 | // :90:27: note: when computing vector element at index '1' |
| 1805 | 1801 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1806 | // :90:27: note: when computing vector element at index '0' | |
| 1802 | // :90:27: note: when computing vector element at index '1' | |
| 1807 | 1803 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1808 | // :90:27: note: when computing vector element at index '0' | |
| 1804 | // :90:27: note: when computing vector element at index '1' | |
| 1809 | 1805 | // :90:27: error: use of undefined value here causes illegal behavior |
| 1810 | // :90:27: note: when computing vector element at index '0' | |
| 1806 | // :90:27: note: when computing vector element at index '1' | |
| 1807 | // :90:27: error: use of undefined value here causes illegal behavior | |
| 1808 | // :90:27: note: when computing vector element at index '1' | |
| 1809 | // :90:27: error: use of undefined value here causes illegal behavior | |
| 1810 | // :90:27: note: when computing vector element at index '1' | |
| 1811 | 1811 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1812 | 1812 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1813 | // :90:30: note: when computing vector element at index '0' | |
| 1814 | 1813 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1815 | // :90:30: note: when computing vector element at index '0' | |
| 1816 | 1814 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1817 | // :90:30: note: when computing vector element at index '1' | |
| 1818 | 1815 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1819 | // :90:30: note: when computing vector element at index '0' | |
| 1820 | 1816 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1821 | // :90:30: note: when computing vector element at index '0' | |
| 1822 | 1817 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1818 | // :90:30: note: when computing vector element at index '0' | |
| 1823 | 1819 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1824 | 1820 | // :90:30: note: when computing vector element at index '0' |
| 1825 | 1821 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1826 | 1822 | // :90:30: note: when computing vector element at index '0' |
| 1827 | 1823 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1828 | // :90:30: note: when computing vector element at index '1' | |
| 1824 | // :90:30: note: when computing vector element at index '0' | |
| 1829 | 1825 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1830 | 1826 | // :90:30: note: when computing vector element at index '0' |
| 1831 | 1827 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1832 | 1828 | // :90:30: note: when computing vector element at index '0' |
| 1833 | 1829 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1830 | // :90:30: note: when computing vector element at index '0' | |
| 1834 | 1831 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1835 | 1832 | // :90:30: note: when computing vector element at index '0' |
| 1836 | 1833 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1837 | 1834 | // :90:30: note: when computing vector element at index '0' |
| 1838 | 1835 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1839 | // :90:30: note: when computing vector element at index '1' | |
| 1836 | // :90:30: note: when computing vector element at index '0' | |
| 1840 | 1837 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1841 | 1838 | // :90:30: note: when computing vector element at index '0' |
| 1842 | 1839 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1843 | 1840 | // :90:30: note: when computing vector element at index '0' |
| 1844 | 1841 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1842 | // :90:30: note: when computing vector element at index '0' | |
| 1845 | 1843 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1846 | 1844 | // :90:30: note: when computing vector element at index '0' |
| 1847 | 1845 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1848 | 1846 | // :90:30: note: when computing vector element at index '0' |
| 1849 | 1847 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1850 | // :90:30: note: when computing vector element at index '1' | |
| 1848 | // :90:30: note: when computing vector element at index '0' | |
| 1851 | 1849 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1852 | 1850 | // :90:30: note: when computing vector element at index '0' |
| 1853 | 1851 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1854 | 1852 | // :90:30: note: when computing vector element at index '0' |
| 1855 | 1853 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1854 | // :90:30: note: when computing vector element at index '0' | |
| 1856 | 1855 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1857 | 1856 | // :90:30: note: when computing vector element at index '0' |
| 1858 | 1857 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1859 | 1858 | // :90:30: note: when computing vector element at index '0' |
| 1860 | 1859 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1861 | // :90:30: note: when computing vector element at index '1' | |
| 1860 | // :90:30: note: when computing vector element at index '0' | |
| 1862 | 1861 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1863 | 1862 | // :90:30: note: when computing vector element at index '0' |
| 1864 | 1863 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1865 | 1864 | // :90:30: note: when computing vector element at index '0' |
| 1866 | 1865 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1866 | // :90:30: note: when computing vector element at index '1' | |
| 1867 | 1867 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1868 | // :90:30: note: when computing vector element at index '0' | |
| 1868 | // :90:30: note: when computing vector element at index '1' | |
| 1869 | 1869 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1870 | // :90:30: note: when computing vector element at index '0' | |
| 1870 | // :90:30: note: when computing vector element at index '1' | |
| 1871 | 1871 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1872 | 1872 | // :90:30: note: when computing vector element at index '1' |
| 1873 | 1873 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1874 | // :90:30: note: when computing vector element at index '0' | |
| 1874 | // :90:30: note: when computing vector element at index '1' | |
| 1875 | 1875 | // :90:30: error: use of undefined value here causes illegal behavior |
| 1876 | // :90:30: note: when computing vector element at index '0' | |
| 1876 | // :90:30: note: when computing vector element at index '1' | |
| 1877 | 1877 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1878 | 1878 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1879 | // :93:34: note: when computing vector element at index '0' | |
| 1880 | 1879 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1881 | // :93:34: note: when computing vector element at index '0' | |
| 1882 | 1880 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1883 | // :93:34: note: when computing vector element at index '0' | |
| 1884 | 1881 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1885 | // :93:34: note: when computing vector element at index '1' | |
| 1886 | 1882 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1887 | // :93:34: note: when computing vector element at index '0' | |
| 1888 | 1883 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1889 | 1884 | // :93:34: note: when computing vector element at index '0' |
| 1890 | 1885 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1891 | 1886 | // :93:34: note: when computing vector element at index '0' |
| 1892 | 1887 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1893 | // :93:34: error: use of undefined value here causes illegal behavior | |
| 1894 | 1888 | // :93:34: note: when computing vector element at index '0' |
| 1895 | 1889 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1896 | 1890 | // :93:34: note: when computing vector element at index '0' |
| 1897 | 1891 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1898 | 1892 | // :93:34: note: when computing vector element at index '0' |
| 1899 | 1893 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1900 | // :93:34: note: when computing vector element at index '1' | |
| 1901 | // :93:34: error: use of undefined value here causes illegal behavior | |
| 1902 | 1894 | // :93:34: note: when computing vector element at index '0' |
| 1903 | 1895 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1904 | 1896 | // :93:34: note: when computing vector element at index '0' |
| 1905 | 1897 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1906 | 1898 | // :93:34: note: when computing vector element at index '0' |
| 1907 | 1899 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1900 | // :93:34: note: when computing vector element at index '0' | |
| 1908 | 1901 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1909 | 1902 | // :93:34: note: when computing vector element at index '0' |
| 1910 | 1903 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1912,7 +1905,7 @@ const std = @import("std"); |
| 1912 | 1905 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1913 | 1906 | // :93:34: note: when computing vector element at index '0' |
| 1914 | 1907 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1915 | // :93:34: note: when computing vector element at index '1' | |
| 1908 | // :93:34: note: when computing vector element at index '0' | |
| 1916 | 1909 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1917 | 1910 | // :93:34: note: when computing vector element at index '0' |
| 1918 | 1911 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1920,6 +1913,7 @@ const std = @import("std"); |
| 1920 | 1913 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1921 | 1914 | // :93:34: note: when computing vector element at index '0' |
| 1922 | 1915 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1916 | // :93:34: note: when computing vector element at index '0' | |
| 1923 | 1917 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1924 | 1918 | // :93:34: note: when computing vector element at index '0' |
| 1925 | 1919 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1927,7 +1921,7 @@ const std = @import("std"); |
| 1927 | 1921 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1928 | 1922 | // :93:34: note: when computing vector element at index '0' |
| 1929 | 1923 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1930 | // :93:34: note: when computing vector element at index '1' | |
| 1924 | // :93:34: note: when computing vector element at index '0' | |
| 1931 | 1925 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1932 | 1926 | // :93:34: note: when computing vector element at index '0' |
| 1933 | 1927 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1935,6 +1929,7 @@ const std = @import("std"); |
| 1935 | 1929 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1936 | 1930 | // :93:34: note: when computing vector element at index '0' |
| 1937 | 1931 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1932 | // :93:34: note: when computing vector element at index '0' | |
| 1938 | 1933 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1939 | 1934 | // :93:34: note: when computing vector element at index '0' |
| 1940 | 1935 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1942,7 +1937,7 @@ const std = @import("std"); |
| 1942 | 1937 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1943 | 1938 | // :93:34: note: when computing vector element at index '0' |
| 1944 | 1939 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1945 | // :93:34: note: when computing vector element at index '1' | |
| 1940 | // :93:34: note: when computing vector element at index '0' | |
| 1946 | 1941 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1947 | 1942 | // :93:34: note: when computing vector element at index '0' |
| 1948 | 1943 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1950,6 +1945,7 @@ const std = @import("std"); |
| 1950 | 1945 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1951 | 1946 | // :93:34: note: when computing vector element at index '0' |
| 1952 | 1947 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1948 | // :93:34: note: when computing vector element at index '0' | |
| 1953 | 1949 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1954 | 1950 | // :93:34: note: when computing vector element at index '0' |
| 1955 | 1951 | // :93:34: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -1959,108 +1955,105 @@ const std = @import("std"); |
| 1959 | 1955 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1960 | 1956 | // :93:34: note: when computing vector element at index '1' |
| 1961 | 1957 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1962 | // :93:34: note: when computing vector element at index '0' | |
| 1958 | // :93:34: note: when computing vector element at index '1' | |
| 1963 | 1959 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1964 | // :93:34: note: when computing vector element at index '0' | |
| 1960 | // :93:34: note: when computing vector element at index '1' | |
| 1965 | 1961 | // :93:34: error: use of undefined value here causes illegal behavior |
| 1966 | // :93:34: note: when computing vector element at index '0' | |
| 1962 | // :93:34: note: when computing vector element at index '1' | |
| 1963 | // :93:34: error: use of undefined value here causes illegal behavior | |
| 1964 | // :93:34: note: when computing vector element at index '1' | |
| 1965 | // :93:34: error: use of undefined value here causes illegal behavior | |
| 1966 | // :93:34: note: when computing vector element at index '1' | |
| 1967 | 1967 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1968 | 1968 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1969 | // :93:37: note: when computing vector element at index '0' | |
| 1970 | 1969 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1971 | // :93:37: note: when computing vector element at index '0' | |
| 1972 | 1970 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1973 | // :93:37: note: when computing vector element at index '1' | |
| 1974 | 1971 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1975 | // :93:37: note: when computing vector element at index '0' | |
| 1976 | 1972 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1977 | // :93:37: note: when computing vector element at index '0' | |
| 1978 | 1973 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1974 | // :93:37: note: when computing vector element at index '0' | |
| 1979 | 1975 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1980 | 1976 | // :93:37: note: when computing vector element at index '0' |
| 1981 | 1977 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1982 | 1978 | // :93:37: note: when computing vector element at index '0' |
| 1983 | 1979 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1984 | // :93:37: note: when computing vector element at index '1' | |
| 1980 | // :93:37: note: when computing vector element at index '0' | |
| 1985 | 1981 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1986 | 1982 | // :93:37: note: when computing vector element at index '0' |
| 1987 | 1983 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1988 | 1984 | // :93:37: note: when computing vector element at index '0' |
| 1989 | 1985 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1986 | // :93:37: note: when computing vector element at index '0' | |
| 1990 | 1987 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1991 | 1988 | // :93:37: note: when computing vector element at index '0' |
| 1992 | 1989 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1993 | 1990 | // :93:37: note: when computing vector element at index '0' |
| 1994 | 1991 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1995 | // :93:37: note: when computing vector element at index '1' | |
| 1992 | // :93:37: note: when computing vector element at index '0' | |
| 1996 | 1993 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1997 | 1994 | // :93:37: note: when computing vector element at index '0' |
| 1998 | 1995 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1999 | 1996 | // :93:37: note: when computing vector element at index '0' |
| 2000 | 1997 | // :93:37: error: use of undefined value here causes illegal behavior |
| 1998 | // :93:37: note: when computing vector element at index '0' | |
| 2001 | 1999 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2002 | 2000 | // :93:37: note: when computing vector element at index '0' |
| 2003 | 2001 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2004 | 2002 | // :93:37: note: when computing vector element at index '0' |
| 2005 | 2003 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2006 | // :93:37: note: when computing vector element at index '1' | |
| 2004 | // :93:37: note: when computing vector element at index '0' | |
| 2007 | 2005 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2008 | 2006 | // :93:37: note: when computing vector element at index '0' |
| 2009 | 2007 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2010 | 2008 | // :93:37: note: when computing vector element at index '0' |
| 2011 | 2009 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2010 | // :93:37: note: when computing vector element at index '0' | |
| 2012 | 2011 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2013 | 2012 | // :93:37: note: when computing vector element at index '0' |
| 2014 | 2013 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2015 | 2014 | // :93:37: note: when computing vector element at index '0' |
| 2016 | 2015 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2017 | // :93:37: note: when computing vector element at index '1' | |
| 2016 | // :93:37: note: when computing vector element at index '0' | |
| 2018 | 2017 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2019 | 2018 | // :93:37: note: when computing vector element at index '0' |
| 2020 | 2019 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2021 | 2020 | // :93:37: note: when computing vector element at index '0' |
| 2022 | 2021 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2022 | // :93:37: note: when computing vector element at index '1' | |
| 2023 | 2023 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2024 | // :93:37: note: when computing vector element at index '0' | |
| 2024 | // :93:37: note: when computing vector element at index '1' | |
| 2025 | 2025 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2026 | // :93:37: note: when computing vector element at index '0' | |
| 2026 | // :93:37: note: when computing vector element at index '1' | |
| 2027 | 2027 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2028 | 2028 | // :93:37: note: when computing vector element at index '1' |
| 2029 | 2029 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2030 | // :93:37: note: when computing vector element at index '0' | |
| 2030 | // :93:37: note: when computing vector element at index '1' | |
| 2031 | 2031 | // :93:37: error: use of undefined value here causes illegal behavior |
| 2032 | // :93:37: note: when computing vector element at index '0' | |
| 2032 | // :93:37: note: when computing vector element at index '1' | |
| 2033 | 2033 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2034 | 2034 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2035 | // :96:17: note: when computing vector element at index '0' | |
| 2036 | 2035 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2037 | // :96:17: note: when computing vector element at index '0' | |
| 2038 | 2036 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2039 | // :96:17: note: when computing vector element at index '0' | |
| 2040 | 2037 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2041 | // :96:17: note: when computing vector element at index '1' | |
| 2042 | 2038 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2043 | // :96:17: note: when computing vector element at index '0' | |
| 2044 | 2039 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2045 | 2040 | // :96:17: note: when computing vector element at index '0' |
| 2046 | 2041 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2047 | 2042 | // :96:17: note: when computing vector element at index '0' |
| 2048 | 2043 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2049 | // :96:17: error: use of undefined value here causes illegal behavior | |
| 2050 | 2044 | // :96:17: note: when computing vector element at index '0' |
| 2051 | 2045 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2052 | 2046 | // :96:17: note: when computing vector element at index '0' |
| 2053 | 2047 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2054 | 2048 | // :96:17: note: when computing vector element at index '0' |
| 2055 | 2049 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2056 | // :96:17: note: when computing vector element at index '1' | |
| 2057 | // :96:17: error: use of undefined value here causes illegal behavior | |
| 2058 | 2050 | // :96:17: note: when computing vector element at index '0' |
| 2059 | 2051 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2060 | 2052 | // :96:17: note: when computing vector element at index '0' |
| 2061 | 2053 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2062 | 2054 | // :96:17: note: when computing vector element at index '0' |
| 2063 | 2055 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2056 | // :96:17: note: when computing vector element at index '0' | |
| 2064 | 2057 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2065 | 2058 | // :96:17: note: when computing vector element at index '0' |
| 2066 | 2059 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2068,7 +2061,7 @@ const std = @import("std"); |
| 2068 | 2061 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2069 | 2062 | // :96:17: note: when computing vector element at index '0' |
| 2070 | 2063 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2071 | // :96:17: note: when computing vector element at index '1' | |
| 2064 | // :96:17: note: when computing vector element at index '0' | |
| 2072 | 2065 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2073 | 2066 | // :96:17: note: when computing vector element at index '0' |
| 2074 | 2067 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2076,6 +2069,7 @@ const std = @import("std"); |
| 2076 | 2069 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2077 | 2070 | // :96:17: note: when computing vector element at index '0' |
| 2078 | 2071 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2072 | // :96:17: note: when computing vector element at index '0' | |
| 2079 | 2073 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2080 | 2074 | // :96:17: note: when computing vector element at index '0' |
| 2081 | 2075 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2083,7 +2077,7 @@ const std = @import("std"); |
| 2083 | 2077 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2084 | 2078 | // :96:17: note: when computing vector element at index '0' |
| 2085 | 2079 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2086 | // :96:17: note: when computing vector element at index '1' | |
| 2080 | // :96:17: note: when computing vector element at index '0' | |
| 2087 | 2081 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2088 | 2082 | // :96:17: note: when computing vector element at index '0' |
| 2089 | 2083 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2091,6 +2085,7 @@ const std = @import("std"); |
| 2091 | 2085 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2092 | 2086 | // :96:17: note: when computing vector element at index '0' |
| 2093 | 2087 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2088 | // :96:17: note: when computing vector element at index '0' | |
| 2094 | 2089 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2095 | 2090 | // :96:17: note: when computing vector element at index '0' |
| 2096 | 2091 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2098,7 +2093,7 @@ const std = @import("std"); |
| 2098 | 2093 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2099 | 2094 | // :96:17: note: when computing vector element at index '0' |
| 2100 | 2095 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2101 | // :96:17: note: when computing vector element at index '1' | |
| 2096 | // :96:17: note: when computing vector element at index '0' | |
| 2102 | 2097 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2103 | 2098 | // :96:17: note: when computing vector element at index '0' |
| 2104 | 2099 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2106,6 +2101,7 @@ const std = @import("std"); |
| 2106 | 2101 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2107 | 2102 | // :96:17: note: when computing vector element at index '0' |
| 2108 | 2103 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2104 | // :96:17: note: when computing vector element at index '0' | |
| 2109 | 2105 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2110 | 2106 | // :96:17: note: when computing vector element at index '0' |
| 2111 | 2107 | // :96:17: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2115,67 +2111,65 @@ const std = @import("std"); |
| 2115 | 2111 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2116 | 2112 | // :96:17: note: when computing vector element at index '1' |
| 2117 | 2113 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2118 | // :96:17: note: when computing vector element at index '0' | |
| 2114 | // :96:17: note: when computing vector element at index '1' | |
| 2119 | 2115 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2120 | // :96:17: note: when computing vector element at index '0' | |
| 2116 | // :96:17: note: when computing vector element at index '1' | |
| 2121 | 2117 | // :96:17: error: use of undefined value here causes illegal behavior |
| 2122 | // :96:17: note: when computing vector element at index '0' | |
| 2123 | // :96:22: error: use of undefined value here causes illegal behavior | |
| 2124 | // :96:22: error: use of undefined value here causes illegal behavior | |
| 2125 | // :96:22: note: when computing vector element at index '0' | |
| 2118 | // :96:17: note: when computing vector element at index '1' | |
| 2119 | // :96:17: error: use of undefined value here causes illegal behavior | |
| 2120 | // :96:17: note: when computing vector element at index '1' | |
| 2121 | // :96:17: error: use of undefined value here causes illegal behavior | |
| 2122 | // :96:17: note: when computing vector element at index '1' | |
| 2126 | 2123 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2127 | // :96:22: note: when computing vector element at index '0' | |
| 2128 | 2124 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2129 | // :96:22: note: when computing vector element at index '1' | |
| 2130 | 2125 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2131 | // :96:22: note: when computing vector element at index '0' | |
| 2132 | 2126 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2133 | // :96:22: note: when computing vector element at index '0' | |
| 2134 | 2127 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2135 | 2128 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2136 | // :96:22: note: when computing vector element at index '0' | |
| 2137 | 2129 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2138 | 2130 | // :96:22: note: when computing vector element at index '0' |
| 2139 | 2131 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2140 | // :96:22: note: when computing vector element at index '1' | |
| 2141 | // :96:22: error: use of undefined value here causes illegal behavior | |
| 2142 | 2132 | // :96:22: note: when computing vector element at index '0' |
| 2143 | 2133 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2144 | 2134 | // :96:22: note: when computing vector element at index '0' |
| 2145 | 2135 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2136 | // :96:22: note: when computing vector element at index '0' | |
| 2146 | 2137 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2147 | 2138 | // :96:22: note: when computing vector element at index '0' |
| 2148 | 2139 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2149 | 2140 | // :96:22: note: when computing vector element at index '0' |
| 2150 | 2141 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2151 | // :96:22: note: when computing vector element at index '1' | |
| 2142 | // :96:22: note: when computing vector element at index '0' | |
| 2152 | 2143 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2153 | 2144 | // :96:22: note: when computing vector element at index '0' |
| 2154 | 2145 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2155 | 2146 | // :96:22: note: when computing vector element at index '0' |
| 2156 | 2147 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2148 | // :96:22: note: when computing vector element at index '0' | |
| 2157 | 2149 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2158 | 2150 | // :96:22: note: when computing vector element at index '0' |
| 2159 | 2151 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2160 | 2152 | // :96:22: note: when computing vector element at index '0' |
| 2161 | 2153 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2162 | // :96:22: note: when computing vector element at index '1' | |
| 2154 | // :96:22: note: when computing vector element at index '0' | |
| 2163 | 2155 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2164 | 2156 | // :96:22: note: when computing vector element at index '0' |
| 2165 | 2157 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2166 | 2158 | // :96:22: note: when computing vector element at index '0' |
| 2167 | 2159 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2160 | // :96:22: note: when computing vector element at index '0' | |
| 2168 | 2161 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2169 | 2162 | // :96:22: note: when computing vector element at index '0' |
| 2170 | 2163 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2171 | 2164 | // :96:22: note: when computing vector element at index '0' |
| 2172 | 2165 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2173 | // :96:22: note: when computing vector element at index '1' | |
| 2166 | // :96:22: note: when computing vector element at index '0' | |
| 2174 | 2167 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2175 | 2168 | // :96:22: note: when computing vector element at index '0' |
| 2176 | 2169 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2177 | 2170 | // :96:22: note: when computing vector element at index '0' |
| 2178 | 2171 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2172 | // :96:22: note: when computing vector element at index '0' | |
| 2179 | 2173 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2180 | 2174 | // :96:22: note: when computing vector element at index '0' |
| 2181 | 2175 | // :96:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2183,40 +2177,39 @@ const std = @import("std"); |
| 2183 | 2177 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2184 | 2178 | // :96:22: note: when computing vector element at index '1' |
| 2185 | 2179 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2186 | // :96:22: note: when computing vector element at index '0' | |
| 2180 | // :96:22: note: when computing vector element at index '1' | |
| 2187 | 2181 | // :96:22: error: use of undefined value here causes illegal behavior |
| 2188 | // :96:22: note: when computing vector element at index '0' | |
| 2182 | // :96:22: note: when computing vector element at index '1' | |
| 2183 | // :96:22: error: use of undefined value here causes illegal behavior | |
| 2184 | // :96:22: note: when computing vector element at index '1' | |
| 2185 | // :96:22: error: use of undefined value here causes illegal behavior | |
| 2186 | // :96:22: note: when computing vector element at index '1' | |
| 2187 | // :96:22: error: use of undefined value here causes illegal behavior | |
| 2188 | // :96:22: note: when computing vector element at index '1' | |
| 2189 | 2189 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2190 | 2190 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2191 | // :99:27: note: when computing vector element at index '0' | |
| 2192 | 2191 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2193 | // :99:27: note: when computing vector element at index '0' | |
| 2194 | 2192 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2195 | // :99:27: note: when computing vector element at index '0' | |
| 2196 | 2193 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2197 | // :99:27: note: when computing vector element at index '1' | |
| 2198 | 2194 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2199 | // :99:27: note: when computing vector element at index '0' | |
| 2200 | 2195 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2201 | 2196 | // :99:27: note: when computing vector element at index '0' |
| 2202 | 2197 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2203 | 2198 | // :99:27: note: when computing vector element at index '0' |
| 2204 | 2199 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2205 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2206 | 2200 | // :99:27: note: when computing vector element at index '0' |
| 2207 | 2201 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2208 | 2202 | // :99:27: note: when computing vector element at index '0' |
| 2209 | 2203 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2210 | 2204 | // :99:27: note: when computing vector element at index '0' |
| 2211 | 2205 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2212 | // :99:27: note: when computing vector element at index '1' | |
| 2213 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2214 | 2206 | // :99:27: note: when computing vector element at index '0' |
| 2215 | 2207 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2216 | 2208 | // :99:27: note: when computing vector element at index '0' |
| 2217 | 2209 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2218 | 2210 | // :99:27: note: when computing vector element at index '0' |
| 2219 | 2211 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2212 | // :99:27: note: when computing vector element at index '0' | |
| 2220 | 2213 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2221 | 2214 | // :99:27: note: when computing vector element at index '0' |
| 2222 | 2215 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2224,7 +2217,7 @@ const std = @import("std"); |
| 2224 | 2217 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2225 | 2218 | // :99:27: note: when computing vector element at index '0' |
| 2226 | 2219 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2227 | // :99:27: note: when computing vector element at index '1' | |
| 2220 | // :99:27: note: when computing vector element at index '0' | |
| 2228 | 2221 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2229 | 2222 | // :99:27: note: when computing vector element at index '0' |
| 2230 | 2223 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2232,6 +2225,7 @@ const std = @import("std"); |
| 2232 | 2225 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2233 | 2226 | // :99:27: note: when computing vector element at index '0' |
| 2234 | 2227 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2228 | // :99:27: note: when computing vector element at index '0' | |
| 2235 | 2229 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2236 | 2230 | // :99:27: note: when computing vector element at index '0' |
| 2237 | 2231 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2239,7 +2233,7 @@ const std = @import("std"); |
| 2239 | 2233 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2240 | 2234 | // :99:27: note: when computing vector element at index '0' |
| 2241 | 2235 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2242 | // :99:27: note: when computing vector element at index '1' | |
| 2236 | // :99:27: note: when computing vector element at index '0' | |
| 2243 | 2237 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2244 | 2238 | // :99:27: note: when computing vector element at index '0' |
| 2245 | 2239 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2247,6 +2241,7 @@ const std = @import("std"); |
| 2247 | 2241 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2248 | 2242 | // :99:27: note: when computing vector element at index '0' |
| 2249 | 2243 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2244 | // :99:27: note: when computing vector element at index '0' | |
| 2250 | 2245 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2251 | 2246 | // :99:27: note: when computing vector element at index '0' |
| 2252 | 2247 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2254,7 +2249,7 @@ const std = @import("std"); |
| 2254 | 2249 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2255 | 2250 | // :99:27: note: when computing vector element at index '0' |
| 2256 | 2251 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2257 | // :99:27: note: when computing vector element at index '1' | |
| 2252 | // :99:27: note: when computing vector element at index '0' | |
| 2258 | 2253 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2259 | 2254 | // :99:27: note: when computing vector element at index '0' |
| 2260 | 2255 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2262,6 +2257,7 @@ const std = @import("std"); |
| 2262 | 2257 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2263 | 2258 | // :99:27: note: when computing vector element at index '0' |
| 2264 | 2259 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2260 | // :99:27: note: when computing vector element at index '0' | |
| 2265 | 2261 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2266 | 2262 | // :99:27: note: when computing vector element at index '0' |
| 2267 | 2263 | // :99:27: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2271,77 +2267,81 @@ const std = @import("std"); |
| 2271 | 2267 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2272 | 2268 | // :99:27: note: when computing vector element at index '1' |
| 2273 | 2269 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2274 | // :99:27: note: when computing vector element at index '0' | |
| 2270 | // :99:27: note: when computing vector element at index '1' | |
| 2275 | 2271 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2276 | // :99:27: note: when computing vector element at index '0' | |
| 2272 | // :99:27: note: when computing vector element at index '1' | |
| 2277 | 2273 | // :99:27: error: use of undefined value here causes illegal behavior |
| 2278 | // :99:27: note: when computing vector element at index '0' | |
| 2274 | // :99:27: note: when computing vector element at index '1' | |
| 2275 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2276 | // :99:27: note: when computing vector element at index '1' | |
| 2277 | // :99:27: error: use of undefined value here causes illegal behavior | |
| 2278 | // :99:27: note: when computing vector element at index '1' | |
| 2279 | 2279 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2280 | 2280 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2281 | // :99:30: note: when computing vector element at index '0' | |
| 2282 | 2281 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2283 | // :99:30: note: when computing vector element at index '0' | |
| 2284 | 2282 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2285 | // :99:30: note: when computing vector element at index '1' | |
| 2286 | 2283 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2287 | // :99:30: note: when computing vector element at index '0' | |
| 2288 | 2284 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2289 | // :99:30: note: when computing vector element at index '0' | |
| 2290 | 2285 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2286 | // :99:30: note: when computing vector element at index '0' | |
| 2291 | 2287 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2292 | 2288 | // :99:30: note: when computing vector element at index '0' |
| 2293 | 2289 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2294 | 2290 | // :99:30: note: when computing vector element at index '0' |
| 2295 | 2291 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2296 | // :99:30: note: when computing vector element at index '1' | |
| 2292 | // :99:30: note: when computing vector element at index '0' | |
| 2297 | 2293 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2298 | 2294 | // :99:30: note: when computing vector element at index '0' |
| 2299 | 2295 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2300 | 2296 | // :99:30: note: when computing vector element at index '0' |
| 2301 | 2297 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2298 | // :99:30: note: when computing vector element at index '0' | |
| 2302 | 2299 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2303 | 2300 | // :99:30: note: when computing vector element at index '0' |
| 2304 | 2301 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2305 | 2302 | // :99:30: note: when computing vector element at index '0' |
| 2306 | 2303 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2307 | // :99:30: note: when computing vector element at index '1' | |
| 2304 | // :99:30: note: when computing vector element at index '0' | |
| 2308 | 2305 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2309 | 2306 | // :99:30: note: when computing vector element at index '0' |
| 2310 | 2307 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2311 | 2308 | // :99:30: note: when computing vector element at index '0' |
| 2312 | 2309 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2310 | // :99:30: note: when computing vector element at index '0' | |
| 2313 | 2311 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2314 | 2312 | // :99:30: note: when computing vector element at index '0' |
| 2315 | 2313 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2316 | 2314 | // :99:30: note: when computing vector element at index '0' |
| 2317 | 2315 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2318 | // :99:30: note: when computing vector element at index '1' | |
| 2316 | // :99:30: note: when computing vector element at index '0' | |
| 2319 | 2317 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2320 | 2318 | // :99:30: note: when computing vector element at index '0' |
| 2321 | 2319 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2322 | 2320 | // :99:30: note: when computing vector element at index '0' |
| 2323 | 2321 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2322 | // :99:30: note: when computing vector element at index '0' | |
| 2324 | 2323 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2325 | 2324 | // :99:30: note: when computing vector element at index '0' |
| 2326 | 2325 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2327 | 2326 | // :99:30: note: when computing vector element at index '0' |
| 2328 | 2327 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2329 | // :99:30: note: when computing vector element at index '1' | |
| 2328 | // :99:30: note: when computing vector element at index '0' | |
| 2330 | 2329 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2331 | 2330 | // :99:30: note: when computing vector element at index '0' |
| 2332 | 2331 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2333 | 2332 | // :99:30: note: when computing vector element at index '0' |
| 2334 | 2333 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2334 | // :99:30: note: when computing vector element at index '1' | |
| 2335 | 2335 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2336 | // :99:30: note: when computing vector element at index '0' | |
| 2336 | // :99:30: note: when computing vector element at index '1' | |
| 2337 | 2337 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2338 | // :99:30: note: when computing vector element at index '0' | |
| 2338 | // :99:30: note: when computing vector element at index '1' | |
| 2339 | 2339 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2340 | 2340 | // :99:30: note: when computing vector element at index '1' |
| 2341 | 2341 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2342 | // :99:30: note: when computing vector element at index '0' | |
| 2342 | // :99:30: note: when computing vector element at index '1' | |
| 2343 | 2343 | // :99:30: error: use of undefined value here causes illegal behavior |
| 2344 | // :99:30: note: when computing vector element at index '0' | |
| 2344 | // :99:30: note: when computing vector element at index '1' | |
| 2345 | 2345 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2346 | 2346 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2347 | 2347 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2349,21 +2349,13 @@ const std = @import("std"); |
| 2349 | 2349 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2350 | 2350 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2351 | 2351 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2352 | // :104:22: note: when computing vector element at index '1' | |
| 2353 | 2352 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2354 | // :104:22: note: when computing vector element at index '1' | |
| 2355 | 2353 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2356 | // :104:22: note: when computing vector element at index '1' | |
| 2357 | 2354 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2358 | // :104:22: note: when computing vector element at index '1' | |
| 2359 | 2355 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2360 | // :104:22: note: when computing vector element at index '0' | |
| 2361 | 2356 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2362 | // :104:22: note: when computing vector element at index '0' | |
| 2363 | 2357 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2364 | // :104:22: note: when computing vector element at index '0' | |
| 2365 | 2358 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2366 | // :104:22: note: when computing vector element at index '0' | |
| 2367 | 2359 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2368 | 2360 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2369 | 2361 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2371,21 +2363,13 @@ const std = @import("std"); |
| 2371 | 2363 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2372 | 2364 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2373 | 2365 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2374 | // :104:22: note: when computing vector element at index '1' | |
| 2375 | 2366 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2376 | // :104:22: note: when computing vector element at index '1' | |
| 2377 | 2367 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2378 | // :104:22: note: when computing vector element at index '1' | |
| 2379 | 2368 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2380 | // :104:22: note: when computing vector element at index '1' | |
| 2381 | 2369 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2382 | // :104:22: note: when computing vector element at index '0' | |
| 2383 | 2370 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2384 | // :104:22: note: when computing vector element at index '0' | |
| 2385 | 2371 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2386 | // :104:22: note: when computing vector element at index '0' | |
| 2387 | 2372 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2388 | // :104:22: note: when computing vector element at index '0' | |
| 2389 | 2373 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2390 | 2374 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2391 | 2375 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2393,13 +2377,11 @@ const std = @import("std"); |
| 2393 | 2377 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2394 | 2378 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2395 | 2379 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2396 | // :104:22: note: when computing vector element at index '1' | |
| 2397 | 2380 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2398 | // :104:22: note: when computing vector element at index '1' | |
| 2399 | 2381 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2400 | // :104:22: note: when computing vector element at index '1' | |
| 2382 | // :104:22: note: when computing vector element at index '0' | |
| 2401 | 2383 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2402 | // :104:22: note: when computing vector element at index '1' | |
| 2384 | // :104:22: note: when computing vector element at index '0' | |
| 2403 | 2385 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2404 | 2386 | // :104:22: note: when computing vector element at index '0' |
| 2405 | 2387 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2409,19 +2391,25 @@ const std = @import("std"); |
| 2409 | 2391 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2410 | 2392 | // :104:22: note: when computing vector element at index '0' |
| 2411 | 2393 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2394 | // :104:22: note: when computing vector element at index '0' | |
| 2412 | 2395 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2396 | // :104:22: note: when computing vector element at index '0' | |
| 2413 | 2397 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2398 | // :104:22: note: when computing vector element at index '0' | |
| 2414 | 2399 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2400 | // :104:22: note: when computing vector element at index '0' | |
| 2415 | 2401 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2402 | // :104:22: note: when computing vector element at index '0' | |
| 2416 | 2403 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2404 | // :104:22: note: when computing vector element at index '0' | |
| 2417 | 2405 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2418 | // :104:22: note: when computing vector element at index '1' | |
| 2406 | // :104:22: note: when computing vector element at index '0' | |
| 2419 | 2407 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2420 | // :104:22: note: when computing vector element at index '1' | |
| 2408 | // :104:22: note: when computing vector element at index '0' | |
| 2421 | 2409 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2422 | // :104:22: note: when computing vector element at index '1' | |
| 2410 | // :104:22: note: when computing vector element at index '0' | |
| 2423 | 2411 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2424 | // :104:22: note: when computing vector element at index '1' | |
| 2412 | // :104:22: note: when computing vector element at index '0' | |
| 2425 | 2413 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2426 | 2414 | // :104:22: note: when computing vector element at index '0' |
| 2427 | 2415 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2431,11 +2419,17 @@ const std = @import("std"); |
| 2431 | 2419 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2432 | 2420 | // :104:22: note: when computing vector element at index '0' |
| 2433 | 2421 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2422 | // :104:22: note: when computing vector element at index '0' | |
| 2434 | 2423 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2424 | // :104:22: note: when computing vector element at index '0' | |
| 2435 | 2425 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2426 | // :104:22: note: when computing vector element at index '0' | |
| 2436 | 2427 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2428 | // :104:22: note: when computing vector element at index '0' | |
| 2437 | 2429 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2430 | // :104:22: note: when computing vector element at index '1' | |
| 2438 | 2431 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2432 | // :104:22: note: when computing vector element at index '1' | |
| 2439 | 2433 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2440 | 2434 | // :104:22: note: when computing vector element at index '1' |
| 2441 | 2435 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2445,19 +2439,25 @@ const std = @import("std"); |
| 2445 | 2439 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2446 | 2440 | // :104:22: note: when computing vector element at index '1' |
| 2447 | 2441 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2448 | // :104:22: note: when computing vector element at index '0' | |
| 2442 | // :104:22: note: when computing vector element at index '1' | |
| 2449 | 2443 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2450 | // :104:22: note: when computing vector element at index '0' | |
| 2444 | // :104:22: note: when computing vector element at index '1' | |
| 2451 | 2445 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2452 | // :104:22: note: when computing vector element at index '0' | |
| 2446 | // :104:22: note: when computing vector element at index '1' | |
| 2453 | 2447 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2454 | // :104:22: note: when computing vector element at index '0' | |
| 2448 | // :104:22: note: when computing vector element at index '1' | |
| 2455 | 2449 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2450 | // :104:22: note: when computing vector element at index '1' | |
| 2456 | 2451 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2452 | // :104:22: note: when computing vector element at index '1' | |
| 2457 | 2453 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2454 | // :104:22: note: when computing vector element at index '1' | |
| 2458 | 2455 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2456 | // :104:22: note: when computing vector element at index '1' | |
| 2459 | 2457 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2458 | // :104:22: note: when computing vector element at index '1' | |
| 2460 | 2459 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2460 | // :104:22: note: when computing vector element at index '1' | |
| 2461 | 2461 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2462 | 2462 | // :104:22: note: when computing vector element at index '1' |
| 2463 | 2463 | // :104:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2467,13 +2467,13 @@ const std = @import("std"); |
| 2467 | 2467 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2468 | 2468 | // :104:22: note: when computing vector element at index '1' |
| 2469 | 2469 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2470 | // :104:22: note: when computing vector element at index '0' | |
| 2470 | // :104:22: note: when computing vector element at index '1' | |
| 2471 | 2471 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2472 | // :104:22: note: when computing vector element at index '0' | |
| 2472 | // :104:22: note: when computing vector element at index '1' | |
| 2473 | 2473 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2474 | // :104:22: note: when computing vector element at index '0' | |
| 2474 | // :104:22: note: when computing vector element at index '1' | |
| 2475 | 2475 | // :104:22: error: use of undefined value here causes illegal behavior |
| 2476 | // :104:22: note: when computing vector element at index '0' | |
| 2476 | // :104:22: note: when computing vector element at index '1' | |
| 2477 | 2477 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2478 | 2478 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2479 | 2479 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2481,21 +2481,13 @@ const std = @import("std"); |
| 2481 | 2481 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2482 | 2482 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2483 | 2483 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2484 | // :107:30: note: when computing vector element at index '1' | |
| 2485 | 2484 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2486 | // :107:30: note: when computing vector element at index '1' | |
| 2487 | 2485 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2488 | // :107:30: note: when computing vector element at index '1' | |
| 2489 | 2486 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2490 | // :107:30: note: when computing vector element at index '1' | |
| 2491 | 2487 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2492 | // :107:30: note: when computing vector element at index '0' | |
| 2493 | 2488 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2494 | // :107:30: note: when computing vector element at index '0' | |
| 2495 | 2489 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2496 | // :107:30: note: when computing vector element at index '0' | |
| 2497 | 2490 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2498 | // :107:30: note: when computing vector element at index '0' | |
| 2499 | 2491 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2500 | 2492 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2501 | 2493 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2503,21 +2495,13 @@ const std = @import("std"); |
| 2503 | 2495 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2504 | 2496 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2505 | 2497 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2506 | // :107:30: note: when computing vector element at index '1' | |
| 2507 | 2498 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2508 | // :107:30: note: when computing vector element at index '1' | |
| 2509 | 2499 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2510 | // :107:30: note: when computing vector element at index '1' | |
| 2511 | 2500 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2512 | // :107:30: note: when computing vector element at index '1' | |
| 2513 | 2501 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2514 | // :107:30: note: when computing vector element at index '0' | |
| 2515 | 2502 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2516 | // :107:30: note: when computing vector element at index '0' | |
| 2517 | 2503 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2518 | // :107:30: note: when computing vector element at index '0' | |
| 2519 | 2504 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2520 | // :107:30: note: when computing vector element at index '0' | |
| 2521 | 2505 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2522 | 2506 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2523 | 2507 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2525,13 +2509,11 @@ const std = @import("std"); |
| 2525 | 2509 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2526 | 2510 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2527 | 2511 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2528 | // :107:30: note: when computing vector element at index '1' | |
| 2529 | 2512 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2530 | // :107:30: note: when computing vector element at index '1' | |
| 2531 | 2513 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2532 | // :107:30: note: when computing vector element at index '1' | |
| 2514 | // :107:30: note: when computing vector element at index '0' | |
| 2533 | 2515 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2534 | // :107:30: note: when computing vector element at index '1' | |
| 2516 | // :107:30: note: when computing vector element at index '0' | |
| 2535 | 2517 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2536 | 2518 | // :107:30: note: when computing vector element at index '0' |
| 2537 | 2519 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2541,19 +2523,25 @@ const std = @import("std"); |
| 2541 | 2523 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2542 | 2524 | // :107:30: note: when computing vector element at index '0' |
| 2543 | 2525 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2526 | // :107:30: note: when computing vector element at index '0' | |
| 2544 | 2527 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2528 | // :107:30: note: when computing vector element at index '0' | |
| 2545 | 2529 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2530 | // :107:30: note: when computing vector element at index '0' | |
| 2546 | 2531 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2532 | // :107:30: note: when computing vector element at index '0' | |
| 2547 | 2533 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2534 | // :107:30: note: when computing vector element at index '0' | |
| 2548 | 2535 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2536 | // :107:30: note: when computing vector element at index '0' | |
| 2549 | 2537 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2550 | // :107:30: note: when computing vector element at index '1' | |
| 2538 | // :107:30: note: when computing vector element at index '0' | |
| 2551 | 2539 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2552 | // :107:30: note: when computing vector element at index '1' | |
| 2540 | // :107:30: note: when computing vector element at index '0' | |
| 2553 | 2541 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2554 | // :107:30: note: when computing vector element at index '1' | |
| 2542 | // :107:30: note: when computing vector element at index '0' | |
| 2555 | 2543 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2556 | // :107:30: note: when computing vector element at index '1' | |
| 2544 | // :107:30: note: when computing vector element at index '0' | |
| 2557 | 2545 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2558 | 2546 | // :107:30: note: when computing vector element at index '0' |
| 2559 | 2547 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2563,11 +2551,17 @@ const std = @import("std"); |
| 2563 | 2551 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2564 | 2552 | // :107:30: note: when computing vector element at index '0' |
| 2565 | 2553 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2554 | // :107:30: note: when computing vector element at index '0' | |
| 2566 | 2555 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2556 | // :107:30: note: when computing vector element at index '0' | |
| 2567 | 2557 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2558 | // :107:30: note: when computing vector element at index '0' | |
| 2568 | 2559 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2560 | // :107:30: note: when computing vector element at index '0' | |
| 2569 | 2561 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2562 | // :107:30: note: when computing vector element at index '1' | |
| 2570 | 2563 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2564 | // :107:30: note: when computing vector element at index '1' | |
| 2571 | 2565 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2572 | 2566 | // :107:30: note: when computing vector element at index '1' |
| 2573 | 2567 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2577,19 +2571,25 @@ const std = @import("std"); |
| 2577 | 2571 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2578 | 2572 | // :107:30: note: when computing vector element at index '1' |
| 2579 | 2573 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2580 | // :107:30: note: when computing vector element at index '0' | |
| 2574 | // :107:30: note: when computing vector element at index '1' | |
| 2581 | 2575 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2582 | // :107:30: note: when computing vector element at index '0' | |
| 2576 | // :107:30: note: when computing vector element at index '1' | |
| 2583 | 2577 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2584 | // :107:30: note: when computing vector element at index '0' | |
| 2578 | // :107:30: note: when computing vector element at index '1' | |
| 2585 | 2579 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2586 | // :107:30: note: when computing vector element at index '0' | |
| 2580 | // :107:30: note: when computing vector element at index '1' | |
| 2587 | 2581 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2582 | // :107:30: note: when computing vector element at index '1' | |
| 2588 | 2583 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2584 | // :107:30: note: when computing vector element at index '1' | |
| 2589 | 2585 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2586 | // :107:30: note: when computing vector element at index '1' | |
| 2590 | 2587 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2588 | // :107:30: note: when computing vector element at index '1' | |
| 2591 | 2589 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2590 | // :107:30: note: when computing vector element at index '1' | |
| 2592 | 2591 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2592 | // :107:30: note: when computing vector element at index '1' | |
| 2593 | 2593 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2594 | 2594 | // :107:30: note: when computing vector element at index '1' |
| 2595 | 2595 | // :107:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2599,13 +2599,13 @@ const std = @import("std"); |
| 2599 | 2599 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2600 | 2600 | // :107:30: note: when computing vector element at index '1' |
| 2601 | 2601 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2602 | // :107:30: note: when computing vector element at index '0' | |
| 2602 | // :107:30: note: when computing vector element at index '1' | |
| 2603 | 2603 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2604 | // :107:30: note: when computing vector element at index '0' | |
| 2604 | // :107:30: note: when computing vector element at index '1' | |
| 2605 | 2605 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2606 | // :107:30: note: when computing vector element at index '0' | |
| 2606 | // :107:30: note: when computing vector element at index '1' | |
| 2607 | 2607 | // :107:30: error: use of undefined value here causes illegal behavior |
| 2608 | // :107:30: note: when computing vector element at index '0' | |
| 2608 | // :107:30: note: when computing vector element at index '1' | |
| 2609 | 2609 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2610 | 2610 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2611 | 2611 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2613,21 +2613,13 @@ const std = @import("std"); |
| 2613 | 2613 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2614 | 2614 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2615 | 2615 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2616 | // :110:37: note: when computing vector element at index '1' | |
| 2617 | 2616 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2618 | // :110:37: note: when computing vector element at index '1' | |
| 2619 | 2617 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2620 | // :110:37: note: when computing vector element at index '1' | |
| 2621 | 2618 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2622 | // :110:37: note: when computing vector element at index '1' | |
| 2623 | 2619 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2624 | // :110:37: note: when computing vector element at index '0' | |
| 2625 | 2620 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2626 | // :110:37: note: when computing vector element at index '0' | |
| 2627 | 2621 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2628 | // :110:37: note: when computing vector element at index '0' | |
| 2629 | 2622 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2630 | // :110:37: note: when computing vector element at index '0' | |
| 2631 | 2623 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2632 | 2624 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2633 | 2625 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2635,21 +2627,13 @@ const std = @import("std"); |
| 2635 | 2627 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2636 | 2628 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2637 | 2629 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2638 | // :110:37: note: when computing vector element at index '1' | |
| 2639 | 2630 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2640 | // :110:37: note: when computing vector element at index '1' | |
| 2641 | 2631 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2642 | // :110:37: note: when computing vector element at index '1' | |
| 2643 | 2632 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2644 | // :110:37: note: when computing vector element at index '1' | |
| 2645 | 2633 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2646 | // :110:37: note: when computing vector element at index '0' | |
| 2647 | 2634 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2648 | // :110:37: note: when computing vector element at index '0' | |
| 2649 | 2635 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2650 | // :110:37: note: when computing vector element at index '0' | |
| 2651 | 2636 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2652 | // :110:37: note: when computing vector element at index '0' | |
| 2653 | 2637 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2654 | 2638 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2655 | 2639 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2657,13 +2641,11 @@ const std = @import("std"); |
| 2657 | 2641 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2658 | 2642 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2659 | 2643 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2660 | // :110:37: note: when computing vector element at index '1' | |
| 2661 | 2644 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2662 | // :110:37: note: when computing vector element at index '1' | |
| 2663 | 2645 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2664 | // :110:37: note: when computing vector element at index '1' | |
| 2646 | // :110:37: note: when computing vector element at index '0' | |
| 2665 | 2647 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2666 | // :110:37: note: when computing vector element at index '1' | |
| 2648 | // :110:37: note: when computing vector element at index '0' | |
| 2667 | 2649 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2668 | 2650 | // :110:37: note: when computing vector element at index '0' |
| 2669 | 2651 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2673,19 +2655,25 @@ const std = @import("std"); |
| 2673 | 2655 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2674 | 2656 | // :110:37: note: when computing vector element at index '0' |
| 2675 | 2657 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2658 | // :110:37: note: when computing vector element at index '0' | |
| 2676 | 2659 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2660 | // :110:37: note: when computing vector element at index '0' | |
| 2677 | 2661 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2662 | // :110:37: note: when computing vector element at index '0' | |
| 2678 | 2663 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2664 | // :110:37: note: when computing vector element at index '0' | |
| 2679 | 2665 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2666 | // :110:37: note: when computing vector element at index '0' | |
| 2680 | 2667 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2668 | // :110:37: note: when computing vector element at index '0' | |
| 2681 | 2669 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2682 | // :110:37: note: when computing vector element at index '1' | |
| 2670 | // :110:37: note: when computing vector element at index '0' | |
| 2683 | 2671 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2684 | // :110:37: note: when computing vector element at index '1' | |
| 2672 | // :110:37: note: when computing vector element at index '0' | |
| 2685 | 2673 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2686 | // :110:37: note: when computing vector element at index '1' | |
| 2674 | // :110:37: note: when computing vector element at index '0' | |
| 2687 | 2675 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2688 | // :110:37: note: when computing vector element at index '1' | |
| 2676 | // :110:37: note: when computing vector element at index '0' | |
| 2689 | 2677 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2690 | 2678 | // :110:37: note: when computing vector element at index '0' |
| 2691 | 2679 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2695,11 +2683,17 @@ const std = @import("std"); |
| 2695 | 2683 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2696 | 2684 | // :110:37: note: when computing vector element at index '0' |
| 2697 | 2685 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2686 | // :110:37: note: when computing vector element at index '0' | |
| 2698 | 2687 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2688 | // :110:37: note: when computing vector element at index '0' | |
| 2699 | 2689 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2690 | // :110:37: note: when computing vector element at index '0' | |
| 2700 | 2691 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2692 | // :110:37: note: when computing vector element at index '0' | |
| 2701 | 2693 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2694 | // :110:37: note: when computing vector element at index '1' | |
| 2702 | 2695 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2696 | // :110:37: note: when computing vector element at index '1' | |
| 2703 | 2697 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2704 | 2698 | // :110:37: note: when computing vector element at index '1' |
| 2705 | 2699 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2709,19 +2703,25 @@ const std = @import("std"); |
| 2709 | 2703 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2710 | 2704 | // :110:37: note: when computing vector element at index '1' |
| 2711 | 2705 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2712 | // :110:37: note: when computing vector element at index '0' | |
| 2706 | // :110:37: note: when computing vector element at index '1' | |
| 2713 | 2707 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2714 | // :110:37: note: when computing vector element at index '0' | |
| 2708 | // :110:37: note: when computing vector element at index '1' | |
| 2715 | 2709 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2716 | // :110:37: note: when computing vector element at index '0' | |
| 2710 | // :110:37: note: when computing vector element at index '1' | |
| 2717 | 2711 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2718 | // :110:37: note: when computing vector element at index '0' | |
| 2712 | // :110:37: note: when computing vector element at index '1' | |
| 2719 | 2713 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2714 | // :110:37: note: when computing vector element at index '1' | |
| 2720 | 2715 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2716 | // :110:37: note: when computing vector element at index '1' | |
| 2721 | 2717 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2718 | // :110:37: note: when computing vector element at index '1' | |
| 2722 | 2719 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2720 | // :110:37: note: when computing vector element at index '1' | |
| 2723 | 2721 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2722 | // :110:37: note: when computing vector element at index '1' | |
| 2724 | 2723 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2724 | // :110:37: note: when computing vector element at index '1' | |
| 2725 | 2725 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2726 | 2726 | // :110:37: note: when computing vector element at index '1' |
| 2727 | 2727 | // :110:37: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2731,13 +2731,13 @@ const std = @import("std"); |
| 2731 | 2731 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2732 | 2732 | // :110:37: note: when computing vector element at index '1' |
| 2733 | 2733 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2734 | // :110:37: note: when computing vector element at index '0' | |
| 2734 | // :110:37: note: when computing vector element at index '1' | |
| 2735 | 2735 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2736 | // :110:37: note: when computing vector element at index '0' | |
| 2736 | // :110:37: note: when computing vector element at index '1' | |
| 2737 | 2737 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2738 | // :110:37: note: when computing vector element at index '0' | |
| 2738 | // :110:37: note: when computing vector element at index '1' | |
| 2739 | 2739 | // :110:37: error: use of undefined value here causes illegal behavior |
| 2740 | // :110:37: note: when computing vector element at index '0' | |
| 2740 | // :110:37: note: when computing vector element at index '1' | |
| 2741 | 2741 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2742 | 2742 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2743 | 2743 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2745,21 +2745,13 @@ const std = @import("std"); |
| 2745 | 2745 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2746 | 2746 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2747 | 2747 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2748 | // :113:22: note: when computing vector element at index '1' | |
| 2749 | 2748 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2750 | // :113:22: note: when computing vector element at index '1' | |
| 2751 | 2749 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2752 | // :113:22: note: when computing vector element at index '1' | |
| 2753 | 2750 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2754 | // :113:22: note: when computing vector element at index '1' | |
| 2755 | 2751 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2756 | // :113:22: note: when computing vector element at index '0' | |
| 2757 | 2752 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2758 | // :113:22: note: when computing vector element at index '0' | |
| 2759 | 2753 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2760 | // :113:22: note: when computing vector element at index '0' | |
| 2761 | 2754 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2762 | // :113:22: note: when computing vector element at index '0' | |
| 2763 | 2755 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2764 | 2756 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2765 | 2757 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2767,21 +2759,13 @@ const std = @import("std"); |
| 2767 | 2759 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2768 | 2760 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2769 | 2761 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2770 | // :113:22: note: when computing vector element at index '1' | |
| 2771 | 2762 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2772 | // :113:22: note: when computing vector element at index '1' | |
| 2773 | 2763 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2774 | // :113:22: note: when computing vector element at index '1' | |
| 2775 | 2764 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2776 | // :113:22: note: when computing vector element at index '1' | |
| 2777 | 2765 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2778 | // :113:22: note: when computing vector element at index '0' | |
| 2779 | 2766 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2780 | // :113:22: note: when computing vector element at index '0' | |
| 2781 | 2767 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2782 | // :113:22: note: when computing vector element at index '0' | |
| 2783 | 2768 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2784 | // :113:22: note: when computing vector element at index '0' | |
| 2785 | 2769 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2786 | 2770 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2787 | 2771 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2789,13 +2773,11 @@ const std = @import("std"); |
| 2789 | 2773 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2790 | 2774 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2791 | 2775 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2792 | // :113:22: note: when computing vector element at index '1' | |
| 2793 | 2776 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2794 | // :113:22: note: when computing vector element at index '1' | |
| 2795 | 2777 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2796 | // :113:22: note: when computing vector element at index '1' | |
| 2778 | // :113:22: note: when computing vector element at index '0' | |
| 2797 | 2779 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2798 | // :113:22: note: when computing vector element at index '1' | |
| 2780 | // :113:22: note: when computing vector element at index '0' | |
| 2799 | 2781 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2800 | 2782 | // :113:22: note: when computing vector element at index '0' |
| 2801 | 2783 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2805,19 +2787,25 @@ const std = @import("std"); |
| 2805 | 2787 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2806 | 2788 | // :113:22: note: when computing vector element at index '0' |
| 2807 | 2789 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2790 | // :113:22: note: when computing vector element at index '0' | |
| 2808 | 2791 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2792 | // :113:22: note: when computing vector element at index '0' | |
| 2809 | 2793 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2794 | // :113:22: note: when computing vector element at index '0' | |
| 2810 | 2795 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2796 | // :113:22: note: when computing vector element at index '0' | |
| 2811 | 2797 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2798 | // :113:22: note: when computing vector element at index '0' | |
| 2812 | 2799 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2800 | // :113:22: note: when computing vector element at index '0' | |
| 2813 | 2801 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2814 | // :113:22: note: when computing vector element at index '1' | |
| 2802 | // :113:22: note: when computing vector element at index '0' | |
| 2815 | 2803 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2816 | // :113:22: note: when computing vector element at index '1' | |
| 2804 | // :113:22: note: when computing vector element at index '0' | |
| 2817 | 2805 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2818 | // :113:22: note: when computing vector element at index '1' | |
| 2806 | // :113:22: note: when computing vector element at index '0' | |
| 2819 | 2807 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2820 | // :113:22: note: when computing vector element at index '1' | |
| 2808 | // :113:22: note: when computing vector element at index '0' | |
| 2821 | 2809 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2822 | 2810 | // :113:22: note: when computing vector element at index '0' |
| 2823 | 2811 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2827,11 +2815,17 @@ const std = @import("std"); |
| 2827 | 2815 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2828 | 2816 | // :113:22: note: when computing vector element at index '0' |
| 2829 | 2817 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2818 | // :113:22: note: when computing vector element at index '0' | |
| 2830 | 2819 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2820 | // :113:22: note: when computing vector element at index '0' | |
| 2831 | 2821 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2822 | // :113:22: note: when computing vector element at index '0' | |
| 2832 | 2823 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2824 | // :113:22: note: when computing vector element at index '0' | |
| 2833 | 2825 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2826 | // :113:22: note: when computing vector element at index '1' | |
| 2834 | 2827 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2828 | // :113:22: note: when computing vector element at index '1' | |
| 2835 | 2829 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2836 | 2830 | // :113:22: note: when computing vector element at index '1' |
| 2837 | 2831 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2841,19 +2835,25 @@ const std = @import("std"); |
| 2841 | 2835 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2842 | 2836 | // :113:22: note: when computing vector element at index '1' |
| 2843 | 2837 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2844 | // :113:22: note: when computing vector element at index '0' | |
| 2838 | // :113:22: note: when computing vector element at index '1' | |
| 2845 | 2839 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2846 | // :113:22: note: when computing vector element at index '0' | |
| 2840 | // :113:22: note: when computing vector element at index '1' | |
| 2847 | 2841 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2848 | // :113:22: note: when computing vector element at index '0' | |
| 2842 | // :113:22: note: when computing vector element at index '1' | |
| 2849 | 2843 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2850 | // :113:22: note: when computing vector element at index '0' | |
| 2844 | // :113:22: note: when computing vector element at index '1' | |
| 2851 | 2845 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2846 | // :113:22: note: when computing vector element at index '1' | |
| 2852 | 2847 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2848 | // :113:22: note: when computing vector element at index '1' | |
| 2853 | 2849 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2850 | // :113:22: note: when computing vector element at index '1' | |
| 2854 | 2851 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2852 | // :113:22: note: when computing vector element at index '1' | |
| 2855 | 2853 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2854 | // :113:22: note: when computing vector element at index '1' | |
| 2856 | 2855 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2856 | // :113:22: note: when computing vector element at index '1' | |
| 2857 | 2857 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2858 | 2858 | // :113:22: note: when computing vector element at index '1' |
| 2859 | 2859 | // :113:22: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2863,13 +2863,13 @@ const std = @import("std"); |
| 2863 | 2863 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2864 | 2864 | // :113:22: note: when computing vector element at index '1' |
| 2865 | 2865 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2866 | // :113:22: note: when computing vector element at index '0' | |
| 2866 | // :113:22: note: when computing vector element at index '1' | |
| 2867 | 2867 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2868 | // :113:22: note: when computing vector element at index '0' | |
| 2868 | // :113:22: note: when computing vector element at index '1' | |
| 2869 | 2869 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2870 | // :113:22: note: when computing vector element at index '0' | |
| 2870 | // :113:22: note: when computing vector element at index '1' | |
| 2871 | 2871 | // :113:22: error: use of undefined value here causes illegal behavior |
| 2872 | // :113:22: note: when computing vector element at index '0' | |
| 2872 | // :113:22: note: when computing vector element at index '1' | |
| 2873 | 2873 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2874 | 2874 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2875 | 2875 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2877,21 +2877,13 @@ const std = @import("std"); |
| 2877 | 2877 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2878 | 2878 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2879 | 2879 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2880 | // :116:30: note: when computing vector element at index '1' | |
| 2881 | 2880 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2882 | // :116:30: note: when computing vector element at index '1' | |
| 2883 | 2881 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2884 | // :116:30: note: when computing vector element at index '1' | |
| 2885 | 2882 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2886 | // :116:30: note: when computing vector element at index '1' | |
| 2887 | 2883 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2888 | // :116:30: note: when computing vector element at index '0' | |
| 2889 | 2884 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2890 | // :116:30: note: when computing vector element at index '0' | |
| 2891 | 2885 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2892 | // :116:30: note: when computing vector element at index '0' | |
| 2893 | 2886 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2894 | // :116:30: note: when computing vector element at index '0' | |
| 2895 | 2887 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2896 | 2888 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2897 | 2889 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2899,21 +2891,13 @@ const std = @import("std"); |
| 2899 | 2891 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2900 | 2892 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2901 | 2893 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2902 | // :116:30: note: when computing vector element at index '1' | |
| 2903 | 2894 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2904 | // :116:30: note: when computing vector element at index '1' | |
| 2905 | 2895 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2906 | // :116:30: note: when computing vector element at index '1' | |
| 2907 | 2896 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2908 | // :116:30: note: when computing vector element at index '1' | |
| 2909 | 2897 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2910 | // :116:30: note: when computing vector element at index '0' | |
| 2911 | 2898 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2912 | // :116:30: note: when computing vector element at index '0' | |
| 2913 | 2899 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2914 | // :116:30: note: when computing vector element at index '0' | |
| 2915 | 2900 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2916 | // :116:30: note: when computing vector element at index '0' | |
| 2917 | 2901 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2918 | 2902 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2919 | 2903 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2921,13 +2905,11 @@ const std = @import("std"); |
| 2921 | 2905 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2922 | 2906 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2923 | 2907 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2924 | // :116:30: note: when computing vector element at index '1' | |
| 2925 | 2908 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2926 | // :116:30: note: when computing vector element at index '1' | |
| 2927 | 2909 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2928 | // :116:30: note: when computing vector element at index '1' | |
| 2910 | // :116:30: note: when computing vector element at index '0' | |
| 2929 | 2911 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2930 | // :116:30: note: when computing vector element at index '1' | |
| 2912 | // :116:30: note: when computing vector element at index '0' | |
| 2931 | 2913 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2932 | 2914 | // :116:30: note: when computing vector element at index '0' |
| 2933 | 2915 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2937,19 +2919,25 @@ const std = @import("std"); |
| 2937 | 2919 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2938 | 2920 | // :116:30: note: when computing vector element at index '0' |
| 2939 | 2921 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2922 | // :116:30: note: when computing vector element at index '0' | |
| 2940 | 2923 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2924 | // :116:30: note: when computing vector element at index '0' | |
| 2941 | 2925 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2926 | // :116:30: note: when computing vector element at index '0' | |
| 2942 | 2927 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2928 | // :116:30: note: when computing vector element at index '0' | |
| 2943 | 2929 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2930 | // :116:30: note: when computing vector element at index '0' | |
| 2944 | 2931 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2932 | // :116:30: note: when computing vector element at index '0' | |
| 2945 | 2933 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2946 | // :116:30: note: when computing vector element at index '1' | |
| 2934 | // :116:30: note: when computing vector element at index '0' | |
| 2947 | 2935 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2948 | // :116:30: note: when computing vector element at index '1' | |
| 2936 | // :116:30: note: when computing vector element at index '0' | |
| 2949 | 2937 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2950 | // :116:30: note: when computing vector element at index '1' | |
| 2938 | // :116:30: note: when computing vector element at index '0' | |
| 2951 | 2939 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2952 | // :116:30: note: when computing vector element at index '1' | |
| 2940 | // :116:30: note: when computing vector element at index '0' | |
| 2953 | 2941 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2954 | 2942 | // :116:30: note: when computing vector element at index '0' |
| 2955 | 2943 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2959,11 +2947,17 @@ const std = @import("std"); |
| 2959 | 2947 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2960 | 2948 | // :116:30: note: when computing vector element at index '0' |
| 2961 | 2949 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2950 | // :116:30: note: when computing vector element at index '0' | |
| 2962 | 2951 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2952 | // :116:30: note: when computing vector element at index '0' | |
| 2963 | 2953 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2954 | // :116:30: note: when computing vector element at index '0' | |
| 2964 | 2955 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2956 | // :116:30: note: when computing vector element at index '0' | |
| 2965 | 2957 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2958 | // :116:30: note: when computing vector element at index '1' | |
| 2966 | 2959 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2960 | // :116:30: note: when computing vector element at index '1' | |
| 2967 | 2961 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2968 | 2962 | // :116:30: note: when computing vector element at index '1' |
| 2969 | 2963 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2973,19 +2967,25 @@ const std = @import("std"); |
| 2973 | 2967 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2974 | 2968 | // :116:30: note: when computing vector element at index '1' |
| 2975 | 2969 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2976 | // :116:30: note: when computing vector element at index '0' | |
| 2970 | // :116:30: note: when computing vector element at index '1' | |
| 2977 | 2971 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2978 | // :116:30: note: when computing vector element at index '0' | |
| 2972 | // :116:30: note: when computing vector element at index '1' | |
| 2979 | 2973 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2980 | // :116:30: note: when computing vector element at index '0' | |
| 2974 | // :116:30: note: when computing vector element at index '1' | |
| 2981 | 2975 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2982 | // :116:30: note: when computing vector element at index '0' | |
| 2976 | // :116:30: note: when computing vector element at index '1' | |
| 2983 | 2977 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2978 | // :116:30: note: when computing vector element at index '1' | |
| 2984 | 2979 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2980 | // :116:30: note: when computing vector element at index '1' | |
| 2985 | 2981 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2982 | // :116:30: note: when computing vector element at index '1' | |
| 2986 | 2983 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2984 | // :116:30: note: when computing vector element at index '1' | |
| 2987 | 2985 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2986 | // :116:30: note: when computing vector element at index '1' | |
| 2988 | 2987 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2988 | // :116:30: note: when computing vector element at index '1' | |
| 2989 | 2989 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2990 | 2990 | // :116:30: note: when computing vector element at index '1' |
| 2991 | 2991 | // :116:30: error: use of undefined value here causes illegal behavior |
| ... | ... | @@ -2995,10 +2995,10 @@ const std = @import("std"); |
| 2995 | 2995 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2996 | 2996 | // :116:30: note: when computing vector element at index '1' |
| 2997 | 2997 | // :116:30: error: use of undefined value here causes illegal behavior |
| 2998 | // :116:30: note: when computing vector element at index '0' | |
| 2998 | // :116:30: note: when computing vector element at index '1' | |
| 2999 | 2999 | // :116:30: error: use of undefined value here causes illegal behavior |
| 3000 | // :116:30: note: when computing vector element at index '0' | |
| 3000 | // :116:30: note: when computing vector element at index '1' | |
| 3001 | 3001 | // :116:30: error: use of undefined value here causes illegal behavior |
| 3002 | // :116:30: note: when computing vector element at index '0' | |
| 3002 | // :116:30: note: when computing vector element at index '1' | |
| 3003 | 3003 | // :116:30: error: use of undefined value here causes illegal behavior |
| 3004 | // :116:30: note: when computing vector element at index '0' | |
| 3004 | // :116:30: note: when computing vector element at index '1' |
test/cases/compile_errors/union_auto-enum_value_already_taken.zig+2-2| ... | ... | @@ -12,5 +12,5 @@ export fn entry() void { |
| 12 | 12 | |
| 13 | 13 | // error |
| 14 | 14 | // |
| 15 | // :6:9: error: enum tag value 60 already taken | |
| 16 | // :4:9: note: other occurrence here | |
| 15 | // :6:9: error: enum tag value '60' for field 'E' already taken | |
| 16 | // :4:9: note: previous occurrence in field 'C' |
test/cases/compile_errors/union_backed_by_enum_backed_by_comptime_int.zig created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | const U = union(enum(comptime_int)) { a: u32 }; | |
| 2 | comptime { | |
| 3 | const u: U = .{ .a = 123 }; | |
| 4 | _ = u; | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // | |
| 9 | // :1:22: error: expected integer tag type, found 'comptime_int' |
test/cases/compile_errors/union_depends_on_pointer_alignment.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const U = union { | |
| 2 | next: ?*align(1) U align(128), | |
| 3 | }; | |
| 4 | ||
| 5 | export fn entry() usize { | |
| 6 | return @alignOf(U); | |
| 7 | } | |
| 8 | ||
| 9 | // error | |
| 10 | // | |
| 11 | // :1:11: error: union layout depends on being pointer aligned |
test/cases/compile_errors/union_enum_field_missing.zig+2-3| ... | ... | @@ -15,6 +15,5 @@ export fn entry() usize { |
| 15 | 15 | |
| 16 | 16 | // error |
| 17 | 17 | // |
| 18 | // :7:11: error: enum field(s) missing in union | |
| 19 | // :4:5: note: field 'c' missing, declared here | |
| 20 | // :1:11: note: enum declared here | |
| 18 | // :7:11: error: enum field 'c' missing from union | |
| 19 | // :4:5: note: enum field here |
test/cases/compile_errors/union_field_ordered_differently_than_enum.zig+3-4| ... | ... | @@ -21,7 +21,6 @@ export fn entry() usize { |
| 21 | 21 | |
| 22 | 22 | // error |
| 23 | 23 | // |
| 24 | // :4:5: error: union field 'b' ordered differently than corresponding enum field | |
| 25 | // :1:23: note: enum field here | |
| 26 | // :14:5: error: union field 'b' ordered differently than corresponding enum field | |
| 27 | // :10:5: note: enum field here | |
| 24 | // :3:15: error: union field order does not match tag enum field order | |
| 25 | // :5:5: note: union field 'a' is index 1 | |
| 26 | // :1:20: note: enum field 'a' is index 0 |
test/cases/compile_errors/union_noreturn_field_initialized.zig+6-6| ... | ... | @@ -15,8 +15,8 @@ pub export fn entry2() void { |
| 15 | 15 | const U = union(enum) { |
| 16 | 16 | a: noreturn, |
| 17 | 17 | }; |
| 18 | var u: U = undefined; | |
| 19 | u = .a; | |
| 18 | const u: U = .a; | |
| 19 | _ = u; | |
| 20 | 20 | } |
| 21 | 21 | pub export fn entry3() void { |
| 22 | 22 | const U = union(enum) { |
| ... | ... | @@ -30,12 +30,12 @@ pub export fn entry3() void { |
| 30 | 30 | |
| 31 | 31 | // error |
| 32 | 32 | // |
| 33 | // :11:14: error: cannot initialize 'noreturn' field of union | |
| 33 | // :11:14: error: cannot initialize union field with uninstantiable type 'noreturn' | |
| 34 | 34 | // :4:9: note: field 'b' declared here |
| 35 | 35 | // :2:15: note: union declared here |
| 36 | // :19:10: error: cannot initialize 'noreturn' field of union | |
| 36 | // :18:19: error: cannot initialize union field with uninstantiable type 'noreturn' | |
| 37 | 37 | // :16:9: note: field 'a' declared here |
| 38 | 38 | // :15:15: note: union declared here |
| 39 | // :28:13: error: runtime coercion from enum '@typeInfo(tmp.entry3.U).@"union".tag_type.?' to union 'tmp.entry3.U' which has a 'noreturn' field | |
| 40 | // :23:9: note: 'noreturn' field here | |
| 39 | // :28:13: error: runtime coercion from enum '@typeInfo(tmp.entry3.U).@"union".tag_type.?' to union 'tmp.entry3.U' which has non-void fields | |
| 40 | // :23:9: note: field 'a' has uninstantiable type 'noreturn' | |
| 41 | 41 | // :22:15: note: union declared here |
test/cases/compile_errors/union_with_specified_enum_omits_field.zig+2-3| ... | ... | @@ -13,6 +13,5 @@ export fn entry() usize { |
| 13 | 13 | |
| 14 | 14 | // error |
| 15 | 15 | // |
| 16 | // :6:17: error: enum field(s) missing in union | |
| 17 | // :4:5: note: field 'C' missing, declared here | |
| 18 | // :1:16: note: enum declared here | |
| 16 | // :6:17: error: enum field 'C' missing from union | |
| 17 | // :4:5: note: enum field here |
test/cases/compile_errors/union_with_too_small_explicit_signed_tag_type.zig+1-2| ... | ... | @@ -10,5 +10,4 @@ export fn entry() void { |
| 10 | 10 | |
| 11 | 11 | // error |
| 12 | 12 | // |
| 13 | // :1:22: error: specified integer tag type cannot represent every field | |
| 14 | // :1:22: note: type 'i2' cannot fit values in range 0...3 | |
| 13 | // :4:5: error: enum tag value '2' too large for type 'i2' |
test/cases/compile_errors/union_with_too_small_explicit_unsigned_tag_type.zig+1-2| ... | ... | @@ -11,5 +11,4 @@ export fn entry() void { |
| 11 | 11 | |
| 12 | 12 | // error |
| 13 | 13 | // |
| 14 | // :1:22: error: specified integer tag type cannot represent every field | |
| 15 | // :1:22: note: type 'u2' cannot fit values in range 0...4 | |
| 14 | // :6:5: error: enum tag value '4' too large for type 'u2' |
test/cases/compile_errors/untagged_union_integer_conversion.zig+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | const UntaggedUnion = union {}; | |
| 1 | const UntaggedUnion = union { a: void }; | |
| 2 | 2 | comptime { |
| 3 | 3 | @intFromEnum(@as(UntaggedUnion, undefined)); |
| 4 | 4 | } |
test/cases/compile_errors/variadic_arg_validation.zig+1-1| ... | ... | @@ -25,4 +25,4 @@ pub export fn entry3() void { |
| 25 | 25 | // :14:24: error: cannot pass 'u48' to variadic function |
| 26 | 26 | // :14:24: note: only integers with 0 or power of two bits are extern compatible |
| 27 | 27 | // :18:24: error: cannot pass 'void' to variadic function |
| 28 | // :18:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque' | |
| 28 | // :18:24: note: 'void' is a zero bit type |
test/cases/compile_errors/zero_width_nonexhaustive_enum.zig+9-6| ... | ... | @@ -1,17 +1,20 @@ |
| 1 | 1 | comptime { |
| 2 | _ = enum(i0) { a, _ }; | |
| 2 | const E = enum(i0) { a, _ }; | |
| 3 | _ = @as(E, undefined); | |
| 3 | 4 | } |
| 4 | 5 | |
| 5 | 6 | comptime { |
| 6 | _ = enum(u0) { a, _ }; | |
| 7 | const E = enum(u0) { a, _ }; | |
| 8 | _ = @as(E, undefined); | |
| 7 | 9 | } |
| 8 | 10 | |
| 9 | 11 | comptime { |
| 10 | _ = enum(u0) { a, b, _ }; | |
| 12 | const E = enum(u0) { a, b, _ }; | |
| 13 | _ = @as(E, undefined); | |
| 11 | 14 | } |
| 12 | 15 | |
| 13 | 16 | // error |
| 14 | 17 | // |
| 15 | // :2:9: error: non-exhaustive enum specifies every value | |
| 16 | // :6:9: error: non-exhaustive enum specifies every value | |
| 17 | // :10:23: error: enumeration value '1' too large for type 'u0' | |
| 18 | // :2:15: error: non-exhaustive enum specifies every value | |
| 19 | // :7:15: error: non-exhaustive enum specifies every value | |
| 20 | // :12:29: error: enum tag value '1' too large for type 'u0' |
test/incremental/change_enum_tag_type+1-1| ... | ... | @@ -44,7 +44,7 @@ comptime { |
| 44 | 44 | } |
| 45 | 45 | const std = @import("std"); |
| 46 | 46 | const io = std.Io.Threaded.global_single_threaded.io(); |
| 47 | #expect_error=main.zig:7:5: error: enumeration value '4' too large for type 'u2' | |
| 47 | #expect_error=main.zig:7:5: error: enum tag value '4' too large for type 'u2' | |
| 48 | 48 | #update=increase tag size |
| 49 | 49 | #file=main.zig |
| 50 | 50 | const Tag = u3; |
test/incremental/type_dependency_loop created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | #target=x86_64-linux-selfhosted | |
| 2 | #target=x86_64-windows-selfhosted | |
| 3 | #target=x86_64-linux-cbe | |
| 4 | #target=x86_64-windows-cbe | |
| 5 | #target=wasm32-wasi-selfhosted | |
| 6 | #update=initial version | |
| 7 | #file=main.zig | |
| 8 | pub const A = struct { b: B }; | |
| 9 | pub const B = struct { a: A }; | |
| 10 | pub fn main() void { | |
| 11 | _ = @as(B, undefined); | |
| 12 | } | |
| 13 | #expect_error=:error: dependency loop with length 2 | |
| 14 | #expect_error=main.zig:2:27: note: type 'main.B' depends on type 'main.A' for field declared here | |
| 15 | #expect_error=main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here | |
| 16 | #expect_error=:note: eliminate any one of these dependencies to break the loop | |
| 17 | ||
| 18 | #update=remove reference to dependency loop | |
| 19 | #file=main.zig | |
| 20 | pub const A = struct { b: B }; | |
| 21 | pub const B = struct { a: A }; | |
| 22 | pub fn main() void { | |
| 23 | _ = B; | |
| 24 | } | |
| 25 | #expect_stdout="" | |
| 26 | ||
| 27 | #update=change dependency loop without fixing it | |
| 28 | #file=main.zig | |
| 29 | pub const A = struct { b: B }; | |
| 30 | pub const B = struct { a: *align(@alignOf(A)) A }; | |
| 31 | pub fn main() void { | |
| 32 | _ = B; | |
| 33 | } | |
| 34 | #expect_stdout="" | |
| 35 | ||
| 36 | #update=reference dependency loop again | |
| 37 | #file=main.zig | |
| 38 | pub const A = struct { b: B }; | |
| 39 | pub const B = struct { a: *align(@alignOf(A)) A }; | |
| 40 | pub fn main() void { | |
| 41 | _ = @as(B, undefined); | |
| 42 | } | |
| 43 | #expect_error=:error: dependency loop with length 2 | |
| 44 | #expect_error=main.zig:2:43: note: type 'main.B' depends on type 'main.A' for alignment query here | |
| 45 | #expect_error=main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here | |
| 46 | #expect_error=:note: eliminate any one of these dependencies to break the loop | |
| 47 | ||
| 48 | #update=fix dependency loop | |
| 49 | #file=main.zig | |
| 50 | pub const A = struct { b: B }; | |
| 51 | pub const B = struct { a: *A }; | |
| 52 | pub fn main() void { | |
| 53 | _ = @as(B, undefined); | |
| 54 | } | |
| 55 | #expect_stdout="" |
tools/incr-check.zig+50-45| ... | ... | @@ -311,12 +311,12 @@ const Eval = struct { |
| 311 | 311 | .error_bundle => { |
| 312 | 312 | const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); |
| 313 | 313 | if (stderr.bufferedLen() > 0) { |
| 314 | const stderr_data = try mr.toOwnedSlice(1); | |
| 315 | 314 | if (eval.allow_stderr) { |
| 316 | std.log.info("error_bundle stderr:\n{s}", .{stderr_data}); | |
| 315 | std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()}); | |
| 317 | 316 | } else { |
| 318 | eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data}); | |
| 317 | eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()}); | |
| 319 | 318 | } |
| 319 | stderr.tossBuffered(); | |
| 320 | 320 | } |
| 321 | 321 | if (result_error_bundle.errorMessageCount() != 0) { |
| 322 | 322 | try eval.checkErrorOutcome(update, result_error_bundle); |
| ... | ... | @@ -327,18 +327,18 @@ const Eval = struct { |
| 327 | 327 | .emit_digest => { |
| 328 | 328 | var r: std.Io.Reader = .fixed(body); |
| 329 | 329 | _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; |
| 330 | ||
| 330 | 331 | if (stderr.bufferedLen() > 0) { |
| 331 | const stderr_data = try mr.toOwnedSlice(1); | |
| 332 | 332 | if (eval.allow_stderr) { |
| 333 | std.log.info("emit_digest stderr:\n{s}", .{stderr_data}); | |
| 333 | std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()}); | |
| 334 | 334 | } else { |
| 335 | eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data}); | |
| 335 | eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()}); | |
| 336 | 336 | } |
| 337 | stderr.tossBuffered(); | |
| 337 | 338 | } |
| 338 | ||
| 339 | 339 | if (eval.target.backend == .sema) { |
| 340 | 340 | try eval.checkSuccessOutcome(update, null, prog_node); |
| 341 | // This message indicates the end of the update. | |
| 341 | continue; | |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | 344 | const digest = r.takeArray(Cache.bin_digest_len) catch unreachable; |
| ... | ... | @@ -352,7 +352,6 @@ const Eval = struct { |
| 352 | 352 | const bin_path = try Dir.path.join(arena, &.{ result_dir, bin_name }); |
| 353 | 353 | |
| 354 | 354 | try eval.checkSuccessOutcome(update, bin_path, prog_node); |
| 355 | // This message indicates the end of the update. | |
| 356 | 355 | }, |
| 357 | 356 | else => { |
| 358 | 357 | // Ignore other messages. |
| ... | ... | @@ -370,7 +369,7 @@ const Eval = struct { |
| 370 | 369 | } |
| 371 | 370 | |
| 372 | 371 | waitChild(eval.child, eval); |
| 373 | eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{}); | |
| 372 | eval.fatal("compiler failed to send terminating error_bundle", .{}); | |
| 374 | 373 | } |
| 375 | 374 | |
| 376 | 375 | fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void { |
| ... | ... | @@ -417,29 +416,32 @@ const Eval = struct { |
| 417 | 416 | is_note: bool, |
| 418 | 417 | err_idx: std.zig.ErrorBundle.MessageIndex, |
| 419 | 418 | ) Allocator.Error!void { |
| 419 | const io = eval.io; | |
| 420 | 420 | const err = eb.getErrorMessage(err_idx); |
| 421 | if (err.src_loc == .none) @panic("TODO error message with no source location"); | |
| 422 | 421 | if (err.count != 1) @panic("TODO error message with count>1"); |
| 423 | 422 | const msg = eb.nullTerminatedString(err.msg); |
| 424 | const src = eb.getSourceLocation(err.src_loc); | |
| 425 | const raw_filename = eb.nullTerminatedString(src.src_path); | |
| 426 | ||
| 427 | const io = eval.io; | |
| 428 | ||
| 429 | // We need to replace backslashes for consistency between platforms. | |
| 430 | const filename = name: { | |
| 431 | if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename; | |
| 432 | const copied = try eval.arena.dupe(u8, raw_filename); | |
| 433 | std.mem.replaceScalar(u8, copied, '\\', '/'); | |
| 434 | break :name copied; | |
| 423 | const matches = matches: { | |
| 424 | if (expected.is_note != is_note) break :matches false; | |
| 425 | if (!std.mem.eql(u8, expected.msg, msg)) break :matches false; | |
| 426 | if (err.src_loc == .none) { | |
| 427 | break :matches expected.src == null; | |
| 428 | } | |
| 429 | const expected_src = expected.src orelse break :matches false; | |
| 430 | const src = eb.getSourceLocation(err.src_loc); | |
| 431 | const raw_filename = eb.nullTerminatedString(src.src_path); | |
| 432 | // We need to replace backslashes for consistency between platforms. | |
| 433 | const filename = name: { | |
| 434 | if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename; | |
| 435 | const copied = try eval.arena.dupe(u8, raw_filename); | |
| 436 | std.mem.replaceScalar(u8, copied, '\\', '/'); | |
| 437 | break :name copied; | |
| 438 | }; | |
| 439 | if (!std.mem.eql(u8, expected_src.filename, filename)) break :matches false; | |
| 440 | if (expected_src.line != src.line + 1) break :matches false; | |
| 441 | if (expected_src.column != src.column + 1) break :matches false; | |
| 442 | break :matches true; | |
| 435 | 443 | }; |
| 436 | ||
| 437 | if (expected.is_note != is_note or | |
| 438 | !std.mem.eql(u8, expected.filename, filename) or | |
| 439 | expected.line != src.line + 1 or | |
| 440 | expected.column != src.column + 1 or | |
| 441 | !std.mem.eql(u8, expected.msg, msg)) | |
| 442 | { | |
| 444 | if (!matches) { | |
| 443 | 445 | eb.renderToStderr(io, .{}, .auto) catch {}; |
| 444 | 446 | eval.fatal("compile error did not match expected error", .{}); |
| 445 | 447 | } |
| ... | ... | @@ -714,10 +716,12 @@ const Case = struct { |
| 714 | 716 | |
| 715 | 717 | const ExpectedError = struct { |
| 716 | 718 | is_note: bool, |
| 717 | filename: []const u8, | |
| 718 | line: u32, | |
| 719 | column: u32, | |
| 720 | 719 | msg: []const u8, |
| 720 | src: ?struct { | |
| 721 | filename: []const u8, | |
| 722 | line: u32, | |
| 723 | column: u32, | |
| 724 | }, | |
| 721 | 725 | }; |
| 722 | 726 | |
| 723 | 727 | fn parse(arena: Allocator, io: Io, bytes: []const u8) !Case { |
| ... | ... | @@ -930,16 +934,16 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { |
| 930 | 934 | |
| 931 | 935 | var it = std.mem.splitScalar(u8, str, ':'); |
| 932 | 936 | const filename = it.first(); |
| 933 | const line_str = it.next() orelse fatal("line {d}: incomplete error specification", .{l}); | |
| 934 | const column_str = it.next() orelse fatal("line {d}: incomplete error specification", .{l}); | |
| 937 | const line_str, const column_str = if (filename.len > 0) .{ | |
| 938 | it.next() orelse fatal("line {d}: incomplete error specification", .{l}), | |
| 939 | it.next() orelse fatal("line {d}: incomplete error specification", .{l}), | |
| 940 | } else .{ undefined, undefined }; | |
| 935 | 941 | const error_or_note_str = std.mem.trim( |
| 936 | 942 | u8, |
| 937 | 943 | it.next() orelse fatal("line {d}: incomplete error specification", .{l}), |
| 938 | 944 | " ", |
| 939 | 945 | ); |
| 940 | const message = std.mem.trim(u8, it.rest(), " "); | |
| 941 | if (filename.len == 0) fatal("line {d}: empty filename", .{l}); | |
| 942 | if (message.len == 0) fatal("line {d}: empty error message", .{l}); | |
| 946 | ||
| 943 | 947 | const is_note = if (std.mem.eql(u8, error_or_note_str, "error")) |
| 944 | 948 | false |
| 945 | 949 | else if (std.mem.eql(u8, error_or_note_str, "note")) |
| ... | ... | @@ -947,18 +951,19 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { |
| 947 | 951 | else |
| 948 | 952 | fatal("line {d}: expeted 'error' or 'note', found '{s}'", .{ l, error_or_note_str }); |
| 949 | 953 | |
| 950 | const line = std.fmt.parseInt(u32, line_str, 10) catch | |
| 951 | fatal("line {d}: invalid line number '{s}'", .{ l, line_str }); | |
| 952 | ||
| 953 | const column = std.fmt.parseInt(u32, column_str, 10) catch | |
| 954 | fatal("line {d}: invalid column number '{s}'", .{ l, column_str }); | |
| 954 | const message = std.mem.trim(u8, it.rest(), " "); | |
| 955 | if (message.len == 0) fatal("line {d}: empty error message", .{l}); | |
| 955 | 956 | |
| 956 | 957 | return .{ |
| 957 | 958 | .is_note = is_note, |
| 958 | .filename = filename, | |
| 959 | .line = line, | |
| 960 | .column = column, | |
| 961 | 959 | .msg = message, |
| 960 | .src = if (filename.len == 0) null else .{ | |
| 961 | .filename = filename, | |
| 962 | .line = std.fmt.parseInt(u32, line_str, 10) catch | |
| 963 | fatal("line {d}: invalid line number '{s}'", .{ l, line_str }), | |
| 964 | .column = std.fmt.parseInt(u32, column_str, 10) catch | |
| 965 | fatal("line {d}: invalid column number '{s}'", .{ l, column_str }), | |
| 966 | }, | |
| 962 | 967 | }; |
| 963 | 968 | } |
| 964 | 969 |