| author | |
| committer | |
| log | 6daa041932ae5ab03eed953dacf3ca506078390c |
| tree | 0f51f6c2ff84dde51b61bba6799e5c5abccf91b4 |
| parent | f0ec308e26ff957c7fbb50ccc69d3d549c42c4da |
| parent | 8d2a902945ef97f28152c3d5a68bb974809c8539 |
| signature |
Refreshing fork.426 files changed, 25085 insertions(+), 16300 deletions(-)
.builds/freebsd.yml created+43| ... | @@ -0,0 +1,43 @@ | ||
| 1 | image: freebsd/latest | ||
| 2 | packages: | ||
| 3 | - cmake | ||
| 4 | - ninja | ||
| 5 | - llvm70 | ||
| 6 | sources: | ||
| 7 | - https://github.com/ziglang/zig | ||
| 8 | tasks: | ||
| 9 | - build: | | ||
| 10 | cd zig && mkdir build && cd build | ||
| 11 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release | ||
| 12 | ninja install | ||
| 13 | - test: | | ||
| 14 | cd zig/build | ||
| 15 | bin/zig test ../test/stage1/behavior.zig | ||
| 16 | bin/zig test ../std/special/compiler_rt/index.zig | ||
| 17 | |||
| 18 | bin/zig test ../test/stage1/behavior.zig --library c | ||
| 19 | bin/zig test ../std/special/compiler_rt/index.zig --library c | ||
| 20 | |||
| 21 | bin/zig test ../test/stage1/behavior.zig --release-fast | ||
| 22 | bin/zig test ../std/special/compiler_rt/index.zig --release-fast | ||
| 23 | |||
| 24 | bin/zig test ../test/stage1/behavior.zig --release-fast --library c | ||
| 25 | bin/zig test ../std/special/compiler_rt/index.zig --release-fast --library c | ||
| 26 | |||
| 27 | bin/zig test ../test/stage1/behavior.zig --release-small --library c | ||
| 28 | bin/zig test ../std/special/compiler_rt/index.zig --release-small --library c | ||
| 29 | |||
| 30 | bin/zig test ../test/stage1/behavior.zig --release-small | ||
| 31 | bin/zig test ../std/special/compiler_rt/index.zig --release-small | ||
| 32 | |||
| 33 | bin/zig test ../test/stage1/behavior.zig --release-safe | ||
| 34 | bin/zig test ../std/special/compiler_rt/index.zig --release-safe | ||
| 35 | |||
| 36 | bin/zig test ../test/stage1/behavior.zig --release-safe --library c | ||
| 37 | bin/zig test ../std/special/compiler_rt/index.zig --release-safe --library c | ||
| 38 | # TODO enable all tests | ||
| 39 | #bin/zig build --build-file ../build.zig test | ||
| 40 | # TODO integrate with the download page updater and make a | ||
| 41 | # static build available to download for FreeBSD. | ||
| 42 | # This will require setting up a cache of LLVM/Clang built | ||
| 43 | # statically. | ||
CMakeLists.txt+27-7| ... | @@ -429,6 +429,7 @@ set(BLAKE_SOURCES | ... | @@ -429,6 +429,7 @@ set(BLAKE_SOURCES |
| 429 | ) | 429 | ) |
| 430 | set(ZIG_CPP_SOURCES | 430 | set(ZIG_CPP_SOURCES |
| 431 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" | 431 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" |
| 432 | "${CMAKE_SOURCE_DIR}/src/zig_clang.cpp" | ||
| 432 | "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp" | 433 | "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp" |
| 433 | ) | 434 | ) |
| 434 | 435 | ||
| ... | @@ -454,10 +455,10 @@ set(ZIG_STD_FILES | ... | @@ -454,10 +455,10 @@ set(ZIG_STD_FILES |
| 454 | "crypto/hmac.zig" | 455 | "crypto/hmac.zig" |
| 455 | "crypto/index.zig" | 456 | "crypto/index.zig" |
| 456 | "crypto/md5.zig" | 457 | "crypto/md5.zig" |
| 458 | "crypto/poly1305.zig" | ||
| 457 | "crypto/sha1.zig" | 459 | "crypto/sha1.zig" |
| 458 | "crypto/sha2.zig" | 460 | "crypto/sha2.zig" |
| 459 | "crypto/sha3.zig" | 461 | "crypto/sha3.zig" |
| 460 | "crypto/poly1305.zig" | ||
| 461 | "crypto/x25519.zig" | 462 | "crypto/x25519.zig" |
| 462 | "cstr.zig" | 463 | "cstr.zig" |
| 463 | "debug/failing_allocator.zig" | 464 | "debug/failing_allocator.zig" |
| ... | @@ -482,6 +483,7 @@ set(ZIG_STD_FILES | ... | @@ -482,6 +483,7 @@ set(ZIG_STD_FILES |
| 482 | "fmt/errol/index.zig" | 483 | "fmt/errol/index.zig" |
| 483 | "fmt/errol/lookup.zig" | 484 | "fmt/errol/lookup.zig" |
| 484 | "fmt/index.zig" | 485 | "fmt/index.zig" |
| 486 | "fmt/parse_float.zig" | ||
| 485 | "hash/adler.zig" | 487 | "hash/adler.zig" |
| 486 | "hash/crc.zig" | 488 | "hash/crc.zig" |
| 487 | "hash/fnv.zig" | 489 | "hash/fnv.zig" |
| ... | @@ -566,9 +568,9 @@ set(ZIG_STD_FILES | ... | @@ -566,9 +568,9 @@ set(ZIG_STD_FILES |
| 566 | "math/tan.zig" | 568 | "math/tan.zig" |
| 567 | "math/tanh.zig" | 569 | "math/tanh.zig" |
| 568 | "math/trunc.zig" | 570 | "math/trunc.zig" |
| 571 | "mem.zig" | ||
| 569 | "meta/index.zig" | 572 | "meta/index.zig" |
| 570 | "meta/trait.zig" | 573 | "meta/trait.zig" |
| 571 | "mem.zig" | ||
| 572 | "mutex.zig" | 574 | "mutex.zig" |
| 573 | "net.zig" | 575 | "net.zig" |
| 574 | "os/child_process.zig" | 576 | "os/child_process.zig" |
| ... | @@ -576,20 +578,19 @@ set(ZIG_STD_FILES | ... | @@ -576,20 +578,19 @@ set(ZIG_STD_FILES |
| 576 | "os/darwin/errno.zig" | 578 | "os/darwin/errno.zig" |
| 577 | "os/epoch.zig" | 579 | "os/epoch.zig" |
| 578 | "os/file.zig" | 580 | "os/file.zig" |
| 581 | "os/freebsd/errno.zig" | ||
| 582 | "os/freebsd/index.zig" | ||
| 579 | "os/get_app_data_dir.zig" | 583 | "os/get_app_data_dir.zig" |
| 580 | "os/get_user_id.zig" | 584 | "os/get_user_id.zig" |
| 581 | "os/index.zig" | 585 | "os/index.zig" |
| 586 | "os/linux/arm64.zig" | ||
| 582 | "os/linux/errno.zig" | 587 | "os/linux/errno.zig" |
| 583 | "os/linux/index.zig" | 588 | "os/linux/index.zig" |
| 584 | "os/linux/vdso.zig" | 589 | "os/linux/vdso.zig" |
| 585 | "os/linux/x86_64.zig" | 590 | "os/linux/x86_64.zig" |
| 586 | "os/linux/arm64.zig" | ||
| 587 | "os/freebsd/errno.zig" | ||
| 588 | "os/freebsd/index.zig" | ||
| 589 | "os/freebsd/syscall.zig" | ||
| 590 | "os/freebsd/x86_64.zig" | ||
| 591 | "os/path.zig" | 591 | "os/path.zig" |
| 592 | "os/time.zig" | 592 | "os/time.zig" |
| 593 | "os/uefi.zig" | ||
| 593 | "os/windows/advapi32.zig" | 594 | "os/windows/advapi32.zig" |
| 594 | "os/windows/error.zig" | 595 | "os/windows/error.zig" |
| 595 | "os/windows/index.zig" | 596 | "os/windows/index.zig" |
| ... | @@ -597,6 +598,7 @@ set(ZIG_STD_FILES | ... | @@ -597,6 +598,7 @@ set(ZIG_STD_FILES |
| 597 | "os/windows/ntdll.zig" | 598 | "os/windows/ntdll.zig" |
| 598 | "os/windows/ole32.zig" | 599 | "os/windows/ole32.zig" |
| 599 | "os/windows/shell32.zig" | 600 | "os/windows/shell32.zig" |
| 601 | "os/windows/tls.zig" | ||
| 600 | "os/windows/util.zig" | 602 | "os/windows/util.zig" |
| 601 | "os/zen.zig" | 603 | "os/zen.zig" |
| 602 | "pdb.zig" | 604 | "pdb.zig" |
| ... | @@ -608,11 +610,22 @@ set(ZIG_STD_FILES | ... | @@ -608,11 +610,22 @@ set(ZIG_STD_FILES |
| 608 | "special/bootstrap_lib.zig" | 610 | "special/bootstrap_lib.zig" |
| 609 | "special/build_runner.zig" | 611 | "special/build_runner.zig" |
| 610 | "special/builtin.zig" | 612 | "special/builtin.zig" |
| 613 | "special/compiler_rt/addXf3.zig" | ||
| 611 | "special/compiler_rt/aulldiv.zig" | 614 | "special/compiler_rt/aulldiv.zig" |
| 612 | "special/compiler_rt/aullrem.zig" | 615 | "special/compiler_rt/aullrem.zig" |
| 613 | "special/compiler_rt/comparetf2.zig" | 616 | "special/compiler_rt/comparetf2.zig" |
| 614 | "special/compiler_rt/divti3.zig" | 617 | "special/compiler_rt/divti3.zig" |
| 615 | "special/compiler_rt/extendXfYf2.zig" | 618 | "special/compiler_rt/extendXfYf2.zig" |
| 619 | "special/compiler_rt/fixdfdi.zig" | ||
| 620 | "special/compiler_rt/fixdfsi.zig" | ||
| 621 | "special/compiler_rt/fixdfti.zig" | ||
| 622 | "special/compiler_rt/fixint.zig" | ||
| 623 | "special/compiler_rt/fixsfdi.zig" | ||
| 624 | "special/compiler_rt/fixsfsi.zig" | ||
| 625 | "special/compiler_rt/fixsfti.zig" | ||
| 626 | "special/compiler_rt/fixtfdi.zig" | ||
| 627 | "special/compiler_rt/fixtfsi.zig" | ||
| 628 | "special/compiler_rt/fixtfti.zig" | ||
| 616 | "special/compiler_rt/fixuint.zig" | 629 | "special/compiler_rt/fixuint.zig" |
| 617 | "special/compiler_rt/fixunsdfdi.zig" | 630 | "special/compiler_rt/fixunsdfdi.zig" |
| 618 | "special/compiler_rt/fixunsdfsi.zig" | 631 | "special/compiler_rt/fixunsdfsi.zig" |
| ... | @@ -640,6 +653,7 @@ set(ZIG_STD_FILES | ... | @@ -640,6 +653,7 @@ set(ZIG_STD_FILES |
| 640 | "special/compiler_rt/udivmodti4.zig" | 653 | "special/compiler_rt/udivmodti4.zig" |
| 641 | "special/compiler_rt/udivti3.zig" | 654 | "special/compiler_rt/udivti3.zig" |
| 642 | "special/compiler_rt/umodti3.zig" | 655 | "special/compiler_rt/umodti3.zig" |
| 656 | "special/fmt_runner.zig" | ||
| 643 | "special/init-exe/build.zig" | 657 | "special/init-exe/build.zig" |
| 644 | "special/init-exe/src/main.zig" | 658 | "special/init-exe/src/main.zig" |
| 645 | "special/init-lib/build.zig" | 659 | "special/init-lib/build.zig" |
| ... | @@ -647,6 +661,8 @@ set(ZIG_STD_FILES | ... | @@ -647,6 +661,8 @@ set(ZIG_STD_FILES |
| 647 | "special/panic.zig" | 661 | "special/panic.zig" |
| 648 | "special/test_runner.zig" | 662 | "special/test_runner.zig" |
| 649 | "spinlock.zig" | 663 | "spinlock.zig" |
| 664 | "statically_initialized_mutex.zig" | ||
| 665 | "testing.zig" | ||
| 650 | "unicode.zig" | 666 | "unicode.zig" |
| 651 | "zig/ast.zig" | 667 | "zig/ast.zig" |
| 652 | "zig/index.zig" | 668 | "zig/index.zig" |
| ... | @@ -891,3 +907,7 @@ foreach(file ${ZIG_STD_FILES}) | ... | @@ -891,3 +907,7 @@ foreach(file ${ZIG_STD_FILES}) |
| 891 | get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY) | 907 | get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY) |
| 892 | install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}") | 908 | install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}") |
| 893 | endforeach() | 909 | endforeach() |
| 910 | |||
| 911 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") | ||
| 912 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") | ||
| 913 | install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/") |
README.md+30-24| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | A programming language designed for robustness, optimality, and | 3 | A programming language designed for robustness, optimality, and |
| 4 | clarity. | 4 | clarity. |
| 5 | 5 | ||
| 6 | [ziglang.org](https://ziglang.org) | 6 | [Download & Documentation](https://ziglang.org/download/) |
| 7 | 7 | ||
| 8 | ## Feature Highlights | 8 | ## Feature Highlights |
| 9 | 9 | ||
| ... | @@ -84,29 +84,32 @@ clarity. | ... | @@ -84,29 +84,32 @@ clarity. |
| 84 | * LLVM may have the target as an experimental target, which means that you | 84 | * LLVM may have the target as an experimental target, which means that you |
| 85 | need to use Zig-provided binaries for the target to be available, or | 85 | need to use Zig-provided binaries for the target to be available, or |
| 86 | build LLVM from source with special configure flags. | 86 | build LLVM from source with special configure flags. |
| 87 | * This target may be considered deprecated by an official party, | ||
| 88 | [such as macosx/i386](https://support.apple.com/en-us/HT208436) in which | ||
| 89 | case this target will remain forever stuck in Tier 4. | ||
| 87 | 90 | ||
| 88 | #### Support Table | 91 | #### Support Table |
| 89 | 92 | ||
| 90 | | | freestanding | linux | macosx | windows | freebsd | other | | 93 | | | freestanding | linux | macosx | windows | freebsd | UEFI | other | |
| 91 | |--------|--------------|--------|--------|---------|---------|--------| | 94 | |--------|--------------|--------|--------|---------|---------|--------|--------| |
| 92 | |x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 | | 95 | |x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 | |
| 93 | |i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | | 96 | |i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | |
| 94 | |arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | 97 | |arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | |
| 95 | |arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | 98 | |arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | |
| 96 | |bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 99 | |bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 97 | |hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 100 | |hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 98 | |mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 101 | |mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 99 | |powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 102 | |powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 100 | |r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 103 | |r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 101 | |amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 104 | |amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 102 | |sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 105 | |sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 103 | |s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 106 | |s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 104 | |spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 107 | |spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 105 | |lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | 108 | |lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 | |
| 106 | |wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | | 109 | |wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | |
| 107 | |wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | | 110 | |wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A | |
| 108 | |riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | | 111 | |riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | |
| 109 | |riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | | 112 | |riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 | |
| 110 | 113 | ||
| 111 | ## Community | 114 | ## Community |
| 112 | 115 | ||
| ... | @@ -171,7 +174,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows | ... | @@ -171,7 +174,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows |
| 171 | *Note: Stage 2 compiler is not complete. Beta users of Zig should use the | 174 | *Note: Stage 2 compiler is not complete. Beta users of Zig should use the |
| 172 | Stage 1 compiler for now.* | 175 | Stage 1 compiler for now.* |
| 173 | 176 | ||
| 174 | Dependencies are the same as Stage 1, except now you have a working zig compiler. | 177 | Dependencies are the same as Stage 1, except now you can use stage 1 to compile |
| 178 | Zig code. | ||
| 175 | 179 | ||
| 176 | ``` | 180 | ``` |
| 177 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install | 181 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install |
| ... | @@ -183,11 +187,13 @@ binary. | ... | @@ -183,11 +187,13 @@ binary. |
| 183 | 187 | ||
| 184 | ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler | 188 | ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler |
| 185 | 189 | ||
| 186 | This is the actual compiler binary that we will install to the system. | ||
| 187 | |||
| 188 | *Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is | 190 | *Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is |
| 189 | not yet supported.* | 191 | not yet supported.* |
| 190 | 192 | ||
| 193 | Once the self-hosted compiler can build itself, this will be the actual | ||
| 194 | compiler binary that we will install to the system. Until then, users should | ||
| 195 | use stage 1. | ||
| 196 | |||
| 191 | #### Debug / Development Build | 197 | #### Debug / Development Build |
| 192 | 198 | ||
| 193 | ``` | 199 | ``` |
build.zig+40-19| ... | @@ -16,7 +16,10 @@ pub fn build(b: *Builder) !void { | ... | @@ -16,7 +16,10 @@ pub fn build(b: *Builder) !void { |
| 16 | var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); | 16 | var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); |
| 17 | 17 | ||
| 18 | const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe); | 18 | const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe); |
| 19 | const langref_out_path = os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable; | 19 | const langref_out_path = os.path.join( |
| 20 | b.allocator, | ||
| 21 | [][]const u8{ b.cache_root, "langref.html" }, | ||
| 22 | ) catch unreachable; | ||
| 20 | var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ | 23 | var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ |
| 21 | docgen_exe.getOutputPath(), | 24 | docgen_exe.getOutputPath(), |
| 22 | rel_zig_exe, | 25 | rel_zig_exe, |
| ... | @@ -104,7 +107,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -104,7 +107,7 @@ pub fn build(b: *Builder) !void { |
| 104 | } | 107 | } |
| 105 | const modes = chosen_modes[0..chosen_mode_index]; | 108 | const modes = chosen_modes[0..chosen_mode_index]; |
| 106 | 109 | ||
| 107 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes)); | 110 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes)); |
| 108 | 111 | ||
| 109 | test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes)); | 112 | test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes)); |
| 110 | 113 | ||
| ... | @@ -125,13 +128,19 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { | ... | @@ -125,13 +128,19 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { |
| 125 | for (dep.libdirs.toSliceConst()) |lib_dir| { | 128 | for (dep.libdirs.toSliceConst()) |lib_dir| { |
| 126 | lib_exe_obj.addLibPath(lib_dir); | 129 | lib_exe_obj.addLibPath(lib_dir); |
| 127 | } | 130 | } |
| 128 | const lib_dir = os.path.join(b.allocator, dep.prefix, "lib") catch unreachable; | 131 | const lib_dir = os.path.join( |
| 132 | b.allocator, | ||
| 133 | [][]const u8{ dep.prefix, "lib" }, | ||
| 134 | ) catch unreachable; | ||
| 129 | for (dep.system_libs.toSliceConst()) |lib| { | 135 | for (dep.system_libs.toSliceConst()) |lib| { |
| 130 | const static_bare_name = if (mem.eql(u8, lib, "curses")) | 136 | const static_bare_name = if (mem.eql(u8, lib, "curses")) |
| 131 | ([]const u8)("libncurses.a") | 137 | ([]const u8)("libncurses.a") |
| 132 | else | 138 | else |
| 133 | b.fmt("lib{}.a", lib); | 139 | b.fmt("lib{}.a", lib); |
| 134 | const static_lib_name = os.path.join(b.allocator, lib_dir, static_bare_name) catch unreachable; | 140 | const static_lib_name = os.path.join( |
| 141 | b.allocator, | ||
| 142 | [][]const u8{ lib_dir, static_bare_name }, | ||
| 143 | ) catch unreachable; | ||
| 135 | const have_static = fileExists(static_lib_name) catch unreachable; | 144 | const have_static = fileExists(static_lib_name) catch unreachable; |
| 136 | if (have_static) { | 145 | if (have_static) { |
| 137 | lib_exe_obj.addObjectFile(static_lib_name); | 146 | lib_exe_obj.addObjectFile(static_lib_name); |
| ... | @@ -159,7 +168,11 @@ fn fileExists(filename: []const u8) !bool { | ... | @@ -159,7 +168,11 @@ fn fileExists(filename: []const u8) !bool { |
| 159 | 168 | ||
| 160 | fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void { | 169 | fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void { |
| 161 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; | 170 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; |
| 162 | lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); | 171 | lib_exe_obj.addObjectFile(os.path.join(b.allocator, [][]const u8{ |
| 172 | cmake_binary_dir, | ||
| 173 | "zig_cpp", | ||
| 174 | b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt()), | ||
| 175 | }) catch unreachable); | ||
| 163 | } | 176 | } |
| 164 | 177 | ||
| 165 | const LibraryDep = struct { | 178 | const LibraryDep = struct { |
| ... | @@ -189,14 +202,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { | ... | @@ -189,14 +202,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { |
| 189 | const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" }); | 202 | const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" }); |
| 190 | 203 | ||
| 191 | var result = LibraryDep{ | 204 | var result = LibraryDep{ |
| 192 | .prefix = mem.split(prefix_output, " \r\n").next().?, | 205 | .prefix = mem.tokenize(prefix_output, " \r\n").next().?, |
| 193 | .libs = ArrayList([]const u8).init(b.allocator), | 206 | .libs = ArrayList([]const u8).init(b.allocator), |
| 194 | .system_libs = ArrayList([]const u8).init(b.allocator), | 207 | .system_libs = ArrayList([]const u8).init(b.allocator), |
| 195 | .includes = ArrayList([]const u8).init(b.allocator), | 208 | .includes = ArrayList([]const u8).init(b.allocator), |
| 196 | .libdirs = ArrayList([]const u8).init(b.allocator), | 209 | .libdirs = ArrayList([]const u8).init(b.allocator), |
| 197 | }; | 210 | }; |
| 198 | { | 211 | { |
| 199 | var it = mem.split(libs_output, " \r\n"); | 212 | var it = mem.tokenize(libs_output, " \r\n"); |
| 200 | while (it.next()) |lib_arg| { | 213 | while (it.next()) |lib_arg| { |
| 201 | if (mem.startsWith(u8, lib_arg, "-l")) { | 214 | if (mem.startsWith(u8, lib_arg, "-l")) { |
| 202 | try result.system_libs.append(lib_arg[2..]); | 215 | try result.system_libs.append(lib_arg[2..]); |
| ... | @@ -210,7 +223,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { | ... | @@ -210,7 +223,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { |
| 210 | } | 223 | } |
| 211 | } | 224 | } |
| 212 | { | 225 | { |
| 213 | var it = mem.split(includes_output, " \r\n"); | 226 | var it = mem.tokenize(includes_output, " \r\n"); |
| 214 | while (it.next()) |include_arg| { | 227 | while (it.next()) |include_arg| { |
| 215 | if (mem.startsWith(u8, include_arg, "-I")) { | 228 | if (mem.startsWith(u8, include_arg, "-I")) { |
| 216 | try result.includes.append(include_arg[2..]); | 229 | try result.includes.append(include_arg[2..]); |
| ... | @@ -220,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { | ... | @@ -220,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { |
| 220 | } | 233 | } |
| 221 | } | 234 | } |
| 222 | { | 235 | { |
| 223 | var it = mem.split(libdir_output, " \r\n"); | 236 | var it = mem.tokenize(libdir_output, " \r\n"); |
| 224 | while (it.next()) |libdir| { | 237 | while (it.next()) |libdir| { |
| 225 | if (mem.startsWith(u8, libdir, "-L")) { | 238 | if (mem.startsWith(u8, libdir, "-L")) { |
| 226 | try result.libdirs.append(libdir[2..]); | 239 | try result.libdirs.append(libdir[2..]); |
| ... | @@ -233,19 +246,25 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { | ... | @@ -233,19 +246,25 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { |
| 233 | } | 246 | } |
| 234 | 247 | ||
| 235 | pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void { | 248 | pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void { |
| 236 | var it = mem.split(stdlib_files, ";"); | 249 | var it = mem.tokenize(stdlib_files, ";"); |
| 237 | while (it.next()) |stdlib_file| { | 250 | while (it.next()) |stdlib_file| { |
| 238 | const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable; | 251 | const src_path = os.path.join(b.allocator, [][]const u8{ "std", stdlib_file }) catch unreachable; |
| 239 | const dest_path = os.path.join(b.allocator, "lib", "zig", "std", stdlib_file) catch unreachable; | 252 | const dest_path = os.path.join( |
| 253 | b.allocator, | ||
| 254 | [][]const u8{ "lib", "zig", "std", stdlib_file }, | ||
| 255 | ) catch unreachable; | ||
| 240 | b.installFile(src_path, dest_path); | 256 | b.installFile(src_path, dest_path); |
| 241 | } | 257 | } |
| 242 | } | 258 | } |
| 243 | 259 | ||
| 244 | pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void { | 260 | pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void { |
| 245 | var it = mem.split(c_header_files, ";"); | 261 | var it = mem.tokenize(c_header_files, ";"); |
| 246 | while (it.next()) |c_header_file| { | 262 | while (it.next()) |c_header_file| { |
| 247 | const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable; | 263 | const src_path = os.path.join(b.allocator, [][]const u8{ "c_headers", c_header_file }) catch unreachable; |
| 248 | const dest_path = os.path.join(b.allocator, "lib", "zig", "include", c_header_file) catch unreachable; | 264 | const dest_path = os.path.join( |
| 265 | b.allocator, | ||
| 266 | [][]const u8{ "lib", "zig", "include", c_header_file }, | ||
| 267 | ) catch unreachable; | ||
| 249 | b.installFile(src_path, dest_path); | 268 | b.installFile(src_path, dest_path); |
| 250 | } | 269 | } |
| 251 | } | 270 | } |
| ... | @@ -277,7 +296,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | ... | @@ -277,7 +296,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 277 | addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp"); | 296 | addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp"); |
| 278 | if (ctx.lld_include_dir.len != 0) { | 297 | if (ctx.lld_include_dir.len != 0) { |
| 279 | exe.addIncludeDir(ctx.lld_include_dir); | 298 | exe.addIncludeDir(ctx.lld_include_dir); |
| 280 | var it = mem.split(ctx.lld_libraries, ";"); | 299 | var it = mem.tokenize(ctx.lld_libraries, ";"); |
| 281 | while (it.next()) |lib| { | 300 | while (it.next()) |lib| { |
| 282 | exe.addObjectFile(lib); | 301 | exe.addObjectFile(lib); |
| 283 | } | 302 | } |
| ... | @@ -293,11 +312,13 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | ... | @@ -293,11 +312,13 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 293 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", | 312 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", |
| 294 | \\Unable to determine path to libstdc++.a | 313 | \\Unable to determine path to libstdc++.a |
| 295 | \\On Fedora, install libstdc++-static and try again. | 314 | \\On Fedora, install libstdc++-static and try again. |
| 296 | \\ | ||
| 297 | ); | 315 | ); |
| 298 | 316 | ||
| 299 | exe.linkSystemLibrary("pthread"); | 317 | exe.linkSystemLibrary("pthread"); |
| 300 | } else if (exe.target.isDarwin() or exe.target.isFreeBSD()) { | 318 | } else if (exe.target.isFreeBSD()) { |
| 319 | try addCxxKnownPath(b, ctx, exe, "libc++.a", null); | ||
| 320 | exe.linkSystemLibrary("pthread"); | ||
| 321 | } else if (exe.target.isDarwin()) { | ||
| 301 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { | 322 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { |
| 302 | // Compiler is GCC. | 323 | // Compiler is GCC. |
| 303 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); | 324 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); |
| ... | @@ -332,7 +353,7 @@ fn addCxxKnownPath( | ... | @@ -332,7 +353,7 @@ fn addCxxKnownPath( |
| 332 | ctx.cxx_compiler, | 353 | ctx.cxx_compiler, |
| 333 | b.fmt("-print-file-name={}", objname), | 354 | b.fmt("-print-file-name={}", objname), |
| 334 | }); | 355 | }); |
| 335 | const path_unpadded = mem.split(path_padded, "\r\n").next().?; | 356 | const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?; |
| 336 | if (mem.eql(u8, path_unpadded, objname)) { | 357 | if (mem.eql(u8, path_unpadded, objname)) { |
| 337 | if (errtxt) |msg| { | 358 | if (errtxt) |msg| { |
| 338 | warn("{}", msg); | 359 | warn("{}", msg); |
ci/azure/windows_install+1| ... | @@ -3,6 +3,7 @@ | ... | @@ -3,6 +3,7 @@ |
| 3 | set -x | 3 | set -x |
| 4 | set -e | 4 | set -e |
| 5 | 5 | ||
| 6 | pacman -Su --needed --noconfirm | ||
| 6 | pacman -S --needed --noconfirm wget p7zip python3-pip | 7 | pacman -S --needed --noconfirm wget p7zip python3-pip |
| 7 | pip install s3cmd | 8 | pip install s3cmd |
| 8 | wget -nv "https://ziglang.org/deps/llvm%2bclang-7.0.0-win64-msvc-release.tar.xz" | 9 | wget -nv "https://ziglang.org/deps/llvm%2bclang-7.0.0-win64-msvc-release.tar.xz" |
cmake/Findllvm.cmake+45| ... | @@ -15,6 +15,51 @@ find_program(LLVM_CONFIG_EXE | ... | @@ -15,6 +15,51 @@ find_program(LLVM_CONFIG_EXE |
| 15 | "c:/msys64/mingw64/bin" | 15 | "c:/msys64/mingw64/bin" |
| 16 | "C:/Libraries/llvm-7.0.0/bin") | 16 | "C:/Libraries/llvm-7.0.0/bin") |
| 17 | 17 | ||
| 18 | if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND") | ||
| 19 | message(FATAL_ERROR "unable to find llvm-config") | ||
| 20 | endif() | ||
| 21 | |||
| 22 | execute_process( | ||
| 23 | 	COMMAND ${LLVM_CONFIG_EXE} --version | ||
| 24 | 	OUTPUT_VARIABLE LLVM_CONFIG_VERSION | ||
| 25 | 	OUTPUT_STRIP_TRAILING_WHITESPACE) | ||
| 26 | |||
| 27 | if("${LLVM_CONFIG_VERSION}" VERSION_LESS 7) | ||
| 28 | message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}") | ||
| 29 | endif() | ||
| 30 | if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 8) | ||
| 31 | message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}") | ||
| 32 | endif() | ||
| 33 | if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 8) | ||
| 34 | message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}") | ||
| 35 | endif() | ||
| 36 | |||
| 37 | execute_process( | ||
| 38 | 	COMMAND ${LLVM_CONFIG_EXE} --targets-built | ||
| 39 | OUTPUT_VARIABLE LLVM_TARGETS_BUILT_SPACES | ||
| 40 | 	OUTPUT_STRIP_TRAILING_WHITESPACE) | ||
| 41 | string(REPLACE " " ";" LLVM_TARGETS_BUILT "${LLVM_TARGETS_BUILT_SPACES}") | ||
| 42 | function(NEED_TARGET TARGET_NAME) | ||
| 43 | list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index) | ||
| 44 | if (${_index} EQUAL -1) | ||
| 45 | message(FATAL_ERROR "LLVM is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.") | ||
| 46 | endif() | ||
| 47 | endfunction(NEED_TARGET) | ||
| 48 | NEED_TARGET("AArch64") | ||
| 49 | NEED_TARGET("AMDGPU") | ||
| 50 | NEED_TARGET("ARM") | ||
| 51 | NEED_TARGET("BPF") | ||
| 52 | NEED_TARGET("Hexagon") | ||
| 53 | NEED_TARGET("Lanai") | ||
| 54 | NEED_TARGET("Mips") | ||
| 55 | NEED_TARGET("MSP430") | ||
| 56 | NEED_TARGET("NVPTX") | ||
| 57 | NEED_TARGET("PowerPC") | ||
| 58 | NEED_TARGET("Sparc") | ||
| 59 | NEED_TARGET("SystemZ") | ||
| 60 | NEED_TARGET("X86") | ||
| 61 | NEED_TARGET("XCore") | ||
| 62 | |||
| 18 | if(NOT(CMAKE_BUILD_TYPE STREQUAL "Debug") OR ZIG_STATIC) | 63 | if(NOT(CMAKE_BUILD_TYPE STREQUAL "Debug") OR ZIG_STATIC) |
| 19 | execute_process( | 64 | execute_process( |
| 20 | COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static | 65 | COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static |
doc/docgen.zig+24-7| ... | @@ -4,7 +4,7 @@ const io = std.io; | ... | @@ -4,7 +4,7 @@ const io = std.io; |
| 4 | const os = std.os; | 4 | const os = std.os; |
| 5 | const warn = std.debug.warn; | 5 | const warn = std.debug.warn; |
| 6 | const mem = std.mem; | 6 | const mem = std.mem; |
| 7 | const assert = std.debug.assert; | 7 | const testing = std.testing; |
| 8 | 8 | ||
| 9 | const max_doc_file_size = 10 * 1024 * 1024; | 9 | const max_doc_file_size = 10 * 1024 * 1024; |
| 10 | 10 | ||
| ... | @@ -620,7 +620,7 @@ const TermState = enum { | ... | @@ -620,7 +620,7 @@ const TermState = enum { |
| 620 | test "term color" { | 620 | test "term color" { |
| 621 | const input_bytes = "A\x1b[32;1mgreen\x1b[0mB"; | 621 | const input_bytes = "A\x1b[32;1mgreen\x1b[0mB"; |
| 622 | const result = try termColor(std.debug.global_allocator, input_bytes); | 622 | const result = try termColor(std.debug.global_allocator, input_bytes); |
| 623 | assert(mem.eql(u8, result, "A<span class=\"t32\">green</span>B")); | 623 | testing.expectEqualSlices(u8, "A<span class=\"t32\">green</span>B", result); |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 { | 626 | fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 { |
| ... | @@ -770,6 +770,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok | ... | @@ -770,6 +770,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 770 | std.zig.Token.Id.Keyword_suspend, | 770 | std.zig.Token.Id.Keyword_suspend, |
| 771 | std.zig.Token.Id.Keyword_switch, | 771 | std.zig.Token.Id.Keyword_switch, |
| 772 | std.zig.Token.Id.Keyword_test, | 772 | std.zig.Token.Id.Keyword_test, |
| 773 | std.zig.Token.Id.Keyword_threadlocal, | ||
| 773 | std.zig.Token.Id.Keyword_try, | 774 | std.zig.Token.Id.Keyword_try, |
| 774 | std.zig.Token.Id.Keyword_union, | 775 | std.zig.Token.Id.Keyword_union, |
| 775 | std.zig.Token.Id.Keyword_unreachable, | 776 | std.zig.Token.Id.Keyword_unreachable, |
| ... | @@ -915,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok | ... | @@ -915,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 915 | std.zig.Token.Id.AngleBracketAngleBracketRightEqual, | 916 | std.zig.Token.Id.AngleBracketAngleBracketRightEqual, |
| 916 | std.zig.Token.Id.Tilde, | 917 | std.zig.Token.Id.Tilde, |
| 917 | std.zig.Token.Id.BracketStarBracket, | 918 | std.zig.Token.Id.BracketStarBracket, |
| 919 | std.zig.Token.Id.BracketStarCBracket, | ||
| 918 | => try writeEscaped(out, src[token.start..token.end]), | 920 | => try writeEscaped(out, src[token.start..token.end]), |
| 919 | 921 | ||
| 920 | std.zig.Token.Id.Invalid => return parseError( | 922 | std.zig.Token.Id.Invalid => return parseError( |
| ... | @@ -990,13 +992,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -990,13 +992,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 990 | try tokenizeAndPrint(tokenizer, out, code.source_token); | 992 | try tokenizeAndPrint(tokenizer, out, code.source_token); |
| 991 | try out.write("</pre>"); | 993 | try out.write("</pre>"); |
| 992 | const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); | 994 | const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); |
| 993 | const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext); | 995 | const tmp_source_file_name = try os.path.join( |
| 996 | allocator, | ||
| 997 | [][]const u8{ tmp_dir_name, name_plus_ext }, | ||
| 998 | ); | ||
| 994 | try io.writeFile(tmp_source_file_name, trimmed_raw_source); | 999 | try io.writeFile(tmp_source_file_name, trimmed_raw_source); |
| 995 | 1000 | ||
| 996 | switch (code.id) { | 1001 | switch (code.id) { |
| 997 | Code.Id.Exe => |expected_outcome| { | 1002 | Code.Id.Exe => |expected_outcome| { |
| 998 | const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext); | 1003 | const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext); |
| 999 | const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext); | 1004 | const tmp_bin_file_name = try os.path.join( |
| 1005 | allocator, | ||
| 1006 | [][]const u8{ tmp_dir_name, name_plus_bin_ext }, | ||
| 1007 | ); | ||
| 1000 | var build_args = std.ArrayList([]const u8).init(allocator); | 1008 | var build_args = std.ArrayList([]const u8).init(allocator); |
| 1001 | defer build_args.deinit(); | 1009 | defer build_args.deinit(); |
| 1002 | try build_args.appendSlice([][]const u8{ | 1010 | try build_args.appendSlice([][]const u8{ |
| ... | @@ -1024,7 +1032,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -1024,7 +1032,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1024 | } | 1032 | } |
| 1025 | for (code.link_objects) |link_object| { | 1033 | for (code.link_objects) |link_object| { |
| 1026 | const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext); | 1034 | const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext); |
| 1027 | const full_path_object = try os.path.join(allocator, tmp_dir_name, name_with_ext); | 1035 | const full_path_object = try os.path.join( |
| 1036 | allocator, | ||
| 1037 | [][]const u8{ tmp_dir_name, name_with_ext }, | ||
| 1038 | ); | ||
| 1028 | try build_args.append("--object"); | 1039 | try build_args.append("--object"); |
| 1029 | try build_args.append(full_path_object); | 1040 | try build_args.append(full_path_object); |
| 1030 | try out.print(" --object {}", name_with_ext); | 1041 | try out.print(" --object {}", name_with_ext); |
| ... | @@ -1216,12 +1227,18 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -1216,12 +1227,18 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1216 | }, | 1227 | }, |
| 1217 | Code.Id.Obj => |maybe_error_match| { | 1228 | Code.Id.Obj => |maybe_error_match| { |
| 1218 | const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext); | 1229 | const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext); |
| 1219 | const tmp_obj_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_obj_ext); | 1230 | const tmp_obj_file_name = try os.path.join( |
| 1231 | allocator, | ||
| 1232 | [][]const u8{ tmp_dir_name, name_plus_obj_ext }, | ||
| 1233 | ); | ||
| 1220 | var build_args = std.ArrayList([]const u8).init(allocator); | 1234 | var build_args = std.ArrayList([]const u8).init(allocator); |
| 1221 | defer build_args.deinit(); | 1235 | defer build_args.deinit(); |
| 1222 | 1236 | ||
| 1223 | const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name); | 1237 | const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name); |
| 1224 | const output_h_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_h_ext); | 1238 | const output_h_file_name = try os.path.join( |
| 1239 | allocator, | ||
| 1240 | [][]const u8{ tmp_dir_name, name_plus_h_ext }, | ||
| 1241 | ); | ||
| 1225 | 1242 | ||
| 1226 | try build_args.appendSlice([][]const u8{ | 1243 | try build_args.appendSlice([][]const u8{ |
| 1227 | zig_exe, | 1244 | zig_exe, |
doc/langref.html.in+280-85| ... | @@ -165,7 +165,7 @@ const std = @import("std"); | ... | @@ -165,7 +165,7 @@ const std = @import("std"); |
| 165 | 165 | ||
| 166 | pub fn main() !void { | 166 | pub fn main() !void { |
| 167 | // If this program is run without stdout attached, exit with an error. | 167 | // If this program is run without stdout attached, exit with an error. |
| 168 | var stdout_file = try std.io.getStdOut(); | 168 | const stdout_file = try std.io.getStdOut(); |
| 169 | // If this program encounters pipe failure when printing to stdout, exit | 169 | // If this program encounters pipe failure when printing to stdout, exit |
| 170 | // with an error. | 170 | // with an error. |
| 171 | try stdout_file.write("Hello, world!\n"); | 171 | try stdout_file.write("Hello, world!\n"); |
| ... | @@ -1531,6 +1531,29 @@ test "array initialization with function calls" { | ... | @@ -1531,6 +1531,29 @@ test "array initialization with function calls" { |
| 1531 | {#code_end#} | 1531 | {#code_end#} |
| 1532 | {#see_also|for|Slices#} | 1532 | {#see_also|for|Slices#} |
| 1533 | {#header_close#} | 1533 | {#header_close#} |
| 1534 | |||
| 1535 | {#header_open|Vectors#} | ||
| 1536 | <p> | ||
| 1537 | A vector is a group of {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on | ||
| 1538 | in parallel using a single instruction ({#link|SIMD#}). Vector types are created with the builtin | ||
| 1539 | function {#link|@Vector#}. | ||
| 1540 | </p> | ||
| 1541 | <p> | ||
| 1542 | TODO talk about C ABI interop | ||
| 1543 | </p> | ||
| 1544 | {#header_open|SIMD#} | ||
| 1545 | <p> | ||
| 1546 | TODO Zig's SIMD abilities are just beginning to be fleshed out. Here are some talking points to update the | ||
| 1547 | docs with: | ||
| 1548 | * What kind of operations can you do? All the operations on integers and floats? What about mixing scalar and vector? | ||
| 1549 | * How to convert to/from vectors/arrays | ||
| 1550 | * How to access individual elements from vectors, how to loop over the elements | ||
| 1551 | * "shuffle" | ||
| 1552 | * Advice on writing high perf software, how to abstract the best way | ||
| 1553 | </p> | ||
| 1554 | {#header_close#} | ||
| 1555 | {#header_close#} | ||
| 1556 | |||
| 1534 | {#header_open|Pointers#} | 1557 | {#header_open|Pointers#} |
| 1535 | <p> | 1558 | <p> |
| 1536 | Zig has two kinds of pointers: | 1559 | Zig has two kinds of pointers: |
| ... | @@ -1671,7 +1694,7 @@ test "comptime @intToPtr" { | ... | @@ -1671,7 +1694,7 @@ test "comptime @intToPtr" { |
| 1671 | } | 1694 | } |
| 1672 | } | 1695 | } |
| 1673 | {#code_end#} | 1696 | {#code_end#} |
| 1674 | {#see_also|Optional Pointers#} | 1697 | {#see_also|Optional Pointers|@intToPtr|@ptrToInt#} |
| 1675 | {#header_open|volatile#} | 1698 | {#header_open|volatile#} |
| 1676 | <p>Loads and stores are assumed to not have side effects. If a given load or store | 1699 | <p>Loads and stores are assumed to not have side effects. If a given load or store |
| 1677 | should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}. | 1700 | should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}. |
| ... | @@ -1800,7 +1823,9 @@ fn foo(bytes: []u8) u32 { | ... | @@ -1800,7 +1823,9 @@ fn foo(bytes: []u8) u32 { |
| 1800 | } | 1823 | } |
| 1801 | {#code_end#} | 1824 | {#code_end#} |
| 1802 | {#header_close#} | 1825 | {#header_close#} |
| 1826 | {#see_also|C Pointers#} | ||
| 1803 | {#header_close#} | 1827 | {#header_close#} |
| 1828 | |||
| 1804 | {#header_open|Slices#} | 1829 | {#header_open|Slices#} |
| 1805 | {#code_begin|test_safety|index out of bounds#} | 1830 | {#code_begin|test_safety|index out of bounds#} |
| 1806 | const assert = @import("std").debug.assert; | 1831 | const assert = @import("std").debug.assert; |
| ... | @@ -3169,7 +3194,16 @@ fn foo() void { } | ... | @@ -3169,7 +3194,16 @@ fn foo() void { } |
| 3169 | {#code_end#} | 3194 | {#code_end#} |
| 3170 | {#header_open|Pass-by-value Parameters#} | 3195 | {#header_open|Pass-by-value Parameters#} |
| 3171 | <p> | 3196 | <p> |
| 3172 | In Zig, structs, unions, and enums with payloads can be passed directly to a function: | 3197 | Primitive types such as {#link|Integers#} and {#link|Floats#} passed as parameters |
| 3198 | are copied, and then the copy is available in the function body. This is called "passing by value". | ||
| 3199 | Copying a primitive type is essentially free and typically involves nothing more than | ||
| 3200 | setting a register. | ||
| 3201 | </p> | ||
| 3202 | <p> | ||
| 3203 | Structs, unions, and arrays can sometimes be more efficiently passed as a reference, since a copy | ||
| 3204 | could be arbitrarily expensive depending on the size. When these types are passed | ||
| 3205 | as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way | ||
| 3206 | Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable. | ||
| 3173 | </p> | 3207 | </p> |
| 3174 | {#code_begin|test#} | 3208 | {#code_begin|test#} |
| 3175 | const Point = struct { | 3209 | const Point = struct { |
| ... | @@ -3178,20 +3212,20 @@ const Point = struct { | ... | @@ -3178,20 +3212,20 @@ const Point = struct { |
| 3178 | }; | 3212 | }; |
| 3179 | 3213 | ||
| 3180 | fn foo(point: Point) i32 { | 3214 | fn foo(point: Point) i32 { |
| 3215 | // Here, `point` could be a reference, or a copy. The function body | ||
| 3216 | // can ignore the difference and treat it as a value. Be very careful | ||
| 3217 | // taking the address of the parameter - it should be treated as if | ||
| 3218 | // the address will become invalid when the function returns. | ||
| 3181 | return point.x + point.y; | 3219 | return point.x + point.y; |
| 3182 | } | 3220 | } |
| 3183 | 3221 | ||
| 3184 | const assert = @import("std").debug.assert; | 3222 | const assert = @import("std").debug.assert; |
| 3185 | 3223 | ||
| 3186 | test "pass aggregate type by non-copy value to function" { | 3224 | test "pass struct to function" { |
| 3187 | assert(foo(Point{ .x = 1, .y = 2 }) == 3); | 3225 | assert(foo(Point{ .x = 1, .y = 2 }) == 3); |
| 3188 | } | 3226 | } |
| 3189 | {#code_end#} | 3227 | {#code_end#} |
| 3190 | <p> | 3228 | <p> |
| 3191 | In this case, the value may be passed by reference, or by value, whichever way | ||
| 3192 | Zig decides will be faster. | ||
| 3193 | </p> | ||
| 3194 | <p> | ||
| 3195 | For extern functions, Zig follows the C ABI for passing structs and unions by value. | 3229 | For extern functions, Zig follows the C ABI for passing structs and unions by value. |
| 3196 | </p> | 3230 | </p> |
| 3197 | {#header_close#} | 3231 | {#header_close#} |
| ... | @@ -3949,7 +3983,7 @@ test "implicit cast - invoke a type as a function" { | ... | @@ -3949,7 +3983,7 @@ test "implicit cast - invoke a type as a function" { |
| 3949 | {#code_end#} | 3983 | {#code_end#} |
| 3950 | <p> | 3984 | <p> |
| 3951 | Implicit casts are only allowed when it is completely unambiguous how to get from one type to another, | 3985 | Implicit casts are only allowed when it is completely unambiguous how to get from one type to another, |
| 3952 | and the transformation is guaranteed to be safe. | 3986 | and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}. |
| 3953 | </p> | 3987 | </p> |
| 3954 | {#header_open|Implicit Cast: Stricter Qualification#} | 3988 | {#header_open|Implicit Cast: Stricter Qualification#} |
| 3955 | <p> | 3989 | <p> |
| ... | @@ -4327,7 +4361,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 { | ... | @@ -4327,7 +4361,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 { |
| 4327 | <p> | 4361 | <p> |
| 4328 | For example, if we were to introduce another function to the above snippet: | 4362 | For example, if we were to introduce another function to the above snippet: |
| 4329 | </p> | 4363 | </p> |
| 4330 | {#code_begin|test_err|unable to evaluate constant expression#} | 4364 | {#code_begin|test_err|values of type 'type' must be comptime known#} |
| 4331 | fn max(comptime T: type, a: T, b: T) T { | 4365 | fn max(comptime T: type, a: T, b: T) T { |
| 4332 | return if (a > b) a else b; | 4366 | return if (a > b) a else b; |
| 4333 | } | 4367 | } |
| ... | @@ -4595,7 +4629,7 @@ test "fibonacci" { | ... | @@ -4595,7 +4629,7 @@ test "fibonacci" { |
| 4595 | <p> | 4629 | <p> |
| 4596 | What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line? | 4630 | What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line? |
| 4597 | </p> | 4631 | </p> |
| 4598 | {#code_begin|test_err|encountered @panic at compile-time#} | 4632 | {#code_begin|test_err|unable to evaluate constant expression#} |
| 4599 | const assert = @import("std").debug.assert; | 4633 | const assert = @import("std").debug.assert; |
| 4600 | 4634 | ||
| 4601 | fn fibonacci(index: i32) i32 { | 4635 | fn fibonacci(index: i32) i32 { |
| ... | @@ -5169,6 +5203,34 @@ fn seq(c: u8) void { | ... | @@ -5169,6 +5203,34 @@ fn seq(c: u8) void { |
| 5169 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. | 5203 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 5170 | </p> | 5204 | </p> |
| 5171 | {#header_close#} | 5205 | {#header_close#} |
| 5206 | {#header_open|@alignCast#} | ||
| 5207 | <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre> | ||
| 5208 | <p> | ||
| 5209 | {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#}, | ||
| 5210 | {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#} | ||
| 5211 | except with the alignment adjusted to the new value. | ||
| 5212 | </p> | ||
| 5213 | <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added | ||
| 5214 | to the generated code to make sure the pointer is aligned as promised.</p> | ||
| 5215 | |||
| 5216 | {#header_close#} | ||
| 5217 | {#header_open|@alignOf#} | ||
| 5218 | <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre> | ||
| 5219 | <p> | ||
| 5220 | This function returns the number of bytes that this type should be aligned to | ||
| 5221 | for the current target to match the C ABI. When the child type of a pointer has | ||
| 5222 | this alignment, the alignment can be omitted from the type. | ||
| 5223 | </p> | ||
| 5224 | <pre>{#syntax#}const assert = @import("std").debug.assert; | ||
| 5225 | comptime { | ||
| 5226 | assert(*u32 == *align(@alignOf(u32)) u32); | ||
| 5227 | }{#endsyntax#}</pre> | ||
| 5228 | <p> | ||
| 5229 | The result is a target-specific compile time constant. It is guaranteed to be | ||
| 5230 | less than or equal to {#link|@sizeOf(T)|@sizeOf#}. | ||
| 5231 | </p> | ||
| 5232 | {#see_also|Alignment#} | ||
| 5233 | {#header_close#} | ||
| 5172 | {#header_open|@ArgType#} | 5234 | {#header_open|@ArgType#} |
| 5173 | <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre> | 5235 | <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre> |
| 5174 | <p> | 5236 | <p> |
| ... | @@ -5241,6 +5303,7 @@ fn seq(c: u8) void { | ... | @@ -5241,6 +5303,7 @@ fn seq(c: u8) void { |
| 5241 | Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works. | 5303 | Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works. |
| 5242 | </p> | 5304 | </p> |
| 5243 | {#header_close#} | 5305 | {#header_close#} |
| 5306 | |||
| 5244 | {#header_open|@bitOffsetOf#} | 5307 | {#header_open|@bitOffsetOf#} |
| 5245 | <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> | 5308 | <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> |
| 5246 | <p> | 5309 | <p> |
| ... | @@ -5253,6 +5316,19 @@ fn seq(c: u8) void { | ... | @@ -5253,6 +5316,19 @@ fn seq(c: u8) void { |
| 5253 | </p> | 5316 | </p> |
| 5254 | {#see_also|@byteOffsetOf#} | 5317 | {#see_also|@byteOffsetOf#} |
| 5255 | {#header_close#} | 5318 | {#header_close#} |
| 5319 | |||
| 5320 | {#header_open|@boolToInt#} | ||
| 5321 | <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre> | ||
| 5322 | <p> | ||
| 5323 | Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to | ||
| 5324 | {#syntax#}u1(0){#endsyntax#}. | ||
| 5325 | </p> | ||
| 5326 | <p> | ||
| 5327 | If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#} | ||
| 5328 | instead of {#syntax#}u1{#endsyntax#}. | ||
| 5329 | </p> | ||
| 5330 | {#header_close#} | ||
| 5331 | |||
| 5256 | {#header_open|@breakpoint#} | 5332 | {#header_open|@breakpoint#} |
| 5257 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> | 5333 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> |
| 5258 | <p> | 5334 | <p> |
| ... | @@ -5264,52 +5340,34 @@ fn seq(c: u8) void { | ... | @@ -5264,52 +5340,34 @@ fn seq(c: u8) void { |
| 5264 | </p> | 5340 | </p> |
| 5265 | 5341 | ||
| 5266 | {#header_close#} | 5342 | {#header_close#} |
| 5267 | {#header_open|@byteOffsetOf#} | 5343 | |
| 5268 | <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> | 5344 | {#header_open|@bswap#} |
| 5345 | <pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre> | ||
| 5346 | <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p> | ||
| 5269 | <p> | 5347 | <p> |
| 5270 | Returns the byte offset of a field relative to its containing struct. | 5348 | Swaps the byte order of the integer. This converts a big endian integer to a little endian integer, |
| 5349 | and converts a little endian integer to a big endian integer. | ||
| 5271 | </p> | 5350 | </p> |
| 5272 | {#see_also|@bitOffsetOf#} | ||
| 5273 | {#header_close#} | 5351 | {#header_close#} |
| 5274 | {#header_open|@alignCast#} | ||
| 5275 | <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre> | ||
| 5276 | <p> | ||
| 5277 | {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#}, | ||
| 5278 | {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#} | ||
| 5279 | except with the alignment adjusted to the new value. | ||
| 5280 | </p> | ||
| 5281 | <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added | ||
| 5282 | to the generated code to make sure the pointer is aligned as promised.</p> | ||
| 5283 | 5352 | ||
| 5284 | {#header_close#} | 5353 | {#header_open|@bitreverse#} |
| 5285 | {#header_open|@alignOf#} | 5354 | <pre>{#syntax#}@bitreverse(comptime T: type, value: T) T{#endsyntax#}</pre> |
| 5286 | <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre> | 5355 | <p>{#syntax#}T{#endsyntax#} accepts any integer type.</p> |
| 5287 | <p> | 5356 | <p> |
| 5288 | This function returns the number of bytes that this type should be aligned to | 5357 | Reverses the bitpattern of an integer value, including the sign bit if applicable. |
| 5289 | for the current target to match the C ABI. When the child type of a pointer has | ||
| 5290 | this alignment, the alignment can be omitted from the type. | ||
| 5291 | </p> | 5358 | </p> |
| 5292 | <pre>{#syntax#}const assert = @import("std").debug.assert; | ||
| 5293 | comptime { | ||
| 5294 | assert(*u32 == *align(@alignOf(u32)) u32); | ||
| 5295 | }{#endsyntax#}</pre> | ||
| 5296 | <p> | 5359 | <p> |
| 5297 | The result is a target-specific compile time constant. It is guaranteed to be | 5360 | For example 0b10110110 ({#syntax#}u8 = 182{#endsyntax#}, {#syntax#}i8 = -74{#endsyntax#}) |
| 5298 | less than or equal to {#link|@sizeOf(T)|@sizeOf#}. | 5361 | becomes 0b01101101 ({#syntax#}u8 = 109{#endsyntax#}, {#syntax#}i8 = 109{#endsyntax#}). |
| 5299 | </p> | 5362 | </p> |
| 5300 | {#see_also|Alignment#} | ||
| 5301 | {#header_close#} | 5363 | {#header_close#} |
| 5302 | 5364 | ||
| 5303 | {#header_open|@boolToInt#} | 5365 | {#header_open|@byteOffsetOf#} |
| 5304 | <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre> | 5366 | <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> |
| 5305 | <p> | ||
| 5306 | Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to | ||
| 5307 | {#syntax#}u1(0){#endsyntax#}. | ||
| 5308 | </p> | ||
| 5309 | <p> | 5367 | <p> |
| 5310 | If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#} | 5368 | Returns the byte offset of a field relative to its containing struct. |
| 5311 | instead of {#syntax#}u1{#endsyntax#}. | ||
| 5312 | </p> | 5369 | </p> |
| 5370 | {#see_also|@bitOffsetOf#} | ||
| 5313 | {#header_close#} | 5371 | {#header_close#} |
| 5314 | 5372 | ||
| 5315 | {#header_open|@bytesToSlice#} | 5373 | {#header_open|@bytesToSlice#} |
| ... | @@ -5378,17 +5436,7 @@ comptime { | ... | @@ -5378,17 +5436,7 @@ comptime { |
| 5378 | </p> | 5436 | </p> |
| 5379 | {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#} | 5437 | {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#} |
| 5380 | {#header_close#} | 5438 | {#header_close#} |
| 5381 | {#header_open|@cUndef#} | 5439 | |
| 5382 | <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre> | ||
| 5383 | <p> | ||
| 5384 | This function can only occur inside {#syntax#}@cImport{#endsyntax#}. | ||
| 5385 | </p> | ||
| 5386 | <p> | ||
| 5387 | This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#} | ||
| 5388 | temporary buffer. | ||
| 5389 | </p> | ||
| 5390 | {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#} | ||
| 5391 | {#header_close#} | ||
| 5392 | {#header_open|@clz#} | 5440 | {#header_open|@clz#} |
| 5393 | <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre> | 5441 | <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre> |
| 5394 | <p> | 5442 | <p> |
| ... | @@ -5404,6 +5452,7 @@ comptime { | ... | @@ -5404,6 +5452,7 @@ comptime { |
| 5404 | </p> | 5452 | </p> |
| 5405 | {#see_also|@ctz|@popCount#} | 5453 | {#see_also|@ctz|@popCount#} |
| 5406 | {#header_close#} | 5454 | {#header_close#} |
| 5455 | |||
| 5407 | {#header_open|@cmpxchgStrong#} | 5456 | {#header_open|@cmpxchgStrong#} |
| 5408 | <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> | 5457 | <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> |
| 5409 | <p> | 5458 | <p> |
| ... | @@ -5459,6 +5508,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5459,6 +5508,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5459 | <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> | 5508 | <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 5460 | {#see_also|Compile Variables|cmpxchgStrong#} | 5509 | {#see_also|Compile Variables|cmpxchgStrong#} |
| 5461 | {#header_close#} | 5510 | {#header_close#} |
| 5511 | |||
| 5462 | {#header_open|@compileError#} | 5512 | {#header_open|@compileError#} |
| 5463 | <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre> | 5513 | <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre> |
| 5464 | <p> | 5514 | <p> |
| ... | @@ -5471,6 +5521,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5471,6 +5521,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5471 | and {#syntax#}comptime{#endsyntax#} functions. | 5521 | and {#syntax#}comptime{#endsyntax#} functions. |
| 5472 | </p> | 5522 | </p> |
| 5473 | {#header_close#} | 5523 | {#header_close#} |
| 5524 | |||
| 5474 | {#header_open|@compileLog#} | 5525 | {#header_open|@compileLog#} |
| 5475 | <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre> | 5526 | <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre> |
| 5476 | <p> | 5527 | <p> |
| ... | @@ -5525,6 +5576,7 @@ test "main" { | ... | @@ -5525,6 +5576,7 @@ test "main" { |
| 5525 | } | 5576 | } |
| 5526 | {#code_end#} | 5577 | {#code_end#} |
| 5527 | {#header_close#} | 5578 | {#header_close#} |
| 5579 | |||
| 5528 | {#header_open|@ctz#} | 5580 | {#header_open|@ctz#} |
| 5529 | <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre> | 5581 | <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre> |
| 5530 | <p> | 5582 | <p> |
| ... | @@ -5540,6 +5592,19 @@ test "main" { | ... | @@ -5540,6 +5592,19 @@ test "main" { |
| 5540 | </p> | 5592 | </p> |
| 5541 | {#see_also|@clz|@popCount#} | 5593 | {#see_also|@clz|@popCount#} |
| 5542 | {#header_close#} | 5594 | {#header_close#} |
| 5595 | |||
| 5596 | {#header_open|@cUndef#} | ||
| 5597 | <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre> | ||
| 5598 | <p> | ||
| 5599 | This function can only occur inside {#syntax#}@cImport{#endsyntax#}. | ||
| 5600 | </p> | ||
| 5601 | <p> | ||
| 5602 | This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#} | ||
| 5603 | temporary buffer. | ||
| 5604 | </p> | ||
| 5605 | {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#} | ||
| 5606 | {#header_close#} | ||
| 5607 | |||
| 5543 | {#header_open|@divExact#} | 5608 | {#header_open|@divExact#} |
| 5544 | <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre> | 5609 | <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 5545 | <p> | 5610 | <p> |
| ... | @@ -5606,14 +5671,6 @@ test "main" { | ... | @@ -5606,14 +5671,6 @@ test "main" { |
| 5606 | {#see_also|@intToEnum#} | 5671 | {#see_also|@intToEnum#} |
| 5607 | {#header_close#} | 5672 | {#header_close#} |
| 5608 | 5673 | ||
| 5609 | {#header_open|@errSetCast#} | ||
| 5610 | <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre> | ||
| 5611 | <p> | ||
| 5612 | Converts an error value from one error set to another error set. Attempting to convert an error | ||
| 5613 | which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}. | ||
| 5614 | </p> | ||
| 5615 | {#header_close#} | ||
| 5616 | |||
| 5617 | {#header_open|@errorName#} | 5674 | {#header_open|@errorName#} |
| 5618 | <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre> | 5675 | <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre> |
| 5619 | <p> | 5676 | <p> |
| ... | @@ -5656,6 +5713,14 @@ test "main" { | ... | @@ -5656,6 +5713,14 @@ test "main" { |
| 5656 | {#see_also|@intToError#} | 5713 | {#see_also|@intToError#} |
| 5657 | {#header_close#} | 5714 | {#header_close#} |
| 5658 | 5715 | ||
| 5716 | {#header_open|@errSetCast#} | ||
| 5717 | <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre> | ||
| 5718 | <p> | ||
| 5719 | Converts an error value from one error set to another error set. Attempting to convert an error | ||
| 5720 | which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}. | ||
| 5721 | </p> | ||
| 5722 | {#header_close#} | ||
| 5723 | |||
| 5659 | {#header_open|@export#} | 5724 | {#header_open|@export#} |
| 5660 | <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre> | 5725 | <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre> |
| 5661 | <p> | 5726 | <p> |
| ... | @@ -5724,6 +5789,7 @@ test "main" { | ... | @@ -5724,6 +5789,7 @@ test "main" { |
| 5724 | This function is only valid within function scope. | 5789 | This function is only valid within function scope. |
| 5725 | </p> | 5790 | </p> |
| 5726 | {#header_close#} | 5791 | {#header_close#} |
| 5792 | |||
| 5727 | {#header_open|@handle#} | 5793 | {#header_open|@handle#} |
| 5728 | <pre>{#syntax#}@handle(){#endsyntax#}</pre> | 5794 | <pre>{#syntax#}@handle(){#endsyntax#}</pre> |
| 5729 | <p> | 5795 | <p> |
| ... | @@ -5734,6 +5800,7 @@ test "main" { | ... | @@ -5734,6 +5800,7 @@ test "main" { |
| 5734 | This function is only valid within an async function scope. | 5800 | This function is only valid within an async function scope. |
| 5735 | </p> | 5801 | </p> |
| 5736 | {#header_close#} | 5802 | {#header_close#} |
| 5803 | |||
| 5737 | {#header_open|@import#} | 5804 | {#header_open|@import#} |
| 5738 | <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre> | 5805 | <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre> |
| 5739 | <p> | 5806 | <p> |
| ... | @@ -5754,6 +5821,7 @@ test "main" { | ... | @@ -5754,6 +5821,7 @@ test "main" { |
| 5754 | </ul> | 5821 | </ul> |
| 5755 | {#see_also|Compile Variables|@embedFile#} | 5822 | {#see_also|Compile Variables|@embedFile#} |
| 5756 | {#header_close#} | 5823 | {#header_close#} |
| 5824 | |||
| 5757 | {#header_open|@inlineCall#} | 5825 | {#header_open|@inlineCall#} |
| 5758 | <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre> | 5826 | <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre> |
| 5759 | <p> | 5827 | <p> |
| ... | @@ -5833,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5833,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5833 | bit count for an integer type is {#syntax#}65535{#endsyntax#}. | 5901 | bit count for an integer type is {#syntax#}65535{#endsyntax#}. |
| 5834 | </p> | 5902 | </p> |
| 5835 | {#header_close#} | 5903 | {#header_close#} |
| 5904 | |||
| 5836 | {#header_open|@memberCount#} | 5905 | {#header_open|@memberCount#} |
| 5837 | <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre> | 5906 | <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre> |
| 5838 | <p> | 5907 | <p> |
| ... | @@ -5859,6 +5928,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5859,6 +5928,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5859 | <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre> | 5928 | <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre> |
| 5860 | <p>Returns the field type of a struct or union.</p> | 5929 | <p>Returns the field type of a struct or union.</p> |
| 5861 | {#header_close#} | 5930 | {#header_close#} |
| 5931 | |||
| 5862 | {#header_open|@memcpy#} | 5932 | {#header_open|@memcpy#} |
| 5863 | <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre> | 5933 | <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre> |
| 5864 | <p> | 5934 | <p> |
| ... | @@ -5869,14 +5939,15 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5869,14 +5939,15 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5869 | This function is a low level intrinsic with no safety mechanisms. Most code | 5939 | This function is a low level intrinsic with no safety mechanisms. Most code |
| 5870 | should not use this function, instead using something like this: | 5940 | should not use this function, instead using something like this: |
| 5871 | </p> | 5941 | </p> |
| 5872 | <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre> | 5942 | <pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre> |
| 5873 | <p> | 5943 | <p> |
| 5874 | The optimizer is intelligent enough to turn the above snippet into a memcpy. | 5944 | The optimizer is intelligent enough to turn the above snippet into a memcpy. |
| 5875 | </p> | 5945 | </p> |
| 5876 | <p>There is also a standard library function for this:</p> | 5946 | <p>There is also a standard library function for this:</p> |
| 5877 | <pre>{#syntax#}const mem = @import("std").mem; | 5947 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5878 | mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> | 5948 | mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre> |
| 5879 | {#header_close#} | 5949 | {#header_close#} |
| 5950 | |||
| 5880 | {#header_open|@memset#} | 5951 | {#header_open|@memset#} |
| 5881 | <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre> | 5952 | <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre> |
| 5882 | <p> | 5953 | <p> |
| ... | @@ -5886,7 +5957,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> | ... | @@ -5886,7 +5957,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5886 | This function is a low level intrinsic with no safety mechanisms. Most | 5957 | This function is a low level intrinsic with no safety mechanisms. Most |
| 5887 | code should not use this function, instead using something like this: | 5958 | code should not use this function, instead using something like this: |
| 5888 | </p> | 5959 | </p> |
| 5889 | <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre> | 5960 | <pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre> |
| 5890 | <p> | 5961 | <p> |
| 5891 | The optimizer is intelligent enough to turn the above snippet into a memset. | 5962 | The optimizer is intelligent enough to turn the above snippet into a memset. |
| 5892 | </p> | 5963 | </p> |
| ... | @@ -5894,6 +5965,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> | ... | @@ -5894,6 +5965,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5894 | <pre>{#syntax#}const mem = @import("std").mem; | 5965 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5895 | mem.set(u8, dest, c);{#endsyntax#}</pre> | 5966 | mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5896 | {#header_close#} | 5967 | {#header_close#} |
| 5968 | |||
| 5897 | {#header_open|@mod#} | 5969 | {#header_open|@mod#} |
| 5898 | <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre> | 5970 | <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 5899 | <p> | 5971 | <p> |
| ... | @@ -5907,6 +5979,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> | ... | @@ -5907,6 +5979,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5907 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p> | 5979 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p> |
| 5908 | {#see_also|@rem#} | 5980 | {#see_also|@rem#} |
| 5909 | {#header_close#} | 5981 | {#header_close#} |
| 5982 | |||
| 5910 | {#header_open|@mulWithOverflow#} | 5983 | {#header_open|@mulWithOverflow#} |
| 5911 | <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> | 5984 | <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> |
| 5912 | <p> | 5985 | <p> |
| ... | @@ -5915,6 +5988,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> | ... | @@ -5915,6 +5988,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5915 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. | 5988 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 5916 | </p> | 5989 | </p> |
| 5917 | {#header_close#} | 5990 | {#header_close#} |
| 5991 | |||
| 5918 | {#header_open|@newStackCall#} | 5992 | {#header_open|@newStackCall#} |
| 5919 | <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre> | 5993 | <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre> |
| 5920 | <p> | 5994 | <p> |
| ... | @@ -5951,6 +6025,7 @@ fn targetFunction(x: i32) usize { | ... | @@ -5951,6 +6025,7 @@ fn targetFunction(x: i32) usize { |
| 5951 | } | 6025 | } |
| 5952 | {#code_end#} | 6026 | {#code_end#} |
| 5953 | {#header_close#} | 6027 | {#header_close#} |
| 6028 | |||
| 5954 | {#header_open|@noInlineCall#} | 6029 | {#header_open|@noInlineCall#} |
| 5955 | <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre> | 6030 | <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre> |
| 5956 | <p> | 6031 | <p> |
| ... | @@ -5973,6 +6048,7 @@ fn add(a: i32, b: i32) i32 { | ... | @@ -5973,6 +6048,7 @@ fn add(a: i32, b: i32) i32 { |
| 5973 | </p> | 6048 | </p> |
| 5974 | {#see_also|@inlineCall#} | 6049 | {#see_also|@inlineCall#} |
| 5975 | {#header_close#} | 6050 | {#header_close#} |
| 6051 | |||
| 5976 | {#header_open|@OpaqueType#} | 6052 | {#header_open|@OpaqueType#} |
| 5977 | <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre> | 6053 | <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre> |
| 5978 | <p> | 6054 | <p> |
| ... | @@ -5996,6 +6072,7 @@ test "call foo" { | ... | @@ -5996,6 +6072,7 @@ test "call foo" { |
| 5996 | } | 6072 | } |
| 5997 | {#code_end#} | 6073 | {#code_end#} |
| 5998 | {#header_close#} | 6074 | {#header_close#} |
| 6075 | |||
| 5999 | {#header_open|@panic#} | 6076 | {#header_open|@panic#} |
| 6000 | <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre> | 6077 | <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre> |
| 6001 | <p> | 6078 | <p> |
| ... | @@ -6012,6 +6089,7 @@ test "call foo" { | ... | @@ -6012,6 +6089,7 @@ test "call foo" { |
| 6012 | </ul> | 6089 | </ul> |
| 6013 | {#see_also|Root Source File#} | 6090 | {#see_also|Root Source File#} |
| 6014 | {#header_close#} | 6091 | {#header_close#} |
| 6092 | |||
| 6015 | {#header_open|@popCount#} | 6093 | {#header_open|@popCount#} |
| 6016 | <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre> | 6094 | <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre> |
| 6017 | <p>Counts the number of bits set in an integer.</p> | 6095 | <p>Counts the number of bits set in an integer.</p> |
| ... | @@ -6022,12 +6100,18 @@ test "call foo" { | ... | @@ -6022,12 +6100,18 @@ test "call foo" { |
| 6022 | </p> | 6100 | </p> |
| 6023 | {#see_also|@ctz|@clz#} | 6101 | {#see_also|@ctz|@clz#} |
| 6024 | {#header_close#} | 6102 | {#header_close#} |
| 6103 | |||
| 6025 | {#header_open|@ptrCast#} | 6104 | {#header_open|@ptrCast#} |
| 6026 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> | 6105 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> |
| 6027 | <p> | 6106 | <p> |
| 6028 | Converts a pointer of one type to a pointer of another type. | 6107 | Converts a pointer of one type to a pointer of another type. |
| 6029 | </p> | 6108 | </p> |
| 6109 | <p> | ||
| 6110 | {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#} | ||
| 6111 | to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}. | ||
| 6112 | </p> | ||
| 6030 | {#header_close#} | 6113 | {#header_close#} |
| 6114 | |||
| 6031 | {#header_open|@ptrToInt#} | 6115 | {#header_open|@ptrToInt#} |
| 6032 | <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre> | 6116 | <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre> |
| 6033 | <p> | 6117 | <p> |
| ... | @@ -6042,6 +6126,7 @@ test "call foo" { | ... | @@ -6042,6 +6126,7 @@ test "call foo" { |
| 6042 | <p>To convert the other way, use {#link|@intToPtr#}</p> | 6126 | <p>To convert the other way, use {#link|@intToPtr#}</p> |
| 6043 | 6127 | ||
| 6044 | {#header_close#} | 6128 | {#header_close#} |
| 6129 | |||
| 6045 | {#header_open|@rem#} | 6130 | {#header_open|@rem#} |
| 6046 | <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre> | 6131 | <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 6047 | <p> | 6132 | <p> |
| ... | @@ -6055,6 +6140,7 @@ test "call foo" { | ... | @@ -6055,6 +6140,7 @@ test "call foo" { |
| 6055 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p> | 6140 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p> |
| 6056 | {#see_also|@mod#} | 6141 | {#see_also|@mod#} |
| 6057 | {#header_close#} | 6142 | {#header_close#} |
| 6143 | |||
| 6058 | {#header_open|@returnAddress#} | 6144 | {#header_open|@returnAddress#} |
| 6059 | <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre> | 6145 | <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre> |
| 6060 | <p> | 6146 | <p> |
| ... | @@ -6075,19 +6161,14 @@ test "call foo" { | ... | @@ -6075,19 +6161,14 @@ test "call foo" { |
| 6075 | Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes. | 6161 | Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes. |
| 6076 | </p> | 6162 | </p> |
| 6077 | {#header_close#} | 6163 | {#header_close#} |
| 6164 | |||
| 6078 | {#header_open|@setCold#} | 6165 | {#header_open|@setCold#} |
| 6079 | <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre> | 6166 | <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre> |
| 6080 | <p> | 6167 | <p> |
| 6081 | Tells the optimizer that a function is rarely called. | 6168 | Tells the optimizer that a function is rarely called. |
| 6082 | </p> | 6169 | </p> |
| 6083 | {#header_close#} | 6170 | {#header_close#} |
| 6084 | {#header_open|@setRuntimeSafety#} | ||
| 6085 | <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre> | ||
| 6086 | <p> | ||
| 6087 | Sets whether runtime safety checks are on for the scope that contains the function call. | ||
| 6088 | </p> | ||
| 6089 | 6171 | ||
| 6090 | {#header_close#} | ||
| 6091 | {#header_open|@setEvalBranchQuota#} | 6172 | {#header_open|@setEvalBranchQuota#} |
| 6092 | <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre> | 6173 | <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre> |
| 6093 | <p> | 6174 | <p> |
| ... | @@ -6122,6 +6203,7 @@ test "foo" { | ... | @@ -6122,6 +6203,7 @@ test "foo" { |
| 6122 | 6203 | ||
| 6123 | {#see_also|comptime#} | 6204 | {#see_also|comptime#} |
| 6124 | {#header_close#} | 6205 | {#header_close#} |
| 6206 | |||
| 6125 | {#header_open|@setFloatMode#} | 6207 | {#header_open|@setFloatMode#} |
| 6126 | <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre> | 6208 | <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre> |
| 6127 | <p> | 6209 | <p> |
| ... | @@ -6156,6 +6238,7 @@ pub const FloatMode = enum { | ... | @@ -6156,6 +6238,7 @@ pub const FloatMode = enum { |
| 6156 | </p> | 6238 | </p> |
| 6157 | {#see_also|Floating Point Operations#} | 6239 | {#see_also|Floating Point Operations#} |
| 6158 | {#header_close#} | 6240 | {#header_close#} |
| 6241 | |||
| 6159 | {#header_open|@setGlobalLinkage#} | 6242 | {#header_open|@setGlobalLinkage#} |
| 6160 | <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre> | 6243 | <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre> |
| 6161 | <p> | 6244 | <p> |
| ... | @@ -6163,6 +6246,15 @@ pub const FloatMode = enum { | ... | @@ -6163,6 +6246,15 @@ pub const FloatMode = enum { |
| 6163 | </p> | 6246 | </p> |
| 6164 | {#see_also|Compile Variables#} | 6247 | {#see_also|Compile Variables#} |
| 6165 | {#header_close#} | 6248 | {#header_close#} |
| 6249 | |||
| 6250 | {#header_open|@setRuntimeSafety#} | ||
| 6251 | <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre> | ||
| 6252 | <p> | ||
| 6253 | Sets whether runtime safety checks are on for the scope that contains the function call. | ||
| 6254 | </p> | ||
| 6255 | |||
| 6256 | {#header_close#} | ||
| 6257 | |||
| 6166 | {#header_open|@shlExact#} | 6258 | {#header_open|@shlExact#} |
| 6167 | <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> | 6259 | <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> |
| 6168 | <p> | 6260 | <p> |
| ... | @@ -6175,6 +6267,7 @@ pub const FloatMode = enum { | ... | @@ -6175,6 +6267,7 @@ pub const FloatMode = enum { |
| 6175 | </p> | 6267 | </p> |
| 6176 | {#see_also|@shrExact|@shlWithOverflow#} | 6268 | {#see_also|@shrExact|@shlWithOverflow#} |
| 6177 | {#header_close#} | 6269 | {#header_close#} |
| 6270 | |||
| 6178 | {#header_open|@shlWithOverflow#} | 6271 | {#header_open|@shlWithOverflow#} |
| 6179 | <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre> | 6272 | <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre> |
| 6180 | <p> | 6273 | <p> |
| ... | @@ -6188,6 +6281,7 @@ pub const FloatMode = enum { | ... | @@ -6188,6 +6281,7 @@ pub const FloatMode = enum { |
| 6188 | </p> | 6281 | </p> |
| 6189 | {#see_also|@shlExact|@shrExact#} | 6282 | {#see_also|@shlExact|@shrExact#} |
| 6190 | {#header_close#} | 6283 | {#header_close#} |
| 6284 | |||
| 6191 | {#header_open|@shrExact#} | 6285 | {#header_open|@shrExact#} |
| 6192 | <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> | 6286 | <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> |
| 6193 | <p> | 6287 | <p> |
| ... | @@ -6205,10 +6299,15 @@ pub const FloatMode = enum { | ... | @@ -6205,10 +6299,15 @@ pub const FloatMode = enum { |
| 6205 | <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre> | 6299 | <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre> |
| 6206 | <p> | 6300 | <p> |
| 6207 | This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory. | 6301 | This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory. |
| 6302 | The result is a target-specific compile time constant. | ||
| 6208 | </p> | 6303 | </p> |
| 6209 | <p> | 6304 | <p> |
| 6210 | The result is a target-specific compile time constant. | 6305 | This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset |
| 6306 | in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#}, | ||
| 6307 | consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or | ||
| 6308 | {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}. | ||
| 6211 | </p> | 6309 | </p> |
| 6310 | {#see_also|@typeInfo#} | ||
| 6212 | {#header_close#} | 6311 | {#header_close#} |
| 6213 | 6312 | ||
| 6214 | {#header_open|@sliceToBytes#} | 6313 | {#header_open|@sliceToBytes#} |
| ... | @@ -6229,6 +6328,7 @@ pub const FloatMode = enum { | ... | @@ -6229,6 +6328,7 @@ pub const FloatMode = enum { |
| 6229 | This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead. | 6328 | This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead. |
| 6230 | </p> | 6329 | </p> |
| 6231 | {#header_close#} | 6330 | {#header_close#} |
| 6331 | |||
| 6232 | {#header_open|@subWithOverflow#} | 6332 | {#header_open|@subWithOverflow#} |
| 6233 | <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> | 6333 | <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> |
| 6234 | <p> | 6334 | <p> |
| ... | @@ -6237,12 +6337,14 @@ pub const FloatMode = enum { | ... | @@ -6237,12 +6337,14 @@ pub const FloatMode = enum { |
| 6237 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. | 6337 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 6238 | </p> | 6338 | </p> |
| 6239 | {#header_close#} | 6339 | {#header_close#} |
| 6340 | |||
| 6240 | {#header_open|@tagName#} | 6341 | {#header_open|@tagName#} |
| 6241 | <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre> | 6342 | <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre> |
| 6242 | <p> | 6343 | <p> |
| 6243 | Converts an enum value or union value to a slice of bytes representing the name. | 6344 | Converts an enum value or union value to a slice of bytes representing the name. |
| 6244 | </p> | 6345 | </p> |
| 6245 | {#header_close#} | 6346 | {#header_close#} |
| 6347 | |||
| 6246 | {#header_open|@TagType#} | 6348 | {#header_open|@TagType#} |
| 6247 | <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre> | 6349 | <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre> |
| 6248 | <p> | 6350 | <p> |
| ... | @@ -6252,6 +6354,7 @@ pub const FloatMode = enum { | ... | @@ -6252,6 +6354,7 @@ pub const FloatMode = enum { |
| 6252 | For a union, returns the enum type that is used to store the tag value. | 6354 | For a union, returns the enum type that is used to store the tag value. |
| 6253 | </p> | 6355 | </p> |
| 6254 | {#header_close#} | 6356 | {#header_close#} |
| 6357 | |||
| 6255 | {#header_open|@This#} | 6358 | {#header_open|@This#} |
| 6256 | <pre>{#syntax#}@This() type{#endsyntax#}</pre> | 6359 | <pre>{#syntax#}@This() type{#endsyntax#}</pre> |
| 6257 | <p> | 6360 | <p> |
| ... | @@ -6287,15 +6390,16 @@ fn List(comptime T: type) type { | ... | @@ -6287,15 +6390,16 @@ fn List(comptime T: type) type { |
| 6287 | <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details. | 6390 | <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details. |
| 6288 | </p> | 6391 | </p> |
| 6289 | {#header_close#} | 6392 | {#header_close#} |
| 6393 | |||
| 6290 | {#header_open|@truncate#} | 6394 | {#header_open|@truncate#} |
| 6291 | <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre> | 6395 | <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre> |
| 6292 | <p> | 6396 | <p> |
| 6293 | This function truncates bits from an integer type, resulting in a smaller | 6397 | This function truncates bits from an integer type, resulting in a smaller |
| 6294 | integer type. | 6398 | integer type. |
| 6295 | </p> | 6399 | </p> |
| 6296 | <p> | 6400 | <p> |
| 6297 | The following produces a crash in debug mode and undefined behavior in | 6401 | The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in |
| 6298 | release mode: | 6402 | {#link|ReleaseFast#} mode: |
| 6299 | </p> | 6403 | </p> |
| 6300 | <pre>{#syntax#}const a: u16 = 0xabcd; | 6404 | <pre>{#syntax#}const a: u16 = 0xabcd; |
| 6301 | const b: u8 = u8(a);{#endsyntax#}</pre> | 6405 | const b: u8 = u8(a);{#endsyntax#}</pre> |
| ... | @@ -6309,8 +6413,12 @@ const b: u8 = @truncate(u8, a); | ... | @@ -6309,8 +6413,12 @@ const b: u8 = @truncate(u8, a); |
| 6309 | This function always truncates the significant bits of the integer, regardless | 6413 | This function always truncates the significant bits of the integer, regardless |
| 6310 | of endianness on the target platform. | 6414 | of endianness on the target platform. |
| 6311 | </p> | 6415 | </p> |
| 6312 | 6416 | <p> | |
| 6417 | If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#}, | ||
| 6418 | then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}. | ||
| 6419 | </p> | ||
| 6313 | {#header_close#} | 6420 | {#header_close#} |
| 6421 | |||
| 6314 | {#header_open|@typeId#} | 6422 | {#header_open|@typeId#} |
| 6315 | <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre> | 6423 | <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre> |
| 6316 | <p> | 6424 | <p> |
| ... | @@ -6345,6 +6453,7 @@ pub const TypeId = enum { | ... | @@ -6345,6 +6453,7 @@ pub const TypeId = enum { |
| 6345 | }; | 6453 | }; |
| 6346 | {#code_end#} | 6454 | {#code_end#} |
| 6347 | {#header_close#} | 6455 | {#header_close#} |
| 6456 | |||
| 6348 | {#header_open|@typeInfo#} | 6457 | {#header_open|@typeInfo#} |
| 6349 | <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre> | 6458 | <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre> |
| 6350 | <p> | 6459 | <p> |
| ... | @@ -6527,13 +6636,16 @@ pub const TypeInfo = union(TypeId) { | ... | @@ -6527,13 +6636,16 @@ pub const TypeInfo = union(TypeId) { |
| 6527 | }; | 6636 | }; |
| 6528 | {#code_end#} | 6637 | {#code_end#} |
| 6529 | {#header_close#} | 6638 | {#header_close#} |
| 6639 | |||
| 6530 | {#header_open|@typeName#} | 6640 | {#header_open|@typeName#} |
| 6531 | <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre> | 6641 | <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre> |
| 6532 | <p> | 6642 | <p> |
| 6533 | This function returns the string representation of a type. | 6643 | This function returns the string representation of a type, as |
| 6644 | an array. It is equivalent to a string literal of the type name. | ||
| 6534 | </p> | 6645 | </p> |
| 6535 | 6646 | ||
| 6536 | {#header_close#} | 6647 | {#header_close#} |
| 6648 | |||
| 6537 | {#header_open|@typeOf#} | 6649 | {#header_open|@typeOf#} |
| 6538 | <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre> | 6650 | <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre> |
| 6539 | <p> | 6651 | <p> |
| ... | @@ -6541,8 +6653,20 @@ pub const TypeInfo = union(TypeId) { | ... | @@ -6541,8 +6653,20 @@ pub const TypeInfo = union(TypeId) { |
| 6541 | expression passed as an argument. The expression is evaluated. | 6653 | expression passed as an argument. The expression is evaluated. |
| 6542 | </p> | 6654 | </p> |
| 6543 | 6655 | ||
| 6656 | {#header_close#} | ||
| 6657 | |||
| 6658 | {#header_open|@Vector#} | ||
| 6659 | <pre>{#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}</pre> | ||
| 6660 | <p> | ||
| 6661 | This function returns a vector type for {#link|SIMD#}. | ||
| 6662 | </p> | ||
| 6663 | <p> | ||
| 6664 | {#syntax#}ElemType{#endsyntax#} must be an {#link|integer|Integers#}, a {#link|float|Floats#}, or a | ||
| 6665 | {#link|pointer|Pointers#}. | ||
| 6666 | </p> | ||
| 6544 | {#header_close#} | 6667 | {#header_close#} |
| 6545 | {#header_close#} | 6668 | {#header_close#} |
| 6669 | |||
| 6546 | {#header_open|Build Mode#} | 6670 | {#header_open|Build Mode#} |
| 6547 | <p> | 6671 | <p> |
| 6548 | Zig has four build modes: | 6672 | Zig has four build modes: |
| ... | @@ -6613,6 +6737,25 @@ pub fn build(b: *Builder) void { | ... | @@ -6613,6 +6737,25 @@ pub fn build(b: *Builder) void { |
| 6613 | {#header_close#} | 6737 | {#header_close#} |
| 6614 | {#see_also|Compile Variables|Zig Build System|Undefined Behavior#} | 6738 | {#see_also|Compile Variables|Zig Build System|Undefined Behavior#} |
| 6615 | {#header_close#} | 6739 | {#header_close#} |
| 6740 | |||
| 6741 | {#header_open|Single Threaded Builds#} | ||
| 6742 | <p>Zig has a compile option <code>--single-threaded</code> which has the following effects: | ||
| 6743 | <ul> | ||
| 6744 | <li>{#link|@atomicLoad#} is emitted as a normal load.</li> | ||
| 6745 | <li>{#link|@atomicRmw#} is emitted as a normal memory load, modify, store.</li> | ||
| 6746 | <li>{#link|@fence#} becomes a no-op.</li> | ||
| 6747 | <li>Variables which have Thread Local Storage instead become globals. TODO thread local variables | ||
| 6748 | are not implemented yet.</li> | ||
| 6749 | <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead. | ||
| 6750 | TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li> | ||
| 6751 | <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#} | ||
| 6752 | and therefore various userland APIs which read this variable become more efficient. | ||
| 6753 | For example {#syntax#}std.Mutex{#endsyntax#} becomes | ||
| 6754 | an empty data structure and all of its functions become no-ops.</li> | ||
| 6755 | </ul> | ||
| 6756 | </p> | ||
| 6757 | {#header_close#} | ||
| 6758 | |||
| 6616 | {#header_open|Undefined Behavior#} | 6759 | {#header_open|Undefined Behavior#} |
| 6617 | <p> | 6760 | <p> |
| 6618 | Zig has many instances of undefined behavior. If undefined behavior is | 6761 | Zig has many instances of undefined behavior. If undefined behavior is |
| ... | @@ -7213,10 +7356,27 @@ fn bar(f: *Foo) void { | ... | @@ -7213,10 +7356,27 @@ fn bar(f: *Foo) void { |
| 7213 | {#code_end#} | 7356 | {#code_end#} |
| 7214 | {#header_close#} | 7357 | {#header_close#} |
| 7215 | 7358 | ||
| 7216 | {#header_open|Out of Bounds Float To Integer Cast#} | 7359 | {#header_open|Out of Bounds Float to Integer Cast#} |
| 7217 | <p>TODO</p> | 7360 | <p>TODO</p> |
| 7218 | {#header_close#} | 7361 | {#header_close#} |
| 7219 | 7362 | ||
| 7363 | {#header_open|Pointer Cast Invalid Null#} | ||
| 7364 | <p>At compile-time:</p> | ||
| 7365 | {#code_begin|test_err|null pointer casted to type#} | ||
| 7366 | comptime { | ||
| 7367 | const opt_ptr: ?*i32 = null; | ||
| 7368 | const ptr = @ptrCast(*i32, opt_ptr); | ||
| 7369 | } | ||
| 7370 | {#code_end#} | ||
| 7371 | <p>At runtime:</p> | ||
| 7372 | {#code_begin|exe_err#} | ||
| 7373 | pub fn main() void { | ||
| 7374 | var opt_ptr: ?*i32 = null; | ||
| 7375 | var ptr = @ptrCast(*i32, opt_ptr); | ||
| 7376 | } | ||
| 7377 | {#code_end#} | ||
| 7378 | {#header_close#} | ||
| 7379 | |||
| 7220 | {#header_close#} | 7380 | {#header_close#} |
| 7221 | {#header_open|Memory#} | 7381 | {#header_open|Memory#} |
| 7222 | <p>TODO: explain no default allocator in zig</p> | 7382 | <p>TODO: explain no default allocator in zig</p> |
| ... | @@ -7307,6 +7467,7 @@ pub fn main() void { | ... | @@ -7307,6 +7467,7 @@ pub fn main() void { |
| 7307 | {#code_end#} | 7467 | {#code_end#} |
| 7308 | {#see_also|String Literals#} | 7468 | {#see_also|String Literals#} |
| 7309 | {#header_close#} | 7469 | {#header_close#} |
| 7470 | |||
| 7310 | {#header_open|Import from C Header File#} | 7471 | {#header_open|Import from C Header File#} |
| 7311 | <p> | 7472 | <p> |
| 7312 | The {#syntax#}@cImport{#endsyntax#} builtin function can be used | 7473 | The {#syntax#}@cImport{#endsyntax#} builtin function can be used |
| ... | @@ -7345,6 +7506,36 @@ const c = @cImport({ | ... | @@ -7345,6 +7506,36 @@ const c = @cImport({ |
| 7345 | {#code_end#} | 7506 | {#code_end#} |
| 7346 | {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#} | 7507 | {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#} |
| 7347 | {#header_close#} | 7508 | {#header_close#} |
| 7509 | |||
| 7510 | {#header_open|C Pointers#} | ||
| 7511 | <p> | ||
| 7512 | This type is to be avoided whenever possible. The only valid reason for using a C pointer is in | ||
| 7513 | auto-generated code from translating C code. | ||
| 7514 | </p> | ||
| 7515 | <p> | ||
| 7516 | When importing C header files, it is ambiguous whether pointers should be translated as | ||
| 7517 | single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}). | ||
| 7518 | C pointers are a compromise so that Zig code can utilize translated header files directly. | ||
| 7519 | </p> | ||
| 7520 | <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p> | ||
| 7521 | <ul> | ||
| 7522 | <li>Supports all the syntax of the other two pointer types.</li> | ||
| 7523 | <li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}. | ||
| 7524 | When a C pointer is implicitly casted to a non-optional pointer, safety-checked | ||
| 7525 | {#link|Undefined Behavior#} occurs if the address is 0. | ||
| 7526 | </li> | ||
| 7527 | <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked | ||
| 7528 | {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of | ||
| 7529 | null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer | ||
| 7530 | is unnecessary as one can use normal {#link|Optional Pointers#}. | ||
| 7531 | </li> | ||
| 7532 | <li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li> | ||
| 7533 | <li>Supports comparison with integers.</li> | ||
| 7534 | <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#} | ||
| 7535 | please!</li> | ||
| 7536 | </ul> | ||
| 7537 | {#header_close#} | ||
| 7538 | |||
| 7348 | {#header_open|Exporting a C Library#} | 7539 | {#header_open|Exporting a C Library#} |
| 7349 | <p> | 7540 | <p> |
| 7350 | One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages | 7541 | One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages |
| ... | @@ -7741,7 +7932,7 @@ TopLevelComptime &lt;- KEYWORD_comptime BlockExpr | ... | @@ -7741,7 +7932,7 @@ TopLevelComptime &lt;- KEYWORD_comptime BlockExpr |
| 7741 | 7932 | ||
| 7742 | TopLevelDecl | 7933 | TopLevelDecl |
| 7743 | &lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) | 7934 | &lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) |
| 7744 | / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl | 7935 | / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl |
| 7745 | / KEYWORD_use Expr SEMICOLON | 7936 | / KEYWORD_use Expr SEMICOLON |
| 7746 | 7937 | ||
| 7747 | FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) | 7938 | FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) |
| ... | @@ -8032,7 +8223,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET | ... | @@ -8032,7 +8223,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET |
| 8032 | PtrTypeStart | 8223 | PtrTypeStart |
| 8033 | &lt;- ASTERISK | 8224 | &lt;- ASTERISK |
| 8034 | / ASTERISK2 | 8225 | / ASTERISK2 |
| 8035 | / LBRACKET ASTERISK RBRACKET | 8226 | / PTRUNKNOWN |
| 8227 | / PTRC | ||
| 8036 | 8228 | ||
| 8037 | # ContainerDecl specific | 8229 | # ContainerDecl specific |
| 8038 | ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE | 8230 | ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE |
| ... | @@ -8130,7 +8322,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip | ... | @@ -8130,7 +8322,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip |
| 8130 | LARROW2EQUAL &lt;- '&lt;&lt;=' skip | 8322 | LARROW2EQUAL &lt;- '&lt;&lt;=' skip |
| 8131 | LARROWEQUAL &lt;- '&lt;=' skip | 8323 | LARROWEQUAL &lt;- '&lt;=' skip |
| 8132 | LBRACE &lt;- '{' skip | 8324 | LBRACE &lt;- '{' skip |
| 8133 | LBRACKET &lt;- '[' skip | 8325 | LBRACKET &lt;- '[' ![*] skip |
| 8134 | LPAREN &lt;- '(' skip | 8326 | LPAREN &lt;- '(' skip |
| 8135 | MINUS &lt;- '-' ![%=&gt;] skip | 8327 | MINUS &lt;- '-' ![%=&gt;] skip |
| 8136 | MINUSEQUAL &lt;- '-=' skip | 8328 | MINUSEQUAL &lt;- '-=' skip |
| ... | @@ -8147,6 +8339,8 @@ PLUS2 &lt;- '++' skip | ... | @@ -8147,6 +8339,8 @@ PLUS2 &lt;- '++' skip |
| 8147 | PLUSEQUAL &lt;- '+=' skip | 8339 | PLUSEQUAL &lt;- '+=' skip |
| 8148 | PLUSPERCENT &lt;- '+%' ![=] skip | 8340 | PLUSPERCENT &lt;- '+%' ![=] skip |
| 8149 | PLUSPERCENTEQUAL &lt;- '+%=' skip | 8341 | PLUSPERCENTEQUAL &lt;- '+%=' skip |
| 8342 | PTRC &lt;- '[*c]' skip | ||
| 8343 | PTRUNKNOWN &lt;- '[*]' skip | ||
| 8150 | QUESTIONMARK &lt;- '?' skip | 8344 | QUESTIONMARK &lt;- '?' skip |
| 8151 | RARROW &lt;- '&gt;' ![&gt;=] skip | 8345 | RARROW &lt;- '&gt;' ![&gt;=] skip |
| 8152 | RARROW2 &lt;- '&gt;&gt;' ![=] skip | 8346 | RARROW2 &lt;- '&gt;&gt;' ![=] skip |
| ... | @@ -8201,6 +8395,7 @@ KEYWORD_struct &lt;- 'struct' end_of_word | ... | @@ -8201,6 +8395,7 @@ KEYWORD_struct &lt;- 'struct' end_of_word |
| 8201 | KEYWORD_suspend &lt;- 'suspend' end_of_word | 8395 | KEYWORD_suspend &lt;- 'suspend' end_of_word |
| 8202 | KEYWORD_switch &lt;- 'switch' end_of_word | 8396 | KEYWORD_switch &lt;- 'switch' end_of_word |
| 8203 | KEYWORD_test &lt;- 'test' end_of_word | 8397 | KEYWORD_test &lt;- 'test' end_of_word |
| 8398 | KEYWORD_threadlocal &lt;- 'threadlocal' end_of_word | ||
| 8204 | KEYWORD_true &lt;- 'true' end_of_word | 8399 | KEYWORD_true &lt;- 'true' end_of_word |
| 8205 | KEYWORD_try &lt;- 'try' end_of_word | 8400 | KEYWORD_try &lt;- 'try' end_of_word |
| 8206 | KEYWORD_undefined &lt;- 'undefined' end_of_word | 8401 | KEYWORD_undefined &lt;- 'undefined' end_of_word |
| ... | @@ -8221,7 +8416,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm | ... | @@ -8221,7 +8416,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm |
| 8221 | / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub | 8416 | / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub |
| 8222 | / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection | 8417 | / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection |
| 8223 | / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend | 8418 | / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend |
| 8224 | / KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try | 8419 | / KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try |
| 8225 | / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable | 8420 | / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable |
| 8226 | / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre> | 8421 | / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre> |
| 8227 | {#header_close#} | 8422 | {#header_close#} |
doc/targets.md deleted-15| ... | @@ -1,15 +0,0 @@ | ||
| 1 | # How to Add Support For More Targets | ||
| 2 | |||
| 3 | Create bootstrap code in std/bootstrap.zig and add conditional compilation | ||
| 4 | logic. This code is responsible for the real executable entry point, calling | ||
| 5 | main() and making the exit syscall when main returns. | ||
| 6 | |||
| 7 | How to pass a byvalue struct parameter in the C calling convention is | ||
| 8 | target-specific. Add logic for how to do function prototypes and function calls | ||
| 9 | for the target when an exported or external function has a byvalue struct. | ||
| 10 | |||
| 11 | Write the target-specific code in the standard library. | ||
| 12 | |||
| 13 | Update the C integer types to be the correct size for the target. | ||
| 14 | |||
| 15 | Make sure that `c_longdouble` codegens the correct floating point value. | ||
example/guess_number/main.zig+1-1| ... | @@ -15,7 +15,7 @@ pub fn main() !void { | ... | @@ -15,7 +15,7 @@ pub fn main() !void { |
| 15 | std.debug.warn("unable to seed random number generator: {}", err); | 15 | std.debug.warn("unable to seed random number generator: {}", err); |
| 16 | return err; | 16 | return err; |
| 17 | }; | 17 | }; |
| 18 | const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big); | 18 | const seed = std.mem.readIntNative(u64, &seed_bytes); |
| 19 | var prng = std.rand.DefaultPrng.init(seed); | 19 | var prng = std.rand.DefaultPrng.init(seed); |
| 20 | 20 | ||
| 21 | const answer = prng.random.range(u8, 0, 100) + 1; | 21 | const answer = prng.random.range(u8, 0, 100) + 1; |
example/hello_world/hello.zig+1-1| ... | @@ -2,7 +2,7 @@ const std = @import("std"); | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | ||
| 3 | pub fn main() !void { | 3 | pub fn main() !void { |
| 4 | // If this program is run without stdout attached, exit with an error. | 4 | // If this program is run without stdout attached, exit with an error. |
| 5 | var stdout_file = try std.io.getStdOut(); | 5 | const stdout_file = try std.io.getStdOut(); |
| 6 | // If this program encounters pipe failure when printing to stdout, exit | 6 | // If this program encounters pipe failure when printing to stdout, exit |
| 7 | // with an error. | 7 | // with an error. |
| 8 | try stdout_file.write("Hello, world!\n"); | 8 | try stdout_file.write("Hello, world!\n"); |
src-self-hosted/arg.zig+12-11| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const debug = std.debug; | 2 | const debug = std.debug; |
| 3 | const testing = std.testing; | ||
| 3 | const mem = std.mem; | 4 | const mem = std.mem; |
| 4 | 5 | ||
| 5 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| ... | @@ -272,21 +273,21 @@ test "parse arguments" { | ... | @@ -272,21 +273,21 @@ test "parse arguments" { |
| 272 | 273 | ||
| 273 | var args = try Args.parse(std.debug.global_allocator, spec1, cliargs); | 274 | var args = try Args.parse(std.debug.global_allocator, spec1, cliargs); |
| 274 | 275 | ||
| 275 | debug.assert(args.present("help")); | 276 | testing.expect(args.present("help")); |
| 276 | debug.assert(!args.present("help2")); | 277 | testing.expect(!args.present("help2")); |
| 277 | debug.assert(!args.present("init")); | 278 | testing.expect(!args.present("init")); |
| 278 | 279 | ||
| 279 | debug.assert(mem.eql(u8, args.single("build-file").?, "build.zig")); | 280 | testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig")); |
| 280 | debug.assert(mem.eql(u8, args.single("color").?, "on")); | 281 | testing.expect(mem.eql(u8, args.single("color").?, "on")); |
| 281 | 282 | ||
| 282 | const objects = args.many("object").?; | 283 | const objects = args.many("object").?; |
| 283 | debug.assert(mem.eql(u8, objects[0], "obj1")); | 284 | testing.expect(mem.eql(u8, objects[0], "obj1")); |
| 284 | debug.assert(mem.eql(u8, objects[1], "obj2")); | 285 | testing.expect(mem.eql(u8, objects[1], "obj2")); |
| 285 | 286 | ||
| 286 | debug.assert(mem.eql(u8, args.single("library").?, "lib2")); | 287 | testing.expect(mem.eql(u8, args.single("library").?, "lib2")); |
| 287 | 288 | ||
| 288 | const pos = args.positionals.toSliceConst(); | 289 | const pos = args.positionals.toSliceConst(); |
| 289 | debug.assert(mem.eql(u8, pos[0], "build")); | 290 | testing.expect(mem.eql(u8, pos[0], "build")); |
| 290 | debug.assert(mem.eql(u8, pos[1], "pos1")); | 291 | testing.expect(mem.eql(u8, pos[1], "pos1")); |
| 291 | debug.assert(mem.eql(u8, pos[2], "pos2")); | 292 | testing.expect(mem.eql(u8, pos[2], "pos2")); |
| 292 | } | 293 | } |
src-self-hosted/codegen.zig+21-21| ... | @@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) | ... | @@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) |
| 137 | 137 | ||
| 138 | pub const ObjectFile = struct { | 138 | pub const ObjectFile = struct { |
| 139 | comp: *Compilation, | 139 | comp: *Compilation, |
| 140 | module: llvm.ModuleRef, | 140 | module: *llvm.Module, |
| 141 | builder: llvm.BuilderRef, | 141 | builder: *llvm.Builder, |
| 142 | dibuilder: *llvm.DIBuilder, | 142 | dibuilder: *llvm.DIBuilder, |
| 143 | context: llvm.ContextRef, | 143 | context: *llvm.Context, |
| 144 | lock: event.Lock, | 144 | lock: event.Lock, |
| 145 | arena: *std.mem.Allocator, | 145 | arena: *std.mem.Allocator, |
| 146 | 146 | ||
| ... | @@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) | ... | @@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) |
| 323 | 323 | ||
| 324 | fn addLLVMAttr( | 324 | fn addLLVMAttr( |
| 325 | ofile: *ObjectFile, | 325 | ofile: *ObjectFile, |
| 326 | val: llvm.ValueRef, | 326 | val: *llvm.Value, |
| 327 | attr_index: llvm.AttributeIndex, | 327 | attr_index: llvm.AttributeIndex, |
| 328 | attr_name: []const u8, | 328 | attr_name: []const u8, |
| 329 | ) !void { | 329 | ) !void { |
| ... | @@ -335,7 +335,7 @@ fn addLLVMAttr( | ... | @@ -335,7 +335,7 @@ fn addLLVMAttr( |
| 335 | 335 | ||
| 336 | fn addLLVMAttrStr( | 336 | fn addLLVMAttrStr( |
| 337 | ofile: *ObjectFile, | 337 | ofile: *ObjectFile, |
| 338 | val: llvm.ValueRef, | 338 | val: *llvm.Value, |
| 339 | attr_index: llvm.AttributeIndex, | 339 | attr_index: llvm.AttributeIndex, |
| 340 | attr_name: []const u8, | 340 | attr_name: []const u8, |
| 341 | attr_val: []const u8, | 341 | attr_val: []const u8, |
| ... | @@ -351,7 +351,7 @@ fn addLLVMAttrStr( | ... | @@ -351,7 +351,7 @@ fn addLLVMAttrStr( |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | fn addLLVMAttrInt( | 353 | fn addLLVMAttrInt( |
| 354 | val: llvm.ValueRef, | 354 | val: *llvm.Value, |
| 355 | attr_index: llvm.AttributeIndex, | 355 | attr_index: llvm.AttributeIndex, |
| 356 | attr_name: []const u8, | 356 | attr_name: []const u8, |
| 357 | attr_val: u64, | 357 | attr_val: u64, |
| ... | @@ -362,25 +362,25 @@ fn addLLVMAttrInt( | ... | @@ -362,25 +362,25 @@ fn addLLVMAttrInt( |
| 362 | llvm.AddAttributeAtIndex(val, attr_index, llvm_attr); | 362 | llvm.AddAttributeAtIndex(val, attr_index, llvm_attr); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void { | 365 | fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void { |
| 366 | return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name); | 366 | return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name); |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void { | 369 | fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void { |
| 370 | return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val); | 370 | return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val); |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void { | 373 | fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void { |
| 374 | return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val); | 374 | return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | fn renderLoadUntyped( | 377 | fn renderLoadUntyped( |
| 378 | ofile: *ObjectFile, | 378 | ofile: *ObjectFile, |
| 379 | ptr: llvm.ValueRef, | 379 | ptr: *llvm.Value, |
| 380 | alignment: Type.Pointer.Align, | 380 | alignment: Type.Pointer.Align, |
| 381 | vol: Type.Pointer.Vol, | 381 | vol: Type.Pointer.Vol, |
| 382 | name: [*]const u8, | 382 | name: [*]const u8, |
| 383 | ) !llvm.ValueRef { | 383 | ) !*llvm.Value { |
| 384 | const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory; | 384 | const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory; |
| 385 | switch (vol) { | 385 | switch (vol) { |
| 386 | Type.Pointer.Vol.Non => {}, | 386 | Type.Pointer.Vol.Non => {}, |
| ... | @@ -390,11 +390,11 @@ fn renderLoadUntyped( | ... | @@ -390,11 +390,11 @@ fn renderLoadUntyped( |
| 390 | return result; | 390 | return result; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef { | 393 | fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value { |
| 394 | return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name); | 394 | return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name); |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef { | 397 | pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value { |
| 398 | const child_type = ptr_type.key.child_type; | 398 | const child_type = ptr_type.key.child_type; |
| 399 | if (!child_type.hasBits()) { | 399 | if (!child_type.hasBits()) { |
| 400 | return null; | 400 | return null; |
| ... | @@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po | ... | @@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po |
| 407 | 407 | ||
| 408 | pub fn renderStoreUntyped( | 408 | pub fn renderStoreUntyped( |
| 409 | ofile: *ObjectFile, | 409 | ofile: *ObjectFile, |
| 410 | value: llvm.ValueRef, | 410 | value: *llvm.Value, |
| 411 | ptr: llvm.ValueRef, | 411 | ptr: *llvm.Value, |
| 412 | alignment: Type.Pointer.Align, | 412 | alignment: Type.Pointer.Align, |
| 413 | vol: Type.Pointer.Vol, | 413 | vol: Type.Pointer.Vol, |
| 414 | ) !llvm.ValueRef { | 414 | ) !*llvm.Value { |
| 415 | const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory; | 415 | const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory; |
| 416 | switch (vol) { | 416 | switch (vol) { |
| 417 | Type.Pointer.Vol.Non => {}, | 417 | Type.Pointer.Vol.Non => {}, |
| ... | @@ -423,10 +423,10 @@ pub fn renderStoreUntyped( | ... | @@ -423,10 +423,10 @@ pub fn renderStoreUntyped( |
| 423 | 423 | ||
| 424 | pub fn renderStore( | 424 | pub fn renderStore( |
| 425 | ofile: *ObjectFile, | 425 | ofile: *ObjectFile, |
| 426 | value: llvm.ValueRef, | 426 | value: *llvm.Value, |
| 427 | ptr: llvm.ValueRef, | 427 | ptr: *llvm.Value, |
| 428 | ptr_type: *Type.Pointer, | 428 | ptr_type: *Type.Pointer, |
| 429 | ) !llvm.ValueRef { | 429 | ) !*llvm.Value { |
| 430 | return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol); | 430 | return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol); |
| 431 | } | 431 | } |
| 432 | 432 | ||
| ... | @@ -435,7 +435,7 @@ pub fn renderAlloca( | ... | @@ -435,7 +435,7 @@ pub fn renderAlloca( |
| 435 | var_type: *Type, | 435 | var_type: *Type, |
| 436 | name: []const u8, | 436 | name: []const u8, |
| 437 | alignment: Type.Pointer.Align, | 437 | alignment: Type.Pointer.Align, |
| 438 | ) !llvm.ValueRef { | 438 | ) !*llvm.Value { |
| 439 | const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context); | 439 | const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context); |
| 440 | const name_with_null = try std.cstr.addNullByte(ofile.arena, name); | 440 | const name_with_null = try std.cstr.addNullByte(ofile.arena, name); |
| 441 | const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory; | 441 | const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory; |
| ... | @@ -443,7 +443,7 @@ pub fn renderAlloca( | ... | @@ -443,7 +443,7 @@ pub fn renderAlloca( |
| 443 | return result; | 443 | return result; |
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 { | 446 | pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 { |
| 447 | return switch (alignment) { | 447 | return switch (alignment) { |
| 448 | Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type), | 448 | Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type), |
| 449 | Type.Pointer.Align.Override => |a| a, | 449 | Type.Pointer.Align.Override => |a| a, |
src-self-hosted/compilation.zig+57-42| ... | @@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB | ... | @@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB |
| 37 | /// Data that is local to the event loop. | 37 | /// Data that is local to the event loop. |
| 38 | pub const ZigCompiler = struct { | 38 | pub const ZigCompiler = struct { |
| 39 | loop: *event.Loop, | 39 | loop: *event.Loop, |
| 40 | llvm_handle_pool: std.atomic.Stack(llvm.ContextRef), | 40 | llvm_handle_pool: std.atomic.Stack(*llvm.Context), |
| 41 | lld_lock: event.Lock, | 41 | lld_lock: event.Lock, |
| 42 | 42 | ||
| 43 | /// TODO pool these so that it doesn't have to lock | 43 | /// TODO pool these so that it doesn't have to lock |
| ... | @@ -55,12 +55,12 @@ pub const ZigCompiler = struct { | ... | @@ -55,12 +55,12 @@ pub const ZigCompiler = struct { |
| 55 | 55 | ||
| 56 | var seed_bytes: [@sizeOf(u64)]u8 = undefined; | 56 | var seed_bytes: [@sizeOf(u64)]u8 = undefined; |
| 57 | try std.os.getRandomBytes(seed_bytes[0..]); | 57 | try std.os.getRandomBytes(seed_bytes[0..]); |
| 58 | const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big); | 58 | const seed = mem.readIntNative(u64, &seed_bytes); |
| 59 | 59 | ||
| 60 | return ZigCompiler{ | 60 | return ZigCompiler{ |
| 61 | .loop = loop, | 61 | .loop = loop, |
| 62 | .lld_lock = event.Lock.init(loop), | 62 | .lld_lock = event.Lock.init(loop), |
| 63 | .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(), | 63 | .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(), |
| 64 | .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)), | 64 | .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)), |
| 65 | .native_libc = event.Future(LibCInstallation).init(loop), | 65 | .native_libc = event.Future(LibCInstallation).init(loop), |
| 66 | }; | 66 | }; |
| ... | @@ -70,7 +70,7 @@ pub const ZigCompiler = struct { | ... | @@ -70,7 +70,7 @@ pub const ZigCompiler = struct { |
| 70 | fn deinit(self: *ZigCompiler) void { | 70 | fn deinit(self: *ZigCompiler) void { |
| 71 | self.lld_lock.deinit(); | 71 | self.lld_lock.deinit(); |
| 72 | while (self.llvm_handle_pool.pop()) |node| { | 72 | while (self.llvm_handle_pool.pop()) |node| { |
| 73 | c.LLVMContextDispose(node.data); | 73 | llvm.ContextDispose(node.data); |
| 74 | self.loop.allocator.destroy(node); | 74 | self.loop.allocator.destroy(node); |
| 75 | } | 75 | } |
| 76 | } | 76 | } |
| ... | @@ -80,13 +80,14 @@ pub const ZigCompiler = struct { | ... | @@ -80,13 +80,14 @@ pub const ZigCompiler = struct { |
| 80 | pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle { | 80 | pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle { |
| 81 | if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node }; | 81 | if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node }; |
| 82 | 82 | ||
| 83 | const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory; | 83 | const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory; |
| 84 | errdefer c.LLVMContextDispose(context_ref); | 84 | errdefer llvm.ContextDispose(context_ref); |
| 85 | 85 | ||
| 86 | const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{ | 86 | const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node); |
| 87 | node.* = std.atomic.Stack(*llvm.Context).Node{ | ||
| 87 | .next = undefined, | 88 | .next = undefined, |
| 88 | .data = context_ref, | 89 | .data = context_ref, |
| 89 | }); | 90 | }; |
| 90 | errdefer self.loop.allocator.destroy(node); | 91 | errdefer self.loop.allocator.destroy(node); |
| 91 | 92 | ||
| 92 | return LlvmHandle{ .node = node }; | 93 | return LlvmHandle{ .node = node }; |
| ... | @@ -113,7 +114,7 @@ pub const ZigCompiler = struct { | ... | @@ -113,7 +114,7 @@ pub const ZigCompiler = struct { |
| 113 | }; | 114 | }; |
| 114 | 115 | ||
| 115 | pub const LlvmHandle = struct { | 116 | pub const LlvmHandle = struct { |
| 116 | node: *std.atomic.Stack(llvm.ContextRef).Node, | 117 | node: *std.atomic.Stack(*llvm.Context).Node, |
| 117 | 118 | ||
| 118 | pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void { | 119 | pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void { |
| 119 | zig_compiler.llvm_handle_pool.push(self.node); | 120 | zig_compiler.llvm_handle_pool.push(self.node); |
| ... | @@ -127,7 +128,7 @@ pub const Compilation = struct { | ... | @@ -127,7 +128,7 @@ pub const Compilation = struct { |
| 127 | llvm_triple: Buffer, | 128 | llvm_triple: Buffer, |
| 128 | root_src_path: ?[]const u8, | 129 | root_src_path: ?[]const u8, |
| 129 | target: Target, | 130 | target: Target, |
| 130 | llvm_target: llvm.TargetRef, | 131 | llvm_target: *llvm.Target, |
| 131 | build_mode: builtin.Mode, | 132 | build_mode: builtin.Mode, |
| 132 | zig_lib_dir: []const u8, | 133 | zig_lib_dir: []const u8, |
| 133 | zig_std_dir: []const u8, | 134 | zig_std_dir: []const u8, |
| ... | @@ -211,8 +212,8 @@ pub const Compilation = struct { | ... | @@ -211,8 +212,8 @@ pub const Compilation = struct { |
| 211 | false_value: *Value.Bool, | 212 | false_value: *Value.Bool, |
| 212 | noreturn_value: *Value.NoReturn, | 213 | noreturn_value: *Value.NoReturn, |
| 213 | 214 | ||
| 214 | target_machine: llvm.TargetMachineRef, | 215 | target_machine: *llvm.TargetMachine, |
| 215 | target_data_ref: llvm.TargetDataRef, | 216 | target_data_ref: *llvm.TargetData, |
| 216 | target_layout_str: [*]u8, | 217 | target_layout_str: [*]u8, |
| 217 | target_ptr_bits: u32, | 218 | target_ptr_bits: u32, |
| 218 | 219 | ||
| ... | @@ -300,6 +301,7 @@ pub const Compilation = struct { | ... | @@ -300,6 +301,7 @@ pub const Compilation = struct { |
| 300 | UserResourceLimitReached, | 301 | UserResourceLimitReached, |
| 301 | InvalidUtf8, | 302 | InvalidUtf8, |
| 302 | BadPathName, | 303 | BadPathName, |
| 304 | DeviceBusy, | ||
| 303 | }; | 305 | }; |
| 304 | 306 | ||
| 305 | pub const Event = union(enum) { | 307 | pub const Event = union(enum) { |
| ... | @@ -485,7 +487,7 @@ pub const Compilation = struct { | ... | @@ -485,7 +487,7 @@ pub const Compilation = struct { |
| 485 | comp.name = try Buffer.init(comp.arena(), name); | 487 | comp.name = try Buffer.init(comp.arena(), name); |
| 486 | comp.llvm_triple = try target.getTriple(comp.arena()); | 488 | comp.llvm_triple = try target.getTriple(comp.arena()); |
| 487 | comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple); | 489 | comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple); |
| 488 | comp.zig_std_dir = try std.os.path.join(comp.arena(), zig_lib_dir, "std"); | 490 | comp.zig_std_dir = try std.os.path.join(comp.arena(), [][]const u8{ zig_lib_dir, "std" }); |
| 489 | 491 | ||
| 490 | const opt_level = switch (build_mode) { | 492 | const opt_level = switch (build_mode) { |
| 491 | builtin.Mode.Debug => llvm.CodeGenLevelNone, | 493 | builtin.Mode.Debug => llvm.CodeGenLevelNone, |
| ... | @@ -595,7 +597,8 @@ pub const Compilation = struct { | ... | @@ -595,7 +597,8 @@ pub const Compilation = struct { |
| 595 | } | 597 | } |
| 596 | 598 | ||
| 597 | fn initTypes(comp: *Compilation) !void { | 599 | fn initTypes(comp: *Compilation) !void { |
| 598 | comp.meta_type = try comp.arena().create(Type.MetaType{ | 600 | comp.meta_type = try comp.arena().create(Type.MetaType); |
| 601 | comp.meta_type.* = Type.MetaType{ | ||
| 599 | .base = Type{ | 602 | .base = Type{ |
| 600 | .name = "type", | 603 | .name = "type", |
| 601 | .base = Value{ | 604 | .base = Value{ |
| ... | @@ -607,12 +610,13 @@ pub const Compilation = struct { | ... | @@ -607,12 +610,13 @@ pub const Compilation = struct { |
| 607 | .abi_alignment = Type.AbiAlignment.init(comp.loop), | 610 | .abi_alignment = Type.AbiAlignment.init(comp.loop), |
| 608 | }, | 611 | }, |
| 609 | .value = undefined, | 612 | .value = undefined, |
| 610 | }); | 613 | }; |
| 611 | comp.meta_type.value = &comp.meta_type.base; | 614 | comp.meta_type.value = &comp.meta_type.base; |
| 612 | comp.meta_type.base.base.typ = &comp.meta_type.base; | 615 | comp.meta_type.base.base.typ = &comp.meta_type.base; |
| 613 | assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null); | 616 | assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null); |
| 614 | 617 | ||
| 615 | comp.void_type = try comp.arena().create(Type.Void{ | 618 | comp.void_type = try comp.arena().create(Type.Void); |
| 619 | comp.void_type.* = Type.Void{ | ||
| 616 | .base = Type{ | 620 | .base = Type{ |
| 617 | .name = "void", | 621 | .name = "void", |
| 618 | .base = Value{ | 622 | .base = Value{ |
| ... | @@ -623,10 +627,11 @@ pub const Compilation = struct { | ... | @@ -623,10 +627,11 @@ pub const Compilation = struct { |
| 623 | .id = builtin.TypeId.Void, | 627 | .id = builtin.TypeId.Void, |
| 624 | .abi_alignment = Type.AbiAlignment.init(comp.loop), | 628 | .abi_alignment = Type.AbiAlignment.init(comp.loop), |
| 625 | }, | 629 | }, |
| 626 | }); | 630 | }; |
| 627 | assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null); | 631 | assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null); |
| 628 | 632 | ||
| 629 | comp.noreturn_type = try comp.arena().create(Type.NoReturn{ | 633 | comp.noreturn_type = try comp.arena().create(Type.NoReturn); |
| 634 | comp.noreturn_type.* = Type.NoReturn{ | ||
| 630 | .base = Type{ | 635 | .base = Type{ |
| 631 | .name = "noreturn", | 636 | .name = "noreturn", |
| 632 | .base = Value{ | 637 | .base = Value{ |
| ... | @@ -637,10 +642,11 @@ pub const Compilation = struct { | ... | @@ -637,10 +642,11 @@ pub const Compilation = struct { |
| 637 | .id = builtin.TypeId.NoReturn, | 642 | .id = builtin.TypeId.NoReturn, |
| 638 | .abi_alignment = Type.AbiAlignment.init(comp.loop), | 643 | .abi_alignment = Type.AbiAlignment.init(comp.loop), |
| 639 | }, | 644 | }, |
| 640 | }); | 645 | }; |
| 641 | assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null); | 646 | assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null); |
| 642 | 647 | ||
| 643 | comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt{ | 648 | comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt); |
| 649 | comp.comptime_int_type.* = Type.ComptimeInt{ | ||
| 644 | .base = Type{ | 650 | .base = Type{ |
| 645 | .name = "comptime_int", | 651 | .name = "comptime_int", |
| 646 | .base = Value{ | 652 | .base = Value{ |
| ... | @@ -651,10 +657,11 @@ pub const Compilation = struct { | ... | @@ -651,10 +657,11 @@ pub const Compilation = struct { |
| 651 | .id = builtin.TypeId.ComptimeInt, | 657 | .id = builtin.TypeId.ComptimeInt, |
| 652 | .abi_alignment = Type.AbiAlignment.init(comp.loop), | 658 | .abi_alignment = Type.AbiAlignment.init(comp.loop), |
| 653 | }, | 659 | }, |
| 654 | }); | 660 | }; |
| 655 | assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null); | 661 | assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null); |
| 656 | 662 | ||
| 657 | comp.bool_type = try comp.arena().create(Type.Bool{ | 663 | comp.bool_type = try comp.arena().create(Type.Bool); |
| 664 | comp.bool_type.* = Type.Bool{ | ||
| 658 | .base = Type{ | 665 | .base = Type{ |
| 659 | .name = "bool", | 666 | .name = "bool", |
| 660 | .base = Value{ | 667 | .base = Value{ |
| ... | @@ -665,45 +672,50 @@ pub const Compilation = struct { | ... | @@ -665,45 +672,50 @@ pub const Compilation = struct { |
| 665 | .id = builtin.TypeId.Bool, | 672 | .id = builtin.TypeId.Bool, |
| 666 | .abi_alignment = Type.AbiAlignment.init(comp.loop), | 673 | .abi_alignment = Type.AbiAlignment.init(comp.loop), |
| 667 | }, | 674 | }, |
| 668 | }); | 675 | }; |
| 669 | assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null); | 676 | assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null); |
| 670 | 677 | ||
| 671 | comp.void_value = try comp.arena().create(Value.Void{ | 678 | comp.void_value = try comp.arena().create(Value.Void); |
| 679 | comp.void_value.* = Value.Void{ | ||
| 672 | .base = Value{ | 680 | .base = Value{ |
| 673 | .id = Value.Id.Void, | 681 | .id = Value.Id.Void, |
| 674 | .typ = &Type.Void.get(comp).base, | 682 | .typ = &Type.Void.get(comp).base, |
| 675 | .ref_count = std.atomic.Int(usize).init(1), | 683 | .ref_count = std.atomic.Int(usize).init(1), |
| 676 | }, | 684 | }, |
| 677 | }); | 685 | }; |
| 678 | 686 | ||
| 679 | comp.true_value = try comp.arena().create(Value.Bool{ | 687 | comp.true_value = try comp.arena().create(Value.Bool); |
| 688 | comp.true_value.* = Value.Bool{ | ||
| 680 | .base = Value{ | 689 | .base = Value{ |
| 681 | .id = Value.Id.Bool, | 690 | .id = Value.Id.Bool, |
| 682 | .typ = &Type.Bool.get(comp).base, | 691 | .typ = &Type.Bool.get(comp).base, |
| 683 | .ref_count = std.atomic.Int(usize).init(1), | 692 | .ref_count = std.atomic.Int(usize).init(1), |
| 684 | }, | 693 | }, |
| 685 | .x = true, | 694 | .x = true, |
| 686 | }); | 695 | }; |
| 687 | 696 | ||
| 688 | comp.false_value = try comp.arena().create(Value.Bool{ | 697 | comp.false_value = try comp.arena().create(Value.Bool); |
| 698 | comp.false_value.* = Value.Bool{ | ||
| 689 | .base = Value{ | 699 | .base = Value{ |
| 690 | .id = Value.Id.Bool, | 700 | .id = Value.Id.Bool, |
| 691 | .typ = &Type.Bool.get(comp).base, | 701 | .typ = &Type.Bool.get(comp).base, |
| 692 | .ref_count = std.atomic.Int(usize).init(1), | 702 | .ref_count = std.atomic.Int(usize).init(1), |
| 693 | }, | 703 | }, |
| 694 | .x = false, | 704 | .x = false, |
| 695 | }); | 705 | }; |
| 696 | 706 | ||
| 697 | comp.noreturn_value = try comp.arena().create(Value.NoReturn{ | 707 | comp.noreturn_value = try comp.arena().create(Value.NoReturn); |
| 708 | comp.noreturn_value.* = Value.NoReturn{ | ||
| 698 | .base = Value{ | 709 | .base = Value{ |
| 699 | .id = Value.Id.NoReturn, | 710 | .id = Value.Id.NoReturn, |
| 700 | .typ = &Type.NoReturn.get(comp).base, | 711 | .typ = &Type.NoReturn.get(comp).base, |
| 701 | .ref_count = std.atomic.Int(usize).init(1), | 712 | .ref_count = std.atomic.Int(usize).init(1), |
| 702 | }, | 713 | }, |
| 703 | }); | 714 | }; |
| 704 | 715 | ||
| 705 | for (CInt.list) |cint, i| { | 716 | for (CInt.list) |cint, i| { |
| 706 | const c_int_type = try comp.arena().create(Type.Int{ | 717 | const c_int_type = try comp.arena().create(Type.Int); |
| 718 | c_int_type.* = Type.Int{ | ||
| 707 | .base = Type{ | 719 | .base = Type{ |
| 708 | .name = cint.zig_name, | 720 | .name = cint.zig_name, |
| 709 | .base = Value{ | 721 | .base = Value{ |
| ... | @@ -719,11 +731,12 @@ pub const Compilation = struct { | ... | @@ -719,11 +731,12 @@ pub const Compilation = struct { |
| 719 | .bit_count = comp.target.cIntTypeSizeInBits(cint.id), | 731 | .bit_count = comp.target.cIntTypeSizeInBits(cint.id), |
| 720 | }, | 732 | }, |
| 721 | .garbage_node = undefined, | 733 | .garbage_node = undefined, |
| 722 | }); | 734 | }; |
| 723 | comp.c_int_types[i] = c_int_type; | 735 | comp.c_int_types[i] = c_int_type; |
| 724 | assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null); | 736 | assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null); |
| 725 | } | 737 | } |
| 726 | comp.u8_type = try comp.arena().create(Type.Int{ | 738 | comp.u8_type = try comp.arena().create(Type.Int); |
| 739 | comp.u8_type.* = Type.Int{ | ||
| 727 | .base = Type{ | 740 | .base = Type{ |
| 728 | .name = "u8", | 741 | .name = "u8", |
| 729 | .base = Value{ | 742 | .base = Value{ |
| ... | @@ -739,7 +752,7 @@ pub const Compilation = struct { | ... | @@ -739,7 +752,7 @@ pub const Compilation = struct { |
| 739 | .bit_count = 8, | 752 | .bit_count = 8, |
| 740 | }, | 753 | }, |
| 741 | .garbage_node = undefined, | 754 | .garbage_node = undefined, |
| 742 | }); | 755 | }; |
| 743 | assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null); | 756 | assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null); |
| 744 | } | 757 | } |
| 745 | 758 | ||
| ... | @@ -828,7 +841,7 @@ pub const Compilation = struct { | ... | @@ -828,7 +841,7 @@ pub const Compilation = struct { |
| 828 | }; | 841 | }; |
| 829 | errdefer self.gpa().free(source_code); | 842 | errdefer self.gpa().free(source_code); |
| 830 | 843 | ||
| 831 | const tree = try self.gpa().createOne(ast.Tree); | 844 | const tree = try self.gpa().create(ast.Tree); |
| 832 | tree.* = try std.zig.parse(self.gpa(), source_code); | 845 | tree.* = try std.zig.parse(self.gpa(), source_code); |
| 833 | errdefer { | 846 | errdefer { |
| 834 | tree.deinit(); | 847 | tree.deinit(); |
| ... | @@ -924,7 +937,8 @@ pub const Compilation = struct { | ... | @@ -924,7 +937,8 @@ pub const Compilation = struct { |
| 924 | } | 937 | } |
| 925 | } else { | 938 | } else { |
| 926 | // add new decl | 939 | // add new decl |
| 927 | const fn_decl = try self.gpa().create(Decl.Fn{ | 940 | const fn_decl = try self.gpa().create(Decl.Fn); |
| 941 | fn_decl.* = Decl.Fn{ | ||
| 928 | .base = Decl{ | 942 | .base = Decl{ |
| 929 | .id = Decl.Id.Fn, | 943 | .id = Decl.Id.Fn, |
| 930 | .name = name, | 944 | .name = name, |
| ... | @@ -935,7 +949,7 @@ pub const Compilation = struct { | ... | @@ -935,7 +949,7 @@ pub const Compilation = struct { |
| 935 | }, | 949 | }, |
| 936 | .value = Decl.Fn.Val{ .Unresolved = {} }, | 950 | .value = Decl.Fn.Val{ .Unresolved = {} }, |
| 937 | .fn_proto = fn_proto, | 951 | .fn_proto = fn_proto, |
| 938 | }); | 952 | }; |
| 939 | tree_scope.base.ref(); | 953 | tree_scope.base.ref(); |
| 940 | errdefer self.gpa().destroy(fn_decl); | 954 | errdefer self.gpa().destroy(fn_decl); |
| 941 | 955 | ||
| ... | @@ -1139,12 +1153,13 @@ pub const Compilation = struct { | ... | @@ -1139,12 +1153,13 @@ pub const Compilation = struct { |
| 1139 | } | 1153 | } |
| 1140 | } | 1154 | } |
| 1141 | 1155 | ||
| 1142 | const link_lib = try self.gpa().create(LinkLib{ | 1156 | const link_lib = try self.gpa().create(LinkLib); |
| 1157 | link_lib.* = LinkLib{ | ||
| 1143 | .name = name, | 1158 | .name = name, |
| 1144 | .path = null, | 1159 | .path = null, |
| 1145 | .provided_explicitly = provided_explicitly, | 1160 | .provided_explicitly = provided_explicitly, |
| 1146 | .symbols = ArrayList([]u8).init(self.gpa()), | 1161 | .symbols = ArrayList([]u8).init(self.gpa()), |
| 1147 | }); | 1162 | }; |
| 1148 | try self.link_libs_list.append(link_lib); | 1163 | try self.link_libs_list.append(link_lib); |
| 1149 | if (is_libc) { | 1164 | if (is_libc) { |
| 1150 | self.libc_link_lib = link_lib; | 1165 | self.libc_link_lib = link_lib; |
| ... | @@ -1183,7 +1198,7 @@ pub const Compilation = struct { | ... | @@ -1183,7 +1198,7 @@ pub const Compilation = struct { |
| 1183 | const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix); | 1198 | const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix); |
| 1184 | defer self.gpa().free(file_name); | 1199 | defer self.gpa().free(file_name); |
| 1185 | 1200 | ||
| 1186 | const full_path = try os.path.join(self.gpa(), tmp_dir, file_name[0..]); | 1201 | const full_path = try os.path.join(self.gpa(), [][]const u8{ tmp_dir, file_name[0..] }); |
| 1187 | errdefer self.gpa().free(full_path); | 1202 | errdefer self.gpa().free(full_path); |
| 1188 | 1203 | ||
| 1189 | return Buffer.fromOwnedSlice(self.gpa(), full_path); | 1204 | return Buffer.fromOwnedSlice(self.gpa(), full_path); |
| ... | @@ -1204,7 +1219,7 @@ pub const Compilation = struct { | ... | @@ -1204,7 +1219,7 @@ pub const Compilation = struct { |
| 1204 | const zig_dir_path = try getZigDir(self.gpa()); | 1219 | const zig_dir_path = try getZigDir(self.gpa()); |
| 1205 | defer self.gpa().free(zig_dir_path); | 1220 | defer self.gpa().free(zig_dir_path); |
| 1206 | 1221 | ||
| 1207 | const tmp_dir = try os.path.join(self.arena(), zig_dir_path, comp_dir_name[0..]); | 1222 | const tmp_dir = try os.path.join(self.arena(), [][]const u8{ zig_dir_path, comp_dir_name[0..] }); |
| 1208 | try os.makePath(self.gpa(), tmp_dir); | 1223 | try os.makePath(self.gpa(), tmp_dir); |
| 1209 | return tmp_dir; | 1224 | return tmp_dir; |
| 1210 | } | 1225 | } |
src-self-hosted/errmsg.zig+12-8| ... | @@ -118,7 +118,8 @@ pub const Msg = struct { | ... | @@ -118,7 +118,8 @@ pub const Msg = struct { |
| 118 | const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath); | 118 | const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath); |
| 119 | errdefer comp.gpa().free(realpath); | 119 | errdefer comp.gpa().free(realpath); |
| 120 | 120 | ||
| 121 | const msg = try comp.gpa().create(Msg{ | 121 | const msg = try comp.gpa().create(Msg); |
| 122 | msg.* = Msg{ | ||
| 122 | .text = text, | 123 | .text = text, |
| 123 | .realpath = realpath, | 124 | .realpath = realpath, |
| 124 | .data = Data{ | 125 | .data = Data{ |
| ... | @@ -128,7 +129,7 @@ pub const Msg = struct { | ... | @@ -128,7 +129,7 @@ pub const Msg = struct { |
| 128 | .span = span, | 129 | .span = span, |
| 129 | }, | 130 | }, |
| 130 | }, | 131 | }, |
| 131 | }); | 132 | }; |
| 132 | tree_scope.base.ref(); | 133 | tree_scope.base.ref(); |
| 133 | return msg; | 134 | return msg; |
| 134 | } | 135 | } |
| ... | @@ -139,13 +140,14 @@ pub const Msg = struct { | ... | @@ -139,13 +140,14 @@ pub const Msg = struct { |
| 139 | const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath); | 140 | const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath); |
| 140 | errdefer comp.gpa().free(realpath_copy); | 141 | errdefer comp.gpa().free(realpath_copy); |
| 141 | 142 | ||
| 142 | const msg = try comp.gpa().create(Msg{ | 143 | const msg = try comp.gpa().create(Msg); |
| 144 | msg.* = Msg{ | ||
| 143 | .text = text, | 145 | .text = text, |
| 144 | .realpath = realpath_copy, | 146 | .realpath = realpath_copy, |
| 145 | .data = Data{ | 147 | .data = Data{ |
| 146 | .Cli = Cli{ .allocator = comp.gpa() }, | 148 | .Cli = Cli{ .allocator = comp.gpa() }, |
| 147 | }, | 149 | }, |
| 148 | }); | 150 | }; |
| 149 | return msg; | 151 | return msg; |
| 150 | } | 152 | } |
| 151 | 153 | ||
| ... | @@ -164,7 +166,8 @@ pub const Msg = struct { | ... | @@ -164,7 +166,8 @@ pub const Msg = struct { |
| 164 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; | 166 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; |
| 165 | try parse_error.render(&tree_scope.tree.tokens, out_stream); | 167 | try parse_error.render(&tree_scope.tree.tokens, out_stream); |
| 166 | 168 | ||
| 167 | const msg = try comp.gpa().create(Msg{ | 169 | const msg = try comp.gpa().create(Msg); |
| 170 | msg.* = Msg{ | ||
| 168 | .text = undefined, | 171 | .text = undefined, |
| 169 | .realpath = realpath_copy, | 172 | .realpath = realpath_copy, |
| 170 | .data = Data{ | 173 | .data = Data{ |
| ... | @@ -177,7 +180,7 @@ pub const Msg = struct { | ... | @@ -177,7 +180,7 @@ pub const Msg = struct { |
| 177 | }, | 180 | }, |
| 178 | }, | 181 | }, |
| 179 | }, | 182 | }, |
| 180 | }); | 183 | }; |
| 181 | tree_scope.base.ref(); | 184 | tree_scope.base.ref(); |
| 182 | msg.text = text_buf.toOwnedSlice(); | 185 | msg.text = text_buf.toOwnedSlice(); |
| 183 | return msg; | 186 | return msg; |
| ... | @@ -203,7 +206,8 @@ pub const Msg = struct { | ... | @@ -203,7 +206,8 @@ pub const Msg = struct { |
| 203 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; | 206 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; |
| 204 | try parse_error.render(&tree.tokens, out_stream); | 207 | try parse_error.render(&tree.tokens, out_stream); |
| 205 | 208 | ||
| 206 | const msg = try allocator.create(Msg{ | 209 | const msg = try allocator.create(Msg); |
| 210 | msg.* = Msg{ | ||
| 207 | .text = undefined, | 211 | .text = undefined, |
| 208 | .realpath = realpath_copy, | 212 | .realpath = realpath_copy, |
| 209 | .data = Data{ | 213 | .data = Data{ |
| ... | @@ -216,7 +220,7 @@ pub const Msg = struct { | ... | @@ -216,7 +220,7 @@ pub const Msg = struct { |
| 216 | }, | 220 | }, |
| 217 | }, | 221 | }, |
| 218 | }, | 222 | }, |
| 219 | }); | 223 | }; |
| 220 | msg.text = text_buf.toOwnedSlice(); | 224 | msg.text = text_buf.toOwnedSlice(); |
| 221 | errdefer allocator.destroy(msg); | 225 | errdefer allocator.destroy(msg); |
| 222 | 226 |
src-self-hosted/introspect.zig+2-2| ... | @@ -8,10 +8,10 @@ const warn = std.debug.warn; | ... | @@ -8,10 +8,10 @@ const warn = std.debug.warn; |
| 8 | 8 | ||
| 9 | /// Caller must free result | 9 | /// Caller must free result |
| 10 | pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 { | 10 | pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 { |
| 11 | const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig"); | 11 | const test_zig_dir = try os.path.join(allocator, [][]const u8{ test_path, "lib", "zig" }); |
| 12 | errdefer allocator.free(test_zig_dir); | 12 | errdefer allocator.free(test_zig_dir); |
| 13 | 13 | ||
| 14 | const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig"); | 14 | const test_index_file = try os.path.join(allocator, [][]const u8{ test_zig_dir, "std", "index.zig" }); |
| 15 | defer allocator.free(test_index_file); | 15 | defer allocator.free(test_index_file); |
| 16 | 16 | ||
| 17 | var file = try os.File.openRead(test_index_file); | 17 | var file = try os.File.openRead(test_index_file); |
src-self-hosted/ir.zig+19-16| ... | @@ -67,7 +67,7 @@ pub const Inst = struct { | ... | @@ -67,7 +67,7 @@ pub const Inst = struct { |
| 67 | parent: ?*Inst, | 67 | parent: ?*Inst, |
| 68 | 68 | ||
| 69 | /// populated durign codegen | 69 | /// populated durign codegen |
| 70 | llvm_value: ?llvm.ValueRef, | 70 | llvm_value: ?*llvm.Value, |
| 71 | 71 | ||
| 72 | pub fn cast(base: *Inst, comptime T: type) ?*T { | 72 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
| 73 | if (base.id == comptime typeToId(T)) { | 73 | if (base.id == comptime typeToId(T)) { |
| ... | @@ -129,7 +129,7 @@ pub const Inst = struct { | ... | @@ -129,7 +129,7 @@ pub const Inst = struct { |
| 129 | } | 129 | } |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) { | 132 | pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) { |
| 133 | switch (base.id) { | 133 | switch (base.id) { |
| 134 | Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val), | 134 | Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val), |
| 135 | Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val), | 135 | Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val), |
| ... | @@ -313,10 +313,10 @@ pub const Inst = struct { | ... | @@ -313,10 +313,10 @@ pub const Inst = struct { |
| 313 | return new_inst; | 313 | return new_inst; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | 316 | pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { |
| 317 | const fn_ref = self.params.fn_ref.llvm_value.?; | 317 | const fn_ref = self.params.fn_ref.llvm_value.?; |
| 318 | 318 | ||
| 319 | const args = try ofile.arena.alloc(llvm.ValueRef, self.params.args.len); | 319 | const args = try ofile.arena.alloc(*llvm.Value, self.params.args.len); |
| 320 | for (self.params.args) |arg, i| { | 320 | for (self.params.args) |arg, i| { |
| 321 | args[i] = arg.llvm_value.?; | 321 | args[i] = arg.llvm_value.?; |
| 322 | } | 322 | } |
| ... | @@ -360,7 +360,7 @@ pub const Inst = struct { | ... | @@ -360,7 +360,7 @@ pub const Inst = struct { |
| 360 | return new_inst; | 360 | return new_inst; |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | 363 | pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { |
| 364 | return self.base.val.KnownValue.getLlvmConst(ofile); | 364 | return self.base.val.KnownValue.getLlvmConst(ofile); |
| 365 | } | 365 | } |
| 366 | }; | 366 | }; |
| ... | @@ -392,7 +392,7 @@ pub const Inst = struct { | ... | @@ -392,7 +392,7 @@ pub const Inst = struct { |
| 392 | return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value }); | 392 | return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value }); |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | 395 | pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { |
| 396 | const value = self.params.return_value.llvm_value; | 396 | const value = self.params.return_value.llvm_value; |
| 397 | const return_type = self.params.return_value.getKnownType(); | 397 | const return_type = self.params.return_value.getKnownType(); |
| 398 | 398 | ||
| ... | @@ -540,7 +540,7 @@ pub const Inst = struct { | ... | @@ -540,7 +540,7 @@ pub const Inst = struct { |
| 540 | } | 540 | } |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) llvm.ValueRef { | 543 | pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value { |
| 544 | switch (self.params.var_scope.data) { | 544 | switch (self.params.var_scope.data) { |
| 545 | Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass | 545 | Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass |
| 546 | Scope.Var.Data.Param => |param| return param.llvm_value, | 546 | Scope.Var.Data.Param => |param| return param.llvm_value, |
| ... | @@ -596,7 +596,7 @@ pub const Inst = struct { | ... | @@ -596,7 +596,7 @@ pub const Inst = struct { |
| 596 | return new_inst; | 596 | return new_inst; |
| 597 | } | 597 | } |
| 598 | 598 | ||
| 599 | pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef { | 599 | pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value { |
| 600 | const child_type = self.base.getKnownType(); | 600 | const child_type = self.base.getKnownType(); |
| 601 | if (!child_type.hasBits()) { | 601 | if (!child_type.hasBits()) { |
| 602 | return null; | 602 | return null; |
| ... | @@ -935,8 +935,8 @@ pub const BasicBlock = struct { | ... | @@ -935,8 +935,8 @@ pub const BasicBlock = struct { |
| 935 | ref_instruction: ?*Inst, | 935 | ref_instruction: ?*Inst, |
| 936 | 936 | ||
| 937 | /// for codegen | 937 | /// for codegen |
| 938 | llvm_block: llvm.BasicBlockRef, | 938 | llvm_block: *llvm.BasicBlock, |
| 939 | llvm_exit_block: llvm.BasicBlockRef, | 939 | llvm_exit_block: *llvm.BasicBlock, |
| 940 | 940 | ||
| 941 | /// the basic block that is derived from this one in analysis | 941 | /// the basic block that is derived from this one in analysis |
| 942 | child: ?*BasicBlock, | 942 | child: ?*BasicBlock, |
| ... | @@ -1021,12 +1021,13 @@ pub const Builder = struct { | ... | @@ -1021,12 +1021,13 @@ pub const Builder = struct { |
| 1021 | pub const Error = Analyze.Error; | 1021 | pub const Error = Analyze.Error; |
| 1022 | 1022 | ||
| 1023 | pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder { | 1023 | pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder { |
| 1024 | const code = try comp.gpa().create(Code{ | 1024 | const code = try comp.gpa().create(Code); |
| 1025 | code.* = Code{ | ||
| 1025 | .basic_block_list = undefined, | 1026 | .basic_block_list = undefined, |
| 1026 | .arena = std.heap.ArenaAllocator.init(comp.gpa()), | 1027 | .arena = std.heap.ArenaAllocator.init(comp.gpa()), |
| 1027 | .return_type = null, | 1028 | .return_type = null, |
| 1028 | .tree_scope = tree_scope, | 1029 | .tree_scope = tree_scope, |
| 1029 | }); | 1030 | }; |
| 1030 | code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator); | 1031 | code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator); |
| 1031 | errdefer code.destroy(comp.gpa()); | 1032 | errdefer code.destroy(comp.gpa()); |
| 1032 | 1033 | ||
| ... | @@ -1052,7 +1053,8 @@ pub const Builder = struct { | ... | @@ -1052,7 +1053,8 @@ pub const Builder = struct { |
| 1052 | 1053 | ||
| 1053 | /// No need to clean up resources thanks to the arena allocator. | 1054 | /// No need to clean up resources thanks to the arena allocator. |
| 1054 | pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock { | 1055 | pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock { |
| 1055 | const basic_block = try self.arena().create(BasicBlock{ | 1056 | const basic_block = try self.arena().create(BasicBlock); |
| 1057 | basic_block.* = BasicBlock{ | ||
| 1056 | .ref_count = 0, | 1058 | .ref_count = 0, |
| 1057 | .name_hint = name_hint, | 1059 | .name_hint = name_hint, |
| 1058 | .debug_id = self.next_debug_id, | 1060 | .debug_id = self.next_debug_id, |
| ... | @@ -1063,7 +1065,7 @@ pub const Builder = struct { | ... | @@ -1063,7 +1065,7 @@ pub const Builder = struct { |
| 1063 | .ref_instruction = null, | 1065 | .ref_instruction = null, |
| 1064 | .llvm_block = undefined, | 1066 | .llvm_block = undefined, |
| 1065 | .llvm_exit_block = undefined, | 1067 | .llvm_exit_block = undefined, |
| 1066 | }); | 1068 | }; |
| 1067 | self.next_debug_id += 1; | 1069 | self.next_debug_id += 1; |
| 1068 | return basic_block; | 1070 | return basic_block; |
| 1069 | } | 1071 | } |
| ... | @@ -1774,7 +1776,8 @@ pub const Builder = struct { | ... | @@ -1774,7 +1776,8 @@ pub const Builder = struct { |
| 1774 | params: I.Params, | 1776 | params: I.Params, |
| 1775 | is_generated: bool, | 1777 | is_generated: bool, |
| 1776 | ) !*Inst { | 1778 | ) !*Inst { |
| 1777 | const inst = try self.arena().create(I{ | 1779 | const inst = try self.arena().create(I); |
| 1780 | inst.* = I{ | ||
| 1778 | .base = Inst{ | 1781 | .base = Inst{ |
| 1779 | .id = Inst.typeToId(I), | 1782 | .id = Inst.typeToId(I), |
| 1780 | .is_generated = is_generated, | 1783 | .is_generated = is_generated, |
| ... | @@ -1793,7 +1796,7 @@ pub const Builder = struct { | ... | @@ -1793,7 +1796,7 @@ pub const Builder = struct { |
| 1793 | .owner_bb = self.current_basic_block, | 1796 | .owner_bb = self.current_basic_block, |
| 1794 | }, | 1797 | }, |
| 1795 | .params = params, | 1798 | .params = params, |
| 1796 | }); | 1799 | }; |
| 1797 | 1800 | ||
| 1798 | // Look at the params and ref() other instructions | 1801 | // Look at the params and ref() other instructions |
| 1799 | comptime var i = 0; | 1802 | comptime var i = 0; |
src-self-hosted/libc_installation.zig+27-18| ... | @@ -57,10 +57,10 @@ pub const LibCInstallation = struct { | ... | @@ -57,10 +57,10 @@ pub const LibCInstallation = struct { |
| 57 | const contents = try std.io.readFileAlloc(allocator, libc_file); | 57 | const contents = try std.io.readFileAlloc(allocator, libc_file); |
| 58 | defer allocator.free(contents); | 58 | defer allocator.free(contents); |
| 59 | 59 | ||
| 60 | var it = std.mem.split(contents, "\n"); | 60 | var it = std.mem.tokenize(contents, "\n"); |
| 61 | while (it.next()) |line| { | 61 | while (it.next()) |line| { |
| 62 | if (line.len == 0 or line[0] == '#') continue; | 62 | if (line.len == 0 or line[0] == '#') continue; |
| 63 | var line_it = std.mem.split(line, "="); | 63 | var line_it = std.mem.separate(line, "="); |
| 64 | const name = line_it.next() orelse { | 64 | const name = line_it.next() orelse { |
| 65 | try stderr.print("missing equal sign after field name\n"); | 65 | try stderr.print("missing equal sign after field name\n"); |
| 66 | return error.ParseError; | 66 | return error.ParseError; |
| ... | @@ -154,8 +154,8 @@ pub const LibCInstallation = struct { | ... | @@ -154,8 +154,8 @@ pub const LibCInstallation = struct { |
| 154 | c.ZigFindWindowsSdkError.None => { | 154 | c.ZigFindWindowsSdkError.None => { |
| 155 | windows_sdk = sdk; | 155 | windows_sdk = sdk; |
| 156 | 156 | ||
| 157 | if (sdk.msvc_lib_dir_ptr) |ptr| { | 157 | if (sdk.msvc_lib_dir_ptr != 0) { |
| 158 | self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]); | 158 | self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); |
| 159 | } | 159 | } |
| 160 | try group.call(findNativeKernel32LibDir, self, loop, sdk); | 160 | try group.call(findNativeKernel32LibDir, self, loop, sdk); |
| 161 | try group.call(findNativeIncludeDirWindows, self, loop, sdk); | 161 | try group.call(findNativeIncludeDirWindows, self, loop, sdk); |
| ... | @@ -213,7 +213,7 @@ pub const LibCInstallation = struct { | ... | @@ -213,7 +213,7 @@ pub const LibCInstallation = struct { |
| 213 | }, | 213 | }, |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | var it = std.mem.split(exec_result.stderr, "\n\r"); | 216 | var it = std.mem.tokenize(exec_result.stderr, "\n\r"); |
| 217 | var search_paths = std.ArrayList([]const u8).init(loop.allocator); | 217 | var search_paths = std.ArrayList([]const u8).init(loop.allocator); |
| 218 | defer search_paths.deinit(); | 218 | defer search_paths.deinit(); |
| 219 | while (it.next()) |line| { | 219 | while (it.next()) |line| { |
| ... | @@ -230,7 +230,7 @@ pub const LibCInstallation = struct { | ... | @@ -230,7 +230,7 @@ pub const LibCInstallation = struct { |
| 230 | while (path_i < search_paths.len) : (path_i += 1) { | 230 | while (path_i < search_paths.len) : (path_i += 1) { |
| 231 | const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); | 231 | const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); |
| 232 | const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); | 232 | const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); |
| 233 | const stdlib_path = try std.os.path.join(loop.allocator, search_path, "stdlib.h"); | 233 | const stdlib_path = try std.os.path.join(loop.allocator, [][]const u8{ search_path, "stdlib.h" }); |
| 234 | defer loop.allocator.free(stdlib_path); | 234 | defer loop.allocator.free(stdlib_path); |
| 235 | 235 | ||
| 236 | if (try fileExists(stdlib_path)) { | 236 | if (try fileExists(stdlib_path)) { |
| ... | @@ -254,7 +254,10 @@ pub const LibCInstallation = struct { | ... | @@ -254,7 +254,10 @@ pub const LibCInstallation = struct { |
| 254 | const stream = &std.io.BufferOutStream.init(&result_buf).stream; | 254 | const stream = &std.io.BufferOutStream.init(&result_buf).stream; |
| 255 | try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version); | 255 | try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version); |
| 256 | 256 | ||
| 257 | const stdlib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "stdlib.h"); | 257 | const stdlib_path = try std.os.path.join( |
| 258 | loop.allocator, | ||
| 259 | [][]const u8{ result_buf.toSliceConst(), "stdlib.h" }, | ||
| 260 | ); | ||
| 258 | defer loop.allocator.free(stdlib_path); | 261 | defer loop.allocator.free(stdlib_path); |
| 259 | 262 | ||
| 260 | if (try fileExists(stdlib_path)) { | 263 | if (try fileExists(stdlib_path)) { |
| ... | @@ -283,7 +286,10 @@ pub const LibCInstallation = struct { | ... | @@ -283,7 +286,10 @@ pub const LibCInstallation = struct { |
| 283 | builtin.Arch.aarch64v8 => try stream.write("arm"), | 286 | builtin.Arch.aarch64v8 => try stream.write("arm"), |
| 284 | else => return error.UnsupportedArchitecture, | 287 | else => return error.UnsupportedArchitecture, |
| 285 | } | 288 | } |
| 286 | const ucrt_lib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "ucrt.lib"); | 289 | const ucrt_lib_path = try std.os.path.join( |
| 290 | loop.allocator, | ||
| 291 | [][]const u8{ result_buf.toSliceConst(), "ucrt.lib" }, | ||
| 292 | ); | ||
| 287 | defer loop.allocator.free(ucrt_lib_path); | 293 | defer loop.allocator.free(ucrt_lib_path); |
| 288 | if (try fileExists(ucrt_lib_path)) { | 294 | if (try fileExists(ucrt_lib_path)) { |
| 289 | self.lib_dir = result_buf.toOwnedSlice(); | 295 | self.lib_dir = result_buf.toOwnedSlice(); |
| ... | @@ -358,7 +364,10 @@ pub const LibCInstallation = struct { | ... | @@ -358,7 +364,10 @@ pub const LibCInstallation = struct { |
| 358 | builtin.Arch.aarch64v8 => try stream.write("arm\\"), | 364 | builtin.Arch.aarch64v8 => try stream.write("arm\\"), |
| 359 | else => return error.UnsupportedArchitecture, | 365 | else => return error.UnsupportedArchitecture, |
| 360 | } | 366 | } |
| 361 | const kernel32_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "kernel32.lib"); | 367 | const kernel32_path = try std.os.path.join( |
| 368 | loop.allocator, | ||
| 369 | [][]const u8{ result_buf.toSliceConst(), "kernel32.lib" }, | ||
| 370 | ); | ||
| 362 | defer loop.allocator.free(kernel32_path); | 371 | defer loop.allocator.free(kernel32_path); |
| 363 | if (try fileExists(kernel32_path)) { | 372 | if (try fileExists(kernel32_path)) { |
| 364 | self.kernel32_lib_dir = result_buf.toOwnedSlice(); | 373 | self.kernel32_lib_dir = result_buf.toOwnedSlice(); |
| ... | @@ -410,7 +419,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo | ... | @@ -410,7 +419,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo |
| 410 | return error.CCompilerCrashed; | 419 | return error.CCompilerCrashed; |
| 411 | }, | 420 | }, |
| 412 | } | 421 | } |
| 413 | var it = std.mem.split(exec_result.stdout, "\n\r"); | 422 | var it = std.mem.tokenize(exec_result.stdout, "\n\r"); |
| 414 | const line = it.next() orelse return error.LibCRuntimeNotFound; | 423 | const line = it.next() orelse return error.LibCRuntimeNotFound; |
| 415 | const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound; | 424 | const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound; |
| 416 | 425 | ||
| ... | @@ -428,20 +437,20 @@ const Search = struct { | ... | @@ -428,20 +437,20 @@ const Search = struct { |
| 428 | 437 | ||
| 429 | fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search { | 438 | fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search { |
| 430 | var search_end: usize = 0; | 439 | var search_end: usize = 0; |
| 431 | if (sdk.path10_ptr) |path10_ptr| { | 440 | if (sdk.path10_ptr != 0) { |
| 432 | if (sdk.version10_ptr) |ver10_ptr| { | 441 | if (sdk.version10_ptr != 0) { |
| 433 | search_buf[search_end] = Search{ | 442 | search_buf[search_end] = Search{ |
| 434 | .path = path10_ptr[0..sdk.path10_len], | 443 | .path = sdk.path10_ptr[0..sdk.path10_len], |
| 435 | .version = ver10_ptr[0..sdk.version10_len], | 444 | .version = sdk.version10_ptr[0..sdk.version10_len], |
| 436 | }; | 445 | }; |
| 437 | search_end += 1; | 446 | search_end += 1; |
| 438 | } | 447 | } |
| 439 | } | 448 | } |
| 440 | if (sdk.path81_ptr) |path81_ptr| { | 449 | if (sdk.path81_ptr != 0) { |
| 441 | if (sdk.version81_ptr) |ver81_ptr| { | 450 | if (sdk.version81_ptr != 0) { |
| 442 | search_buf[search_end] = Search{ | 451 | search_buf[search_end] = Search{ |
| 443 | .path = path81_ptr[0..sdk.path81_len], | 452 | .path = sdk.path81_ptr[0..sdk.path81_len], |
| 444 | .version = ver81_ptr[0..sdk.version81_len], | 453 | .version = sdk.version81_ptr[0..sdk.version81_len], |
| 445 | }; | 454 | }; |
| 446 | search_end += 1; | 455 | search_end += 1; |
| 447 | } | 456 | } |
src-self-hosted/link.zig+1-1| ... | @@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void { | ... | @@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void { | 317 | fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void { |
| 318 | const full_path = try std.os.path.join(&ctx.arena.allocator, dirname, basename); | 318 | const full_path = try std.os.path.join(&ctx.arena.allocator, [][]const u8{ dirname, basename }); |
| 319 | const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path); | 319 | const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path); |
| 320 | try ctx.args.append(full_path_with_null.ptr); | 320 | try ctx.args.append(full_path_with_null.ptr); |
| 321 | } | 321 | } |
src-self-hosted/llvm.zig+129-52| ... | @@ -11,45 +11,31 @@ const assert = @import("std").debug.assert; | ... | @@ -11,45 +11,31 @@ const assert = @import("std").debug.assert; |
| 11 | pub const AttributeIndex = c_uint; | 11 | pub const AttributeIndex = c_uint; |
| 12 | pub const Bool = c_int; | 12 | pub const Bool = c_int; |
| 13 | 13 | ||
| 14 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); | 14 | pub const Builder = c.LLVMBuilderRef.Child.Child; |
| 15 | pub const ContextRef = removeNullability(c.LLVMContextRef); | 15 | pub const Context = c.LLVMContextRef.Child.Child; |
| 16 | pub const ModuleRef = removeNullability(c.LLVMModuleRef); | 16 | pub const Module = c.LLVMModuleRef.Child.Child; |
| 17 | pub const ValueRef = removeNullability(c.LLVMValueRef); | 17 | pub const Value = c.LLVMValueRef.Child.Child; |
| 18 | pub const TypeRef = removeNullability(c.LLVMTypeRef); | 18 | pub const Type = c.LLVMTypeRef.Child.Child; |
| 19 | pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef); | 19 | pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child; |
| 20 | pub const AttributeRef = removeNullability(c.LLVMAttributeRef); | 20 | pub const Attribute = c.LLVMAttributeRef.Child.Child; |
| 21 | pub const TargetRef = removeNullability(c.LLVMTargetRef); | 21 | pub const Target = c.LLVMTargetRef.Child.Child; |
| 22 | pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef); | 22 | pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child; |
| 23 | pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef); | 23 | pub const TargetData = c.LLVMTargetDataRef.Child.Child; |
| 24 | pub const DIBuilder = c.ZigLLVMDIBuilder; | 24 | pub const DIBuilder = c.ZigLLVMDIBuilder; |
| 25 | pub const DIFile = c.ZigLLVMDIFile; | ||
| 26 | pub const DICompileUnit = c.ZigLLVMDICompileUnit; | ||
| 25 | 27 | ||
| 26 | pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType; | 28 | pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType; |
| 27 | pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex; | 29 | pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex; |
| 28 | pub const AddFunction = c.LLVMAddFunction; | ||
| 29 | pub const AddGlobal = c.LLVMAddGlobal; | ||
| 30 | pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag; | 30 | pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag; |
| 31 | pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag; | 31 | pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag; |
| 32 | pub const ArrayType = c.LLVMArrayType; | ||
| 33 | pub const BuildLoad = c.LLVMBuildLoad; | ||
| 34 | pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation; | 32 | pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation; |
| 35 | pub const ConstAllOnes = c.LLVMConstAllOnes; | 33 | pub const ConstAllOnes = c.LLVMConstAllOnes; |
| 36 | pub const ConstArray = c.LLVMConstArray; | 34 | pub const ConstArray = c.LLVMConstArray; |
| 37 | pub const ConstBitCast = c.LLVMConstBitCast; | 35 | pub const ConstBitCast = c.LLVMConstBitCast; |
| 38 | pub const ConstInt = c.LLVMConstInt; | ||
| 39 | pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision; | 36 | pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision; |
| 40 | pub const ConstNeg = c.LLVMConstNeg; | 37 | pub const ConstNeg = c.LLVMConstNeg; |
| 41 | pub const ConstNull = c.LLVMConstNull; | ||
| 42 | pub const ConstStringInContext = c.LLVMConstStringInContext; | ||
| 43 | pub const ConstStructInContext = c.LLVMConstStructInContext; | 38 | pub const ConstStructInContext = c.LLVMConstStructInContext; |
| 44 | pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData; | ||
| 45 | pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext; | ||
| 46 | pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit; | ||
| 47 | pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder; | ||
| 48 | pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute; | ||
| 49 | pub const CreateFile = c.ZigLLVMCreateFile; | ||
| 50 | pub const CreateStringAttribute = c.LLVMCreateStringAttribute; | ||
| 51 | pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout; | ||
| 52 | pub const CreateTargetMachine = c.LLVMCreateTargetMachine; | ||
| 53 | pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize; | 39 | pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize; |
| 54 | pub const DisposeBuilder = c.LLVMDisposeBuilder; | 40 | pub const DisposeBuilder = c.LLVMDisposeBuilder; |
| 55 | pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder; | 41 | pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder; |
| ... | @@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule; | ... | @@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule; |
| 62 | pub const FP128TypeInContext = c.LLVMFP128TypeInContext; | 48 | pub const FP128TypeInContext = c.LLVMFP128TypeInContext; |
| 63 | pub const FloatTypeInContext = c.LLVMFloatTypeInContext; | 49 | pub const FloatTypeInContext = c.LLVMFloatTypeInContext; |
| 64 | pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName; | 50 | pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName; |
| 65 | pub const GetHostCPUName = c.ZigLLVMGetHostCPUName; | ||
| 66 | pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext; | 51 | pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext; |
| 67 | pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures; | ||
| 68 | pub const GetUndef = c.LLVMGetUndef; | 52 | pub const GetUndef = c.LLVMGetUndef; |
| 69 | pub const HalfTypeInContext = c.LLVMHalfTypeInContext; | 53 | pub const HalfTypeInContext = c.LLVMHalfTypeInContext; |
| 70 | pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers; | 54 | pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers; |
| ... | @@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext; | ... | @@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext; |
| 81 | pub const Int8TypeInContext = c.LLVMInt8TypeInContext; | 65 | pub const Int8TypeInContext = c.LLVMInt8TypeInContext; |
| 82 | pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext; | 66 | pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext; |
| 83 | pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext; | 67 | pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext; |
| 84 | pub const IntTypeInContext = c.LLVMIntTypeInContext; | ||
| 85 | pub const LabelTypeInContext = c.LLVMLabelTypeInContext; | 68 | pub const LabelTypeInContext = c.LLVMLabelTypeInContext; |
| 86 | pub const MDNodeInContext = c.LLVMMDNodeInContext; | 69 | pub const MDNodeInContext = c.LLVMMDNodeInContext; |
| 87 | pub const MDStringInContext = c.LLVMMDStringInContext; | 70 | pub const MDStringInContext = c.LLVMMDStringInContext; |
| 88 | pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext; | 71 | pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext; |
| 89 | pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext; | ||
| 90 | pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext; | 72 | pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext; |
| 91 | pub const PointerType = c.LLVMPointerType; | ||
| 92 | pub const SetAlignment = c.LLVMSetAlignment; | 73 | pub const SetAlignment = c.LLVMSetAlignment; |
| 93 | pub const SetDataLayout = c.LLVMSetDataLayout; | 74 | pub const SetDataLayout = c.LLVMSetDataLayout; |
| 94 | pub const SetGlobalConstant = c.LLVMSetGlobalConstant; | 75 | pub const SetGlobalConstant = c.LLVMSetGlobalConstant; |
| ... | @@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr; | ... | @@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr; |
| 99 | pub const SetVolatile = c.LLVMSetVolatile; | 80 | pub const SetVolatile = c.LLVMSetVolatile; |
| 100 | pub const StructTypeInContext = c.LLVMStructTypeInContext; | 81 | pub const StructTypeInContext = c.LLVMStructTypeInContext; |
| 101 | pub const TokenTypeInContext = c.LLVMTokenTypeInContext; | 82 | pub const TokenTypeInContext = c.LLVMTokenTypeInContext; |
| 102 | pub const VoidTypeInContext = c.LLVMVoidTypeInContext; | ||
| 103 | pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext; | 83 | pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext; |
| 104 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; | 84 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; |
| 105 | 85 | ||
| 86 | pub const AddGlobal = LLVMAddGlobal; | ||
| 87 | extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value; | ||
| 88 | |||
| 89 | pub const ConstStringInContext = LLVMConstStringInContext; | ||
| 90 | extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value; | ||
| 91 | |||
| 92 | pub const ConstInt = LLVMConstInt; | ||
| 93 | extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value; | ||
| 94 | |||
| 95 | pub const BuildLoad = LLVMBuildLoad; | ||
| 96 | extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value; | ||
| 97 | |||
| 98 | pub const ConstNull = LLVMConstNull; | ||
| 99 | extern fn LLVMConstNull(Ty: *Type) ?*Value; | ||
| 100 | |||
| 101 | pub const CreateStringAttribute = LLVMCreateStringAttribute; | ||
| 102 | extern fn LLVMCreateStringAttribute( | ||
| 103 | C: *Context, | ||
| 104 | K: [*]const u8, | ||
| 105 | KLength: c_uint, | ||
| 106 | V: [*]const u8, | ||
| 107 | VLength: c_uint, | ||
| 108 | ) ?*Attribute; | ||
| 109 | |||
| 110 | pub const CreateEnumAttribute = LLVMCreateEnumAttribute; | ||
| 111 | extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute; | ||
| 112 | |||
| 113 | pub const AddFunction = LLVMAddFunction; | ||
| 114 | extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value; | ||
| 115 | |||
| 116 | pub const CreateCompileUnit = ZigLLVMCreateCompileUnit; | ||
| 117 | extern fn ZigLLVMCreateCompileUnit( | ||
| 118 | dibuilder: *DIBuilder, | ||
| 119 | lang: c_uint, | ||
| 120 | difile: *DIFile, | ||
| 121 | producer: [*]const u8, | ||
| 122 | is_optimized: bool, | ||
| 123 | flags: [*]const u8, | ||
| 124 | runtime_version: c_uint, | ||
| 125 | split_name: [*]const u8, | ||
| 126 | dwo_id: u64, | ||
| 127 | emit_debug_info: bool, | ||
| 128 | ) ?*DICompileUnit; | ||
| 129 | |||
| 130 | pub const CreateFile = ZigLLVMCreateFile; | ||
| 131 | extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile; | ||
| 132 | |||
| 133 | pub const ArrayType = LLVMArrayType; | ||
| 134 | extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type; | ||
| 135 | |||
| 136 | pub const CreateDIBuilder = ZigLLVMCreateDIBuilder; | ||
| 137 | extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder; | ||
| 138 | |||
| 139 | pub const PointerType = LLVMPointerType; | ||
| 140 | extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type; | ||
| 141 | |||
| 142 | pub const CreateBuilderInContext = LLVMCreateBuilderInContext; | ||
| 143 | extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder; | ||
| 144 | |||
| 145 | pub const IntTypeInContext = LLVMIntTypeInContext; | ||
| 146 | extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type; | ||
| 147 | |||
| 148 | pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext; | ||
| 149 | extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module; | ||
| 150 | |||
| 151 | pub const VoidTypeInContext = LLVMVoidTypeInContext; | ||
| 152 | extern fn LLVMVoidTypeInContext(C: *Context) ?*Type; | ||
| 153 | |||
| 154 | pub const ContextCreate = LLVMContextCreate; | ||
| 155 | extern fn LLVMContextCreate() ?*Context; | ||
| 156 | |||
| 157 | pub const ContextDispose = LLVMContextDispose; | ||
| 158 | extern fn LLVMContextDispose(C: *Context) void; | ||
| 159 | |||
| 160 | pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData; | ||
| 161 | extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8; | ||
| 162 | |||
| 163 | pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout; | ||
| 164 | extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData; | ||
| 165 | |||
| 166 | pub const CreateTargetMachine = LLVMCreateTargetMachine; | ||
| 167 | extern fn LLVMCreateTargetMachine( | ||
| 168 | T: *Target, | ||
| 169 | Triple: [*]const u8, | ||
| 170 | CPU: [*]const u8, | ||
| 171 | Features: [*]const u8, | ||
| 172 | Level: CodeGenOptLevel, | ||
| 173 | Reloc: RelocMode, | ||
| 174 | CodeModel: CodeModel, | ||
| 175 | ) ?*TargetMachine; | ||
| 176 | |||
| 177 | pub const GetHostCPUName = LLVMGetHostCPUName; | ||
| 178 | extern fn LLVMGetHostCPUName() ?[*]u8; | ||
| 179 | |||
| 180 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | ||
| 181 | extern fn ZigLLVMGetNativeFeatures() ?[*]u8; | ||
| 182 | |||
| 106 | pub const GetElementType = LLVMGetElementType; | 183 | pub const GetElementType = LLVMGetElementType; |
| 107 | extern fn LLVMGetElementType(Ty: TypeRef) TypeRef; | 184 | extern fn LLVMGetElementType(Ty: *Type) *Type; |
| 108 | 185 | ||
| 109 | pub const TypeOf = LLVMTypeOf; | 186 | pub const TypeOf = LLVMTypeOf; |
| 110 | extern fn LLVMTypeOf(Val: ValueRef) TypeRef; | 187 | extern fn LLVMTypeOf(Val: *Value) *Type; |
| 111 | 188 | ||
| 112 | pub const BuildStore = LLVMBuildStore; | 189 | pub const BuildStore = LLVMBuildStore; |
| 113 | extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef; | 190 | extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value; |
| 114 | 191 | ||
| 115 | pub const BuildAlloca = LLVMBuildAlloca; | 192 | pub const BuildAlloca = LLVMBuildAlloca; |
| 116 | extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef; | 193 | extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value; |
| 117 | 194 | ||
| 118 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; | 195 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; |
| 119 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef; | 196 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value; |
| 120 | 197 | ||
| 121 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; | 198 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; |
| 122 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool; | 199 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool; |
| 123 | 200 | ||
| 124 | pub const VerifyModule = LLVMVerifyModule; | 201 | pub const VerifyModule = LLVMVerifyModule; |
| 125 | extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; | 202 | extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; |
| 126 | 203 | ||
| 127 | pub const GetInsertBlock = LLVMGetInsertBlock; | 204 | pub const GetInsertBlock = LLVMGetInsertBlock; |
| 128 | extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef; | 205 | extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock; |
| 129 | 206 | ||
| 130 | pub const FunctionType = LLVMFunctionType; | 207 | pub const FunctionType = LLVMFunctionType; |
| 131 | extern fn LLVMFunctionType( | 208 | extern fn LLVMFunctionType( |
| 132 | ReturnType: TypeRef, | 209 | ReturnType: *Type, |
| 133 | ParamTypes: [*]TypeRef, | 210 | ParamTypes: [*]*Type, |
| 134 | ParamCount: c_uint, | 211 | ParamCount: c_uint, |
| 135 | IsVarArg: Bool, | 212 | IsVarArg: Bool, |
| 136 | ) ?TypeRef; | 213 | ) ?*Type; |
| 137 | 214 | ||
| 138 | pub const GetParam = LLVMGetParam; | 215 | pub const GetParam = LLVMGetParam; |
| 139 | extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef; | 216 | extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; |
| 140 | 217 | ||
| 141 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; | 218 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; |
| 142 | extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef; | 219 | extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock; |
| 143 | 220 | ||
| 144 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; | 221 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; |
| 145 | extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void; | 222 | extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void; |
| 146 | 223 | ||
| 147 | pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction; | 224 | pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction; |
| 148 | pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction; | 225 | pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction; |
| ... | @@ -190,17 +267,17 @@ pub const FnInline = extern enum { | ... | @@ -190,17 +267,17 @@ pub const FnInline = extern enum { |
| 190 | }; | 267 | }; |
| 191 | 268 | ||
| 192 | fn removeNullability(comptime T: type) type { | 269 | fn removeNullability(comptime T: type) type { |
| 193 | comptime assert(@typeId(T) == builtin.TypeId.Optional); | 270 | comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C); |
| 194 | return T.Child; | 271 | return *T.Child; |
| 195 | } | 272 | } |
| 196 | 273 | ||
| 197 | pub const BuildRet = LLVMBuildRet; | 274 | pub const BuildRet = LLVMBuildRet; |
| 198 | extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef; | 275 | extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value; |
| 199 | 276 | ||
| 200 | pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; | 277 | pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; |
| 201 | extern fn ZigLLVMTargetMachineEmitToFile( | 278 | extern fn ZigLLVMTargetMachineEmitToFile( |
| 202 | targ_machine_ref: TargetMachineRef, | 279 | targ_machine_ref: *TargetMachine, |
| 203 | module_ref: ModuleRef, | 280 | module_ref: *Module, |
| 204 | filename: [*]const u8, | 281 | filename: [*]const u8, |
| 205 | output_type: EmitOutputType, | 282 | output_type: EmitOutputType, |
| 206 | error_message: *[*]u8, | 283 | error_message: *[*]u8, |
| ... | @@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile( | ... | @@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile( |
| 209 | ) bool; | 286 | ) bool; |
| 210 | 287 | ||
| 211 | pub const BuildCall = ZigLLVMBuildCall; | 288 | pub const BuildCall = ZigLLVMBuildCall; |
| 212 | extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef; | 289 | extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value; |
| 213 | 290 | ||
| 214 | pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage; | 291 | pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage; |
src-self-hosted/main.zig+8-7| ... | @@ -24,7 +24,7 @@ var stderr_file: os.File = undefined; | ... | @@ -24,7 +24,7 @@ var stderr_file: os.File = undefined; |
| 24 | var stderr: *io.OutStream(os.File.WriteError) = undefined; | 24 | var stderr: *io.OutStream(os.File.WriteError) = undefined; |
| 25 | var stdout: *io.OutStream(os.File.WriteError) = undefined; | 25 | var stdout: *io.OutStream(os.File.WriteError) = undefined; |
| 26 | 26 | ||
| 27 | const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB | 27 | pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB |
| 28 | 28 | ||
| 29 | const usage = | 29 | const usage = |
| 30 | \\usage: zig [command] [options] | 30 | \\usage: zig [command] [options] |
| ... | @@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co | ... | @@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 351 | const root_name = if (provided_name) |n| n else blk: { | 351 | const root_name = if (provided_name) |n| n else blk: { |
| 352 | if (root_source_file) |file| { | 352 | if (root_source_file) |file| { |
| 353 | const basename = os.path.basename(file); | 353 | const basename = os.path.basename(file); |
| 354 | var it = mem.split(basename, "."); | 354 | var it = mem.separate(basename, "."); |
| 355 | break :blk it.next() orelse basename; | 355 | break :blk it.next() orelse basename; |
| 356 | } else { | 356 | } else { |
| 357 | try stderr.write("--name [name] not provided and unable to infer\n"); | 357 | try stderr.write("--name [name] not provided and unable to infer\n"); |
| ... | @@ -510,7 +510,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void { | ... | @@ -510,7 +510,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void { |
| 510 | return buildOutputType(allocator, args, Compilation.Kind.Obj); | 510 | return buildOutputType(allocator, args, Compilation.Kind.Obj); |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | const usage_fmt = | 513 | pub const usage_fmt = |
| 514 | \\usage: zig fmt [file]... | 514 | \\usage: zig fmt [file]... |
| 515 | \\ | 515 | \\ |
| 516 | \\ Formats the input files and modifies them in-place. | 516 | \\ Formats the input files and modifies them in-place. |
| ... | @@ -527,7 +527,7 @@ const usage_fmt = | ... | @@ -527,7 +527,7 @@ const usage_fmt = |
| 527 | \\ | 527 | \\ |
| 528 | ; | 528 | ; |
| 529 | 529 | ||
| 530 | const args_fmt_spec = []Flag{ | 530 | pub const args_fmt_spec = []Flag{ |
| 531 | Flag.Bool("--help"), | 531 | Flag.Bool("--help"), |
| 532 | Flag.Bool("--check"), | 532 | Flag.Bool("--check"), |
| 533 | Flag.Option("--color", []const []const u8{ | 533 | Flag.Option("--color", []const []const u8{ |
| ... | @@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro | ... | @@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro |
| 757 | var group = event.Group(FmtError!void).init(fmt.loop); | 757 | var group = event.Group(FmtError!void).init(fmt.loop); |
| 758 | while (try dir.next()) |entry| { | 758 | while (try dir.next()) |entry| { |
| 759 | if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { | 759 | if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { |
| 760 | const full_path = try os.path.join(fmt.loop.allocator, file_path, entry.name); | 760 | const full_path = try os.path.join(fmt.loop.allocator, [][]const u8{ file_path, entry.name }); |
| 761 | try group.call(fmtPath, fmt, full_path, check_mode); | 761 | try group.call(fmtPath, fmt, full_path, check_mode); |
| 762 | } | 762 | } |
| 763 | } | 763 | } |
| ... | @@ -944,12 +944,13 @@ const CliPkg = struct { | ... | @@ -944,12 +944,13 @@ const CliPkg = struct { |
| 944 | parent: ?*CliPkg, | 944 | parent: ?*CliPkg, |
| 945 | 945 | ||
| 946 | pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg { | 946 | pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg { |
| 947 | var pkg = try allocator.create(CliPkg{ | 947 | var pkg = try allocator.create(CliPkg); |
| 948 | pkg.* = CliPkg{ | ||
| 948 | .name = name, | 949 | .name = name, |
| 949 | .path = path, | 950 | .path = path, |
| 950 | .children = ArrayList(*CliPkg).init(allocator), | 951 | .children = ArrayList(*CliPkg).init(allocator), |
| 951 | .parent = parent, | 952 | .parent = parent, |
| 952 | }); | 953 | }; |
| 953 | return pkg; | 954 | return pkg; |
| 954 | } | 955 | } |
| 955 | 956 |
src-self-hosted/package.zig+4-2| ... | @@ -15,11 +15,13 @@ pub const Package = struct { | ... | @@ -15,11 +15,13 @@ pub const Package = struct { |
| 15 | /// makes internal copies of root_src_dir and root_src_path | 15 | /// makes internal copies of root_src_dir and root_src_path |
| 16 | /// allocator should be an arena allocator because Package never frees anything | 16 | /// allocator should be an arena allocator because Package never frees anything |
| 17 | pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package { | 17 | pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package { |
| 18 | return allocator.create(Package{ | 18 | const ptr = try allocator.create(Package); |
| 19 | ptr.* = Package{ | ||
| 19 | .root_src_dir = try Buffer.init(allocator, root_src_dir), | 20 | .root_src_dir = try Buffer.init(allocator, root_src_dir), |
| 20 | .root_src_path = try Buffer.init(allocator, root_src_path), | 21 | .root_src_path = try Buffer.init(allocator, root_src_path), |
| 21 | .table = Table.init(allocator), | 22 | .table = Table.init(allocator), |
| 22 | }); | 23 | }; |
| 24 | return ptr; | ||
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | pub fn add(self: *Package, name: []const u8, package: *Package) !void { | 27 | pub fn add(self: *Package, name: []const u8, package: *Package) !void { |
src-self-hosted/scope.zig+10-10| ... | @@ -120,7 +120,7 @@ pub const Scope = struct { | ... | @@ -120,7 +120,7 @@ pub const Scope = struct { |
| 120 | /// Creates a Root scope with 1 reference | 120 | /// Creates a Root scope with 1 reference |
| 121 | /// Takes ownership of realpath | 121 | /// Takes ownership of realpath |
| 122 | pub fn create(comp: *Compilation, realpath: []u8) !*Root { | 122 | pub fn create(comp: *Compilation, realpath: []u8) !*Root { |
| 123 | const self = try comp.gpa().createOne(Root); | 123 | const self = try comp.gpa().create(Root); |
| 124 | self.* = Root{ | 124 | self.* = Root{ |
| 125 | .base = Scope{ | 125 | .base = Scope{ |
| 126 | .id = Id.Root, | 126 | .id = Id.Root, |
| ... | @@ -150,7 +150,7 @@ pub const Scope = struct { | ... | @@ -150,7 +150,7 @@ pub const Scope = struct { |
| 150 | /// Creates a scope with 1 reference | 150 | /// Creates a scope with 1 reference |
| 151 | /// Takes ownership of tree, will deinit and destroy when done. | 151 | /// Takes ownership of tree, will deinit and destroy when done. |
| 152 | pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree { | 152 | pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree { |
| 153 | const self = try comp.gpa().createOne(AstTree); | 153 | const self = try comp.gpa().create(AstTree); |
| 154 | self.* = AstTree{ | 154 | self.* = AstTree{ |
| 155 | .base = undefined, | 155 | .base = undefined, |
| 156 | .tree = tree, | 156 | .tree = tree, |
| ... | @@ -182,7 +182,7 @@ pub const Scope = struct { | ... | @@ -182,7 +182,7 @@ pub const Scope = struct { |
| 182 | 182 | ||
| 183 | /// Creates a Decls scope with 1 reference | 183 | /// Creates a Decls scope with 1 reference |
| 184 | pub fn create(comp: *Compilation, parent: *Scope) !*Decls { | 184 | pub fn create(comp: *Compilation, parent: *Scope) !*Decls { |
| 185 | const self = try comp.gpa().createOne(Decls); | 185 | const self = try comp.gpa().create(Decls); |
| 186 | self.* = Decls{ | 186 | self.* = Decls{ |
| 187 | .base = undefined, | 187 | .base = undefined, |
| 188 | .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())), | 188 | .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())), |
| ... | @@ -235,7 +235,7 @@ pub const Scope = struct { | ... | @@ -235,7 +235,7 @@ pub const Scope = struct { |
| 235 | 235 | ||
| 236 | /// Creates a Block scope with 1 reference | 236 | /// Creates a Block scope with 1 reference |
| 237 | pub fn create(comp: *Compilation, parent: *Scope) !*Block { | 237 | pub fn create(comp: *Compilation, parent: *Scope) !*Block { |
| 238 | const self = try comp.gpa().createOne(Block); | 238 | const self = try comp.gpa().create(Block); |
| 239 | self.* = Block{ | 239 | self.* = Block{ |
| 240 | .base = undefined, | 240 | .base = undefined, |
| 241 | .incoming_values = undefined, | 241 | .incoming_values = undefined, |
| ... | @@ -262,7 +262,7 @@ pub const Scope = struct { | ... | @@ -262,7 +262,7 @@ pub const Scope = struct { |
| 262 | /// Creates a FnDef scope with 1 reference | 262 | /// Creates a FnDef scope with 1 reference |
| 263 | /// Must set the fn_val later | 263 | /// Must set the fn_val later |
| 264 | pub fn create(comp: *Compilation, parent: *Scope) !*FnDef { | 264 | pub fn create(comp: *Compilation, parent: *Scope) !*FnDef { |
| 265 | const self = try comp.gpa().createOne(FnDef); | 265 | const self = try comp.gpa().create(FnDef); |
| 266 | self.* = FnDef{ | 266 | self.* = FnDef{ |
| 267 | .base = undefined, | 267 | .base = undefined, |
| 268 | .fn_val = null, | 268 | .fn_val = null, |
| ... | @@ -281,7 +281,7 @@ pub const Scope = struct { | ... | @@ -281,7 +281,7 @@ pub const Scope = struct { |
| 281 | 281 | ||
| 282 | /// Creates a CompTime scope with 1 reference | 282 | /// Creates a CompTime scope with 1 reference |
| 283 | pub fn create(comp: *Compilation, parent: *Scope) !*CompTime { | 283 | pub fn create(comp: *Compilation, parent: *Scope) !*CompTime { |
| 284 | const self = try comp.gpa().createOne(CompTime); | 284 | const self = try comp.gpa().create(CompTime); |
| 285 | self.* = CompTime{ .base = undefined }; | 285 | self.* = CompTime{ .base = undefined }; |
| 286 | self.base.init(Id.CompTime, parent); | 286 | self.base.init(Id.CompTime, parent); |
| 287 | return self; | 287 | return self; |
| ... | @@ -309,7 +309,7 @@ pub const Scope = struct { | ... | @@ -309,7 +309,7 @@ pub const Scope = struct { |
| 309 | kind: Kind, | 309 | kind: Kind, |
| 310 | defer_expr_scope: *DeferExpr, | 310 | defer_expr_scope: *DeferExpr, |
| 311 | ) !*Defer { | 311 | ) !*Defer { |
| 312 | const self = try comp.gpa().createOne(Defer); | 312 | const self = try comp.gpa().create(Defer); |
| 313 | self.* = Defer{ | 313 | self.* = Defer{ |
| 314 | .base = undefined, | 314 | .base = undefined, |
| 315 | .defer_expr_scope = defer_expr_scope, | 315 | .defer_expr_scope = defer_expr_scope, |
| ... | @@ -333,7 +333,7 @@ pub const Scope = struct { | ... | @@ -333,7 +333,7 @@ pub const Scope = struct { |
| 333 | 333 | ||
| 334 | /// Creates a DeferExpr scope with 1 reference | 334 | /// Creates a DeferExpr scope with 1 reference |
| 335 | pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr { | 335 | pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr { |
| 336 | const self = try comp.gpa().createOne(DeferExpr); | 336 | const self = try comp.gpa().create(DeferExpr); |
| 337 | self.* = DeferExpr{ | 337 | self.* = DeferExpr{ |
| 338 | .base = undefined, | 338 | .base = undefined, |
| 339 | .expr_node = expr_node, | 339 | .expr_node = expr_node, |
| ... | @@ -362,7 +362,7 @@ pub const Scope = struct { | ... | @@ -362,7 +362,7 @@ pub const Scope = struct { |
| 362 | pub const Param = struct { | 362 | pub const Param = struct { |
| 363 | index: usize, | 363 | index: usize, |
| 364 | typ: *Type, | 364 | typ: *Type, |
| 365 | llvm_value: llvm.ValueRef, | 365 | llvm_value: *llvm.Value, |
| 366 | }; | 366 | }; |
| 367 | 367 | ||
| 368 | pub fn createParam( | 368 | pub fn createParam( |
| ... | @@ -398,7 +398,7 @@ pub const Scope = struct { | ... | @@ -398,7 +398,7 @@ pub const Scope = struct { |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var { | 400 | fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var { |
| 401 | const self = try comp.gpa().createOne(Var); | 401 | const self = try comp.gpa().create(Var); |
| 402 | self.* = Var{ | 402 | self.* = Var{ |
| 403 | .base = undefined, | 403 | .base = undefined, |
| 404 | .name = name, | 404 | .name = name, |
src-self-hosted/target.zig+3-3| ... | @@ -457,8 +457,8 @@ pub const Target = union(enum) { | ... | @@ -457,8 +457,8 @@ pub const Target = union(enum) { |
| 457 | } | 457 | } |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef { | 460 | pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target { |
| 461 | var result: llvm.TargetRef = undefined; | 461 | var result: *llvm.Target = undefined; |
| 462 | var err_msg: [*]u8 = undefined; | 462 | var err_msg: [*]u8 = undefined; |
| 463 | if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) { | 463 | if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) { |
| 464 | std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg); | 464 | std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg); |
| ... | @@ -520,7 +520,7 @@ pub const Target = union(enum) { | ... | @@ -520,7 +520,7 @@ pub const Target = union(enum) { |
| 520 | => return 64, | 520 | => return 64, |
| 521 | }, | 521 | }, |
| 522 | 522 | ||
| 523 | builtin.Os.windows => switch (id) { | 523 | builtin.Os.windows, builtin.Os.uefi => switch (id) { |
| 524 | CInt.Id.Short, | 524 | CInt.Id.Short, |
| 525 | CInt.Id.UShort, | 525 | CInt.Id.UShort, |
| 526 | => return 16, | 526 | => return 16, |
src-self-hosted/test.zig+4-4| ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); | ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); |
| 4 | const Target = @import("target.zig").Target; | 4 | const Target = @import("target.zig").Target; |
| 5 | const Compilation = @import("compilation.zig").Compilation; | 5 | const Compilation = @import("compilation.zig").Compilation; |
| 6 | const introspect = @import("introspect.zig"); | 6 | const introspect = @import("introspect.zig"); |
| 7 | const assertOrPanic = std.debug.assertOrPanic; | 7 | const testing = std.testing; |
| 8 | const errmsg = @import("errmsg.zig"); | 8 | const errmsg = @import("errmsg.zig"); |
| 9 | const ZigCompiler = @import("compilation.zig").ZigCompiler; | 9 | const ZigCompiler = @import("compilation.zig").ZigCompiler; |
| 10 | 10 | ||
| ... | @@ -87,7 +87,7 @@ pub const TestContext = struct { | ... | @@ -87,7 +87,7 @@ pub const TestContext = struct { |
| 87 | ) !void { | 87 | ) !void { |
| 88 | var file_index_buf: [20]u8 = undefined; | 88 | var file_index_buf: [20]u8 = undefined; |
| 89 | const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); | 89 | const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); |
| 90 | const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1); | 90 | const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 }); |
| 91 | 91 | ||
| 92 | if (std.os.path.dirname(file1_path)) |dirname| { | 92 | if (std.os.path.dirname(file1_path)) |dirname| { |
| 93 | try std.os.makePath(allocator, dirname); | 93 | try std.os.makePath(allocator, dirname); |
| ... | @@ -120,7 +120,7 @@ pub const TestContext = struct { | ... | @@ -120,7 +120,7 @@ pub const TestContext = struct { |
| 120 | ) !void { | 120 | ) !void { |
| 121 | var file_index_buf: [20]u8 = undefined; | 121 | var file_index_buf: [20]u8 = undefined; |
| 122 | const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); | 122 | const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); |
| 123 | const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1); | 123 | const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 }); |
| 124 | 124 | ||
| 125 | const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt()); | 125 | const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt()); |
| 126 | if (std.os.path.dirname(file1_path)) |dirname| { | 126 | if (std.os.path.dirname(file1_path)) |dirname| { |
| ... | @@ -210,7 +210,7 @@ pub const TestContext = struct { | ... | @@ -210,7 +210,7 @@ pub const TestContext = struct { |
| 210 | @panic("build incorrectly failed"); | 210 | @panic("build incorrectly failed"); |
| 211 | }, | 211 | }, |
| 212 | Compilation.Event.Fail => |msgs| { | 212 | Compilation.Event.Fail => |msgs| { |
| 213 | assertOrPanic(msgs.len != 0); | 213 | testing.expect(msgs.len != 0); |
| 214 | for (msgs) |msg| { | 214 | for (msgs) |msg| { |
| 215 | if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) { | 215 | if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) { |
| 216 | const span = msg.getSpan(); | 216 | const span = msg.getSpan(); |
src-self-hosted/type.zig+48-27| ... | @@ -44,14 +44,15 @@ pub const Type = struct { | ... | @@ -44,14 +44,15 @@ pub const Type = struct { |
| 44 | Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), | 44 | Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), |
| 45 | Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), | 45 | Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), |
| 46 | Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp), | 46 | Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp), |
| 47 | Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp), | ||
| 47 | } | 48 | } |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | pub fn getLlvmType( | 51 | pub fn getLlvmType( |
| 51 | base: *Type, | 52 | base: *Type, |
| 52 | allocator: *Allocator, | 53 | allocator: *Allocator, |
| 53 | llvm_context: llvm.ContextRef, | 54 | llvm_context: *llvm.Context, |
| 54 | ) (error{OutOfMemory}!llvm.TypeRef) { | 55 | ) (error{OutOfMemory}!*llvm.Type) { |
| 55 | switch (base.id) { | 56 | switch (base.id) { |
| 56 | Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context), | 57 | Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context), |
| 57 | Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context), | 58 | Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context), |
| ... | @@ -77,6 +78,7 @@ pub const Type = struct { | ... | @@ -77,6 +78,7 @@ pub const Type = struct { |
| 77 | Id.ArgTuple => unreachable, | 78 | Id.ArgTuple => unreachable, |
| 78 | Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), | 79 | Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), |
| 79 | Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context), | 80 | Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context), |
| 81 | Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context), | ||
| 80 | } | 82 | } |
| 81 | } | 83 | } |
| 82 | 84 | ||
| ... | @@ -103,6 +105,7 @@ pub const Type = struct { | ... | @@ -103,6 +105,7 @@ pub const Type = struct { |
| 103 | Id.Enum, | 105 | Id.Enum, |
| 104 | Id.Fn, | 106 | Id.Fn, |
| 105 | Id.Promise, | 107 | Id.Promise, |
| 108 | Id.Vector, | ||
| 106 | => return false, | 109 | => return false, |
| 107 | 110 | ||
| 108 | Id.Struct => @panic("TODO"), | 111 | Id.Struct => @panic("TODO"), |
| ... | @@ -135,6 +138,7 @@ pub const Type = struct { | ... | @@ -135,6 +138,7 @@ pub const Type = struct { |
| 135 | Id.Float, | 138 | Id.Float, |
| 136 | Id.Fn, | 139 | Id.Fn, |
| 137 | Id.Promise, | 140 | Id.Promise, |
| 141 | Id.Vector, | ||
| 138 | => return true, | 142 | => return true, |
| 139 | 143 | ||
| 140 | Id.Pointer => { | 144 | Id.Pointer => { |
| ... | @@ -192,7 +196,7 @@ pub const Type = struct { | ... | @@ -192,7 +196,7 @@ pub const Type = struct { |
| 192 | } | 196 | } |
| 193 | 197 | ||
| 194 | /// If you have an llvm conext handy, you can use it here. | 198 | /// If you have an llvm conext handy, you can use it here. |
| 195 | pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 { | 199 | pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 { |
| 196 | if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*; | 200 | if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*; |
| 197 | 201 | ||
| 198 | base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable); | 202 | base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable); |
| ... | @@ -201,7 +205,7 @@ pub const Type = struct { | ... | @@ -201,7 +205,7 @@ pub const Type = struct { |
| 201 | } | 205 | } |
| 202 | 206 | ||
| 203 | /// Lower level function that does the work. See getAbiAlignment. | 207 | /// Lower level function that does the work. See getAbiAlignment. |
| 204 | async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 { | 208 | async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 { |
| 205 | const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context); | 209 | const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context); |
| 206 | return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type)); | 210 | return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type)); |
| 207 | } | 211 | } |
| ... | @@ -214,7 +218,7 @@ pub const Type = struct { | ... | @@ -214,7 +218,7 @@ pub const Type = struct { |
| 214 | comp.gpa().destroy(self); | 218 | comp.gpa().destroy(self); |
| 215 | } | 219 | } |
| 216 | 220 | ||
| 217 | pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 221 | pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 218 | @panic("TODO"); | 222 | @panic("TODO"); |
| 219 | } | 223 | } |
| 220 | }; | 224 | }; |
| ... | @@ -409,7 +413,7 @@ pub const Type = struct { | ... | @@ -409,7 +413,7 @@ pub const Type = struct { |
| 409 | key.ref(); | 413 | key.ref(); |
| 410 | errdefer key.deref(comp); | 414 | errdefer key.deref(comp); |
| 411 | 415 | ||
| 412 | const self = try comp.gpa().createOne(Fn); | 416 | const self = try comp.gpa().create(Fn); |
| 413 | self.* = Fn{ | 417 | self.* = Fn{ |
| 414 | .base = undefined, | 418 | .base = undefined, |
| 415 | .key = key, | 419 | .key = key, |
| ... | @@ -492,13 +496,13 @@ pub const Type = struct { | ... | @@ -492,13 +496,13 @@ pub const Type = struct { |
| 492 | comp.gpa().destroy(self); | 496 | comp.gpa().destroy(self); |
| 493 | } | 497 | } |
| 494 | 498 | ||
| 495 | pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | 499 | pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { |
| 496 | const normal = &self.key.data.Normal; | 500 | const normal = &self.key.data.Normal; |
| 497 | const llvm_return_type = switch (normal.return_type.id) { | 501 | const llvm_return_type = switch (normal.return_type.id) { |
| 498 | Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory, | 502 | Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory, |
| 499 | else => try normal.return_type.getLlvmType(allocator, llvm_context), | 503 | else => try normal.return_type.getLlvmType(allocator, llvm_context), |
| 500 | }; | 504 | }; |
| 501 | const llvm_param_types = try allocator.alloc(llvm.TypeRef, normal.params.len); | 505 | const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len); |
| 502 | defer allocator.free(llvm_param_types); | 506 | defer allocator.free(llvm_param_types); |
| 503 | for (llvm_param_types) |*llvm_param_type, i| { | 507 | for (llvm_param_types) |*llvm_param_type, i| { |
| 504 | llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context); | 508 | llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context); |
| ... | @@ -555,7 +559,7 @@ pub const Type = struct { | ... | @@ -555,7 +559,7 @@ pub const Type = struct { |
| 555 | comp.gpa().destroy(self); | 559 | comp.gpa().destroy(self); |
| 556 | } | 560 | } |
| 557 | 561 | ||
| 558 | pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 562 | pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 559 | @panic("TODO"); | 563 | @panic("TODO"); |
| 560 | } | 564 | } |
| 561 | }; | 565 | }; |
| ... | @@ -611,11 +615,12 @@ pub const Type = struct { | ... | @@ -611,11 +615,12 @@ pub const Type = struct { |
| 611 | } | 615 | } |
| 612 | } | 616 | } |
| 613 | 617 | ||
| 614 | const self = try comp.gpa().create(Int{ | 618 | const self = try comp.gpa().create(Int); |
| 619 | self.* = Int{ | ||
| 615 | .base = undefined, | 620 | .base = undefined, |
| 616 | .key = key, | 621 | .key = key, |
| 617 | .garbage_node = undefined, | 622 | .garbage_node = undefined, |
| 618 | }); | 623 | }; |
| 619 | errdefer comp.gpa().destroy(self); | 624 | errdefer comp.gpa().destroy(self); |
| 620 | 625 | ||
| 621 | const u_or_i = "ui"[@boolToInt(key.is_signed)]; | 626 | const u_or_i = "ui"[@boolToInt(key.is_signed)]; |
| ... | @@ -653,7 +658,7 @@ pub const Type = struct { | ... | @@ -653,7 +658,7 @@ pub const Type = struct { |
| 653 | comp.gpa().destroy(self); | 658 | comp.gpa().destroy(self); |
| 654 | } | 659 | } |
| 655 | 660 | ||
| 656 | pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | 661 | pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { |
| 657 | return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory; | 662 | return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory; |
| 658 | } | 663 | } |
| 659 | }; | 664 | }; |
| ... | @@ -665,7 +670,7 @@ pub const Type = struct { | ... | @@ -665,7 +670,7 @@ pub const Type = struct { |
| 665 | comp.gpa().destroy(self); | 670 | comp.gpa().destroy(self); |
| 666 | } | 671 | } |
| 667 | 672 | ||
| 668 | pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 673 | pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 669 | @panic("TODO"); | 674 | @panic("TODO"); |
| 670 | } | 675 | } |
| 671 | }; | 676 | }; |
| ... | @@ -777,17 +782,19 @@ pub const Type = struct { | ... | @@ -777,17 +782,19 @@ pub const Type = struct { |
| 777 | } | 782 | } |
| 778 | } | 783 | } |
| 779 | 784 | ||
| 780 | const self = try comp.gpa().create(Pointer{ | 785 | const self = try comp.gpa().create(Pointer); |
| 786 | self.* = Pointer{ | ||
| 781 | .base = undefined, | 787 | .base = undefined, |
| 782 | .key = normal_key, | 788 | .key = normal_key, |
| 783 | .garbage_node = undefined, | 789 | .garbage_node = undefined, |
| 784 | }); | 790 | }; |
| 785 | errdefer comp.gpa().destroy(self); | 791 | errdefer comp.gpa().destroy(self); |
| 786 | 792 | ||
| 787 | const size_str = switch (self.key.size) { | 793 | const size_str = switch (self.key.size) { |
| 788 | Size.One => "*", | 794 | Size.One => "*", |
| 789 | Size.Many => "[*]", | 795 | Size.Many => "[*]", |
| 790 | Size.Slice => "[]", | 796 | Size.Slice => "[]", |
| 797 | Size.C => "[*c]", | ||
| 791 | }; | 798 | }; |
| 792 | const mut_str = switch (self.key.mut) { | 799 | const mut_str = switch (self.key.mut) { |
| 793 | Mut.Const => "const ", | 800 | Mut.Const => "const ", |
| ... | @@ -829,7 +836,7 @@ pub const Type = struct { | ... | @@ -829,7 +836,7 @@ pub const Type = struct { |
| 829 | return self; | 836 | return self; |
| 830 | } | 837 | } |
| 831 | 838 | ||
| 832 | pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | 839 | pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { |
| 833 | const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context); | 840 | const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context); |
| 834 | return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory; | 841 | return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory; |
| 835 | } | 842 | } |
| ... | @@ -875,11 +882,12 @@ pub const Type = struct { | ... | @@ -875,11 +882,12 @@ pub const Type = struct { |
| 875 | } | 882 | } |
| 876 | } | 883 | } |
| 877 | 884 | ||
| 878 | const self = try comp.gpa().create(Array{ | 885 | const self = try comp.gpa().create(Array); |
| 886 | self.* = Array{ | ||
| 879 | .base = undefined, | 887 | .base = undefined, |
| 880 | .key = key, | 888 | .key = key, |
| 881 | .garbage_node = undefined, | 889 | .garbage_node = undefined, |
| 882 | }); | 890 | }; |
| 883 | errdefer comp.gpa().destroy(self); | 891 | errdefer comp.gpa().destroy(self); |
| 884 | 892 | ||
| 885 | const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name); | 893 | const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name); |
| ... | @@ -896,12 +904,24 @@ pub const Type = struct { | ... | @@ -896,12 +904,24 @@ pub const Type = struct { |
| 896 | return self; | 904 | return self; |
| 897 | } | 905 | } |
| 898 | 906 | ||
| 899 | pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef { | 907 | pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { |
| 900 | const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context); | 908 | const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context); |
| 901 | return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory; | 909 | return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory; |
| 902 | } | 910 | } |
| 903 | }; | 911 | }; |
| 904 | 912 | ||
| 913 | pub const Vector = struct { | ||
| 914 | base: Type, | ||
| 915 | |||
| 916 | pub fn destroy(self: *Vector, comp: *Compilation) void { | ||
| 917 | comp.gpa().destroy(self); | ||
| 918 | } | ||
| 919 | |||
| 920 | pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { | ||
| 921 | @panic("TODO"); | ||
| 922 | } | ||
| 923 | }; | ||
| 924 | |||
| 905 | pub const ComptimeFloat = struct { | 925 | pub const ComptimeFloat = struct { |
| 906 | base: Type, | 926 | base: Type, |
| 907 | 927 | ||
| ... | @@ -947,7 +967,7 @@ pub const Type = struct { | ... | @@ -947,7 +967,7 @@ pub const Type = struct { |
| 947 | comp.gpa().destroy(self); | 967 | comp.gpa().destroy(self); |
| 948 | } | 968 | } |
| 949 | 969 | ||
| 950 | pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 970 | pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 951 | @panic("TODO"); | 971 | @panic("TODO"); |
| 952 | } | 972 | } |
| 953 | }; | 973 | }; |
| ... | @@ -959,7 +979,7 @@ pub const Type = struct { | ... | @@ -959,7 +979,7 @@ pub const Type = struct { |
| 959 | comp.gpa().destroy(self); | 979 | comp.gpa().destroy(self); |
| 960 | } | 980 | } |
| 961 | 981 | ||
| 962 | pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 982 | pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 963 | @panic("TODO"); | 983 | @panic("TODO"); |
| 964 | } | 984 | } |
| 965 | }; | 985 | }; |
| ... | @@ -971,7 +991,7 @@ pub const Type = struct { | ... | @@ -971,7 +991,7 @@ pub const Type = struct { |
| 971 | comp.gpa().destroy(self); | 991 | comp.gpa().destroy(self); |
| 972 | } | 992 | } |
| 973 | 993 | ||
| 974 | pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 994 | pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 975 | @panic("TODO"); | 995 | @panic("TODO"); |
| 976 | } | 996 | } |
| 977 | }; | 997 | }; |
| ... | @@ -983,7 +1003,7 @@ pub const Type = struct { | ... | @@ -983,7 +1003,7 @@ pub const Type = struct { |
| 983 | comp.gpa().destroy(self); | 1003 | comp.gpa().destroy(self); |
| 984 | } | 1004 | } |
| 985 | 1005 | ||
| 986 | pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 1006 | pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 987 | @panic("TODO"); | 1007 | @panic("TODO"); |
| 988 | } | 1008 | } |
| 989 | }; | 1009 | }; |
| ... | @@ -995,7 +1015,7 @@ pub const Type = struct { | ... | @@ -995,7 +1015,7 @@ pub const Type = struct { |
| 995 | comp.gpa().destroy(self); | 1015 | comp.gpa().destroy(self); |
| 996 | } | 1016 | } |
| 997 | 1017 | ||
| 998 | pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 1018 | pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 999 | @panic("TODO"); | 1019 | @panic("TODO"); |
| 1000 | } | 1020 | } |
| 1001 | }; | 1021 | }; |
| ... | @@ -1015,7 +1035,7 @@ pub const Type = struct { | ... | @@ -1015,7 +1035,7 @@ pub const Type = struct { |
| 1015 | comp.gpa().destroy(self); | 1035 | comp.gpa().destroy(self); |
| 1016 | } | 1036 | } |
| 1017 | 1037 | ||
| 1018 | pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 1038 | pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 1019 | @panic("TODO"); | 1039 | @panic("TODO"); |
| 1020 | } | 1040 | } |
| 1021 | }; | 1041 | }; |
| ... | @@ -1035,7 +1055,7 @@ pub const Type = struct { | ... | @@ -1035,7 +1055,7 @@ pub const Type = struct { |
| 1035 | comp.gpa().destroy(self); | 1055 | comp.gpa().destroy(self); |
| 1036 | } | 1056 | } |
| 1037 | 1057 | ||
| 1038 | pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 1058 | pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 1039 | @panic("TODO"); | 1059 | @panic("TODO"); |
| 1040 | } | 1060 | } |
| 1041 | }; | 1061 | }; |
| ... | @@ -1047,7 +1067,7 @@ pub const Type = struct { | ... | @@ -1047,7 +1067,7 @@ pub const Type = struct { |
| 1047 | comp.gpa().destroy(self); | 1067 | comp.gpa().destroy(self); |
| 1048 | } | 1068 | } |
| 1049 | 1069 | ||
| 1050 | pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef { | 1070 | pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { |
| 1051 | @panic("TODO"); | 1071 | @panic("TODO"); |
| 1052 | } | 1072 | } |
| 1053 | }; | 1073 | }; |
| ... | @@ -1069,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 { | ... | @@ -1069,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 { |
| 1069 | builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed), | 1089 | builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed), |
| 1070 | builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"), | 1090 | builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"), |
| 1071 | builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"), | 1091 | builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"), |
| 1092 | builtin.TypeInfo.Pointer.Size.C => unreachable, | ||
| 1072 | } | 1093 | } |
| 1073 | }, | 1094 | }, |
| 1074 | builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed), | 1095 | builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed), |
src-self-hosted/value.zig+30-23| ... | @@ -57,7 +57,7 @@ pub const Value = struct { | ... | @@ -57,7 +57,7 @@ pub const Value = struct { |
| 57 | std.debug.warn("{}", @tagName(base.id)); | 57 | std.debug.warn("{}", @tagName(base.id)); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) { | 60 | pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) { |
| 61 | switch (base.id) { | 61 | switch (base.id) { |
| 62 | Id.Type => unreachable, | 62 | Id.Type => unreachable, |
| 63 | Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile), | 63 | Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile), |
| ... | @@ -135,14 +135,15 @@ pub const Value = struct { | ... | @@ -135,14 +135,15 @@ pub const Value = struct { |
| 135 | symbol_name: Buffer, | 135 | symbol_name: Buffer, |
| 136 | 136 | ||
| 137 | pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto { | 137 | pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto { |
| 138 | const self = try comp.gpa().create(FnProto{ | 138 | const self = try comp.gpa().create(FnProto); |
| 139 | self.* = FnProto{ | ||
| 139 | .base = Value{ | 140 | .base = Value{ |
| 140 | .id = Value.Id.FnProto, | 141 | .id = Value.Id.FnProto, |
| 141 | .typ = &fn_type.base, | 142 | .typ = &fn_type.base, |
| 142 | .ref_count = std.atomic.Int(usize).init(1), | 143 | .ref_count = std.atomic.Int(usize).init(1), |
| 143 | }, | 144 | }, |
| 144 | .symbol_name = symbol_name, | 145 | .symbol_name = symbol_name, |
| 145 | }); | 146 | }; |
| 146 | fn_type.base.base.ref(); | 147 | fn_type.base.base.ref(); |
| 147 | return self; | 148 | return self; |
| 148 | } | 149 | } |
| ... | @@ -152,7 +153,7 @@ pub const Value = struct { | ... | @@ -152,7 +153,7 @@ pub const Value = struct { |
| 152 | comp.gpa().destroy(self); | 153 | comp.gpa().destroy(self); |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef { | 156 | pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value { |
| 156 | const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); | 157 | const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| 157 | const llvm_fn = llvm.AddFunction( | 158 | const llvm_fn = llvm.AddFunction( |
| 158 | ofile.module, | 159 | ofile.module, |
| ... | @@ -190,14 +191,16 @@ pub const Value = struct { | ... | @@ -190,14 +191,16 @@ pub const Value = struct { |
| 190 | /// Creates a Fn value with 1 ref | 191 | /// Creates a Fn value with 1 ref |
| 191 | /// Takes ownership of symbol_name | 192 | /// Takes ownership of symbol_name |
| 192 | pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn { | 193 | pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn { |
| 193 | const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node{ | 194 | const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node); |
| 195 | link_set_node.* = Compilation.FnLinkSet.Node{ | ||
| 194 | .data = null, | 196 | .data = null, |
| 195 | .next = undefined, | 197 | .next = undefined, |
| 196 | .prev = undefined, | 198 | .prev = undefined, |
| 197 | }); | 199 | }; |
| 198 | errdefer comp.gpa().destroy(link_set_node); | 200 | errdefer comp.gpa().destroy(link_set_node); |
| 199 | 201 | ||
| 200 | const self = try comp.gpa().create(Fn{ | 202 | const self = try comp.gpa().create(Fn); |
| 203 | self.* = Fn{ | ||
| 201 | .base = Value{ | 204 | .base = Value{ |
| 202 | .id = Value.Id.Fn, | 205 | .id = Value.Id.Fn, |
| 203 | .typ = &fn_type.base, | 206 | .typ = &fn_type.base, |
| ... | @@ -209,7 +212,7 @@ pub const Value = struct { | ... | @@ -209,7 +212,7 @@ pub const Value = struct { |
| 209 | .symbol_name = symbol_name, | 212 | .symbol_name = symbol_name, |
| 210 | .containing_object = Buffer.initNull(comp.gpa()), | 213 | .containing_object = Buffer.initNull(comp.gpa()), |
| 211 | .link_set_node = link_set_node, | 214 | .link_set_node = link_set_node, |
| 212 | }); | 215 | }; |
| 213 | fn_type.base.base.ref(); | 216 | fn_type.base.base.ref(); |
| 214 | fndef_scope.fn_val = self; | 217 | fndef_scope.fn_val = self; |
| 215 | fndef_scope.base.ref(); | 218 | fndef_scope.base.ref(); |
| ... | @@ -235,7 +238,7 @@ pub const Value = struct { | ... | @@ -235,7 +238,7 @@ pub const Value = struct { |
| 235 | /// We know that the function definition will end up in an .o file somewhere. | 238 | /// We know that the function definition will end up in an .o file somewhere. |
| 236 | /// Here, all we have to do is generate a global prototype. | 239 | /// Here, all we have to do is generate a global prototype. |
| 237 | /// TODO cache the prototype per ObjectFile | 240 | /// TODO cache the prototype per ObjectFile |
| 238 | pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?llvm.ValueRef { | 241 | pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?*llvm.Value { |
| 239 | const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); | 242 | const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| 240 | const llvm_fn = llvm.AddFunction( | 243 | const llvm_fn = llvm.AddFunction( |
| 241 | ofile.module, | 244 | ofile.module, |
| ... | @@ -280,8 +283,8 @@ pub const Value = struct { | ... | @@ -280,8 +283,8 @@ pub const Value = struct { |
| 280 | comp.gpa().destroy(self); | 283 | comp.gpa().destroy(self); |
| 281 | } | 284 | } |
| 282 | 285 | ||
| 283 | pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef { | 286 | pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value { |
| 284 | const llvm_type = llvm.Int1TypeInContext(ofile.context); | 287 | const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory; |
| 285 | if (self.x) { | 288 | if (self.x) { |
| 286 | return llvm.ConstAllOnes(llvm_type); | 289 | return llvm.ConstAllOnes(llvm_type); |
| 287 | } else { | 290 | } else { |
| ... | @@ -353,7 +356,8 @@ pub const Value = struct { | ... | @@ -353,7 +356,8 @@ pub const Value = struct { |
| 353 | var ptr_type_consumed = false; | 356 | var ptr_type_consumed = false; |
| 354 | errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp); | 357 | errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp); |
| 355 | 358 | ||
| 356 | const self = try comp.gpa().create(Value.Ptr{ | 359 | const self = try comp.gpa().create(Value.Ptr); |
| 360 | self.* = Value.Ptr{ | ||
| 357 | .base = Value{ | 361 | .base = Value{ |
| 358 | .id = Value.Id.Ptr, | 362 | .id = Value.Id.Ptr, |
| 359 | .typ = &ptr_type.base, | 363 | .typ = &ptr_type.base, |
| ... | @@ -366,7 +370,7 @@ pub const Value = struct { | ... | @@ -366,7 +370,7 @@ pub const Value = struct { |
| 366 | }, | 370 | }, |
| 367 | }, | 371 | }, |
| 368 | .mut = Mut.CompTimeConst, | 372 | .mut = Mut.CompTimeConst, |
| 369 | }); | 373 | }; |
| 370 | ptr_type_consumed = true; | 374 | ptr_type_consumed = true; |
| 371 | errdefer comp.gpa().destroy(self); | 375 | errdefer comp.gpa().destroy(self); |
| 372 | 376 | ||
| ... | @@ -377,7 +381,7 @@ pub const Value = struct { | ... | @@ -377,7 +381,7 @@ pub const Value = struct { |
| 377 | comp.gpa().destroy(self); | 381 | comp.gpa().destroy(self); |
| 378 | } | 382 | } |
| 379 | 383 | ||
| 380 | pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef { | 384 | pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value { |
| 381 | const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context); | 385 | const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| 382 | // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr | 386 | // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr |
| 383 | switch (self.special) { | 387 | switch (self.special) { |
| ... | @@ -387,7 +391,7 @@ pub const Value = struct { | ... | @@ -387,7 +391,7 @@ pub const Value = struct { |
| 387 | const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?; | 391 | const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?; |
| 388 | const ptr_bit_count = ofile.comp.target_ptr_bits; | 392 | const ptr_bit_count = ofile.comp.target_ptr_bits; |
| 389 | const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory; | 393 | const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory; |
| 390 | const indices = []llvm.ValueRef{ | 394 | const indices = []*llvm.Value{ |
| 391 | llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory, | 395 | llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory, |
| 392 | llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory, | 396 | llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory, |
| 393 | }; | 397 | }; |
| ... | @@ -430,14 +434,15 @@ pub const Value = struct { | ... | @@ -430,14 +434,15 @@ pub const Value = struct { |
| 430 | }) catch unreachable); | 434 | }) catch unreachable); |
| 431 | errdefer array_type.base.base.deref(comp); | 435 | errdefer array_type.base.base.deref(comp); |
| 432 | 436 | ||
| 433 | const self = try comp.gpa().create(Value.Array{ | 437 | const self = try comp.gpa().create(Value.Array); |
| 438 | self.* = Value.Array{ | ||
| 434 | .base = Value{ | 439 | .base = Value{ |
| 435 | .id = Value.Id.Array, | 440 | .id = Value.Id.Array, |
| 436 | .typ = &array_type.base, | 441 | .typ = &array_type.base, |
| 437 | .ref_count = std.atomic.Int(usize).init(1), | 442 | .ref_count = std.atomic.Int(usize).init(1), |
| 438 | }, | 443 | }, |
| 439 | .special = Special{ .OwnedBuffer = buffer }, | 444 | .special = Special{ .OwnedBuffer = buffer }, |
| 440 | }); | 445 | }; |
| 441 | errdefer comp.gpa().destroy(self); | 446 | errdefer comp.gpa().destroy(self); |
| 442 | 447 | ||
| 443 | return self; | 448 | return self; |
| ... | @@ -454,7 +459,7 @@ pub const Value = struct { | ... | @@ -454,7 +459,7 @@ pub const Value = struct { |
| 454 | comp.gpa().destroy(self); | 459 | comp.gpa().destroy(self); |
| 455 | } | 460 | } |
| 456 | 461 | ||
| 457 | pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef { | 462 | pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value { |
| 458 | switch (self.special) { | 463 | switch (self.special) { |
| 459 | Special.Undefined => { | 464 | Special.Undefined => { |
| 460 | const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); | 465 | const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| ... | @@ -509,14 +514,15 @@ pub const Value = struct { | ... | @@ -509,14 +514,15 @@ pub const Value = struct { |
| 509 | big_int: std.math.big.Int, | 514 | big_int: std.math.big.Int, |
| 510 | 515 | ||
| 511 | pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int { | 516 | pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int { |
| 512 | const self = try comp.gpa().create(Value.Int{ | 517 | const self = try comp.gpa().create(Value.Int); |
| 518 | self.* = Value.Int{ | ||
| 513 | .base = Value{ | 519 | .base = Value{ |
| 514 | .id = Value.Id.Int, | 520 | .id = Value.Id.Int, |
| 515 | .typ = typ, | 521 | .typ = typ, |
| 516 | .ref_count = std.atomic.Int(usize).init(1), | 522 | .ref_count = std.atomic.Int(usize).init(1), |
| 517 | }, | 523 | }, |
| 518 | .big_int = undefined, | 524 | .big_int = undefined, |
| 519 | }); | 525 | }; |
| 520 | typ.base.ref(); | 526 | typ.base.ref(); |
| 521 | errdefer comp.gpa().destroy(self); | 527 | errdefer comp.gpa().destroy(self); |
| 522 | 528 | ||
| ... | @@ -528,7 +534,7 @@ pub const Value = struct { | ... | @@ -528,7 +534,7 @@ pub const Value = struct { |
| 528 | return self; | 534 | return self; |
| 529 | } | 535 | } |
| 530 | 536 | ||
| 531 | pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef { | 537 | pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value { |
| 532 | switch (self.base.typ.id) { | 538 | switch (self.base.typ.id) { |
| 533 | Type.Id.Int => { | 539 | Type.Id.Int => { |
| 534 | const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context); | 540 | const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context); |
| ... | @@ -557,14 +563,15 @@ pub const Value = struct { | ... | @@ -557,14 +563,15 @@ pub const Value = struct { |
| 557 | old.base.typ.base.ref(); | 563 | old.base.typ.base.ref(); |
| 558 | errdefer old.base.typ.base.deref(comp); | 564 | errdefer old.base.typ.base.deref(comp); |
| 559 | 565 | ||
| 560 | const new = try comp.gpa().create(Value.Int{ | 566 | const new = try comp.gpa().create(Value.Int); |
| 567 | new.* = Value.Int{ | ||
| 561 | .base = Value{ | 568 | .base = Value{ |
| 562 | .id = Value.Id.Int, | 569 | .id = Value.Id.Int, |
| 563 | .typ = old.base.typ, | 570 | .typ = old.base.typ, |
| 564 | .ref_count = std.atomic.Int(usize).init(1), | 571 | .ref_count = std.atomic.Int(usize).init(1), |
| 565 | }, | 572 | }, |
| 566 | .big_int = undefined, | 573 | .big_int = undefined, |
| 567 | }); | 574 | }; |
| 568 | errdefer comp.gpa().destroy(new); | 575 | errdefer comp.gpa().destroy(new); |
| 569 | 576 | ||
| 570 | new.big_int = try old.big_int.clone(); | 577 | new.big_int = try old.big_int.clone(); |
src/all_types.hpp+212-61| ... | @@ -56,9 +56,6 @@ struct IrExecutable { | ... | @@ -56,9 +56,6 @@ struct IrExecutable { |
| 56 | size_t next_debug_id; | 56 | size_t next_debug_id; |
| 57 | size_t *backward_branch_count; | 57 | size_t *backward_branch_count; |
| 58 | size_t backward_branch_quota; | 58 | size_t backward_branch_quota; |
| 59 | bool invalid; | ||
| 60 | bool is_inline; | ||
| 61 | bool is_generic_instantiation; | ||
| 62 | ZigFn *fn_entry; | 59 | ZigFn *fn_entry; |
| 63 | Buf *c_import_buf; | 60 | Buf *c_import_buf; |
| 64 | AstNode *source_node; | 61 | AstNode *source_node; |
| ... | @@ -78,6 +75,10 @@ struct IrExecutable { | ... | @@ -78,6 +75,10 @@ struct IrExecutable { |
| 78 | IrBasicBlock *coro_suspend_block; | 75 | IrBasicBlock *coro_suspend_block; |
| 79 | IrBasicBlock *coro_final_cleanup_block; | 76 | IrBasicBlock *coro_final_cleanup_block; |
| 80 | ZigVar *coro_allocator_var; | 77 | ZigVar *coro_allocator_var; |
| 78 | |||
| 79 | bool invalid; | ||
| 80 | bool is_inline; | ||
| 81 | bool is_generic_instantiation; | ||
| 81 | }; | 82 | }; |
| 82 | 83 | ||
| 83 | enum OutType { | 84 | enum OutType { |
| ... | @@ -90,6 +91,9 @@ enum OutType { | ... | @@ -90,6 +91,9 @@ enum OutType { |
| 90 | enum ConstParentId { | 91 | enum ConstParentId { |
| 91 | ConstParentIdNone, | 92 | ConstParentIdNone, |
| 92 | ConstParentIdStruct, | 93 | ConstParentIdStruct, |
| 94 | ConstParentIdErrUnionCode, | ||
| 95 | ConstParentIdErrUnionPayload, | ||
| 96 | ConstParentIdOptionalPayload, | ||
| 93 | ConstParentIdArray, | 97 | ConstParentIdArray, |
| 94 | ConstParentIdUnion, | 98 | ConstParentIdUnion, |
| 95 | ConstParentIdScalar, | 99 | ConstParentIdScalar, |
| ... | @@ -107,6 +111,15 @@ struct ConstParent { | ... | @@ -107,6 +111,15 @@ struct ConstParent { |
| 107 | ConstExprValue *struct_val; | 111 | ConstExprValue *struct_val; |
| 108 | size_t field_index; | 112 | size_t field_index; |
| 109 | } p_struct; | 113 | } p_struct; |
| 114 | struct { | ||
| 115 | ConstExprValue *err_union_val; | ||
| 116 | } p_err_union_code; | ||
| 117 | struct { | ||
| 118 | ConstExprValue *err_union_val; | ||
| 119 | } p_err_union_payload; | ||
| 120 | struct { | ||
| 121 | ConstExprValue *optional_val; | ||
| 122 | } p_optional_payload; | ||
| 110 | struct { | 123 | struct { |
| 111 | ConstExprValue *union_val; | 124 | ConstExprValue *union_val; |
| 112 | } p_union; | 125 | } p_union; |
| ... | @@ -118,13 +131,11 @@ struct ConstParent { | ... | @@ -118,13 +131,11 @@ struct ConstParent { |
| 118 | 131 | ||
| 119 | struct ConstStructValue { | 132 | struct ConstStructValue { |
| 120 | ConstExprValue *fields; | 133 | ConstExprValue *fields; |
| 121 | ConstParent parent; | ||
| 122 | }; | 134 | }; |
| 123 | 135 | ||
| 124 | struct ConstUnionValue { | 136 | struct ConstUnionValue { |
| 125 | BigInt tag; | 137 | BigInt tag; |
| 126 | ConstExprValue *payload; | 138 | ConstExprValue *payload; |
| 127 | ConstParent parent; | ||
| 128 | }; | 139 | }; |
| 129 | 140 | ||
| 130 | enum ConstArraySpecial { | 141 | enum ConstArraySpecial { |
| ... | @@ -138,7 +149,6 @@ struct ConstArrayValue { | ... | @@ -138,7 +149,6 @@ struct ConstArrayValue { |
| 138 | union { | 149 | union { |
| 139 | struct { | 150 | struct { |
| 140 | ConstExprValue *elements; | 151 | ConstExprValue *elements; |
| 141 | ConstParent parent; | ||
| 142 | } s_none; | 152 | } s_none; |
| 143 | Buf *s_buf; | 153 | Buf *s_buf; |
| 144 | } data; | 154 | } data; |
| ... | @@ -153,19 +163,29 @@ enum ConstPtrSpecial { | ... | @@ -153,19 +163,29 @@ enum ConstPtrSpecial { |
| 153 | ConstPtrSpecialBaseArray, | 163 | ConstPtrSpecialBaseArray, |
| 154 | // The pointer points to a field in an underlying struct. | 164 | // The pointer points to a field in an underlying struct. |
| 155 | ConstPtrSpecialBaseStruct, | 165 | ConstPtrSpecialBaseStruct, |
| 166 | // The pointer points to the error set field of an error union | ||
| 167 | ConstPtrSpecialBaseErrorUnionCode, | ||
| 168 | // The pointer points to the payload field of an error union | ||
| 169 | ConstPtrSpecialBaseErrorUnionPayload, | ||
| 170 | // The pointer points to the payload field of an optional | ||
| 171 | ConstPtrSpecialBaseOptionalPayload, | ||
| 156 | // This means that we did a compile-time pointer reinterpret and we cannot | 172 | // This means that we did a compile-time pointer reinterpret and we cannot |
| 157 | // understand the value of pointee at compile time. However, we will still | 173 | // understand the value of pointee at compile time. However, we will still |
| 158 | // emit a binary with a compile time known address. | 174 | // emit a binary with a compile time known address. |
| 159 | // In this case index is the numeric address value. | 175 | // In this case index is the numeric address value. |
| 160 | // We also use this for null pointer. We need the data layout for ConstCastOnly == true | ||
| 161 | // types to be the same, so all optionals of pointer types use x_ptr | ||
| 162 | // instead of x_optional | ||
| 163 | ConstPtrSpecialHardCodedAddr, | 176 | ConstPtrSpecialHardCodedAddr, |
| 164 | // This means that the pointer represents memory of assigning to _. | 177 | // This means that the pointer represents memory of assigning to _. |
| 165 | // That is, storing discards the data, and loading is invalid. | 178 | // That is, storing discards the data, and loading is invalid. |
| 166 | ConstPtrSpecialDiscard, | 179 | ConstPtrSpecialDiscard, |
| 167 | // This is actually a function. | 180 | // This is actually a function. |
| 168 | ConstPtrSpecialFunction, | 181 | ConstPtrSpecialFunction, |
| 182 | // This means the pointer is null. This is only allowed when the type is ?*T. | ||
| 183 | // We use this instead of ConstPtrSpecialHardCodedAddr because often we check | ||
| 184 | // for that value to avoid doing comptime work. | ||
| 185 | // We need the data layout for ConstCastOnly == true | ||
| 186 | // types to be the same, so all optionals of pointer types use x_ptr | ||
| 187 | // instead of x_optional. | ||
| 188 | ConstPtrSpecialNull, | ||
| 169 | }; | 189 | }; |
| 170 | 190 | ||
| 171 | enum ConstPtrMut { | 191 | enum ConstPtrMut { |
| ... | @@ -199,6 +219,15 @@ struct ConstPtrValue { | ... | @@ -199,6 +219,15 @@ struct ConstPtrValue { |
| 199 | ConstExprValue *struct_val; | 219 | ConstExprValue *struct_val; |
| 200 | size_t field_index; | 220 | size_t field_index; |
| 201 | } base_struct; | 221 | } base_struct; |
| 222 | struct { | ||
| 223 | ConstExprValue *err_union_val; | ||
| 224 | } base_err_union_code; | ||
| 225 | struct { | ||
| 226 | ConstExprValue *err_union_val; | ||
| 227 | } base_err_union_payload; | ||
| 228 | struct { | ||
| 229 | ConstExprValue *optional_val; | ||
| 230 | } base_optional_payload; | ||
| 202 | struct { | 231 | struct { |
| 203 | uint64_t addr; | 232 | uint64_t addr; |
| 204 | } hard_coded_addr; | 233 | } hard_coded_addr; |
| ... | @@ -209,7 +238,7 @@ struct ConstPtrValue { | ... | @@ -209,7 +238,7 @@ struct ConstPtrValue { |
| 209 | }; | 238 | }; |
| 210 | 239 | ||
| 211 | struct ConstErrValue { | 240 | struct ConstErrValue { |
| 212 | ErrorTableEntry *err; | 241 | ConstExprValue *error_set; |
| 213 | ConstExprValue *payload; | 242 | ConstExprValue *payload; |
| 214 | }; | 243 | }; |
| 215 | 244 | ||
| ... | @@ -265,6 +294,7 @@ struct ConstGlobalRefs { | ... | @@ -265,6 +294,7 @@ struct ConstGlobalRefs { |
| 265 | struct ConstExprValue { | 294 | struct ConstExprValue { |
| 266 | ZigType *type; | 295 | ZigType *type; |
| 267 | ConstValSpecial special; | 296 | ConstValSpecial special; |
| 297 | ConstParent parent; | ||
| 268 | ConstGlobalRefs *global_refs; | 298 | ConstGlobalRefs *global_refs; |
| 269 | 299 | ||
| 270 | union { | 300 | union { |
| ... | @@ -433,7 +463,7 @@ enum NodeType { | ... | @@ -433,7 +463,7 @@ enum NodeType { |
| 433 | NodeTypeArrayType, | 463 | NodeTypeArrayType, |
| 434 | NodeTypeErrorType, | 464 | NodeTypeErrorType, |
| 435 | NodeTypeIfErrorExpr, | 465 | NodeTypeIfErrorExpr, |
| 436 | NodeTypeTestExpr, | 466 | NodeTypeIfOptional, |
| 437 | NodeTypeErrorSetDecl, | 467 | NodeTypeErrorSetDecl, |
| 438 | NodeTypeCancel, | 468 | NodeTypeCancel, |
| 439 | NodeTypeResume, | 469 | NodeTypeResume, |
| ... | @@ -514,12 +544,7 @@ struct AstNodeDefer { | ... | @@ -514,12 +544,7 @@ struct AstNodeDefer { |
| 514 | }; | 544 | }; |
| 515 | 545 | ||
| 516 | struct AstNodeVariableDeclaration { | 546 | struct AstNodeVariableDeclaration { |
| 517 | VisibMod visib_mod; | ||
| 518 | Buf *symbol; | 547 | Buf *symbol; |
| 519 | bool is_const; | ||
| 520 | bool is_comptime; | ||
| 521 | bool is_export; | ||
| 522 | bool is_extern; | ||
| 523 | // one or both of type and expr will be non null | 548 | // one or both of type and expr will be non null |
| 524 | AstNode *type; | 549 | AstNode *type; |
| 525 | AstNode *expr; | 550 | AstNode *expr; |
| ... | @@ -529,6 +554,13 @@ struct AstNodeVariableDeclaration { | ... | @@ -529,6 +554,13 @@ struct AstNodeVariableDeclaration { |
| 529 | AstNode *align_expr; | 554 | AstNode *align_expr; |
| 530 | // populated if the "section(S)" is present | 555 | // populated if the "section(S)" is present |
| 531 | AstNode *section_expr; | 556 | AstNode *section_expr; |
| 557 | Token *threadlocal_tok; | ||
| 558 | |||
| 559 | VisibMod visib_mod; | ||
| 560 | bool is_const; | ||
| 561 | bool is_comptime; | ||
| 562 | bool is_export; | ||
| 563 | bool is_extern; | ||
| 532 | }; | 564 | }; |
| 533 | 565 | ||
| 534 | struct AstNodeTestDecl { | 566 | struct AstNodeTestDecl { |
| ... | @@ -605,7 +637,6 @@ enum CastOp { | ... | @@ -605,7 +637,6 @@ enum CastOp { |
| 605 | CastOpFloatToInt, | 637 | CastOpFloatToInt, |
| 606 | CastOpBoolToInt, | 638 | CastOpBoolToInt, |
| 607 | CastOpResizeSlice, | 639 | CastOpResizeSlice, |
| 608 | CastOpBytesToSlice, | ||
| 609 | CastOpNumLitToConcrete, | 640 | CastOpNumLitToConcrete, |
| 610 | CastOpErrSet, | 641 | CastOpErrSet, |
| 611 | CastOpBitCast, | 642 | CastOpBitCast, |
| ... | @@ -660,15 +691,17 @@ struct AstNodePointerType { | ... | @@ -660,15 +691,17 @@ struct AstNodePointerType { |
| 660 | AstNode *align_expr; | 691 | AstNode *align_expr; |
| 661 | BigInt *bit_offset_start; | 692 | BigInt *bit_offset_start; |
| 662 | BigInt *host_int_bytes; | 693 | BigInt *host_int_bytes; |
| 694 | AstNode *op_expr; | ||
| 695 | Token *allow_zero_token; | ||
| 663 | bool is_const; | 696 | bool is_const; |
| 664 | bool is_volatile; | 697 | bool is_volatile; |
| 665 | AstNode *op_expr; | ||
| 666 | }; | 698 | }; |
| 667 | 699 | ||
| 668 | struct AstNodeArrayType { | 700 | struct AstNodeArrayType { |
| 669 | AstNode *size; | 701 | AstNode *size; |
| 670 | AstNode *child_type; | 702 | AstNode *child_type; |
| 671 | AstNode *align_expr; | 703 | AstNode *align_expr; |
| 704 | Token *allow_zero_token; | ||
| 672 | bool is_const; | 705 | bool is_const; |
| 673 | bool is_volatile; | 706 | bool is_volatile; |
| 674 | }; | 707 | }; |
| ... | @@ -678,7 +711,7 @@ struct AstNodeUse { | ... | @@ -678,7 +711,7 @@ struct AstNodeUse { |
| 678 | AstNode *expr; | 711 | AstNode *expr; |
| 679 | 712 | ||
| 680 | TldResolution resolution; | 713 | TldResolution resolution; |
| 681 | IrInstruction *value; | 714 | ConstExprValue *value; |
| 682 | }; | 715 | }; |
| 683 | 716 | ||
| 684 | struct AstNodeIfBoolExpr { | 717 | struct AstNodeIfBoolExpr { |
| ... | @@ -1007,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); | ... | @@ -1007,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); |
| 1007 | enum PtrLen { | 1040 | enum PtrLen { |
| 1008 | PtrLenUnknown, | 1041 | PtrLenUnknown, |
| 1009 | PtrLenSingle, | 1042 | PtrLenSingle, |
| 1043 | PtrLenC, | ||
| 1010 | }; | 1044 | }; |
| 1011 | 1045 | ||
| 1012 | struct ZigTypePointer { | 1046 | struct ZigTypePointer { |
| ... | @@ -1018,6 +1052,7 @@ struct ZigTypePointer { | ... | @@ -1018,6 +1052,7 @@ struct ZigTypePointer { |
| 1018 | uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned | 1052 | uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned |
| 1019 | bool is_const; | 1053 | bool is_const; |
| 1020 | bool is_volatile; | 1054 | bool is_volatile; |
| 1055 | bool allow_zero; | ||
| 1021 | }; | 1056 | }; |
| 1022 | 1057 | ||
| 1023 | struct ZigTypeInt { | 1058 | struct ZigTypeInt { |
| ... | @@ -1167,6 +1202,7 @@ struct ZigTypeFn { | ... | @@ -1167,6 +1202,7 @@ struct ZigTypeFn { |
| 1167 | FnGenParamInfo *gen_param_info; | 1202 | FnGenParamInfo *gen_param_info; |
| 1168 | 1203 | ||
| 1169 | LLVMTypeRef raw_type_ref; | 1204 | LLVMTypeRef raw_type_ref; |
| 1205 | ZigLLVMDIType *raw_di_type; | ||
| 1170 | 1206 | ||
| 1171 | ZigType *bound_fn_parent; | 1207 | ZigType *bound_fn_parent; |
| 1172 | }; | 1208 | }; |
| ... | @@ -1180,6 +1216,12 @@ struct ZigTypePromise { | ... | @@ -1180,6 +1216,12 @@ struct ZigTypePromise { |
| 1180 | ZigType *result_type; | 1216 | ZigType *result_type; |
| 1181 | }; | 1217 | }; |
| 1182 | 1218 | ||
| 1219 | struct ZigTypeVector { | ||
| 1220 | // The type must be a pointer, integer, or float | ||
| 1221 | ZigType *elem_type; | ||
| 1222 | uint32_t len; | ||
| 1223 | }; | ||
| 1224 | |||
| 1183 | enum ZigTypeId { | 1225 | enum ZigTypeId { |
| 1184 | ZigTypeIdInvalid, | 1226 | ZigTypeIdInvalid, |
| 1185 | ZigTypeIdMetaType, | 1227 | ZigTypeIdMetaType, |
| ... | @@ -1206,6 +1248,7 @@ enum ZigTypeId { | ... | @@ -1206,6 +1248,7 @@ enum ZigTypeId { |
| 1206 | ZigTypeIdArgTuple, | 1248 | ZigTypeIdArgTuple, |
| 1207 | ZigTypeIdOpaque, | 1249 | ZigTypeIdOpaque, |
| 1208 | ZigTypeIdPromise, | 1250 | ZigTypeIdPromise, |
| 1251 | ZigTypeIdVector, | ||
| 1209 | }; | 1252 | }; |
| 1210 | 1253 | ||
| 1211 | struct ZigType { | 1254 | struct ZigType { |
| ... | @@ -1232,6 +1275,7 @@ struct ZigType { | ... | @@ -1232,6 +1275,7 @@ struct ZigType { |
| 1232 | ZigTypeFn fn; | 1275 | ZigTypeFn fn; |
| 1233 | ZigTypeBoundFn bound_fn; | 1276 | ZigTypeBoundFn bound_fn; |
| 1234 | ZigTypePromise promise; | 1277 | ZigTypePromise promise; |
| 1278 | ZigTypeVector vector; | ||
| 1235 | } data; | 1279 | } data; |
| 1236 | 1280 | ||
| 1237 | // use these fields to make sure we don't duplicate type table entries for the same type | 1281 | // use these fields to make sure we don't duplicate type table entries for the same type |
| ... | @@ -1385,6 +1429,7 @@ enum BuiltinFnId { | ... | @@ -1385,6 +1429,7 @@ enum BuiltinFnId { |
| 1385 | BuiltinFnIdEnumToInt, | 1429 | BuiltinFnIdEnumToInt, |
| 1386 | BuiltinFnIdIntToEnum, | 1430 | BuiltinFnIdIntToEnum, |
| 1387 | BuiltinFnIdIntType, | 1431 | BuiltinFnIdIntType, |
| 1432 | BuiltinFnIdVectorType, | ||
| 1388 | BuiltinFnIdSetCold, | 1433 | BuiltinFnIdSetCold, |
| 1389 | BuiltinFnIdSetRuntimeSafety, | 1434 | BuiltinFnIdSetRuntimeSafety, |
| 1390 | BuiltinFnIdSetFloatMode, | 1435 | BuiltinFnIdSetFloatMode, |
| ... | @@ -1415,6 +1460,8 @@ enum BuiltinFnId { | ... | @@ -1415,6 +1460,8 @@ enum BuiltinFnId { |
| 1415 | BuiltinFnIdErrorReturnTrace, | 1460 | BuiltinFnIdErrorReturnTrace, |
| 1416 | BuiltinFnIdAtomicRmw, | 1461 | BuiltinFnIdAtomicRmw, |
| 1417 | BuiltinFnIdAtomicLoad, | 1462 | BuiltinFnIdAtomicLoad, |
| 1463 | BuiltinFnIdBswap, | ||
| 1464 | BuiltinFnIdBitReverse, | ||
| 1418 | }; | 1465 | }; |
| 1419 | 1466 | ||
| 1420 | struct BuiltinFnEntry { | 1467 | struct BuiltinFnEntry { |
| ... | @@ -1441,6 +1488,7 @@ enum PanicMsgId { | ... | @@ -1441,6 +1488,7 @@ enum PanicMsgId { |
| 1441 | PanicMsgIdBadUnionField, | 1488 | PanicMsgIdBadUnionField, |
| 1442 | PanicMsgIdBadEnumValue, | 1489 | PanicMsgIdBadEnumValue, |
| 1443 | PanicMsgIdFloatToInt, | 1490 | PanicMsgIdFloatToInt, |
| 1491 | PanicMsgIdPtrCastNull, | ||
| 1444 | 1492 | ||
| 1445 | PanicMsgIdCount, | 1493 | PanicMsgIdCount, |
| 1446 | }; | 1494 | }; |
| ... | @@ -1455,11 +1503,12 @@ struct TypeId { | ... | @@ -1455,11 +1503,12 @@ struct TypeId { |
| 1455 | struct { | 1503 | struct { |
| 1456 | ZigType *child_type; | 1504 | ZigType *child_type; |
| 1457 | PtrLen ptr_len; | 1505 | PtrLen ptr_len; |
| 1458 | bool is_const; | ||
| 1459 | bool is_volatile; | ||
| 1460 | uint32_t alignment; | 1506 | uint32_t alignment; |
| 1461 | uint32_t bit_offset_in_host; | 1507 | uint32_t bit_offset_in_host; |
| 1462 | uint32_t host_int_bytes; | 1508 | uint32_t host_int_bytes; |
| 1509 | bool is_const; | ||
| 1510 | bool is_volatile; | ||
| 1511 | bool allow_zero; | ||
| 1463 | } pointer; | 1512 | } pointer; |
| 1464 | struct { | 1513 | struct { |
| 1465 | ZigType *child_type; | 1514 | ZigType *child_type; |
| ... | @@ -1473,6 +1522,10 @@ struct TypeId { | ... | @@ -1473,6 +1522,10 @@ struct TypeId { |
| 1473 | ZigType *err_set_type; | 1522 | ZigType *err_set_type; |
| 1474 | ZigType *payload_type; | 1523 | ZigType *payload_type; |
| 1475 | } error_union; | 1524 | } error_union; |
| 1525 | struct { | ||
| 1526 | ZigType *elem_type; | ||
| 1527 | uint32_t len; | ||
| 1528 | } vector; | ||
| 1476 | } data; | 1529 | } data; |
| 1477 | }; | 1530 | }; |
| 1478 | 1531 | ||
| ... | @@ -1487,8 +1540,12 @@ enum ZigLLVMFnId { | ... | @@ -1487,8 +1540,12 @@ enum ZigLLVMFnId { |
| 1487 | ZigLLVMFnIdFloor, | 1540 | ZigLLVMFnIdFloor, |
| 1488 | ZigLLVMFnIdCeil, | 1541 | ZigLLVMFnIdCeil, |
| 1489 | ZigLLVMFnIdSqrt, | 1542 | ZigLLVMFnIdSqrt, |
| 1543 | ZigLLVMFnIdBswap, | ||
| 1544 | ZigLLVMFnIdBitReverse, | ||
| 1490 | }; | 1545 | }; |
| 1491 | 1546 | ||
| 1547 | // There are a bunch of places in code that rely on these values being in | ||
| 1548 | // exactly this order. | ||
| 1492 | enum AddSubMul { | 1549 | enum AddSubMul { |
| 1493 | AddSubMulAdd = 0, | 1550 | AddSubMulAdd = 0, |
| 1494 | AddSubMulSub = 1, | 1551 | AddSubMulSub = 1, |
| ... | @@ -1514,8 +1571,15 @@ struct ZigLLVMFnKey { | ... | @@ -1514,8 +1571,15 @@ struct ZigLLVMFnKey { |
| 1514 | struct { | 1571 | struct { |
| 1515 | AddSubMul add_sub_mul; | 1572 | AddSubMul add_sub_mul; |
| 1516 | uint32_t bit_count; | 1573 | uint32_t bit_count; |
| 1574 | uint32_t vector_len; // 0 means not a vector | ||
| 1517 | bool is_signed; | 1575 | bool is_signed; |
| 1518 | } overflow_arithmetic; | 1576 | } overflow_arithmetic; |
| 1577 | struct { | ||
| 1578 | uint32_t bit_count; | ||
| 1579 | } bswap; | ||
| 1580 | struct { | ||
| 1581 | uint32_t bit_count; | ||
| 1582 | } bit_reverse; | ||
| 1519 | } data; | 1583 | } data; |
| 1520 | }; | 1584 | }; |
| 1521 | 1585 | ||
| ... | @@ -1600,7 +1664,7 @@ struct CodeGen { | ... | @@ -1600,7 +1664,7 @@ struct CodeGen { |
| 1600 | HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table; | 1664 | HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table; |
| 1601 | HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table; | 1665 | HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table; |
| 1602 | HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; | 1666 | HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; |
| 1603 | HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; | 1667 | HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; |
| 1604 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; | 1668 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1605 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; | 1669 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; |
| 1606 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; | 1670 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; |
| ... | @@ -1694,6 +1758,7 @@ struct CodeGen { | ... | @@ -1694,6 +1758,7 @@ struct CodeGen { |
| 1694 | ZigFn *cur_fn; | 1758 | ZigFn *cur_fn; |
| 1695 | ZigFn *main_fn; | 1759 | ZigFn *main_fn; |
| 1696 | ZigFn *panic_fn; | 1760 | ZigFn *panic_fn; |
| 1761 | TldFn *panic_tld_fn; | ||
| 1697 | AstNode *root_export_decl; | 1762 | AstNode *root_export_decl; |
| 1698 | 1763 | ||
| 1699 | CacheHash cache_hash; | 1764 | CacheHash cache_hash; |
| ... | @@ -1746,12 +1811,12 @@ struct CodeGen { | ... | @@ -1746,12 +1811,12 @@ struct CodeGen { |
| 1746 | BuildMode build_mode; | 1811 | BuildMode build_mode; |
| 1747 | OutType out_type; | 1812 | OutType out_type; |
| 1748 | ZigTarget zig_target; | 1813 | ZigTarget zig_target; |
| 1814 | TargetSubsystem subsystem; | ||
| 1749 | bool is_static; | 1815 | bool is_static; |
| 1750 | bool strip_debug_symbols; | 1816 | bool strip_debug_symbols; |
| 1751 | bool is_test_build; | 1817 | bool is_test_build; |
| 1818 | bool is_single_threaded; | ||
| 1752 | bool is_native_target; | 1819 | bool is_native_target; |
| 1753 | bool windows_subsystem_windows; | ||
| 1754 | bool windows_subsystem_console; | ||
| 1755 | bool linker_rdynamic; | 1820 | bool linker_rdynamic; |
| 1756 | bool no_rosegment_workaround; | 1821 | bool no_rosegment_workaround; |
| 1757 | bool each_lib_rpath; | 1822 | bool each_lib_rpath; |
| ... | @@ -1793,10 +1858,9 @@ enum VarLinkage { | ... | @@ -1793,10 +1858,9 @@ enum VarLinkage { |
| 1793 | 1858 | ||
| 1794 | struct ZigVar { | 1859 | struct ZigVar { |
| 1795 | Buf name; | 1860 | Buf name; |
| 1796 | ConstExprValue *value; | 1861 | ConstExprValue *const_value; |
| 1862 | ZigType *var_type; | ||
| 1797 | LLVMValueRef value_ref; | 1863 | LLVMValueRef value_ref; |
| 1798 | bool src_is_const; | ||
| 1799 | bool gen_is_const; | ||
| 1800 | IrInstruction *is_comptime; | 1864 | IrInstruction *is_comptime; |
| 1801 | // which node is the declaration of the variable | 1865 | // which node is the declaration of the variable |
| 1802 | AstNode *decl_node; | 1866 | AstNode *decl_node; |
| ... | @@ -1806,17 +1870,22 @@ struct ZigVar { | ... | @@ -1806,17 +1870,22 @@ struct ZigVar { |
| 1806 | Scope *parent_scope; | 1870 | Scope *parent_scope; |
| 1807 | Scope *child_scope; | 1871 | Scope *child_scope; |
| 1808 | LLVMValueRef param_value_ref; | 1872 | LLVMValueRef param_value_ref; |
| 1809 | bool shadowable; | ||
| 1810 | size_t mem_slot_index; | 1873 | size_t mem_slot_index; |
| 1811 | IrExecutable *owner_exec; | 1874 | IrExecutable *owner_exec; |
| 1812 | size_t ref_count; | 1875 | size_t ref_count; |
| 1813 | VarLinkage linkage; | ||
| 1814 | uint32_t align_bytes; | ||
| 1815 | 1876 | ||
| 1816 | // In an inline loop, multiple variables may be created, | 1877 | // In an inline loop, multiple variables may be created, |
| 1817 | // In this case, a reference to a variable should follow | 1878 | // In this case, a reference to a variable should follow |
| 1818 | // this pointer to the redefined variable. | 1879 | // this pointer to the redefined variable. |
| 1819 | ZigVar *next_var; | 1880 | ZigVar *next_var; |
| 1881 | |||
| 1882 | uint32_t align_bytes; | ||
| 1883 | VarLinkage linkage; | ||
| 1884 | |||
| 1885 | bool shadowable; | ||
| 1886 | bool src_is_const; | ||
| 1887 | bool gen_is_const; | ||
| 1888 | bool is_thread_local; | ||
| 1820 | }; | 1889 | }; |
| 1821 | 1890 | ||
| 1822 | struct ErrorTableEntry { | 1891 | struct ErrorTableEntry { |
| ... | @@ -1882,10 +1951,11 @@ struct ScopeBlock { | ... | @@ -1882,10 +1951,11 @@ struct ScopeBlock { |
| 1882 | ZigList<IrInstruction *> *incoming_values; | 1951 | ZigList<IrInstruction *> *incoming_values; |
| 1883 | ZigList<IrBasicBlock *> *incoming_blocks; | 1952 | ZigList<IrBasicBlock *> *incoming_blocks; |
| 1884 | 1953 | ||
| 1885 | bool safety_off; | ||
| 1886 | AstNode *safety_set_node; | 1954 | AstNode *safety_set_node; |
| 1887 | bool fast_math_on; | ||
| 1888 | AstNode *fast_math_set_node; | 1955 | AstNode *fast_math_set_node; |
| 1956 | |||
| 1957 | bool safety_off; | ||
| 1958 | bool fast_math_on; | ||
| 1889 | }; | 1959 | }; |
| 1890 | 1960 | ||
| 1891 | // This scope is created from every defer expression. | 1961 | // This scope is created from every defer expression. |
| ... | @@ -2021,8 +2091,19 @@ struct IrBasicBlock { | ... | @@ -2021,8 +2091,19 @@ struct IrBasicBlock { |
| 2021 | IrInstruction *must_be_comptime_source_instr; | 2091 | IrInstruction *must_be_comptime_source_instr; |
| 2022 | }; | 2092 | }; |
| 2023 | 2093 | ||
| 2094 | // These instructions are in transition to having "pass 1" instructions | ||
| 2095 | // and "pass 2" instructions. The pass 1 instructions are suffixed with Src | ||
| 2096 | // and pass 2 are suffixed with Gen. | ||
| 2097 | // Once all instructions are separated in this way, they'll have different | ||
| 2098 | // base types for better type safety. | ||
| 2099 | // Src instructions are generated by ir_gen_* functions in ir.cpp from AST. | ||
| 2100 | // ir_analyze_* functions consume Src instructions and produce Gen instructions. | ||
| 2101 | // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. | ||
| 2102 | // Src instructions do not have type information; Gen instructions do. | ||
| 2024 | enum IrInstructionId { | 2103 | enum IrInstructionId { |
| 2025 | IrInstructionIdInvalid, | 2104 | IrInstructionIdInvalid, |
| 2105 | IrInstructionIdDeclVarSrc, | ||
| 2106 | IrInstructionIdDeclVarGen, | ||
| 2026 | IrInstructionIdBr, | 2107 | IrInstructionIdBr, |
| 2027 | IrInstructionIdCondBr, | 2108 | IrInstructionIdCondBr, |
| 2028 | IrInstructionIdSwitchBr, | 2109 | IrInstructionIdSwitchBr, |
| ... | @@ -2031,7 +2112,6 @@ enum IrInstructionId { | ... | @@ -2031,7 +2112,6 @@ enum IrInstructionId { |
| 2031 | IrInstructionIdPhi, | 2112 | IrInstructionIdPhi, |
| 2032 | IrInstructionIdUnOp, | 2113 | IrInstructionIdUnOp, |
| 2033 | IrInstructionIdBinOp, | 2114 | IrInstructionIdBinOp, |
| 2034 | IrInstructionIdDeclVar, | ||
| 2035 | IrInstructionIdLoadPtr, | 2115 | IrInstructionIdLoadPtr, |
| 2036 | IrInstructionIdStorePtr, | 2116 | IrInstructionIdStorePtr, |
| 2037 | IrInstructionIdFieldPtr, | 2117 | IrInstructionIdFieldPtr, |
| ... | @@ -2060,7 +2140,7 @@ enum IrInstructionId { | ... | @@ -2060,7 +2140,7 @@ enum IrInstructionId { |
| 2060 | IrInstructionIdAsm, | 2140 | IrInstructionIdAsm, |
| 2061 | IrInstructionIdSizeOf, | 2141 | IrInstructionIdSizeOf, |
| 2062 | IrInstructionIdTestNonNull, | 2142 | IrInstructionIdTestNonNull, |
| 2063 | IrInstructionIdUnwrapOptional, | 2143 | IrInstructionIdOptionalUnwrapPtr, |
| 2064 | IrInstructionIdOptionalWrap, | 2144 | IrInstructionIdOptionalWrap, |
| 2065 | IrInstructionIdUnionTag, | 2145 | IrInstructionIdUnionTag, |
| 2066 | IrInstructionIdClz, | 2146 | IrInstructionIdClz, |
| ... | @@ -2076,7 +2156,8 @@ enum IrInstructionId { | ... | @@ -2076,7 +2156,8 @@ enum IrInstructionId { |
| 2076 | IrInstructionIdCompileLog, | 2156 | IrInstructionIdCompileLog, |
| 2077 | IrInstructionIdErrName, | 2157 | IrInstructionIdErrName, |
| 2078 | IrInstructionIdEmbedFile, | 2158 | IrInstructionIdEmbedFile, |
| 2079 | IrInstructionIdCmpxchg, | 2159 | IrInstructionIdCmpxchgSrc, |
| 2160 | IrInstructionIdCmpxchgGen, | ||
| 2080 | IrInstructionIdFence, | 2161 | IrInstructionIdFence, |
| 2081 | IrInstructionIdTruncate, | 2162 | IrInstructionIdTruncate, |
| 2082 | IrInstructionIdIntCast, | 2163 | IrInstructionIdIntCast, |
| ... | @@ -2085,6 +2166,7 @@ enum IrInstructionId { | ... | @@ -2085,6 +2166,7 @@ enum IrInstructionId { |
| 2085 | IrInstructionIdFloatToInt, | 2166 | IrInstructionIdFloatToInt, |
| 2086 | IrInstructionIdBoolToInt, | 2167 | IrInstructionIdBoolToInt, |
| 2087 | IrInstructionIdIntType, | 2168 | IrInstructionIdIntType, |
| 2169 | IrInstructionIdVectorType, | ||
| 2088 | IrInstructionIdBoolNot, | 2170 | IrInstructionIdBoolNot, |
| 2089 | IrInstructionIdMemset, | 2171 | IrInstructionIdMemset, |
| 2090 | IrInstructionIdMemcpy, | 2172 | IrInstructionIdMemcpy, |
| ... | @@ -2105,7 +2187,8 @@ enum IrInstructionId { | ... | @@ -2105,7 +2187,8 @@ enum IrInstructionId { |
| 2105 | IrInstructionIdErrWrapPayload, | 2187 | IrInstructionIdErrWrapPayload, |
| 2106 | IrInstructionIdFnProto, | 2188 | IrInstructionIdFnProto, |
| 2107 | IrInstructionIdTestComptime, | 2189 | IrInstructionIdTestComptime, |
| 2108 | IrInstructionIdPtrCast, | 2190 | IrInstructionIdPtrCastSrc, |
| 2191 | IrInstructionIdPtrCastGen, | ||
| 2109 | IrInstructionIdBitCast, | 2192 | IrInstructionIdBitCast, |
| 2110 | IrInstructionIdWidenOrShorten, | 2193 | IrInstructionIdWidenOrShorten, |
| 2111 | IrInstructionIdIntToPtr, | 2194 | IrInstructionIdIntToPtr, |
| ... | @@ -2158,10 +2241,15 @@ enum IrInstructionId { | ... | @@ -2158,10 +2241,15 @@ enum IrInstructionId { |
| 2158 | IrInstructionIdMergeErrRetTraces, | 2241 | IrInstructionIdMergeErrRetTraces, |
| 2159 | IrInstructionIdMarkErrRetTracePtr, | 2242 | IrInstructionIdMarkErrRetTracePtr, |
| 2160 | IrInstructionIdSqrt, | 2243 | IrInstructionIdSqrt, |
| 2244 | IrInstructionIdBswap, | ||
| 2245 | IrInstructionIdBitReverse, | ||
| 2161 | IrInstructionIdErrSetCast, | 2246 | IrInstructionIdErrSetCast, |
| 2162 | IrInstructionIdToBytes, | 2247 | IrInstructionIdToBytes, |
| 2163 | IrInstructionIdFromBytes, | 2248 | IrInstructionIdFromBytes, |
| 2164 | IrInstructionIdCheckRuntimeScope, | 2249 | IrInstructionIdCheckRuntimeScope, |
| 2250 | IrInstructionIdVectorToArray, | ||
| 2251 | IrInstructionIdArrayToVector, | ||
| 2252 | IrInstructionIdAssertZero, | ||
| 2165 | }; | 2253 | }; |
| 2166 | 2254 | ||
| 2167 | struct IrInstruction { | 2255 | struct IrInstruction { |
| ... | @@ -2183,6 +2271,22 @@ struct IrInstruction { | ... | @@ -2183,6 +2271,22 @@ struct IrInstruction { |
| 2183 | bool is_gen; | 2271 | bool is_gen; |
| 2184 | }; | 2272 | }; |
| 2185 | 2273 | ||
| 2274 | struct IrInstructionDeclVarSrc { | ||
| 2275 | IrInstruction base; | ||
| 2276 | |||
| 2277 | ZigVar *var; | ||
| 2278 | IrInstruction *var_type; | ||
| 2279 | IrInstruction *align_value; | ||
| 2280 | IrInstruction *init_value; | ||
| 2281 | }; | ||
| 2282 | |||
| 2283 | struct IrInstructionDeclVarGen { | ||
| 2284 | IrInstruction base; | ||
| 2285 | |||
| 2286 | ZigVar *var; | ||
| 2287 | IrInstruction *init_value; | ||
| 2288 | }; | ||
| 2289 | |||
| 2186 | struct IrInstructionCondBr { | 2290 | struct IrInstructionCondBr { |
| 2187 | IrInstruction base; | 2291 | IrInstruction base; |
| 2188 | 2292 | ||
| ... | @@ -2291,20 +2395,11 @@ struct IrInstructionBinOp { | ... | @@ -2291,20 +2395,11 @@ struct IrInstructionBinOp { |
| 2291 | IrInstruction base; | 2395 | IrInstruction base; |
| 2292 | 2396 | ||
| 2293 | IrInstruction *op1; | 2397 | IrInstruction *op1; |
| 2294 | IrBinOp op_id; | ||
| 2295 | IrInstruction *op2; | 2398 | IrInstruction *op2; |
| 2399 | IrBinOp op_id; | ||
| 2296 | bool safety_check_on; | 2400 | bool safety_check_on; |
| 2297 | }; | 2401 | }; |
| 2298 | 2402 | ||
| 2299 | struct IrInstructionDeclVar { | ||
| 2300 | IrInstruction base; | ||
| 2301 | |||
| 2302 | ZigVar *var; | ||
| 2303 | IrInstruction *var_type; | ||
| 2304 | IrInstruction *align_value; | ||
| 2305 | IrInstruction *init_value; | ||
| 2306 | }; | ||
| 2307 | |||
| 2308 | struct IrInstructionLoadPtr { | 2403 | struct IrInstructionLoadPtr { |
| 2309 | IrInstruction base; | 2404 | IrInstruction base; |
| 2310 | 2405 | ||
| ... | @@ -2324,7 +2419,6 @@ struct IrInstructionFieldPtr { | ... | @@ -2324,7 +2419,6 @@ struct IrInstructionFieldPtr { |
| 2324 | IrInstruction *container_ptr; | 2419 | IrInstruction *container_ptr; |
| 2325 | Buf *field_name_buffer; | 2420 | Buf *field_name_buffer; |
| 2326 | IrInstruction *field_name_expr; | 2421 | IrInstruction *field_name_expr; |
| 2327 | bool is_const; | ||
| 2328 | }; | 2422 | }; |
| 2329 | 2423 | ||
| 2330 | struct IrInstructionStructFieldPtr { | 2424 | struct IrInstructionStructFieldPtr { |
| ... | @@ -2367,13 +2461,13 @@ struct IrInstructionCall { | ... | @@ -2367,13 +2461,13 @@ struct IrInstructionCall { |
| 2367 | ZigFn *fn_entry; | 2461 | ZigFn *fn_entry; |
| 2368 | size_t arg_count; | 2462 | size_t arg_count; |
| 2369 | IrInstruction **args; | 2463 | IrInstruction **args; |
| 2370 | bool is_comptime; | ||
| 2371 | LLVMValueRef tmp_ptr; | 2464 | LLVMValueRef tmp_ptr; |
| 2372 | FnInline fn_inline; | ||
| 2373 | bool is_async; | ||
| 2374 | 2465 | ||
| 2375 | IrInstruction *async_allocator; | 2466 | IrInstruction *async_allocator; |
| 2376 | IrInstruction *new_stack; | 2467 | IrInstruction *new_stack; |
| 2468 | FnInline fn_inline; | ||
| 2469 | bool is_async; | ||
| 2470 | bool is_comptime; | ||
| 2377 | }; | 2471 | }; |
| 2378 | 2472 | ||
| 2379 | struct IrInstructionConst { | 2473 | struct IrInstructionConst { |
| ... | @@ -2504,6 +2598,7 @@ struct IrInstructionPtrType { | ... | @@ -2504,6 +2598,7 @@ struct IrInstructionPtrType { |
| 2504 | PtrLen ptr_len; | 2598 | PtrLen ptr_len; |
| 2505 | bool is_const; | 2599 | bool is_const; |
| 2506 | bool is_volatile; | 2600 | bool is_volatile; |
| 2601 | bool allow_zero; | ||
| 2507 | }; | 2602 | }; |
| 2508 | 2603 | ||
| 2509 | struct IrInstructionPromiseType { | 2604 | struct IrInstructionPromiseType { |
| ... | @@ -2516,9 +2611,10 @@ struct IrInstructionSliceType { | ... | @@ -2516,9 +2611,10 @@ struct IrInstructionSliceType { |
| 2516 | IrInstruction base; | 2611 | IrInstruction base; |
| 2517 | 2612 | ||
| 2518 | IrInstruction *align_value; | 2613 | IrInstruction *align_value; |
| 2614 | IrInstruction *child_type; | ||
| 2519 | bool is_const; | 2615 | bool is_const; |
| 2520 | bool is_volatile; | 2616 | bool is_volatile; |
| 2521 | IrInstruction *child_type; | 2617 | bool allow_zero; |
| 2522 | }; | 2618 | }; |
| 2523 | 2619 | ||
| 2524 | struct IrInstructionAsm { | 2620 | struct IrInstructionAsm { |
| ... | @@ -2546,10 +2642,12 @@ struct IrInstructionTestNonNull { | ... | @@ -2546,10 +2642,12 @@ struct IrInstructionTestNonNull { |
| 2546 | IrInstruction *value; | 2642 | IrInstruction *value; |
| 2547 | }; | 2643 | }; |
| 2548 | 2644 | ||
| 2549 | struct IrInstructionUnwrapOptional { | 2645 | // Takes a pointer to an optional value, returns a pointer |
| 2646 | // to the payload. | ||
| 2647 | struct IrInstructionOptionalUnwrapPtr { | ||
| 2550 | IrInstruction base; | 2648 | IrInstruction base; |
| 2551 | 2649 | ||
| 2552 | IrInstruction *value; | 2650 | IrInstruction *base_ptr; |
| 2553 | bool safety_check_on; | 2651 | bool safety_check_on; |
| 2554 | }; | 2652 | }; |
| 2555 | 2653 | ||
| ... | @@ -2640,7 +2738,7 @@ struct IrInstructionEmbedFile { | ... | @@ -2640,7 +2738,7 @@ struct IrInstructionEmbedFile { |
| 2640 | IrInstruction *name; | 2738 | IrInstruction *name; |
| 2641 | }; | 2739 | }; |
| 2642 | 2740 | ||
| 2643 | struct IrInstructionCmpxchg { | 2741 | struct IrInstructionCmpxchgSrc { |
| 2644 | IrInstruction base; | 2742 | IrInstruction base; |
| 2645 | 2743 | ||
| 2646 | IrInstruction *type_value; | 2744 | IrInstruction *type_value; |
| ... | @@ -2650,14 +2748,19 @@ struct IrInstructionCmpxchg { | ... | @@ -2650,14 +2748,19 @@ struct IrInstructionCmpxchg { |
| 2650 | IrInstruction *success_order_value; | 2748 | IrInstruction *success_order_value; |
| 2651 | IrInstruction *failure_order_value; | 2749 | IrInstruction *failure_order_value; |
| 2652 | 2750 | ||
| 2653 | // if this instruction gets to runtime then we know these values: | ||
| 2654 | ZigType *type; | ||
| 2655 | AtomicOrder success_order; | ||
| 2656 | AtomicOrder failure_order; | ||
| 2657 | |||
| 2658 | bool is_weak; | 2751 | bool is_weak; |
| 2752 | }; | ||
| 2659 | 2753 | ||
| 2754 | struct IrInstructionCmpxchgGen { | ||
| 2755 | IrInstruction base; | ||
| 2756 | |||
| 2757 | IrInstruction *ptr; | ||
| 2758 | IrInstruction *cmp_value; | ||
| 2759 | IrInstruction *new_value; | ||
| 2660 | LLVMValueRef tmp_ptr; | 2760 | LLVMValueRef tmp_ptr; |
| 2761 | AtomicOrder success_order; | ||
| 2762 | AtomicOrder failure_order; | ||
| 2763 | bool is_weak; | ||
| 2661 | }; | 2764 | }; |
| 2662 | 2765 | ||
| 2663 | struct IrInstructionFence { | 2766 | struct IrInstructionFence { |
| ... | @@ -2737,6 +2840,13 @@ struct IrInstructionIntType { | ... | @@ -2737,6 +2840,13 @@ struct IrInstructionIntType { |
| 2737 | IrInstruction *bit_count; | 2840 | IrInstruction *bit_count; |
| 2738 | }; | 2841 | }; |
| 2739 | 2842 | ||
| 2843 | struct IrInstructionVectorType { | ||
| 2844 | IrInstruction base; | ||
| 2845 | |||
| 2846 | IrInstruction *len; | ||
| 2847 | IrInstruction *elem_type; | ||
| 2848 | }; | ||
| 2849 | |||
| 2740 | struct IrInstructionBoolNot { | 2850 | struct IrInstructionBoolNot { |
| 2741 | IrInstruction base; | 2851 | IrInstruction base; |
| 2742 | 2852 | ||
| ... | @@ -2840,7 +2950,7 @@ struct IrInstructionTestErr { | ... | @@ -2840,7 +2950,7 @@ struct IrInstructionTestErr { |
| 2840 | struct IrInstructionUnwrapErrCode { | 2950 | struct IrInstructionUnwrapErrCode { |
| 2841 | IrInstruction base; | 2951 | IrInstruction base; |
| 2842 | 2952 | ||
| 2843 | IrInstruction *value; | 2953 | IrInstruction *err_union; |
| 2844 | }; | 2954 | }; |
| 2845 | 2955 | ||
| 2846 | struct IrInstructionUnwrapErrPayload { | 2956 | struct IrInstructionUnwrapErrPayload { |
| ... | @@ -2888,11 +2998,19 @@ struct IrInstructionTestComptime { | ... | @@ -2888,11 +2998,19 @@ struct IrInstructionTestComptime { |
| 2888 | IrInstruction *value; | 2998 | IrInstruction *value; |
| 2889 | }; | 2999 | }; |
| 2890 | 3000 | ||
| 2891 | struct IrInstructionPtrCast { | 3001 | struct IrInstructionPtrCastSrc { |
| 2892 | IrInstruction base; | 3002 | IrInstruction base; |
| 2893 | 3003 | ||
| 2894 | IrInstruction *dest_type; | 3004 | IrInstruction *dest_type; |
| 2895 | IrInstruction *ptr; | 3005 | IrInstruction *ptr; |
| 3006 | bool safety_check_on; | ||
| 3007 | }; | ||
| 3008 | |||
| 3009 | struct IrInstructionPtrCastGen { | ||
| 3010 | IrInstruction base; | ||
| 3011 | |||
| 3012 | IrInstruction *ptr; | ||
| 3013 | bool safety_check_on; | ||
| 2896 | }; | 3014 | }; |
| 2897 | 3015 | ||
| 2898 | struct IrInstructionBitCast { | 3016 | struct IrInstructionBitCast { |
| ... | @@ -3251,6 +3369,39 @@ struct IrInstructionCheckRuntimeScope { | ... | @@ -3251,6 +3369,39 @@ struct IrInstructionCheckRuntimeScope { |
| 3251 | IrInstruction *is_comptime; | 3369 | IrInstruction *is_comptime; |
| 3252 | }; | 3370 | }; |
| 3253 | 3371 | ||
| 3372 | struct IrInstructionBswap { | ||
| 3373 | IrInstruction base; | ||
| 3374 | |||
| 3375 | IrInstruction *type; | ||
| 3376 | IrInstruction *op; | ||
| 3377 | }; | ||
| 3378 | |||
| 3379 | struct IrInstructionBitReverse { | ||
| 3380 | IrInstruction base; | ||
| 3381 | |||
| 3382 | IrInstruction *type; | ||
| 3383 | IrInstruction *op; | ||
| 3384 | }; | ||
| 3385 | |||
| 3386 | struct IrInstructionArrayToVector { | ||
| 3387 | IrInstruction base; | ||
| 3388 | |||
| 3389 | IrInstruction *array; | ||
| 3390 | }; | ||
| 3391 | |||
| 3392 | struct IrInstructionVectorToArray { | ||
| 3393 | IrInstruction base; | ||
| 3394 | |||
| 3395 | IrInstruction *vector; | ||
| 3396 | LLVMValueRef tmp_ptr; | ||
| 3397 | }; | ||
| 3398 | |||
| 3399 | struct IrInstructionAssertZero { | ||
| 3400 | IrInstruction base; | ||
| 3401 | |||
| 3402 | IrInstruction *target; | ||
| 3403 | }; | ||
| 3404 | |||
| 3254 | static const size_t slice_ptr_index = 0; | 3405 | static const size_t slice_ptr_index = 0; |
| 3255 | static const size_t slice_len_index = 1; | 3406 | static const size_t slice_len_index = 1; |
| 3256 | 3407 |
src/analyze.cpp+651-268| ... | @@ -28,28 +28,10 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum | ... | @@ -28,28 +28,10 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum |
| 28 | static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type); | 28 | static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type); |
| 29 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); | 29 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); |
| 30 | 30 | ||
| 31 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | 31 | static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ImportTableEntry *owner, Token *token, |
| 32 | if (node->owner->c_import_node != nullptr) { | 32 | Buf *msg) |
| 33 | // if this happens, then translate_c generated code that | 33 | { |
| 34 | // failed semantic analysis, which isn't supposed to happen | 34 | if (owner->c_import_node != nullptr) { |
| 35 | ErrorMsg *err = add_node_error(g, node->owner->c_import_node, | ||
| 36 | buf_sprintf("compiler bug: @cImport generated invalid zig code")); | ||
| 37 | |||
| 38 | add_error_note(g, err, node, msg); | ||
| 39 | |||
| 40 | g->errors.append(err); | ||
| 41 | return err; | ||
| 42 | } | ||
| 43 | |||
| 44 | ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column, | ||
| 45 | node->owner->source_code, node->owner->line_offsets, msg); | ||
| 46 | |||
| 47 | g->errors.append(err); | ||
| 48 | return err; | ||
| 49 | } | ||
| 50 | |||
| 51 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) { | ||
| 52 | if (node->owner->c_import_node != nullptr) { | ||
| 53 | // if this happens, then translate_c generated code that | 35 | // if this happens, then translate_c generated code that |
| 54 | // failed semantic analysis, which isn't supposed to happen | 36 | // failed semantic analysis, which isn't supposed to happen |
| 55 | 37 | ||
| ... | @@ -64,13 +46,46 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m | ... | @@ -64,13 +46,46 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m |
| 64 | return note; | 46 | return note; |
| 65 | } | 47 | } |
| 66 | 48 | ||
| 67 | ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column, | 49 | ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column, |
| 68 | node->owner->source_code, node->owner->line_offsets, msg); | 50 | owner->source_code, owner->line_offsets, msg); |
| 69 | 51 | ||
| 70 | err_msg_add_note(parent_msg, err); | 52 | err_msg_add_note(parent_msg, err); |
| 71 | return err; | 53 | return err; |
| 72 | } | 54 | } |
| 73 | 55 | ||
| 56 | ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg) { | ||
| 57 | if (owner->c_import_node != nullptr) { | ||
| 58 | // if this happens, then translate_c generated code that | ||
| 59 | // failed semantic analysis, which isn't supposed to happen | ||
| 60 | ErrorMsg *err = add_node_error(g, owner->c_import_node, | ||
| 61 | buf_sprintf("compiler bug: @cImport generated invalid zig code")); | ||
| 62 | |||
| 63 | add_error_note_token(g, err, owner, token, msg); | ||
| 64 | |||
| 65 | g->errors.append(err); | ||
| 66 | return err; | ||
| 67 | } | ||
| 68 | ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column, | ||
| 69 | owner->source_code, owner->line_offsets, msg); | ||
| 70 | |||
| 71 | g->errors.append(err); | ||
| 72 | return err; | ||
| 73 | } | ||
| 74 | |||
| 75 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | ||
| 76 | Token fake_token; | ||
| 77 | fake_token.start_line = node->line; | ||
| 78 | fake_token.start_column = node->column; | ||
| 79 | return add_token_error(g, node->owner, &fake_token, msg); | ||
| 80 | } | ||
| 81 | |||
| 82 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) { | ||
| 83 | Token fake_token; | ||
| 84 | fake_token.start_line = node->line; | ||
| 85 | fake_token.start_column = node->column; | ||
| 86 | return add_error_note_token(g, parent_msg, node->owner, &fake_token, msg); | ||
| 87 | } | ||
| 88 | |||
| 74 | ZigType *new_type_table_entry(ZigTypeId id) { | 89 | ZigType *new_type_table_entry(ZigTypeId id) { |
| 75 | ZigType *entry = allocate<ZigType>(1); | 90 | ZigType *entry = allocate<ZigType>(1); |
| 76 | entry->id = id; | 91 | entry->id = id; |
| ... | @@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) { | ... | @@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) { |
| 250 | case ZigTypeIdBoundFn: | 265 | case ZigTypeIdBoundFn: |
| 251 | case ZigTypeIdArgTuple: | 266 | case ZigTypeIdArgTuple: |
| 252 | case ZigTypeIdPromise: | 267 | case ZigTypeIdPromise: |
| 268 | case ZigTypeIdVector: | ||
| 253 | return nullptr; | 269 | return nullptr; |
| 254 | } | 270 | } |
| 255 | zig_unreachable(); | 271 | zig_unreachable(); |
| ... | @@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { | ... | @@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { |
| 311 | case ZigTypeIdBoundFn: | 327 | case ZigTypeIdBoundFn: |
| 312 | case ZigTypeIdArgTuple: | 328 | case ZigTypeIdArgTuple: |
| 313 | case ZigTypeIdPromise: | 329 | case ZigTypeIdPromise: |
| 330 | case ZigTypeIdVector: | ||
| 314 | return true; | 331 | return true; |
| 315 | } | 332 | } |
| 316 | zig_unreachable(); | 333 | zig_unreachable(); |
| ... | @@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) { | ... | @@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) { |
| 339 | } | 356 | } |
| 340 | } | 357 | } |
| 341 | 358 | ||
| 359 | return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); | ||
| 360 | } | ||
| 361 | |||
| 362 | uint64_t type_size_store(CodeGen *g, ZigType *type_entry) { | ||
| 363 | assert(type_is_complete(type_entry)); | ||
| 364 | |||
| 365 | if (!type_has_bits(type_entry)) | ||
| 366 | return 0; | ||
| 367 | |||
| 368 | if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) { | ||
| 369 | uint64_t size_in_bits = type_size_bits(g, type_entry); | ||
| 370 | return (size_in_bits + 7) / 8; | ||
| 371 | } else if (type_entry->id == ZigTypeIdArray) { | ||
| 372 | ZigType *child_type = type_entry->data.array.child_type; | ||
| 373 | if (child_type->id == ZigTypeIdStruct && | ||
| 374 | child_type->data.structure.layout == ContainerLayoutPacked) | ||
| 375 | { | ||
| 376 | uint64_t size_in_bits = type_size_bits(g, type_entry); | ||
| 377 | return (size_in_bits + 7) / 8; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 342 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); | 381 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); |
| 343 | } | 382 | } |
| 344 | 383 | ||
| ... | @@ -400,9 +439,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { | ... | @@ -400,9 +439,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { |
| 400 | return entry; | 439 | return entry; |
| 401 | } | 440 | } |
| 402 | 441 | ||
| 442 | static const char *ptr_len_to_star_str(PtrLen ptr_len) { | ||
| 443 | switch (ptr_len) { | ||
| 444 | case PtrLenSingle: | ||
| 445 | return "*"; | ||
| 446 | case PtrLenUnknown: | ||
| 447 | return "[*]"; | ||
| 448 | case PtrLenC: | ||
| 449 | return "[*c]"; | ||
| 450 | } | ||
| 451 | zig_unreachable(); | ||
| 452 | } | ||
| 453 | |||
| 403 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 454 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 404 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes) | 455 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, |
| 456 | uint32_t bit_offset_in_host, uint32_t host_int_bytes) | ||
| 405 | { | 457 | { |
| 458 | // TODO when implementing https://github.com/ziglang/zig/issues/1953 | ||
| 459 | // move this to a parameter | ||
| 460 | bool allow_zero = (ptr_len == PtrLenC); | ||
| 406 | assert(!type_is_invalid(child_type)); | 461 | assert(!type_is_invalid(child_type)); |
| 407 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); | 462 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); |
| 408 | 463 | ||
| ... | @@ -422,7 +477,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -422,7 +477,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 422 | 477 | ||
| 423 | TypeId type_id = {}; | 478 | TypeId type_id = {}; |
| 424 | ZigType **parent_pointer = nullptr; | 479 | ZigType **parent_pointer = nullptr; |
| 425 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { | 480 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) { |
| 426 | type_id.id = ZigTypeIdPointer; | 481 | type_id.id = ZigTypeIdPointer; |
| 427 | type_id.data.pointer.child_type = child_type; | 482 | type_id.data.pointer.child_type = child_type; |
| 428 | type_id.data.pointer.is_const = is_const; | 483 | type_id.data.pointer.is_const = is_const; |
| ... | @@ -431,6 +486,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -431,6 +486,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 431 | type_id.data.pointer.bit_offset_in_host = bit_offset_in_host; | 486 | type_id.data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 432 | type_id.data.pointer.host_int_bytes = host_int_bytes; | 487 | type_id.data.pointer.host_int_bytes = host_int_bytes; |
| 433 | type_id.data.pointer.ptr_len = ptr_len; | 488 | type_id.data.pointer.ptr_len = ptr_len; |
| 489 | type_id.data.pointer.allow_zero = allow_zero; | ||
| 434 | 490 | ||
| 435 | auto existing_entry = g->type_table.maybe_get(type_id); | 491 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 436 | if (existing_entry) | 492 | if (existing_entry) |
| ... | @@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 448 | 504 | ||
| 449 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); | 505 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); |
| 450 | 506 | ||
| 451 | const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]"; | 507 | const char *star_str = ptr_len_to_star_str(ptr_len); |
| 452 | const char *const_str = is_const ? "const " : ""; | 508 | const char *const_str = is_const ? "const " : ""; |
| 453 | const char *volatile_str = is_volatile ? "volatile " : ""; | 509 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| 510 | const char *allow_zero_str; | ||
| 511 | if (ptr_len == PtrLenC) { | ||
| 512 | assert(allow_zero); | ||
| 513 | allow_zero_str = ""; | ||
| 514 | } else { | ||
| 515 | allow_zero_str = allow_zero ? "allowzero " : ""; | ||
| 516 | } | ||
| 454 | buf_resize(&entry->name, 0); | 517 | buf_resize(&entry->name, 0); |
| 455 | if (host_int_bytes == 0 && byte_alignment == 0) { | 518 | if (host_int_bytes == 0 && byte_alignment == 0) { |
| 456 | buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name)); | 519 | buf_appendf(&entry->name, "%s%s%s%s%s", |
| 520 | star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); | ||
| 457 | } else if (host_int_bytes == 0) { | 521 | } else if (host_int_bytes == 0) { |
| 458 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment, | 522 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, |
| 459 | const_str, volatile_str, buf_ptr(&child_type->name)); | 523 | const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); |
| 460 | } else if (byte_alignment == 0) { | 524 | } else if (byte_alignment == 0) { |
| 461 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, | 525 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, |
| 462 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); | 526 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, |
| 527 | buf_ptr(&child_type->name)); | ||
| 463 | } else { | 528 | } else { |
| 464 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment, | 529 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, |
| 465 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); | 530 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str, |
| 531 | buf_ptr(&child_type->name)); | ||
| 466 | } | 532 | } |
| 467 | 533 | ||
| 468 | assert(child_type->id != ZigTypeIdInvalid); | 534 | assert(child_type->id != ZigTypeIdInvalid); |
| ... | @@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 470 | entry->zero_bits = !type_has_bits(child_type); | 536 | entry->zero_bits = !type_has_bits(child_type); |
| 471 | 537 | ||
| 472 | if (!entry->zero_bits) { | 538 | if (!entry->zero_bits) { |
| 473 | if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) { | 539 | if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || |
| 540 | bit_offset_in_host != 0 || allow_zero) | ||
| 541 | { | ||
| 474 | ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false, | 542 | ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false, |
| 475 | PtrLenSingle, 0, 0, host_int_bytes); | 543 | PtrLenSingle, 0, 0, host_int_bytes); |
| 476 | entry->type_ref = peer_type->type_ref; | 544 | entry->type_ref = peer_type->type_ref; |
| ... | @@ -504,6 +572,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -504,6 +572,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 504 | entry->data.pointer.explicit_alignment = byte_alignment; | 572 | entry->data.pointer.explicit_alignment = byte_alignment; |
| 505 | entry->data.pointer.bit_offset_in_host = bit_offset_in_host; | 573 | entry->data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 506 | entry->data.pointer.host_int_bytes = host_int_bytes; | 574 | entry->data.pointer.host_int_bytes = host_int_bytes; |
| 575 | entry->data.pointer.allow_zero = allow_zero; | ||
| 507 | 576 | ||
| 508 | if (parent_pointer) { | 577 | if (parent_pointer) { |
| 509 | *parent_pointer = entry; | 578 | *parent_pointer = entry; |
| ... | @@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { | ... | @@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { |
| 569 | if (child_type->zero_bits) { | 638 | if (child_type->zero_bits) { |
| 570 | entry->type_ref = LLVMInt1Type(); | 639 | entry->type_ref = LLVMInt1Type(); |
| 571 | entry->di_type = g->builtin_types.entry_bool->di_type; | 640 | entry->di_type = g->builtin_types.entry_bool->di_type; |
| 572 | } else if (type_is_codegen_pointer(child_type)) { | 641 | } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { |
| 573 | assert(child_type->di_type); | 642 | assert(child_type->di_type); |
| 574 | // this is an optimization but also is necessary for calling C | 643 | // this is an optimization but also is necessary for calling C |
| 575 | // functions where all pointers are maybe pointers | 644 | // functions where all pointers are maybe pointers |
| 576 | // function types are technically pointers | 645 | // function types are technically pointers |
| 577 | entry->type_ref = child_type->type_ref; | 646 | entry->type_ref = child_type->type_ref; |
| 578 | entry->di_type = child_type->di_type; | 647 | entry->di_type = child_type->di_type; |
| 648 | if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) { | ||
| 649 | g->error_di_types.append(&entry->di_type); | ||
| 650 | } | ||
| 579 | } else { | 651 | } else { |
| 580 | assert(child_type->di_type); | 652 | assert(child_type->di_type); |
| 581 | // create a struct with a boolean whether this is the null value | 653 | // create a struct with a boolean whether this is the null value |
| ... | @@ -817,7 +889,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { | ... | @@ -817,7 +889,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 817 | 889 | ||
| 818 | ZigType *child_type = ptr_type->data.pointer.child_type; | 890 | ZigType *child_type = ptr_type->data.pointer.child_type; |
| 819 | if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || | 891 | if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || |
| 820 | ptr_type->data.pointer.explicit_alignment != 0) | 892 | ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero) |
| 821 | { | 893 | { |
| 822 | ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, | 894 | ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, |
| 823 | PtrLenUnknown, 0, 0, 0); | 895 | PtrLenUnknown, 0, 0, 0); |
| ... | @@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { | ... | @@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 840 | ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; | 912 | ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; |
| 841 | assert(child_ptr_type->id == ZigTypeIdPointer); | 913 | assert(child_ptr_type->id == ZigTypeIdPointer); |
| 842 | if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || | 914 | if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || |
| 843 | child_ptr_type->data.pointer.explicit_alignment != 0) | 915 | child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero) |
| 844 | { | 916 | { |
| 845 | ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; | 917 | ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; |
| 846 | ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false, | 918 | ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false, |
| ... | @@ -1054,11 +1126,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -1054,11 +1126,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 1054 | } | 1126 | } |
| 1055 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { | 1127 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { |
| 1056 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); | 1128 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); |
| 1057 | if (abi_class == X64CABIClass_MEMORY) { | 1129 | return abi_class == X64CABIClass_MEMORY; |
| 1058 | return true; | ||
| 1059 | } | ||
| 1060 | zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481", | ||
| 1061 | buf_ptr(&fn_type_id->return_type->name)); | ||
| 1062 | } else if (target_is_arm(&g->zig_target)) { | 1130 | } else if (target_is_arm(&g->zig_target)) { |
| 1063 | return type_size(g, fn_type_id->return_type) > 16; | 1131 | return type_size(g, fn_type_id->return_type) > 16; |
| 1064 | } | 1132 | } |
| ... | @@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1219 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, | 1287 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, |
| 1220 | gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); | 1288 | gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); |
| 1221 | fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); | 1289 | fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); |
| 1222 | fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); | 1290 | fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); |
| 1291 | fn_type->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type, | ||
| 1292 | LLVMStoreSizeOfType(g->target_data_ref, fn_type->type_ref), | ||
| 1293 | LLVMABIAlignmentOfType(g->target_data_ref, fn_type->type_ref), ""); | ||
| 1223 | } | 1294 | } |
| 1224 | 1295 | ||
| 1225 | g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); | 1296 | g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); |
| ... | @@ -1274,20 +1345,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind | ... | @@ -1274,20 +1345,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind |
| 1274 | return entry; | 1345 | return entry; |
| 1275 | } | 1346 | } |
| 1276 | 1347 | ||
| 1277 | static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) { | 1348 | static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, |
| 1349 | Buf *type_name) | ||
| 1350 | { | ||
| 1278 | size_t backward_branch_count = 0; | 1351 | size_t backward_branch_count = 0; |
| 1279 | return ir_eval_const_value(g, scope, node, type_entry, | 1352 | return ir_eval_const_value(g, scope, node, type_entry, |
| 1280 | &backward_branch_count, default_backward_branch_quota, | 1353 | &backward_branch_count, default_backward_branch_quota, |
| 1281 | nullptr, nullptr, node, type_name, nullptr); | 1354 | nullptr, nullptr, node, type_name, nullptr, nullptr); |
| 1282 | } | 1355 | } |
| 1283 | 1356 | ||
| 1284 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { | 1357 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| 1285 | IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); | 1358 | ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); |
| 1286 | if (result->value.type->id == ZigTypeIdInvalid) | 1359 | if (type_is_invalid(result->type)) |
| 1287 | return g->builtin_types.entry_invalid; | 1360 | return g->builtin_types.entry_invalid; |
| 1288 | 1361 | ||
| 1289 | assert(result->value.special != ConstValSpecialRuntime); | 1362 | assert(result->special != ConstValSpecialRuntime); |
| 1290 | return result->value.data.x_type; | 1363 | return result->data.x_type; |
| 1291 | } | 1364 | } |
| 1292 | 1365 | ||
| 1293 | ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | 1366 | ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| ... | @@ -1338,11 +1411,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou | ... | @@ -1338,11 +1411,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou |
| 1338 | } | 1411 | } |
| 1339 | 1412 | ||
| 1340 | static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { | 1413 | static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { |
| 1341 | IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); | 1414 | ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); |
| 1342 | if (type_is_invalid(align_result->value.type)) | 1415 | if (type_is_invalid(align_result->type)) |
| 1343 | return false; | 1416 | return false; |
| 1344 | 1417 | ||
| 1345 | uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); | 1418 | uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint); |
| 1346 | if (align_bytes == 0) { | 1419 | if (align_bytes == 0) { |
| 1347 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); | 1420 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); |
| 1348 | return false; | 1421 | return false; |
| ... | @@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** | ... | @@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1360 | ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, | 1433 | ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, |
| 1361 | PtrLenUnknown, 0, 0, 0); | 1434 | PtrLenUnknown, 0, 0, 0); |
| 1362 | ZigType *str_type = get_slice_type(g, ptr_type); | 1435 | ZigType *str_type = get_slice_type(g, ptr_type); |
| 1363 | IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr); | 1436 | ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr); |
| 1364 | if (type_is_invalid(instr->value.type)) | 1437 | if (type_is_invalid(result_val->type)) |
| 1365 | return false; | 1438 | return false; |
| 1366 | 1439 | ||
| 1367 | ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index]; | 1440 | ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index]; |
| 1368 | ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index]; | 1441 | ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index]; |
| 1369 | 1442 | ||
| 1370 | assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); | 1443 | assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); |
| 1371 | ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; | 1444 | ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; |
| ... | @@ -1418,6 +1491,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { | ... | @@ -1418,6 +1491,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { |
| 1418 | case ZigTypeIdPointer: | 1491 | case ZigTypeIdPointer: |
| 1419 | case ZigTypeIdArray: | 1492 | case ZigTypeIdArray: |
| 1420 | case ZigTypeIdFn: | 1493 | case ZigTypeIdFn: |
| 1494 | case ZigTypeIdVector: | ||
| 1421 | return true; | 1495 | return true; |
| 1422 | case ZigTypeIdStruct: | 1496 | case ZigTypeIdStruct: |
| 1423 | return type_entry->data.structure.layout == ContainerLayoutPacked; | 1497 | return type_entry->data.structure.layout == ContainerLayoutPacked; |
| ... | @@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { | ... | @@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { |
| 1434 | zig_unreachable(); | 1508 | zig_unreachable(); |
| 1435 | } | 1509 | } |
| 1436 | 1510 | ||
| 1437 | static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | 1511 | bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1438 | switch (type_entry->id) { | 1512 | switch (type_entry->id) { |
| 1439 | case ZigTypeIdInvalid: | 1513 | case ZigTypeIdInvalid: |
| 1440 | zig_unreachable(); | 1514 | zig_unreachable(); |
| ... | @@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | ... | @@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1466 | default: | 1540 | default: |
| 1467 | return false; | 1541 | return false; |
| 1468 | } | 1542 | } |
| 1543 | case ZigTypeIdVector: | ||
| 1544 | return type_allowed_in_extern(g, type_entry->data.vector.elem_type); | ||
| 1469 | case ZigTypeIdFloat: | 1545 | case ZigTypeIdFloat: |
| 1470 | return true; | 1546 | return true; |
| 1471 | case ZigTypeIdArray: | 1547 | case ZigTypeIdArray: |
| ... | @@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1619 | case ZigTypeIdUnion: | 1695 | case ZigTypeIdUnion: |
| 1620 | case ZigTypeIdFn: | 1696 | case ZigTypeIdFn: |
| 1621 | case ZigTypeIdPromise: | 1697 | case ZigTypeIdPromise: |
| 1698 | case ZigTypeIdVector: | ||
| 1622 | switch (type_requires_comptime(g, type_entry)) { | 1699 | switch (type_requires_comptime(g, type_entry)) { |
| 1623 | case ReqCompTimeNo: | 1700 | case ReqCompTimeNo: |
| 1624 | break; | 1701 | break; |
| ... | @@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1714 | case ZigTypeIdUnion: | 1791 | case ZigTypeIdUnion: |
| 1715 | case ZigTypeIdFn: | 1792 | case ZigTypeIdFn: |
| 1716 | case ZigTypeIdPromise: | 1793 | case ZigTypeIdPromise: |
| 1794 | case ZigTypeIdVector: | ||
| 1717 | switch (type_requires_comptime(g, fn_type_id.return_type)) { | 1795 | switch (type_requires_comptime(g, fn_type_id.return_type)) { |
| 1718 | case ReqCompTimeInvalid: | 1796 | case ReqCompTimeInvalid: |
| 1719 | return g->builtin_types.entry_invalid; | 1797 | return g->builtin_types.entry_invalid; |
| ... | @@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2500 | // In this first pass we resolve explicit tag values. | 2578 | // In this first pass we resolve explicit tag values. |
| 2501 | // In a second pass we will fill in the unspecified ones. | 2579 | // In a second pass we will fill in the unspecified ones. |
| 2502 | if (tag_value != nullptr) { | 2580 | if (tag_value != nullptr) { |
| 2503 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | 2581 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| 2504 | if (result_inst->value.type->id == ZigTypeIdInvalid) { | 2582 | if (type_is_invalid(result->type)) { |
| 2505 | enum_type->data.enumeration.is_invalid = true; | 2583 | enum_type->data.enumeration.is_invalid = true; |
| 2506 | continue; | 2584 | continue; |
| 2507 | } | 2585 | } |
| 2508 | assert(result_inst->value.special != ConstValSpecialRuntime); | 2586 | assert(result->special != ConstValSpecialRuntime); |
| 2509 | assert(result_inst->value.type->id == ZigTypeIdInt || | 2587 | assert(result->type->id == ZigTypeIdInt || |
| 2510 | result_inst->value.type->id == ZigTypeIdComptimeInt); | 2588 | result->type->id == ZigTypeIdComptimeInt); |
| 2511 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | 2589 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); |
| 2512 | if (entry == nullptr) { | 2590 | if (entry == nullptr) { |
| 2513 | bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint); | 2591 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); |
| 2514 | } else { | 2592 | } else { |
| 2515 | Buf *val_buf = buf_alloc(); | 2593 | Buf *val_buf = buf_alloc(); |
| 2516 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | 2594 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); |
| 2517 | 2595 | ||
| 2518 | ErrorMsg *msg = add_node_error(g, tag_value, | 2596 | ErrorMsg *msg = add_node_error(g, tag_value, |
| 2519 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | 2597 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| ... | @@ -2623,6 +2701,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2623,6 +2701,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2623 | buf_sprintf("enums, not structs, support field assignment")); | 2701 | buf_sprintf("enums, not structs, support field assignment")); |
| 2624 | } | 2702 | } |
| 2625 | 2703 | ||
| 2704 | if (field_type->id == ZigTypeIdOpaque) { | ||
| 2705 | add_node_error(g, field_node->data.struct_field.type, | ||
| 2706 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); | ||
| 2707 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2708 | continue; | ||
| 2709 | } | ||
| 2710 | |||
| 2626 | switch (type_requires_comptime(g, field_type)) { | 2711 | switch (type_requires_comptime(g, field_type)) { |
| 2627 | case ReqCompTimeYes: | 2712 | case ReqCompTimeYes: |
| 2628 | struct_type->data.structure.requires_comptime = true; | 2713 | struct_type->data.structure.requires_comptime = true; |
| ... | @@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2680 | assert(decl_node->type == NodeTypeContainerDecl); | 2765 | assert(decl_node->type == NodeTypeContainerDecl); |
| 2681 | assert(struct_type->di_type); | 2766 | assert(struct_type->di_type); |
| 2682 | 2767 | ||
| 2768 | size_t field_count = struct_type->data.structure.src_field_count; | ||
| 2683 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | 2769 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2684 | struct_type->data.structure.abi_alignment = 1; | 2770 | struct_type->data.structure.abi_alignment = 1; |
| 2685 | } | 2771 | for (size_t i = 0; i < field_count; i += 1) { |
| 2686 | 2772 | TypeStructField *field = &struct_type->data.structure.fields[i]; | |
| 2687 | size_t field_count = struct_type->data.structure.src_field_count; | 2773 | if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { |
| 2688 | for (size_t i = 0; i < field_count; i += 1) { | 2774 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2689 | TypeStructField *field = &struct_type->data.structure.fields[i]; | 2775 | break; |
| 2690 | 2776 | } | |
| 2691 | // If this assertion trips, look up the call stack. Probably something is | ||
| 2692 | // calling type_resolve with ResolveStatusAlignmentKnown when it should only | ||
| 2693 | // be resolving ResolveStatusZeroBitsKnown | ||
| 2694 | assert(field->type_entry != nullptr); | ||
| 2695 | |||
| 2696 | if (type_is_invalid(field->type_entry)) { | ||
| 2697 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2698 | break; | ||
| 2699 | } | 2777 | } |
| 2778 | } else for (size_t i = 0; i < field_count; i += 1) { | ||
| 2779 | TypeStructField *field = &struct_type->data.structure.fields[i]; | ||
| 2780 | uint32_t this_field_align; | ||
| 2781 | |||
| 2782 | // TODO If we have no type_entry for the field, we've already failed to | ||
| 2783 | // compile the program correctly. This stage1 compiler needs a deeper | ||
| 2784 | // reworking to make this correct, or we can ignore the problem | ||
| 2785 | // and make sure it is fixed in stage2. This workaround is for when | ||
| 2786 | // there is a false positive of a dependency loop, of alignment depending | ||
| 2787 | // on itself. When this false positive happens we assume a pointer-aligned | ||
| 2788 | // field, which is usually fine but could be incorrectly over-aligned or | ||
| 2789 | // even under-aligned. See https://github.com/ziglang/zig/issues/1512 | ||
| 2790 | if (field->type_entry == nullptr) { | ||
| 2791 | this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); | ||
| 2792 | } else { | ||
| 2793 | if (type_is_invalid(field->type_entry)) { | ||
| 2794 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2795 | break; | ||
| 2796 | } | ||
| 2700 | 2797 | ||
| 2701 | if (!type_has_bits(field->type_entry)) | 2798 | if (!type_has_bits(field->type_entry)) |
| 2702 | continue; | 2799 | continue; |
| 2703 | 2800 | ||
| 2704 | // alignment of structs is the alignment of the most-aligned field | ||
| 2705 | if (struct_type->data.structure.layout != ContainerLayoutPacked) { | ||
| 2706 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { | 2801 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { |
| 2707 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2802 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2708 | break; | 2803 | break; |
| 2709 | } | 2804 | } |
| 2710 | 2805 | ||
| 2711 | uint32_t this_field_align = get_abi_alignment(g, field->type_entry); | 2806 | this_field_align = get_abi_alignment(g, field->type_entry); |
| 2712 | assert(this_field_align != 0); | 2807 | assert(this_field_align != 0); |
| 2713 | if (this_field_align > struct_type->data.structure.abi_alignment) { | 2808 | } |
| 2714 | struct_type->data.structure.abi_alignment = this_field_align; | 2809 | // alignment of structs is the alignment of the most-aligned field |
| 2715 | } | 2810 | if (this_field_align > struct_type->data.structure.abi_alignment) { |
| 2811 | struct_type->data.structure.abi_alignment = this_field_align; | ||
| 2716 | } | 2812 | } |
| 2717 | } | 2813 | } |
| 2718 | 2814 | ||
| ... | @@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { | ... | @@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 2790 | union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum || | 2886 | union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum || |
| 2791 | enum_type_node != nullptr; | 2887 | enum_type_node != nullptr; |
| 2792 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | 2888 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); |
| 2793 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); | 2889 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease); |
| 2794 | ZigType *tag_type; | 2890 | ZigType *tag_type; |
| 2795 | bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); | 2891 | bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); |
| 2796 | bool *covered_enum_fields; | 2892 | bool *covered_enum_fields; |
| ... | @@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { | ... | @@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 2896 | } | 2992 | } |
| 2897 | union_field->type_entry = field_type; | 2993 | union_field->type_entry = field_type; |
| 2898 | 2994 | ||
| 2995 | if (field_type->id == ZigTypeIdOpaque) { | ||
| 2996 | add_node_error(g, field_node->data.struct_field.type, | ||
| 2997 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions")); | ||
| 2998 | union_type->data.unionation.is_invalid = true; | ||
| 2999 | continue; | ||
| 3000 | } | ||
| 3001 | |||
| 2899 | switch (type_requires_comptime(g, field_type)) { | 3002 | switch (type_requires_comptime(g, field_type)) { |
| 2900 | case ReqCompTimeInvalid: | 3003 | case ReqCompTimeInvalid: |
| 2901 | union_type->data.unionation.is_invalid = true; | 3004 | union_type->data.unionation.is_invalid = true; |
| ... | @@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { | ... | @@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 2929 | // In a second pass we will fill in the unspecified ones. | 3032 | // In a second pass we will fill in the unspecified ones. |
| 2930 | if (tag_value != nullptr) { | 3033 | if (tag_value != nullptr) { |
| 2931 | ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; | 3034 | ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; |
| 2932 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | 3035 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| 2933 | if (result_inst->value.type->id == ZigTypeIdInvalid) { | 3036 | if (type_is_invalid(result->type)) { |
| 2934 | union_type->data.unionation.is_invalid = true; | 3037 | union_type->data.unionation.is_invalid = true; |
| 2935 | continue; | 3038 | continue; |
| 2936 | } | 3039 | } |
| 2937 | assert(result_inst->value.special != ConstValSpecialRuntime); | 3040 | assert(result->special != ConstValSpecialRuntime); |
| 2938 | assert(result_inst->value.type->id == ZigTypeIdInt); | 3041 | assert(result->type->id == ZigTypeIdInt); |
| 2939 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | 3042 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); |
| 2940 | if (entry == nullptr) { | 3043 | if (entry == nullptr) { |
| 2941 | bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); | 3044 | bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint); |
| 2942 | } else { | 3045 | } else { |
| 2943 | Buf *val_buf = buf_alloc(); | 3046 | Buf *val_buf = buf_alloc(); |
| 2944 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | 3047 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); |
| 2945 | 3048 | ||
| 2946 | ErrorMsg *msg = add_node_error(g, tag_value, | 3049 | ErrorMsg *msg = add_node_error(g, tag_value, |
| 2947 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | 3050 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| ... | @@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) { | ... | @@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) { |
| 3144 | zig_unreachable(); | 3247 | zig_unreachable(); |
| 3145 | } | 3248 | } |
| 3146 | 3249 | ||
| 3147 | static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) { | 3250 | void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) { |
| 3148 | add_node_error(g, proto_node, | 3251 | ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn"); |
| 3149 | buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'", | 3252 | assert(panic_fn_type_val != nullptr); |
| 3150 | buf_ptr(&fn_type->name))); | 3253 | assert(panic_fn_type_val->type->id == ZigTypeIdMetaType); |
| 3151 | } | 3254 | ZigType *panic_fn_type = panic_fn_type_val->data.x_type; |
| 3152 | |||
| 3153 | static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) { | ||
| 3154 | AstNode *proto_node = panic_fn->proto_node; | ||
| 3155 | assert(proto_node->type == NodeTypeFnProto); | ||
| 3156 | ZigType *fn_type = panic_fn->type_entry; | ||
| 3157 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | ||
| 3158 | if (fn_type_id->param_count != 2) { | ||
| 3159 | return wrong_panic_prototype(g, proto_node, fn_type); | ||
| 3160 | } | ||
| 3161 | ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, | ||
| 3162 | PtrLenUnknown, 0, 0, 0); | ||
| 3163 | ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr); | ||
| 3164 | if (fn_type_id->param_info[0].type != const_u8_slice) { | ||
| 3165 | return wrong_panic_prototype(g, proto_node, fn_type); | ||
| 3166 | } | ||
| 3167 | 3255 | ||
| 3168 | ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g)); | 3256 | AstNode *fake_decl = allocate<AstNode>(1); |
| 3169 | if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) { | 3257 | *fake_decl = *panic_fn->proto_node; |
| 3170 | return wrong_panic_prototype(g, proto_node, fn_type); | 3258 | fake_decl->type = NodeTypeSymbol; |
| 3171 | } | 3259 | fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name; |
| 3172 | 3260 | ||
| 3173 | ZigType *actual_return_type = fn_type_id->return_type; | 3261 | // call this for the side effects of casting to panic_fn_type |
| 3174 | if (actual_return_type != g->builtin_types.entry_unreachable) { | 3262 | analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr); |
| 3175 | return wrong_panic_prototype(g, proto_node, fn_type); | ||
| 3176 | } | ||
| 3177 | } | 3263 | } |
| 3178 | 3264 | ||
| 3179 | ZigType *get_test_fn_type(CodeGen *g) { | 3265 | ZigType *get_test_fn_type(CodeGen *g) { |
| ... | @@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi | ... | @@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi |
| 3191 | if (ccc) { | 3277 | if (ccc) { |
| 3192 | if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { | 3278 | if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { |
| 3193 | g->have_c_main = true; | 3279 | g->have_c_main = true; |
| 3194 | g->windows_subsystem_windows = false; | 3280 | g->subsystem = TargetSubsystemConsole; |
| 3195 | g->windows_subsystem_console = true; | ||
| 3196 | } else if (buf_eql_str(symbol_name, "WinMain") && | 3281 | } else if (buf_eql_str(symbol_name, "WinMain") && |
| 3197 | g->zig_target.os == OsWindows) | 3282 | g->zig_target.os == OsWindows) |
| 3198 | { | 3283 | { |
| 3199 | g->have_winmain = true; | 3284 | g->have_winmain = true; |
| 3200 | g->windows_subsystem_windows = true; | 3285 | g->subsystem = TargetSubsystemWindows; |
| 3201 | g->windows_subsystem_console = false; | ||
| 3202 | } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && | 3286 | } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && |
| 3203 | g->zig_target.os == OsWindows) | 3287 | g->zig_target.os == OsWindows) |
| 3204 | { | 3288 | { |
| ... | @@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi | ... | @@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi |
| 3209 | g->have_dllmain_crt_startup = true; | 3293 | g->have_dllmain_crt_startup = true; |
| 3210 | } | 3294 | } |
| 3211 | } | 3295 | } |
| 3296 | |||
| 3212 | FnExport *fn_export = fn_table_entry->export_list.add_one(); | 3297 | FnExport *fn_export = fn_table_entry->export_list.add_one(); |
| 3213 | memset(fn_export, 0, sizeof(FnExport)); | 3298 | memset(fn_export, 0, sizeof(FnExport)); |
| 3214 | buf_init_from_buf(&fn_export->name, symbol_name); | 3299 | buf_init_from_buf(&fn_export->name, symbol_name); |
| ... | @@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { | ... | @@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3269 | if (!fn_table_entry->type_entry->data.fn.is_generic) { | 3354 | if (!fn_table_entry->type_entry->data.fn.is_generic) { |
| 3270 | if (fn_def_node) | 3355 | if (fn_def_node) |
| 3271 | g->fn_defs.append(fn_table_entry); | 3356 | g->fn_defs.append(fn_table_entry); |
| 3357 | } | ||
| 3272 | 3358 | ||
| 3273 | if (scope_is_root_decls(tld_fn->base.parent_scope) && | 3359 | if (scope_is_root_decls(tld_fn->base.parent_scope) && |
| 3274 | (import == g->root_import || import->package == g->panic_package)) | 3360 | (import == g->root_import || import->package == g->panic_package)) |
| 3361 | { | ||
| 3362 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { | ||
| 3363 | g->main_fn = fn_table_entry; | ||
| 3364 | } else if ((import->package == g->panic_package || g->have_pub_panic) && | ||
| 3365 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) | ||
| 3275 | { | 3366 | { |
| 3276 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { | 3367 | g->panic_fn = fn_table_entry; |
| 3277 | g->main_fn = fn_table_entry; | 3368 | g->panic_tld_fn = tld_fn; |
| 3278 | } else if ((import->package == g->panic_package || g->have_pub_panic) && | ||
| 3279 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) | ||
| 3280 | { | ||
| 3281 | g->panic_fn = fn_table_entry; | ||
| 3282 | typecheck_panic_fn(g, fn_table_entry); | ||
| 3283 | } | ||
| 3284 | } | 3369 | } |
| 3285 | } | 3370 | } |
| 3286 | } else if (source_node->type == NodeTypeTestDecl) { | 3371 | } else if (source_node->type == NodeTypeTestDecl) { |
| ... | @@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { | ... | @@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { |
| 3405 | resolve_top_level_decl(g, tld, false, tld->source_node); | 3490 | resolve_top_level_decl(g, tld, false, tld->source_node); |
| 3406 | assert(tld->id == TldIdVar); | 3491 | assert(tld->id == TldIdVar); |
| 3407 | TldVar *tld_var = (TldVar *)tld; | 3492 | TldVar *tld_var = (TldVar *)tld; |
| 3408 | tld_var->var->value = value; | 3493 | tld_var->var->const_value = value; |
| 3494 | tld_var->var->var_type = value->type; | ||
| 3409 | tld_var->var->align_bytes = get_abi_alignment(g, value->type); | 3495 | tld_var->var->align_bytes = get_abi_alignment(g, value->type); |
| 3410 | } | 3496 | } |
| 3411 | 3497 | ||
| ... | @@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3499 | case NodeTypeArrayType: | 3585 | case NodeTypeArrayType: |
| 3500 | case NodeTypeErrorType: | 3586 | case NodeTypeErrorType: |
| 3501 | case NodeTypeIfErrorExpr: | 3587 | case NodeTypeIfErrorExpr: |
| 3502 | case NodeTypeTestExpr: | 3588 | case NodeTypeIfOptional: |
| 3503 | case NodeTypeErrorSetDecl: | 3589 | case NodeTypeErrorSetDecl: |
| 3504 | case NodeTypeCancel: | 3590 | case NodeTypeCancel: |
| 3505 | case NodeTypeResume: | 3591 | case NodeTypeResume: |
| ... | @@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry | ... | @@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry |
| 3560 | case ZigTypeIdFn: | 3646 | case ZigTypeIdFn: |
| 3561 | case ZigTypeIdBoundFn: | 3647 | case ZigTypeIdBoundFn: |
| 3562 | case ZigTypeIdPromise: | 3648 | case ZigTypeIdPromise: |
| 3649 | case ZigTypeIdVector: | ||
| 3563 | return type_entry; | 3650 | return type_entry; |
| 3564 | } | 3651 | } |
| 3565 | zig_unreachable(); | 3652 | zig_unreachable(); |
| ... | @@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry | ... | @@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry |
| 3568 | // Set name to nullptr to make the variable anonymous (not visible to programmer). | 3655 | // Set name to nullptr to make the variable anonymous (not visible to programmer). |
| 3569 | // TODO merge with definition of add_local_var in ir.cpp | 3656 | // TODO merge with definition of add_local_var in ir.cpp |
| 3570 | ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, | 3657 | ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, |
| 3571 | bool is_const, ConstExprValue *value, Tld *src_tld) | 3658 | bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type) |
| 3572 | { | 3659 | { |
| 3573 | Error err; | 3660 | Error err; |
| 3574 | assert(value); | 3661 | assert(const_value != nullptr); |
| 3662 | assert(var_type != nullptr); | ||
| 3575 | 3663 | ||
| 3576 | ZigVar *variable_entry = allocate<ZigVar>(1); | 3664 | ZigVar *variable_entry = allocate<ZigVar>(1); |
| 3577 | variable_entry->value = value; | 3665 | variable_entry->const_value = const_value; |
| 3666 | variable_entry->var_type = var_type; | ||
| 3578 | variable_entry->parent_scope = parent_scope; | 3667 | variable_entry->parent_scope = parent_scope; |
| 3579 | variable_entry->shadowable = false; | 3668 | variable_entry->shadowable = false; |
| 3580 | variable_entry->mem_slot_index = SIZE_MAX; | 3669 | variable_entry->mem_slot_index = SIZE_MAX; |
| ... | @@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf | ... | @@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf |
| 3583 | assert(name); | 3672 | assert(name); |
| 3584 | buf_init_from_buf(&variable_entry->name, name); | 3673 | buf_init_from_buf(&variable_entry->name, name); |
| 3585 | 3674 | ||
| 3586 | if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) { | 3675 | if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) { |
| 3587 | variable_entry->value->type = g->builtin_types.entry_invalid; | 3676 | variable_entry->var_type = g->builtin_types.entry_invalid; |
| 3588 | } else { | 3677 | } else { |
| 3589 | variable_entry->align_bytes = get_abi_alignment(g, value->type); | 3678 | variable_entry->align_bytes = get_abi_alignment(g, var_type); |
| 3590 | 3679 | ||
| 3591 | ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr); | 3680 | ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr); |
| 3592 | if (existing_var && !existing_var->shadowable) { | 3681 | if (existing_var && !existing_var->shadowable) { |
| 3593 | ErrorMsg *msg = add_node_error(g, source_node, | 3682 | ErrorMsg *msg = add_node_error(g, source_node, |
| 3594 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | 3683 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| 3595 | add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); | 3684 | add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); |
| 3596 | variable_entry->value->type = g->builtin_types.entry_invalid; | 3685 | variable_entry->var_type = g->builtin_types.entry_invalid; |
| 3597 | } else { | 3686 | } else { |
| 3598 | ZigType *type; | 3687 | ZigType *type; |
| 3599 | if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) { | 3688 | if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) { |
| 3600 | add_node_error(g, source_node, | 3689 | add_node_error(g, source_node, |
| 3601 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); | 3690 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); |
| 3602 | variable_entry->value->type = g->builtin_types.entry_invalid; | 3691 | variable_entry->var_type = g->builtin_types.entry_invalid; |
| 3603 | } else { | 3692 | } else { |
| 3604 | Scope *search_scope = nullptr; | 3693 | Scope *search_scope = nullptr; |
| 3605 | if (src_tld == nullptr) { | 3694 | if (src_tld == nullptr) { |
| ... | @@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf | ... | @@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf |
| 3613 | ErrorMsg *msg = add_node_error(g, source_node, | 3702 | ErrorMsg *msg = add_node_error(g, source_node, |
| 3614 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | 3703 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 3615 | add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here")); | 3704 | add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here")); |
| 3616 | variable_entry->value->type = g->builtin_types.entry_invalid; | 3705 | variable_entry->var_type = g->builtin_types.entry_invalid; |
| 3617 | } | 3706 | } |
| 3618 | } | 3707 | } |
| 3619 | } | 3708 | } |
| ... | @@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3645 | bool is_const = var_decl->is_const; | 3734 | bool is_const = var_decl->is_const; |
| 3646 | bool is_extern = var_decl->is_extern; | 3735 | bool is_extern = var_decl->is_extern; |
| 3647 | bool is_export = var_decl->is_export; | 3736 | bool is_export = var_decl->is_export; |
| 3737 | bool is_thread_local = var_decl->threadlocal_tok != nullptr; | ||
| 3648 | 3738 | ||
| 3649 | ZigType *explicit_type = nullptr; | 3739 | ZigType *explicit_type = nullptr; |
| 3650 | if (var_decl->type) { | 3740 | if (var_decl->type) { |
| ... | @@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3663 | linkage = VarLinkageInternal; | 3753 | linkage = VarLinkageInternal; |
| 3664 | } | 3754 | } |
| 3665 | 3755 | ||
| 3666 | IrInstruction *init_value = nullptr; | 3756 | ConstExprValue *init_value = nullptr; |
| 3667 | 3757 | ||
| 3668 | // TODO more validation for types that can't be used for export/extern variables | 3758 | // TODO more validation for types that can't be used for export/extern variables |
| 3669 | ZigType *implicit_type = nullptr; | 3759 | ZigType *implicit_type = nullptr; |
| ... | @@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3672 | } else if (var_decl->expr) { | 3762 | } else if (var_decl->expr) { |
| 3673 | init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); | 3763 | init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); |
| 3674 | assert(init_value); | 3764 | assert(init_value); |
| 3675 | implicit_type = init_value->value.type; | 3765 | implicit_type = init_value->type; |
| 3676 | 3766 | ||
| 3677 | if (implicit_type->id == ZigTypeIdUnreachable) { | 3767 | if (implicit_type->id == ZigTypeIdUnreachable) { |
| 3678 | add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable")); | 3768 | add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable")); |
| ... | @@ -3690,7 +3780,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3690,7 +3780,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3690 | add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); | 3780 | add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); |
| 3691 | implicit_type = g->builtin_types.entry_invalid; | 3781 | implicit_type = g->builtin_types.entry_invalid; |
| 3692 | } | 3782 | } |
| 3693 | assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime); | 3783 | assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime); |
| 3694 | } else if (linkage != VarLinkageExternal) { | 3784 | } else if (linkage != VarLinkageExternal) { |
| 3695 | add_node_error(g, source_node, buf_sprintf("variables must be initialized")); | 3785 | add_node_error(g, source_node, buf_sprintf("variables must be initialized")); |
| 3696 | implicit_type = g->builtin_types.entry_invalid; | 3786 | implicit_type = g->builtin_types.entry_invalid; |
| ... | @@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3699 | ZigType *type = explicit_type ? explicit_type : implicit_type; | 3789 | ZigType *type = explicit_type ? explicit_type : implicit_type; |
| 3700 | assert(type != nullptr); // should have been caught by the parser | 3790 | assert(type != nullptr); // should have been caught by the parser |
| 3701 | 3791 | ||
| 3702 | ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type); | 3792 | ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type); |
| 3703 | 3793 | ||
| 3704 | tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, | 3794 | tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, |
| 3705 | is_const, init_val, &tld_var->base); | 3795 | is_const, init_val, &tld_var->base, type); |
| 3706 | tld_var->var->linkage = linkage; | 3796 | tld_var->var->linkage = linkage; |
| 3797 | tld_var->var->is_thread_local = is_thread_local; | ||
| 3707 | 3798 | ||
| 3708 | if (implicit_type != nullptr && type_is_invalid(implicit_type)) { | 3799 | if (implicit_type != nullptr && type_is_invalid(implicit_type)) { |
| 3709 | tld_var->var->value->type = g->builtin_types.entry_invalid; | 3800 | tld_var->var->var_type = g->builtin_types.entry_invalid; |
| 3710 | } | 3801 | } |
| 3711 | 3802 | ||
| 3712 | if (var_decl->align_expr != nullptr) { | 3803 | if (var_decl->align_expr != nullptr) { |
| 3713 | if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { | 3804 | if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { |
| 3714 | tld_var->var->value->type = g->builtin_types.entry_invalid; | 3805 | tld_var->var->var_type = g->builtin_types.entry_invalid; |
| 3715 | } | 3806 | } |
| 3716 | } | 3807 | } |
| 3717 | 3808 | ||
| ... | @@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3724 | } | 3815 | } |
| 3725 | } | 3816 | } |
| 3726 | 3817 | ||
| 3818 | if (is_thread_local && is_const) { | ||
| 3819 | add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant")); | ||
| 3820 | } | ||
| 3821 | |||
| 3727 | g->global_vars.append(tld_var); | 3822 | g->global_vars.append(tld_var); |
| 3728 | } | 3823 | } |
| 3729 | 3824 | ||
| ... | @@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) { | ... | @@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) { |
| 3924 | case ZigTypeIdArgTuple: | 4019 | case ZigTypeIdArgTuple: |
| 3925 | case ZigTypeIdOpaque: | 4020 | case ZigTypeIdOpaque: |
| 3926 | case ZigTypeIdPromise: | 4021 | case ZigTypeIdPromise: |
| 4022 | case ZigTypeIdVector: | ||
| 3927 | return false; | 4023 | return false; |
| 3928 | } | 4024 | } |
| 3929 | zig_unreachable(); | 4025 | zig_unreachable(); |
| ... | @@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { | ... | @@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { |
| 3983 | case ZigTypeIdArgTuple: | 4079 | case ZigTypeIdArgTuple: |
| 3984 | case ZigTypeIdOpaque: | 4080 | case ZigTypeIdOpaque: |
| 3985 | case ZigTypeIdPromise: | 4081 | case ZigTypeIdPromise: |
| 4082 | case ZigTypeIdVector: | ||
| 3986 | zig_unreachable(); | 4083 | zig_unreachable(); |
| 3987 | } | 4084 | } |
| 3988 | } | 4085 | } |
| ... | @@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) { | ... | @@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) { |
| 3992 | if (type->id == ZigTypeIdFn) return type; | 4089 | if (type->id == ZigTypeIdFn) return type; |
| 3993 | if (type->id == ZigTypeIdPromise) return type; | 4090 | if (type->id == ZigTypeIdPromise) return type; |
| 3994 | if (type->id == ZigTypeIdOptional) { | 4091 | if (type->id == ZigTypeIdOptional) { |
| 3995 | if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type; | 4092 | if (type->data.maybe.child_type->id == ZigTypeIdPointer) { |
| 4093 | return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type; | ||
| 4094 | } | ||
| 3996 | if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type; | 4095 | if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type; |
| 3997 | if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type; | 4096 | if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type; |
| 3998 | } | 4097 | } |
| ... | @@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) { | ... | @@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) { |
| 4006 | return ty; | 4105 | return ty; |
| 4007 | } | 4106 | } |
| 4008 | 4107 | ||
| 4108 | bool type_is_nonnull_ptr(ZigType *type) { | ||
| 4109 | return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type); | ||
| 4110 | } | ||
| 4111 | |||
| 4009 | bool type_is_codegen_pointer(ZigType *type) { | 4112 | bool type_is_codegen_pointer(ZigType *type) { |
| 4010 | return get_codegen_ptr_type(type) == type; | 4113 | return get_codegen_ptr_type(type) == type; |
| 4011 | } | 4114 | } |
| ... | @@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { |
| 4076 | } | 4179 | } |
| 4077 | 4180 | ||
| 4078 | ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, | 4181 | ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, |
| 4079 | param_name, true, create_const_runtime(param_type), nullptr); | 4182 | param_name, true, create_const_runtime(param_type), nullptr, param_type); |
| 4080 | var->src_arg_index = i; | 4183 | var->src_arg_index = i; |
| 4081 | fn_table_entry->child_scope = var->child_scope; | 4184 | fn_table_entry->child_scope = var->child_scope; |
| 4082 | var->shadowable = var->shadowable || is_var_args; | 4185 | var->shadowable = var->shadowable || is_var_args; |
| ... | @@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * | ... | @@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * |
| 4214 | preview_use_decl(g, src_use_node); | 4317 | preview_use_decl(g, src_use_node); |
| 4215 | } | 4318 | } |
| 4216 | 4319 | ||
| 4217 | IrInstruction *use_target_value = src_use_node->data.use.value; | 4320 | ConstExprValue *use_target_value = src_use_node->data.use.value; |
| 4218 | if (use_target_value->value.type->id == ZigTypeIdInvalid) { | 4321 | if (type_is_invalid(use_target_value->type)) { |
| 4219 | dst_use_node->owner->any_imports_failed = true; | 4322 | dst_use_node->owner->any_imports_failed = true; |
| 4220 | return; | 4323 | return; |
| 4221 | } | 4324 | } |
| 4222 | 4325 | ||
| 4223 | dst_use_node->data.use.resolution = TldResolutionOk; | 4326 | dst_use_node->data.use.resolution = TldResolutionOk; |
| 4224 | 4327 | ||
| 4225 | ConstExprValue *const_val = &use_target_value->value; | 4328 | assert(use_target_value->special != ConstValSpecialRuntime); |
| 4226 | assert(const_val->special != ConstValSpecialRuntime); | ||
| 4227 | 4329 | ||
| 4228 | ImportTableEntry *target_import = const_val->data.x_import; | 4330 | ImportTableEntry *target_import = use_target_value->data.x_import; |
| 4229 | assert(target_import); | 4331 | assert(target_import); |
| 4230 | 4332 | ||
| 4231 | if (target_import->any_imports_failed) { | 4333 | if (target_import->any_imports_failed) { |
| ... | @@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) { | ... | @@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) { |
| 4288 | } | 4390 | } |
| 4289 | 4391 | ||
| 4290 | node->data.use.resolution = TldResolutionResolving; | 4392 | node->data.use.resolution = TldResolutionResolving; |
| 4291 | IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base, | 4393 | ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base, |
| 4292 | node->data.use.expr, g->builtin_types.entry_namespace, nullptr); | 4394 | node->data.use.expr, g->builtin_types.entry_namespace, nullptr); |
| 4293 | 4395 | ||
| 4294 | if (result->value.type->id == ZigTypeIdInvalid) | 4396 | if (type_is_invalid(result->type)) |
| 4295 | node->owner->any_imports_failed = true; | 4397 | node->owner->any_imports_failed = true; |
| 4296 | 4398 | ||
| 4297 | node->data.use.value = result; | 4399 | node->data.use.value = result; |
| ... | @@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r | ... | @@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r |
| 4364 | if (is_pub && ok_cc) { | 4466 | if (is_pub && ok_cc) { |
| 4365 | if (buf_eql_str(proto_name, "main")) { | 4467 | if (buf_eql_str(proto_name, "main")) { |
| 4366 | g->have_pub_main = true; | 4468 | g->have_pub_main = true; |
| 4367 | g->windows_subsystem_windows = false; | 4469 | g->subsystem = TargetSubsystemConsole; |
| 4368 | g->windows_subsystem_console = true; | ||
| 4369 | } else if (buf_eql_str(proto_name, "panic")) { | 4470 | } else if (buf_eql_str(proto_name, "panic")) { |
| 4370 | g->have_pub_panic = true; | 4471 | g->have_pub_panic = true; |
| 4371 | } | 4472 | } |
| ... | @@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { | ... | @@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 4434 | return new_entry; | 4535 | return new_entry; |
| 4435 | } | 4536 | } |
| 4436 | 4537 | ||
| 4538 | bool is_valid_vector_elem_type(ZigType *elem_type) { | ||
| 4539 | return elem_type->id == ZigTypeIdInt || | ||
| 4540 | elem_type->id == ZigTypeIdFloat || | ||
| 4541 | get_codegen_ptr_type(elem_type) != nullptr; | ||
| 4542 | } | ||
| 4543 | |||
| 4544 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { | ||
| 4545 | assert(is_valid_vector_elem_type(elem_type)); | ||
| 4546 | |||
| 4547 | TypeId type_id = {}; | ||
| 4548 | type_id.id = ZigTypeIdVector; | ||
| 4549 | type_id.data.vector.len = len; | ||
| 4550 | type_id.data.vector.elem_type = elem_type; | ||
| 4551 | |||
| 4552 | { | ||
| 4553 | auto entry = g->type_table.maybe_get(type_id); | ||
| 4554 | if (entry) | ||
| 4555 | return entry->value; | ||
| 4556 | } | ||
| 4557 | |||
| 4558 | ZigType *entry = new_type_table_entry(ZigTypeIdVector); | ||
| 4559 | entry->zero_bits = (len == 0) || !type_has_bits(elem_type); | ||
| 4560 | entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len); | ||
| 4561 | entry->data.vector.len = len; | ||
| 4562 | entry->data.vector.elem_type = elem_type; | ||
| 4563 | |||
| 4564 | buf_resize(&entry->name, 0); | ||
| 4565 | buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name)); | ||
| 4566 | |||
| 4567 | entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder, | ||
| 4568 | len * type_size_bits(g, elem_type), | ||
| 4569 | LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type, len); | ||
| 4570 | |||
| 4571 | g->type_table.put(type_id, entry); | ||
| 4572 | return entry; | ||
| 4573 | } | ||
| 4574 | |||
| 4437 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { | 4575 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { |
| 4438 | return &g->builtin_types.entry_c_int[c_int_type]; | 4576 | return &g->builtin_types.entry_c_int[c_int_type]; |
| 4439 | } | 4577 | } |
| ... | @@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) { | ... | @@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4465 | case ZigTypeIdFn: | 4603 | case ZigTypeIdFn: |
| 4466 | case ZigTypeIdEnum: | 4604 | case ZigTypeIdEnum: |
| 4467 | case ZigTypeIdPromise: | 4605 | case ZigTypeIdPromise: |
| 4606 | case ZigTypeIdVector: | ||
| 4468 | return false; | 4607 | return false; |
| 4469 | case ZigTypeIdArray: | 4608 | case ZigTypeIdArray: |
| 4470 | case ZigTypeIdStruct: | 4609 | case ZigTypeIdStruct: |
| ... | @@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) { | ... | @@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4473 | return type_has_bits(type_entry->data.error_union.payload_type); | 4612 | return type_has_bits(type_entry->data.error_union.payload_type); |
| 4474 | case ZigTypeIdOptional: | 4613 | case ZigTypeIdOptional: |
| 4475 | return type_has_bits(type_entry->data.maybe.child_type) && | 4614 | return type_has_bits(type_entry->data.maybe.child_type) && |
| 4476 | !type_is_codegen_pointer(type_entry->data.maybe.child_type); | 4615 | !type_is_codegen_pointer(type_entry->data.maybe.child_type) && |
| 4616 | type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; | ||
| 4477 | case ZigTypeIdUnion: | 4617 | case ZigTypeIdUnion: |
| 4478 | assert(type_entry->data.unionation.zero_bits_known); | 4618 | assert(type_entry->data.unionation.zero_bits_known); |
| 4479 | if (type_entry->data.unionation.gen_field_count == 0) | 4619 | if (type_entry->data.unionation.gen_field_count == 0) |
| ... | @@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) { | ... | @@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) { |
| 4580 | void find_libc_include_path(CodeGen *g) { | 4720 | void find_libc_include_path(CodeGen *g) { |
| 4581 | if (g->libc_include_dir == nullptr) { | 4721 | if (g->libc_include_dir == nullptr) { |
| 4582 | if (!g->is_native_target) { | 4722 | if (!g->is_native_target) { |
| 4583 | fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); | 4723 | return; |
| 4584 | exit(1); | ||
| 4585 | } | 4724 | } |
| 4586 | 4725 | ||
| 4587 | if (g->zig_target.os == OsWindows) { | 4726 | if (g->zig_target.os == OsWindows) { |
| ... | @@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { | ... | @@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { |
| 4720 | return true; | 4859 | return true; |
| 4721 | } | 4860 | } |
| 4722 | 4861 | ||
| 4862 | static uint32_t hash_const_val_error_set(ConstExprValue *const_val) { | ||
| 4863 | assert(const_val->data.x_err_set != nullptr); | ||
| 4864 | return const_val->data.x_err_set->value ^ 2630160122; | ||
| 4865 | } | ||
| 4866 | |||
| 4723 | static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { | 4867 | static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { |
| 4724 | uint32_t hash_val = 0; | 4868 | uint32_t hash_val = 0; |
| 4725 | switch (const_val->data.x_ptr.mut) { | 4869 | switch (const_val->data.x_ptr.mut) { |
| ... | @@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { | ... | @@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { |
| 4751 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); | 4895 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); |
| 4752 | hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); | 4896 | hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); |
| 4753 | return hash_val; | 4897 | return hash_val; |
| 4898 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 4899 | hash_val += (uint32_t)2994743799; | ||
| 4900 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val); | ||
| 4901 | return hash_val; | ||
| 4902 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 4903 | hash_val += (uint32_t)3456080131; | ||
| 4904 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val); | ||
| 4905 | return hash_val; | ||
| 4906 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 4907 | hash_val += (uint32_t)3163140517; | ||
| 4908 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val); | ||
| 4909 | return hash_val; | ||
| 4754 | case ConstPtrSpecialHardCodedAddr: | 4910 | case ConstPtrSpecialHardCodedAddr: |
| 4755 | hash_val += (uint32_t)4048518294; | 4911 | hash_val += (uint32_t)4048518294; |
| 4756 | hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); | 4912 | hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); |
| ... | @@ -4762,6 +4918,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { | ... | @@ -4762,6 +4918,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { |
| 4762 | hash_val += (uint32_t)2590901619; | 4918 | hash_val += (uint32_t)2590901619; |
| 4763 | hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); | 4919 | hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); |
| 4764 | return hash_val; | 4920 | return hash_val; |
| 4921 | case ConstPtrSpecialNull: | ||
| 4922 | hash_val += (uint32_t)1486246455; | ||
| 4923 | return hash_val; | ||
| 4765 | } | 4924 | } |
| 4766 | zig_unreachable(); | 4925 | zig_unreachable(); |
| 4767 | } | 4926 | } |
| ... | @@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4860 | return 2709806591; | 5019 | return 2709806591; |
| 4861 | case ZigTypeIdOptional: | 5020 | case ZigTypeIdOptional: |
| 4862 | if (get_codegen_ptr_type(const_val->type) != nullptr) { | 5021 | if (get_codegen_ptr_type(const_val->type) != nullptr) { |
| 4863 | return hash_const_val(const_val) * 1992916303; | 5022 | return hash_const_val_ptr(const_val) * 1992916303; |
| 5023 | } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) { | ||
| 5024 | return hash_const_val_error_set(const_val) * 3147031929; | ||
| 4864 | } else { | 5025 | } else { |
| 4865 | if (const_val->data.x_optional) { | 5026 | if (const_val->data.x_optional) { |
| 4866 | return hash_const_val(const_val->data.x_optional) * 1992916303; | 5027 | return hash_const_val(const_val->data.x_optional) * 1992916303; |
| ... | @@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4872 | // TODO better hashing algorithm | 5033 | // TODO better hashing algorithm |
| 4873 | return 3415065496; | 5034 | return 3415065496; |
| 4874 | case ZigTypeIdErrorSet: | 5035 | case ZigTypeIdErrorSet: |
| 4875 | assert(const_val->data.x_err_set != nullptr); | 5036 | return hash_const_val_error_set(const_val); |
| 4876 | return const_val->data.x_err_set->value ^ 2630160122; | ||
| 4877 | case ZigTypeIdNamespace: | 5037 | case ZigTypeIdNamespace: |
| 4878 | return hash_ptr(const_val->data.x_import); | 5038 | return hash_ptr(const_val->data.x_import); |
| 5039 | case ZigTypeIdVector: | ||
| 5040 | // TODO better hashing algorithm | ||
| 5041 | return 3647867726; | ||
| 4879 | case ZigTypeIdBoundFn: | 5042 | case ZigTypeIdBoundFn: |
| 4880 | case ZigTypeIdInvalid: | 5043 | case ZigTypeIdInvalid: |
| 4881 | case ZigTypeIdUnreachable: | 5044 | case ZigTypeIdUnreachable: |
| ... | @@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { | ... | @@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4928 | case ZigTypeIdBool: | 5091 | case ZigTypeIdBool: |
| 4929 | case ZigTypeIdUnreachable: | 5092 | case ZigTypeIdUnreachable: |
| 4930 | case ZigTypeIdInt: | 5093 | case ZigTypeIdInt: |
| 5094 | case ZigTypeIdVector: | ||
| 4931 | case ZigTypeIdFloat: | 5095 | case ZigTypeIdFloat: |
| 4932 | case ZigTypeIdComptimeFloat: | 5096 | case ZigTypeIdComptimeFloat: |
| 4933 | case ZigTypeIdComptimeInt: | 5097 | case ZigTypeIdComptimeInt: |
| ... | @@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { | ... | @@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4975 | return can_mutate_comptime_var_state(value->data.x_optional); | 5139 | return can_mutate_comptime_var_state(value->data.x_optional); |
| 4976 | 5140 | ||
| 4977 | case ZigTypeIdErrorUnion: | 5141 | case ZigTypeIdErrorUnion: |
| 4978 | if (value->data.x_err_union.err != nullptr) | 5142 | if (value->data.x_err_union.error_set->data.x_err_set != nullptr) |
| 4979 | return false; | 5143 | return false; |
| 4980 | assert(value->data.x_err_union.payload != nullptr); | 5144 | assert(value->data.x_err_union.payload != nullptr); |
| 4981 | return can_mutate_comptime_var_state(value->data.x_err_union.payload); | 5145 | return can_mutate_comptime_var_state(value->data.x_err_union.payload); |
| ... | @@ -5011,6 +5175,7 @@ static bool return_type_is_cacheable(ZigType *return_type) { | ... | @@ -5011,6 +5175,7 @@ static bool return_type_is_cacheable(ZigType *return_type) { |
| 5011 | case ZigTypeIdErrorSet: | 5175 | case ZigTypeIdErrorSet: |
| 5012 | case ZigTypeIdEnum: | 5176 | case ZigTypeIdEnum: |
| 5013 | case ZigTypeIdPointer: | 5177 | case ZigTypeIdPointer: |
| 5178 | case ZigTypeIdVector: | ||
| 5014 | return true; | 5179 | return true; |
| 5015 | 5180 | ||
| 5016 | case ZigTypeIdArray: | 5181 | case ZigTypeIdArray: |
| ... | @@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) { | ... | @@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) { |
| 5036 | while (scope) { | 5201 | while (scope) { |
| 5037 | if (scope->id == ScopeIdVarDecl) { | 5202 | if (scope->id == ScopeIdVarDecl) { |
| 5038 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; | 5203 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| 5039 | if (type_is_invalid(var_scope->var->value->type)) | 5204 | if (type_is_invalid(var_scope->var->var_type)) |
| 5040 | return false; | 5205 | return false; |
| 5041 | if (can_mutate_comptime_var_state(var_scope->var->value)) | 5206 | if (can_mutate_comptime_var_state(var_scope->var->const_value)) |
| 5042 | return false; | 5207 | return false; |
| 5043 | } else if (scope->id == ScopeIdFnDef) { | 5208 | } else if (scope->id == ScopeIdFnDef) { |
| 5044 | return true; | 5209 | return true; |
| ... | @@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) { | ... | @@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) { |
| 5056 | while (scope) { | 5221 | while (scope) { |
| 5057 | if (scope->id == ScopeIdVarDecl) { | 5222 | if (scope->id == ScopeIdVarDecl) { |
| 5058 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; | 5223 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| 5059 | result += hash_const_val(var_scope->var->value); | 5224 | result += hash_const_val(var_scope->var->const_value); |
| 5060 | } else if (scope->id == ScopeIdFnDef) { | 5225 | } else if (scope->id == ScopeIdFnDef) { |
| 5061 | ScopeFnDef *fn_scope = (ScopeFnDef *)scope; | 5226 | ScopeFnDef *fn_scope = (ScopeFnDef *)scope; |
| 5062 | result += hash_ptr(fn_scope->fn_entry); | 5227 | result += hash_ptr(fn_scope->fn_entry); |
| ... | @@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) { | ... | @@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) { |
| 5080 | if (a->id == ScopeIdVarDecl) { | 5245 | if (a->id == ScopeIdVarDecl) { |
| 5081 | ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a; | 5246 | ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a; |
| 5082 | ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b; | 5247 | ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b; |
| 5083 | if (a_var_scope->var->value->type != b_var_scope->var->value->type) | 5248 | if (a_var_scope->var->var_type != b_var_scope->var->var_type) |
| 5084 | return false; | ||
| 5085 | if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value)) | ||
| 5086 | return false; | 5249 | return false; |
| 5250 | if (a_var_scope->var->var_type == a_var_scope->var->const_value->type && | ||
| 5251 | b_var_scope->var->var_type == b_var_scope->var->const_value->type) | ||
| 5252 | { | ||
| 5253 | if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value)) | ||
| 5254 | return false; | ||
| 5255 | } else { | ||
| 5256 | zig_panic("TODO comptime ptr reinterpret for fn_eval_eql"); | ||
| 5257 | } | ||
| 5087 | } else if (a->id == ScopeIdFnDef) { | 5258 | } else if (a->id == ScopeIdFnDef) { |
| 5088 | ScopeFnDef *a_fn_scope = (ScopeFnDef *)a; | 5259 | ScopeFnDef *a_fn_scope = (ScopeFnDef *)a; |
| 5089 | ScopeFnDef *b_fn_scope = (ScopeFnDef *)b; | 5260 | ScopeFnDef *b_fn_scope = (ScopeFnDef *)b; |
| ... | @@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { | ... | @@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { |
| 5101 | return false; | 5272 | return false; |
| 5102 | } | 5273 | } |
| 5103 | 5274 | ||
| 5275 | // Whether the type has bits at runtime. | ||
| 5104 | bool type_has_bits(ZigType *type_entry) { | 5276 | bool type_has_bits(ZigType *type_entry) { |
| 5105 | assert(type_entry); | 5277 | assert(type_entry); |
| 5106 | assert(!type_is_invalid(type_entry)); | 5278 | assert(!type_is_invalid(type_entry)); |
| ... | @@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) { | ... | @@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) { |
| 5108 | return !type_entry->zero_bits; | 5280 | return !type_entry->zero_bits; |
| 5109 | } | 5281 | } |
| 5110 | 5282 | ||
| 5283 | // Whether you can infer the value based solely on the type. | ||
| 5284 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { | ||
| 5285 | assert(type_entry != nullptr); | ||
| 5286 | Error err; | ||
| 5287 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | ||
| 5288 | return OnePossibleValueInvalid; | ||
| 5289 | switch (type_entry->id) { | ||
| 5290 | case ZigTypeIdInvalid: | ||
| 5291 | zig_unreachable(); | ||
| 5292 | case ZigTypeIdOpaque: | ||
| 5293 | case ZigTypeIdComptimeFloat: | ||
| 5294 | case ZigTypeIdComptimeInt: | ||
| 5295 | case ZigTypeIdMetaType: | ||
| 5296 | case ZigTypeIdNamespace: | ||
| 5297 | case ZigTypeIdBoundFn: | ||
| 5298 | case ZigTypeIdArgTuple: | ||
| 5299 | case ZigTypeIdOptional: | ||
| 5300 | case ZigTypeIdFn: | ||
| 5301 | case ZigTypeIdBool: | ||
| 5302 | case ZigTypeIdFloat: | ||
| 5303 | case ZigTypeIdPromise: | ||
| 5304 | case ZigTypeIdErrorUnion: | ||
| 5305 | return OnePossibleValueNo; | ||
| 5306 | case ZigTypeIdUndefined: | ||
| 5307 | case ZigTypeIdNull: | ||
| 5308 | case ZigTypeIdVoid: | ||
| 5309 | case ZigTypeIdUnreachable: | ||
| 5310 | return OnePossibleValueYes; | ||
| 5311 | case ZigTypeIdArray: | ||
| 5312 | if (type_entry->data.array.len == 0) | ||
| 5313 | return OnePossibleValueYes; | ||
| 5314 | return type_has_one_possible_value(g, type_entry->data.array.child_type); | ||
| 5315 | case ZigTypeIdStruct: | ||
| 5316 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | ||
| 5317 | TypeStructField *field = &type_entry->data.structure.fields[i]; | ||
| 5318 | switch (type_has_one_possible_value(g, field->type_entry)) { | ||
| 5319 | case OnePossibleValueInvalid: | ||
| 5320 | return OnePossibleValueInvalid; | ||
| 5321 | case OnePossibleValueNo: | ||
| 5322 | return OnePossibleValueNo; | ||
| 5323 | case OnePossibleValueYes: | ||
| 5324 | continue; | ||
| 5325 | } | ||
| 5326 | } | ||
| 5327 | return OnePossibleValueYes; | ||
| 5328 | case ZigTypeIdErrorSet: | ||
| 5329 | case ZigTypeIdEnum: | ||
| 5330 | case ZigTypeIdInt: | ||
| 5331 | case ZigTypeIdVector: | ||
| 5332 | return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; | ||
| 5333 | case ZigTypeIdPointer: | ||
| 5334 | return type_has_one_possible_value(g, type_entry->data.pointer.child_type); | ||
| 5335 | case ZigTypeIdUnion: | ||
| 5336 | if (type_entry->data.unionation.src_field_count > 1) | ||
| 5337 | return OnePossibleValueNo; | ||
| 5338 | return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry); | ||
| 5339 | } | ||
| 5340 | zig_unreachable(); | ||
| 5341 | } | ||
| 5342 | |||
| 5111 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { | 5343 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 5112 | Error err; | 5344 | Error err; |
| 5113 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | 5345 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) |
| ... | @@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { | ... | @@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 5147 | case ZigTypeIdErrorSet: | 5379 | case ZigTypeIdErrorSet: |
| 5148 | case ZigTypeIdBool: | 5380 | case ZigTypeIdBool: |
| 5149 | case ZigTypeIdInt: | 5381 | case ZigTypeIdInt: |
| 5382 | case ZigTypeIdVector: | ||
| 5150 | case ZigTypeIdFloat: | 5383 | case ZigTypeIdFloat: |
| 5151 | case ZigTypeIdVoid: | 5384 | case ZigTypeIdVoid: |
| 5152 | case ZigTypeIdUnreachable: | 5385 | case ZigTypeIdUnreachable: |
| ... | @@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { |
| 5562 | if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) | 5795 | if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) |
| 5563 | return false; | 5796 | return false; |
| 5564 | return true; | 5797 | return true; |
| 5798 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 5799 | if (a->data.x_ptr.data.base_err_union_code.err_union_val != | ||
| 5800 | b->data.x_ptr.data.base_err_union_code.err_union_val && | ||
| 5801 | a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs != | ||
| 5802 | b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs) | ||
| 5803 | { | ||
| 5804 | return false; | ||
| 5805 | } | ||
| 5806 | return true; | ||
| 5807 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 5808 | if (a->data.x_ptr.data.base_err_union_payload.err_union_val != | ||
| 5809 | b->data.x_ptr.data.base_err_union_payload.err_union_val && | ||
| 5810 | a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs != | ||
| 5811 | b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs) | ||
| 5812 | { | ||
| 5813 | return false; | ||
| 5814 | } | ||
| 5815 | return true; | ||
| 5816 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 5817 | if (a->data.x_ptr.data.base_optional_payload.optional_val != | ||
| 5818 | b->data.x_ptr.data.base_optional_payload.optional_val && | ||
| 5819 | a->data.x_ptr.data.base_optional_payload.optional_val->global_refs != | ||
| 5820 | b->data.x_ptr.data.base_optional_payload.optional_val->global_refs) | ||
| 5821 | { | ||
| 5822 | return false; | ||
| 5823 | } | ||
| 5824 | return true; | ||
| 5565 | case ConstPtrSpecialHardCodedAddr: | 5825 | case ConstPtrSpecialHardCodedAddr: |
| 5566 | if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) | 5826 | if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) |
| 5567 | return false; | 5827 | return false; |
| ... | @@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { |
| 5570 | return true; | 5830 | return true; |
| 5571 | case ConstPtrSpecialFunction: | 5831 | case ConstPtrSpecialFunction: |
| 5572 | return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; | 5832 | return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; |
| 5833 | case ConstPtrSpecialNull: | ||
| 5834 | return true; | ||
| 5573 | } | 5835 | } |
| 5574 | zig_unreachable(); | 5836 | zig_unreachable(); |
| 5575 | } | 5837 | } |
| 5576 | 5838 | ||
| 5839 | static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) { | ||
| 5840 | assert(a->data.x_array.special != ConstArraySpecialUndef); | ||
| 5841 | assert(b->data.x_array.special != ConstArraySpecialUndef); | ||
| 5842 | if (a->data.x_array.special == ConstArraySpecialBuf && | ||
| 5843 | b->data.x_array.special == ConstArraySpecialBuf) | ||
| 5844 | { | ||
| 5845 | return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf); | ||
| 5846 | } | ||
| 5847 | expand_undef_array(g, a); | ||
| 5848 | expand_undef_array(g, b); | ||
| 5849 | |||
| 5850 | ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; | ||
| 5851 | ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; | ||
| 5852 | |||
| 5853 | for (size_t i = 0; i < len; i += 1) { | ||
| 5854 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) | ||
| 5855 | return false; | ||
| 5856 | } | ||
| 5857 | |||
| 5858 | return true; | ||
| 5859 | } | ||
| 5860 | |||
| 5577 | bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { | 5861 | bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5578 | assert(a->type->id == b->type->id); | 5862 | assert(a->type->id == b->type->id); |
| 5579 | assert(a->special == ConstValSpecialStatic); | 5863 | assert(a->special == ConstValSpecialStatic); |
| ... | @@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5628 | case ZigTypeIdPointer: | 5912 | case ZigTypeIdPointer: |
| 5629 | case ZigTypeIdFn: | 5913 | case ZigTypeIdFn: |
| 5630 | return const_values_equal_ptr(a, b); | 5914 | return const_values_equal_ptr(a, b); |
| 5915 | case ZigTypeIdVector: | ||
| 5916 | assert(a->type->data.vector.len == b->type->data.vector.len); | ||
| 5917 | return const_values_equal_array(g, a, b, a->type->data.vector.len); | ||
| 5631 | case ZigTypeIdArray: { | 5918 | case ZigTypeIdArray: { |
| 5632 | assert(a->type->data.array.len == b->type->data.array.len); | 5919 | assert(a->type->data.array.len == b->type->data.array.len); |
| 5633 | assert(a->data.x_array.special != ConstArraySpecialUndef); | 5920 | return const_values_equal_array(g, a, b, a->type->data.array.len); |
| 5634 | assert(b->data.x_array.special != ConstArraySpecialUndef); | ||
| 5635 | if (a->data.x_array.special == ConstArraySpecialBuf && | ||
| 5636 | b->data.x_array.special == ConstArraySpecialBuf) | ||
| 5637 | { | ||
| 5638 | return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf); | ||
| 5639 | } | ||
| 5640 | expand_undef_array(g, a); | ||
| 5641 | expand_undef_array(g, b); | ||
| 5642 | |||
| 5643 | size_t len = a->type->data.array.len; | ||
| 5644 | ConstExprValue *a_elems = a->data.x_array.data.s_none.elements; | ||
| 5645 | ConstExprValue *b_elems = b->data.x_array.data.s_none.elements; | ||
| 5646 | |||
| 5647 | for (size_t i = 0; i < len; ++i) { | ||
| 5648 | if (!const_values_equal(g, &a_elems[i], &b_elems[i])) | ||
| 5649 | return false; | ||
| 5650 | } | ||
| 5651 | |||
| 5652 | return true; | ||
| 5653 | } | 5921 | } |
| 5654 | case ZigTypeIdStruct: | 5922 | case ZigTypeIdStruct: |
| 5655 | for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { | 5923 | for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { |
| ... | @@ -5738,14 +6006,25 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v | ... | @@ -5738,14 +6006,25 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v |
| 5738 | } | 6006 | } |
| 5739 | } | 6007 | } |
| 5740 | 6008 | ||
| 5741 | void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { | 6009 | static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { |
| 6010 | assert(type_entry->id == ZigTypeIdPointer); | ||
| 6011 | |||
| 6012 | if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { | ||
| 6013 | buf_append_buf(buf, &type_entry->name); | ||
| 6014 | return; | ||
| 6015 | } | ||
| 6016 | |||
| 5742 | switch (const_val->data.x_ptr.special) { | 6017 | switch (const_val->data.x_ptr.special) { |
| 5743 | case ConstPtrSpecialInvalid: | 6018 | case ConstPtrSpecialInvalid: |
| 5744 | zig_unreachable(); | 6019 | zig_unreachable(); |
| 5745 | case ConstPtrSpecialRef: | 6020 | case ConstPtrSpecialRef: |
| 5746 | case ConstPtrSpecialBaseStruct: | 6021 | case ConstPtrSpecialBaseStruct: |
| 6022 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 6023 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 6024 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 5747 | buf_appendf(buf, "*"); | 6025 | buf_appendf(buf, "*"); |
| 5748 | render_const_value(g, buf, const_ptr_pointee(g, const_val)); | 6026 | // TODO we need a source node for const_ptr_pointee because it can generate compile errors |
| 6027 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); | ||
| 5749 | return; | 6028 | return; |
| 5750 | case ConstPtrSpecialBaseArray: | 6029 | case ConstPtrSpecialBaseArray: |
| 5751 | if (const_val->data.x_ptr.data.base_array.is_cstr) { | 6030 | if (const_val->data.x_ptr.data.base_array.is_cstr) { |
| ... | @@ -5753,7 +6032,8 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy | ... | @@ -5753,7 +6032,8 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy |
| 5753 | return; | 6032 | return; |
| 5754 | } else { | 6033 | } else { |
| 5755 | buf_appendf(buf, "*"); | 6034 | buf_appendf(buf, "*"); |
| 5756 | render_const_value(g, buf, const_ptr_pointee(g, const_val)); | 6035 | // TODO we need a source node for const_ptr_pointee because it can generate compile errors |
| 6036 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); | ||
| 5757 | return; | 6037 | return; |
| 5758 | } | 6038 | } |
| 5759 | case ConstPtrSpecialHardCodedAddr: | 6039 | case ConstPtrSpecialHardCodedAddr: |
| ... | @@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy | ... | @@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy |
| 5769 | buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); | 6049 | buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); |
| 5770 | return; | 6050 | return; |
| 5771 | } | 6051 | } |
| 6052 | case ConstPtrSpecialNull: | ||
| 6053 | buf_append_str(buf, "null"); | ||
| 6054 | return; | ||
| 6055 | } | ||
| 6056 | zig_unreachable(); | ||
| 6057 | } | ||
| 6058 | |||
| 6059 | static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { | ||
| 6060 | if (const_val->data.x_err_set == nullptr) { | ||
| 6061 | buf_append_str(buf, "null"); | ||
| 6062 | } else { | ||
| 6063 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); | ||
| 6064 | } | ||
| 6065 | } | ||
| 6066 | |||
| 6067 | static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) { | ||
| 6068 | ConstArrayValue *array = &const_val->data.x_array; | ||
| 6069 | switch (array->special) { | ||
| 6070 | case ConstArraySpecialUndef: | ||
| 6071 | buf_append_str(buf, "undefined"); | ||
| 6072 | return; | ||
| 6073 | case ConstArraySpecialBuf: { | ||
| 6074 | Buf *array_buf = array->data.s_buf; | ||
| 6075 | const char *base = &buf_ptr(array_buf)[start]; | ||
| 6076 | assert(start + len <= buf_len(array_buf)); | ||
| 6077 | |||
| 6078 | buf_append_char(buf, '"'); | ||
| 6079 | for (size_t i = 0; i < len; i += 1) { | ||
| 6080 | uint8_t c = base[i]; | ||
| 6081 | if (c == '"') { | ||
| 6082 | buf_append_str(buf, "\\\""); | ||
| 6083 | } else { | ||
| 6084 | buf_append_char(buf, c); | ||
| 6085 | } | ||
| 6086 | } | ||
| 6087 | buf_append_char(buf, '"'); | ||
| 6088 | return; | ||
| 6089 | } | ||
| 6090 | case ConstArraySpecialNone: { | ||
| 6091 | ConstExprValue *base = &array->data.s_none.elements[start]; | ||
| 6092 | assert(start + len <= const_val->type->data.array.len); | ||
| 6093 | |||
| 6094 | buf_appendf(buf, "%s{", buf_ptr(type_name)); | ||
| 6095 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6096 | if (i != 0) buf_appendf(buf, ","); | ||
| 6097 | render_const_value(g, buf, &base[i]); | ||
| 6098 | } | ||
| 6099 | buf_appendf(buf, "}"); | ||
| 6100 | return; | ||
| 6101 | } | ||
| 5772 | } | 6102 | } |
| 5773 | zig_unreachable(); | 6103 | zig_unreachable(); |
| 5774 | } | 6104 | } |
| ... | @@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5853 | } | 6183 | } |
| 5854 | case ZigTypeIdPointer: | 6184 | case ZigTypeIdPointer: |
| 5855 | return render_const_val_ptr(g, buf, const_val, type_entry); | 6185 | return render_const_val_ptr(g, buf, const_val, type_entry); |
| 5856 | case ZigTypeIdArray: | 6186 | case ZigTypeIdArray: { |
| 5857 | switch (const_val->data.x_array.special) { | 6187 | uint64_t len = type_entry->data.array.len; |
| 5858 | case ConstArraySpecialUndef: | 6188 | render_const_val_array(g, buf, &type_entry->name, const_val, 0, len); |
| 5859 | buf_append_str(buf, "undefined"); | 6189 | return; |
| 5860 | return; | 6190 | } |
| 5861 | case ConstArraySpecialBuf: { | 6191 | case ZigTypeIdVector: { |
| 5862 | Buf *array_buf = const_val->data.x_array.data.s_buf; | 6192 | uint32_t len = type_entry->data.vector.len; |
| 5863 | buf_append_char(buf, '"'); | 6193 | render_const_val_array(g, buf, &type_entry->name, const_val, 0, len); |
| 5864 | for (size_t i = 0; i < buf_len(array_buf); i += 1) { | 6194 | return; |
| 5865 | uint8_t c = buf_ptr(array_buf)[i]; | 6195 | } |
| 5866 | if (c == '"') { | ||
| 5867 | buf_append_str(buf, "\\\""); | ||
| 5868 | } else { | ||
| 5869 | buf_append_char(buf, c); | ||
| 5870 | } | ||
| 5871 | } | ||
| 5872 | buf_append_char(buf, '"'); | ||
| 5873 | return; | ||
| 5874 | } | ||
| 5875 | case ConstArraySpecialNone: { | ||
| 5876 | buf_appendf(buf, "%s{", buf_ptr(&type_entry->name)); | ||
| 5877 | uint64_t len = type_entry->data.array.len; | ||
| 5878 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 5879 | if (i != 0) | ||
| 5880 | buf_appendf(buf, ","); | ||
| 5881 | ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i]; | ||
| 5882 | render_const_value(g, buf, child_value); | ||
| 5883 | } | ||
| 5884 | buf_appendf(buf, "}"); | ||
| 5885 | return; | ||
| 5886 | } | ||
| 5887 | } | ||
| 5888 | zig_unreachable(); | ||
| 5889 | case ZigTypeIdNull: | 6196 | case ZigTypeIdNull: |
| 5890 | { | 6197 | { |
| 5891 | buf_appendf(buf, "null"); | 6198 | buf_appendf(buf, "null"); |
| ... | @@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5900 | { | 6207 | { |
| 5901 | if (get_codegen_ptr_type(const_val->type) != nullptr) | 6208 | if (get_codegen_ptr_type(const_val->type) != nullptr) |
| 5902 | return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); | 6209 | return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); |
| 6210 | if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet) | ||
| 6211 | return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type); | ||
| 5903 | if (const_val->data.x_optional) { | 6212 | if (const_val->data.x_optional) { |
| 5904 | render_const_value(g, buf, const_val->data.x_optional); | 6213 | render_const_value(g, buf, const_val->data.x_optional); |
| 5905 | } else { | 6214 | } else { |
| ... | @@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5925 | } | 6234 | } |
| 5926 | case ZigTypeIdStruct: | 6235 | case ZigTypeIdStruct: |
| 5927 | { | 6236 | { |
| 5928 | buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name)); | 6237 | if (is_slice(type_entry)) { |
| 6238 | ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index]; | ||
| 6239 | size_t len = bigint_as_unsigned(&len_val->data.x_bigint); | ||
| 6240 | |||
| 6241 | ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; | ||
| 6242 | if (ptr_val->special == ConstValSpecialUndef) { | ||
| 6243 | assert(len == 0); | ||
| 6244 | buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name)); | ||
| 6245 | return; | ||
| 6246 | } | ||
| 6247 | assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); | ||
| 6248 | ConstExprValue *array = ptr_val->data.x_ptr.data.base_array.array_val; | ||
| 6249 | size_t start = ptr_val->data.x_ptr.data.base_array.elem_index; | ||
| 6250 | |||
| 6251 | render_const_val_array(g, buf, &type_entry->name, array, start, len); | ||
| 6252 | } else { | ||
| 6253 | buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name)); | ||
| 6254 | } | ||
| 5929 | return; | 6255 | return; |
| 5930 | } | 6256 | } |
| 5931 | case ZigTypeIdEnum: | 6257 | case ZigTypeIdEnum: |
| ... | @@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5937 | case ZigTypeIdErrorUnion: | 6263 | case ZigTypeIdErrorUnion: |
| 5938 | { | 6264 | { |
| 5939 | buf_appendf(buf, "%s(", buf_ptr(&type_entry->name)); | 6265 | buf_appendf(buf, "%s(", buf_ptr(&type_entry->name)); |
| 5940 | if (const_val->data.x_err_union.err == nullptr) { | 6266 | ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; |
| 6267 | if (err_set == nullptr) { | ||
| 5941 | render_const_value(g, buf, const_val->data.x_err_union.payload); | 6268 | render_const_value(g, buf, const_val->data.x_err_union.payload); |
| 5942 | } else { | 6269 | } else { |
| 5943 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name), | 6270 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name), |
| 5944 | buf_ptr(&const_val->data.x_err_union.err->name)); | 6271 | buf_ptr(&err_set->name)); |
| 5945 | } | 6272 | } |
| 5946 | buf_appendf(buf, ")"); | 6273 | buf_appendf(buf, ")"); |
| 5947 | return; | 6274 | return; |
| ... | @@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5956 | return; | 6283 | return; |
| 5957 | } | 6284 | } |
| 5958 | case ZigTypeIdErrorSet: | 6285 | case ZigTypeIdErrorSet: |
| 5959 | { | 6286 | return render_const_val_err_set(g, buf, const_val, type_entry); |
| 5960 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); | ||
| 5961 | return; | ||
| 5962 | } | ||
| 5963 | case ZigTypeIdArgTuple: | 6287 | case ZigTypeIdArgTuple: |
| 5964 | { | 6288 | { |
| 5965 | buf_appendf(buf, "(args value)"); | 6289 | buf_appendf(buf, "(args value)"); |
| ... | @@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) { |
| 6035 | ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) + | 6359 | ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) + |
| 6036 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + | 6360 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + |
| 6037 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + | 6361 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + |
| 6362 | (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) + | ||
| 6038 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + | 6363 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + |
| 6039 | (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + | 6364 | (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + |
| 6040 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); | 6365 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); |
| ... | @@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) { |
| 6044 | case ZigTypeIdInt: | 6369 | case ZigTypeIdInt: |
| 6045 | return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + | 6370 | return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + |
| 6046 | (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557); | 6371 | (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557); |
| 6372 | case ZigTypeIdVector: | ||
| 6373 | return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681); | ||
| 6047 | } | 6374 | } |
| 6048 | zig_unreachable(); | 6375 | zig_unreachable(); |
| 6049 | } | 6376 | } |
| ... | @@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6083 | a.data.pointer.ptr_len == b.data.pointer.ptr_len && | 6410 | a.data.pointer.ptr_len == b.data.pointer.ptr_len && |
| 6084 | a.data.pointer.is_const == b.data.pointer.is_const && | 6411 | a.data.pointer.is_const == b.data.pointer.is_const && |
| 6085 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && | 6412 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && |
| 6413 | a.data.pointer.allow_zero == b.data.pointer.allow_zero && | ||
| 6086 | a.data.pointer.alignment == b.data.pointer.alignment && | 6414 | a.data.pointer.alignment == b.data.pointer.alignment && |
| 6087 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && | 6415 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && |
| 6088 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; | 6416 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; |
| ... | @@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6092 | case ZigTypeIdInt: | 6420 | case ZigTypeIdInt: |
| 6093 | return a.data.integer.is_signed == b.data.integer.is_signed && | 6421 | return a.data.integer.is_signed == b.data.integer.is_signed && |
| 6094 | a.data.integer.bit_count == b.data.integer.bit_count; | 6422 | a.data.integer.bit_count == b.data.integer.bit_count; |
| 6423 | case ZigTypeIdVector: | ||
| 6424 | return a.data.vector.elem_type == b.data.vector.elem_type && | ||
| 6425 | a.data.vector.len == b.data.vector.len; | ||
| 6095 | } | 6426 | } |
| 6096 | zig_unreachable(); | 6427 | zig_unreachable(); |
| 6097 | } | 6428 | } |
| ... | @@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { | ... | @@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { |
| 6110 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089; | 6441 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089; |
| 6111 | case ZigLLVMFnIdSqrt: | 6442 | case ZigLLVMFnIdSqrt: |
| 6112 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385; | 6443 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385; |
| 6444 | case ZigLLVMFnIdBswap: | ||
| 6445 | return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335; | ||
| 6446 | case ZigLLVMFnIdBitReverse: | ||
| 6447 | return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431; | ||
| 6113 | case ZigLLVMFnIdOverflowArithmetic: | 6448 | case ZigLLVMFnIdOverflowArithmetic: |
| 6114 | return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) + | 6449 | return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) + |
| 6115 | ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) + | 6450 | ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) + |
| 6116 | ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820); | 6451 | ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820) + |
| 6452 | x.data.overflow_arithmetic.vector_len * 1435156945; | ||
| 6117 | } | 6453 | } |
| 6118 | zig_unreachable(); | 6454 | zig_unreachable(); |
| 6119 | } | 6455 | } |
| ... | @@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { | ... | @@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { |
| 6128 | return a.data.clz.bit_count == b.data.clz.bit_count; | 6464 | return a.data.clz.bit_count == b.data.clz.bit_count; |
| 6129 | case ZigLLVMFnIdPopCount: | 6465 | case ZigLLVMFnIdPopCount: |
| 6130 | return a.data.pop_count.bit_count == b.data.pop_count.bit_count; | 6466 | return a.data.pop_count.bit_count == b.data.pop_count.bit_count; |
| 6467 | case ZigLLVMFnIdBswap: | ||
| 6468 | return a.data.bswap.bit_count == b.data.bswap.bit_count; | ||
| 6469 | case ZigLLVMFnIdBitReverse: | ||
| 6470 | return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count; | ||
| 6131 | case ZigLLVMFnIdFloor: | 6471 | case ZigLLVMFnIdFloor: |
| 6132 | case ZigLLVMFnIdCeil: | 6472 | case ZigLLVMFnIdCeil: |
| 6133 | case ZigLLVMFnIdSqrt: | 6473 | case ZigLLVMFnIdSqrt: |
| ... | @@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { | ... | @@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { |
| 6135 | case ZigLLVMFnIdOverflowArithmetic: | 6475 | case ZigLLVMFnIdOverflowArithmetic: |
| 6136 | return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) && | 6476 | return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) && |
| 6137 | (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) && | 6477 | (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) && |
| 6138 | (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed); | 6478 | (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed) && |
| 6479 | (a.data.overflow_arithmetic.vector_len == b.data.overflow_arithmetic.vector_len); | ||
| 6139 | } | 6480 | } |
| 6140 | zig_unreachable(); | 6481 | zig_unreachable(); |
| 6141 | } | 6482 | } |
| 6142 | 6483 | ||
| 6143 | // Canonicalize the array value as ConstArraySpecialNone | 6484 | // Canonicalize the array value as ConstArraySpecialNone |
| 6144 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | 6485 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6145 | assert(const_val->type->id == ZigTypeIdArray); | 6486 | size_t elem_count; |
| 6487 | ZigType *elem_type; | ||
| 6488 | if (const_val->type->id == ZigTypeIdArray) { | ||
| 6489 | elem_count = const_val->type->data.array.len; | ||
| 6490 | elem_type = const_val->type->data.array.child_type; | ||
| 6491 | } else if (const_val->type->id == ZigTypeIdVector) { | ||
| 6492 | elem_count = const_val->type->data.vector.len; | ||
| 6493 | elem_type = const_val->type->data.vector.elem_type; | ||
| 6494 | } else { | ||
| 6495 | zig_unreachable(); | ||
| 6496 | } | ||
| 6497 | if (const_val->special == ConstValSpecialUndef) { | ||
| 6498 | const_val->special = ConstValSpecialStatic; | ||
| 6499 | const_val->data.x_array.special = ConstArraySpecialUndef; | ||
| 6500 | } | ||
| 6146 | switch (const_val->data.x_array.special) { | 6501 | switch (const_val->data.x_array.special) { |
| 6147 | case ConstArraySpecialNone: | 6502 | case ConstArraySpecialNone: |
| 6148 | return; | 6503 | return; |
| 6149 | case ConstArraySpecialUndef: { | 6504 | case ConstArraySpecialUndef: { |
| 6150 | const_val->data.x_array.special = ConstArraySpecialNone; | 6505 | const_val->data.x_array.special = ConstArraySpecialNone; |
| 6151 | size_t elem_count = const_val->type->data.array.len; | ||
| 6152 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); | 6506 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); |
| 6153 | for (size_t i = 0; i < elem_count; i += 1) { | 6507 | for (size_t i = 0; i < elem_count; i += 1) { |
| 6154 | ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i]; | 6508 | ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i]; |
| 6155 | element_val->type = const_val->type->data.array.child_type; | 6509 | element_val->type = elem_type; |
| 6156 | init_const_undefined(g, element_val); | 6510 | init_const_undefined(g, element_val); |
| 6157 | ConstParent *parent = get_const_val_parent(g, element_val); | 6511 | element_val->parent.id = ConstParentIdArray; |
| 6158 | if (parent != nullptr) { | 6512 | element_val->parent.data.p_array.array_val = const_val; |
| 6159 | parent->id = ConstParentIdArray; | 6513 | element_val->parent.data.p_array.elem_index = i; |
| 6160 | parent->data.p_array.array_val = const_val; | ||
| 6161 | parent->data.p_array.elem_index = i; | ||
| 6162 | } | ||
| 6163 | } | 6514 | } |
| 6164 | return; | 6515 | return; |
| 6165 | } | 6516 | } |
| ... | @@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6170 | g->string_literals_table.maybe_remove(buf); | 6521 | g->string_literals_table.maybe_remove(buf); |
| 6171 | 6522 | ||
| 6172 | const_val->data.x_array.special = ConstArraySpecialNone; | 6523 | const_val->data.x_array.special = ConstArraySpecialNone; |
| 6173 | size_t elem_count = const_val->type->data.array.len; | ||
| 6174 | assert(elem_count == buf_len(buf)); | 6524 | assert(elem_count == buf_len(buf)); |
| 6175 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); | 6525 | const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); |
| 6176 | for (size_t i = 0; i < elem_count; i += 1) { | 6526 | for (size_t i = 0; i < elem_count; i += 1) { |
| ... | @@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6178 | this_char->special = ConstValSpecialStatic; | 6528 | this_char->special = ConstValSpecialStatic; |
| 6179 | this_char->type = g->builtin_types.entry_u8; | 6529 | this_char->type = g->builtin_types.entry_u8; |
| 6180 | bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]); | 6530 | bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]); |
| 6531 | this_char->parent.id = ConstParentIdArray; | ||
| 6532 | this_char->parent.data.p_array.array_val = const_val; | ||
| 6533 | this_char->parent.data.p_array.elem_index = i; | ||
| 6181 | } | 6534 | } |
| 6182 | return; | 6535 | return; |
| 6183 | } | 6536 | } |
| ... | @@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6185 | zig_unreachable(); | 6538 | zig_unreachable(); |
| 6186 | } | 6539 | } |
| 6187 | 6540 | ||
| 6541 | // Deprecated. Reference the parent field directly. | ||
| 6188 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { | 6542 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { |
| 6189 | assert(value->type); | 6543 | return &value->parent; |
| 6190 | ZigType *type_entry = value->type; | ||
| 6191 | if (type_entry->id == ZigTypeIdArray) { | ||
| 6192 | expand_undef_array(g, value); | ||
| 6193 | return &value->data.x_array.data.s_none.parent; | ||
| 6194 | } else if (type_entry->id == ZigTypeIdStruct) { | ||
| 6195 | return &value->data.x_struct.parent; | ||
| 6196 | } else if (type_entry->id == ZigTypeIdUnion) { | ||
| 6197 | return &value->data.x_union.parent; | ||
| 6198 | } | ||
| 6199 | return nullptr; | ||
| 6200 | } | 6544 | } |
| 6201 | 6545 | ||
| 6202 | static const ZigTypeId all_type_ids[] = { | 6546 | static const ZigTypeId all_type_ids[] = { |
| ... | @@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = { | ... | @@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = { |
| 6224 | ZigTypeIdArgTuple, | 6568 | ZigTypeIdArgTuple, |
| 6225 | ZigTypeIdOpaque, | 6569 | ZigTypeIdOpaque, |
| 6226 | ZigTypeIdPromise, | 6570 | ZigTypeIdPromise, |
| 6571 | ZigTypeIdVector, | ||
| 6227 | }; | 6572 | }; |
| 6228 | 6573 | ||
| 6229 | ZigTypeId type_id_at_index(size_t index) { | 6574 | ZigTypeId type_id_at_index(size_t index) { |
| ... | @@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) { | ... | @@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) { |
| 6289 | return 22; | 6634 | return 22; |
| 6290 | case ZigTypeIdPromise: | 6635 | case ZigTypeIdPromise: |
| 6291 | return 23; | 6636 | return 23; |
| 6637 | case ZigTypeIdVector: | ||
| 6638 | return 24; | ||
| 6292 | } | 6639 | } |
| 6293 | zig_unreachable(); | 6640 | zig_unreachable(); |
| 6294 | } | 6641 | } |
| ... | @@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) { | ... | @@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) { |
| 6345 | return "Opaque"; | 6692 | return "Opaque"; |
| 6346 | case ZigTypeIdPromise: | 6693 | case ZigTypeIdPromise: |
| 6347 | return "Promise"; | 6694 | return "Promise"; |
| 6695 | case ZigTypeIdVector: | ||
| 6696 | return "Vector"; | ||
| 6348 | } | 6697 | } |
| 6349 | zig_unreachable(); | 6698 | zig_unreachable(); |
| 6350 | } | 6699 | } |
| ... | @@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { | ... | @@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { |
| 6361 | if (is_libc && g->libc_link_lib != nullptr) | 6710 | if (is_libc && g->libc_link_lib != nullptr) |
| 6362 | return g->libc_link_lib; | 6711 | return g->libc_link_lib; |
| 6363 | 6712 | ||
| 6364 | if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS) { | 6713 | if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD) { |
| 6365 | fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n" | 6714 | fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n" |
| 6366 | "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n"); | 6715 | "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n"); |
| 6367 | exit(1); | 6716 | exit(1); |
| ... | @@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { | ... | @@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { |
| 6424 | resolve_top_level_decl(codegen, tld, false, nullptr); | 6773 | resolve_top_level_decl(codegen, tld, false, nullptr); |
| 6425 | assert(tld->id == TldIdVar); | 6774 | assert(tld->id == TldIdVar); |
| 6426 | TldVar *tld_var = (TldVar *)tld; | 6775 | TldVar *tld_var = (TldVar *)tld; |
| 6427 | ConstExprValue *var_value = tld_var->var->value; | 6776 | ConstExprValue *var_value = tld_var->var->const_value; |
| 6428 | assert(var_value != nullptr); | 6777 | assert(var_value != nullptr); |
| 6429 | return var_value; | 6778 | return var_value; |
| 6430 | } | 6779 | } |
| ... | @@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { | ... | @@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) { |
| 6500 | case ZigTypeIdBool: | 6849 | case ZigTypeIdBool: |
| 6501 | return X64CABIClass_INTEGER; | 6850 | return X64CABIClass_INTEGER; |
| 6502 | case ZigTypeIdFloat: | 6851 | case ZigTypeIdFloat: |
| 6852 | case ZigTypeIdVector: | ||
| 6503 | return X64CABIClass_SSE; | 6853 | return X64CABIClass_SSE; |
| 6504 | case ZigTypeIdStruct: { | 6854 | case ZigTypeIdStruct: { |
| 6505 | // "If the size of an object is larger than four eightbytes, or it contains unaligned | 6855 | // "If the size of an object is larger than four eightbytes, or it contains unaligned |
| ... | @@ -6579,3 +6929,36 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f | ... | @@ -6579,3 +6929,36 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f |
| 6579 | LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index); | 6929 | LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index); |
| 6580 | return LLVMStoreSizeOfType(g->target_data_ref, field_type); | 6930 | return LLVMStoreSizeOfType(g->target_data_ref, field_type); |
| 6581 | } | 6931 | } |
| 6932 | |||
| 6933 | Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, | ||
| 6934 | ConstExprValue *const_val, ZigType *wanted_type) | ||
| 6935 | { | ||
| 6936 | ConstExprValue ptr_val = {}; | ||
| 6937 | ptr_val.special = ConstValSpecialStatic; | ||
| 6938 | ptr_val.type = get_pointer_to_type(codegen, wanted_type, true); | ||
| 6939 | ptr_val.data.x_ptr.mut = ConstPtrMutComptimeConst; | ||
| 6940 | ptr_val.data.x_ptr.special = ConstPtrSpecialRef; | ||
| 6941 | ptr_val.data.x_ptr.data.ref.pointee = const_val; | ||
| 6942 | if (const_ptr_pointee(ira, codegen, &ptr_val, source_node) == nullptr) | ||
| 6943 | return ErrorSemanticAnalyzeFail; | ||
| 6944 | |||
| 6945 | return ErrorNone; | ||
| 6946 | } | ||
| 6947 | |||
| 6948 | const char *container_string(ContainerKind kind) { | ||
| 6949 | switch (kind) { | ||
| 6950 | case ContainerKindEnum: return "enum"; | ||
| 6951 | case ContainerKindStruct: return "struct"; | ||
| 6952 | case ContainerKindUnion: return "union"; | ||
| 6953 | } | ||
| 6954 | zig_unreachable(); | ||
| 6955 | } | ||
| 6956 | |||
| 6957 | bool ptr_allows_addr_zero(ZigType *ptr_type) { | ||
| 6958 | if (ptr_type->id == ZigTypeIdPointer) { | ||
| 6959 | return ptr_type->data.pointer.allow_zero; | ||
| 6960 | } else if (ptr_type->id == ZigTypeIdOptional) { | ||
| 6961 | return true; | ||
| 6962 | } | ||
| 6963 | return false; | ||
| 6964 | } |
src/analyze.hpp+20-2| ... | @@ -12,14 +12,17 @@ | ... | @@ -12,14 +12,17 @@ |
| 12 | 12 | ||
| 13 | void semantic_analyze(CodeGen *g); | 13 | void semantic_analyze(CodeGen *g); |
| 14 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); | 14 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 15 | ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg); | ||
| 15 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg); | 16 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg); |
| 16 | ZigType *new_type_table_entry(ZigTypeId id); | 17 | ZigType *new_type_table_entry(ZigTypeId id); |
| 17 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); | 18 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); |
| 18 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 19 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 19 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count); | 20 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count); |
| 20 | uint64_t type_size(CodeGen *g, ZigType *type_entry); | 21 | uint64_t type_size(CodeGen *g, ZigType *type_entry); |
| 22 | uint64_t type_size_store(CodeGen *g, ZigType *type_entry); | ||
| 21 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); | 23 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); |
| 22 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 24 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| 25 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type); | ||
| 23 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); | 26 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); |
| 24 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); | 27 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 25 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); | 28 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
| ... | @@ -42,7 +45,9 @@ void find_libc_include_path(CodeGen *g); | ... | @@ -42,7 +45,9 @@ void find_libc_include_path(CodeGen *g); |
| 42 | void find_libc_lib_path(CodeGen *g); | 45 | void find_libc_lib_path(CodeGen *g); |
| 43 | 46 | ||
| 44 | bool type_has_bits(ZigType *type_entry); | 47 | bool type_has_bits(ZigType *type_entry); |
| 45 | 48 | bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry); | |
| 49 | bool ptr_allows_addr_zero(ZigType *ptr_type); | ||
| 50 | bool type_is_nonnull_ptr(ZigType *type); | ||
| 46 | 51 | ||
| 47 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); | 52 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); |
| 48 | 53 | ||
| ... | @@ -73,6 +78,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag); | ... | @@ -73,6 +78,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag); |
| 73 | bool is_ref(ZigType *type_entry); | 78 | bool is_ref(ZigType *type_entry); |
| 74 | bool is_array_ref(ZigType *type_entry); | 79 | bool is_array_ref(ZigType *type_entry); |
| 75 | bool is_container_ref(ZigType *type_entry); | 80 | bool is_container_ref(ZigType *type_entry); |
| 81 | bool is_valid_vector_elem_type(ZigType *elem_type); | ||
| 76 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); | 82 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| 77 | void scan_import(CodeGen *g, ImportTableEntry *import); | 83 | void scan_import(CodeGen *g, ImportTableEntry *import); |
| 78 | void preview_use_decl(CodeGen *g, AstNode *node); | 84 | void preview_use_decl(CodeGen *g, AstNode *node); |
| ... | @@ -81,7 +87,7 @@ ZigFn *scope_fn_entry(Scope *scope); | ... | @@ -81,7 +87,7 @@ ZigFn *scope_fn_entry(Scope *scope); |
| 81 | ImportTableEntry *get_scope_import(Scope *scope); | 87 | ImportTableEntry *get_scope_import(Scope *scope); |
| 82 | void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope); | 88 | void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope); |
| 83 | ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, | 89 | ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, |
| 84 | bool is_const, ConstExprValue *init_value, Tld *src_tld); | 90 | bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type); |
| 85 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); | 91 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); |
| 86 | ZigFn *create_fn(CodeGen *g, AstNode *proto_node); | 92 | ZigFn *create_fn(CodeGen *g, AstNode *proto_node); |
| 87 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); | 93 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); |
| ... | @@ -212,6 +218,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); | ... | @@ -212,6 +218,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); |
| 212 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); | 218 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); |
| 213 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); | 219 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); |
| 214 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); | 220 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); |
| 221 | const char *container_string(ContainerKind kind); | ||
| 215 | 222 | ||
| 216 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); | 223 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); |
| 217 | 224 | ||
| ... | @@ -222,4 +229,15 @@ enum ReqCompTime { | ... | @@ -222,4 +229,15 @@ enum ReqCompTime { |
| 222 | }; | 229 | }; |
| 223 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); | 230 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); |
| 224 | 231 | ||
| 232 | enum OnePossibleValue { | ||
| 233 | OnePossibleValueInvalid, | ||
| 234 | OnePossibleValueNo, | ||
| 235 | OnePossibleValueYes, | ||
| 236 | }; | ||
| 237 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); | ||
| 238 | |||
| 239 | Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, | ||
| 240 | ConstExprValue *const_val, ZigType *wanted_type); | ||
| 241 | |||
| 242 | void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn); | ||
| 225 | #endif | 243 | #endif |
src/ast_render.cpp+24-18| ... | @@ -132,13 +132,23 @@ static const char *const_or_var_string(bool is_const) { | ... | @@ -132,13 +132,23 @@ static const char *const_or_var_string(bool is_const) { |
| 132 | return is_const ? "const" : "var"; | 132 | return is_const ? "const" : "var"; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | const char *container_string(ContainerKind kind) { | 135 | static const char *thread_local_string(Token *tok) { |
| 136 | switch (kind) { | 136 | return (tok == nullptr) ? "" : "threadlocal "; |
| 137 | case ContainerKindEnum: return "enum"; | 137 | } |
| 138 | case ContainerKindStruct: return "struct"; | 138 | |
| 139 | case ContainerKindUnion: return "union"; | 139 | static const char *token_to_ptr_len_str(Token *tok) { |
| 140 | assert(tok != nullptr); | ||
| 141 | switch (tok->id) { | ||
| 142 | case TokenIdStar: | ||
| 143 | case TokenIdStarStar: | ||
| 144 | return "*"; | ||
| 145 | case TokenIdBracketStarBracket: | ||
| 146 | return "[*]"; | ||
| 147 | case TokenIdBracketStarCBracket: | ||
| 148 | return "[*c]"; | ||
| 149 | default: | ||
| 150 | zig_unreachable(); | ||
| 140 | } | 151 | } |
| 141 | zig_unreachable(); | ||
| 142 | } | 152 | } |
| 143 | 153 | ||
| 144 | static const char *node_type_str(NodeType node_type) { | 154 | static const char *node_type_str(NodeType node_type) { |
| ... | @@ -233,8 +243,8 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -233,8 +243,8 @@ static const char *node_type_str(NodeType node_type) { |
| 233 | return "ErrorType"; | 243 | return "ErrorType"; |
| 234 | case NodeTypeIfErrorExpr: | 244 | case NodeTypeIfErrorExpr: |
| 235 | return "IfErrorExpr"; | 245 | return "IfErrorExpr"; |
| 236 | case NodeTypeTestExpr: | 246 | case NodeTypeIfOptional: |
| 237 | return "TestExpr"; | 247 | return "IfOptional"; |
| 238 | case NodeTypeErrorSetDecl: | 248 | case NodeTypeErrorSetDecl: |
| 239 | return "ErrorSetDecl"; | 249 | return "ErrorSetDecl"; |
| 240 | case NodeTypeCancel: | 250 | case NodeTypeCancel: |
| ... | @@ -387,7 +397,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) { | ... | @@ -387,7 +397,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) { |
| 387 | if (node->data.if_err_expr.else_node) | 397 | if (node->data.if_err_expr.else_node) |
| 388 | return statement_terminates_without_semicolon(node->data.if_err_expr.else_node); | 398 | return statement_terminates_without_semicolon(node->data.if_err_expr.else_node); |
| 389 | return node->data.if_err_expr.then_node->type == NodeTypeBlock; | 399 | return node->data.if_err_expr.then_node->type == NodeTypeBlock; |
| 390 | case NodeTypeTestExpr: | 400 | case NodeTypeIfOptional: |
| 391 | if (node->data.test_expr.else_node) | 401 | if (node->data.test_expr.else_node) |
| 392 | return statement_terminates_without_semicolon(node->data.test_expr.else_node); | 402 | return statement_terminates_without_semicolon(node->data.test_expr.else_node); |
| 393 | return node->data.test_expr.then_node->type == NodeTypeBlock; | 403 | return node->data.test_expr.then_node->type == NodeTypeBlock; |
| ... | @@ -554,8 +564,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -554,8 +564,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 554 | { | 564 | { |
| 555 | const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod); | 565 | const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod); |
| 556 | const char *extern_str = extern_string(node->data.variable_declaration.is_extern); | 566 | const char *extern_str = extern_string(node->data.variable_declaration.is_extern); |
| 567 | const char *thread_local_str = thread_local_string(node->data.variable_declaration.threadlocal_tok); | ||
| 557 | const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const); | 568 | const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const); |
| 558 | fprintf(ar->f, "%s%s%s ", pub_str, extern_str, const_or_var); | 569 | fprintf(ar->f, "%s%s%s%s ", pub_str, extern_str, thread_local_str, const_or_var); |
| 559 | print_symbol(ar, node->data.variable_declaration.symbol); | 570 | print_symbol(ar, node->data.variable_declaration.symbol); |
| 560 | 571 | ||
| 561 | if (node->data.variable_declaration.type) { | 572 | if (node->data.variable_declaration.type) { |
| ... | @@ -639,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -639,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 639 | case NodeTypePointerType: | 650 | case NodeTypePointerType: |
| 640 | { | 651 | { |
| 641 | if (!grouped) fprintf(ar->f, "("); | 652 | if (!grouped) fprintf(ar->f, "("); |
| 642 | const char *star = "[*]"; | 653 | const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token); |
| 643 | if (node->data.pointer_type.star_token != nullptr && | 654 | fprintf(ar->f, "%s", ptr_len_str); |
| 644 | (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar)) | ||
| 645 | { | ||
| 646 | star = "*"; | ||
| 647 | } | ||
| 648 | fprintf(ar->f, "%s", star); | ||
| 649 | if (node->data.pointer_type.align_expr != nullptr) { | 655 | if (node->data.pointer_type.align_expr != nullptr) { |
| 650 | fprintf(ar->f, "align("); | 656 | fprintf(ar->f, "align("); |
| 651 | render_node_grouped(ar, node->data.pointer_type.align_expr); | 657 | render_node_grouped(ar, node->data.pointer_type.align_expr); |
| ... | @@ -974,7 +980,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -974,7 +980,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 974 | } | 980 | } |
| 975 | break; | 981 | break; |
| 976 | } | 982 | } |
| 977 | case NodeTypeTestExpr: | 983 | case NodeTypeIfOptional: |
| 978 | { | 984 | { |
| 979 | fprintf(ar->f, "if ("); | 985 | fprintf(ar->f, "if ("); |
| 980 | render_node_grouped(ar, node->data.test_expr.target_node); | 986 | render_node_grouped(ar, node->data.test_expr.target_node); |
src/ast_render.hpp-3| ... | @@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent); | ... | @@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent); |
| 17 | 17 | ||
| 18 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); | 18 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); |
| 19 | 19 | ||
| 20 | const char *container_string(ContainerKind kind); | ||
| 21 | |||
| 22 | #endif | 20 | #endif |
| 23 |
src/bigint.cpp+1| ... | @@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) { | ... | @@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) { |
| 1722 | 1722 | ||
| 1723 | bigint_add(x, &copy, &one); | 1723 | bigint_add(x, &copy, &one); |
| 1724 | } | 1724 | } |
| 1725 |
src/cache_hash.cpp+3-13| ... | @@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents | ... | @@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents |
| 222 | assert(chf->path != nullptr); | 222 | assert(chf->path != nullptr); |
| 223 | 223 | ||
| 224 | OsFile this_file; | 224 | OsFile this_file; |
| 225 | if ((err = os_file_open_r(chf->path, &this_file))) | 225 | if ((err = os_file_open_r(chf->path, &this_file, &chf->mtime))) |
| 226 | return err; | 226 | return err; |
| 227 | 227 | ||
| 228 | if ((err = os_file_mtime(this_file, &chf->mtime))) { | ||
| 229 | os_file_close(this_file); | ||
| 230 | return err; | ||
| 231 | } | ||
| 232 | |||
| 233 | if ((err = hash_file(chf->bin_digest, this_file, contents))) { | 228 | if ((err = hash_file(chf->bin_digest, this_file, contents))) { |
| 234 | os_file_close(this_file); | 229 | os_file_close(this_file); |
| 235 | return err; | 230 | return err; |
| ... | @@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { | ... | @@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 351 | 346 | ||
| 352 | // if the mtime matches we can trust the digest | 347 | // if the mtime matches we can trust the digest |
| 353 | OsFile this_file; | 348 | OsFile this_file; |
| 354 | if ((err = os_file_open_r(chf->path, &this_file))) { | 349 | OsTimeStamp actual_mtime; |
| 350 | if ((err = os_file_open_r(chf->path, &this_file, &actual_mtime))) { | ||
| 355 | fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err)); | 351 | fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err)); |
| 356 | os_file_close(ch->manifest_file); | 352 | os_file_close(ch->manifest_file); |
| 357 | return ErrorCacheUnavailable; | 353 | return ErrorCacheUnavailable; |
| 358 | } | 354 | } |
| 359 | OsTimeStamp actual_mtime; | ||
| 360 | if ((err = os_file_mtime(this_file, &actual_mtime))) { | ||
| 361 | os_file_close(this_file); | ||
| 362 | os_file_close(ch->manifest_file); | ||
| 363 | return err; | ||
| 364 | } | ||
| 365 | if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) { | 355 | if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) { |
| 366 | os_file_close(this_file); | 356 | os_file_close(this_file); |
| 367 | } else { | 357 | } else { |
src/codegen.cpp+686-296| ... | @@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = { | ... | @@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = { |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, | 90 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, |
| 91 | Buf *zig_lib_dir) | 91 | Buf *zig_lib_dir, Buf *override_std_dir) |
| 92 | { | 92 | { |
| 93 | CodeGen *g = allocate<CodeGen>(1); | 93 | CodeGen *g = allocate<CodeGen>(1); |
| 94 | 94 | ||
| ... | @@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out | ... | @@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 96 | 96 | ||
| 97 | g->zig_lib_dir = zig_lib_dir; | 97 | g->zig_lib_dir = zig_lib_dir; |
| 98 | 98 | ||
| 99 | g->zig_std_dir = buf_alloc(); | 99 | if (override_std_dir == nullptr) { |
| 100 | os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); | 100 | g->zig_std_dir = buf_alloc(); |
| 101 | os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); | ||
| 102 | } else { | ||
| 103 | g->zig_std_dir = override_std_dir; | ||
| 104 | } | ||
| 101 | 105 | ||
| 102 | g->zig_c_headers_dir = buf_alloc(); | 106 | g->zig_c_headers_dir = buf_alloc(); |
| 103 | os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); | 107 | os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); |
| ... | @@ -118,6 +122,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out | ... | @@ -118,6 +122,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 118 | g->string_literals_table.init(16); | 122 | g->string_literals_table.init(16); |
| 119 | g->type_info_cache.init(32); | 123 | g->type_info_cache.init(32); |
| 120 | g->is_test_build = false; | 124 | g->is_test_build = false; |
| 125 | g->is_single_threaded = false; | ||
| 121 | buf_resize(&g->global_asm, 0); | 126 | buf_resize(&g->global_asm, 0); |
| 122 | 127 | ||
| 123 | for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { | 128 | for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { |
| ... | @@ -178,7 +183,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out | ... | @@ -178,7 +183,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 178 | 183 | ||
| 179 | // On Darwin/MacOS/iOS, we always link libSystem which contains libc. | 184 | // On Darwin/MacOS/iOS, we always link libSystem which contains libc. |
| 180 | if (g->zig_target.os == OsMacOSX || | 185 | if (g->zig_target.os == OsMacOSX || |
| 181 | g->zig_target.os == OsIOS) | 186 | g->zig_target.os == OsIOS || |
| 187 | 	g->zig_target.os == OsFreeBSD) | ||
| 182 | { | 188 | { |
| 183 | g->libc_link_lib = create_link_lib(buf_create_from_str("c")); | 189 | g->libc_link_lib = create_link_lib(buf_create_from_str("c")); |
| 184 | g->link_libs_list.append(g->libc_link_lib); | 190 | g->link_libs_list.append(g->libc_link_lib); |
| ... | @@ -291,11 +297,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) { | ... | @@ -291,11 +297,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) { |
| 291 | g->darwin_frameworks.append(buf_create_from_str(framework)); | 297 | g->darwin_frameworks.append(buf_create_from_str(framework)); |
| 292 | } | 298 | } |
| 293 | 299 | ||
| 294 | void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) { | ||
| 295 | g->windows_subsystem_windows = mwindows; | ||
| 296 | g->windows_subsystem_console = mconsole; | ||
| 297 | } | ||
| 298 | |||
| 299 | void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) { | 300 | void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) { |
| 300 | g->mmacosx_version_min = mmacosx_version_min; | 301 | g->mmacosx_version_min = mmacosx_version_min; |
| 301 | } | 302 | } |
| ... | @@ -317,6 +318,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char * | ... | @@ -317,6 +318,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char * |
| 317 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name); | 318 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name); |
| 318 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name); | 319 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name); |
| 319 | static void generate_error_name_table(CodeGen *g); | 320 | static void generate_error_name_table(CodeGen *g); |
| 321 | static bool value_is_all_undef(ConstExprValue *const_val); | ||
| 322 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); | ||
| 320 | 323 | ||
| 321 | static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { | 324 | static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { |
| 322 | unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); | 325 | unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); |
| ... | @@ -465,6 +468,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag | ... | @@ -465,6 +468,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag |
| 465 | } | 468 | } |
| 466 | } | 469 | } |
| 467 | 470 | ||
| 471 | static bool cc_want_sret_attr(CallingConvention cc) { | ||
| 472 | switch (cc) { | ||
| 473 | case CallingConventionNaked: | ||
| 474 | zig_unreachable(); | ||
| 475 | case CallingConventionC: | ||
| 476 | case CallingConventionCold: | ||
| 477 | case CallingConventionStdcall: | ||
| 478 | return true; | ||
| 479 | case CallingConventionAsync: | ||
| 480 | case CallingConventionUnspecified: | ||
| 481 | return false; | ||
| 482 | } | ||
| 483 | zig_unreachable(); | ||
| 484 | } | ||
| 485 | |||
| 468 | static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | 486 | static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 469 | if (fn_table_entry->llvm_value) | 487 | if (fn_table_entry->llvm_value) |
| 470 | return fn_table_entry->llvm_value; | 488 | return fn_table_entry->llvm_value; |
| ... | @@ -599,12 +617,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -599,12 +617,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 599 | unsigned init_gen_i = 0; | 617 | unsigned init_gen_i = 0; |
| 600 | if (!type_has_bits(return_type)) { | 618 | if (!type_has_bits(return_type)) { |
| 601 | // nothing to do | 619 | // nothing to do |
| 602 | } else if (type_is_codegen_pointer(return_type)) { | 620 | } else if (type_is_nonnull_ptr(return_type)) { |
| 603 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); | 621 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 604 | } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { | 622 | } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { |
| 605 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); | 623 | // Sret pointers must not be address 0 |
| 606 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); | 624 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 607 | if (cc == CallingConventionC) { | 625 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); |
| 626 | if (cc_want_sret_attr(cc)) { | ||
| 608 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias"); | 627 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias"); |
| 609 | } | 628 | } |
| 610 | init_gen_i = 1; | 629 | init_gen_i = 1; |
| ... | @@ -619,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -619,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 619 | 638 | ||
| 620 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); | 639 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| 621 | if (err_ret_trace_arg_index != UINT32_MAX) { | 640 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 641 | // Error return trace memory is in the stack, which is impossible to be at address 0 | ||
| 642 | // on any architecture. | ||
| 622 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); | 643 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); |
| 623 | } | 644 | } |
| 624 | 645 | ||
| ... | @@ -653,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { | ... | @@ -653,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 653 | ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, | 674 | ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, |
| 654 | fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "", | 675 | fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "", |
| 655 | import->di_file, line_number, | 676 | import->di_file, line_number, |
| 656 | fn_table_entry->type_entry->di_type, is_internal_linkage, | 677 | fn_table_entry->type_entry->data.fn.raw_di_type, is_internal_linkage, |
| 657 | is_definition, scope_line, flags, is_optimized, nullptr); | 678 | is_definition, scope_line, flags, is_optimized, nullptr); |
| 658 | 679 | ||
| 659 | scope->di_scope = ZigLLVMSubprogramToScope(subprogram); | 680 | scope->di_scope = ZigLLVMSubprogramToScope(subprogram); |
| ... | @@ -697,38 +718,59 @@ static void clear_debug_source_node(CodeGen *g) { | ... | @@ -697,38 +718,59 @@ static void clear_debug_source_node(CodeGen *g) { |
| 697 | ZigLLVMClearCurrentDebugLocation(g->builder); | 718 | ZigLLVMClearCurrentDebugLocation(g->builder); |
| 698 | } | 719 | } |
| 699 | 720 | ||
| 700 | static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *type_entry, | 721 | static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type, |
| 701 | const char *signed_name, const char *unsigned_name) | 722 | const char *signed_name, const char *unsigned_name) |
| 702 | { | 723 | { |
| 724 | ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; | ||
| 703 | char fn_name[64]; | 725 | char fn_name[64]; |
| 704 | 726 | ||
| 705 | assert(type_entry->id == ZigTypeIdInt); | 727 | assert(int_type->id == ZigTypeIdInt); |
| 706 | const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name; | 728 | const char *signed_str = int_type->data.integral.is_signed ? signed_name : unsigned_name; |
| 707 | sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, type_entry->data.integral.bit_count); | ||
| 708 | 729 | ||
| 709 | LLVMTypeRef return_elem_types[] = { | ||
| 710 | type_entry->type_ref, | ||
| 711 | LLVMInt1Type(), | ||
| 712 | }; | ||
| 713 | LLVMTypeRef param_types[] = { | 730 | LLVMTypeRef param_types[] = { |
| 714 | type_entry->type_ref, | 731 | operand_type->type_ref, |
| 715 | type_entry->type_ref, | 732 | operand_type->type_ref, |
| 716 | }; | 733 | }; |
| 717 | LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false); | 734 | |
| 718 | LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false); | 735 | if (operand_type->id == ZigTypeIdVector) { |
| 719 | LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type); | 736 | sprintf(fn_name, "llvm.%s.with.overflow.v%" PRIu32 "i%" PRIu32, signed_str, |
| 720 | assert(LLVMGetIntrinsicID(fn_val)); | 737 | operand_type->data.vector.len, int_type->data.integral.bit_count); |
| 721 | return fn_val; | 738 | |
| 739 | LLVMTypeRef return_elem_types[] = { | ||
| 740 | operand_type->type_ref, | ||
| 741 | LLVMVectorType(LLVMInt1Type(), operand_type->data.vector.len), | ||
| 742 | }; | ||
| 743 | LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false); | ||
| 744 | LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false); | ||
| 745 | LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type); | ||
| 746 | assert(LLVMGetIntrinsicID(fn_val)); | ||
| 747 | return fn_val; | ||
| 748 | } else { | ||
| 749 | sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, int_type->data.integral.bit_count); | ||
| 750 | |||
| 751 | LLVMTypeRef return_elem_types[] = { | ||
| 752 | operand_type->type_ref, | ||
| 753 | LLVMInt1Type(), | ||
| 754 | }; | ||
| 755 | LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false); | ||
| 756 | LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false); | ||
| 757 | LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type); | ||
| 758 | assert(LLVMGetIntrinsicID(fn_val)); | ||
| 759 | return fn_val; | ||
| 760 | } | ||
| 722 | } | 761 | } |
| 723 | 762 | ||
| 724 | static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubMul add_sub_mul) { | 763 | static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSubMul add_sub_mul) { |
| 725 | assert(type_entry->id == ZigTypeIdInt); | 764 | ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; |
| 765 | assert(int_type->id == ZigTypeIdInt); | ||
| 726 | 766 | ||
| 727 | ZigLLVMFnKey key = {}; | 767 | ZigLLVMFnKey key = {}; |
| 728 | key.id = ZigLLVMFnIdOverflowArithmetic; | 768 | key.id = ZigLLVMFnIdOverflowArithmetic; |
| 729 | key.data.overflow_arithmetic.is_signed = type_entry->data.integral.is_signed; | 769 | key.data.overflow_arithmetic.is_signed = int_type->data.integral.is_signed; |
| 730 | key.data.overflow_arithmetic.add_sub_mul = add_sub_mul; | 770 | key.data.overflow_arithmetic.add_sub_mul = add_sub_mul; |
| 731 | key.data.overflow_arithmetic.bit_count = (uint32_t)type_entry->data.integral.bit_count; | 771 | key.data.overflow_arithmetic.bit_count = (uint32_t)int_type->data.integral.bit_count; |
| 772 | key.data.overflow_arithmetic.vector_len = (operand_type->id == ZigTypeIdVector) ? | ||
| 773 | operand_type->data.vector.len : 0; | ||
| 732 | 774 | ||
| 733 | auto existing_entry = g->llvm_fn_table.maybe_get(key); | 775 | auto existing_entry = g->llvm_fn_table.maybe_get(key); |
| 734 | if (existing_entry) | 776 | if (existing_entry) |
| ... | @@ -737,13 +779,13 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubM | ... | @@ -737,13 +779,13 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubM |
| 737 | LLVMValueRef fn_val; | 779 | LLVMValueRef fn_val; |
| 738 | switch (add_sub_mul) { | 780 | switch (add_sub_mul) { |
| 739 | case AddSubMulAdd: | 781 | case AddSubMulAdd: |
| 740 | fn_val = get_arithmetic_overflow_fn(g, type_entry, "sadd", "uadd"); | 782 | fn_val = get_arithmetic_overflow_fn(g, operand_type, "sadd", "uadd"); |
| 741 | break; | 783 | break; |
| 742 | case AddSubMulSub: | 784 | case AddSubMulSub: |
| 743 | fn_val = get_arithmetic_overflow_fn(g, type_entry, "ssub", "usub"); | 785 | fn_val = get_arithmetic_overflow_fn(g, operand_type, "ssub", "usub"); |
| 744 | break; | 786 | break; |
| 745 | case AddSubMulMul: | 787 | case AddSubMulMul: |
| 746 | fn_val = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul"); | 788 | fn_val = get_arithmetic_overflow_fn(g, operand_type, "smul", "umul"); |
| 747 | break; | 789 | break; |
| 748 | } | 790 | } |
| 749 | 791 | ||
| ... | @@ -911,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { | ... | @@ -911,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 911 | return buf_create_from_str("invalid enum value"); | 953 | return buf_create_from_str("invalid enum value"); |
| 912 | case PanicMsgIdFloatToInt: | 954 | case PanicMsgIdFloatToInt: |
| 913 | return buf_create_from_str("integer part of floating point value out of bounds"); | 955 | return buf_create_from_str("integer part of floating point value out of bounds"); |
| 956 | case PanicMsgIdPtrCastNull: | ||
| 957 | return buf_create_from_str("cast causes pointer to be null"); | ||
| 914 | } | 958 | } |
| 915 | zig_unreachable(); | 959 | zig_unreachable(); |
| 916 | } | 960 | } |
| ... | @@ -1205,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { | ... | @@ -1205,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { |
| 1205 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | 1249 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 1206 | addLLVMFnAttr(fn_val, "nounwind"); | 1250 | addLLVMFnAttr(fn_val, "nounwind"); |
| 1207 | add_uwtable_attr(g, fn_val); | 1251 | add_uwtable_attr(g, fn_val); |
| 1252 | // Error return trace memory is in the stack, which is impossible to be at address 0 | ||
| 1253 | // on any architecture. | ||
| 1208 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | 1254 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 1209 | if (g->build_mode == BuildModeDebug) { | 1255 | if (g->build_mode == BuildModeDebug) { |
| 1210 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); | 1256 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| ... | @@ -1279,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { | ... | @@ -1279,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { |
| 1279 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | 1325 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 1280 | addLLVMFnAttr(fn_val, "nounwind"); | 1326 | addLLVMFnAttr(fn_val, "nounwind"); |
| 1281 | add_uwtable_attr(g, fn_val); | 1327 | add_uwtable_attr(g, fn_val); |
| 1328 | // Error return trace memory is in the stack, which is impossible to be at address 0 | ||
| 1329 | // on any architecture. | ||
| 1282 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | 1330 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 1283 | addLLVMArgAttr(fn_val, (unsigned)0, "noalias"); | 1331 | addLLVMArgAttr(fn_val, (unsigned)0, "noalias"); |
| 1284 | addLLVMArgAttr(fn_val, (unsigned)0, "writeonly"); | 1332 | addLLVMArgAttr(fn_val, (unsigned)0, "writeonly"); |
| 1333 | // Error return trace memory is in the stack, which is impossible to be at address 0 | ||
| 1334 | // on any architecture. | ||
| 1285 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); | 1335 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); |
| 1286 | addLLVMArgAttr(fn_val, (unsigned)1, "noalias"); | 1336 | addLLVMArgAttr(fn_val, (unsigned)1, "noalias"); |
| 1287 | addLLVMArgAttr(fn_val, (unsigned)1, "readonly"); | 1337 | addLLVMArgAttr(fn_val, (unsigned)1, "readonly"); |
| ... | @@ -1409,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { | ... | @@ -1409,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 1409 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | 1459 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 1410 | addLLVMFnAttr(fn_val, "nounwind"); | 1460 | addLLVMFnAttr(fn_val, "nounwind"); |
| 1411 | add_uwtable_attr(g, fn_val); | 1461 | add_uwtable_attr(g, fn_val); |
| 1462 | // Error return trace memory is in the stack, which is impossible to be at address 0 | ||
| 1463 | // on any architecture. | ||
| 1412 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | 1464 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 1413 | if (g->build_mode == BuildModeDebug) { | 1465 | if (g->build_mode == BuildModeDebug) { |
| 1414 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); | 1466 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| ... | @@ -1633,10 +1685,25 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, | ... | @@ -1633,10 +1685,25 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, |
| 1633 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | 1685 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1634 | } | 1686 | } |
| 1635 | 1687 | ||
| 1688 | static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *int_type) { | ||
| 1689 | LLVMValueRef zero = LLVMConstNull(int_type->type_ref); | ||
| 1690 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, ""); | ||
| 1691 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk"); | ||
| 1692 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail"); | ||
| 1693 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 1694 | |||
| 1695 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 1696 | gen_safety_crash(g, PanicMsgIdCastTruncatedData); | ||
| 1697 | |||
| 1698 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 1699 | return nullptr; | ||
| 1700 | } | ||
| 1701 | |||
| 1636 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type, | 1702 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type, |
| 1637 | ZigType *wanted_type, LLVMValueRef expr_val) | 1703 | ZigType *wanted_type, LLVMValueRef expr_val) |
| 1638 | { | 1704 | { |
| 1639 | assert(actual_type->id == wanted_type->id); | 1705 | assert(actual_type->id == wanted_type->id); |
| 1706 | assert(expr_val != nullptr); | ||
| 1640 | 1707 | ||
| 1641 | uint64_t actual_bits; | 1708 | uint64_t actual_bits; |
| 1642 | uint64_t wanted_bits; | 1709 | uint64_t wanted_bits; |
| ... | @@ -1689,17 +1756,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z | ... | @@ -1689,17 +1756,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1689 | if (!want_runtime_safety) | 1756 | if (!want_runtime_safety) |
| 1690 | return nullptr; | 1757 | return nullptr; |
| 1691 | 1758 | ||
| 1692 | LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); | 1759 | return gen_assert_zero(g, expr_val, actual_type); |
| 1693 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, ""); | ||
| 1694 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk"); | ||
| 1695 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail"); | ||
| 1696 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 1697 | |||
| 1698 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 1699 | gen_safety_crash(g, PanicMsgIdCastTruncatedData); | ||
| 1700 | |||
| 1701 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 1702 | return nullptr; | ||
| 1703 | } | 1760 | } |
| 1704 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | 1761 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1705 | if (!want_runtime_safety) { | 1762 | if (!want_runtime_safety) { |
| ... | @@ -1729,17 +1786,49 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z | ... | @@ -1729,17 +1786,49 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1729 | } | 1786 | } |
| 1730 | } | 1787 | } |
| 1731 | 1788 | ||
| 1732 | static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *type_entry, AddSubMul op, | 1789 | typedef LLVMValueRef (*BuildBinOpFunc)(LLVMBuilderRef, LLVMValueRef, LLVMValueRef, const char *); |
| 1790 | // These are lookup table using the AddSubMul enum as the lookup. | ||
| 1791 | // If AddSubMul ever changes, then these tables will be out of | ||
| 1792 | // date. | ||
| 1793 | static const BuildBinOpFunc float_op[3] = { LLVMBuildFAdd, LLVMBuildFSub, LLVMBuildFMul }; | ||
| 1794 | static const BuildBinOpFunc wrap_op[3] = { LLVMBuildAdd, LLVMBuildSub, LLVMBuildMul }; | ||
| 1795 | static const BuildBinOpFunc signed_op[3] = { LLVMBuildNSWAdd, LLVMBuildNSWSub, LLVMBuildNSWMul }; | ||
| 1796 | static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, LLVMBuildNUWMul }; | ||
| 1797 | |||
| 1798 | static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul op, | ||
| 1733 | LLVMValueRef val1, LLVMValueRef val2) | 1799 | LLVMValueRef val1, LLVMValueRef val2) |
| 1734 | { | 1800 | { |
| 1735 | LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op); | 1801 | LLVMValueRef overflow_bit; |
| 1736 | LLVMValueRef params[] = { | 1802 | LLVMValueRef result; |
| 1737 | val1, | 1803 | |
| 1738 | val2, | 1804 | if (operand_type->id == ZigTypeIdVector) { |
| 1739 | }; | 1805 | ZigType *int_type = operand_type->data.vector.elem_type; |
| 1740 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); | 1806 | assert(int_type->id == ZigTypeIdInt); |
| 1741 | LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); | 1807 | LLVMTypeRef one_more_bit_int = LLVMIntType(int_type->data.integral.bit_count + 1); |
| 1742 | LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); | 1808 | LLVMTypeRef one_more_bit_int_vector = LLVMVectorType(one_more_bit_int, operand_type->data.vector.len); |
| 1809 | const auto buildExtFn = int_type->data.integral.is_signed ? LLVMBuildSExt : LLVMBuildZExt; | ||
| 1810 | LLVMValueRef extended1 = buildExtFn(g->builder, val1, one_more_bit_int_vector, ""); | ||
| 1811 | LLVMValueRef extended2 = buildExtFn(g->builder, val2, one_more_bit_int_vector, ""); | ||
| 1812 | LLVMValueRef extended_result = wrap_op[op](g->builder, extended1, extended2, ""); | ||
| 1813 | result = LLVMBuildTrunc(g->builder, extended_result, operand_type->type_ref, ""); | ||
| 1814 | |||
| 1815 | LLVMValueRef re_extended_result = buildExtFn(g->builder, result, one_more_bit_int_vector, ""); | ||
| 1816 | LLVMValueRef overflow_vector = LLVMBuildICmp(g->builder, LLVMIntNE, extended_result, re_extended_result, ""); | ||
| 1817 | LLVMTypeRef bitcast_int_type = LLVMIntType(operand_type->data.vector.len); | ||
| 1818 | LLVMValueRef bitcasted_overflow = LLVMBuildBitCast(g->builder, overflow_vector, bitcast_int_type, ""); | ||
| 1819 | LLVMValueRef zero = LLVMConstNull(bitcast_int_type); | ||
| 1820 | overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, bitcasted_overflow, zero, ""); | ||
| 1821 | } else { | ||
| 1822 | LLVMValueRef fn_val = get_int_overflow_fn(g, operand_type, op); | ||
| 1823 | LLVMValueRef params[] = { | ||
| 1824 | val1, | ||
| 1825 | val2, | ||
| 1826 | }; | ||
| 1827 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); | ||
| 1828 | result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); | ||
| 1829 | overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); | ||
| 1830 | } | ||
| 1831 | |||
| 1743 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail"); | 1832 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail"); |
| 1744 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk"); | 1833 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk"); |
| 1745 | LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block); | 1834 | LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block); |
| ... | @@ -1907,9 +1996,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { | ... | @@ -1907,9 +1996,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { |
| 1907 | } | 1996 | } |
| 1908 | 1997 | ||
| 1909 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) { | 1998 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) { |
| 1910 | assert(alignment > 0); | ||
| 1911 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); | 1999 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); |
| 1912 | LLVMSetAlignment(result, alignment); | 2000 | LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment); |
| 1913 | return result; | 2001 | return result; |
| 1914 | } | 2002 | } |
| 1915 | 2003 | ||
| ... | @@ -1967,14 +2055,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -1967,14 +2055,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1967 | break; | 2055 | break; |
| 1968 | } | 2056 | } |
| 1969 | 2057 | ||
| 1970 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || | 2058 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector || |
| 1971 | ty->id == ZigTypeIdInt // TODO investigate if we need to change this | 2059 | ty->id == ZigTypeIdInt // TODO investigate if we need to change this |
| 1972 | ) { | 2060 | ) { |
| 1973 | switch (fn_walk->id) { | 2061 | switch (fn_walk->id) { |
| 1974 | case FnWalkIdAttrs: { | 2062 | case FnWalkIdAttrs: { |
| 1975 | ZigType *ptr_type = get_codegen_ptr_type(ty); | 2063 | ZigType *ptr_type = get_codegen_ptr_type(ty); |
| 1976 | if (ptr_type != nullptr) { | 2064 | if (ptr_type != nullptr) { |
| 1977 | if (ty->id != ZigTypeIdOptional) { | 2065 | if (type_is_nonnull_ptr(ty)) { |
| 1978 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); | 2066 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); |
| 1979 | } | 2067 | } |
| 1980 | if (ptr_type->data.pointer.is_const) { | 2068 | if (ptr_type->data.pointer.is_const) { |
| ... | @@ -2018,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -2018,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2018 | assert(handle_is_ptr(ty)); | 2106 | assert(handle_is_ptr(ty)); |
| 2019 | switch (fn_walk->id) { | 2107 | switch (fn_walk->id) { |
| 2020 | case FnWalkIdAttrs: | 2108 | case FnWalkIdAttrs: |
| 2109 | // arrays passed to C ABI functions may not be at address 0 | ||
| 2021 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); | 2110 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); |
| 2022 | addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); | 2111 | addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); |
| 2023 | fn_walk->data.attrs.gen_i += 1; | 2112 | fn_walk->data.attrs.gen_i += 1; |
| ... | @@ -2057,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -2057,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2057 | case FnWalkIdAttrs: | 2146 | case FnWalkIdAttrs: |
| 2058 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval"); | 2147 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval"); |
| 2059 | addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); | 2148 | addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); |
| 2149 | // Byvalue parameters must not have address 0 | ||
| 2060 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); | 2150 | addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); |
| 2061 | fn_walk->data.attrs.gen_i += 1; | 2151 | fn_walk->data.attrs.gen_i += 1; |
| 2062 | break; | 2152 | break; |
| ... | @@ -2189,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { | ... | @@ -2189,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2189 | if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) { | 2279 | if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) { |
| 2190 | addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly"); | 2280 | addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly"); |
| 2191 | } | 2281 | } |
| 2192 | if (param_type->id == ZigTypeIdPointer) { | 2282 | if (type_is_nonnull_ptr(param_type)) { |
| 2193 | addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull"); | 2283 | addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull"); |
| 2194 | } | 2284 | } |
| 2195 | break; | 2285 | break; |
| ... | @@ -2204,10 +2294,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { | ... | @@ -2204,10 +2294,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2204 | assert(variable); | 2294 | assert(variable); |
| 2205 | assert(variable->value_ref); | 2295 | assert(variable->value_ref); |
| 2206 | 2296 | ||
| 2207 | if (!handle_is_ptr(variable->value->type)) { | 2297 | if (!handle_is_ptr(variable->var_type)) { |
| 2208 | clear_debug_source_node(g); | 2298 | clear_debug_source_node(g); |
| 2209 | gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref, | 2299 | gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), |
| 2210 | variable->align_bytes, false); | 2300 | variable->value_ref, variable->align_bytes, false); |
| 2211 | } | 2301 | } |
| 2212 | 2302 | ||
| 2213 | if (variable->decl_node) { | 2303 | if (variable->decl_node) { |
| ... | @@ -2582,9 +2672,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2582,9 +2672,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2582 | (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) || | 2672 | (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) || |
| 2583 | (op1->value.type->id == ZigTypeIdPointer && | 2673 | (op1->value.type->id == ZigTypeIdPointer && |
| 2584 | (op_id == IrBinOpAdd || op_id == IrBinOpSub) && | 2674 | (op_id == IrBinOpAdd || op_id == IrBinOpSub) && |
| 2585 | op1->value.type->data.pointer.ptr_len == PtrLenUnknown) | 2675 | op1->value.type->data.pointer.ptr_len != PtrLenSingle) |
| 2586 | ); | 2676 | ); |
| 2587 | ZigType *type_entry = op1->value.type; | 2677 | ZigType *operand_type = op1->value.type; |
| 2678 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; | ||
| 2588 | 2679 | ||
| 2589 | bool want_runtime_safety = bin_op_instruction->safety_check_on && | 2680 | bool want_runtime_safety = bin_op_instruction->safety_check_on && |
| 2590 | ir_want_runtime_safety(g, &bin_op_instruction->base); | 2681 | ir_want_runtime_safety(g, &bin_op_instruction->base); |
| ... | @@ -2610,46 +2701,71 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2610,46 +2701,71 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2610 | case IrBinOpCmpGreaterThan: | 2701 | case IrBinOpCmpGreaterThan: |
| 2611 | case IrBinOpCmpLessOrEq: | 2702 | case IrBinOpCmpLessOrEq: |
| 2612 | case IrBinOpCmpGreaterOrEq: | 2703 | case IrBinOpCmpGreaterOrEq: |
| 2613 | if (type_entry->id == ZigTypeIdFloat) { | 2704 | if (scalar_type->id == ZigTypeIdFloat) { |
| 2614 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); | 2705 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); |
| 2615 | LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id); | 2706 | LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id); |
| 2616 | return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, ""); | 2707 | return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, ""); |
| 2617 | } else if (type_entry->id == ZigTypeIdInt) { | 2708 | } else if (scalar_type->id == ZigTypeIdInt) { |
| 2618 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed); | 2709 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, scalar_type->data.integral.is_signed); |
| 2619 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | 2710 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); |
| 2620 | } else if (type_entry->id == ZigTypeIdEnum || | 2711 | } else if (scalar_type->id == ZigTypeIdEnum || |
| 2621 | type_entry->id == ZigTypeIdErrorSet || | 2712 | scalar_type->id == ZigTypeIdErrorSet || |
| 2622 | type_entry->id == ZigTypeIdBool || | 2713 | scalar_type->id == ZigTypeIdBool || |
| 2623 | get_codegen_ptr_type(type_entry) != nullptr) | 2714 | get_codegen_ptr_type(scalar_type) != nullptr) |
| 2624 | { | 2715 | { |
| 2625 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | 2716 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); |
| 2626 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | 2717 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); |
| 2627 | } else { | 2718 | } else { |
| 2628 | zig_unreachable(); | 2719 | zig_unreachable(); |
| 2629 | } | 2720 | } |
| 2721 | case IrBinOpMult: | ||
| 2722 | case IrBinOpMultWrap: | ||
| 2630 | case IrBinOpAdd: | 2723 | case IrBinOpAdd: |
| 2631 | case IrBinOpAddWrap: | 2724 | case IrBinOpAddWrap: |
| 2632 | if (type_entry->id == ZigTypeIdPointer) { | 2725 | case IrBinOpSub: |
| 2633 | assert(type_entry->data.pointer.ptr_len == PtrLenUnknown); | 2726 | case IrBinOpSubWrap: { |
| 2727 | bool is_wrapping = (op_id == IrBinOpSubWrap || op_id == IrBinOpAddWrap || op_id == IrBinOpMultWrap); | ||
| 2728 | AddSubMul add_sub_mul = | ||
| 2729 | op_id == IrBinOpAdd || op_id == IrBinOpAddWrap ? AddSubMulAdd : | ||
| 2730 | op_id == IrBinOpSub || op_id == IrBinOpSubWrap ? AddSubMulSub : | ||
| 2731 | AddSubMulMul; | ||
| 2732 | |||
| 2733 | if (scalar_type->id == ZigTypeIdPointer) { | ||
| 2734 | assert(scalar_type->data.pointer.ptr_len != PtrLenSingle); | ||
| 2735 | LLVMValueRef subscript_value; | ||
| 2736 | if (operand_type->id == ZigTypeIdVector) | ||
| 2737 | zig_panic("TODO: Implement vector operations on pointers."); | ||
| 2738 | |||
| 2739 | switch (add_sub_mul) { | ||
| 2740 | case AddSubMulAdd: | ||
| 2741 | subscript_value = op2_value; | ||
| 2742 | break; | ||
| 2743 | case AddSubMulSub: | ||
| 2744 | subscript_value = LLVMBuildNeg(g->builder, op2_value, ""); | ||
| 2745 | break; | ||
| 2746 | case AddSubMulMul: | ||
| 2747 | zig_unreachable(); | ||
| 2748 | } | ||
| 2749 | |||
| 2634 | // TODO runtime safety | 2750 | // TODO runtime safety |
| 2635 | return LLVMBuildInBoundsGEP(g->builder, op1_value, &op2_value, 1, ""); | 2751 | return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, ""); |
| 2636 | } else if (type_entry->id == ZigTypeIdFloat) { | 2752 | } else if (scalar_type->id == ZigTypeIdFloat) { |
| 2637 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); | 2753 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); |
| 2638 | return LLVMBuildFAdd(g->builder, op1_value, op2_value, ""); | 2754 | return float_op[add_sub_mul](g->builder, op1_value, op2_value, ""); |
| 2639 | } else if (type_entry->id == ZigTypeIdInt) { | 2755 | } else if (scalar_type->id == ZigTypeIdInt) { |
| 2640 | bool is_wrapping = (op_id == IrBinOpAddWrap); | ||
| 2641 | if (is_wrapping) { | 2756 | if (is_wrapping) { |
| 2642 | return LLVMBuildAdd(g->builder, op1_value, op2_value, ""); | 2757 | return wrap_op[add_sub_mul](g->builder, op1_value, op2_value, ""); |
| 2643 | } else if (want_runtime_safety) { | 2758 | } else if (want_runtime_safety) { |
| 2644 | return gen_overflow_op(g, type_entry, AddSubMulAdd, op1_value, op2_value); | 2759 | return gen_overflow_op(g, operand_type, add_sub_mul, op1_value, op2_value); |
| 2645 | } else if (type_entry->data.integral.is_signed) { | 2760 | } else if (scalar_type->data.integral.is_signed) { |
| 2646 | return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, ""); | 2761 | return signed_op[add_sub_mul](g->builder, op1_value, op2_value, ""); |
| 2647 | } else { | 2762 | } else { |
| 2648 | return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, ""); | 2763 | return unsigned_op[add_sub_mul](g->builder, op1_value, op2_value, ""); |
| 2649 | } | 2764 | } |
| 2650 | } else { | 2765 | } else { |
| 2651 | zig_unreachable(); | 2766 | zig_unreachable(); |
| 2652 | } | 2767 | } |
| 2768 | } | ||
| 2653 | case IrBinOpBinOr: | 2769 | case IrBinOpBinOr: |
| 2654 | return LLVMBuildOr(g->builder, op1_value, op2_value, ""); | 2770 | return LLVMBuildOr(g->builder, op1_value, op2_value, ""); |
| 2655 | case IrBinOpBinXor: | 2771 | case IrBinOpBinXor: |
| ... | @@ -2659,15 +2775,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2659,15 +2775,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2659 | case IrBinOpBitShiftLeftLossy: | 2775 | case IrBinOpBitShiftLeftLossy: |
| 2660 | case IrBinOpBitShiftLeftExact: | 2776 | case IrBinOpBitShiftLeftExact: |
| 2661 | { | 2777 | { |
| 2662 | assert(type_entry->id == ZigTypeIdInt); | 2778 | assert(scalar_type->id == ZigTypeIdInt); |
| 2663 | LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, | 2779 | LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value); |
| 2664 | type_entry, op2_value); | ||
| 2665 | bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy); | 2780 | bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy); |
| 2666 | if (is_sloppy) { | 2781 | if (is_sloppy) { |
| 2667 | return LLVMBuildShl(g->builder, op1_value, op2_casted, ""); | 2782 | return LLVMBuildShl(g->builder, op1_value, op2_casted, ""); |
| 2668 | } else if (want_runtime_safety) { | 2783 | } else if (want_runtime_safety) { |
| 2669 | return gen_overflow_shl_op(g, type_entry, op1_value, op2_casted); | 2784 | return gen_overflow_shl_op(g, scalar_type, op1_value, op2_casted); |
| 2670 | } else if (type_entry->data.integral.is_signed) { | 2785 | } else if (scalar_type->data.integral.is_signed) { |
| 2671 | return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, ""); | 2786 | return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, ""); |
| 2672 | } else { | 2787 | } else { |
| 2673 | return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, ""); | 2788 | return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, ""); |
| ... | @@ -2676,85 +2791,41 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2676,85 +2791,41 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2676 | case IrBinOpBitShiftRightLossy: | 2791 | case IrBinOpBitShiftRightLossy: |
| 2677 | case IrBinOpBitShiftRightExact: | 2792 | case IrBinOpBitShiftRightExact: |
| 2678 | { | 2793 | { |
| 2679 | assert(type_entry->id == ZigTypeIdInt); | 2794 | assert(scalar_type->id == ZigTypeIdInt); |
| 2680 | LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, | 2795 | LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value); |
| 2681 | type_entry, op2_value); | ||
| 2682 | bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy); | 2796 | bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy); |
| 2683 | if (is_sloppy) { | 2797 | if (is_sloppy) { |
| 2684 | if (type_entry->data.integral.is_signed) { | 2798 | if (scalar_type->data.integral.is_signed) { |
| 2685 | return LLVMBuildAShr(g->builder, op1_value, op2_casted, ""); | 2799 | return LLVMBuildAShr(g->builder, op1_value, op2_casted, ""); |
| 2686 | } else { | 2800 | } else { |
| 2687 | return LLVMBuildLShr(g->builder, op1_value, op2_casted, ""); | 2801 | return LLVMBuildLShr(g->builder, op1_value, op2_casted, ""); |
| 2688 | } | 2802 | } |
| 2689 | } else if (want_runtime_safety) { | 2803 | } else if (want_runtime_safety) { |
| 2690 | return gen_overflow_shr_op(g, type_entry, op1_value, op2_casted); | 2804 | return gen_overflow_shr_op(g, scalar_type, op1_value, op2_casted); |
| 2691 | } else if (type_entry->data.integral.is_signed) { | 2805 | } else if (scalar_type->data.integral.is_signed) { |
| 2692 | return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, ""); | 2806 | return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, ""); |
| 2693 | } else { | 2807 | } else { |
| 2694 | return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, ""); | 2808 | return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, ""); |
| 2695 | } | 2809 | } |
| 2696 | } | 2810 | } |
| 2697 | case IrBinOpSub: | ||
| 2698 | case IrBinOpSubWrap: | ||
| 2699 | if (type_entry->id == ZigTypeIdPointer) { | ||
| 2700 | assert(type_entry->data.pointer.ptr_len == PtrLenUnknown); | ||
| 2701 | // TODO runtime safety | ||
| 2702 | LLVMValueRef subscript_value = LLVMBuildNeg(g->builder, op2_value, ""); | ||
| 2703 | return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, ""); | ||
| 2704 | } else if (type_entry->id == ZigTypeIdFloat) { | ||
| 2705 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); | ||
| 2706 | return LLVMBuildFSub(g->builder, op1_value, op2_value, ""); | ||
| 2707 | } else if (type_entry->id == ZigTypeIdInt) { | ||
| 2708 | bool is_wrapping = (op_id == IrBinOpSubWrap); | ||
| 2709 | if (is_wrapping) { | ||
| 2710 | return LLVMBuildSub(g->builder, op1_value, op2_value, ""); | ||
| 2711 | } else if (want_runtime_safety) { | ||
| 2712 | return gen_overflow_op(g, type_entry, AddSubMulSub, op1_value, op2_value); | ||
| 2713 | } else if (type_entry->data.integral.is_signed) { | ||
| 2714 | return LLVMBuildNSWSub(g->builder, op1_value, op2_value, ""); | ||
| 2715 | } else { | ||
| 2716 | return LLVMBuildNUWSub(g->builder, op1_value, op2_value, ""); | ||
| 2717 | } | ||
| 2718 | } else { | ||
| 2719 | zig_unreachable(); | ||
| 2720 | } | ||
| 2721 | case IrBinOpMult: | ||
| 2722 | case IrBinOpMultWrap: | ||
| 2723 | if (type_entry->id == ZigTypeIdFloat) { | ||
| 2724 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); | ||
| 2725 | return LLVMBuildFMul(g->builder, op1_value, op2_value, ""); | ||
| 2726 | } else if (type_entry->id == ZigTypeIdInt) { | ||
| 2727 | bool is_wrapping = (op_id == IrBinOpMultWrap); | ||
| 2728 | if (is_wrapping) { | ||
| 2729 | return LLVMBuildMul(g->builder, op1_value, op2_value, ""); | ||
| 2730 | } else if (want_runtime_safety) { | ||
| 2731 | return gen_overflow_op(g, type_entry, AddSubMulMul, op1_value, op2_value); | ||
| 2732 | } else if (type_entry->data.integral.is_signed) { | ||
| 2733 | return LLVMBuildNSWMul(g->builder, op1_value, op2_value, ""); | ||
| 2734 | } else { | ||
| 2735 | return LLVMBuildNUWMul(g->builder, op1_value, op2_value, ""); | ||
| 2736 | } | ||
| 2737 | } else { | ||
| 2738 | zig_unreachable(); | ||
| 2739 | } | ||
| 2740 | case IrBinOpDivUnspecified: | 2811 | case IrBinOpDivUnspecified: |
| 2741 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | 2812 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), |
| 2742 | op1_value, op2_value, type_entry, DivKindFloat); | 2813 | op1_value, op2_value, scalar_type, DivKindFloat); |
| 2743 | case IrBinOpDivExact: | 2814 | case IrBinOpDivExact: |
| 2744 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | 2815 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), |
| 2745 | op1_value, op2_value, type_entry, DivKindExact); | 2816 | op1_value, op2_value, scalar_type, DivKindExact); |
| 2746 | case IrBinOpDivTrunc: | 2817 | case IrBinOpDivTrunc: |
| 2747 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | 2818 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), |
| 2748 | op1_value, op2_value, type_entry, DivKindTrunc); | 2819 | op1_value, op2_value, scalar_type, DivKindTrunc); |
| 2749 | case IrBinOpDivFloor: | 2820 | case IrBinOpDivFloor: |
| 2750 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | 2821 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), |
| 2751 | op1_value, op2_value, type_entry, DivKindFloor); | 2822 | op1_value, op2_value, scalar_type, DivKindFloor); |
| 2752 | case IrBinOpRemRem: | 2823 | case IrBinOpRemRem: |
| 2753 | return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | 2824 | return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), |
| 2754 | op1_value, op2_value, type_entry, RemKindRem); | 2825 | op1_value, op2_value, scalar_type, RemKindRem); |
| 2755 | case IrBinOpRemMod: | 2826 | case IrBinOpRemMod: |
| 2756 | return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | 2827 | return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), |
| 2757 | op1_value, op2_value, type_entry, RemKindMod); | 2828 | op1_value, op2_value, scalar_type, RemKindMod); |
| 2758 | } | 2829 | } |
| 2759 | zig_unreachable(); | 2830 | zig_unreachable(); |
| 2760 | } | 2831 | } |
| ... | @@ -2882,32 +2953,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, | ... | @@ -2882,32 +2953,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2882 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); | 2953 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); |
| 2883 | 2954 | ||
| 2884 | 2955 | ||
| 2885 | return cast_instruction->tmp_ptr; | ||
| 2886 | } | ||
| 2887 | case CastOpBytesToSlice: | ||
| 2888 | { | ||
| 2889 | assert(cast_instruction->tmp_ptr); | ||
| 2890 | assert(wanted_type->id == ZigTypeIdStruct); | ||
| 2891 | assert(wanted_type->data.structure.is_slice); | ||
| 2892 | assert(actual_type->id == ZigTypeIdArray); | ||
| 2893 | |||
| 2894 | ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; | ||
| 2895 | ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; | ||
| 2896 | |||
| 2897 | |||
| 2898 | size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; | ||
| 2899 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | ||
| 2900 | (unsigned)wanted_ptr_index, ""); | ||
| 2901 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, ""); | ||
| 2902 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); | ||
| 2903 | |||
| 2904 | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; | ||
| 2905 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | ||
| 2906 | (unsigned)wanted_len_index, ""); | ||
| 2907 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, | ||
| 2908 | actual_type->data.array.len / type_size(g, wanted_child_type), false); | ||
| 2909 | gen_store_untyped(g, len_val, len_ptr, 0, false); | ||
| 2910 | |||
| 2911 | return cast_instruction->tmp_ptr; | 2956 | return cast_instruction->tmp_ptr; |
| 2912 | } | 2957 | } |
| 2913 | case CastOpIntToFloat: | 2958 | case CastOpIntToFloat: |
| ... | @@ -2991,14 +3036,29 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, | ... | @@ -2991,14 +3036,29 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2991 | } | 3036 | } |
| 2992 | 3037 | ||
| 2993 | static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, | 3038 | static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, |
| 2994 | IrInstructionPtrCast *instruction) | 3039 | IrInstructionPtrCastGen *instruction) |
| 2995 | { | 3040 | { |
| 2996 | ZigType *wanted_type = instruction->base.value.type; | 3041 | ZigType *wanted_type = instruction->base.value.type; |
| 2997 | if (!type_has_bits(wanted_type)) { | 3042 | if (!type_has_bits(wanted_type)) { |
| 2998 | return nullptr; | 3043 | return nullptr; |
| 2999 | } | 3044 | } |
| 3000 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | 3045 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 3001 | return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); | 3046 | LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); |
| 3047 | bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); | ||
| 3048 | if (!want_safety_check || ptr_allows_addr_zero(wanted_type)) | ||
| 3049 | return result_ptr; | ||
| 3050 | |||
| 3051 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr)); | ||
| 3052 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, ""); | ||
| 3053 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail"); | ||
| 3054 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk"); | ||
| 3055 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 3056 | |||
| 3057 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 3058 | gen_safety_crash(g, PanicMsgIdPtrCastNull); | ||
| 3059 | |||
| 3060 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 3061 | return result_ptr; | ||
| 3002 | } | 3062 | } |
| 3003 | 3063 | ||
| 3004 | static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, | 3064 | static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, |
| ... | @@ -3179,11 +3239,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3179,11 +3239,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI |
| 3179 | } | 3239 | } |
| 3180 | 3240 | ||
| 3181 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, | 3241 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 3182 | IrInstructionDeclVar *decl_var_instruction) | 3242 | IrInstructionDeclVarGen *decl_var_instruction) |
| 3183 | { | 3243 | { |
| 3184 | ZigVar *var = decl_var_instruction->var; | 3244 | ZigVar *var = decl_var_instruction->var; |
| 3185 | 3245 | ||
| 3186 | if (!type_has_bits(var->value->type)) | 3246 | if (!type_has_bits(var->var_type)) |
| 3187 | return nullptr; | 3247 | return nullptr; |
| 3188 | 3248 | ||
| 3189 | if (var->ref_count == 0 && g->build_mode != BuildModeDebug) | 3249 | if (var->ref_count == 0 && g->build_mode != BuildModeDebug) |
| ... | @@ -3191,34 +3251,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, | ... | @@ -3191,34 +3251,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 3191 | 3251 | ||
| 3192 | IrInstruction *init_value = decl_var_instruction->init_value; | 3252 | IrInstruction *init_value = decl_var_instruction->init_value; |
| 3193 | 3253 | ||
| 3194 | bool have_init_expr = false; | 3254 | bool have_init_expr = !value_is_all_undef(&init_value->value); |
| 3195 | |||
| 3196 | ConstExprValue *const_val = &init_value->value; | ||
| 3197 | if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic) | ||
| 3198 | have_init_expr = true; | ||
| 3199 | 3255 | ||
| 3200 | if (have_init_expr) { | 3256 | if (have_init_expr) { |
| 3201 | assert(var->value->type == init_value->value.type); | 3257 | ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false, |
| 3202 | ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false, | ||
| 3203 | PtrLenSingle, var->align_bytes, 0, 0); | 3258 | PtrLenSingle, var->align_bytes, 0, 0); |
| 3204 | LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value); | 3259 | LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value); |
| 3205 | gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val); | 3260 | gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val); |
| 3206 | } else { | 3261 | } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) { |
| 3207 | bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base); | 3262 | uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes; |
| 3208 | if (want_safe) { | 3263 | gen_undef_init(g, align_bytes, var->var_type, var->value_ref); |
| 3209 | ZigType *usize = g->builtin_types.entry_usize; | ||
| 3210 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref); | ||
| 3211 | assert(size_bytes > 0); | ||
| 3212 | |||
| 3213 | assert(var->align_bytes > 0); | ||
| 3214 | |||
| 3215 | // memset uninitialized memory to 0xa | ||
| 3216 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | ||
| 3217 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | ||
| 3218 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); | ||
| 3219 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); | ||
| 3220 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false); | ||
| 3221 | } | ||
| 3222 | } | 3264 | } |
| 3223 | 3265 | ||
| 3224 | gen_var_debug_decl(g, var); | 3266 | gen_var_debug_decl(g, var); |
| ... | @@ -3255,21 +3297,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3255,21 +3297,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3255 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); | 3297 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); |
| 3256 | } | 3298 | } |
| 3257 | 3299 | ||
| 3258 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | 3300 | static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { |
| 3259 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | 3301 | switch (const_val->data.x_array.special) { |
| 3260 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | 3302 | case ConstArraySpecialUndef: |
| 3303 | return true; | ||
| 3304 | case ConstArraySpecialBuf: | ||
| 3305 | return false; | ||
| 3306 | case ConstArraySpecialNone: | ||
| 3307 | for (size_t i = 0; i < len; i += 1) { | ||
| 3308 | if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i])) | ||
| 3309 | return false; | ||
| 3310 | } | ||
| 3311 | return true; | ||
| 3312 | } | ||
| 3313 | zig_unreachable(); | ||
| 3314 | } | ||
| 3261 | 3315 | ||
| 3262 | assert(instruction->ptr->value.type->id == ZigTypeIdPointer); | 3316 | static bool value_is_all_undef(ConstExprValue *const_val) { |
| 3263 | ZigType *ptr_type = instruction->ptr->value.type; | 3317 | switch (const_val->special) { |
| 3318 | case ConstValSpecialRuntime: | ||
| 3319 | return false; | ||
| 3320 | case ConstValSpecialUndef: | ||
| 3321 | return true; | ||
| 3322 | case ConstValSpecialStatic: | ||
| 3323 | if (const_val->type->id == ZigTypeIdStruct) { | ||
| 3324 | for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) { | ||
| 3325 | if (!value_is_all_undef(&const_val->data.x_struct.fields[i])) | ||
| 3326 | return false; | ||
| 3327 | } | ||
| 3328 | return true; | ||
| 3329 | } else if (const_val->type->id == ZigTypeIdArray) { | ||
| 3330 | return value_is_all_undef_array(const_val, const_val->type->data.array.len); | ||
| 3331 | } else if (const_val->type->id == ZigTypeIdVector) { | ||
| 3332 | return value_is_all_undef_array(const_val, const_val->type->data.vector.len); | ||
| 3333 | } else { | ||
| 3334 | return false; | ||
| 3335 | } | ||
| 3336 | } | ||
| 3337 | zig_unreachable(); | ||
| 3338 | } | ||
| 3264 | 3339 | ||
| 3265 | gen_assign_raw(g, ptr, ptr_type, value); | 3340 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { |
| 3341 | assert(type_has_bits(value_type)); | ||
| 3342 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref); | ||
| 3343 | assert(size_bytes > 0); | ||
| 3344 | assert(ptr_align_bytes > 0); | ||
| 3345 | // memset uninitialized memory to 0xaa | ||
| 3346 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | ||
| 3347 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | ||
| 3348 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, ""); | ||
| 3349 | ZigType *usize = g->builtin_types.entry_usize; | ||
| 3350 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); | ||
| 3351 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); | ||
| 3352 | } | ||
| 3266 | 3353 | ||
| 3354 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | ||
| 3355 | ZigType *ptr_type = instruction->ptr->value.type; | ||
| 3356 | assert(ptr_type->id == ZigTypeIdPointer); | ||
| 3357 | if (!type_has_bits(ptr_type)) | ||
| 3358 | return nullptr; | ||
| 3359 | |||
| 3360 | bool have_init_expr = !value_is_all_undef(&instruction->value->value); | ||
| 3361 | if (have_init_expr) { | ||
| 3362 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | ||
| 3363 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | ||
| 3364 | gen_assign_raw(g, ptr, ptr_type, value); | ||
| 3365 | } else if (ir_want_runtime_safety(g, &instruction->base)) { | ||
| 3366 | gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type, | ||
| 3367 | ir_llvm_value(g, instruction->ptr)); | ||
| 3368 | } | ||
| 3267 | return nullptr; | 3369 | return nullptr; |
| 3268 | } | 3370 | } |
| 3269 | 3371 | ||
| 3270 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { | 3372 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { |
| 3271 | ZigVar *var = instruction->var; | 3373 | ZigVar *var = instruction->var; |
| 3272 | if (type_has_bits(var->value->type)) { | 3374 | if (type_has_bits(var->var_type)) { |
| 3273 | assert(var->value_ref); | 3375 | assert(var->value_ref); |
| 3274 | return var->value_ref; | 3376 | return var->value_ref; |
| 3275 | } else { | 3377 | } else { |
| ... | @@ -3583,7 +3685,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab | ... | @@ -3583,7 +3685,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 3583 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | 3685 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 3584 | } | 3686 | } |
| 3585 | 3687 | ||
| 3586 | LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, ""); | 3688 | LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, |
| 3689 | union_type->data.unionation.gen_union_index, ""); | ||
| 3587 | LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); | 3690 | LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); |
| 3588 | return bitcasted_union_field_ptr; | 3691 | return bitcasted_union_field_ptr; |
| 3589 | } | 3692 | } |
| ... | @@ -3745,8 +3848,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR | ... | @@ -3745,8 +3848,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR |
| 3745 | if (child_type->zero_bits) { | 3848 | if (child_type->zero_bits) { |
| 3746 | return maybe_handle; | 3849 | return maybe_handle; |
| 3747 | } else { | 3850 | } else { |
| 3748 | bool maybe_is_ptr = type_is_codegen_pointer(child_type); | 3851 | bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet; |
| 3749 | if (maybe_is_ptr) { | 3852 | if (is_scalar) { |
| 3750 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); | 3853 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); |
| 3751 | } else { | 3854 | } else { |
| 3752 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); | 3855 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); |
| ... | @@ -3761,17 +3864,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable | ... | @@ -3761,17 +3864,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable |
| 3761 | return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value)); | 3864 | return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value)); |
| 3762 | } | 3865 | } |
| 3763 | 3866 | ||
| 3764 | static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | 3867 | static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable, |
| 3765 | IrInstructionUnwrapOptional *instruction) | 3868 | IrInstructionOptionalUnwrapPtr *instruction) |
| 3766 | { | 3869 | { |
| 3767 | ZigType *ptr_type = instruction->value->value.type; | 3870 | ZigType *ptr_type = instruction->base_ptr->value.type; |
| 3768 | assert(ptr_type->id == ZigTypeIdPointer); | 3871 | assert(ptr_type->id == ZigTypeIdPointer); |
| 3769 | ZigType *maybe_type = ptr_type->data.pointer.child_type; | 3872 | ZigType *maybe_type = ptr_type->data.pointer.child_type; |
| 3770 | assert(maybe_type->id == ZigTypeIdOptional); | 3873 | assert(maybe_type->id == ZigTypeIdOptional); |
| 3771 | ZigType *child_type = maybe_type->data.maybe.child_type; | 3874 | ZigType *child_type = maybe_type->data.maybe.child_type; |
| 3772 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); | 3875 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr); |
| 3773 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | ||
| 3774 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) { | 3876 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 3877 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | ||
| 3775 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); | 3878 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); |
| 3776 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk"); | 3879 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk"); |
| 3777 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail"); | 3880 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail"); |
| ... | @@ -3785,8 +3888,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | ... | @@ -3785,8 +3888,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 3785 | if (child_type->zero_bits) { | 3888 | if (child_type->zero_bits) { |
| 3786 | return nullptr; | 3889 | return nullptr; |
| 3787 | } else { | 3890 | } else { |
| 3788 | bool maybe_is_ptr = type_is_codegen_pointer(child_type); | 3891 | bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet; |
| 3789 | if (maybe_is_ptr) { | 3892 | if (is_scalar) { |
| 3790 | return maybe_ptr; | 3893 | return maybe_ptr; |
| 3791 | } else { | 3894 | } else { |
| 3792 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | 3895 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); |
| ... | @@ -3814,6 +3917,16 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI | ... | @@ -3814,6 +3917,16 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI |
| 3814 | n_args = 1; | 3917 | n_args = 1; |
| 3815 | key.id = ZigLLVMFnIdPopCount; | 3918 | key.id = ZigLLVMFnIdPopCount; |
| 3816 | key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count; | 3919 | key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count; |
| 3920 | } else if (fn_id == BuiltinFnIdBswap) { | ||
| 3921 | fn_name = "bswap"; | ||
| 3922 | n_args = 1; | ||
| 3923 | key.id = ZigLLVMFnIdBswap; | ||
| 3924 | key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count; | ||
| 3925 | } else if (fn_id == BuiltinFnIdBitReverse) { | ||
| 3926 | fn_name = "bitreverse"; | ||
| 3927 | n_args = 1; | ||
| 3928 | key.id = ZigLLVMFnIdBitReverse; | ||
| 3929 | key.data.bit_reverse.bit_count = (uint32_t)int_type->data.integral.bit_count; | ||
| 3817 | } else { | 3930 | } else { |
| 3818 | zig_unreachable(); | 3931 | zig_unreachable(); |
| 3819 | } | 3932 | } |
| ... | @@ -4194,7 +4307,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed) | ... | @@ -4194,7 +4307,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed) |
| 4194 | zig_unreachable(); | 4307 | zig_unreachable(); |
| 4195 | } | 4308 | } |
| 4196 | 4309 | ||
| 4197 | static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) { | 4310 | static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) { |
| 4198 | LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); | 4311 | LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); |
| 4199 | LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); | 4312 | LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); |
| 4200 | LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); | 4313 | LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); |
| ... | @@ -4209,18 +4322,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn | ... | @@ -4209,18 +4322,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn |
| 4209 | assert(maybe_type->id == ZigTypeIdOptional); | 4322 | assert(maybe_type->id == ZigTypeIdOptional); |
| 4210 | ZigType *child_type = maybe_type->data.maybe.child_type; | 4323 | ZigType *child_type = maybe_type->data.maybe.child_type; |
| 4211 | 4324 | ||
| 4212 | if (type_is_codegen_pointer(child_type)) { | 4325 | if (!handle_is_ptr(maybe_type)) { |
| 4213 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); | 4326 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4214 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); | 4327 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 4215 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, ""); | 4328 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, ""); |
| 4216 | } | 4329 | } |
| 4217 | 4330 | ||
| 4218 | assert(instruction->tmp_ptr != nullptr); | 4331 | assert(instruction->tmp_ptr != nullptr); |
| 4219 | assert(type_has_bits(instruction->type)); | 4332 | assert(type_has_bits(child_type)); |
| 4220 | 4333 | ||
| 4221 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); | 4334 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4222 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, ""); | 4335 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, ""); |
| 4223 | gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val); | 4336 | gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); |
| 4224 | 4337 | ||
| 4225 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); | 4338 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 4226 | LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); | 4339 | LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); |
| ... | @@ -4371,6 +4484,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -4371,6 +4484,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 4371 | assert(array_type->data.structure.is_slice); | 4484 | assert(array_type->data.structure.is_slice); |
| 4372 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); | 4485 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); |
| 4373 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); | 4486 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); |
| 4487 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind); | ||
| 4374 | 4488 | ||
| 4375 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; | 4489 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; |
| 4376 | assert(ptr_index != SIZE_MAX); | 4490 | assert(ptr_index != SIZE_MAX); |
| ... | @@ -4560,12 +4674,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -4560,12 +4674,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 4560 | return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); | 4674 | return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); |
| 4561 | } | 4675 | } |
| 4562 | 4676 | ||
| 4563 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { | 4677 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, |
| 4564 | ZigType *ptr_type = instruction->value->value.type; | 4678 | IrInstructionUnwrapErrCode *instruction) |
| 4679 | { | ||
| 4680 | ZigType *ptr_type = instruction->err_union->value.type; | ||
| 4565 | assert(ptr_type->id == ZigTypeIdPointer); | 4681 | assert(ptr_type->id == ZigTypeIdPointer); |
| 4566 | ZigType *err_union_type = ptr_type->data.pointer.child_type; | 4682 | ZigType *err_union_type = ptr_type->data.pointer.child_type; |
| 4567 | ZigType *payload_type = err_union_type->data.error_union.payload_type; | 4683 | ZigType *payload_type = err_union_type->data.error_union.payload_type; |
| 4568 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 4684 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union); |
| 4569 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | 4685 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 4570 | 4686 | ||
| 4571 | if (type_has_bits(payload_type)) { | 4687 | if (type_has_bits(payload_type)) { |
| ... | @@ -4576,7 +4692,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab | ... | @@ -4576,7 +4692,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 4576 | } | 4692 | } |
| 4577 | } | 4693 | } |
| 4578 | 4694 | ||
| 4579 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { | 4695 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, |
| 4696 | IrInstructionUnwrapErrPayload *instruction) | ||
| 4697 | { | ||
| 4698 | bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && | ||
| 4699 | g->errors_by_index.length > 1; | ||
| 4700 | if (!want_safety && !type_has_bits(instruction->base.value.type)) | ||
| 4701 | return nullptr; | ||
| 4580 | ZigType *ptr_type = instruction->value->value.type; | 4702 | ZigType *ptr_type = instruction->value->value.type; |
| 4581 | assert(ptr_type->id == ZigTypeIdPointer); | 4703 | assert(ptr_type->id == ZigTypeIdPointer); |
| 4582 | ZigType *err_union_type = ptr_type->data.pointer.child_type; | 4704 | ZigType *err_union_type = ptr_type->data.pointer.child_type; |
| ... | @@ -4588,7 +4710,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu | ... | @@ -4588,7 +4710,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 4588 | return err_union_handle; | 4710 | return err_union_handle; |
| 4589 | } | 4711 | } |
| 4590 | 4712 | ||
| 4591 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { | 4713 | if (want_safety) { |
| 4592 | LLVMValueRef err_val; | 4714 | LLVMValueRef err_val; |
| 4593 | if (type_has_bits(payload_type)) { | 4715 | if (type_has_bits(payload_type)) { |
| 4594 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | 4716 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| ... | @@ -4627,7 +4749,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I | ... | @@ -4627,7 +4749,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I |
| 4627 | } | 4749 | } |
| 4628 | 4750 | ||
| 4629 | LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); | 4751 | LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); |
| 4630 | if (type_is_codegen_pointer(child_type)) { | 4752 | if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { |
| 4631 | return payload_val; | 4753 | return payload_val; |
| 4632 | } | 4754 | } |
| 4633 | 4755 | ||
| ... | @@ -5098,6 +5220,74 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -5098,6 +5220,74 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr |
| 5098 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | 5220 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); |
| 5099 | } | 5221 | } |
| 5100 | 5222 | ||
| 5223 | static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) { | ||
| 5224 | LLVMValueRef op = ir_llvm_value(g, instruction->op); | ||
| 5225 | ZigType *int_type = instruction->base.value.type; | ||
| 5226 | assert(int_type->id == ZigTypeIdInt); | ||
| 5227 | if (int_type->data.integral.bit_count % 16 == 0) { | ||
| 5228 | LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap); | ||
| 5229 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | ||
| 5230 | } | ||
| 5231 | // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate | ||
| 5232 | ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, | ||
| 5233 | int_type->data.integral.bit_count + 8); | ||
| 5234 | // aabbcc | ||
| 5235 | LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, ""); | ||
| 5236 | // 00aabbcc | ||
| 5237 | LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); | ||
| 5238 | LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); | ||
| 5239 | // ccbbaa00 | ||
| 5240 | LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, | ||
| 5241 | LLVMConstInt(extended_type->type_ref, 8, false), ""); | ||
| 5242 | // 00ccbbaa | ||
| 5243 | return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, ""); | ||
| 5244 | } | ||
| 5245 | |||
| 5246 | static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) { | ||
| 5247 | LLVMValueRef op = ir_llvm_value(g, instruction->op); | ||
| 5248 | ZigType *int_type = instruction->base.value.type; | ||
| 5249 | assert(int_type->id == ZigTypeIdInt); | ||
| 5250 | LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBitReverse); | ||
| 5251 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | ||
| 5252 | } | ||
| 5253 | |||
| 5254 | static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable, | ||
| 5255 | IrInstructionVectorToArray *instruction) | ||
| 5256 | { | ||
| 5257 | ZigType *array_type = instruction->base.value.type; | ||
| 5258 | assert(array_type->id == ZigTypeIdArray); | ||
| 5259 | assert(handle_is_ptr(array_type)); | ||
| 5260 | assert(instruction->tmp_ptr); | ||
| 5261 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); | ||
| 5262 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, | ||
| 5263 | LLVMPointerType(instruction->vector->value.type->type_ref, 0), ""); | ||
| 5264 | gen_store_untyped(g, vector, casted_ptr, 0, false); | ||
| 5265 | return instruction->tmp_ptr; | ||
| 5266 | } | ||
| 5267 | |||
| 5268 | static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable, | ||
| 5269 | IrInstructionArrayToVector *instruction) | ||
| 5270 | { | ||
| 5271 | ZigType *vector_type = instruction->base.value.type; | ||
| 5272 | assert(vector_type->id == ZigTypeIdVector); | ||
| 5273 | assert(!handle_is_ptr(vector_type)); | ||
| 5274 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); | ||
| 5275 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, | ||
| 5276 | LLVMPointerType(vector_type->type_ref, 0), ""); | ||
| 5277 | return gen_load_untyped(g, casted_ptr, 0, false, ""); | ||
| 5278 | } | ||
| 5279 | |||
| 5280 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, | ||
| 5281 | IrInstructionAssertZero *instruction) | ||
| 5282 | { | ||
| 5283 | LLVMValueRef target = ir_llvm_value(g, instruction->target); | ||
| 5284 | ZigType *int_type = instruction->target->value.type; | ||
| 5285 | if (ir_want_runtime_safety(g, &instruction->base)) { | ||
| 5286 | return gen_assert_zero(g, target, int_type); | ||
| 5287 | } | ||
| 5288 | return nullptr; | ||
| 5289 | } | ||
| 5290 | |||
| 5101 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | 5291 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 5102 | AstNode *source_node = instruction->source_node; | 5292 | AstNode *source_node = instruction->source_node; |
| 5103 | Scope *scope = instruction->scope; | 5293 | Scope *scope = instruction->scope; |
| ... | @@ -5137,6 +5327,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5137,6 +5327,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5137 | case IrInstructionIdCUndef: | 5327 | case IrInstructionIdCUndef: |
| 5138 | case IrInstructionIdEmbedFile: | 5328 | case IrInstructionIdEmbedFile: |
| 5139 | case IrInstructionIdIntType: | 5329 | case IrInstructionIdIntType: |
| 5330 | case IrInstructionIdVectorType: | ||
| 5140 | case IrInstructionIdMemberCount: | 5331 | case IrInstructionIdMemberCount: |
| 5141 | case IrInstructionIdMemberType: | 5332 | case IrInstructionIdMemberType: |
| 5142 | case IrInstructionIdMemberName: | 5333 | case IrInstructionIdMemberName: |
| ... | @@ -5173,12 +5364,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5173,12 +5364,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5173 | case IrInstructionIdToBytes: | 5364 | case IrInstructionIdToBytes: |
| 5174 | case IrInstructionIdEnumToInt: | 5365 | case IrInstructionIdEnumToInt: |
| 5175 | case IrInstructionIdCheckRuntimeScope: | 5366 | case IrInstructionIdCheckRuntimeScope: |
| 5367 | case IrInstructionIdDeclVarSrc: | ||
| 5368 | case IrInstructionIdPtrCastSrc: | ||
| 5369 | case IrInstructionIdCmpxchgSrc: | ||
| 5176 | zig_unreachable(); | 5370 | zig_unreachable(); |
| 5177 | 5371 | ||
| 5372 | case IrInstructionIdDeclVarGen: | ||
| 5373 | return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction); | ||
| 5178 | case IrInstructionIdReturn: | 5374 | case IrInstructionIdReturn: |
| 5179 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); | 5375 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| 5180 | case IrInstructionIdDeclVar: | ||
| 5181 | return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction); | ||
| 5182 | case IrInstructionIdBinOp: | 5376 | case IrInstructionIdBinOp: |
| 5183 | return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction); | 5377 | return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction); |
| 5184 | case IrInstructionIdCast: | 5378 | case IrInstructionIdCast: |
| ... | @@ -5209,8 +5403,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5209,8 +5403,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5209 | return ir_render_asm(g, executable, (IrInstructionAsm *)instruction); | 5403 | return ir_render_asm(g, executable, (IrInstructionAsm *)instruction); |
| 5210 | case IrInstructionIdTestNonNull: | 5404 | case IrInstructionIdTestNonNull: |
| 5211 | return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction); | 5405 | return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction); |
| 5212 | case IrInstructionIdUnwrapOptional: | 5406 | case IrInstructionIdOptionalUnwrapPtr: |
| 5213 | return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction); | 5407 | return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction); |
| 5214 | case IrInstructionIdClz: | 5408 | case IrInstructionIdClz: |
| 5215 | return ir_render_clz(g, executable, (IrInstructionClz *)instruction); | 5409 | return ir_render_clz(g, executable, (IrInstructionClz *)instruction); |
| 5216 | case IrInstructionIdCtz: | 5410 | case IrInstructionIdCtz: |
| ... | @@ -5225,8 +5419,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5225,8 +5419,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5225 | return ir_render_ref(g, executable, (IrInstructionRef *)instruction); | 5419 | return ir_render_ref(g, executable, (IrInstructionRef *)instruction); |
| 5226 | case IrInstructionIdErrName: | 5420 | case IrInstructionIdErrName: |
| 5227 | return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction); | 5421 | return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction); |
| 5228 | case IrInstructionIdCmpxchg: | 5422 | case IrInstructionIdCmpxchgGen: |
| 5229 | return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction); | 5423 | return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction); |
| 5230 | case IrInstructionIdFence: | 5424 | case IrInstructionIdFence: |
| 5231 | return ir_render_fence(g, executable, (IrInstructionFence *)instruction); | 5425 | return ir_render_fence(g, executable, (IrInstructionFence *)instruction); |
| 5232 | case IrInstructionIdTruncate: | 5426 | case IrInstructionIdTruncate: |
| ... | @@ -5267,8 +5461,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5267,8 +5461,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5267 | return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); | 5461 | return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); |
| 5268 | case IrInstructionIdUnionInit: | 5462 | case IrInstructionIdUnionInit: |
| 5269 | return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction); | 5463 | return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction); |
| 5270 | case IrInstructionIdPtrCast: | 5464 | case IrInstructionIdPtrCastGen: |
| 5271 | return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction); | 5465 | return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction); |
| 5272 | case IrInstructionIdBitCast: | 5466 | case IrInstructionIdBitCast: |
| 5273 | return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction); | 5467 | return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction); |
| 5274 | case IrInstructionIdWidenOrShorten: | 5468 | case IrInstructionIdWidenOrShorten: |
| ... | @@ -5335,6 +5529,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5335,6 +5529,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5335 | return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); | 5529 | return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); |
| 5336 | case IrInstructionIdSqrt: | 5530 | case IrInstructionIdSqrt: |
| 5337 | return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); | 5531 | return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); |
| 5532 | case IrInstructionIdBswap: | ||
| 5533 | return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); | ||
| 5534 | case IrInstructionIdBitReverse: | ||
| 5535 | return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction); | ||
| 5536 | case IrInstructionIdArrayToVector: | ||
| 5537 | return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction); | ||
| 5538 | case IrInstructionIdVectorToArray: | ||
| 5539 | return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); | ||
| 5540 | case IrInstructionIdAssertZero: | ||
| 5541 | return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction); | ||
| 5338 | } | 5542 | } |
| 5339 | zig_unreachable(); | 5543 | zig_unreachable(); |
| 5340 | } | 5544 | } |
| ... | @@ -5362,6 +5566,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { | ... | @@ -5362,6 +5566,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { |
| 5362 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index); | 5566 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index); |
| 5363 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index); | 5567 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index); |
| 5364 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val); | 5568 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val); |
| 5569 | static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val); | ||
| 5570 | static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val); | ||
| 5571 | static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val); | ||
| 5365 | 5572 | ||
| 5366 | static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) { | 5573 | static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) { |
| 5367 | switch (parent->id) { | 5574 | switch (parent->id) { |
| ... | @@ -5372,6 +5579,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent | ... | @@ -5372,6 +5579,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent |
| 5372 | case ConstParentIdStruct: | 5579 | case ConstParentIdStruct: |
| 5373 | return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val, | 5580 | return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val, |
| 5374 | parent->data.p_struct.field_index); | 5581 | parent->data.p_struct.field_index); |
| 5582 | case ConstParentIdErrUnionCode: | ||
| 5583 | return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val); | ||
| 5584 | case ConstParentIdErrUnionPayload: | ||
| 5585 | return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val); | ||
| 5586 | case ConstParentIdOptionalPayload: | ||
| 5587 | return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val); | ||
| 5375 | case ConstParentIdArray: | 5588 | case ConstParentIdArray: |
| 5376 | return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val, | 5589 | return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val, |
| 5377 | parent->data.p_array.elem_index); | 5590 | parent->data.p_array.elem_index); |
| ... | @@ -5387,7 +5600,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent | ... | @@ -5387,7 +5600,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent |
| 5387 | 5600 | ||
| 5388 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) { | 5601 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) { |
| 5389 | expand_undef_array(g, array_const_val); | 5602 | expand_undef_array(g, array_const_val); |
| 5390 | ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent; | 5603 | ConstParent *parent = &array_const_val->parent; |
| 5391 | LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); | 5604 | LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); |
| 5392 | 5605 | ||
| 5393 | LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); | 5606 | LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); |
| ... | @@ -5412,7 +5625,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar | ... | @@ -5412,7 +5625,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar |
| 5412 | } | 5625 | } |
| 5413 | 5626 | ||
| 5414 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) { | 5627 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) { |
| 5415 | ConstParent *parent = &struct_const_val->data.x_struct.parent; | 5628 | ConstParent *parent = &struct_const_val->parent; |
| 5416 | LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent); | 5629 | LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent); |
| 5417 | 5630 | ||
| 5418 | ZigType *u32 = g->builtin_types.entry_u32; | 5631 | ZigType *u32 = g->builtin_types.entry_u32; |
| ... | @@ -5423,8 +5636,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s | ... | @@ -5423,8 +5636,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s |
| 5423 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | 5636 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 5424 | } | 5637 | } |
| 5425 | 5638 | ||
| 5639 | static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) { | ||
| 5640 | ConstParent *parent = &err_union_const_val->parent; | ||
| 5641 | LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent); | ||
| 5642 | |||
| 5643 | ZigType *u32 = g->builtin_types.entry_u32; | ||
| 5644 | LLVMValueRef indices[] = { | ||
| 5645 | LLVMConstNull(u32->type_ref), | ||
| 5646 | LLVMConstInt(u32->type_ref, err_union_err_index, false), | ||
| 5647 | }; | ||
| 5648 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | ||
| 5649 | } | ||
| 5650 | |||
| 5651 | static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) { | ||
| 5652 | ConstParent *parent = &err_union_const_val->parent; | ||
| 5653 | LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent); | ||
| 5654 | |||
| 5655 | ZigType *u32 = g->builtin_types.entry_u32; | ||
| 5656 | LLVMValueRef indices[] = { | ||
| 5657 | LLVMConstNull(u32->type_ref), | ||
| 5658 | LLVMConstInt(u32->type_ref, err_union_payload_index, false), | ||
| 5659 | }; | ||
| 5660 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | ||
| 5661 | } | ||
| 5662 | |||
| 5663 | static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) { | ||
| 5664 | ConstParent *parent = &optional_const_val->parent; | ||
| 5665 | LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent); | ||
| 5666 | |||
| 5667 | ZigType *u32 = g->builtin_types.entry_u32; | ||
| 5668 | LLVMValueRef indices[] = { | ||
| 5669 | LLVMConstNull(u32->type_ref), | ||
| 5670 | LLVMConstInt(u32->type_ref, maybe_child_index, false), | ||
| 5671 | }; | ||
| 5672 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | ||
| 5673 | } | ||
| 5674 | |||
| 5426 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) { | 5675 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) { |
| 5427 | ConstParent *parent = &union_const_val->data.x_union.parent; | 5676 | ConstParent *parent = &union_const_val->parent; |
| 5428 | LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent); | 5677 | LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent); |
| 5429 | 5678 | ||
| 5430 | ZigType *u32 = g->builtin_types.entry_u32; | 5679 | ZigType *u32 = g->builtin_types.entry_u32; |
| ... | @@ -5494,6 +5743,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -5494,6 +5743,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 5494 | } | 5743 | } |
| 5495 | case ZigTypeIdArray: | 5744 | case ZigTypeIdArray: |
| 5496 | zig_panic("TODO bit pack an array"); | 5745 | zig_panic("TODO bit pack an array"); |
| 5746 | case ZigTypeIdVector: | ||
| 5747 | zig_panic("TODO bit pack a vector"); | ||
| 5497 | case ZigTypeIdUnion: | 5748 | case ZigTypeIdUnion: |
| 5498 | zig_panic("TODO bit pack a union"); | 5749 | zig_panic("TODO bit pack a union"); |
| 5499 | case ZigTypeIdStruct: | 5750 | case ZigTypeIdStruct: |
| ... | @@ -5541,76 +5792,127 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con | ... | @@ -5541,76 +5792,127 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con |
| 5541 | zig_unreachable(); | 5792 | zig_unreachable(); |
| 5542 | case ConstPtrSpecialRef: | 5793 | case ConstPtrSpecialRef: |
| 5543 | { | 5794 | { |
| 5544 | render_const_val_global(g, const_val, name); | 5795 | assert(const_val->global_refs != nullptr); |
| 5545 | ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee; | 5796 | ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee; |
| 5546 | render_const_val(g, pointee, ""); | 5797 | render_const_val(g, pointee, ""); |
| 5547 | render_const_val_global(g, pointee, ""); | 5798 | render_const_val_global(g, pointee, ""); |
| 5548 | ConstExprValue *other_val = pointee; | 5799 | const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global, const_val->type->type_ref); |
| 5549 | const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref); | ||
| 5550 | render_const_val_global(g, const_val, ""); | ||
| 5551 | return const_val->global_refs->llvm_value; | 5800 | return const_val->global_refs->llvm_value; |
| 5552 | } | 5801 | } |
| 5553 | case ConstPtrSpecialBaseArray: | 5802 | case ConstPtrSpecialBaseArray: |
| 5554 | { | 5803 | { |
| 5555 | render_const_val_global(g, const_val, name); | 5804 | assert(const_val->global_refs != nullptr); |
| 5556 | ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; | 5805 | ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; |
| 5557 | size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; | ||
| 5558 | assert(array_const_val->type->id == ZigTypeIdArray); | 5806 | assert(array_const_val->type->id == ZigTypeIdArray); |
| 5559 | if (array_const_val->type->zero_bits) { | 5807 | if (!type_has_bits(array_const_val->type)) { |
| 5560 | // make this a null pointer | 5808 | // make this a null pointer |
| 5561 | ZigType *usize = g->builtin_types.entry_usize; | 5809 | ZigType *usize = g->builtin_types.entry_usize; |
| 5562 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | 5810 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), |
| 5563 | const_val->type->type_ref); | 5811 | const_val->type->type_ref); |
| 5564 | render_const_val_global(g, const_val, ""); | ||
| 5565 | return const_val->global_refs->llvm_value; | 5812 | return const_val->global_refs->llvm_value; |
| 5566 | } | 5813 | } |
| 5567 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, | 5814 | size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; |
| 5568 | elem_index); | 5815 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index); |
| 5569 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | 5816 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); |
| 5570 | const_val->global_refs->llvm_value = ptr_val; | 5817 | const_val->global_refs->llvm_value = ptr_val; |
| 5571 | render_const_val_global(g, const_val, ""); | ||
| 5572 | return ptr_val; | 5818 | return ptr_val; |
| 5573 | } | 5819 | } |
| 5574 | case ConstPtrSpecialBaseStruct: | 5820 | case ConstPtrSpecialBaseStruct: |
| 5575 | { | 5821 | { |
| 5576 | render_const_val_global(g, const_val, name); | 5822 | assert(const_val->global_refs != nullptr); |
| 5577 | ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val; | 5823 | ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val; |
| 5578 | assert(struct_const_val->type->id == ZigTypeIdStruct); | 5824 | assert(struct_const_val->type->id == ZigTypeIdStruct); |
| 5579 | if (struct_const_val->type->zero_bits) { | 5825 | if (!type_has_bits(struct_const_val->type)) { |
| 5580 | // make this a null pointer | 5826 | // make this a null pointer |
| 5581 | ZigType *usize = g->builtin_types.entry_usize; | 5827 | ZigType *usize = g->builtin_types.entry_usize; |
| 5582 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | 5828 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), |
| 5583 | const_val->type->type_ref); | 5829 | const_val->type->type_ref); |
| 5584 | render_const_val_global(g, const_val, ""); | ||
| 5585 | return const_val->global_refs->llvm_value; | 5830 | return const_val->global_refs->llvm_value; |
| 5586 | } | 5831 | } |
| 5587 | size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; | 5832 | size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; |
| 5588 | size_t gen_field_index = | 5833 | size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index; |
| 5589 | struct_const_val->type->data.structure.fields[src_field_index].gen_index; | ||
| 5590 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, | 5834 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, |
| 5591 | gen_field_index); | 5835 | gen_field_index); |
| 5592 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | 5836 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); |
| 5593 | const_val->global_refs->llvm_value = ptr_val; | 5837 | const_val->global_refs->llvm_value = ptr_val; |
| 5594 | render_const_val_global(g, const_val, ""); | 5838 | return ptr_val; |
| 5839 | } | ||
| 5840 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 5841 | { | ||
| 5842 | assert(const_val->global_refs != nullptr); | ||
| 5843 | ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val; | ||
| 5844 | assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); | ||
| 5845 | if (!type_has_bits(err_union_const_val->type)) { | ||
| 5846 | // make this a null pointer | ||
| 5847 | ZigType *usize = g->builtin_types.entry_usize; | ||
| 5848 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5849 | const_val->type->type_ref); | ||
| 5850 | return const_val->global_refs->llvm_value; | ||
| 5851 | } | ||
| 5852 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val); | ||
| 5853 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5854 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5855 | return ptr_val; | ||
| 5856 | } | ||
| 5857 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 5858 | { | ||
| 5859 | assert(const_val->global_refs != nullptr); | ||
| 5860 | ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val; | ||
| 5861 | assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); | ||
| 5862 | if (err_union_const_val->type->zero_bits) { | ||
| 5863 | // make this a null pointer | ||
| 5864 | ZigType *usize = g->builtin_types.entry_usize; | ||
| 5865 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5866 | const_val->type->type_ref); | ||
| 5867 | return const_val->global_refs->llvm_value; | ||
| 5868 | } | ||
| 5869 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val); | ||
| 5870 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5871 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5872 | return ptr_val; | ||
| 5873 | } | ||
| 5874 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 5875 | { | ||
| 5876 | assert(const_val->global_refs != nullptr); | ||
| 5877 | ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val; | ||
| 5878 | assert(optional_const_val->type->id == ZigTypeIdOptional); | ||
| 5879 | if (optional_const_val->type->zero_bits) { | ||
| 5880 | // make this a null pointer | ||
| 5881 | ZigType *usize = g->builtin_types.entry_usize; | ||
| 5882 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5883 | const_val->type->type_ref); | ||
| 5884 | return const_val->global_refs->llvm_value; | ||
| 5885 | } | ||
| 5886 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val); | ||
| 5887 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5888 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5595 | return ptr_val; | 5889 | return ptr_val; |
| 5596 | } | 5890 | } |
| 5597 | case ConstPtrSpecialHardCodedAddr: | 5891 | case ConstPtrSpecialHardCodedAddr: |
| 5598 | { | 5892 | { |
| 5599 | render_const_val_global(g, const_val, name); | 5893 | assert(const_val->global_refs != nullptr); |
| 5600 | uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr; | 5894 | uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr; |
| 5601 | ZigType *usize = g->builtin_types.entry_usize; | 5895 | ZigType *usize = g->builtin_types.entry_usize; |
| 5602 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false), | 5896 | const_val->global_refs->llvm_value = LLVMConstIntToPtr( |
| 5603 | const_val->type->type_ref); | 5897 | LLVMConstInt(usize->type_ref, addr_value, false), const_val->type->type_ref); |
| 5604 | render_const_val_global(g, const_val, ""); | ||
| 5605 | return const_val->global_refs->llvm_value; | 5898 | return const_val->global_refs->llvm_value; |
| 5606 | } | 5899 | } |
| 5607 | case ConstPtrSpecialFunction: | 5900 | case ConstPtrSpecialFunction: |
| 5608 | return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); | 5901 | return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); |
| 5902 | case ConstPtrSpecialNull: | ||
| 5903 | return LLVMConstNull(const_val->type->type_ref); | ||
| 5609 | } | 5904 | } |
| 5610 | zig_unreachable(); | 5905 | zig_unreachable(); |
| 5611 | } | 5906 | } |
| 5612 | 5907 | ||
| 5908 | static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) { | ||
| 5909 | uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value; | ||
| 5910 | return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false); | ||
| 5911 | } | ||
| 5912 | |||
| 5613 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { | 5913 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { |
| 5914 | Error err; | ||
| 5915 | |||
| 5614 | ZigType *type_entry = const_val->type; | 5916 | ZigType *type_entry = const_val->type; |
| 5615 | assert(!type_entry->zero_bits); | 5917 | assert(!type_entry->zero_bits); |
| 5616 | 5918 | ||
| ... | @@ -5627,9 +5929,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5627,9 +5929,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5627 | case ZigTypeIdInt: | 5929 | case ZigTypeIdInt: |
| 5628 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); | 5930 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); |
| 5629 | case ZigTypeIdErrorSet: | 5931 | case ZigTypeIdErrorSet: |
| 5630 | assert(const_val->data.x_err_set != nullptr); | 5932 | return gen_const_val_err_set(g, const_val, name); |
| 5631 | return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, | ||
| 5632 | const_val->data.x_err_set->value, false); | ||
| 5633 | case ZigTypeIdFloat: | 5933 | case ZigTypeIdFloat: |
| 5634 | switch (type_entry->data.floating.bit_count) { | 5934 | switch (type_entry->data.floating.bit_count) { |
| 5635 | case 16: | 5935 | case 16: |
| ... | @@ -5663,6 +5963,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5663,6 +5963,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5663 | return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false); | 5963 | return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false); |
| 5664 | } else if (type_is_codegen_pointer(child_type)) { | 5964 | } else if (type_is_codegen_pointer(child_type)) { |
| 5665 | return gen_const_val_ptr(g, const_val, name); | 5965 | return gen_const_val_ptr(g, const_val, name); |
| 5966 | } else if (child_type->id == ZigTypeIdErrorSet) { | ||
| 5967 | return gen_const_val_err_set(g, const_val, name); | ||
| 5666 | } else { | 5968 | } else { |
| 5667 | LLVMValueRef child_val; | 5969 | LLVMValueRef child_val; |
| 5668 | LLVMValueRef maybe_val; | 5970 | LLVMValueRef maybe_val; |
| ... | @@ -5754,6 +6056,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5754,6 +6056,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5754 | } | 6056 | } |
| 5755 | ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; | 6057 | ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; |
| 5756 | assert(field_val->type != nullptr); | 6058 | assert(field_val->type != nullptr); |
| 6059 | if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, | ||
| 6060 | type_struct_field->type_entry))) | ||
| 6061 | { | ||
| 6062 | zig_unreachable(); | ||
| 6063 | } | ||
| 6064 | |||
| 5757 | LLVMValueRef val = gen_const_val(g, field_val, ""); | 6065 | LLVMValueRef val = gen_const_val(g, field_val, ""); |
| 5758 | fields[type_struct_field->gen_index] = val; | 6066 | fields[type_struct_field->gen_index] = val; |
| 5759 | make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); | 6067 | make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); |
| ... | @@ -5793,7 +6101,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5793,7 +6101,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5793 | return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true); | 6101 | return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true); |
| 5794 | } | 6102 | } |
| 5795 | } | 6103 | } |
| 6104 | zig_unreachable(); | ||
| 6105 | } | ||
| 6106 | case ZigTypeIdVector: { | ||
| 6107 | uint32_t len = type_entry->data.vector.len; | ||
| 6108 | switch (const_val->data.x_array.special) { | ||
| 6109 | case ConstArraySpecialUndef: | ||
| 6110 | return LLVMGetUndef(type_entry->type_ref); | ||
| 6111 | case ConstArraySpecialNone: { | ||
| 6112 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | ||
| 6113 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6114 | ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i]; | ||
| 6115 | values[i] = gen_const_val(g, elem_value, ""); | ||
| 6116 | } | ||
| 6117 | return LLVMConstVector(values, len); | ||
| 6118 | } | ||
| 6119 | case ConstArraySpecialBuf: { | ||
| 6120 | Buf *buf = const_val->data.x_array.data.s_buf; | ||
| 6121 | assert(buf_len(buf) == len); | ||
| 6122 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | ||
| 6123 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 6124 | values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false); | ||
| 6125 | } | ||
| 6126 | return LLVMConstVector(values, len); | ||
| 6127 | } | ||
| 5796 | } | 6128 | } |
| 6129 | zig_unreachable(); | ||
| 6130 | } | ||
| 5797 | case ZigTypeIdUnion: | 6131 | case ZigTypeIdUnion: |
| 5798 | { | 6132 | { |
| 5799 | LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref; | 6133 | LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref; |
| ... | @@ -5891,7 +6225,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5891,7 +6225,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5891 | ZigType *err_set_type = type_entry->data.error_union.err_set_type; | 6225 | ZigType *err_set_type = type_entry->data.error_union.err_set_type; |
| 5892 | if (!type_has_bits(payload_type)) { | 6226 | if (!type_has_bits(payload_type)) { |
| 5893 | assert(type_has_bits(err_set_type)); | 6227 | assert(type_has_bits(err_set_type)); |
| 5894 | uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0; | 6228 | ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; |
| 6229 | uint64_t value = (err_set == nullptr) ? 0 : err_set->value; | ||
| 5895 | return LLVMConstInt(g->err_tag_type->type_ref, value, false); | 6230 | return LLVMConstInt(g->err_tag_type->type_ref, value, false); |
| 5896 | } else if (!type_has_bits(err_set_type)) { | 6231 | } else if (!type_has_bits(err_set_type)) { |
| 5897 | assert(type_has_bits(payload_type)); | 6232 | assert(type_has_bits(payload_type)); |
| ... | @@ -5900,8 +6235,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5900,8 +6235,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5900 | LLVMValueRef err_tag_value; | 6235 | LLVMValueRef err_tag_value; |
| 5901 | LLVMValueRef err_payload_value; | 6236 | LLVMValueRef err_payload_value; |
| 5902 | bool make_unnamed_struct; | 6237 | bool make_unnamed_struct; |
| 5903 | if (const_val->data.x_err_union.err) { | 6238 | ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; |
| 5904 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); | 6239 | if (err_set != nullptr) { |
| 6240 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false); | ||
| 5905 | err_payload_value = LLVMConstNull(payload_type->type_ref); | 6241 | err_payload_value = LLVMConstNull(payload_type->type_ref); |
| 5906 | make_unnamed_struct = false; | 6242 | make_unnamed_struct = false; |
| 5907 | } else { | 6243 | } else { |
| ... | @@ -6075,6 +6411,12 @@ static void validate_inline_fns(CodeGen *g) { | ... | @@ -6075,6 +6411,12 @@ static void validate_inline_fns(CodeGen *g) { |
| 6075 | report_errors_and_maybe_exit(g); | 6411 | report_errors_and_maybe_exit(g); |
| 6076 | } | 6412 | } |
| 6077 | 6413 | ||
| 6414 | static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) { | ||
| 6415 | if (var->is_thread_local && !g->is_single_threaded) { | ||
| 6416 | LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel); | ||
| 6417 | } | ||
| 6418 | } | ||
| 6419 | |||
| 6078 | static void do_code_gen(CodeGen *g) { | 6420 | static void do_code_gen(CodeGen *g) { |
| 6079 | assert(!g->errors.length); | 6421 | assert(!g->errors.length); |
| 6080 | 6422 | ||
| ... | @@ -6107,10 +6449,13 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6107,10 +6449,13 @@ static void do_code_gen(CodeGen *g) { |
| 6107 | TldVar *tld_var = g->global_vars.at(i); | 6449 | TldVar *tld_var = g->global_vars.at(i); |
| 6108 | ZigVar *var = tld_var->var; | 6450 | ZigVar *var = tld_var->var; |
| 6109 | 6451 | ||
| 6110 | if (var->value->type->id == ZigTypeIdComptimeFloat) { | 6452 | if (var->var_type->id == ZigTypeIdComptimeFloat) { |
| 6111 | // Generate debug info for it but that's it. | 6453 | // Generate debug info for it but that's it. |
| 6112 | ConstExprValue *const_val = var->value; | 6454 | ConstExprValue *const_val = var->const_value; |
| 6113 | assert(const_val->special != ConstValSpecialRuntime); | 6455 | assert(const_val->special != ConstValSpecialRuntime); |
| 6456 | if (const_val->type != var->var_type) { | ||
| 6457 | zig_panic("TODO debug info for var with ptr casted value"); | ||
| 6458 | } | ||
| 6114 | ZigType *var_type = g->builtin_types.entry_f128; | 6459 | ZigType *var_type = g->builtin_types.entry_f128; |
| 6115 | ConstExprValue coerced_value; | 6460 | ConstExprValue coerced_value; |
| 6116 | coerced_value.special = ConstValSpecialStatic; | 6461 | coerced_value.special = ConstValSpecialStatic; |
| ... | @@ -6121,10 +6466,13 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6121,10 +6466,13 @@ static void do_code_gen(CodeGen *g) { |
| 6121 | continue; | 6466 | continue; |
| 6122 | } | 6467 | } |
| 6123 | 6468 | ||
| 6124 | if (var->value->type->id == ZigTypeIdComptimeInt) { | 6469 | if (var->var_type->id == ZigTypeIdComptimeInt) { |
| 6125 | // Generate debug info for it but that's it. | 6470 | // Generate debug info for it but that's it. |
| 6126 | ConstExprValue *const_val = var->value; | 6471 | ConstExprValue *const_val = var->const_value; |
| 6127 | assert(const_val->special != ConstValSpecialRuntime); | 6472 | assert(const_val->special != ConstValSpecialRuntime); |
| 6473 | if (const_val->type != var->var_type) { | ||
| 6474 | zig_panic("TODO debug info for var with ptr casted value"); | ||
| 6475 | } | ||
| 6128 | size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint); | 6476 | size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint); |
| 6129 | if (bits_needed < 8) { | 6477 | if (bits_needed < 8) { |
| 6130 | bits_needed = 8; | 6478 | bits_needed = 8; |
| ... | @@ -6135,7 +6483,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6135,7 +6483,7 @@ static void do_code_gen(CodeGen *g) { |
| 6135 | continue; | 6483 | continue; |
| 6136 | } | 6484 | } |
| 6137 | 6485 | ||
| 6138 | if (!type_has_bits(var->value->type)) | 6486 | if (!type_has_bits(var->var_type)) |
| 6139 | continue; | 6487 | continue; |
| 6140 | 6488 | ||
| 6141 | assert(var->decl_node); | 6489 | assert(var->decl_node); |
| ... | @@ -6144,22 +6492,23 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6144,22 +6492,23 @@ static void do_code_gen(CodeGen *g) { |
| 6144 | if (var->linkage == VarLinkageExternal) { | 6492 | if (var->linkage == VarLinkageExternal) { |
| 6145 | LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name)); | 6493 | LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name)); |
| 6146 | if (existing_llvm_var) { | 6494 | if (existing_llvm_var) { |
| 6147 | global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0)); | 6495 | global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0)); |
| 6148 | } else { | 6496 | } else { |
| 6149 | global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name)); | 6497 | global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name)); |
| 6150 | // TODO debug info for the extern variable | 6498 | // TODO debug info for the extern variable |
| 6151 | 6499 | ||
| 6152 | LLVMSetLinkage(global_value, LLVMExternalLinkage); | 6500 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| 6153 | maybe_import_dll(g, global_value, GlobalLinkageIdStrong); | 6501 | maybe_import_dll(g, global_value, GlobalLinkageIdStrong); |
| 6154 | LLVMSetAlignment(global_value, var->align_bytes); | 6502 | LLVMSetAlignment(global_value, var->align_bytes); |
| 6155 | LLVMSetGlobalConstant(global_value, var->gen_is_const); | 6503 | LLVMSetGlobalConstant(global_value, var->gen_is_const); |
| 6504 | set_global_tls(g, var, global_value); | ||
| 6156 | } | 6505 | } |
| 6157 | } else { | 6506 | } else { |
| 6158 | bool exported = (var->linkage == VarLinkageExport); | 6507 | bool exported = (var->linkage == VarLinkageExport); |
| 6159 | const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported)); | 6508 | const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported)); |
| 6160 | render_const_val(g, var->value, mangled_name); | 6509 | render_const_val(g, var->const_value, mangled_name); |
| 6161 | render_const_val_global(g, var->value, mangled_name); | 6510 | render_const_val_global(g, var->const_value, mangled_name); |
| 6162 | global_value = var->value->global_refs->llvm_global; | 6511 | global_value = var->const_value->global_refs->llvm_global; |
| 6163 | 6512 | ||
| 6164 | if (exported) { | 6513 | if (exported) { |
| 6165 | LLVMSetLinkage(global_value, LLVMExternalLinkage); | 6514 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| ... | @@ -6171,11 +6520,14 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6171,11 +6520,14 @@ static void do_code_gen(CodeGen *g) { |
| 6171 | LLVMSetAlignment(global_value, var->align_bytes); | 6520 | LLVMSetAlignment(global_value, var->align_bytes); |
| 6172 | 6521 | ||
| 6173 | // TODO debug info for function pointers | 6522 | // TODO debug info for function pointers |
| 6174 | if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) { | 6523 | // Here we use const_value->type because that's the type of the llvm global, |
| 6175 | gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type); | 6524 | // which we const ptr cast upon use to whatever it needs to be. |
| 6525 | if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) { | ||
| 6526 | gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type); | ||
| 6176 | } | 6527 | } |
| 6177 | 6528 | ||
| 6178 | LLVMSetGlobalConstant(global_value, var->gen_is_const); | 6529 | LLVMSetGlobalConstant(global_value, var->gen_is_const); |
| 6530 | set_global_tls(g, var, global_value); | ||
| 6179 | } | 6531 | } |
| 6180 | 6532 | ||
| 6181 | var->value_ref = global_value; | 6533 | var->value_ref = global_value; |
| ... | @@ -6226,6 +6578,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6226,6 +6578,7 @@ static void do_code_gen(CodeGen *g) { |
| 6226 | IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i); | 6578 | IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i); |
| 6227 | LLVMValueRef *slot; | 6579 | LLVMValueRef *slot; |
| 6228 | ZigType *slot_type = instruction->value.type; | 6580 | ZigType *slot_type = instruction->value.type; |
| 6581 | uint32_t alignment_bytes = 0; | ||
| 6229 | if (instruction->id == IrInstructionIdCast) { | 6582 | if (instruction->id == IrInstructionIdCast) { |
| 6230 | IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction; | 6583 | IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction; |
| 6231 | slot = &cast_instruction->tmp_ptr; | 6584 | slot = &cast_instruction->tmp_ptr; |
| ... | @@ -6258,13 +6611,17 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6258,13 +6611,17 @@ static void do_code_gen(CodeGen *g) { |
| 6258 | } else if (instruction->id == IrInstructionIdErrWrapCode) { | 6611 | } else if (instruction->id == IrInstructionIdErrWrapCode) { |
| 6259 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; | 6612 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; |
| 6260 | slot = &err_wrap_code_instruction->tmp_ptr; | 6613 | slot = &err_wrap_code_instruction->tmp_ptr; |
| 6261 | } else if (instruction->id == IrInstructionIdCmpxchg) { | 6614 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { |
| 6262 | IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction; | 6615 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; |
| 6263 | slot = &cmpxchg_instruction->tmp_ptr; | 6616 | slot = &cmpxchg_instruction->tmp_ptr; |
| 6617 | } else if (instruction->id == IrInstructionIdVectorToArray) { | ||
| 6618 | IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction; | ||
| 6619 | alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type); | ||
| 6620 | slot = &vector_to_array_instruction->tmp_ptr; | ||
| 6264 | } else { | 6621 | } else { |
| 6265 | zig_unreachable(); | 6622 | zig_unreachable(); |
| 6266 | } | 6623 | } |
| 6267 | *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type)); | 6624 | *slot = build_alloca(g, slot_type, "", alignment_bytes); |
| 6268 | } | 6625 | } |
| 6269 | 6626 | ||
| 6270 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); | 6627 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| ... | @@ -6281,12 +6638,12 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6281,12 +6638,12 @@ static void do_code_gen(CodeGen *g) { |
| 6281 | for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { | 6638 | for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { |
| 6282 | ZigVar *var = fn_table_entry->variable_list.at(var_i); | 6639 | ZigVar *var = fn_table_entry->variable_list.at(var_i); |
| 6283 | 6640 | ||
| 6284 | if (!type_has_bits(var->value->type)) { | 6641 | if (!type_has_bits(var->var_type)) { |
| 6285 | continue; | 6642 | continue; |
| 6286 | } | 6643 | } |
| 6287 | if (ir_get_var_is_comptime(var)) | 6644 | if (ir_get_var_is_comptime(var)) |
| 6288 | continue; | 6645 | continue; |
| 6289 | switch (type_requires_comptime(g, var->value->type)) { | 6646 | switch (type_requires_comptime(g, var->var_type)) { |
| 6290 | case ReqCompTimeInvalid: | 6647 | case ReqCompTimeInvalid: |
| 6291 | zig_unreachable(); | 6648 | zig_unreachable(); |
| 6292 | case ReqCompTimeYes: | 6649 | case ReqCompTimeYes: |
| ... | @@ -6296,11 +6653,11 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6296,11 +6653,11 @@ static void do_code_gen(CodeGen *g) { |
| 6296 | } | 6653 | } |
| 6297 | 6654 | ||
| 6298 | if (var->src_arg_index == SIZE_MAX) { | 6655 | if (var->src_arg_index == SIZE_MAX) { |
| 6299 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | 6656 | var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); |
| 6300 | 6657 | ||
| 6301 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 6658 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 6302 | buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1), | 6659 | buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1), |
| 6303 | var->value->type->di_type, !g->strip_debug_symbols, 0); | 6660 | var->var_type->di_type, !g->strip_debug_symbols, 0); |
| 6304 | 6661 | ||
| 6305 | } else if (is_c_abi) { | 6662 | } else if (is_c_abi) { |
| 6306 | fn_walk_var.data.vars.var = var; | 6663 | fn_walk_var.data.vars.var = var; |
| ... | @@ -6310,16 +6667,16 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6310,16 +6667,16 @@ static void do_code_gen(CodeGen *g) { |
| 6310 | ZigType *gen_type; | 6667 | ZigType *gen_type; |
| 6311 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; | 6668 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; |
| 6312 | 6669 | ||
| 6313 | if (handle_is_ptr(var->value->type)) { | 6670 | if (handle_is_ptr(var->var_type)) { |
| 6314 | if (gen_info->is_byval) { | 6671 | if (gen_info->is_byval) { |
| 6315 | gen_type = var->value->type; | 6672 | gen_type = var->var_type; |
| 6316 | } else { | 6673 | } else { |
| 6317 | gen_type = gen_info->type; | 6674 | gen_type = gen_info->type; |
| 6318 | } | 6675 | } |
| 6319 | var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); | 6676 | var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); |
| 6320 | } else { | 6677 | } else { |
| 6321 | gen_type = var->value->type; | 6678 | gen_type = var->var_type; |
| 6322 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | 6679 | var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); |
| 6323 | } | 6680 | } |
| 6324 | if (var->decl_node) { | 6681 | if (var->decl_node) { |
| 6325 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 6682 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| ... | @@ -6719,6 +7076,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -6719,6 +7076,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 6719 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); | 7076 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); |
| 6720 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); | 7077 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); |
| 6721 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int | 7078 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int |
| 7079 | create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2); | ||
| 6722 | create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1); | 7080 | create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1); |
| 6723 | create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1); | 7081 | create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1); |
| 6724 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1); | 7082 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1); |
| ... | @@ -6757,6 +7115,8 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -6757,6 +7115,8 @@ static void define_builtin_fns(CodeGen *g) { |
| 6757 | create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); | 7115 | create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); |
| 6758 | create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); | 7116 | create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); |
| 6759 | create_builtin_fn(g, BuiltinFnIdThis, "This", 0); | 7117 | create_builtin_fn(g, BuiltinFnIdThis, "This", 0); |
| 7118 | create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2); | ||
| 7119 | create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2); | ||
| 6760 | } | 7120 | } |
| 6761 | 7121 | ||
| 6762 | static const char *bool_to_str(bool b) { | 7122 | static const char *bool_to_str(bool b) { |
| ... | @@ -6784,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -6784,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 6784 | " instruction_addresses: []usize,\n" | 7144 | " instruction_addresses: []usize,\n" |
| 6785 | "};\n\n"); | 7145 | "};\n\n"); |
| 6786 | 7146 | ||
| 7147 | buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n"); | ||
| 7148 | |||
| 6787 | const char *cur_os = nullptr; | 7149 | const char *cur_os = nullptr; |
| 6788 | { | 7150 | { |
| 6789 | buf_appendf(contents, "pub const Os = enum {\n"); | 7151 | buf_appendf(contents, "pub const Os = enum {\n"); |
| ... | @@ -6942,6 +7304,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -6942,6 +7304,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 6942 | " ArgTuple: void,\n" | 7304 | " ArgTuple: void,\n" |
| 6943 | " Opaque: void,\n" | 7305 | " Opaque: void,\n" |
| 6944 | " Promise: Promise,\n" | 7306 | " Promise: Promise,\n" |
| 7307 | " Vector: Vector,\n" | ||
| 6945 | "\n\n" | 7308 | "\n\n" |
| 6946 | " pub const Int = struct {\n" | 7309 | " pub const Int = struct {\n" |
| 6947 | " is_signed: bool,\n" | 7310 | " is_signed: bool,\n" |
| ... | @@ -6963,6 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -6963,6 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 6963 | " One,\n" | 7326 | " One,\n" |
| 6964 | " Many,\n" | 7327 | " Many,\n" |
| 6965 | " Slice,\n" | 7328 | " Slice,\n" |
| 7329 | " C,\n" | ||
| 6966 | " };\n" | 7330 | " };\n" |
| 6967 | " };\n" | 7331 | " };\n" |
| 6968 | "\n" | 7332 | "\n" |
| ... | @@ -7060,6 +7424,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -7060,6 +7424,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7060 | " child: ?type,\n" | 7424 | " child: ?type,\n" |
| 7061 | " };\n" | 7425 | " };\n" |
| 7062 | "\n" | 7426 | "\n" |
| 7427 | " pub const Vector = struct {\n" | ||
| 7428 | " len: u32,\n" | ||
| 7429 | " child: type,\n" | ||
| 7430 | " };\n" | ||
| 7431 | "\n" | ||
| 7063 | " pub const Definition = struct {\n" | 7432 | " pub const Definition = struct {\n" |
| 7064 | " name: []const u8,\n" | 7433 | " name: []const u8,\n" |
| 7065 | " is_pub: bool,\n" | 7434 | " is_pub: bool,\n" |
| ... | @@ -7128,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -7128,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7128 | buf_appendf(contents, "pub const endian = %s;\n", endian_str); | 7497 | buf_appendf(contents, "pub const endian = %s;\n", endian_str); |
| 7129 | } | 7498 | } |
| 7130 | buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); | 7499 | buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); |
| 7500 | buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); | ||
| 7131 | buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); | 7501 | buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); |
| 7132 | buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); | 7502 | buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); |
| 7133 | buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ); | 7503 | buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ); |
| ... | @@ -7162,6 +7532,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { | ... | @@ -7162,6 +7532,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 7162 | cache_buf(&cache_hash, compiler_id); | 7532 | cache_buf(&cache_hash, compiler_id); |
| 7163 | cache_int(&cache_hash, g->build_mode); | 7533 | cache_int(&cache_hash, g->build_mode); |
| 7164 | cache_bool(&cache_hash, g->is_test_build); | 7534 | cache_bool(&cache_hash, g->is_test_build); |
| 7535 | cache_bool(&cache_hash, g->is_single_threaded); | ||
| 7165 | cache_int(&cache_hash, g->zig_target.arch.arch); | 7536 | cache_int(&cache_hash, g->zig_target.arch.arch); |
| 7166 | cache_int(&cache_hash, g->zig_target.arch.sub_arch); | 7537 | cache_int(&cache_hash, g->zig_target.arch.sub_arch); |
| 7167 | cache_int(&cache_hash, g->zig_target.vendor); | 7538 | cache_int(&cache_hash, g->zig_target.vendor); |
| ... | @@ -7210,6 +7581,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { | ... | @@ -7210,6 +7581,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 7210 | g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename); | 7581 | g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename); |
| 7211 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); | 7582 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 7212 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); | 7583 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 7584 | g->std_package->package_table.put(buf_create_from_str("std"), g->std_package); | ||
| 7213 | g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents); | 7585 | g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents); |
| 7214 | scan_import(g, g->compile_var_import); | 7586 | scan_import(g, g->compile_var_import); |
| 7215 | 7587 | ||
| ... | @@ -7231,8 +7603,7 @@ static void init(CodeGen *g) { | ... | @@ -7231,8 +7603,7 @@ static void init(CodeGen *g) { |
| 7231 | } | 7603 | } |
| 7232 | 7604 | ||
| 7233 | if (g->is_test_build) { | 7605 | if (g->is_test_build) { |
| 7234 | g->windows_subsystem_windows = false; | 7606 | g->subsystem = TargetSubsystemConsole; |
| 7235 | g->windows_subsystem_console = true; | ||
| 7236 | } | 7607 | } |
| 7237 | 7608 | ||
| 7238 | assert(g->root_out_name); | 7609 | assert(g->root_out_name); |
| ... | @@ -7251,7 +7622,13 @@ static void init(CodeGen *g) { | ... | @@ -7251,7 +7622,13 @@ static void init(CodeGen *g) { |
| 7251 | LLVMTargetRef target_ref; | 7622 | LLVMTargetRef target_ref; |
| 7252 | char *err_msg = nullptr; | 7623 | char *err_msg = nullptr; |
| 7253 | if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) { | 7624 | if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) { |
| 7254 | zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str)); | 7625 | fprintf(stderr, |
| 7626 | "Zig is expecting LLVM to understand this target: '%s'\n" | ||
| 7627 | "However LLVM responded with: \"%s\"\n" | ||
| 7628 | "Zig is unable to continue. This is a bug in Zig:\n" | ||
| 7629 | "https://github.com/ziglang/zig/issues/438\n" | ||
| 7630 | , buf_ptr(&g->triple_str), err_msg); | ||
| 7631 | exit(1); | ||
| 7255 | } | 7632 | } |
| 7256 | 7633 | ||
| 7257 | bool is_optimized = g->build_mode != BuildModeDebug; | 7634 | bool is_optimized = g->build_mode != BuildModeDebug; |
| ... | @@ -7268,7 +7645,7 @@ static void init(CodeGen *g) { | ... | @@ -7268,7 +7645,7 @@ static void init(CodeGen *g) { |
| 7268 | // LLVM creates invalid binaries on Windows sometimes. | 7645 | // LLVM creates invalid binaries on Windows sometimes. |
| 7269 | // See https://github.com/ziglang/zig/issues/508 | 7646 | // See https://github.com/ziglang/zig/issues/508 |
| 7270 | // As a workaround we do not use target native features on Windows. | 7647 | // As a workaround we do not use target native features on Windows. |
| 7271 | if (g->zig_target.os == OsWindows) { | 7648 | if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) { |
| 7272 | target_specific_cpu_args = ""; | 7649 | target_specific_cpu_args = ""; |
| 7273 | target_specific_features = ""; | 7650 | target_specific_features = ""; |
| 7274 | } else { | 7651 | } else { |
| ... | @@ -7434,9 +7811,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { | ... | @@ -7434,9 +7811,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 7434 | ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i]; | 7811 | ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i]; |
| 7435 | this_val->special = ConstValSpecialStatic; | 7812 | this_val->special = ConstValSpecialStatic; |
| 7436 | this_val->type = struct_type; | 7813 | this_val->type = struct_type; |
| 7437 | this_val->data.x_struct.parent.id = ConstParentIdArray; | 7814 | this_val->parent.id = ConstParentIdArray; |
| 7438 | this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array; | 7815 | this_val->parent.data.p_array.array_val = test_fn_array; |
| 7439 | this_val->data.x_struct.parent.data.p_array.elem_index = i; | 7816 | this_val->parent.data.p_array.elem_index = i; |
| 7440 | this_val->data.x_struct.fields = create_const_vals(2); | 7817 | this_val->data.x_struct.fields = create_const_vals(2); |
| 7441 | 7818 | ||
| 7442 | ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; | 7819 | ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; |
| ... | @@ -7514,6 +7891,7 @@ static void gen_root_source(CodeGen *g) { | ... | @@ -7514,6 +7891,7 @@ static void gen_root_source(CodeGen *g) { |
| 7514 | report_errors_and_maybe_exit(g); | 7891 | report_errors_and_maybe_exit(g); |
| 7515 | 7892 | ||
| 7516 | if (!g->is_test_build && g->zig_target.os != OsFreestanding && | 7893 | if (!g->is_test_build && g->zig_target.os != OsFreestanding && |
| 7894 | g->zig_target.os != OsUefi && | ||
| 7517 | !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup && | 7895 | !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup && |
| 7518 | ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) | 7896 | ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) |
| 7519 | { | 7897 | { |
| ... | @@ -7537,6 +7915,8 @@ static void gen_root_source(CodeGen *g) { | ... | @@ -7537,6 +7915,8 @@ static void gen_root_source(CodeGen *g) { |
| 7537 | } | 7915 | } |
| 7538 | } | 7916 | } |
| 7539 | 7917 | ||
| 7918 | typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn); | ||
| 7919 | |||
| 7540 | report_errors_and_maybe_exit(g); | 7920 | report_errors_and_maybe_exit(g); |
| 7541 | 7921 | ||
| 7542 | } | 7922 | } |
| ... | @@ -7631,6 +8011,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e | ... | @@ -7631,6 +8011,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e |
| 7631 | case ZigTypeIdArray: | 8011 | case ZigTypeIdArray: |
| 7632 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type); | 8012 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type); |
| 7633 | return; | 8013 | return; |
| 8014 | case ZigTypeIdVector: | ||
| 8015 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type); | ||
| 8016 | return; | ||
| 7634 | case ZigTypeIdOptional: | 8017 | case ZigTypeIdOptional: |
| 7635 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type); | 8018 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type); |
| 7636 | return; | 8019 | return; |
| ... | @@ -7762,6 +8145,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu | ... | @@ -7762,6 +8145,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu |
| 7762 | buf_appendf(out_buf, "%s", buf_ptr(child_buf)); | 8145 | buf_appendf(out_buf, "%s", buf_ptr(child_buf)); |
| 7763 | return; | 8146 | return; |
| 7764 | } | 8147 | } |
| 8148 | case ZigTypeIdVector: | ||
| 8149 | zig_panic("TODO implement get_c_type for vector types"); | ||
| 7765 | case ZigTypeIdErrorUnion: | 8150 | case ZigTypeIdErrorUnion: |
| 7766 | case ZigTypeIdErrorSet: | 8151 | case ZigTypeIdErrorSet: |
| 7767 | case ZigTypeIdFn: | 8152 | case ZigTypeIdFn: |
| ... | @@ -7927,6 +8312,7 @@ static void gen_h_file(CodeGen *g) { | ... | @@ -7927,6 +8312,7 @@ static void gen_h_file(CodeGen *g) { |
| 7927 | case ZigTypeIdOptional: | 8312 | case ZigTypeIdOptional: |
| 7928 | case ZigTypeIdFn: | 8313 | case ZigTypeIdFn: |
| 7929 | case ZigTypeIdPromise: | 8314 | case ZigTypeIdPromise: |
| 8315 | case ZigTypeIdVector: | ||
| 7930 | zig_unreachable(); | 8316 | zig_unreachable(); |
| 7931 | case ZigTypeIdEnum: | 8317 | case ZigTypeIdEnum: |
| 7932 | if (type_entry->data.enumeration.layout == ContainerLayoutExtern) { | 8318 | if (type_entry->data.enumeration.layout == ContainerLayoutExtern) { |
| ... | @@ -8033,8 +8419,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) { | ... | @@ -8033,8 +8419,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) { |
| 8033 | if (!entry) | 8419 | if (!entry) |
| 8034 | break; | 8420 | break; |
| 8035 | 8421 | ||
| 8036 | cache_buf(ch, entry->key); | 8422 | // TODO: I think we need a more sophisticated detection of |
| 8037 | add_cache_pkg(g, ch, entry->value); | 8423 | // packages we have already seen |
| 8424 | if (entry->value != pkg) { | ||
| 8425 | cache_buf(ch, entry->key); | ||
| 8426 | add_cache_pkg(g, ch, entry->value); | ||
| 8427 | } | ||
| 8038 | } | 8428 | } |
| 8039 | } | 8429 | } |
| 8040 | 8430 | ||
| ... | @@ -8070,12 +8460,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { | ... | @@ -8070,12 +8460,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 8070 | cache_int(ch, g->zig_target.os); | 8460 | cache_int(ch, g->zig_target.os); |
| 8071 | cache_int(ch, g->zig_target.env_type); | 8461 | cache_int(ch, g->zig_target.env_type); |
| 8072 | cache_int(ch, g->zig_target.oformat); | 8462 | cache_int(ch, g->zig_target.oformat); |
| 8463 | cache_int(ch, g->subsystem); | ||
| 8073 | cache_bool(ch, g->is_static); | 8464 | cache_bool(ch, g->is_static); |
| 8074 | cache_bool(ch, g->strip_debug_symbols); | 8465 | cache_bool(ch, g->strip_debug_symbols); |
| 8075 | cache_bool(ch, g->is_test_build); | 8466 | cache_bool(ch, g->is_test_build); |
| 8467 | cache_bool(ch, g->is_single_threaded); | ||
| 8076 | cache_bool(ch, g->is_native_target); | 8468 | cache_bool(ch, g->is_native_target); |
| 8077 | cache_bool(ch, g->windows_subsystem_windows); | ||
| 8078 | cache_bool(ch, g->windows_subsystem_console); | ||
| 8079 | cache_bool(ch, g->linker_rdynamic); | 8469 | cache_bool(ch, g->linker_rdynamic); |
| 8080 | cache_bool(ch, g->no_rosegment_workaround); | 8470 | cache_bool(ch, g->no_rosegment_workaround); |
| 8081 | cache_bool(ch, g->each_lib_rpath); | 8471 | cache_bool(ch, g->each_lib_rpath); |
src/codegen.hpp+1-2| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | #include <stdio.h> | 15 | #include <stdio.h> |
| 16 | 16 | ||
| 17 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, | 17 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, |
| 18 | Buf *zig_lib_dir); | 18 | Buf *zig_lib_dir, Buf *override_std_dir); |
| 19 | 19 | ||
| 20 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); | 20 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 21 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); | 21 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); |
| ... | @@ -33,7 +33,6 @@ void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); | ... | @@ -33,7 +33,6 @@ void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); |
| 33 | void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir); | 33 | void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir); |
| 34 | void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir); | 34 | void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir); |
| 35 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); | 35 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); |
| 36 | void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole); | ||
| 37 | void codegen_add_lib_dir(CodeGen *codegen, const char *dir); | 36 | void codegen_add_lib_dir(CodeGen *codegen, const char *dir); |
| 38 | void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); | 37 | void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); |
| 39 | LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); | 38 | LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); |
src/ir.cpp+2127-1051| ... | @@ -61,7 +61,7 @@ enum ConstCastResultId { | ... | @@ -61,7 +61,7 @@ enum ConstCastResultId { |
| 61 | ConstCastResultIdType, | 61 | ConstCastResultIdType, |
| 62 | ConstCastResultIdUnresolvedInferredErrSet, | 62 | ConstCastResultIdUnresolvedInferredErrSet, |
| 63 | ConstCastResultIdAsyncAllocatorType, | 63 | ConstCastResultIdAsyncAllocatorType, |
| 64 | ConstCastResultIdNullWrapPtr | 64 | ConstCastResultIdBadAllowsZero, |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct ConstCastOnly; | 67 | struct ConstCastOnly; |
| ... | @@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch; | ... | @@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch; |
| 83 | struct ConstCastErrUnionPayloadMismatch; | 83 | struct ConstCastErrUnionPayloadMismatch; |
| 84 | struct ConstCastErrSetMismatch; | 84 | struct ConstCastErrSetMismatch; |
| 85 | struct ConstCastTypeMismatch; | 85 | struct ConstCastTypeMismatch; |
| 86 | struct ConstCastBadAllowsZero; | ||
| 86 | 87 | ||
| 87 | struct ConstCastOnly { | 88 | struct ConstCastOnly { |
| 88 | ConstCastResultId id; | 89 | ConstCastResultId id; |
| ... | @@ -99,6 +100,7 @@ struct ConstCastOnly { | ... | @@ -99,6 +100,7 @@ struct ConstCastOnly { |
| 99 | ConstCastOnly *null_wrap_ptr_child; | 100 | ConstCastOnly *null_wrap_ptr_child; |
| 100 | ConstCastArg fn_arg; | 101 | ConstCastArg fn_arg; |
| 101 | ConstCastArgNoAlias arg_no_alias; | 102 | ConstCastArgNoAlias arg_no_alias; |
| 103 | ConstCastBadAllowsZero *bad_allows_zero; | ||
| 102 | } data; | 104 | } data; |
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| ... | @@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch { | ... | @@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch { |
| 141 | ZigList<ErrorTableEntry *> missing_errors; | 143 | ZigList<ErrorTableEntry *> missing_errors; |
| 142 | }; | 144 | }; |
| 143 | 145 | ||
| 146 | struct ConstCastBadAllowsZero { | ||
| 147 | ZigType *wanted_type; | ||
| 148 | ZigType *actual_type; | ||
| 149 | }; | ||
| 150 | |||
| 151 | |||
| 144 | enum UndefAllowed { | 152 | enum UndefAllowed { |
| 145 | UndefOk, | 153 | UndefOk, |
| 146 | UndefBad, | 154 | UndefBad, |
| ... | @@ -159,13 +167,20 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op | ... | @@ -159,13 +167,20 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op |
| 159 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); | 167 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); |
| 160 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); | 168 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); |
| 161 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); | 169 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); |
| 162 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 170 | static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val); |
| 163 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 171 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 164 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | 172 | static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, |
| 165 | ConstExprValue *out_val, ConstExprValue *ptr_val); | 173 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| 166 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, | 174 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| 167 | ZigType *dest_type, IrInstruction *dest_type_src); | 175 | ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on); |
| 168 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); | 176 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); |
| 177 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); | ||
| 178 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); | ||
| 179 | static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry); | ||
| 180 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | ||
| 181 | ZigType *ptr_type); | ||
| 182 | static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | ||
| 183 | ZigType *dest_type); | ||
| 169 | 184 | ||
| 170 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 185 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 171 | assert(get_src_ptr_type(const_val->type) != nullptr); | 186 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -177,15 +192,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c | ... | @@ -177,15 +192,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c |
| 177 | case ConstPtrSpecialRef: | 192 | case ConstPtrSpecialRef: |
| 178 | result = const_val->data.x_ptr.data.ref.pointee; | 193 | result = const_val->data.x_ptr.data.ref.pointee; |
| 179 | break; | 194 | break; |
| 180 | case ConstPtrSpecialBaseArray: | 195 | case ConstPtrSpecialBaseArray: { |
| 181 | expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val); | 196 | ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val; |
| 182 | result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[ | 197 | expand_undef_array(g, array_val); |
| 183 | const_val->data.x_ptr.data.base_array.elem_index]; | 198 | result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index]; |
| 184 | break; | 199 | break; |
| 200 | } | ||
| 185 | case ConstPtrSpecialBaseStruct: | 201 | case ConstPtrSpecialBaseStruct: |
| 186 | result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[ | 202 | result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[ |
| 187 | const_val->data.x_ptr.data.base_struct.field_index]; | 203 | const_val->data.x_ptr.data.base_struct.field_index]; |
| 188 | break; | 204 | break; |
| 205 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 206 | result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set; | ||
| 207 | break; | ||
| 208 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 209 | result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload; | ||
| 210 | break; | ||
| 211 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 212 | result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional; | ||
| 213 | break; | ||
| 214 | case ConstPtrSpecialNull: | ||
| 215 | result = const_val; | ||
| 216 | break; | ||
| 189 | case ConstPtrSpecialHardCodedAddr: | 217 | case ConstPtrSpecialHardCodedAddr: |
| 190 | zig_unreachable(); | 218 | zig_unreachable(); |
| 191 | case ConstPtrSpecialDiscard: | 219 | case ConstPtrSpecialDiscard: |
| ... | @@ -197,6 +225,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c | ... | @@ -197,6 +225,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c |
| 197 | return result; | 225 | return result; |
| 198 | } | 226 | } |
| 199 | 227 | ||
| 228 | static bool is_opt_err_set(ZigType *ty) { | ||
| 229 | return ty->id == ZigTypeIdErrorSet || | ||
| 230 | (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet); | ||
| 231 | } | ||
| 232 | |||
| 200 | static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { | 233 | static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 201 | if (a == b) | 234 | if (a == b) |
| 202 | return true; | 235 | return true; |
| ... | @@ -207,15 +240,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { | ... | @@ -207,15 +240,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 207 | if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr) | 240 | if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr) |
| 208 | return true; | 241 | return true; |
| 209 | 242 | ||
| 210 | return false; | 243 | if (is_opt_err_set(a) && is_opt_err_set(b)) |
| 211 | } | 244 | return true; |
| 212 | 245 | ||
| 213 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { | 246 | return false; |
| 214 | ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val); | ||
| 215 | if (const_val->type->id == ZigTypeIdPointer) { | ||
| 216 | assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type)); | ||
| 217 | } | ||
| 218 | return result; | ||
| 219 | } | 247 | } |
| 220 | 248 | ||
| 221 | static bool ir_should_inline(IrExecutable *exec, Scope *scope) { | 249 | static bool ir_should_inline(IrExecutable *exec, Scope *scope) { |
| ... | @@ -304,6 +332,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { | ... | @@ -304,6 +332,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { |
| 304 | return new_bb; | 332 | return new_bb; |
| 305 | } | 333 | } |
| 306 | 334 | ||
| 335 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) { | ||
| 336 | return IrInstructionIdDeclVarSrc; | ||
| 337 | } | ||
| 338 | |||
| 339 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) { | ||
| 340 | return IrInstructionIdDeclVarGen; | ||
| 341 | } | ||
| 342 | |||
| 307 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) { | 343 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) { |
| 308 | return IrInstructionIdCondBr; | 344 | return IrInstructionIdCondBr; |
| 309 | } | 345 | } |
| ... | @@ -336,10 +372,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) { | ... | @@ -336,10 +372,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) { |
| 336 | return IrInstructionIdBinOp; | 372 | return IrInstructionIdBinOp; |
| 337 | } | 373 | } |
| 338 | 374 | ||
| 339 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) { | ||
| 340 | return IrInstructionIdDeclVar; | ||
| 341 | } | ||
| 342 | |||
| 343 | static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { | 375 | static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { |
| 344 | return IrInstructionIdExport; | 376 | return IrInstructionIdExport; |
| 345 | } | 377 | } |
| ... | @@ -448,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) { | ... | @@ -448,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) { |
| 448 | return IrInstructionIdTestNonNull; | 480 | return IrInstructionIdTestNonNull; |
| 449 | } | 481 | } |
| 450 | 482 | ||
| 451 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) { | 483 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) { |
| 452 | return IrInstructionIdUnwrapOptional; | 484 | return IrInstructionIdOptionalUnwrapPtr; |
| 453 | } | 485 | } |
| 454 | 486 | ||
| 455 | static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) { | 487 | static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) { |
| ... | @@ -516,8 +548,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) { | ... | @@ -516,8 +548,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) { |
| 516 | return IrInstructionIdEmbedFile; | 548 | return IrInstructionIdEmbedFile; |
| 517 | } | 549 | } |
| 518 | 550 | ||
| 519 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) { | 551 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) { |
| 520 | return IrInstructionIdCmpxchg; | 552 | return IrInstructionIdCmpxchgSrc; |
| 553 | } | ||
| 554 | |||
| 555 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) { | ||
| 556 | return IrInstructionIdCmpxchgGen; | ||
| 521 | } | 557 | } |
| 522 | 558 | ||
| 523 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) { | 559 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) { |
| ... | @@ -564,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) { | ... | @@ -564,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) { |
| 564 | return IrInstructionIdIntType; | 600 | return IrInstructionIdIntType; |
| 565 | } | 601 | } |
| 566 | 602 | ||
| 603 | static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) { | ||
| 604 | return IrInstructionIdVectorType; | ||
| 605 | } | ||
| 606 | |||
| 567 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) { | 607 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) { |
| 568 | return IrInstructionIdBoolNot; | 608 | return IrInstructionIdBoolNot; |
| 569 | } | 609 | } |
| ... | @@ -648,8 +688,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) | ... | @@ -648,8 +688,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) |
| 648 | return IrInstructionIdTestComptime; | 688 | return IrInstructionIdTestComptime; |
| 649 | } | 689 | } |
| 650 | 690 | ||
| 651 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { | 691 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) { |
| 652 | return IrInstructionIdPtrCast; | 692 | return IrInstructionIdPtrCastSrc; |
| 693 | } | ||
| 694 | |||
| 695 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) { | ||
| 696 | return IrInstructionIdPtrCastGen; | ||
| 653 | } | 697 | } |
| 654 | 698 | ||
| 655 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) { | 699 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) { |
| ... | @@ -856,10 +900,30 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { | ... | @@ -856,10 +900,30 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { |
| 856 | return IrInstructionIdSqrt; | 900 | return IrInstructionIdSqrt; |
| 857 | } | 901 | } |
| 858 | 902 | ||
| 903 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { | ||
| 904 | return IrInstructionIdBswap; | ||
| 905 | } | ||
| 906 | |||
| 907 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) { | ||
| 908 | return IrInstructionIdBitReverse; | ||
| 909 | } | ||
| 910 | |||
| 859 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { | 911 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { |
| 860 | return IrInstructionIdCheckRuntimeScope; | 912 | return IrInstructionIdCheckRuntimeScope; |
| 861 | } | 913 | } |
| 862 | 914 | ||
| 915 | static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) { | ||
| 916 | return IrInstructionIdVectorToArray; | ||
| 917 | } | ||
| 918 | |||
| 919 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) { | ||
| 920 | return IrInstructionIdArrayToVector; | ||
| 921 | } | ||
| 922 | |||
| 923 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) { | ||
| 924 | return IrInstructionIdAssertZero; | ||
| 925 | } | ||
| 926 | |||
| 863 | template<typename T> | 927 | template<typename T> |
| 864 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 928 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 865 | T *special_instruction = allocate<T>(1); | 929 | T *special_instruction = allocate<T>(1); |
| ... | @@ -906,7 +970,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so | ... | @@ -906,7 +970,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so |
| 906 | ir_ref_instruction(condition, irb->current_basic_block); | 970 | ir_ref_instruction(condition, irb->current_basic_block); |
| 907 | ir_ref_bb(then_block); | 971 | ir_ref_bb(then_block); |
| 908 | ir_ref_bb(else_block); | 972 | ir_ref_bb(else_block); |
| 909 | if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); | 973 | if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); |
| 910 | 974 | ||
| 911 | return &cond_br_instruction->base; | 975 | return &cond_br_instruction->base; |
| 912 | } | 976 | } |
| ... | @@ -922,16 +986,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou | ... | @@ -922,16 +986,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou |
| 922 | return &return_instruction->base; | 986 | return &return_instruction->base; |
| 923 | } | 987 | } |
| 924 | 988 | ||
| 925 | static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 926 | ZigType *type_entry) | ||
| 927 | { | ||
| 928 | assert(type_entry); | ||
| 929 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node); | ||
| 930 | const_instruction->base.value.type = type_entry; | ||
| 931 | const_instruction->base.value.special = ConstValSpecialStatic; | ||
| 932 | return &const_instruction->base; | ||
| 933 | } | ||
| 934 | |||
| 935 | static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 989 | static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 936 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); | 990 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); |
| 937 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_void; | 991 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| ... | @@ -1179,14 +1233,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc | ... | @@ -1179,14 +1233,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 1179 | call_instruction->async_allocator = async_allocator; | 1233 | call_instruction->async_allocator = async_allocator; |
| 1180 | call_instruction->new_stack = new_stack; | 1234 | call_instruction->new_stack = new_stack; |
| 1181 | 1235 | ||
| 1182 | if (fn_ref) | 1236 | if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); |
| 1183 | ir_ref_instruction(fn_ref, irb->current_basic_block); | ||
| 1184 | for (size_t i = 0; i < arg_count; i += 1) | 1237 | for (size_t i = 0; i < arg_count; i += 1) |
| 1185 | ir_ref_instruction(args[i], irb->current_basic_block); | 1238 | ir_ref_instruction(args[i], irb->current_basic_block); |
| 1186 | if (async_allocator) | 1239 | if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block); |
| 1187 | ir_ref_instruction(async_allocator, irb->current_basic_block); | 1240 | if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); |
| 1188 | if (new_stack != nullptr) | ||
| 1189 | ir_ref_instruction(new_stack, irb->current_basic_block); | ||
| 1190 | 1241 | ||
| 1191 | return &call_instruction->base; | 1242 | return &call_instruction->base; |
| 1192 | } | 1243 | } |
| ... | @@ -1271,7 +1322,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, | ... | @@ -1271,7 +1322,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, |
| 1271 | container_init_list_instruction->item_count = item_count; | 1322 | container_init_list_instruction->item_count = item_count; |
| 1272 | container_init_list_instruction->items = items; | 1323 | container_init_list_instruction->items = items; |
| 1273 | 1324 | ||
| 1274 | ir_ref_instruction(container_type, irb->current_basic_block); | 1325 | if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block); |
| 1275 | for (size_t i = 0; i < item_count; i += 1) { | 1326 | for (size_t i = 0; i < item_count; i += 1) { |
| 1276 | ir_ref_instruction(items[i], irb->current_basic_block); | 1327 | ir_ref_instruction(items[i], irb->current_basic_block); |
| 1277 | } | 1328 | } |
| ... | @@ -1346,10 +1397,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -1346,10 +1397,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * |
| 1346 | return &instruction->base; | 1397 | return &instruction->base; |
| 1347 | } | 1398 | } |
| 1348 | 1399 | ||
| 1349 | static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1400 | static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1350 | ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value) | 1401 | ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value) |
| 1351 | { | 1402 | { |
| 1352 | IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node); | 1403 | IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node); |
| 1353 | decl_var_instruction->base.value.special = ConstValSpecialStatic; | 1404 | decl_var_instruction->base.value.special = ConstValSpecialStatic; |
| 1354 | decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; | 1405 | decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 1355 | decl_var_instruction->var = var; | 1406 | decl_var_instruction->var = var; |
| ... | @@ -1357,13 +1408,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -1357,13 +1408,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s |
| 1357 | decl_var_instruction->align_value = align_value; | 1408 | decl_var_instruction->align_value = align_value; |
| 1358 | decl_var_instruction->init_value = init_value; | 1409 | decl_var_instruction->init_value = init_value; |
| 1359 | 1410 | ||
| 1360 | if (var_type) ir_ref_instruction(var_type, irb->current_basic_block); | 1411 | if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block); |
| 1361 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); | 1412 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); |
| 1362 | ir_ref_instruction(init_value, irb->current_basic_block); | 1413 | ir_ref_instruction(init_value, irb->current_basic_block); |
| 1363 | 1414 | ||
| 1364 | return &decl_var_instruction->base; | 1415 | return &decl_var_instruction->base; |
| 1365 | } | 1416 | } |
| 1366 | 1417 | ||
| 1418 | static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 1419 | ZigVar *var, IrInstruction *init_value) | ||
| 1420 | { | ||
| 1421 | IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb, | ||
| 1422 | source_instruction->scope, source_instruction->source_node); | ||
| 1423 | decl_var_instruction->base.value.special = ConstValSpecialStatic; | ||
| 1424 | decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void; | ||
| 1425 | decl_var_instruction->var = var; | ||
| 1426 | decl_var_instruction->init_value = init_value; | ||
| 1427 | |||
| 1428 | ir_ref_instruction(init_value, ira->new_irb.current_basic_block); | ||
| 1429 | |||
| 1430 | return &decl_var_instruction->base; | ||
| 1431 | } | ||
| 1432 | |||
| 1367 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1433 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1368 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) | 1434 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) |
| 1369 | { | 1435 | { |
| ... | @@ -1533,14 +1599,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -1533,14 +1599,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod |
| 1533 | return &instruction->base; | 1599 | return &instruction->base; |
| 1534 | } | 1600 | } |
| 1535 | 1601 | ||
| 1536 | static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value, | 1602 | static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1537 | bool safety_check_on) | 1603 | IrInstruction *base_ptr, bool safety_check_on) |
| 1538 | { | 1604 | { |
| 1539 | IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node); | 1605 | IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node); |
| 1540 | instruction->value = value; | 1606 | instruction->base_ptr = base_ptr; |
| 1541 | instruction->safety_check_on = safety_check_on; | 1607 | instruction->safety_check_on = safety_check_on; |
| 1542 | 1608 | ||
| 1543 | ir_ref_instruction(value, irb->current_basic_block); | 1609 | ir_ref_instruction(base_ptr, irb->current_basic_block); |
| 1544 | 1610 | ||
| 1545 | return &instruction->base; | 1611 | return &instruction->base; |
| 1546 | } | 1612 | } |
| ... | @@ -1756,13 +1822,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -1756,13 +1822,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode |
| 1756 | return &instruction->base; | 1822 | return &instruction->base; |
| 1757 | } | 1823 | } |
| 1758 | 1824 | ||
| 1759 | static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, | 1825 | static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1760 | IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, | 1826 | IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, |
| 1761 | IrInstruction *success_order_value, IrInstruction *failure_order_value, | 1827 | IrInstruction *success_order_value, IrInstruction *failure_order_value, |
| 1762 | bool is_weak, | 1828 | bool is_weak) |
| 1763 | ZigType *type, AtomicOrder success_order, AtomicOrder failure_order) | ||
| 1764 | { | 1829 | { |
| 1765 | IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node); | 1830 | IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node); |
| 1766 | instruction->type_value = type_value; | 1831 | instruction->type_value = type_value; |
| 1767 | instruction->ptr = ptr; | 1832 | instruction->ptr = ptr; |
| 1768 | instruction->cmp_value = cmp_value; | 1833 | instruction->cmp_value = cmp_value; |
| ... | @@ -1770,16 +1835,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so | ... | @@ -1770,16 +1835,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so |
| 1770 | instruction->success_order_value = success_order_value; | 1835 | instruction->success_order_value = success_order_value; |
| 1771 | instruction->failure_order_value = failure_order_value; | 1836 | instruction->failure_order_value = failure_order_value; |
| 1772 | instruction->is_weak = is_weak; | 1837 | instruction->is_weak = is_weak; |
| 1773 | instruction->type = type; | ||
| 1774 | instruction->success_order = success_order; | ||
| 1775 | instruction->failure_order = failure_order; | ||
| 1776 | 1838 | ||
| 1777 | if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block); | 1839 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 1778 | ir_ref_instruction(ptr, irb->current_basic_block); | 1840 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1779 | ir_ref_instruction(cmp_value, irb->current_basic_block); | 1841 | ir_ref_instruction(cmp_value, irb->current_basic_block); |
| 1780 | ir_ref_instruction(new_value, irb->current_basic_block); | 1842 | ir_ref_instruction(new_value, irb->current_basic_block); |
| 1781 | if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block); | 1843 | ir_ref_instruction(success_order_value, irb->current_basic_block); |
| 1782 | if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block); | 1844 | ir_ref_instruction(failure_order_value, irb->current_basic_block); |
| 1845 | |||
| 1846 | return &instruction->base; | ||
| 1847 | } | ||
| 1848 | |||
| 1849 | static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 1850 | IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, | ||
| 1851 | AtomicOrder success_order, AtomicOrder failure_order, bool is_weak) | ||
| 1852 | { | ||
| 1853 | IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb, | ||
| 1854 | source_instruction->scope, source_instruction->source_node); | ||
| 1855 | instruction->ptr = ptr; | ||
| 1856 | instruction->cmp_value = cmp_value; | ||
| 1857 | instruction->new_value = new_value; | ||
| 1858 | instruction->success_order = success_order; | ||
| 1859 | instruction->failure_order = failure_order; | ||
| 1860 | instruction->is_weak = is_weak; | ||
| 1861 | |||
| 1862 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); | ||
| 1863 | ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block); | ||
| 1864 | ir_ref_instruction(new_value, ira->new_irb.current_basic_block); | ||
| 1783 | 1865 | ||
| 1784 | return &instruction->base; | 1866 | return &instruction->base; |
| 1785 | } | 1867 | } |
| ... | @@ -1900,6 +1982,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -1900,6 +1982,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s |
| 1900 | return &instruction->base; | 1982 | return &instruction->base; |
| 1901 | } | 1983 | } |
| 1902 | 1984 | ||
| 1985 | static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *len, | ||
| 1986 | IrInstruction *elem_type) | ||
| 1987 | { | ||
| 1988 | IrInstructionVectorType *instruction = ir_build_instruction<IrInstructionVectorType>(irb, scope, source_node); | ||
| 1989 | instruction->len = len; | ||
| 1990 | instruction->elem_type = elem_type; | ||
| 1991 | |||
| 1992 | ir_ref_instruction(len, irb->current_basic_block); | ||
| 1993 | ir_ref_instruction(elem_type, irb->current_basic_block); | ||
| 1994 | |||
| 1995 | return &instruction->base; | ||
| 1996 | } | ||
| 1997 | |||
| 1903 | static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | 1998 | static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1904 | IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node); | 1999 | IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node); |
| 1905 | instruction->value = value; | 2000 | instruction->value = value; |
| ... | @@ -2051,12 +2146,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -2051,12 +2146,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s |
| 2051 | } | 2146 | } |
| 2052 | 2147 | ||
| 2053 | static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2148 | static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2054 | IrInstruction *value) | 2149 | IrInstruction *err_union) |
| 2055 | { | 2150 | { |
| 2056 | IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node); | 2151 | IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node); |
| 2057 | instruction->value = value; | 2152 | instruction->err_union = err_union; |
| 2058 | 2153 | ||
| 2059 | ir_ref_instruction(value, irb->current_basic_block); | 2154 | ir_ref_instruction(err_union, irb->current_basic_block); |
| 2060 | 2155 | ||
| 2061 | return &instruction->base; | 2156 | return &instruction->base; |
| 2062 | } | 2157 | } |
| ... | @@ -2106,20 +2201,35 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -2106,20 +2201,35 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo |
| 2106 | return &instruction->base; | 2201 | return &instruction->base; |
| 2107 | } | 2202 | } |
| 2108 | 2203 | ||
| 2109 | static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2204 | static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2110 | IrInstruction *dest_type, IrInstruction *ptr) | 2205 | IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on) |
| 2111 | { | 2206 | { |
| 2112 | IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>( | 2207 | IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>( |
| 2113 | irb, scope, source_node); | 2208 | irb, scope, source_node); |
| 2114 | instruction->dest_type = dest_type; | 2209 | instruction->dest_type = dest_type; |
| 2115 | instruction->ptr = ptr; | 2210 | instruction->ptr = ptr; |
| 2211 | instruction->safety_check_on = safety_check_on; | ||
| 2116 | 2212 | ||
| 2117 | if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); | 2213 | ir_ref_instruction(dest_type, irb->current_basic_block); |
| 2118 | ir_ref_instruction(ptr, irb->current_basic_block); | 2214 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 2119 | 2215 | ||
| 2120 | return &instruction->base; | 2216 | return &instruction->base; |
| 2121 | } | 2217 | } |
| 2122 | 2218 | ||
| 2219 | static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 2220 | ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on) | ||
| 2221 | { | ||
| 2222 | IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>( | ||
| 2223 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 2224 | instruction->base.value.type = ptr_type; | ||
| 2225 | instruction->ptr = ptr; | ||
| 2226 | instruction->safety_check_on = safety_check_on; | ||
| 2227 | |||
| 2228 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); | ||
| 2229 | |||
| 2230 | return &instruction->base; | ||
| 2231 | } | ||
| 2232 | |||
| 2123 | static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2233 | static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2124 | IrInstruction *dest_type, IrInstruction *value) | 2234 | IrInstruction *dest_type, IrInstruction *value) |
| 2125 | { | 2235 | { |
| ... | @@ -2362,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -2362,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode * |
| 2362 | 2472 | ||
| 2363 | ir_ref_instruction(type_value, irb->current_basic_block); | 2473 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 2364 | 2474 | ||
| 2365 | return &instruction->base; | 2475 | return &instruction->base; |
| 2366 | } | 2476 | } |
| 2367 | 2477 | ||
| 2368 | static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2478 | static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| ... | @@ -2705,6 +2815,28 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc | ... | @@ -2705,6 +2815,28 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 2705 | return &instruction->base; | 2815 | return &instruction->base; |
| 2706 | } | 2816 | } |
| 2707 | 2817 | ||
| 2818 | static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { | ||
| 2819 | IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node); | ||
| 2820 | instruction->type = type; | ||
| 2821 | instruction->op = op; | ||
| 2822 | |||
| 2823 | if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); | ||
| 2824 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 2825 | |||
| 2826 | return &instruction->base; | ||
| 2827 | } | ||
| 2828 | |||
| 2829 | static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { | ||
| 2830 | IrInstructionBitReverse *instruction = ir_build_instruction<IrInstructionBitReverse>(irb, scope, source_node); | ||
| 2831 | instruction->type = type; | ||
| 2832 | instruction->op = op; | ||
| 2833 | |||
| 2834 | if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); | ||
| 2835 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 2836 | |||
| 2837 | return &instruction->base; | ||
| 2838 | } | ||
| 2839 | |||
| 2708 | static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { | 2840 | static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { |
| 2709 | IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node); | 2841 | IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node); |
| 2710 | instruction->scope_is_comptime = scope_is_comptime; | 2842 | instruction->scope_is_comptime = scope_is_comptime; |
| ... | @@ -2716,6 +2848,47 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, | ... | @@ -2716,6 +2848,47 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, |
| 2716 | return &instruction->base; | 2848 | return &instruction->base; |
| 2717 | } | 2849 | } |
| 2718 | 2850 | ||
| 2851 | static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 2852 | IrInstruction *vector, ZigType *result_type) | ||
| 2853 | { | ||
| 2854 | IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb, | ||
| 2855 | source_instruction->scope, source_instruction->source_node); | ||
| 2856 | instruction->base.value.type = result_type; | ||
| 2857 | instruction->vector = vector; | ||
| 2858 | |||
| 2859 | ir_ref_instruction(vector, ira->new_irb.current_basic_block); | ||
| 2860 | |||
| 2861 | ir_add_alloca(ira, &instruction->base, result_type); | ||
| 2862 | |||
| 2863 | return &instruction->base; | ||
| 2864 | } | ||
| 2865 | |||
| 2866 | static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 2867 | IrInstruction *array, ZigType *result_type) | ||
| 2868 | { | ||
| 2869 | IrInstructionArrayToVector *instruction = ir_build_instruction<IrInstructionArrayToVector>(&ira->new_irb, | ||
| 2870 | source_instruction->scope, source_instruction->source_node); | ||
| 2871 | instruction->base.value.type = result_type; | ||
| 2872 | instruction->array = array; | ||
| 2873 | |||
| 2874 | ir_ref_instruction(array, ira->new_irb.current_basic_block); | ||
| 2875 | |||
| 2876 | return &instruction->base; | ||
| 2877 | } | ||
| 2878 | |||
| 2879 | static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 2880 | IrInstruction *target) | ||
| 2881 | { | ||
| 2882 | IrInstructionAssertZero *instruction = ir_build_instruction<IrInstructionAssertZero>(&ira->new_irb, | ||
| 2883 | source_instruction->scope, source_instruction->source_node); | ||
| 2884 | instruction->base.value.type = ira->codegen->builtin_types.entry_void; | ||
| 2885 | instruction->target = target; | ||
| 2886 | |||
| 2887 | ir_ref_instruction(target, ira->new_irb.current_basic_block); | ||
| 2888 | |||
| 2889 | return &instruction->base; | ||
| 2890 | } | ||
| 2891 | |||
| 2719 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2892 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2720 | results[ReturnKindUnconditional] = 0; | 2893 | results[ReturnKindUnconditional] = 0; |
| 2721 | results[ReturnKindError] = 0; | 2894 | results[ReturnKindError] = 0; |
| ... | @@ -2776,10 +2949,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o | ... | @@ -2776,10 +2949,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o |
| 2776 | Scope *defer_expr_scope = defer_node->data.defer.expr_scope; | 2949 | Scope *defer_expr_scope = defer_node->data.defer.expr_scope; |
| 2777 | IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); | 2950 | IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); |
| 2778 | if (defer_expr_value != irb->codegen->invalid_instruction) { | 2951 | if (defer_expr_value != irb->codegen->invalid_instruction) { |
| 2779 | if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) { | 2952 | if (defer_expr_value->value.type != nullptr && |
| 2953 | defer_expr_value->value.type->id == ZigTypeIdUnreachable) | ||
| 2954 | { | ||
| 2780 | is_noreturn = true; | 2955 | is_noreturn = true; |
| 2781 | } else { | 2956 | } else { |
| 2782 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); | 2957 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, |
| 2958 | defer_expr_value)); | ||
| 2783 | } | 2959 | } |
| 2784 | } | 2960 | } |
| 2785 | } | 2961 | } |
| ... | @@ -3034,7 +3210,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s | ... | @@ -3034,7 +3210,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s |
| 3034 | variable_entry->mem_slot_index = SIZE_MAX; | 3210 | variable_entry->mem_slot_index = SIZE_MAX; |
| 3035 | variable_entry->is_comptime = is_comptime; | 3211 | variable_entry->is_comptime = is_comptime; |
| 3036 | variable_entry->src_arg_index = SIZE_MAX; | 3212 | variable_entry->src_arg_index = SIZE_MAX; |
| 3037 | variable_entry->value = create_const_vals(1); | 3213 | variable_entry->const_value = create_const_vals(1); |
| 3038 | 3214 | ||
| 3039 | if (is_comptime != nullptr) { | 3215 | if (is_comptime != nullptr) { |
| 3040 | is_comptime->ref_count += 1; | 3216 | is_comptime->ref_count += 1; |
| ... | @@ -3049,20 +3225,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s | ... | @@ -3049,20 +3225,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s |
| 3049 | ErrorMsg *msg = add_node_error(codegen, node, | 3225 | ErrorMsg *msg = add_node_error(codegen, node, |
| 3050 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | 3226 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| 3051 | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); | 3227 | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); |
| 3052 | variable_entry->value->type = codegen->builtin_types.entry_invalid; | 3228 | variable_entry->var_type = codegen->builtin_types.entry_invalid; |
| 3053 | } else { | 3229 | } else { |
| 3054 | ZigType *type; | 3230 | ZigType *type; |
| 3055 | if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { | 3231 | if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { |
| 3056 | add_node_error(codegen, node, | 3232 | add_node_error(codegen, node, |
| 3057 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); | 3233 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); |
| 3058 | variable_entry->value->type = codegen->builtin_types.entry_invalid; | 3234 | variable_entry->var_type = codegen->builtin_types.entry_invalid; |
| 3059 | } else { | 3235 | } else { |
| 3060 | Tld *tld = find_decl(codegen, parent_scope, name); | 3236 | Tld *tld = find_decl(codegen, parent_scope, name); |
| 3061 | if (tld != nullptr) { | 3237 | if (tld != nullptr) { |
| 3062 | ErrorMsg *msg = add_node_error(codegen, node, | 3238 | ErrorMsg *msg = add_node_error(codegen, node, |
| 3063 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | 3239 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 3064 | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); | 3240 | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); |
| 3065 | variable_entry->value->type = codegen->builtin_types.entry_invalid; | 3241 | variable_entry->var_type = codegen->builtin_types.entry_invalid; |
| 3066 | } | 3242 | } |
| 3067 | } | 3243 | } |
| 3068 | } | 3244 | } |
| ... | @@ -3125,7 +3301,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3125,7 +3301,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3125 | scope_block->incoming_blocks = &incoming_blocks; | 3301 | scope_block->incoming_blocks = &incoming_blocks; |
| 3126 | scope_block->incoming_values = &incoming_values; | 3302 | scope_block->incoming_values = &incoming_values; |
| 3127 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); | 3303 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); |
| 3128 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope)); | 3304 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, |
| 3305 | ir_should_inline(irb->exec, parent_scope)); | ||
| 3129 | } | 3306 | } |
| 3130 | 3307 | ||
| 3131 | bool is_continuation_unreachable = false; | 3308 | bool is_continuation_unreachable = false; |
| ... | @@ -3143,9 +3320,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode | ... | @@ -3143,9 +3320,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3143 | // defer starts a new scope | 3320 | // defer starts a new scope |
| 3144 | child_scope = statement_node->data.defer.child_scope; | 3321 | child_scope = statement_node->data.defer.child_scope; |
| 3145 | assert(child_scope); | 3322 | assert(child_scope); |
| 3146 | } else if (statement_value->id == IrInstructionIdDeclVar) { | 3323 | } else if (statement_value->id == IrInstructionIdDeclVarSrc) { |
| 3147 | // variable declarations start a new scope | 3324 | // variable declarations start a new scope |
| 3148 | IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value; | 3325 | IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value; |
| 3149 | child_scope = decl_var_instruction->var->child_scope; | 3326 | child_scope = decl_var_instruction->var->child_scope; |
| 3150 | } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) { | 3327 | } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) { |
| 3151 | // this statement's value must be void | 3328 | // this statement's value must be void |
| ... | @@ -3300,7 +3477,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -3300,7 +3477,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 3300 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); | 3477 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| 3301 | } | 3478 | } |
| 3302 | 3479 | ||
| 3303 | static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 3480 | static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| 3304 | assert(node->type == NodeTypeBinOpExpr); | 3481 | assert(node->type == NodeTypeBinOpExpr); |
| 3305 | 3482 | ||
| 3306 | AstNode *op1_node = node->data.bin_op_expr.op1; | 3483 | AstNode *op1_node = node->data.bin_op_expr.op1; |
| ... | @@ -3334,7 +3511,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As | ... | @@ -3334,7 +3511,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 3334 | ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); | 3511 | ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); |
| 3335 | 3512 | ||
| 3336 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | 3513 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 3337 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false); | 3514 | IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); |
| 3338 | IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); | 3515 | IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); |
| 3339 | IrBasicBlock *after_ok_block = irb->current_basic_block; | 3516 | IrBasicBlock *after_ok_block = irb->current_basic_block; |
| 3340 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); | 3517 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); |
| ... | @@ -3452,7 +3629,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -3452,7 +3629,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) |
| 3452 | case BinOpTypeMergeErrorSets: | 3629 | case BinOpTypeMergeErrorSets: |
| 3453 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets); | 3630 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets); |
| 3454 | case BinOpTypeUnwrapOptional: | 3631 | case BinOpTypeUnwrapOptional: |
| 3455 | return ir_gen_maybe_ok_or(irb, scope, node); | 3632 | return ir_gen_orelse(irb, scope, node); |
| 3456 | case BinOpTypeErrorUnion: | 3633 | case BinOpTypeErrorUnion: |
| 3457 | return ir_gen_error_union(irb, scope, node); | 3634 | return ir_gen_error_union(irb, scope, node); |
| 3458 | } | 3635 | } |
| ... | @@ -3511,6 +3688,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3511,6 +3688,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3511 | buf_ptr(variable_name))); | 3688 | buf_ptr(variable_name))); |
| 3512 | return irb->codegen->invalid_instruction; | 3689 | return irb->codegen->invalid_instruction; |
| 3513 | } | 3690 | } |
| 3691 | assert(err == ErrorPrimitiveTypeNotFound); | ||
| 3514 | } else { | 3692 | } else { |
| 3515 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type); | 3693 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type); |
| 3516 | if (lval == LValPtr) { | 3694 | if (lval == LValPtr) { |
| ... | @@ -3630,7 +3808,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -3630,7 +3808,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3630 | Buf *name = fn_ref_expr->data.symbol_expr.symbol; | 3808 | Buf *name = fn_ref_expr->data.symbol_expr.symbol; |
| 3631 | auto entry = irb->codegen->builtin_fn_table.maybe_get(name); | 3809 | auto entry = irb->codegen->builtin_fn_table.maybe_get(name); |
| 3632 | 3810 | ||
| 3633 | if (!entry) { | 3811 | if (!entry) { // new built in not found |
| 3634 | add_node_error(irb->codegen, node, | 3812 | add_node_error(irb->codegen, node, |
| 3635 | buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); | 3813 | buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); |
| 3636 | return irb->codegen->invalid_instruction; | 3814 | return irb->codegen->invalid_instruction; |
| ... | @@ -3873,9 +4051,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -3873,9 +4051,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3873 | if (arg5_value == irb->codegen->invalid_instruction) | 4051 | if (arg5_value == irb->codegen->invalid_instruction) |
| 3874 | return arg5_value; | 4052 | return arg5_value; |
| 3875 | 4053 | ||
| 3876 | IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value, | 4054 | IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, |
| 3877 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), | 4055 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak)); |
| 3878 | nullptr, AtomicOrderUnordered, AtomicOrderUnordered); | ||
| 3879 | return ir_lval_wrap(irb, scope, cmpxchg, lval); | 4056 | return ir_lval_wrap(irb, scope, cmpxchg, lval); |
| 3880 | } | 4057 | } |
| 3881 | case BuiltinFnIdFence: | 4058 | case BuiltinFnIdFence: |
| ... | @@ -4138,6 +4315,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4138,6 +4315,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4138 | IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value); | 4315 | IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value); |
| 4139 | return ir_lval_wrap(irb, scope, int_type, lval); | 4316 | return ir_lval_wrap(irb, scope, int_type, lval); |
| 4140 | } | 4317 | } |
| 4318 | case BuiltinFnIdVectorType: | ||
| 4319 | { | ||
| 4320 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4321 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4322 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4323 | return arg0_value; | ||
| 4324 | |||
| 4325 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4326 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4327 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4328 | return arg1_value; | ||
| 4329 | |||
| 4330 | IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); | ||
| 4331 | return ir_lval_wrap(irb, scope, vector_type, lval); | ||
| 4332 | } | ||
| 4141 | case BuiltinFnIdMemcpy: | 4333 | case BuiltinFnIdMemcpy: |
| 4142 | { | 4334 | { |
| 4143 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | 4335 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | @@ -4315,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4315,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4315 | if (arg1_value == irb->codegen->invalid_instruction) | 4507 | if (arg1_value == irb->codegen->invalid_instruction) |
| 4316 | return arg1_value; | 4508 | return arg1_value; |
| 4317 | 4509 | ||
| 4318 | IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value); | 4510 | IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); |
| 4319 | return ir_lval_wrap(irb, scope, ptr_cast, lval); | 4511 | return ir_lval_wrap(irb, scope, ptr_cast, lval); |
| 4320 | } | 4512 | } |
| 4321 | case BuiltinFnIdBitCast: | 4513 | case BuiltinFnIdBitCast: |
| ... | @@ -4689,6 +4881,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4689,6 +4881,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4689 | IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); | 4881 | IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); |
| 4690 | return ir_lval_wrap(irb, scope, result, lval); | 4882 | return ir_lval_wrap(irb, scope, result, lval); |
| 4691 | } | 4883 | } |
| 4884 | case BuiltinFnIdBswap: | ||
| 4885 | { | ||
| 4886 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4887 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4888 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4889 | return arg0_value; | ||
| 4890 | |||
| 4891 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4892 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4893 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4894 | return arg1_value; | ||
| 4895 | |||
| 4896 | IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); | ||
| 4897 | return ir_lval_wrap(irb, scope, result, lval); | ||
| 4898 | } | ||
| 4899 | case BuiltinFnIdBitReverse: | ||
| 4900 | { | ||
| 4901 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4902 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4903 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4904 | return arg0_value; | ||
| 4905 | |||
| 4906 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4907 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4908 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4909 | return arg1_value; | ||
| 4910 | |||
| 4911 | IrInstruction *result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); | ||
| 4912 | return ir_lval_wrap(irb, scope, result, lval); | ||
| 4913 | } | ||
| 4692 | } | 4914 | } |
| 4693 | zig_unreachable(); | 4915 | zig_unreachable(); |
| 4694 | } | 4916 | } |
| ... | @@ -4723,7 +4945,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node | ... | @@ -4723,7 +4945,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node |
| 4723 | } | 4945 | } |
| 4724 | } | 4946 | } |
| 4725 | 4947 | ||
| 4726 | IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr); | 4948 | IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, |
| 4949 | is_async, async_allocator, nullptr); | ||
| 4727 | return ir_lval_wrap(irb, scope, fn_call, lval); | 4950 | return ir_lval_wrap(irb, scope, fn_call, lval); |
| 4728 | } | 4951 | } |
| 4729 | 4952 | ||
| ... | @@ -4732,7 +4955,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4732,7 +4955,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4732 | 4955 | ||
| 4733 | IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); | 4956 | IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); |
| 4734 | if (condition == irb->codegen->invalid_instruction) | 4957 | if (condition == irb->codegen->invalid_instruction) |
| 4735 | return condition; | 4958 | return irb->codegen->invalid_instruction; |
| 4736 | 4959 | ||
| 4737 | IrInstruction *is_comptime; | 4960 | IrInstruction *is_comptime; |
| 4738 | if (ir_should_inline(irb->exec, scope)) { | 4961 | if (ir_should_inline(irb->exec, scope)) { |
| ... | @@ -4755,7 +4978,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4755,7 +4978,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4755 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | 4978 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| 4756 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope); | 4979 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope); |
| 4757 | if (then_expr_result == irb->codegen->invalid_instruction) | 4980 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 4758 | return then_expr_result; | 4981 | return irb->codegen->invalid_instruction; |
| 4759 | IrBasicBlock *after_then_block = irb->current_basic_block; | 4982 | IrBasicBlock *after_then_block = irb->current_basic_block; |
| 4760 | if (!instr_is_unreachable(then_expr_result)) | 4983 | if (!instr_is_unreachable(then_expr_result)) |
| 4761 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | 4984 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); |
| ... | @@ -4765,7 +4988,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4765,7 +4988,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4765 | if (else_node) { | 4988 | if (else_node) { |
| 4766 | else_expr_result = ir_gen_node(irb, else_node, subexpr_scope); | 4989 | else_expr_result = ir_gen_node(irb, else_node, subexpr_scope); |
| 4767 | if (else_expr_result == irb->codegen->invalid_instruction) | 4990 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 4768 | return else_expr_result; | 4991 | return irb->codegen->invalid_instruction; |
| 4769 | } else { | 4992 | } else { |
| 4770 | else_expr_result = ir_build_const_void(irb, scope, node); | 4993 | else_expr_result = ir_build_const_void(irb, scope, node); |
| 4771 | } | 4994 | } |
| ... | @@ -4810,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction * | ... | @@ -4810,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction * |
| 4810 | return ir_build_ref(irb, scope, value->source_node, value, false, false); | 5033 | return ir_build_ref(irb, scope, value->source_node, value, false, false); |
| 4811 | } | 5034 | } |
| 4812 | 5035 | ||
| 5036 | static PtrLen star_token_to_ptr_len(TokenId token_id) { | ||
| 5037 | switch (token_id) { | ||
| 5038 | case TokenIdStar: | ||
| 5039 | case TokenIdStarStar: | ||
| 5040 | return PtrLenSingle; | ||
| 5041 | case TokenIdBracketStarBracket: | ||
| 5042 | return PtrLenUnknown; | ||
| 5043 | case TokenIdBracketStarCBracket: | ||
| 5044 | return PtrLenC; | ||
| 5045 | default: | ||
| 5046 | zig_unreachable(); | ||
| 5047 | } | ||
| 5048 | } | ||
| 5049 | |||
| 4813 | static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) { | 5050 | static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 4814 | assert(node->type == NodeTypePointerType); | 5051 | assert(node->type == NodeTypePointerType); |
| 4815 | PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar || | 5052 | PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id); |
| 4816 | node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown; | ||
| 4817 | bool is_const = node->data.pointer_type.is_const; | 5053 | bool is_const = node->data.pointer_type.is_const; |
| 4818 | bool is_volatile = node->data.pointer_type.is_volatile; | 5054 | bool is_volatile = node->data.pointer_type.is_volatile; |
| 4819 | AstNode *expr_node = node->data.pointer_type.op_expr; | 5055 | AstNode *expr_node = node->data.pointer_type.op_expr; |
| ... | @@ -4866,7 +5102,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4866,7 +5102,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 4866 | ptr_len, align_value, bit_offset_start, host_int_bytes); | 5102 | ptr_len, align_value, bit_offset_start, host_int_bytes); |
| 4867 | } | 5103 | } |
| 4868 | 5104 | ||
| 4869 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, | 5105 | static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, |
| 4870 | LVal lval) | 5106 | LVal lval) |
| 4871 | { | 5107 | { |
| 4872 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr); | 5108 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr); |
| ... | @@ -4992,11 +5228,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -4992,11 +5228,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4992 | ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); | 5228 | ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); |
| 4993 | ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, | 5229 | ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, |
| 4994 | is_const, is_const, is_shadowable, is_comptime); | 5230 | is_const, is_const, is_shadowable, is_comptime); |
| 4995 | // we detect IrInstructionIdDeclVar in gen_block to make sure the next node | 5231 | // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node |
| 4996 | // is inside var->child_scope | 5232 | // is inside var->child_scope |
| 4997 | 5233 | ||
| 4998 | if (!is_extern && !variable_declaration->expr) { | 5234 | if (!is_extern && !variable_declaration->expr) { |
| 4999 | var->value->type = irb->codegen->builtin_types.entry_invalid; | 5235 | var->var_type = irb->codegen->builtin_types.entry_invalid; |
| 5000 | add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); | 5236 | add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); |
| 5001 | return irb->codegen->invalid_instruction; | 5237 | return irb->codegen->invalid_instruction; |
| 5002 | } | 5238 | } |
| ... | @@ -5012,6 +5248,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5012,6 +5248,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5012 | add_node_error(irb->codegen, variable_declaration->section_expr, | 5248 | add_node_error(irb->codegen, variable_declaration->section_expr, |
| 5013 | buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); | 5249 | buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); |
| 5014 | } | 5250 | } |
| 5251 | if (variable_declaration->threadlocal_tok != nullptr) { | ||
| 5252 | add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok, | ||
| 5253 | buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol))); | ||
| 5254 | } | ||
| 5015 | 5255 | ||
| 5016 | // Temporarily set the name of the IrExecutable to the VariableDeclaration | 5256 | // Temporarily set the name of the IrExecutable to the VariableDeclaration |
| 5017 | // so that the struct or enum from the init expression inherits the name. | 5257 | // so that the struct or enum from the init expression inherits the name. |
| ... | @@ -5023,7 +5263,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5023,7 +5263,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5023 | if (init_value == irb->codegen->invalid_instruction) | 5263 | if (init_value == irb->codegen->invalid_instruction) |
| 5024 | return init_value; | 5264 | return init_value; |
| 5025 | 5265 | ||
| 5026 | return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value); | 5266 | return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value); |
| 5027 | } | 5267 | } |
| 5028 | 5268 | ||
| 5029 | static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | 5269 | static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| ... | @@ -5079,7 +5319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5079,7 +5319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5079 | err_val_ptr, false); | 5319 | err_val_ptr, false); |
| 5080 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? | 5320 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 5081 | var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value); | 5321 | var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value); |
| 5082 | ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | 5322 | ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); |
| 5083 | } | 5323 | } |
| 5084 | 5324 | ||
| 5085 | ZigList<IrInstruction *> incoming_values = {0}; | 5325 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | @@ -5119,7 +5359,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5119,7 +5359,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5119 | true, false, false, is_comptime); | 5359 | true, false, false, is_comptime); |
| 5120 | Scope *err_scope = err_var->child_scope; | 5360 | Scope *err_scope = err_var->child_scope; |
| 5121 | IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); | 5361 | IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); |
| 5122 | ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); | 5362 | ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); |
| 5123 | 5363 | ||
| 5124 | IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope); | 5364 | IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope); |
| 5125 | if (else_result == irb->codegen->invalid_instruction) | 5365 | if (else_result == irb->codegen->invalid_instruction) |
| ... | @@ -5159,10 +5399,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -5159,10 +5399,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5159 | } | 5399 | } |
| 5160 | 5400 | ||
| 5161 | ir_set_cursor_at_end_and_append_block(irb, body_block); | 5401 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 5162 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false); | 5402 | IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false); |
| 5163 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? | 5403 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 5164 | var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value); | 5404 | var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value); |
| 5165 | ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | 5405 | ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); |
| 5166 | 5406 | ||
| 5167 | ZigList<IrInstruction *> incoming_values = {0}; | 5407 | ZigList<IrInstruction *> incoming_values = {0}; |
| 5168 | ZigList<IrBasicBlock *> incoming_blocks = {0}; | 5408 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| ... | @@ -5319,7 +5559,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5319,7 +5559,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5319 | Scope *child_scope = elem_var->child_scope; | 5559 | Scope *child_scope = elem_var->child_scope; |
| 5320 | 5560 | ||
| 5321 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); | 5561 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); |
| 5322 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); | 5562 | ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); |
| 5323 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); | 5563 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); |
| 5324 | 5564 | ||
| 5325 | AstNode *index_var_source_node; | 5565 | AstNode *index_var_source_node; |
| ... | @@ -5337,7 +5577,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5337,7 +5577,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5337 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); | 5577 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); |
| 5338 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); | 5578 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); |
| 5339 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); | 5579 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); |
| 5340 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); | 5580 | ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); |
| 5341 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); | 5581 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); |
| 5342 | 5582 | ||
| 5343 | 5583 | ||
| ... | @@ -5561,8 +5801,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5561,8 +5801,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5561 | return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile); | 5801 | return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile); |
| 5562 | } | 5802 | } |
| 5563 | 5803 | ||
| 5564 | static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | 5804 | static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 5565 | assert(node->type == NodeTypeTestExpr); | 5805 | assert(node->type == NodeTypeIfOptional); |
| 5566 | 5806 | ||
| 5567 | Buf *var_symbol = node->data.test_expr.var_symbol; | 5807 | Buf *var_symbol = node->data.test_expr.var_symbol; |
| 5568 | AstNode *expr_node = node->data.test_expr.target_node; | 5808 | AstNode *expr_node = node->data.test_expr.target_node; |
| ... | @@ -5600,9 +5840,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no | ... | @@ -5600,9 +5840,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no |
| 5600 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, | 5840 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, |
| 5601 | var_symbol, is_const, is_const, is_shadowable, is_comptime); | 5841 | var_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5602 | 5842 | ||
| 5603 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false); | 5843 | IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); |
| 5604 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); | 5844 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); |
| 5605 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | 5845 | ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); |
| 5606 | var_scope = var->child_scope; | 5846 | var_scope = var->child_scope; |
| 5607 | } else { | 5847 | } else { |
| 5608 | var_scope = subexpr_scope; | 5848 | var_scope = subexpr_scope; |
| ... | @@ -5677,7 +5917,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -5677,7 +5917,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 5677 | 5917 | ||
| 5678 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false); | 5918 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false); |
| 5679 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); | 5919 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); |
| 5680 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | 5920 | ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); |
| 5681 | var_scope = var->child_scope; | 5921 | var_scope = var->child_scope; |
| 5682 | } else { | 5922 | } else { |
| 5683 | var_scope = subexpr_scope; | 5923 | var_scope = subexpr_scope; |
| ... | @@ -5702,7 +5942,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -5702,7 +5942,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 5702 | err_symbol, is_const, is_const, is_shadowable, is_comptime); | 5942 | err_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5703 | 5943 | ||
| 5704 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr); | 5944 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr); |
| 5705 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | 5945 | ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); |
| 5706 | err_var_scope = var->child_scope; | 5946 | err_var_scope = var->child_scope; |
| 5707 | } else { | 5947 | } else { |
| 5708 | err_var_scope = subexpr_scope; | 5948 | err_var_scope = subexpr_scope; |
| ... | @@ -5757,7 +5997,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit | ... | @@ -5757,7 +5997,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 5757 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); | 5997 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); |
| 5758 | } | 5998 | } |
| 5759 | IrInstruction *var_type = nullptr; // infer the type | 5999 | IrInstruction *var_type = nullptr; // infer the type |
| 5760 | ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); | 6000 | ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); |
| 5761 | } else { | 6001 | } else { |
| 5762 | child_scope = scope; | 6002 | child_scope = scope; |
| 5763 | } | 6003 | } |
| ... | @@ -6167,7 +6407,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -6167,7 +6407,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) |
| 6167 | return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true); | 6407 | return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true); |
| 6168 | } | 6408 | } |
| 6169 | 6409 | ||
| 6170 | static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 6410 | static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| 6171 | assert(node->type == NodeTypeUnwrapErrorExpr); | 6411 | assert(node->type == NodeTypeUnwrapErrorExpr); |
| 6172 | 6412 | ||
| 6173 | AstNode *op1_node = node->data.unwrap_err_expr.op1; | 6413 | AstNode *op1_node = node->data.unwrap_err_expr.op1; |
| ... | @@ -6181,7 +6421,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN | ... | @@ -6181,7 +6421,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 6181 | add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); | 6421 | add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); |
| 6182 | return irb->codegen->invalid_instruction; | 6422 | return irb->codegen->invalid_instruction; |
| 6183 | } | 6423 | } |
| 6184 | return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone); | 6424 | return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone); |
| 6185 | } | 6425 | } |
| 6186 | 6426 | ||
| 6187 | 6427 | ||
| ... | @@ -6215,7 +6455,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN | ... | @@ -6215,7 +6455,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 6215 | is_const, is_const, is_shadowable, is_comptime); | 6455 | is_const, is_const, is_shadowable, is_comptime); |
| 6216 | err_scope = var->child_scope; | 6456 | err_scope = var->child_scope; |
| 6217 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); | 6457 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); |
| 6218 | ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val); | 6458 | ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val); |
| 6219 | } else { | 6459 | } else { |
| 6220 | err_scope = parent_scope; | 6460 | err_scope = parent_scope; |
| 6221 | } | 6461 | } |
| ... | @@ -6251,7 +6491,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o | ... | @@ -6251,7 +6491,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o |
| 6251 | ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; | 6491 | ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; |
| 6252 | if (need_comma) | 6492 | if (need_comma) |
| 6253 | buf_append_char(name, ','); | 6493 | buf_append_char(name, ','); |
| 6254 | render_const_value(codegen, name, var_scope->var->value); | 6494 | // TODO: const ptr reinterpret here to make the var type agree with the value? |
| 6495 | render_const_value(codegen, name, var_scope->var->const_value); | ||
| 6255 | return true; | 6496 | return true; |
| 6256 | } | 6497 | } |
| 6257 | 6498 | ||
| ... | @@ -6501,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -6501,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode |
| 6501 | IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 | 6742 | IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 |
| 6502 | 6743 | ||
| 6503 | // TODO relies on Zig not re-ordering fields | 6744 | // TODO relies on Zig not re-ordering fields |
| 6504 | IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst); | 6745 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst, |
| 6746 | false); | ||
| 6505 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); | 6747 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); |
| 6506 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); | 6748 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 6507 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, | 6749 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 6508 | atomic_state_field_name); | 6750 | atomic_state_field_name); |
| 6509 | 6751 | ||
| 6510 | // set the is_canceled bit | 6752 | // set the is_canceled bit |
| 6511 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | 6753 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, |
| 6512 | usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr, | 6754 | usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr, |
| 6513 | AtomicRmwOp_or, AtomicOrderSeqCst); | 6755 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6514 | 6756 | ||
| ... | @@ -6579,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -6579,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode |
| 6579 | get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void)); | 6821 | get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void)); |
| 6580 | 6822 | ||
| 6581 | // TODO relies on Zig not re-ordering fields | 6823 | // TODO relies on Zig not re-ordering fields |
| 6582 | IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst); | 6824 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst, |
| 6825 | false); | ||
| 6583 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); | 6826 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); |
| 6584 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); | 6827 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 6585 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, | 6828 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 6586 | atomic_state_field_name); | 6829 | atomic_state_field_name); |
| 6587 | 6830 | ||
| 6588 | // clear the is_suspended bit | 6831 | // clear the is_suspended bit |
| 6589 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | 6832 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, |
| 6590 | usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr, | 6833 | usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr, |
| 6591 | AtomicRmwOp_and, AtomicOrderSeqCst); | 6834 | AtomicRmwOp_and, AtomicOrderSeqCst); |
| 6592 | 6835 | ||
| ... | @@ -6695,14 +6938,14 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -6695,14 +6938,14 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6695 | IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst); | 6938 | IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst); |
| 6696 | IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type); | 6939 | IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type); |
| 6697 | ir_build_await_bookkeeping(irb, scope, node, promise_result_type); | 6940 | ir_build_await_bookkeeping(irb, scope, node, promise_result_type); |
| 6698 | ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value); | 6941 | ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value); |
| 6699 | IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var); | 6942 | IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var); |
| 6700 | ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr); | 6943 | ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr); |
| 6701 | IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle); | 6944 | IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle); |
| 6702 | 6945 | ||
| 6703 | IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle); | 6946 | IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle); |
| 6704 | IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false); | 6947 | IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false); |
| 6705 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | 6948 | IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, |
| 6706 | usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr, | 6949 | usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr, |
| 6707 | AtomicRmwOp_or, AtomicOrderSeqCst); | 6950 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6708 | 6951 | ||
| ... | @@ -6745,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -6745,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6745 | 6988 | ||
| 6746 | 6989 | ||
| 6747 | ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block); | 6990 | ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block); |
| 6748 | IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | 6991 | IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, |
| 6749 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr, | 6992 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr, |
| 6750 | AtomicRmwOp_or, AtomicOrderSeqCst); | 6993 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6751 | IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false); | 6994 | IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false); |
| ... | @@ -6777,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -6777,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6777 | 7020 | ||
| 6778 | ir_set_cursor_at_end_and_append_block(irb, cleanup_block); | 7021 | ir_set_cursor_at_end_and_append_block(irb, cleanup_block); |
| 6779 | IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false); | 7022 | IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false); |
| 6780 | IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, | 7023 | IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, |
| 6781 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr, | 7024 | usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr, |
| 6782 | AtomicRmwOp_or, AtomicOrderSeqCst); | 7025 | AtomicRmwOp_or, AtomicOrderSeqCst); |
| 6783 | IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false); | 7026 | IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false); |
| ... | @@ -6989,7 +7232,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -6989,7 +7232,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6989 | if (maybe_ptr == irb->codegen->invalid_instruction) | 7232 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 6990 | return irb->codegen->invalid_instruction; | 7233 | return irb->codegen->invalid_instruction; |
| 6991 | 7234 | ||
| 6992 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); | 7235 | IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true); |
| 6993 | if (lval == LValPtr) | 7236 | if (lval == LValPtr) |
| 6994 | return unwrapped_ptr; | 7237 | return unwrapped_ptr; |
| 6995 | 7238 | ||
| ... | @@ -7013,8 +7256,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -7013,8 +7256,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7013 | return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); | 7256 | return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); |
| 7014 | case NodeTypeIfErrorExpr: | 7257 | case NodeTypeIfErrorExpr: |
| 7015 | return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); | 7258 | return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); |
| 7016 | case NodeTypeTestExpr: | 7259 | case NodeTypeIfOptional: |
| 7017 | return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval); | 7260 | return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval); |
| 7018 | case NodeTypeSwitchExpr: | 7261 | case NodeTypeSwitchExpr: |
| 7019 | return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval); | 7262 | return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval); |
| 7020 | case NodeTypeCompTime: | 7263 | case NodeTypeCompTime: |
| ... | @@ -7032,7 +7275,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -7032,7 +7275,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7032 | case NodeTypeSliceExpr: | 7275 | case NodeTypeSliceExpr: |
| 7033 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); | 7276 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); |
| 7034 | case NodeTypeUnwrapErrorExpr: | 7277 | case NodeTypeUnwrapErrorExpr: |
| 7035 | return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); | 7278 | return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval); |
| 7036 | case NodeTypeContainerDecl: | 7279 | case NodeTypeContainerDecl: |
| 7037 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); | 7280 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); |
| 7038 | case NodeTypeFnProto: | 7281 | case NodeTypeFnProto: |
| ... | @@ -7091,6 +7334,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -7091,6 +7334,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7091 | ir_ref_bb(irb->current_basic_block); | 7334 | ir_ref_bb(irb->current_basic_block); |
| 7092 | 7335 | ||
| 7093 | ZigFn *fn_entry = exec_fn_entry(irb->exec); | 7336 | ZigFn *fn_entry = exec_fn_entry(irb->exec); |
| 7337 | |||
| 7094 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | 7338 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 7095 | IrInstruction *coro_id; | 7339 | IrInstruction *coro_id; |
| 7096 | IrInstruction *u8_ptr_type; | 7340 | IrInstruction *u8_ptr_type; |
| ... | @@ -7111,27 +7355,28 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -7111,27 +7355,28 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7111 | ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type); | 7355 | ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type); |
| 7112 | IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type); | 7356 | IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type); |
| 7113 | // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa | 7357 | // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa |
| 7114 | ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef); | 7358 | ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef); |
| 7115 | coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var); | 7359 | coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var); |
| 7116 | 7360 | ||
| 7117 | ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); | 7361 | ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); |
| 7118 | IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node); | 7362 | IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node); |
| 7119 | IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node, | 7363 | IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node, |
| 7120 | get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); | 7364 | get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); |
| 7121 | ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value); | 7365 | ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value); |
| 7122 | irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var); | 7366 | irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var); |
| 7123 | 7367 | ||
| 7124 | u8_ptr_type = ir_build_const_type(irb, coro_scope, node, | 7368 | u8_ptr_type = ir_build_const_type(irb, coro_scope, node, |
| 7125 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); | 7369 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| 7126 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr); | 7370 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, |
| 7371 | coro_promise_ptr, false); | ||
| 7127 | coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr); | 7372 | coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr); |
| 7128 | coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); | 7373 | coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); |
| 7129 | IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node); | 7374 | IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node); |
| 7130 | ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size); | 7375 | ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size); |
| 7131 | IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node, | 7376 | IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node, |
| 7132 | ImplicitAllocatorIdArg); | 7377 | ImplicitAllocatorIdArg); |
| 7133 | irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false); | 7378 | irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false); |
| 7134 | ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); | 7379 | ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); |
| 7135 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); | 7380 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| 7136 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name); | 7381 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name); |
| 7137 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr); | 7382 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr); |
| ... | @@ -7147,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -7147,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7147 | ir_build_return(irb, coro_scope, node, undef); | 7392 | ir_build_return(irb, coro_scope, node, undef); |
| 7148 | 7393 | ||
| 7149 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); | 7394 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); |
| 7150 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr); | 7395 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr, |
| 7396 | false); | ||
| 7151 | irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr); | 7397 | irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr); |
| 7152 | 7398 | ||
| 7153 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); | 7399 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| ... | @@ -7225,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -7225,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7225 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, | 7471 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, |
| 7226 | false, false, PtrLenUnknown, 0, 0, 0)); | 7472 | false, false, PtrLenUnknown, 0, 0, 0)); |
| 7227 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); | 7473 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); |
| 7228 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); | 7474 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, |
| 7229 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, | 7475 | result_ptr, false); |
| 7230 | irb->exec->coro_result_field_ptr); | 7476 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, |
| 7477 | u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false); | ||
| 7231 | IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node, | 7478 | IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node, |
| 7232 | fn_entry->type_entry->data.fn.fn_type_id.return_type); | 7479 | fn_entry->type_entry->data.fn.fn_type_id.return_type); |
| 7233 | IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst); | 7480 | IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst); |
| ... | @@ -7242,7 +7489,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -7242,7 +7489,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7242 | // Before we destroy the coroutine frame, we need to load the target promise into | 7489 | // Before we destroy the coroutine frame, we need to load the target promise into |
| 7243 | // a register or local variable which does not get spilled into the frame, | 7490 | // a register or local variable which does not get spilled into the frame, |
| 7244 | // otherwise llvm tries to access memory inside the destroyed frame. | 7491 | // otherwise llvm tries to access memory inside the destroyed frame. |
| 7245 | IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node, | 7492 | IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, |
| 7246 | irb->exec->await_handle_var_ptr, false); | 7493 | irb->exec->await_handle_var_ptr, false); |
| 7247 | IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr); | 7494 | IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr); |
| 7248 | ir_build_br(irb, scope, node, check_free_block, const_bool_false); | 7495 | ir_build_br(irb, scope, node, check_free_block, const_bool_false); |
| ... | @@ -7277,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -7277,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7277 | IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, | 7524 | IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, |
| 7278 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, | 7525 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, |
| 7279 | false, false, PtrLenUnknown, 0, 0, 0)); | 7526 | false, false, PtrLenUnknown, 0, 0, 0)); |
| 7280 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); | 7527 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, |
| 7528 | coro_mem_ptr_maybe, false); | ||
| 7281 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); | 7529 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); |
| 7282 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); | 7530 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); |
| 7283 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); | 7531 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); |
| ... | @@ -7330,24 +7578,51 @@ static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *ms | ... | @@ -7330,24 +7578,51 @@ static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *ms |
| 7330 | return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg); | 7578 | return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg); |
| 7331 | } | 7579 | } |
| 7332 | 7580 | ||
| 7581 | static ErrorMsg *opt_ir_add_error_node(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, Buf *msg) { | ||
| 7582 | if (ira != nullptr) | ||
| 7583 | return exec_add_error_node(codegen, ira->new_irb.exec, source_node, msg); | ||
| 7584 | else | ||
| 7585 | return add_node_error(codegen, source_node, msg); | ||
| 7586 | } | ||
| 7587 | |||
| 7333 | static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) { | 7588 | static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) { |
| 7334 | return ir_add_error_node(ira, source_instruction->source_node, msg); | 7589 | return ir_add_error_node(ira, source_instruction->source_node, msg); |
| 7335 | } | 7590 | } |
| 7336 | 7591 | ||
| 7337 | static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) { | 7592 | // This function takes a comptime ptr and makes the child const value conform to the type |
| 7338 | ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val); | 7593 | // described by the pointer. |
| 7594 | static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, | ||
| 7595 | ConstExprValue *ptr_val) | ||
| 7596 | { | ||
| 7597 | Error err; | ||
| 7598 | assert(ptr_val->type->id == ZigTypeIdPointer); | ||
| 7599 | ConstExprValue tmp = {}; | ||
| 7600 | tmp.special = ConstValSpecialStatic; | ||
| 7601 | tmp.type = ptr_val->type->data.pointer.child_type; | ||
| 7602 | if ((err = ir_read_const_ptr(ira, codegen, source_node, &tmp, ptr_val))) | ||
| 7603 | return err; | ||
| 7604 | ConstExprValue *child_val = const_ptr_pointee_unchecked(codegen, ptr_val); | ||
| 7605 | copy_const_val(child_val, &tmp, false); | ||
| 7606 | return ErrorNone; | ||
| 7607 | } | ||
| 7608 | |||
| 7609 | ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val, | ||
| 7610 | AstNode *source_node) | ||
| 7611 | { | ||
| 7612 | Error err; | ||
| 7613 | ConstExprValue *val = const_ptr_pointee_unchecked(codegen, const_val); | ||
| 7339 | assert(val != nullptr); | 7614 | assert(val != nullptr); |
| 7340 | assert(const_val->type->id == ZigTypeIdPointer); | 7615 | assert(const_val->type->id == ZigTypeIdPointer); |
| 7341 | ZigType *expected_type = const_val->type->data.pointer.child_type; | 7616 | ZigType *expected_type = const_val->type->data.pointer.child_type; |
| 7342 | if (!types_have_same_zig_comptime_repr(val->type, expected_type)) { | 7617 | if (!types_have_same_zig_comptime_repr(val->type, expected_type)) { |
| 7343 | ir_add_error_node(ira, source_node, | 7618 | if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val))) |
| 7344 | buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955")); | 7619 | return nullptr; |
| 7345 | return nullptr; | 7620 | return const_ptr_pointee_unchecked(codegen, const_val); |
| 7346 | } | 7621 | } |
| 7347 | return val; | 7622 | return val; |
| 7348 | } | 7623 | } |
| 7349 | 7624 | ||
| 7350 | static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { | 7625 | static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { |
| 7351 | IrBasicBlock *bb = exec->basic_block_list.at(0); | 7626 | IrBasicBlock *bb = exec->basic_block_list.at(0); |
| 7352 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { | 7627 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { |
| 7353 | IrInstruction *instruction = bb->instruction_list.at(i); | 7628 | IrInstruction *instruction = bb->instruction_list.at(i); |
| ... | @@ -7357,16 +7632,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) | ... | @@ -7357,16 +7632,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) |
| 7357 | if (value->value.special == ConstValSpecialRuntime) { | 7632 | if (value->value.special == ConstValSpecialRuntime) { |
| 7358 | exec_add_error_node(codegen, exec, value->source_node, | 7633 | exec_add_error_node(codegen, exec, value->source_node, |
| 7359 | buf_sprintf("unable to evaluate constant expression")); | 7634 | buf_sprintf("unable to evaluate constant expression")); |
| 7360 | return codegen->invalid_instruction; | 7635 | return &codegen->invalid_instruction->value; |
| 7361 | } | 7636 | } |
| 7362 | return value; | 7637 | return &value->value; |
| 7363 | } else if (ir_has_side_effects(instruction)) { | 7638 | } else if (ir_has_side_effects(instruction)) { |
| 7364 | exec_add_error_node(codegen, exec, instruction->source_node, | 7639 | exec_add_error_node(codegen, exec, instruction->source_node, |
| 7365 | buf_sprintf("unable to evaluate constant expression")); | 7640 | buf_sprintf("unable to evaluate constant expression")); |
| 7366 | return codegen->invalid_instruction; | 7641 | return &codegen->invalid_instruction->value; |
| 7367 | } | 7642 | } |
| 7368 | } | 7643 | } |
| 7369 | return codegen->invalid_instruction; | 7644 | return &codegen->invalid_instruction->value; |
| 7370 | } | 7645 | } |
| 7371 | 7646 | ||
| 7372 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { | 7647 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { |
| ... | @@ -8086,6 +8361,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8086,6 +8361,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 8086 | 8361 | ||
| 8087 | bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt); | 8362 | bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt); |
| 8088 | bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat); | 8363 | bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat); |
| 8364 | assert(const_val_is_int || const_val_is_float); | ||
| 8089 | 8365 | ||
| 8090 | if (other_type->id == ZigTypeIdFloat) { | 8366 | if (other_type->id == ZigTypeIdFloat) { |
| 8091 | if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) { | 8367 | if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) { |
| ... | @@ -8376,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp | ... | @@ -8376,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp |
| 8376 | return err_set_type; | 8652 | return err_set_type; |
| 8377 | } | 8653 | } |
| 8378 | 8654 | ||
| 8379 | |||
| 8380 | static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type, | 8655 | static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type, |
| 8381 | ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable) | 8656 | ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable) |
| 8382 | { | 8657 | { |
| ... | @@ -8389,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted | ... | @@ -8389,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8389 | if (wanted_type == actual_type) | 8664 | if (wanted_type == actual_type) |
| 8390 | return result; | 8665 | return result; |
| 8391 | 8666 | ||
| 8392 | // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively | 8667 | // If pointers have the same representation in memory, they can be "const-casted". |
| 8393 | // but not if we want a mutable pointer | 8668 | // `const` attribute can be gained |
| 8394 | // and not if the actual pointer has zero bits | 8669 | // `volatile` attribute can be gained |
| 8395 | if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional && | 8670 | // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer) |
| 8396 | wanted_type->data.maybe.child_type->id == ZigTypeIdPointer && | 8671 | // but only if !wanted_is_mutable |
| 8397 | actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type)) | 8672 | // alignment can be decreased |
| 8398 | { | 8673 | // bit offset attributes must match exactly |
| 8399 | ConstCastOnly child = types_match_const_cast_only(ira, | 8674 | // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one |
| 8400 | wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable); | 8675 | ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type); |
| 8401 | if (child.id == ConstCastResultIdInvalid) | 8676 | ZigType *actual_ptr_type = get_src_ptr_type(actual_type); |
| 8402 | return child; | 8677 | bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type); |
| 8403 | if (child.id != ConstCastResultIdOk) { | 8678 | bool actual_allows_zero = ptr_allows_addr_zero(actual_type); |
| 8404 | result.id = ConstCastResultIdNullWrapPtr; | 8679 | bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC; |
| 8405 | result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1); | 8680 | bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC; |
| 8406 | *result.data.null_wrap_ptr_child = child; | 8681 | bool wanted_opt_or_ptr = wanted_ptr_type != nullptr && |
| 8407 | } | 8682 | (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional); |
| 8408 | return result; | 8683 | bool actual_opt_or_ptr = actual_ptr_type != nullptr && |
| 8409 | } | 8684 | (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional); |
| 8410 | 8685 | if (wanted_opt_or_ptr && actual_opt_or_ptr) { | |
| 8411 | // pointer const | 8686 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, |
| 8412 | if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) { | 8687 | actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const); |
| 8413 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | ||
| 8414 | actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const); | ||
| 8415 | if (child.id == ConstCastResultIdInvalid) | 8688 | if (child.id == ConstCastResultIdInvalid) |
| 8416 | return child; | 8689 | return child; |
| 8417 | if (child.id != ConstCastResultIdOk) { | 8690 | if (child.id != ConstCastResultIdOk) { |
| 8418 | result.id = ConstCastResultIdPointerChild; | 8691 | result.id = ConstCastResultIdPointerChild; |
| 8419 | result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1); | 8692 | result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1); |
| 8420 | result.data.pointer_mismatch->child = child; | 8693 | result.data.pointer_mismatch->child = child; |
| 8421 | result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type; | 8694 | result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type; |
| 8422 | result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type; | 8695 | result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type; |
| 8696 | return result; | ||
| 8697 | } | ||
| 8698 | bool ok_allows_zero = (wanted_allows_zero && | ||
| 8699 | (actual_allows_zero || !wanted_is_mutable)) || | ||
| 8700 | (!wanted_allows_zero && !actual_allows_zero); | ||
| 8701 | if (!ok_allows_zero) { | ||
| 8702 | result.id = ConstCastResultIdBadAllowsZero; | ||
| 8703 | result.data.bad_allows_zero = allocate_nonzero<ConstCastBadAllowsZero>(1); | ||
| 8704 | result.data.bad_allows_zero->wanted_type = wanted_type; | ||
| 8705 | result.data.bad_allows_zero->actual_type = actual_type; | ||
| 8423 | return result; | 8706 | return result; |
| 8424 | } | 8707 | } |
| 8425 | if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { | 8708 | if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { |
| 8426 | result.id = ConstCastResultIdInvalid; | 8709 | result.id = ConstCastResultIdInvalid; |
| 8427 | return result; | 8710 | return result; |
| 8428 | } | 8711 | } |
| 8429 | if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { | 8712 | if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { |
| 8430 | result.id = ConstCastResultIdInvalid; | 8713 | result.id = ConstCastResultIdInvalid; |
| 8431 | return result; | 8714 | return result; |
| 8432 | } | 8715 | } |
| 8433 | if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) && | 8716 | bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len; |
| 8434 | (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && | 8717 | if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) && |
| 8435 | (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) && | 8718 | type_has_bits(wanted_type) == type_has_bits(actual_type) && |
| 8436 | actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host && | 8719 | (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && |
| 8437 | actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes && | 8720 | (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && |
| 8438 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type)) | 8721 | actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host && |
| 8722 | actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes && | ||
| 8723 | get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type)) | ||
| 8439 | { | 8724 | { |
| 8440 | return result; | 8725 | return result; |
| 8441 | } | 8726 | } |
| ... | @@ -8669,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * | ... | @@ -8669,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * |
| 8669 | *errors = reallocate(*errors, old_errors_count, *errors_count); | 8954 | *errors = reallocate(*errors, old_errors_count, *errors_count); |
| 8670 | } | 8955 | } |
| 8671 | 8956 | ||
| 8672 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) { | 8957 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, |
| 8958 | IrInstruction **instructions, size_t instruction_count) | ||
| 8959 | { | ||
| 8673 | Error err; | 8960 | Error err; |
| 8674 | assert(instruction_count >= 1); | 8961 | assert(instruction_count >= 1); |
| 8675 | IrInstruction *prev_inst = instructions[0]; | 8962 | IrInstruction *prev_inst = instructions[0]; |
| ... | @@ -8680,13 +8967,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -8680,13 +8967,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8680 | size_t errors_count = 0; | 8967 | size_t errors_count = 0; |
| 8681 | ZigType *err_set_type = nullptr; | 8968 | ZigType *err_set_type = nullptr; |
| 8682 | if (prev_inst->value.type->id == ZigTypeIdErrorSet) { | 8969 | if (prev_inst->value.type->id == ZigTypeIdErrorSet) { |
| 8970 | if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) { | ||
| 8971 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8972 | } | ||
| 8683 | if (type_is_global_error_set(prev_inst->value.type)) { | 8973 | if (type_is_global_error_set(prev_inst->value.type)) { |
| 8684 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; | 8974 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; |
| 8685 | } else { | 8975 | } else { |
| 8686 | err_set_type = prev_inst->value.type; | 8976 | err_set_type = prev_inst->value.type; |
| 8687 | if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) { | ||
| 8688 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8689 | } | ||
| 8690 | update_errors_helper(ira->codegen, &errors, &errors_count); | 8977 | update_errors_helper(ira->codegen, &errors, &errors_count); |
| 8691 | 8978 | ||
| 8692 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | 8979 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { |
| ... | @@ -8845,6 +9132,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -8845,6 +9132,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8845 | if (prev_type->id == ZigTypeIdArray) { | 9132 | if (prev_type->id == ZigTypeIdArray) { |
| 8846 | convert_to_const_slice = true; | 9133 | convert_to_const_slice = true; |
| 8847 | } | 9134 | } |
| 9135 | if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { | ||
| 9136 | return ira->codegen->builtin_types.entry_invalid; | ||
| 9137 | } | ||
| 8848 | if (type_is_global_error_set(cur_type)) { | 9138 | if (type_is_global_error_set(cur_type)) { |
| 8849 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; | 9139 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; |
| 8850 | continue; | 9140 | continue; |
| ... | @@ -8852,9 +9142,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -8852,9 +9142,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8852 | if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) { | 9142 | if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) { |
| 8853 | continue; | 9143 | continue; |
| 8854 | } | 9144 | } |
| 8855 | if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { | ||
| 8856 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8857 | } | ||
| 8858 | 9145 | ||
| 8859 | update_errors_helper(ira->codegen, &errors, &errors_count); | 9146 | update_errors_helper(ira->codegen, &errors, &errors_count); |
| 8860 | 9147 | ||
| ... | @@ -8986,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -8986,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8986 | continue; | 9273 | continue; |
| 8987 | } | 9274 | } |
| 8988 | 9275 | ||
| 9276 | if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC && | ||
| 9277 | (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt)) | ||
| 9278 | { | ||
| 9279 | continue; | ||
| 9280 | } | ||
| 9281 | |||
| 9282 | if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC && | ||
| 9283 | (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt)) | ||
| 9284 | { | ||
| 9285 | prev_inst = cur_inst; | ||
| 9286 | continue; | ||
| 9287 | } | ||
| 9288 | |||
| 9289 | if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) { | ||
| 9290 | if (prev_type->data.pointer.ptr_len == PtrLenC && | ||
| 9291 | types_match_const_cast_only(ira, prev_type->data.pointer.child_type, | ||
| 9292 | cur_type->data.pointer.child_type, source_node, | ||
| 9293 | !prev_type->data.pointer.is_const).id == ConstCastResultIdOk) | ||
| 9294 | { | ||
| 9295 | continue; | ||
| 9296 | } | ||
| 9297 | if (cur_type->data.pointer.ptr_len == PtrLenC && | ||
| 9298 | types_match_const_cast_only(ira, cur_type->data.pointer.child_type, | ||
| 9299 | prev_type->data.pointer.child_type, source_node, | ||
| 9300 | !cur_type->data.pointer.is_const).id == ConstCastResultIdOk) | ||
| 9301 | { | ||
| 9302 | prev_inst = cur_inst; | ||
| 9303 | continue; | ||
| 9304 | } | ||
| 9305 | } | ||
| 9306 | |||
| 8989 | if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) { | 9307 | if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) { |
| 8990 | continue; | 9308 | continue; |
| 8991 | } | 9309 | } |
| ... | @@ -9292,7 +9610,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -9292,7 +9610,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9292 | const_val->type = new_type; | 9610 | const_val->type = new_type; |
| 9293 | break; | 9611 | break; |
| 9294 | case CastOpResizeSlice: | 9612 | case CastOpResizeSlice: |
| 9295 | case CastOpBytesToSlice: | ||
| 9296 | // can't do it | 9613 | // can't do it |
| 9297 | zig_unreachable(); | 9614 | zig_unreachable(); |
| 9298 | case CastOpIntToFloat: | 9615 | case CastOpIntToFloat: |
| ... | @@ -9345,14 +9662,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -9345,14 +9662,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9345 | } | 9662 | } |
| 9346 | return true; | 9663 | return true; |
| 9347 | } | 9664 | } |
| 9348 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | 9665 | |
| 9349 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) | 9666 | static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { |
| 9350 | { | 9667 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9668 | old_instruction->scope, old_instruction->source_node); | ||
| 9669 | IrInstruction *new_instruction = &const_instruction->base; | ||
| 9670 | new_instruction->value.type = ty; | ||
| 9671 | new_instruction->value.special = ConstValSpecialStatic; | ||
| 9672 | return new_instruction; | ||
| 9673 | } | ||
| 9674 | |||
| 9675 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | ||
| 9676 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) | ||
| 9677 | { | ||
| 9351 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && | 9678 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && |
| 9352 | cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice) | 9679 | cast_op != CastOpResizeSlice) |
| 9353 | { | 9680 | { |
| 9354 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 9681 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9355 | source_instr->source_node, wanted_type); | ||
| 9356 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, | 9682 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, |
| 9357 | &result->value, wanted_type)) | 9683 | &result->value, wanted_type)) |
| 9358 | { | 9684 | { |
| ... | @@ -9385,13 +9711,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, | ... | @@ -9385,13 +9711,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, |
| 9385 | wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type)); | 9711 | wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type)); |
| 9386 | 9712 | ||
| 9387 | if (instr_is_comptime(value)) { | 9713 | if (instr_is_comptime(value)) { |
| 9388 | ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node); | 9714 | ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node); |
| 9389 | if (pointee == nullptr) | 9715 | if (pointee == nullptr) |
| 9390 | return ira->codegen->invalid_instruction; | 9716 | return ira->codegen->invalid_instruction; |
| 9391 | if (pointee->special != ConstValSpecialRuntime) { | 9717 | if (pointee->special != ConstValSpecialRuntime) { |
| 9392 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 9718 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9393 | source_instr->source_node, wanted_type); | ||
| 9394 | result->value.type = wanted_type; | ||
| 9395 | result->value.data.x_ptr.special = ConstPtrSpecialBaseArray; | 9719 | result->value.data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 9396 | result->value.data.x_ptr.mut = value->value.data.x_ptr.mut; | 9720 | result->value.data.x_ptr.mut = value->value.data.x_ptr.mut; |
| 9397 | result->value.data.x_ptr.data.base_array.array_val = pointee; | 9721 | result->value.data.x_ptr.data.base_array.array_val = pointee; |
| ... | @@ -9421,7 +9745,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc | ... | @@ -9421,7 +9745,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc |
| 9421 | wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type)); | 9745 | wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type)); |
| 9422 | 9746 | ||
| 9423 | if (instr_is_comptime(value)) { | 9747 | if (instr_is_comptime(value)) { |
| 9424 | ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node); | 9748 | ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node); |
| 9425 | if (pointee == nullptr) | 9749 | if (pointee == nullptr) |
| 9426 | return ira->codegen->invalid_instruction; | 9750 | return ira->codegen->invalid_instruction; |
| 9427 | if (pointee->special != ConstValSpecialRuntime) { | 9751 | if (pointee->special != ConstValSpecialRuntime) { |
| ... | @@ -9430,8 +9754,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc | ... | @@ -9430,8 +9754,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc |
| 9430 | assert(is_slice(wanted_type)); | 9754 | assert(is_slice(wanted_type)); |
| 9431 | bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; | 9755 | bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; |
| 9432 | 9756 | ||
| 9433 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 9757 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9434 | source_instr->source_node, wanted_type); | ||
| 9435 | init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const); | 9758 | init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const); |
| 9436 | result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = | 9759 | result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = |
| 9437 | value->value.data.x_ptr.mut; | 9760 | value->value.data.x_ptr.mut; |
| ... | @@ -9566,15 +9889,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction) | ... | @@ -9566,15 +9889,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction) |
| 9566 | return instruction; | 9889 | return instruction; |
| 9567 | } | 9890 | } |
| 9568 | 9891 | ||
| 9569 | static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { | ||
| 9570 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | ||
| 9571 | old_instruction->scope, old_instruction->source_node); | ||
| 9572 | IrInstruction *new_instruction = &const_instruction->base; | ||
| 9573 | new_instruction->value.type = ty; | ||
| 9574 | new_instruction->value.special = ConstValSpecialStatic; | ||
| 9575 | return new_instruction; | ||
| 9576 | } | ||
| 9577 | |||
| 9578 | static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { | 9892 | static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { |
| 9579 | IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type); | 9893 | IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type); |
| 9580 | result->value.data.x_type = ty; | 9894 | result->value.data.x_type = ty; |
| ... | @@ -9625,20 +9939,20 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un | ... | @@ -9625,20 +9939,20 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un |
| 9625 | if (undef_allowed == UndefOk) { | 9939 | if (undef_allowed == UndefOk) { |
| 9626 | return &value->value; | 9940 | return &value->value; |
| 9627 | } else { | 9941 | } else { |
| 9628 | ir_add_error(ira, value, buf_sprintf("use of undefined value")); | 9942 | ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior")); |
| 9629 | return nullptr; | 9943 | return nullptr; |
| 9630 | } | 9944 | } |
| 9631 | } | 9945 | } |
| 9632 | zig_unreachable(); | 9946 | zig_unreachable(); |
| 9633 | } | 9947 | } |
| 9634 | 9948 | ||
| 9635 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | 9949 | ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 9636 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, | 9950 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 9637 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, | 9951 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 9638 | IrExecutable *parent_exec) | 9952 | IrExecutable *parent_exec, AstNode *expected_type_source_node) |
| 9639 | { | 9953 | { |
| 9640 | if (expected_type != nullptr && type_is_invalid(expected_type)) | 9954 | if (expected_type != nullptr && type_is_invalid(expected_type)) |
| 9641 | return codegen->invalid_instruction; | 9955 | return &codegen->invalid_instruction->value; |
| 9642 | 9956 | ||
| 9643 | IrExecutable *ir_executable = allocate<IrExecutable>(1); | 9957 | IrExecutable *ir_executable = allocate<IrExecutable>(1); |
| 9644 | ir_executable->source_node = source_node; | 9958 | ir_executable->source_node = source_node; |
| ... | @@ -9651,13 +9965,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node | ... | @@ -9651,13 +9965,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 9651 | ir_gen(codegen, node, scope, ir_executable); | 9965 | ir_gen(codegen, node, scope, ir_executable); |
| 9652 | 9966 | ||
| 9653 | if (ir_executable->invalid) | 9967 | if (ir_executable->invalid) |
| 9654 | return codegen->invalid_instruction; | 9968 | return &codegen->invalid_instruction->value; |
| 9655 | 9969 | ||
| 9656 | if (codegen->verbose_ir) { | 9970 | if (codegen->verbose_ir) { |
| 9657 | fprintf(stderr, "\nSource: "); | 9971 | fprintf(stderr, "\nSource: "); |
| 9658 | ast_render(codegen, stderr, node, 4); | 9972 | ast_render(codegen, stderr, node, 4); |
| 9659 | fprintf(stderr, "\n{ // (IR)\n"); | 9973 | fprintf(stderr, "\n{ // (IR)\n"); |
| 9660 | ir_print(codegen, stderr, ir_executable, 4); | 9974 | ir_print(codegen, stderr, ir_executable, 2); |
| 9661 | fprintf(stderr, "}\n"); | 9975 | fprintf(stderr, "}\n"); |
| 9662 | } | 9976 | } |
| 9663 | IrExecutable *analyzed_executable = allocate<IrExecutable>(1); | 9977 | IrExecutable *analyzed_executable = allocate<IrExecutable>(1); |
| ... | @@ -9671,13 +9985,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node | ... | @@ -9671,13 +9985,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 9671 | analyzed_executable->backward_branch_count = backward_branch_count; | 9985 | analyzed_executable->backward_branch_count = backward_branch_count; |
| 9672 | analyzed_executable->backward_branch_quota = backward_branch_quota; | 9986 | analyzed_executable->backward_branch_quota = backward_branch_quota; |
| 9673 | analyzed_executable->begin_scope = scope; | 9987 | analyzed_executable->begin_scope = scope; |
| 9674 | ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node); | 9988 | ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node); |
| 9675 | if (type_is_invalid(result_type)) | 9989 | if (type_is_invalid(result_type)) |
| 9676 | return codegen->invalid_instruction; | 9990 | return &codegen->invalid_instruction->value; |
| 9677 | 9991 | ||
| 9678 | if (codegen->verbose_ir) { | 9992 | if (codegen->verbose_ir) { |
| 9679 | fprintf(stderr, "{ // (analyzed)\n"); | 9993 | fprintf(stderr, "{ // (analyzed)\n"); |
| 9680 | ir_print(codegen, stderr, analyzed_executable, 4); | 9994 | ir_print(codegen, stderr, analyzed_executable, 2); |
| 9681 | fprintf(stderr, "}\n"); | 9995 | fprintf(stderr, "}\n"); |
| 9682 | } | 9996 | } |
| 9683 | 9997 | ||
| ... | @@ -9702,6 +10016,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { | ... | @@ -9702,6 +10016,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| 9702 | return const_val->data.x_type; | 10016 | return const_val->data.x_type; |
| 9703 | } | 10017 | } |
| 9704 | 10018 | ||
| 10019 | static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { | ||
| 10020 | if (type_is_invalid(type_value->value.type)) | ||
| 10021 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10022 | |||
| 10023 | if (type_value->value.type->id != ZigTypeIdMetaType) { | ||
| 10024 | ErrorMsg *msg = ir_add_error(ira, type_value, | ||
| 10025 | buf_sprintf("expected error set type, found '%s'", buf_ptr(&type_value->value.type->name))); | ||
| 10026 | add_error_note(ira->codegen, msg, op_source->source_node, | ||
| 10027 | buf_sprintf("`||` merges error sets; `or` performs boolean OR")); | ||
| 10028 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10029 | } | ||
| 10030 | |||
| 10031 | ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad); | ||
| 10032 | if (!const_val) | ||
| 10033 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10034 | |||
| 10035 | assert(const_val->data.x_type != nullptr); | ||
| 10036 | ZigType *result_type = const_val->data.x_type; | ||
| 10037 | if (result_type->id != ZigTypeIdErrorSet) { | ||
| 10038 | ErrorMsg *msg = ir_add_error(ira, type_value, | ||
| 10039 | buf_sprintf("expected error set type, found type '%s'", buf_ptr(&result_type->name))); | ||
| 10040 | add_error_note(ira->codegen, msg, op_source->source_node, | ||
| 10041 | buf_sprintf("`||` merges error sets; `or` performs boolean OR")); | ||
| 10042 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10043 | } | ||
| 10044 | return result_type; | ||
| 10045 | } | ||
| 10046 | |||
| 9705 | static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { | 10047 | static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 9706 | if (fn_value == ira->codegen->invalid_instruction) | 10048 | if (fn_value == ira->codegen->invalid_instruction) |
| 9707 | return nullptr; | 10049 | return nullptr; |
| ... | @@ -9723,7 +10065,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { | ... | @@ -9723,7 +10065,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 9723 | return const_val->data.x_ptr.data.fn.fn_entry; | 10065 | return const_val->data.x_ptr.data.fn.fn_entry; |
| 9724 | } | 10066 | } |
| 9725 | 10067 | ||
| 9726 | static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) { | 10068 | static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 10069 | ZigType *wanted_type) | ||
| 10070 | { | ||
| 9727 | assert(wanted_type->id == ZigTypeIdOptional); | 10071 | assert(wanted_type->id == ZigTypeIdOptional); |
| 9728 | 10072 | ||
| 9729 | if (instr_is_comptime(value)) { | 10073 | if (instr_is_comptime(value)) { |
| ... | @@ -9739,7 +10083,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -9739,7 +10083,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc |
| 9739 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | 10083 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9740 | source_instr->scope, source_instr->source_node); | 10084 | source_instr->scope, source_instr->source_node); |
| 9741 | const_instruction->base.value.special = ConstValSpecialStatic; | 10085 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9742 | if (get_codegen_ptr_type(wanted_type) != nullptr) { | 10086 | if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) { |
| 9743 | copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst); | 10087 | copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst); |
| 9744 | } else { | 10088 | } else { |
| 9745 | const_instruction->base.value.data.x_optional = val; | 10089 | const_instruction->base.value.data.x_optional = val; |
| ... | @@ -9770,11 +10114,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction | ... | @@ -9770,11 +10114,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 9770 | if (!val) | 10114 | if (!val) |
| 9771 | return ira->codegen->invalid_instruction; | 10115 | return ira->codegen->invalid_instruction; |
| 9772 | 10116 | ||
| 10117 | ConstExprValue *err_set_val = create_const_vals(1); | ||
| 10118 | err_set_val->type = wanted_type->data.error_union.err_set_type; | ||
| 10119 | err_set_val->special = ConstValSpecialStatic; | ||
| 10120 | err_set_val->data.x_err_set = nullptr; | ||
| 10121 | |||
| 9773 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | 10122 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9774 | source_instr->scope, source_instr->source_node); | 10123 | source_instr->scope, source_instr->source_node); |
| 9775 | const_instruction->base.value.type = wanted_type; | 10124 | const_instruction->base.value.type = wanted_type; |
| 9776 | const_instruction->base.value.special = ConstValSpecialStatic; | 10125 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9777 | const_instruction->base.value.data.x_err_union.err = nullptr; | 10126 | const_instruction->base.value.data.x_err_union.error_set = err_set_val; |
| 9778 | const_instruction->base.value.data.x_err_union.payload = val; | 10127 | const_instruction->base.value.data.x_err_union.payload = val; |
| 9779 | return &const_instruction->base; | 10128 | return &const_instruction->base; |
| 9780 | } | 10129 | } |
| ... | @@ -9839,11 +10188,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so | ... | @@ -9839,11 +10188,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 9839 | if (!val) | 10188 | if (!val) |
| 9840 | return ira->codegen->invalid_instruction; | 10189 | return ira->codegen->invalid_instruction; |
| 9841 | 10190 | ||
| 10191 | ConstExprValue *err_set_val = create_const_vals(1); | ||
| 10192 | err_set_val->special = ConstValSpecialStatic; | ||
| 10193 | err_set_val->type = wanted_type->data.error_union.err_set_type; | ||
| 10194 | err_set_val->data.x_err_set = val->data.x_err_set; | ||
| 10195 | |||
| 9842 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | 10196 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9843 | source_instr->scope, source_instr->source_node); | 10197 | source_instr->scope, source_instr->source_node); |
| 9844 | const_instruction->base.value.type = wanted_type; | 10198 | const_instruction->base.value.type = wanted_type; |
| 9845 | const_instruction->base.value.special = ConstValSpecialStatic; | 10199 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9846 | const_instruction->base.value.data.x_err_union.err = val->data.x_err_set; | 10200 | const_instruction->base.value.data.x_err_union.error_set = err_set_val; |
| 9847 | const_instruction->base.value.data.x_err_union.payload = nullptr; | 10201 | const_instruction->base.value.data.x_err_union.payload = nullptr; |
| 9848 | return &const_instruction->base; | 10202 | return &const_instruction->base; |
| 9849 | } | 10203 | } |
| ... | @@ -9865,8 +10219,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so | ... | @@ -9865,8 +10219,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so |
| 9865 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); | 10219 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 9866 | const_instruction->base.value.special = ConstValSpecialStatic; | 10220 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9867 | if (get_codegen_ptr_type(wanted_type) != nullptr) { | 10221 | if (get_codegen_ptr_type(wanted_type) != nullptr) { |
| 9868 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 10222 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull; |
| 9869 | const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0; | 10223 | } else if (is_opt_err_set(wanted_type)) { |
| 10224 | const_instruction->base.value.data.x_err_set = nullptr; | ||
| 9870 | } else { | 10225 | } else { |
| 9871 | const_instruction->base.value.data.x_optional = nullptr; | 10226 | const_instruction->base.value.data.x_optional = nullptr; |
| 9872 | } | 10227 | } |
| ... | @@ -9899,7 +10254,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi | ... | @@ -9899,7 +10254,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 9899 | source_instruction->source_node, value, is_const, is_volatile); | 10254 | source_instruction->source_node, value, is_const, is_volatile); |
| 9900 | new_instruction->value.type = ptr_type; | 10255 | new_instruction->value.type = ptr_type; |
| 9901 | new_instruction->value.data.rh_ptr = RuntimeHintPtrStack; | 10256 | new_instruction->value.data.rh_ptr = RuntimeHintPtrStack; |
| 9902 | if (type_has_bits(ptr_type)) { | 10257 | if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) { |
| 9903 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); | 10258 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 9904 | assert(fn_entry); | 10259 | assert(fn_entry); |
| 9905 | fn_entry->alloca_list.append(new_instruction); | 10260 | fn_entry->alloca_list.append(new_instruction); |
| ... | @@ -9925,20 +10280,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s | ... | @@ -9925,20 +10280,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 9925 | ZigType *array_type = array->value.type; | 10280 | ZigType *array_type = array->value.type; |
| 9926 | assert(array_type->id == ZigTypeIdArray); | 10281 | assert(array_type->id == ZigTypeIdArray); |
| 9927 | 10282 | ||
| 9928 | if (instr_is_comptime(array)) { | 10283 | if (instr_is_comptime(array) || array_type->data.array.len == 0) { |
| 9929 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10284 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9930 | source_instr->source_node, wanted_type); | ||
| 9931 | init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true); | 10285 | init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true); |
| 9932 | result->value.type = wanted_type; | 10286 | result->value.type = wanted_type; |
| 9933 | return result; | 10287 | return result; |
| 9934 | } | 10288 | } |
| 9935 | 10289 | ||
| 9936 | IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope, | 10290 | IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize); |
| 9937 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); | ||
| 9938 | init_const_usize(ira->codegen, &start->value, 0); | 10291 | init_const_usize(ira->codegen, &start->value, 0); |
| 9939 | 10292 | ||
| 9940 | IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope, | 10293 | IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize); |
| 9941 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); | ||
| 9942 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); | 10294 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); |
| 9943 | 10295 | ||
| 9944 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); | 10296 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| ... | @@ -9977,8 +10329,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour | ... | @@ -9977,8 +10329,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 9977 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 10329 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 9978 | if (!val) | 10330 | if (!val) |
| 9979 | return ira->codegen->invalid_instruction; | 10331 | return ira->codegen->invalid_instruction; |
| 9980 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10332 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9981 | source_instr->source_node, wanted_type); | ||
| 9982 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); | 10333 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); |
| 9983 | return result; | 10334 | return result; |
| 9984 | } | 10335 | } |
| ... | @@ -9988,8 +10339,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour | ... | @@ -9988,8 +10339,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 9988 | actual_type->data.enumeration.src_field_count == 1) | 10339 | actual_type->data.enumeration.src_field_count == 1) |
| 9989 | { | 10340 | { |
| 9990 | assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int); | 10341 | assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int); |
| 9991 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10342 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9992 | source_instr->source_node, wanted_type); | ||
| 9993 | init_const_bigint(&result->value, wanted_type, | 10343 | init_const_bigint(&result->value, wanted_type, |
| 9994 | &actual_type->data.enumeration.fields[0].value); | 10344 | &actual_type->data.enumeration.fields[0].value); |
| 9995 | return result; | 10345 | return result; |
| ... | @@ -10012,8 +10362,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou | ... | @@ -10012,8 +10362,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou |
| 10012 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 10362 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 10013 | if (!val) | 10363 | if (!val) |
| 10014 | return ira->codegen->invalid_instruction; | 10364 | return ira->codegen->invalid_instruction; |
| 10015 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10365 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10016 | source_instr->source_node, wanted_type); | ||
| 10017 | result->value.special = ConstValSpecialStatic; | 10366 | result->value.special = ConstValSpecialStatic; |
| 10018 | result->value.type = wanted_type; | 10367 | result->value.type = wanted_type; |
| 10019 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag); | 10368 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag); |
| ... | @@ -10024,8 +10373,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou | ... | @@ -10024,8 +10373,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou |
| 10024 | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && | 10373 | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && |
| 10025 | wanted_type->data.enumeration.src_field_count == 1) | 10374 | wanted_type->data.enumeration.src_field_count == 1) |
| 10026 | { | 10375 | { |
| 10027 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10376 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10028 | source_instr->source_node, wanted_type); | ||
| 10029 | result->value.special = ConstValSpecialStatic; | 10377 | result->value.special = ConstValSpecialStatic; |
| 10030 | result->value.type = wanted_type; | 10378 | result->value.type = wanted_type; |
| 10031 | TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field; | 10379 | TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field; |
| ... | @@ -10042,8 +10390,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou | ... | @@ -10042,8 +10390,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou |
| 10042 | static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, | 10390 | static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, |
| 10043 | IrInstruction *target, ZigType *wanted_type) | 10391 | IrInstruction *target, ZigType *wanted_type) |
| 10044 | { | 10392 | { |
| 10045 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10393 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10046 | source_instr->source_node, wanted_type); | ||
| 10047 | init_const_undefined(ira->codegen, &result->value); | 10394 | init_const_undefined(ira->codegen, &result->value); |
| 10048 | return result; | 10395 | return result; |
| 10049 | } | 10396 | } |
| ... | @@ -10075,8 +10422,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so | ... | @@ -10075,8 +10422,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so |
| 10075 | buf_sprintf("field '%s' declared here", buf_ptr(union_field->name))); | 10422 | buf_sprintf("field '%s' declared here", buf_ptr(union_field->name))); |
| 10076 | return ira->codegen->invalid_instruction; | 10423 | return ira->codegen->invalid_instruction; |
| 10077 | } | 10424 | } |
| 10078 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10425 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10079 | source_instr->source_node, wanted_type); | ||
| 10080 | result->value.special = ConstValSpecialStatic; | 10426 | result->value.special = ConstValSpecialStatic; |
| 10081 | result->value.type = wanted_type; | 10427 | result->value.type = wanted_type; |
| 10082 | bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag); | 10428 | bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag); |
| ... | @@ -10131,8 +10477,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction | ... | @@ -10131,8 +10477,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction |
| 10131 | return ira->codegen->invalid_instruction; | 10477 | return ira->codegen->invalid_instruction; |
| 10132 | } | 10478 | } |
| 10133 | } | 10479 | } |
| 10134 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10480 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10135 | source_instr->source_node, wanted_type); | ||
| 10136 | result->value.type = wanted_type; | 10481 | result->value.type = wanted_type; |
| 10137 | if (wanted_type->id == ZigTypeIdInt) { | 10482 | if (wanted_type->id == ZigTypeIdInt) { |
| 10138 | bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint); | 10483 | bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint); |
| ... | @@ -10142,6 +10487,18 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction | ... | @@ -10142,6 +10487,18 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction |
| 10142 | return result; | 10487 | return result; |
| 10143 | } | 10488 | } |
| 10144 | 10489 | ||
| 10490 | // If the destination integer type has no bits, then we can emit a comptime | ||
| 10491 | // zero. However, we still want to emit a runtime safety check to make sure | ||
| 10492 | // the target is zero. | ||
| 10493 | if (!type_has_bits(wanted_type)) { | ||
| 10494 | assert(wanted_type->id == ZigTypeIdInt); | ||
| 10495 | assert(type_has_bits(target->value.type)); | ||
| 10496 | ir_build_assert_zero(ira, source_instr, target); | ||
| 10497 | IrInstruction *result = ir_const_unsigned(ira, source_instr, 0); | ||
| 10498 | result->value.type = wanted_type; | ||
| 10499 | return result; | ||
| 10500 | } | ||
| 10501 | |||
| 10145 | IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, | 10502 | IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, |
| 10146 | source_instr->source_node, target); | 10503 | source_instr->source_node, target); |
| 10147 | result->value.type = wanted_type; | 10504 | result->value.type = wanted_type; |
| ... | @@ -10186,8 +10543,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -10186,8 +10543,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 10186 | return ira->codegen->invalid_instruction; | 10543 | return ira->codegen->invalid_instruction; |
| 10187 | } | 10544 | } |
| 10188 | 10545 | ||
| 10189 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10546 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10190 | source_instr->source_node, wanted_type); | ||
| 10191 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint); | 10547 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint); |
| 10192 | return result; | 10548 | return result; |
| 10193 | } | 10549 | } |
| ... | @@ -10205,8 +10561,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction | ... | @@ -10205,8 +10561,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction |
| 10205 | if (!val) | 10561 | if (!val) |
| 10206 | return ira->codegen->invalid_instruction; | 10562 | return ira->codegen->invalid_instruction; |
| 10207 | 10563 | ||
| 10208 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10564 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10209 | source_instr->source_node, wanted_type); | ||
| 10210 | if (wanted_type->id == ZigTypeIdComptimeFloat) { | 10565 | if (wanted_type->id == ZigTypeIdComptimeFloat) { |
| 10211 | float_init_float(&result->value, val); | 10566 | float_init_float(&result->value, val); |
| 10212 | } else if (wanted_type->id == ZigTypeIdComptimeInt) { | 10567 | } else if (wanted_type->id == ZigTypeIdComptimeInt) { |
| ... | @@ -10229,8 +10584,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -10229,8 +10584,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc |
| 10229 | if (!val) | 10584 | if (!val) |
| 10230 | return ira->codegen->invalid_instruction; | 10585 | return ira->codegen->invalid_instruction; |
| 10231 | 10586 | ||
| 10232 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10587 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10233 | source_instr->source_node, wanted_type); | ||
| 10234 | 10588 | ||
| 10235 | if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) { | 10589 | if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) { |
| 10236 | return ira->codegen->invalid_instruction; | 10590 | return ira->codegen->invalid_instruction; |
| ... | @@ -10294,12 +10648,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -10294,12 +10648,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 10294 | if (!val) | 10648 | if (!val) |
| 10295 | return ira->codegen->invalid_instruction; | 10649 | return ira->codegen->invalid_instruction; |
| 10296 | 10650 | ||
| 10297 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10651 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10298 | source_instr->source_node, wanted_type); | ||
| 10299 | 10652 | ||
| 10300 | ErrorTableEntry *err; | 10653 | ErrorTableEntry *err; |
| 10301 | if (err_type->id == ZigTypeIdErrorUnion) { | 10654 | if (err_type->id == ZigTypeIdErrorUnion) { |
| 10302 | err = val->data.x_err_union.err; | 10655 | err = val->data.x_err_union.error_set->data.x_err_set; |
| 10303 | } else if (err_type->id == ZigTypeIdErrorSet) { | 10656 | } else if (err_type->id == ZigTypeIdErrorSet) { |
| 10304 | err = val->data.x_err_set; | 10657 | err = val->data.x_err_set; |
| 10305 | } else { | 10658 | } else { |
| ... | @@ -10334,15 +10687,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -10334,15 +10687,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 10334 | return ira->codegen->invalid_instruction; | 10687 | return ira->codegen->invalid_instruction; |
| 10335 | } | 10688 | } |
| 10336 | if (err_set_type->data.error_set.err_count == 0) { | 10689 | if (err_set_type->data.error_set.err_count == 0) { |
| 10337 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10690 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10338 | source_instr->source_node, wanted_type); | ||
| 10339 | result->value.type = wanted_type; | ||
| 10340 | bigint_init_unsigned(&result->value.data.x_bigint, 0); | 10691 | bigint_init_unsigned(&result->value.data.x_bigint, 0); |
| 10341 | return result; | 10692 | return result; |
| 10342 | } else if (err_set_type->data.error_set.err_count == 1) { | 10693 | } else if (err_set_type->data.error_set.err_count == 1) { |
| 10343 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 10694 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10344 | source_instr->source_node, wanted_type); | ||
| 10345 | result->value.type = wanted_type; | ||
| 10346 | ErrorTableEntry *err = err_set_type->data.error_set.errors[0]; | 10695 | ErrorTableEntry *err = err_set_type->data.error_set.errors[0]; |
| 10347 | bigint_init_unsigned(&result->value.data.x_bigint, err->value); | 10696 | bigint_init_unsigned(&result->value.data.x_bigint, err->value); |
| 10348 | return result; | 10697 | return result; |
| ... | @@ -10380,7 +10729,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou | ... | @@ -10380,7 +10729,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou |
| 10380 | return ira->codegen->invalid_instruction; | 10729 | return ira->codegen->invalid_instruction; |
| 10381 | 10730 | ||
| 10382 | assert(val->type->id == ZigTypeIdPointer); | 10731 | assert(val->type->id == ZigTypeIdPointer); |
| 10383 | ConstExprValue *pointee = ir_const_ptr_pointee(ira, val, source_instr->source_node); | 10732 | ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); |
| 10384 | if (pointee == nullptr) | 10733 | if (pointee == nullptr) |
| 10385 | return ira->codegen->invalid_instruction; | 10734 | return ira->codegen->invalid_instruction; |
| 10386 | if (pointee->special != ConstValSpecialRuntime) { | 10735 | if (pointee->special != ConstValSpecialRuntime) { |
| ... | @@ -10389,8 +10738,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou | ... | @@ -10389,8 +10738,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou |
| 10389 | array_val->type = array_type; | 10738 | array_val->type = array_type; |
| 10390 | array_val->data.x_array.special = ConstArraySpecialNone; | 10739 | array_val->data.x_array.special = ConstArraySpecialNone; |
| 10391 | array_val->data.x_array.data.s_none.elements = pointee; | 10740 | array_val->data.x_array.data.s_none.elements = pointee; |
| 10392 | array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar; | 10741 | array_val->parent.id = ConstParentIdScalar; |
| 10393 | array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee; | 10742 | array_val->parent.data.p_scalar.scalar_val = pointee; |
| 10394 | 10743 | ||
| 10395 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | 10744 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 10396 | source_instr->scope, source_instr->source_node); | 10745 | source_instr->scope, source_instr->source_node); |
| ... | @@ -10496,21 +10845,100 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa | ... | @@ -10496,21 +10845,100 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10496 | report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg); | 10845 | report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg); |
| 10497 | break; | 10846 | break; |
| 10498 | } | 10847 | } |
| 10848 | case ConstCastResultIdBadAllowsZero: { | ||
| 10849 | ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type; | ||
| 10850 | ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type; | ||
| 10851 | bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type); | ||
| 10852 | bool actual_allows_zero = ptr_allows_addr_zero(actual_type); | ||
| 10853 | if (actual_allows_zero && !wanted_allows_zero) { | ||
| 10854 | add_error_note(ira->codegen, parent_msg, source_node, | ||
| 10855 | buf_sprintf("'%s' could have null values which are illegal in type '%s'", | ||
| 10856 | buf_ptr(&actual_type->name), | ||
| 10857 | buf_ptr(&wanted_type->name))); | ||
| 10858 | } else { | ||
| 10859 | add_error_note(ira->codegen, parent_msg, source_node, | ||
| 10860 | buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'", | ||
| 10861 | buf_ptr(&wanted_type->name), | ||
| 10862 | buf_ptr(&actual_type->name))); | ||
| 10863 | } | ||
| 10864 | break; | ||
| 10865 | } | ||
| 10866 | case ConstCastResultIdFnIsGeneric: | ||
| 10867 | add_error_note(ira->codegen, parent_msg, source_node, | ||
| 10868 | buf_sprintf("only one of the functions is generic")); | ||
| 10869 | break; | ||
| 10499 | case ConstCastResultIdFnAlign: // TODO | 10870 | case ConstCastResultIdFnAlign: // TODO |
| 10500 | case ConstCastResultIdFnCC: // TODO | 10871 | case ConstCastResultIdFnCC: // TODO |
| 10501 | case ConstCastResultIdFnVarArgs: // TODO | 10872 | case ConstCastResultIdFnVarArgs: // TODO |
| 10502 | case ConstCastResultIdFnIsGeneric: // TODO | ||
| 10503 | case ConstCastResultIdFnReturnType: // TODO | 10873 | case ConstCastResultIdFnReturnType: // TODO |
| 10504 | case ConstCastResultIdFnArgCount: // TODO | 10874 | case ConstCastResultIdFnArgCount: // TODO |
| 10505 | case ConstCastResultIdFnGenericArgCount: // TODO | 10875 | case ConstCastResultIdFnGenericArgCount: // TODO |
| 10506 | case ConstCastResultIdFnArgNoAlias: // TODO | 10876 | case ConstCastResultIdFnArgNoAlias: // TODO |
| 10507 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO | 10877 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO |
| 10508 | case ConstCastResultIdAsyncAllocatorType: // TODO | 10878 | case ConstCastResultIdAsyncAllocatorType: // TODO |
| 10509 | case ConstCastResultIdNullWrapPtr: // TODO | ||
| 10510 | break; | 10879 | break; |
| 10511 | } | 10880 | } |
| 10512 | } | 10881 | } |
| 10513 | 10882 | ||
| 10883 | static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 10884 | IrInstruction *array, ZigType *vector_type) | ||
| 10885 | { | ||
| 10886 | if (instr_is_comptime(array)) { | ||
| 10887 | // arrays and vectors have the same ConstExprValue representation | ||
| 10888 | IrInstruction *result = ir_const(ira, source_instr, vector_type); | ||
| 10889 | copy_const_val(&result->value, &array->value, false); | ||
| 10890 | result->value.type = vector_type; | ||
| 10891 | return result; | ||
| 10892 | } | ||
| 10893 | return ir_build_array_to_vector(ira, source_instr, array, vector_type); | ||
| 10894 | } | ||
| 10895 | |||
| 10896 | static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 10897 | IrInstruction *vector, ZigType *array_type) | ||
| 10898 | { | ||
| 10899 | if (instr_is_comptime(vector)) { | ||
| 10900 | // arrays and vectors have the same ConstExprValue representation | ||
| 10901 | IrInstruction *result = ir_const(ira, source_instr, array_type); | ||
| 10902 | copy_const_val(&result->value, &vector->value, false); | ||
| 10903 | result->value.type = array_type; | ||
| 10904 | return result; | ||
| 10905 | } | ||
| 10906 | return ir_build_vector_to_array(ira, source_instr, vector, array_type); | ||
| 10907 | } | ||
| 10908 | |||
| 10909 | static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 10910 | IrInstruction *integer, ZigType *dest_type) | ||
| 10911 | { | ||
| 10912 | IrInstruction *unsigned_integer; | ||
| 10913 | if (instr_is_comptime(integer)) { | ||
| 10914 | unsigned_integer = integer; | ||
| 10915 | } else { | ||
| 10916 | assert(integer->value.type->id == ZigTypeIdInt); | ||
| 10917 | |||
| 10918 | if (integer->value.type->data.integral.bit_count > | ||
| 10919 | ira->codegen->builtin_types.entry_usize->data.integral.bit_count) | ||
| 10920 | { | ||
| 10921 | ir_add_error(ira, source_instr, | ||
| 10922 | buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'", | ||
| 10923 | buf_ptr(&integer->value.type->name), | ||
| 10924 | buf_ptr(&dest_type->name))); | ||
| 10925 | return ira->codegen->invalid_instruction; | ||
| 10926 | } | ||
| 10927 | |||
| 10928 | if (integer->value.type->data.integral.is_signed) { | ||
| 10929 | ZigType *unsigned_int_type = get_int_type(ira->codegen, false, | ||
| 10930 | integer->value.type->data.integral.bit_count); | ||
| 10931 | unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type); | ||
| 10932 | if (type_is_invalid(unsigned_integer->value.type)) | ||
| 10933 | return ira->codegen->invalid_instruction; | ||
| 10934 | } else { | ||
| 10935 | unsigned_integer = integer; | ||
| 10936 | } | ||
| 10937 | } | ||
| 10938 | |||
| 10939 | return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type); | ||
| 10940 | } | ||
| 10941 | |||
| 10514 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 10942 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 10515 | ZigType *wanted_type, IrInstruction *value) | 10943 | ZigType *wanted_type, IrInstruction *value) |
| 10516 | { | 10944 | { |
| ... | @@ -10538,12 +10966,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10538,12 +10966,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10538 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, | 10966 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, |
| 10539 | false).id == ConstCastResultIdOk) | 10967 | false).id == ConstCastResultIdOk) |
| 10540 | { | 10968 | { |
| 10541 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | 10969 | return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type); |
| 10542 | } else if (actual_type->id == ZigTypeIdComptimeInt || | 10970 | } else if (actual_type->id == ZigTypeIdComptimeInt || |
| 10543 | actual_type->id == ZigTypeIdComptimeFloat) | 10971 | actual_type->id == ZigTypeIdComptimeFloat) |
| 10544 | { | 10972 | { |
| 10545 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { | 10973 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { |
| 10546 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | 10974 | return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type); |
| 10547 | } else { | 10975 | } else { |
| 10548 | return ira->codegen->invalid_instruction; | 10976 | return ira->codegen->invalid_instruction; |
| 10549 | } | 10977 | } |
| ... | @@ -10567,7 +10995,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10567,7 +10995,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10567 | wanted_child_type); | 10995 | wanted_child_type); |
| 10568 | if (type_is_invalid(cast1->value.type)) | 10996 | if (type_is_invalid(cast1->value.type)) |
| 10569 | return ira->codegen->invalid_instruction; | 10997 | return ira->codegen->invalid_instruction; |
| 10570 | return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); | 10998 | return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type); |
| 10571 | } | 10999 | } |
| 10572 | } | 11000 | } |
| 10573 | } | 11001 | } |
| ... | @@ -10620,6 +11048,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10620,6 +11048,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10620 | (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt || | 11048 | (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt || |
| 10621 | wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) | 11049 | wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) |
| 10622 | { | 11050 | { |
| 11051 | if (value->value.special == ConstValSpecialUndef) { | ||
| 11052 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | ||
| 11053 | result->value.special = ConstValSpecialUndef; | ||
| 11054 | return result; | ||
| 11055 | } | ||
| 10623 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { | 11056 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { |
| 10624 | if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { | 11057 | if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { |
| 10625 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | 11058 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| ... | @@ -10673,6 +11106,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10673,6 +11106,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10673 | 11106 | ||
| 10674 | 11107 | ||
| 10675 | // cast from [N]T to []const T | 11108 | // cast from [N]T to []const T |
| 11109 | // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this | ||
| 10676 | if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { | 11110 | if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { |
| 10677 | ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; | 11111 | ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; |
| 10678 | assert(ptr_type->id == ZigTypeIdPointer); | 11112 | assert(ptr_type->id == ZigTypeIdPointer); |
| ... | @@ -10685,6 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10685,6 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10685 | } | 11119 | } |
| 10686 | 11120 | ||
| 10687 | // cast from [N]T to ?[]const T | 11121 | // cast from [N]T to ?[]const T |
| 11122 | // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this | ||
| 10688 | if (wanted_type->id == ZigTypeIdOptional && | 11123 | if (wanted_type->id == ZigTypeIdOptional && |
| 10689 | is_slice(wanted_type->data.maybe.child_type) && | 11124 | is_slice(wanted_type->data.maybe.child_type) && |
| 10690 | actual_type->id == ZigTypeIdArray) | 11125 | actual_type->id == ZigTypeIdArray) |
| ... | @@ -10779,7 +11214,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10779,7 +11214,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10779 | } | 11214 | } |
| 10780 | } | 11215 | } |
| 10781 | 11216 | ||
| 10782 | // cast from error set to error union type | 11217 | // cast from E to E!T |
| 10783 | if (wanted_type->id == ZigTypeIdErrorUnion && | 11218 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| 10784 | actual_type->id == ZigTypeIdErrorSet) | 11219 | actual_type->id == ZigTypeIdErrorSet) |
| 10785 | { | 11220 | { |
| ... | @@ -10875,7 +11310,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10875,7 +11310,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10875 | actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes && | 11310 | actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes && |
| 10876 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) | 11311 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) |
| 10877 | { | 11312 | { |
| 10878 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr); | 11313 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); |
| 10879 | } | 11314 | } |
| 10880 | } | 11315 | } |
| 10881 | 11316 | ||
| ... | @@ -10892,6 +11327,40 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10892,6 +11327,40 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10892 | } | 11327 | } |
| 10893 | } | 11328 | } |
| 10894 | 11329 | ||
| 11330 | // cast from @Vector(N, T) to [N]T | ||
| 11331 | if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector && | ||
| 11332 | wanted_type->data.array.len == actual_type->data.vector.len && | ||
| 11333 | types_match_const_cast_only(ira, wanted_type->data.array.child_type, | ||
| 11334 | actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk) | ||
| 11335 | { | ||
| 11336 | return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type); | ||
| 11337 | } | ||
| 11338 | |||
| 11339 | // cast from [N]T to @Vector(N, T) | ||
| 11340 | if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector && | ||
| 11341 | actual_type->data.array.len == wanted_type->data.vector.len && | ||
| 11342 | types_match_const_cast_only(ira, actual_type->data.array.child_type, | ||
| 11343 | wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk) | ||
| 11344 | { | ||
| 11345 | return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type); | ||
| 11346 | } | ||
| 11347 | |||
| 11348 | // casting between C pointers and normal pointers | ||
| 11349 | if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer && | ||
| 11350 | (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) && | ||
| 11351 | types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | ||
| 11352 | actual_type->data.pointer.child_type, source_node, | ||
| 11353 | !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) | ||
| 11354 | { | ||
| 11355 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); | ||
| 11356 | } | ||
| 11357 | |||
| 11358 | // cast from integer to C pointer | ||
| 11359 | if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC && | ||
| 11360 | (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt)) | ||
| 11361 | { | ||
| 11362 | return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type); | ||
| 11363 | } | ||
| 10895 | 11364 | ||
| 10896 | // cast from undefined to anything | 11365 | // cast from undefined to anything |
| 10897 | if (actual_type->id == ZigTypeIdUndefined) { | 11366 | if (actual_type->id == ZigTypeIdUndefined) { |
| ... | @@ -10931,8 +11400,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -10931,8 +11400,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 10931 | ZigType *child_type = type_entry->data.pointer.child_type; | 11400 | ZigType *child_type = type_entry->data.pointer.child_type; |
| 10932 | // dereferencing a *u0 is comptime known to be 0 | 11401 | // dereferencing a *u0 is comptime known to be 0 |
| 10933 | if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { | 11402 | if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { |
| 10934 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | 11403 | IrInstruction *result = ir_const(ira, source_instruction, child_type); |
| 10935 | source_instruction->source_node, child_type); | ||
| 10936 | init_const_unsigned_negative(&result->value, child_type, 0, false); | 11404 | init_const_unsigned_negative(&result->value, child_type, 0, false); |
| 10937 | return result; | 11405 | return result; |
| 10938 | } | 11406 | } |
| ... | @@ -10946,10 +11414,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -10946,10 +11414,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 10946 | { | 11414 | { |
| 10947 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); | 11415 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 10948 | if (pointee->special != ConstValSpecialRuntime) { | 11416 | if (pointee->special != ConstValSpecialRuntime) { |
| 10949 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | 11417 | IrInstruction *result = ir_const(ira, source_instruction, child_type); |
| 10950 | source_instruction->source_node, child_type); | ||
| 10951 | 11418 | ||
| 10952 | if ((err = ir_read_const_ptr(ira, source_instruction->source_node, &result->value, | 11419 | if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value, |
| 10953 | &ptr->value))) | 11420 | &ptr->value))) |
| 10954 | { | 11421 | { |
| 10955 | return ira->codegen->invalid_instruction; | 11422 | return ira->codegen->invalid_instruction; |
| ... | @@ -10959,7 +11426,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -10959,7 +11426,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 10959 | } | 11426 | } |
| 10960 | } | 11427 | } |
| 10961 | } | 11428 | } |
| 10962 | // TODO if the instruction is a const ref instruction we can skip it | 11429 | // if the instruction is a const ref instruction we can skip it |
| 11430 | if (ptr->id == IrInstructionIdRef) { | ||
| 11431 | IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr); | ||
| 11432 | return ref_inst->value; | ||
| 11433 | } | ||
| 10963 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, | 11434 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, |
| 10964 | source_instruction->source_node, ptr); | 11435 | source_instruction->source_node, ptr); |
| 10965 | load_ptr_instruction->value.type = child_type; | 11436 | load_ptr_instruction->value.type = child_type; |
| ... | @@ -11184,10 +11655,13 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio | ... | @@ -11184,10 +11655,13 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 11184 | return ir_unreach_error(ira); | 11655 | return ir_unreach_error(ira); |
| 11185 | 11656 | ||
| 11186 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); | 11657 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); |
| 11187 | if (type_is_invalid(casted_value->value.type) && ira->explicit_return_type_source_node != nullptr) { | 11658 | if (type_is_invalid(casted_value->value.type)) { |
| 11188 | ErrorMsg *msg = ira->codegen->errors.last(); | 11659 | AstNode *source_node = ira->explicit_return_type_source_node; |
| 11189 | add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node, | 11660 | if (source_node != nullptr) { |
| 11190 | buf_sprintf("return type declared here")); | 11661 | ErrorMsg *msg = ira->codegen->errors.last(); |
| 11662 | add_error_note(ira->codegen, msg, source_node, | ||
| 11663 | buf_sprintf("return type declared here")); | ||
| 11664 | } | ||
| 11191 | return ir_unreach_error(ira); | 11665 | return ir_unreach_error(ira); |
| 11192 | } | 11666 | } |
| 11193 | 11667 | ||
| ... | @@ -11206,8 +11680,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio | ... | @@ -11206,8 +11680,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 11206 | 11680 | ||
| 11207 | static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) { | 11681 | static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) { |
| 11208 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | 11682 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); |
| 11209 | // TODO determine if we need to use copy_const_val here | 11683 | copy_const_val(&result->value, &instruction->base.value, true); |
| 11210 | result->value = instruction->base.value; | ||
| 11211 | return result; | 11684 | return result; |
| 11212 | } | 11685 | } |
| 11213 | 11686 | ||
| ... | @@ -11260,28 +11733,36 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -11260,28 +11733,36 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 11260 | } | 11733 | } |
| 11261 | 11734 | ||
| 11262 | static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { | 11735 | static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { |
| 11263 | if (op_id == IrBinOpCmpEq) { | 11736 | switch (op_id) { |
| 11264 | return cmp == CmpEQ; | 11737 | case IrBinOpCmpEq: |
| 11265 | } else if (op_id == IrBinOpCmpNotEq) { | 11738 | return cmp == CmpEQ; |
| 11266 | return cmp != CmpEQ; | 11739 | case IrBinOpCmpNotEq: |
| 11267 | } else if (op_id == IrBinOpCmpLessThan) { | 11740 | return cmp != CmpEQ; |
| 11268 | return cmp == CmpLT; | 11741 | case IrBinOpCmpLessThan: |
| 11269 | } else if (op_id == IrBinOpCmpGreaterThan) { | 11742 | return cmp == CmpLT; |
| 11270 | return cmp == CmpGT; | 11743 | case IrBinOpCmpGreaterThan: |
| 11271 | } else if (op_id == IrBinOpCmpLessOrEq) { | 11744 | return cmp == CmpGT; |
| 11272 | return cmp != CmpGT; | 11745 | case IrBinOpCmpLessOrEq: |
| 11273 | } else if (op_id == IrBinOpCmpGreaterOrEq) { | 11746 | return cmp != CmpGT; |
| 11274 | return cmp != CmpLT; | 11747 | case IrBinOpCmpGreaterOrEq: |
| 11275 | } else { | 11748 | return cmp != CmpLT; |
| 11276 | zig_unreachable(); | 11749 | default: |
| 11750 | zig_unreachable(); | ||
| 11277 | } | 11751 | } |
| 11278 | } | 11752 | } |
| 11279 | 11753 | ||
| 11280 | static bool optional_value_is_null(ConstExprValue *val) { | 11754 | static bool optional_value_is_null(ConstExprValue *val) { |
| 11281 | assert(val->special == ConstValSpecialStatic); | 11755 | assert(val->special == ConstValSpecialStatic); |
| 11282 | if (get_codegen_ptr_type(val->type) != nullptr) { | 11756 | if (get_codegen_ptr_type(val->type) != nullptr) { |
| 11283 | return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | 11757 | if (val->data.x_ptr.special == ConstPtrSpecialNull) { |
| 11284 | val->data.x_ptr.data.hard_coded_addr.addr == 0; | 11758 | return true; |
| 11759 | } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { | ||
| 11760 | return val->data.x_ptr.data.hard_coded_addr.addr == 0; | ||
| 11761 | } else { | ||
| 11762 | return false; | ||
| 11763 | } | ||
| 11764 | } else if (is_opt_err_set(val->type)) { | ||
| 11765 | return val->data.x_err_set == nullptr; | ||
| 11285 | } else { | 11766 | } else { |
| 11286 | return val->data.x_optional == nullptr; | 11767 | return val->data.x_optional == nullptr; |
| 11287 | } | 11768 | } |
| ... | @@ -11436,13 +11917,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11436,13 +11917,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11436 | case ZigTypeIdComptimeInt: | 11917 | case ZigTypeIdComptimeInt: |
| 11437 | case ZigTypeIdInt: | 11918 | case ZigTypeIdInt: |
| 11438 | case ZigTypeIdFloat: | 11919 | case ZigTypeIdFloat: |
| 11920 | case ZigTypeIdVector: | ||
| 11439 | operator_allowed = true; | 11921 | operator_allowed = true; |
| 11440 | break; | 11922 | break; |
| 11441 | 11923 | ||
| 11442 | case ZigTypeIdBool: | 11924 | case ZigTypeIdBool: |
| 11443 | case ZigTypeIdMetaType: | 11925 | case ZigTypeIdMetaType: |
| 11444 | case ZigTypeIdVoid: | 11926 | case ZigTypeIdVoid: |
| 11445 | case ZigTypeIdPointer: | ||
| 11446 | case ZigTypeIdErrorSet: | 11927 | case ZigTypeIdErrorSet: |
| 11447 | case ZigTypeIdFn: | 11928 | case ZigTypeIdFn: |
| 11448 | case ZigTypeIdOpaque: | 11929 | case ZigTypeIdOpaque: |
| ... | @@ -11454,6 +11935,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11454,6 +11935,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11454 | operator_allowed = is_equality_cmp; | 11935 | operator_allowed = is_equality_cmp; |
| 11455 | break; | 11936 | break; |
| 11456 | 11937 | ||
| 11938 | case ZigTypeIdPointer: | ||
| 11939 | operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC); | ||
| 11940 | break; | ||
| 11941 | |||
| 11457 | case ZigTypeIdUnreachable: | 11942 | case ZigTypeIdUnreachable: |
| 11458 | case ZigTypeIdArray: | 11943 | case ZigTypeIdArray: |
| 11459 | case ZigTypeIdStruct: | 11944 | case ZigTypeIdStruct: |
| ... | @@ -11481,19 +11966,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11481,19 +11966,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11481 | if (casted_op2 == ira->codegen->invalid_instruction) | 11966 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 11482 | return ira->codegen->invalid_instruction; | 11967 | return ira->codegen->invalid_instruction; |
| 11483 | 11968 | ||
| 11484 | bool requires_comptime; | 11969 | bool one_possible_value; |
| 11485 | switch (type_requires_comptime(ira->codegen, resolved_type)) { | 11970 | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { |
| 11486 | case ReqCompTimeYes: | 11971 | case OnePossibleValueInvalid: |
| 11487 | requires_comptime = true; | 11972 | return ira->codegen->invalid_instruction; |
| 11973 | case OnePossibleValueYes: | ||
| 11974 | one_possible_value = true; | ||
| 11488 | break; | 11975 | break; |
| 11489 | case ReqCompTimeNo: | 11976 | case OnePossibleValueNo: |
| 11490 | requires_comptime = false; | 11977 | one_possible_value = false; |
| 11491 | break; | 11978 | break; |
| 11492 | case ReqCompTimeInvalid: | ||
| 11493 | return ira->codegen->invalid_instruction; | ||
| 11494 | } | 11979 | } |
| 11495 | 11980 | ||
| 11496 | bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type); | ||
| 11497 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { | 11981 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 11498 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); | 11982 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 11499 | if (op1_val == nullptr) | 11983 | if (op1_val == nullptr) |
| ... | @@ -11502,15 +11986,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11502,15 +11986,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11502 | if (op2_val == nullptr) | 11986 | if (op2_val == nullptr) |
| 11503 | return ira->codegen->invalid_instruction; | 11987 | return ira->codegen->invalid_instruction; |
| 11504 | 11988 | ||
| 11505 | bool answer; | ||
| 11506 | if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) { | 11989 | if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) { |
| 11507 | Cmp cmp_result = float_cmp(op1_val, op2_val); | 11990 | Cmp cmp_result = float_cmp(op1_val, op2_val); |
| 11508 | answer = resolve_cmp_op_id(op_id, cmp_result); | 11991 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 11992 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | ||
| 11509 | } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) { | 11993 | } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) { |
| 11510 | Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint); | 11994 | Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11511 | answer = resolve_cmp_op_id(op_id, cmp_result); | 11995 | bool answer = resolve_cmp_op_id(op_id, cmp_result); |
| 11996 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | ||
| 11997 | } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { | ||
| 11998 | if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | ||
| 11999 | op1_val->data.x_ptr.special == ConstPtrSpecialNull) && | ||
| 12000 | (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | ||
| 12001 | op2_val->data.x_ptr.special == ConstPtrSpecialNull)) | ||
| 12002 | { | ||
| 12003 | uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ? | ||
| 12004 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; | ||
| 12005 | uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ? | ||
| 12006 | 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr; | ||
| 12007 | Cmp cmp_result; | ||
| 12008 | if (op1_addr > op2_addr) { | ||
| 12009 | cmp_result = CmpGT; | ||
| 12010 | } else if (op1_addr < op2_addr) { | ||
| 12011 | cmp_result = CmpLT; | ||
| 12012 | } else { | ||
| 12013 | cmp_result = CmpEQ; | ||
| 12014 | } | ||
| 12015 | bool answer = resolve_cmp_op_id(op_id, cmp_result); | ||
| 12016 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | ||
| 12017 | } | ||
| 11512 | } else { | 12018 | } else { |
| 11513 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); | 12019 | bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); |
| 12020 | bool answer; | ||
| 11514 | if (op_id == IrBinOpCmpEq) { | 12021 | if (op_id == IrBinOpCmpEq) { |
| 11515 | answer = are_equal; | 12022 | answer = are_equal; |
| 11516 | } else if (op_id == IrBinOpCmpNotEq) { | 12023 | } else if (op_id == IrBinOpCmpNotEq) { |
| ... | @@ -11518,9 +12025,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11518,9 +12025,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11518 | } else { | 12025 | } else { |
| 11519 | zig_unreachable(); | 12026 | zig_unreachable(); |
| 11520 | } | 12027 | } |
| 12028 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | ||
| 11521 | } | 12029 | } |
| 11522 | |||
| 11523 | return ir_const_bool(ira, &bin_op_instruction->base, answer); | ||
| 11524 | } | 12030 | } |
| 11525 | 12031 | ||
| 11526 | // some comparisons with unsigned numbers can be evaluated | 12032 | // some comparisons with unsigned numbers can be evaluated |
| ... | @@ -11567,8 +12073,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11567,8 +12073,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11567 | return result; | 12073 | return result; |
| 11568 | } | 12074 | } |
| 11569 | 12075 | ||
| 11570 | static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | 12076 | static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry, |
| 11571 | IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val) | 12077 | ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val) |
| 11572 | { | 12078 | { |
| 11573 | bool is_int; | 12079 | bool is_int; |
| 11574 | bool is_float; | 12080 | bool is_float; |
| ... | @@ -11590,10 +12096,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11590,10 +12096,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11590 | if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod || | 12096 | if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod || |
| 11591 | op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ) | 12097 | op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ) |
| 11592 | { | 12098 | { |
| 11593 | return ErrorDivByZero; | 12099 | return ir_add_error(ira, source_instr, buf_sprintf("division by zero")); |
| 11594 | } | 12100 | } |
| 11595 | if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) { | 12101 | if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) { |
| 11596 | return ErrorNegativeDenominator; | 12102 | return ir_add_error(ira, source_instr, buf_sprintf("negative denominator")); |
| 11597 | } | 12103 | } |
| 11598 | 12104 | ||
| 11599 | switch (op_id) { | 12105 | switch (op_id) { |
| ... | @@ -11639,7 +12145,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11639,7 +12145,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11639 | BigInt orig_bigint; | 12145 | BigInt orig_bigint; |
| 11640 | bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint); | 12146 | bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11641 | if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) { | 12147 | if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) { |
| 11642 | return ErrorShiftedOutOneBits; | 12148 | return ir_add_error(ira, source_instr, buf_sprintf("exact shift shifted out 1 bits")); |
| 11643 | } | 12149 | } |
| 11644 | break; | 12150 | break; |
| 11645 | } | 12151 | } |
| ... | @@ -11707,14 +12213,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11707,14 +12213,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11707 | BigInt remainder; | 12213 | BigInt remainder; |
| 11708 | bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint); | 12214 | bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint); |
| 11709 | if (bigint_cmp_zero(&remainder) != CmpEQ) { | 12215 | if (bigint_cmp_zero(&remainder) != CmpEQ) { |
| 11710 | return ErrorExactDivRemainder; | 12216 | return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder")); |
| 11711 | } | 12217 | } |
| 11712 | } else { | 12218 | } else { |
| 11713 | float_div_trunc(out_val, op1_val, op2_val); | 12219 | float_div_trunc(out_val, op1_val, op2_val); |
| 11714 | ConstExprValue remainder; | 12220 | ConstExprValue remainder; |
| 11715 | float_rem(&remainder, op1_val, op2_val); | 12221 | float_rem(&remainder, op1_val, op2_val); |
| 11716 | if (float_cmp_zero(&remainder) != CmpEQ) { | 12222 | if (float_cmp_zero(&remainder) != CmpEQ) { |
| 11717 | return ErrorExactDivRemainder; | 12223 | return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder")); |
| 11718 | } | 12224 | } |
| 11719 | } | 12225 | } |
| 11720 | break; | 12226 | break; |
| ... | @@ -11738,13 +12244,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, | ... | @@ -11738,13 +12244,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val, |
| 11738 | if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count, | 12244 | if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count, |
| 11739 | type_entry->data.integral.is_signed)) | 12245 | type_entry->data.integral.is_signed)) |
| 11740 | { | 12246 | { |
| 11741 | return ErrorOverflow; | 12247 | return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow")); |
| 11742 | } | 12248 | } |
| 11743 | } | 12249 | } |
| 11744 | 12250 | ||
| 11745 | out_val->type = type_entry; | 12251 | out_val->type = type_entry; |
| 11746 | out_val->special = ConstValSpecialStatic; | 12252 | out_val->special = ConstValSpecialStatic; |
| 11747 | return 0; | 12253 | return nullptr; |
| 12254 | } | ||
| 12255 | |||
| 12256 | // This works on operands that have already been checked to be comptime known. | ||
| 12257 | static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 12258 | ZigType *type_entry, ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val) | ||
| 12259 | { | ||
| 12260 | IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry); | ||
| 12261 | ConstExprValue *out_val = &result_instruction->value; | ||
| 12262 | if (type_entry->id == ZigTypeIdVector) { | ||
| 12263 | expand_undef_array(ira->codegen, op1_val); | ||
| 12264 | expand_undef_array(ira->codegen, op2_val); | ||
| 12265 | out_val->special = ConstValSpecialUndef; | ||
| 12266 | expand_undef_array(ira->codegen, out_val); | ||
| 12267 | size_t len = type_entry->data.vector.len; | ||
| 12268 | ZigType *scalar_type = type_entry->data.vector.elem_type; | ||
| 12269 | for (size_t i = 0; i < len; i += 1) { | ||
| 12270 | ConstExprValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i]; | ||
| 12271 | ConstExprValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i]; | ||
| 12272 | ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i]; | ||
| 12273 | assert(scalar_op1_val->type == scalar_type); | ||
| 12274 | assert(scalar_op2_val->type == scalar_type); | ||
| 12275 | assert(scalar_out_val->type == scalar_type); | ||
| 12276 | ErrorMsg *msg = ir_eval_math_op_scalar(ira, source_instr, scalar_type, | ||
| 12277 | scalar_op1_val, op_id, scalar_op2_val, scalar_out_val); | ||
| 12278 | if (msg != nullptr) { | ||
| 12279 | add_error_note(ira->codegen, msg, source_instr->source_node, | ||
| 12280 | buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); | ||
| 12281 | return ira->codegen->invalid_instruction; | ||
| 12282 | } | ||
| 12283 | } | ||
| 12284 | out_val->type = type_entry; | ||
| 12285 | out_val->special = ConstValSpecialStatic; | ||
| 12286 | } else { | ||
| 12287 | if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) { | ||
| 12288 | return ira->codegen->invalid_instruction; | ||
| 12289 | } | ||
| 12290 | } | ||
| 12291 | return ir_implicit_cast(ira, result_instruction, type_entry); | ||
| 11748 | } | 12292 | } |
| 11749 | 12293 | ||
| 11750 | static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 12294 | static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| ... | @@ -11816,24 +12360,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b | ... | @@ -11816,24 +12360,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b |
| 11816 | if (op2_val == nullptr) | 12360 | if (op2_val == nullptr) |
| 11817 | return ira->codegen->invalid_instruction; | 12361 | return ira->codegen->invalid_instruction; |
| 11818 | 12362 | ||
| 11819 | IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type); | 12363 | return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val); |
| 11820 | |||
| 11821 | int err; | ||
| 11822 | if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) { | ||
| 11823 | if (err == ErrorOverflow) { | ||
| 11824 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow")); | ||
| 11825 | return ira->codegen->invalid_instruction; | ||
| 11826 | } else if (err == ErrorShiftedOutOneBits) { | ||
| 11827 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits")); | ||
| 11828 | return ira->codegen->invalid_instruction; | ||
| 11829 | } else { | ||
| 11830 | zig_unreachable(); | ||
| 11831 | } | ||
| 11832 | return ira->codegen->invalid_instruction; | ||
| 11833 | } | ||
| 11834 | |||
| 11835 | ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false); | ||
| 11836 | return result_instruction; | ||
| 11837 | } else if (op1->value.type->id == ZigTypeIdComptimeInt) { | 12364 | } else if (op1->value.type->id == ZigTypeIdComptimeInt) { |
| 11838 | ir_add_error(ira, &bin_op_instruction->base, | 12365 | ir_add_error(ira, &bin_op_instruction->base, |
| 11839 | buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known")); | 12366 | buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known")); |
| ... | @@ -11852,7 +12379,71 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b | ... | @@ -11852,7 +12379,71 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b |
| 11852 | return result; | 12379 | return result; |
| 11853 | } | 12380 | } |
| 11854 | 12381 | ||
| 12382 | static bool ok_float_op(IrBinOp op) { | ||
| 12383 | switch (op) { | ||
| 12384 | case IrBinOpInvalid: | ||
| 12385 | zig_unreachable(); | ||
| 12386 | case IrBinOpAdd: | ||
| 12387 | case IrBinOpSub: | ||
| 12388 | case IrBinOpMult: | ||
| 12389 | case IrBinOpDivUnspecified: | ||
| 12390 | case IrBinOpDivTrunc: | ||
| 12391 | case IrBinOpDivFloor: | ||
| 12392 | case IrBinOpDivExact: | ||
| 12393 | case IrBinOpRemRem: | ||
| 12394 | case IrBinOpRemMod: | ||
| 12395 | return true; | ||
| 12396 | |||
| 12397 | case IrBinOpBoolOr: | ||
| 12398 | case IrBinOpBoolAnd: | ||
| 12399 | case IrBinOpCmpEq: | ||
| 12400 | case IrBinOpCmpNotEq: | ||
| 12401 | case IrBinOpCmpLessThan: | ||
| 12402 | case IrBinOpCmpGreaterThan: | ||
| 12403 | case IrBinOpCmpLessOrEq: | ||
| 12404 | case IrBinOpCmpGreaterOrEq: | ||
| 12405 | case IrBinOpBinOr: | ||
| 12406 | case IrBinOpBinXor: | ||
| 12407 | case IrBinOpBinAnd: | ||
| 12408 | case IrBinOpBitShiftLeftLossy: | ||
| 12409 | case IrBinOpBitShiftLeftExact: | ||
| 12410 | case IrBinOpBitShiftRightLossy: | ||
| 12411 | case IrBinOpBitShiftRightExact: | ||
| 12412 | case IrBinOpAddWrap: | ||
| 12413 | case IrBinOpSubWrap: | ||
| 12414 | case IrBinOpMultWrap: | ||
| 12415 | case IrBinOpRemUnspecified: | ||
| 12416 | case IrBinOpArrayCat: | ||
| 12417 | case IrBinOpArrayMult: | ||
| 12418 | case IrBinOpMergeErrorSets: | ||
| 12419 | return false; | ||
| 12420 | } | ||
| 12421 | zig_unreachable(); | ||
| 12422 | } | ||
| 12423 | |||
| 12424 | static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { | ||
| 12425 | if (lhs_type->id != ZigTypeIdPointer) | ||
| 12426 | return false; | ||
| 12427 | switch (op) { | ||
| 12428 | case IrBinOpAdd: | ||
| 12429 | case IrBinOpSub: | ||
| 12430 | break; | ||
| 12431 | default: | ||
| 12432 | return false; | ||
| 12433 | } | ||
| 12434 | switch (lhs_type->data.pointer.ptr_len) { | ||
| 12435 | case PtrLenSingle: | ||
| 12436 | return false; | ||
| 12437 | case PtrLenUnknown: | ||
| 12438 | case PtrLenC: | ||
| 12439 | break; | ||
| 12440 | } | ||
| 12441 | return true; | ||
| 12442 | } | ||
| 12443 | |||
| 11855 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 12444 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 12445 | Error err; | ||
| 12446 | |||
| 11856 | IrInstruction *op1 = instruction->op1->child; | 12447 | IrInstruction *op1 = instruction->op1->child; |
| 11857 | if (type_is_invalid(op1->value.type)) | 12448 | if (type_is_invalid(op1->value.type)) |
| 11858 | return ira->codegen->invalid_instruction; | 12449 | return ira->codegen->invalid_instruction; |
| ... | @@ -11864,13 +12455,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -11864,13 +12455,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 11864 | IrBinOp op_id = instruction->op_id; | 12455 | IrBinOp op_id = instruction->op_id; |
| 11865 | 12456 | ||
| 11866 | // look for pointer math | 12457 | // look for pointer math |
| 11867 | if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown && | 12458 | if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) { |
| 11868 | (op_id == IrBinOpAdd || op_id == IrBinOpSub)) | ||
| 11869 | { | ||
| 11870 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); | 12459 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); |
| 11871 | if (casted_op2 == ira->codegen->invalid_instruction) | 12460 | if (type_is_invalid(casted_op2->value.type)) |
| 11872 | return ira->codegen->invalid_instruction; | 12461 | return ira->codegen->invalid_instruction; |
| 11873 | 12462 | ||
| 12463 | if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) { | ||
| 12464 | IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type); | ||
| 12465 | result->value.special = ConstValSpecialUndef; | ||
| 12466 | return result; | ||
| 12467 | } | ||
| 12468 | if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic && | ||
| 12469 | (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | ||
| 12470 | op1->value.data.x_ptr.special == ConstPtrSpecialNull)) | ||
| 12471 | { | ||
| 12472 | uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ? | ||
| 12473 | 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr; | ||
| 12474 | uint64_t elem_offset; | ||
| 12475 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) | ||
| 12476 | return ira->codegen->invalid_instruction; | ||
| 12477 | ZigType *elem_type = op1->value.type->data.pointer.child_type; | ||
| 12478 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) | ||
| 12479 | return ira->codegen->invalid_instruction; | ||
| 12480 | uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset; | ||
| 12481 | uint64_t new_addr; | ||
| 12482 | if (op_id == IrBinOpAdd) { | ||
| 12483 | new_addr = start_addr + byte_offset; | ||
| 12484 | } else if (op_id == IrBinOpSub) { | ||
| 12485 | new_addr = start_addr - byte_offset; | ||
| 12486 | } else { | ||
| 12487 | zig_unreachable(); | ||
| 12488 | } | ||
| 12489 | IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type); | ||
| 12490 | result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | ||
| 12491 | result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar; | ||
| 12492 | result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr; | ||
| 12493 | return result; | ||
| 12494 | } | ||
| 12495 | |||
| 11874 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | 12496 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, |
| 11875 | instruction->base.source_node, op_id, op1, casted_op2, true); | 12497 | instruction->base.source_node, op_id, op1, casted_op2, true); |
| 11876 | result->value.type = op1->value.type; | 12498 | result->value.type = op1->value.type; |
| ... | @@ -11989,21 +12611,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -11989,21 +12611,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 11989 | op_id = IrBinOpRemRem; | 12611 | op_id = IrBinOpRemRem; |
| 11990 | } | 12612 | } |
| 11991 | 12613 | ||
| 12614 | bool ok = false; | ||
| 11992 | if (is_int) { | 12615 | if (is_int) { |
| 11993 | // int | 12616 | ok = true; |
| 11994 | } else if (is_float && | 12617 | } else if (is_float && ok_float_op(op_id)) { |
| 11995 | (op_id == IrBinOpAdd || | 12618 | ok = true; |
| 11996 | op_id == IrBinOpSub || | 12619 | } else if (resolved_type->id == ZigTypeIdVector) { |
| 11997 | op_id == IrBinOpMult || | 12620 | ZigType *elem_type = resolved_type->data.vector.elem_type; |
| 11998 | op_id == IrBinOpDivUnspecified || | 12621 | if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) { |
| 11999 | op_id == IrBinOpDivTrunc || | 12622 | ok = true; |
| 12000 | op_id == IrBinOpDivFloor || | 12623 | } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) { |
| 12001 | op_id == IrBinOpDivExact || | 12624 | ok = true; |
| 12002 | op_id == IrBinOpRemRem || | 12625 | } |
| 12003 | op_id == IrBinOpRemMod)) | 12626 | } |
| 12004 | { | 12627 | if (!ok) { |
| 12005 | // float | ||
| 12006 | } else { | ||
| 12007 | AstNode *source_node = instruction->base.source_node; | 12628 | AstNode *source_node = instruction->base.source_node; |
| 12008 | ir_add_error_node(ira, source_node, | 12629 | ir_add_error_node(ira, source_node, |
| 12009 | buf_sprintf("invalid operands to binary expression: '%s' and '%s'", | 12630 | buf_sprintf("invalid operands to binary expression: '%s' and '%s'", |
| ... | @@ -12038,30 +12659,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -12038,30 +12659,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 12038 | if (op2_val == nullptr) | 12659 | if (op2_val == nullptr) |
| 12039 | return ira->codegen->invalid_instruction; | 12660 | return ira->codegen->invalid_instruction; |
| 12040 | 12661 | ||
| 12041 | IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type); | 12662 | return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val); |
| 12042 | |||
| 12043 | int err; | ||
| 12044 | if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) { | ||
| 12045 | if (err == ErrorDivByZero) { | ||
| 12046 | ir_add_error(ira, &instruction->base, buf_sprintf("division by zero")); | ||
| 12047 | return ira->codegen->invalid_instruction; | ||
| 12048 | } else if (err == ErrorOverflow) { | ||
| 12049 | ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow")); | ||
| 12050 | return ira->codegen->invalid_instruction; | ||
| 12051 | } else if (err == ErrorExactDivRemainder) { | ||
| 12052 | ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder")); | ||
| 12053 | return ira->codegen->invalid_instruction; | ||
| 12054 | } else if (err == ErrorNegativeDenominator) { | ||
| 12055 | ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator")); | ||
| 12056 | return ira->codegen->invalid_instruction; | ||
| 12057 | } else { | ||
| 12058 | zig_unreachable(); | ||
| 12059 | } | ||
| 12060 | return ira->codegen->invalid_instruction; | ||
| 12061 | } | ||
| 12062 | |||
| 12063 | ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false); | ||
| 12064 | return result_instruction; | ||
| 12065 | } | 12663 | } |
| 12066 | 12664 | ||
| 12067 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | 12665 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, |
| ... | @@ -12115,7 +12713,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i | ... | @@ -12115,7 +12713,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 12115 | op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; | 12713 | op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 12116 | op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; | 12714 | op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; |
| 12117 | ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index]; | 12715 | ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index]; |
| 12118 | op1_array_end = bigint_as_unsigned(&len_val->data.x_bigint); | 12716 | op1_array_end = op1_array_index + bigint_as_unsigned(&len_val->data.x_bigint); |
| 12119 | } else { | 12717 | } else { |
| 12120 | ir_add_error(ira, op1, | 12718 | ir_add_error(ira, op1, |
| 12121 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name))); | 12719 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name))); |
| ... | @@ -12125,13 +12723,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i | ... | @@ -12125,13 +12723,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 12125 | ConstExprValue *op2_array_val; | 12723 | ConstExprValue *op2_array_val; |
| 12126 | size_t op2_array_index; | 12724 | size_t op2_array_index; |
| 12127 | size_t op2_array_end; | 12725 | size_t op2_array_end; |
| 12726 | bool op2_type_valid; | ||
| 12128 | if (op2_type->id == ZigTypeIdArray) { | 12727 | if (op2_type->id == ZigTypeIdArray) { |
| 12129 | if (op2_type->data.array.child_type != child_type) { | 12728 | op2_type_valid = op2_type->data.array.child_type == child_type; |
| 12130 | ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", | ||
| 12131 | buf_ptr(&child_type->name), | ||
| 12132 | buf_ptr(&op2->value.type->name))); | ||
| 12133 | return ira->codegen->invalid_instruction; | ||
| 12134 | } | ||
| 12135 | op2_array_val = op2_val; | 12729 | op2_array_val = op2_val; |
| 12136 | op2_array_index = 0; | 12730 | op2_array_index = 0; |
| 12137 | op2_array_end = op2_array_val->type->data.array.len; | 12731 | op2_array_end = op2_array_val->type->data.array.len; |
| ... | @@ -12140,35 +12734,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i | ... | @@ -12140,35 +12734,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 12140 | op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray && | 12734 | op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray && |
| 12141 | op2_val->data.x_ptr.data.base_array.is_cstr) | 12735 | op2_val->data.x_ptr.data.base_array.is_cstr) |
| 12142 | { | 12736 | { |
| 12143 | if (child_type != ira->codegen->builtin_types.entry_u8) { | 12737 | op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8; |
| 12144 | ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", | ||
| 12145 | buf_ptr(&child_type->name), | ||
| 12146 | buf_ptr(&op2->value.type->name))); | ||
| 12147 | return ira->codegen->invalid_instruction; | ||
| 12148 | } | ||
| 12149 | op2_array_val = op2_val->data.x_ptr.data.base_array.array_val; | 12738 | op2_array_val = op2_val->data.x_ptr.data.base_array.array_val; |
| 12150 | op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index; | 12739 | op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index; |
| 12151 | op2_array_end = op2_array_val->type->data.array.len - 1; | 12740 | op2_array_end = op2_array_val->type->data.array.len - 1; |
| 12152 | } else if (is_slice(op2_type)) { | 12741 | } else if (is_slice(op2_type)) { |
| 12153 | ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry; | 12742 | ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry; |
| 12154 | if (ptr_type->data.pointer.child_type != child_type) { | 12743 | op2_type_valid = ptr_type->data.pointer.child_type == child_type; |
| 12155 | ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", | ||
| 12156 | buf_ptr(&child_type->name), | ||
| 12157 | buf_ptr(&op2->value.type->name))); | ||
| 12158 | return ira->codegen->invalid_instruction; | ||
| 12159 | } | ||
| 12160 | ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index]; | 12744 | ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index]; |
| 12161 | assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); | 12745 | assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); |
| 12162 | op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; | 12746 | op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 12163 | op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; | 12747 | op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; |
| 12164 | op2_array_end = op2_array_val->type->data.array.len; | ||
| 12165 | ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index]; | 12748 | ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index]; |
| 12166 | op2_array_end = bigint_as_unsigned(&len_val->data.x_bigint); | 12749 | op2_array_end = op2_array_index + bigint_as_unsigned(&len_val->data.x_bigint); |
| 12167 | } else { | 12750 | } else { |
| 12168 | ir_add_error(ira, op2, | 12751 | ir_add_error(ira, op2, |
| 12169 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name))); | 12752 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name))); |
| 12170 | return ira->codegen->invalid_instruction; | 12753 | return ira->codegen->invalid_instruction; |
| 12171 | } | 12754 | } |
| 12755 | if (!op2_type_valid) { | ||
| 12756 | ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", | ||
| 12757 | buf_ptr(&child_type->name), | ||
| 12758 | buf_ptr(&op2->value.type->name))); | ||
| 12759 | return ira->codegen->invalid_instruction; | ||
| 12760 | } | ||
| 12172 | 12761 | ||
| 12173 | // The type of result is populated in the following if blocks | 12762 | // The type of result is populated in the following if blocks |
| 12174 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | 12763 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); |
| ... | @@ -12301,26 +12890,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -12301,26 +12890,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * |
| 12301 | } | 12890 | } |
| 12302 | 12891 | ||
| 12303 | static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 12892 | static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) { |
| 12304 | ZigType *op1_type = ir_resolve_type(ira, instruction->op1->child); | 12893 | ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op1->child); |
| 12305 | if (type_is_invalid(op1_type)) | 12894 | if (type_is_invalid(op1_type)) |
| 12306 | return ira->codegen->invalid_instruction; | 12895 | return ira->codegen->invalid_instruction; |
| 12307 | 12896 | ||
| 12308 | if (op1_type->id != ZigTypeIdErrorSet) { | 12897 | ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child); |
| 12309 | ir_add_error(ira, instruction->op1, | ||
| 12310 | buf_sprintf("expected error set type, found '%s'", buf_ptr(&op1_type->name))); | ||
| 12311 | return ira->codegen->invalid_instruction; | ||
| 12312 | } | ||
| 12313 | |||
| 12314 | ZigType *op2_type = ir_resolve_type(ira, instruction->op2->child); | ||
| 12315 | if (type_is_invalid(op2_type)) | 12898 | if (type_is_invalid(op2_type)) |
| 12316 | return ira->codegen->invalid_instruction; | 12899 | return ira->codegen->invalid_instruction; |
| 12317 | 12900 | ||
| 12318 | if (op2_type->id != ZigTypeIdErrorSet) { | ||
| 12319 | ir_add_error(ira, instruction->op2, | ||
| 12320 | buf_sprintf("expected error set type, found '%s'", buf_ptr(&op2_type->name))); | ||
| 12321 | return ira->codegen->invalid_instruction; | ||
| 12322 | } | ||
| 12323 | |||
| 12324 | if (type_is_global_error_set(op1_type) || | 12901 | if (type_is_global_error_set(op1_type) || |
| 12325 | type_is_global_error_set(op2_type)) | 12902 | type_is_global_error_set(op2_type)) |
| 12326 | { | 12903 | { |
| ... | @@ -12394,13 +12971,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio | ... | @@ -12394,13 +12971,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio |
| 12394 | zig_unreachable(); | 12971 | zig_unreachable(); |
| 12395 | } | 12972 | } |
| 12396 | 12973 | ||
| 12397 | static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) { | 12974 | static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, |
| 12975 | IrInstructionDeclVarSrc *decl_var_instruction) | ||
| 12976 | { | ||
| 12398 | Error err; | 12977 | Error err; |
| 12399 | ZigVar *var = decl_var_instruction->var; | 12978 | ZigVar *var = decl_var_instruction->var; |
| 12400 | 12979 | ||
| 12401 | IrInstruction *init_value = decl_var_instruction->init_value->child; | 12980 | IrInstruction *init_value = decl_var_instruction->init_value->child; |
| 12402 | if (type_is_invalid(init_value->value.type)) { | 12981 | if (type_is_invalid(init_value->value.type)) { |
| 12403 | var->value->type = ira->codegen->builtin_types.entry_invalid; | 12982 | var->var_type = ira->codegen->builtin_types.entry_invalid; |
| 12404 | return ira->codegen->invalid_instruction; | 12983 | return ira->codegen->invalid_instruction; |
| 12405 | } | 12984 | } |
| 12406 | 12985 | ||
| ... | @@ -12411,7 +12990,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12411,7 +12990,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12411 | ZigType *proposed_type = ir_resolve_type(ira, var_type); | 12990 | ZigType *proposed_type = ir_resolve_type(ira, var_type); |
| 12412 | explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); | 12991 | explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); |
| 12413 | if (type_is_invalid(explicit_type)) { | 12992 | if (type_is_invalid(explicit_type)) { |
| 12414 | var->value->type = ira->codegen->builtin_types.entry_invalid; | 12993 | var->var_type = ira->codegen->builtin_types.entry_invalid; |
| 12415 | return ira->codegen->invalid_instruction; | 12994 | return ira->codegen->invalid_instruction; |
| 12416 | } | 12995 | } |
| 12417 | } | 12996 | } |
| ... | @@ -12436,7 +13015,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12436,7 +13015,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12436 | case ReqCompTimeInvalid: | 13015 | case ReqCompTimeInvalid: |
| 12437 | result_type = ira->codegen->builtin_types.entry_invalid; | 13016 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12438 | break; | 13017 | break; |
| 12439 | case ReqCompTimeYes: { | 13018 | case ReqCompTimeYes: |
| 12440 | var_class_requires_const = true; | 13019 | var_class_requires_const = true; |
| 12441 | if (!var->gen_is_const && !is_comptime_var) { | 13020 | if (!var->gen_is_const && !is_comptime_var) { |
| 12442 | ir_add_error_node(ira, source_node, | 13021 | ir_add_error_node(ira, source_node, |
| ... | @@ -12445,10 +13024,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12445,10 +13024,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12445 | result_type = ira->codegen->builtin_types.entry_invalid; | 13024 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12446 | } | 13025 | } |
| 12447 | break; | 13026 | break; |
| 12448 | } | ||
| 12449 | case ReqCompTimeNo: | 13027 | case ReqCompTimeNo: |
| 12450 | if (casted_init_value->value.special == ConstValSpecialStatic && | 13028 | if (casted_init_value->value.special == ConstValSpecialStatic && |
| 12451 | casted_init_value->value.type->id == ZigTypeIdFn && | 13029 | casted_init_value->value.type->id == ZigTypeIdFn && |
| 13030 | casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr && | ||
| 12452 | casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) | 13031 | casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) |
| 12453 | { | 13032 | { |
| 12454 | var_class_requires_const = true; | 13033 | var_class_requires_const = true; |
| ... | @@ -12463,7 +13042,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12463,7 +13042,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12463 | break; | 13042 | break; |
| 12464 | } | 13043 | } |
| 12465 | 13044 | ||
| 12466 | if (var->value->type != nullptr && !is_comptime_var) { | 13045 | if (var->var_type != nullptr && !is_comptime_var) { |
| 12467 | // This is at least the second time we've seen this variable declaration during analysis. | 13046 | // This is at least the second time we've seen this variable declaration during analysis. |
| 12468 | // This means that this is actually a different variable due to, e.g. an inline while loop. | 13047 | // This means that this is actually a different variable due to, e.g. an inline while loop. |
| 12469 | // We make a new variable so that it can hold a different type, and so the debug info can | 13048 | // We make a new variable so that it can hold a different type, and so the debug info can |
| ... | @@ -12485,8 +13064,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12485,8 +13064,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12485 | // This must be done after possibly creating a new variable above | 13064 | // This must be done after possibly creating a new variable above |
| 12486 | var->ref_count = 0; | 13065 | var->ref_count = 0; |
| 12487 | 13066 | ||
| 12488 | var->value->type = result_type; | 13067 | var->var_type = result_type; |
| 12489 | assert(var->value->type); | 13068 | assert(var->var_type); |
| 12490 | 13069 | ||
| 12491 | if (type_is_invalid(result_type)) { | 13070 | if (type_is_invalid(result_type)) { |
| 12492 | return ir_const_void(ira, &decl_var_instruction->base); | 13071 | return ir_const_void(ira, &decl_var_instruction->base); |
| ... | @@ -12494,13 +13073,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12494,13 +13073,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12494 | 13073 | ||
| 12495 | if (decl_var_instruction->align_value == nullptr) { | 13074 | if (decl_var_instruction->align_value == nullptr) { |
| 12496 | if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) { | 13075 | if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) { |
| 12497 | var->value->type = ira->codegen->builtin_types.entry_invalid; | 13076 | var->var_type = ira->codegen->builtin_types.entry_invalid; |
| 12498 | return ir_const_void(ira, &decl_var_instruction->base); | 13077 | return ir_const_void(ira, &decl_var_instruction->base); |
| 12499 | } | 13078 | } |
| 12500 | var->align_bytes = get_abi_alignment(ira->codegen, result_type); | 13079 | var->align_bytes = get_abi_alignment(ira->codegen, result_type); |
| 12501 | } else { | 13080 | } else { |
| 12502 | if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) { | 13081 | if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) { |
| 12503 | var->value->type = ira->codegen->builtin_types.entry_invalid; | 13082 | var->var_type = ira->codegen->builtin_types.entry_invalid; |
| 12504 | } | 13083 | } |
| 12505 | } | 13084 | } |
| 12506 | 13085 | ||
| ... | @@ -12517,7 +13096,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12517,7 +13096,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12517 | } else if (is_comptime_var) { | 13096 | } else if (is_comptime_var) { |
| 12518 | ir_add_error(ira, &decl_var_instruction->base, | 13097 | ir_add_error(ira, &decl_var_instruction->base, |
| 12519 | buf_sprintf("cannot store runtime value in compile time variable")); | 13098 | buf_sprintf("cannot store runtime value in compile time variable")); |
| 12520 | var->value->type = ira->codegen->builtin_types.entry_invalid; | 13099 | var->var_type = ira->codegen->builtin_types.entry_invalid; |
| 12521 | return ira->codegen->invalid_instruction; | 13100 | return ira->codegen->invalid_instruction; |
| 12522 | } | 13101 | } |
| 12523 | 13102 | ||
| ... | @@ -12525,11 +13104,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12525,11 +13104,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12525 | if (fn_entry) | 13104 | if (fn_entry) |
| 12526 | fn_entry->variable_list.append(var); | 13105 | fn_entry->variable_list.append(var); |
| 12527 | 13106 | ||
| 12528 | IrInstruction *result = ir_build_var_decl(&ira->new_irb, | 13107 | return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value); |
| 12529 | decl_var_instruction->base.scope, decl_var_instruction->base.source_node, | ||
| 12530 | var, var_type, nullptr, casted_init_value); | ||
| 12531 | result->value.type = ira->codegen->builtin_types.entry_void; | ||
| 12532 | return result; | ||
| 12533 | } | 13108 | } |
| 12534 | 13109 | ||
| 12535 | static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { | 13110 | static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { |
| ... | @@ -12651,6 +13226,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio | ... | @@ -12651,6 +13226,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12651 | case ZigTypeIdPointer: | 13226 | case ZigTypeIdPointer: |
| 12652 | case ZigTypeIdArray: | 13227 | case ZigTypeIdArray: |
| 12653 | case ZigTypeIdBool: | 13228 | case ZigTypeIdBool: |
| 13229 | case ZigTypeIdVector: | ||
| 12654 | break; | 13230 | break; |
| 12655 | case ZigTypeIdMetaType: | 13231 | case ZigTypeIdMetaType: |
| 12656 | case ZigTypeIdVoid: | 13232 | case ZigTypeIdVoid: |
| ... | @@ -12685,6 +13261,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio | ... | @@ -12685,6 +13261,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 12685 | case ZigTypeIdOptional: | 13261 | case ZigTypeIdOptional: |
| 12686 | case ZigTypeIdErrorUnion: | 13262 | case ZigTypeIdErrorUnion: |
| 12687 | case ZigTypeIdErrorSet: | 13263 | case ZigTypeIdErrorSet: |
| 13264 | case ZigTypeIdVector: | ||
| 12688 | zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); | 13265 | zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); |
| 12689 | case ZigTypeIdNamespace: | 13266 | case ZigTypeIdNamespace: |
| 12690 | case ZigTypeIdBoundFn: | 13267 | case ZigTypeIdBoundFn: |
| ... | @@ -12859,7 +13436,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node | ... | @@ -12859,7 +13436,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node |
| 12859 | 13436 | ||
| 12860 | Buf *param_name = param_decl_node->data.param_decl.name; | 13437 | Buf *param_name = param_decl_node->data.param_decl.name; |
| 12861 | ZigVar *var = add_variable(ira->codegen, param_decl_node, | 13438 | ZigVar *var = add_variable(ira->codegen, param_decl_node, |
| 12862 | *exec_scope, param_name, true, arg_val, nullptr); | 13439 | *exec_scope, param_name, true, arg_val, nullptr, arg_val->type); |
| 12863 | *exec_scope = var->child_scope; | 13440 | *exec_scope = var->child_scope; |
| 12864 | *next_proto_i += 1; | 13441 | *next_proto_i += 1; |
| 12865 | 13442 | ||
| ... | @@ -12917,7 +13494,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -12917,7 +13494,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 12917 | if (!param_name) return false; | 13494 | if (!param_name) return false; |
| 12918 | if (!is_var_args) { | 13495 | if (!is_var_args) { |
| 12919 | ZigVar *var = add_variable(ira->codegen, param_decl_node, | 13496 | ZigVar *var = add_variable(ira->codegen, param_decl_node, |
| 12920 | *child_scope, param_name, true, arg_val, nullptr); | 13497 | *child_scope, param_name, true, arg_val, nullptr, arg_val->type); |
| 12921 | *child_scope = var->child_scope; | 13498 | *child_scope = var->child_scope; |
| 12922 | var->shadowable = !comptime_arg; | 13499 | var->shadowable = !comptime_arg; |
| 12923 | 13500 | ||
| ... | @@ -12971,9 +13548,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { | ... | @@ -12971,9 +13548,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { |
| 12971 | return fn_entry->variable_list.at(next_var_i); | 13548 | return fn_entry->variable_list.at(next_var_i); |
| 12972 | } | 13549 | } |
| 12973 | 13550 | ||
| 12974 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | 13551 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) { |
| 12975 | ZigVar *var) | ||
| 12976 | { | ||
| 12977 | while (var->next_var != nullptr) { | 13552 | while (var->next_var != nullptr) { |
| 12978 | var = var->next_var; | 13553 | var = var->next_var; |
| 12979 | } | 13554 | } |
| ... | @@ -12982,14 +13557,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | ... | @@ -12982,14 +13557,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 12982 | assert(ira->codegen->errors.length != 0); | 13557 | assert(ira->codegen->errors.length != 0); |
| 12983 | return ira->codegen->invalid_instruction; | 13558 | return ira->codegen->invalid_instruction; |
| 12984 | } | 13559 | } |
| 12985 | if (var->value->type == nullptr || type_is_invalid(var->value->type)) | 13560 | if (var->var_type == nullptr || type_is_invalid(var->var_type)) |
| 12986 | return ira->codegen->invalid_instruction; | 13561 | return ira->codegen->invalid_instruction; |
| 12987 | 13562 | ||
| 12988 | bool comptime_var_mem = ir_get_var_is_comptime(var); | 13563 | bool comptime_var_mem = ir_get_var_is_comptime(var); |
| 12989 | 13564 | ||
| 12990 | ConstExprValue *mem_slot = nullptr; | 13565 | ConstExprValue *mem_slot = nullptr; |
| 12991 | if (var->value->special == ConstValSpecialStatic) { | 13566 | if (var->const_value->special == ConstValSpecialStatic) { |
| 12992 | mem_slot = var->value; | 13567 | mem_slot = var->const_value; |
| 12993 | } else { | 13568 | } else { |
| 12994 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { | 13569 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { |
| 12995 | // find the relevant exec_context | 13570 | // find the relevant exec_context |
| ... | @@ -13018,7 +13593,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | ... | @@ -13018,7 +13593,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 13018 | assert(!comptime_var_mem); | 13593 | assert(!comptime_var_mem); |
| 13019 | ptr_mut = ConstPtrMutRuntimeVar; | 13594 | ptr_mut = ConstPtrMutRuntimeVar; |
| 13020 | } | 13595 | } |
| 13021 | return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type, | 13596 | return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type, |
| 13022 | ptr_mut, is_const, is_volatile, var->align_bytes); | 13597 | ptr_mut, is_const, is_volatile, var->align_bytes); |
| 13023 | } | 13598 | } |
| 13024 | } | 13599 | } |
| ... | @@ -13029,7 +13604,7 @@ no_mem_slot: | ... | @@ -13029,7 +13604,7 @@ no_mem_slot: |
| 13029 | 13604 | ||
| 13030 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, | 13605 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, |
| 13031 | instruction->scope, instruction->source_node, var); | 13606 | instruction->scope, instruction->source_node, var); |
| 13032 | var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type, | 13607 | var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type, |
| 13033 | var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0); | 13608 | var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0); |
| 13034 | 13609 | ||
| 13035 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); | 13610 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); |
| ... | @@ -13038,6 +13613,96 @@ no_mem_slot: | ... | @@ -13038,6 +13613,96 @@ no_mem_slot: |
| 13038 | return var_ptr_instruction; | 13613 | return var_ptr_instruction; |
| 13039 | } | 13614 | } |
| 13040 | 13615 | ||
| 13616 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 13617 | IrInstruction *ptr, IrInstruction *uncasted_value) | ||
| 13618 | { | ||
| 13619 | if (ptr->value.type->id != ZigTypeIdPointer) { | ||
| 13620 | ir_add_error(ira, ptr, | ||
| 13621 | buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); | ||
| 13622 | return ira->codegen->invalid_instruction; | ||
| 13623 | } | ||
| 13624 | |||
| 13625 | if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { | ||
| 13626 | return ir_const_void(ira, source_instr); | ||
| 13627 | } | ||
| 13628 | |||
| 13629 | if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) { | ||
| 13630 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | ||
| 13631 | return ira->codegen->invalid_instruction; | ||
| 13632 | } | ||
| 13633 | |||
| 13634 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | ||
| 13635 | IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); | ||
| 13636 | if (value == ira->codegen->invalid_instruction) | ||
| 13637 | return ira->codegen->invalid_instruction; | ||
| 13638 | |||
| 13639 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | ||
| 13640 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { | ||
| 13641 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | ||
| 13642 | return ira->codegen->invalid_instruction; | ||
| 13643 | } | ||
| 13644 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { | ||
| 13645 | if (instr_is_comptime(value)) { | ||
| 13646 | ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node); | ||
| 13647 | if (dest_val == nullptr) | ||
| 13648 | return ira->codegen->invalid_instruction; | ||
| 13649 | if (dest_val->special != ConstValSpecialRuntime) { | ||
| 13650 | // TODO this allows a value stored to have the original value modified and then | ||
| 13651 | // have that affect what should be a copy. We need some kind of advanced copy-on-write | ||
| 13652 | // system to make these two tests pass at the same time: | ||
| 13653 | // * "string literal used as comptime slice is memoized" | ||
| 13654 | // * "comptime modification of const struct field" - except modified to avoid | ||
| 13655 | // ConstPtrMutComptimeVar, thus defeating the logic below. | ||
| 13656 | bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar; | ||
| 13657 | copy_const_val(dest_val, &value->value, same_global_refs); | ||
| 13658 | if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { | ||
| 13659 | switch (type_has_one_possible_value(ira->codegen, child_type)) { | ||
| 13660 | case OnePossibleValueInvalid: | ||
| 13661 | return ira->codegen->invalid_instruction; | ||
| 13662 | case OnePossibleValueNo: | ||
| 13663 | ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr; | ||
| 13664 | break; | ||
| 13665 | case OnePossibleValueYes: | ||
| 13666 | break; | ||
| 13667 | } | ||
| 13668 | } | ||
| 13669 | return ir_const_void(ira, source_instr); | ||
| 13670 | } | ||
| 13671 | } | ||
| 13672 | ir_add_error(ira, source_instr, | ||
| 13673 | buf_sprintf("cannot store runtime value in compile time variable")); | ||
| 13674 | ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); | ||
| 13675 | dest_val->type = ira->codegen->builtin_types.entry_invalid; | ||
| 13676 | |||
| 13677 | return ira->codegen->invalid_instruction; | ||
| 13678 | } | ||
| 13679 | } | ||
| 13680 | |||
| 13681 | switch (type_requires_comptime(ira->codegen, child_type)) { | ||
| 13682 | case ReqCompTimeInvalid: | ||
| 13683 | return ira->codegen->invalid_instruction; | ||
| 13684 | case ReqCompTimeYes: | ||
| 13685 | switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) { | ||
| 13686 | case OnePossibleValueInvalid: | ||
| 13687 | return ira->codegen->invalid_instruction; | ||
| 13688 | case OnePossibleValueNo: | ||
| 13689 | ir_add_error(ira, source_instr, | ||
| 13690 | buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name))); | ||
| 13691 | return ira->codegen->invalid_instruction; | ||
| 13692 | case OnePossibleValueYes: | ||
| 13693 | return ir_const_void(ira, source_instr); | ||
| 13694 | } | ||
| 13695 | zig_unreachable(); | ||
| 13696 | case ReqCompTimeNo: | ||
| 13697 | break; | ||
| 13698 | } | ||
| 13699 | |||
| 13700 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, | ||
| 13701 | ptr, value); | ||
| 13702 | result->value.type = ira->codegen->builtin_types.entry_void; | ||
| 13703 | return result; | ||
| 13704 | } | ||
| 13705 | |||
| 13041 | static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, | 13706 | static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, |
| 13042 | ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, | 13707 | ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, |
| 13043 | IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline) | 13708 | IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline) |
| ... | @@ -13182,7 +13847,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13182,7 +13847,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13182 | } | 13847 | } |
| 13183 | 13848 | ||
| 13184 | bool cacheable = fn_eval_cacheable(exec_scope, return_type); | 13849 | bool cacheable = fn_eval_cacheable(exec_scope, return_type); |
| 13185 | IrInstruction *result = nullptr; | 13850 | ConstExprValue *result = nullptr; |
| 13186 | if (cacheable) { | 13851 | if (cacheable) { |
| 13187 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); | 13852 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); |
| 13188 | if (entry) | 13853 | if (entry) |
| ... | @@ -13194,22 +13859,23 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13194,22 +13859,23 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13194 | AstNode *body_node = fn_entry->body_node; | 13859 | AstNode *body_node = fn_entry->body_node; |
| 13195 | result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, | 13860 | result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, |
| 13196 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, | 13861 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, |
| 13197 | nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); | 13862 | nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node); |
| 13198 | 13863 | ||
| 13199 | if (inferred_err_set_type != nullptr) { | 13864 | if (inferred_err_set_type != nullptr) { |
| 13200 | inferred_err_set_type->data.error_set.infer_fn = nullptr; | 13865 | inferred_err_set_type->data.error_set.infer_fn = nullptr; |
| 13201 | if (result->value.type->id == ZigTypeIdErrorUnion) { | 13866 | if (result->type->id == ZigTypeIdErrorUnion) { |
| 13202 | if (result->value.data.x_err_union.err != nullptr) { | 13867 | ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set; |
| 13868 | if (err != nullptr) { | ||
| 13203 | inferred_err_set_type->data.error_set.err_count = 1; | 13869 | inferred_err_set_type->data.error_set.err_count = 1; |
| 13204 | inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1); | 13870 | inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1); |
| 13205 | inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err; | 13871 | inferred_err_set_type->data.error_set.errors[0] = err; |
| 13206 | } | 13872 | } |
| 13207 | ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type; | 13873 | ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type; |
| 13208 | inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count; | 13874 | inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count; |
| 13209 | inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors; | 13875 | inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors; |
| 13210 | } else if (result->value.type->id == ZigTypeIdErrorSet) { | 13876 | } else if (result->type->id == ZigTypeIdErrorSet) { |
| 13211 | inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count; | 13877 | inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count; |
| 13212 | inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors; | 13878 | inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors; |
| 13213 | } | 13879 | } |
| 13214 | } | 13880 | } |
| 13215 | 13881 | ||
| ... | @@ -13217,13 +13883,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13217,13 +13883,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13217 | ira->codegen->memoized_fn_eval_table.put(exec_scope, result); | 13883 | ira->codegen->memoized_fn_eval_table.put(exec_scope, result); |
| 13218 | } | 13884 | } |
| 13219 | 13885 | ||
| 13220 | if (type_is_invalid(result->value.type)) | 13886 | if (type_is_invalid(result->type)) |
| 13221 | return ira->codegen->invalid_instruction; | 13887 | return ira->codegen->invalid_instruction; |
| 13222 | } | 13888 | } |
| 13223 | 13889 | ||
| 13224 | IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type); | 13890 | IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type); |
| 13225 | // TODO should we use copy_const_val? | 13891 | copy_const_val(&new_instruction->value, result, true); |
| 13226 | new_instruction->value = result->value; | ||
| 13227 | new_instruction->value.type = return_type; | 13892 | new_instruction->value.type = return_type; |
| 13228 | return ir_finish_anal(ira, new_instruction); | 13893 | return ir_finish_anal(ira, new_instruction); |
| 13229 | } | 13894 | } |
| ... | @@ -13382,18 +14047,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13382,18 +14047,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13382 | ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen, | 14047 | ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen, |
| 13383 | first_var_arg, inst_fn_type_id.param_count); | 14048 | first_var_arg, inst_fn_type_id.param_count); |
| 13384 | ZigVar *var = add_variable(ira->codegen, param_decl_node, | 14049 | ZigVar *var = add_variable(ira->codegen, param_decl_node, |
| 13385 | impl_fn->child_scope, param_name, true, var_args_val, nullptr); | 14050 | impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type); |
| 13386 | impl_fn->child_scope = var->child_scope; | 14051 | impl_fn->child_scope = var->child_scope; |
| 13387 | } | 14052 | } |
| 13388 | 14053 | ||
| 13389 | if (fn_proto_node->data.fn_proto.align_expr != nullptr) { | 14054 | if (fn_proto_node->data.fn_proto.align_expr != nullptr) { |
| 13390 | IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, | 14055 | ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, |
| 13391 | fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), | 14056 | fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), |
| 13392 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | 14057 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, |
| 13393 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec); | 14058 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr); |
| 14059 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | ||
| 14060 | impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); | ||
| 14061 | const_instruction->base.value = *align_result; | ||
| 13394 | 14062 | ||
| 13395 | uint32_t align_bytes = 0; | 14063 | uint32_t align_bytes = 0; |
| 13396 | ir_resolve_align(ira, align_result, &align_bytes); | 14064 | ir_resolve_align(ira, &const_instruction->base, &align_bytes); |
| 13397 | impl_fn->align_bytes = align_bytes; | 14065 | impl_fn->align_bytes = align_bytes; |
| 13398 | inst_fn_type_id.alignment = align_bytes; | 14066 | inst_fn_type_id.alignment = align_bytes; |
| 13399 | } | 14067 | } |
| ... | @@ -13471,12 +14139,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13471,12 +14139,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13471 | ira->codegen->fn_defs.append(impl_fn); | 14139 | ira->codegen->fn_defs.append(impl_fn); |
| 13472 | } | 14140 | } |
| 13473 | 14141 | ||
| 13474 | ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; | 14142 | FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id; |
| 13475 | if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) { | 14143 | if (fn_type_can_fail(impl_fn_type_id)) { |
| 13476 | parent_fn_entry->calls_or_awaits_errorable_fn = true; | 14144 | parent_fn_entry->calls_or_awaits_errorable_fn = true; |
| 13477 | } | 14145 | } |
| 13478 | 14146 | ||
| 13479 | size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count; | 14147 | size_t impl_param_count = impl_fn_type_id->param_count; |
| 13480 | if (call_instruction->is_async) { | 14148 | if (call_instruction->is_async) { |
| 13481 | IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, | 14149 | IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, |
| 13482 | fn_ref, casted_args, impl_param_count, async_allocator_inst); | 14150 | fn_ref, casted_args, impl_param_count, async_allocator_inst); |
| ... | @@ -13489,9 +14157,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13489,9 +14157,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13489 | call_instruction->base.scope, call_instruction->base.source_node, | 14157 | call_instruction->base.scope, call_instruction->base.source_node, |
| 13490 | impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, | 14158 | impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, |
| 13491 | call_instruction->is_async, nullptr, casted_new_stack); | 14159 | call_instruction->is_async, nullptr, casted_new_stack); |
| 13492 | new_call_instruction->value.type = return_type; | 14160 | new_call_instruction->value.type = impl_fn_type_id->return_type; |
| 13493 | 14161 | ||
| 13494 | ir_add_alloca(ira, new_call_instruction, return_type); | 14162 | ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type); |
| 13495 | 14163 | ||
| 13496 | return ir_finish_anal(ira, new_call_instruction); | 14164 | return ir_finish_anal(ira, new_call_instruction); |
| 13497 | } | 14165 | } |
| ... | @@ -13653,39 +14321,87 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC | ... | @@ -13653,39 +14321,87 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC |
| 13653 | 14321 | ||
| 13654 | // out_val->type must be the type to read the pointer as | 14322 | // out_val->type must be the type to read the pointer as |
| 13655 | // if the type is different than the actual type then it does a comptime byte reinterpretation | 14323 | // if the type is different than the actual type then it does a comptime byte reinterpretation |
| 13656 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | 14324 | static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, |
| 13657 | ConstExprValue *out_val, ConstExprValue *ptr_val) | 14325 | ConstExprValue *out_val, ConstExprValue *ptr_val) |
| 13658 | { | 14326 | { |
| 13659 | Error err; | 14327 | Error err; |
| 13660 | assert(out_val->type != nullptr); | 14328 | assert(out_val->type != nullptr); |
| 13661 | 14329 | ||
| 13662 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val); | 14330 | ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val); |
| 13663 | 14331 | ||
| 13664 | if ((err = type_resolve(ira->codegen, pointee->type, ResolveStatusSizeKnown))) | 14332 | if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown))) |
| 13665 | return ErrorSemanticAnalyzeFail; | 14333 | return ErrorSemanticAnalyzeFail; |
| 13666 | if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown))) | 14334 | if ((err = type_resolve(codegen, out_val->type, ResolveStatusSizeKnown))) |
| 13667 | return ErrorSemanticAnalyzeFail; | 14335 | return ErrorSemanticAnalyzeFail; |
| 13668 | 14336 | ||
| 13669 | size_t src_size = type_size(ira->codegen, pointee->type); | 14337 | // We don't need to read the padding bytes, so we look at type_size_store bytes |
| 13670 | size_t dst_size = type_size(ira->codegen, out_val->type); | 14338 | size_t src_size = type_size_store(codegen, pointee->type); |
| 14339 | size_t dst_size = type_size_store(codegen, out_val->type); | ||
| 13671 | 14340 | ||
| 13672 | if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) { | 14341 | if (dst_size <= src_size) { |
| 13673 | copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | 14342 | if (types_have_same_zig_comptime_repr(pointee->type, out_val->type)) { |
| 14343 | copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | ||
| 14344 | return ErrorNone; | ||
| 14345 | } | ||
| 14346 | Buf buf = BUF_INIT; | ||
| 14347 | buf_resize(&buf, src_size); | ||
| 14348 | buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee); | ||
| 14349 | if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val))) | ||
| 14350 | return err; | ||
| 13674 | return ErrorNone; | 14351 | return ErrorNone; |
| 13675 | } | 14352 | } |
| 13676 | 14353 | ||
| 13677 | if (dst_size > src_size) { | 14354 | switch (ptr_val->data.x_ptr.special) { |
| 13678 | ir_add_error_node(ira, source_node, | 14355 | case ConstPtrSpecialInvalid: |
| 13679 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", | 14356 | zig_unreachable(); |
| 13680 | dst_size, buf_ptr(&pointee->type->name), src_size)); | 14357 | case ConstPtrSpecialNull: |
| 13681 | return ErrorSemanticAnalyzeFail; | 14358 | if (dst_size == 0) |
| 14359 | return ErrorNone; | ||
| 14360 | opt_ir_add_error_node(ira, codegen, source_node, | ||
| 14361 | buf_sprintf("attempt to read %zu bytes from null pointer", | ||
| 14362 | dst_size)); | ||
| 14363 | return ErrorSemanticAnalyzeFail; | ||
| 14364 | case ConstPtrSpecialRef: { | ||
| 14365 | opt_ir_add_error_node(ira, codegen, source_node, | ||
| 14366 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", | ||
| 14367 | dst_size, buf_ptr(&pointee->type->name), src_size)); | ||
| 14368 | return ErrorSemanticAnalyzeFail; | ||
| 14369 | } | ||
| 14370 | case ConstPtrSpecialBaseArray: { | ||
| 14371 | ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val; | ||
| 14372 | assert(array_val->type->id == ZigTypeIdArray); | ||
| 14373 | if (array_val->data.x_array.special != ConstArraySpecialNone) | ||
| 14374 | zig_panic("TODO"); | ||
| 14375 | size_t elem_size = src_size; | ||
| 14376 | size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index; | ||
| 14377 | src_size = elem_size * (array_val->type->data.array.len - elem_index); | ||
| 14378 | if (dst_size > src_size) { | ||
| 14379 | opt_ir_add_error_node(ira, codegen, source_node, | ||
| 14380 | buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes", | ||
| 14381 | dst_size, buf_ptr(&array_val->type->name), elem_index, src_size)); | ||
| 14382 | return ErrorSemanticAnalyzeFail; | ||
| 14383 | } | ||
| 14384 | size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1); | ||
| 14385 | Buf buf = BUF_INIT; | ||
| 14386 | buf_resize(&buf, elem_count * elem_size); | ||
| 14387 | for (size_t i = 0; i < elem_count; i += 1) { | ||
| 14388 | ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; | ||
| 14389 | buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); | ||
| 14390 | } | ||
| 14391 | if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val))) | ||
| 14392 | return err; | ||
| 14393 | return ErrorNone; | ||
| 14394 | } | ||
| 14395 | case ConstPtrSpecialBaseStruct: | ||
| 14396 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 14397 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 14398 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 14399 | case ConstPtrSpecialDiscard: | ||
| 14400 | case ConstPtrSpecialHardCodedAddr: | ||
| 14401 | case ConstPtrSpecialFunction: | ||
| 14402 | zig_panic("TODO"); | ||
| 13682 | } | 14403 | } |
| 13683 | 14404 | zig_unreachable(); | |
| 13684 | Buf buf = BUF_INIT; | ||
| 13685 | buf_resize(&buf, src_size); | ||
| 13686 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); | ||
| 13687 | buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); | ||
| 13688 | return ErrorNone; | ||
| 13689 | } | 14405 | } |
| 13690 | 14406 | ||
| 13691 | static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | 14407 | static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| ... | @@ -13704,6 +14420,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_ | ... | @@ -13704,6 +14420,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_ |
| 13704 | case ZigTypeIdVoid: | 14420 | case ZigTypeIdVoid: |
| 13705 | case ZigTypeIdBool: | 14421 | case ZigTypeIdBool: |
| 13706 | case ZigTypeIdInt: | 14422 | case ZigTypeIdInt: |
| 14423 | case ZigTypeIdVector: | ||
| 13707 | case ZigTypeIdFloat: | 14424 | case ZigTypeIdFloat: |
| 13708 | case ZigTypeIdPointer: | 14425 | case ZigTypeIdPointer: |
| 13709 | case ZigTypeIdArray: | 14426 | case ZigTypeIdArray: |
| ... | @@ -13875,9 +14592,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi | ... | @@ -13875,9 +14592,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi |
| 13875 | if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime)) | 14592 | if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime)) |
| 13876 | return ir_unreach_error(ira); | 14593 | return ir_unreach_error(ira); |
| 13877 | 14594 | ||
| 13878 | if (is_comptime || instr_is_comptime(condition)) { | 14595 | ZigType *bool_type = ira->codegen->builtin_types.entry_bool; |
| 14596 | IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); | ||
| 14597 | if (type_is_invalid(casted_condition->value.type)) | ||
| 14598 | return ir_unreach_error(ira); | ||
| 14599 | |||
| 14600 | if (is_comptime || instr_is_comptime(casted_condition)) { | ||
| 13879 | bool cond_is_true; | 14601 | bool cond_is_true; |
| 13880 | if (!ir_resolve_bool(ira, condition, &cond_is_true)) | 14602 | if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) |
| 13881 | return ir_unreach_error(ira); | 14603 | return ir_unreach_error(ira); |
| 13882 | 14604 | ||
| 13883 | IrBasicBlock *old_dest_block = cond_is_true ? | 14605 | IrBasicBlock *old_dest_block = cond_is_true ? |
| ... | @@ -13896,11 +14618,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi | ... | @@ -13896,11 +14618,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi |
| 13896 | return ir_finish_anal(ira, result); | 14618 | return ir_finish_anal(ira, result); |
| 13897 | } | 14619 | } |
| 13898 | 14620 | ||
| 13899 | ZigType *bool_type = ira->codegen->builtin_types.entry_bool; | ||
| 13900 | IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); | ||
| 13901 | if (casted_condition == ira->codegen->invalid_instruction) | ||
| 13902 | return ir_unreach_error(ira); | ||
| 13903 | |||
| 13904 | assert(cond_br_instruction->then_block != cond_br_instruction->else_block); | 14621 | assert(cond_br_instruction->then_block != cond_br_instruction->else_block); |
| 13905 | IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base); | 14622 | IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base); |
| 13906 | if (new_then_block == nullptr) | 14623 | if (new_then_block == nullptr) |
| ... | @@ -13939,8 +14656,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh | ... | @@ -13939,8 +14656,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 13939 | 14656 | ||
| 13940 | if (value->value.special != ConstValSpecialRuntime) { | 14657 | if (value->value.special != ConstValSpecialRuntime) { |
| 13941 | IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr); | 14658 | IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr); |
| 13942 | // TODO use copy_const_val? | 14659 | copy_const_val(&result->value, &value->value, true); |
| 13943 | result->value = value->value; | ||
| 13944 | return result; | 14660 | return result; |
| 13945 | } else { | 14661 | } else { |
| 13946 | return value; | 14662 | return value; |
| ... | @@ -13989,14 +14705,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh | ... | @@ -13989,14 +14705,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 13989 | if (type_is_invalid(resolved_type)) | 14705 | if (type_is_invalid(resolved_type)) |
| 13990 | return ira->codegen->invalid_instruction; | 14706 | return ira->codegen->invalid_instruction; |
| 13991 | 14707 | ||
| 13992 | if (resolved_type->id == ZigTypeIdComptimeFloat || | 14708 | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { |
| 13993 | resolved_type->id == ZigTypeIdComptimeInt || | 14709 | case OnePossibleValueInvalid: |
| 13994 | resolved_type->id == ZigTypeIdNull || | 14710 | return ira->codegen->invalid_instruction; |
| 13995 | resolved_type->id == ZigTypeIdUndefined) | 14711 | case OnePossibleValueYes: |
| 13996 | { | 14712 | return ir_const(ira, &phi_instruction->base, resolved_type); |
| 14713 | case OnePossibleValueNo: | ||
| 14714 | break; | ||
| 14715 | } | ||
| 14716 | |||
| 14717 | switch (type_requires_comptime(ira->codegen, resolved_type)) { | ||
| 14718 | case ReqCompTimeInvalid: | ||
| 14719 | return ira->codegen->invalid_instruction; | ||
| 14720 | case ReqCompTimeYes: | ||
| 13997 | ir_add_error_node(ira, phi_instruction->base.source_node, | 14721 | ir_add_error_node(ira, phi_instruction->base.source_node, |
| 13998 | buf_sprintf("unable to infer expression type")); | 14722 | buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name))); |
| 13999 | return ira->codegen->invalid_instruction; | 14723 | return ira->codegen->invalid_instruction; |
| 14724 | case ReqCompTimeNo: | ||
| 14725 | break; | ||
| 14000 | } | 14726 | } |
| 14001 | 14727 | ||
| 14002 | bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer); | 14728 | bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer); |
| ... | @@ -14112,7 +14838,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -14112,7 +14838,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14112 | array_type = array_type->data.pointer.child_type; | 14838 | array_type = array_type->data.pointer.child_type; |
| 14113 | ptr_type = ptr_type->data.pointer.child_type; | 14839 | ptr_type = ptr_type->data.pointer.child_type; |
| 14114 | if (orig_array_ptr_val->special != ConstValSpecialRuntime) { | 14840 | if (orig_array_ptr_val->special != ConstValSpecialRuntime) { |
| 14115 | orig_array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val, | 14841 | orig_array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, |
| 14116 | elem_ptr_instruction->base.source_node); | 14842 | elem_ptr_instruction->base.source_node); |
| 14117 | if (orig_array_ptr_val == nullptr) | 14843 | if (orig_array_ptr_val == nullptr) |
| 14118 | return ira->codegen->invalid_instruction; | 14844 | return ira->codegen->invalid_instruction; |
| ... | @@ -14156,7 +14882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -14156,7 +14882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14156 | ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); | 14882 | ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); |
| 14157 | if (!ptr_val) | 14883 | if (!ptr_val) |
| 14158 | return ira->codegen->invalid_instruction; | 14884 | return ira->codegen->invalid_instruction; |
| 14159 | ConstExprValue *args_val = ir_const_ptr_pointee(ira, ptr_val, elem_ptr_instruction->base.source_node); | 14885 | ConstExprValue *args_val = const_ptr_pointee(ira, ira->codegen, ptr_val, elem_ptr_instruction->base.source_node); |
| 14160 | if (args_val == nullptr) | 14886 | if (args_val == nullptr) |
| 14161 | return ira->codegen->invalid_instruction; | 14887 | return ira->codegen->invalid_instruction; |
| 14162 | size_t start = args_val->data.x_arg_tuple.start_index; | 14888 | size_t start = args_val->data.x_arg_tuple.start_index; |
| ... | @@ -14238,7 +14964,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -14238,7 +14964,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14238 | (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || | 14964 | (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || |
| 14239 | array_type->id == ZigTypeIdArray)) | 14965 | array_type->id == ZigTypeIdArray)) |
| 14240 | { | 14966 | { |
| 14241 | ConstExprValue *array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val, | 14967 | ConstExprValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, |
| 14242 | elem_ptr_instruction->base.source_node); | 14968 | elem_ptr_instruction->base.source_node); |
| 14243 | if (array_ptr_val == nullptr) | 14969 | if (array_ptr_val == nullptr) |
| 14244 | return ira->codegen->invalid_instruction; | 14970 | return ira->codegen->invalid_instruction; |
| ... | @@ -14286,10 +15012,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -14286,10 +15012,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14286 | } | 15012 | } |
| 14287 | case ConstPtrSpecialBaseStruct: | 15013 | case ConstPtrSpecialBaseStruct: |
| 14288 | zig_panic("TODO elem ptr on a const inner struct"); | 15014 | zig_panic("TODO elem ptr on a const inner struct"); |
| 15015 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 15016 | zig_panic("TODO elem ptr on a const inner error union code"); | ||
| 15017 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 15018 | zig_panic("TODO elem ptr on a const inner error union payload"); | ||
| 15019 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 15020 | zig_panic("TODO elem ptr on a const inner optional payload"); | ||
| 14289 | case ConstPtrSpecialHardCodedAddr: | 15021 | case ConstPtrSpecialHardCodedAddr: |
| 14290 | zig_unreachable(); | 15022 | zig_unreachable(); |
| 14291 | case ConstPtrSpecialFunction: | 15023 | case ConstPtrSpecialFunction: |
| 14292 | zig_panic("TODO element ptr of a function casted to a ptr"); | 15024 | zig_panic("TODO element ptr of a function casted to a ptr"); |
| 15025 | case ConstPtrSpecialNull: | ||
| 15026 | zig_panic("TODO elem ptr on a null pointer"); | ||
| 14293 | } | 15027 | } |
| 14294 | if (new_index >= mem_size) { | 15028 | if (new_index >= mem_size) { |
| 14295 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 15029 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| ... | @@ -14339,10 +15073,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -14339,10 +15073,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14339 | } | 15073 | } |
| 14340 | case ConstPtrSpecialBaseStruct: | 15074 | case ConstPtrSpecialBaseStruct: |
| 14341 | zig_panic("TODO elem ptr on a slice backed by const inner struct"); | 15075 | zig_panic("TODO elem ptr on a slice backed by const inner struct"); |
| 15076 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 15077 | zig_panic("TODO elem ptr on a slice backed by const inner error union code"); | ||
| 15078 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 15079 | zig_panic("TODO elem ptr on a slice backed by const inner error union payload"); | ||
| 15080 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 15081 | zig_panic("TODO elem ptr on a slice backed by const optional payload"); | ||
| 14342 | case ConstPtrSpecialHardCodedAddr: | 15082 | case ConstPtrSpecialHardCodedAddr: |
| 14343 | zig_unreachable(); | 15083 | zig_unreachable(); |
| 14344 | case ConstPtrSpecialFunction: | 15084 | case ConstPtrSpecialFunction: |
| 14345 | zig_panic("TODO elem ptr on a slice that was ptrcast from a function"); | 15085 | zig_panic("TODO elem ptr on a slice that was ptrcast from a function"); |
| 15086 | case ConstPtrSpecialNull: | ||
| 15087 | zig_panic("TODO elem ptr on a slice has a null pointer"); | ||
| 14346 | } | 15088 | } |
| 14347 | return result; | 15089 | return result; |
| 14348 | } else if (array_type->id == ZigTypeIdArray) { | 15090 | } else if (array_type->id == ZigTypeIdArray) { |
| ... | @@ -14457,13 +15199,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -14457,13 +15199,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 14457 | return ira->codegen->invalid_instruction; | 15199 | return ira->codegen->invalid_instruction; |
| 14458 | 15200 | ||
| 14459 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | 15201 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 14460 | ConstExprValue *struct_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node); | 15202 | ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 14461 | if (struct_val == nullptr) | 15203 | if (struct_val == nullptr) |
| 14462 | return ira->codegen->invalid_instruction; | 15204 | return ira->codegen->invalid_instruction; |
| 14463 | if (type_is_invalid(struct_val->type)) | 15205 | if (type_is_invalid(struct_val->type)) |
| 14464 | return ira->codegen->invalid_instruction; | 15206 | return ira->codegen->invalid_instruction; |
| 14465 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; | 15207 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, |
| 14466 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, | ||
| 14467 | is_const, is_volatile, PtrLenSingle, align_bytes, | 15208 | is_const, is_volatile, PtrLenSingle, align_bytes, |
| 14468 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), | 15209 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), |
| 14469 | (uint32_t)host_int_bytes_for_result_type); | 15210 | (uint32_t)host_int_bytes_for_result_type); |
| ... | @@ -14500,7 +15241,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -14500,7 +15241,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 14500 | return ira->codegen->invalid_instruction; | 15241 | return ira->codegen->invalid_instruction; |
| 14501 | 15242 | ||
| 14502 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | 15243 | if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 14503 | ConstExprValue *union_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node); | 15244 | ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 14504 | if (union_val == nullptr) | 15245 | if (union_val == nullptr) |
| 14505 | return ira->codegen->invalid_instruction; | 15246 | return ira->codegen->invalid_instruction; |
| 14506 | if (type_is_invalid(union_val->type)) | 15247 | if (type_is_invalid(union_val->type)) |
| ... | @@ -14697,7 +15438,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -14697,7 +15438,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc |
| 14697 | return ira->codegen->invalid_instruction; | 15438 | return ira->codegen->invalid_instruction; |
| 14698 | 15439 | ||
| 14699 | assert(container_ptr->value.type->id == ZigTypeIdPointer); | 15440 | assert(container_ptr->value.type->id == ZigTypeIdPointer); |
| 14700 | ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node); | 15441 | ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node); |
| 14701 | if (child_val == nullptr) | 15442 | if (child_val == nullptr) |
| 14702 | return ira->codegen->invalid_instruction; | 15443 | return ira->codegen->invalid_instruction; |
| 14703 | 15444 | ||
| ... | @@ -14723,7 +15464,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -14723,7 +15464,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc |
| 14723 | return ira->codegen->invalid_instruction; | 15464 | return ira->codegen->invalid_instruction; |
| 14724 | 15465 | ||
| 14725 | assert(container_ptr->value.type->id == ZigTypeIdPointer); | 15466 | assert(container_ptr->value.type->id == ZigTypeIdPointer); |
| 14726 | ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node); | 15467 | ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node); |
| 14727 | if (child_val == nullptr) | 15468 | if (child_val == nullptr) |
| 14728 | return ira->codegen->invalid_instruction; | 15469 | return ira->codegen->invalid_instruction; |
| 14729 | ZigType *child_type = child_val->data.x_type; | 15470 | ZigType *child_type = child_val->data.x_type; |
| ... | @@ -14998,7 +15739,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -14998,7 +15739,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc |
| 14998 | if (!container_ptr_val) | 15739 | if (!container_ptr_val) |
| 14999 | return ira->codegen->invalid_instruction; | 15740 | return ira->codegen->invalid_instruction; |
| 15000 | 15741 | ||
| 15001 | ConstExprValue *namespace_val = ir_const_ptr_pointee(ira, container_ptr_val, | 15742 | ConstExprValue *namespace_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, |
| 15002 | field_ptr_instruction->base.source_node); | 15743 | field_ptr_instruction->base.source_node); |
| 15003 | if (namespace_val == nullptr) | 15744 | if (namespace_val == nullptr) |
| 15004 | return ira->codegen->invalid_instruction; | 15745 | return ira->codegen->invalid_instruction; |
| ... | @@ -15030,74 +15771,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -15030,74 +15771,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc |
| 15030 | } | 15771 | } |
| 15031 | } | 15772 | } |
| 15032 | 15773 | ||
| 15033 | static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { | 15774 | static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) { |
| 15034 | IrInstruction *ptr = load_ptr_instruction->ptr->child; | 15775 | IrInstruction *ptr = instruction->ptr->child; |
| 15035 | if (type_is_invalid(ptr->value.type)) | ||
| 15036 | return ira->codegen->invalid_instruction; | ||
| 15037 | return ir_get_deref(ira, &load_ptr_instruction->base, ptr); | ||
| 15038 | } | ||
| 15039 | |||
| 15040 | static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { | ||
| 15041 | IrInstruction *ptr = store_ptr_instruction->ptr->child; | ||
| 15042 | if (type_is_invalid(ptr->value.type)) | 15776 | if (type_is_invalid(ptr->value.type)) |
| 15043 | return ira->codegen->invalid_instruction; | 15777 | return ira->codegen->invalid_instruction; |
| 15044 | 15778 | ||
| 15045 | IrInstruction *value = store_ptr_instruction->value->child; | 15779 | IrInstruction *value = instruction->value->child; |
| 15046 | if (type_is_invalid(value->value.type)) | 15780 | if (type_is_invalid(value->value.type)) |
| 15047 | return ira->codegen->invalid_instruction; | 15781 | return ira->codegen->invalid_instruction; |
| 15048 | 15782 | ||
| 15049 | if (ptr->value.type->id != ZigTypeIdPointer) { | 15783 | return ir_analyze_store_ptr(ira, &instruction->base, ptr, value); |
| 15050 | ir_add_error(ira, ptr, | 15784 | } |
| 15051 | buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); | ||
| 15052 | return ira->codegen->invalid_instruction; | ||
| 15053 | } | ||
| 15054 | |||
| 15055 | if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { | ||
| 15056 | return ir_const_void(ira, &store_ptr_instruction->base); | ||
| 15057 | } | ||
| 15058 | |||
| 15059 | if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) { | ||
| 15060 | ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); | ||
| 15061 | return ira->codegen->invalid_instruction; | ||
| 15062 | } | ||
| 15063 | 15785 | ||
| 15064 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | 15786 | static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) { |
| 15065 | IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type); | 15787 | IrInstruction *ptr = instruction->ptr->child; |
| 15066 | if (casted_value == ira->codegen->invalid_instruction) | 15788 | if (type_is_invalid(ptr->value.type)) |
| 15067 | return ira->codegen->invalid_instruction; | 15789 | return ira->codegen->invalid_instruction; |
| 15068 | 15790 | return ir_get_deref(ira, &instruction->base, ptr); | |
| 15069 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | ||
| 15070 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { | ||
| 15071 | ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); | ||
| 15072 | return ira->codegen->invalid_instruction; | ||
| 15073 | } | ||
| 15074 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { | ||
| 15075 | if (instr_is_comptime(casted_value)) { | ||
| 15076 | ConstExprValue *dest_val = ir_const_ptr_pointee(ira, &ptr->value, store_ptr_instruction->base.source_node); | ||
| 15077 | if (dest_val == nullptr) | ||
| 15078 | return ira->codegen->invalid_instruction; | ||
| 15079 | if (dest_val->special != ConstValSpecialRuntime) { | ||
| 15080 | *dest_val = casted_value->value; | ||
| 15081 | if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { | ||
| 15082 | ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base; | ||
| 15083 | } | ||
| 15084 | return ir_const_void(ira, &store_ptr_instruction->base); | ||
| 15085 | } | ||
| 15086 | } | ||
| 15087 | ir_add_error(ira, &store_ptr_instruction->base, | ||
| 15088 | buf_sprintf("cannot store runtime value in compile time variable")); | ||
| 15089 | ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); | ||
| 15090 | dest_val->type = ira->codegen->builtin_types.entry_invalid; | ||
| 15091 | |||
| 15092 | return ira->codegen->invalid_instruction; | ||
| 15093 | } | ||
| 15094 | } | ||
| 15095 | |||
| 15096 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, | ||
| 15097 | store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node, | ||
| 15098 | ptr, casted_value); | ||
| 15099 | result->value.type = ira->codegen->builtin_types.entry_void; | ||
| 15100 | return result; | ||
| 15101 | } | 15791 | } |
| 15102 | 15792 | ||
| 15103 | static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) { | 15793 | static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) { |
| ... | @@ -15105,42 +15795,14 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio | ... | @@ -15105,42 +15795,14 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio |
| 15105 | ZigType *type_entry = expr_value->value.type; | 15795 | ZigType *type_entry = expr_value->value.type; |
| 15106 | if (type_is_invalid(type_entry)) | 15796 | if (type_is_invalid(type_entry)) |
| 15107 | return ira->codegen->invalid_instruction; | 15797 | return ira->codegen->invalid_instruction; |
| 15108 | switch (type_entry->id) { | 15798 | return ir_const_type(ira, &typeof_instruction->base, type_entry); |
| 15109 | case ZigTypeIdInvalid: | ||
| 15110 | zig_unreachable(); // handled above | ||
| 15111 | case ZigTypeIdComptimeFloat: | ||
| 15112 | case ZigTypeIdComptimeInt: | ||
| 15113 | case ZigTypeIdUndefined: | ||
| 15114 | case ZigTypeIdNull: | ||
| 15115 | case ZigTypeIdNamespace: | ||
| 15116 | case ZigTypeIdBoundFn: | ||
| 15117 | case ZigTypeIdMetaType: | ||
| 15118 | case ZigTypeIdVoid: | ||
| 15119 | case ZigTypeIdBool: | ||
| 15120 | case ZigTypeIdUnreachable: | ||
| 15121 | case ZigTypeIdInt: | ||
| 15122 | case ZigTypeIdFloat: | ||
| 15123 | case ZigTypeIdPointer: | ||
| 15124 | case ZigTypeIdArray: | ||
| 15125 | case ZigTypeIdStruct: | ||
| 15126 | case ZigTypeIdOptional: | ||
| 15127 | case ZigTypeIdErrorUnion: | ||
| 15128 | case ZigTypeIdErrorSet: | ||
| 15129 | case ZigTypeIdEnum: | ||
| 15130 | case ZigTypeIdUnion: | ||
| 15131 | case ZigTypeIdFn: | ||
| 15132 | case ZigTypeIdArgTuple: | ||
| 15133 | case ZigTypeIdOpaque: | ||
| 15134 | case ZigTypeIdPromise: | ||
| 15135 | return ir_const_type(ira, &typeof_instruction->base, type_entry); | ||
| 15136 | } | ||
| 15137 | |||
| 15138 | zig_unreachable(); | ||
| 15139 | } | 15799 | } |
| 15140 | 15800 | ||
| 15141 | static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, | 15801 | static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| 15142 | IrInstructionToPtrType *to_ptr_type_instruction) | 15802 | IrInstructionToPtrType *to_ptr_type_instruction) |
| 15143 | { | 15803 | { |
| 15804 | Error err; | ||
| 15805 | |||
| 15144 | IrInstruction *value = to_ptr_type_instruction->value->child; | 15806 | IrInstruction *value = to_ptr_type_instruction->value->child; |
| 15145 | ZigType *type_entry = value->value.type; | 15807 | ZigType *type_entry = value->value.type; |
| 15146 | if (type_is_invalid(type_entry)) | 15808 | if (type_is_invalid(type_entry)) |
| ... | @@ -15156,7 +15818,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, | ... | @@ -15156,7 +15818,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| 15156 | ptr_type = get_pointer_to_type(ira->codegen, | 15818 | ptr_type = get_pointer_to_type(ira->codegen, |
| 15157 | type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const); | 15819 | type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const); |
| 15158 | } else if (is_slice(type_entry)) { | 15820 | } else if (is_slice(type_entry)) { |
| 15159 | ptr_type = adjust_ptr_len(ira->codegen, type_entry->data.structure.fields[0].type_entry, PtrLenSingle); | 15821 | ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry; |
| 15822 | ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle); | ||
| 15823 | // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type. | ||
| 15824 | if (slice_ptr_type->data.pointer.explicit_alignment != 0) { | ||
| 15825 | ZigType *elem_type = slice_ptr_type->data.pointer.child_type; | ||
| 15826 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown))) | ||
| 15827 | return ira->codegen->invalid_instruction; | ||
| 15828 | uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type); | ||
| 15829 | uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment); | ||
| 15830 | ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align); | ||
| 15831 | } | ||
| 15160 | } else if (type_entry->id == ZigTypeIdArgTuple) { | 15832 | } else if (type_entry->id == ZigTypeIdArgTuple) { |
| 15161 | ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad); | 15833 | ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad); |
| 15162 | if (!arg_tuple_val) | 15834 | if (!arg_tuple_val) |
| ... | @@ -15374,6 +16046,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -15374,6 +16046,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 15374 | case ZigTypeIdNamespace: | 16046 | case ZigTypeIdNamespace: |
| 15375 | case ZigTypeIdBoundFn: | 16047 | case ZigTypeIdBoundFn: |
| 15376 | case ZigTypeIdPromise: | 16048 | case ZigTypeIdPromise: |
| 16049 | case ZigTypeIdVector: | ||
| 15377 | { | 16050 | { |
| 15378 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) | 16051 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) |
| 15379 | return ira->codegen->invalid_instruction; | 16052 | return ira->codegen->invalid_instruction; |
| ... | @@ -15494,6 +16167,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, | ... | @@ -15494,6 +16167,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 15494 | case ZigTypeIdNamespace: | 16167 | case ZigTypeIdNamespace: |
| 15495 | case ZigTypeIdBoundFn: | 16168 | case ZigTypeIdBoundFn: |
| 15496 | case ZigTypeIdPromise: | 16169 | case ZigTypeIdPromise: |
| 16170 | case ZigTypeIdVector: | ||
| 15497 | { | 16171 | { |
| 15498 | if ((err = ensure_complete_type(ira->codegen, child_type))) | 16172 | if ((err = ensure_complete_type(ira->codegen, child_type))) |
| 15499 | return ira->codegen->invalid_instruction; | 16173 | return ira->codegen->invalid_instruction; |
| ... | @@ -15560,6 +16234,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -15560,6 +16234,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 15560 | case ZigTypeIdUnion: | 16234 | case ZigTypeIdUnion: |
| 15561 | case ZigTypeIdFn: | 16235 | case ZigTypeIdFn: |
| 15562 | case ZigTypeIdPromise: | 16236 | case ZigTypeIdPromise: |
| 16237 | case ZigTypeIdVector: | ||
| 15563 | { | 16238 | { |
| 15564 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); | 16239 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| 15565 | return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes); | 16240 | return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes); |
| ... | @@ -15568,11 +16243,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -15568,11 +16243,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 15568 | zig_unreachable(); | 16243 | zig_unreachable(); |
| 15569 | } | 16244 | } |
| 15570 | 16245 | ||
| 15571 | static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { | 16246 | static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) { |
| 15572 | IrInstruction *value = instruction->value->child; | ||
| 15573 | if (type_is_invalid(value->value.type)) | ||
| 15574 | return ira->codegen->invalid_instruction; | ||
| 15575 | |||
| 15576 | ZigType *type_entry = value->value.type; | 16247 | ZigType *type_entry = value->value.type; |
| 15577 | 16248 | ||
| 15578 | if (type_entry->id == ZigTypeIdOptional) { | 16249 | if (type_entry->id == ZigTypeIdOptional) { |
| ... | @@ -15581,60 +16252,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns | ... | @@ -15581,60 +16252,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns |
| 15581 | if (!maybe_val) | 16252 | if (!maybe_val) |
| 15582 | return ira->codegen->invalid_instruction; | 16253 | return ira->codegen->invalid_instruction; |
| 15583 | 16254 | ||
| 15584 | return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val)); | 16255 | return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val)); |
| 15585 | } | 16256 | } |
| 15586 | 16257 | ||
| 15587 | IrInstruction *result = ir_build_test_nonnull(&ira->new_irb, | 16258 | IrInstruction *result = ir_build_test_nonnull(&ira->new_irb, |
| 15588 | instruction->base.scope, instruction->base.source_node, value); | 16259 | source_inst->scope, source_inst->source_node, value); |
| 15589 | result->value.type = ira->codegen->builtin_types.entry_bool; | 16260 | result->value.type = ira->codegen->builtin_types.entry_bool; |
| 15590 | return result; | 16261 | return result; |
| 15591 | } else if (type_entry->id == ZigTypeIdNull) { | 16262 | } else if (type_entry->id == ZigTypeIdNull) { |
| 15592 | return ir_const_bool(ira, &instruction->base, false); | 16263 | return ir_const_bool(ira, source_inst, false); |
| 15593 | } else { | 16264 | } else { |
| 15594 | return ir_const_bool(ira, &instruction->base, true); | 16265 | return ir_const_bool(ira, source_inst, true); |
| 15595 | } | 16266 | } |
| 15596 | } | 16267 | } |
| 15597 | 16268 | ||
| 15598 | static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | 16269 | static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { |
| 15599 | IrInstructionUnwrapOptional *unwrap_maybe_instruction) | 16270 | IrInstruction *value = instruction->value->child; |
| 15600 | { | ||
| 15601 | IrInstruction *value = unwrap_maybe_instruction->value->child; | ||
| 15602 | if (type_is_invalid(value->value.type)) | 16271 | if (type_is_invalid(value->value.type)) |
| 15603 | return ira->codegen->invalid_instruction; | 16272 | return ira->codegen->invalid_instruction; |
| 15604 | 16273 | ||
| 15605 | ZigType *ptr_type = value->value.type; | 16274 | return ir_analyze_test_non_null(ira, &instruction->base, value); |
| 16275 | } | ||
| 16276 | |||
| 16277 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, | ||
| 16278 | IrInstruction *base_ptr, bool safety_check_on) | ||
| 16279 | { | ||
| 16280 | ZigType *ptr_type = base_ptr->value.type; | ||
| 15606 | assert(ptr_type->id == ZigTypeIdPointer); | 16281 | assert(ptr_type->id == ZigTypeIdPointer); |
| 15607 | 16282 | ||
| 15608 | ZigType *type_entry = ptr_type->data.pointer.child_type; | 16283 | ZigType *type_entry = ptr_type->data.pointer.child_type; |
| 15609 | if (type_is_invalid(type_entry)) { | 16284 | if (type_is_invalid(type_entry)) |
| 15610 | return ira->codegen->invalid_instruction; | 16285 | return ira->codegen->invalid_instruction; |
| 15611 | } else if (type_entry->id != ZigTypeIdOptional) { | 16286 | |
| 15612 | ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node, | 16287 | if (type_entry->id != ZigTypeIdOptional) { |
| 16288 | ir_add_error_node(ira, base_ptr->source_node, | ||
| 15613 | buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name))); | 16289 | buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name))); |
| 15614 | return ira->codegen->invalid_instruction; | 16290 | return ira->codegen->invalid_instruction; |
| 15615 | } | 16291 | } |
| 16292 | |||
| 15616 | ZigType *child_type = type_entry->data.maybe.child_type; | 16293 | ZigType *child_type = type_entry->data.maybe.child_type; |
| 15617 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type, | 16294 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 15618 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0); | 16295 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0); |
| 15619 | 16296 | ||
| 15620 | if (instr_is_comptime(value)) { | 16297 | if (instr_is_comptime(base_ptr)) { |
| 15621 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 16298 | ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad); |
| 15622 | if (!val) | 16299 | if (!val) |
| 15623 | return ira->codegen->invalid_instruction; | 16300 | return ira->codegen->invalid_instruction; |
| 15624 | ConstExprValue *maybe_val = ir_const_ptr_pointee(ira, val, unwrap_maybe_instruction->base.source_node); | 16301 | ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); |
| 15625 | if (maybe_val == nullptr) | 16302 | if (maybe_val == nullptr) |
| 15626 | return ira->codegen->invalid_instruction; | 16303 | return ira->codegen->invalid_instruction; |
| 15627 | 16304 | ||
| 15628 | if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { | 16305 | if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 15629 | if (optional_value_is_null(maybe_val)) { | 16306 | if (optional_value_is_null(maybe_val)) { |
| 15630 | ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null")); | 16307 | ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); |
| 15631 | return ira->codegen->invalid_instruction; | 16308 | return ira->codegen->invalid_instruction; |
| 15632 | } | 16309 | } |
| 15633 | IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type); | 16310 | IrInstruction *result = ir_const(ira, source_instr, result_type); |
| 15634 | ConstExprValue *out_val = &result->value; | 16311 | ConstExprValue *out_val = &result->value; |
| 15635 | out_val->data.x_ptr.special = ConstPtrSpecialRef; | 16312 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 15636 | out_val->data.x_ptr.mut = val->data.x_ptr.mut; | 16313 | out_val->data.x_ptr.mut = val->data.x_ptr.mut; |
| 15637 | if (type_is_codegen_pointer(child_type)) { | 16314 | if (types_have_same_zig_comptime_repr(type_entry, child_type)) { |
| 15638 | out_val->data.x_ptr.data.ref.pointee = maybe_val; | 16315 | out_val->data.x_ptr.data.ref.pointee = maybe_val; |
| 15639 | } else { | 16316 | } else { |
| 15640 | out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional; | 16317 | out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional; |
| ... | @@ -15643,13 +16320,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | ... | @@ -15643,13 +16320,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 15643 | } | 16320 | } |
| 15644 | } | 16321 | } |
| 15645 | 16322 | ||
| 15646 | IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb, | 16323 | IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope, |
| 15647 | unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node, | 16324 | source_instr->source_node, base_ptr, safety_check_on); |
| 15648 | value, unwrap_maybe_instruction->safety_check_on); | ||
| 15649 | result->value.type = result_type; | 16325 | result->value.type = result_type; |
| 15650 | return result; | 16326 | return result; |
| 15651 | } | 16327 | } |
| 15652 | 16328 | ||
| 16329 | static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, | ||
| 16330 | IrInstructionOptionalUnwrapPtr *instruction) | ||
| 16331 | { | ||
| 16332 | IrInstruction *base_ptr = instruction->base_ptr->child; | ||
| 16333 | if (type_is_invalid(base_ptr->value.type)) | ||
| 16334 | return ira->codegen->invalid_instruction; | ||
| 16335 | |||
| 16336 | return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on); | ||
| 16337 | } | ||
| 16338 | |||
| 15653 | static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) { | 16339 | static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) { |
| 15654 | IrInstruction *value = ctz_instruction->value->child; | 16340 | IrInstruction *value = ctz_instruction->value->child; |
| 15655 | if (type_is_invalid(value->value.type)) { | 16341 | if (type_is_invalid(value->value.type)) { |
| ... | @@ -15918,10 +16604,10 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -15918,10 +16604,10 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 15918 | ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type; | 16604 | ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type; |
| 15919 | ConstExprValue *pointee_val = nullptr; | 16605 | ConstExprValue *pointee_val = nullptr; |
| 15920 | if (instr_is_comptime(target_value_ptr)) { | 16606 | if (instr_is_comptime(target_value_ptr)) { |
| 15921 | pointee_val = ir_const_ptr_pointee(ira, &target_value_ptr->value, target_value_ptr->source_node); | 16607 | pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node); |
| 15922 | if (pointee_val == nullptr) | 16608 | if (pointee_val == nullptr) |
| 15923 | return ira->codegen->invalid_instruction; | 16609 | return ira->codegen->invalid_instruction; |
| 15924 | 16610 | ||
| 15925 | if (pointee_val->special == ConstValSpecialRuntime) | 16611 | if (pointee_val->special == ConstValSpecialRuntime) |
| 15926 | pointee_val = nullptr; | 16612 | pointee_val = nullptr; |
| 15927 | } | 16613 | } |
| ... | @@ -15950,9 +16636,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -15950,9 +16636,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 15950 | return result; | 16636 | return result; |
| 15951 | } | 16637 | } |
| 15952 | 16638 | ||
| 15953 | IrInstruction *result = ir_build_load_ptr(&ira->new_irb, | 16639 | IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); |
| 15954 | switch_target_instruction->base.scope, switch_target_instruction->base.source_node, | ||
| 15955 | target_value_ptr); | ||
| 15956 | result->value.type = target_type; | 16640 | result->value.type = target_type; |
| 15957 | return result; | 16641 | return result; |
| 15958 | } | 16642 | } |
| ... | @@ -15982,8 +16666,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -15982,8 +16666,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 15982 | return result; | 16666 | return result; |
| 15983 | } | 16667 | } |
| 15984 | 16668 | ||
| 15985 | IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | 16669 | IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); |
| 15986 | switch_target_instruction->base.source_node, target_value_ptr); | ||
| 15987 | union_value->value.type = target_type; | 16670 | union_value->value.type = target_type; |
| 15988 | 16671 | ||
| 15989 | IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope, | 16672 | IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope, |
| ... | @@ -16007,8 +16690,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -16007,8 +16690,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16007 | return result; | 16690 | return result; |
| 16008 | } | 16691 | } |
| 16009 | 16692 | ||
| 16010 | IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | 16693 | IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); |
| 16011 | switch_target_instruction->base.source_node, target_value_ptr); | ||
| 16012 | enum_value->value.type = target_type; | 16694 | enum_value->value.type = target_type; |
| 16013 | return enum_value; | 16695 | return enum_value; |
| 16014 | } | 16696 | } |
| ... | @@ -16022,6 +16704,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -16022,6 +16704,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16022 | case ZigTypeIdBoundFn: | 16704 | case ZigTypeIdBoundFn: |
| 16023 | case ZigTypeIdArgTuple: | 16705 | case ZigTypeIdArgTuple: |
| 16024 | case ZigTypeIdOpaque: | 16706 | case ZigTypeIdOpaque: |
| 16707 | case ZigTypeIdVector: | ||
| 16025 | ir_add_error(ira, &switch_target_instruction->base, | 16708 | ir_add_error(ira, &switch_target_instruction->base, |
| 16026 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); | 16709 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); |
| 16027 | return ira->codegen->invalid_instruction; | 16710 | return ira->codegen->invalid_instruction; |
| ... | @@ -16053,7 +16736,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru | ... | @@ -16053,7 +16736,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru |
| 16053 | if (!target_value_ptr) | 16736 | if (!target_value_ptr) |
| 16054 | return ira->codegen->invalid_instruction; | 16737 | return ira->codegen->invalid_instruction; |
| 16055 | 16738 | ||
| 16056 | ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, target_val_ptr, instruction->base.source_node); | 16739 | ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, target_val_ptr, instruction->base.source_node); |
| 16057 | if (pointee_val == nullptr) | 16740 | if (pointee_val == nullptr) |
| 16058 | return ira->codegen->invalid_instruction; | 16741 | return ira->codegen->invalid_instruction; |
| 16059 | 16742 | ||
| ... | @@ -16165,7 +16848,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI | ... | @@ -16165,7 +16848,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 16165 | Error err; | 16848 | Error err; |
| 16166 | assert(container_type->id == ZigTypeIdUnion); | 16849 | assert(container_type->id == ZigTypeIdUnion); |
| 16167 | 16850 | ||
| 16168 | if ((err = ensure_complete_type(ira->codegen, container_type))) | 16851 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) |
| 16169 | return ira->codegen->invalid_instruction; | 16852 | return ira->codegen->invalid_instruction; |
| 16170 | 16853 | ||
| 16171 | if (instr_field_count != 1) { | 16854 | if (instr_field_count != 1) { |
| ... | @@ -16197,7 +16880,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI | ... | @@ -16197,7 +16880,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 16197 | if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown))) | 16880 | if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown))) |
| 16198 | return ira->codegen->invalid_instruction; | 16881 | return ira->codegen->invalid_instruction; |
| 16199 | 16882 | ||
| 16200 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope); | 16883 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) |
| 16884 | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; | ||
| 16201 | if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime || | 16885 | if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime || |
| 16202 | !type_has_bits(casted_field_value->value.type)) | 16886 | !type_has_bits(casted_field_value->value.type)) |
| 16203 | { | 16887 | { |
| ... | @@ -16209,12 +16893,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI | ... | @@ -16209,12 +16893,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 16209 | ConstExprValue *out_val = &result->value; | 16893 | ConstExprValue *out_val = &result->value; |
| 16210 | out_val->data.x_union.payload = field_val; | 16894 | out_val->data.x_union.payload = field_val; |
| 16211 | out_val->data.x_union.tag = type_field->enum_field->value; | 16895 | out_val->data.x_union.tag = type_field->enum_field->value; |
| 16212 | 16896 | out_val->parent.id = ConstParentIdUnion; | |
| 16213 | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); | 16897 | out_val->parent.data.p_union.union_val = out_val; |
| 16214 | if (parent != nullptr) { | ||
| 16215 | parent->id = ConstParentIdUnion; | ||
| 16216 | parent->data.p_union.union_val = out_val; | ||
| 16217 | } | ||
| 16218 | 16898 | ||
| 16219 | return result; | 16899 | return result; |
| 16220 | } | 16900 | } |
| ... | @@ -16241,7 +16921,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -16241,7 +16921,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16241 | return ira->codegen->invalid_instruction; | 16921 | return ira->codegen->invalid_instruction; |
| 16242 | } | 16922 | } |
| 16243 | 16923 | ||
| 16244 | if ((err = ensure_complete_type(ira->codegen, container_type))) | 16924 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) |
| 16245 | return ira->codegen->invalid_instruction; | 16925 | return ira->codegen->invalid_instruction; |
| 16246 | 16926 | ||
| 16247 | size_t actual_field_count = container_type->data.structure.src_field_count; | 16927 | size_t actual_field_count = container_type->data.structure.src_field_count; |
| ... | @@ -16252,7 +16932,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -16252,7 +16932,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16252 | 16932 | ||
| 16253 | IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count); | 16933 | IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count); |
| 16254 | 16934 | ||
| 16255 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope); | 16935 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) |
| 16936 | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; | ||
| 16256 | 16937 | ||
| 16257 | ConstExprValue const_val = {}; | 16938 | ConstExprValue const_val = {}; |
| 16258 | const_val.special = ConstValSpecialStatic; | 16939 | const_val.special = ConstValSpecialStatic; |
| ... | @@ -16320,9 +17001,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -16320,9 +17001,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16320 | if (const_val.special == ConstValSpecialStatic) { | 17001 | if (const_val.special == ConstValSpecialStatic) { |
| 16321 | IrInstruction *result = ir_const(ira, instruction, nullptr); | 17002 | IrInstruction *result = ir_const(ira, instruction, nullptr); |
| 16322 | ConstExprValue *out_val = &result->value; | 17003 | ConstExprValue *out_val = &result->value; |
| 16323 | // TODO copy_const_val? | 17004 | copy_const_val(out_val, &const_val, true); |
| 16324 | *out_val = const_val; | 17005 | out_val->type = container_type; |
| 16325 | result->value.type = container_type; | ||
| 16326 | 17006 | ||
| 16327 | for (size_t i = 0; i < instr_field_count; i += 1) { | 17007 | for (size_t i = 0; i < instr_field_count; i += 1) { |
| 16328 | ConstExprValue *field_val = &out_val->data.x_struct.fields[i]; | 17008 | ConstExprValue *field_val = &out_val->data.x_struct.fields[i]; |
| ... | @@ -16354,127 +17034,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -16354,127 +17034,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16354 | static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, | 17034 | static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| 16355 | IrInstructionContainerInitList *instruction) | 17035 | IrInstructionContainerInitList *instruction) |
| 16356 | { | 17036 | { |
| 16357 | IrInstruction *container_type_value = instruction->container_type->child; | 17037 | ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); |
| 16358 | if (type_is_invalid(container_type_value->value.type)) | 17038 | if (type_is_invalid(container_type)) |
| 16359 | return ira->codegen->invalid_instruction; | 17039 | return ira->codegen->invalid_instruction; |
| 16360 | 17040 | ||
| 16361 | size_t elem_count = instruction->item_count; | 17041 | size_t elem_count = instruction->item_count; |
| 16362 | if (container_type_value->value.type->id == ZigTypeIdMetaType) { | ||
| 16363 | ZigType *container_type = ir_resolve_type(ira, container_type_value); | ||
| 16364 | if (type_is_invalid(container_type)) | ||
| 16365 | return ira->codegen->invalid_instruction; | ||
| 16366 | 17042 | ||
| 16367 | if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { | 17043 | if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { |
| 16368 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, | 17044 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, |
| 16369 | 0, nullptr); | 17045 | 0, nullptr); |
| 16370 | } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) { | 17046 | } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) { |
| 16371 | // array is same as slice init but we make a compile error if the length is wrong | 17047 | // array is same as slice init but we make a compile error if the length is wrong |
| 16372 | ZigType *child_type; | 17048 | ZigType *child_type; |
| 16373 | if (container_type->id == ZigTypeIdArray) { | 17049 | if (container_type->id == ZigTypeIdArray) { |
| 16374 | child_type = container_type->data.array.child_type; | 17050 | child_type = container_type->data.array.child_type; |
| 16375 | if (container_type->data.array.len != elem_count) { | 17051 | if (container_type->data.array.len != elem_count) { |
| 16376 | ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); | 17052 | ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); |
| 16377 | 17053 | ||
| 16378 | ir_add_error(ira, &instruction->base, | 17054 | ir_add_error(ira, &instruction->base, |
| 16379 | buf_sprintf("expected %s literal, found %s literal", | 17055 | buf_sprintf("expected %s literal, found %s literal", |
| 16380 | buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); | 17056 | buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); |
| 16381 | return ira->codegen->invalid_instruction; | 17057 | return ira->codegen->invalid_instruction; |
| 16382 | } | ||
| 16383 | } else { | ||
| 16384 | ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; | ||
| 16385 | assert(pointer_type->id == ZigTypeIdPointer); | ||
| 16386 | child_type = pointer_type->data.pointer.child_type; | ||
| 16387 | } | 17058 | } |
| 17059 | } else { | ||
| 17060 | ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; | ||
| 17061 | assert(pointer_type->id == ZigTypeIdPointer); | ||
| 17062 | child_type = pointer_type->data.pointer.child_type; | ||
| 17063 | } | ||
| 16388 | 17064 | ||
| 16389 | ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); | 17065 | ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); |
| 16390 | 17066 | ||
| 16391 | ConstExprValue const_val = {}; | 17067 | ConstExprValue const_val = {}; |
| 16392 | const_val.special = ConstValSpecialStatic; | 17068 | const_val.special = ConstValSpecialStatic; |
| 16393 | const_val.type = fixed_size_array_type; | 17069 | const_val.type = fixed_size_array_type; |
| 16394 | const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); | 17070 | const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); |
| 16395 | 17071 | ||
| 16396 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); | 17072 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); |
| 16397 | 17073 | ||
| 16398 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); | 17074 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); |
| 16399 | 17075 | ||
| 16400 | IrInstruction *first_non_const_instruction = nullptr; | 17076 | IrInstruction *first_non_const_instruction = nullptr; |
| 16401 | 17077 | ||
| 16402 | for (size_t i = 0; i < elem_count; i += 1) { | 17078 | for (size_t i = 0; i < elem_count; i += 1) { |
| 16403 | IrInstruction *arg_value = instruction->items[i]->child; | 17079 | IrInstruction *arg_value = instruction->items[i]->child; |
| 16404 | if (type_is_invalid(arg_value->value.type)) | 17080 | if (type_is_invalid(arg_value->value.type)) |
| 16405 | return ira->codegen->invalid_instruction; | 17081 | return ira->codegen->invalid_instruction; |
| 16406 | 17082 | ||
| 16407 | IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type); | 17083 | IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type); |
| 16408 | if (casted_arg == ira->codegen->invalid_instruction) | 17084 | if (casted_arg == ira->codegen->invalid_instruction) |
| 16409 | return ira->codegen->invalid_instruction; | 17085 | return ira->codegen->invalid_instruction; |
| 16410 | 17086 | ||
| 16411 | new_items[i] = casted_arg; | 17087 | new_items[i] = casted_arg; |
| 16412 | 17088 | ||
| 16413 | if (const_val.special == ConstValSpecialStatic) { | 17089 | if (const_val.special == ConstValSpecialStatic) { |
| 16414 | if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) { | 17090 | if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) { |
| 16415 | ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad); | 17091 | ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad); |
| 16416 | if (!elem_val) | 17092 | if (!elem_val) |
| 16417 | return ira->codegen->invalid_instruction; | 17093 | return ira->codegen->invalid_instruction; |
| 16418 | 17094 | ||
| 16419 | copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true); | 17095 | copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true); |
| 16420 | } else { | 17096 | } else { |
| 16421 | first_non_const_instruction = casted_arg; | 17097 | first_non_const_instruction = casted_arg; |
| 16422 | const_val.special = ConstValSpecialRuntime; | 17098 | const_val.special = ConstValSpecialRuntime; |
| 16423 | } | ||
| 16424 | } | 17099 | } |
| 16425 | } | 17100 | } |
| 17101 | } | ||
| 16426 | 17102 | ||
| 16427 | if (const_val.special == ConstValSpecialStatic) { | 17103 | if (const_val.special == ConstValSpecialStatic) { |
| 16428 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | 17104 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); |
| 16429 | ConstExprValue *out_val = &result->value; | 17105 | ConstExprValue *out_val = &result->value; |
| 16430 | // TODO copy_const_val? | 17106 | copy_const_val(out_val, &const_val, true); |
| 16431 | *out_val = const_val; | 17107 | result->value.type = fixed_size_array_type; |
| 16432 | result->value.type = fixed_size_array_type; | 17108 | for (size_t i = 0; i < elem_count; i += 1) { |
| 16433 | for (size_t i = 0; i < elem_count; i += 1) { | 17109 | ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i]; |
| 16434 | ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i]; | 17110 | ConstParent *parent = get_const_val_parent(ira->codegen, elem_val); |
| 16435 | ConstParent *parent = get_const_val_parent(ira->codegen, elem_val); | 17111 | if (parent != nullptr) { |
| 16436 | if (parent != nullptr) { | 17112 | parent->id = ConstParentIdArray; |
| 16437 | parent->id = ConstParentIdArray; | 17113 | parent->data.p_array.array_val = out_val; |
| 16438 | parent->data.p_array.array_val = out_val; | 17114 | parent->data.p_array.elem_index = i; |
| 16439 | parent->data.p_array.elem_index = i; | ||
| 16440 | } | ||
| 16441 | } | 17115 | } |
| 16442 | return result; | ||
| 16443 | } | 17116 | } |
| 17117 | return result; | ||
| 17118 | } | ||
| 16444 | 17119 | ||
| 16445 | if (is_comptime) { | 17120 | if (is_comptime) { |
| 16446 | ir_add_error_node(ira, first_non_const_instruction->source_node, | 17121 | ir_add_error_node(ira, first_non_const_instruction->source_node, |
| 16447 | buf_sprintf("unable to evaluate constant expression")); | 17122 | buf_sprintf("unable to evaluate constant expression")); |
| 16448 | return ira->codegen->invalid_instruction; | 17123 | return ira->codegen->invalid_instruction; |
| 16449 | } | 17124 | } |
| 16450 | 17125 | ||
| 16451 | IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb, | 17126 | IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb, |
| 16452 | instruction->base.scope, instruction->base.source_node, | 17127 | instruction->base.scope, instruction->base.source_node, |
| 16453 | container_type_value, elem_count, new_items); | 17128 | nullptr, elem_count, new_items); |
| 16454 | new_instruction->value.type = fixed_size_array_type; | 17129 | new_instruction->value.type = fixed_size_array_type; |
| 16455 | ir_add_alloca(ira, new_instruction, fixed_size_array_type); | 17130 | ir_add_alloca(ira, new_instruction, fixed_size_array_type); |
| 16456 | return new_instruction; | 17131 | return new_instruction; |
| 16457 | } else if (container_type->id == ZigTypeIdVoid) { | 17132 | } else if (container_type->id == ZigTypeIdVoid) { |
| 16458 | if (elem_count != 0) { | 17133 | if (elem_count != 0) { |
| 16459 | ir_add_error_node(ira, instruction->base.source_node, | ||
| 16460 | buf_sprintf("void expression expects no arguments")); | ||
| 16461 | return ira->codegen->invalid_instruction; | ||
| 16462 | } | ||
| 16463 | return ir_const_void(ira, &instruction->base); | ||
| 16464 | } else { | ||
| 16465 | ir_add_error_node(ira, instruction->base.source_node, | 17134 | ir_add_error_node(ira, instruction->base.source_node, |
| 16466 | buf_sprintf("type '%s' does not support array initialization", | 17135 | buf_sprintf("void expression expects no arguments")); |
| 16467 | buf_ptr(&container_type->name))); | ||
| 16468 | return ira->codegen->invalid_instruction; | 17136 | return ira->codegen->invalid_instruction; |
| 16469 | } | 17137 | } |
| 17138 | return ir_const_void(ira, &instruction->base); | ||
| 16470 | } else { | 17139 | } else { |
| 16471 | ir_add_error(ira, container_type_value, | 17140 | ir_add_error_node(ira, instruction->base.source_node, |
| 16472 | buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name))); | 17141 | buf_sprintf("type '%s' does not support array initialization", |
| 17142 | buf_ptr(&container_type->name))); | ||
| 16473 | return ira->codegen->invalid_instruction; | 17143 | return ira->codegen->invalid_instruction; |
| 16474 | } | 17144 | } |
| 16475 | } | 17145 | } |
| 16476 | 17146 | ||
| 16477 | static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) { | 17147 | static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, |
| 17148 | IrInstructionContainerInitFields *instruction) | ||
| 17149 | { | ||
| 16478 | IrInstruction *container_type_value = instruction->container_type->child; | 17150 | IrInstruction *container_type_value = instruction->container_type->child; |
| 16479 | ZigType *container_type = ir_resolve_type(ira, container_type_value); | 17151 | ZigType *container_type = ir_resolve_type(ira, container_type_value); |
| 16480 | if (type_is_invalid(container_type)) | 17152 | if (type_is_invalid(container_type)) |
| ... | @@ -16534,7 +17206,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct | ... | @@ -16534,7 +17206,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct |
| 16534 | if (type_is_invalid(value->value.type)) | 17206 | if (type_is_invalid(value->value.type)) |
| 16535 | return ira->codegen->invalid_instruction; | 17207 | return ira->codegen->invalid_instruction; |
| 16536 | 17208 | ||
| 16537 | IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type); | 17209 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set); |
| 16538 | if (type_is_invalid(casted_value->value.type)) | 17210 | if (type_is_invalid(casted_value->value.type)) |
| 16539 | return ira->codegen->invalid_instruction; | 17211 | return ira->codegen->invalid_instruction; |
| 16540 | 17212 | ||
| ... | @@ -16685,7 +17357,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, | ... | @@ -16685,7 +17357,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 16685 | static TypeStructField *validate_byte_offset(IrAnalyze *ira, | 17357 | static TypeStructField *validate_byte_offset(IrAnalyze *ira, |
| 16686 | IrInstruction *type_value, | 17358 | IrInstruction *type_value, |
| 16687 | IrInstruction *field_name_value, | 17359 | IrInstruction *field_name_value, |
| 16688 | size_t *byte_offset) | 17360 | size_t *byte_offset) |
| 16689 | { | 17361 | { |
| 16690 | ZigType *container_type = ir_resolve_type(ira, type_value); | 17362 | ZigType *container_type = ir_resolve_type(ira, type_value); |
| 16691 | if (type_is_invalid(container_type)) | 17363 | if (type_is_invalid(container_type)) |
| ... | @@ -16768,16 +17440,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind | ... | @@ -16768,16 +17440,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind |
| 16768 | 17440 | ||
| 16769 | static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) { | 17441 | static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) { |
| 16770 | Error err; | 17442 | Error err; |
| 16771 | static ConstExprValue *type_info_var = nullptr; // TODO oops this global variable made it past code review | 17443 | ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); |
| 16772 | static ZigType *type_info_type = nullptr; // TODO oops this global variable made it past code review | 17444 | assert(type_info_var->type->id == ZigTypeIdMetaType); |
| 16773 | if (type_info_var == nullptr) { | 17445 | assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type)); |
| 16774 | type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); | ||
| 16775 | assert(type_info_var->type->id == ZigTypeIdMetaType); | ||
| 16776 | 17446 | ||
| 16777 | assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type)); | 17447 | ZigType *type_info_type = type_info_var->data.x_type; |
| 16778 | type_info_type = type_info_var->data.x_type; | 17448 | assert(type_info_type->id == ZigTypeIdUnion); |
| 16779 | assert(type_info_type->id == ZigTypeIdUnion); | ||
| 16780 | } | ||
| 16781 | 17449 | ||
| 16782 | if (type_name == nullptr && root == nullptr) | 17450 | if (type_name == nullptr && root == nullptr) |
| 16783 | return type_info_type; | 17451 | return type_info_type; |
| ... | @@ -16799,10 +17467,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig | ... | @@ -16799,10 +17467,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig |
| 16799 | 17467 | ||
| 16800 | ZigVar *var = tld->var; | 17468 | ZigVar *var = tld->var; |
| 16801 | 17469 | ||
| 16802 | if ((err = ensure_complete_type(ira->codegen, var->value->type))) | 17470 | if ((err = ensure_complete_type(ira->codegen, var->const_value->type))) |
| 16803 | return ira->codegen->builtin_types.entry_invalid; | 17471 | return ira->codegen->builtin_types.entry_invalid; |
| 16804 | assert(var->value->type->id == ZigTypeIdMetaType); | 17472 | |
| 16805 | return var->value->data.x_type; | 17473 | assert(var->const_value->type->id == ZigTypeIdMetaType); |
| 17474 | return var->const_value->data.x_type; | ||
| 16806 | } | 17475 | } |
| 16807 | 17476 | ||
| 16808 | static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) { | 17477 | static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) { |
| ... | @@ -16857,13 +17526,12 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco | ... | @@ -16857,13 +17526,12 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 16857 | definition_array->special = ConstValSpecialStatic; | 17526 | definition_array->special = ConstValSpecialStatic; |
| 16858 | definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count); | 17527 | definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count); |
| 16859 | definition_array->data.x_array.special = ConstArraySpecialNone; | 17528 | definition_array->data.x_array.special = ConstArraySpecialNone; |
| 16860 | definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 16861 | definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count); | 17529 | definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count); |
| 16862 | init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false); | 17530 | init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false); |
| 16863 | 17531 | ||
| 16864 | // Loop through the definitions and generate info. | 17532 | // Loop through the definitions and generate info. |
| 16865 | decl_it = decls_scope->decl_table.entry_iterator(); | 17533 | decl_it = decls_scope->decl_table.entry_iterator(); |
| 16866 | curr_entry = nullptr; | 17534 | curr_entry = nullptr; |
| 16867 | int definition_index = 0; | 17535 | int definition_index = 0; |
| 16868 | while ((curr_entry = decl_it.next()) != nullptr) { | 17536 | while ((curr_entry = decl_it.next()) != nullptr) { |
| 16869 | // Skip comptime blocks and test functions. | 17537 | // Skip comptime blocks and test functions. |
| ... | @@ -16888,33 +17556,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco | ... | @@ -16888,33 +17556,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 16888 | inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; | 17556 | inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; |
| 16889 | inner_fields[2].special = ConstValSpecialStatic; | 17557 | inner_fields[2].special = ConstValSpecialStatic; |
| 16890 | inner_fields[2].type = type_info_definition_data_type; | 17558 | inner_fields[2].type = type_info_definition_data_type; |
| 16891 | inner_fields[2].data.x_union.parent.id = ConstParentIdStruct; | 17559 | inner_fields[2].parent.id = ConstParentIdStruct; |
| 16892 | inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val; | 17560 | inner_fields[2].parent.data.p_struct.struct_val = definition_val; |
| 16893 | inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1; | 17561 | inner_fields[2].parent.data.p_struct.field_index = 1; |
| 16894 | 17562 | ||
| 16895 | switch (curr_entry->value->id) { | 17563 | switch (curr_entry->value->id) { |
| 16896 | case TldIdVar: | 17564 | case TldIdVar: |
| 16897 | { | 17565 | { |
| 16898 | ZigVar *var = ((TldVar *)curr_entry->value)->var; | 17566 | ZigVar *var = ((TldVar *)curr_entry->value)->var; |
| 16899 | if ((err = ensure_complete_type(ira->codegen, var->value->type))) | 17567 | if ((err = ensure_complete_type(ira->codegen, var->const_value->type))) |
| 16900 | return ErrorSemanticAnalyzeFail; | 17568 | return ErrorSemanticAnalyzeFail; |
| 16901 | 17569 | ||
| 16902 | if (var->value->type->id == ZigTypeIdMetaType) | 17570 | if (var->const_value->type->id == ZigTypeIdMetaType) { |
| 16903 | { | ||
| 16904 | // We have a variable of type 'type', so it's actually a type definition. | 17571 | // We have a variable of type 'type', so it's actually a type definition. |
| 16905 | // 0: Data.Type: type | 17572 | // 0: Data.Type: type |
| 16906 | bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); | 17573 | bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); |
| 16907 | inner_fields[2].data.x_union.payload = var->value; | 17574 | inner_fields[2].data.x_union.payload = var->const_value; |
| 16908 | } | 17575 | } else { |
| 16909 | else | ||
| 16910 | { | ||
| 16911 | // We have a variable of another type, so we store the type of the variable. | 17576 | // We have a variable of another type, so we store the type of the variable. |
| 16912 | // 1: Data.Var: type | 17577 | // 1: Data.Var: type |
| 16913 | bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); | 17578 | bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); |
| 16914 | 17579 | ||
| 16915 | ConstExprValue *payload = create_const_vals(1); | 17580 | ConstExprValue *payload = create_const_vals(1); |
| 16916 | payload->type = ira->codegen->builtin_types.entry_type; | 17581 | payload->type = ira->codegen->builtin_types.entry_type; |
| 16917 | payload->data.x_type = var->value->type; | 17582 | payload->data.x_type = var->const_value->type; |
| 16918 | 17583 | ||
| 16919 | inner_fields[2].data.x_union.payload = payload; | 17584 | inner_fields[2].data.x_union.payload = payload; |
| 16920 | } | 17585 | } |
| ... | @@ -16934,8 +17599,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco | ... | @@ -16934,8 +17599,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 16934 | ConstExprValue *fn_def_val = create_const_vals(1); | 17599 | ConstExprValue *fn_def_val = create_const_vals(1); |
| 16935 | fn_def_val->special = ConstValSpecialStatic; | 17600 | fn_def_val->special = ConstValSpecialStatic; |
| 16936 | fn_def_val->type = type_info_fn_def_type; | 17601 | fn_def_val->type = type_info_fn_def_type; |
| 16937 | fn_def_val->data.x_struct.parent.id = ConstParentIdUnion; | 17602 | fn_def_val->parent.id = ConstParentIdUnion; |
| 16938 | fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2]; | 17603 | fn_def_val->parent.data.p_union.union_val = &inner_fields[2]; |
| 16939 | 17604 | ||
| 16940 | ConstExprValue *fn_def_fields = create_const_vals(9); | 17605 | ConstExprValue *fn_def_fields = create_const_vals(9); |
| 16941 | fn_def_val->data.x_struct.fields = fn_def_fields; | 17606 | fn_def_val->data.x_struct.fields = fn_def_fields; |
| ... | @@ -16990,12 +17655,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco | ... | @@ -16990,12 +17655,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 16990 | ensure_field_index(fn_def_val->type, "return_type", 7); | 17655 | ensure_field_index(fn_def_val->type, "return_type", 7); |
| 16991 | fn_def_fields[7].special = ConstValSpecialStatic; | 17656 | fn_def_fields[7].special = ConstValSpecialStatic; |
| 16992 | fn_def_fields[7].type = ira->codegen->builtin_types.entry_type; | 17657 | fn_def_fields[7].type = ira->codegen->builtin_types.entry_type; |
| 16993 | if (fn_entry->src_implicit_return_type != nullptr) | 17658 | fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; |
| 16994 | fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type; | ||
| 16995 | else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr) | ||
| 16996 | fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.gen_return_type; | ||
| 16997 | else | ||
| 16998 | fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; | ||
| 16999 | // arg_names: [][] const u8 | 17659 | // arg_names: [][] const u8 |
| 17000 | ensure_field_index(fn_def_val->type, "arg_names", 8); | 17660 | ensure_field_index(fn_def_val->type, "arg_names", 8); |
| 17001 | size_t fn_arg_count = fn_entry->variable_list.length; | 17661 | size_t fn_arg_count = fn_entry->variable_list.length; |
| ... | @@ -17004,20 +17664,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco | ... | @@ -17004,20 +17664,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17004 | fn_arg_name_array->type = get_array_type(ira->codegen, | 17664 | fn_arg_name_array->type = get_array_type(ira->codegen, |
| 17005 | get_slice_type(ira->codegen, u8_ptr), fn_arg_count); | 17665 | get_slice_type(ira->codegen, u8_ptr), fn_arg_count); |
| 17006 | fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; | 17666 | fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; |
| 17007 | fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 17008 | fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); | 17667 | fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); |
| 17009 | 17668 | ||
| 17010 | init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false); | 17669 | init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false); |
| 17011 | 17670 | ||
| 17012 | for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) | 17671 | for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { |
| 17013 | { | ||
| 17014 | ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); | 17672 | ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); |
| 17015 | ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index]; | 17673 | ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index]; |
| 17016 | ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); | 17674 | ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); |
| 17017 | init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); | 17675 | init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); |
| 17018 | fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray; | 17676 | fn_arg_name_val->parent.id = ConstParentIdArray; |
| 17019 | fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array; | 17677 | fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array; |
| 17020 | fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; | 17678 | fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; |
| 17021 | } | 17679 | } |
| 17022 | 17680 | ||
| 17023 | inner_fields[2].data.x_union.payload = fn_def_val; | 17681 | inner_fields[2].data.x_union.payload = fn_def_val; |
| ... | @@ -17052,6 +17710,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco | ... | @@ -17052,6 +17710,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17052 | return ErrorNone; | 17710 | return ErrorNone; |
| 17053 | } | 17711 | } |
| 17054 | 17712 | ||
| 17713 | static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { | ||
| 17714 | switch (ptr_len) { | ||
| 17715 | case PtrLenSingle: | ||
| 17716 | return 0; | ||
| 17717 | case PtrLenUnknown: | ||
| 17718 | return 1; | ||
| 17719 | case PtrLenC: | ||
| 17720 | return 3; | ||
| 17721 | } | ||
| 17722 | zig_unreachable(); | ||
| 17723 | } | ||
| 17724 | |||
| 17055 | static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { | 17725 | static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { |
| 17056 | Error err; | 17726 | Error err; |
| 17057 | ZigType *attrs_type; | 17727 | ZigType *attrs_type; |
| ... | @@ -17061,7 +17731,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty | ... | @@ -17061,7 +17731,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty |
| 17061 | size_enum_index = 2; | 17731 | size_enum_index = 2; |
| 17062 | } else if (ptr_type_entry->id == ZigTypeIdPointer) { | 17732 | } else if (ptr_type_entry->id == ZigTypeIdPointer) { |
| 17063 | attrs_type = ptr_type_entry; | 17733 | attrs_type = ptr_type_entry; |
| 17064 | size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1; | 17734 | size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len); |
| 17065 | } else { | 17735 | } else { |
| 17066 | zig_unreachable(); | 17736 | zig_unreachable(); |
| 17067 | } | 17737 | } |
| ... | @@ -17129,21 +17799,16 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val, | ... | @@ -17129,21 +17799,16 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val, |
| 17129 | enum_field_val->data.x_struct.fields = inner_fields; | 17799 | enum_field_val->data.x_struct.fields = inner_fields; |
| 17130 | } | 17800 | } |
| 17131 | 17801 | ||
| 17132 | static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstExprValue **out) { | 17802 | static Error ir_make_type_info_value(IrAnalyze *ira, AstNode *source_node, ZigType *type_entry, ConstExprValue **out) { |
| 17133 | Error err; | 17803 | Error err; |
| 17134 | assert(type_entry != nullptr); | 17804 | assert(type_entry != nullptr); |
| 17135 | assert(!type_is_invalid(type_entry)); | 17805 | assert(!type_is_invalid(type_entry)); |
| 17136 | 17806 | ||
| 17137 | if ((err = ensure_complete_type(ira->codegen, type_entry))) | 17807 | if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown))) |
| 17138 | return err; | 17808 | return err; |
| 17139 | 17809 | ||
| 17140 | if (type_entry == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 17141 | zig_panic("TODO implement @typeInfo for global error set"); | ||
| 17142 | } | ||
| 17143 | |||
| 17144 | ConstExprValue *result = nullptr; | 17810 | ConstExprValue *result = nullptr; |
| 17145 | switch (type_entry->id) | 17811 | switch (type_entry->id) { |
| 17146 | { | ||
| 17147 | case ZigTypeIdInvalid: | 17812 | case ZigTypeIdInvalid: |
| 17148 | zig_unreachable(); | 17813 | zig_unreachable(); |
| 17149 | case ZigTypeIdMetaType: | 17814 | case ZigTypeIdMetaType: |
| ... | @@ -17238,6 +17903,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17238,6 +17903,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17238 | 17903 | ||
| 17239 | break; | 17904 | break; |
| 17240 | } | 17905 | } |
| 17906 | case ZigTypeIdVector: { | ||
| 17907 | result = create_const_vals(1); | ||
| 17908 | result->special = ConstValSpecialStatic; | ||
| 17909 | result->type = ir_type_info_get_type(ira, "Vector", nullptr); | ||
| 17910 | |||
| 17911 | ConstExprValue *fields = create_const_vals(2); | ||
| 17912 | result->data.x_struct.fields = fields; | ||
| 17913 | |||
| 17914 | // len: usize | ||
| 17915 | ensure_field_index(result->type, "len", 0); | ||
| 17916 | fields[0].special = ConstValSpecialStatic; | ||
| 17917 | fields[0].type = ira->codegen->builtin_types.entry_u32; | ||
| 17918 | bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len); | ||
| 17919 | // child: type | ||
| 17920 | ensure_field_index(result->type, "child", 1); | ||
| 17921 | fields[1].special = ConstValSpecialStatic; | ||
| 17922 | fields[1].type = ira->codegen->builtin_types.entry_type; | ||
| 17923 | fields[1].data.x_type = type_entry->data.vector.elem_type; | ||
| 17924 | |||
| 17925 | break; | ||
| 17926 | } | ||
| 17241 | case ZigTypeIdOptional: | 17927 | case ZigTypeIdOptional: |
| 17242 | { | 17928 | { |
| 17243 | result = create_const_vals(1); | 17929 | result = create_const_vals(1); |
| ... | @@ -17310,7 +17996,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17310,7 +17996,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17310 | enum_field_array->special = ConstValSpecialStatic; | 17996 | enum_field_array->special = ConstValSpecialStatic; |
| 17311 | enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count); | 17997 | enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count); |
| 17312 | enum_field_array->data.x_array.special = ConstArraySpecialNone; | 17998 | enum_field_array->data.x_array.special = ConstArraySpecialNone; |
| 17313 | enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 17314 | enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); | 17999 | enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); |
| 17315 | 18000 | ||
| 17316 | init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); | 18001 | init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); |
| ... | @@ -17320,9 +18005,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17320,9 +18005,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17320 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; | 18005 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; |
| 17321 | ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index]; | 18006 | ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index]; |
| 17322 | make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type); | 18007 | make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type); |
| 17323 | enum_field_val->data.x_struct.parent.id = ConstParentIdArray; | 18008 | enum_field_val->parent.id = ConstParentIdArray; |
| 17324 | enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; | 18009 | enum_field_val->parent.data.p_array.array_val = enum_field_array; |
| 17325 | enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; | 18010 | enum_field_val->parent.data.p_array.elem_index = enum_field_index; |
| 17326 | } | 18011 | } |
| 17327 | // defs: []TypeInfo.Definition | 18012 | // defs: []TypeInfo.Definition |
| 17328 | ensure_field_index(result->type, "defs", 3); | 18013 | ensure_field_index(result->type, "defs", 3); |
| ... | @@ -17344,12 +18029,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17344,12 +18029,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17344 | ensure_field_index(result->type, "errors", 0); | 18029 | ensure_field_index(result->type, "errors", 0); |
| 17345 | 18030 | ||
| 17346 | ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr); | 18031 | ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr); |
| 18032 | if (!resolve_inferred_error_set(ira->codegen, type_entry, source_node)) { | ||
| 18033 | return ErrorSemanticAnalyzeFail; | ||
| 18034 | } | ||
| 18035 | if (type_is_global_error_set(type_entry)) { | ||
| 18036 | ir_add_error_node(ira, source_node, | ||
| 18037 | buf_sprintf("TODO: compiler bug: implement @typeInfo support for anyerror. https://github.com/ziglang/zig/issues/1936")); | ||
| 18038 | return ErrorSemanticAnalyzeFail; | ||
| 18039 | } | ||
| 18040 | |||
| 17347 | uint32_t error_count = type_entry->data.error_set.err_count; | 18041 | uint32_t error_count = type_entry->data.error_set.err_count; |
| 17348 | ConstExprValue *error_array = create_const_vals(1); | 18042 | ConstExprValue *error_array = create_const_vals(1); |
| 17349 | error_array->special = ConstValSpecialStatic; | 18043 | error_array->special = ConstValSpecialStatic; |
| 17350 | error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count); | 18044 | error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count); |
| 17351 | error_array->data.x_array.special = ConstArraySpecialNone; | 18045 | error_array->data.x_array.special = ConstArraySpecialNone; |
| 17352 | error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 17353 | error_array->data.x_array.data.s_none.elements = create_const_vals(error_count); | 18046 | error_array->data.x_array.data.s_none.elements = create_const_vals(error_count); |
| 17354 | 18047 | ||
| 17355 | init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false); | 18048 | init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false); |
| ... | @@ -17373,9 +18066,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17373,9 +18066,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17373 | bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); | 18066 | bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); |
| 17374 | 18067 | ||
| 17375 | error_val->data.x_struct.fields = inner_fields; | 18068 | error_val->data.x_struct.fields = inner_fields; |
| 17376 | error_val->data.x_struct.parent.id = ConstParentIdArray; | 18069 | error_val->parent.id = ConstParentIdArray; |
| 17377 | error_val->data.x_struct.parent.data.p_array.array_val = error_array; | 18070 | error_val->parent.data.p_array.array_val = error_array; |
| 17378 | error_val->data.x_struct.parent.data.p_array.elem_index = error_index; | 18071 | error_val->parent.data.p_array.elem_index = error_index; |
| 17379 | } | 18072 | } |
| 17380 | 18073 | ||
| 17381 | break; | 18074 | break; |
| ... | @@ -17444,7 +18137,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17444,7 +18137,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17444 | union_field_array->special = ConstValSpecialStatic; | 18137 | union_field_array->special = ConstValSpecialStatic; |
| 17445 | union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count); | 18138 | union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count); |
| 17446 | union_field_array->data.x_array.special = ConstArraySpecialNone; | 18139 | union_field_array->data.x_array.special = ConstArraySpecialNone; |
| 17447 | union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 17448 | union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); | 18140 | union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); |
| 17449 | 18141 | ||
| 17450 | init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); | 18142 | init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); |
| ... | @@ -17477,9 +18169,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17477,9 +18169,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17477 | init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); | 18169 | init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); |
| 17478 | 18170 | ||
| 17479 | union_field_val->data.x_struct.fields = inner_fields; | 18171 | union_field_val->data.x_struct.fields = inner_fields; |
| 17480 | union_field_val->data.x_struct.parent.id = ConstParentIdArray; | 18172 | union_field_val->parent.id = ConstParentIdArray; |
| 17481 | union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array; | 18173 | union_field_val->parent.data.p_array.array_val = union_field_array; |
| 17482 | union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; | 18174 | union_field_val->parent.data.p_array.elem_index = union_field_index; |
| 17483 | } | 18175 | } |
| 17484 | // defs: []TypeInfo.Definition | 18176 | // defs: []TypeInfo.Definition |
| 17485 | ensure_field_index(result->type, "defs", 3); | 18177 | ensure_field_index(result->type, "defs", 3); |
| ... | @@ -17519,7 +18211,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17519,7 +18211,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17519 | struct_field_array->special = ConstValSpecialStatic; | 18211 | struct_field_array->special = ConstValSpecialStatic; |
| 17520 | struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count); | 18212 | struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count); |
| 17521 | struct_field_array->data.x_array.special = ConstArraySpecialNone; | 18213 | struct_field_array->data.x_array.special = ConstArraySpecialNone; |
| 17522 | struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 17523 | struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); | 18214 | struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); |
| 17524 | 18215 | ||
| 17525 | init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); | 18216 | init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); |
| ... | @@ -17553,9 +18244,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17553,9 +18244,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17553 | init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); | 18244 | init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); |
| 17554 | 18245 | ||
| 17555 | struct_field_val->data.x_struct.fields = inner_fields; | 18246 | struct_field_val->data.x_struct.fields = inner_fields; |
| 17556 | struct_field_val->data.x_struct.parent.id = ConstParentIdArray; | 18247 | struct_field_val->parent.id = ConstParentIdArray; |
| 17557 | struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array; | 18248 | struct_field_val->parent.data.p_array.array_val = struct_field_array; |
| 17558 | struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index; | 18249 | struct_field_val->parent.data.p_array.elem_index = struct_field_index; |
| 17559 | } | 18250 | } |
| 17560 | // defs: []TypeInfo.Definition | 18251 | // defs: []TypeInfo.Definition |
| 17561 | ensure_field_index(result->type, "defs", 2); | 18252 | ensure_field_index(result->type, "defs", 2); |
| ... | @@ -17625,7 +18316,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17625,7 +18316,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17625 | fn_arg_array->special = ConstValSpecialStatic; | 18316 | fn_arg_array->special = ConstValSpecialStatic; |
| 17626 | fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count); | 18317 | fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count); |
| 17627 | fn_arg_array->data.x_array.special = ConstArraySpecialNone; | 18318 | fn_arg_array->data.x_array.special = ConstArraySpecialNone; |
| 17628 | fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | ||
| 17629 | fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); | 18319 | fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); |
| 17630 | 18320 | ||
| 17631 | init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false); | 18321 | init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false); |
| ... | @@ -17662,9 +18352,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17662,9 +18352,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17662 | } | 18352 | } |
| 17663 | 18353 | ||
| 17664 | fn_arg_val->data.x_struct.fields = inner_fields; | 18354 | fn_arg_val->data.x_struct.fields = inner_fields; |
| 17665 | fn_arg_val->data.x_struct.parent.id = ConstParentIdArray; | 18355 | fn_arg_val->parent.id = ConstParentIdArray; |
| 17666 | fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array; | 18356 | fn_arg_val->parent.data.p_array.array_val = fn_arg_array; |
| 17667 | fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; | 18357 | fn_arg_val->parent.data.p_array.elem_index = fn_arg_index; |
| 17668 | } | 18358 | } |
| 17669 | 18359 | ||
| 17670 | break; | 18360 | break; |
| ... | @@ -17673,7 +18363,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE | ... | @@ -17673,7 +18363,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17673 | { | 18363 | { |
| 17674 | ZigType *fn_type = type_entry->data.bound_fn.fn_type; | 18364 | ZigType *fn_type = type_entry->data.bound_fn.fn_type; |
| 17675 | assert(fn_type->id == ZigTypeIdFn); | 18365 | assert(fn_type->id == ZigTypeIdFn); |
| 17676 | if ((err = ir_make_type_info_value(ira, fn_type, &result))) | 18366 | if ((err = ir_make_type_info_value(ira, source_node, fn_type, &result))) |
| 17677 | return err; | 18367 | return err; |
| 17678 | 18368 | ||
| 17679 | break; | 18369 | break; |
| ... | @@ -17698,7 +18388,7 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, | ... | @@ -17698,7 +18388,7 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, |
| 17698 | ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr); | 18388 | ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr); |
| 17699 | 18389 | ||
| 17700 | ConstExprValue *payload; | 18390 | ConstExprValue *payload; |
| 17701 | if ((err = ir_make_type_info_value(ira, type_entry, &payload))) | 18391 | if ((err = ir_make_type_info_value(ira, instruction->base.source_node, type_entry, &payload))) |
| 17702 | return ira->codegen->invalid_instruction; | 18392 | return ira->codegen->invalid_instruction; |
| 17703 | 18393 | ||
| 17704 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); | 18394 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); |
| ... | @@ -17708,8 +18398,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, | ... | @@ -17708,8 +18398,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, |
| 17708 | 18398 | ||
| 17709 | if (payload != nullptr) { | 18399 | if (payload != nullptr) { |
| 17710 | assert(payload->type->id == ZigTypeIdStruct); | 18400 | assert(payload->type->id == ZigTypeIdStruct); |
| 17711 | payload->data.x_struct.parent.id = ConstParentIdUnion; | 18401 | payload->parent.id = ConstParentIdUnion; |
| 17712 | payload->data.x_struct.parent.data.p_union.union_val = out_val; | 18402 | payload->parent.data.p_union.union_val = out_val; |
| 17713 | } | 18403 | } |
| 17714 | 18404 | ||
| 17715 | return result; | 18405 | return result; |
| ... | @@ -17735,12 +18425,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, | ... | @@ -17735,12 +18425,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, |
| 17735 | static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, | 18425 | static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, |
| 17736 | IrInstructionSetEvalBranchQuota *instruction) | 18426 | IrInstructionSetEvalBranchQuota *instruction) |
| 17737 | { | 18427 | { |
| 17738 | if (ira->new_irb.exec->parent_exec != nullptr && !ira->new_irb.exec->is_generic_instantiation) { | ||
| 17739 | ir_add_error(ira, &instruction->base, | ||
| 17740 | buf_sprintf("@setEvalBranchQuota must be called from the top of the comptime stack")); | ||
| 17741 | return ira->codegen->invalid_instruction; | ||
| 17742 | } | ||
| 17743 | |||
| 17744 | uint64_t new_quota; | 18428 | uint64_t new_quota; |
| 17745 | if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota)) | 18429 | if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota)) |
| 17746 | return ira->codegen->invalid_instruction; | 18430 | return ira->codegen->invalid_instruction; |
| ... | @@ -17781,10 +18465,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct | ... | @@ -17781,10 +18465,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 17781 | 18465 | ||
| 17782 | // Execute the C import block like an inline function | 18466 | // Execute the C import block like an inline function |
| 17783 | ZigType *void_type = ira->codegen->builtin_types.entry_void; | 18467 | ZigType *void_type = ira->codegen->builtin_types.entry_void; |
| 17784 | IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, | 18468 | ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, |
| 17785 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, | 18469 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, |
| 17786 | &cimport_scope->buf, block_node, nullptr, nullptr); | 18470 | &cimport_scope->buf, block_node, nullptr, nullptr, nullptr); |
| 17787 | if (type_is_invalid(cimport_result->value.type)) | 18471 | if (type_is_invalid(cimport_result->type)) |
| 17788 | return ira->codegen->invalid_instruction; | 18472 | return ira->codegen->invalid_instruction; |
| 17789 | 18473 | ||
| 17790 | find_libc_include_path(ira->codegen); | 18474 | find_libc_include_path(ira->codegen); |
| ... | @@ -17934,7 +18618,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru | ... | @@ -17934,7 +18618,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru |
| 17934 | return result; | 18618 | return result; |
| 17935 | } | 18619 | } |
| 17936 | 18620 | ||
| 17937 | static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) { | 18621 | static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) { |
| 17938 | ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child); | 18622 | ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child); |
| 17939 | if (type_is_invalid(operand_type)) | 18623 | if (type_is_invalid(operand_type)) |
| 17940 | return ira->codegen->invalid_instruction; | 18624 | return ira->codegen->invalid_instruction; |
| ... | @@ -18006,9 +18690,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi | ... | @@ -18006,9 +18690,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi |
| 18006 | zig_panic("TODO compile-time execution of cmpxchg"); | 18690 | zig_panic("TODO compile-time execution of cmpxchg"); |
| 18007 | } | 18691 | } |
| 18008 | 18692 | ||
| 18009 | IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node, | 18693 | IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base, |
| 18010 | nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak, | 18694 | casted_ptr, casted_cmp_value, casted_new_value, |
| 18011 | operand_type, success_order, failure_order); | 18695 | success_order, failure_order, instruction->is_weak); |
| 18012 | result->value.type = get_optional_type(ira->codegen, operand_type); | 18696 | result->value.type = get_optional_type(ira->codegen, operand_type); |
| 18013 | ir_add_alloca(ira, result, result->value.type); | 18697 | ir_add_alloca(ira, result, result->value.type); |
| 18014 | return result; | 18698 | return result; |
| ... | @@ -18054,6 +18738,27 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct | ... | @@ -18054,6 +18738,27 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct |
| 18054 | return ira->codegen->invalid_instruction; | 18738 | return ira->codegen->invalid_instruction; |
| 18055 | } | 18739 | } |
| 18056 | 18740 | ||
| 18741 | if (dest_type->id == ZigTypeIdComptimeInt) { | ||
| 18742 | return ir_implicit_cast(ira, target, dest_type); | ||
| 18743 | } | ||
| 18744 | |||
| 18745 | if (instr_is_comptime(target)) { | ||
| 18746 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | ||
| 18747 | if (val == nullptr) | ||
| 18748 | return ira->codegen->invalid_instruction; | ||
| 18749 | |||
| 18750 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | ||
| 18751 | bigint_truncate(&result->value.data.x_bigint, &val->data.x_bigint, | ||
| 18752 | dest_type->data.integral.bit_count, dest_type->data.integral.is_signed); | ||
| 18753 | return result; | ||
| 18754 | } | ||
| 18755 | |||
| 18756 | if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) { | ||
| 18757 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | ||
| 18758 | bigint_init_unsigned(&result->value.data.x_bigint, 0); | ||
| 18759 | return result; | ||
| 18760 | } | ||
| 18761 | |||
| 18057 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { | 18762 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { |
| 18058 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; | 18763 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; |
| 18059 | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); | 18764 | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); |
| ... | @@ -18064,13 +18769,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct | ... | @@ -18064,13 +18769,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct |
| 18064 | return ira->codegen->invalid_instruction; | 18769 | return ira->codegen->invalid_instruction; |
| 18065 | } | 18770 | } |
| 18066 | 18771 | ||
| 18067 | if (target->value.special == ConstValSpecialStatic) { | ||
| 18068 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | ||
| 18069 | bigint_truncate(&result->value.data.x_bigint, &target->value.data.x_bigint, | ||
| 18070 | dest_type->data.integral.bit_count, dest_type->data.integral.is_signed); | ||
| 18071 | return result; | ||
| 18072 | } | ||
| 18073 | |||
| 18074 | IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope, | 18772 | IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope, |
| 18075 | instruction->base.source_node, dest_type_value, target); | 18773 | instruction->base.source_node, dest_type_value, target); |
| 18076 | new_instruction->value.type = dest_type; | 18774 | new_instruction->value.type = dest_type; |
| ... | @@ -18174,18 +18872,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst | ... | @@ -18174,18 +18872,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst |
| 18174 | return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type); | 18872 | return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type); |
| 18175 | } | 18873 | } |
| 18176 | 18874 | ||
| 18177 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { | ||
| 18178 | Error err; | ||
| 18179 | |||
| 18180 | if (ty->id == ZigTypeIdPointer) { | ||
| 18181 | if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown))) | ||
| 18182 | return err; | ||
| 18183 | } | ||
| 18184 | |||
| 18185 | *result_align = get_ptr_align(ira->codegen, ty); | ||
| 18186 | return ErrorNone; | ||
| 18187 | } | ||
| 18188 | |||
| 18189 | static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) { | 18875 | static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) { |
| 18190 | Error err; | 18876 | Error err; |
| 18191 | 18877 | ||
| ... | @@ -18304,6 +18990,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct | ... | @@ -18304,6 +18990,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 18304 | return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); | 18990 | return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); |
| 18305 | } | 18991 | } |
| 18306 | 18992 | ||
| 18993 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { | ||
| 18994 | Error err; | ||
| 18995 | |||
| 18996 | ZigType *ptr_type = get_src_ptr_type(ty); | ||
| 18997 | assert(ptr_type != nullptr); | ||
| 18998 | if (ptr_type->id == ZigTypeIdPointer) { | ||
| 18999 | if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) | ||
| 19000 | return err; | ||
| 19001 | } | ||
| 19002 | |||
| 19003 | *result_align = get_ptr_align(ira->codegen, ty); | ||
| 19004 | return ErrorNone; | ||
| 19005 | } | ||
| 19006 | |||
| 18307 | static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) { | 19007 | static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) { |
| 18308 | ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); | 19008 | ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); |
| 18309 | if (type_is_invalid(dest_type)) | 19009 | if (type_is_invalid(dest_type)) |
| ... | @@ -18410,6 +19110,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct | ... | @@ -18410,6 +19110,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct |
| 18410 | return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count)); | 19110 | return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count)); |
| 18411 | } | 19111 | } |
| 18412 | 19112 | ||
| 19113 | static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstructionVectorType *instruction) { | ||
| 19114 | uint64_t len; | ||
| 19115 | if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len)) | ||
| 19116 | return ira->codegen->invalid_instruction; | ||
| 19117 | |||
| 19118 | ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child); | ||
| 19119 | if (type_is_invalid(elem_type)) | ||
| 19120 | return ira->codegen->invalid_instruction; | ||
| 19121 | |||
| 19122 | if (!is_valid_vector_elem_type(elem_type)) { | ||
| 19123 | ir_add_error(ira, instruction->elem_type, | ||
| 19124 | buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid", | ||
| 19125 | buf_ptr(&elem_type->name))); | ||
| 19126 | return ira->codegen->invalid_instruction; | ||
| 19127 | } | ||
| 19128 | |||
| 19129 | ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type); | ||
| 19130 | |||
| 19131 | return ir_const_type(ira, &instruction->base, vector_type); | ||
| 19132 | } | ||
| 19133 | |||
| 18413 | static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) { | 19134 | static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) { |
| 18414 | IrInstruction *value = instruction->value->child; | 19135 | IrInstruction *value = instruction->value->child; |
| 18415 | if (type_is_invalid(value->value.type)) | 19136 | if (type_is_invalid(value->value.type)) |
| ... | @@ -18508,10 +19229,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio | ... | @@ -18508,10 +19229,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio |
| 18508 | } | 19229 | } |
| 18509 | case ConstPtrSpecialBaseStruct: | 19230 | case ConstPtrSpecialBaseStruct: |
| 18510 | zig_panic("TODO memset on const inner struct"); | 19231 | zig_panic("TODO memset on const inner struct"); |
| 19232 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 19233 | zig_panic("TODO memset on const inner error union code"); | ||
| 19234 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 19235 | zig_panic("TODO memset on const inner error union payload"); | ||
| 19236 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 19237 | zig_panic("TODO memset on const inner optional payload"); | ||
| 18511 | case ConstPtrSpecialHardCodedAddr: | 19238 | case ConstPtrSpecialHardCodedAddr: |
| 18512 | zig_unreachable(); | 19239 | zig_unreachable(); |
| 18513 | case ConstPtrSpecialFunction: | 19240 | case ConstPtrSpecialFunction: |
| 18514 | zig_panic("TODO memset on ptr cast from function"); | 19241 | zig_panic("TODO memset on ptr cast from function"); |
| 19242 | case ConstPtrSpecialNull: | ||
| 19243 | zig_panic("TODO memset on null ptr"); | ||
| 18515 | } | 19244 | } |
| 18516 | 19245 | ||
| 18517 | size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint); | 19246 | size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint); |
| ... | @@ -18623,10 +19352,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio | ... | @@ -18623,10 +19352,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio |
| 18623 | } | 19352 | } |
| 18624 | case ConstPtrSpecialBaseStruct: | 19353 | case ConstPtrSpecialBaseStruct: |
| 18625 | zig_panic("TODO memcpy on const inner struct"); | 19354 | zig_panic("TODO memcpy on const inner struct"); |
| 19355 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 19356 | zig_panic("TODO memcpy on const inner error union code"); | ||
| 19357 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 19358 | zig_panic("TODO memcpy on const inner error union payload"); | ||
| 19359 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 19360 | zig_panic("TODO memcpy on const inner optional payload"); | ||
| 18626 | case ConstPtrSpecialHardCodedAddr: | 19361 | case ConstPtrSpecialHardCodedAddr: |
| 18627 | zig_unreachable(); | 19362 | zig_unreachable(); |
| 18628 | case ConstPtrSpecialFunction: | 19363 | case ConstPtrSpecialFunction: |
| 18629 | zig_panic("TODO memcpy on ptr cast from function"); | 19364 | zig_panic("TODO memcpy on ptr cast from function"); |
| 19365 | case ConstPtrSpecialNull: | ||
| 19366 | zig_panic("TODO memcpy on null ptr"); | ||
| 18630 | } | 19367 | } |
| 18631 | 19368 | ||
| 18632 | if (dest_start + count > dest_end) { | 19369 | if (dest_start + count > dest_end) { |
| ... | @@ -18659,10 +19396,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio | ... | @@ -18659,10 +19396,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio |
| 18659 | } | 19396 | } |
| 18660 | case ConstPtrSpecialBaseStruct: | 19397 | case ConstPtrSpecialBaseStruct: |
| 18661 | zig_panic("TODO memcpy on const inner struct"); | 19398 | zig_panic("TODO memcpy on const inner struct"); |
| 19399 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 19400 | zig_panic("TODO memcpy on const inner error union code"); | ||
| 19401 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 19402 | zig_panic("TODO memcpy on const inner error union payload"); | ||
| 19403 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 19404 | zig_panic("TODO memcpy on const inner optional payload"); | ||
| 18662 | case ConstPtrSpecialHardCodedAddr: | 19405 | case ConstPtrSpecialHardCodedAddr: |
| 18663 | zig_unreachable(); | 19406 | zig_unreachable(); |
| 18664 | case ConstPtrSpecialFunction: | 19407 | case ConstPtrSpecialFunction: |
| 18665 | zig_panic("TODO memcpy on ptr cast from function"); | 19408 | zig_panic("TODO memcpy on ptr cast from function"); |
| 19409 | case ConstPtrSpecialNull: | ||
| 19410 | zig_panic("TODO memcpy on null ptr"); | ||
| 18666 | } | 19411 | } |
| 18667 | 19412 | ||
| 18668 | if (src_start + count > src_end) { | 19413 | if (src_start + count > src_end) { |
| ... | @@ -18690,9 +19435,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18690,9 +19435,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18690 | if (type_is_invalid(ptr_ptr->value.type)) | 19435 | if (type_is_invalid(ptr_ptr->value.type)) |
| 18691 | return ira->codegen->invalid_instruction; | 19436 | return ira->codegen->invalid_instruction; |
| 18692 | 19437 | ||
| 18693 | ZigType *ptr_type = ptr_ptr->value.type; | 19438 | ZigType *ptr_ptr_type = ptr_ptr->value.type; |
| 18694 | assert(ptr_type->id == ZigTypeIdPointer); | 19439 | assert(ptr_ptr_type->id == ZigTypeIdPointer); |
| 18695 | ZigType *array_type = ptr_type->data.pointer.child_type; | 19440 | ZigType *array_type = ptr_ptr_type->data.pointer.child_type; |
| 18696 | 19441 | ||
| 18697 | IrInstruction *start = instruction->start->child; | 19442 | IrInstruction *start = instruction->start->child; |
| 18698 | if (type_is_invalid(start->value.type)) | 19443 | if (type_is_invalid(start->value.type)) |
| ... | @@ -18721,10 +19466,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18721,10 +19466,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18721 | bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic && | 19466 | bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic && |
| 18722 | ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst; | 19467 | ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst; |
| 18723 | ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, | 19468 | ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, |
| 18724 | ptr_type->data.pointer.is_const || is_comptime_const, | 19469 | ptr_ptr_type->data.pointer.is_const || is_comptime_const, |
| 18725 | ptr_type->data.pointer.is_volatile, | 19470 | ptr_ptr_type->data.pointer.is_volatile, |
| 18726 | PtrLenUnknown, | 19471 | PtrLenUnknown, |
| 18727 | ptr_type->data.pointer.explicit_alignment, 0, 0); | 19472 | ptr_ptr_type->data.pointer.explicit_alignment, 0, 0); |
| 18728 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | 19473 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| 18729 | } else if (array_type->id == ZigTypeIdPointer) { | 19474 | } else if (array_type->id == ZigTypeIdPointer) { |
| 18730 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { | 19475 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { |
| ... | @@ -18771,18 +19516,18 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18771,18 +19516,18 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18771 | if (array_type->id == ZigTypeIdPointer) { | 19516 | if (array_type->id == ZigTypeIdPointer) { |
| 18772 | ZigType *child_array_type = array_type->data.pointer.child_type; | 19517 | ZigType *child_array_type = array_type->data.pointer.child_type; |
| 18773 | assert(child_array_type->id == ZigTypeIdArray); | 19518 | assert(child_array_type->id == ZigTypeIdArray); |
| 18774 | parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node); | 19519 | parent_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); |
| 18775 | if (parent_ptr == nullptr) | 19520 | if (parent_ptr == nullptr) |
| 18776 | return ira->codegen->invalid_instruction; | 19521 | return ira->codegen->invalid_instruction; |
| 18777 | 19522 | ||
| 18778 | array_val = ir_const_ptr_pointee(ira, parent_ptr, instruction->base.source_node); | 19523 | array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node); |
| 18779 | if (array_val == nullptr) | 19524 | if (array_val == nullptr) |
| 18780 | return ira->codegen->invalid_instruction; | 19525 | return ira->codegen->invalid_instruction; |
| 18781 | 19526 | ||
| 18782 | rel_end = child_array_type->data.array.len; | 19527 | rel_end = child_array_type->data.array.len; |
| 18783 | abs_offset = 0; | 19528 | abs_offset = 0; |
| 18784 | } else { | 19529 | } else { |
| 18785 | array_val = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node); | 19530 | array_val = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); |
| 18786 | if (array_val == nullptr) | 19531 | if (array_val == nullptr) |
| 18787 | return ira->codegen->invalid_instruction; | 19532 | return ira->codegen->invalid_instruction; |
| 18788 | rel_end = array_type->data.array.len; | 19533 | rel_end = array_type->data.array.len; |
| ... | @@ -18791,7 +19536,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18791,7 +19536,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18791 | } | 19536 | } |
| 18792 | } else if (array_type->id == ZigTypeIdPointer) { | 19537 | } else if (array_type->id == ZigTypeIdPointer) { |
| 18793 | assert(array_type->data.pointer.ptr_len == PtrLenUnknown); | 19538 | assert(array_type->data.pointer.ptr_len == PtrLenUnknown); |
| 18794 | parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node); | 19539 | parent_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); |
| 18795 | if (parent_ptr == nullptr) | 19540 | if (parent_ptr == nullptr) |
| 18796 | return ira->codegen->invalid_instruction; | 19541 | return ira->codegen->invalid_instruction; |
| 18797 | 19542 | ||
| ... | @@ -18822,6 +19567,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18822,6 +19567,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18822 | break; | 19567 | break; |
| 18823 | case ConstPtrSpecialBaseStruct: | 19568 | case ConstPtrSpecialBaseStruct: |
| 18824 | zig_panic("TODO slice const inner struct"); | 19569 | zig_panic("TODO slice const inner struct"); |
| 19570 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 19571 | zig_panic("TODO slice const inner error union code"); | ||
| 19572 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 19573 | zig_panic("TODO slice const inner error union payload"); | ||
| 19574 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 19575 | zig_panic("TODO slice const inner optional payload"); | ||
| 18825 | case ConstPtrSpecialHardCodedAddr: | 19576 | case ConstPtrSpecialHardCodedAddr: |
| 18826 | array_val = nullptr; | 19577 | array_val = nullptr; |
| 18827 | abs_offset = 0; | 19578 | abs_offset = 0; |
| ... | @@ -18829,9 +19580,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18829,9 +19580,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18829 | break; | 19580 | break; |
| 18830 | case ConstPtrSpecialFunction: | 19581 | case ConstPtrSpecialFunction: |
| 18831 | zig_panic("TODO slice of ptr cast from function"); | 19582 | zig_panic("TODO slice of ptr cast from function"); |
| 19583 | case ConstPtrSpecialNull: | ||
| 19584 | zig_panic("TODO slice of null ptr"); | ||
| 18832 | } | 19585 | } |
| 18833 | } else if (is_slice(array_type)) { | 19586 | } else if (is_slice(array_type)) { |
| 18834 | ConstExprValue *slice_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node); | 19587 | ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); |
| 18835 | if (slice_ptr == nullptr) | 19588 | if (slice_ptr == nullptr) |
| 18836 | return ira->codegen->invalid_instruction; | 19589 | return ira->codegen->invalid_instruction; |
| 18837 | 19590 | ||
| ... | @@ -18859,6 +19612,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18859,6 +19612,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18859 | break; | 19612 | break; |
| 18860 | case ConstPtrSpecialBaseStruct: | 19613 | case ConstPtrSpecialBaseStruct: |
| 18861 | zig_panic("TODO slice const inner struct"); | 19614 | zig_panic("TODO slice const inner struct"); |
| 19615 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 19616 | zig_panic("TODO slice const inner error union code"); | ||
| 19617 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 19618 | zig_panic("TODO slice const inner error union payload"); | ||
| 19619 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 19620 | zig_panic("TODO slice const inner optional payload"); | ||
| 18862 | case ConstPtrSpecialHardCodedAddr: | 19621 | case ConstPtrSpecialHardCodedAddr: |
| 18863 | array_val = nullptr; | 19622 | array_val = nullptr; |
| 18864 | abs_offset = 0; | 19623 | abs_offset = 0; |
| ... | @@ -18866,6 +19625,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18866,6 +19625,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18866 | break; | 19625 | break; |
| 18867 | case ConstPtrSpecialFunction: | 19626 | case ConstPtrSpecialFunction: |
| 18868 | zig_panic("TODO slice of slice cast from function"); | 19627 | zig_panic("TODO slice of slice cast from function"); |
| 19628 | case ConstPtrSpecialNull: | ||
| 19629 | zig_panic("TODO slice of null"); | ||
| 18869 | } | 19630 | } |
| 18870 | } else { | 19631 | } else { |
| 18871 | zig_unreachable(); | 19632 | zig_unreachable(); |
| ... | @@ -18931,6 +19692,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18931,6 +19692,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18931 | zig_unreachable(); | 19692 | zig_unreachable(); |
| 18932 | case ConstPtrSpecialBaseStruct: | 19693 | case ConstPtrSpecialBaseStruct: |
| 18933 | zig_panic("TODO"); | 19694 | zig_panic("TODO"); |
| 19695 | case ConstPtrSpecialBaseErrorUnionCode: | ||
| 19696 | zig_panic("TODO"); | ||
| 19697 | case ConstPtrSpecialBaseErrorUnionPayload: | ||
| 19698 | zig_panic("TODO"); | ||
| 19699 | case ConstPtrSpecialBaseOptionalPayload: | ||
| 19700 | zig_panic("TODO"); | ||
| 18934 | case ConstPtrSpecialHardCodedAddr: | 19701 | case ConstPtrSpecialHardCodedAddr: |
| 18935 | init_const_ptr_hard_coded_addr(ira->codegen, ptr_val, | 19702 | init_const_ptr_hard_coded_addr(ira->codegen, ptr_val, |
| 18936 | parent_ptr->type->data.pointer.child_type, | 19703 | parent_ptr->type->data.pointer.child_type, |
| ... | @@ -18939,6 +19706,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -18939,6 +19706,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18939 | break; | 19706 | break; |
| 18940 | case ConstPtrSpecialFunction: | 19707 | case ConstPtrSpecialFunction: |
| 18941 | zig_panic("TODO"); | 19708 | zig_panic("TODO"); |
| 19709 | case ConstPtrSpecialNull: | ||
| 19710 | zig_panic("TODO"); | ||
| 18942 | } | 19711 | } |
| 18943 | 19712 | ||
| 18944 | ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; | 19713 | ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; |
| ... | @@ -19165,6 +19934,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct | ... | @@ -19165,6 +19934,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct |
| 19165 | case ZigTypeIdEnum: | 19934 | case ZigTypeIdEnum: |
| 19166 | case ZigTypeIdUnion: | 19935 | case ZigTypeIdUnion: |
| 19167 | case ZigTypeIdFn: | 19936 | case ZigTypeIdFn: |
| 19937 | case ZigTypeIdVector: | ||
| 19168 | { | 19938 | { |
| 19169 | uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); | 19939 | uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); |
| 19170 | return ir_const_unsigned(ira, &instruction->base, align_in_bytes); | 19940 | return ir_const_unsigned(ira, &instruction->base, align_in_bytes); |
| ... | @@ -19240,7 +20010,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr | ... | @@ -19240,7 +20010,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr |
| 19240 | { | 20010 | { |
| 19241 | BigInt *op1_bigint = &casted_op1->value.data.x_bigint; | 20011 | BigInt *op1_bigint = &casted_op1->value.data.x_bigint; |
| 19242 | BigInt *op2_bigint = &casted_op2->value.data.x_bigint; | 20012 | BigInt *op2_bigint = &casted_op2->value.data.x_bigint; |
| 19243 | ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, &casted_result_ptr->value, casted_result_ptr->source_node); | 20013 | ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, &casted_result_ptr->value, casted_result_ptr->source_node); |
| 19244 | if (pointee_val == nullptr) | 20014 | if (pointee_val == nullptr) |
| 19245 | return ira->codegen->invalid_instruction; | 20015 | return ira->codegen->invalid_instruction; |
| 19246 | BigInt *dest_bigint = &pointee_val->data.x_bigint; | 20016 | BigInt *dest_bigint = &pointee_val->data.x_bigint; |
| ... | @@ -19294,7 +20064,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct | ... | @@ -19294,7 +20064,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct |
| 19294 | return ira->codegen->invalid_instruction; | 20064 | return ira->codegen->invalid_instruction; |
| 19295 | 20065 | ||
| 19296 | if (err_union_val->special != ConstValSpecialRuntime) { | 20066 | if (err_union_val->special != ConstValSpecialRuntime) { |
| 19297 | return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr)); | 20067 | ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; |
| 20068 | return ir_const_bool(ira, &instruction->base, (err != nullptr)); | ||
| 19298 | } | 20069 | } |
| 19299 | } | 20070 | } |
| 19300 | 20071 | ||
| ... | @@ -19320,48 +20091,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct | ... | @@ -19320,48 +20091,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct |
| 19320 | } | 20091 | } |
| 19321 | } | 20092 | } |
| 19322 | 20093 | ||
| 19323 | static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, | 20094 | static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) { |
| 19324 | IrInstructionUnwrapErrCode *instruction) | 20095 | IrInstruction *base_ptr = instruction->err_union->child; |
| 19325 | { | 20096 | if (type_is_invalid(base_ptr->value.type)) |
| 19326 | IrInstruction *value = instruction->value->child; | ||
| 19327 | if (type_is_invalid(value->value.type)) | ||
| 19328 | return ira->codegen->invalid_instruction; | 20097 | return ira->codegen->invalid_instruction; |
| 19329 | ZigType *ptr_type = value->value.type; | 20098 | ZigType *ptr_type = base_ptr->value.type; |
| 19330 | 20099 | ||
| 19331 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. | 20100 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. |
| 19332 | assert(ptr_type->id == ZigTypeIdPointer); | 20101 | assert(ptr_type->id == ZigTypeIdPointer); |
| 19333 | 20102 | ||
| 19334 | ZigType *type_entry = ptr_type->data.pointer.child_type; | 20103 | ZigType *type_entry = ptr_type->data.pointer.child_type; |
| 19335 | if (type_is_invalid(type_entry)) { | 20104 | if (type_is_invalid(type_entry)) |
| 19336 | return ira->codegen->invalid_instruction; | 20105 | return ira->codegen->invalid_instruction; |
| 19337 | } else if (type_entry->id == ZigTypeIdErrorUnion) { | ||
| 19338 | if (instr_is_comptime(value)) { | ||
| 19339 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | ||
| 19340 | if (!ptr_val) | ||
| 19341 | return ira->codegen->invalid_instruction; | ||
| 19342 | ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node); | ||
| 19343 | if (err_union_val == nullptr) | ||
| 19344 | return ira->codegen->invalid_instruction; | ||
| 19345 | if (err_union_val->special != ConstValSpecialRuntime) { | ||
| 19346 | ErrorTableEntry *err = err_union_val->data.x_err_union.err; | ||
| 19347 | assert(err); | ||
| 19348 | 20106 | ||
| 19349 | IrInstruction *result = ir_const(ira, &instruction->base, | 20107 | if (type_entry->id != ZigTypeIdErrorUnion) { |
| 19350 | type_entry->data.error_union.err_set_type); | 20108 | ir_add_error(ira, base_ptr, |
| 19351 | result->value.data.x_err_set = err; | ||
| 19352 | return result; | ||
| 19353 | } | ||
| 19354 | } | ||
| 19355 | |||
| 19356 | IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, | ||
| 19357 | instruction->base.scope, instruction->base.source_node, value); | ||
| 19358 | result->value.type = type_entry->data.error_union.err_set_type; | ||
| 19359 | return result; | ||
| 19360 | } else { | ||
| 19361 | ir_add_error(ira, value, | ||
| 19362 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); | 20109 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); |
| 19363 | return ira->codegen->invalid_instruction; | 20110 | return ira->codegen->invalid_instruction; |
| 19364 | } | 20111 | } |
| 20112 | |||
| 20113 | if (instr_is_comptime(base_ptr)) { | ||
| 20114 | ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); | ||
| 20115 | if (!ptr_val) | ||
| 20116 | return ira->codegen->invalid_instruction; | ||
| 20117 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); | ||
| 20118 | if (err_union_val == nullptr) | ||
| 20119 | return ira->codegen->invalid_instruction; | ||
| 20120 | if (err_union_val->special != ConstValSpecialRuntime) { | ||
| 20121 | ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; | ||
| 20122 | assert(err); | ||
| 20123 | |||
| 20124 | IrInstruction *result = ir_const(ira, &instruction->base, | ||
| 20125 | type_entry->data.error_union.err_set_type); | ||
| 20126 | result->value.data.x_err_set = err; | ||
| 20127 | return result; | ||
| 20128 | } | ||
| 20129 | } | ||
| 20130 | |||
| 20131 | IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, | ||
| 20132 | instruction->base.scope, instruction->base.source_node, base_ptr); | ||
| 20133 | result->value.type = type_entry->data.error_union.err_set_type; | ||
| 20134 | return result; | ||
| 19365 | } | 20135 | } |
| 19366 | 20136 | ||
| 19367 | static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, | 20137 | static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| ... | @@ -19377,48 +20147,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, | ... | @@ -19377,48 +20147,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 19377 | assert(ptr_type->id == ZigTypeIdPointer); | 20147 | assert(ptr_type->id == ZigTypeIdPointer); |
| 19378 | 20148 | ||
| 19379 | ZigType *type_entry = ptr_type->data.pointer.child_type; | 20149 | ZigType *type_entry = ptr_type->data.pointer.child_type; |
| 19380 | if (type_is_invalid(type_entry)) { | 20150 | if (type_is_invalid(type_entry)) |
| 19381 | return ira->codegen->invalid_instruction; | 20151 | return ira->codegen->invalid_instruction; |
| 19382 | } else if (type_entry->id == ZigTypeIdErrorUnion) { | ||
| 19383 | ZigType *payload_type = type_entry->data.error_union.payload_type; | ||
| 19384 | if (type_is_invalid(payload_type)) { | ||
| 19385 | return ira->codegen->invalid_instruction; | ||
| 19386 | } | ||
| 19387 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, | ||
| 19388 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | ||
| 19389 | PtrLenSingle, 0, 0, 0); | ||
| 19390 | if (instr_is_comptime(value)) { | ||
| 19391 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | ||
| 19392 | if (!ptr_val) | ||
| 19393 | return ira->codegen->invalid_instruction; | ||
| 19394 | ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node); | ||
| 19395 | if (err_union_val == nullptr) | ||
| 19396 | return ira->codegen->invalid_instruction; | ||
| 19397 | if (err_union_val->special != ConstValSpecialRuntime) { | ||
| 19398 | ErrorTableEntry *err = err_union_val->data.x_err_union.err; | ||
| 19399 | if (err != nullptr) { | ||
| 19400 | ir_add_error(ira, &instruction->base, | ||
| 19401 | buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); | ||
| 19402 | return ira->codegen->invalid_instruction; | ||
| 19403 | } | ||
| 19404 | 20152 | ||
| 19405 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); | 20153 | if (type_entry->id != ZigTypeIdErrorUnion) { |
| 19406 | result->value.data.x_ptr.special = ConstPtrSpecialRef; | ||
| 19407 | result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload; | ||
| 19408 | return result; | ||
| 19409 | } | ||
| 19410 | } | ||
| 19411 | |||
| 19412 | IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, | ||
| 19413 | instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on); | ||
| 19414 | result->value.type = result_type; | ||
| 19415 | return result; | ||
| 19416 | } else { | ||
| 19417 | ir_add_error(ira, value, | 20154 | ir_add_error(ira, value, |
| 19418 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); | 20155 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); |
| 19419 | return ira->codegen->invalid_instruction; | 20156 | return ira->codegen->invalid_instruction; |
| 19420 | } | 20157 | } |
| 19421 | 20158 | ||
| 20159 | ZigType *payload_type = type_entry->data.error_union.payload_type; | ||
| 20160 | if (type_is_invalid(payload_type)) | ||
| 20161 | return ira->codegen->invalid_instruction; | ||
| 20162 | |||
| 20163 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, | ||
| 20164 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | ||
| 20165 | PtrLenSingle, 0, 0, 0); | ||
| 20166 | if (instr_is_comptime(value)) { | ||
| 20167 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | ||
| 20168 | if (!ptr_val) | ||
| 20169 | return ira->codegen->invalid_instruction; | ||
| 20170 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); | ||
| 20171 | if (err_union_val == nullptr) | ||
| 20172 | return ira->codegen->invalid_instruction; | ||
| 20173 | if (err_union_val->special != ConstValSpecialRuntime) { | ||
| 20174 | ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; | ||
| 20175 | if (err != nullptr) { | ||
| 20176 | ir_add_error(ira, &instruction->base, | ||
| 20177 | buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); | ||
| 20178 | return ira->codegen->invalid_instruction; | ||
| 20179 | } | ||
| 20180 | |||
| 20181 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); | ||
| 20182 | result->value.data.x_ptr.special = ConstPtrSpecialRef; | ||
| 20183 | result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload; | ||
| 20184 | return result; | ||
| 20185 | } | ||
| 20186 | } | ||
| 20187 | |||
| 20188 | IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, | ||
| 20189 | instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on); | ||
| 20190 | result->value.type = result_type; | ||
| 20191 | return result; | ||
| 19422 | } | 20192 | } |
| 19423 | 20193 | ||
| 19424 | static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { | 20194 | static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { |
| ... | @@ -19696,6 +20466,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -19696,6 +20466,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 19696 | return ira->codegen->invalid_instruction; | 20466 | return ira->codegen->invalid_instruction; |
| 19697 | } | 20467 | } |
| 19698 | } | 20468 | } |
| 20469 | } else if (switch_type->id == ZigTypeIdBool) { | ||
| 20470 | int seenTrue = 0; | ||
| 20471 | int seenFalse = 0; | ||
| 20472 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { | ||
| 20473 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; | ||
| 20474 | |||
| 20475 | IrInstruction *value = range->start->child; | ||
| 20476 | |||
| 20477 | IrInstruction *casted_value = ir_implicit_cast(ira, value, switch_type); | ||
| 20478 | if (type_is_invalid(casted_value->value.type)) | ||
| 20479 | return ira->codegen->invalid_instruction; | ||
| 20480 | |||
| 20481 | ConstExprValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad); | ||
| 20482 | if (!const_expr_val) | ||
| 20483 | return ira->codegen->invalid_instruction; | ||
| 20484 | |||
| 20485 | assert(const_expr_val->type->id == ZigTypeIdBool); | ||
| 20486 | |||
| 20487 | if (const_expr_val->data.x_bool == true) { | ||
| 20488 | seenTrue += 1; | ||
| 20489 | } else { | ||
| 20490 | seenFalse += 1; | ||
| 20491 | } | ||
| 20492 | |||
| 20493 | if ((seenTrue > 1) || (seenFalse > 1)) { | ||
| 20494 | ir_add_error(ira, value, buf_sprintf("duplicate switch value")); | ||
| 20495 | return ira->codegen->invalid_instruction; | ||
| 20496 | } | ||
| 20497 | } | ||
| 20498 | if (((seenTrue < 1) || (seenFalse < 1)) && !instruction->have_else_prong) { | ||
| 20499 | ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities")); | ||
| 20500 | return ira->codegen->invalid_instruction; | ||
| 20501 | } | ||
| 19699 | } else if (!instruction->have_else_prong) { | 20502 | } else if (!instruction->have_else_prong) { |
| 19700 | ir_add_error(ira, &instruction->base, | 20503 | ir_add_error(ira, &instruction->base, |
| 19701 | buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); | 20504 | buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); |
| ... | @@ -19802,7 +20605,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 | ... | @@ -19802,7 +20605,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 19802 | return ira->codegen->invalid_instruction; | 20605 | return ira->codegen->invalid_instruction; |
| 19803 | } | 20606 | } |
| 19804 | 20607 | ||
| 19805 | IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); | 20608 | IrInstruction *result = ir_const(ira, target, result_type); |
| 19806 | copy_const_val(&result->value, val, false); | 20609 | copy_const_val(&result->value, val, false); |
| 19807 | result->value.type = result_type; | 20610 | result->value.type = result_type; |
| 19808 | return result; | 20611 | return result; |
| ... | @@ -19819,7 +20622,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 | ... | @@ -19819,7 +20622,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 19819 | } | 20622 | } |
| 19820 | 20623 | ||
| 19821 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, | 20624 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| 19822 | ZigType *dest_type, IrInstruction *dest_type_src) | 20625 | ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on) |
| 19823 | { | 20626 | { |
| 19824 | Error err; | 20627 | Error err; |
| 19825 | 20628 | ||
| ... | @@ -19829,12 +20632,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -19829,12 +20632,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 19829 | // We have a check for zero bits later so we use get_src_ptr_type to | 20632 | // We have a check for zero bits later so we use get_src_ptr_type to |
| 19830 | // validate src_type and dest_type. | 20633 | // validate src_type and dest_type. |
| 19831 | 20634 | ||
| 19832 | if (get_src_ptr_type(src_type) == nullptr) { | 20635 | ZigType *src_ptr_type = get_src_ptr_type(src_type); |
| 20636 | if (src_ptr_type == nullptr) { | ||
| 19833 | ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); | 20637 | ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); |
| 19834 | return ira->codegen->invalid_instruction; | 20638 | return ira->codegen->invalid_instruction; |
| 19835 | } | 20639 | } |
| 19836 | 20640 | ||
| 19837 | if (get_src_ptr_type(dest_type) == nullptr) { | 20641 | ZigType *dest_ptr_type = get_src_ptr_type(dest_type); |
| 20642 | if (dest_ptr_type == nullptr) { | ||
| 19838 | ir_add_error(ira, dest_type_src, | 20643 | ir_add_error(ira, dest_type_src, |
| 19839 | buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); | 20644 | buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); |
| 19840 | return ira->codegen->invalid_instruction; | 20645 | return ira->codegen->invalid_instruction; |
| ... | @@ -19846,12 +20651,24 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -19846,12 +20651,24 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 19846 | } | 20651 | } |
| 19847 | 20652 | ||
| 19848 | if (instr_is_comptime(ptr)) { | 20653 | if (instr_is_comptime(ptr)) { |
| 19849 | ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); | 20654 | bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type); |
| 20655 | UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad; | ||
| 20656 | ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed); | ||
| 19850 | if (!val) | 20657 | if (!val) |
| 19851 | return ira->codegen->invalid_instruction; | 20658 | return ira->codegen->invalid_instruction; |
| 19852 | 20659 | ||
| 19853 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node, | 20660 | if (val->special == ConstValSpecialStatic) { |
| 19854 | dest_type); | 20661 | bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull || |
| 20662 | (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | ||
| 20663 | val->data.x_ptr.data.hard_coded_addr.addr == 0); | ||
| 20664 | if (is_addr_zero && !dest_allows_addr_zero) { | ||
| 20665 | ir_add_error(ira, source_instr, | ||
| 20666 | buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name))); | ||
| 20667 | return ira->codegen->invalid_instruction; | ||
| 20668 | } | ||
| 20669 | } | ||
| 20670 | |||
| 20671 | IrInstruction *result = ir_const(ira, source_instr, dest_type); | ||
| 19855 | copy_const_val(&result->value, val, false); | 20672 | copy_const_val(&result->value, val, false); |
| 19856 | result->value.type = dest_type; | 20673 | result->value.type = dest_type; |
| 19857 | return result; | 20674 | return result; |
| ... | @@ -19874,9 +20691,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -19874,9 +20691,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 19874 | return ira->codegen->invalid_instruction; | 20691 | return ira->codegen->invalid_instruction; |
| 19875 | } | 20692 | } |
| 19876 | 20693 | ||
| 19877 | IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope, | 20694 | IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); |
| 19878 | source_instr->source_node, nullptr, ptr); | ||
| 19879 | casted_ptr->value.type = dest_type; | ||
| 19880 | 20695 | ||
| 19881 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { | 20696 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { |
| 19882 | ErrorMsg *msg = ir_add_error(ira, source_instr, | 20697 | ErrorMsg *msg = ir_add_error(ira, source_instr, |
| ... | @@ -19902,7 +20717,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -19902,7 +20717,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 19902 | return result; | 20717 | return result; |
| 19903 | } | 20718 | } |
| 19904 | 20719 | ||
| 19905 | static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { | 20720 | static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) { |
| 19906 | IrInstruction *dest_type_value = instruction->dest_type->child; | 20721 | IrInstruction *dest_type_value = instruction->dest_type->child; |
| 19907 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | 20722 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); |
| 19908 | if (type_is_invalid(dest_type)) | 20723 | if (type_is_invalid(dest_type)) |
| ... | @@ -19913,10 +20728,24 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct | ... | @@ -19913,10 +20728,24 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct |
| 19913 | if (type_is_invalid(src_type)) | 20728 | if (type_is_invalid(src_type)) |
| 19914 | return ira->codegen->invalid_instruction; | 20729 | return ira->codegen->invalid_instruction; |
| 19915 | 20730 | ||
| 19916 | return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value); | 20731 | return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value, |
| 20732 | instruction->safety_check_on); | ||
| 20733 | } | ||
| 20734 | |||
| 20735 | static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) { | ||
| 20736 | size_t buf_i = 0; | ||
| 20737 | // TODO optimize the buf case | ||
| 20738 | expand_undef_array(codegen, val); | ||
| 20739 | for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) { | ||
| 20740 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i]; | ||
| 20741 | buf_write_value_bytes(codegen, &buf[buf_i], elem); | ||
| 20742 | buf_i += type_size(codegen, elem->type); | ||
| 20743 | } | ||
| 19917 | } | 20744 | } |
| 19918 | 20745 | ||
| 19919 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { | 20746 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { |
| 20747 | if (val->special == ConstValSpecialUndef) | ||
| 20748 | val->special = ConstValSpecialStatic; | ||
| 19920 | assert(val->special == ConstValSpecialStatic); | 20749 | assert(val->special == ConstValSpecialStatic); |
| 19921 | switch (val->type->id) { | 20750 | switch (val->type->id) { |
| 19922 | case ZigTypeIdInvalid: | 20751 | case ZigTypeIdInvalid: |
| ... | @@ -19959,17 +20788,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -19959,17 +20788,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19959 | zig_unreachable(); | 20788 | zig_unreachable(); |
| 19960 | } | 20789 | } |
| 19961 | case ZigTypeIdArray: | 20790 | case ZigTypeIdArray: |
| 19962 | { | 20791 | return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len); |
| 19963 | size_t buf_i = 0; | 20792 | case ZigTypeIdVector: |
| 19964 | // TODO optimize the buf case | 20793 | return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len); |
| 19965 | expand_undef_array(codegen, val); | ||
| 19966 | for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) { | ||
| 19967 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i]; | ||
| 19968 | buf_write_value_bytes(codegen, &buf[buf_i], elem); | ||
| 19969 | buf_i += type_size(codegen, elem->type); | ||
| 19970 | } | ||
| 19971 | } | ||
| 19972 | return; | ||
| 19973 | case ZigTypeIdStruct: | 20794 | case ZigTypeIdStruct: |
| 19974 | zig_panic("TODO buf_write_value_bytes struct type"); | 20795 | zig_panic("TODO buf_write_value_bytes struct type"); |
| 19975 | case ZigTypeIdOptional: | 20796 | case ZigTypeIdOptional: |
| ... | @@ -19986,7 +20807,33 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -19986,7 +20807,33 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19986 | zig_unreachable(); | 20807 | zig_unreachable(); |
| 19987 | } | 20808 | } |
| 19988 | 20809 | ||
| 19989 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { | 20810 | static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, |
| 20811 | ConstExprValue *val, ZigType *elem_type, size_t len) | ||
| 20812 | { | ||
| 20813 | Error err; | ||
| 20814 | uint64_t elem_size = type_size(codegen, elem_type); | ||
| 20815 | |||
| 20816 | switch (val->data.x_array.special) { | ||
| 20817 | case ConstArraySpecialNone: | ||
| 20818 | val->data.x_array.data.s_none.elements = create_const_vals(len); | ||
| 20819 | for (size_t i = 0; i < len; i++) { | ||
| 20820 | ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i]; | ||
| 20821 | elem->special = ConstValSpecialStatic; | ||
| 20822 | elem->type = elem_type; | ||
| 20823 | if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) | ||
| 20824 | return err; | ||
| 20825 | } | ||
| 20826 | return ErrorNone; | ||
| 20827 | case ConstArraySpecialUndef: | ||
| 20828 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type"); | ||
| 20829 | case ConstArraySpecialBuf: | ||
| 20830 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type"); | ||
| 20831 | } | ||
| 20832 | zig_unreachable(); | ||
| 20833 | } | ||
| 20834 | |||
| 20835 | static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { | ||
| 20836 | Error err; | ||
| 19990 | assert(val->special == ConstValSpecialStatic); | 20837 | assert(val->special == ConstValSpecialStatic); |
| 19991 | switch (val->type->id) { | 20838 | switch (val->type->id) { |
| 19992 | case ZigTypeIdInvalid: | 20839 | case ZigTypeIdInvalid: |
| ... | @@ -20003,17 +20850,17 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20003,17 +20850,17 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20003 | case ZigTypeIdPromise: | 20850 | case ZigTypeIdPromise: |
| 20004 | zig_unreachable(); | 20851 | zig_unreachable(); |
| 20005 | case ZigTypeIdVoid: | 20852 | case ZigTypeIdVoid: |
| 20006 | return; | 20853 | return ErrorNone; |
| 20007 | case ZigTypeIdBool: | 20854 | case ZigTypeIdBool: |
| 20008 | val->data.x_bool = (buf[0] != 0); | 20855 | val->data.x_bool = (buf[0] != 0); |
| 20009 | return; | 20856 | return ErrorNone; |
| 20010 | case ZigTypeIdInt: | 20857 | case ZigTypeIdInt: |
| 20011 | bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, | 20858 | bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, |
| 20012 | codegen->is_big_endian, val->type->data.integral.is_signed); | 20859 | codegen->is_big_endian, val->type->data.integral.is_signed); |
| 20013 | return; | 20860 | return ErrorNone; |
| 20014 | case ZigTypeIdFloat: | 20861 | case ZigTypeIdFloat: |
| 20015 | float_read_ieee597(val, buf, codegen->is_big_endian); | 20862 | float_read_ieee597(val, buf, codegen->is_big_endian); |
| 20016 | return; | 20863 | return ErrorNone; |
| 20017 | case ZigTypeIdPointer: | 20864 | case ZigTypeIdPointer: |
| 20018 | { | 20865 | { |
| 20019 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 20866 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| ... | @@ -20021,20 +20868,67 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20021,20 +20868,67 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20021 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, | 20868 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, |
| 20022 | codegen->is_big_endian, false); | 20869 | codegen->is_big_endian, false); |
| 20023 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); | 20870 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); |
| 20024 | return; | 20871 | return ErrorNone; |
| 20025 | } | 20872 | } |
| 20026 | case ZigTypeIdArray: | 20873 | case ZigTypeIdArray: |
| 20027 | zig_panic("TODO buf_read_value_bytes array type"); | 20874 | return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type, |
| 20875 | val->type->data.array.len); | ||
| 20876 | case ZigTypeIdVector: | ||
| 20877 | return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type, | ||
| 20878 | val->type->data.vector.len); | ||
| 20879 | case ZigTypeIdEnum: | ||
| 20880 | switch (val->type->data.enumeration.layout) { | ||
| 20881 | case ContainerLayoutAuto: | ||
| 20882 | zig_panic("TODO buf_read_value_bytes enum auto"); | ||
| 20883 | case ContainerLayoutPacked: | ||
| 20884 | zig_panic("TODO buf_read_value_bytes enum packed"); | ||
| 20885 | case ContainerLayoutExtern: { | ||
| 20886 | ZigType *tag_int_type = val->type->data.enumeration.tag_int_type; | ||
| 20887 | assert(tag_int_type->id == ZigTypeIdInt); | ||
| 20888 | bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count, | ||
| 20889 | codegen->is_big_endian, tag_int_type->data.integral.is_signed); | ||
| 20890 | return ErrorNone; | ||
| 20891 | } | ||
| 20892 | } | ||
| 20893 | zig_unreachable(); | ||
| 20028 | case ZigTypeIdStruct: | 20894 | case ZigTypeIdStruct: |
| 20029 | zig_panic("TODO buf_read_value_bytes struct type"); | 20895 | switch (val->type->data.structure.layout) { |
| 20896 | case ContainerLayoutAuto: { | ||
| 20897 | ErrorMsg *msg = opt_ir_add_error_node(ira, codegen, source_node, | ||
| 20898 | buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted", | ||
| 20899 | buf_ptr(&val->type->name))); | ||
| 20900 | add_error_note(codegen, msg, val->type->data.structure.decl_node, | ||
| 20901 | buf_sprintf("declared here")); | ||
| 20902 | return ErrorSemanticAnalyzeFail; | ||
| 20903 | } | ||
| 20904 | case ContainerLayoutExtern: { | ||
| 20905 | size_t src_field_count = val->type->data.structure.src_field_count; | ||
| 20906 | val->data.x_struct.fields = create_const_vals(src_field_count); | ||
| 20907 | for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { | ||
| 20908 | ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; | ||
| 20909 | field_val->special = ConstValSpecialStatic; | ||
| 20910 | TypeStructField *type_field = &val->type->data.structure.fields[field_i]; | ||
| 20911 | field_val->type = type_field->type_entry; | ||
| 20912 | if (type_field->gen_index == SIZE_MAX) | ||
| 20913 | continue; | ||
| 20914 | size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref, | ||
| 20915 | type_field->gen_index); | ||
| 20916 | uint8_t *new_buf = buf + offset; | ||
| 20917 | if ((err = buf_read_value_bytes(ira, codegen, source_node, new_buf, field_val))) | ||
| 20918 | return err; | ||
| 20919 | } | ||
| 20920 | return ErrorNone; | ||
| 20921 | } | ||
| 20922 | case ContainerLayoutPacked: | ||
| 20923 | zig_panic("TODO buf_read_value_bytes packed struct"); | ||
| 20924 | } | ||
| 20925 | zig_unreachable(); | ||
| 20030 | case ZigTypeIdOptional: | 20926 | case ZigTypeIdOptional: |
| 20031 | zig_panic("TODO buf_read_value_bytes maybe type"); | 20927 | zig_panic("TODO buf_read_value_bytes maybe type"); |
| 20032 | case ZigTypeIdErrorUnion: | 20928 | case ZigTypeIdErrorUnion: |
| 20033 | zig_panic("TODO buf_read_value_bytes error union"); | 20929 | zig_panic("TODO buf_read_value_bytes error union"); |
| 20034 | case ZigTypeIdErrorSet: | 20930 | case ZigTypeIdErrorSet: |
| 20035 | zig_panic("TODO buf_read_value_bytes pure error type"); | 20931 | zig_panic("TODO buf_read_value_bytes pure error type"); |
| 20036 | case ZigTypeIdEnum: | ||
| 20037 | zig_panic("TODO buf_read_value_bytes enum type"); | ||
| 20038 | case ZigTypeIdFn: | 20932 | case ZigTypeIdFn: |
| 20039 | zig_panic("TODO buf_read_value_bytes fn type"); | 20933 | zig_panic("TODO buf_read_value_bytes fn type"); |
| 20040 | case ZigTypeIdUnion: | 20934 | case ZigTypeIdUnion: |
| ... | @@ -20043,32 +20937,10 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20043,32 +20937,10 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20043 | zig_unreachable(); | 20937 | zig_unreachable(); |
| 20044 | } | 20938 | } |
| 20045 | 20939 | ||
| 20046 | static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { | 20940 | static bool type_can_bit_cast(ZigType *t) { |
| 20047 | Error err; | 20941 | switch (t->id) { |
| 20048 | IrInstruction *dest_type_value = instruction->dest_type->child; | ||
| 20049 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | ||
| 20050 | if (type_is_invalid(dest_type)) | ||
| 20051 | return ira->codegen->invalid_instruction; | ||
| 20052 | |||
| 20053 | IrInstruction *value = instruction->value->child; | ||
| 20054 | ZigType *src_type = value->value.type; | ||
| 20055 | if (type_is_invalid(src_type)) | ||
| 20056 | return ira->codegen->invalid_instruction; | ||
| 20057 | |||
| 20058 | if ((err = ensure_complete_type(ira->codegen, dest_type))) | ||
| 20059 | return ira->codegen->invalid_instruction; | ||
| 20060 | |||
| 20061 | if ((err = ensure_complete_type(ira->codegen, src_type))) | ||
| 20062 | return ira->codegen->invalid_instruction; | ||
| 20063 | |||
| 20064 | if (get_codegen_ptr_type(src_type) != nullptr) { | ||
| 20065 | ir_add_error(ira, value, | ||
| 20066 | buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name))); | ||
| 20067 | return ira->codegen->invalid_instruction; | ||
| 20068 | } | ||
| 20069 | |||
| 20070 | switch (src_type->id) { | ||
| 20071 | case ZigTypeIdInvalid: | 20942 | case ZigTypeIdInvalid: |
| 20943 | zig_unreachable(); | ||
| 20072 | case ZigTypeIdMetaType: | 20944 | case ZigTypeIdMetaType: |
| 20073 | case ZigTypeIdOpaque: | 20945 | case ZigTypeIdOpaque: |
| 20074 | case ZigTypeIdBoundFn: | 20946 | case ZigTypeIdBoundFn: |
| ... | @@ -20079,90 +20951,114 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct | ... | @@ -20079,90 +20951,114 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 20079 | case ZigTypeIdComptimeInt: | 20951 | case ZigTypeIdComptimeInt: |
| 20080 | case ZigTypeIdUndefined: | 20952 | case ZigTypeIdUndefined: |
| 20081 | case ZigTypeIdNull: | 20953 | case ZigTypeIdNull: |
| 20082 | ir_add_error(ira, dest_type_value, | 20954 | case ZigTypeIdPointer: |
| 20083 | buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name))); | 20955 | return false; |
| 20084 | return ira->codegen->invalid_instruction; | ||
| 20085 | default: | 20956 | default: |
| 20086 | break; | 20957 | // TODO list these types out explicitly, there are probably some other invalid ones here |
| 20958 | return true; | ||
| 20087 | } | 20959 | } |
| 20960 | } | ||
| 20088 | 20961 | ||
| 20089 | if (get_codegen_ptr_type(dest_type) != nullptr) { | 20962 | static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 20090 | ir_add_error(ira, dest_type_value, | 20963 | ZigType *dest_type) |
| 20091 | buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name))); | 20964 | { |
| 20965 | Error err; | ||
| 20966 | |||
| 20967 | ZigType *src_type = value->value.type; | ||
| 20968 | assert(get_codegen_ptr_type(src_type) == nullptr); | ||
| 20969 | assert(type_can_bit_cast(src_type)); | ||
| 20970 | assert(get_codegen_ptr_type(dest_type) == nullptr); | ||
| 20971 | assert(type_can_bit_cast(dest_type)); | ||
| 20972 | |||
| 20973 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) | ||
| 20974 | return ira->codegen->invalid_instruction; | ||
| 20975 | |||
| 20976 | if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown))) | ||
| 20092 | return ira->codegen->invalid_instruction; | 20977 | return ira->codegen->invalid_instruction; |
| 20093 | } | ||
| 20094 | 20978 | ||
| 20095 | switch (dest_type->id) { | ||
| 20096 | case ZigTypeIdInvalid: | ||
| 20097 | case ZigTypeIdMetaType: | ||
| 20098 | case ZigTypeIdOpaque: | ||
| 20099 | case ZigTypeIdBoundFn: | ||
| 20100 | case ZigTypeIdArgTuple: | ||
| 20101 | case ZigTypeIdNamespace: | ||
| 20102 | case ZigTypeIdUnreachable: | ||
| 20103 | case ZigTypeIdComptimeFloat: | ||
| 20104 | case ZigTypeIdComptimeInt: | ||
| 20105 | case ZigTypeIdUndefined: | ||
| 20106 | case ZigTypeIdNull: | ||
| 20107 | ir_add_error(ira, dest_type_value, | ||
| 20108 | buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name))); | ||
| 20109 | return ira->codegen->invalid_instruction; | ||
| 20110 | default: | ||
| 20111 | break; | ||
| 20112 | } | ||
| 20113 | 20979 | ||
| 20114 | uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); | 20980 | uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); |
| 20115 | uint64_t src_size_bytes = type_size(ira->codegen, src_type); | 20981 | uint64_t src_size_bytes = type_size(ira->codegen, src_type); |
| 20116 | if (dest_size_bytes != src_size_bytes) { | 20982 | if (dest_size_bytes != src_size_bytes) { |
| 20117 | ir_add_error(ira, &instruction->base, | 20983 | ir_add_error(ira, source_instr, |
| 20118 | buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64, | 20984 | buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64, |
| 20119 | buf_ptr(&dest_type->name), dest_size_bytes, | 20985 | buf_ptr(&dest_type->name), dest_size_bytes, |
| 20120 | buf_ptr(&src_type->name), src_size_bytes)); | 20986 | buf_ptr(&src_type->name), src_size_bytes)); |
| 20121 | return ira->codegen->invalid_instruction; | 20987 | return ira->codegen->invalid_instruction; |
| 20122 | } | 20988 | } |
| 20123 | 20989 | ||
| 20990 | uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type); | ||
| 20991 | uint64_t src_size_bits = type_size_bits(ira->codegen, src_type); | ||
| 20992 | if (dest_size_bits != src_size_bits) { | ||
| 20993 | ir_add_error(ira, source_instr, | ||
| 20994 | buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits", | ||
| 20995 | buf_ptr(&dest_type->name), dest_size_bits, | ||
| 20996 | buf_ptr(&src_type->name), src_size_bits)); | ||
| 20997 | return ira->codegen->invalid_instruction; | ||
| 20998 | } | ||
| 20999 | |||
| 20124 | if (instr_is_comptime(value)) { | 21000 | if (instr_is_comptime(value)) { |
| 20125 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 21001 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 20126 | if (!val) | 21002 | if (!val) |
| 20127 | return ira->codegen->invalid_instruction; | 21003 | return ira->codegen->invalid_instruction; |
| 20128 | 21004 | ||
| 20129 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | 21005 | IrInstruction *result = ir_const(ira, source_instr, dest_type); |
| 20130 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); | 21006 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); |
| 20131 | buf_write_value_bytes(ira->codegen, buf, val); | 21007 | buf_write_value_bytes(ira->codegen, buf, val); |
| 20132 | buf_read_value_bytes(ira->codegen, buf, &result->value); | 21008 | if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value))) |
| 21009 | return ira->codegen->invalid_instruction; | ||
| 20133 | return result; | 21010 | return result; |
| 20134 | } | 21011 | } |
| 20135 | 21012 | ||
| 20136 | IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope, | 21013 | IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope, |
| 20137 | instruction->base.source_node, nullptr, value); | 21014 | source_instr->source_node, nullptr, value); |
| 20138 | result->value.type = dest_type; | 21015 | result->value.type = dest_type; |
| 20139 | return result; | 21016 | return result; |
| 20140 | } | 21017 | } |
| 20141 | 21018 | ||
| 20142 | static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { | 21019 | static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { |
| 20143 | Error err; | ||
| 20144 | IrInstruction *dest_type_value = instruction->dest_type->child; | 21020 | IrInstruction *dest_type_value = instruction->dest_type->child; |
| 20145 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | 21021 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); |
| 20146 | if (type_is_invalid(dest_type)) | 21022 | if (type_is_invalid(dest_type)) |
| 20147 | return ira->codegen->invalid_instruction; | 21023 | return ira->codegen->invalid_instruction; |
| 20148 | 21024 | ||
| 20149 | // We explicitly check for the size, so we can use get_src_ptr_type | 21025 | IrInstruction *value = instruction->value->child; |
| 20150 | if (get_src_ptr_type(dest_type) == nullptr) { | 21026 | ZigType *src_type = value->value.type; |
| 20151 | ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); | 21027 | if (type_is_invalid(src_type)) |
| 21028 | return ira->codegen->invalid_instruction; | ||
| 21029 | |||
| 21030 | if (get_codegen_ptr_type(src_type) != nullptr) { | ||
| 21031 | ir_add_error(ira, value, | ||
| 21032 | buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name))); | ||
| 20152 | return ira->codegen->invalid_instruction; | 21033 | return ira->codegen->invalid_instruction; |
| 20153 | } | 21034 | } |
| 20154 | 21035 | ||
| 20155 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) | 21036 | if (!type_can_bit_cast(src_type)) { |
| 21037 | ir_add_error(ira, dest_type_value, | ||
| 21038 | buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name))); | ||
| 20156 | return ira->codegen->invalid_instruction; | 21039 | return ira->codegen->invalid_instruction; |
| 20157 | if (!type_has_bits(dest_type)) { | 21040 | } |
| 21041 | |||
| 21042 | if (get_codegen_ptr_type(dest_type) != nullptr) { | ||
| 20158 | ir_add_error(ira, dest_type_value, | 21043 | ir_add_error(ira, dest_type_value, |
| 20159 | buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name))); | 21044 | buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name))); |
| 20160 | return ira->codegen->invalid_instruction; | 21045 | return ira->codegen->invalid_instruction; |
| 20161 | } | 21046 | } |
| 20162 | 21047 | ||
| 20163 | IrInstruction *target = instruction->target->child; | 21048 | if (!type_can_bit_cast(dest_type)) { |
| 20164 | if (type_is_invalid(target->value.type)) | 21049 | ir_add_error(ira, dest_type_value, |
| 21050 | buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name))); | ||
| 20165 | return ira->codegen->invalid_instruction; | 21051 | return ira->codegen->invalid_instruction; |
| 21052 | } | ||
| 21053 | |||
| 21054 | return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type); | ||
| 21055 | } | ||
| 21056 | |||
| 21057 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | ||
| 21058 | ZigType *ptr_type) | ||
| 21059 | { | ||
| 21060 | assert(get_src_ptr_type(ptr_type) != nullptr); | ||
| 21061 | assert(type_has_bits(ptr_type)); | ||
| 20166 | 21062 | ||
| 20167 | IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); | 21063 | IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); |
| 20168 | if (type_is_invalid(casted_int->value.type)) | 21064 | if (type_is_invalid(casted_int->value.type)) |
| ... | @@ -20173,18 +21069,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru | ... | @@ -20173,18 +21069,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru |
| 20173 | if (!val) | 21069 | if (!val) |
| 20174 | return ira->codegen->invalid_instruction; | 21070 | return ira->codegen->invalid_instruction; |
| 20175 | 21071 | ||
| 20176 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | 21072 | IrInstruction *result = ir_const(ira, source_instr, ptr_type); |
| 20177 | result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 21073 | result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 21074 | result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar; | ||
| 20178 | result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint); | 21075 | result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint); |
| 20179 | return result; | 21076 | return result; |
| 20180 | } | 21077 | } |
| 20181 | 21078 | ||
| 20182 | IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope, | 21079 | IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope, |
| 20183 | instruction->base.source_node, nullptr, casted_int); | 21080 | source_instr->source_node, nullptr, casted_int); |
| 20184 | result->value.type = dest_type; | 21081 | result->value.type = ptr_type; |
| 20185 | return result; | 21082 | return result; |
| 20186 | } | 21083 | } |
| 20187 | 21084 | ||
| 21085 | static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { | ||
| 21086 | Error err; | ||
| 21087 | IrInstruction *dest_type_value = instruction->dest_type->child; | ||
| 21088 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | ||
| 21089 | if (type_is_invalid(dest_type)) | ||
| 21090 | return ira->codegen->invalid_instruction; | ||
| 21091 | |||
| 21092 | // We explicitly check for the size, so we can use get_src_ptr_type | ||
| 21093 | if (get_src_ptr_type(dest_type) == nullptr) { | ||
| 21094 | ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); | ||
| 21095 | return ira->codegen->invalid_instruction; | ||
| 21096 | } | ||
| 21097 | |||
| 21098 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) | ||
| 21099 | return ira->codegen->invalid_instruction; | ||
| 21100 | if (!type_has_bits(dest_type)) { | ||
| 21101 | ir_add_error(ira, dest_type_value, | ||
| 21102 | buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name))); | ||
| 21103 | return ira->codegen->invalid_instruction; | ||
| 21104 | } | ||
| 21105 | |||
| 21106 | |||
| 21107 | IrInstruction *target = instruction->target->child; | ||
| 21108 | if (type_is_invalid(target->value.type)) | ||
| 21109 | return ira->codegen->invalid_instruction; | ||
| 21110 | |||
| 21111 | return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type); | ||
| 21112 | } | ||
| 21113 | |||
| 20188 | static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, | 21114 | static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 20189 | IrInstructionDeclRef *instruction) | 21115 | IrInstructionDeclRef *instruction) |
| 20190 | { | 21116 | { |
| ... | @@ -20199,8 +21125,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, | ... | @@ -20199,8 +21125,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 20199 | case TldIdContainer: | 21125 | case TldIdContainer: |
| 20200 | case TldIdCompTime: | 21126 | case TldIdCompTime: |
| 20201 | zig_unreachable(); | 21127 | zig_unreachable(); |
| 20202 | case TldIdVar: | 21128 | case TldIdVar: { |
| 20203 | { | ||
| 20204 | TldVar *tld_var = (TldVar *)tld; | 21129 | TldVar *tld_var = (TldVar *)tld; |
| 20205 | ZigVar *var = tld_var->var; | 21130 | ZigVar *var = tld_var->var; |
| 20206 | 21131 | ||
| ... | @@ -20218,8 +21143,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, | ... | @@ -20218,8 +21143,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 20218 | return ir_get_deref(ira, &instruction->base, var_ptr); | 21143 | return ir_get_deref(ira, &instruction->base, var_ptr); |
| 20219 | } | 21144 | } |
| 20220 | } | 21145 | } |
| 20221 | case TldIdFn: | 21146 | case TldIdFn: { |
| 20222 | { | ||
| 20223 | TldFn *tld_fn = (TldFn *)tld; | 21147 | TldFn *tld_fn = (TldFn *)tld; |
| 20224 | ZigFn *fn_entry = tld_fn->fn_entry; | 21148 | ZigFn *fn_entry = tld_fn->fn_entry; |
| 20225 | assert(fn_entry->type_entry); | 21149 | assert(fn_entry->type_entry); |
| ... | @@ -20265,8 +21189,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru | ... | @@ -20265,8 +21189,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru |
| 20265 | if (!val) | 21189 | if (!val) |
| 20266 | return ira->codegen->invalid_instruction; | 21190 | return ira->codegen->invalid_instruction; |
| 20267 | if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { | 21191 | if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| 20268 | IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope, | 21192 | IrInstruction *result = ir_const(ira, &instruction->base, usize); |
| 20269 | instruction->base.source_node, usize); | ||
| 20270 | bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr); | 21193 | bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr); |
| 20271 | result->value.type = usize; | 21194 | result->value.type = usize; |
| 20272 | return result; | 21195 | return result; |
| ... | @@ -20291,6 +21214,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct | ... | @@ -20291,6 +21214,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct |
| 20291 | } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) { | 21214 | } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) { |
| 20292 | ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque")); | 21215 | ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque")); |
| 20293 | return ira->codegen->invalid_instruction; | 21216 | return ira->codegen->invalid_instruction; |
| 21217 | } else if (instruction->ptr_len == PtrLenC) { | ||
| 21218 | if (!type_allowed_in_extern(ira->codegen, child_type)) { | ||
| 21219 | ir_add_error(ira, &instruction->base, | ||
| 21220 | buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name))); | ||
| 21221 | return ira->codegen->invalid_instruction; | ||
| 21222 | } else if (child_type->id == ZigTypeIdOpaque) { | ||
| 21223 | ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types")); | ||
| 21224 | return ira->codegen->invalid_instruction; | ||
| 21225 | } | ||
| 20294 | } | 21226 | } |
| 20295 | 21227 | ||
| 20296 | uint32_t align_bytes; | 21228 | uint32_t align_bytes; |
| ... | @@ -20299,6 +21231,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct | ... | @@ -20299,6 +21231,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct |
| 20299 | return ira->codegen->invalid_instruction; | 21231 | return ira->codegen->invalid_instruction; |
| 20300 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) | 21232 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) |
| 20301 | return ira->codegen->invalid_instruction; | 21233 | return ira->codegen->invalid_instruction; |
| 21234 | if (!type_has_bits(child_type)) { | ||
| 21235 | align_bytes = 0; | ||
| 21236 | } | ||
| 20302 | } else { | 21237 | } else { |
| 20303 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) | 21238 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) |
| 20304 | return ira->codegen->invalid_instruction; | 21239 | return ira->codegen->invalid_instruction; |
| ... | @@ -20898,6 +21833,126 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS | ... | @@ -20898,6 +21833,126 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS |
| 20898 | return result; | 21833 | return result; |
| 20899 | } | 21834 | } |
| 20900 | 21835 | ||
| 21836 | static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { | ||
| 21837 | ZigType *int_type = ir_resolve_type(ira, instruction->type->child); | ||
| 21838 | if (type_is_invalid(int_type)) | ||
| 21839 | return ira->codegen->invalid_instruction; | ||
| 21840 | |||
| 21841 | IrInstruction *op = instruction->op->child; | ||
| 21842 | if (type_is_invalid(op->value.type)) | ||
| 21843 | return ira->codegen->invalid_instruction; | ||
| 21844 | |||
| 21845 | if (int_type->id != ZigTypeIdInt) { | ||
| 21846 | ir_add_error(ira, instruction->type, | ||
| 21847 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); | ||
| 21848 | return ira->codegen->invalid_instruction; | ||
| 21849 | } | ||
| 21850 | |||
| 21851 | if (int_type->data.integral.bit_count % 8 != 0) { | ||
| 21852 | ir_add_error(ira, instruction->type, | ||
| 21853 | buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", | ||
| 21854 | buf_ptr(&int_type->name), int_type->data.integral.bit_count)); | ||
| 21855 | return ira->codegen->invalid_instruction; | ||
| 21856 | } | ||
| 21857 | |||
| 21858 | IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); | ||
| 21859 | if (type_is_invalid(casted_op->value.type)) | ||
| 21860 | return ira->codegen->invalid_instruction; | ||
| 21861 | |||
| 21862 | if (int_type->data.integral.bit_count == 0) { | ||
| 21863 | IrInstruction *result = ir_const(ira, &instruction->base, int_type); | ||
| 21864 | bigint_init_unsigned(&result->value.data.x_bigint, 0); | ||
| 21865 | return result; | ||
| 21866 | } | ||
| 21867 | |||
| 21868 | if (int_type->data.integral.bit_count == 8) { | ||
| 21869 | return casted_op; | ||
| 21870 | } | ||
| 21871 | |||
| 21872 | if (instr_is_comptime(casted_op)) { | ||
| 21873 | ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); | ||
| 21874 | if (!val) | ||
| 21875 | return ira->codegen->invalid_instruction; | ||
| 21876 | |||
| 21877 | IrInstruction *result = ir_const(ira, &instruction->base, int_type); | ||
| 21878 | size_t buf_size = int_type->data.integral.bit_count / 8; | ||
| 21879 | uint8_t *buf = allocate_nonzero<uint8_t>(buf_size); | ||
| 21880 | bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true); | ||
| 21881 | bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false, | ||
| 21882 | int_type->data.integral.is_signed); | ||
| 21883 | return result; | ||
| 21884 | } | ||
| 21885 | |||
| 21886 | IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, | ||
| 21887 | instruction->base.source_node, nullptr, casted_op); | ||
| 21888 | result->value.type = int_type; | ||
| 21889 | return result; | ||
| 21890 | } | ||
| 21891 | |||
| 21892 | static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstructionBitReverse *instruction) { | ||
| 21893 | ZigType *int_type = ir_resolve_type(ira, instruction->type->child); | ||
| 21894 | if (type_is_invalid(int_type)) | ||
| 21895 | return ira->codegen->invalid_instruction; | ||
| 21896 | |||
| 21897 | IrInstruction *op = instruction->op->child; | ||
| 21898 | if (type_is_invalid(op->value.type)) | ||
| 21899 | return ira->codegen->invalid_instruction; | ||
| 21900 | |||
| 21901 | if (int_type->id != ZigTypeIdInt) { | ||
| 21902 | ir_add_error(ira, instruction->type, | ||
| 21903 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); | ||
| 21904 | return ira->codegen->invalid_instruction; | ||
| 21905 | } | ||
| 21906 | |||
| 21907 | IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); | ||
| 21908 | if (type_is_invalid(casted_op->value.type)) | ||
| 21909 | return ira->codegen->invalid_instruction; | ||
| 21910 | |||
| 21911 | if (int_type->data.integral.bit_count == 0) { | ||
| 21912 | IrInstruction *result = ir_const(ira, &instruction->base, int_type); | ||
| 21913 | bigint_init_unsigned(&result->value.data.x_bigint, 0); | ||
| 21914 | return result; | ||
| 21915 | } | ||
| 21916 | |||
| 21917 | if (instr_is_comptime(casted_op)) { | ||
| 21918 | ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); | ||
| 21919 | if (!val) | ||
| 21920 | return ira->codegen->invalid_instruction; | ||
| 21921 | |||
| 21922 | IrInstruction *result = ir_const(ira, &instruction->base, int_type); | ||
| 21923 | size_t num_bits = int_type->data.integral.bit_count; | ||
| 21924 | size_t buf_size = (num_bits + 7) / 8; | ||
| 21925 | uint8_t *comptime_buf = allocate_nonzero<uint8_t>(buf_size); | ||
| 21926 | uint8_t *result_buf = allocate_nonzero<uint8_t>(buf_size); | ||
| 21927 | memset(comptime_buf,0,buf_size); | ||
| 21928 | memset(result_buf,0,buf_size); | ||
| 21929 | |||
| 21930 | bigint_write_twos_complement(&val->data.x_bigint,comptime_buf,num_bits,ira->codegen->is_big_endian); | ||
| 21931 | |||
| 21932 | size_t bit_i = 0; | ||
| 21933 | size_t bit_rev_i = num_bits - 1; | ||
| 21934 | for (; bit_i < num_bits; bit_i++, bit_rev_i--) { | ||
| 21935 | if (comptime_buf[bit_i / 8] & (1 << (bit_i % 8))) { | ||
| 21936 | result_buf[bit_rev_i / 8] |= (1 << (bit_rev_i % 8)); | ||
| 21937 | } | ||
| 21938 | } | ||
| 21939 | |||
| 21940 | bigint_read_twos_complement(&result->value.data.x_bigint, | ||
| 21941 | result_buf, | ||
| 21942 | int_type->data.integral.bit_count, | ||
| 21943 | ira->codegen->is_big_endian, | ||
| 21944 | int_type->data.integral.is_signed); | ||
| 21945 | |||
| 21946 | return result; | ||
| 21947 | } | ||
| 21948 | |||
| 21949 | IrInstruction *result = ir_build_bit_reverse(&ira->new_irb, instruction->base.scope, | ||
| 21950 | instruction->base.source_node, nullptr, casted_op); | ||
| 21951 | result->value.type = int_type; | ||
| 21952 | return result; | ||
| 21953 | } | ||
| 21954 | |||
| 21955 | |||
| 20901 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { | 21956 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { |
| 20902 | Error err; | 21957 | Error err; |
| 20903 | IrInstruction *target = instruction->target->child; | 21958 | IrInstruction *target = instruction->target->child; |
| ... | @@ -20981,6 +22036,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -20981,6 +22036,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 20981 | case IrInstructionIdErrWrapCode: | 22036 | case IrInstructionIdErrWrapCode: |
| 20982 | case IrInstructionIdErrWrapPayload: | 22037 | case IrInstructionIdErrWrapPayload: |
| 20983 | case IrInstructionIdCast: | 22038 | case IrInstructionIdCast: |
| 22039 | case IrInstructionIdDeclVarGen: | ||
| 22040 | case IrInstructionIdPtrCastGen: | ||
| 22041 | case IrInstructionIdCmpxchgGen: | ||
| 22042 | case IrInstructionIdArrayToVector: | ||
| 22043 | case IrInstructionIdVectorToArray: | ||
| 22044 | case IrInstructionIdAssertZero: | ||
| 20984 | zig_unreachable(); | 22045 | zig_unreachable(); |
| 20985 | 22046 | ||
| 20986 | case IrInstructionIdReturn: | 22047 | case IrInstructionIdReturn: |
| ... | @@ -20991,8 +22052,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -20991,8 +22052,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 20991 | return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); | 22052 | return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); |
| 20992 | case IrInstructionIdBinOp: | 22053 | case IrInstructionIdBinOp: |
| 20993 | return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); | 22054 | return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); |
| 20994 | case IrInstructionIdDeclVar: | 22055 | case IrInstructionIdDeclVarSrc: |
| 20995 | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction); | 22056 | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction); |
| 20996 | case IrInstructionIdLoadPtr: | 22057 | case IrInstructionIdLoadPtr: |
| 20997 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); | 22058 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); |
| 20998 | case IrInstructionIdStorePtr: | 22059 | case IrInstructionIdStorePtr: |
| ... | @@ -21037,8 +22098,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21037,8 +22098,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21037 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); | 22098 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); |
| 21038 | case IrInstructionIdTestNonNull: | 22099 | case IrInstructionIdTestNonNull: |
| 21039 | return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction); | 22100 | return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction); |
| 21040 | case IrInstructionIdUnwrapOptional: | 22101 | case IrInstructionIdOptionalUnwrapPtr: |
| 21041 | return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction); | 22102 | return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction); |
| 21042 | case IrInstructionIdClz: | 22103 | case IrInstructionIdClz: |
| 21043 | return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction); | 22104 | return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction); |
| 21044 | case IrInstructionIdCtz: | 22105 | case IrInstructionIdCtz: |
| ... | @@ -21079,8 +22140,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21079,8 +22140,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21079 | return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); | 22140 | return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); |
| 21080 | case IrInstructionIdEmbedFile: | 22141 | case IrInstructionIdEmbedFile: |
| 21081 | return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction); | 22142 | return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction); |
| 21082 | case IrInstructionIdCmpxchg: | 22143 | case IrInstructionIdCmpxchgSrc: |
| 21083 | return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction); | 22144 | return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction); |
| 21084 | case IrInstructionIdFence: | 22145 | case IrInstructionIdFence: |
| 21085 | return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction); | 22146 | return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction); |
| 21086 | case IrInstructionIdTruncate: | 22147 | case IrInstructionIdTruncate: |
| ... | @@ -21103,6 +22164,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21103,6 +22164,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21103 | return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction); | 22164 | return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction); |
| 21104 | case IrInstructionIdIntType: | 22165 | case IrInstructionIdIntType: |
| 21105 | return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction); | 22166 | return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction); |
| 22167 | case IrInstructionIdVectorType: | ||
| 22168 | return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction); | ||
| 21106 | case IrInstructionIdBoolNot: | 22169 | case IrInstructionIdBoolNot: |
| 21107 | return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction); | 22170 | return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction); |
| 21108 | case IrInstructionIdMemset: | 22171 | case IrInstructionIdMemset: |
| ... | @@ -21147,8 +22210,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21147,8 +22210,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21147 | return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); | 22210 | return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); |
| 21148 | case IrInstructionIdPanic: | 22211 | case IrInstructionIdPanic: |
| 21149 | return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); | 22212 | return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); |
| 21150 | case IrInstructionIdPtrCast: | 22213 | case IrInstructionIdPtrCastSrc: |
| 21151 | return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); | 22214 | return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction); |
| 21152 | case IrInstructionIdBitCast: | 22215 | case IrInstructionIdBitCast: |
| 21153 | return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction); | 22216 | return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction); |
| 21154 | case IrInstructionIdIntToPtr: | 22217 | case IrInstructionIdIntToPtr: |
| ... | @@ -21233,6 +22296,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21233,6 +22296,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21233 | return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); | 22296 | return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); |
| 21234 | case IrInstructionIdSqrt: | 22297 | case IrInstructionIdSqrt: |
| 21235 | return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); | 22298 | return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); |
| 22299 | case IrInstructionIdBswap: | ||
| 22300 | return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); | ||
| 22301 | case IrInstructionIdBitReverse: | ||
| 22302 | return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction); | ||
| 21236 | case IrInstructionIdIntToErr: | 22303 | case IrInstructionIdIntToErr: |
| 21237 | return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); | 22304 | return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); |
| 21238 | case IrInstructionIdErrToInt: | 22305 | case IrInstructionIdErrToInt: |
| ... | @@ -21328,7 +22395,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21328,7 +22395,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21328 | case IrInstructionIdBr: | 22395 | case IrInstructionIdBr: |
| 21329 | case IrInstructionIdCondBr: | 22396 | case IrInstructionIdCondBr: |
| 21330 | case IrInstructionIdSwitchBr: | 22397 | case IrInstructionIdSwitchBr: |
| 21331 | case IrInstructionIdDeclVar: | 22398 | case IrInstructionIdDeclVarSrc: |
| 22399 | case IrInstructionIdDeclVarGen: | ||
| 21332 | case IrInstructionIdStorePtr: | 22400 | case IrInstructionIdStorePtr: |
| 21333 | case IrInstructionIdCall: | 22401 | case IrInstructionIdCall: |
| 21334 | case IrInstructionIdReturn: | 22402 | case IrInstructionIdReturn: |
| ... | @@ -21343,7 +22411,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21343,7 +22411,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21343 | case IrInstructionIdCInclude: | 22411 | case IrInstructionIdCInclude: |
| 21344 | case IrInstructionIdCDefine: | 22412 | case IrInstructionIdCDefine: |
| 21345 | case IrInstructionIdCUndef: | 22413 | case IrInstructionIdCUndef: |
| 21346 | case IrInstructionIdCmpxchg: | ||
| 21347 | case IrInstructionIdFence: | 22414 | case IrInstructionIdFence: |
| 21348 | case IrInstructionIdMemset: | 22415 | case IrInstructionIdMemset: |
| 21349 | case IrInstructionIdMemcpy: | 22416 | case IrInstructionIdMemcpy: |
| ... | @@ -21371,6 +22438,9 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21371,6 +22438,9 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21371 | case IrInstructionIdMergeErrRetTraces: | 22438 | case IrInstructionIdMergeErrRetTraces: |
| 21372 | case IrInstructionIdMarkErrRetTracePtr: | 22439 | case IrInstructionIdMarkErrRetTracePtr: |
| 21373 | case IrInstructionIdAtomicRmw: | 22440 | case IrInstructionIdAtomicRmw: |
| 22441 | case IrInstructionIdCmpxchgGen: | ||
| 22442 | case IrInstructionIdCmpxchgSrc: | ||
| 22443 | case IrInstructionIdAssertZero: | ||
| 21374 | return true; | 22444 | return true; |
| 21375 | 22445 | ||
| 21376 | case IrInstructionIdPhi: | 22446 | case IrInstructionIdPhi: |
| ... | @@ -21396,7 +22466,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21396,7 +22466,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21396 | case IrInstructionIdSliceType: | 22466 | case IrInstructionIdSliceType: |
| 21397 | case IrInstructionIdSizeOf: | 22467 | case IrInstructionIdSizeOf: |
| 21398 | case IrInstructionIdTestNonNull: | 22468 | case IrInstructionIdTestNonNull: |
| 21399 | case IrInstructionIdUnwrapOptional: | 22469 | case IrInstructionIdOptionalUnwrapPtr: |
| 21400 | case IrInstructionIdClz: | 22470 | case IrInstructionIdClz: |
| 21401 | case IrInstructionIdCtz: | 22471 | case IrInstructionIdCtz: |
| 21402 | case IrInstructionIdPopCount: | 22472 | case IrInstructionIdPopCount: |
| ... | @@ -21407,6 +22477,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21407,6 +22477,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21407 | case IrInstructionIdEmbedFile: | 22477 | case IrInstructionIdEmbedFile: |
| 21408 | case IrInstructionIdTruncate: | 22478 | case IrInstructionIdTruncate: |
| 21409 | case IrInstructionIdIntType: | 22479 | case IrInstructionIdIntType: |
| 22480 | case IrInstructionIdVectorType: | ||
| 21410 | case IrInstructionIdBoolNot: | 22481 | case IrInstructionIdBoolNot: |
| 21411 | case IrInstructionIdSlice: | 22482 | case IrInstructionIdSlice: |
| 21412 | case IrInstructionIdMemberCount: | 22483 | case IrInstructionIdMemberCount: |
| ... | @@ -21423,7 +22494,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21423,7 +22494,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21423 | case IrInstructionIdErrWrapPayload: | 22494 | case IrInstructionIdErrWrapPayload: |
| 21424 | case IrInstructionIdFnProto: | 22495 | case IrInstructionIdFnProto: |
| 21425 | case IrInstructionIdTestComptime: | 22496 | case IrInstructionIdTestComptime: |
| 21426 | case IrInstructionIdPtrCast: | 22497 | case IrInstructionIdPtrCastSrc: |
| 22498 | case IrInstructionIdPtrCastGen: | ||
| 21427 | case IrInstructionIdBitCast: | 22499 | case IrInstructionIdBitCast: |
| 21428 | case IrInstructionIdWidenOrShorten: | 22500 | case IrInstructionIdWidenOrShorten: |
| 21429 | case IrInstructionIdPtrToInt: | 22501 | case IrInstructionIdPtrToInt: |
| ... | @@ -21454,6 +22526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21454,6 +22526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21454 | case IrInstructionIdCoroPromise: | 22526 | case IrInstructionIdCoroPromise: |
| 21455 | case IrInstructionIdPromiseResultType: | 22527 | case IrInstructionIdPromiseResultType: |
| 21456 | case IrInstructionIdSqrt: | 22528 | case IrInstructionIdSqrt: |
| 22529 | case IrInstructionIdBswap: | ||
| 22530 | case IrInstructionIdBitReverse: | ||
| 21457 | case IrInstructionIdAtomicLoad: | 22531 | case IrInstructionIdAtomicLoad: |
| 21458 | case IrInstructionIdIntCast: | 22532 | case IrInstructionIdIntCast: |
| 21459 | case IrInstructionIdFloatCast: | 22533 | case IrInstructionIdFloatCast: |
| ... | @@ -21464,6 +22538,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21464,6 +22538,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21464 | case IrInstructionIdFromBytes: | 22538 | case IrInstructionIdFromBytes: |
| 21465 | case IrInstructionIdToBytes: | 22539 | case IrInstructionIdToBytes: |
| 21466 | case IrInstructionIdEnumToInt: | 22540 | case IrInstructionIdEnumToInt: |
| 22541 | case IrInstructionIdVectorToArray: | ||
| 22542 | case IrInstructionIdArrayToVector: | ||
| 21467 | return false; | 22543 | return false; |
| 21468 | 22544 | ||
| 21469 | case IrInstructionIdAsm: | 22545 | case IrInstructionIdAsm: |
src/ir.hpp+6-3| ... | @@ -13,15 +13,18 @@ | ... | @@ -13,15 +13,18 @@ |
| 13 | bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); | 13 | bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); |
| 14 | bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); | 14 | bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); |
| 15 | 15 | ||
| 16 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | 16 | ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 17 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, | 17 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 18 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, | 18 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 19 | IrExecutable *parent_exec); | 19 | IrExecutable *parent_exec, AstNode *expected_type_source_node); |
| 20 | 20 | ||
| 21 | ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, | 21 | ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, |
| 22 | ZigType *expected_type, AstNode *expected_type_source_node); | 22 | ZigType *expected_type, AstNode *expected_type_source_node); |
| 23 | 23 | ||
| 24 | bool ir_has_side_effects(IrInstruction *instruction); | 24 | bool ir_has_side_effects(IrInstruction *instruction); |
| 25 | ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val); | 25 | |
| 26 | struct IrAnalyze; | ||
| 27 | ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val, | ||
| 28 | AstNode *source_node); | ||
| 26 | 29 | ||
| 27 | #endif | 30 | #endif |
src/ir_print.cpp+129-22| ... | @@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction | ... | @@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction |
| 172 | } | 172 | } |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) { | 175 | static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { |
| 176 | const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; | 176 | const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; |
| 177 | const char *name = buf_ptr(&decl_var_instruction->var->name); | 177 | const char *name = buf_ptr(&decl_var_instruction->var->name); |
| 178 | if (decl_var_instruction->var_type) { | 178 | if (decl_var_instruction->var_type) { |
| ... | @@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { | ... | @@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { | 334 | static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { |
| 335 | fprintf(irp->f, "*"); | ||
| 336 | ir_print_other_instruction(irp, instruction->ptr); | 335 | ir_print_other_instruction(irp, instruction->ptr); |
| 336 | fprintf(irp->f, ".*"); | ||
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { | 339 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { |
| ... | @@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { | ... | @@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { |
| 479 | fprintf(irp->f, ")"); | 479 | fprintf(irp->f, ")"); |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { | 482 | static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { |
| 483 | fprintf(irp->f, "*"); | ||
| 484 | ir_print_other_instruction(irp, instruction->value); | 483 | ir_print_other_instruction(irp, instruction->value); |
| 485 | fprintf(irp->f, " != null"); | 484 | fprintf(irp->f, " != null"); |
| 486 | } | 485 | } |
| 487 | 486 | ||
| 488 | static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) { | 487 | static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) { |
| 489 | fprintf(irp->f, "&??*"); | 488 | fprintf(irp->f, "&"); |
| 490 | ir_print_other_instruction(irp, instruction->value); | 489 | ir_print_other_instruction(irp, instruction->base_ptr); |
| 490 | fprintf(irp->f, ".*.?"); | ||
| 491 | if (!instruction->safety_check_on) { | 491 | if (!instruction->safety_check_on) { |
| 492 | fprintf(irp->f, " // no safety"); | 492 | fprintf(irp->f, " // no safety"); |
| 493 | } | 493 | } |
| ... | @@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio | ... | @@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio |
| 613 | fprintf(irp->f, ")"); | 613 | fprintf(irp->f, ")"); |
| 614 | } | 614 | } |
| 615 | 615 | ||
| 616 | static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { | 616 | static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) { |
| 617 | fprintf(irp->f, "@cmpxchg("); | 617 | fprintf(irp->f, "@cmpxchg("); |
| 618 | ir_print_other_instruction(irp, instruction->ptr); | 618 | ir_print_other_instruction(irp, instruction->ptr); |
| 619 | fprintf(irp->f, ", "); | 619 | fprintf(irp->f, ", "); |
| ... | @@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { | ... | @@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { |
| 627 | fprintf(irp->f, ")"); | 627 | fprintf(irp->f, ")"); |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) { | ||
| 631 | fprintf(irp->f, "@cmpxchg("); | ||
| 632 | ir_print_other_instruction(irp, instruction->ptr); | ||
| 633 | fprintf(irp->f, ", "); | ||
| 634 | ir_print_other_instruction(irp, instruction->cmp_value); | ||
| 635 | fprintf(irp->f, ", "); | ||
| 636 | ir_print_other_instruction(irp, instruction->new_value); | ||
| 637 | fprintf(irp->f, ", TODO print atomic orders)"); | ||
| 638 | } | ||
| 639 | |||
| 630 | static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { | 640 | static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { |
| 631 | fprintf(irp->f, "@fence("); | 641 | fprintf(irp->f, "@fence("); |
| 632 | ir_print_other_instruction(irp, instruction->order_value); | 642 | ir_print_other_instruction(irp, instruction->order_value); |
| ... | @@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) { | ... | @@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) { |
| 709 | fprintf(irp->f, ")"); | 719 | fprintf(irp->f, ")"); |
| 710 | } | 720 | } |
| 711 | 721 | ||
| 722 | static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) { | ||
| 723 | fprintf(irp->f, "@Vector("); | ||
| 724 | ir_print_other_instruction(irp, instruction->len); | ||
| 725 | fprintf(irp->f, ", "); | ||
| 726 | ir_print_other_instruction(irp, instruction->elem_type); | ||
| 727 | fprintf(irp->f, ")"); | ||
| 728 | } | ||
| 729 | |||
| 712 | static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) { | 730 | static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) { |
| 713 | fprintf(irp->f, "! "); | 731 | fprintf(irp->f, "! "); |
| 714 | ir_print_other_instruction(irp, instruction->value); | 732 | ir_print_other_instruction(irp, instruction->value); |
| ... | @@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) { | ... | @@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) { |
| 820 | } | 838 | } |
| 821 | 839 | ||
| 822 | static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) { | 840 | static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) { |
| 823 | fprintf(irp->f, "@unwrapErrorCode("); | 841 | fprintf(irp->f, "UnwrapErrorCode("); |
| 824 | ir_print_other_instruction(irp, instruction->value); | 842 | ir_print_other_instruction(irp, instruction->err_union); |
| 825 | fprintf(irp->f, ")"); | 843 | fprintf(irp->f, ")"); |
| 826 | } | 844 | } |
| 827 | 845 | ||
| 828 | static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) { | 846 | static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) { |
| 829 | fprintf(irp->f, "@unwrapErrorPayload("); | 847 | fprintf(irp->f, "ErrorUnionFieldPayload("); |
| 830 | ir_print_other_instruction(irp, instruction->value); | 848 | ir_print_other_instruction(irp, instruction->value); |
| 831 | fprintf(irp->f, ")"); | 849 | fprintf(irp->f, ")"); |
| 832 | if (!instruction->safety_check_on) { | 850 | if (!instruction->safety_check_on) { |
| ... | @@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst | ... | @@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst |
| 879 | fprintf(irp->f, ")"); | 897 | fprintf(irp->f, ")"); |
| 880 | } | 898 | } |
| 881 | 899 | ||
| 882 | static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { | 900 | static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) { |
| 883 | fprintf(irp->f, "@ptrCast("); | 901 | fprintf(irp->f, "@ptrCast("); |
| 884 | if (instruction->dest_type) { | 902 | if (instruction->dest_type) { |
| 885 | ir_print_other_instruction(irp, instruction->dest_type); | 903 | ir_print_other_instruction(irp, instruction->dest_type); |
| ... | @@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { | ... | @@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { |
| 889 | fprintf(irp->f, ")"); | 907 | fprintf(irp->f, ")"); |
| 890 | } | 908 | } |
| 891 | 909 | ||
| 910 | static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) { | ||
| 911 | fprintf(irp->f, "@ptrCast("); | ||
| 912 | ir_print_other_instruction(irp, instruction->ptr); | ||
| 913 | fprintf(irp->f, ")"); | ||
| 914 | } | ||
| 915 | |||
| 892 | static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { | 916 | static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { |
| 893 | fprintf(irp->f, "@bitCast("); | 917 | fprintf(irp->f, "@bitCast("); |
| 894 | if (instruction->dest_type) { | 918 | if (instruction->dest_type) { |
| ... | @@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { | ... | @@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { |
| 900 | } | 924 | } |
| 901 | 925 | ||
| 902 | static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { | 926 | static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { |
| 903 | fprintf(irp->f, "@widenOrShorten("); | 927 | fprintf(irp->f, "WidenOrShorten("); |
| 904 | ir_print_other_instruction(irp, instruction->target); | 928 | ir_print_other_instruction(irp, instruction->target); |
| 905 | fprintf(irp->f, ")"); | 929 | fprintf(irp->f, ")"); |
| 906 | } | 930 | } |
| ... | @@ -948,6 +972,24 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime | ... | @@ -948,6 +972,24 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime |
| 948 | fprintf(irp->f, ")"); | 972 | fprintf(irp->f, ")"); |
| 949 | } | 973 | } |
| 950 | 974 | ||
| 975 | static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) { | ||
| 976 | fprintf(irp->f, "ArrayToVector("); | ||
| 977 | ir_print_other_instruction(irp, instruction->array); | ||
| 978 | fprintf(irp->f, ")"); | ||
| 979 | } | ||
| 980 | |||
| 981 | static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) { | ||
| 982 | fprintf(irp->f, "VectorToArray("); | ||
| 983 | ir_print_other_instruction(irp, instruction->vector); | ||
| 984 | fprintf(irp->f, ")"); | ||
| 985 | } | ||
| 986 | |||
| 987 | static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) { | ||
| 988 | fprintf(irp->f, "AssertZero("); | ||
| 989 | ir_print_other_instruction(irp, instruction->target); | ||
| 990 | fprintf(irp->f, ")"); | ||
| 991 | } | ||
| 992 | |||
| 951 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { | 993 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { |
| 952 | fprintf(irp->f, "inttoerr "); | 994 | fprintf(irp->f, "inttoerr "); |
| 953 | ir_print_other_instruction(irp, instruction->target); | 995 | ir_print_other_instruction(irp, instruction->target); |
| ... | @@ -1323,6 +1365,44 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { | ... | @@ -1323,6 +1365,44 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { |
| 1323 | fprintf(irp->f, ")"); | 1365 | fprintf(irp->f, ")"); |
| 1324 | } | 1366 | } |
| 1325 | 1367 | ||
| 1368 | static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { | ||
| 1369 | ZigVar *var = decl_var_instruction->var; | ||
| 1370 | const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; | ||
| 1371 | const char *name = buf_ptr(&decl_var_instruction->var->name); | ||
| 1372 | fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), | ||
| 1373 | var->align_bytes); | ||
| 1374 | |||
| 1375 | ir_print_other_instruction(irp, decl_var_instruction->init_value); | ||
| 1376 | if (decl_var_instruction->var->is_comptime != nullptr) { | ||
| 1377 | fprintf(irp->f, " // comptime = "); | ||
| 1378 | ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); | ||
| 1379 | } | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { | ||
| 1383 | fprintf(irp->f, "@bswap("); | ||
| 1384 | if (instruction->type != nullptr) { | ||
| 1385 | ir_print_other_instruction(irp, instruction->type); | ||
| 1386 | } else { | ||
| 1387 | fprintf(irp->f, "null"); | ||
| 1388 | } | ||
| 1389 | fprintf(irp->f, ","); | ||
| 1390 | ir_print_other_instruction(irp, instruction->op); | ||
| 1391 | fprintf(irp->f, ")"); | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) { | ||
| 1395 | fprintf(irp->f, "@bitreverse("); | ||
| 1396 | if (instruction->type != nullptr) { | ||
| 1397 | ir_print_other_instruction(irp, instruction->type); | ||
| 1398 | } else { | ||
| 1399 | fprintf(irp->f, "null"); | ||
| 1400 | } | ||
| 1401 | fprintf(irp->f, ","); | ||
| 1402 | ir_print_other_instruction(irp, instruction->op); | ||
| 1403 | fprintf(irp->f, ")"); | ||
| 1404 | } | ||
| 1405 | |||
| 1326 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1406 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1327 | ir_print_prefix(irp, instruction); | 1407 | ir_print_prefix(irp, instruction); |
| 1328 | switch (instruction->id) { | 1408 | switch (instruction->id) { |
| ... | @@ -1337,8 +1417,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1337,8 +1417,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1337 | case IrInstructionIdBinOp: | 1417 | case IrInstructionIdBinOp: |
| 1338 | ir_print_bin_op(irp, (IrInstructionBinOp *)instruction); | 1418 | ir_print_bin_op(irp, (IrInstructionBinOp *)instruction); |
| 1339 | break; | 1419 | break; |
| 1340 | case IrInstructionIdDeclVar: | 1420 | case IrInstructionIdDeclVarSrc: |
| 1341 | ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction); | 1421 | ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction); |
| 1342 | break; | 1422 | break; |
| 1343 | case IrInstructionIdCast: | 1423 | case IrInstructionIdCast: |
| 1344 | ir_print_cast(irp, (IrInstructionCast *)instruction); | 1424 | ir_print_cast(irp, (IrInstructionCast *)instruction); |
| ... | @@ -1428,10 +1508,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1428,10 +1508,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1428 | ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); | 1508 | ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); |
| 1429 | break; | 1509 | break; |
| 1430 | case IrInstructionIdTestNonNull: | 1510 | case IrInstructionIdTestNonNull: |
| 1431 | ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction); | 1511 | ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction); |
| 1432 | break; | 1512 | break; |
| 1433 | case IrInstructionIdUnwrapOptional: | 1513 | case IrInstructionIdOptionalUnwrapPtr: |
| 1434 | ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction); | 1514 | ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction); |
| 1435 | break; | 1515 | break; |
| 1436 | case IrInstructionIdCtz: | 1516 | case IrInstructionIdCtz: |
| 1437 | ir_print_ctz(irp, (IrInstructionCtz *)instruction); | 1517 | ir_print_ctz(irp, (IrInstructionCtz *)instruction); |
| ... | @@ -1484,8 +1564,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1484,8 +1564,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1484 | case IrInstructionIdEmbedFile: | 1564 | case IrInstructionIdEmbedFile: |
| 1485 | ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction); | 1565 | ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction); |
| 1486 | break; | 1566 | break; |
| 1487 | case IrInstructionIdCmpxchg: | 1567 | case IrInstructionIdCmpxchgSrc: |
| 1488 | ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction); | 1568 | ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction); |
| 1569 | break; | ||
| 1570 | case IrInstructionIdCmpxchgGen: | ||
| 1571 | ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction); | ||
| 1489 | break; | 1572 | break; |
| 1490 | case IrInstructionIdFence: | 1573 | case IrInstructionIdFence: |
| 1491 | ir_print_fence(irp, (IrInstructionFence *)instruction); | 1574 | ir_print_fence(irp, (IrInstructionFence *)instruction); |
| ... | @@ -1520,6 +1603,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1520,6 +1603,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1520 | case IrInstructionIdIntType: | 1603 | case IrInstructionIdIntType: |
| 1521 | ir_print_int_type(irp, (IrInstructionIntType *)instruction); | 1604 | ir_print_int_type(irp, (IrInstructionIntType *)instruction); |
| 1522 | break; | 1605 | break; |
| 1606 | case IrInstructionIdVectorType: | ||
| 1607 | ir_print_vector_type(irp, (IrInstructionVectorType *)instruction); | ||
| 1608 | break; | ||
| 1523 | case IrInstructionIdBoolNot: | 1609 | case IrInstructionIdBoolNot: |
| 1524 | ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction); | 1610 | ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction); |
| 1525 | break; | 1611 | break; |
| ... | @@ -1583,8 +1669,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1583,8 +1669,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1583 | case IrInstructionIdTestComptime: | 1669 | case IrInstructionIdTestComptime: |
| 1584 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); | 1670 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); |
| 1585 | break; | 1671 | break; |
| 1586 | case IrInstructionIdPtrCast: | 1672 | case IrInstructionIdPtrCastSrc: |
| 1587 | ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); | 1673 | ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction); |
| 1674 | break; | ||
| 1675 | case IrInstructionIdPtrCastGen: | ||
| 1676 | ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction); | ||
| 1588 | break; | 1677 | break; |
| 1589 | case IrInstructionIdBitCast: | 1678 | case IrInstructionIdBitCast: |
| 1590 | ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); | 1679 | ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); |
| ... | @@ -1736,6 +1825,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1736,6 +1825,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1736 | case IrInstructionIdSqrt: | 1825 | case IrInstructionIdSqrt: |
| 1737 | ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); | 1826 | ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); |
| 1738 | break; | 1827 | break; |
| 1828 | case IrInstructionIdBswap: | ||
| 1829 | ir_print_bswap(irp, (IrInstructionBswap *)instruction); | ||
| 1830 | break; | ||
| 1831 | case IrInstructionIdBitReverse: | ||
| 1832 | ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction); | ||
| 1833 | break; | ||
| 1739 | case IrInstructionIdAtomicLoad: | 1834 | case IrInstructionIdAtomicLoad: |
| 1740 | ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); | 1835 | ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); |
| 1741 | break; | 1836 | break; |
| ... | @@ -1745,6 +1840,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1745,6 +1840,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1745 | case IrInstructionIdCheckRuntimeScope: | 1840 | case IrInstructionIdCheckRuntimeScope: |
| 1746 | ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction); | 1841 | ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction); |
| 1747 | break; | 1842 | break; |
| 1843 | case IrInstructionIdDeclVarGen: | ||
| 1844 | ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); | ||
| 1845 | break; | ||
| 1846 | case IrInstructionIdArrayToVector: | ||
| 1847 | ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction); | ||
| 1848 | break; | ||
| 1849 | case IrInstructionIdVectorToArray: | ||
| 1850 | ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction); | ||
| 1851 | break; | ||
| 1852 | case IrInstructionIdAssertZero: | ||
| 1853 | ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); | ||
| 1854 | break; | ||
| 1748 | } | 1855 | } |
| 1749 | fprintf(irp->f, "\n"); | 1856 | fprintf(irp->f, "\n"); |
| 1750 | } | 1857 | } |
src/link.cpp+178-128| ... | @@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) | ... | @@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type, | 44 | CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type, |
| 45 | parent_gen->build_mode, parent_gen->zig_lib_dir); | 45 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir); |
| 46 | 46 | ||
| 47 | child_gen->out_h_path = nullptr; | 47 | child_gen->out_h_path = nullptr; |
| 48 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; | 48 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; |
| ... | @@ -444,72 +444,19 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si | ... | @@ -444,72 +444,19 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si |
| 444 | return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag); | 444 | return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag); |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | static void construct_linker_job_coff(LinkJob *lj) { | 447 | static void add_uefi_link_args(LinkJob *lj) { |
| 448 | CodeGen *g = lj->codegen; | 448 | lj->args.append("/BASE:0"); |
| 449 | 449 | lj->args.append("/ENTRY:EfiMain"); | |
| 450 | lj->args.append("/ERRORLIMIT:0"); | 450 | lj->args.append("/OPT:REF"); |
| 451 | 451 | lj->args.append("/SAFESEH:NO"); | |
| 452 | if (g->libc_link_lib != nullptr) { | 452 | lj->args.append("/MERGE:.rdata=.data"); |
| 453 | find_libc_lib_path(g); | 453 | lj->args.append("/ALIGN:32"); |
| 454 | } | 454 | lj->args.append("/NODEFAULTLIB"); |
| 455 | 455 | lj->args.append("/SECTION:.xdata,D"); | |
| 456 | lj->args.append("-NOLOGO"); | 456 | } |
| 457 | |||
| 458 | if (!g->strip_debug_symbols) { | ||
| 459 | lj->args.append("-DEBUG"); | ||
| 460 | } | ||
| 461 | |||
| 462 | if (g->out_type == OutTypeExe) { | ||
| 463 | // TODO compile time stack upper bound detection | ||
| 464 | lj->args.append("/STACK:16777216"); | ||
| 465 | } | ||
| 466 | |||
| 467 | coff_append_machine_arg(g, &lj->args); | ||
| 468 | |||
| 469 | if (g->windows_subsystem_windows) { | ||
| 470 | lj->args.append("/SUBSYSTEM:windows"); | ||
| 471 | } else if (g->windows_subsystem_console) { | ||
| 472 | lj->args.append("/SUBSYSTEM:console"); | ||
| 473 | } | ||
| 474 | // The commented out stuff is from when we linked with MinGW | ||
| 475 | // Now that we're linking with LLD it remains to be determined | ||
| 476 | // how to handle --target-environ gnu | ||
| 477 | // These comments are a clue | ||
| 478 | |||
| 479 | bool is_library = g->out_type == OutTypeLib; | ||
| 480 | //bool dll = g->out_type == OutTypeLib; | ||
| 481 | //bool shared = !g->is_static && dll; | ||
| 482 | //if (g->is_static) { | ||
| 483 | // lj->args.append("-Bstatic"); | ||
| 484 | //} else { | ||
| 485 | // if (dll) { | ||
| 486 | // lj->args.append("--dll"); | ||
| 487 | // } else if (shared) { | ||
| 488 | // lj->args.append("--shared"); | ||
| 489 | // } | ||
| 490 | // lj->args.append("-Bdynamic"); | ||
| 491 | // if (dll || shared) { | ||
| 492 | // lj->args.append("-e"); | ||
| 493 | // if (g->zig_target.arch.arch == ZigLLVM_x86) { | ||
| 494 | // lj->args.append("_DllMainCRTStartup@12"); | ||
| 495 | // } else { | ||
| 496 | // lj->args.append("DllMainCRTStartup"); | ||
| 497 | // } | ||
| 498 | // lj->args.append("--enable-auto-image-base"); | ||
| 499 | // } | ||
| 500 | //} | ||
| 501 | |||
| 502 | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); | ||
| 503 | |||
| 504 | if (g->libc_link_lib != nullptr) { | ||
| 505 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); | ||
| 506 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); | ||
| 507 | 457 | ||
| 508 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); | 458 | static void add_nt_link_args(LinkJob *lj, bool is_library) { |
| 509 | if (g->libc_static_lib_dir != nullptr) { | 459 | CodeGen *g = lj->codegen; |
| 510 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); | ||
| 511 | } | ||
| 512 | } | ||
| 513 | 460 | ||
| 514 | if (lj->link_in_crt) { | 461 | if (lj->link_in_crt) { |
| 515 | const char *lib_str = g->is_static ? "lib" : ""; | 462 | const char *lib_str = g->is_static ? "lib" : ""; |
| ... | @@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) { | ... | @@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 533 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx | 480 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx |
| 534 | lj->args.append("legacy_stdio_definitions.lib"); | 481 | lj->args.append("legacy_stdio_definitions.lib"); |
| 535 | 482 | ||
| 536 | //if (shared || dll) { | ||
| 537 | // lj->args.append(get_libc_file(g, "dllcrt2.o")); | ||
| 538 | //} else { | ||
| 539 | // if (g->windows_linker_unicode) { | ||
| 540 | // lj->args.append(get_libc_file(g, "crt2u.o")); | ||
| 541 | // } else { | ||
| 542 | // lj->args.append(get_libc_file(g, "crt2.o")); | ||
| 543 | // } | ||
| 544 | //} | ||
| 545 | //lj->args.append(get_libc_static_file(g, "crtbegin.o")); | ||
| 546 | |||
| 547 | // msvcrt depends on kernel32 | 483 | // msvcrt depends on kernel32 |
| 548 | lj->args.append("kernel32.lib"); | 484 | lj->args.append("kernel32.lib"); |
| 549 | } else { | 485 | } else { |
| 550 | lj->args.append("-NODEFAULTLIB"); | 486 | lj->args.append("/NODEFAULTLIB"); |
| 551 | if (!is_library) { | 487 | if (!is_library) { |
| 552 | if (g->have_winmain) { | 488 | if (g->have_winmain) { |
| 553 | lj->args.append("-ENTRY:WinMain"); | 489 | lj->args.append("/ENTRY:WinMain"); |
| 554 | } else { | 490 | } else { |
| 555 | lj->args.append("-ENTRY:WinMainCRTStartup"); | 491 | lj->args.append("/ENTRY:WinMainCRTStartup"); |
| 556 | } | 492 | } |
| 557 | } | 493 | } |
| 558 | } | 494 | } |
| 495 | } | ||
| 496 | |||
| 497 | // These are n actual command lines from LINK.EXE UEFI builds (app & driver) to be used as guidance cleaning | ||
| 498 | // up a bit for building the COFF linker args: | ||
| 499 | // /OUT:"J:\coding\nebulae\k\x64\Release\k.efi" /LTCG:incremental /Driver /PDB:"J:\coding\nebulae\k\x64\Release\k.pdb" "UefiApplicationEntryPoint.lib" "UefiRuntimeLib.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\nebulae\k\x64\Release\k.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_APPLICATION /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D" | ||
| 500 | // /OUT:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.efi" /LTCG:incremental /Driver /PDB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.pdb" "UefiDriverEntryPoint.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D" | ||
| 501 | // This commented out stuff is from when we linked with MinGW | ||
| 502 | // Now that we're linking with LLD it remains to be determined | ||
| 503 | // how to handle --target-environ gnu | ||
| 504 | // These comments are a clue | ||
| 505 | //bool dll = g->out_type == OutTypeLib; | ||
| 506 | //bool shared = !g->is_static && dll; | ||
| 507 | //if (g->is_static) { | ||
| 508 | // lj->args.append("-Bstatic"); | ||
| 509 | //} else { | ||
| 510 | // if (dll) { | ||
| 511 | // lj->args.append("--dll"); | ||
| 512 | // } else if (shared) { | ||
| 513 | // lj->args.append("--shared"); | ||
| 514 | // } | ||
| 515 | // lj->args.append("-Bdynamic"); | ||
| 516 | // if (dll || shared) { | ||
| 517 | // lj->args.append("-e"); | ||
| 518 | // if (g->zig_target.arch.arch == ZigLLVM_x86) { | ||
| 519 | // lj->args.append("_DllMainCRTStartup@12"); | ||
| 520 | // } else { | ||
| 521 | // lj->args.append("DllMainCRTStartup"); | ||
| 522 | // } | ||
| 523 | // lj->args.append("--enable-auto-image-base"); | ||
| 524 | // } | ||
| 525 | //} | ||
| 526 | //if (shared || dll) { | ||
| 527 | // lj->args.append(get_libc_file(g, "dllcrt2.o")); | ||
| 528 | //} else { | ||
| 529 | // if (g->windows_linker_unicode) { | ||
| 530 | // lj->args.append(get_libc_file(g, "crt2u.o")); | ||
| 531 | // } else { | ||
| 532 | // lj->args.append(get_libc_file(g, "crt2.o")); | ||
| 533 | // } | ||
| 534 | //} | ||
| 535 | //lj->args.append(get_libc_static_file(g, "crtbegin.o")); | ||
| 536 | //if (g->libc_link_lib != nullptr) { | ||
| 537 | //if (g->is_static) { | ||
| 538 | // lj->args.append("--start-group"); | ||
| 539 | //} | ||
| 540 | |||
| 541 | //lj->args.append("-lmingw32"); | ||
| 542 | |||
| 543 | //lj->args.append("-lgcc"); | ||
| 544 | //bool is_android = (g->zig_target.env_type == ZigLLVM_Android); | ||
| 545 | //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target); | ||
| 546 | //if (!g->is_static && !is_android) { | ||
| 547 | // if (!is_cyg_ming) { | ||
| 548 | // lj->args.append("--as-needed"); | ||
| 549 | // } | ||
| 550 | // //lj->args.append("-lgcc_s"); | ||
| 551 | // if (!is_cyg_ming) { | ||
| 552 | // lj->args.append("--no-as-needed"); | ||
| 553 | // } | ||
| 554 | //} | ||
| 555 | //if (g->is_static && !is_android) { | ||
| 556 | // //lj->args.append("-lgcc_eh"); | ||
| 557 | //} | ||
| 558 | //if (is_android && !g->is_static) { | ||
| 559 | // lj->args.append("-ldl"); | ||
| 560 | //} | ||
| 561 | |||
| 562 | //lj->args.append("-lmoldname"); | ||
| 563 | //lj->args.append("-lmingwex"); | ||
| 564 | //lj->args.append("-lmsvcrt"); | ||
| 565 | |||
| 566 | |||
| 567 | //if (g->windows_subsystem_windows) { | ||
| 568 | // lj->args.append("-lgdi32"); | ||
| 569 | // lj->args.append("-lcomdlg32"); | ||
| 570 | //} | ||
| 571 | //lj->args.append("-ladvapi32"); | ||
| 572 | //lj->args.append("-lshell32"); | ||
| 573 | //lj->args.append("-luser32"); | ||
| 574 | //lj->args.append("-lkernel32"); | ||
| 575 | |||
| 576 | //if (g->is_static) { | ||
| 577 | // lj->args.append("--end-group"); | ||
| 578 | //} | ||
| 579 | |||
| 580 | //if (lj->link_in_crt) { | ||
| 581 | // lj->args.append(get_libc_static_file(g, "crtend.o")); | ||
| 582 | //} | ||
| 583 | //} | ||
| 584 | |||
| 585 | |||
| 586 | static void construct_linker_job_coff(LinkJob *lj) { | ||
| 587 | CodeGen *g = lj->codegen; | ||
| 588 | |||
| 589 | lj->args.append("/ERRORLIMIT:0"); | ||
| 590 | |||
| 591 | if (g->libc_link_lib != nullptr) { | ||
| 592 | find_libc_lib_path(g); | ||
| 593 | } | ||
| 594 | |||
| 595 | lj->args.append("/NOLOGO"); | ||
| 596 | |||
| 597 | if (!g->strip_debug_symbols) { | ||
| 598 | lj->args.append("/DEBUG"); | ||
| 599 | } | ||
| 600 | |||
| 601 | if (g->out_type == OutTypeExe) { | ||
| 602 | // TODO compile time stack upper bound detection | ||
| 603 | lj->args.append("/STACK:16777216"); | ||
| 604 | } | ||
| 605 | |||
| 606 | coff_append_machine_arg(g, &lj->args); | ||
| 607 | |||
| 608 | bool is_library = g->out_type == OutTypeLib; | ||
| 609 | switch (g->subsystem) { | ||
| 610 | case TargetSubsystemAuto: | ||
| 611 | break; | ||
| 612 | case TargetSubsystemConsole: | ||
| 613 | lj->args.append("/SUBSYSTEM:console"); | ||
| 614 | add_nt_link_args(lj, is_library); | ||
| 615 | break; | ||
| 616 | case TargetSubsystemEfiApplication: | ||
| 617 | lj->args.append("/SUBSYSTEM:efi_application"); | ||
| 618 | add_uefi_link_args(lj); | ||
| 619 | break; | ||
| 620 | case TargetSubsystemEfiBootServiceDriver: | ||
| 621 | lj->args.append("/SUBSYSTEM:efi_boot_service_driver"); | ||
| 622 | add_uefi_link_args(lj); | ||
| 623 | break; | ||
| 624 | case TargetSubsystemEfiRom: | ||
| 625 | lj->args.append("/SUBSYSTEM:efi_rom"); | ||
| 626 | add_uefi_link_args(lj); | ||
| 627 | break; | ||
| 628 | case TargetSubsystemEfiRuntimeDriver: | ||
| 629 | lj->args.append("/SUBSYSTEM:efi_runtime_driver"); | ||
| 630 | add_uefi_link_args(lj); | ||
| 631 | break; | ||
| 632 | case TargetSubsystemNative: | ||
| 633 | lj->args.append("/SUBSYSTEM:native"); | ||
| 634 | add_nt_link_args(lj, is_library); | ||
| 635 | break; | ||
| 636 | case TargetSubsystemPosix: | ||
| 637 | lj->args.append("/SUBSYSTEM:posix"); | ||
| 638 | add_nt_link_args(lj, is_library); | ||
| 639 | break; | ||
| 640 | case TargetSubsystemWindows: | ||
| 641 | lj->args.append("/SUBSYSTEM:windows"); | ||
| 642 | add_nt_link_args(lj, is_library); | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | |||
| 646 | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); | ||
| 647 | |||
| 648 | if (g->libc_link_lib != nullptr) { | ||
| 649 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); | ||
| 650 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); | ||
| 651 | |||
| 652 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); | ||
| 653 | if (g->libc_static_lib_dir != nullptr) { | ||
| 654 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); | ||
| 655 | } | ||
| 656 | } | ||
| 559 | 657 | ||
| 560 | if (is_library && !g->is_static) { | 658 | if (is_library && !g->is_static) { |
| 561 | lj->args.append("-DLL"); | 659 | lj->args.append("-DLL"); |
| ... | @@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) { | ... | @@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 627 | } | 725 | } |
| 628 | } | 726 | } |
| 629 | 727 | ||
| 630 | //if (g->libc_link_lib != nullptr) { | ||
| 631 | //if (g->is_static) { | ||
| 632 | // lj->args.append("--start-group"); | ||
| 633 | //} | ||
| 634 | |||
| 635 | //lj->args.append("-lmingw32"); | ||
| 636 | |||
| 637 | //lj->args.append("-lgcc"); | ||
| 638 | //bool is_android = (g->zig_target.env_type == ZigLLVM_Android); | ||
| 639 | //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target); | ||
| 640 | //if (!g->is_static && !is_android) { | ||
| 641 | // if (!is_cyg_ming) { | ||
| 642 | // lj->args.append("--as-needed"); | ||
| 643 | // } | ||
| 644 | // //lj->args.append("-lgcc_s"); | ||
| 645 | // if (!is_cyg_ming) { | ||
| 646 | // lj->args.append("--no-as-needed"); | ||
| 647 | // } | ||
| 648 | //} | ||
| 649 | //if (g->is_static && !is_android) { | ||
| 650 | // //lj->args.append("-lgcc_eh"); | ||
| 651 | //} | ||
| 652 | //if (is_android && !g->is_static) { | ||
| 653 | // lj->args.append("-ldl"); | ||
| 654 | //} | ||
| 655 | |||
| 656 | //lj->args.append("-lmoldname"); | ||
| 657 | //lj->args.append("-lmingwex"); | ||
| 658 | //lj->args.append("-lmsvcrt"); | ||
| 659 | |||
| 660 | |||
| 661 | //if (g->windows_subsystem_windows) { | ||
| 662 | // lj->args.append("-lgdi32"); | ||
| 663 | // lj->args.append("-lcomdlg32"); | ||
| 664 | //} | ||
| 665 | //lj->args.append("-ladvapi32"); | ||
| 666 | //lj->args.append("-lshell32"); | ||
| 667 | //lj->args.append("-luser32"); | ||
| 668 | //lj->args.append("-lkernel32"); | ||
| 669 | |||
| 670 | //if (g->is_static) { | ||
| 671 | // lj->args.append("--end-group"); | ||
| 672 | //} | ||
| 673 | |||
| 674 | //if (lj->link_in_crt) { | ||
| 675 | // lj->args.append(get_libc_static_file(g, "crtend.o")); | ||
| 676 | //} | ||
| 677 | //} | ||
| 678 | } | 728 | } |
| 679 | 729 | ||
| 680 | 730 |
src/main.cpp+82-16| ... | @@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) { | ... | @@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) { |
| 21 | return EXIT_FAILURE; | 21 | return EXIT_FAILURE; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | static int print_full_usage(const char *arg0) { | 24 | static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 25 | fprintf(stdout, | 25 | fprintf(file, |
| 26 | "Usage: %s [command] [options]\n" | 26 | "Usage: %s [command] [options]\n" |
| 27 | "\n" | 27 | "\n" |
| 28 | "Commands:\n" | 28 | "Commands:\n" |
| ... | @@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) { | ... | @@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) { |
| 31 | " build-lib [source] create library from source or object files\n" | 31 | " build-lib [source] create library from source or object files\n" |
| 32 | " build-obj [source] create object from source or assembly\n" | 32 | " build-obj [source] create object from source or assembly\n" |
| 33 | " builtin show the source code of that @import(\"builtin\")\n" | 33 | " builtin show the source code of that @import(\"builtin\")\n" |
| 34 | " fmt parse files and render in canonical zig format\n" | ||
| 34 | " help show this usage information\n" | 35 | " help show this usage information\n" |
| 35 | " id print the base64-encoded compiler id\n" | 36 | " id print the base64-encoded compiler id\n" |
| 36 | " init-exe initialize a `zig build` application in the cwd\n" | 37 | " init-exe initialize a `zig build` application in the cwd\n" |
| ... | @@ -59,6 +60,7 @@ static int print_full_usage(const char *arg0) { | ... | @@ -59,6 +60,7 @@ static int print_full_usage(const char *arg0) { |
| 59 | " --release-fast build with optimizations on and safety off\n" | 60 | " --release-fast build with optimizations on and safety off\n" |
| 60 | " --release-safe build with optimizations on and safety on\n" | 61 | " --release-safe build with optimizations on and safety on\n" |
| 61 | " --release-small build with size optimizations on and safety off\n" | 62 | " --release-small build with size optimizations on and safety off\n" |
| 63 | " --single-threaded source may assume it is only used single-threaded\n" | ||
| 62 | " --static output will be statically linked\n" | 64 | " --static output will be statically linked\n" |
| 63 | " --strip exclude debug symbols\n" | 65 | " --strip exclude debug symbols\n" |
| 64 | " --target-arch [name] specify target architecture\n" | 66 | " --target-arch [name] specify target architecture\n" |
| ... | @@ -73,6 +75,7 @@ static int print_full_usage(const char *arg0) { | ... | @@ -73,6 +75,7 @@ static int print_full_usage(const char *arg0) { |
| 73 | " -dirafter [dir] same as -isystem but do it last\n" | 75 | " -dirafter [dir] same as -isystem but do it last\n" |
| 74 | " -isystem [dir] add additional search path for other .h files\n" | 76 | " -isystem [dir] add additional search path for other .h files\n" |
| 75 | " -mllvm [arg] forward an arg to LLVM's option processing\n" | 77 | " -mllvm [arg] forward an arg to LLVM's option processing\n" |
| 78 | " --override-std-dir [arg] use an alternate Zig standard library\n" | ||
| 76 | "\n" | 79 | "\n" |
| 77 | "Link Options:\n" | 80 | "Link Options:\n" |
| 78 | " --dynamic-linker [path] set the path to ld.so\n" | 81 | " --dynamic-linker [path] set the path to ld.so\n" |
| ... | @@ -90,8 +93,7 @@ static int print_full_usage(const char *arg0) { | ... | @@ -90,8 +93,7 @@ static int print_full_usage(const char *arg0) { |
| 90 | " -rdynamic add all symbols to the dynamic symbol table\n" | 93 | " -rdynamic add all symbols to the dynamic symbol table\n" |
| 91 | " -rpath [path] add directory to the runtime library search path\n" | 94 | " -rpath [path] add directory to the runtime library search path\n" |
| 92 | " --no-rosegment compromise security to workaround valgrind bug\n" | 95 | " --no-rosegment compromise security to workaround valgrind bug\n" |
| 93 | " -mconsole (windows) --subsystem console to the linker\n" | 96 | " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n" |
| 94 | " -mwindows (windows) --subsystem windows to the linker\n" | ||
| 95 | " -framework [name] (darwin) link against framework\n" | 97 | " -framework [name] (darwin) link against framework\n" |
| 96 | " -mios-version-min [ver] (darwin) set iOS deployment target\n" | 98 | " -mios-version-min [ver] (darwin) set iOS deployment target\n" |
| 97 | " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n" | 99 | " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n" |
| ... | @@ -105,7 +107,7 @@ static int print_full_usage(const char *arg0) { | ... | @@ -105,7 +107,7 @@ static int print_full_usage(const char *arg0) { |
| 105 | " --test-cmd [arg] specify test execution command one arg at a time\n" | 107 | " --test-cmd [arg] specify test execution command one arg at a time\n" |
| 106 | " --test-cmd-bin appends test binary path to test cmd args\n" | 108 | " --test-cmd-bin appends test binary path to test cmd args\n" |
| 107 | , arg0); | 109 | , arg0); |
| 108 | return EXIT_SUCCESS; | 110 | return return_code; |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 111 | static const char *ZIG_ZEN = "\n" | 113 | static const char *ZIG_ZEN = "\n" |
| ... | @@ -371,8 +373,6 @@ int main(int argc, char **argv) { | ... | @@ -371,8 +373,6 @@ int main(int argc, char **argv) { |
| 371 | const char *target_arch = nullptr; | 373 | const char *target_arch = nullptr; |
| 372 | const char *target_os = nullptr; | 374 | const char *target_os = nullptr; |
| 373 | const char *target_environ = nullptr; | 375 | const char *target_environ = nullptr; |
| 374 | bool mwindows = false; | ||
| 375 | bool mconsole = false; | ||
| 376 | bool rdynamic = false; | 376 | bool rdynamic = false; |
| 377 | const char *mmacosx_version_min = nullptr; | 377 | const char *mmacosx_version_min = nullptr; |
| 378 | const char *mios_version_min = nullptr; | 378 | const char *mios_version_min = nullptr; |
| ... | @@ -395,6 +395,9 @@ int main(int argc, char **argv) { | ... | @@ -395,6 +395,9 @@ int main(int argc, char **argv) { |
| 395 | int runtime_args_start = -1; | 395 | int runtime_args_start = -1; |
| 396 | bool no_rosegment_workaround = false; | 396 | bool no_rosegment_workaround = false; |
| 397 | bool system_linker_hack = false; | 397 | bool system_linker_hack = false; |
| 398 | TargetSubsystem subsystem = TargetSubsystemAuto; | ||
| 399 | bool is_single_threaded = false; | ||
| 400 | Buf *override_std_dir = nullptr; | ||
| 398 | 401 | ||
| 399 | if (argc >= 2 && strcmp(argv[1], "build") == 0) { | 402 | if (argc >= 2 && strcmp(argv[1], "build") == 0) { |
| 400 | Buf zig_exe_path_buf = BUF_INIT; | 403 | Buf zig_exe_path_buf = BUF_INIT; |
| ... | @@ -430,7 +433,8 @@ int main(int argc, char **argv) { | ... | @@ -430,7 +433,8 @@ int main(int argc, char **argv) { |
| 430 | Buf *build_runner_path = buf_alloc(); | 433 | Buf *build_runner_path = buf_alloc(); |
| 431 | os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path); | 434 | os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path); |
| 432 | 435 | ||
| 433 | CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir()); | 436 | CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), |
| 437 | override_std_dir); | ||
| 434 | g->enable_time_report = timing_info; | 438 | g->enable_time_report = timing_info; |
| 435 | buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name); | 439 | buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name); |
| 436 | codegen_set_out_name(g, buf_create_from_str("build")); | 440 | codegen_set_out_name(g, buf_create_from_str("build")); |
| ... | @@ -512,6 +516,31 @@ int main(int argc, char **argv) { | ... | @@ -512,6 +516,31 @@ int main(int argc, char **argv) { |
| 512 | fprintf(stderr, "\n"); | 516 | fprintf(stderr, "\n"); |
| 513 | } | 517 | } |
| 514 | return (term.how == TerminationIdClean) ? term.code : -1; | 518 | return (term.how == TerminationIdClean) ? term.code : -1; |
| 519 | } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) { | ||
| 520 | init_all_targets(); | ||
| 521 | Buf *fmt_runner_path = buf_alloc(); | ||
| 522 | os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path); | ||
| 523 | CodeGen *g = codegen_create(fmt_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), | ||
| 524 | nullptr); | ||
| 525 | g->is_single_threaded = true; | ||
| 526 | codegen_set_out_name(g, buf_create_from_str("fmt")); | ||
| 527 | g->enable_cache = true; | ||
| 528 | |||
| 529 | codegen_build_and_link(g); | ||
| 530 | |||
| 531 | ZigList<const char*> args = {0}; | ||
| 532 | for (int i = 2; i < argc; i += 1) { | ||
| 533 | args.append(argv[i]); | ||
| 534 | } | ||
| 535 | args.append(nullptr); | ||
| 536 | const char *exec_path = buf_ptr(&g->output_file_path); | ||
| 537 | |||
| 538 | os_execv(exec_path, args.items); | ||
| 539 | |||
| 540 | args.pop(); | ||
| 541 | Termination term; | ||
| 542 | os_spawn_process(exec_path, args, &term); | ||
| 543 | return term.code; | ||
| 515 | } | 544 | } |
| 516 | 545 | ||
| 517 | for (int i = 1; i < argc; i += 1) { | 546 | for (int i = 1; i < argc; i += 1) { |
| ... | @@ -524,6 +553,8 @@ int main(int argc, char **argv) { | ... | @@ -524,6 +553,8 @@ int main(int argc, char **argv) { |
| 524 | build_mode = BuildModeSafeRelease; | 553 | build_mode = BuildModeSafeRelease; |
| 525 | } else if (strcmp(arg, "--release-small") == 0) { | 554 | } else if (strcmp(arg, "--release-small") == 0) { |
| 526 | build_mode = BuildModeSmallRelease; | 555 | build_mode = BuildModeSmallRelease; |
| 556 | } else if (strcmp(arg, "--help") == 0) { | ||
| 557 | return print_full_usage(arg0, stderr, EXIT_FAILURE); | ||
| 527 | } else if (strcmp(arg, "--strip") == 0) { | 558 | } else if (strcmp(arg, "--strip") == 0) { |
| 528 | strip = true; | 559 | strip = true; |
| 529 | } else if (strcmp(arg, "--static") == 0) { | 560 | } else if (strcmp(arg, "--static") == 0) { |
| ... | @@ -540,10 +571,6 @@ int main(int argc, char **argv) { | ... | @@ -540,10 +571,6 @@ int main(int argc, char **argv) { |
| 540 | verbose_llvm_ir = true; | 571 | verbose_llvm_ir = true; |
| 541 | } else if (strcmp(arg, "--verbose-cimport") == 0) { | 572 | } else if (strcmp(arg, "--verbose-cimport") == 0) { |
| 542 | verbose_cimport = true; | 573 | verbose_cimport = true; |
| 543 | } else if (strcmp(arg, "-mwindows") == 0) { | ||
| 544 | mwindows = true; | ||
| 545 | } else if (strcmp(arg, "-mconsole") == 0) { | ||
| 546 | mconsole = true; | ||
| 547 | } else if (strcmp(arg, "-rdynamic") == 0) { | 574 | } else if (strcmp(arg, "-rdynamic") == 0) { |
| 548 | rdynamic = true; | 575 | rdynamic = true; |
| 549 | } else if (strcmp(arg, "--no-rosegment") == 0) { | 576 | } else if (strcmp(arg, "--no-rosegment") == 0) { |
| ... | @@ -556,6 +583,8 @@ int main(int argc, char **argv) { | ... | @@ -556,6 +583,8 @@ int main(int argc, char **argv) { |
| 556 | disable_pic = true; | 583 | disable_pic = true; |
| 557 | } else if (strcmp(arg, "--system-linker-hack") == 0) { | 584 | } else if (strcmp(arg, "--system-linker-hack") == 0) { |
| 558 | system_linker_hack = true; | 585 | system_linker_hack = true; |
| 586 | } else if (strcmp(arg, "--single-threaded") == 0) { | ||
| 587 | is_single_threaded = true; | ||
| 559 | } else if (strcmp(arg, "--test-cmd-bin") == 0) { | 588 | } else if (strcmp(arg, "--test-cmd-bin") == 0) { |
| 560 | test_exec_args.append(nullptr); | 589 | test_exec_args.append(nullptr); |
| 561 | } else if (arg[1] == 'L' && arg[2] != 0) { | 590 | } else if (arg[1] == 'L' && arg[2] != 0) { |
| ... | @@ -647,6 +676,8 @@ int main(int argc, char **argv) { | ... | @@ -647,6 +676,8 @@ int main(int argc, char **argv) { |
| 647 | clang_argv.append(argv[i]); | 676 | clang_argv.append(argv[i]); |
| 648 | 677 | ||
| 649 | llvm_argv.append(argv[i]); | 678 | llvm_argv.append(argv[i]); |
| 679 | } else if (strcmp(arg, "--override-std-dir") == 0) { | ||
| 680 | override_std_dir = buf_create_from_str(argv[i]); | ||
| 650 | } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { | 681 | } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { |
| 651 | lib_dirs.append(argv[i]); | 682 | lib_dirs.append(argv[i]); |
| 652 | } else if (strcmp(arg, "--library") == 0) { | 683 | } else if (strcmp(arg, "--library") == 0) { |
| ... | @@ -687,6 +718,37 @@ int main(int argc, char **argv) { | ... | @@ -687,6 +718,37 @@ int main(int argc, char **argv) { |
| 687 | ver_patch = atoi(argv[i]); | 718 | ver_patch = atoi(argv[i]); |
| 688 | } else if (strcmp(arg, "--test-cmd") == 0) { | 719 | } else if (strcmp(arg, "--test-cmd") == 0) { |
| 689 | test_exec_args.append(argv[i]); | 720 | test_exec_args.append(argv[i]); |
| 721 | } else if (strcmp(arg, "--subsystem") == 0) { | ||
| 722 | if (strcmp(argv[i], "console") == 0) { | ||
| 723 | subsystem = TargetSubsystemConsole; | ||
| 724 | } else if (strcmp(argv[i], "windows") == 0) { | ||
| 725 | subsystem = TargetSubsystemWindows; | ||
| 726 | } else if (strcmp(argv[i], "posix") == 0) { | ||
| 727 | subsystem = TargetSubsystemPosix; | ||
| 728 | } else if (strcmp(argv[i], "native") == 0) { | ||
| 729 | subsystem = TargetSubsystemNative; | ||
| 730 | } else if (strcmp(argv[i], "efi_application") == 0) { | ||
| 731 | subsystem = TargetSubsystemEfiApplication; | ||
| 732 | } else if (strcmp(argv[i], "efi_boot_service_driver") == 0) { | ||
| 733 | subsystem = TargetSubsystemEfiBootServiceDriver; | ||
| 734 | } else if (strcmp(argv[i], "efi_rom") == 0) { | ||
| 735 | subsystem = TargetSubsystemEfiRom; | ||
| 736 | } else if (strcmp(argv[i], "efi_runtime_driver") == 0) { | ||
| 737 | subsystem = TargetSubsystemEfiRuntimeDriver; | ||
| 738 | } else { | ||
| 739 | fprintf(stderr, "invalid: --subsystem %s\n" | ||
| 740 | "Options are:\n" | ||
| 741 | " console\n" | ||
| 742 | " windows\n" | ||
| 743 | " posix\n" | ||
| 744 | " native\n" | ||
| 745 | " efi_application\n" | ||
| 746 | " efi_boot_service_driver\n" | ||
| 747 | " efi_rom\n" | ||
| 748 | " efi_runtime_driver\n" | ||
| 749 | , argv[i]); | ||
| 750 | return EXIT_FAILURE; | ||
| 751 | } | ||
| 690 | } else { | 752 | } else { |
| 691 | fprintf(stderr, "Invalid argument: %s\n", arg); | 753 | fprintf(stderr, "Invalid argument: %s\n", arg); |
| 692 | return print_error_usage(arg0); | 754 | return print_error_usage(arg0); |
| ... | @@ -790,7 +852,8 @@ int main(int argc, char **argv) { | ... | @@ -790,7 +852,8 @@ int main(int argc, char **argv) { |
| 790 | 852 | ||
| 791 | switch (cmd) { | 853 | switch (cmd) { |
| 792 | case CmdBuiltin: { | 854 | case CmdBuiltin: { |
| 793 | CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir()); | 855 | CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir); |
| 856 | g->is_single_threaded = is_single_threaded; | ||
| 794 | Buf *builtin_source = codegen_generate_builtin_source(g); | 857 | Buf *builtin_source = codegen_generate_builtin_source(g); |
| 795 | if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { | 858 | if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { |
| 796 | fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); | 859 | fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); |
| ... | @@ -848,7 +911,10 @@ int main(int argc, char **argv) { | ... | @@ -848,7 +911,10 @@ int main(int argc, char **argv) { |
| 848 | if (cmd == CmdRun && buf_out_name == nullptr) { | 911 | if (cmd == CmdRun && buf_out_name == nullptr) { |
| 849 | buf_out_name = buf_create_from_str("run"); | 912 | buf_out_name = buf_create_from_str("run"); |
| 850 | } | 913 | } |
| 851 | CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir()); | 914 | CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(), |
| 915 | override_std_dir); | ||
| 916 | g->subsystem = subsystem; | ||
| 917 | |||
| 852 | if (disable_pic) { | 918 | if (disable_pic) { |
| 853 | if (out_type != OutTypeLib || !is_static) { | 919 | if (out_type != OutTypeLib || !is_static) { |
| 854 | fprintf(stderr, "--disable-pic only applies to static libraries"); | 920 | fprintf(stderr, "--disable-pic only applies to static libraries"); |
| ... | @@ -862,6 +928,7 @@ int main(int argc, char **argv) { | ... | @@ -862,6 +928,7 @@ int main(int argc, char **argv) { |
| 862 | codegen_set_out_name(g, buf_out_name); | 928 | codegen_set_out_name(g, buf_out_name); |
| 863 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); | 929 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 864 | codegen_set_is_test(g, cmd == CmdTest); | 930 | codegen_set_is_test(g, cmd == CmdTest); |
| 931 | g->is_single_threaded = is_single_threaded; | ||
| 865 | codegen_set_linker_script(g, linker_script); | 932 | codegen_set_linker_script(g, linker_script); |
| 866 | if (each_lib_rpath) | 933 | if (each_lib_rpath) |
| 867 | codegen_set_each_lib_rpath(g, each_lib_rpath); | 934 | codegen_set_each_lib_rpath(g, each_lib_rpath); |
| ... | @@ -909,7 +976,6 @@ int main(int argc, char **argv) { | ... | @@ -909,7 +976,6 @@ int main(int argc, char **argv) { |
| 909 | codegen_add_rpath(g, rpath_list.at(i)); | 976 | codegen_add_rpath(g, rpath_list.at(i)); |
| 910 | } | 977 | } |
| 911 | 978 | ||
| 912 | codegen_set_windows_subsystem(g, mwindows, mconsole); | ||
| 913 | codegen_set_rdynamic(g, rdynamic); | 979 | codegen_set_rdynamic(g, rdynamic); |
| 914 | g->no_rosegment_workaround = no_rosegment_workaround; | 980 | g->no_rosegment_workaround = no_rosegment_workaround; |
| 915 | if (mmacosx_version_min && mios_version_min) { | 981 | if (mmacosx_version_min && mios_version_min) { |
| ... | @@ -1042,7 +1108,7 @@ int main(int argc, char **argv) { | ... | @@ -1042,7 +1108,7 @@ int main(int argc, char **argv) { |
| 1042 | } | 1108 | } |
| 1043 | } | 1109 | } |
| 1044 | case CmdHelp: | 1110 | case CmdHelp: |
| 1045 | return print_full_usage(arg0); | 1111 | return print_full_usage(arg0, stdout, EXIT_SUCCESS); |
| 1046 | case CmdVersion: | 1112 | case CmdVersion: |
| 1047 | printf("%s\n", ZIG_VERSION_STRING); | 1113 | printf("%s\n", ZIG_VERSION_STRING); |
| 1048 | return EXIT_SUCCESS; | 1114 | return EXIT_SUCCESS; |
src/os.cpp+32-32| ... | @@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) { | ... | @@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) { |
| 1456 | if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { | 1456 | if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { |
| 1457 | return ErrorUnexpected; | 1457 | return ErrorUnexpected; |
| 1458 | } | 1458 | } |
| 1459 | buf_resize(out_path, cb); | 1459 | buf_resize(out_path, cb - 1); |
| 1460 | return ErrorNone; | 1460 | return ErrorNone; |
| 1461 | #endif | 1461 | #endif |
| 1462 | return ErrorFileNotFound; | 1462 | return ErrorFileNotFound; |
| ... | @@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) { | ... | @@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) { |
| 1808 | #endif | 1808 | #endif |
| 1809 | } | 1809 | } |
| 1810 | 1810 | ||
| 1811 | Error os_file_open_r(Buf *full_path, OsFile *out_file) { | 1811 | Error os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime) { |
| 1812 | #if defined(ZIG_OS_WINDOWS) | 1812 | #if defined(ZIG_OS_WINDOWS) |
| 1813 | // TODO use CreateFileW | 1813 | // TODO use CreateFileW |
| 1814 | HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); | 1814 | HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); |
| ... | @@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) { | ... | @@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) { |
| 1834 | return ErrorUnexpected; | 1834 | return ErrorUnexpected; |
| 1835 | } | 1835 | } |
| 1836 | } | 1836 | } |
| 1837 | |||
| 1838 | *out_file = result; | 1837 | *out_file = result; |
| 1838 | |||
| 1839 | if (mtime != nullptr) { | ||
| 1840 | FILETIME last_write_time; | ||
| 1841 | if (!GetFileTime(result, nullptr, nullptr, &last_write_time)) { | ||
| 1842 | CloseHandle(result); | ||
| 1843 | return ErrorUnexpected; | ||
| 1844 | } | ||
| 1845 | mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; | ||
| 1846 | mtime->nsec = 0; | ||
| 1847 | } | ||
| 1848 | |||
| 1839 | return ErrorNone; | 1849 | return ErrorNone; |
| 1840 | #else | 1850 | #else |
| 1841 | for (;;) { | 1851 | for (;;) { |
| ... | @@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) { | ... | @@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) { |
| 1858 | return ErrorFileSystem; | 1868 | return ErrorFileSystem; |
| 1859 | } | 1869 | } |
| 1860 | } | 1870 | } |
| 1871 | struct stat statbuf; | ||
| 1872 | if (fstat(fd, &statbuf) == -1) { | ||
| 1873 | close(fd); | ||
| 1874 | return ErrorFileSystem; | ||
| 1875 | } | ||
| 1876 | if (S_ISDIR(statbuf.st_mode)) { | ||
| 1877 | close(fd); | ||
| 1878 | return ErrorIsDir; | ||
| 1879 | } | ||
| 1861 | *out_file = fd; | 1880 | *out_file = fd; |
| 1881 | |||
| 1882 | if (mtime != nullptr) { | ||
| 1883 | #if defined(ZIG_OS_DARWIN) | ||
| 1884 | mtime->sec = statbuf.st_mtimespec.tv_sec; | ||
| 1885 | mtime->nsec = statbuf.st_mtimespec.tv_nsec; | ||
| 1886 | #else | ||
| 1887 | mtime->sec = statbuf.st_mtim.tv_sec; | ||
| 1888 | mtime->nsec = statbuf.st_mtim.tv_nsec; | ||
| 1889 | #endif | ||
| 1890 | } | ||
| 1862 | return ErrorNone; | 1891 | return ErrorNone; |
| 1863 | } | 1892 | } |
| 1864 | #endif | 1893 | #endif |
| ... | @@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { | ... | @@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { |
| 1948 | #endif | 1977 | #endif |
| 1949 | } | 1978 | } |
| 1950 | 1979 | ||
| 1951 | Error os_file_mtime(OsFile file, OsTimeStamp *mtime) { | ||
| 1952 | #if defined(ZIG_OS_WINDOWS) | ||
| 1953 | FILETIME last_write_time; | ||
| 1954 | if (!GetFileTime(file, nullptr, nullptr, &last_write_time)) | ||
| 1955 | return ErrorUnexpected; | ||
| 1956 | mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; | ||
| 1957 | mtime->nsec = 0; | ||
| 1958 | return ErrorNone; | ||
| 1959 | #elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) | ||
| 1960 | struct stat statbuf; | ||
| 1961 | if (fstat(file, &statbuf) == -1) | ||
| 1962 | return ErrorFileSystem; | ||
| 1963 | |||
| 1964 | mtime->sec = statbuf.st_mtim.tv_sec; | ||
| 1965 | mtime->nsec = statbuf.st_mtim.tv_nsec; | ||
| 1966 | return ErrorNone; | ||
| 1967 | #elif defined(ZIG_OS_DARWIN) | ||
| 1968 | struct stat statbuf; | ||
| 1969 | if (fstat(file, &statbuf) == -1) | ||
| 1970 | return ErrorFileSystem; | ||
| 1971 | |||
| 1972 | mtime->sec = statbuf.st_mtimespec.tv_sec; | ||
| 1973 | mtime->nsec = statbuf.st_mtimespec.tv_nsec; | ||
| 1974 | return ErrorNone; | ||
| 1975 | #else | ||
| 1976 | #error unimplemented | ||
| 1977 | #endif | ||
| 1978 | } | ||
| 1979 | |||
| 1980 | Error os_file_read(OsFile file, void *ptr, size_t *len) { | 1980 | Error os_file_read(OsFile file, void *ptr, size_t *len) { |
| 1981 | #if defined(ZIG_OS_WINDOWS) | 1981 | #if defined(ZIG_OS_WINDOWS) |
| 1982 | DWORD amt_read; | 1982 | DWORD amt_read; |
src/os.hpp+1-2| ... | @@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path); | ... | @@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path); |
| 101 | Error ATTRIBUTE_MUST_USE os_make_path(Buf *path); | 101 | Error ATTRIBUTE_MUST_USE os_make_path(Buf *path); |
| 102 | Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path); | 102 | Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path); |
| 103 | 103 | ||
| 104 | Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file); | 104 | Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime); |
| 105 | Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file); | 105 | Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file); |
| 106 | Error ATTRIBUTE_MUST_USE os_file_mtime(OsFile file, OsTimeStamp *mtime); | ||
| 107 | Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len); | 106 | Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len); |
| 108 | Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents); | 107 | Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents); |
| 109 | Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents); | 108 | Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents); |
src/parser.cpp+27-13| ... | @@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse | ... | @@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse |
| 381 | else_body = ast_expect(pc, body_parser); | 381 | else_body = ast_expect(pc, body_parser); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | assert(res->type == NodeTypeTestExpr); | 384 | assert(res->type == NodeTypeIfOptional); |
| 385 | if (err_payload != nullptr) { | 385 | if (err_payload != nullptr) { |
| 386 | AstNodeTestExpr old = res->data.test_expr; | 386 | AstNodeTestExpr old = res->data.test_expr; |
| 387 | res->type = NodeTypeIfErrorExpr; | 387 | res->type = NodeTypeIfErrorExpr; |
| ... | @@ -844,12 +844,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { | ... | @@ -844,12 +844,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 844 | 844 | ||
| 845 | // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON | 845 | // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON |
| 846 | static AstNode *ast_parse_var_decl(ParseContext *pc) { | 846 | static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 847 | Token *first = eat_token_if(pc, TokenIdKeywordConst); | 847 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); |
| 848 | if (first == nullptr) | 848 | Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst); |
| 849 | first = eat_token_if(pc, TokenIdKeywordVar); | 849 | if (mut_kw == nullptr) |
| 850 | if (first == nullptr) | 850 | mut_kw = eat_token_if(pc, TokenIdKeywordVar); |
| 851 | return nullptr; | 851 | if (mut_kw == nullptr) { |
| 852 | 852 | if (thread_local_kw == nullptr) { | |
| 853 | return nullptr; | ||
| 854 | } else { | ||
| 855 | ast_invalid_token_error(pc, peek_token(pc)); | ||
| 856 | } | ||
| 857 | } | ||
| 853 | Token *identifier = expect_token(pc, TokenIdSymbol); | 858 | Token *identifier = expect_token(pc, TokenIdSymbol); |
| 854 | AstNode *type_expr = nullptr; | 859 | AstNode *type_expr = nullptr; |
| 855 | if (eat_token_if(pc, TokenIdColon) != nullptr) | 860 | if (eat_token_if(pc, TokenIdColon) != nullptr) |
| ... | @@ -863,8 +868,9 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { | ... | @@ -863,8 +868,9 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 863 | 868 | ||
| 864 | expect_token(pc, TokenIdSemicolon); | 869 | expect_token(pc, TokenIdSemicolon); |
| 865 | 870 | ||
| 866 | AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, first); | 871 | AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw); |
| 867 | res->data.variable_declaration.is_const = first->id == TokenIdKeywordConst; | 872 | res->data.variable_declaration.threadlocal_tok = thread_local_kw; |
| 873 | res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst; | ||
| 868 | res->data.variable_declaration.symbol = token_buf(identifier); | 874 | res->data.variable_declaration.symbol = token_buf(identifier); |
| 869 | res->data.variable_declaration.type = type_expr; | 875 | res->data.variable_declaration.type = type_expr; |
| 870 | res->data.variable_declaration.align_expr = align_expr; | 876 | res->data.variable_declaration.align_expr = align_expr; |
| ... | @@ -990,7 +996,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { | ... | @@ -990,7 +996,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { |
| 990 | if (requires_semi && else_body == nullptr) | 996 | if (requires_semi && else_body == nullptr) |
| 991 | expect_token(pc, TokenIdSemicolon); | 997 | expect_token(pc, TokenIdSemicolon); |
| 992 | 998 | ||
| 993 | assert(res->type == NodeTypeTestExpr); | 999 | assert(res->type == NodeTypeIfOptional); |
| 994 | if (err_payload != nullptr) { | 1000 | if (err_payload != nullptr) { |
| 995 | AstNodeTestExpr old = res->data.test_expr; | 1001 | AstNodeTestExpr old = res->data.test_expr; |
| 996 | res->type = NodeTypeIfErrorExpr; | 1002 | res->type = NodeTypeIfErrorExpr; |
| ... | @@ -2204,7 +2210,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { | ... | @@ -2204,7 +2210,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { |
| 2204 | Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc); | 2210 | Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc); |
| 2205 | 2211 | ||
| 2206 | PtrPayload payload; | 2212 | PtrPayload payload; |
| 2207 | AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first); | 2213 | AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first); |
| 2208 | res->data.test_expr.target_node = condition; | 2214 | res->data.test_expr.target_node = condition; |
| 2209 | if (opt_payload.unwrap(&payload)) { | 2215 | if (opt_payload.unwrap(&payload)) { |
| 2210 | res->data.test_expr.var_symbol = token_buf(payload.payload); | 2216 | res->data.test_expr.var_symbol = token_buf(payload.payload); |
| ... | @@ -2772,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) { | ... | @@ -2772,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) { |
| 2772 | // PtrTypeStart | 2778 | // PtrTypeStart |
| 2773 | // <- ASTERISK | 2779 | // <- ASTERISK |
| 2774 | // / ASTERISK2 | 2780 | // / ASTERISK2 |
| 2775 | // / LBRACKET ASTERISK RBRACKET | 2781 | // / PTRUNKNOWN |
| 2782 | // / PTRC | ||
| 2776 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | 2783 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2777 | Token *asterisk = eat_token_if(pc, TokenIdStar); | 2784 | Token *asterisk = eat_token_if(pc, TokenIdStar); |
| 2778 | if (asterisk != nullptr) { | 2785 | if (asterisk != nullptr) { |
| ... | @@ -2798,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | ... | @@ -2798,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2798 | return res; | 2805 | return res; |
| 2799 | } | 2806 | } |
| 2800 | 2807 | ||
| 2808 | Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket); | ||
| 2809 | if (cptr != nullptr) { | ||
| 2810 | AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr); | ||
| 2811 | res->data.pointer_type.star_token = cptr; | ||
| 2812 | return res; | ||
| 2813 | } | ||
| 2814 | |||
| 2801 | return nullptr; | 2815 | return nullptr; |
| 2802 | } | 2816 | } |
| 2803 | 2817 | ||
| ... | @@ -2999,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2999,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2999 | visit_field(&node->data.if_err_expr.then_node, visit, context); | 3013 | visit_field(&node->data.if_err_expr.then_node, visit, context); |
| 3000 | visit_field(&node->data.if_err_expr.else_node, visit, context); | 3014 | visit_field(&node->data.if_err_expr.else_node, visit, context); |
| 3001 | break; | 3015 | break; |
| 3002 | case NodeTypeTestExpr: | 3016 | case NodeTypeIfOptional: |
| 3003 | visit_field(&node->data.test_expr.target_node, visit, context); | 3017 | visit_field(&node->data.test_expr.target_node, visit, context); |
| 3004 | visit_field(&node->data.test_expr.then_node, visit, context); | 3018 | visit_field(&node->data.test_expr.then_node, visit, context); |
| 3005 | visit_field(&node->data.test_expr.else_node, visit, context); | 3019 | visit_field(&node->data.test_expr.else_node, visit, context); |
src/target.cpp+13-2| ... | @@ -174,6 +174,7 @@ static const Os os_list[] = { | ... | @@ -174,6 +174,7 @@ static const Os os_list[] = { |
| 174 | OsContiki, | 174 | OsContiki, |
| 175 | OsAMDPAL, | 175 | OsAMDPAL, |
| 176 | OsZen, | 176 | OsZen, |
| 177 | OsUefi, | ||
| 177 | }; | 178 | }; |
| 178 | 179 | ||
| 179 | // Coordinate with zig_llvm.h | 180 | // Coordinate with zig_llvm.h |
| ... | @@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) { | ... | @@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) { |
| 282 | case OsSolaris: | 283 | case OsSolaris: |
| 283 | return ZigLLVM_Solaris; | 284 | return ZigLLVM_Solaris; |
| 284 | case OsWindows: | 285 | case OsWindows: |
| 286 | case OsUefi: | ||
| 285 | return ZigLLVM_Win32; | 287 | return ZigLLVM_Win32; |
| 286 | case OsHaiku: | 288 | case OsHaiku: |
| 287 | return ZigLLVM_Haiku; | 289 | return ZigLLVM_Haiku; |
| ... | @@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) { | ... | @@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) { |
| 394 | return "freestanding"; | 396 | return "freestanding"; |
| 395 | case OsZen: | 397 | case OsZen: |
| 396 | return "zen"; | 398 | return "zen"; |
| 399 | case OsUefi: | ||
| 400 | return "uefi"; | ||
| 397 | case OsAnanas: | 401 | case OsAnanas: |
| 398 | case OsCloudABI: | 402 | case OsCloudABI: |
| 399 | case OsDragonFly: | 403 | case OsDragonFly: |
| ... | @@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { | ... | @@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 756 | case CIntTypeCount: | 760 | case CIntTypeCount: |
| 757 | zig_unreachable(); | 761 | zig_unreachable(); |
| 758 | } | 762 | } |
| 763 | case OsUefi: | ||
| 759 | case OsWindows: | 764 | case OsWindows: |
| 760 | switch (id) { | 765 | switch (id) { |
| 761 | case CIntTypeShort: | 766 | case CIntTypeShort: |
| ... | @@ -802,8 +807,12 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { | ... | @@ -802,8 +807,12 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 802 | zig_unreachable(); | 807 | zig_unreachable(); |
| 803 | } | 808 | } |
| 804 | 809 | ||
| 810 | bool target_allows_addr_zero(const ZigTarget *target) { | ||
| 811 | return target->os == OsFreestanding; | ||
| 812 | } | ||
| 813 | |||
| 805 | const char *target_o_file_ext(ZigTarget *target) { | 814 | const char *target_o_file_ext(ZigTarget *target) { |
| 806 | if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows) { | 815 | if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) { |
| 807 | return ".obj"; | 816 | return ".obj"; |
| 808 | } else { | 817 | } else { |
| 809 | return ".o"; | 818 | return ".o"; |
| ... | @@ -821,13 +830,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) { | ... | @@ -821,13 +830,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) { |
| 821 | const char *target_exe_file_ext(ZigTarget *target) { | 830 | const char *target_exe_file_ext(ZigTarget *target) { |
| 822 | if (target->os == OsWindows) { | 831 | if (target->os == OsWindows) { |
| 823 | return ".exe"; | 832 | return ".exe"; |
| 833 | } else if (target->os == OsUefi) { | ||
| 834 | return ".efi"; | ||
| 824 | } else { | 835 | } else { |
| 825 | return ""; | 836 | return ""; |
| 826 | } | 837 | } |
| 827 | } | 838 | } |
| 828 | 839 | ||
| 829 | const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) { | 840 | const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) { |
| 830 | if (target->os == OsWindows) { | 841 | if (target->os == OsWindows || target->os == OsUefi) { |
| 831 | if (is_static) { | 842 | if (is_static) { |
| 832 | return ".lib"; | 843 | return ".lib"; |
| 833 | } else { | 844 | } else { |
src/target.hpp+14| ... | @@ -51,6 +51,19 @@ enum Os { | ... | @@ -51,6 +51,19 @@ enum Os { |
| 51 | OsContiki, | 51 | OsContiki, |
| 52 | OsAMDPAL, | 52 | OsAMDPAL, |
| 53 | OsZen, | 53 | OsZen, |
| 54 | OsUefi, | ||
| 55 | }; | ||
| 56 | |||
| 57 | enum TargetSubsystem { | ||
| 58 | TargetSubsystemAuto, // Zig should infer the subsystem | ||
| 59 | TargetSubsystemConsole, | ||
| 60 | TargetSubsystemWindows, | ||
| 61 | TargetSubsystemPosix, | ||
| 62 | TargetSubsystemNative, | ||
| 63 | TargetSubsystemEfiApplication, | ||
| 64 | TargetSubsystemEfiBootServiceDriver, | ||
| 65 | TargetSubsystemEfiRom, | ||
| 66 | TargetSubsystemEfiRuntimeDriver, | ||
| 54 | }; | 67 | }; |
| 55 | 68 | ||
| 56 | struct ZigTarget { | 69 | struct ZigTarget { |
| ... | @@ -122,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target | ... | @@ -122,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target |
| 122 | ZigLLVM_OSType get_llvm_os_type(Os os_type); | 135 | ZigLLVM_OSType get_llvm_os_type(Os os_type); |
| 123 | 136 | ||
| 124 | bool target_is_arm(const ZigTarget *target); | 137 | bool target_is_arm(const ZigTarget *target); |
| 138 | bool target_allows_addr_zero(const ZigTarget *target); | ||
| 125 | 139 | ||
| 126 | #endif | 140 | #endif |
src/tokenizer.cpp+25-8| ... | @@ -146,6 +146,7 @@ static const struct ZigKeyword zig_keywords[] = { | ... | @@ -146,6 +146,7 @@ static const struct ZigKeyword zig_keywords[] = { |
| 146 | {"suspend", TokenIdKeywordSuspend}, | 146 | {"suspend", TokenIdKeywordSuspend}, |
| 147 | {"switch", TokenIdKeywordSwitch}, | 147 | {"switch", TokenIdKeywordSwitch}, |
| 148 | {"test", TokenIdKeywordTest}, | 148 | {"test", TokenIdKeywordTest}, |
| 149 | {"threadlocal", TokenIdKeywordThreadLocal}, | ||
| 149 | {"true", TokenIdKeywordTrue}, | 150 | {"true", TokenIdKeywordTrue}, |
| 150 | {"try", TokenIdKeywordTry}, | 151 | {"try", TokenIdKeywordTry}, |
| 151 | {"undefined", TokenIdKeywordUndefined}, | 152 | {"undefined", TokenIdKeywordUndefined}, |
| ... | @@ -220,6 +221,7 @@ enum TokenizeState { | ... | @@ -220,6 +221,7 @@ enum TokenizeState { |
| 220 | TokenizeStateError, | 221 | TokenizeStateError, |
| 221 | TokenizeStateLBracket, | 222 | TokenizeStateLBracket, |
| 222 | TokenizeStateLBracketStar, | 223 | TokenizeStateLBracketStar, |
| 224 | TokenizeStateLBracketStarC, | ||
| 223 | }; | 225 | }; |
| 224 | 226 | ||
| 225 | 227 | ||
| ... | @@ -248,13 +250,8 @@ ATTRIBUTE_PRINTF(2, 3) | ... | @@ -248,13 +250,8 @@ ATTRIBUTE_PRINTF(2, 3) |
| 248 | static void tokenize_error(Tokenize *t, const char *format, ...) { | 250 | static void tokenize_error(Tokenize *t, const char *format, ...) { |
| 249 | t->state = TokenizeStateError; | 251 | t->state = TokenizeStateError; |
| 250 | 252 | ||
| 251 | if (t->cur_tok) { | 253 | t->out->err_line = t->line; |
| 252 | t->out->err_line = t->cur_tok->start_line; | 254 | t->out->err_column = t->column; |
| 253 | t->out->err_column = t->cur_tok->start_column; | ||
| 254 | } else { | ||
| 255 | t->out->err_line = t->line; | ||
| 256 | t->out->err_column = t->column; | ||
| 257 | } | ||
| 258 | 255 | ||
| 259 | va_list ap; | 256 | va_list ap; |
| 260 | va_start(ap, format); | 257 | va_start(ap, format); |
| ... | @@ -850,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -850,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 850 | switch (c) { | 847 | switch (c) { |
| 851 | case '*': | 848 | case '*': |
| 852 | t.state = TokenizeStateLBracketStar; | 849 | t.state = TokenizeStateLBracketStar; |
| 853 | set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket); | ||
| 854 | break; | 850 | break; |
| 855 | default: | 851 | default: |
| 856 | // reinterpret as just an lbracket | 852 | // reinterpret as just an lbracket |
| ... | @@ -861,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -861,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 861 | } | 857 | } |
| 862 | break; | 858 | break; |
| 863 | case TokenizeStateLBracketStar: | 859 | case TokenizeStateLBracketStar: |
| 860 | switch (c) { | ||
| 861 | case 'c': | ||
| 862 | t.state = TokenizeStateLBracketStarC; | ||
| 863 | set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket); | ||
| 864 | break; | ||
| 865 | case ']': | ||
| 866 | set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket); | ||
| 867 | end_token(&t); | ||
| 868 | t.state = TokenizeStateStart; | ||
| 869 | break; | ||
| 870 | default: | ||
| 871 | invalid_char_error(&t, c); | ||
| 872 | } | ||
| 873 | break; | ||
| 874 | case TokenizeStateLBracketStarC: | ||
| 864 | switch (c) { | 875 | switch (c) { |
| 865 | case ']': | 876 | case ']': |
| 866 | end_token(&t); | 877 | end_token(&t); |
| ... | @@ -886,6 +897,9 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -886,6 +897,9 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 886 | break; | 897 | break; |
| 887 | case TokenizeStateSawAmpersand: | 898 | case TokenizeStateSawAmpersand: |
| 888 | switch (c) { | 899 | switch (c) { |
| 900 | case '&': | ||
| 901 | tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND."); | ||
| 902 | break; | ||
| 889 | case '=': | 903 | case '=': |
| 890 | set_token_id(&t, t.cur_tok, TokenIdBitAndEq); | 904 | set_token_id(&t, t.cur_tok, TokenIdBitAndEq); |
| 891 | end_token(&t); | 905 | end_token(&t); |
| ... | @@ -1492,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -1492,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1492 | case TokenizeStateLineStringContinue: | 1506 | case TokenizeStateLineStringContinue: |
| 1493 | case TokenizeStateLineStringContinueC: | 1507 | case TokenizeStateLineStringContinueC: |
| 1494 | case TokenizeStateLBracketStar: | 1508 | case TokenizeStateLBracketStar: |
| 1509 | case TokenizeStateLBracketStarC: | ||
| 1495 | tokenize_error(&t, "unexpected EOF"); | 1510 | tokenize_error(&t, "unexpected EOF"); |
| 1496 | break; | 1511 | break; |
| 1497 | case TokenizeStateLineComment: | 1512 | case TokenizeStateLineComment: |
| ... | @@ -1529,6 +1544,7 @@ const char * token_name(TokenId id) { | ... | @@ -1529,6 +1544,7 @@ const char * token_name(TokenId id) { |
| 1529 | case TokenIdBitShiftRightEq: return ">>="; | 1544 | case TokenIdBitShiftRightEq: return ">>="; |
| 1530 | case TokenIdBitXorEq: return "^="; | 1545 | case TokenIdBitXorEq: return "^="; |
| 1531 | case TokenIdBracketStarBracket: return "[*]"; | 1546 | case TokenIdBracketStarBracket: return "[*]"; |
| 1547 | case TokenIdBracketStarCBracket: return "[*c]"; | ||
| 1532 | case TokenIdCharLiteral: return "CharLiteral"; | 1548 | case TokenIdCharLiteral: return "CharLiteral"; |
| 1533 | case TokenIdCmpEq: return "=="; | 1549 | case TokenIdCmpEq: return "=="; |
| 1534 | case TokenIdCmpGreaterOrEq: return ">="; | 1550 | case TokenIdCmpGreaterOrEq: return ">="; |
| ... | @@ -1588,6 +1604,7 @@ const char * token_name(TokenId id) { | ... | @@ -1588,6 +1604,7 @@ const char * token_name(TokenId id) { |
| 1588 | case TokenIdKeywordStruct: return "struct"; | 1604 | case TokenIdKeywordStruct: return "struct"; |
| 1589 | case TokenIdKeywordSwitch: return "switch"; | 1605 | case TokenIdKeywordSwitch: return "switch"; |
| 1590 | case TokenIdKeywordTest: return "test"; | 1606 | case TokenIdKeywordTest: return "test"; |
| 1607 | case TokenIdKeywordThreadLocal: return "threadlocal"; | ||
| 1591 | case TokenIdKeywordTrue: return "true"; | 1608 | case TokenIdKeywordTrue: return "true"; |
| 1592 | case TokenIdKeywordTry: return "try"; | 1609 | case TokenIdKeywordTry: return "try"; |
| 1593 | case TokenIdKeywordUndefined: return "undefined"; | 1610 | case TokenIdKeywordUndefined: return "undefined"; |
src/tokenizer.hpp+2| ... | @@ -29,6 +29,7 @@ enum TokenId { | ... | @@ -29,6 +29,7 @@ enum TokenId { |
| 29 | TokenIdBitShiftRightEq, | 29 | TokenIdBitShiftRightEq, |
| 30 | TokenIdBitXorEq, | 30 | TokenIdBitXorEq, |
| 31 | TokenIdBracketStarBracket, | 31 | TokenIdBracketStarBracket, |
| 32 | TokenIdBracketStarCBracket, | ||
| 32 | TokenIdCharLiteral, | 33 | TokenIdCharLiteral, |
| 33 | TokenIdCmpEq, | 34 | TokenIdCmpEq, |
| 34 | TokenIdCmpGreaterOrEq, | 35 | TokenIdCmpGreaterOrEq, |
| ... | @@ -88,6 +89,7 @@ enum TokenId { | ... | @@ -88,6 +89,7 @@ enum TokenId { |
| 88 | TokenIdKeywordSuspend, | 89 | TokenIdKeywordSuspend, |
| 89 | TokenIdKeywordSwitch, | 90 | TokenIdKeywordSwitch, |
| 90 | TokenIdKeywordTest, | 91 | TokenIdKeywordTest, |
| 92 | TokenIdKeywordThreadLocal, | ||
| 91 | TokenIdKeywordTrue, | 93 | TokenIdKeywordTrue, |
| 92 | TokenIdKeywordTry, | 94 | TokenIdKeywordTry, |
| 93 | TokenIdKeywordUndefined, | 95 | TokenIdKeywordUndefined, |
src/translate_c.cpp+1226-1173| ... | @@ -4,7 +4,6 @@ | ... | @@ -4,7 +4,6 @@ |
| 4 | * This file is part of zig, which is MIT licensed. | 4 | * This file is part of zig, which is MIT licensed. |
| 5 | * See http://opensource.org/licenses/MIT | 5 | * See http://opensource.org/licenses/MIT |
| 6 | */ | 6 | */ |
| 7 | |||
| 8 | #include "all_types.hpp" | 7 | #include "all_types.hpp" |
| 9 | #include "analyze.hpp" | 8 | #include "analyze.hpp" |
| 10 | #include "c_tokenizer.hpp" | 9 | #include "c_tokenizer.hpp" |
| ... | @@ -13,7 +12,7 @@ | ... | @@ -13,7 +12,7 @@ |
| 13 | #include "os.hpp" | 12 | #include "os.hpp" |
| 14 | #include "translate_c.hpp" | 13 | #include "translate_c.hpp" |
| 15 | #include "parser.hpp" | 14 | #include "parser.hpp" |
| 16 | 15 | #include "zig_clang.h" | |
| 17 | 16 | ||
| 18 | #if __GNUC__ >= 8 | 17 | #if __GNUC__ >= 8 |
| 19 | #pragma GCC diagnostic push | 18 | #pragma GCC diagnostic push |
| ... | @@ -30,8 +29,6 @@ | ... | @@ -30,8 +29,6 @@ |
| 30 | 29 | ||
| 31 | #include <string.h> | 30 | #include <string.h> |
| 32 | 31 | ||
| 33 | using namespace clang; | ||
| 34 | |||
| 35 | struct Alias { | 32 | struct Alias { |
| 36 | Buf *new_name; | 33 | Buf *new_name; |
| 37 | Buf *canon_name; | 34 | Buf *canon_name; |
| ... | @@ -87,13 +84,13 @@ struct Context { | ... | @@ -87,13 +84,13 @@ struct Context { |
| 87 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; | 84 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; |
| 88 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; | 85 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; |
| 89 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; | 86 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; |
| 90 | SourceManager *source_manager; | 87 | ZigClangSourceManager *source_manager; |
| 91 | ZigList<Alias> aliases; | 88 | ZigList<Alias> aliases; |
| 92 | AstNode *source_node; | 89 | AstNode *source_node; |
| 93 | bool warnings_on; | 90 | bool warnings_on; |
| 94 | 91 | ||
| 95 | CodeGen *codegen; | 92 | CodeGen *codegen; |
| 96 | ASTContext *ctx; | 93 | ZigClangASTContext *ctx; |
| 97 | 94 | ||
| 98 | TransScopeRoot *global_scope; | 95 | TransScopeRoot *global_scope; |
| 99 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; | 96 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params; |
| ... | @@ -117,21 +114,37 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren | ... | @@ -117,21 +114,37 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren |
| 117 | 114 | ||
| 118 | static TransScopeBlock *trans_scope_block_find(TransScope *scope); | 115 | static TransScopeBlock *trans_scope_block_find(TransScope *scope); |
| 119 | 116 | ||
| 120 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); | 117 | static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl); |
| 121 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); | 118 | static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl); |
| 122 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); | 119 | static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl); |
| 123 | 120 | ||
| 124 | static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | 121 | static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt, |
| 125 | ResultUsed result_used, TransLRValue lrval, | 122 | ResultUsed result_used, TransLRValue lrval, |
| 126 | AstNode **out_node, TransScope **out_child_scope, | 123 | AstNode **out_node, TransScope **out_child_scope, |
| 127 | TransScope **out_node_scope); | 124 | TransScope **out_node_scope); |
| 128 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); | 125 | static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node); |
| 129 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | 126 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); |
| 130 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | 127 | static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc); |
| 131 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | 128 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval); |
| 129 | |||
| 130 | static ZigClangSourceLocation bitcast(clang::SourceLocation src) { | ||
| 131 | ZigClangSourceLocation dest; | ||
| 132 | memcpy(&dest, &src, sizeof(ZigClangSourceLocation)); | ||
| 133 | return dest; | ||
| 134 | } | ||
| 135 | static ZigClangQualType bitcast(clang::QualType src) { | ||
| 136 | ZigClangQualType dest; | ||
| 137 | memcpy(&dest, &src, sizeof(ZigClangQualType)); | ||
| 138 | return dest; | ||
| 139 | } | ||
| 140 | static clang::QualType bitcast(ZigClangQualType src) { | ||
| 141 | clang::QualType dest; | ||
| 142 | memcpy(&dest, &src, sizeof(ZigClangQualType)); | ||
| 143 | return dest; | ||
| 144 | } | ||
| 132 | 145 | ||
| 133 | ATTRIBUTE_PRINTF(3, 4) | 146 | ATTRIBUTE_PRINTF(3, 4) |
| 134 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | 147 | static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) { |
| 135 | if (!c->warnings_on) { | 148 | if (!c->warnings_on) { |
| 136 | return; | 149 | return; |
| 137 | } | 150 | } |
| ... | @@ -141,16 +154,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma | ... | @@ -141,16 +154,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma |
| 141 | Buf *msg = buf_vprintf(format, ap); | 154 | Buf *msg = buf_vprintf(format, ap); |
| 142 | va_end(ap); | 155 | va_end(ap); |
| 143 | 156 | ||
| 144 | StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl)); | 157 | ZigClangSourceLocation sl = bitcast(clang_sl); |
| 145 | const char *filename_bytes = (const char *)filename.bytes_begin(); | 158 | const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager, |
| 159 | ZigClangSourceManager_getSpellingLoc(c->source_manager, sl)); | ||
| 146 | Buf *path; | 160 | Buf *path; |
| 147 | if (filename_bytes) { | 161 | if (filename_bytes) { |
| 148 | path = buf_create_from_str(filename_bytes); | 162 | path = buf_create_from_str(filename_bytes); |
| 149 | } else { | 163 | } else { |
| 150 | path = buf_sprintf("(no file)"); | 164 | path = buf_sprintf("(no file)"); |
| 151 | } | 165 | } |
| 152 | unsigned line = c->source_manager->getSpellingLineNumber(sl); | 166 | unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl); |
| 153 | unsigned column = c->source_manager->getSpellingColumnNumber(sl); | 167 | unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl); |
| 154 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); | 168 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); |
| 155 | } | 169 | } |
| 156 | 170 | ||
| ... | @@ -291,11 +305,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod | ... | @@ -291,11 +305,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod |
| 291 | node); | 305 | node); |
| 292 | } | 306 | } |
| 293 | 307 | ||
| 308 | static TokenId ptr_len_to_token_id(PtrLen ptr_len) { | ||
| 309 | switch (ptr_len) { | ||
| 310 | case PtrLenSingle: | ||
| 311 | return TokenIdStar; | ||
| 312 | case PtrLenUnknown: | ||
| 313 | return TokenIdBracketStarBracket; | ||
| 314 | case PtrLenC: | ||
| 315 | return TokenIdBracketStarCBracket; | ||
| 316 | } | ||
| 317 | zig_unreachable(); | ||
| 318 | } | ||
| 319 | |||
| 294 | static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) { | 320 | static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) { |
| 295 | AstNode *node = trans_create_node(c, NodeTypePointerType); | 321 | AstNode *node = trans_create_node(c, NodeTypePointerType); |
| 296 | node->data.pointer_type.star_token = allocate<ZigToken>(1); | 322 | node->data.pointer_type.star_token = allocate<ZigToken>(1); |
| 297 | node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket; | 323 | node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len); |
| 298 | node->data.pointer_type.is_const = is_const; | ||
| 299 | node->data.pointer_type.is_const = is_const; | 324 | node->data.pointer_type.is_const = is_const; |
| 300 | node->data.pointer_type.is_volatile = is_volatile; | 325 | node->data.pointer_type.is_volatile = is_volatile; |
| 301 | node->data.pointer_type.op_expr = child_node; | 326 | node->data.pointer_type.op_expr = child_node; |
| ... | @@ -460,15 +485,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) { | ... | @@ -460,15 +485,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) { |
| 460 | return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size()); | 485 | return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size()); |
| 461 | } | 486 | } |
| 462 | 487 | ||
| 463 | static const char *decl_name(const Decl *decl) { | 488 | static const char *decl_name(const clang::Decl *decl) { |
| 464 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | 489 | const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl); |
| 465 | return (const char *)named_decl->getName().bytes_begin(); | 490 | return (const char *)named_decl->getName().bytes_begin(); |
| 466 | } | 491 | } |
| 467 | 492 | ||
| 468 | static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { | 493 | static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { |
| 469 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | 494 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); |
| 470 | node->data.int_literal.bigint = allocate<BigInt>(1); | 495 | node->data.int_literal.bigint = allocate<BigInt>(1); |
| 471 | bool is_negative = aps_int.isNegative(); | 496 | bool is_negative = aps_int.isSigned() && aps_int.isNegative(); |
| 472 | if (!is_negative) { | 497 | if (!is_negative) { |
| 473 | bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false); | 498 | bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false); |
| 474 | return node; | 499 | return node; |
| ... | @@ -479,41 +504,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) | ... | @@ -479,41 +504,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 479 | 504 | ||
| 480 | } | 505 | } |
| 481 | 506 | ||
| 482 | static const Type *qual_type_canon(QualType qt) { | 507 | static const clang::Type *qual_type_canon(clang::QualType qt) { |
| 483 | return qt.getCanonicalType().getTypePtr(); | 508 | return qt.getCanonicalType().getTypePtr(); |
| 484 | } | 509 | } |
| 485 | 510 | ||
| 486 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { | 511 | static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) { |
| 487 | // String literals in C are `char *` but they should really be `const char *`. | 512 | // String literals in C are `char *` but they should really be `const char *`. |
| 488 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | 513 | if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { |
| 489 | const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr); | 514 | const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr); |
| 490 | if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) { | 515 | if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) { |
| 491 | const Expr *sub_expr = cast_expr->getSubExpr(); | 516 | const clang::Expr *sub_expr = cast_expr->getSubExpr(); |
| 492 | if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) { | 517 | if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) { |
| 493 | QualType array_qt = sub_expr->getType(); | 518 | clang::QualType array_qt = sub_expr->getType(); |
| 494 | const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr()); | 519 | const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr()); |
| 495 | QualType pointee_qt = array_type->getElementType(); | 520 | clang::QualType pointee_qt = array_type->getElementType(); |
| 496 | pointee_qt.addConst(); | 521 | pointee_qt.addConst(); |
| 497 | return c->ctx->getPointerType(pointee_qt); | 522 | return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt))); |
| 498 | } | 523 | } |
| 499 | } | 524 | } |
| 500 | } | 525 | } |
| 501 | return expr->getType(); | 526 | return expr->getType(); |
| 502 | } | 527 | } |
| 503 | 528 | ||
| 504 | static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) { | 529 | static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) { |
| 505 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | 530 | if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { |
| 506 | const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr); | 531 | const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr); |
| 507 | return get_expr_qual_type(c, cast_expr->getSubExpr()); | 532 | return get_expr_qual_type(c, cast_expr->getSubExpr()); |
| 508 | } | 533 | } |
| 509 | return expr->getType(); | 534 | return expr->getType(); |
| 510 | } | 535 | } |
| 511 | 536 | ||
| 512 | static AstNode *get_expr_type(Context *c, const Expr *expr) { | 537 | static AstNode *get_expr_type(Context *c, const clang::Expr *expr) { |
| 513 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); | 538 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); |
| 514 | } | 539 | } |
| 515 | 540 | ||
| 516 | static bool qual_types_equal(QualType t1, QualType t2) { | 541 | static bool qual_types_equal(clang::QualType t1, clang::QualType t2) { |
| 517 | if (t1.isConstQualified() != t2.isConstQualified()) { | 542 | if (t1.isConstQualified() != t2.isConstQualified()) { |
| 518 | return false; | 543 | return false; |
| 519 | } | 544 | } |
| ... | @@ -530,37 +555,37 @@ static bool is_c_void_type(AstNode *node) { | ... | @@ -530,37 +555,37 @@ static bool is_c_void_type(AstNode *node) { |
| 530 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | 555 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 531 | } | 556 | } |
| 532 | 557 | ||
| 533 | static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) { | 558 | static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) { |
| 534 | QualType t1 = get_expr_qual_type(c, expr1); | 559 | clang::QualType t1 = get_expr_qual_type(c, expr1); |
| 535 | QualType t2 = get_expr_qual_type(c, expr2); | 560 | clang::QualType t2 = get_expr_qual_type(c, expr2); |
| 536 | 561 | ||
| 537 | return qual_types_equal(t1, t2); | 562 | return qual_types_equal(t1, t2); |
| 538 | } | 563 | } |
| 539 | 564 | ||
| 540 | static bool qual_type_is_ptr(QualType qt) { | 565 | static bool qual_type_is_ptr(clang::QualType qt) { |
| 541 | const Type *ty = qual_type_canon(qt); | 566 | const clang::Type *ty = qual_type_canon(qt); |
| 542 | return ty->getTypeClass() == Type::Pointer; | 567 | return ty->getTypeClass() == clang::Type::Pointer; |
| 543 | } | 568 | } |
| 544 | 569 | ||
| 545 | static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) { | 570 | static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) { |
| 546 | const Type *ty = qual_type_canon(qt); | 571 | const clang::Type *ty = qual_type_canon(qt); |
| 547 | *is_ptr = false; | 572 | *is_ptr = false; |
| 548 | 573 | ||
| 549 | if (ty->getTypeClass() == Type::Pointer) { | 574 | if (ty->getTypeClass() == clang::Type::Pointer) { |
| 550 | *is_ptr = true; | 575 | *is_ptr = true; |
| 551 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | 576 | const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty); |
| 552 | QualType child_qt = pointer_ty->getPointeeType(); | 577 | clang::QualType child_qt = pointer_ty->getPointeeType(); |
| 553 | ty = child_qt.getTypePtr(); | 578 | ty = child_qt.getTypePtr(); |
| 554 | } | 579 | } |
| 555 | 580 | ||
| 556 | if (ty->getTypeClass() == Type::FunctionProto) { | 581 | if (ty->getTypeClass() == clang::Type::FunctionProto) { |
| 557 | return static_cast<const FunctionProtoType*>(ty); | 582 | return static_cast<const clang::FunctionProtoType*>(ty); |
| 558 | } | 583 | } |
| 559 | 584 | ||
| 560 | return nullptr; | 585 | return nullptr; |
| 561 | } | 586 | } |
| 562 | 587 | ||
| 563 | static bool qual_type_is_fn_ptr(QualType qt) { | 588 | static bool qual_type_is_fn_ptr(clang::QualType qt) { |
| 564 | bool is_ptr; | 589 | bool is_ptr; |
| 565 | if (qual_type_get_fn_proto(qt, &is_ptr)) { | 590 | if (qual_type_get_fn_proto(qt, &is_ptr)) { |
| 566 | return is_ptr; | 591 | return is_ptr; |
| ... | @@ -569,30 +594,30 @@ static bool qual_type_is_fn_ptr(QualType qt) { | ... | @@ -569,30 +594,30 @@ static bool qual_type_is_fn_ptr(QualType qt) { |
| 569 | return false; | 594 | return false; |
| 570 | } | 595 | } |
| 571 | 596 | ||
| 572 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { | 597 | static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) { |
| 573 | const Type *ty = qt.getTypePtr(); | 598 | const clang::Type *ty = qt.getTypePtr(); |
| 574 | switch (ty->getTypeClass()) { | 599 | switch (ty->getTypeClass()) { |
| 575 | case Type::Builtin: | 600 | case clang::Type::Builtin: |
| 576 | { | 601 | { |
| 577 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | 602 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); |
| 578 | switch (builtin_ty->getKind()) { | 603 | switch (builtin_ty->getKind()) { |
| 579 | case BuiltinType::Char_U: | 604 | case clang::BuiltinType::Char_U: |
| 580 | case BuiltinType::UChar: | 605 | case clang::BuiltinType::UChar: |
| 581 | case BuiltinType::Char_S: | 606 | case clang::BuiltinType::Char_S: |
| 582 | case BuiltinType::SChar: | 607 | case clang::BuiltinType::SChar: |
| 583 | return 8; | 608 | return 8; |
| 584 | case BuiltinType::UInt128: | 609 | case clang::BuiltinType::UInt128: |
| 585 | case BuiltinType::Int128: | 610 | case clang::BuiltinType::Int128: |
| 586 | return 128; | 611 | return 128; |
| 587 | default: | 612 | default: |
| 588 | return 0; | 613 | return 0; |
| 589 | } | 614 | } |
| 590 | zig_unreachable(); | 615 | zig_unreachable(); |
| 591 | } | 616 | } |
| 592 | case Type::Typedef: | 617 | case clang::Type::Typedef: |
| 593 | { | 618 | { |
| 594 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 619 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); |
| 595 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 620 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 596 | const char *type_name = decl_name(typedef_decl); | 621 | const char *type_name = decl_name(typedef_decl); |
| 597 | if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) { | 622 | if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) { |
| 598 | return 8; | 623 | return 8; |
| ... | @@ -613,8 +638,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So | ... | @@ -613,8 +638,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So |
| 613 | } | 638 | } |
| 614 | 639 | ||
| 615 | 640 | ||
| 616 | static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, | 641 | static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt, |
| 617 | const SourceLocation &source_loc) | 642 | const clang::SourceLocation &source_loc) |
| 618 | { | 643 | { |
| 619 | uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc); | 644 | uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc); |
| 620 | if (int_bit_width != 0) { | 645 | if (int_bit_width != 0) { |
| ... | @@ -632,7 +657,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, | ... | @@ -632,7 +657,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| 632 | // FieldAccess | 657 | // FieldAccess |
| 633 | // FnCall (.builtin = true) | 658 | // FnCall (.builtin = true) |
| 634 | // Symbol "import" | 659 | // Symbol "import" |
| 635 | // StringLiteral "std" | 660 | // clang::StringLiteral "std" |
| 636 | // Symbol "math" | 661 | // Symbol "math" |
| 637 | // Symbol "Log2Int" | 662 | // Symbol "Log2Int" |
| 638 | // zig_type_node | 663 | // zig_type_node |
| ... | @@ -646,21 +671,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, | ... | @@ -646,21 +671,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt, |
| 646 | return log2int_fn_call; | 671 | return log2int_fn_call; |
| 647 | } | 672 | } |
| 648 | 673 | ||
| 649 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | 674 | static bool qual_type_child_is_fn_proto(const clang::QualType &qt) { |
| 650 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | 675 | if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) { |
| 651 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | 676 | const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr()); |
| 652 | if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) { | 677 | if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) { |
| 653 | return true; | 678 | return true; |
| 654 | } | 679 | } |
| 655 | } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) { | 680 | } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) { |
| 656 | const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr()); | 681 | const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr()); |
| 657 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); | 682 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); |
| 658 | } | 683 | } |
| 659 | return false; | 684 | return false; |
| 660 | } | 685 | } |
| 661 | 686 | ||
| 662 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type, | 687 | static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type, |
| 663 | QualType src_type, AstNode *expr) | 688 | clang::QualType src_type, AstNode *expr) |
| 664 | { | 689 | { |
| 665 | if (qual_types_equal(dest_type, src_type)) { | 690 | if (qual_types_equal(dest_type, src_type)) { |
| 666 | return expr; | 691 | return expr; |
| ... | @@ -677,72 +702,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, | ... | @@ -677,72 +702,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, |
| 677 | return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); | 702 | return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); |
| 678 | } | 703 | } |
| 679 | 704 | ||
| 680 | static bool c_is_signed_integer(Context *c, QualType qt) { | 705 | static bool c_is_signed_integer(Context *c, clang::QualType qt) { |
| 681 | const Type *c_type = qual_type_canon(qt); | 706 | const clang::Type *c_type = qual_type_canon(qt); |
| 682 | if (c_type->getTypeClass() != Type::Builtin) | 707 | if (c_type->getTypeClass() != clang::Type::Builtin) |
| 683 | return false; | 708 | return false; |
| 684 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 709 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); |
| 685 | switch (builtin_ty->getKind()) { | 710 | switch (builtin_ty->getKind()) { |
| 686 | case BuiltinType::SChar: | 711 | case clang::BuiltinType::SChar: |
| 687 | case BuiltinType::Short: | 712 | case clang::BuiltinType::Short: |
| 688 | case BuiltinType::Int: | 713 | case clang::BuiltinType::Int: |
| 689 | case BuiltinType::Long: | 714 | case clang::BuiltinType::Long: |
| 690 | case BuiltinType::LongLong: | 715 | case clang::BuiltinType::LongLong: |
| 691 | case BuiltinType::Int128: | 716 | case clang::BuiltinType::Int128: |
| 692 | case BuiltinType::WChar_S: | 717 | case clang::BuiltinType::WChar_S: |
| 693 | return true; | 718 | return true; |
| 694 | default: | 719 | default: |
| 695 | return false; | 720 | return false; |
| 696 | } | 721 | } |
| 697 | } | 722 | } |
| 698 | 723 | ||
| 699 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | 724 | static bool c_is_unsigned_integer(Context *c, clang::QualType qt) { |
| 700 | const Type *c_type = qual_type_canon(qt); | 725 | const clang::Type *c_type = qual_type_canon(qt); |
| 701 | if (c_type->getTypeClass() != Type::Builtin) | 726 | if (c_type->getTypeClass() != clang::Type::Builtin) |
| 702 | return false; | 727 | return false; |
| 703 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 728 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); |
| 704 | switch (builtin_ty->getKind()) { | 729 | switch (builtin_ty->getKind()) { |
| 705 | case BuiltinType::Char_U: | 730 | case clang::BuiltinType::Char_U: |
| 706 | case BuiltinType::UChar: | 731 | case clang::BuiltinType::UChar: |
| 707 | case BuiltinType::Char_S: | 732 | case clang::BuiltinType::Char_S: |
| 708 | case BuiltinType::UShort: | 733 | case clang::BuiltinType::UShort: |
| 709 | case BuiltinType::UInt: | 734 | case clang::BuiltinType::UInt: |
| 710 | case BuiltinType::ULong: | 735 | case clang::BuiltinType::ULong: |
| 711 | case BuiltinType::ULongLong: | 736 | case clang::BuiltinType::ULongLong: |
| 712 | case BuiltinType::UInt128: | 737 | case clang::BuiltinType::UInt128: |
| 713 | case BuiltinType::WChar_U: | 738 | case clang::BuiltinType::WChar_U: |
| 714 | return true; | 739 | return true; |
| 715 | default: | 740 | default: |
| 716 | return false; | 741 | return false; |
| 717 | } | 742 | } |
| 718 | } | 743 | } |
| 719 | 744 | ||
| 720 | static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) { | 745 | static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) { |
| 721 | const Type *c_type = qual_type_canon(qt); | 746 | const clang::Type *c_type = qual_type_canon(qt); |
| 722 | if (c_type->getTypeClass() != Type::Builtin) | 747 | if (c_type->getTypeClass() != clang::Type::Builtin) |
| 723 | return false; | 748 | return false; |
| 724 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 749 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); |
| 725 | return builtin_ty->getKind() == kind; | 750 | return builtin_ty->getKind() == kind; |
| 726 | } | 751 | } |
| 727 | 752 | ||
| 728 | static bool c_is_float(Context *c, QualType qt) { | 753 | static bool c_is_float(Context *c, clang::QualType qt) { |
| 729 | const Type *c_type = qt.getTypePtr(); | 754 | const clang::Type *c_type = qt.getTypePtr(); |
| 730 | if (c_type->getTypeClass() != Type::Builtin) | 755 | if (c_type->getTypeClass() != clang::Type::Builtin) |
| 731 | return false; | 756 | return false; |
| 732 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 757 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type); |
| 733 | switch (builtin_ty->getKind()) { | 758 | switch (builtin_ty->getKind()) { |
| 734 | case BuiltinType::Half: | 759 | case clang::BuiltinType::Half: |
| 735 | case BuiltinType::Float: | 760 | case clang::BuiltinType::Float: |
| 736 | case BuiltinType::Double: | 761 | case clang::BuiltinType::Double: |
| 737 | case BuiltinType::Float128: | 762 | case clang::BuiltinType::Float128: |
| 738 | case BuiltinType::LongDouble: | 763 | case clang::BuiltinType::LongDouble: |
| 739 | return true; | 764 | return true; |
| 740 | default: | 765 | default: |
| 741 | return false; | 766 | return false; |
| 742 | } | 767 | } |
| 743 | } | 768 | } |
| 744 | 769 | ||
| 745 | static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { | 770 | static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) { |
| 746 | if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) { | 771 | if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) { |
| 747 | // float and signed integer overflow is undefined behavior. | 772 | // float and signed integer overflow is undefined behavior. |
| 748 | return false; | 773 | return false; |
| ... | @@ -752,23 +777,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { | ... | @@ -752,23 +777,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) { |
| 752 | } | 777 | } |
| 753 | } | 778 | } |
| 754 | 779 | ||
| 755 | static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) { | 780 | static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { |
| 756 | switch (ty->getTypeClass()) { | 781 | switch (ty->getTypeClass()) { |
| 757 | case Type::Builtin: { | 782 | case clang::Type::Builtin: { |
| 758 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | 783 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); |
| 759 | return builtin_ty->getKind() == BuiltinType::Void; | 784 | return builtin_ty->getKind() == clang::BuiltinType::Void; |
| 760 | } | 785 | } |
| 761 | case Type::Record: { | 786 | case clang::Type::Record: { |
| 762 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | 787 | const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty); |
| 763 | return record_ty->getDecl()->getDefinition() == nullptr; | 788 | return record_ty->getDecl()->getDefinition() == nullptr; |
| 764 | } | 789 | } |
| 765 | case Type::Elaborated: { | 790 | case clang::Type::Elaborated: { |
| 766 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | 791 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); |
| 767 | return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc); | 792 | return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc); |
| 768 | } | 793 | } |
| 769 | case Type::Typedef: { | 794 | case clang::Type::Typedef: { |
| 770 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 795 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); |
| 771 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 796 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 772 | return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc); | 797 | return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc); |
| 773 | } | 798 | } |
| 774 | default: | 799 | default: |
| ... | @@ -776,145 +801,145 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -776,145 +801,145 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou |
| 776 | } | 801 | } |
| 777 | } | 802 | } |
| 778 | 803 | ||
| 779 | static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) { | 804 | static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) { |
| 780 | switch (ty->getTypeClass()) { | 805 | switch (ty->getTypeClass()) { |
| 781 | case Type::Builtin: | 806 | case clang::Type::Builtin: |
| 782 | { | 807 | { |
| 783 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | 808 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); |
| 784 | switch (builtin_ty->getKind()) { | 809 | switch (builtin_ty->getKind()) { |
| 785 | case BuiltinType::Void: | 810 | case clang::BuiltinType::Void: |
| 786 | return trans_create_node_symbol_str(c, "c_void"); | 811 | return trans_create_node_symbol_str(c, "c_void"); |
| 787 | case BuiltinType::Bool: | 812 | case clang::BuiltinType::Bool: |
| 788 | return trans_create_node_symbol_str(c, "bool"); | 813 | return trans_create_node_symbol_str(c, "bool"); |
| 789 | case BuiltinType::Char_U: | 814 | case clang::BuiltinType::Char_U: |
| 790 | case BuiltinType::UChar: | 815 | case clang::BuiltinType::UChar: |
| 791 | case BuiltinType::Char_S: | 816 | case clang::BuiltinType::Char_S: |
| 792 | case BuiltinType::Char8: | 817 | case clang::BuiltinType::Char8: |
| 793 | return trans_create_node_symbol_str(c, "u8"); | 818 | return trans_create_node_symbol_str(c, "u8"); |
| 794 | case BuiltinType::SChar: | 819 | case clang::BuiltinType::SChar: |
| 795 | return trans_create_node_symbol_str(c, "i8"); | 820 | return trans_create_node_symbol_str(c, "i8"); |
| 796 | case BuiltinType::UShort: | 821 | case clang::BuiltinType::UShort: |
| 797 | return trans_create_node_symbol_str(c, "c_ushort"); | 822 | return trans_create_node_symbol_str(c, "c_ushort"); |
| 798 | case BuiltinType::UInt: | 823 | case clang::BuiltinType::UInt: |
| 799 | return trans_create_node_symbol_str(c, "c_uint"); | 824 | return trans_create_node_symbol_str(c, "c_uint"); |
| 800 | case BuiltinType::ULong: | 825 | case clang::BuiltinType::ULong: |
| 801 | return trans_create_node_symbol_str(c, "c_ulong"); | 826 | return trans_create_node_symbol_str(c, "c_ulong"); |
| 802 | case BuiltinType::ULongLong: | 827 | case clang::BuiltinType::ULongLong: |
| 803 | return trans_create_node_symbol_str(c, "c_ulonglong"); | 828 | return trans_create_node_symbol_str(c, "c_ulonglong"); |
| 804 | case BuiltinType::Short: | 829 | case clang::BuiltinType::Short: |
| 805 | return trans_create_node_symbol_str(c, "c_short"); | 830 | return trans_create_node_symbol_str(c, "c_short"); |
| 806 | case BuiltinType::Int: | 831 | case clang::BuiltinType::Int: |
| 807 | return trans_create_node_symbol_str(c, "c_int"); | 832 | return trans_create_node_symbol_str(c, "c_int"); |
| 808 | case BuiltinType::Long: | 833 | case clang::BuiltinType::Long: |
| 809 | return trans_create_node_symbol_str(c, "c_long"); | 834 | return trans_create_node_symbol_str(c, "c_long"); |
| 810 | case BuiltinType::LongLong: | 835 | case clang::BuiltinType::LongLong: |
| 811 | return trans_create_node_symbol_str(c, "c_longlong"); | 836 | return trans_create_node_symbol_str(c, "c_longlong"); |
| 812 | case BuiltinType::UInt128: | 837 | case clang::BuiltinType::UInt128: |
| 813 | return trans_create_node_symbol_str(c, "u128"); | 838 | return trans_create_node_symbol_str(c, "u128"); |
| 814 | case BuiltinType::Int128: | 839 | case clang::BuiltinType::Int128: |
| 815 | return trans_create_node_symbol_str(c, "i128"); | 840 | return trans_create_node_symbol_str(c, "i128"); |
| 816 | case BuiltinType::Float: | 841 | case clang::BuiltinType::Float: |
| 817 | return trans_create_node_symbol_str(c, "f32"); | 842 | return trans_create_node_symbol_str(c, "f32"); |
| 818 | case BuiltinType::Double: | 843 | case clang::BuiltinType::Double: |
| 819 | return trans_create_node_symbol_str(c, "f64"); | 844 | return trans_create_node_symbol_str(c, "f64"); |
| 820 | case BuiltinType::Float128: | 845 | case clang::BuiltinType::Float128: |
| 821 | return trans_create_node_symbol_str(c, "f128"); | 846 | return trans_create_node_symbol_str(c, "f128"); |
| 822 | case BuiltinType::Float16: | 847 | case clang::BuiltinType::Float16: |
| 823 | return trans_create_node_symbol_str(c, "f16"); | 848 | return trans_create_node_symbol_str(c, "f16"); |
| 824 | case BuiltinType::LongDouble: | 849 | case clang::BuiltinType::LongDouble: |
| 825 | return trans_create_node_symbol_str(c, "c_longdouble"); | 850 | return trans_create_node_symbol_str(c, "c_longdouble"); |
| 826 | case BuiltinType::WChar_U: | 851 | case clang::BuiltinType::WChar_U: |
| 827 | case BuiltinType::Char16: | 852 | case clang::BuiltinType::Char16: |
| 828 | case BuiltinType::Char32: | 853 | case clang::BuiltinType::Char32: |
| 829 | case BuiltinType::WChar_S: | 854 | case clang::BuiltinType::WChar_S: |
| 830 | case BuiltinType::Half: | 855 | case clang::BuiltinType::Half: |
| 831 | case BuiltinType::NullPtr: | 856 | case clang::BuiltinType::NullPtr: |
| 832 | case BuiltinType::ObjCId: | 857 | case clang::BuiltinType::ObjCId: |
| 833 | case BuiltinType::ObjCClass: | 858 | case clang::BuiltinType::ObjCClass: |
| 834 | case BuiltinType::ObjCSel: | 859 | case clang::BuiltinType::ObjCSel: |
| 835 | case BuiltinType::OMPArraySection: | 860 | case clang::BuiltinType::OMPArraySection: |
| 836 | case BuiltinType::Dependent: | 861 | case clang::BuiltinType::Dependent: |
| 837 | case BuiltinType::Overload: | 862 | case clang::BuiltinType::Overload: |
| 838 | case BuiltinType::BoundMember: | 863 | case clang::BuiltinType::BoundMember: |
| 839 | case BuiltinType::PseudoObject: | 864 | case clang::BuiltinType::PseudoObject: |
| 840 | case BuiltinType::UnknownAny: | 865 | case clang::BuiltinType::UnknownAny: |
| 841 | case BuiltinType::BuiltinFn: | 866 | case clang::BuiltinType::BuiltinFn: |
| 842 | case BuiltinType::ARCUnbridgedCast: | 867 | case clang::BuiltinType::ARCUnbridgedCast: |
| 843 | case BuiltinType::ShortAccum: | 868 | case clang::BuiltinType::ShortAccum: |
| 844 | case BuiltinType::Accum: | 869 | case clang::BuiltinType::Accum: |
| 845 | case BuiltinType::LongAccum: | 870 | case clang::BuiltinType::LongAccum: |
| 846 | case BuiltinType::UShortAccum: | 871 | case clang::BuiltinType::UShortAccum: |
| 847 | case BuiltinType::UAccum: | 872 | case clang::BuiltinType::UAccum: |
| 848 | case BuiltinType::ULongAccum: | 873 | case clang::BuiltinType::ULongAccum: |
| 849 | 874 | ||
| 850 | case BuiltinType::OCLImage1dRO: | 875 | case clang::BuiltinType::OCLImage1dRO: |
| 851 | case BuiltinType::OCLImage1dArrayRO: | 876 | case clang::BuiltinType::OCLImage1dArrayRO: |
| 852 | case BuiltinType::OCLImage1dBufferRO: | 877 | case clang::BuiltinType::OCLImage1dBufferRO: |
| 853 | case BuiltinType::OCLImage2dRO: | 878 | case clang::BuiltinType::OCLImage2dRO: |
| 854 | case BuiltinType::OCLImage2dArrayRO: | 879 | case clang::BuiltinType::OCLImage2dArrayRO: |
| 855 | case BuiltinType::OCLImage2dDepthRO: | 880 | case clang::BuiltinType::OCLImage2dDepthRO: |
| 856 | case BuiltinType::OCLImage2dArrayDepthRO: | 881 | case clang::BuiltinType::OCLImage2dArrayDepthRO: |
| 857 | case BuiltinType::OCLImage2dMSAARO: | 882 | case clang::BuiltinType::OCLImage2dMSAARO: |
| 858 | case BuiltinType::OCLImage2dArrayMSAARO: | 883 | case clang::BuiltinType::OCLImage2dArrayMSAARO: |
| 859 | case BuiltinType::OCLImage2dMSAADepthRO: | 884 | case clang::BuiltinType::OCLImage2dMSAADepthRO: |
| 860 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | 885 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRO: |
| 861 | case BuiltinType::OCLImage3dRO: | 886 | case clang::BuiltinType::OCLImage3dRO: |
| 862 | case BuiltinType::OCLImage1dWO: | 887 | case clang::BuiltinType::OCLImage1dWO: |
| 863 | case BuiltinType::OCLImage1dArrayWO: | 888 | case clang::BuiltinType::OCLImage1dArrayWO: |
| 864 | case BuiltinType::OCLImage1dBufferWO: | 889 | case clang::BuiltinType::OCLImage1dBufferWO: |
| 865 | case BuiltinType::OCLImage2dWO: | 890 | case clang::BuiltinType::OCLImage2dWO: |
| 866 | case BuiltinType::OCLImage2dArrayWO: | 891 | case clang::BuiltinType::OCLImage2dArrayWO: |
| 867 | case BuiltinType::OCLImage2dDepthWO: | 892 | case clang::BuiltinType::OCLImage2dDepthWO: |
| 868 | case BuiltinType::OCLImage2dArrayDepthWO: | 893 | case clang::BuiltinType::OCLImage2dArrayDepthWO: |
| 869 | case BuiltinType::OCLImage2dMSAAWO: | 894 | case clang::BuiltinType::OCLImage2dMSAAWO: |
| 870 | case BuiltinType::OCLImage2dArrayMSAAWO: | 895 | case clang::BuiltinType::OCLImage2dArrayMSAAWO: |
| 871 | case BuiltinType::OCLImage2dMSAADepthWO: | 896 | case clang::BuiltinType::OCLImage2dMSAADepthWO: |
| 872 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | 897 | case clang::BuiltinType::OCLImage2dArrayMSAADepthWO: |
| 873 | case BuiltinType::OCLImage3dWO: | 898 | case clang::BuiltinType::OCLImage3dWO: |
| 874 | case BuiltinType::OCLImage1dRW: | 899 | case clang::BuiltinType::OCLImage1dRW: |
| 875 | case BuiltinType::OCLImage1dArrayRW: | 900 | case clang::BuiltinType::OCLImage1dArrayRW: |
| 876 | case BuiltinType::OCLImage1dBufferRW: | 901 | case clang::BuiltinType::OCLImage1dBufferRW: |
| 877 | case BuiltinType::OCLImage2dRW: | 902 | case clang::BuiltinType::OCLImage2dRW: |
| 878 | case BuiltinType::OCLImage2dArrayRW: | 903 | case clang::BuiltinType::OCLImage2dArrayRW: |
| 879 | case BuiltinType::OCLImage2dDepthRW: | 904 | case clang::BuiltinType::OCLImage2dDepthRW: |
| 880 | case BuiltinType::OCLImage2dArrayDepthRW: | 905 | case clang::BuiltinType::OCLImage2dArrayDepthRW: |
| 881 | case BuiltinType::OCLImage2dMSAARW: | 906 | case clang::BuiltinType::OCLImage2dMSAARW: |
| 882 | case BuiltinType::OCLImage2dArrayMSAARW: | 907 | case clang::BuiltinType::OCLImage2dArrayMSAARW: |
| 883 | case BuiltinType::OCLImage2dMSAADepthRW: | 908 | case clang::BuiltinType::OCLImage2dMSAADepthRW: |
| 884 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | 909 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRW: |
| 885 | case BuiltinType::OCLImage3dRW: | 910 | case clang::BuiltinType::OCLImage3dRW: |
| 886 | case BuiltinType::OCLSampler: | 911 | case clang::BuiltinType::OCLSampler: |
| 887 | case BuiltinType::OCLEvent: | 912 | case clang::BuiltinType::OCLEvent: |
| 888 | case BuiltinType::OCLClkEvent: | 913 | case clang::BuiltinType::OCLClkEvent: |
| 889 | case BuiltinType::OCLQueue: | 914 | case clang::BuiltinType::OCLQueue: |
| 890 | case BuiltinType::OCLReserveID: | 915 | case clang::BuiltinType::OCLReserveID: |
| 891 | case BuiltinType::ShortFract: | 916 | case clang::BuiltinType::ShortFract: |
| 892 | case BuiltinType::Fract: | 917 | case clang::BuiltinType::Fract: |
| 893 | case BuiltinType::LongFract: | 918 | case clang::BuiltinType::LongFract: |
| 894 | case BuiltinType::UShortFract: | 919 | case clang::BuiltinType::UShortFract: |
| 895 | case BuiltinType::UFract: | 920 | case clang::BuiltinType::UFract: |
| 896 | case BuiltinType::ULongFract: | 921 | case clang::BuiltinType::ULongFract: |
| 897 | case BuiltinType::SatShortAccum: | 922 | case clang::BuiltinType::SatShortAccum: |
| 898 | case BuiltinType::SatAccum: | 923 | case clang::BuiltinType::SatAccum: |
| 899 | case BuiltinType::SatLongAccum: | 924 | case clang::BuiltinType::SatLongAccum: |
| 900 | case BuiltinType::SatUShortAccum: | 925 | case clang::BuiltinType::SatUShortAccum: |
| 901 | case BuiltinType::SatUAccum: | 926 | case clang::BuiltinType::SatUAccum: |
| 902 | case BuiltinType::SatULongAccum: | 927 | case clang::BuiltinType::SatULongAccum: |
| 903 | case BuiltinType::SatShortFract: | 928 | case clang::BuiltinType::SatShortFract: |
| 904 | case BuiltinType::SatFract: | 929 | case clang::BuiltinType::SatFract: |
| 905 | case BuiltinType::SatLongFract: | 930 | case clang::BuiltinType::SatLongFract: |
| 906 | case BuiltinType::SatUShortFract: | 931 | case clang::BuiltinType::SatUShortFract: |
| 907 | case BuiltinType::SatUFract: | 932 | case clang::BuiltinType::SatUFract: |
| 908 | case BuiltinType::SatULongFract: | 933 | case clang::BuiltinType::SatULongFract: |
| 909 | emit_warning(c, source_loc, "unsupported builtin type"); | 934 | emit_warning(c, source_loc, "unsupported builtin type"); |
| 910 | return nullptr; | 935 | return nullptr; |
| 911 | } | 936 | } |
| 912 | break; | 937 | break; |
| 913 | } | 938 | } |
| 914 | case Type::Pointer: | 939 | case clang::Type::Pointer: |
| 915 | { | 940 | { |
| 916 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | 941 | const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty); |
| 917 | QualType child_qt = pointer_ty->getPointeeType(); | 942 | clang::QualType child_qt = pointer_ty->getPointeeType(); |
| 918 | AstNode *child_node = trans_qual_type(c, child_qt, source_loc); | 943 | AstNode *child_node = trans_qual_type(c, child_qt, source_loc); |
| 919 | if (child_node == nullptr) { | 944 | if (child_node == nullptr) { |
| 920 | emit_warning(c, source_loc, "pointer to unsupported type"); | 945 | emit_warning(c, source_loc, "pointer to unsupported type"); |
| ... | @@ -925,90 +950,93 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -925,90 +950,93 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 925 | return trans_create_node_prefix_op(c, PrefixOpOptional, child_node); | 950 | return trans_create_node_prefix_op(c, PrefixOpOptional, child_node); |
| 926 | } | 951 | } |
| 927 | 952 | ||
| 928 | PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown; | 953 | if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) { |
| 929 | 954 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | |
| 930 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | 955 | child_qt.isVolatileQualified(), child_node, PtrLenSingle); |
| 931 | child_qt.isVolatileQualified(), child_node, ptr_len); | 956 | return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node); |
| 932 | return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node); | 957 | } else { |
| 958 | return trans_create_node_ptr_type(c, child_qt.isConstQualified(), | ||
| 959 | child_qt.isVolatileQualified(), child_node, PtrLenC); | ||
| 960 | } | ||
| 933 | } | 961 | } |
| 934 | case Type::Typedef: | 962 | case clang::Type::Typedef: |
| 935 | { | 963 | { |
| 936 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 964 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); |
| 937 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 965 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 938 | return resolve_typedef_decl(c, typedef_decl); | 966 | return resolve_typedef_decl(c, typedef_decl); |
| 939 | } | 967 | } |
| 940 | case Type::Elaborated: | 968 | case clang::Type::Elaborated: |
| 941 | { | 969 | { |
| 942 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | 970 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); |
| 943 | switch (elaborated_ty->getKeyword()) { | 971 | switch (elaborated_ty->getKeyword()) { |
| 944 | case ETK_Struct: | 972 | case clang::ETK_Struct: |
| 945 | case ETK_Enum: | 973 | case clang::ETK_Enum: |
| 946 | case ETK_Union: | 974 | case clang::ETK_Union: |
| 947 | return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc); | 975 | return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc); |
| 948 | case ETK_Interface: | 976 | case clang::ETK_Interface: |
| 949 | case ETK_Class: | 977 | case clang::ETK_Class: |
| 950 | case ETK_Typename: | 978 | case clang::ETK_Typename: |
| 951 | case ETK_None: | 979 | case clang::ETK_None: |
| 952 | emit_warning(c, source_loc, "unsupported elaborated type"); | 980 | emit_warning(c, source_loc, "unsupported elaborated type"); |
| 953 | return nullptr; | 981 | return nullptr; |
| 954 | } | 982 | } |
| 955 | } | 983 | } |
| 956 | case Type::FunctionProto: | 984 | case clang::Type::FunctionProto: |
| 957 | { | 985 | { |
| 958 | const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty); | 986 | const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty); |
| 959 | 987 | ||
| 960 | AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); | 988 | AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); |
| 961 | switch (fn_proto_ty->getCallConv()) { | 989 | switch (fn_proto_ty->getCallConv()) { |
| 962 | case CC_C: // __attribute__((cdecl)) | 990 | case clang::CC_C: // __attribute__((cdecl)) |
| 963 | proto_node->data.fn_proto.cc = CallingConventionC; | 991 | proto_node->data.fn_proto.cc = CallingConventionC; |
| 964 | proto_node->data.fn_proto.is_extern = true; | 992 | proto_node->data.fn_proto.is_extern = true; |
| 965 | break; | 993 | break; |
| 966 | case CC_X86StdCall: // __attribute__((stdcall)) | 994 | case clang::CC_X86StdCall: // __attribute__((stdcall)) |
| 967 | proto_node->data.fn_proto.cc = CallingConventionStdcall; | 995 | proto_node->data.fn_proto.cc = CallingConventionStdcall; |
| 968 | break; | 996 | break; |
| 969 | case CC_X86FastCall: // __attribute__((fastcall)) | 997 | case clang::CC_X86FastCall: // __attribute__((fastcall)) |
| 970 | emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); | 998 | emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); |
| 971 | return nullptr; | 999 | return nullptr; |
| 972 | case CC_X86ThisCall: // __attribute__((thiscall)) | 1000 | case clang::CC_X86ThisCall: // __attribute__((thiscall)) |
| 973 | emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); | 1001 | emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); |
| 974 | return nullptr; | 1002 | return nullptr; |
| 975 | case CC_X86VectorCall: // __attribute__((vectorcall)) | 1003 | case clang::CC_X86VectorCall: // __attribute__((vectorcall)) |
| 976 | emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); | 1004 | emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); |
| 977 | return nullptr; | 1005 | return nullptr; |
| 978 | case CC_X86Pascal: // __attribute__((pascal)) | 1006 | case clang::CC_X86Pascal: // __attribute__((pascal)) |
| 979 | emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); | 1007 | emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); |
| 980 | return nullptr; | 1008 | return nullptr; |
| 981 | case CC_Win64: // __attribute__((ms_abi)) | 1009 | case clang::CC_Win64: // __attribute__((ms_abi)) |
| 982 | emit_warning(c, source_loc, "unsupported calling convention: win64"); | 1010 | emit_warning(c, source_loc, "unsupported calling convention: win64"); |
| 983 | return nullptr; | 1011 | return nullptr; |
| 984 | case CC_X86_64SysV: // __attribute__((sysv_abi)) | 1012 | case clang::CC_X86_64SysV: // __attribute__((sysv_abi)) |
| 985 | emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); | 1013 | emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); |
| 986 | return nullptr; | 1014 | return nullptr; |
| 987 | case CC_X86RegCall: | 1015 | case clang::CC_X86RegCall: |
| 988 | emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); | 1016 | emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); |
| 989 | return nullptr; | 1017 | return nullptr; |
| 990 | case CC_AAPCS: // __attribute__((pcs("aapcs"))) | 1018 | case clang::CC_AAPCS: // __attribute__((pcs("aapcs"))) |
| 991 | emit_warning(c, source_loc, "unsupported calling convention: aapcs"); | 1019 | emit_warning(c, source_loc, "unsupported calling convention: aapcs"); |
| 992 | return nullptr; | 1020 | return nullptr; |
| 993 | case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | 1021 | case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) |
| 994 | emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); | 1022 | emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); |
| 995 | return nullptr; | 1023 | return nullptr; |
| 996 | case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | 1024 | case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) |
| 997 | emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); | 1025 | emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); |
| 998 | return nullptr; | 1026 | return nullptr; |
| 999 | case CC_SpirFunction: // default for OpenCL functions on SPIR target | 1027 | case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target |
| 1000 | emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); | 1028 | emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); |
| 1001 | return nullptr; | 1029 | return nullptr; |
| 1002 | case CC_OpenCLKernel: | 1030 | case clang::CC_OpenCLKernel: |
| 1003 | emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); | 1031 | emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); |
| 1004 | return nullptr; | 1032 | return nullptr; |
| 1005 | case CC_Swift: | 1033 | case clang::CC_Swift: |
| 1006 | emit_warning(c, source_loc, "unsupported calling convention: Swift"); | 1034 | emit_warning(c, source_loc, "unsupported calling convention: Swift"); |
| 1007 | return nullptr; | 1035 | return nullptr; |
| 1008 | case CC_PreserveMost: | 1036 | case clang::CC_PreserveMost: |
| 1009 | emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); | 1037 | emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); |
| 1010 | return nullptr; | 1038 | return nullptr; |
| 1011 | case CC_PreserveAll: | 1039 | case clang::CC_PreserveAll: |
| 1012 | emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); | 1040 | emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); |
| 1013 | return nullptr; | 1041 | return nullptr; |
| 1014 | } | 1042 | } |
| ... | @@ -1026,7 +1054,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -1026,7 +1054,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1026 | return nullptr; | 1054 | return nullptr; |
| 1027 | } | 1055 | } |
| 1028 | // convert c_void to actual void (only for return type) | 1056 | // convert c_void to actual void (only for return type) |
| 1029 | // we do want to look at the AstNode instead of QualType, because | 1057 | // we do want to look at the AstNode instead of clang::QualType, because |
| 1030 | // if they do something like: | 1058 | // if they do something like: |
| 1031 | // typedef Foo void; | 1059 | // typedef Foo void; |
| 1032 | // void foo(void) -> Foo; | 1060 | // void foo(void) -> Foo; |
| ... | @@ -1043,7 +1071,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -1043,7 +1071,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1043 | } | 1071 | } |
| 1044 | 1072 | ||
| 1045 | for (size_t i = 0; i < param_count; i += 1) { | 1073 | for (size_t i = 0; i < param_count; i += 1) { |
| 1046 | QualType qt = fn_proto_ty->getParamType(i); | 1074 | clang::QualType qt = fn_proto_ty->getParamType(i); |
| 1047 | AstNode *param_type_node = trans_qual_type(c, qt, source_loc); | 1075 | AstNode *param_type_node = trans_qual_type(c, qt, source_loc); |
| 1048 | 1076 | ||
| 1049 | if (param_type_node == nullptr) { | 1077 | if (param_type_node == nullptr) { |
| ... | @@ -1066,19 +1094,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -1066,19 +1094,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1066 | 1094 | ||
| 1067 | return proto_node; | 1095 | return proto_node; |
| 1068 | } | 1096 | } |
| 1069 | case Type::Record: | 1097 | case clang::Type::Record: |
| 1070 | { | 1098 | { |
| 1071 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | 1099 | const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty); |
| 1072 | return resolve_record_decl(c, record_ty->getDecl()); | 1100 | return resolve_record_decl(c, record_ty->getDecl()); |
| 1073 | } | 1101 | } |
| 1074 | case Type::Enum: | 1102 | case clang::Type::Enum: |
| 1075 | { | 1103 | { |
| 1076 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | 1104 | const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty); |
| 1077 | return resolve_enum_decl(c, enum_ty->getDecl()); | 1105 | return resolve_enum_decl(c, enum_ty->getDecl()); |
| 1078 | } | 1106 | } |
| 1079 | case Type::ConstantArray: | 1107 | case clang::Type::ConstantArray: |
| 1080 | { | 1108 | { |
| 1081 | const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty); | 1109 | const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty); |
| 1082 | AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); | 1110 | AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); |
| 1083 | if (child_type_node == nullptr) { | 1111 | if (child_type_node == nullptr) { |
| 1084 | emit_warning(c, source_loc, "unresolved array element type"); | 1112 | emit_warning(c, source_loc, "unresolved array element type"); |
| ... | @@ -1088,84 +1116,84 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -1088,84 +1116,84 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 1088 | AstNode *size_node = trans_create_node_unsigned(c, size); | 1116 | AstNode *size_node = trans_create_node_unsigned(c, size); |
| 1089 | return trans_create_node_array_type(c, size_node, child_type_node); | 1117 | return trans_create_node_array_type(c, size_node, child_type_node); |
| 1090 | } | 1118 | } |
| 1091 | case Type::Paren: | 1119 | case clang::Type::Paren: |
| 1092 | { | 1120 | { |
| 1093 | const ParenType *paren_ty = static_cast<const ParenType *>(ty); | 1121 | const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty); |
| 1094 | return trans_qual_type(c, paren_ty->getInnerType(), source_loc); | 1122 | return trans_qual_type(c, paren_ty->getInnerType(), source_loc); |
| 1095 | } | 1123 | } |
| 1096 | case Type::Decayed: | 1124 | case clang::Type::Decayed: |
| 1097 | { | 1125 | { |
| 1098 | const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty); | 1126 | const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty); |
| 1099 | return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); | 1127 | return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); |
| 1100 | } | 1128 | } |
| 1101 | case Type::Attributed: | 1129 | case clang::Type::Attributed: |
| 1102 | { | 1130 | { |
| 1103 | const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty); | 1131 | const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty); |
| 1104 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); | 1132 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); |
| 1105 | } | 1133 | } |
| 1106 | case Type::IncompleteArray: | 1134 | case clang::Type::IncompleteArray: |
| 1107 | { | 1135 | { |
| 1108 | const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty); | 1136 | const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty); |
| 1109 | QualType child_qt = incomplete_array_ty->getElementType(); | 1137 | clang::QualType child_qt = incomplete_array_ty->getElementType(); |
| 1110 | AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc); | 1138 | AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc); |
| 1111 | if (child_type_node == nullptr) { | 1139 | if (child_type_node == nullptr) { |
| 1112 | emit_warning(c, source_loc, "unresolved array element type"); | 1140 | emit_warning(c, source_loc, "unresolved array element type"); |
| 1113 | return nullptr; | 1141 | return nullptr; |
| 1114 | } | 1142 | } |
| 1115 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), | 1143 | AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(), |
| 1116 | child_qt.isVolatileQualified(), child_type_node, PtrLenUnknown); | 1144 | child_qt.isVolatileQualified(), child_type_node, PtrLenC); |
| 1117 | return pointer_node; | 1145 | return pointer_node; |
| 1118 | } | 1146 | } |
| 1119 | case Type::BlockPointer: | 1147 | case clang::Type::BlockPointer: |
| 1120 | case Type::LValueReference: | 1148 | case clang::Type::LValueReference: |
| 1121 | case Type::RValueReference: | 1149 | case clang::Type::RValueReference: |
| 1122 | case Type::MemberPointer: | 1150 | case clang::Type::MemberPointer: |
| 1123 | case Type::VariableArray: | 1151 | case clang::Type::VariableArray: |
| 1124 | case Type::DependentSizedArray: | 1152 | case clang::Type::DependentSizedArray: |
| 1125 | case Type::DependentSizedExtVector: | 1153 | case clang::Type::DependentSizedExtVector: |
| 1126 | case Type::Vector: | 1154 | case clang::Type::Vector: |
| 1127 | case Type::ExtVector: | 1155 | case clang::Type::ExtVector: |
| 1128 | case Type::FunctionNoProto: | 1156 | case clang::Type::FunctionNoProto: |
| 1129 | case Type::UnresolvedUsing: | 1157 | case clang::Type::UnresolvedUsing: |
| 1130 | case Type::Adjusted: | 1158 | case clang::Type::Adjusted: |
| 1131 | case Type::TypeOfExpr: | 1159 | case clang::Type::TypeOfExpr: |
| 1132 | case Type::TypeOf: | 1160 | case clang::Type::TypeOf: |
| 1133 | case Type::Decltype: | 1161 | case clang::Type::Decltype: |
| 1134 | case Type::UnaryTransform: | 1162 | case clang::Type::UnaryTransform: |
| 1135 | case Type::TemplateTypeParm: | 1163 | case clang::Type::TemplateTypeParm: |
| 1136 | case Type::SubstTemplateTypeParm: | 1164 | case clang::Type::SubstTemplateTypeParm: |
| 1137 | case Type::SubstTemplateTypeParmPack: | 1165 | case clang::Type::SubstTemplateTypeParmPack: |
| 1138 | case Type::TemplateSpecialization: | 1166 | case clang::Type::TemplateSpecialization: |
| 1139 | case Type::Auto: | 1167 | case clang::Type::Auto: |
| 1140 | case Type::InjectedClassName: | 1168 | case clang::Type::InjectedClassName: |
| 1141 | case Type::DependentName: | 1169 | case clang::Type::DependentName: |
| 1142 | case Type::DependentTemplateSpecialization: | 1170 | case clang::Type::DependentTemplateSpecialization: |
| 1143 | case Type::PackExpansion: | 1171 | case clang::Type::PackExpansion: |
| 1144 | case Type::ObjCObject: | 1172 | case clang::Type::ObjCObject: |
| 1145 | case Type::ObjCInterface: | 1173 | case clang::Type::ObjCInterface: |
| 1146 | case Type::Complex: | 1174 | case clang::Type::Complex: |
| 1147 | case Type::ObjCObjectPointer: | 1175 | case clang::Type::ObjCObjectPointer: |
| 1148 | case Type::Atomic: | 1176 | case clang::Type::Atomic: |
| 1149 | case Type::Pipe: | 1177 | case clang::Type::Pipe: |
| 1150 | case Type::ObjCTypeParam: | 1178 | case clang::Type::ObjCTypeParam: |
| 1151 | case Type::DeducedTemplateSpecialization: | 1179 | case clang::Type::DeducedTemplateSpecialization: |
| 1152 | case Type::DependentAddressSpace: | 1180 | case clang::Type::DependentAddressSpace: |
| 1153 | case Type::DependentVector: | 1181 | case clang::Type::DependentVector: |
| 1154 | emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); | 1182 | emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); |
| 1155 | return nullptr; | 1183 | return nullptr; |
| 1156 | } | 1184 | } |
| 1157 | zig_unreachable(); | 1185 | zig_unreachable(); |
| 1158 | } | 1186 | } |
| 1159 | 1187 | ||
| 1160 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) { | 1188 | static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) { |
| 1161 | return trans_type(c, qt.getTypePtr(), source_loc); | 1189 | return trans_type(c, qt.getTypePtr(), source_loc); |
| 1162 | } | 1190 | } |
| 1163 | 1191 | ||
| 1164 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt, | 1192 | static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, |
| 1165 | AstNode *block_node, TransScope **out_node_scope) | 1193 | AstNode *block_node, TransScope **out_node_scope) |
| 1166 | { | 1194 | { |
| 1167 | assert(block_node->type == NodeTypeBlock); | 1195 | assert(block_node->type == NodeTypeBlock); |
| 1168 | for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | 1196 | for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { |
| 1169 | AstNode *child_node; | 1197 | AstNode *child_node; |
| 1170 | scope = trans_stmt(c, scope, *it, &child_node); | 1198 | scope = trans_stmt(c, scope, *it, &child_node); |
| 1171 | if (scope == nullptr) | 1199 | if (scope == nullptr) |
| ... | @@ -1179,7 +1207,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo | ... | @@ -1179,7 +1207,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo |
| 1179 | return ErrorNone; | 1207 | return ErrorNone; |
| 1180 | } | 1208 | } |
| 1181 | 1209 | ||
| 1182 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt, | 1210 | static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt, |
| 1183 | TransScope **out_node_scope) | 1211 | TransScope **out_node_scope) |
| 1184 | { | 1212 | { |
| 1185 | TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope); | 1213 | TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope); |
| ... | @@ -1188,8 +1216,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun | ... | @@ -1188,8 +1216,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun |
| 1188 | return child_scope_block->node; | 1216 | return child_scope_block->node; |
| 1189 | } | 1217 | } |
| 1190 | 1218 | ||
| 1191 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) { | 1219 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) { |
| 1192 | const Expr *value_expr = stmt->getRetValue(); | 1220 | const clang::Expr *value_expr = stmt->getRetValue(); |
| 1193 | if (value_expr == nullptr) { | 1221 | if (value_expr == nullptr) { |
| 1194 | return trans_create_node(c, NodeTypeReturnExpr); | 1222 | return trans_create_node(c, NodeTypeReturnExpr); |
| 1195 | } else { | 1223 | } else { |
| ... | @@ -1201,9 +1229,9 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm | ... | @@ -1201,9 +1229,9 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm |
| 1201 | } | 1229 | } |
| 1202 | } | 1230 | } |
| 1203 | 1231 | ||
| 1204 | static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) { | 1232 | static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) { |
| 1205 | llvm::APSInt result; | 1233 | llvm::APSInt result; |
| 1206 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { | 1234 | if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) { |
| 1207 | emit_warning(c, stmt->getLocStart(), "invalid integer literal"); | 1235 | emit_warning(c, stmt->getLocStart(), "invalid integer literal"); |
| 1208 | return nullptr; | 1236 | return nullptr; |
| 1209 | } | 1237 | } |
| ... | @@ -1211,13 +1239,13 @@ static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) { | ... | @@ -1211,13 +1239,13 @@ static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) { |
| 1211 | } | 1239 | } |
| 1212 | 1240 | ||
| 1213 | static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope, | 1241 | static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| 1214 | const ConditionalOperator *stmt) | 1242 | const clang::ConditionalOperator *stmt) |
| 1215 | { | 1243 | { |
| 1216 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); | 1244 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 1217 | 1245 | ||
| 1218 | Expr *cond_expr = stmt->getCond(); | 1246 | clang::Expr *cond_expr = stmt->getCond(); |
| 1219 | Expr *true_expr = stmt->getTrueExpr(); | 1247 | clang::Expr *true_expr = stmt->getTrueExpr(); |
| 1220 | Expr *false_expr = stmt->getFalseExpr(); | 1248 | clang::Expr *false_expr = stmt->getFalseExpr(); |
| 1221 | 1249 | ||
| 1222 | node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue); | 1250 | node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue); |
| 1223 | if (node->data.if_bool_expr.condition == nullptr) | 1251 | if (node->data.if_bool_expr.condition == nullptr) |
| ... | @@ -1234,7 +1262,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T | ... | @@ -1234,7 +1262,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T |
| 1234 | return maybe_suppress_result(c, result_used, node); | 1262 | return maybe_suppress_result(c, result_used, node); |
| 1235 | } | 1263 | } |
| 1236 | 1264 | ||
| 1237 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { | 1265 | static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) { |
| 1238 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1266 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1239 | node->data.bin_op_expr.bin_op = bin_op; | 1267 | node->data.bin_op_expr.bin_op = bin_op; |
| 1240 | 1268 | ||
| ... | @@ -1249,7 +1277,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi | ... | @@ -1249,7 +1277,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi |
| 1249 | return node; | 1277 | return node; |
| 1250 | } | 1278 | } |
| 1251 | 1279 | ||
| 1252 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { | 1280 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) { |
| 1253 | assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr); | 1281 | assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr); |
| 1254 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1282 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| 1255 | node->data.bin_op_expr.bin_op = bin_op; | 1283 | node->data.bin_op_expr.bin_op = bin_op; |
| ... | @@ -1265,7 +1293,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh | ... | @@ -1265,7 +1293,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh |
| 1265 | return node; | 1293 | return node; |
| 1266 | } | 1294 | } |
| 1267 | 1295 | ||
| 1268 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) { | 1296 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) { |
| 1269 | if (result_used == ResultUsedNo) { | 1297 | if (result_used == ResultUsedNo) { |
| 1270 | // common case | 1298 | // common case |
| 1271 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | 1299 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); |
| ... | @@ -1316,10 +1344,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco | ... | @@ -1316,10 +1344,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco |
| 1316 | } | 1344 | } |
| 1317 | } | 1345 | } |
| 1318 | 1346 | ||
| 1319 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type, | 1347 | static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type, |
| 1320 | Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) | 1348 | clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr) |
| 1321 | { | 1349 | { |
| 1322 | const SourceLocation &rhs_location = rhs_expr->getLocStart(); | 1350 | const clang::SourceLocation &rhs_location = rhs_expr->getLocStart(); |
| 1323 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); | 1351 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location); |
| 1324 | // lhs >> u5(rh) | 1352 | // lhs >> u5(rh) |
| 1325 | 1353 | ||
| ... | @@ -1333,22 +1361,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re | ... | @@ -1333,22 +1361,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re |
| 1333 | return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); | 1361 | return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); |
| 1334 | } | 1362 | } |
| 1335 | 1363 | ||
| 1336 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) { | 1364 | static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) { |
| 1337 | switch (stmt->getOpcode()) { | 1365 | switch (stmt->getOpcode()) { |
| 1338 | case BO_PtrMemD: | 1366 | case clang::BO_PtrMemD: |
| 1339 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD"); | 1367 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemD"); |
| 1340 | return nullptr; | 1368 | return nullptr; |
| 1341 | case BO_PtrMemI: | 1369 | case clang::BO_PtrMemI: |
| 1342 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); | 1370 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemI"); |
| 1343 | return nullptr; | 1371 | return nullptr; |
| 1344 | case BO_Cmp: | 1372 | case clang::BO_Cmp: |
| 1345 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Cmp"); | 1373 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_Cmp"); |
| 1346 | return nullptr; | 1374 | return nullptr; |
| 1347 | case BO_Mul: | 1375 | case clang::BO_Mul: |
| 1348 | return trans_create_bin_op(c, scope, stmt->getLHS(), | 1376 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1349 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, | 1377 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| 1350 | stmt->getRHS()); | 1378 | stmt->getRHS()); |
| 1351 | case BO_Div: | 1379 | case clang::BO_Div: |
| 1352 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { | 1380 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1353 | // unsigned/float division uses the operator | 1381 | // unsigned/float division uses the operator |
| 1354 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); | 1382 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| ... | @@ -1363,7 +1391,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS | ... | @@ -1363,7 +1391,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1363 | fn_call->data.fn_call_expr.params.append(rhs); | 1391 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1364 | return fn_call; | 1392 | return fn_call; |
| 1365 | } | 1393 | } |
| 1366 | case BO_Rem: | 1394 | case clang::BO_Rem: |
| 1367 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { | 1395 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 1368 | // unsigned/float division uses the operator | 1396 | // unsigned/float division uses the operator |
| 1369 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); | 1397 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| ... | @@ -1378,43 +1406,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS | ... | @@ -1378,43 +1406,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1378 | fn_call->data.fn_call_expr.params.append(rhs); | 1406 | fn_call->data.fn_call_expr.params.append(rhs); |
| 1379 | return fn_call; | 1407 | return fn_call; |
| 1380 | } | 1408 | } |
| 1381 | case BO_Add: | 1409 | case clang::BO_Add: |
| 1382 | return trans_create_bin_op(c, scope, stmt->getLHS(), | 1410 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1383 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, | 1411 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| 1384 | stmt->getRHS()); | 1412 | stmt->getRHS()); |
| 1385 | case BO_Sub: | 1413 | case clang::BO_Sub: |
| 1386 | return trans_create_bin_op(c, scope, stmt->getLHS(), | 1414 | return trans_create_bin_op(c, scope, stmt->getLHS(), |
| 1387 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, | 1415 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| 1388 | stmt->getRHS()); | 1416 | stmt->getRHS()); |
| 1389 | case BO_Shl: | 1417 | case clang::BO_Shl: |
| 1390 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); | 1418 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); |
| 1391 | case BO_Shr: | 1419 | case clang::BO_Shr: |
| 1392 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); | 1420 | return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); |
| 1393 | case BO_LT: | 1421 | case clang::BO_LT: |
| 1394 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); | 1422 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); |
| 1395 | case BO_GT: | 1423 | case clang::BO_GT: |
| 1396 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); | 1424 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); |
| 1397 | case BO_LE: | 1425 | case clang::BO_LE: |
| 1398 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); | 1426 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); |
| 1399 | case BO_GE: | 1427 | case clang::BO_GE: |
| 1400 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); | 1428 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); |
| 1401 | case BO_EQ: | 1429 | case clang::BO_EQ: |
| 1402 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); | 1430 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); |
| 1403 | case BO_NE: | 1431 | case clang::BO_NE: |
| 1404 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); | 1432 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); |
| 1405 | case BO_And: | 1433 | case clang::BO_And: |
| 1406 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); | 1434 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); |
| 1407 | case BO_Xor: | 1435 | case clang::BO_Xor: |
| 1408 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); | 1436 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); |
| 1409 | case BO_Or: | 1437 | case clang::BO_Or: |
| 1410 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); | 1438 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 1411 | case BO_LAnd: | 1439 | case clang::BO_LAnd: |
| 1412 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); | 1440 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 1413 | case BO_LOr: | 1441 | case clang::BO_LOr: |
| 1414 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); | 1442 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1415 | case BO_Assign: | 1443 | case clang::BO_Assign: |
| 1416 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); | 1444 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); |
| 1417 | case BO_Comma: | 1445 | case clang::BO_Comma: |
| 1418 | { | 1446 | { |
| 1419 | TransScopeBlock *scope_block = trans_scope_block_create(c, scope); | 1447 | TransScopeBlock *scope_block = trans_scope_block_create(c, scope); |
| 1420 | Buf *label_name = buf_create_from_str("x"); | 1448 | Buf *label_name = buf_create_from_str("x"); |
| ... | @@ -1431,16 +1459,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS | ... | @@ -1431,16 +1459,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1431 | scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs))); | 1459 | scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs))); |
| 1432 | return scope_block->node; | 1460 | return scope_block->node; |
| 1433 | } | 1461 | } |
| 1434 | case BO_MulAssign: | 1462 | case clang::BO_MulAssign: |
| 1435 | case BO_DivAssign: | 1463 | case clang::BO_DivAssign: |
| 1436 | case BO_RemAssign: | 1464 | case clang::BO_RemAssign: |
| 1437 | case BO_AddAssign: | 1465 | case clang::BO_AddAssign: |
| 1438 | case BO_SubAssign: | 1466 | case clang::BO_SubAssign: |
| 1439 | case BO_ShlAssign: | 1467 | case clang::BO_ShlAssign: |
| 1440 | case BO_ShrAssign: | 1468 | case clang::BO_ShrAssign: |
| 1441 | case BO_AndAssign: | 1469 | case clang::BO_AndAssign: |
| 1442 | case BO_XorAssign: | 1470 | case clang::BO_XorAssign: |
| 1443 | case BO_OrAssign: | 1471 | case clang::BO_OrAssign: |
| 1444 | zig_unreachable(); | 1472 | zig_unreachable(); |
| 1445 | } | 1473 | } |
| 1446 | 1474 | ||
| ... | @@ -1448,9 +1476,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS | ... | @@ -1448,9 +1476,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1448 | } | 1476 | } |
| 1449 | 1477 | ||
| 1450 | static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, | 1478 | static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope, |
| 1451 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) | 1479 | const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| 1452 | { | 1480 | { |
| 1453 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); | 1481 | const clang::SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1454 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); | 1482 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1455 | 1483 | ||
| 1456 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); | 1484 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| ... | @@ -1530,7 +1558,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result | ... | @@ -1530,7 +1558,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1530 | } | 1558 | } |
| 1531 | 1559 | ||
| 1532 | static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope, | 1560 | static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope, |
| 1533 | const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) | 1561 | const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) |
| 1534 | { | 1562 | { |
| 1535 | if (result_used == ResultUsedNo) { | 1563 | if (result_used == ResultUsedNo) { |
| 1536 | // simple common case, where the C and Zig are identical: | 1564 | // simple common case, where the C and Zig are identical: |
| ... | @@ -1590,76 +1618,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, | ... | @@ -1590,76 +1618,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1590 | 1618 | ||
| 1591 | 1619 | ||
| 1592 | static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope, | 1620 | static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope, |
| 1593 | const CompoundAssignOperator *stmt) | 1621 | const clang::CompoundAssignOperator *stmt) |
| 1594 | { | 1622 | { |
| 1595 | switch (stmt->getOpcode()) { | 1623 | switch (stmt->getOpcode()) { |
| 1596 | case BO_MulAssign: | 1624 | case clang::BO_MulAssign: |
| 1597 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1625 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1598 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); | 1626 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap); |
| 1599 | else | 1627 | else |
| 1600 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); | 1628 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult); |
| 1601 | case BO_DivAssign: | 1629 | case clang::BO_DivAssign: |
| 1602 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign"); | 1630 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_DivAssign"); |
| 1603 | return nullptr; | 1631 | return nullptr; |
| 1604 | case BO_RemAssign: | 1632 | case clang::BO_RemAssign: |
| 1605 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign"); | 1633 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_RemAssign"); |
| 1606 | return nullptr; | 1634 | return nullptr; |
| 1607 | case BO_Cmp: | 1635 | case clang::BO_Cmp: |
| 1608 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_Cmp"); | 1636 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_Cmp"); |
| 1609 | return nullptr; | 1637 | return nullptr; |
| 1610 | case BO_AddAssign: | 1638 | case clang::BO_AddAssign: |
| 1611 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1639 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1612 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); | 1640 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap); |
| 1613 | else | 1641 | else |
| 1614 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); | 1642 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd); |
| 1615 | case BO_SubAssign: | 1643 | case clang::BO_SubAssign: |
| 1616 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 1644 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1617 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); | 1645 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap); |
| 1618 | else | 1646 | else |
| 1619 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub); | 1647 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub); |
| 1620 | case BO_ShlAssign: | 1648 | case clang::BO_ShlAssign: |
| 1621 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); | 1649 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft); |
| 1622 | case BO_ShrAssign: | 1650 | case clang::BO_ShrAssign: |
| 1623 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); | 1651 | return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight); |
| 1624 | case BO_AndAssign: | 1652 | case clang::BO_AndAssign: |
| 1625 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); | 1653 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd); |
| 1626 | case BO_XorAssign: | 1654 | case clang::BO_XorAssign: |
| 1627 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); | 1655 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor); |
| 1628 | case BO_OrAssign: | 1656 | case clang::BO_OrAssign: |
| 1629 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); | 1657 | return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr); |
| 1630 | case BO_PtrMemD: | 1658 | case clang::BO_PtrMemD: |
| 1631 | case BO_PtrMemI: | 1659 | case clang::BO_PtrMemI: |
| 1632 | case BO_Assign: | 1660 | case clang::BO_Assign: |
| 1633 | case BO_Mul: | 1661 | case clang::BO_Mul: |
| 1634 | case BO_Div: | 1662 | case clang::BO_Div: |
| 1635 | case BO_Rem: | 1663 | case clang::BO_Rem: |
| 1636 | case BO_Add: | 1664 | case clang::BO_Add: |
| 1637 | case BO_Sub: | 1665 | case clang::BO_Sub: |
| 1638 | case BO_Shl: | 1666 | case clang::BO_Shl: |
| 1639 | case BO_Shr: | 1667 | case clang::BO_Shr: |
| 1640 | case BO_LT: | 1668 | case clang::BO_LT: |
| 1641 | case BO_GT: | 1669 | case clang::BO_GT: |
| 1642 | case BO_LE: | 1670 | case clang::BO_LE: |
| 1643 | case BO_GE: | 1671 | case clang::BO_GE: |
| 1644 | case BO_EQ: | 1672 | case clang::BO_EQ: |
| 1645 | case BO_NE: | 1673 | case clang::BO_NE: |
| 1646 | case BO_And: | 1674 | case clang::BO_And: |
| 1647 | case BO_Xor: | 1675 | case clang::BO_Xor: |
| 1648 | case BO_Or: | 1676 | case clang::BO_Or: |
| 1649 | case BO_LAnd: | 1677 | case clang::BO_LAnd: |
| 1650 | case BO_LOr: | 1678 | case clang::BO_LOr: |
| 1651 | case BO_Comma: | 1679 | case clang::BO_Comma: |
| 1652 | zig_unreachable(); | 1680 | zig_unreachable(); |
| 1653 | } | 1681 | } |
| 1654 | 1682 | ||
| 1655 | zig_unreachable(); | 1683 | zig_unreachable(); |
| 1656 | } | 1684 | } |
| 1657 | 1685 | ||
| 1658 | static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) { | 1686 | static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) { |
| 1659 | switch (stmt->getCastKind()) { | 1687 | switch (stmt->getCastKind()) { |
| 1660 | case CK_LValueToRValue: | 1688 | case clang::CK_LValueToRValue: |
| 1661 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | 1689 | return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1662 | case CK_IntegralCast: | 1690 | case clang::CK_IntegralCast: |
| 1663 | { | 1691 | { |
| 1664 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | 1692 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1665 | if (target_node == nullptr) | 1693 | if (target_node == nullptr) |
| ... | @@ -1667,15 +1695,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im | ... | @@ -1667,15 +1695,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1667 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), | 1695 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), |
| 1668 | stmt->getSubExpr()->getType(), target_node); | 1696 | stmt->getSubExpr()->getType(), target_node); |
| 1669 | } | 1697 | } |
| 1670 | case CK_FunctionToPointerDecay: | 1698 | case clang::CK_FunctionToPointerDecay: |
| 1671 | case CK_ArrayToPointerDecay: | 1699 | case clang::CK_ArrayToPointerDecay: |
| 1672 | { | 1700 | { |
| 1673 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | 1701 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1674 | if (target_node == nullptr) | 1702 | if (target_node == nullptr) |
| 1675 | return nullptr; | 1703 | return nullptr; |
| 1676 | return target_node; | 1704 | return target_node; |
| 1677 | } | 1705 | } |
| 1678 | case CK_BitCast: | 1706 | case clang::CK_BitCast: |
| 1679 | { | 1707 | { |
| 1680 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | 1708 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1681 | if (target_node == nullptr) | 1709 | if (target_node == nullptr) |
| ... | @@ -1692,170 +1720,170 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im | ... | @@ -1692,170 +1720,170 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1692 | node->data.fn_call_expr.params.append(target_node); | 1720 | node->data.fn_call_expr.params.append(target_node); |
| 1693 | return node; | 1721 | return node; |
| 1694 | } | 1722 | } |
| 1695 | case CK_NullToPointer: | 1723 | case clang::CK_NullToPointer: |
| 1696 | return trans_create_node(c, NodeTypeNullLiteral); | 1724 | return trans_create_node_unsigned(c, 0); |
| 1697 | case CK_Dependent: | 1725 | case clang::CK_Dependent: |
| 1698 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent"); | 1726 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dependent"); |
| 1699 | return nullptr; | 1727 | return nullptr; |
| 1700 | case CK_LValueBitCast: | 1728 | case clang::CK_LValueBitCast: |
| 1701 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast"); | 1729 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_LValueBitCast"); |
| 1702 | return nullptr; | 1730 | return nullptr; |
| 1703 | case CK_NoOp: | 1731 | case clang::CK_NoOp: |
| 1704 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NoOp"); | 1732 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NoOp"); |
| 1705 | return nullptr; | 1733 | return nullptr; |
| 1706 | case CK_BaseToDerived: | 1734 | case clang::CK_BaseToDerived: |
| 1707 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerived"); | 1735 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerived"); |
| 1708 | return nullptr; | 1736 | return nullptr; |
| 1709 | case CK_DerivedToBase: | 1737 | case clang::CK_DerivedToBase: |
| 1710 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBase"); | 1738 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBase"); |
| 1711 | return nullptr; | 1739 | return nullptr; |
| 1712 | case CK_UncheckedDerivedToBase: | 1740 | case clang::CK_UncheckedDerivedToBase: |
| 1713 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UncheckedDerivedToBase"); | 1741 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UncheckedDerivedToBase"); |
| 1714 | return nullptr; | 1742 | return nullptr; |
| 1715 | case CK_Dynamic: | 1743 | case clang::CK_Dynamic: |
| 1716 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dynamic"); | 1744 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dynamic"); |
| 1717 | return nullptr; | 1745 | return nullptr; |
| 1718 | case CK_ToUnion: | 1746 | case clang::CK_ToUnion: |
| 1719 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion"); | 1747 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToUnion"); |
| 1720 | return nullptr; | 1748 | return nullptr; |
| 1721 | case CK_NullToMemberPointer: | 1749 | case clang::CK_NullToMemberPointer: |
| 1722 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToMemberPointer"); | 1750 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NullToMemberPointer"); |
| 1723 | return nullptr; | 1751 | return nullptr; |
| 1724 | case CK_BaseToDerivedMemberPointer: | 1752 | case clang::CK_BaseToDerivedMemberPointer: |
| 1725 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer"); | 1753 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerivedMemberPointer"); |
| 1726 | return nullptr; | 1754 | return nullptr; |
| 1727 | case CK_DerivedToBaseMemberPointer: | 1755 | case clang::CK_DerivedToBaseMemberPointer: |
| 1728 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer"); | 1756 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBaseMemberPointer"); |
| 1729 | return nullptr; | 1757 | return nullptr; |
| 1730 | case CK_MemberPointerToBoolean: | 1758 | case clang::CK_MemberPointerToBoolean: |
| 1731 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_MemberPointerToBoolean"); | 1759 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_MemberPointerToBoolean"); |
| 1732 | return nullptr; | 1760 | return nullptr; |
| 1733 | case CK_ReinterpretMemberPointer: | 1761 | case clang::CK_ReinterpretMemberPointer: |
| 1734 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ReinterpretMemberPointer"); | 1762 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ReinterpretMemberPointer"); |
| 1735 | return nullptr; | 1763 | return nullptr; |
| 1736 | case CK_UserDefinedConversion: | 1764 | case clang::CK_UserDefinedConversion: |
| 1737 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UserDefinedConversion"); | 1765 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UserDefinedConversion"); |
| 1738 | return nullptr; | 1766 | return nullptr; |
| 1739 | case CK_ConstructorConversion: | 1767 | case clang::CK_ConstructorConversion: |
| 1740 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ConstructorConversion"); | 1768 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ConstructorConversion"); |
| 1741 | return nullptr; | 1769 | return nullptr; |
| 1742 | case CK_IntegralToPointer: | 1770 | case clang::CK_IntegralToPointer: |
| 1743 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToPointer"); | 1771 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToPointer"); |
| 1744 | return nullptr; | 1772 | return nullptr; |
| 1745 | case CK_PointerToIntegral: | 1773 | case clang::CK_PointerToIntegral: |
| 1746 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToIntegral"); | 1774 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToIntegral"); |
| 1747 | return nullptr; | 1775 | return nullptr; |
| 1748 | case CK_PointerToBoolean: | 1776 | case clang::CK_PointerToBoolean: |
| 1749 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToBoolean"); | 1777 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToBoolean"); |
| 1750 | return nullptr; | 1778 | return nullptr; |
| 1751 | case CK_ToVoid: | 1779 | case clang::CK_ToVoid: |
| 1752 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToVoid"); | 1780 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToVoid"); |
| 1753 | return nullptr; | 1781 | return nullptr; |
| 1754 | case CK_VectorSplat: | 1782 | case clang::CK_VectorSplat: |
| 1755 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_VectorSplat"); | 1783 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_VectorSplat"); |
| 1756 | return nullptr; | 1784 | return nullptr; |
| 1757 | case CK_IntegralToBoolean: | 1785 | case clang::CK_IntegralToBoolean: |
| 1758 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToBoolean"); | 1786 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToBoolean"); |
| 1759 | return nullptr; | 1787 | return nullptr; |
| 1760 | case CK_IntegralToFloating: | 1788 | case clang::CK_IntegralToFloating: |
| 1761 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToFloating"); | 1789 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToFloating"); |
| 1762 | return nullptr; | 1790 | return nullptr; |
| 1763 | case CK_FloatingToIntegral: | 1791 | case clang::CK_FloatingToIntegral: |
| 1764 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToIntegral"); | 1792 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToIntegral"); |
| 1765 | return nullptr; | 1793 | return nullptr; |
| 1766 | case CK_FloatingToBoolean: | 1794 | case clang::CK_FloatingToBoolean: |
| 1767 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToBoolean"); | 1795 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToBoolean"); |
| 1768 | return nullptr; | 1796 | return nullptr; |
| 1769 | case CK_BooleanToSignedIntegral: | 1797 | case clang::CK_BooleanToSignedIntegral: |
| 1770 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BooleanToSignedIntegral"); | 1798 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BooleanToSignedIntegral"); |
| 1771 | return nullptr; | 1799 | return nullptr; |
| 1772 | case CK_FloatingCast: | 1800 | case clang::CK_FloatingCast: |
| 1773 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingCast"); | 1801 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingCast"); |
| 1774 | return nullptr; | 1802 | return nullptr; |
| 1775 | case CK_CPointerToObjCPointerCast: | 1803 | case clang::CK_CPointerToObjCPointerCast: |
| 1776 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CPointerToObjCPointerCast"); | 1804 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CPointerToObjCPointerCast"); |
| 1777 | return nullptr; | 1805 | return nullptr; |
| 1778 | case CK_BlockPointerToObjCPointerCast: | 1806 | case clang::CK_BlockPointerToObjCPointerCast: |
| 1779 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast"); | 1807 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BlockPointerToObjCPointerCast"); |
| 1780 | return nullptr; | 1808 | return nullptr; |
| 1781 | case CK_AnyPointerToBlockPointerCast: | 1809 | case clang::CK_AnyPointerToBlockPointerCast: |
| 1782 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast"); | 1810 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AnyPointerToBlockPointerCast"); |
| 1783 | return nullptr; | 1811 | return nullptr; |
| 1784 | case CK_ObjCObjectLValueCast: | 1812 | case clang::CK_ObjCObjectLValueCast: |
| 1785 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ObjCObjectLValueCast"); | 1813 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ObjCObjectLValueCast"); |
| 1786 | return nullptr; | 1814 | return nullptr; |
| 1787 | case CK_FloatingRealToComplex: | 1815 | case clang::CK_FloatingRealToComplex: |
| 1788 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingRealToComplex"); | 1816 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingRealToComplex"); |
| 1789 | return nullptr; | 1817 | return nullptr; |
| 1790 | case CK_FloatingComplexToReal: | 1818 | case clang::CK_FloatingComplexToReal: |
| 1791 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToReal"); | 1819 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToReal"); |
| 1792 | return nullptr; | 1820 | return nullptr; |
| 1793 | case CK_FloatingComplexToBoolean: | 1821 | case clang::CK_FloatingComplexToBoolean: |
| 1794 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToBoolean"); | 1822 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToBoolean"); |
| 1795 | return nullptr; | 1823 | return nullptr; |
| 1796 | case CK_FloatingComplexCast: | 1824 | case clang::CK_FloatingComplexCast: |
| 1797 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexCast"); | 1825 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexCast"); |
| 1798 | return nullptr; | 1826 | return nullptr; |
| 1799 | case CK_FloatingComplexToIntegralComplex: | 1827 | case clang::CK_FloatingComplexToIntegralComplex: |
| 1800 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex"); | 1828 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToIntegralComplex"); |
| 1801 | return nullptr; | 1829 | return nullptr; |
| 1802 | case CK_IntegralRealToComplex: | 1830 | case clang::CK_IntegralRealToComplex: |
| 1803 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralRealToComplex"); | 1831 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralRealToComplex"); |
| 1804 | return nullptr; | 1832 | return nullptr; |
| 1805 | case CK_IntegralComplexToReal: | 1833 | case clang::CK_IntegralComplexToReal: |
| 1806 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToReal"); | 1834 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToReal"); |
| 1807 | return nullptr; | 1835 | return nullptr; |
| 1808 | case CK_IntegralComplexToBoolean: | 1836 | case clang::CK_IntegralComplexToBoolean: |
| 1809 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToBoolean"); | 1837 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToBoolean"); |
| 1810 | return nullptr; | 1838 | return nullptr; |
| 1811 | case CK_IntegralComplexCast: | 1839 | case clang::CK_IntegralComplexCast: |
| 1812 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexCast"); | 1840 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexCast"); |
| 1813 | return nullptr; | 1841 | return nullptr; |
| 1814 | case CK_IntegralComplexToFloatingComplex: | 1842 | case clang::CK_IntegralComplexToFloatingComplex: |
| 1815 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex"); | 1843 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToFloatingComplex"); |
| 1816 | return nullptr; | 1844 | return nullptr; |
| 1817 | case CK_ARCProduceObject: | 1845 | case clang::CK_ARCProduceObject: |
| 1818 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCProduceObject"); | 1846 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCProduceObject"); |
| 1819 | return nullptr; | 1847 | return nullptr; |
| 1820 | case CK_ARCConsumeObject: | 1848 | case clang::CK_ARCConsumeObject: |
| 1821 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCConsumeObject"); | 1849 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCConsumeObject"); |
| 1822 | return nullptr; | 1850 | return nullptr; |
| 1823 | case CK_ARCReclaimReturnedObject: | 1851 | case clang::CK_ARCReclaimReturnedObject: |
| 1824 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCReclaimReturnedObject"); | 1852 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCReclaimReturnedObject"); |
| 1825 | return nullptr; | 1853 | return nullptr; |
| 1826 | case CK_ARCExtendBlockObject: | 1854 | case clang::CK_ARCExtendBlockObject: |
| 1827 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCExtendBlockObject"); | 1855 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCExtendBlockObject"); |
| 1828 | return nullptr; | 1856 | return nullptr; |
| 1829 | case CK_AtomicToNonAtomic: | 1857 | case clang::CK_AtomicToNonAtomic: |
| 1830 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AtomicToNonAtomic"); | 1858 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AtomicToNonAtomic"); |
| 1831 | return nullptr; | 1859 | return nullptr; |
| 1832 | case CK_NonAtomicToAtomic: | 1860 | case clang::CK_NonAtomicToAtomic: |
| 1833 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NonAtomicToAtomic"); | 1861 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NonAtomicToAtomic"); |
| 1834 | return nullptr; | 1862 | return nullptr; |
| 1835 | case CK_CopyAndAutoreleaseBlockObject: | 1863 | case clang::CK_CopyAndAutoreleaseBlockObject: |
| 1836 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject"); | 1864 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CopyAndAutoreleaseBlockObject"); |
| 1837 | return nullptr; | 1865 | return nullptr; |
| 1838 | case CK_BuiltinFnToFnPtr: | 1866 | case clang::CK_BuiltinFnToFnPtr: |
| 1839 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BuiltinFnToFnPtr"); | 1867 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BuiltinFnToFnPtr"); |
| 1840 | return nullptr; | 1868 | return nullptr; |
| 1841 | case CK_ZeroToOCLEvent: | 1869 | case clang::CK_ZeroToOCLEvent: |
| 1842 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLEvent"); | 1870 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLEvent"); |
| 1843 | return nullptr; | 1871 | return nullptr; |
| 1844 | case CK_ZeroToOCLQueue: | 1872 | case clang::CK_ZeroToOCLQueue: |
| 1845 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLQueue"); | 1873 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLQueue"); |
| 1846 | return nullptr; | 1874 | return nullptr; |
| 1847 | case CK_AddressSpaceConversion: | 1875 | case clang::CK_AddressSpaceConversion: |
| 1848 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AddressSpaceConversion"); | 1876 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AddressSpaceConversion"); |
| 1849 | return nullptr; | 1877 | return nullptr; |
| 1850 | case CK_IntToOCLSampler: | 1878 | case clang::CK_IntToOCLSampler: |
| 1851 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntToOCLSampler"); | 1879 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntToOCLSampler"); |
| 1852 | return nullptr; | 1880 | return nullptr; |
| 1853 | } | 1881 | } |
| 1854 | zig_unreachable(); | 1882 | zig_unreachable(); |
| 1855 | } | 1883 | } |
| 1856 | 1884 | ||
| 1857 | static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) { | 1885 | static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) { |
| 1858 | const ValueDecl *value_decl = stmt->getDecl(); | 1886 | const clang::ValueDecl *value_decl = stmt->getDecl(); |
| 1859 | Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl)); | 1887 | Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl)); |
| 1860 | Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name); | 1888 | Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name); |
| 1861 | if (lrval == TransLValue) { | 1889 | if (lrval == TransLValue) { |
| ... | @@ -1865,9 +1893,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef | ... | @@ -1865,9 +1893,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef |
| 1865 | } | 1893 | } |
| 1866 | 1894 | ||
| 1867 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, | 1895 | static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 1868 | const UnaryOperator *stmt, BinOpType assign_op) | 1896 | const clang::UnaryOperator *stmt, BinOpType assign_op) |
| 1869 | { | 1897 | { |
| 1870 | Expr *op_expr = stmt->getSubExpr(); | 1898 | clang::Expr *op_expr = stmt->getSubExpr(); |
| 1871 | 1899 | ||
| 1872 | if (result_used == ResultUsedNo) { | 1900 | if (result_used == ResultUsedNo) { |
| 1873 | // common case | 1901 | // common case |
| ... | @@ -1921,9 +1949,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr | ... | @@ -1921,9 +1949,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr |
| 1921 | } | 1949 | } |
| 1922 | 1950 | ||
| 1923 | static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope, | 1951 | static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope, |
| 1924 | const UnaryOperator *stmt, BinOpType assign_op) | 1952 | const clang::UnaryOperator *stmt, BinOpType assign_op) |
| 1925 | { | 1953 | { |
| 1926 | Expr *op_expr = stmt->getSubExpr(); | 1954 | clang::Expr *op_expr = stmt->getSubExpr(); |
| 1927 | 1955 | ||
| 1928 | if (result_used == ResultUsedNo) { | 1956 | if (result_used == ResultUsedNo) { |
| 1929 | // common case | 1957 | // common case |
| ... | @@ -1970,36 +1998,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra | ... | @@ -1970,36 +1998,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra |
| 1970 | return child_scope->node; | 1998 | return child_scope->node; |
| 1971 | } | 1999 | } |
| 1972 | 2000 | ||
| 1973 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) { | 2001 | static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) { |
| 1974 | switch (stmt->getOpcode()) { | 2002 | switch (stmt->getOpcode()) { |
| 1975 | case UO_PostInc: | 2003 | case clang::UO_PostInc: |
| 1976 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 2004 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1977 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); | 2005 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 1978 | else | 2006 | else |
| 1979 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); | 2007 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 1980 | case UO_PostDec: | 2008 | case clang::UO_PostDec: |
| 1981 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 2009 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1982 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); | 2010 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 1983 | else | 2011 | else |
| 1984 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); | 2012 | return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 1985 | case UO_PreInc: | 2013 | case clang::UO_PreInc: |
| 1986 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 2014 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1987 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); | 2015 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap); |
| 1988 | else | 2016 | else |
| 1989 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); | 2017 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus); |
| 1990 | case UO_PreDec: | 2018 | case clang::UO_PreDec: |
| 1991 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | 2019 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) |
| 1992 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); | 2020 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap); |
| 1993 | else | 2021 | else |
| 1994 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); | 2022 | return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus); |
| 1995 | case UO_AddrOf: | 2023 | case clang::UO_AddrOf: |
| 1996 | { | 2024 | { |
| 1997 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); | 2025 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); |
| 1998 | if (value_node == nullptr) | 2026 | if (value_node == nullptr) |
| 1999 | return value_node; | 2027 | return value_node; |
| 2000 | return trans_create_node_addr_of(c, value_node); | 2028 | return trans_create_node_addr_of(c, value_node); |
| 2001 | } | 2029 | } |
| 2002 | case UO_Deref: | 2030 | case clang::UO_Deref: |
| 2003 | { | 2031 | { |
| 2004 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); | 2032 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); |
| 2005 | if (value_node == nullptr) | 2033 | if (value_node == nullptr) |
| ... | @@ -2010,12 +2038,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc | ... | @@ -2010,12 +2038,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2010 | AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node); | 2038 | AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node); |
| 2011 | return trans_create_node_ptr_deref(c, unwrapped); | 2039 | return trans_create_node_ptr_deref(c, unwrapped); |
| 2012 | } | 2040 | } |
| 2013 | case UO_Plus: | 2041 | case clang::UO_Plus: |
| 2014 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus"); | 2042 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Plus"); |
| 2015 | return nullptr; | 2043 | return nullptr; |
| 2016 | case UO_Minus: | 2044 | case clang::UO_Minus: |
| 2017 | { | 2045 | { |
| 2018 | Expr *op_expr = stmt->getSubExpr(); | 2046 | clang::Expr *op_expr = stmt->getSubExpr(); |
| 2019 | if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) { | 2047 | if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) { |
| 2020 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | 2048 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 2021 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; | 2049 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; |
| ... | @@ -2041,41 +2069,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc | ... | @@ -2041,41 +2069,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2041 | return nullptr; | 2069 | return nullptr; |
| 2042 | } | 2070 | } |
| 2043 | } | 2071 | } |
| 2044 | case UO_Not: | 2072 | case clang::UO_Not: |
| 2045 | { | 2073 | { |
| 2046 | Expr *op_expr = stmt->getSubExpr(); | 2074 | clang::Expr *op_expr = stmt->getSubExpr(); |
| 2047 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); | 2075 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 2048 | if (sub_node == nullptr) | 2076 | if (sub_node == nullptr) |
| 2049 | return nullptr; | 2077 | return nullptr; |
| 2050 | 2078 | ||
| 2051 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); | 2079 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); |
| 2052 | } | 2080 | } |
| 2053 | case UO_LNot: | 2081 | case clang::UO_LNot: |
| 2054 | { | 2082 | { |
| 2055 | Expr *op_expr = stmt->getSubExpr(); | 2083 | clang::Expr *op_expr = stmt->getSubExpr(); |
| 2056 | AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue); | 2084 | AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 2057 | if (sub_node == nullptr) | 2085 | if (sub_node == nullptr) |
| 2058 | return nullptr; | 2086 | return nullptr; |
| 2059 | 2087 | ||
| 2060 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node); | 2088 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node); |
| 2061 | } | 2089 | } |
| 2062 | case UO_Real: | 2090 | case clang::UO_Real: |
| 2063 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real"); | 2091 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Real"); |
| 2064 | return nullptr; | 2092 | return nullptr; |
| 2065 | case UO_Imag: | 2093 | case clang::UO_Imag: |
| 2066 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Imag"); | 2094 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag"); |
| 2067 | return nullptr; | 2095 | return nullptr; |
| 2068 | case UO_Extension: | 2096 | case clang::UO_Extension: |
| 2069 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Extension"); | 2097 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension"); |
| 2070 | return nullptr; | 2098 | return nullptr; |
| 2071 | case UO_Coawait: | 2099 | case clang::UO_Coawait: |
| 2072 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Coawait"); | 2100 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait"); |
| 2073 | return nullptr; | 2101 | return nullptr; |
| 2074 | } | 2102 | } |
| 2075 | zig_unreachable(); | 2103 | zig_unreachable(); |
| 2076 | } | 2104 | } |
| 2077 | 2105 | ||
| 2078 | static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt, | 2106 | static int trans_local_declaration(Context *c, TransScope *scope, const clang::DeclStmt *stmt, |
| 2079 | AstNode **out_node, TransScope **out_scope) | 2107 | AstNode **out_node, TransScope **out_scope) |
| 2080 | { | 2108 | { |
| 2081 | // declarations are added via the scope | 2109 | // declarations are added via the scope |
| ... | @@ -2085,11 +2113,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt | ... | @@ -2085,11 +2113,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2085 | assert(scope_block != nullptr); | 2113 | assert(scope_block != nullptr); |
| 2086 | 2114 | ||
| 2087 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { | 2115 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { |
| 2088 | Decl *decl = *iter; | 2116 | clang::Decl *decl = *iter; |
| 2089 | switch (decl->getKind()) { | 2117 | switch (decl->getKind()) { |
| 2090 | case Decl::Var: { | 2118 | case clang::Decl::Var: { |
| 2091 | VarDecl *var_decl = (VarDecl *)decl; | 2119 | clang::VarDecl *var_decl = (clang::VarDecl *)decl; |
| 2092 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | 2120 | clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType(); |
| 2093 | AstNode *init_node = nullptr; | 2121 | AstNode *init_node = nullptr; |
| 2094 | if (var_decl->hasInit()) { | 2122 | if (var_decl->hasInit()) { |
| 2095 | init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue); | 2123 | init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue); |
| ... | @@ -2114,220 +2142,220 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt | ... | @@ -2114,220 +2142,220 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2114 | scope_block->node->data.block.statements.append(node); | 2142 | scope_block->node->data.block.statements.append(node); |
| 2115 | continue; | 2143 | continue; |
| 2116 | } | 2144 | } |
| 2117 | case Decl::AccessSpec: | 2145 | case clang::Decl::AccessSpec: |
| 2118 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec"); | 2146 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec"); |
| 2119 | return ErrorUnexpected; | 2147 | return ErrorUnexpected; |
| 2120 | case Decl::Block: | 2148 | case clang::Decl::Block: |
| 2121 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block"); | 2149 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block"); |
| 2122 | return ErrorUnexpected; | 2150 | return ErrorUnexpected; |
| 2123 | case Decl::Captured: | 2151 | case clang::Decl::Captured: |
| 2124 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured"); | 2152 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured"); |
| 2125 | return ErrorUnexpected; | 2153 | return ErrorUnexpected; |
| 2126 | case Decl::ClassScopeFunctionSpecialization: | 2154 | case clang::Decl::ClassScopeFunctionSpecialization: |
| 2127 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization"); | 2155 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization"); |
| 2128 | return ErrorUnexpected; | 2156 | return ErrorUnexpected; |
| 2129 | case Decl::Empty: | 2157 | case clang::Decl::Empty: |
| 2130 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty"); | 2158 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty"); |
| 2131 | return ErrorUnexpected; | 2159 | return ErrorUnexpected; |
| 2132 | case Decl::Export: | 2160 | case clang::Decl::Export: |
| 2133 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export"); | 2161 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export"); |
| 2134 | return ErrorUnexpected; | 2162 | return ErrorUnexpected; |
| 2135 | case Decl::ExternCContext: | 2163 | case clang::Decl::ExternCContext: |
| 2136 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext"); | 2164 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext"); |
| 2137 | return ErrorUnexpected; | 2165 | return ErrorUnexpected; |
| 2138 | case Decl::FileScopeAsm: | 2166 | case clang::Decl::FileScopeAsm: |
| 2139 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm"); | 2167 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm"); |
| 2140 | return ErrorUnexpected; | 2168 | return ErrorUnexpected; |
| 2141 | case Decl::Friend: | 2169 | case clang::Decl::Friend: |
| 2142 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend"); | 2170 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend"); |
| 2143 | return ErrorUnexpected; | 2171 | return ErrorUnexpected; |
| 2144 | case Decl::FriendTemplate: | 2172 | case clang::Decl::FriendTemplate: |
| 2145 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate"); | 2173 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate"); |
| 2146 | return ErrorUnexpected; | 2174 | return ErrorUnexpected; |
| 2147 | case Decl::Import: | 2175 | case clang::Decl::Import: |
| 2148 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import"); | 2176 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import"); |
| 2149 | return ErrorUnexpected; | 2177 | return ErrorUnexpected; |
| 2150 | case Decl::LinkageSpec: | 2178 | case clang::Decl::LinkageSpec: |
| 2151 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec"); | 2179 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec"); |
| 2152 | return ErrorUnexpected; | 2180 | return ErrorUnexpected; |
| 2153 | case Decl::Label: | 2181 | case clang::Decl::Label: |
| 2154 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label"); | 2182 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label"); |
| 2155 | return ErrorUnexpected; | 2183 | return ErrorUnexpected; |
| 2156 | case Decl::Namespace: | 2184 | case clang::Decl::Namespace: |
| 2157 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace"); | 2185 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace"); |
| 2158 | return ErrorUnexpected; | 2186 | return ErrorUnexpected; |
| 2159 | case Decl::NamespaceAlias: | 2187 | case clang::Decl::NamespaceAlias: |
| 2160 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias"); | 2188 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias"); |
| 2161 | return ErrorUnexpected; | 2189 | return ErrorUnexpected; |
| 2162 | case Decl::ObjCCompatibleAlias: | 2190 | case clang::Decl::ObjCCompatibleAlias: |
| 2163 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias"); | 2191 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias"); |
| 2164 | return ErrorUnexpected; | 2192 | return ErrorUnexpected; |
| 2165 | case Decl::ObjCCategory: | 2193 | case clang::Decl::ObjCCategory: |
| 2166 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory"); | 2194 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory"); |
| 2167 | return ErrorUnexpected; | 2195 | return ErrorUnexpected; |
| 2168 | case Decl::ObjCCategoryImpl: | 2196 | case clang::Decl::ObjCCategoryImpl: |
| 2169 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl"); | 2197 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl"); |
| 2170 | return ErrorUnexpected; | 2198 | return ErrorUnexpected; |
| 2171 | case Decl::ObjCImplementation: | 2199 | case clang::Decl::ObjCImplementation: |
| 2172 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation"); | 2200 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation"); |
| 2173 | return ErrorUnexpected; | 2201 | return ErrorUnexpected; |
| 2174 | case Decl::ObjCInterface: | 2202 | case clang::Decl::ObjCInterface: |
| 2175 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface"); | 2203 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface"); |
| 2176 | return ErrorUnexpected; | 2204 | return ErrorUnexpected; |
| 2177 | case Decl::ObjCProtocol: | 2205 | case clang::Decl::ObjCProtocol: |
| 2178 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol"); | 2206 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol"); |
| 2179 | return ErrorUnexpected; | 2207 | return ErrorUnexpected; |
| 2180 | case Decl::ObjCMethod: | 2208 | case clang::Decl::ObjCMethod: |
| 2181 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod"); | 2209 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod"); |
| 2182 | return ErrorUnexpected; | 2210 | return ErrorUnexpected; |
| 2183 | case Decl::ObjCProperty: | 2211 | case clang::Decl::ObjCProperty: |
| 2184 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty"); | 2212 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty"); |
| 2185 | return ErrorUnexpected; | 2213 | return ErrorUnexpected; |
| 2186 | case Decl::BuiltinTemplate: | 2214 | case clang::Decl::BuiltinTemplate: |
| 2187 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate"); | 2215 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate"); |
| 2188 | return ErrorUnexpected; | 2216 | return ErrorUnexpected; |
| 2189 | case Decl::ClassTemplate: | 2217 | case clang::Decl::ClassTemplate: |
| 2190 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate"); | 2218 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate"); |
| 2191 | return ErrorUnexpected; | 2219 | return ErrorUnexpected; |
| 2192 | case Decl::FunctionTemplate: | 2220 | case clang::Decl::FunctionTemplate: |
| 2193 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate"); | 2221 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate"); |
| 2194 | return ErrorUnexpected; | 2222 | return ErrorUnexpected; |
| 2195 | case Decl::TypeAliasTemplate: | 2223 | case clang::Decl::TypeAliasTemplate: |
| 2196 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate"); | 2224 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate"); |
| 2197 | return ErrorUnexpected; | 2225 | return ErrorUnexpected; |
| 2198 | case Decl::VarTemplate: | 2226 | case clang::Decl::VarTemplate: |
| 2199 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate"); | 2227 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate"); |
| 2200 | return ErrorUnexpected; | 2228 | return ErrorUnexpected; |
| 2201 | case Decl::TemplateTemplateParm: | 2229 | case clang::Decl::TemplateTemplateParm: |
| 2202 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm"); | 2230 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm"); |
| 2203 | return ErrorUnexpected; | 2231 | return ErrorUnexpected; |
| 2204 | case Decl::Enum: | 2232 | case clang::Decl::Enum: |
| 2205 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum"); | 2233 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum"); |
| 2206 | return ErrorUnexpected; | 2234 | return ErrorUnexpected; |
| 2207 | case Decl::Record: | 2235 | case clang::Decl::Record: |
| 2208 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record"); | 2236 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record"); |
| 2209 | return ErrorUnexpected; | 2237 | return ErrorUnexpected; |
| 2210 | case Decl::CXXRecord: | 2238 | case clang::Decl::CXXRecord: |
| 2211 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord"); | 2239 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord"); |
| 2212 | return ErrorUnexpected; | 2240 | return ErrorUnexpected; |
| 2213 | case Decl::ClassTemplateSpecialization: | 2241 | case clang::Decl::ClassTemplateSpecialization: |
| 2214 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization"); | 2242 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization"); |
| 2215 | return ErrorUnexpected; | 2243 | return ErrorUnexpected; |
| 2216 | case Decl::ClassTemplatePartialSpecialization: | 2244 | case clang::Decl::ClassTemplatePartialSpecialization: |
| 2217 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization"); | 2245 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization"); |
| 2218 | return ErrorUnexpected; | 2246 | return ErrorUnexpected; |
| 2219 | case Decl::TemplateTypeParm: | 2247 | case clang::Decl::TemplateTypeParm: |
| 2220 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm"); | 2248 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm"); |
| 2221 | return ErrorUnexpected; | 2249 | return ErrorUnexpected; |
| 2222 | case Decl::ObjCTypeParam: | 2250 | case clang::Decl::ObjCTypeParam: |
| 2223 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam"); | 2251 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam"); |
| 2224 | return ErrorUnexpected; | 2252 | return ErrorUnexpected; |
| 2225 | case Decl::TypeAlias: | 2253 | case clang::Decl::TypeAlias: |
| 2226 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias"); | 2254 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias"); |
| 2227 | return ErrorUnexpected; | 2255 | return ErrorUnexpected; |
| 2228 | case Decl::Typedef: | 2256 | case clang::Decl::Typedef: |
| 2229 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef"); | 2257 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef"); |
| 2230 | return ErrorUnexpected; | 2258 | return ErrorUnexpected; |
| 2231 | case Decl::UnresolvedUsingTypename: | 2259 | case clang::Decl::UnresolvedUsingTypename: |
| 2232 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename"); | 2260 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename"); |
| 2233 | return ErrorUnexpected; | 2261 | return ErrorUnexpected; |
| 2234 | case Decl::Using: | 2262 | case clang::Decl::Using: |
| 2235 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using"); | 2263 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using"); |
| 2236 | return ErrorUnexpected; | 2264 | return ErrorUnexpected; |
| 2237 | case Decl::UsingDirective: | 2265 | case clang::Decl::UsingDirective: |
| 2238 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective"); | 2266 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective"); |
| 2239 | return ErrorUnexpected; | 2267 | return ErrorUnexpected; |
| 2240 | case Decl::UsingPack: | 2268 | case clang::Decl::UsingPack: |
| 2241 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack"); | 2269 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack"); |
| 2242 | return ErrorUnexpected; | 2270 | return ErrorUnexpected; |
| 2243 | case Decl::UsingShadow: | 2271 | case clang::Decl::UsingShadow: |
| 2244 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow"); | 2272 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow"); |
| 2245 | return ErrorUnexpected; | 2273 | return ErrorUnexpected; |
| 2246 | case Decl::ConstructorUsingShadow: | 2274 | case clang::Decl::ConstructorUsingShadow: |
| 2247 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow"); | 2275 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow"); |
| 2248 | return ErrorUnexpected; | 2276 | return ErrorUnexpected; |
| 2249 | case Decl::Binding: | 2277 | case clang::Decl::Binding: |
| 2250 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding"); | 2278 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding"); |
| 2251 | return ErrorUnexpected; | 2279 | return ErrorUnexpected; |
| 2252 | case Decl::Field: | 2280 | case clang::Decl::Field: |
| 2253 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field"); | 2281 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field"); |
| 2254 | return ErrorUnexpected; | 2282 | return ErrorUnexpected; |
| 2255 | case Decl::ObjCAtDefsField: | 2283 | case clang::Decl::ObjCAtDefsField: |
| 2256 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField"); | 2284 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField"); |
| 2257 | return ErrorUnexpected; | 2285 | return ErrorUnexpected; |
| 2258 | case Decl::ObjCIvar: | 2286 | case clang::Decl::ObjCIvar: |
| 2259 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar"); | 2287 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar"); |
| 2260 | return ErrorUnexpected; | 2288 | return ErrorUnexpected; |
| 2261 | case Decl::Function: | 2289 | case clang::Decl::Function: |
| 2262 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function"); | 2290 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function"); |
| 2263 | return ErrorUnexpected; | 2291 | return ErrorUnexpected; |
| 2264 | case Decl::CXXDeductionGuide: | 2292 | case clang::Decl::CXXDeductionGuide: |
| 2265 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide"); | 2293 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide"); |
| 2266 | return ErrorUnexpected; | 2294 | return ErrorUnexpected; |
| 2267 | case Decl::CXXMethod: | 2295 | case clang::Decl::CXXMethod: |
| 2268 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod"); | 2296 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod"); |
| 2269 | return ErrorUnexpected; | 2297 | return ErrorUnexpected; |
| 2270 | case Decl::CXXConstructor: | 2298 | case clang::Decl::CXXConstructor: |
| 2271 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor"); | 2299 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor"); |
| 2272 | return ErrorUnexpected; | 2300 | return ErrorUnexpected; |
| 2273 | case Decl::CXXConversion: | 2301 | case clang::Decl::CXXConversion: |
| 2274 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion"); | 2302 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion"); |
| 2275 | return ErrorUnexpected; | 2303 | return ErrorUnexpected; |
| 2276 | case Decl::CXXDestructor: | 2304 | case clang::Decl::CXXDestructor: |
| 2277 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor"); | 2305 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor"); |
| 2278 | return ErrorUnexpected; | 2306 | return ErrorUnexpected; |
| 2279 | case Decl::MSProperty: | 2307 | case clang::Decl::MSProperty: |
| 2280 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty"); | 2308 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty"); |
| 2281 | return ErrorUnexpected; | 2309 | return ErrorUnexpected; |
| 2282 | case Decl::NonTypeTemplateParm: | 2310 | case clang::Decl::NonTypeTemplateParm: |
| 2283 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm"); | 2311 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm"); |
| 2284 | return ErrorUnexpected; | 2312 | return ErrorUnexpected; |
| 2285 | case Decl::Decomposition: | 2313 | case clang::Decl::Decomposition: |
| 2286 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition"); | 2314 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition"); |
| 2287 | return ErrorUnexpected; | 2315 | return ErrorUnexpected; |
| 2288 | case Decl::ImplicitParam: | 2316 | case clang::Decl::ImplicitParam: |
| 2289 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam"); | 2317 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam"); |
| 2290 | return ErrorUnexpected; | 2318 | return ErrorUnexpected; |
| 2291 | case Decl::OMPCapturedExpr: | 2319 | case clang::Decl::OMPCapturedExpr: |
| 2292 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr"); | 2320 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr"); |
| 2293 | return ErrorUnexpected; | 2321 | return ErrorUnexpected; |
| 2294 | case Decl::ParmVar: | 2322 | case clang::Decl::ParmVar: |
| 2295 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar"); | 2323 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar"); |
| 2296 | return ErrorUnexpected; | 2324 | return ErrorUnexpected; |
| 2297 | case Decl::VarTemplateSpecialization: | 2325 | case clang::Decl::VarTemplateSpecialization: |
| 2298 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization"); | 2326 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization"); |
| 2299 | return ErrorUnexpected; | 2327 | return ErrorUnexpected; |
| 2300 | case Decl::VarTemplatePartialSpecialization: | 2328 | case clang::Decl::VarTemplatePartialSpecialization: |
| 2301 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization"); | 2329 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization"); |
| 2302 | return ErrorUnexpected; | 2330 | return ErrorUnexpected; |
| 2303 | case Decl::EnumConstant: | 2331 | case clang::Decl::EnumConstant: |
| 2304 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant"); | 2332 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant"); |
| 2305 | return ErrorUnexpected; | 2333 | return ErrorUnexpected; |
| 2306 | case Decl::IndirectField: | 2334 | case clang::Decl::IndirectField: |
| 2307 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField"); | 2335 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField"); |
| 2308 | return ErrorUnexpected; | 2336 | return ErrorUnexpected; |
| 2309 | case Decl::OMPDeclareReduction: | 2337 | case clang::Decl::OMPDeclareReduction: |
| 2310 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction"); | 2338 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction"); |
| 2311 | return ErrorUnexpected; | 2339 | return ErrorUnexpected; |
| 2312 | case Decl::UnresolvedUsingValue: | 2340 | case clang::Decl::UnresolvedUsingValue: |
| 2313 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue"); | 2341 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue"); |
| 2314 | return ErrorUnexpected; | 2342 | return ErrorUnexpected; |
| 2315 | case Decl::OMPThreadPrivate: | 2343 | case clang::Decl::OMPThreadPrivate: |
| 2316 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate"); | 2344 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate"); |
| 2317 | return ErrorUnexpected; | 2345 | return ErrorUnexpected; |
| 2318 | case Decl::ObjCPropertyImpl: | 2346 | case clang::Decl::ObjCPropertyImpl: |
| 2319 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl"); | 2347 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl"); |
| 2320 | return ErrorUnexpected; | 2348 | return ErrorUnexpected; |
| 2321 | case Decl::PragmaComment: | 2349 | case clang::Decl::PragmaComment: |
| 2322 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment"); | 2350 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment"); |
| 2323 | return ErrorUnexpected; | 2351 | return ErrorUnexpected; |
| 2324 | case Decl::PragmaDetectMismatch: | 2352 | case clang::Decl::PragmaDetectMismatch: |
| 2325 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch"); | 2353 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch"); |
| 2326 | return ErrorUnexpected; | 2354 | return ErrorUnexpected; |
| 2327 | case Decl::StaticAssert: | 2355 | case clang::Decl::StaticAssert: |
| 2328 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert"); | 2356 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert"); |
| 2329 | return ErrorUnexpected; | 2357 | return ErrorUnexpected; |
| 2330 | case Decl::TranslationUnit: | 2358 | case clang::Decl::TranslationUnit: |
| 2331 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit"); | 2359 | emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit"); |
| 2332 | return ErrorUnexpected; | 2360 | return ErrorUnexpected; |
| 2333 | } | 2361 | } |
| ... | @@ -2354,7 +2382,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) | ... | @@ -2354,7 +2382,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) |
| 2354 | return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast); | 2382 | return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast); |
| 2355 | } | 2383 | } |
| 2356 | 2384 | ||
| 2357 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) { | 2385 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) { |
| 2358 | AstNode *res = trans_expr(c, result_used, scope, expr, lrval); | 2386 | AstNode *res = trans_expr(c, result_used, scope, expr, lrval); |
| 2359 | if (res == nullptr) | 2387 | if (res == nullptr) |
| 2360 | return nullptr; | 2388 | return nullptr; |
| ... | @@ -2391,131 +2419,133 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2391,131 +2419,133 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2391 | } | 2419 | } |
| 2392 | 2420 | ||
| 2393 | 2421 | ||
| 2394 | const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr(); | 2422 | const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr(); |
| 2395 | auto classs = ty->getTypeClass(); | 2423 | auto classs = ty->getTypeClass(); |
| 2396 | switch (classs) { | 2424 | switch (classs) { |
| 2397 | case Type::Builtin: | 2425 | case clang::Type::Builtin: |
| 2398 | { | 2426 | { |
| 2399 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | 2427 | const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty); |
| 2400 | switch (builtin_ty->getKind()) { | 2428 | switch (builtin_ty->getKind()) { |
| 2401 | case BuiltinType::Bool: | 2429 | case clang::BuiltinType::Bool: |
| 2402 | case BuiltinType::Char_U: | 2430 | case clang::BuiltinType::Char_U: |
| 2403 | case BuiltinType::UChar: | 2431 | case clang::BuiltinType::UChar: |
| 2404 | case BuiltinType::Char_S: | 2432 | case clang::BuiltinType::Char_S: |
| 2405 | case BuiltinType::SChar: | 2433 | case clang::BuiltinType::SChar: |
| 2406 | case BuiltinType::UShort: | 2434 | case clang::BuiltinType::UShort: |
| 2407 | case BuiltinType::UInt: | 2435 | case clang::BuiltinType::UInt: |
| 2408 | case BuiltinType::ULong: | 2436 | case clang::BuiltinType::ULong: |
| 2409 | case BuiltinType::ULongLong: | 2437 | case clang::BuiltinType::ULongLong: |
| 2410 | case BuiltinType::Short: | 2438 | case clang::BuiltinType::Short: |
| 2411 | case BuiltinType::Int: | 2439 | case clang::BuiltinType::Int: |
| 2412 | case BuiltinType::Long: | 2440 | case clang::BuiltinType::Long: |
| 2413 | case BuiltinType::LongLong: | 2441 | case clang::BuiltinType::LongLong: |
| 2414 | case BuiltinType::UInt128: | 2442 | case clang::BuiltinType::UInt128: |
| 2415 | case BuiltinType::Int128: | 2443 | case clang::BuiltinType::Int128: |
| 2416 | case BuiltinType::Float: | 2444 | case clang::BuiltinType::Float: |
| 2417 | case BuiltinType::Double: | 2445 | case clang::BuiltinType::Double: |
| 2418 | case BuiltinType::Float128: | 2446 | case clang::BuiltinType::Float128: |
| 2419 | case BuiltinType::LongDouble: | 2447 | case clang::BuiltinType::LongDouble: |
| 2420 | case BuiltinType::WChar_U: | 2448 | case clang::BuiltinType::WChar_U: |
| 2421 | case BuiltinType::Char8: | 2449 | case clang::BuiltinType::Char8: |
| 2422 | case BuiltinType::Char16: | 2450 | case clang::BuiltinType::Char16: |
| 2423 | case BuiltinType::Char32: | 2451 | case clang::BuiltinType::Char32: |
| 2424 | case BuiltinType::WChar_S: | 2452 | case clang::BuiltinType::WChar_S: |
| 2425 | case BuiltinType::Float16: | 2453 | case clang::BuiltinType::Float16: |
| 2426 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); | 2454 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); |
| 2427 | case BuiltinType::NullPtr: | 2455 | case clang::BuiltinType::NullPtr: |
| 2428 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | 2456 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, |
| 2429 | 2457 | trans_create_node_unsigned(c, 0)); | |
| 2430 | case BuiltinType::Void: | 2458 | |
| 2431 | case BuiltinType::Half: | 2459 | case clang::BuiltinType::Void: |
| 2432 | case BuiltinType::ObjCId: | 2460 | case clang::BuiltinType::Half: |
| 2433 | case BuiltinType::ObjCClass: | 2461 | case clang::BuiltinType::ObjCId: |
| 2434 | case BuiltinType::ObjCSel: | 2462 | case clang::BuiltinType::ObjCClass: |
| 2435 | case BuiltinType::OMPArraySection: | 2463 | case clang::BuiltinType::ObjCSel: |
| 2436 | case BuiltinType::Dependent: | 2464 | case clang::BuiltinType::OMPArraySection: |
| 2437 | case BuiltinType::Overload: | 2465 | case clang::BuiltinType::Dependent: |
| 2438 | case BuiltinType::BoundMember: | 2466 | case clang::BuiltinType::Overload: |
| 2439 | case BuiltinType::PseudoObject: | 2467 | case clang::BuiltinType::BoundMember: |
| 2440 | case BuiltinType::UnknownAny: | 2468 | case clang::BuiltinType::PseudoObject: |
| 2441 | case BuiltinType::BuiltinFn: | 2469 | case clang::BuiltinType::UnknownAny: |
| 2442 | case BuiltinType::ARCUnbridgedCast: | 2470 | case clang::BuiltinType::BuiltinFn: |
| 2443 | case BuiltinType::OCLImage1dRO: | 2471 | case clang::BuiltinType::ARCUnbridgedCast: |
| 2444 | case BuiltinType::OCLImage1dArrayRO: | 2472 | case clang::BuiltinType::OCLImage1dRO: |
| 2445 | case BuiltinType::OCLImage1dBufferRO: | 2473 | case clang::BuiltinType::OCLImage1dArrayRO: |
| 2446 | case BuiltinType::OCLImage2dRO: | 2474 | case clang::BuiltinType::OCLImage1dBufferRO: |
| 2447 | case BuiltinType::OCLImage2dArrayRO: | 2475 | case clang::BuiltinType::OCLImage2dRO: |
| 2448 | case BuiltinType::OCLImage2dDepthRO: | 2476 | case clang::BuiltinType::OCLImage2dArrayRO: |
| 2449 | case BuiltinType::OCLImage2dArrayDepthRO: | 2477 | case clang::BuiltinType::OCLImage2dDepthRO: |
| 2450 | case BuiltinType::OCLImage2dMSAARO: | 2478 | case clang::BuiltinType::OCLImage2dArrayDepthRO: |
| 2451 | case BuiltinType::OCLImage2dArrayMSAARO: | 2479 | case clang::BuiltinType::OCLImage2dMSAARO: |
| 2452 | case BuiltinType::OCLImage2dMSAADepthRO: | 2480 | case clang::BuiltinType::OCLImage2dArrayMSAARO: |
| 2453 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | 2481 | case clang::BuiltinType::OCLImage2dMSAADepthRO: |
| 2454 | case BuiltinType::OCLImage3dRO: | 2482 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRO: |
| 2455 | case BuiltinType::OCLImage1dWO: | 2483 | case clang::BuiltinType::OCLImage3dRO: |
| 2456 | case BuiltinType::OCLImage1dArrayWO: | 2484 | case clang::BuiltinType::OCLImage1dWO: |
| 2457 | case BuiltinType::OCLImage1dBufferWO: | 2485 | case clang::BuiltinType::OCLImage1dArrayWO: |
| 2458 | case BuiltinType::OCLImage2dWO: | 2486 | case clang::BuiltinType::OCLImage1dBufferWO: |
| 2459 | case BuiltinType::OCLImage2dArrayWO: | 2487 | case clang::BuiltinType::OCLImage2dWO: |
| 2460 | case BuiltinType::OCLImage2dDepthWO: | 2488 | case clang::BuiltinType::OCLImage2dArrayWO: |
| 2461 | case BuiltinType::OCLImage2dArrayDepthWO: | 2489 | case clang::BuiltinType::OCLImage2dDepthWO: |
| 2462 | case BuiltinType::OCLImage2dMSAAWO: | 2490 | case clang::BuiltinType::OCLImage2dArrayDepthWO: |
| 2463 | case BuiltinType::OCLImage2dArrayMSAAWO: | 2491 | case clang::BuiltinType::OCLImage2dMSAAWO: |
| 2464 | case BuiltinType::OCLImage2dMSAADepthWO: | 2492 | case clang::BuiltinType::OCLImage2dArrayMSAAWO: |
| 2465 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | 2493 | case clang::BuiltinType::OCLImage2dMSAADepthWO: |
| 2466 | case BuiltinType::OCLImage3dWO: | 2494 | case clang::BuiltinType::OCLImage2dArrayMSAADepthWO: |
| 2467 | case BuiltinType::OCLImage1dRW: | 2495 | case clang::BuiltinType::OCLImage3dWO: |
| 2468 | case BuiltinType::OCLImage1dArrayRW: | 2496 | case clang::BuiltinType::OCLImage1dRW: |
| 2469 | case BuiltinType::OCLImage1dBufferRW: | 2497 | case clang::BuiltinType::OCLImage1dArrayRW: |
| 2470 | case BuiltinType::OCLImage2dRW: | 2498 | case clang::BuiltinType::OCLImage1dBufferRW: |
| 2471 | case BuiltinType::OCLImage2dArrayRW: | 2499 | case clang::BuiltinType::OCLImage2dRW: |
| 2472 | case BuiltinType::OCLImage2dDepthRW: | 2500 | case clang::BuiltinType::OCLImage2dArrayRW: |
| 2473 | case BuiltinType::OCLImage2dArrayDepthRW: | 2501 | case clang::BuiltinType::OCLImage2dDepthRW: |
| 2474 | case BuiltinType::OCLImage2dMSAARW: | 2502 | case clang::BuiltinType::OCLImage2dArrayDepthRW: |
| 2475 | case BuiltinType::OCLImage2dArrayMSAARW: | 2503 | case clang::BuiltinType::OCLImage2dMSAARW: |
| 2476 | case BuiltinType::OCLImage2dMSAADepthRW: | 2504 | case clang::BuiltinType::OCLImage2dArrayMSAARW: |
| 2477 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | 2505 | case clang::BuiltinType::OCLImage2dMSAADepthRW: |
| 2478 | case BuiltinType::OCLImage3dRW: | 2506 | case clang::BuiltinType::OCLImage2dArrayMSAADepthRW: |
| 2479 | case BuiltinType::OCLSampler: | 2507 | case clang::BuiltinType::OCLImage3dRW: |
| 2480 | case BuiltinType::OCLEvent: | 2508 | case clang::BuiltinType::OCLSampler: |
| 2481 | case BuiltinType::OCLClkEvent: | 2509 | case clang::BuiltinType::OCLEvent: |
| 2482 | case BuiltinType::OCLQueue: | 2510 | case clang::BuiltinType::OCLClkEvent: |
| 2483 | case BuiltinType::OCLReserveID: | 2511 | case clang::BuiltinType::OCLQueue: |
| 2484 | case BuiltinType::ShortAccum: | 2512 | case clang::BuiltinType::OCLReserveID: |
| 2485 | case BuiltinType::Accum: | 2513 | case clang::BuiltinType::ShortAccum: |
| 2486 | case BuiltinType::LongAccum: | 2514 | case clang::BuiltinType::Accum: |
| 2487 | case BuiltinType::UShortAccum: | 2515 | case clang::BuiltinType::LongAccum: |
| 2488 | case BuiltinType::UAccum: | 2516 | case clang::BuiltinType::UShortAccum: |
| 2489 | case BuiltinType::ULongAccum: | 2517 | case clang::BuiltinType::UAccum: |
| 2490 | case BuiltinType::ShortFract: | 2518 | case clang::BuiltinType::ULongAccum: |
| 2491 | case BuiltinType::Fract: | 2519 | case clang::BuiltinType::ShortFract: |
| 2492 | case BuiltinType::LongFract: | 2520 | case clang::BuiltinType::Fract: |
| 2493 | case BuiltinType::UShortFract: | 2521 | case clang::BuiltinType::LongFract: |
| 2494 | case BuiltinType::UFract: | 2522 | case clang::BuiltinType::UShortFract: |
| 2495 | case BuiltinType::ULongFract: | 2523 | case clang::BuiltinType::UFract: |
| 2496 | case BuiltinType::SatShortAccum: | 2524 | case clang::BuiltinType::ULongFract: |
| 2497 | case BuiltinType::SatAccum: | 2525 | case clang::BuiltinType::SatShortAccum: |
| 2498 | case BuiltinType::SatLongAccum: | 2526 | case clang::BuiltinType::SatAccum: |
| 2499 | case BuiltinType::SatUShortAccum: | 2527 | case clang::BuiltinType::SatLongAccum: |
| 2500 | case BuiltinType::SatUAccum: | 2528 | case clang::BuiltinType::SatUShortAccum: |
| 2501 | case BuiltinType::SatULongAccum: | 2529 | case clang::BuiltinType::SatUAccum: |
| 2502 | case BuiltinType::SatShortFract: | 2530 | case clang::BuiltinType::SatULongAccum: |
| 2503 | case BuiltinType::SatFract: | 2531 | case clang::BuiltinType::SatShortFract: |
| 2504 | case BuiltinType::SatLongFract: | 2532 | case clang::BuiltinType::SatFract: |
| 2505 | case BuiltinType::SatUShortFract: | 2533 | case clang::BuiltinType::SatLongFract: |
| 2506 | case BuiltinType::SatUFract: | 2534 | case clang::BuiltinType::SatUShortFract: |
| 2507 | case BuiltinType::SatULongFract: | 2535 | case clang::BuiltinType::SatUFract: |
| 2536 | case clang::BuiltinType::SatULongFract: | ||
| 2508 | return res; | 2537 | return res; |
| 2509 | } | 2538 | } |
| 2510 | break; | 2539 | break; |
| 2511 | } | 2540 | } |
| 2512 | case Type::Pointer: | 2541 | case clang::Type::Pointer: |
| 2513 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | 2542 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, |
| 2543 | trans_create_node_unsigned(c, 0)); | ||
| 2514 | 2544 | ||
| 2515 | case Type::Typedef: | 2545 | case clang::Type::Typedef: |
| 2516 | { | 2546 | { |
| 2517 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 2547 | const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty); |
| 2518 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 2548 | const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 2519 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); | 2549 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); |
| 2520 | if (existing_entry) { | 2550 | if (existing_entry) { |
| 2521 | return existing_entry->value; | 2551 | return existing_entry->value; |
| ... | @@ -2524,79 +2554,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2524,79 +2554,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope * |
| 2524 | return res; | 2554 | return res; |
| 2525 | } | 2555 | } |
| 2526 | 2556 | ||
| 2527 | case Type::Enum: | 2557 | case clang::Type::Enum: |
| 2528 | { | 2558 | { |
| 2529 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | 2559 | const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty); |
| 2530 | AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl()); | 2560 | AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl()); |
| 2531 | return to_enum_zero_cmp(c, res, enum_type); | 2561 | return to_enum_zero_cmp(c, res, enum_type); |
| 2532 | } | 2562 | } |
| 2533 | 2563 | ||
| 2534 | case Type::Elaborated: | 2564 | case clang::Type::Elaborated: |
| 2535 | { | 2565 | { |
| 2536 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | 2566 | const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty); |
| 2537 | switch (elaborated_ty->getKeyword()) { | 2567 | switch (elaborated_ty->getKeyword()) { |
| 2538 | case ETK_Enum: { | 2568 | case clang::ETK_Enum: { |
| 2539 | AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart()); | 2569 | AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart()); |
| 2540 | return to_enum_zero_cmp(c, res, enum_type); | 2570 | return to_enum_zero_cmp(c, res, enum_type); |
| 2541 | } | 2571 | } |
| 2542 | case ETK_Struct: | 2572 | case clang::ETK_Struct: |
| 2543 | case ETK_Union: | 2573 | case clang::ETK_Union: |
| 2544 | case ETK_Interface: | 2574 | case clang::ETK_Interface: |
| 2545 | case ETK_Class: | 2575 | case clang::ETK_Class: |
| 2546 | case ETK_Typename: | 2576 | case clang::ETK_Typename: |
| 2547 | case ETK_None: | 2577 | case clang::ETK_None: |
| 2548 | return res; | 2578 | return res; |
| 2549 | } | 2579 | } |
| 2550 | } | 2580 | } |
| 2551 | 2581 | ||
| 2552 | case Type::FunctionProto: | 2582 | case clang::Type::FunctionProto: |
| 2553 | case Type::Record: | 2583 | case clang::Type::Record: |
| 2554 | case Type::ConstantArray: | 2584 | case clang::Type::ConstantArray: |
| 2555 | case Type::Paren: | 2585 | case clang::Type::Paren: |
| 2556 | case Type::Decayed: | 2586 | case clang::Type::Decayed: |
| 2557 | case Type::Attributed: | 2587 | case clang::Type::Attributed: |
| 2558 | case Type::IncompleteArray: | 2588 | case clang::Type::IncompleteArray: |
| 2559 | case Type::BlockPointer: | 2589 | case clang::Type::BlockPointer: |
| 2560 | case Type::LValueReference: | 2590 | case clang::Type::LValueReference: |
| 2561 | case Type::RValueReference: | 2591 | case clang::Type::RValueReference: |
| 2562 | case Type::MemberPointer: | 2592 | case clang::Type::MemberPointer: |
| 2563 | case Type::VariableArray: | 2593 | case clang::Type::VariableArray: |
| 2564 | case Type::DependentSizedArray: | 2594 | case clang::Type::DependentSizedArray: |
| 2565 | case Type::DependentSizedExtVector: | 2595 | case clang::Type::DependentSizedExtVector: |
| 2566 | case Type::Vector: | 2596 | case clang::Type::Vector: |
| 2567 | case Type::ExtVector: | 2597 | case clang::Type::ExtVector: |
| 2568 | case Type::FunctionNoProto: | 2598 | case clang::Type::FunctionNoProto: |
| 2569 | case Type::UnresolvedUsing: | 2599 | case clang::Type::UnresolvedUsing: |
| 2570 | case Type::Adjusted: | 2600 | case clang::Type::Adjusted: |
| 2571 | case Type::TypeOfExpr: | 2601 | case clang::Type::TypeOfExpr: |
| 2572 | case Type::TypeOf: | 2602 | case clang::Type::TypeOf: |
| 2573 | case Type::Decltype: | 2603 | case clang::Type::Decltype: |
| 2574 | case Type::UnaryTransform: | 2604 | case clang::Type::UnaryTransform: |
| 2575 | case Type::TemplateTypeParm: | 2605 | case clang::Type::TemplateTypeParm: |
| 2576 | case Type::SubstTemplateTypeParm: | 2606 | case clang::Type::SubstTemplateTypeParm: |
| 2577 | case Type::SubstTemplateTypeParmPack: | 2607 | case clang::Type::SubstTemplateTypeParmPack: |
| 2578 | case Type::TemplateSpecialization: | 2608 | case clang::Type::TemplateSpecialization: |
| 2579 | case Type::Auto: | 2609 | case clang::Type::Auto: |
| 2580 | case Type::InjectedClassName: | 2610 | case clang::Type::InjectedClassName: |
| 2581 | case Type::DependentName: | 2611 | case clang::Type::DependentName: |
| 2582 | case Type::DependentTemplateSpecialization: | 2612 | case clang::Type::DependentTemplateSpecialization: |
| 2583 | case Type::PackExpansion: | 2613 | case clang::Type::PackExpansion: |
| 2584 | case Type::ObjCObject: | 2614 | case clang::Type::ObjCObject: |
| 2585 | case Type::ObjCInterface: | 2615 | case clang::Type::ObjCInterface: |
| 2586 | case Type::Complex: | 2616 | case clang::Type::Complex: |
| 2587 | case Type::ObjCObjectPointer: | 2617 | case clang::Type::ObjCObjectPointer: |
| 2588 | case Type::Atomic: | 2618 | case clang::Type::Atomic: |
| 2589 | case Type::Pipe: | 2619 | case clang::Type::Pipe: |
| 2590 | case Type::ObjCTypeParam: | 2620 | case clang::Type::ObjCTypeParam: |
| 2591 | case Type::DeducedTemplateSpecialization: | 2621 | case clang::Type::DeducedTemplateSpecialization: |
| 2592 | case Type::DependentAddressSpace: | 2622 | case clang::Type::DependentAddressSpace: |
| 2593 | case Type::DependentVector: | 2623 | case clang::Type::DependentVector: |
| 2594 | return res; | 2624 | return res; |
| 2595 | } | 2625 | } |
| 2596 | zig_unreachable(); | 2626 | zig_unreachable(); |
| 2597 | } | 2627 | } |
| 2598 | 2628 | ||
| 2599 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { | 2629 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) { |
| 2600 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); | 2630 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 2601 | 2631 | ||
| 2602 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); | 2632 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| ... | @@ -2611,7 +2641,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt | ... | @@ -2611,7 +2641,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt |
| 2611 | return while_scope->node; | 2641 | return while_scope->node; |
| 2612 | } | 2642 | } |
| 2613 | 2643 | ||
| 2614 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) { | 2644 | static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::IfStmt *stmt) { |
| 2615 | // if (c) t | 2645 | // if (c) t |
| 2616 | // if (c) t else e | 2646 | // if (c) t else e |
| 2617 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); | 2647 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| ... | @@ -2633,7 +2663,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2633,7 +2663,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2633 | return if_node; | 2663 | return if_node; |
| 2634 | } | 2664 | } |
| 2635 | 2665 | ||
| 2636 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { | 2666 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) { |
| 2637 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | 2667 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 2638 | 2668 | ||
| 2639 | AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue); | 2669 | AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue); |
| ... | @@ -2641,16 +2671,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2641,16 +2671,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2641 | return nullptr; | 2671 | return nullptr; |
| 2642 | 2672 | ||
| 2643 | bool is_ptr = false; | 2673 | bool is_ptr = false; |
| 2644 | const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr); | 2674 | const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr); |
| 2645 | AstNode *callee_node = nullptr; | 2675 | AstNode *callee_node = nullptr; |
| 2646 | if (is_ptr && fn_ty) { | 2676 | if (is_ptr && fn_ty) { |
| 2647 | if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) { | 2677 | if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) { |
| 2648 | const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee()); | 2678 | const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee()); |
| 2649 | if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) { | 2679 | if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) { |
| 2650 | if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) { | 2680 | if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) { |
| 2651 | const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr()); | 2681 | const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr()); |
| 2652 | const Decl *decl = decl_ref->getFoundDecl(); | 2682 | const clang::Decl *decl = decl_ref->getFoundDecl(); |
| 2653 | if (decl->getKind() == Decl::Function) { | 2683 | if (decl->getKind() == clang::Decl::Function) { |
| 2654 | callee_node = callee_raw_node; | 2684 | callee_node = callee_raw_node; |
| 2655 | } | 2685 | } |
| 2656 | } | 2686 | } |
| ... | @@ -2666,7 +2696,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2666,7 +2696,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2666 | node->data.fn_call_expr.fn_ref_expr = callee_node; | 2696 | node->data.fn_call_expr.fn_ref_expr = callee_node; |
| 2667 | 2697 | ||
| 2668 | unsigned num_args = stmt->getNumArgs(); | 2698 | unsigned num_args = stmt->getNumArgs(); |
| 2669 | const Expr * const* args = stmt->getArgs(); | 2699 | const clang::Expr * const* args = stmt->getArgs(); |
| 2670 | for (unsigned i = 0; i < num_args; i += 1) { | 2700 | for (unsigned i = 0; i < num_args; i += 1) { |
| 2671 | AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue); | 2701 | AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue); |
| 2672 | if (arg_node == nullptr) | 2702 | if (arg_node == nullptr) |
| ... | @@ -2682,7 +2712,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2682,7 +2712,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2682 | return node; | 2712 | return node; |
| 2683 | } | 2713 | } |
| 2684 | 2714 | ||
| 2685 | static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) { | 2715 | static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) { |
| 2686 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); | 2716 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2687 | if (container_node == nullptr) | 2717 | if (container_node == nullptr) |
| 2688 | return nullptr; | 2718 | return nullptr; |
| ... | @@ -2697,7 +2727,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp | ... | @@ -2697,7 +2727,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp |
| 2697 | return node; | 2727 | return node; |
| 2698 | } | 2728 | } |
| 2699 | 2729 | ||
| 2700 | static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) { | 2730 | static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) { |
| 2701 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); | 2731 | AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); |
| 2702 | if (container_node == nullptr) | 2732 | if (container_node == nullptr) |
| 2703 | return nullptr; | 2733 | return nullptr; |
| ... | @@ -2714,7 +2744,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const | ... | @@ -2714,7 +2744,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const |
| 2714 | } | 2744 | } |
| 2715 | 2745 | ||
| 2716 | static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, | 2746 | static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, |
| 2717 | const CStyleCastExpr *stmt, TransLRValue lrvalue) | 2747 | const clang::CStyleCastExpr *stmt, TransLRValue lrvalue) |
| 2718 | { | 2748 | { |
| 2719 | AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue); | 2749 | AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue); |
| 2720 | if (sub_expr_node == nullptr) | 2750 | if (sub_expr_node == nullptr) |
| ... | @@ -2724,7 +2754,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran | ... | @@ -2724,7 +2754,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran |
| 2724 | } | 2754 | } |
| 2725 | 2755 | ||
| 2726 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, | 2756 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, |
| 2727 | const UnaryExprOrTypeTraitExpr *stmt) | 2757 | const clang::UnaryExprOrTypeTraitExpr *stmt) |
| 2728 | { | 2758 | { |
| 2729 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); | 2759 | AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); |
| 2730 | if (type_node == nullptr) | 2760 | if (type_node == nullptr) |
| ... | @@ -2735,14 +2765,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop | ... | @@ -2735,14 +2765,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop |
| 2735 | return node; | 2765 | return node; |
| 2736 | } | 2766 | } |
| 2737 | 2767 | ||
| 2738 | static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) { | 2768 | static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) { |
| 2739 | TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope); | 2769 | TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope); |
| 2740 | 2770 | ||
| 2741 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); | 2771 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2742 | 2772 | ||
| 2743 | AstNode *body_node; | 2773 | AstNode *body_node; |
| 2744 | TransScope *child_scope; | 2774 | TransScope *child_scope; |
| 2745 | if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) { | 2775 | if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) { |
| 2746 | // there's already a block in C, so we'll append our condition to it. | 2776 | // there's already a block in C, so we'll append our condition to it. |
| 2747 | // c: do { | 2777 | // c: do { |
| 2748 | // c: a; | 2778 | // c: a; |
| ... | @@ -2795,11 +2825,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt | ... | @@ -2795,11 +2825,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt |
| 2795 | return while_scope->node; | 2825 | return while_scope->node; |
| 2796 | } | 2826 | } |
| 2797 | 2827 | ||
| 2798 | static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) { | 2828 | static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang::ForStmt *stmt) { |
| 2799 | AstNode *loop_block_node; | 2829 | AstNode *loop_block_node; |
| 2800 | TransScopeWhile *while_scope; | 2830 | TransScopeWhile *while_scope; |
| 2801 | TransScope *cond_scope; | 2831 | TransScope *cond_scope; |
| 2802 | const Stmt *init_stmt = stmt->getInit(); | 2832 | const clang::Stmt *init_stmt = stmt->getInit(); |
| 2803 | if (init_stmt == nullptr) { | 2833 | if (init_stmt == nullptr) { |
| 2804 | while_scope = trans_scope_while_create(c, parent_scope); | 2834 | while_scope = trans_scope_while_create(c, parent_scope); |
| 2805 | loop_block_node = while_scope->node; | 2835 | loop_block_node = while_scope->node; |
| ... | @@ -2820,12 +2850,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt | ... | @@ -2820,12 +2850,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2820 | child_scope->node->data.block.statements.append(while_scope->node); | 2850 | child_scope->node->data.block.statements.append(while_scope->node); |
| 2821 | } | 2851 | } |
| 2822 | 2852 | ||
| 2823 | const Stmt *cond_stmt = stmt->getCond(); | 2853 | const clang::Stmt *cond_stmt = stmt->getCond(); |
| 2824 | if (cond_stmt == nullptr) { | 2854 | if (cond_stmt == nullptr) { |
| 2825 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); | 2855 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2826 | } else { | 2856 | } else { |
| 2827 | if (Expr::classof(cond_stmt)) { | 2857 | if (clang::Expr::classof(cond_stmt)) { |
| 2828 | const Expr *cond_expr = static_cast<const Expr*>(cond_stmt); | 2858 | const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt); |
| 2829 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue); | 2859 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue); |
| 2830 | 2860 | ||
| 2831 | if (while_scope->node->data.while_expr.condition == nullptr) | 2861 | if (while_scope->node->data.while_expr.condition == nullptr) |
| ... | @@ -2838,7 +2868,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt | ... | @@ -2838,7 +2868,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2838 | } | 2868 | } |
| 2839 | } | 2869 | } |
| 2840 | 2870 | ||
| 2841 | const Stmt *inc_stmt = stmt->getInc(); | 2871 | const clang::Stmt *inc_stmt = stmt->getInc(); |
| 2842 | if (inc_stmt != nullptr) { | 2872 | if (inc_stmt != nullptr) { |
| 2843 | AstNode *inc_node; | 2873 | AstNode *inc_node; |
| 2844 | TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node); | 2874 | TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node); |
| ... | @@ -2861,12 +2891,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt | ... | @@ -2861,12 +2891,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2861 | return loop_block_node; | 2891 | return loop_block_node; |
| 2862 | } | 2892 | } |
| 2863 | 2893 | ||
| 2864 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { | 2894 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const clang::SwitchStmt *stmt) { |
| 2865 | TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope); | 2895 | TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope); |
| 2866 | 2896 | ||
| 2867 | TransScopeSwitch *switch_scope; | 2897 | TransScopeSwitch *switch_scope; |
| 2868 | 2898 | ||
| 2869 | const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); | 2899 | const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); |
| 2870 | if (var_decl_stmt == nullptr) { | 2900 | if (var_decl_stmt == nullptr) { |
| 2871 | switch_scope = trans_scope_switch_create(c, &block_scope->base); | 2901 | switch_scope = trans_scope_switch_create(c, &block_scope->base); |
| 2872 | } else { | 2902 | } else { |
| ... | @@ -2885,7 +2915,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw | ... | @@ -2885,7 +2915,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2885 | switch_scope->end_label_name = end_label_name; | 2915 | switch_scope->end_label_name = end_label_name; |
| 2886 | block_scope->node->data.block.name = end_label_name; | 2916 | block_scope->node->data.block.name = end_label_name; |
| 2887 | 2917 | ||
| 2888 | const Expr *cond_expr = stmt->getCond(); | 2918 | const clang::Expr *cond_expr = stmt->getCond(); |
| 2889 | assert(cond_expr != nullptr); | 2919 | assert(cond_expr != nullptr); |
| 2890 | 2920 | ||
| 2891 | AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue); | 2921 | AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue); |
| ... | @@ -2894,9 +2924,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw | ... | @@ -2894,9 +2924,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw |
| 2894 | switch_scope->switch_node->data.switch_expr.expr = expr_node; | 2924 | switch_scope->switch_node->data.switch_expr.expr = expr_node; |
| 2895 | 2925 | ||
| 2896 | AstNode *body_node; | 2926 | AstNode *body_node; |
| 2897 | const Stmt *body_stmt = stmt->getBody(); | 2927 | const clang::Stmt *body_stmt = stmt->getBody(); |
| 2898 | if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) { | 2928 | if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) { |
| 2899 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt, | 2929 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt, |
| 2900 | block_scope->node, nullptr)) | 2930 | block_scope->node, nullptr)) |
| 2901 | { | 2931 | { |
| 2902 | return nullptr; | 2932 | return nullptr; |
| ... | @@ -2928,7 +2958,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) { | ... | @@ -2928,7 +2958,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) { |
| 2928 | return nullptr; | 2958 | return nullptr; |
| 2929 | } | 2959 | } |
| 2930 | 2960 | ||
| 2931 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, | 2961 | static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::CaseStmt *stmt, AstNode **out_node, |
| 2932 | TransScope **out_scope) { | 2962 | TransScope **out_scope) { |
| 2933 | *out_node = nullptr; | 2963 | *out_node = nullptr; |
| 2934 | 2964 | ||
| ... | @@ -2973,7 +3003,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm | ... | @@ -2973,7 +3003,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm |
| 2973 | return ErrorNone; | 3003 | return ErrorNone; |
| 2974 | } | 3004 | } |
| 2975 | 3005 | ||
| 2976 | static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node, | 3006 | static int trans_switch_default(Context *c, TransScope *parent_scope, const clang::DefaultStmt *stmt, AstNode **out_node, |
| 2977 | TransScope **out_scope) | 3007 | TransScope **out_scope) |
| 2978 | { | 3008 | { |
| 2979 | *out_node = nullptr; | 3009 | *out_node = nullptr; |
| ... | @@ -3010,25 +3040,25 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa | ... | @@ -3010,25 +3040,25 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa |
| 3010 | return ErrorNone; | 3040 | return ErrorNone; |
| 3011 | } | 3041 | } |
| 3012 | 3042 | ||
| 3013 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) { | 3043 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) { |
| 3014 | switch (stmt->getKind()) { | 3044 | switch (stmt->getKind()) { |
| 3015 | case StringLiteral::Ascii: | 3045 | case clang::StringLiteral::Ascii: |
| 3016 | case StringLiteral::UTF8: | 3046 | case clang::StringLiteral::UTF8: |
| 3017 | return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString())); | 3047 | return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString())); |
| 3018 | case StringLiteral::UTF16: | 3048 | case clang::StringLiteral::UTF16: |
| 3019 | emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals"); | 3049 | emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals"); |
| 3020 | return nullptr; | 3050 | return nullptr; |
| 3021 | case StringLiteral::UTF32: | 3051 | case clang::StringLiteral::UTF32: |
| 3022 | emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals"); | 3052 | emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals"); |
| 3023 | return nullptr; | 3053 | return nullptr; |
| 3024 | case StringLiteral::Wide: | 3054 | case clang::StringLiteral::Wide: |
| 3025 | emit_warning(c, stmt->getLocStart(), "TODO support wide string literals"); | 3055 | emit_warning(c, stmt->getLocStart(), "TODO support wide string literals"); |
| 3026 | return nullptr; | 3056 | return nullptr; |
| 3027 | } | 3057 | } |
| 3028 | zig_unreachable(); | 3058 | zig_unreachable(); |
| 3029 | } | 3059 | } |
| 3030 | 3060 | ||
| 3031 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) { | 3061 | static AstNode *trans_break_stmt(Context *c, TransScope *scope, const clang::BreakStmt *stmt) { |
| 3032 | TransScope *cur_scope = scope; | 3062 | TransScope *cur_scope = scope; |
| 3033 | while (cur_scope != nullptr) { | 3063 | while (cur_scope != nullptr) { |
| 3034 | if (cur_scope->id == TransScopeIdWhile) { | 3064 | if (cur_scope->id == TransScopeIdWhile) { |
| ... | @@ -3042,7 +3072,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt | ... | @@ -3042,7 +3072,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt |
| 3042 | zig_unreachable(); | 3072 | zig_unreachable(); |
| 3043 | } | 3073 | } |
| 3044 | 3074 | ||
| 3045 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) { | 3075 | static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::ContinueStmt *stmt) { |
| 3046 | return trans_create_node(c, NodeTypeContinue); | 3076 | return trans_create_node(c, NodeTypeContinue); |
| 3047 | } | 3077 | } |
| 3048 | 3078 | ||
| ... | @@ -3055,47 +3085,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_ | ... | @@ -3055,47 +3085,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_ |
| 3055 | return ErrorNone; | 3085 | return ErrorNone; |
| 3056 | } | 3086 | } |
| 3057 | 3087 | ||
| 3058 | static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | 3088 | static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt, |
| 3059 | ResultUsed result_used, TransLRValue lrvalue, | 3089 | ResultUsed result_used, TransLRValue lrvalue, |
| 3060 | AstNode **out_node, TransScope **out_child_scope, | 3090 | AstNode **out_node, TransScope **out_child_scope, |
| 3061 | TransScope **out_node_scope) | 3091 | TransScope **out_node_scope) |
| 3062 | { | 3092 | { |
| 3063 | Stmt::StmtClass sc = stmt->getStmtClass(); | 3093 | clang::Stmt::StmtClass sc = stmt->getStmtClass(); |
| 3064 | switch (sc) { | 3094 | switch (sc) { |
| 3065 | case Stmt::ReturnStmtClass: | 3095 | case clang::Stmt::ReturnStmtClass: |
| 3066 | return wrap_stmt(out_node, out_child_scope, scope, | 3096 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3067 | trans_return_stmt(c, scope, (const ReturnStmt *)stmt)); | 3097 | trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt)); |
| 3068 | case Stmt::CompoundStmtClass: | 3098 | case clang::Stmt::CompoundStmtClass: |
| 3069 | return wrap_stmt(out_node, out_child_scope, scope, | 3099 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3070 | trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope)); | 3100 | trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope)); |
| 3071 | case Stmt::IntegerLiteralClass: | 3101 | case clang::Stmt::IntegerLiteralClass: |
| 3072 | return wrap_stmt(out_node, out_child_scope, scope, | 3102 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3073 | trans_integer_literal(c, (const IntegerLiteral *)stmt)); | 3103 | trans_integer_literal(c, (const clang::IntegerLiteral *)stmt)); |
| 3074 | case Stmt::ConditionalOperatorClass: | 3104 | case clang::Stmt::ConditionalOperatorClass: |
| 3075 | return wrap_stmt(out_node, out_child_scope, scope, | 3105 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3076 | trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt)); | 3106 | trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt)); |
| 3077 | case Stmt::BinaryOperatorClass: | 3107 | case clang::Stmt::BinaryOperatorClass: |
| 3078 | return wrap_stmt(out_node, out_child_scope, scope, | 3108 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3079 | trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt)); | 3109 | trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt)); |
| 3080 | case Stmt::CompoundAssignOperatorClass: | 3110 | case clang::Stmt::CompoundAssignOperatorClass: |
| 3081 | return wrap_stmt(out_node, out_child_scope, scope, | 3111 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3082 | trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt)); | 3112 | trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt)); |
| 3083 | case Stmt::ImplicitCastExprClass: | 3113 | case clang::Stmt::ImplicitCastExprClass: |
| 3084 | return wrap_stmt(out_node, out_child_scope, scope, | 3114 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3085 | trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt)); | 3115 | trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt)); |
| 3086 | case Stmt::DeclRefExprClass: | 3116 | case clang::Stmt::DeclRefExprClass: |
| 3087 | return wrap_stmt(out_node, out_child_scope, scope, | 3117 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3088 | trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue)); | 3118 | trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue)); |
| 3089 | case Stmt::UnaryOperatorClass: | 3119 | case clang::Stmt::UnaryOperatorClass: |
| 3090 | return wrap_stmt(out_node, out_child_scope, scope, | 3120 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3091 | trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt)); | 3121 | trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt)); |
| 3092 | case Stmt::DeclStmtClass: | 3122 | case clang::Stmt::DeclStmtClass: |
| 3093 | return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope); | 3123 | return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope); |
| 3094 | case Stmt::DoStmtClass: | 3124 | case clang::Stmt::DoStmtClass: |
| 3095 | case Stmt::WhileStmtClass: { | 3125 | case clang::Stmt::WhileStmtClass: { |
| 3096 | AstNode *while_node = sc == Stmt::DoStmtClass | 3126 | AstNode *while_node = sc == clang::Stmt::DoStmtClass |
| 3097 | ? trans_do_loop(c, scope, (const DoStmt *)stmt) | 3127 | ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt) |
| 3098 | : trans_while_loop(c, scope, (const WhileStmt *)stmt); | 3128 | : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt); |
| 3099 | 3129 | ||
| 3100 | if (while_node == nullptr) | 3130 | if (while_node == nullptr) |
| 3101 | return ErrorUnexpected; | 3131 | return ErrorUnexpected; |
| ... | @@ -3106,556 +3136,556 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | ... | @@ -3106,556 +3136,556 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 3106 | 3136 | ||
| 3107 | return wrap_stmt(out_node, out_child_scope, scope, while_node); | 3137 | return wrap_stmt(out_node, out_child_scope, scope, while_node); |
| 3108 | } | 3138 | } |
| 3109 | case Stmt::IfStmtClass: | 3139 | case clang::Stmt::IfStmtClass: |
| 3110 | return wrap_stmt(out_node, out_child_scope, scope, | 3140 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3111 | trans_if_statement(c, scope, (const IfStmt *)stmt)); | 3141 | trans_if_statement(c, scope, (const clang::IfStmt *)stmt)); |
| 3112 | case Stmt::CallExprClass: | 3142 | case clang::Stmt::CallExprClass: |
| 3113 | return wrap_stmt(out_node, out_child_scope, scope, | 3143 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3114 | trans_call_expr(c, result_used, scope, (const CallExpr *)stmt)); | 3144 | trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt)); |
| 3115 | case Stmt::NullStmtClass: | 3145 | case clang::Stmt::NullStmtClass: |
| 3116 | *out_node = nullptr; | 3146 | *out_node = nullptr; |
| 3117 | *out_child_scope = scope; | 3147 | *out_child_scope = scope; |
| 3118 | return ErrorNone; | 3148 | return ErrorNone; |
| 3119 | case Stmt::MemberExprClass: | 3149 | case clang::Stmt::MemberExprClass: |
| 3120 | return wrap_stmt(out_node, out_child_scope, scope, | 3150 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3121 | trans_member_expr(c, scope, (const MemberExpr *)stmt)); | 3151 | trans_member_expr(c, scope, (const clang::MemberExpr *)stmt)); |
| 3122 | case Stmt::ArraySubscriptExprClass: | 3152 | case clang::Stmt::ArraySubscriptExprClass: |
| 3123 | return wrap_stmt(out_node, out_child_scope, scope, | 3153 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3124 | trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt)); | 3154 | trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt)); |
| 3125 | case Stmt::CStyleCastExprClass: | 3155 | case clang::Stmt::CStyleCastExprClass: |
| 3126 | return wrap_stmt(out_node, out_child_scope, scope, | 3156 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3127 | trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue)); | 3157 | trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue)); |
| 3128 | case Stmt::UnaryExprOrTypeTraitExprClass: | 3158 | case clang::Stmt::UnaryExprOrTypeTraitExprClass: |
| 3129 | return wrap_stmt(out_node, out_child_scope, scope, | 3159 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3130 | trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt)); | 3160 | trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt)); |
| 3131 | case Stmt::ForStmtClass: { | 3161 | case clang::Stmt::ForStmtClass: { |
| 3132 | AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt); | 3162 | AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt); |
| 3133 | return wrap_stmt(out_node, out_child_scope, scope, node); | 3163 | return wrap_stmt(out_node, out_child_scope, scope, node); |
| 3134 | } | 3164 | } |
| 3135 | case Stmt::StringLiteralClass: | 3165 | case clang::Stmt::StringLiteralClass: |
| 3136 | return wrap_stmt(out_node, out_child_scope, scope, | 3166 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3137 | trans_string_literal(c, scope, (const StringLiteral *)stmt)); | 3167 | trans_string_literal(c, scope, (const clang::StringLiteral *)stmt)); |
| 3138 | case Stmt::BreakStmtClass: | 3168 | case clang::Stmt::BreakStmtClass: |
| 3139 | return wrap_stmt(out_node, out_child_scope, scope, | 3169 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3140 | trans_break_stmt(c, scope, (const BreakStmt *)stmt)); | 3170 | trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt)); |
| 3141 | case Stmt::ContinueStmtClass: | 3171 | case clang::Stmt::ContinueStmtClass: |
| 3142 | return wrap_stmt(out_node, out_child_scope, scope, | 3172 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3143 | trans_continue_stmt(c, scope, (const ContinueStmt *)stmt)); | 3173 | trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt)); |
| 3144 | case Stmt::ParenExprClass: | 3174 | case clang::Stmt::ParenExprClass: |
| 3145 | return wrap_stmt(out_node, out_child_scope, scope, | 3175 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3146 | trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue)); | 3176 | trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue)); |
| 3147 | case Stmt::SwitchStmtClass: | 3177 | case clang::Stmt::SwitchStmtClass: |
| 3148 | return wrap_stmt(out_node, out_child_scope, scope, | 3178 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3149 | trans_switch_stmt(c, scope, (const SwitchStmt *)stmt)); | 3179 | trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt)); |
| 3150 | case Stmt::CaseStmtClass: | 3180 | case clang::Stmt::CaseStmtClass: |
| 3151 | return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope); | 3181 | return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope); |
| 3152 | case Stmt::DefaultStmtClass: | 3182 | case clang::Stmt::DefaultStmtClass: |
| 3153 | return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope); | 3183 | return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope); |
| 3154 | case Stmt::NoStmtClass: | 3184 | case clang::Stmt::NoStmtClass: |
| 3155 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); | 3185 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); |
| 3156 | return ErrorUnexpected; | 3186 | return ErrorUnexpected; |
| 3157 | case Stmt::GCCAsmStmtClass: | 3187 | case clang::Stmt::GCCAsmStmtClass: |
| 3158 | emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass"); | 3188 | emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass"); |
| 3159 | return ErrorUnexpected; | 3189 | return ErrorUnexpected; |
| 3160 | case Stmt::MSAsmStmtClass: | 3190 | case clang::Stmt::MSAsmStmtClass: |
| 3161 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass"); | 3191 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass"); |
| 3162 | return ErrorUnexpected; | 3192 | return ErrorUnexpected; |
| 3163 | case Stmt::AttributedStmtClass: | 3193 | case clang::Stmt::AttributedStmtClass: |
| 3164 | emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass"); | 3194 | emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass"); |
| 3165 | return ErrorUnexpected; | 3195 | return ErrorUnexpected; |
| 3166 | case Stmt::CXXCatchStmtClass: | 3196 | case clang::Stmt::CXXCatchStmtClass: |
| 3167 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass"); | 3197 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass"); |
| 3168 | return ErrorUnexpected; | 3198 | return ErrorUnexpected; |
| 3169 | case Stmt::CXXForRangeStmtClass: | 3199 | case clang::Stmt::CXXForRangeStmtClass: |
| 3170 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass"); | 3200 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass"); |
| 3171 | return ErrorUnexpected; | 3201 | return ErrorUnexpected; |
| 3172 | case Stmt::CXXTryStmtClass: | 3202 | case clang::Stmt::CXXTryStmtClass: |
| 3173 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass"); | 3203 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass"); |
| 3174 | return ErrorUnexpected; | 3204 | return ErrorUnexpected; |
| 3175 | case Stmt::CapturedStmtClass: | 3205 | case clang::Stmt::CapturedStmtClass: |
| 3176 | emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass"); | 3206 | emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass"); |
| 3177 | return ErrorUnexpected; | 3207 | return ErrorUnexpected; |
| 3178 | case Stmt::CoreturnStmtClass: | 3208 | case clang::Stmt::CoreturnStmtClass: |
| 3179 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass"); | 3209 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass"); |
| 3180 | return ErrorUnexpected; | 3210 | return ErrorUnexpected; |
| 3181 | case Stmt::CoroutineBodyStmtClass: | 3211 | case clang::Stmt::CoroutineBodyStmtClass: |
| 3182 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass"); | 3212 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass"); |
| 3183 | return ErrorUnexpected; | 3213 | return ErrorUnexpected; |
| 3184 | case Stmt::BinaryConditionalOperatorClass: | 3214 | case clang::Stmt::BinaryConditionalOperatorClass: |
| 3185 | emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass"); | 3215 | emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass"); |
| 3186 | return ErrorUnexpected; | 3216 | return ErrorUnexpected; |
| 3187 | case Stmt::AddrLabelExprClass: | 3217 | case clang::Stmt::AddrLabelExprClass: |
| 3188 | emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass"); | 3218 | emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass"); |
| 3189 | return ErrorUnexpected; | 3219 | return ErrorUnexpected; |
| 3190 | case Stmt::ArrayInitIndexExprClass: | 3220 | case clang::Stmt::ArrayInitIndexExprClass: |
| 3191 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass"); | 3221 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass"); |
| 3192 | return ErrorUnexpected; | 3222 | return ErrorUnexpected; |
| 3193 | case Stmt::ArrayInitLoopExprClass: | 3223 | case clang::Stmt::ArrayInitLoopExprClass: |
| 3194 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass"); | 3224 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass"); |
| 3195 | return ErrorUnexpected; | 3225 | return ErrorUnexpected; |
| 3196 | case Stmt::ArrayTypeTraitExprClass: | 3226 | case clang::Stmt::ArrayTypeTraitExprClass: |
| 3197 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass"); | 3227 | emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass"); |
| 3198 | return ErrorUnexpected; | 3228 | return ErrorUnexpected; |
| 3199 | case Stmt::AsTypeExprClass: | 3229 | case clang::Stmt::AsTypeExprClass: |
| 3200 | emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass"); | 3230 | emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass"); |
| 3201 | return ErrorUnexpected; | 3231 | return ErrorUnexpected; |
| 3202 | case Stmt::AtomicExprClass: | 3232 | case clang::Stmt::AtomicExprClass: |
| 3203 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); | 3233 | emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass"); |
| 3204 | return ErrorUnexpected; | 3234 | return ErrorUnexpected; |
| 3205 | case Stmt::BlockExprClass: | 3235 | case clang::Stmt::BlockExprClass: |
| 3206 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); | 3236 | emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass"); |
| 3207 | return ErrorUnexpected; | 3237 | return ErrorUnexpected; |
| 3208 | case Stmt::CXXBindTemporaryExprClass: | 3238 | case clang::Stmt::CXXBindTemporaryExprClass: |
| 3209 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass"); | 3239 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass"); |
| 3210 | return ErrorUnexpected; | 3240 | return ErrorUnexpected; |
| 3211 | case Stmt::CXXBoolLiteralExprClass: | 3241 | case clang::Stmt::CXXBoolLiteralExprClass: |
| 3212 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass"); | 3242 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass"); |
| 3213 | return ErrorUnexpected; | 3243 | return ErrorUnexpected; |
| 3214 | case Stmt::CXXConstructExprClass: | 3244 | case clang::Stmt::CXXConstructExprClass: |
| 3215 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass"); | 3245 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass"); |
| 3216 | return ErrorUnexpected; | 3246 | return ErrorUnexpected; |
| 3217 | case Stmt::CXXTemporaryObjectExprClass: | 3247 | case clang::Stmt::CXXTemporaryObjectExprClass: |
| 3218 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass"); | 3248 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass"); |
| 3219 | return ErrorUnexpected; | 3249 | return ErrorUnexpected; |
| 3220 | case Stmt::CXXDefaultArgExprClass: | 3250 | case clang::Stmt::CXXDefaultArgExprClass: |
| 3221 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass"); | 3251 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass"); |
| 3222 | return ErrorUnexpected; | 3252 | return ErrorUnexpected; |
| 3223 | case Stmt::CXXDefaultInitExprClass: | 3253 | case clang::Stmt::CXXDefaultInitExprClass: |
| 3224 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass"); | 3254 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass"); |
| 3225 | return ErrorUnexpected; | 3255 | return ErrorUnexpected; |
| 3226 | case Stmt::CXXDeleteExprClass: | 3256 | case clang::Stmt::CXXDeleteExprClass: |
| 3227 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass"); | 3257 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass"); |
| 3228 | return ErrorUnexpected; | 3258 | return ErrorUnexpected; |
| 3229 | case Stmt::CXXDependentScopeMemberExprClass: | 3259 | case clang::Stmt::CXXDependentScopeMemberExprClass: |
| 3230 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass"); | 3260 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass"); |
| 3231 | return ErrorUnexpected; | 3261 | return ErrorUnexpected; |
| 3232 | case Stmt::CXXFoldExprClass: | 3262 | case clang::Stmt::CXXFoldExprClass: |
| 3233 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass"); | 3263 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass"); |
| 3234 | return ErrorUnexpected; | 3264 | return ErrorUnexpected; |
| 3235 | case Stmt::CXXInheritedCtorInitExprClass: | 3265 | case clang::Stmt::CXXInheritedCtorInitExprClass: |
| 3236 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass"); | 3266 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass"); |
| 3237 | return ErrorUnexpected; | 3267 | return ErrorUnexpected; |
| 3238 | case Stmt::CXXNewExprClass: | 3268 | case clang::Stmt::CXXNewExprClass: |
| 3239 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass"); | 3269 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass"); |
| 3240 | return ErrorUnexpected; | 3270 | return ErrorUnexpected; |
| 3241 | case Stmt::CXXNoexceptExprClass: | 3271 | case clang::Stmt::CXXNoexceptExprClass: |
| 3242 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass"); | 3272 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass"); |
| 3243 | return ErrorUnexpected; | 3273 | return ErrorUnexpected; |
| 3244 | case Stmt::CXXNullPtrLiteralExprClass: | 3274 | case clang::Stmt::CXXNullPtrLiteralExprClass: |
| 3245 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass"); | 3275 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass"); |
| 3246 | return ErrorUnexpected; | 3276 | return ErrorUnexpected; |
| 3247 | case Stmt::CXXPseudoDestructorExprClass: | 3277 | case clang::Stmt::CXXPseudoDestructorExprClass: |
| 3248 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass"); | 3278 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass"); |
| 3249 | return ErrorUnexpected; | 3279 | return ErrorUnexpected; |
| 3250 | case Stmt::CXXScalarValueInitExprClass: | 3280 | case clang::Stmt::CXXScalarValueInitExprClass: |
| 3251 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass"); | 3281 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass"); |
| 3252 | return ErrorUnexpected; | 3282 | return ErrorUnexpected; |
| 3253 | case Stmt::CXXStdInitializerListExprClass: | 3283 | case clang::Stmt::CXXStdInitializerListExprClass: |
| 3254 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass"); | 3284 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass"); |
| 3255 | return ErrorUnexpected; | 3285 | return ErrorUnexpected; |
| 3256 | case Stmt::CXXThisExprClass: | 3286 | case clang::Stmt::CXXThisExprClass: |
| 3257 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass"); | 3287 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass"); |
| 3258 | return ErrorUnexpected; | 3288 | return ErrorUnexpected; |
| 3259 | case Stmt::CXXThrowExprClass: | 3289 | case clang::Stmt::CXXThrowExprClass: |
| 3260 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass"); | 3290 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass"); |
| 3261 | return ErrorUnexpected; | 3291 | return ErrorUnexpected; |
| 3262 | case Stmt::CXXTypeidExprClass: | 3292 | case clang::Stmt::CXXTypeidExprClass: |
| 3263 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass"); | 3293 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass"); |
| 3264 | return ErrorUnexpected; | 3294 | return ErrorUnexpected; |
| 3265 | case Stmt::CXXUnresolvedConstructExprClass: | 3295 | case clang::Stmt::CXXUnresolvedConstructExprClass: |
| 3266 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass"); | 3296 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass"); |
| 3267 | return ErrorUnexpected; | 3297 | return ErrorUnexpected; |
| 3268 | case Stmt::CXXUuidofExprClass: | 3298 | case clang::Stmt::CXXUuidofExprClass: |
| 3269 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass"); | 3299 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass"); |
| 3270 | return ErrorUnexpected; | 3300 | return ErrorUnexpected; |
| 3271 | case Stmt::CUDAKernelCallExprClass: | 3301 | case clang::Stmt::CUDAKernelCallExprClass: |
| 3272 | emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass"); | 3302 | emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass"); |
| 3273 | return ErrorUnexpected; | 3303 | return ErrorUnexpected; |
| 3274 | case Stmt::CXXMemberCallExprClass: | 3304 | case clang::Stmt::CXXMemberCallExprClass: |
| 3275 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass"); | 3305 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass"); |
| 3276 | return ErrorUnexpected; | 3306 | return ErrorUnexpected; |
| 3277 | case Stmt::CXXOperatorCallExprClass: | 3307 | case clang::Stmt::CXXOperatorCallExprClass: |
| 3278 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass"); | 3308 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass"); |
| 3279 | return ErrorUnexpected; | 3309 | return ErrorUnexpected; |
| 3280 | case Stmt::UserDefinedLiteralClass: | 3310 | case clang::Stmt::UserDefinedLiteralClass: |
| 3281 | emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass"); | 3311 | emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass"); |
| 3282 | return ErrorUnexpected; | 3312 | return ErrorUnexpected; |
| 3283 | case Stmt::CXXFunctionalCastExprClass: | 3313 | case clang::Stmt::CXXFunctionalCastExprClass: |
| 3284 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass"); | 3314 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass"); |
| 3285 | return ErrorUnexpected; | 3315 | return ErrorUnexpected; |
| 3286 | case Stmt::CXXConstCastExprClass: | 3316 | case clang::Stmt::CXXConstCastExprClass: |
| 3287 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass"); | 3317 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass"); |
| 3288 | return ErrorUnexpected; | 3318 | return ErrorUnexpected; |
| 3289 | case Stmt::CXXDynamicCastExprClass: | 3319 | case clang::Stmt::CXXDynamicCastExprClass: |
| 3290 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass"); | 3320 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass"); |
| 3291 | return ErrorUnexpected; | 3321 | return ErrorUnexpected; |
| 3292 | case Stmt::CXXReinterpretCastExprClass: | 3322 | case clang::Stmt::CXXReinterpretCastExprClass: |
| 3293 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass"); | 3323 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass"); |
| 3294 | return ErrorUnexpected; | 3324 | return ErrorUnexpected; |
| 3295 | case Stmt::CXXStaticCastExprClass: | 3325 | case clang::Stmt::CXXStaticCastExprClass: |
| 3296 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass"); | 3326 | emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass"); |
| 3297 | return ErrorUnexpected; | 3327 | return ErrorUnexpected; |
| 3298 | case Stmt::ObjCBridgedCastExprClass: | 3328 | case clang::Stmt::ObjCBridgedCastExprClass: |
| 3299 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass"); | 3329 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass"); |
| 3300 | return ErrorUnexpected; | 3330 | return ErrorUnexpected; |
| 3301 | case Stmt::CharacterLiteralClass: | 3331 | case clang::Stmt::CharacterLiteralClass: |
| 3302 | emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass"); | 3332 | emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass"); |
| 3303 | return ErrorUnexpected; | 3333 | return ErrorUnexpected; |
| 3304 | case Stmt::ChooseExprClass: | 3334 | case clang::Stmt::ChooseExprClass: |
| 3305 | emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass"); | 3335 | emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass"); |
| 3306 | return ErrorUnexpected; | 3336 | return ErrorUnexpected; |
| 3307 | case Stmt::CompoundLiteralExprClass: | 3337 | case clang::Stmt::CompoundLiteralExprClass: |
| 3308 | emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass"); | 3338 | emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass"); |
| 3309 | return ErrorUnexpected; | 3339 | return ErrorUnexpected; |
| 3310 | case Stmt::ConvertVectorExprClass: | 3340 | case clang::Stmt::ConvertVectorExprClass: |
| 3311 | emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass"); | 3341 | emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass"); |
| 3312 | return ErrorUnexpected; | 3342 | return ErrorUnexpected; |
| 3313 | case Stmt::CoawaitExprClass: | 3343 | case clang::Stmt::CoawaitExprClass: |
| 3314 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass"); | 3344 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass"); |
| 3315 | return ErrorUnexpected; | 3345 | return ErrorUnexpected; |
| 3316 | case Stmt::CoyieldExprClass: | 3346 | case clang::Stmt::CoyieldExprClass: |
| 3317 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass"); | 3347 | emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass"); |
| 3318 | return ErrorUnexpected; | 3348 | return ErrorUnexpected; |
| 3319 | case Stmt::DependentCoawaitExprClass: | 3349 | case clang::Stmt::DependentCoawaitExprClass: |
| 3320 | emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass"); | 3350 | emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass"); |
| 3321 | return ErrorUnexpected; | 3351 | return ErrorUnexpected; |
| 3322 | case Stmt::DependentScopeDeclRefExprClass: | 3352 | case clang::Stmt::DependentScopeDeclRefExprClass: |
| 3323 | emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass"); | 3353 | emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass"); |
| 3324 | return ErrorUnexpected; | 3354 | return ErrorUnexpected; |
| 3325 | case Stmt::DesignatedInitExprClass: | 3355 | case clang::Stmt::DesignatedInitExprClass: |
| 3326 | emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass"); | 3356 | emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass"); |
| 3327 | return ErrorUnexpected; | 3357 | return ErrorUnexpected; |
| 3328 | case Stmt::DesignatedInitUpdateExprClass: | 3358 | case clang::Stmt::DesignatedInitUpdateExprClass: |
| 3329 | emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass"); | 3359 | emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass"); |
| 3330 | return ErrorUnexpected; | 3360 | return ErrorUnexpected; |
| 3331 | case Stmt::ExprWithCleanupsClass: | 3361 | case clang::Stmt::ExprWithCleanupsClass: |
| 3332 | emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass"); | 3362 | emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass"); |
| 3333 | return ErrorUnexpected; | 3363 | return ErrorUnexpected; |
| 3334 | case Stmt::ExpressionTraitExprClass: | 3364 | case clang::Stmt::ExpressionTraitExprClass: |
| 3335 | emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass"); | 3365 | emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass"); |
| 3336 | return ErrorUnexpected; | 3366 | return ErrorUnexpected; |
| 3337 | case Stmt::ExtVectorElementExprClass: | 3367 | case clang::Stmt::ExtVectorElementExprClass: |
| 3338 | emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass"); | 3368 | emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass"); |
| 3339 | return ErrorUnexpected; | 3369 | return ErrorUnexpected; |
| 3340 | case Stmt::FloatingLiteralClass: | 3370 | case clang::Stmt::FloatingLiteralClass: |
| 3341 | emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass"); | 3371 | emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass"); |
| 3342 | return ErrorUnexpected; | 3372 | return ErrorUnexpected; |
| 3343 | case Stmt::FunctionParmPackExprClass: | 3373 | case clang::Stmt::FunctionParmPackExprClass: |
| 3344 | emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass"); | 3374 | emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass"); |
| 3345 | return ErrorUnexpected; | 3375 | return ErrorUnexpected; |
| 3346 | case Stmt::GNUNullExprClass: | 3376 | case clang::Stmt::GNUNullExprClass: |
| 3347 | emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass"); | 3377 | emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass"); |
| 3348 | return ErrorUnexpected; | 3378 | return ErrorUnexpected; |
| 3349 | case Stmt::GenericSelectionExprClass: | 3379 | case clang::Stmt::GenericSelectionExprClass: |
| 3350 | emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass"); | 3380 | emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass"); |
| 3351 | return ErrorUnexpected; | 3381 | return ErrorUnexpected; |
| 3352 | case Stmt::ImaginaryLiteralClass: | 3382 | case clang::Stmt::ImaginaryLiteralClass: |
| 3353 | emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass"); | 3383 | emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass"); |
| 3354 | return ErrorUnexpected; | 3384 | return ErrorUnexpected; |
| 3355 | case Stmt::ImplicitValueInitExprClass: | 3385 | case clang::Stmt::ImplicitValueInitExprClass: |
| 3356 | emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass"); | 3386 | emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass"); |
| 3357 | return ErrorUnexpected; | 3387 | return ErrorUnexpected; |
| 3358 | case Stmt::InitListExprClass: | 3388 | case clang::Stmt::InitListExprClass: |
| 3359 | emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass"); | 3389 | emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass"); |
| 3360 | return ErrorUnexpected; | 3390 | return ErrorUnexpected; |
| 3361 | case Stmt::LambdaExprClass: | 3391 | case clang::Stmt::LambdaExprClass: |
| 3362 | emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass"); | 3392 | emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass"); |
| 3363 | return ErrorUnexpected; | 3393 | return ErrorUnexpected; |
| 3364 | case Stmt::MSPropertyRefExprClass: | 3394 | case clang::Stmt::MSPropertyRefExprClass: |
| 3365 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass"); | 3395 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass"); |
| 3366 | return ErrorUnexpected; | 3396 | return ErrorUnexpected; |
| 3367 | case Stmt::MSPropertySubscriptExprClass: | 3397 | case clang::Stmt::MSPropertySubscriptExprClass: |
| 3368 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass"); | 3398 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass"); |
| 3369 | return ErrorUnexpected; | 3399 | return ErrorUnexpected; |
| 3370 | case Stmt::MaterializeTemporaryExprClass: | 3400 | case clang::Stmt::MaterializeTemporaryExprClass: |
| 3371 | emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass"); | 3401 | emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass"); |
| 3372 | return ErrorUnexpected; | 3402 | return ErrorUnexpected; |
| 3373 | case Stmt::NoInitExprClass: | 3403 | case clang::Stmt::NoInitExprClass: |
| 3374 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass"); | 3404 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass"); |
| 3375 | return ErrorUnexpected; | 3405 | return ErrorUnexpected; |
| 3376 | case Stmt::OMPArraySectionExprClass: | 3406 | case clang::Stmt::OMPArraySectionExprClass: |
| 3377 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass"); | 3407 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass"); |
| 3378 | return ErrorUnexpected; | 3408 | return ErrorUnexpected; |
| 3379 | case Stmt::ObjCArrayLiteralClass: | 3409 | case clang::Stmt::ObjCArrayLiteralClass: |
| 3380 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass"); | 3410 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass"); |
| 3381 | return ErrorUnexpected; | 3411 | return ErrorUnexpected; |
| 3382 | case Stmt::ObjCAvailabilityCheckExprClass: | 3412 | case clang::Stmt::ObjCAvailabilityCheckExprClass: |
| 3383 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass"); | 3413 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass"); |
| 3384 | return ErrorUnexpected; | 3414 | return ErrorUnexpected; |
| 3385 | case Stmt::ObjCBoolLiteralExprClass: | 3415 | case clang::Stmt::ObjCBoolLiteralExprClass: |
| 3386 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass"); | 3416 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass"); |
| 3387 | return ErrorUnexpected; | 3417 | return ErrorUnexpected; |
| 3388 | case Stmt::ObjCBoxedExprClass: | 3418 | case clang::Stmt::ObjCBoxedExprClass: |
| 3389 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass"); | 3419 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass"); |
| 3390 | return ErrorUnexpected; | 3420 | return ErrorUnexpected; |
| 3391 | case Stmt::ObjCDictionaryLiteralClass: | 3421 | case clang::Stmt::ObjCDictionaryLiteralClass: |
| 3392 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass"); | 3422 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass"); |
| 3393 | return ErrorUnexpected; | 3423 | return ErrorUnexpected; |
| 3394 | case Stmt::ObjCEncodeExprClass: | 3424 | case clang::Stmt::ObjCEncodeExprClass: |
| 3395 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass"); | 3425 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass"); |
| 3396 | return ErrorUnexpected; | 3426 | return ErrorUnexpected; |
| 3397 | case Stmt::ObjCIndirectCopyRestoreExprClass: | 3427 | case clang::Stmt::ObjCIndirectCopyRestoreExprClass: |
| 3398 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass"); | 3428 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass"); |
| 3399 | return ErrorUnexpected; | 3429 | return ErrorUnexpected; |
| 3400 | case Stmt::ObjCIsaExprClass: | 3430 | case clang::Stmt::ObjCIsaExprClass: |
| 3401 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass"); | 3431 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass"); |
| 3402 | return ErrorUnexpected; | 3432 | return ErrorUnexpected; |
| 3403 | case Stmt::ObjCIvarRefExprClass: | 3433 | case clang::Stmt::ObjCIvarRefExprClass: |
| 3404 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass"); | 3434 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass"); |
| 3405 | return ErrorUnexpected; | 3435 | return ErrorUnexpected; |
| 3406 | case Stmt::ObjCMessageExprClass: | 3436 | case clang::Stmt::ObjCMessageExprClass: |
| 3407 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass"); | 3437 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass"); |
| 3408 | return ErrorUnexpected; | 3438 | return ErrorUnexpected; |
| 3409 | case Stmt::ObjCPropertyRefExprClass: | 3439 | case clang::Stmt::ObjCPropertyRefExprClass: |
| 3410 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass"); | 3440 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass"); |
| 3411 | return ErrorUnexpected; | 3441 | return ErrorUnexpected; |
| 3412 | case Stmt::ObjCProtocolExprClass: | 3442 | case clang::Stmt::ObjCProtocolExprClass: |
| 3413 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass"); | 3443 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass"); |
| 3414 | return ErrorUnexpected; | 3444 | return ErrorUnexpected; |
| 3415 | case Stmt::ObjCSelectorExprClass: | 3445 | case clang::Stmt::ObjCSelectorExprClass: |
| 3416 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass"); | 3446 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass"); |
| 3417 | return ErrorUnexpected; | 3447 | return ErrorUnexpected; |
| 3418 | case Stmt::ObjCStringLiteralClass: | 3448 | case clang::Stmt::ObjCStringLiteralClass: |
| 3419 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass"); | 3449 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass"); |
| 3420 | return ErrorUnexpected; | 3450 | return ErrorUnexpected; |
| 3421 | case Stmt::ObjCSubscriptRefExprClass: | 3451 | case clang::Stmt::ObjCSubscriptRefExprClass: |
| 3422 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass"); | 3452 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass"); |
| 3423 | return ErrorUnexpected; | 3453 | return ErrorUnexpected; |
| 3424 | case Stmt::OffsetOfExprClass: | 3454 | case clang::Stmt::OffsetOfExprClass: |
| 3425 | emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass"); | 3455 | emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass"); |
| 3426 | return ErrorUnexpected; | 3456 | return ErrorUnexpected; |
| 3427 | case Stmt::OpaqueValueExprClass: | 3457 | case clang::Stmt::OpaqueValueExprClass: |
| 3428 | emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass"); | 3458 | emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass"); |
| 3429 | return ErrorUnexpected; | 3459 | return ErrorUnexpected; |
| 3430 | case Stmt::UnresolvedLookupExprClass: | 3460 | case clang::Stmt::UnresolvedLookupExprClass: |
| 3431 | emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass"); | 3461 | emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass"); |
| 3432 | return ErrorUnexpected; | 3462 | return ErrorUnexpected; |
| 3433 | case Stmt::UnresolvedMemberExprClass: | 3463 | case clang::Stmt::UnresolvedMemberExprClass: |
| 3434 | emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass"); | 3464 | emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass"); |
| 3435 | return ErrorUnexpected; | 3465 | return ErrorUnexpected; |
| 3436 | case Stmt::PackExpansionExprClass: | 3466 | case clang::Stmt::PackExpansionExprClass: |
| 3437 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); | 3467 | emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass"); |
| 3438 | return ErrorUnexpected; | 3468 | return ErrorUnexpected; |
| 3439 | case Stmt::ParenListExprClass: | 3469 | case clang::Stmt::ParenListExprClass: |
| 3440 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); | 3470 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); |
| 3441 | return ErrorUnexpected; | 3471 | return ErrorUnexpected; |
| 3442 | case Stmt::PredefinedExprClass: | 3472 | case clang::Stmt::PredefinedExprClass: |
| 3443 | emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass"); | 3473 | emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass"); |
| 3444 | return ErrorUnexpected; | 3474 | return ErrorUnexpected; |
| 3445 | case Stmt::PseudoObjectExprClass: | 3475 | case clang::Stmt::PseudoObjectExprClass: |
| 3446 | emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass"); | 3476 | emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass"); |
| 3447 | return ErrorUnexpected; | 3477 | return ErrorUnexpected; |
| 3448 | case Stmt::ShuffleVectorExprClass: | 3478 | case clang::Stmt::ShuffleVectorExprClass: |
| 3449 | emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass"); | 3479 | emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass"); |
| 3450 | return ErrorUnexpected; | 3480 | return ErrorUnexpected; |
| 3451 | case Stmt::SizeOfPackExprClass: | 3481 | case clang::Stmt::SizeOfPackExprClass: |
| 3452 | emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass"); | 3482 | emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass"); |
| 3453 | return ErrorUnexpected; | 3483 | return ErrorUnexpected; |
| 3454 | case Stmt::StmtExprClass: | 3484 | case clang::Stmt::StmtExprClass: |
| 3455 | emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass"); | 3485 | emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass"); |
| 3456 | return ErrorUnexpected; | 3486 | return ErrorUnexpected; |
| 3457 | case Stmt::SubstNonTypeTemplateParmExprClass: | 3487 | case clang::Stmt::SubstNonTypeTemplateParmExprClass: |
| 3458 | emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass"); | 3488 | emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass"); |
| 3459 | return ErrorUnexpected; | 3489 | return ErrorUnexpected; |
| 3460 | case Stmt::SubstNonTypeTemplateParmPackExprClass: | 3490 | case clang::Stmt::SubstNonTypeTemplateParmPackExprClass: |
| 3461 | emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); | 3491 | emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass"); |
| 3462 | return ErrorUnexpected; | 3492 | return ErrorUnexpected; |
| 3463 | case Stmt::TypeTraitExprClass: | 3493 | case clang::Stmt::TypeTraitExprClass: |
| 3464 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass"); | 3494 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass"); |
| 3465 | return ErrorUnexpected; | 3495 | return ErrorUnexpected; |
| 3466 | case Stmt::TypoExprClass: | 3496 | case clang::Stmt::TypoExprClass: |
| 3467 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass"); | 3497 | emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass"); |
| 3468 | return ErrorUnexpected; | 3498 | return ErrorUnexpected; |
| 3469 | case Stmt::VAArgExprClass: | 3499 | case clang::Stmt::VAArgExprClass: |
| 3470 | emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass"); | 3500 | emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass"); |
| 3471 | return ErrorUnexpected; | 3501 | return ErrorUnexpected; |
| 3472 | case Stmt::GotoStmtClass: | 3502 | case clang::Stmt::GotoStmtClass: |
| 3473 | emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass"); | 3503 | emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass"); |
| 3474 | return ErrorUnexpected; | 3504 | return ErrorUnexpected; |
| 3475 | case Stmt::IndirectGotoStmtClass: | 3505 | case clang::Stmt::IndirectGotoStmtClass: |
| 3476 | emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass"); | 3506 | emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass"); |
| 3477 | return ErrorUnexpected; | 3507 | return ErrorUnexpected; |
| 3478 | case Stmt::LabelStmtClass: | 3508 | case clang::Stmt::LabelStmtClass: |
| 3479 | emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass"); | 3509 | emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass"); |
| 3480 | return ErrorUnexpected; | 3510 | return ErrorUnexpected; |
| 3481 | case Stmt::MSDependentExistsStmtClass: | 3511 | case clang::Stmt::MSDependentExistsStmtClass: |
| 3482 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass"); | 3512 | emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass"); |
| 3483 | return ErrorUnexpected; | 3513 | return ErrorUnexpected; |
| 3484 | case Stmt::OMPAtomicDirectiveClass: | 3514 | case clang::Stmt::OMPAtomicDirectiveClass: |
| 3485 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass"); | 3515 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass"); |
| 3486 | return ErrorUnexpected; | 3516 | return ErrorUnexpected; |
| 3487 | case Stmt::OMPBarrierDirectiveClass: | 3517 | case clang::Stmt::OMPBarrierDirectiveClass: |
| 3488 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass"); | 3518 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass"); |
| 3489 | return ErrorUnexpected; | 3519 | return ErrorUnexpected; |
| 3490 | case Stmt::OMPCancelDirectiveClass: | 3520 | case clang::Stmt::OMPCancelDirectiveClass: |
| 3491 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass"); | 3521 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass"); |
| 3492 | return ErrorUnexpected; | 3522 | return ErrorUnexpected; |
| 3493 | case Stmt::OMPCancellationPointDirectiveClass: | 3523 | case clang::Stmt::OMPCancellationPointDirectiveClass: |
| 3494 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass"); | 3524 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass"); |
| 3495 | return ErrorUnexpected; | 3525 | return ErrorUnexpected; |
| 3496 | case Stmt::OMPCriticalDirectiveClass: | 3526 | case clang::Stmt::OMPCriticalDirectiveClass: |
| 3497 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass"); | 3527 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass"); |
| 3498 | return ErrorUnexpected; | 3528 | return ErrorUnexpected; |
| 3499 | case Stmt::OMPFlushDirectiveClass: | 3529 | case clang::Stmt::OMPFlushDirectiveClass: |
| 3500 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass"); | 3530 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass"); |
| 3501 | return ErrorUnexpected; | 3531 | return ErrorUnexpected; |
| 3502 | case Stmt::OMPDistributeDirectiveClass: | 3532 | case clang::Stmt::OMPDistributeDirectiveClass: |
| 3503 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass"); | 3533 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass"); |
| 3504 | return ErrorUnexpected; | 3534 | return ErrorUnexpected; |
| 3505 | case Stmt::OMPDistributeParallelForDirectiveClass: | 3535 | case clang::Stmt::OMPDistributeParallelForDirectiveClass: |
| 3506 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass"); | 3536 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass"); |
| 3507 | return ErrorUnexpected; | 3537 | return ErrorUnexpected; |
| 3508 | case Stmt::OMPDistributeParallelForSimdDirectiveClass: | 3538 | case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass: |
| 3509 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | 3539 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass"); |
| 3510 | return ErrorUnexpected; | 3540 | return ErrorUnexpected; |
| 3511 | case Stmt::OMPDistributeSimdDirectiveClass: | 3541 | case clang::Stmt::OMPDistributeSimdDirectiveClass: |
| 3512 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass"); | 3542 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass"); |
| 3513 | return ErrorUnexpected; | 3543 | return ErrorUnexpected; |
| 3514 | case Stmt::OMPForDirectiveClass: | 3544 | case clang::Stmt::OMPForDirectiveClass: |
| 3515 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass"); | 3545 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass"); |
| 3516 | return ErrorUnexpected; | 3546 | return ErrorUnexpected; |
| 3517 | case Stmt::OMPForSimdDirectiveClass: | 3547 | case clang::Stmt::OMPForSimdDirectiveClass: |
| 3518 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass"); | 3548 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass"); |
| 3519 | return ErrorUnexpected; | 3549 | return ErrorUnexpected; |
| 3520 | case Stmt::OMPParallelForDirectiveClass: | 3550 | case clang::Stmt::OMPParallelForDirectiveClass: |
| 3521 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass"); | 3551 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass"); |
| 3522 | return ErrorUnexpected; | 3552 | return ErrorUnexpected; |
| 3523 | case Stmt::OMPParallelForSimdDirectiveClass: | 3553 | case clang::Stmt::OMPParallelForSimdDirectiveClass: |
| 3524 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass"); | 3554 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass"); |
| 3525 | return ErrorUnexpected; | 3555 | return ErrorUnexpected; |
| 3526 | case Stmt::OMPSimdDirectiveClass: | 3556 | case clang::Stmt::OMPSimdDirectiveClass: |
| 3527 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass"); | 3557 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass"); |
| 3528 | return ErrorUnexpected; | 3558 | return ErrorUnexpected; |
| 3529 | case Stmt::OMPTargetParallelForSimdDirectiveClass: | 3559 | case clang::Stmt::OMPTargetParallelForSimdDirectiveClass: |
| 3530 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); | 3560 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass"); |
| 3531 | return ErrorUnexpected; | 3561 | return ErrorUnexpected; |
| 3532 | case Stmt::OMPTargetSimdDirectiveClass: | 3562 | case clang::Stmt::OMPTargetSimdDirectiveClass: |
| 3533 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass"); | 3563 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass"); |
| 3534 | return ErrorUnexpected; | 3564 | return ErrorUnexpected; |
| 3535 | case Stmt::OMPTargetTeamsDistributeDirectiveClass: | 3565 | case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass: |
| 3536 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | 3566 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass"); |
| 3537 | return ErrorUnexpected; | 3567 | return ErrorUnexpected; |
| 3538 | case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: | 3568 | case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: |
| 3539 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | 3569 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); |
| 3540 | return ErrorUnexpected; | 3570 | return ErrorUnexpected; |
| 3541 | case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | 3571 | case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: |
| 3542 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | 3572 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); |
| 3543 | return ErrorUnexpected; | 3573 | return ErrorUnexpected; |
| 3544 | case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: | 3574 | case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: |
| 3545 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | 3575 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); |
| 3546 | return ErrorUnexpected; | 3576 | return ErrorUnexpected; |
| 3547 | case Stmt::OMPTaskLoopDirectiveClass: | 3577 | case clang::Stmt::OMPTaskLoopDirectiveClass: |
| 3548 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass"); | 3578 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass"); |
| 3549 | return ErrorUnexpected; | 3579 | return ErrorUnexpected; |
| 3550 | case Stmt::OMPTaskLoopSimdDirectiveClass: | 3580 | case clang::Stmt::OMPTaskLoopSimdDirectiveClass: |
| 3551 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass"); | 3581 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass"); |
| 3552 | return ErrorUnexpected; | 3582 | return ErrorUnexpected; |
| 3553 | case Stmt::OMPTeamsDistributeDirectiveClass: | 3583 | case clang::Stmt::OMPTeamsDistributeDirectiveClass: |
| 3554 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass"); | 3584 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass"); |
| 3555 | return ErrorUnexpected; | 3585 | return ErrorUnexpected; |
| 3556 | case Stmt::OMPTeamsDistributeParallelForDirectiveClass: | 3586 | case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass: |
| 3557 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | 3587 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); |
| 3558 | return ErrorUnexpected; | 3588 | return ErrorUnexpected; |
| 3559 | case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: | 3589 | case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: |
| 3560 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | 3590 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); |
| 3561 | return ErrorUnexpected; | 3591 | return ErrorUnexpected; |
| 3562 | case Stmt::OMPTeamsDistributeSimdDirectiveClass: | 3592 | case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass: |
| 3563 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | 3593 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass"); |
| 3564 | return ErrorUnexpected; | 3594 | return ErrorUnexpected; |
| 3565 | case Stmt::OMPMasterDirectiveClass: | 3595 | case clang::Stmt::OMPMasterDirectiveClass: |
| 3566 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass"); | 3596 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass"); |
| 3567 | return ErrorUnexpected; | 3597 | return ErrorUnexpected; |
| 3568 | case Stmt::OMPOrderedDirectiveClass: | 3598 | case clang::Stmt::OMPOrderedDirectiveClass: |
| 3569 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass"); | 3599 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass"); |
| 3570 | return ErrorUnexpected; | 3600 | return ErrorUnexpected; |
| 3571 | case Stmt::OMPParallelDirectiveClass: | 3601 | case clang::Stmt::OMPParallelDirectiveClass: |
| 3572 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass"); | 3602 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass"); |
| 3573 | return ErrorUnexpected; | 3603 | return ErrorUnexpected; |
| 3574 | case Stmt::OMPParallelSectionsDirectiveClass: | 3604 | case clang::Stmt::OMPParallelSectionsDirectiveClass: |
| 3575 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass"); | 3605 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass"); |
| 3576 | return ErrorUnexpected; | 3606 | return ErrorUnexpected; |
| 3577 | case Stmt::OMPSectionDirectiveClass: | 3607 | case clang::Stmt::OMPSectionDirectiveClass: |
| 3578 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass"); | 3608 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass"); |
| 3579 | return ErrorUnexpected; | 3609 | return ErrorUnexpected; |
| 3580 | case Stmt::OMPSectionsDirectiveClass: | 3610 | case clang::Stmt::OMPSectionsDirectiveClass: |
| 3581 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass"); | 3611 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass"); |
| 3582 | return ErrorUnexpected; | 3612 | return ErrorUnexpected; |
| 3583 | case Stmt::OMPSingleDirectiveClass: | 3613 | case clang::Stmt::OMPSingleDirectiveClass: |
| 3584 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass"); | 3614 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass"); |
| 3585 | return ErrorUnexpected; | 3615 | return ErrorUnexpected; |
| 3586 | case Stmt::OMPTargetDataDirectiveClass: | 3616 | case clang::Stmt::OMPTargetDataDirectiveClass: |
| 3587 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass"); | 3617 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass"); |
| 3588 | return ErrorUnexpected; | 3618 | return ErrorUnexpected; |
| 3589 | case Stmt::OMPTargetDirectiveClass: | 3619 | case clang::Stmt::OMPTargetDirectiveClass: |
| 3590 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass"); | 3620 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass"); |
| 3591 | return ErrorUnexpected; | 3621 | return ErrorUnexpected; |
| 3592 | case Stmt::OMPTargetEnterDataDirectiveClass: | 3622 | case clang::Stmt::OMPTargetEnterDataDirectiveClass: |
| 3593 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass"); | 3623 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass"); |
| 3594 | return ErrorUnexpected; | 3624 | return ErrorUnexpected; |
| 3595 | case Stmt::OMPTargetExitDataDirectiveClass: | 3625 | case clang::Stmt::OMPTargetExitDataDirectiveClass: |
| 3596 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass"); | 3626 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass"); |
| 3597 | return ErrorUnexpected; | 3627 | return ErrorUnexpected; |
| 3598 | case Stmt::OMPTargetParallelDirectiveClass: | 3628 | case clang::Stmt::OMPTargetParallelDirectiveClass: |
| 3599 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass"); | 3629 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass"); |
| 3600 | return ErrorUnexpected; | 3630 | return ErrorUnexpected; |
| 3601 | case Stmt::OMPTargetParallelForDirectiveClass: | 3631 | case clang::Stmt::OMPTargetParallelForDirectiveClass: |
| 3602 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass"); | 3632 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass"); |
| 3603 | return ErrorUnexpected; | 3633 | return ErrorUnexpected; |
| 3604 | case Stmt::OMPTargetTeamsDirectiveClass: | 3634 | case clang::Stmt::OMPTargetTeamsDirectiveClass: |
| 3605 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass"); | 3635 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass"); |
| 3606 | return ErrorUnexpected; | 3636 | return ErrorUnexpected; |
| 3607 | case Stmt::OMPTargetUpdateDirectiveClass: | 3637 | case clang::Stmt::OMPTargetUpdateDirectiveClass: |
| 3608 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass"); | 3638 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass"); |
| 3609 | return ErrorUnexpected; | 3639 | return ErrorUnexpected; |
| 3610 | case Stmt::OMPTaskDirectiveClass: | 3640 | case clang::Stmt::OMPTaskDirectiveClass: |
| 3611 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass"); | 3641 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass"); |
| 3612 | return ErrorUnexpected; | 3642 | return ErrorUnexpected; |
| 3613 | case Stmt::OMPTaskgroupDirectiveClass: | 3643 | case clang::Stmt::OMPTaskgroupDirectiveClass: |
| 3614 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass"); | 3644 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass"); |
| 3615 | return ErrorUnexpected; | 3645 | return ErrorUnexpected; |
| 3616 | case Stmt::OMPTaskwaitDirectiveClass: | 3646 | case clang::Stmt::OMPTaskwaitDirectiveClass: |
| 3617 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass"); | 3647 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass"); |
| 3618 | return ErrorUnexpected; | 3648 | return ErrorUnexpected; |
| 3619 | case Stmt::OMPTaskyieldDirectiveClass: | 3649 | case clang::Stmt::OMPTaskyieldDirectiveClass: |
| 3620 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass"); | 3650 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass"); |
| 3621 | return ErrorUnexpected; | 3651 | return ErrorUnexpected; |
| 3622 | case Stmt::OMPTeamsDirectiveClass: | 3652 | case clang::Stmt::OMPTeamsDirectiveClass: |
| 3623 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass"); | 3653 | emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass"); |
| 3624 | return ErrorUnexpected; | 3654 | return ErrorUnexpected; |
| 3625 | case Stmt::ObjCAtCatchStmtClass: | 3655 | case clang::Stmt::ObjCAtCatchStmtClass: |
| 3626 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass"); | 3656 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass"); |
| 3627 | return ErrorUnexpected; | 3657 | return ErrorUnexpected; |
| 3628 | case Stmt::ObjCAtFinallyStmtClass: | 3658 | case clang::Stmt::ObjCAtFinallyStmtClass: |
| 3629 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass"); | 3659 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass"); |
| 3630 | return ErrorUnexpected; | 3660 | return ErrorUnexpected; |
| 3631 | case Stmt::ObjCAtSynchronizedStmtClass: | 3661 | case clang::Stmt::ObjCAtSynchronizedStmtClass: |
| 3632 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass"); | 3662 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass"); |
| 3633 | return ErrorUnexpected; | 3663 | return ErrorUnexpected; |
| 3634 | case Stmt::ObjCAtThrowStmtClass: | 3664 | case clang::Stmt::ObjCAtThrowStmtClass: |
| 3635 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass"); | 3665 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass"); |
| 3636 | return ErrorUnexpected; | 3666 | return ErrorUnexpected; |
| 3637 | case Stmt::ObjCAtTryStmtClass: | 3667 | case clang::Stmt::ObjCAtTryStmtClass: |
| 3638 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass"); | 3668 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass"); |
| 3639 | return ErrorUnexpected; | 3669 | return ErrorUnexpected; |
| 3640 | case Stmt::ObjCAutoreleasePoolStmtClass: | 3670 | case clang::Stmt::ObjCAutoreleasePoolStmtClass: |
| 3641 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass"); | 3671 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass"); |
| 3642 | return ErrorUnexpected; | 3672 | return ErrorUnexpected; |
| 3643 | case Stmt::ObjCForCollectionStmtClass: | 3673 | case clang::Stmt::ObjCForCollectionStmtClass: |
| 3644 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass"); | 3674 | emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass"); |
| 3645 | return ErrorUnexpected; | 3675 | return ErrorUnexpected; |
| 3646 | case Stmt::SEHExceptStmtClass: | 3676 | case clang::Stmt::SEHExceptStmtClass: |
| 3647 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass"); | 3677 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass"); |
| 3648 | return ErrorUnexpected; | 3678 | return ErrorUnexpected; |
| 3649 | case Stmt::SEHFinallyStmtClass: | 3679 | case clang::Stmt::SEHFinallyStmtClass: |
| 3650 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass"); | 3680 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass"); |
| 3651 | return ErrorUnexpected; | 3681 | return ErrorUnexpected; |
| 3652 | case Stmt::SEHLeaveStmtClass: | 3682 | case clang::Stmt::SEHLeaveStmtClass: |
| 3653 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass"); | 3683 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass"); |
| 3654 | return ErrorUnexpected; | 3684 | return ErrorUnexpected; |
| 3655 | case Stmt::SEHTryStmtClass: | 3685 | case clang::Stmt::SEHTryStmtClass: |
| 3656 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass"); | 3686 | emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass"); |
| 3657 | return ErrorUnexpected; | 3687 | return ErrorUnexpected; |
| 3658 | case Stmt::FixedPointLiteralClass: | 3688 | case clang::Stmt::FixedPointLiteralClass: |
| 3659 | emit_warning(c, stmt->getLocStart(), "TODO handle C FixedPointLiteralClass"); | 3689 | emit_warning(c, stmt->getLocStart(), "TODO handle C FixedPointLiteralClass"); |
| 3660 | return ErrorUnexpected; | 3690 | return ErrorUnexpected; |
| 3661 | } | 3691 | } |
| ... | @@ -3663,7 +3693,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | ... | @@ -3663,7 +3693,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 3663 | } | 3693 | } |
| 3664 | 3694 | ||
| 3665 | // Returns null if there was an error | 3695 | // Returns null if there was an error |
| 3666 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, | 3696 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, |
| 3667 | TransLRValue lrval) | 3697 | TransLRValue lrval) |
| 3668 | { | 3698 | { |
| 3669 | AstNode *result_node; | 3699 | AstNode *result_node; |
| ... | @@ -3676,7 +3706,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope | ... | @@ -3676,7 +3706,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope |
| 3676 | 3706 | ||
| 3677 | // Statements have no result and no concept of L or R value. | 3707 | // Statements have no result and no concept of L or R value. |
| 3678 | // Returns child scope, or null if there was an error | 3708 | // Returns child scope, or null if there was an error |
| 3679 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node) { | 3709 | static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) { |
| 3680 | TransScope *child_scope; | 3710 | TransScope *child_scope; |
| 3681 | if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) { | 3711 | if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) { |
| 3682 | return nullptr; | 3712 | return nullptr; |
| ... | @@ -3684,7 +3714,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A | ... | @@ -3684,7 +3714,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A |
| 3684 | return child_scope; | 3714 | return child_scope; |
| 3685 | } | 3715 | } |
| 3686 | 3716 | ||
| 3687 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | 3717 | static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) { |
| 3688 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); | 3718 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); |
| 3689 | 3719 | ||
| 3690 | if (get_global(c, fn_name)) { | 3720 | if (get_global(c, fn_name)) { |
| ... | @@ -3701,13 +3731,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -3701,13 +3731,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3701 | proto_node->data.fn_proto.name = fn_name; | 3731 | proto_node->data.fn_proto.name = fn_name; |
| 3702 | proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); | 3732 | proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); |
| 3703 | 3733 | ||
| 3704 | StorageClass sc = fn_decl->getStorageClass(); | 3734 | clang::StorageClass sc = fn_decl->getStorageClass(); |
| 3705 | if (sc == SC_None) { | 3735 | if (sc == clang::SC_None) { |
| 3706 | proto_node->data.fn_proto.visib_mod = c->visib_mod; | 3736 | proto_node->data.fn_proto.visib_mod = c->visib_mod; |
| 3707 | proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false; | 3737 | proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false; |
| 3708 | } else if (sc == SC_Extern || sc == SC_Static) { | 3738 | } else if (sc == clang::SC_Extern || sc == clang::SC_Static) { |
| 3709 | proto_node->data.fn_proto.visib_mod = c->visib_mod; | 3739 | proto_node->data.fn_proto.visib_mod = c->visib_mod; |
| 3710 | } else if (sc == SC_PrivateExtern) { | 3740 | } else if (sc == clang::SC_PrivateExtern) { |
| 3711 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); | 3741 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); |
| 3712 | return; | 3742 | return; |
| 3713 | } else { | 3743 | } else { |
| ... | @@ -3719,7 +3749,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -3719,7 +3749,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3719 | 3749 | ||
| 3720 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { | 3750 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { |
| 3721 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); | 3751 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); |
| 3722 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | 3752 | const clang::ParmVarDecl *param = fn_decl->getParamDecl(i); |
| 3723 | const char *name = decl_name(param); | 3753 | const char *name = decl_name(param); |
| 3724 | 3754 | ||
| 3725 | Buf *proto_param_name; | 3755 | Buf *proto_param_name; |
| ... | @@ -3746,7 +3776,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -3746,7 +3776,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3746 | 3776 | ||
| 3747 | // actual function definition with body | 3777 | // actual function definition with body |
| 3748 | c->ptr_params.clear(); | 3778 | c->ptr_params.clear(); |
| 3749 | Stmt *body = fn_decl->getBody(); | 3779 | clang::Stmt *body = fn_decl->getBody(); |
| 3750 | AstNode *actual_body_node; | 3780 | AstNode *actual_body_node; |
| 3751 | TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node); | 3781 | TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node); |
| 3752 | if (result_scope == nullptr) { | 3782 | if (result_scope == nullptr) { |
| ... | @@ -3788,19 +3818,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ... | @@ -3788,19 +3818,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3788 | add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node); | 3818 | add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node); |
| 3789 | } | 3819 | } |
| 3790 | 3820 | ||
| 3791 | static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) { | 3821 | static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) { |
| 3792 | AstNode *node = trans_create_node_symbol_str(c, primitive_name); | 3822 | AstNode *node = trans_create_node_symbol_str(c, primitive_name); |
| 3793 | c->decl_table.put(typedef_decl, node); | 3823 | c->decl_table.put(typedef_decl, node); |
| 3794 | return node; | 3824 | return node; |
| 3795 | } | 3825 | } |
| 3796 | 3826 | ||
| 3797 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { | 3827 | static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) { |
| 3798 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); | 3828 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); |
| 3799 | if (existing_entry) { | 3829 | if (existing_entry) { |
| 3800 | return existing_entry->value; | 3830 | return existing_entry->value; |
| 3801 | } | 3831 | } |
| 3802 | 3832 | ||
| 3803 | QualType child_qt = typedef_decl->getUnderlyingType(); | 3833 | clang::QualType child_qt = typedef_decl->getUnderlyingType(); |
| 3804 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); | 3834 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); |
| 3805 | 3835 | ||
| 3806 | if (buf_eql_str(type_name, "uint8_t")) { | 3836 | if (buf_eql_str(type_name, "uint8_t")) { |
| ... | @@ -3849,7 +3879,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_ | ... | @@ -3849,7 +3879,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_ |
| 3849 | return symbol_node; | 3879 | return symbol_node; |
| 3850 | } | 3880 | } |
| 3851 | 3881 | ||
| 3852 | struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, | 3882 | struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl, |
| 3853 | Buf *full_type_name, Buf *bare_name) | 3883 | Buf *full_type_name, Buf *bare_name) |
| 3854 | { | 3884 | { |
| 3855 | AstNode *opaque_node = trans_create_node_opaque(c); | 3885 | AstNode *opaque_node = trans_create_node_opaque(c); |
| ... | @@ -3864,7 +3894,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, | ... | @@ -3864,7 +3894,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, |
| 3864 | return symbol_node; | 3894 | return symbol_node; |
| 3865 | } | 3895 | } |
| 3866 | 3896 | ||
| 3867 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | 3897 | static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) { |
| 3868 | auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl()); | 3898 | auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl()); |
| 3869 | if (existing_entry) { | 3899 | if (existing_entry) { |
| 3870 | return existing_entry->value; | 3900 | return existing_entry->value; |
| ... | @@ -3875,7 +3905,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -3875,7 +3905,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3875 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); | 3905 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); |
| 3876 | Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); | 3906 | Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); |
| 3877 | 3907 | ||
| 3878 | const EnumDecl *enum_def = enum_decl->getDefinition(); | 3908 | const clang::EnumDecl *enum_def = enum_decl->getDefinition(); |
| 3879 | if (!enum_def) { | 3909 | if (!enum_def) { |
| 3880 | return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name); | 3910 | return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name); |
| 3881 | } | 3911 | } |
| ... | @@ -3887,7 +3917,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -3887,7 +3917,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3887 | it_end = enum_def->enumerator_end(); | 3917 | it_end = enum_def->enumerator_end(); |
| 3888 | it != it_end; ++it, field_count += 1) | 3918 | it != it_end; ++it, field_count += 1) |
| 3889 | { | 3919 | { |
| 3890 | const EnumConstantDecl *enum_const = *it; | 3920 | const clang::EnumConstantDecl *enum_const = *it; |
| 3891 | if (enum_const->getInitExpr()) { | 3921 | if (enum_const->getInitExpr()) { |
| 3892 | pure_enum = false; | 3922 | pure_enum = false; |
| 3893 | } | 3923 | } |
| ... | @@ -3901,8 +3931,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -3901,8 +3931,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3901 | // TODO only emit this tag type if the enum tag type is not the default. | 3931 | // TODO only emit this tag type if the enum tag type is not the default. |
| 3902 | // I don't know what the default is, need to figure out how clang is deciding. | 3932 | // I don't know what the default is, need to figure out how clang is deciding. |
| 3903 | // it appears to at least be different across gcc/msvc | 3933 | // it appears to at least be different across gcc/msvc |
| 3904 | if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) && | 3934 | if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) && |
| 3905 | !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int)) | 3935 | !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int)) |
| 3906 | { | 3936 | { |
| 3907 | enum_node->data.container_decl.init_arg_expr = tag_int_type; | 3937 | enum_node->data.container_decl.init_arg_expr = tag_int_type; |
| 3908 | } | 3938 | } |
| ... | @@ -3912,7 +3942,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -3912,7 +3942,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3912 | it_end = enum_def->enumerator_end(); | 3942 | it_end = enum_def->enumerator_end(); |
| 3913 | it != it_end; ++it, i += 1) | 3943 | it != it_end; ++it, i += 1) |
| 3914 | { | 3944 | { |
| 3915 | const EnumConstantDecl *enum_const = *it; | 3945 | const clang::EnumConstantDecl *enum_const = *it; |
| 3916 | 3946 | ||
| 3917 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); | 3947 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); |
| 3918 | Buf *field_name; | 3948 | Buf *field_name; |
| ... | @@ -3953,7 +3983,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -3953,7 +3983,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 3953 | } | 3983 | } |
| 3954 | } | 3984 | } |
| 3955 | 3985 | ||
| 3956 | static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl, | 3986 | static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl, |
| 3957 | Buf *full_type_name, Buf *bare_name) | 3987 | Buf *full_type_name, Buf *bare_name) |
| 3958 | { | 3988 | { |
| 3959 | AstNode *opaque_node = trans_create_node_opaque(c); | 3989 | AstNode *opaque_node = trans_create_node_opaque(c); |
| ... | @@ -3968,7 +3998,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec | ... | @@ -3968,7 +3998,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec |
| 3968 | return symbol_node; | 3998 | return symbol_node; |
| 3969 | } | 3999 | } |
| 3970 | 4000 | ||
| 3971 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | 4001 | static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) { |
| 3972 | auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); | 4002 | auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); |
| 3973 | if (existing_entry) { | 4003 | if (existing_entry) { |
| 3974 | return existing_entry->value; | 4004 | return existing_entry->value; |
| ... | @@ -3994,7 +4024,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -3994,7 +4024,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 3994 | Buf *full_type_name = (bare_name == nullptr) ? | 4024 | Buf *full_type_name = (bare_name == nullptr) ? |
| 3995 | nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name)); | 4025 | nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name)); |
| 3996 | 4026 | ||
| 3997 | RecordDecl *record_def = record_decl->getDefinition(); | 4027 | clang::RecordDecl *record_def = record_decl->getDefinition(); |
| 3998 | if (record_def == nullptr) { | 4028 | if (record_def == nullptr) { |
| 3999 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | 4029 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); |
| 4000 | } | 4030 | } |
| ... | @@ -4005,7 +4035,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -4005,7 +4035,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4005 | it_end = record_def->field_end(); | 4035 | it_end = record_def->field_end(); |
| 4006 | it != it_end; ++it, field_count += 1) | 4036 | it != it_end; ++it, field_count += 1) |
| 4007 | { | 4037 | { |
| 4008 | const FieldDecl *field_decl = *it; | 4038 | const clang::FieldDecl *field_decl = *it; |
| 4009 | 4039 | ||
| 4010 | if (field_decl->isBitField()) { | 4040 | if (field_decl->isBitField()) { |
| 4011 | emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield", | 4041 | emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield", |
| ... | @@ -4035,7 +4065,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -4035,7 +4065,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4035 | it_end = record_def->field_end(); | 4065 | it_end = record_def->field_end(); |
| 4036 | it != it_end; ++it, i += 1) | 4066 | it != it_end; ++it, i += 1) |
| 4037 | { | 4067 | { |
| 4038 | const FieldDecl *field_decl = *it; | 4068 | const clang::FieldDecl *field_decl = *it; |
| 4039 | 4069 | ||
| 4040 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); | 4070 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); |
| 4041 | field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); | 4071 | field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); |
| ... | @@ -4062,13 +4092,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -4062,13 +4092,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 4062 | } | 4092 | } |
| 4063 | } | 4093 | } |
| 4064 | 4094 | ||
| 4065 | static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) { | 4095 | static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) { |
| 4066 | switch (ap_value->getKind()) { | 4096 | switch (ap_value->getKind()) { |
| 4067 | case APValue::Int: | 4097 | case clang::APValue::Int: |
| 4068 | return trans_create_node_apint(c, ap_value->getInt()); | 4098 | return trans_create_node_apint(c, ap_value->getInt()); |
| 4069 | case APValue::Uninitialized: | 4099 | case clang::APValue::Uninitialized: |
| 4070 | return trans_create_node(c, NodeTypeUndefinedLiteral); | 4100 | return trans_create_node(c, NodeTypeUndefinedLiteral); |
| 4071 | case APValue::Array: { | 4101 | case clang::APValue::Array: { |
| 4072 | emit_warning(c, source_loc, "TODO add a test case for this code"); | 4102 | emit_warning(c, source_loc, "TODO add a test case for this code"); |
| 4073 | 4103 | ||
| 4074 | unsigned init_count = ap_value->getArrayInitializedElts(); | 4104 | unsigned init_count = ap_value->getArrayInitializedElts(); |
| ... | @@ -4076,13 +4106,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const | ... | @@ -4076,13 +4106,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const |
| 4076 | unsigned leftover_count = all_count - init_count; | 4106 | unsigned leftover_count = all_count - init_count; |
| 4077 | AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr); | 4107 | AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr); |
| 4078 | AstNode *arr_type_node = trans_qual_type(c, qt, source_loc); | 4108 | AstNode *arr_type_node = trans_qual_type(c, qt, source_loc); |
| 4109 | if (leftover_count != 0) { // We can't use the size of the final array for a partial initializer. | ||
| 4110 | bigint_init_unsigned(arr_type_node->data.array_type.size->data.int_literal.bigint, init_count); | ||
| 4111 | } | ||
| 4079 | init_node->data.container_init_expr.type = arr_type_node; | 4112 | init_node->data.container_init_expr.type = arr_type_node; |
| 4080 | init_node->data.container_init_expr.kind = ContainerInitKindArray; | 4113 | init_node->data.container_init_expr.kind = ContainerInitKindArray; |
| 4081 | 4114 | ||
| 4082 | QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType(); | 4115 | clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType(); |
| 4083 | 4116 | ||
| 4084 | for (size_t i = 0; i < init_count; i += 1) { | 4117 | for (size_t i = 0; i < init_count; i += 1) { |
| 4085 | APValue &elem_ap_val = ap_value->getArrayInitializedElt(i); | 4118 | clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i); |
| 4086 | AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc); | 4119 | AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc); |
| 4087 | if (elem_node == nullptr) | 4120 | if (elem_node == nullptr) |
| 4088 | return nullptr; | 4121 | return nullptr; |
| ... | @@ -4092,15 +4125,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const | ... | @@ -4092,15 +4125,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const |
| 4092 | return init_node; | 4125 | return init_node; |
| 4093 | } | 4126 | } |
| 4094 | 4127 | ||
| 4095 | APValue &filler_ap_val = ap_value->getArrayFiller(); | 4128 | clang::APValue &filler_ap_val = ap_value->getArrayFiller(); |
| 4096 | AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc); | 4129 | AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc); |
| 4097 | if (filler_node == nullptr) | 4130 | if (filler_node == nullptr) |
| 4098 | return nullptr; | 4131 | return nullptr; |
| 4099 | 4132 | ||
| 4133 | AstNode* filler_arr_type = trans_create_node(c, NodeTypeArrayType); | ||
| 4134 | *filler_arr_type = *arr_type_node; | ||
| 4135 | filler_arr_type->data.array_type.size = trans_create_node_unsigned(c, 1); | ||
| 4136 | |||
| 4100 | AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr); | 4137 | AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr); |
| 4101 | init_node->data.container_init_expr.type = arr_type_node; | 4138 | filler_arr_1->data.container_init_expr.type = filler_arr_type; |
| 4102 | init_node->data.container_init_expr.kind = ContainerInitKindArray; | 4139 | filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray; |
| 4103 | init_node->data.container_init_expr.entries.append(filler_node); | 4140 | filler_arr_1->data.container_init_expr.entries.append(filler_node); |
| 4104 | 4141 | ||
| 4105 | AstNode *rhs_node; | 4142 | AstNode *rhs_node; |
| 4106 | if (leftover_count == 1) { | 4143 | if (leftover_count == 1) { |
| ... | @@ -4110,62 +4147,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const | ... | @@ -4110,62 +4147,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const |
| 4110 | rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node); | 4147 | rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node); |
| 4111 | } | 4148 | } |
| 4112 | 4149 | ||
| 4150 | if (init_count == 0) { | ||
| 4151 | return rhs_node; | ||
| 4152 | } | ||
| 4153 | |||
| 4113 | return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node); | 4154 | return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node); |
| 4114 | } | 4155 | } |
| 4115 | case APValue::LValue: { | 4156 | case clang::APValue::LValue: { |
| 4116 | const APValue::LValueBase lval_base = ap_value->getLValueBase(); | 4157 | const clang::APValue::LValueBase lval_base = ap_value->getLValueBase(); |
| 4117 | if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) { | 4158 | if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) { |
| 4118 | return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue); | 4159 | return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue); |
| 4119 | } | 4160 | } |
| 4120 | //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>(); | 4161 | //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>(); |
| 4121 | emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl"); | 4162 | emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl"); |
| 4122 | return nullptr; | 4163 | return nullptr; |
| 4123 | } | 4164 | } |
| 4124 | case APValue::Float: | 4165 | case clang::APValue::Float: |
| 4125 | emit_warning(c, source_loc, "unsupported initializer value kind: Float"); | 4166 | emit_warning(c, source_loc, "unsupported initializer value kind: Float"); |
| 4126 | return nullptr; | 4167 | return nullptr; |
| 4127 | case APValue::ComplexInt: | 4168 | case clang::APValue::ComplexInt: |
| 4128 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt"); | 4169 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt"); |
| 4129 | return nullptr; | 4170 | return nullptr; |
| 4130 | case APValue::ComplexFloat: | 4171 | case clang::APValue::ComplexFloat: |
| 4131 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat"); | 4172 | emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat"); |
| 4132 | return nullptr; | 4173 | return nullptr; |
| 4133 | case APValue::Vector: | 4174 | case clang::APValue::Vector: |
| 4134 | emit_warning(c, source_loc, "unsupported initializer value kind: Vector"); | 4175 | emit_warning(c, source_loc, "unsupported initializer value kind: Vector"); |
| 4135 | return nullptr; | 4176 | return nullptr; |
| 4136 | case APValue::Struct: | 4177 | case clang::APValue::Struct: |
| 4137 | emit_warning(c, source_loc, "unsupported initializer value kind: Struct"); | 4178 | emit_warning(c, source_loc, "unsupported initializer value kind: Struct"); |
| 4138 | return nullptr; | 4179 | return nullptr; |
| 4139 | case APValue::Union: | 4180 | case clang::APValue::Union: |
| 4140 | emit_warning(c, source_loc, "unsupported initializer value kind: Union"); | 4181 | emit_warning(c, source_loc, "unsupported initializer value kind: Union"); |
| 4141 | return nullptr; | 4182 | return nullptr; |
| 4142 | case APValue::MemberPointer: | 4183 | case clang::APValue::MemberPointer: |
| 4143 | emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer"); | 4184 | emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer"); |
| 4144 | return nullptr; | 4185 | return nullptr; |
| 4145 | case APValue::AddrLabelDiff: | 4186 | case clang::APValue::AddrLabelDiff: |
| 4146 | emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff"); | 4187 | emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff"); |
| 4147 | return nullptr; | 4188 | return nullptr; |
| 4148 | } | 4189 | } |
| 4149 | zig_unreachable(); | 4190 | zig_unreachable(); |
| 4150 | } | 4191 | } |
| 4151 | 4192 | ||
| 4152 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { | 4193 | static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) { |
| 4153 | Buf *name = buf_create_from_str(decl_name(var_decl)); | 4194 | Buf *name = buf_create_from_str(decl_name(var_decl)); |
| 4154 | 4195 | ||
| 4155 | switch (var_decl->getTLSKind()) { | 4196 | switch (var_decl->getTLSKind()) { |
| 4156 | case VarDecl::TLS_None: | 4197 | case clang::VarDecl::TLS_None: |
| 4157 | break; | 4198 | break; |
| 4158 | case VarDecl::TLS_Static: | 4199 | case clang::VarDecl::TLS_Static: |
| 4159 | emit_warning(c, var_decl->getLocation(), | 4200 | emit_warning(c, var_decl->getLocation(), |
| 4160 | "ignoring variable '%s' - static thread local storage", buf_ptr(name)); | 4201 | "ignoring variable '%s' - static thread local storage", buf_ptr(name)); |
| 4161 | return; | 4202 | return; |
| 4162 | case VarDecl::TLS_Dynamic: | 4203 | case clang::VarDecl::TLS_Dynamic: |
| 4163 | emit_warning(c, var_decl->getLocation(), | 4204 | emit_warning(c, var_decl->getLocation(), |
| 4164 | "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); | 4205 | "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); |
| 4165 | return; | 4206 | return; |
| 4166 | } | 4207 | } |
| 4167 | 4208 | ||
| 4168 | QualType qt = var_decl->getType(); | 4209 | clang::QualType qt = var_decl->getType(); |
| 4169 | AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); | 4210 | AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); |
| 4170 | if (var_type == nullptr) { | 4211 | if (var_type == nullptr) { |
| 4171 | emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); | 4212 | emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); |
| ... | @@ -4179,7 +4220,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { | ... | @@ -4179,7 +4220,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 4179 | if (is_static && !is_extern) { | 4220 | if (is_static && !is_extern) { |
| 4180 | AstNode *init_node; | 4221 | AstNode *init_node; |
| 4181 | if (var_decl->hasInit()) { | 4222 | if (var_decl->hasInit()) { |
| 4182 | APValue *ap_value = var_decl->evaluateValue(); | 4223 | clang::APValue *ap_value = var_decl->evaluateValue(); |
| 4183 | if (ap_value == nullptr) { | 4224 | if (ap_value == nullptr) { |
| 4184 | emit_warning(c, var_decl->getLocation(), | 4225 | emit_warning(c, var_decl->getLocation(), |
| 4185 | "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); | 4226 | "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); |
| ... | @@ -4209,24 +4250,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { | ... | @@ -4209,24 +4250,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| 4209 | return; | 4250 | return; |
| 4210 | } | 4251 | } |
| 4211 | 4252 | ||
| 4212 | static bool decl_visitor(void *context, const Decl *decl) { | 4253 | static bool decl_visitor(void *context, const ZigClangDecl *zdecl) { |
| 4254 | const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl); | ||
| 4213 | Context *c = (Context*)context; | 4255 | Context *c = (Context*)context; |
| 4214 | 4256 | ||
| 4215 | switch (decl->getKind()) { | 4257 | switch (decl->getKind()) { |
| 4216 | case Decl::Function: | 4258 | case clang::Decl::Function: |
| 4217 | visit_fn_decl(c, static_cast<const FunctionDecl*>(decl)); | 4259 | visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl)); |
| 4218 | break; | 4260 | break; |
| 4219 | case Decl::Typedef: | 4261 | case clang::Decl::Typedef: |
| 4220 | resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); | 4262 | resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl)); |
| 4221 | break; | 4263 | break; |
| 4222 | case Decl::Enum: | 4264 | case clang::Decl::Enum: |
| 4223 | resolve_enum_decl(c, static_cast<const EnumDecl *>(decl)); | 4265 | resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl)); |
| 4224 | break; | 4266 | break; |
| 4225 | case Decl::Record: | 4267 | case clang::Decl::Record: |
| 4226 | resolve_record_decl(c, static_cast<const RecordDecl *>(decl)); | 4268 | resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl)); |
| 4227 | break; | 4269 | break; |
| 4228 | case Decl::Var: | 4270 | case clang::Decl::Var: |
| 4229 | visit_var_decl(c, static_cast<const VarDecl *>(decl)); | 4271 | visit_var_decl(c, static_cast<const clang::VarDecl *>(decl)); |
| 4230 | break; | 4272 | break; |
| 4231 | default: | 4273 | default: |
| 4232 | emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); | 4274 | emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); |
| ... | @@ -4568,7 +4610,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t | ... | @@ -4568,7 +4610,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t |
| 4568 | } else if (first_tok->id == CTokIdAsterisk) { | 4610 | } else if (first_tok->id == CTokIdAsterisk) { |
| 4569 | *tok_i += 1; | 4611 | *tok_i += 1; |
| 4570 | 4612 | ||
| 4571 | node = trans_create_node_ptr_type(c, false, false, node, PtrLenUnknown); | 4613 | node = trans_create_node_ptr_type(c, false, false, node, PtrLenC); |
| 4572 | } else { | 4614 | } else { |
| 4573 | return node; | 4615 | return node; |
| 4574 | } | 4616 | } |
| ... | @@ -4647,24 +4689,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch | ... | @@ -4647,24 +4689,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 4647 | c->macro_table.put(name, result_node); | 4689 | c->macro_table.put(name, result_node); |
| 4648 | } | 4690 | } |
| 4649 | 4691 | ||
| 4650 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | 4692 | static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { |
| 4693 | clang::ASTUnit *unit = reinterpret_cast<clang::ASTUnit *>(zunit); | ||
| 4651 | CTokenize ctok = {{0}}; | 4694 | CTokenize ctok = {{0}}; |
| 4652 | 4695 | ||
| 4653 | // TODO if we see #undef, delete it from the table | 4696 | // TODO if we see #undef, delete it from the table |
| 4654 | 4697 | ||
| 4655 | for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) { | 4698 | for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) { |
| 4656 | switch (entity->getKind()) { | 4699 | switch (entity->getKind()) { |
| 4657 | case PreprocessedEntity::InvalidKind: | 4700 | case clang::PreprocessedEntity::InvalidKind: |
| 4658 | case PreprocessedEntity::InclusionDirectiveKind: | 4701 | case clang::PreprocessedEntity::InclusionDirectiveKind: |
| 4659 | case PreprocessedEntity::MacroExpansionKind: | 4702 | case clang::PreprocessedEntity::MacroExpansionKind: |
| 4660 | continue; | 4703 | continue; |
| 4661 | case PreprocessedEntity::MacroDefinitionKind: | 4704 | case clang::PreprocessedEntity::MacroDefinitionKind: |
| 4662 | { | 4705 | { |
| 4663 | MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity); | 4706 | clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity); |
| 4664 | const char *raw_name = macro->getName()->getNameStart(); | 4707 | const char *raw_name = macro->getName()->getNameStart(); |
| 4665 | SourceRange range = macro->getSourceRange(); | 4708 | clang::SourceRange range = macro->getSourceRange(); |
| 4666 | SourceLocation begin_loc = range.getBegin(); | 4709 | clang::SourceLocation begin_loc = range.getBegin(); |
| 4667 | SourceLocation end_loc = range.getEnd(); | 4710 | clang::SourceLocation end_loc = range.getEnd(); |
| 4668 | 4711 | ||
| 4669 | if (begin_loc == end_loc) { | 4712 | if (begin_loc == end_loc) { |
| 4670 | // this means it is a macro without a value | 4713 | // this means it is a macro without a value |
| ... | @@ -4676,7 +4719,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | ... | @@ -4676,7 +4719,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 4676 | continue; | 4719 | continue; |
| 4677 | } | 4720 | } |
| 4678 | 4721 | ||
| 4679 | const char *begin_c = c->source_manager->getCharacterData(begin_loc); | 4722 | const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc)); |
| 4680 | process_macro(c, &ctok, name, begin_c); | 4723 | process_macro(c, &ctok, name, begin_c); |
| 4681 | } | 4724 | } |
| 4682 | } | 4725 | } |
| ... | @@ -4749,8 +4792,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4749,8 +4792,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4749 | clang_argv.append("-isystem"); | 4792 | clang_argv.append("-isystem"); |
| 4750 | clang_argv.append(buf_ptr(codegen->zig_c_headers_dir)); | 4793 | clang_argv.append(buf_ptr(codegen->zig_c_headers_dir)); |
| 4751 | 4794 | ||
| 4752 | clang_argv.append("-isystem"); | 4795 | if (codegen->libc_include_dir != nullptr) { |
| 4753 | clang_argv.append(buf_ptr(codegen->libc_include_dir)); | 4796 | clang_argv.append("-isystem"); |
| 4797 | clang_argv.append(buf_ptr(codegen->libc_include_dir)); | ||
| 4798 | } | ||
| 4754 | 4799 | ||
| 4755 | // windows c runtime requires -D_DEBUG if using debug libraries | 4800 | // windows c runtime requires -D_DEBUG if using debug libraries |
| 4756 | if (codegen->build_mode == BuildModeDebug) { | 4801 | if (codegen->build_mode == BuildModeDebug) { |
| ... | @@ -4776,12 +4821,20 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4776,12 +4821,20 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4776 | 4821 | ||
| 4777 | clang_argv.append(target_file); | 4822 | clang_argv.append(target_file); |
| 4778 | 4823 | ||
| 4824 | if (codegen->verbose_cimport) { | ||
| 4825 | fprintf(stderr, "clang"); | ||
| 4826 | for (size_t i = 0; i < clang_argv.length; i += 1) { | ||
| 4827 | fprintf(stderr, " %s", clang_argv.at(i)); | ||
| 4828 | } | ||
| 4829 | fprintf(stderr, "\n"); | ||
| 4830 | } | ||
| 4831 | |||
| 4779 | // to make the [start...end] argument work | 4832 | // to make the [start...end] argument work |
| 4780 | clang_argv.append(nullptr); | 4833 | clang_argv.append(nullptr); |
| 4781 | 4834 | ||
| 4782 | IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); | 4835 | clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions)); |
| 4783 | 4836 | ||
| 4784 | std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>(); | 4837 | std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>(); |
| 4785 | 4838 | ||
| 4786 | bool only_local_decls = true; | 4839 | bool only_local_decls = true; |
| 4787 | bool capture_diagnostics = true; | 4840 | bool capture_diagnostics = true; |
| ... | @@ -4790,13 +4843,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4790,13 +4843,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4790 | bool single_file_parse = false; | 4843 | bool single_file_parse = false; |
| 4791 | bool for_serialization = false; | 4844 | bool for_serialization = false; |
| 4792 | const char *resources_path = buf_ptr(codegen->zig_c_headers_dir); | 4845 | const char *resources_path = buf_ptr(codegen->zig_c_headers_dir); |
| 4793 | std::unique_ptr<ASTUnit> err_unit; | 4846 | std::unique_ptr<clang::ASTUnit> err_unit; |
| 4794 | std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine( | 4847 | ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine( |
| 4795 | &clang_argv.at(0), &clang_argv.last(), | 4848 | &clang_argv.at(0), &clang_argv.last(), |
| 4796 | pch_container_ops, diags, resources_path, | 4849 | pch_container_ops, diags, resources_path, |
| 4797 | only_local_decls, capture_diagnostics, None, true, 0, TU_Complete, | 4850 | only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete, |
| 4798 | false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None, | 4851 | false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None, |
| 4799 | single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit, | 4852 | single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit, |
| 4800 | nullptr)); | 4853 | nullptr)); |
| 4801 | 4854 | ||
| 4802 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. | 4855 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. |
| ... | @@ -4806,29 +4859,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4806,29 +4859,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4806 | 4859 | ||
| 4807 | if (diags->getClient()->getNumErrors() > 0) { | 4860 | if (diags->getClient()->getNumErrors() > 0) { |
| 4808 | if (ast_unit) { | 4861 | if (ast_unit) { |
| 4809 | err_unit = std::move(ast_unit); | 4862 | err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit)); |
| 4810 | } | 4863 | } |
| 4811 | 4864 | ||
| 4812 | for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | 4865 | for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), |
| 4813 | it_end = err_unit->stored_diag_end(); | 4866 | it_end = err_unit->stored_diag_end(); |
| 4814 | it != it_end; ++it) | 4867 | it != it_end; ++it) |
| 4815 | { | 4868 | { |
| 4816 | switch (it->getLevel()) { | 4869 | switch (it->getLevel()) { |
| 4817 | case DiagnosticsEngine::Ignored: | 4870 | case clang::DiagnosticsEngine::Ignored: |
| 4818 | case DiagnosticsEngine::Note: | 4871 | case clang::DiagnosticsEngine::Note: |
| 4819 | case DiagnosticsEngine::Remark: | 4872 | case clang::DiagnosticsEngine::Remark: |
| 4820 | case DiagnosticsEngine::Warning: | 4873 | case clang::DiagnosticsEngine::Warning: |
| 4821 | continue; | 4874 | continue; |
| 4822 | case DiagnosticsEngine::Error: | 4875 | case clang::DiagnosticsEngine::Error: |
| 4823 | case DiagnosticsEngine::Fatal: | 4876 | case clang::DiagnosticsEngine::Fatal: |
| 4824 | break; | 4877 | break; |
| 4825 | } | 4878 | } |
| 4826 | StringRef msg_str_ref = it->getMessage(); | 4879 | StringRef msg_str_ref = it->getMessage(); |
| 4827 | Buf *msg = string_ref_to_buf(msg_str_ref); | 4880 | Buf *msg = string_ref_to_buf(msg_str_ref); |
| 4828 | FullSourceLoc fsl = it->getLocation(); | 4881 | clang::FullSourceLoc fsl = it->getLocation(); |
| 4829 | if (fsl.hasManager()) { | 4882 | if (fsl.hasManager()) { |
| 4830 | FileID file_id = fsl.getFileID(); | 4883 | clang::FileID file_id = fsl.getFileID(); |
| 4831 | StringRef filename = fsl.getManager().getFilename(fsl); | 4884 | clang::StringRef filename = fsl.getManager().getFilename(fsl); |
| 4832 | unsigned line = fsl.getSpellingLineNumber() - 1; | 4885 | unsigned line = fsl.getSpellingLineNumber() - 1; |
| 4833 | unsigned column = fsl.getSpellingColumnNumber() - 1; | 4886 | unsigned column = fsl.getSpellingColumnNumber() - 1; |
| 4834 | unsigned offset = fsl.getManager().getFileOffset(fsl); | 4887 | unsigned offset = fsl.getManager().getFileOffset(fsl); |
| ... | @@ -4853,14 +4906,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4853,14 +4906,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4853 | return ErrorCCompileErrors; | 4906 | return ErrorCCompileErrors; |
| 4854 | } | 4907 | } |
| 4855 | 4908 | ||
| 4856 | c->ctx = &ast_unit->getASTContext(); | 4909 | c->ctx = ZigClangASTUnit_getASTContext(ast_unit); |
| 4857 | c->source_manager = &ast_unit->getSourceManager(); | 4910 | c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit); |
| 4858 | c->root = trans_create_node(c, NodeTypeContainerDecl); | 4911 | c->root = trans_create_node(c, NodeTypeContainerDecl); |
| 4859 | c->root->data.container_decl.is_root = true; | 4912 | c->root->data.container_decl.is_root = true; |
| 4860 | 4913 | ||
| 4861 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); | 4914 | ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor); |
| 4862 | 4915 | ||
| 4863 | process_preprocessor_entities(c, *ast_unit); | 4916 | process_preprocessor_entities(c, ast_unit); |
| 4864 | 4917 | ||
| 4865 | render_macros(c); | 4918 | render_macros(c); |
| 4866 | render_aliases(c); | 4919 | render_aliases(c); |
src/zig_clang.cpp created+214| ... | @@ -0,0 +1,214 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2019 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | |||
| 9 | /* | ||
| 10 | * The point of this file is to contain all the Clang C++ API interaction so that: | ||
| 11 | * 1. The compile time of other files is kept under control. | ||
| 12 | * 2. Provide a C interface to the Clang functions we need for self-hosting purposes. | ||
| 13 | * 3. Prevent C++ from infecting the rest of the project. | ||
| 14 | */ | ||
| 15 | #include "zig_clang.h" | ||
| 16 | |||
| 17 | #if __GNUC__ >= 8 | ||
| 18 | #pragma GCC diagnostic push | ||
| 19 | #pragma GCC diagnostic ignored "-Wclass-memaccess" | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include <clang/Frontend/ASTUnit.h> | ||
| 23 | #include <clang/Frontend/CompilerInstance.h> | ||
| 24 | #include <clang/AST/Expr.h> | ||
| 25 | |||
| 26 | #if __GNUC__ >= 8 | ||
| 27 | #pragma GCC diagnostic pop | ||
| 28 | #endif | ||
| 29 | |||
| 30 | // Detect additions to the enum | ||
| 31 | void zig2clang_BO(ZigClangBO op) { | ||
| 32 | switch (op) { | ||
| 33 | case ZigClangBO_PtrMemD: | ||
| 34 | case ZigClangBO_PtrMemI: | ||
| 35 | case ZigClangBO_Cmp: | ||
| 36 | case ZigClangBO_Mul: | ||
| 37 | case ZigClangBO_Div: | ||
| 38 | case ZigClangBO_Rem: | ||
| 39 | case ZigClangBO_Add: | ||
| 40 | case ZigClangBO_Sub: | ||
| 41 | case ZigClangBO_Shl: | ||
| 42 | case ZigClangBO_Shr: | ||
| 43 | case ZigClangBO_LT: | ||
| 44 | case ZigClangBO_GT: | ||
| 45 | case ZigClangBO_LE: | ||
| 46 | case ZigClangBO_GE: | ||
| 47 | case ZigClangBO_EQ: | ||
| 48 | case ZigClangBO_NE: | ||
| 49 | case ZigClangBO_And: | ||
| 50 | case ZigClangBO_Xor: | ||
| 51 | case ZigClangBO_Or: | ||
| 52 | case ZigClangBO_LAnd: | ||
| 53 | case ZigClangBO_LOr: | ||
| 54 | case ZigClangBO_Assign: | ||
| 55 | case ZigClangBO_Comma: | ||
| 56 | case ZigClangBO_MulAssign: | ||
| 57 | case ZigClangBO_DivAssign: | ||
| 58 | case ZigClangBO_RemAssign: | ||
| 59 | case ZigClangBO_AddAssign: | ||
| 60 | case ZigClangBO_SubAssign: | ||
| 61 | case ZigClangBO_ShlAssign: | ||
| 62 | case ZigClangBO_ShrAssign: | ||
| 63 | case ZigClangBO_AndAssign: | ||
| 64 | case ZigClangBO_XorAssign: | ||
| 65 | case ZigClangBO_OrAssign: | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Add == clang::BO_Add, ""); | ||
| 71 | static_assert((clang::BinaryOperatorKind)ZigClangBO_AddAssign == clang::BO_AddAssign, ""); | ||
| 72 | static_assert((clang::BinaryOperatorKind)ZigClangBO_And == clang::BO_And, ""); | ||
| 73 | static_assert((clang::BinaryOperatorKind)ZigClangBO_AndAssign == clang::BO_AndAssign, ""); | ||
| 74 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Assign == clang::BO_Assign, ""); | ||
| 75 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Cmp == clang::BO_Cmp, ""); | ||
| 76 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Comma == clang::BO_Comma, ""); | ||
| 77 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Div == clang::BO_Div, ""); | ||
| 78 | static_assert((clang::BinaryOperatorKind)ZigClangBO_DivAssign == clang::BO_DivAssign, ""); | ||
| 79 | static_assert((clang::BinaryOperatorKind)ZigClangBO_EQ == clang::BO_EQ, ""); | ||
| 80 | static_assert((clang::BinaryOperatorKind)ZigClangBO_GE == clang::BO_GE, ""); | ||
| 81 | static_assert((clang::BinaryOperatorKind)ZigClangBO_GT == clang::BO_GT, ""); | ||
| 82 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LAnd == clang::BO_LAnd, ""); | ||
| 83 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LE == clang::BO_LE, ""); | ||
| 84 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LOr == clang::BO_LOr, ""); | ||
| 85 | static_assert((clang::BinaryOperatorKind)ZigClangBO_LT == clang::BO_LT, ""); | ||
| 86 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Mul == clang::BO_Mul, ""); | ||
| 87 | static_assert((clang::BinaryOperatorKind)ZigClangBO_MulAssign == clang::BO_MulAssign, ""); | ||
| 88 | static_assert((clang::BinaryOperatorKind)ZigClangBO_NE == clang::BO_NE, ""); | ||
| 89 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Or == clang::BO_Or, ""); | ||
| 90 | static_assert((clang::BinaryOperatorKind)ZigClangBO_OrAssign == clang::BO_OrAssign, ""); | ||
| 91 | static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemD == clang::BO_PtrMemD, ""); | ||
| 92 | static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemI == clang::BO_PtrMemI, ""); | ||
| 93 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Rem == clang::BO_Rem, ""); | ||
| 94 | static_assert((clang::BinaryOperatorKind)ZigClangBO_RemAssign == clang::BO_RemAssign, ""); | ||
| 95 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Shl == clang::BO_Shl, ""); | ||
| 96 | static_assert((clang::BinaryOperatorKind)ZigClangBO_ShlAssign == clang::BO_ShlAssign, ""); | ||
| 97 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Shr == clang::BO_Shr, ""); | ||
| 98 | static_assert((clang::BinaryOperatorKind)ZigClangBO_ShrAssign == clang::BO_ShrAssign, ""); | ||
| 99 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Sub == clang::BO_Sub, ""); | ||
| 100 | static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAssign, ""); | ||
| 101 | static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, ""); | ||
| 102 | static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, ""); | ||
| 103 | |||
| 104 | // This function detects additions to the enum | ||
| 105 | void zig2clang_UO(ZigClangUO op) { | ||
| 106 | switch (op) { | ||
| 107 | case ZigClangUO_AddrOf: | ||
| 108 | case ZigClangUO_Coawait: | ||
| 109 | case ZigClangUO_Deref: | ||
| 110 | case ZigClangUO_Extension: | ||
| 111 | case ZigClangUO_Imag: | ||
| 112 | case ZigClangUO_LNot: | ||
| 113 | case ZigClangUO_Minus: | ||
| 114 | case ZigClangUO_Not: | ||
| 115 | case ZigClangUO_Plus: | ||
| 116 | case ZigClangUO_PostDec: | ||
| 117 | case ZigClangUO_PostInc: | ||
| 118 | case ZigClangUO_PreDec: | ||
| 119 | case ZigClangUO_PreInc: | ||
| 120 | case ZigClangUO_Real: | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | static_assert((clang::UnaryOperatorKind)ZigClangUO_AddrOf == clang::UO_AddrOf, ""); | ||
| 126 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Coawait == clang::UO_Coawait, ""); | ||
| 127 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Deref == clang::UO_Deref, ""); | ||
| 128 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Extension == clang::UO_Extension, ""); | ||
| 129 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Imag == clang::UO_Imag, ""); | ||
| 130 | static_assert((clang::UnaryOperatorKind)ZigClangUO_LNot == clang::UO_LNot, ""); | ||
| 131 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Minus == clang::UO_Minus, ""); | ||
| 132 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Not == clang::UO_Not, ""); | ||
| 133 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Plus == clang::UO_Plus, ""); | ||
| 134 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PostDec == clang::UO_PostDec, ""); | ||
| 135 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PostInc == clang::UO_PostInc, ""); | ||
| 136 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, ""); | ||
| 137 | static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, ""); | ||
| 138 | static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, ""); | ||
| 139 | |||
| 140 | static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), ""); | ||
| 141 | static ZigClangSourceLocation bitcast(clang::SourceLocation src) { | ||
| 142 | ZigClangSourceLocation dest; | ||
| 143 | memcpy(&dest, &src, sizeof(ZigClangSourceLocation)); | ||
| 144 | return dest; | ||
| 145 | } | ||
| 146 | static clang::SourceLocation bitcast(ZigClangSourceLocation src) { | ||
| 147 | clang::SourceLocation dest; | ||
| 148 | memcpy(&dest, &src, sizeof(ZigClangSourceLocation)); | ||
| 149 | return dest; | ||
| 150 | } | ||
| 151 | |||
| 152 | static_assert(sizeof(ZigClangQualType) == sizeof(clang::QualType), ""); | ||
| 153 | static ZigClangQualType bitcast(clang::QualType src) { | ||
| 154 | ZigClangQualType dest; | ||
| 155 | memcpy(&dest, &src, sizeof(ZigClangQualType)); | ||
| 156 | return dest; | ||
| 157 | } | ||
| 158 | static clang::QualType bitcast(ZigClangQualType src) { | ||
| 159 | clang::QualType dest; | ||
| 160 | memcpy(&dest, &src, sizeof(ZigClangQualType)); | ||
| 161 | return dest; | ||
| 162 | } | ||
| 163 | |||
| 164 | ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self, | ||
| 165 | ZigClangSourceLocation Loc) | ||
| 166 | { | ||
| 167 | return bitcast(reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLoc(bitcast(Loc))); | ||
| 168 | } | ||
| 169 | |||
| 170 | const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *self, | ||
| 171 | ZigClangSourceLocation SpellingLoc) | ||
| 172 | { | ||
| 173 | StringRef s = reinterpret_cast<const clang::SourceManager *>(self)->getFilename(bitcast(SpellingLoc)); | ||
| 174 | return (const char *)s.bytes_begin(); | ||
| 175 | } | ||
| 176 | |||
| 177 | unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *self, | ||
| 178 | ZigClangSourceLocation Loc) | ||
| 179 | { | ||
| 180 | return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLineNumber(bitcast(Loc)); | ||
| 181 | } | ||
| 182 | |||
| 183 | unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *self, | ||
| 184 | ZigClangSourceLocation Loc) | ||
| 185 | { | ||
| 186 | return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingColumnNumber(bitcast(Loc)); | ||
| 187 | } | ||
| 188 | |||
| 189 | const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *self, | ||
| 190 | ZigClangSourceLocation SL) | ||
| 191 | { | ||
| 192 | return reinterpret_cast<const clang::SourceManager *>(self)->getCharacterData(bitcast(SL)); | ||
| 193 | } | ||
| 194 | |||
| 195 | ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* self, ZigClangQualType T) { | ||
| 196 | return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T))); | ||
| 197 | } | ||
| 198 | |||
| 199 | ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) { | ||
| 200 | clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext(); | ||
| 201 | return reinterpret_cast<ZigClangASTContext *>(result); | ||
| 202 | } | ||
| 203 | |||
| 204 | ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) { | ||
| 205 | clang::SourceManager *result = &reinterpret_cast<clang::ASTUnit *>(self)->getSourceManager(); | ||
| 206 | return reinterpret_cast<ZigClangSourceManager *>(result); | ||
| 207 | } | ||
| 208 | |||
| 209 | bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context, | ||
| 210 | bool (*Fn)(void *context, const ZigClangDecl *decl)) | ||
| 211 | { | ||
| 212 | return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context, | ||
| 213 | reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn)); | ||
| 214 | } | ||
src/zig_clang.h created+259| ... | @@ -0,0 +1,259 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2019 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_ZIG_CLANG_H | ||
| 9 | #define ZIG_ZIG_CLANG_H | ||
| 10 | |||
| 11 | #ifdef __cplusplus | ||
| 12 | #define ZIG_EXTERN_C extern "C" | ||
| 13 | #else | ||
| 14 | #define ZIG_EXTERN_C | ||
| 15 | #endif | ||
| 16 | |||
| 17 | // ATTENTION: If you modify this file, be sure to update the corresponding | ||
| 18 | // extern function declarations in the self-hosted compiler. | ||
| 19 | |||
| 20 | struct ZigClangSourceLocation { | ||
| 21 | unsigned ID; | ||
| 22 | }; | ||
| 23 | |||
| 24 | struct ZigClangQualType { | ||
| 25 | void *ptr; | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct ZigClangAPValue; | ||
| 29 | struct ZigClangASTContext; | ||
| 30 | struct ZigClangASTUnit; | ||
| 31 | struct ZigClangArraySubscriptExpr; | ||
| 32 | struct ZigClangArrayType; | ||
| 33 | struct ZigClangAttributedType; | ||
| 34 | struct ZigClangBinaryOperator; | ||
| 35 | struct ZigClangBreakStmt; | ||
| 36 | struct ZigClangBuiltinType; | ||
| 37 | struct ZigClangCStyleCastExpr; | ||
| 38 | struct ZigClangCallExpr; | ||
| 39 | struct ZigClangCaseStmt; | ||
| 40 | struct ZigClangCompoundAssignOperator; | ||
| 41 | struct ZigClangCompoundStmt; | ||
| 42 | struct ZigClangConditionalOperator; | ||
| 43 | struct ZigClangConstantArrayType; | ||
| 44 | struct ZigClangContinueStmt; | ||
| 45 | struct ZigClangDecayedType; | ||
| 46 | struct ZigClangDecl; | ||
| 47 | struct ZigClangDeclRefExpr; | ||
| 48 | struct ZigClangDeclStmt; | ||
| 49 | struct ZigClangDefaultStmt; | ||
| 50 | struct ZigClangDiagnosticOptions; | ||
| 51 | struct ZigClangDiagnosticsEngine; | ||
| 52 | struct ZigClangDoStmt; | ||
| 53 | struct ZigClangElaboratedType; | ||
| 54 | struct ZigClangEnumConstantDecl; | ||
| 55 | struct ZigClangEnumDecl; | ||
| 56 | struct ZigClangEnumType; | ||
| 57 | struct ZigClangExpr; | ||
| 58 | struct ZigClangFieldDecl; | ||
| 59 | struct ZigClangFileID; | ||
| 60 | struct ZigClangForStmt; | ||
| 61 | struct ZigClangFullSourceLoc; | ||
| 62 | struct ZigClangFunctionDecl; | ||
| 63 | struct ZigClangFunctionProtoType; | ||
| 64 | struct ZigClangIfStmt; | ||
| 65 | struct ZigClangImplicitCastExpr; | ||
| 66 | struct ZigClangIncompleteArrayType; | ||
| 67 | struct ZigClangIntegerLiteral; | ||
| 68 | struct ZigClangMacroDefinitionRecord; | ||
| 69 | struct ZigClangMemberExpr; | ||
| 70 | struct ZigClangNamedDecl; | ||
| 71 | struct ZigClangNone; | ||
| 72 | struct ZigClangPCHContainerOperations; | ||
| 73 | struct ZigClangParenExpr; | ||
| 74 | struct ZigClangParenType; | ||
| 75 | struct ZigClangParmVarDecl; | ||
| 76 | struct ZigClangPointerType; | ||
| 77 | struct ZigClangPreprocessedEntity; | ||
| 78 | struct ZigClangRecordDecl; | ||
| 79 | struct ZigClangRecordType; | ||
| 80 | struct ZigClangReturnStmt; | ||
| 81 | struct ZigClangSkipFunctionBodiesScope; | ||
| 82 | struct ZigClangSourceManager; | ||
| 83 | struct ZigClangSourceRange; | ||
| 84 | struct ZigClangStmt; | ||
| 85 | struct ZigClangStorageClass; | ||
| 86 | struct ZigClangStringLiteral; | ||
| 87 | struct ZigClangStringRef; | ||
| 88 | struct ZigClangSwitchStmt; | ||
| 89 | struct ZigClangType; | ||
| 90 | struct ZigClangTypedefNameDecl; | ||
| 91 | struct ZigClangTypedefType; | ||
| 92 | struct ZigClangUnaryExprOrTypeTraitExpr; | ||
| 93 | struct ZigClangUnaryOperator; | ||
| 94 | struct ZigClangValueDecl; | ||
| 95 | struct ZigClangVarDecl; | ||
| 96 | struct ZigClangWhileStmt; | ||
| 97 | |||
| 98 | enum ZigClangBO { | ||
| 99 | ZigClangBO_PtrMemD, | ||
| 100 | ZigClangBO_PtrMemI, | ||
| 101 | ZigClangBO_Mul, | ||
| 102 | ZigClangBO_Div, | ||
| 103 | ZigClangBO_Rem, | ||
| 104 | ZigClangBO_Add, | ||
| 105 | ZigClangBO_Sub, | ||
| 106 | ZigClangBO_Shl, | ||
| 107 | ZigClangBO_Shr, | ||
| 108 | ZigClangBO_Cmp, | ||
| 109 | ZigClangBO_LT, | ||
| 110 | ZigClangBO_GT, | ||
| 111 | ZigClangBO_LE, | ||
| 112 | ZigClangBO_GE, | ||
| 113 | ZigClangBO_EQ, | ||
| 114 | ZigClangBO_NE, | ||
| 115 | ZigClangBO_And, | ||
| 116 | ZigClangBO_Xor, | ||
| 117 | ZigClangBO_Or, | ||
| 118 | ZigClangBO_LAnd, | ||
| 119 | ZigClangBO_LOr, | ||
| 120 | ZigClangBO_Assign, | ||
| 121 | ZigClangBO_MulAssign, | ||
| 122 | ZigClangBO_DivAssign, | ||
| 123 | ZigClangBO_RemAssign, | ||
| 124 | ZigClangBO_AddAssign, | ||
| 125 | ZigClangBO_SubAssign, | ||
| 126 | ZigClangBO_ShlAssign, | ||
| 127 | ZigClangBO_ShrAssign, | ||
| 128 | ZigClangBO_AndAssign, | ||
| 129 | ZigClangBO_XorAssign, | ||
| 130 | ZigClangBO_OrAssign, | ||
| 131 | ZigClangBO_Comma, | ||
| 132 | }; | ||
| 133 | |||
| 134 | enum ZigClangUO { | ||
| 135 | ZigClangUO_PostInc, | ||
| 136 | ZigClangUO_PostDec, | ||
| 137 | ZigClangUO_PreInc, | ||
| 138 | ZigClangUO_PreDec, | ||
| 139 | ZigClangUO_AddrOf, | ||
| 140 | ZigClangUO_Deref, | ||
| 141 | ZigClangUO_Plus, | ||
| 142 | ZigClangUO_Minus, | ||
| 143 | ZigClangUO_Not, | ||
| 144 | ZigClangUO_LNot, | ||
| 145 | ZigClangUO_Real, | ||
| 146 | ZigClangUO_Imag, | ||
| 147 | ZigClangUO_Extension, | ||
| 148 | ZigClangUO_Coawait, | ||
| 149 | }; | ||
| 150 | |||
| 151 | //struct ZigClangCC_AAPCS; | ||
| 152 | //struct ZigClangCC_AAPCS_VFP; | ||
| 153 | //struct ZigClangCC_C; | ||
| 154 | //struct ZigClangCC_IntelOclBicc; | ||
| 155 | //struct ZigClangCC_OpenCLKernel; | ||
| 156 | //struct ZigClangCC_PreserveAll; | ||
| 157 | //struct ZigClangCC_PreserveMost; | ||
| 158 | //struct ZigClangCC_SpirFunction; | ||
| 159 | //struct ZigClangCC_Swift; | ||
| 160 | //struct ZigClangCC_Win64; | ||
| 161 | //struct ZigClangCC_X86FastCall; | ||
| 162 | //struct ZigClangCC_X86Pascal; | ||
| 163 | //struct ZigClangCC_X86RegCall; | ||
| 164 | //struct ZigClangCC_X86StdCall; | ||
| 165 | //struct ZigClangCC_X86ThisCall; | ||
| 166 | //struct ZigClangCC_X86VectorCall; | ||
| 167 | //struct ZigClangCC_X86_64SysV; | ||
| 168 | |||
| 169 | //struct ZigClangCK_ARCConsumeObject; | ||
| 170 | //struct ZigClangCK_ARCExtendBlockObject; | ||
| 171 | //struct ZigClangCK_ARCProduceObject; | ||
| 172 | //struct ZigClangCK_ARCReclaimReturnedObject; | ||
| 173 | //struct ZigClangCK_AddressSpaceConversion; | ||
| 174 | //struct ZigClangCK_AnyPointerToBlockPointerCast; | ||
| 175 | //struct ZigClangCK_ArrayToPointerDecay; | ||
| 176 | //struct ZigClangCK_AtomicToNonAtomic; | ||
| 177 | //struct ZigClangCK_BaseToDerived; | ||
| 178 | //struct ZigClangCK_BaseToDerivedMemberPointer; | ||
| 179 | //struct ZigClangCK_BitCast; | ||
| 180 | //struct ZigClangCK_BlockPointerToObjCPointerCast; | ||
| 181 | //struct ZigClangCK_BooleanToSignedIntegral; | ||
| 182 | //struct ZigClangCK_BuiltinFnToFnPtr; | ||
| 183 | //struct ZigClangCK_CPointerToObjCPointerCast; | ||
| 184 | //struct ZigClangCK_ConstructorConversion; | ||
| 185 | //struct ZigClangCK_CopyAndAutoreleaseBlockObject; | ||
| 186 | //struct ZigClangCK_Dependent; | ||
| 187 | //struct ZigClangCK_DerivedToBase; | ||
| 188 | //struct ZigClangCK_DerivedToBaseMemberPointer; | ||
| 189 | //struct ZigClangCK_Dynamic; | ||
| 190 | //struct ZigClangCK_FloatingCast; | ||
| 191 | //struct ZigClangCK_FloatingComplexCast; | ||
| 192 | //struct ZigClangCK_FloatingComplexToBoolean; | ||
| 193 | //struct ZigClangCK_FloatingComplexToIntegralComplex; | ||
| 194 | //struct ZigClangCK_FloatingComplexToReal; | ||
| 195 | //struct ZigClangCK_FloatingRealToComplex; | ||
| 196 | //struct ZigClangCK_FloatingToBoolean; | ||
| 197 | //struct ZigClangCK_FloatingToIntegral; | ||
| 198 | //struct ZigClangCK_FunctionToPointerDecay; | ||
| 199 | //struct ZigClangCK_IntToOCLSampler; | ||
| 200 | //struct ZigClangCK_IntegralCast; | ||
| 201 | //struct ZigClangCK_IntegralComplexCast; | ||
| 202 | //struct ZigClangCK_IntegralComplexToBoolean; | ||
| 203 | //struct ZigClangCK_IntegralComplexToFloatingComplex; | ||
| 204 | //struct ZigClangCK_IntegralComplexToReal; | ||
| 205 | //struct ZigClangCK_IntegralRealToComplex; | ||
| 206 | //struct ZigClangCK_IntegralToBoolean; | ||
| 207 | //struct ZigClangCK_IntegralToFloating; | ||
| 208 | //struct ZigClangCK_IntegralToPointer; | ||
| 209 | //struct ZigClangCK_LValueBitCast; | ||
| 210 | //struct ZigClangCK_LValueToRValue; | ||
| 211 | //struct ZigClangCK_MemberPointerToBoolean; | ||
| 212 | //struct ZigClangCK_NoOp; | ||
| 213 | //struct ZigClangCK_NonAtomicToAtomic; | ||
| 214 | //struct ZigClangCK_NullToMemberPointer; | ||
| 215 | //struct ZigClangCK_NullToPointer; | ||
| 216 | //struct ZigClangCK_ObjCObjectLValueCast; | ||
| 217 | //struct ZigClangCK_PointerToBoolean; | ||
| 218 | //struct ZigClangCK_PointerToIntegral; | ||
| 219 | //struct ZigClangCK_ReinterpretMemberPointer; | ||
| 220 | //struct ZigClangCK_ToUnion; | ||
| 221 | //struct ZigClangCK_ToVoid; | ||
| 222 | //struct ZigClangCK_UncheckedDerivedToBase; | ||
| 223 | //struct ZigClangCK_UserDefinedConversion; | ||
| 224 | //struct ZigClangCK_VectorSplat; | ||
| 225 | //struct ZigClangCK_ZeroToOCLEvent; | ||
| 226 | //struct ZigClangCK_ZeroToOCLQueue; | ||
| 227 | |||
| 228 | //struct ZigClangETK_Class; | ||
| 229 | //struct ZigClangETK_Enum; | ||
| 230 | //struct ZigClangETK_Interface; | ||
| 231 | //struct ZigClangETK_None; | ||
| 232 | //struct ZigClangETK_Struct; | ||
| 233 | //struct ZigClangETK_Typename; | ||
| 234 | //struct ZigClangETK_Union; | ||
| 235 | |||
| 236 | //struct ZigClangSC_None; | ||
| 237 | //struct ZigClangSC_PrivateExtern; | ||
| 238 | //struct ZigClangSC_Static; | ||
| 239 | |||
| 240 | //struct ZigClangTU_Complete; | ||
| 241 | |||
| 242 | ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *, | ||
| 243 | ZigClangSourceLocation Loc); | ||
| 244 | ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *, | ||
| 245 | ZigClangSourceLocation SpellingLoc); | ||
| 246 | ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *, | ||
| 247 | ZigClangSourceLocation Loc); | ||
| 248 | ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *, | ||
| 249 | ZigClangSourceLocation Loc); | ||
| 250 | ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *, | ||
| 251 | ZigClangSourceLocation SL); | ||
| 252 | |||
| 253 | ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T); | ||
| 254 | |||
| 255 | ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *); | ||
| 256 | ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *); | ||
| 257 | ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context, | ||
| 258 | bool (*Fn)(void *context, const ZigClangDecl *decl)); | ||
| 259 | #endif | ||
src/zig_llvm.cpp+14-1| ... | @@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch | ... | @@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch |
| 263 | return reinterpret_cast<ZigLLVMDIType*>(di_type); | 263 | return reinterpret_cast<ZigLLVMDIType*>(di_type); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder, | ||
| 267 | uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count) | ||
| 268 | { | ||
| 269 | SmallVector<Metadata *, 1> subrange; | ||
| 270 | subrange.push_back(reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateSubrange(0, elem_count)); | ||
| 271 | DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createVectorType( | ||
| 272 | SizeInBits, | ||
| 273 | AlignInBits, | ||
| 274 | reinterpret_cast<DIType*>(Ty), | ||
| 275 | reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(subrange)); | ||
| 276 | return reinterpret_cast<ZigLLVMDIType*>(di_type); | ||
| 277 | } | ||
| 278 | |||
| 266 | ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits, | 279 | ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits, |
| 267 | uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count) | 280 | uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count) |
| 268 | { | 281 | { |
| ... | @@ -605,7 +618,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD | ... | @@ -605,7 +618,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD |
| 605 | reinterpret_cast<DIFile*>(file), | 618 | reinterpret_cast<DIFile*>(file), |
| 606 | lineno, | 619 | lineno, |
| 607 | di_sub_type, | 620 | di_sub_type, |
| 608 | is_local_to_unit, is_definition, scope_line, DINode::FlagZero, is_optimized, | 621 | is_local_to_unit, is_definition, scope_line, DINode::FlagStaticMember, is_optimized, |
| 609 | nullptr, | 622 | nullptr, |
| 610 | reinterpret_cast<DISubprogram *>(decl_subprogram)); | 623 | reinterpret_cast<DISubprogram *>(decl_subprogram)); |
| 611 | return reinterpret_cast<ZigLLVMDISubprogram*>(result); | 624 | return reinterpret_cast<ZigLLVMDISubprogram*>(result); |
src/zig_llvm.h+3| ... | @@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB | ... | @@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB |
| 191 | unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, | 191 | unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, |
| 192 | unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram); | 192 | unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram); |
| 193 | 193 | ||
| 194 | ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder, | ||
| 195 | uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count); | ||
| 196 | |||
| 194 | ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram); | 197 | ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram); |
| 195 | 198 | ||
| 196 | ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder); | 199 | ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder); |
std/array_list.zig+63-52| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const debug = std.debug; | 2 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 3 | const assert = debug.assert; |
| 4 | const assertError = debug.assertError; | 4 | const testing = std.testing; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| 7 | 7 | ||
| ... | @@ -212,8 +212,8 @@ test "std.ArrayList.init" { | ... | @@ -212,8 +212,8 @@ test "std.ArrayList.init" { |
| 212 | var list = ArrayList(i32).init(allocator); | 212 | var list = ArrayList(i32).init(allocator); |
| 213 | defer list.deinit(); | 213 | defer list.deinit(); |
| 214 | 214 | ||
| 215 | assert(list.count() == 0); | 215 | testing.expect(list.count() == 0); |
| 216 | assert(list.capacity() == 0); | 216 | testing.expect(list.capacity() == 0); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | test "std.ArrayList.basic" { | 219 | test "std.ArrayList.basic" { |
| ... | @@ -224,7 +224,7 @@ test "std.ArrayList.basic" { | ... | @@ -224,7 +224,7 @@ test "std.ArrayList.basic" { |
| 224 | defer list.deinit(); | 224 | defer list.deinit(); |
| 225 | 225 | ||
| 226 | // setting on empty list is out of bounds | 226 | // setting on empty list is out of bounds |
| 227 | assertError(list.setOrError(0, 1), error.OutOfBounds); | 227 | testing.expectError(error.OutOfBounds, list.setOrError(0, 1)); |
| 228 | 228 | ||
| 229 | { | 229 | { |
| 230 | var i: usize = 0; | 230 | var i: usize = 0; |
| ... | @@ -236,44 +236,44 @@ test "std.ArrayList.basic" { | ... | @@ -236,44 +236,44 @@ test "std.ArrayList.basic" { |
| 236 | { | 236 | { |
| 237 | var i: usize = 0; | 237 | var i: usize = 0; |
| 238 | while (i < 10) : (i += 1) { | 238 | while (i < 10) : (i += 1) { |
| 239 | assert(list.items[i] == @intCast(i32, i + 1)); | 239 | testing.expect(list.items[i] == @intCast(i32, i + 1)); |
| 240 | } | 240 | } |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | for (list.toSlice()) |v, i| { | 243 | for (list.toSlice()) |v, i| { |
| 244 | assert(v == @intCast(i32, i + 1)); | 244 | testing.expect(v == @intCast(i32, i + 1)); |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | for (list.toSliceConst()) |v, i| { | 247 | for (list.toSliceConst()) |v, i| { |
| 248 | assert(v == @intCast(i32, i + 1)); | 248 | testing.expect(v == @intCast(i32, i + 1)); |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | assert(list.pop() == 10); | 251 | testing.expect(list.pop() == 10); |
| 252 | assert(list.len == 9); | 252 | testing.expect(list.len == 9); |
| 253 | 253 | ||
| 254 | list.appendSlice([]const i32{ | 254 | list.appendSlice([]const i32{ |
| 255 | 1, | 255 | 1, |
| 256 | 2, | 256 | 2, |
| 257 | 3, | 257 | 3, |
| 258 | }) catch unreachable; | 258 | }) catch unreachable; |
| 259 | assert(list.len == 12); | 259 | testing.expect(list.len == 12); |
| 260 | assert(list.pop() == 3); | 260 | testing.expect(list.pop() == 3); |
| 261 | assert(list.pop() == 2); | 261 | testing.expect(list.pop() == 2); |
| 262 | assert(list.pop() == 1); | 262 | testing.expect(list.pop() == 1); |
| 263 | assert(list.len == 9); | 263 | testing.expect(list.len == 9); |
| 264 | 264 | ||
| 265 | list.appendSlice([]const i32{}) catch unreachable; | 265 | list.appendSlice([]const i32{}) catch unreachable; |
| 266 | assert(list.len == 9); | 266 | testing.expect(list.len == 9); |
| 267 | 267 | ||
| 268 | // can only set on indices < self.len | 268 | // can only set on indices < self.len |
| 269 | list.set(7, 33); | 269 | list.set(7, 33); |
| 270 | list.set(8, 42); | 270 | list.set(8, 42); |
| 271 | 271 | ||
| 272 | assertError(list.setOrError(9, 99), error.OutOfBounds); | 272 | testing.expectError(error.OutOfBounds, list.setOrError(9, 99)); |
| 273 | assertError(list.setOrError(10, 123), error.OutOfBounds); | 273 | testing.expectError(error.OutOfBounds, list.setOrError(10, 123)); |
| 274 | 274 | ||
| 275 | assert(list.pop() == 42); | 275 | testing.expect(list.pop() == 42); |
| 276 | assert(list.pop() == 33); | 276 | testing.expect(list.pop() == 33); |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | test "std.ArrayList.swapRemove" { | 279 | test "std.ArrayList.swapRemove" { |
| ... | @@ -289,18 +289,18 @@ test "std.ArrayList.swapRemove" { | ... | @@ -289,18 +289,18 @@ test "std.ArrayList.swapRemove" { |
| 289 | try list.append(7); | 289 | try list.append(7); |
| 290 | 290 | ||
| 291 | //remove from middle | 291 | //remove from middle |
| 292 | assert(list.swapRemove(3) == 4); | 292 | testing.expect(list.swapRemove(3) == 4); |
| 293 | assert(list.at(3) == 7); | 293 | testing.expect(list.at(3) == 7); |
| 294 | assert(list.len == 6); | 294 | testing.expect(list.len == 6); |
| 295 | 295 | ||
| 296 | //remove from end | 296 | //remove from end |
| 297 | assert(list.swapRemove(5) == 6); | 297 | testing.expect(list.swapRemove(5) == 6); |
| 298 | assert(list.len == 5); | 298 | testing.expect(list.len == 5); |
| 299 | 299 | ||
| 300 | //remove from front | 300 | //remove from front |
| 301 | assert(list.swapRemove(0) == 1); | 301 | testing.expect(list.swapRemove(0) == 1); |
| 302 | assert(list.at(0) == 5); | 302 | testing.expect(list.at(0) == 5); |
| 303 | assert(list.len == 4); | 303 | testing.expect(list.len == 4); |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | test "std.ArrayList.swapRemoveOrError" { | 306 | test "std.ArrayList.swapRemoveOrError" { |
| ... | @@ -308,27 +308,27 @@ test "std.ArrayList.swapRemoveOrError" { | ... | @@ -308,27 +308,27 @@ test "std.ArrayList.swapRemoveOrError" { |
| 308 | defer list.deinit(); | 308 | defer list.deinit(); |
| 309 | 309 | ||
| 310 | // Test just after initialization | 310 | // Test just after initialization |
| 311 | assertError(list.swapRemoveOrError(0), error.OutOfBounds); | 311 | testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0)); |
| 312 | 312 | ||
| 313 | // Test after adding one item and remote it | 313 | // Test after adding one item and remote it |
| 314 | try list.append(1); | 314 | try list.append(1); |
| 315 | assert((try list.swapRemoveOrError(0)) == 1); | 315 | testing.expect((try list.swapRemoveOrError(0)) == 1); |
| 316 | assertError(list.swapRemoveOrError(0), error.OutOfBounds); | 316 | testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0)); |
| 317 | 317 | ||
| 318 | // Test after adding two items and remote both | 318 | // Test after adding two items and remote both |
| 319 | try list.append(1); | 319 | try list.append(1); |
| 320 | try list.append(2); | 320 | try list.append(2); |
| 321 | assert((try list.swapRemoveOrError(1)) == 2); | 321 | testing.expect((try list.swapRemoveOrError(1)) == 2); |
| 322 | assert((try list.swapRemoveOrError(0)) == 1); | 322 | testing.expect((try list.swapRemoveOrError(0)) == 1); |
| 323 | assertError(list.swapRemoveOrError(0), error.OutOfBounds); | 323 | testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0)); |
| 324 | 324 | ||
| 325 | // Test out of bounds with one item | 325 | // Test out of bounds with one item |
| 326 | try list.append(1); | 326 | try list.append(1); |
| 327 | assertError(list.swapRemoveOrError(1), error.OutOfBounds); | 327 | testing.expectError(error.OutOfBounds, list.swapRemoveOrError(1)); |
| 328 | 328 | ||
| 329 | // Test out of bounds with two items | 329 | // Test out of bounds with two items |
| 330 | try list.append(2); | 330 | try list.append(2); |
| 331 | assertError(list.swapRemoveOrError(2), error.OutOfBounds); | 331 | testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2)); |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | test "std.ArrayList.iterator" { | 334 | test "std.ArrayList.iterator" { |
| ... | @@ -342,22 +342,22 @@ test "std.ArrayList.iterator" { | ... | @@ -342,22 +342,22 @@ test "std.ArrayList.iterator" { |
| 342 | var count: i32 = 0; | 342 | var count: i32 = 0; |
| 343 | var it = list.iterator(); | 343 | var it = list.iterator(); |
| 344 | while (it.next()) |next| { | 344 | while (it.next()) |next| { |
| 345 | assert(next == count + 1); | 345 | testing.expect(next == count + 1); |
| 346 | count += 1; | 346 | count += 1; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | assert(count == 3); | 349 | testing.expect(count == 3); |
| 350 | assert(it.next() == null); | 350 | testing.expect(it.next() == null); |
| 351 | it.reset(); | 351 | it.reset(); |
| 352 | count = 0; | 352 | count = 0; |
| 353 | while (it.next()) |next| { | 353 | while (it.next()) |next| { |
| 354 | assert(next == count + 1); | 354 | testing.expect(next == count + 1); |
| 355 | count += 1; | 355 | count += 1; |
| 356 | if (count == 2) break; | 356 | if (count == 2) break; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | it.reset(); | 359 | it.reset(); |
| 360 | assert(it.next().? == 1); | 360 | testing.expect(it.next().? == 1); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | test "std.ArrayList.insert" { | 363 | test "std.ArrayList.insert" { |
| ... | @@ -368,10 +368,10 @@ test "std.ArrayList.insert" { | ... | @@ -368,10 +368,10 @@ test "std.ArrayList.insert" { |
| 368 | try list.append(2); | 368 | try list.append(2); |
| 369 | try list.append(3); | 369 | try list.append(3); |
| 370 | try list.insert(0, 5); | 370 | try list.insert(0, 5); |
| 371 | assert(list.items[0] == 5); | 371 | testing.expect(list.items[0] == 5); |
| 372 | assert(list.items[1] == 1); | 372 | testing.expect(list.items[1] == 1); |
| 373 | assert(list.items[2] == 2); | 373 | testing.expect(list.items[2] == 2); |
| 374 | assert(list.items[3] == 3); | 374 | testing.expect(list.items[3] == 3); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | test "std.ArrayList.insertSlice" { | 377 | test "std.ArrayList.insertSlice" { |
| ... | @@ -386,15 +386,26 @@ test "std.ArrayList.insertSlice" { | ... | @@ -386,15 +386,26 @@ test "std.ArrayList.insertSlice" { |
| 386 | 9, | 386 | 9, |
| 387 | 8, | 387 | 8, |
| 388 | }); | 388 | }); |
| 389 | assert(list.items[0] == 1); | 389 | testing.expect(list.items[0] == 1); |
| 390 | assert(list.items[1] == 9); | 390 | testing.expect(list.items[1] == 9); |
| 391 | assert(list.items[2] == 8); | 391 | testing.expect(list.items[2] == 8); |
| 392 | assert(list.items[3] == 2); | 392 | testing.expect(list.items[3] == 2); |
| 393 | assert(list.items[4] == 3); | 393 | testing.expect(list.items[4] == 3); |
| 394 | assert(list.items[5] == 4); | 394 | testing.expect(list.items[5] == 4); |
| 395 | 395 | ||
| 396 | const items = []const i32{1}; | 396 | const items = []const i32{1}; |
| 397 | try list.insertSlice(0, items[0..0]); | 397 | try list.insertSlice(0, items[0..0]); |
| 398 | assert(list.len == 6); | 398 | testing.expect(list.len == 6); |
| 399 | assert(list.items[0] == 1); | 399 | testing.expect(list.items[0] == 1); |
| 400 | } | ||
| 401 | |||
| 402 | const Item = struct { | ||
| 403 | integer: i32, | ||
| 404 | sub_items: ArrayList(Item), | ||
| 405 | }; | ||
| 406 | |||
| 407 | test "std.ArrayList: ArrayList(T) of struct T" { | ||
| 408 | var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) }; | ||
| 409 | try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } ); | ||
| 410 | testing.expect(root.sub_items.items[0].integer == 42); | ||
| 400 | } | 411 | } |
std/atomic/queue.zig+42-24| ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const AtomicOrder = builtin.AtomicOrder; | 3 | const AtomicOrder = builtin.AtomicOrder; |
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | 4 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| 6 | const expect = std.testing.expect; | ||
| 6 | 7 | ||
| 7 | /// Many producer, many consumer, non-allocating, thread-safe. | 8 | /// Many producer, many consumer, non-allocating, thread-safe. |
| 8 | /// Uses a mutex to protect access. | 9 | /// Uses a mutex to protect access. |
| ... | @@ -170,20 +171,36 @@ test "std.atomic.Queue" { | ... | @@ -170,20 +171,36 @@ test "std.atomic.Queue" { |
| 170 | .get_count = 0, | 171 | .get_count = 0, |
| 171 | }; | 172 | }; |
| 172 | 173 | ||
| 173 | var putters: [put_thread_count]*std.os.Thread = undefined; | 174 | if (builtin.single_threaded) { |
| 174 | for (putters) |*t| { | 175 | { |
| 175 | t.* = try std.os.spawnThread(&context, startPuts); | 176 | var i: usize = 0; |
| 176 | } | 177 | while (i < put_thread_count) : (i += 1) { |
| 177 | var getters: [put_thread_count]*std.os.Thread = undefined; | 178 | expect(startPuts(&context) == 0); |
| 178 | for (getters) |*t| { | 179 | } |
| 179 | t.* = try std.os.spawnThread(&context, startGets); | 180 | } |
| 180 | } | 181 | context.puts_done = 1; |
| 182 | { | ||
| 183 | var i: usize = 0; | ||
| 184 | while (i < put_thread_count) : (i += 1) { | ||
| 185 | expect(startGets(&context) == 0); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } else { | ||
| 189 | var putters: [put_thread_count]*std.os.Thread = undefined; | ||
| 190 | for (putters) |*t| { | ||
| 191 | t.* = try std.os.spawnThread(&context, startPuts); | ||
| 192 | } | ||
| 193 | var getters: [put_thread_count]*std.os.Thread = undefined; | ||
| 194 | for (getters) |*t| { | ||
| 195 | t.* = try std.os.spawnThread(&context, startGets); | ||
| 196 | } | ||
| 181 | 197 | ||
| 182 | for (putters) |t| | 198 | for (putters) |t| |
| 183 | t.wait(); | 199 | t.wait(); |
| 184 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); | 200 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); |
| 185 | for (getters) |t| | 201 | for (getters) |t| |
| 186 | t.wait(); | 202 | t.wait(); |
| 203 | } | ||
| 187 | 204 | ||
| 188 | if (context.put_sum != context.get_sum) { | 205 | if (context.put_sum != context.get_sum) { |
| 189 | std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum); | 206 | std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum); |
| ... | @@ -205,11 +222,12 @@ fn startPuts(ctx: *Context) u8 { | ... | @@ -205,11 +222,12 @@ fn startPuts(ctx: *Context) u8 { |
| 205 | while (put_count != 0) : (put_count -= 1) { | 222 | while (put_count != 0) : (put_count -= 1) { |
| 206 | std.os.time.sleep(1); // let the os scheduler be our fuzz | 223 | std.os.time.sleep(1); // let the os scheduler be our fuzz |
| 207 | const x = @bitCast(i32, r.random.scalar(u32)); | 224 | const x = @bitCast(i32, r.random.scalar(u32)); |
| 208 | const node = ctx.allocator.create(Queue(i32).Node{ | 225 | const node = ctx.allocator.create(Queue(i32).Node) catch unreachable; |
| 226 | node.* = Queue(i32).Node{ | ||
| 209 | .prev = undefined, | 227 | .prev = undefined, |
| 210 | .next = undefined, | 228 | .next = undefined, |
| 211 | .data = x, | 229 | .data = x, |
| 212 | }) catch unreachable; | 230 | }; |
| 213 | ctx.queue.put(node); | 231 | ctx.queue.put(node); |
| 214 | _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst); | 232 | _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst); |
| 215 | } | 233 | } |
| ... | @@ -247,7 +265,7 @@ test "std.atomic.Queue single-threaded" { | ... | @@ -247,7 +265,7 @@ test "std.atomic.Queue single-threaded" { |
| 247 | }; | 265 | }; |
| 248 | queue.put(&node_1); | 266 | queue.put(&node_1); |
| 249 | 267 | ||
| 250 | assert(queue.get().?.data == 0); | 268 | expect(queue.get().?.data == 0); |
| 251 | 269 | ||
| 252 | var node_2 = Queue(i32).Node{ | 270 | var node_2 = Queue(i32).Node{ |
| 253 | .data = 2, | 271 | .data = 2, |
| ... | @@ -263,9 +281,9 @@ test "std.atomic.Queue single-threaded" { | ... | @@ -263,9 +281,9 @@ test "std.atomic.Queue single-threaded" { |
| 263 | }; | 281 | }; |
| 264 | queue.put(&node_3); | 282 | queue.put(&node_3); |
| 265 | 283 | ||
| 266 | assert(queue.get().?.data == 1); | 284 | expect(queue.get().?.data == 1); |
| 267 | 285 | ||
| 268 | assert(queue.get().?.data == 2); | 286 | expect(queue.get().?.data == 2); |
| 269 | 287 | ||
| 270 | var node_4 = Queue(i32).Node{ | 288 | var node_4 = Queue(i32).Node{ |
| 271 | .data = 4, | 289 | .data = 4, |
| ... | @@ -274,12 +292,12 @@ test "std.atomic.Queue single-threaded" { | ... | @@ -274,12 +292,12 @@ test "std.atomic.Queue single-threaded" { |
| 274 | }; | 292 | }; |
| 275 | queue.put(&node_4); | 293 | queue.put(&node_4); |
| 276 | 294 | ||
| 277 | assert(queue.get().?.data == 3); | 295 | expect(queue.get().?.data == 3); |
| 278 | node_3.next = null; | 296 | node_3.next = null; |
| 279 | 297 | ||
| 280 | assert(queue.get().?.data == 4); | 298 | expect(queue.get().?.data == 4); |
| 281 | 299 | ||
| 282 | assert(queue.get() == null); | 300 | expect(queue.get() == null); |
| 283 | } | 301 | } |
| 284 | 302 | ||
| 285 | test "std.atomic.Queue dump" { | 303 | test "std.atomic.Queue dump" { |
| ... | @@ -294,7 +312,7 @@ test "std.atomic.Queue dump" { | ... | @@ -294,7 +312,7 @@ test "std.atomic.Queue dump" { |
| 294 | // Test empty stream | 312 | // Test empty stream |
| 295 | sos.reset(); | 313 | sos.reset(); |
| 296 | try queue.dumpToStream(SliceOutStream.Error, &sos.stream); | 314 | try queue.dumpToStream(SliceOutStream.Error, &sos.stream); |
| 297 | assert(mem.eql(u8, buffer[0..sos.pos], | 315 | expect(mem.eql(u8, buffer[0..sos.pos], |
| 298 | \\head: (null) | 316 | \\head: (null) |
| 299 | \\tail: (null) | 317 | \\tail: (null) |
| 300 | \\ | 318 | \\ |
| ... | @@ -318,7 +336,7 @@ test "std.atomic.Queue dump" { | ... | @@ -318,7 +336,7 @@ test "std.atomic.Queue dump" { |
| 318 | \\ (null) | 336 | \\ (null) |
| 319 | \\ | 337 | \\ |
| 320 | , @ptrToInt(queue.head), @ptrToInt(queue.tail)); | 338 | , @ptrToInt(queue.head), @ptrToInt(queue.tail)); |
| 321 | assert(mem.eql(u8, buffer[0..sos.pos], expected)); | 339 | expect(mem.eql(u8, buffer[0..sos.pos], expected)); |
| 322 | 340 | ||
| 323 | // Test a stream with two elements | 341 | // Test a stream with two elements |
| 324 | var node_1 = Queue(i32).Node{ | 342 | var node_1 = Queue(i32).Node{ |
| ... | @@ -339,5 +357,5 @@ test "std.atomic.Queue dump" { | ... | @@ -339,5 +357,5 @@ test "std.atomic.Queue dump" { |
| 339 | \\ (null) | 357 | \\ (null) |
| 340 | \\ | 358 | \\ |
| 341 | , @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail)); | 359 | , @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail)); |
| 342 | assert(mem.eql(u8, buffer[0..sos.pos], expected)); | 360 | expect(mem.eql(u8, buffer[0..sos.pos], expected)); |
| 343 | } | 361 | } |
std/atomic/stack.zig+60-28| ... | @@ -1,13 +1,17 @@ | ... | @@ -1,13 +1,17 @@ |
| 1 | const assert = std.debug.assert; | 1 | const assert = std.debug.assert; |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const AtomicOrder = builtin.AtomicOrder; | 3 | const AtomicOrder = builtin.AtomicOrder; |
| 4 | const expect = std.testing.expect; | ||
| 4 | 5 | ||
| 5 | /// Many reader, many writer, non-allocating, thread-safe | 6 | /// Many reader, many writer, non-allocating, thread-safe |
| 6 | /// Uses a spinlock to protect push() and pop() | 7 | /// Uses a spinlock to protect push() and pop() |
| 8 | /// When building in single threaded mode, this is a simple linked list. | ||
| 7 | pub fn Stack(comptime T: type) type { | 9 | pub fn Stack(comptime T: type) type { |
| 8 | return struct { | 10 | return struct { |
| 9 | root: ?*Node, | 11 | root: ?*Node, |
| 10 | lock: u8, | 12 | lock: @typeOf(lock_init), |
| 13 | |||
| 14 | const lock_init = if (builtin.single_threaded) {} else u8(0); | ||
| 11 | 15 | ||
| 12 | pub const Self = @This(); | 16 | pub const Self = @This(); |
| 13 | 17 | ||
| ... | @@ -19,7 +23,7 @@ pub fn Stack(comptime T: type) type { | ... | @@ -19,7 +23,7 @@ pub fn Stack(comptime T: type) type { |
| 19 | pub fn init() Self { | 23 | pub fn init() Self { |
| 20 | return Self{ | 24 | return Self{ |
| 21 | .root = null, | 25 | .root = null, |
| 22 | .lock = 0, | 26 | .lock = lock_init, |
| 23 | }; | 27 | }; |
| 24 | } | 28 | } |
| 25 | 29 | ||
| ... | @@ -31,20 +35,31 @@ pub fn Stack(comptime T: type) type { | ... | @@ -31,20 +35,31 @@ pub fn Stack(comptime T: type) type { |
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | pub fn push(self: *Self, node: *Node) void { | 37 | pub fn push(self: *Self, node: *Node) void { |
| 34 | while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {} | 38 | if (builtin.single_threaded) { |
| 35 | defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1); | 39 | node.next = self.root; |
| 36 | 40 | self.root = node; | |
| 37 | node.next = self.root; | 41 | } else { |
| 38 | self.root = node; | 42 | while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {} |
| 43 | defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1); | ||
| 44 | |||
| 45 | node.next = self.root; | ||
| 46 | self.root = node; | ||
| 47 | } | ||
| 39 | } | 48 | } |
| 40 | 49 | ||
| 41 | pub fn pop(self: *Self) ?*Node { | 50 | pub fn pop(self: *Self) ?*Node { |
| 42 | while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {} | 51 | if (builtin.single_threaded) { |
| 43 | defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1); | 52 | const root = self.root orelse return null; |
| 44 | 53 | self.root = root.next; | |
| 45 | const root = self.root orelse return null; | 54 | return root; |
| 46 | self.root = root.next; | 55 | } else { |
| 47 | return root; | 56 | while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {} |
| 57 | defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1); | ||
| 58 | |||
| 59 | const root = self.root orelse return null; | ||
| 60 | self.root = root.next; | ||
| 61 | return root; | ||
| 62 | } | ||
| 48 | } | 63 | } |
| 49 | 64 | ||
| 50 | pub fn isEmpty(self: *Self) bool { | 65 | pub fn isEmpty(self: *Self) bool { |
| ... | @@ -90,20 +105,36 @@ test "std.atomic.stack" { | ... | @@ -90,20 +105,36 @@ test "std.atomic.stack" { |
| 90 | .get_count = 0, | 105 | .get_count = 0, |
| 91 | }; | 106 | }; |
| 92 | 107 | ||
| 93 | var putters: [put_thread_count]*std.os.Thread = undefined; | 108 | if (builtin.single_threaded) { |
| 94 | for (putters) |*t| { | 109 | { |
| 95 | t.* = try std.os.spawnThread(&context, startPuts); | 110 | var i: usize = 0; |
| 96 | } | 111 | while (i < put_thread_count) : (i += 1) { |
| 97 | var getters: [put_thread_count]*std.os.Thread = undefined; | 112 | expect(startPuts(&context) == 0); |
| 98 | for (getters) |*t| { | 113 | } |
| 99 | t.* = try std.os.spawnThread(&context, startGets); | 114 | } |
| 100 | } | 115 | context.puts_done = 1; |
| 116 | { | ||
| 117 | var i: usize = 0; | ||
| 118 | while (i < put_thread_count) : (i += 1) { | ||
| 119 | expect(startGets(&context) == 0); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } else { | ||
| 123 | var putters: [put_thread_count]*std.os.Thread = undefined; | ||
| 124 | for (putters) |*t| { | ||
| 125 | t.* = try std.os.spawnThread(&context, startPuts); | ||
| 126 | } | ||
| 127 | var getters: [put_thread_count]*std.os.Thread = undefined; | ||
| 128 | for (getters) |*t| { | ||
| 129 | t.* = try std.os.spawnThread(&context, startGets); | ||
| 130 | } | ||
| 101 | 131 | ||
| 102 | for (putters) |t| | 132 | for (putters) |t| |
| 103 | t.wait(); | 133 | t.wait(); |
| 104 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); | 134 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); |
| 105 | for (getters) |t| | 135 | for (getters) |t| |
| 106 | t.wait(); | 136 | t.wait(); |
| 137 | } | ||
| 107 | 138 | ||
| 108 | if (context.put_sum != context.get_sum) { | 139 | if (context.put_sum != context.get_sum) { |
| 109 | std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum); | 140 | std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum); |
| ... | @@ -125,10 +156,11 @@ fn startPuts(ctx: *Context) u8 { | ... | @@ -125,10 +156,11 @@ fn startPuts(ctx: *Context) u8 { |
| 125 | while (put_count != 0) : (put_count -= 1) { | 156 | while (put_count != 0) : (put_count -= 1) { |
| 126 | std.os.time.sleep(1); // let the os scheduler be our fuzz | 157 | std.os.time.sleep(1); // let the os scheduler be our fuzz |
| 127 | const x = @bitCast(i32, r.random.scalar(u32)); | 158 | const x = @bitCast(i32, r.random.scalar(u32)); |
| 128 | const node = ctx.allocator.create(Stack(i32).Node{ | 159 | const node = ctx.allocator.create(Stack(i32).Node) catch unreachable; |
| 160 | node.* = Stack(i32).Node{ | ||
| 129 | .next = undefined, | 161 | .next = undefined, |
| 130 | .data = x, | 162 | .data = x, |
| 131 | }) catch unreachable; | 163 | }; |
| 132 | ctx.stack.push(node); | 164 | ctx.stack.push(node); |
| 133 | _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst); | 165 | _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst); |
| 134 | } | 166 | } |
std/base64.zig+7-6| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | ||
| 3 | const mem = std.mem; | 4 | const mem = std.mem; |
| 4 | 5 | ||
| 5 | pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 6 | pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| ... | @@ -394,7 +395,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void | ... | @@ -394,7 +395,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void |
| 394 | var buffer: [0x100]u8 = undefined; | 395 | var buffer: [0x100]u8 = undefined; |
| 395 | var encoded = buffer[0..Base64Encoder.calcSize(expected_decoded.len)]; | 396 | var encoded = buffer[0..Base64Encoder.calcSize(expected_decoded.len)]; |
| 396 | standard_encoder.encode(encoded, expected_decoded); | 397 | standard_encoder.encode(encoded, expected_decoded); |
| 397 | assert(mem.eql(u8, encoded, expected_encoded)); | 398 | testing.expectEqualSlices(u8, expected_encoded, encoded); |
| 398 | } | 399 | } |
| 399 | 400 | ||
| 400 | // Base64Decoder | 401 | // Base64Decoder |
| ... | @@ -402,7 +403,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void | ... | @@ -402,7 +403,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void |
| 402 | var buffer: [0x100]u8 = undefined; | 403 | var buffer: [0x100]u8 = undefined; |
| 403 | var decoded = buffer[0..try standard_decoder.calcSize(expected_encoded)]; | 404 | var decoded = buffer[0..try standard_decoder.calcSize(expected_encoded)]; |
| 404 | try standard_decoder.decode(decoded, expected_encoded); | 405 | try standard_decoder.decode(decoded, expected_encoded); |
| 405 | assert(mem.eql(u8, decoded, expected_decoded)); | 406 | testing.expectEqualSlices(u8, expected_decoded, decoded); |
| 406 | } | 407 | } |
| 407 | 408 | ||
| 408 | // Base64DecoderWithIgnore | 409 | // Base64DecoderWithIgnore |
| ... | @@ -411,8 +412,8 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void | ... | @@ -411,8 +412,8 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void |
| 411 | var buffer: [0x100]u8 = undefined; | 412 | var buffer: [0x100]u8 = undefined; |
| 412 | var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; | 413 | var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)]; |
| 413 | var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded); | 414 | var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded); |
| 414 | assert(written <= decoded.len); | 415 | testing.expect(written <= decoded.len); |
| 415 | assert(mem.eql(u8, decoded[0..written], expected_decoded)); | 416 | testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]); |
| 416 | } | 417 | } |
| 417 | 418 | ||
| 418 | // Base64DecoderUnsafe | 419 | // Base64DecoderUnsafe |
| ... | @@ -420,7 +421,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void | ... | @@ -420,7 +421,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void |
| 420 | var buffer: [0x100]u8 = undefined; | 421 | var buffer: [0x100]u8 = undefined; |
| 421 | var decoded = buffer[0..standard_decoder_unsafe.calcSize(expected_encoded)]; | 422 | var decoded = buffer[0..standard_decoder_unsafe.calcSize(expected_encoded)]; |
| 422 | standard_decoder_unsafe.decode(decoded, expected_encoded); | 423 | standard_decoder_unsafe.decode(decoded, expected_encoded); |
| 423 | assert(mem.eql(u8, decoded, expected_decoded)); | 424 | testing.expectEqualSlices(u8, expected_decoded, decoded); |
| 424 | } | 425 | } |
| 425 | } | 426 | } |
| 426 | 427 | ||
| ... | @@ -429,7 +430,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi | ... | @@ -429,7 +430,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi |
| 429 | var buffer: [0x100]u8 = undefined; | 430 | var buffer: [0x100]u8 = undefined; |
| 430 | var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; | 431 | var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)]; |
| 431 | var written = try standard_decoder_ignore_space.decode(decoded, encoded); | 432 | var written = try standard_decoder_ignore_space.decode(decoded, encoded); |
| 432 | assert(mem.eql(u8, decoded[0..written], expected_decoded)); | 433 | testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]); |
| 433 | } | 434 | } |
| 434 | 435 | ||
| 435 | fn testError(encoded: []const u8, expected_err: anyerror) !void { | 436 | fn testError(encoded: []const u8, expected_err: anyerror) !void { |
std/buf_map.zig+35-17| ... | @@ -2,7 +2,7 @@ const std = @import("index.zig"); | ... | @@ -2,7 +2,7 @@ const std = @import("index.zig"); |
| 2 | const HashMap = std.HashMap; | 2 | const HashMap = std.HashMap; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | const assert = std.debug.assert; | 5 | const testing = std.testing; |
| 6 | 6 | ||
| 7 | /// BufMap copies keys and values before they go into the map, and | 7 | /// BufMap copies keys and values before they go into the map, and |
| 8 | /// frees them when they get removed. | 8 | /// frees them when they get removed. |
| ... | @@ -16,7 +16,7 @@ pub const BufMap = struct { | ... | @@ -16,7 +16,7 @@ pub const BufMap = struct { |
| 16 | return self; | 16 | return self; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | pub fn deinit(self: *const BufMap) void { | 19 | pub fn deinit(self: *BufMap) void { |
| 20 | var it = self.hash_map.iterator(); | 20 | var it = self.hash_map.iterator(); |
| 21 | while (true) { | 21 | while (true) { |
| 22 | const entry = it.next() orelse break; | 22 | const entry = it.next() orelse break; |
| ... | @@ -27,16 +27,34 @@ pub const BufMap = struct { | ... | @@ -27,16 +27,34 @@ pub const BufMap = struct { |
| 27 | self.hash_map.deinit(); | 27 | self.hash_map.deinit(); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /// Same as `set` but the key and value become owned by the BufMap rather | ||
| 31 | /// than being copied. | ||
| 32 | /// If `setMove` fails, the ownership of key and value does not transfer. | ||
| 33 | pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void { | ||
| 34 | const get_or_put = try self.hash_map.getOrPut(key); | ||
| 35 | if (get_or_put.found_existing) { | ||
| 36 | self.free(get_or_put.kv.key); | ||
| 37 | get_or_put.kv.key = key; | ||
| 38 | } | ||
| 39 | get_or_put.kv.value = value; | ||
| 40 | } | ||
| 41 | |||
| 42 | /// `key` and `value` are copied into the BufMap. | ||
| 30 | pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void { | 43 | pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void { |
| 31 | self.delete(key); | ||
| 32 | const key_copy = try self.copy(key); | ||
| 33 | errdefer self.free(key_copy); | ||
| 34 | const value_copy = try self.copy(value); | 44 | const value_copy = try self.copy(value); |
| 35 | errdefer self.free(value_copy); | 45 | errdefer self.free(value_copy); |
| 36 | _ = try self.hash_map.put(key_copy, value_copy); | 46 | // Avoid copying key if it already exists |
| 47 | const get_or_put = try self.hash_map.getOrPut(key); | ||
| 48 | if (!get_or_put.found_existing) { | ||
| 49 | get_or_put.kv.key = self.copy(key) catch |err| { | ||
| 50 | _ = self.hash_map.remove(key); | ||
| 51 | return err; | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | get_or_put.kv.value = value_copy; | ||
| 37 | } | 55 | } |
| 38 | 56 | ||
| 39 | pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 { | 57 | pub fn get(self: BufMap, key: []const u8) ?[]const u8 { |
| 40 | const entry = self.hash_map.get(key) orelse return null; | 58 | const entry = self.hash_map.get(key) orelse return null; |
| 41 | return entry.value; | 59 | return entry.value; |
| 42 | } | 60 | } |
| ... | @@ -47,7 +65,7 @@ pub const BufMap = struct { | ... | @@ -47,7 +65,7 @@ pub const BufMap = struct { |
| 47 | self.free(entry.value); | 65 | self.free(entry.value); |
| 48 | } | 66 | } |
| 49 | 67 | ||
| 50 | pub fn count(self: *const BufMap) usize { | 68 | pub fn count(self: BufMap) usize { |
| 51 | return self.hash_map.count(); | 69 | return self.hash_map.count(); |
| 52 | } | 70 | } |
| 53 | 71 | ||
| ... | @@ -55,11 +73,11 @@ pub const BufMap = struct { | ... | @@ -55,11 +73,11 @@ pub const BufMap = struct { |
| 55 | return self.hash_map.iterator(); | 73 | return self.hash_map.iterator(); |
| 56 | } | 74 | } |
| 57 | 75 | ||
| 58 | fn free(self: *const BufMap, value: []const u8) void { | 76 | fn free(self: BufMap, value: []const u8) void { |
| 59 | self.hash_map.allocator.free(value); | 77 | self.hash_map.allocator.free(value); |
| 60 | } | 78 | } |
| 61 | 79 | ||
| 62 | fn copy(self: *const BufMap, value: []const u8) ![]const u8 { | 80 | fn copy(self: BufMap, value: []const u8) ![]u8 { |
| 63 | return mem.dupe(self.hash_map.allocator, u8, value); | 81 | return mem.dupe(self.hash_map.allocator, u8, value); |
| 64 | } | 82 | } |
| 65 | }; | 83 | }; |
| ... | @@ -72,17 +90,17 @@ test "BufMap" { | ... | @@ -72,17 +90,17 @@ test "BufMap" { |
| 72 | defer bufmap.deinit(); | 90 | defer bufmap.deinit(); |
| 73 | 91 | ||
| 74 | try bufmap.set("x", "1"); | 92 | try bufmap.set("x", "1"); |
| 75 | assert(mem.eql(u8, bufmap.get("x").?, "1")); | 93 | testing.expect(mem.eql(u8, bufmap.get("x").?, "1")); |
| 76 | assert(1 == bufmap.count()); | 94 | testing.expect(1 == bufmap.count()); |
| 77 | 95 | ||
| 78 | try bufmap.set("x", "2"); | 96 | try bufmap.set("x", "2"); |
| 79 | assert(mem.eql(u8, bufmap.get("x").?, "2")); | 97 | testing.expect(mem.eql(u8, bufmap.get("x").?, "2")); |
| 80 | assert(1 == bufmap.count()); | 98 | testing.expect(1 == bufmap.count()); |
| 81 | 99 | ||
| 82 | try bufmap.set("x", "3"); | 100 | try bufmap.set("x", "3"); |
| 83 | assert(mem.eql(u8, bufmap.get("x").?, "3")); | 101 | testing.expect(mem.eql(u8, bufmap.get("x").?, "3")); |
| 84 | assert(1 == bufmap.count()); | 102 | testing.expect(1 == bufmap.count()); |
| 85 | 103 | ||
| 86 | bufmap.delete("x"); | 104 | bufmap.delete("x"); |
| 87 | assert(0 == bufmap.count()); | 105 | testing.expect(0 == bufmap.count()); |
| 88 | } | 106 | } |
std/buf_set.zig+3-3| ... | @@ -2,7 +2,7 @@ const std = @import("index.zig"); | ... | @@ -2,7 +2,7 @@ const std = @import("index.zig"); |
| 2 | const HashMap = @import("hash_map.zig").HashMap; | 2 | const HashMap = @import("hash_map.zig").HashMap; |
| 3 | const mem = @import("mem.zig"); | 3 | const mem = @import("mem.zig"); |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | const assert = std.debug.assert; | 5 | const testing = std.testing; |
| 6 | 6 | ||
| 7 | pub const BufSet = struct { | 7 | pub const BufSet = struct { |
| 8 | hash_map: BufSetHashMap, | 8 | hash_map: BufSetHashMap, |
| ... | @@ -68,9 +68,9 @@ test "BufSet" { | ... | @@ -68,9 +68,9 @@ test "BufSet" { |
| 68 | defer bufset.deinit(); | 68 | defer bufset.deinit(); |
| 69 | 69 | ||
| 70 | try bufset.put("x"); | 70 | try bufset.put("x"); |
| 71 | assert(bufset.count() == 1); | 71 | testing.expect(bufset.count() == 1); |
| 72 | bufset.delete("x"); | 72 | bufset.delete("x"); |
| 73 | assert(bufset.count() == 0); | 73 | testing.expect(bufset.count() == 0); |
| 74 | 74 | ||
| 75 | try bufset.put("x"); | 75 | try bufset.put("x"); |
| 76 | try bufset.put("y"); | 76 | try bufset.put("y"); |
std/buffer.zig+8-7| ... | @@ -3,6 +3,7 @@ const debug = std.debug; | ... | @@ -3,6 +3,7 @@ const debug = std.debug; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | const assert = debug.assert; | 5 | const assert = debug.assert; |
| 6 | const testing = std.testing; | ||
| 6 | const ArrayList = std.ArrayList; | 7 | const ArrayList = std.ArrayList; |
| 7 | 8 | ||
| 8 | /// A buffer that allocates memory and maintains a null byte at the end. | 9 | /// A buffer that allocates memory and maintains a null byte at the end. |
| ... | @@ -141,19 +142,19 @@ test "simple Buffer" { | ... | @@ -141,19 +142,19 @@ test "simple Buffer" { |
| 141 | const cstr = @import("cstr.zig"); | 142 | const cstr = @import("cstr.zig"); |
| 142 | 143 | ||
| 143 | var buf = try Buffer.init(debug.global_allocator, ""); | 144 | var buf = try Buffer.init(debug.global_allocator, ""); |
| 144 | assert(buf.len() == 0); | 145 | testing.expect(buf.len() == 0); |
| 145 | try buf.append("hello"); | 146 | try buf.append("hello"); |
| 146 | try buf.append(" "); | 147 | try buf.append(" "); |
| 147 | try buf.append("world"); | 148 | try buf.append("world"); |
| 148 | assert(buf.eql("hello world")); | 149 | testing.expect(buf.eql("hello world")); |
| 149 | assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst())); | 150 | testing.expect(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst())); |
| 150 | 151 | ||
| 151 | var buf2 = try Buffer.initFromBuffer(buf); | 152 | var buf2 = try Buffer.initFromBuffer(buf); |
| 152 | assert(buf.eql(buf2.toSliceConst())); | 153 | testing.expect(buf.eql(buf2.toSliceConst())); |
| 153 | 154 | ||
| 154 | assert(buf.startsWith("hell")); | 155 | testing.expect(buf.startsWith("hell")); |
| 155 | assert(buf.endsWith("orld")); | 156 | testing.expect(buf.endsWith("orld")); |
| 156 | 157 | ||
| 157 | try buf2.resize(4); | 158 | try buf2.resize(4); |
| 158 | assert(buf.startsWith(buf2.toSlice())); | 159 | testing.expect(buf.startsWith(buf2.toSlice())); |
| 159 | } | 160 | } |
std/build.zig+107-42| ... | @@ -89,7 +89,7 @@ pub const Builder = struct { | ... | @@ -89,7 +89,7 @@ pub const Builder = struct { |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder { | 91 | pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder { |
| 92 | const env_map = allocator.createOne(BufMap) catch unreachable; | 92 | const env_map = allocator.create(BufMap) catch unreachable; |
| 93 | env_map.* = os.getEnvMap(allocator) catch unreachable; | 93 | env_map.* = os.getEnvMap(allocator) catch unreachable; |
| 94 | var self = Builder{ | 94 | var self = Builder{ |
| 95 | .zig_exe = zig_exe, | 95 | .zig_exe = zig_exe, |
| ... | @@ -145,8 +145,8 @@ pub const Builder = struct { | ... | @@ -145,8 +145,8 @@ pub const Builder = struct { |
| 145 | 145 | ||
| 146 | pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void { | 146 | pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void { |
| 147 | self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default | 147 | self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default |
| 148 | self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable; | 148 | self.lib_dir = os.path.join(self.allocator, [][]const u8{ self.prefix, "lib" }) catch unreachable; |
| 149 | self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable; | 149 | self.exe_dir = os.path.join(self.allocator, [][]const u8{ self.prefix, "bin" }) catch unreachable; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | 152 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| ... | @@ -170,7 +170,8 @@ pub const Builder = struct { | ... | @@ -170,7 +170,8 @@ pub const Builder = struct { |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | pub fn addTest(self: *Builder, root_src: []const u8) *TestStep { | 172 | pub fn addTest(self: *Builder, root_src: []const u8) *TestStep { |
| 173 | const test_step = self.allocator.create(TestStep.init(self, root_src)) catch unreachable; | 173 | const test_step = self.allocator.create(TestStep) catch unreachable; |
| 174 | test_step.* = TestStep.init(self, root_src); | ||
| 174 | return test_step; | 175 | return test_step; |
| 175 | } | 176 | } |
| 176 | 177 | ||
| ... | @@ -202,18 +203,21 @@ pub const Builder = struct { | ... | @@ -202,18 +203,21 @@ pub const Builder = struct { |
| 202 | } | 203 | } |
| 203 | 204 | ||
| 204 | pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep { | 205 | pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep { |
| 205 | const write_file_step = self.allocator.create(WriteFileStep.init(self, file_path, data)) catch unreachable; | 206 | const write_file_step = self.allocator.create(WriteFileStep) catch unreachable; |
| 207 | write_file_step.* = WriteFileStep.init(self, file_path, data); | ||
| 206 | return write_file_step; | 208 | return write_file_step; |
| 207 | } | 209 | } |
| 208 | 210 | ||
| 209 | pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep { | 211 | pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep { |
| 210 | const data = self.fmt(format, args); | 212 | const data = self.fmt(format, args); |
| 211 | const log_step = self.allocator.create(LogStep.init(self, data)) catch unreachable; | 213 | const log_step = self.allocator.create(LogStep) catch unreachable; |
| 214 | log_step.* = LogStep.init(self, data); | ||
| 212 | return log_step; | 215 | return log_step; |
| 213 | } | 216 | } |
| 214 | 217 | ||
| 215 | pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep { | 218 | pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep { |
| 216 | const remove_dir_step = self.allocator.create(RemoveDirStep.init(self, dir_path)) catch unreachable; | 219 | const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable; |
| 220 | remove_dir_step.* = RemoveDirStep.init(self, dir_path); | ||
| 217 | return remove_dir_step; | 221 | return remove_dir_step; |
| 218 | } | 222 | } |
| 219 | 223 | ||
| ... | @@ -320,7 +324,7 @@ pub const Builder = struct { | ... | @@ -320,7 +324,7 @@ pub const Builder = struct { |
| 320 | 324 | ||
| 321 | fn processNixOSEnvVars(self: *Builder) void { | 325 | fn processNixOSEnvVars(self: *Builder) void { |
| 322 | if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { | 326 | if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { |
| 323 | var it = mem.split(nix_cflags_compile, " "); | 327 | var it = mem.tokenize(nix_cflags_compile, " "); |
| 324 | while (true) { | 328 | while (true) { |
| 325 | const word = it.next() orelse break; | 329 | const word = it.next() orelse break; |
| 326 | if (mem.eql(u8, word, "-isystem")) { | 330 | if (mem.eql(u8, word, "-isystem")) { |
| ... | @@ -338,7 +342,7 @@ pub const Builder = struct { | ... | @@ -338,7 +342,7 @@ pub const Builder = struct { |
| 338 | assert(err == error.EnvironmentVariableNotFound); | 342 | assert(err == error.EnvironmentVariableNotFound); |
| 339 | } | 343 | } |
| 340 | if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| { | 344 | if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| { |
| 341 | var it = mem.split(nix_ldflags, " "); | 345 | var it = mem.tokenize(nix_ldflags, " "); |
| 342 | while (true) { | 346 | while (true) { |
| 343 | const word = it.next() orelse break; | 347 | const word = it.next() orelse break; |
| 344 | if (mem.eql(u8, word, "-rpath")) { | 348 | if (mem.eql(u8, word, "-rpath")) { |
| ... | @@ -414,10 +418,11 @@ pub const Builder = struct { | ... | @@ -414,10 +418,11 @@ pub const Builder = struct { |
| 414 | } | 418 | } |
| 415 | 419 | ||
| 416 | pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step { | 420 | pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step { |
| 417 | const step_info = self.allocator.create(TopLevelStep{ | 421 | const step_info = self.allocator.create(TopLevelStep) catch unreachable; |
| 422 | step_info.* = TopLevelStep{ | ||
| 418 | .step = Step.initNoOp(name, self.allocator), | 423 | .step = Step.initNoOp(name, self.allocator), |
| 419 | .description = description, | 424 | .description = description, |
| 420 | }) catch unreachable; | 425 | }; |
| 421 | self.top_level_steps.append(step_info) catch unreachable; | 426 | self.top_level_steps.append(step_info) catch unreachable; |
| 422 | return &step_info.step; | 427 | return &step_info.step; |
| 423 | } | 428 | } |
| ... | @@ -613,10 +618,14 @@ pub const Builder = struct { | ... | @@ -613,10 +618,14 @@ pub const Builder = struct { |
| 613 | 618 | ||
| 614 | ///::dest_rel_path is relative to prefix path or it can be an absolute path | 619 | ///::dest_rel_path is relative to prefix path or it can be an absolute path |
| 615 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { | 620 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { |
| 616 | const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable; | 621 | const full_dest_path = os.path.resolve( |
| 622 | self.allocator, | ||
| 623 | [][]const u8{ self.prefix, dest_rel_path }, | ||
| 624 | ) catch unreachable; | ||
| 617 | self.pushInstalledFile(full_dest_path); | 625 | self.pushInstalledFile(full_dest_path); |
| 618 | 626 | ||
| 619 | const install_step = self.allocator.create(InstallFileStep.init(self, src_path, full_dest_path)) catch unreachable; | 627 | const install_step = self.allocator.create(InstallFileStep) catch unreachable; |
| 628 | install_step.* = InstallFileStep.init(self, src_path, full_dest_path); | ||
| 620 | return install_step; | 629 | return install_step; |
| 621 | } | 630 | } |
| 622 | 631 | ||
| ... | @@ -647,7 +656,7 @@ pub const Builder = struct { | ... | @@ -647,7 +656,7 @@ pub const Builder = struct { |
| 647 | } | 656 | } |
| 648 | 657 | ||
| 649 | fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 { | 658 | fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 { |
| 650 | return os.path.resolve(self.allocator, self.build_root, rel_path) catch unreachable; | 659 | return os.path.resolve(self.allocator, [][]const u8{ self.build_root, rel_path }) catch unreachable; |
| 651 | } | 660 | } |
| 652 | 661 | ||
| 653 | pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 { | 662 | pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 { |
| ... | @@ -670,7 +679,7 @@ pub const Builder = struct { | ... | @@ -670,7 +679,7 @@ pub const Builder = struct { |
| 670 | if (os.path.isAbsolute(name)) { | 679 | if (os.path.isAbsolute(name)) { |
| 671 | return name; | 680 | return name; |
| 672 | } | 681 | } |
| 673 | const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension)); | 682 | const full_path = try os.path.join(self.allocator, [][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) }); |
| 674 | if (os.path.real(self.allocator, full_path)) |real_path| { | 683 | if (os.path.real(self.allocator, full_path)) |real_path| { |
| 675 | return real_path; | 684 | return real_path; |
| 676 | } else |_| { | 685 | } else |_| { |
| ... | @@ -683,9 +692,9 @@ pub const Builder = struct { | ... | @@ -683,9 +692,9 @@ pub const Builder = struct { |
| 683 | if (os.path.isAbsolute(name)) { | 692 | if (os.path.isAbsolute(name)) { |
| 684 | return name; | 693 | return name; |
| 685 | } | 694 | } |
| 686 | var it = mem.split(PATH, []u8{os.path.delimiter}); | 695 | var it = mem.tokenize(PATH, []u8{os.path.delimiter}); |
| 687 | while (it.next()) |path| { | 696 | while (it.next()) |path| { |
| 688 | const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension)); | 697 | const full_path = try os.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) }); |
| 689 | if (os.path.real(self.allocator, full_path)) |real_path| { | 698 | if (os.path.real(self.allocator, full_path)) |real_path| { |
| 690 | return real_path; | 699 | return real_path; |
| 691 | } else |_| { | 700 | } else |_| { |
| ... | @@ -699,7 +708,7 @@ pub const Builder = struct { | ... | @@ -699,7 +708,7 @@ pub const Builder = struct { |
| 699 | return name; | 708 | return name; |
| 700 | } | 709 | } |
| 701 | for (paths) |path| { | 710 | for (paths) |path| { |
| 702 | const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension)); | 711 | const full_path = try os.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) }); |
| 703 | if (os.path.real(self.allocator, full_path)) |real_path| { | 712 | if (os.path.real(self.allocator, full_path)) |real_path| { |
| 704 | return real_path; | 713 | return real_path; |
| 705 | } else |_| { | 714 | } else |_| { |
| ... | @@ -865,43 +874,51 @@ pub const LibExeObjStep = struct { | ... | @@ -865,43 +874,51 @@ pub const LibExeObjStep = struct { |
| 865 | }; | 874 | }; |
| 866 | 875 | ||
| 867 | pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep { | 876 | pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep { |
| 868 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Lib, false, ver)) catch unreachable; | 877 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 878 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); | ||
| 869 | return self; | 879 | return self; |
| 870 | } | 880 | } |
| 871 | 881 | ||
| 872 | pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep { | 882 | pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep { |
| 873 | const self = builder.allocator.create(initC(builder, name, Kind.Lib, version, false)) catch unreachable; | 883 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 884 | self.* = initC(builder, name, Kind.Lib, version, false); | ||
| 874 | return self; | 885 | return self; |
| 875 | } | 886 | } |
| 876 | 887 | ||
| 877 | pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | 888 | pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| 878 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0))) catch unreachable; | 889 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 890 | self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); | ||
| 879 | return self; | 891 | return self; |
| 880 | } | 892 | } |
| 881 | 893 | ||
| 882 | pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep { | 894 | pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep { |
| 883 | const self = builder.allocator.create(initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true)) catch unreachable; | 895 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 896 | self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); | ||
| 884 | return self; | 897 | return self; |
| 885 | } | 898 | } |
| 886 | 899 | ||
| 887 | pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { | 900 | pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { |
| 888 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0))) catch unreachable; | 901 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 902 | self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); | ||
| 889 | return self; | 903 | return self; |
| 890 | } | 904 | } |
| 891 | 905 | ||
| 892 | pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep { | 906 | pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep { |
| 893 | const self = builder.allocator.create(initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false)) catch unreachable; | 907 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 908 | self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); | ||
| 894 | self.object_src = src; | 909 | self.object_src = src; |
| 895 | return self; | 910 | return self; |
| 896 | } | 911 | } |
| 897 | 912 | ||
| 898 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep { | 913 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep { |
| 899 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable; | 914 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 915 | self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0)); | ||
| 900 | return self; | 916 | return self; |
| 901 | } | 917 | } |
| 902 | 918 | ||
| 903 | pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep { | 919 | pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep { |
| 904 | const self = builder.allocator.create(initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false)) catch unreachable; | 920 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 921 | self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); | ||
| 905 | return self; | 922 | return self; |
| 906 | } | 923 | } |
| 907 | 924 | ||
| ... | @@ -1099,7 +1116,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1099,7 +1116,10 @@ pub const LibExeObjStep = struct { |
| 1099 | } | 1116 | } |
| 1100 | 1117 | ||
| 1101 | pub fn getOutputPath(self: *LibExeObjStep) []const u8 { | 1118 | pub fn getOutputPath(self: *LibExeObjStep) []const u8 { |
| 1102 | return if (self.output_path) |output_path| output_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable; | 1119 | return if (self.output_path) |output_path| output_path else os.path.join( |
| 1120 | self.builder.allocator, | ||
| 1121 | [][]const u8{ self.builder.cache_root, self.out_filename }, | ||
| 1122 | ) catch unreachable; | ||
| 1103 | } | 1123 | } |
| 1104 | 1124 | ||
| 1105 | pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void { | 1125 | pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void { |
| ... | @@ -1112,7 +1132,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1112,7 +1132,10 @@ pub const LibExeObjStep = struct { |
| 1112 | } | 1132 | } |
| 1113 | 1133 | ||
| 1114 | pub fn getOutputHPath(self: *LibExeObjStep) []const u8 { | 1134 | pub fn getOutputHPath(self: *LibExeObjStep) []const u8 { |
| 1115 | return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable; | 1135 | return if (self.output_h_path) |output_h_path| output_h_path else os.path.join( |
| 1136 | self.builder.allocator, | ||
| 1137 | [][]const u8{ self.builder.cache_root, self.out_h_filename }, | ||
| 1138 | ) catch unreachable; | ||
| 1116 | } | 1139 | } |
| 1117 | 1140 | ||
| 1118 | pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { | 1141 | pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { |
| ... | @@ -1212,7 +1235,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1212,7 +1235,10 @@ pub const LibExeObjStep = struct { |
| 1212 | } | 1235 | } |
| 1213 | 1236 | ||
| 1214 | if (self.build_options_contents.len() > 0) { | 1237 | if (self.build_options_contents.len() > 0) { |
| 1215 | const build_options_file = try os.path.join(builder.allocator, builder.cache_root, builder.fmt("{}_build_options.zig", self.name)); | 1238 | const build_options_file = try os.path.join( |
| 1239 | builder.allocator, | ||
| 1240 | [][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", self.name) }, | ||
| 1241 | ); | ||
| 1216 | try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst()); | 1242 | try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst()); |
| 1217 | try zig_args.append("--pkg-begin"); | 1243 | try zig_args.append("--pkg-begin"); |
| 1218 | try zig_args.append("build_options"); | 1244 | try zig_args.append("build_options"); |
| ... | @@ -1462,7 +1488,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1462,7 +1488,10 @@ pub const LibExeObjStep = struct { |
| 1462 | cc_args.append("-c") catch unreachable; | 1488 | cc_args.append("-c") catch unreachable; |
| 1463 | cc_args.append(abs_source_file) catch unreachable; | 1489 | cc_args.append(abs_source_file) catch unreachable; |
| 1464 | 1490 | ||
| 1465 | const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable; | 1491 | const cache_o_src = os.path.join( |
| 1492 | builder.allocator, | ||
| 1493 | [][]const u8{ builder.cache_root, source_file }, | ||
| 1494 | ) catch unreachable; | ||
| 1466 | if (os.path.dirname(cache_o_src)) |cache_o_dir| { | 1495 | if (os.path.dirname(cache_o_src)) |cache_o_dir| { |
| 1467 | try builder.makePath(cache_o_dir); | 1496 | try builder.makePath(cache_o_dir); |
| 1468 | } | 1497 | } |
| ... | @@ -1514,7 +1543,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1514,7 +1543,10 @@ pub const LibExeObjStep = struct { |
| 1514 | cc_args.append("-current_version") catch unreachable; | 1543 | cc_args.append("-current_version") catch unreachable; |
| 1515 | cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable; | 1544 | cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable; |
| 1516 | 1545 | ||
| 1517 | const install_name = builder.pathFromRoot(os.path.join(builder.allocator, builder.cache_root, self.major_only_filename) catch unreachable); | 1546 | const install_name = builder.pathFromRoot(os.path.join( |
| 1547 | builder.allocator, | ||
| 1548 | [][]const u8{ builder.cache_root, self.major_only_filename }, | ||
| 1549 | ) catch unreachable); | ||
| 1518 | cc_args.append("-install_name") catch unreachable; | 1550 | cc_args.append("-install_name") catch unreachable; |
| 1519 | cc_args.append(install_name) catch unreachable; | 1551 | cc_args.append(install_name) catch unreachable; |
| 1520 | } else { | 1552 | } else { |
| ... | @@ -1580,7 +1612,10 @@ pub const LibExeObjStep = struct { | ... | @@ -1580,7 +1612,10 @@ pub const LibExeObjStep = struct { |
| 1580 | cc_args.append("-c") catch unreachable; | 1612 | cc_args.append("-c") catch unreachable; |
| 1581 | cc_args.append(abs_source_file) catch unreachable; | 1613 | cc_args.append(abs_source_file) catch unreachable; |
| 1582 | 1614 | ||
| 1583 | const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable; | 1615 | const cache_o_src = os.path.join( |
| 1616 | builder.allocator, | ||
| 1617 | [][]const u8{ builder.cache_root, source_file }, | ||
| 1618 | ) catch unreachable; | ||
| 1584 | if (os.path.dirname(cache_o_src)) |cache_o_dir| { | 1619 | if (os.path.dirname(cache_o_src)) |cache_o_dir| { |
| 1585 | try builder.makePath(cache_o_dir); | 1620 | try builder.makePath(cache_o_dir); |
| 1586 | } | 1621 | } |
| ... | @@ -1672,6 +1707,7 @@ pub const TestStep = struct { | ... | @@ -1672,6 +1707,7 @@ pub const TestStep = struct { |
| 1672 | no_rosegment: bool, | 1707 | no_rosegment: bool, |
| 1673 | output_path: ?[]const u8, | 1708 | output_path: ?[]const u8, |
| 1674 | system_linker_hack: bool, | 1709 | system_linker_hack: bool, |
| 1710 | override_std_dir: ?[]const u8, | ||
| 1675 | 1711 | ||
| 1676 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { | 1712 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { |
| 1677 | const step_name = builder.fmt("test {}", root_src); | 1713 | const step_name = builder.fmt("test {}", root_src); |
| ... | @@ -1693,6 +1729,7 @@ pub const TestStep = struct { | ... | @@ -1693,6 +1729,7 @@ pub const TestStep = struct { |
| 1693 | .no_rosegment = false, | 1729 | .no_rosegment = false, |
| 1694 | .output_path = null, | 1730 | .output_path = null, |
| 1695 | .system_linker_hack = false, | 1731 | .system_linker_hack = false, |
| 1732 | .override_std_dir = null, | ||
| 1696 | }; | 1733 | }; |
| 1697 | } | 1734 | } |
| 1698 | 1735 | ||
| ... | @@ -1723,6 +1760,10 @@ pub const TestStep = struct { | ... | @@ -1723,6 +1760,10 @@ pub const TestStep = struct { |
| 1723 | self.build_mode = mode; | 1760 | self.build_mode = mode; |
| 1724 | } | 1761 | } |
| 1725 | 1762 | ||
| 1763 | pub fn overrideStdDir(self: *TestStep, dir_path: []const u8) void { | ||
| 1764 | self.override_std_dir = dir_path; | ||
| 1765 | } | ||
| 1766 | |||
| 1726 | pub fn setOutputPath(self: *TestStep, file_path: []const u8) void { | 1767 | pub fn setOutputPath(self: *TestStep, file_path: []const u8) void { |
| 1727 | self.output_path = file_path; | 1768 | self.output_path = file_path; |
| 1728 | 1769 | ||
| ... | @@ -1737,7 +1778,10 @@ pub const TestStep = struct { | ... | @@ -1737,7 +1778,10 @@ pub const TestStep = struct { |
| 1737 | return output_path; | 1778 | return output_path; |
| 1738 | } else { | 1779 | } else { |
| 1739 | const basename = self.builder.fmt("test{}", self.target.exeFileExt()); | 1780 | const basename = self.builder.fmt("test{}", self.target.exeFileExt()); |
| 1740 | return os.path.join(self.builder.allocator, self.builder.cache_root, basename) catch unreachable; | 1781 | return os.path.join( |
| 1782 | self.builder.allocator, | ||
| 1783 | [][]const u8{ self.builder.cache_root, basename }, | ||
| 1784 | ) catch unreachable; | ||
| 1741 | } | 1785 | } |
| 1742 | } | 1786 | } |
| 1743 | 1787 | ||
| ... | @@ -1900,6 +1944,10 @@ pub const TestStep = struct { | ... | @@ -1900,6 +1944,10 @@ pub const TestStep = struct { |
| 1900 | if (self.system_linker_hack) { | 1944 | if (self.system_linker_hack) { |
| 1901 | try zig_args.append("--system-linker-hack"); | 1945 | try zig_args.append("--system-linker-hack"); |
| 1902 | } | 1946 | } |
| 1947 | if (self.override_std_dir) |dir| { | ||
| 1948 | try zig_args.append("--override-std-dir"); | ||
| 1949 | try zig_args.append(builder.pathFromRoot(dir)); | ||
| 1950 | } | ||
| 1903 | 1951 | ||
| 1904 | try builder.spawnChild(zig_args.toSliceConst()); | 1952 | try builder.spawnChild(zig_args.toSliceConst()); |
| 1905 | } | 1953 | } |
| ... | @@ -1914,13 +1962,14 @@ pub const CommandStep = struct { | ... | @@ -1914,13 +1962,14 @@ pub const CommandStep = struct { |
| 1914 | 1962 | ||
| 1915 | /// ::argv is copied. | 1963 | /// ::argv is copied. |
| 1916 | pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep { | 1964 | pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep { |
| 1917 | const self = builder.allocator.create(CommandStep{ | 1965 | const self = builder.allocator.create(CommandStep) catch unreachable; |
| 1966 | self.* = CommandStep{ | ||
| 1918 | .builder = builder, | 1967 | .builder = builder, |
| 1919 | .step = Step.init(argv[0], builder.allocator, make), | 1968 | .step = Step.init(argv[0], builder.allocator, make), |
| 1920 | .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable, | 1969 | .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable, |
| 1921 | .cwd = cwd, | 1970 | .cwd = cwd, |
| 1922 | .env_map = env_map, | 1971 | .env_map = env_map, |
| 1923 | }) catch unreachable; | 1972 | }; |
| 1924 | 1973 | ||
| 1925 | mem.copy([]const u8, self.argv, argv); | 1974 | mem.copy([]const u8, self.argv, argv); |
| 1926 | self.step.name = self.argv[0]; | 1975 | self.step.name = self.argv[0]; |
| ... | @@ -1949,17 +1998,27 @@ const InstallArtifactStep = struct { | ... | @@ -1949,17 +1998,27 @@ const InstallArtifactStep = struct { |
| 1949 | LibExeObjStep.Kind.Exe => builder.exe_dir, | 1998 | LibExeObjStep.Kind.Exe => builder.exe_dir, |
| 1950 | LibExeObjStep.Kind.Lib => builder.lib_dir, | 1999 | LibExeObjStep.Kind.Lib => builder.lib_dir, |
| 1951 | }; | 2000 | }; |
| 1952 | const self = builder.allocator.create(Self{ | 2001 | const self = builder.allocator.create(Self) catch unreachable; |
| 2002 | self.* = Self{ | ||
| 1953 | .builder = builder, | 2003 | .builder = builder, |
| 1954 | .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), | 2004 | .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), |
| 1955 | .artifact = artifact, | 2005 | .artifact = artifact, |
| 1956 | .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable, | 2006 | .dest_file = os.path.join( |
| 1957 | }) catch unreachable; | 2007 | builder.allocator, |
| 2008 | [][]const u8{ dest_dir, artifact.out_filename }, | ||
| 2009 | ) catch unreachable, | ||
| 2010 | }; | ||
| 1958 | self.step.dependOn(&artifact.step); | 2011 | self.step.dependOn(&artifact.step); |
| 1959 | builder.pushInstalledFile(self.dest_file); | 2012 | builder.pushInstalledFile(self.dest_file); |
| 1960 | if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { | 2013 | if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) { |
| 1961 | builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable); | 2014 | builder.pushInstalledFile(os.path.join( |
| 1962 | builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable); | 2015 | builder.allocator, |
| 2016 | [][]const u8{ builder.lib_dir, artifact.major_only_filename }, | ||
| 2017 | ) catch unreachable); | ||
| 2018 | builder.pushInstalledFile(os.path.join( | ||
| 2019 | builder.allocator, | ||
| 2020 | [][]const u8{ builder.lib_dir, artifact.name_only_filename }, | ||
| 2021 | ) catch unreachable); | ||
| 1963 | } | 2022 | } |
| 1964 | return self; | 2023 | return self; |
| 1965 | } | 2024 | } |
| ... | @@ -2115,13 +2174,19 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj | ... | @@ -2115,13 +2174,19 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj |
| 2115 | const out_dir = os.path.dirname(output_path) orelse "."; | 2174 | const out_dir = os.path.dirname(output_path) orelse "."; |
| 2116 | const out_basename = os.path.basename(output_path); | 2175 | const out_basename = os.path.basename(output_path); |
| 2117 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 | 2176 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 |
| 2118 | const major_only_path = os.path.join(allocator, out_dir, filename_major_only) catch unreachable; | 2177 | const major_only_path = os.path.join( |
| 2178 | allocator, | ||
| 2179 | [][]const u8{ out_dir, filename_major_only }, | ||
| 2180 | ) catch unreachable; | ||
| 2119 | os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| { | 2181 | os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| { |
| 2120 | warn("Unable to symlink {} -> {}\n", major_only_path, out_basename); | 2182 | warn("Unable to symlink {} -> {}\n", major_only_path, out_basename); |
| 2121 | return err; | 2183 | return err; |
| 2122 | }; | 2184 | }; |
| 2123 | // sym link for libfoo.so to libfoo.so.1 | 2185 | // sym link for libfoo.so to libfoo.so.1 |
| 2124 | const name_only_path = os.path.join(allocator, out_dir, filename_name_only) catch unreachable; | 2186 | const name_only_path = os.path.join( |
| 2187 | allocator, | ||
| 2188 | [][]const u8{ out_dir, filename_name_only }, | ||
| 2189 | ) catch unreachable; | ||
| 2125 | os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| { | 2190 | os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| { |
| 2126 | warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only); | 2191 | warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only); |
| 2127 | return err; | 2192 | return err; |
std/c/darwin.zig+20-2| ... | @@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct { | ... | @@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct { |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | pub const timeval = extern struct { | 75 | pub const timeval = extern struct { |
| 76 | tv_sec: isize, | 76 | tv_sec: c_long, |
| 77 | tv_usec: isize, | 77 | tv_usec: i32, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | pub const timezone = extern struct { | 80 | pub const timezone = extern struct { |
| ... | @@ -176,6 +176,24 @@ pub const kevent64_s = extern struct { | ... | @@ -176,6 +176,24 @@ pub const kevent64_s = extern struct { |
| 176 | ext: [2]u64, | 176 | ext: [2]u64, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | pub const mach_port_t = c_uint; | ||
| 180 | pub const clock_serv_t = mach_port_t; | ||
| 181 | pub const clock_res_t = c_int; | ||
| 182 | pub const mach_port_name_t = natural_t; | ||
| 183 | pub const natural_t = c_uint; | ||
| 184 | pub const mach_timespec_t = extern struct { | ||
| 185 | tv_sec: c_uint, | ||
| 186 | tv_nsec: clock_res_t, | ||
| 187 | }; | ||
| 188 | pub const kern_return_t = c_int; | ||
| 189 | pub const host_t = mach_port_t; | ||
| 190 | pub const CALENDAR_CLOCK = 1; | ||
| 191 | |||
| 192 | pub extern fn mach_host_self() mach_port_t; | ||
| 193 | pub extern fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t; | ||
| 194 | pub extern fn host_get_clock_service(host: host_t, clock_id: clock_id_t, clock_serv: ?[*]clock_serv_t) kern_return_t; | ||
| 195 | pub extern fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t; | ||
| 196 | |||
| 179 | // sys/types.h on macos uses #pragma pack() so these checks are | 197 | // sys/types.h on macos uses #pragma pack() so these checks are |
| 180 | // to make sure the struct is laid out the same. These values were | 198 | // to make sure the struct is laid out the same. These values were |
| 181 | // produced from C code using the offsetof macro. | 199 | // produced from C code using the offsetof macro. |
std/c/freebsd.zig+89-2| ... | @@ -1,5 +1,3 @@ | ... | @@ -1,5 +1,3 @@ |
| 1 | const timespec = @import("../os/freebsd/index.zig").timespec; | ||
| 2 | |||
| 3 | extern "c" fn __error() *c_int; | 1 | extern "c" fn __error() *c_int; |
| 4 | pub const _errno = __error; | 2 | pub const _errno = __error; |
| 5 | 3 | ||
| ... | @@ -15,6 +13,17 @@ pub extern "c" fn kevent( | ... | @@ -15,6 +13,17 @@ pub extern "c" fn kevent( |
| 15 | pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; | 13 | pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; |
| 16 | pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; | 14 | pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; |
| 17 | pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int; | 15 | pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int; |
| 16 | pub extern "c" fn getdirentries(fd: c_int, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize; | ||
| 17 | pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize; | ||
| 18 | pub extern "c" fn pipe2(arg0: *[2]c_int, arg1: u32) c_int; | ||
| 19 | pub extern "c" fn preadv(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize; | ||
| 20 | pub extern "c" fn pwritev(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize; | ||
| 21 | pub extern "c" fn openat(fd: c_int, path: ?[*]const u8, flags: c_int) c_int; | ||
| 22 | pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int; | ||
| 23 | pub extern "c" fn setuid(uid: c_uint) c_int; | ||
| 24 | pub extern "c" fn kill(pid: c_int, sig: c_int) c_int; | ||
| 25 | pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int; | ||
| 26 | pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int; | ||
| 18 | 27 | ||
| 19 | /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. | 28 | /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. |
| 20 | pub const Kevent = extern struct { | 29 | pub const Kevent = extern struct { |
| ... | @@ -31,3 +40,81 @@ pub const pthread_attr_t = extern struct { | ... | @@ -31,3 +40,81 @@ pub const pthread_attr_t = extern struct { |
| 31 | __size: [56]u8, | 40 | __size: [56]u8, |
| 32 | __align: c_long, | 41 | __align: c_long, |
| 33 | }; | 42 | }; |
| 43 | |||
| 44 | pub const msghdr = extern struct { | ||
| 45 | msg_name: *u8, | ||
| 46 | msg_namelen: socklen_t, | ||
| 47 | msg_iov: *iovec, | ||
| 48 | msg_iovlen: i32, | ||
| 49 | __pad1: i32, | ||
| 50 | msg_control: *u8, | ||
| 51 | msg_controllen: socklen_t, | ||
| 52 | __pad2: socklen_t, | ||
| 53 | msg_flags: i32, | ||
| 54 | }; | ||
| 55 | |||
| 56 | pub const Stat = extern struct { | ||
| 57 | dev: u64, | ||
| 58 | ino: u64, | ||
| 59 | nlink: usize, | ||
| 60 | |||
| 61 | mode: u16, | ||
| 62 | __pad0: u16, | ||
| 63 | uid: u32, | ||
| 64 | gid: u32, | ||
| 65 | __pad1: u32, | ||
| 66 | rdev: u64, | ||
| 67 | |||
| 68 | atim: timespec, | ||
| 69 | mtim: timespec, | ||
| 70 | ctim: timespec, | ||
| 71 | birthtim: timespec, | ||
| 72 | |||
| 73 | size: i64, | ||
| 74 | blocks: i64, | ||
| 75 | blksize: isize, | ||
| 76 | flags: u32, | ||
| 77 | gen: u64, | ||
| 78 | __spare: [10]u64, | ||
| 79 | }; | ||
| 80 | |||
| 81 | pub const timespec = extern struct { | ||
| 82 | tv_sec: isize, | ||
| 83 | tv_nsec: isize, | ||
| 84 | }; | ||
| 85 | |||
| 86 | pub const dirent = extern struct { | ||
| 87 | d_fileno: usize, | ||
| 88 | d_off: i64, | ||
| 89 | d_reclen: u16, | ||
| 90 | d_type: u8, | ||
| 91 | d_pad0: u8, | ||
| 92 | d_namlen: u16, | ||
| 93 | d_pad1: u16, | ||
| 94 | d_name: [256]u8, | ||
| 95 | }; | ||
| 96 | |||
| 97 | pub const in_port_t = u16; | ||
| 98 | pub const sa_family_t = u16; | ||
| 99 | |||
| 100 | pub const sockaddr = extern union { | ||
| 101 | in: sockaddr_in, | ||
| 102 | in6: sockaddr_in6, | ||
| 103 | }; | ||
| 104 | |||
| 105 | pub const sockaddr_in = extern struct { | ||
| 106 | len: u8, | ||
| 107 | family: sa_family_t, | ||
| 108 | port: in_port_t, | ||
| 109 | addr: [16]u8, | ||
| 110 | zero: [8]u8, | ||
| 111 | }; | ||
| 112 | |||
| 113 | pub const sockaddr_in6 = extern struct { | ||
| 114 | len: u8, | ||
| 115 | family: sa_family_t, | ||
| 116 | port: in_port_t, | ||
| 117 | flowinfo: u32, | ||
| 118 | addr: [16]u8, | ||
| 119 | scope_id: u32, | ||
| 120 | }; |
std/c/index.zig+1-1| ... | @@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int; | ... | @@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int; |
| 44 | pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize; | 44 | pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize; |
| 45 | pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8; | 45 | pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8; |
| 46 | pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int; | 46 | pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 47 | pub extern "c" fn gettimeofday(tv: ?*timeval, tz: ?*timezone) c_int; | 47 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 48 | pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; | 48 | pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; |
| 49 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 49 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 50 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; | 50 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; |
std/coff.zig+22-22| ... | @@ -51,7 +51,7 @@ pub const Coff = struct { | ... | @@ -51,7 +51,7 @@ pub const Coff = struct { |
| 51 | 51 | ||
| 52 | // Seek to PE File Header (coff header) | 52 | // Seek to PE File Header (coff header) |
| 53 | try self.in_file.seekTo(pe_pointer_offset); | 53 | try self.in_file.seekTo(pe_pointer_offset); |
| 54 | const pe_magic_offset = try in.readIntLe(u32); | 54 | const pe_magic_offset = try in.readIntLittle(u32); |
| 55 | try self.in_file.seekTo(pe_magic_offset); | 55 | try self.in_file.seekTo(pe_magic_offset); |
| 56 | 56 | ||
| 57 | var pe_header_magic: [4]u8 = undefined; | 57 | var pe_header_magic: [4]u8 = undefined; |
| ... | @@ -60,13 +60,13 @@ pub const Coff = struct { | ... | @@ -60,13 +60,13 @@ pub const Coff = struct { |
| 60 | return error.InvalidPEHeader; | 60 | return error.InvalidPEHeader; |
| 61 | 61 | ||
| 62 | self.coff_header = CoffHeader{ | 62 | self.coff_header = CoffHeader{ |
| 63 | .machine = try in.readIntLe(u16), | 63 | .machine = try in.readIntLittle(u16), |
| 64 | .number_of_sections = try in.readIntLe(u16), | 64 | .number_of_sections = try in.readIntLittle(u16), |
| 65 | .timedate_stamp = try in.readIntLe(u32), | 65 | .timedate_stamp = try in.readIntLittle(u32), |
| 66 | .pointer_to_symbol_table = try in.readIntLe(u32), | 66 | .pointer_to_symbol_table = try in.readIntLittle(u32), |
| 67 | .number_of_symbols = try in.readIntLe(u32), | 67 | .number_of_symbols = try in.readIntLittle(u32), |
| 68 | .size_of_optional_header = try in.readIntLe(u16), | 68 | .size_of_optional_header = try in.readIntLittle(u16), |
| 69 | .characteristics = try in.readIntLe(u16), | 69 | .characteristics = try in.readIntLittle(u16), |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | switch (self.coff_header.machine) { | 72 | switch (self.coff_header.machine) { |
| ... | @@ -79,7 +79,7 @@ pub const Coff = struct { | ... | @@ -79,7 +79,7 @@ pub const Coff = struct { |
| 79 | 79 | ||
| 80 | fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void { | 80 | fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void { |
| 81 | const in = &file_stream.stream; | 81 | const in = &file_stream.stream; |
| 82 | self.pe_header.magic = try in.readIntLe(u16); | 82 | self.pe_header.magic = try in.readIntLittle(u16); |
| 83 | // For now we're only interested in finding the reference to the .pdb, | 83 | // For now we're only interested in finding the reference to the .pdb, |
| 84 | // so we'll skip most of this header, which size is different in 32 | 84 | // so we'll skip most of this header, which size is different in 32 |
| 85 | // 64 bits by the way. | 85 | // 64 bits by the way. |
| ... | @@ -93,14 +93,14 @@ pub const Coff = struct { | ... | @@ -93,14 +93,14 @@ pub const Coff = struct { |
| 93 | 93 | ||
| 94 | try self.in_file.seekForward(skip_size); | 94 | try self.in_file.seekForward(skip_size); |
| 95 | 95 | ||
| 96 | const number_of_rva_and_sizes = try in.readIntLe(u32); | 96 | const number_of_rva_and_sizes = try in.readIntLittle(u32); |
| 97 | if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) | 97 | if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) |
| 98 | return error.InvalidPEHeader; | 98 | return error.InvalidPEHeader; |
| 99 | 99 | ||
| 100 | for (self.pe_header.data_directory) |*data_dir| { | 100 | for (self.pe_header.data_directory) |*data_dir| { |
| 101 | data_dir.* = OptionalHeader.DataDirectory{ | 101 | data_dir.* = OptionalHeader.DataDirectory{ |
| 102 | .virtual_address = try in.readIntLe(u32), | 102 | .virtual_address = try in.readIntLittle(u32), |
| 103 | .size = try in.readIntLe(u32), | 103 | .size = try in.readIntLittle(u32), |
| 104 | }; | 104 | }; |
| 105 | } | 105 | } |
| 106 | } | 106 | } |
| ... | @@ -124,7 +124,7 @@ pub const Coff = struct { | ... | @@ -124,7 +124,7 @@ pub const Coff = struct { |
| 124 | if (!mem.eql(u8, cv_signature, "RSDS")) | 124 | if (!mem.eql(u8, cv_signature, "RSDS")) |
| 125 | return error.InvalidPEMagic; | 125 | return error.InvalidPEMagic; |
| 126 | try in.readNoEof(self.guid[0..]); | 126 | try in.readNoEof(self.guid[0..]); |
| 127 | self.age = try in.readIntLe(u32); | 127 | self.age = try in.readIntLittle(u32); |
| 128 | 128 | ||
| 129 | // Finally read the null-terminated string. | 129 | // Finally read the null-terminated string. |
| 130 | var byte = try in.readByte(); | 130 | var byte = try in.readByte(); |
| ... | @@ -157,15 +157,15 @@ pub const Coff = struct { | ... | @@ -157,15 +157,15 @@ pub const Coff = struct { |
| 157 | try self.sections.append(Section{ | 157 | try self.sections.append(Section{ |
| 158 | .header = SectionHeader{ | 158 | .header = SectionHeader{ |
| 159 | .name = name, | 159 | .name = name, |
| 160 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) }, | 160 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) }, |
| 161 | .virtual_address = try in.readIntLe(u32), | 161 | .virtual_address = try in.readIntLittle(u32), |
| 162 | .size_of_raw_data = try in.readIntLe(u32), | 162 | .size_of_raw_data = try in.readIntLittle(u32), |
| 163 | .pointer_to_raw_data = try in.readIntLe(u32), | 163 | .pointer_to_raw_data = try in.readIntLittle(u32), |
| 164 | .pointer_to_relocations = try in.readIntLe(u32), | 164 | .pointer_to_relocations = try in.readIntLittle(u32), |
| 165 | .pointer_to_line_numbers = try in.readIntLe(u32), | 165 | .pointer_to_line_numbers = try in.readIntLittle(u32), |
| 166 | .number_of_relocations = try in.readIntLe(u16), | 166 | .number_of_relocations = try in.readIntLittle(u16), |
| 167 | .number_of_line_numbers = try in.readIntLe(u16), | 167 | .number_of_line_numbers = try in.readIntLittle(u16), |
| 168 | .characteristics = try in.readIntLe(u32), | 168 | .characteristics = try in.readIntLittle(u32), |
| 169 | }, | 169 | }, |
| 170 | }); | 170 | }); |
| 171 | } | 171 | } |
std/crypto/blake2.zig+7-4| ... | @@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type { | ... | @@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type { |
| 123 | const rr = d.h[0 .. out_len / 32]; | 123 | const rr = d.h[0 .. out_len / 32]; |
| 124 | 124 | ||
| 125 | for (rr) |s, j| { | 125 | for (rr) |s, j| { |
| 126 | mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little); | 126 | // TODO https://github.com/ziglang/zig/issues/863 |
| 127 | mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s); | ||
| 127 | } | 128 | } |
| 128 | } | 129 | } |
| 129 | 130 | ||
| ... | @@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type { | ... | @@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type { |
| 134 | var v: [16]u32 = undefined; | 135 | var v: [16]u32 = undefined; |
| 135 | 136 | ||
| 136 | for (m) |*r, i| { | 137 | for (m) |*r, i| { |
| 137 | r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]); | 138 | // TODO https://github.com/ziglang/zig/issues/863 |
| 139 | r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]); | ||
| 138 | } | 140 | } |
| 139 | 141 | ||
| 140 | var k: usize = 0; | 142 | var k: usize = 0; |
| ... | @@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type { | ... | @@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type { |
| 356 | const rr = d.h[0 .. out_len / 64]; | 358 | const rr = d.h[0 .. out_len / 64]; |
| 357 | 359 | ||
| 358 | for (rr) |s, j| { | 360 | for (rr) |s, j| { |
| 359 | mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little); | 361 | // TODO https://github.com/ziglang/zig/issues/863 |
| 362 | mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s); | ||
| 360 | } | 363 | } |
| 361 | } | 364 | } |
| 362 | 365 | ||
| ... | @@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type { | ... | @@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type { |
| 367 | var v: [16]u64 = undefined; | 370 | var v: [16]u64 = undefined; |
| 368 | 371 | ||
| 369 | for (m) |*r, i| { | 372 | for (m) |*r, i| { |
| 370 | r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]); | 373 | r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]); |
| 371 | } | 374 | } |
| 372 | 375 | ||
| 373 | var k: usize = 0; | 376 | var k: usize = 0; |
std/crypto/chacha20.zig+35-33| ... | @@ -4,6 +4,7 @@ const std = @import("../index.zig"); | ... | @@ -4,6 +4,7 @@ const std = @import("../index.zig"); |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const endian = std.endian; | 5 | const endian = std.endian; |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const testing = std.testing; | ||
| 7 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 8 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| 9 | 10 | ||
| ... | @@ -59,7 +60,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { | ... | @@ -59,7 +60,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | for (x) |_, i| { | 62 | for (x) |_, i| { |
| 62 | mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little); | 63 | // TODO https://github.com/ziglang/zig/issues/863 |
| 64 | mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]); | ||
| 63 | } | 65 | } |
| 64 | } | 66 | } |
| 65 | 67 | ||
| ... | @@ -70,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo | ... | @@ -70,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo |
| 70 | 72 | ||
| 71 | const c = "expand 32-byte k"; | 73 | const c = "expand 32-byte k"; |
| 72 | const constant_le = []u32{ | 74 | const constant_le = []u32{ |
| 73 | mem.readIntLE(u32, c[0..4]), | 75 | mem.readIntSliceLittle(u32, c[0..4]), |
| 74 | mem.readIntLE(u32, c[4..8]), | 76 | mem.readIntSliceLittle(u32, c[4..8]), |
| 75 | mem.readIntLE(u32, c[8..12]), | 77 | mem.readIntSliceLittle(u32, c[8..12]), |
| 76 | mem.readIntLE(u32, c[12..16]), | 78 | mem.readIntSliceLittle(u32, c[12..16]), |
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 79 | mem.copy(u32, ctx[0..], constant_le[0..4]); | 81 | mem.copy(u32, ctx[0..], constant_le[0..4]); |
| ... | @@ -117,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: | ... | @@ -117,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: |
| 117 | var k: [8]u32 = undefined; | 119 | var k: [8]u32 = undefined; |
| 118 | var c: [4]u32 = undefined; | 120 | var c: [4]u32 = undefined; |
| 119 | 121 | ||
| 120 | k[0] = mem.readIntLE(u32, key[0..4]); | 122 | k[0] = mem.readIntSliceLittle(u32, key[0..4]); |
| 121 | k[1] = mem.readIntLE(u32, key[4..8]); | 123 | k[1] = mem.readIntSliceLittle(u32, key[4..8]); |
| 122 | k[2] = mem.readIntLE(u32, key[8..12]); | 124 | k[2] = mem.readIntSliceLittle(u32, key[8..12]); |
| 123 | k[3] = mem.readIntLE(u32, key[12..16]); | 125 | k[3] = mem.readIntSliceLittle(u32, key[12..16]); |
| 124 | k[4] = mem.readIntLE(u32, key[16..20]); | 126 | k[4] = mem.readIntSliceLittle(u32, key[16..20]); |
| 125 | k[5] = mem.readIntLE(u32, key[20..24]); | 127 | k[5] = mem.readIntSliceLittle(u32, key[20..24]); |
| 126 | k[6] = mem.readIntLE(u32, key[24..28]); | 128 | k[6] = mem.readIntSliceLittle(u32, key[24..28]); |
| 127 | k[7] = mem.readIntLE(u32, key[28..32]); | 129 | k[7] = mem.readIntSliceLittle(u32, key[28..32]); |
| 128 | 130 | ||
| 129 | c[0] = counter; | 131 | c[0] = counter; |
| 130 | c[1] = mem.readIntLE(u32, nonce[0..4]); | 132 | c[1] = mem.readIntSliceLittle(u32, nonce[0..4]); |
| 131 | c[2] = mem.readIntLE(u32, nonce[4..8]); | 133 | c[2] = mem.readIntSliceLittle(u32, nonce[4..8]); |
| 132 | c[3] = mem.readIntLE(u32, nonce[8..12]); | 134 | c[3] = mem.readIntSliceLittle(u32, nonce[8..12]); |
| 133 | chaCha20_internal(out, in, k, c); | 135 | chaCha20_internal(out, in, k, c); |
| 134 | } | 136 | } |
| 135 | 137 | ||
| ... | @@ -144,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] | ... | @@ -144,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] |
| 144 | var k: [8]u32 = undefined; | 146 | var k: [8]u32 = undefined; |
| 145 | var c: [4]u32 = undefined; | 147 | var c: [4]u32 = undefined; |
| 146 | 148 | ||
| 147 | k[0] = mem.readIntLE(u32, key[0..4]); | 149 | k[0] = mem.readIntSliceLittle(u32, key[0..4]); |
| 148 | k[1] = mem.readIntLE(u32, key[4..8]); | 150 | k[1] = mem.readIntSliceLittle(u32, key[4..8]); |
| 149 | k[2] = mem.readIntLE(u32, key[8..12]); | 151 | k[2] = mem.readIntSliceLittle(u32, key[8..12]); |
| 150 | k[3] = mem.readIntLE(u32, key[12..16]); | 152 | k[3] = mem.readIntSliceLittle(u32, key[12..16]); |
| 151 | k[4] = mem.readIntLE(u32, key[16..20]); | 153 | k[4] = mem.readIntSliceLittle(u32, key[16..20]); |
| 152 | k[5] = mem.readIntLE(u32, key[20..24]); | 154 | k[5] = mem.readIntSliceLittle(u32, key[20..24]); |
| 153 | k[6] = mem.readIntLE(u32, key[24..28]); | 155 | k[6] = mem.readIntSliceLittle(u32, key[24..28]); |
| 154 | k[7] = mem.readIntLE(u32, key[28..32]); | 156 | k[7] = mem.readIntSliceLittle(u32, key[28..32]); |
| 155 | 157 | ||
| 156 | c[0] = @truncate(u32, counter); | 158 | c[0] = @truncate(u32, counter); |
| 157 | c[1] = @truncate(u32, counter >> 32); | 159 | c[1] = @truncate(u32, counter >> 32); |
| 158 | c[2] = mem.readIntLE(u32, nonce[0..4]); | 160 | c[2] = mem.readIntSliceLittle(u32, nonce[0..4]); |
| 159 | c[3] = mem.readIntLE(u32, nonce[4..8]); | 161 | c[3] = mem.readIntSliceLittle(u32, nonce[4..8]); |
| 160 | 162 | ||
| 161 | const block_size = (1 << 6); | 163 | const block_size = (1 << 6); |
| 162 | const big_block = (block_size << 32); | 164 | const big_block = (block_size << 32); |
| ... | @@ -215,12 +217,12 @@ test "crypto.chacha20 test vector sunscreen" { | ... | @@ -215,12 +217,12 @@ test "crypto.chacha20 test vector sunscreen" { |
| 215 | }; | 217 | }; |
| 216 | 218 | ||
| 217 | chaCha20IETF(result[0..], input[0..], 1, key, nonce); | 219 | chaCha20IETF(result[0..], input[0..], 1, key, nonce); |
| 218 | assert(mem.eql(u8, expected_result, result)); | 220 | testing.expectEqualSlices(u8, expected_result, result); |
| 219 | 221 | ||
| 220 | // Chacha20 is self-reversing. | 222 | // Chacha20 is self-reversing. |
| 221 | var plaintext: [114]u8 = undefined; | 223 | var plaintext: [114]u8 = undefined; |
| 222 | chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce); | 224 | chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce); |
| 223 | assert(mem.compare(u8, input, plaintext) == mem.Compare.Equal); | 225 | testing.expect(mem.compare(u8, input, plaintext) == mem.Compare.Equal); |
| 224 | } | 226 | } |
| 225 | 227 | ||
| 226 | // https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 | 228 | // https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 |
| ... | @@ -255,7 +257,7 @@ test "crypto.chacha20 test vector 1" { | ... | @@ -255,7 +257,7 @@ test "crypto.chacha20 test vector 1" { |
| 255 | const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; | 257 | const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 256 | 258 | ||
| 257 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 259 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); |
| 258 | assert(mem.eql(u8, expected_result, result)); | 260 | testing.expectEqualSlices(u8, expected_result, result); |
| 259 | } | 261 | } |
| 260 | 262 | ||
| 261 | test "crypto.chacha20 test vector 2" { | 263 | test "crypto.chacha20 test vector 2" { |
| ... | @@ -289,7 +291,7 @@ test "crypto.chacha20 test vector 2" { | ... | @@ -289,7 +291,7 @@ test "crypto.chacha20 test vector 2" { |
| 289 | const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; | 291 | const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 290 | 292 | ||
| 291 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 293 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); |
| 292 | assert(mem.eql(u8, expected_result, result)); | 294 | testing.expectEqualSlices(u8, expected_result, result); |
| 293 | } | 295 | } |
| 294 | 296 | ||
| 295 | test "crypto.chacha20 test vector 3" { | 297 | test "crypto.chacha20 test vector 3" { |
| ... | @@ -323,7 +325,7 @@ test "crypto.chacha20 test vector 3" { | ... | @@ -323,7 +325,7 @@ test "crypto.chacha20 test vector 3" { |
| 323 | const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 }; | 325 | const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 }; |
| 324 | 326 | ||
| 325 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 327 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); |
| 326 | assert(mem.eql(u8, expected_result, result)); | 328 | testing.expectEqualSlices(u8, expected_result, result); |
| 327 | } | 329 | } |
| 328 | 330 | ||
| 329 | test "crypto.chacha20 test vector 4" { | 331 | test "crypto.chacha20 test vector 4" { |
| ... | @@ -357,7 +359,7 @@ test "crypto.chacha20 test vector 4" { | ... | @@ -357,7 +359,7 @@ test "crypto.chacha20 test vector 4" { |
| 357 | const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 }; | 359 | const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 }; |
| 358 | 360 | ||
| 359 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 361 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); |
| 360 | assert(mem.eql(u8, expected_result, result)); | 362 | testing.expectEqualSlices(u8, expected_result, result); |
| 361 | } | 363 | } |
| 362 | 364 | ||
| 363 | test "crypto.chacha20 test vector 5" { | 365 | test "crypto.chacha20 test vector 5" { |
| ... | @@ -429,5 +431,5 @@ test "crypto.chacha20 test vector 5" { | ... | @@ -429,5 +431,5 @@ test "crypto.chacha20 test vector 5" { |
| 429 | }; | 431 | }; |
| 430 | 432 | ||
| 431 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 433 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); |
| 432 | assert(mem.eql(u8, expected_result, result)); | 434 | testing.expectEqualSlices(u8, expected_result, result); |
| 433 | } | 435 | } |
std/crypto/md5.zig+2-1| ... | @@ -112,7 +112,8 @@ pub const Md5 = struct { | ... | @@ -112,7 +112,8 @@ pub const Md5 = struct { |
| 112 | d.round(d.buf[0..]); | 112 | d.round(d.buf[0..]); |
| 113 | 113 | ||
| 114 | for (d.s) |s, j| { | 114 | for (d.s) |s, j| { |
| 115 | mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little); | 115 | // TODO https://github.com/ziglang/zig/issues/863 |
| 116 | mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s); | ||
| 116 | } | 117 | } |
| 117 | } | 118 | } |
| 118 | 119 |
std/crypto/poly1305.zig+15-14| ... | @@ -6,8 +6,8 @@ const std = @import("../index.zig"); | ... | @@ -6,8 +6,8 @@ const std = @import("../index.zig"); |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | 7 | ||
| 8 | const Endian = builtin.Endian; | 8 | const Endian = builtin.Endian; |
| 9 | const readInt = std.mem.readInt; | 9 | const readIntSliceLittle = std.mem.readIntSliceLittle; |
| 10 | const writeInt = std.mem.writeInt; | 10 | const writeIntSliceLittle = std.mem.writeIntSliceLittle; |
| 11 | 11 | ||
| 12 | pub const Poly1305 = struct { | 12 | pub const Poly1305 = struct { |
| 13 | const Self = @This(); | 13 | const Self = @This(); |
| ... | @@ -59,19 +59,19 @@ pub const Poly1305 = struct { | ... | @@ -59,19 +59,19 @@ pub const Poly1305 = struct { |
| 59 | { | 59 | { |
| 60 | var i: usize = 0; | 60 | var i: usize = 0; |
| 61 | while (i < 1) : (i += 1) { | 61 | while (i < 1) : (i += 1) { |
| 62 | ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff; | 62 | ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff; |
| 63 | } | 63 | } |
| 64 | } | 64 | } |
| 65 | { | 65 | { |
| 66 | var i: usize = 1; | 66 | var i: usize = 1; |
| 67 | while (i < 4) : (i += 1) { | 67 | while (i < 4) : (i += 1) { |
| 68 | ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc; | 68 | ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc; |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
| 71 | { | 71 | { |
| 72 | var i: usize = 0; | 72 | var i: usize = 0; |
| 73 | while (i < 4) : (i += 1) { | 73 | while (i < 4) : (i += 1) { |
| 74 | ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little); | 74 | ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]); |
| 75 | } | 75 | } |
| 76 | } | 76 | } |
| 77 | 77 | ||
| ... | @@ -168,10 +168,10 @@ pub const Poly1305 = struct { | ... | @@ -168,10 +168,10 @@ pub const Poly1305 = struct { |
| 168 | const nb_blocks = nmsg.len >> 4; | 168 | const nb_blocks = nmsg.len >> 4; |
| 169 | var i: usize = 0; | 169 | var i: usize = 0; |
| 170 | while (i < nb_blocks) : (i += 1) { | 170 | while (i < nb_blocks) : (i += 1) { |
| 171 | ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little); | 171 | ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]); |
| 172 | ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little); | 172 | ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]); |
| 173 | ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little); | 173 | ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]); |
| 174 | ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little); | 174 | ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]); |
| 175 | polyBlock(ctx); | 175 | polyBlock(ctx); |
| 176 | nmsg = nmsg[16..]; | 176 | nmsg = nmsg[16..]; |
| 177 | } | 177 | } |
| ... | @@ -210,10 +210,11 @@ pub const Poly1305 = struct { | ... | @@ -210,10 +210,11 @@ pub const Poly1305 = struct { |
| 210 | const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000 | 210 | const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000 |
| 211 | const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000 | 211 | const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000 |
| 212 | 212 | ||
| 213 | writeInt(out[0..], @truncate(u32, uu0), Endian.Little); | 213 | // TODO https://github.com/ziglang/zig/issues/863 |
| 214 | writeInt(out[4..], @truncate(u32, uu1), Endian.Little); | 214 | writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0)); |
| 215 | writeInt(out[8..], @truncate(u32, uu2), Endian.Little); | 215 | writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1)); |
| 216 | writeInt(out[12..], @truncate(u32, uu3), Endian.Little); | 216 | writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2)); |
| 217 | writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3)); | ||
| 217 | 218 | ||
| 218 | ctx.secureZero(); | 219 | ctx.secureZero(); |
| 219 | } | 220 | } |
| ... | @@ -229,5 +230,5 @@ test "poly1305 rfc7439 vector1" { | ... | @@ -229,5 +230,5 @@ test "poly1305 rfc7439 vector1" { |
| 229 | var mac: [16]u8 = undefined; | 230 | var mac: [16]u8 = undefined; |
| 230 | Poly1305.create(mac[0..], msg, key); | 231 | Poly1305.create(mac[0..], msg, key); |
| 231 | 232 | ||
| 232 | std.debug.assert(std.mem.eql(u8, mac, expected_mac)); | 233 | std.testing.expectEqualSlices(u8, expected_mac, mac); |
| 233 | } | 234 | } |
std/crypto/sha1.zig+2-1| ... | @@ -109,7 +109,8 @@ pub const Sha1 = struct { | ... | @@ -109,7 +109,8 @@ pub const Sha1 = struct { |
| 109 | d.round(d.buf[0..]); | 109 | d.round(d.buf[0..]); |
| 110 | 110 | ||
| 111 | for (d.s) |s, j| { | 111 | for (d.s) |s, j| { |
| 112 | mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big); | 112 | // TODO https://github.com/ziglang/zig/issues/863 |
| 113 | mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s); | ||
| 113 | } | 114 | } |
| 114 | } | 115 | } |
| 115 | 116 |
std/crypto/sha2.zig+4-2| ... | @@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type { | ... | @@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type { |
| 167 | const rr = d.s[0 .. params.out_len / 32]; | 167 | const rr = d.s[0 .. params.out_len / 32]; |
| 168 | 168 | ||
| 169 | for (rr) |s, j| { | 169 | for (rr) |s, j| { |
| 170 | mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big); | 170 | // TODO https://github.com/ziglang/zig/issues/863 |
| 171 | mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s); | ||
| 171 | } | 172 | } |
| 172 | } | 173 | } |
| 173 | 174 | ||
| ... | @@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type { | ... | @@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type { |
| 508 | const rr = d.s[0 .. params.out_len / 64]; | 509 | const rr = d.s[0 .. params.out_len / 64]; |
| 509 | 510 | ||
| 510 | for (rr) |s, j| { | 511 | for (rr) |s, j| { |
| 511 | mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big); | 512 | // TODO https://github.com/ziglang/zig/issues/863 |
| 513 | mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s); | ||
| 512 | } | 514 | } |
| 513 | } | 515 | } |
| 514 | 516 |
std/crypto/sha3.zig+3-2| ... | @@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void { | ... | @@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void { |
| 120 | var c = []const u64{0} ** 5; | 120 | var c = []const u64{0} ** 5; |
| 121 | 121 | ||
| 122 | for (s) |*r, i| { | 122 | for (s) |*r, i| { |
| 123 | r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]); | 123 | r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | comptime var x: usize = 0; | 126 | comptime var x: usize = 0; |
| ... | @@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void { | ... | @@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void { |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | for (s) |r, i| { | 169 | for (s) |r, i| { |
| 170 | mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little); | 170 | // TODO https://github.com/ziglang/zig/issues/863 |
| 171 | mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r); | ||
| 171 | } | 172 | } |
| 172 | } | 173 | } |
| 173 | 174 |
std/crypto/test.zig+5-4| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const debug = @import("../debug/index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const mem = @import("../mem.zig"); | 2 | const testing = std.testing; |
| 3 | const fmt = @import("../fmt/index.zig"); | 3 | const mem = std.mem; |
| 4 | const fmt = std.fmt; | ||
| 4 | 5 | ||
| 5 | // Hash using the specified hasher `H` asserting `expected == H(input)`. | 6 | // Hash using the specified hasher `H` asserting `expected == H(input)`. |
| 6 | pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void { | 7 | pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void { |
| ... | @@ -17,5 +18,5 @@ pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { | ... | @@ -17,5 +18,5 @@ pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { |
| 17 | r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; | 18 | r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; |
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | debug.assert(mem.eql(u8, expected_bytes, input)); | 21 | testing.expectEqualSlices(u8, expected_bytes, input); |
| 21 | } | 22 | } |
std/crypto/x25519.zig+33-32| ... | @@ -7,8 +7,8 @@ const builtin = @import("builtin"); | ... | @@ -7,8 +7,8 @@ const builtin = @import("builtin"); |
| 7 | const fmt = std.fmt; | 7 | const fmt = std.fmt; |
| 8 | 8 | ||
| 9 | const Endian = builtin.Endian; | 9 | const Endian = builtin.Endian; |
| 10 | const readInt = std.mem.readInt; | 10 | const readIntSliceLittle = std.mem.readIntSliceLittle; |
| 11 | const writeInt = std.mem.writeInt; | 11 | const writeIntSliceLittle = std.mem.writeIntSliceLittle; |
| 12 | 12 | ||
| 13 | // Based on Supercop's ref10 implementation. | 13 | // Based on Supercop's ref10 implementation. |
| 14 | pub const X25519 = struct { | 14 | pub const X25519 = struct { |
| ... | @@ -255,16 +255,16 @@ const Fe = struct { | ... | @@ -255,16 +255,16 @@ const Fe = struct { |
| 255 | 255 | ||
| 256 | var t: [10]i64 = undefined; | 256 | var t: [10]i64 = undefined; |
| 257 | 257 | ||
| 258 | t[0] = readInt(s[0..4], u32, Endian.Little); | 258 | t[0] = readIntSliceLittle(u32, s[0..4]); |
| 259 | t[1] = readInt(s[4..7], u32, Endian.Little) << 6; | 259 | t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6; |
| 260 | t[2] = readInt(s[7..10], u32, Endian.Little) << 5; | 260 | t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5; |
| 261 | t[3] = readInt(s[10..13], u32, Endian.Little) << 3; | 261 | t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3; |
| 262 | t[4] = readInt(s[13..16], u32, Endian.Little) << 2; | 262 | t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2; |
| 263 | t[5] = readInt(s[16..20], u32, Endian.Little); | 263 | t[5] = readIntSliceLittle(u32, s[16..20]); |
| 264 | t[6] = readInt(s[20..23], u32, Endian.Little) << 7; | 264 | t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7; |
| 265 | t[7] = readInt(s[23..26], u32, Endian.Little) << 5; | 265 | t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5; |
| 266 | t[8] = readInt(s[26..29], u32, Endian.Little) << 4; | 266 | t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4; |
| 267 | t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2; | 267 | t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2; |
| 268 | 268 | ||
| 269 | carry1(h, t[0..]); | 269 | carry1(h, t[0..]); |
| 270 | } | 270 | } |
| ... | @@ -544,14 +544,15 @@ const Fe = struct { | ... | @@ -544,14 +544,15 @@ const Fe = struct { |
| 544 | ut[i] = @bitCast(u32, @intCast(i32, t[i])); | 544 | ut[i] = @bitCast(u32, @intCast(i32, t[i])); |
| 545 | } | 545 | } |
| 546 | 546 | ||
| 547 | writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little); | 547 | // TODO https://github.com/ziglang/zig/issues/863 |
| 548 | writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little); | 548 | writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26)); |
| 549 | writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little); | 549 | writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19)); |
| 550 | writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little); | 550 | writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13)); |
| 551 | writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little); | 551 | writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6)); |
| 552 | writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little); | 552 | writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25)); |
| 553 | writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little); | 553 | writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19)); |
| 554 | writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little); | 554 | writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12)); |
| 555 | writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6)); | ||
| 555 | 556 | ||
| 556 | std.mem.secureZero(i64, t[0..]); | 557 | std.mem.secureZero(i64, t[0..]); |
| 557 | } | 558 | } |
| ... | @@ -580,8 +581,8 @@ test "x25519 public key calculation from secret key" { | ... | @@ -580,8 +581,8 @@ test "x25519 public key calculation from secret key" { |
| 580 | var pk_calculated: [32]u8 = undefined; | 581 | var pk_calculated: [32]u8 = undefined; |
| 581 | try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); | 582 | try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); |
| 582 | try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50"); | 583 | try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50"); |
| 583 | std.debug.assert(X25519.createPublicKey(pk_calculated[0..], sk)); | 584 | std.testing.expect(X25519.createPublicKey(pk_calculated[0..], sk)); |
| 584 | std.debug.assert(std.mem.eql(u8, pk_calculated, pk_expected)); | 585 | std.testing.expect(std.mem.eql(u8, pk_calculated, pk_expected)); |
| 585 | } | 586 | } |
| 586 | 587 | ||
| 587 | test "x25519 rfc7748 vector1" { | 588 | test "x25519 rfc7748 vector1" { |
| ... | @@ -592,8 +593,8 @@ test "x25519 rfc7748 vector1" { | ... | @@ -592,8 +593,8 @@ test "x25519 rfc7748 vector1" { |
| 592 | 593 | ||
| 593 | var output: [32]u8 = undefined; | 594 | var output: [32]u8 = undefined; |
| 594 | 595 | ||
| 595 | std.debug.assert(X25519.create(output[0..], secret_key, public_key)); | 596 | std.testing.expect(X25519.create(output[0..], secret_key, public_key)); |
| 596 | std.debug.assert(std.mem.eql(u8, output, expected_output)); | 597 | std.testing.expect(std.mem.eql(u8, output, expected_output)); |
| 597 | } | 598 | } |
| 598 | 599 | ||
| 599 | test "x25519 rfc7748 vector2" { | 600 | test "x25519 rfc7748 vector2" { |
| ... | @@ -604,8 +605,8 @@ test "x25519 rfc7748 vector2" { | ... | @@ -604,8 +605,8 @@ test "x25519 rfc7748 vector2" { |
| 604 | 605 | ||
| 605 | var output: [32]u8 = undefined; | 606 | var output: [32]u8 = undefined; |
| 606 | 607 | ||
| 607 | std.debug.assert(X25519.create(output[0..], secret_key, public_key)); | 608 | std.testing.expect(X25519.create(output[0..], secret_key, public_key)); |
| 608 | std.debug.assert(std.mem.eql(u8, output, expected_output)); | 609 | std.testing.expect(std.mem.eql(u8, output, expected_output)); |
| 609 | } | 610 | } |
| 610 | 611 | ||
| 611 | test "x25519 rfc7748 one iteration" { | 612 | test "x25519 rfc7748 one iteration" { |
| ... | @@ -618,13 +619,13 @@ test "x25519 rfc7748 one iteration" { | ... | @@ -618,13 +619,13 @@ test "x25519 rfc7748 one iteration" { |
| 618 | var i: usize = 0; | 619 | var i: usize = 0; |
| 619 | while (i < 1) : (i += 1) { | 620 | while (i < 1) : (i += 1) { |
| 620 | var output: [32]u8 = undefined; | 621 | var output: [32]u8 = undefined; |
| 621 | std.debug.assert(X25519.create(output[0..], k, u)); | 622 | std.testing.expect(X25519.create(output[0..], k, u)); |
| 622 | 623 | ||
| 623 | std.mem.copy(u8, u[0..], k[0..]); | 624 | std.mem.copy(u8, u[0..], k[0..]); |
| 624 | std.mem.copy(u8, k[0..], output[0..]); | 625 | std.mem.copy(u8, k[0..], output[0..]); |
| 625 | } | 626 | } |
| 626 | 627 | ||
| 627 | std.debug.assert(std.mem.eql(u8, k[0..], expected_output)); | 628 | std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); |
| 628 | } | 629 | } |
| 629 | 630 | ||
| 630 | test "x25519 rfc7748 1,000 iterations" { | 631 | test "x25519 rfc7748 1,000 iterations" { |
| ... | @@ -642,13 +643,13 @@ test "x25519 rfc7748 1,000 iterations" { | ... | @@ -642,13 +643,13 @@ test "x25519 rfc7748 1,000 iterations" { |
| 642 | var i: usize = 0; | 643 | var i: usize = 0; |
| 643 | while (i < 1000) : (i += 1) { | 644 | while (i < 1000) : (i += 1) { |
| 644 | var output: [32]u8 = undefined; | 645 | var output: [32]u8 = undefined; |
| 645 | std.debug.assert(X25519.create(output[0..], k, u)); | 646 | std.testing.expect(X25519.create(output[0..], k, u)); |
| 646 | 647 | ||
| 647 | std.mem.copy(u8, u[0..], k[0..]); | 648 | std.mem.copy(u8, u[0..], k[0..]); |
| 648 | std.mem.copy(u8, k[0..], output[0..]); | 649 | std.mem.copy(u8, k[0..], output[0..]); |
| 649 | } | 650 | } |
| 650 | 651 | ||
| 651 | std.debug.assert(std.mem.eql(u8, k[0..], expected_output)); | 652 | std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); |
| 652 | } | 653 | } |
| 653 | 654 | ||
| 654 | test "x25519 rfc7748 1,000,000 iterations" { | 655 | test "x25519 rfc7748 1,000,000 iterations" { |
| ... | @@ -665,11 +666,11 @@ test "x25519 rfc7748 1,000,000 iterations" { | ... | @@ -665,11 +666,11 @@ test "x25519 rfc7748 1,000,000 iterations" { |
| 665 | var i: usize = 0; | 666 | var i: usize = 0; |
| 666 | while (i < 1000000) : (i += 1) { | 667 | while (i < 1000000) : (i += 1) { |
| 667 | var output: [32]u8 = undefined; | 668 | var output: [32]u8 = undefined; |
| 668 | std.debug.assert(X25519.create(output[0..], k, u)); | 669 | std.testing.expect(X25519.create(output[0..], k, u)); |
| 669 | 670 | ||
| 670 | std.mem.copy(u8, u[0..], k[0..]); | 671 | std.mem.copy(u8, u[0..], k[0..]); |
| 671 | std.mem.copy(u8, k[0..], output[0..]); | 672 | std.mem.copy(u8, k[0..], output[0..]); |
| 672 | } | 673 | } |
| 673 | 674 | ||
| 674 | std.debug.assert(std.mem.eql(u8, k[0..], expected_output)); | 675 | std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); |
| 675 | } | 676 | } |
std/cstr.zig+3-3| ... | @@ -2,7 +2,7 @@ const std = @import("index.zig"); | ... | @@ -2,7 +2,7 @@ const std = @import("index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 3 | const debug = std.debug; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const assert = debug.assert; | 5 | const testing = std.testing; |
| 6 | 6 | ||
| 7 | pub const line_sep = switch (builtin.os) { | 7 | pub const line_sep = switch (builtin.os) { |
| 8 | builtin.Os.windows => "\r\n", | 8 | builtin.Os.windows => "\r\n", |
| ... | @@ -42,8 +42,8 @@ test "cstr fns" { | ... | @@ -42,8 +42,8 @@ test "cstr fns" { |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | fn testCStrFnsImpl() void { | 44 | fn testCStrFnsImpl() void { |
| 45 | assert(cmp(c"aoeu", c"aoez") == -1); | 45 | testing.expect(cmp(c"aoeu", c"aoez") == -1); |
| 46 | assert(len(c"123456789") == 9); | 46 | testing.expect(len(c"123456789") == 9); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /// Returns a mutable slice with 1 more byte of length which is a null byte. | 49 | /// Returns a mutable slice with 1 more byte of length which is a null byte. |
std/debug/index.zig+96-94| ... | @@ -37,7 +37,6 @@ const Module = struct { | ... | @@ -37,7 +37,6 @@ const Module = struct { |
| 37 | var stderr_file: os.File = undefined; | 37 | var stderr_file: os.File = undefined; |
| 38 | var stderr_file_out_stream: os.File.OutStream = undefined; | 38 | var stderr_file_out_stream: os.File.OutStream = undefined; |
| 39 | 39 | ||
| 40 | /// TODO multithreaded awareness | ||
| 41 | var stderr_stream: ?*io.OutStream(os.File.WriteError) = null; | 40 | var stderr_stream: ?*io.OutStream(os.File.WriteError) = null; |
| 42 | var stderr_mutex = std.Mutex.init(); | 41 | var stderr_mutex = std.Mutex.init(); |
| 43 | pub fn warn(comptime fmt: []const u8, args: ...) void { | 42 | pub fn warn(comptime fmt: []const u8, args: ...) void { |
| ... | @@ -108,37 +107,15 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { | ... | @@ -108,37 +107,15 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { |
| 108 | /// This function invokes undefined behavior when `ok` is `false`. | 107 | /// This function invokes undefined behavior when `ok` is `false`. |
| 109 | /// In Debug and ReleaseSafe modes, calls to this function are always | 108 | /// In Debug and ReleaseSafe modes, calls to this function are always |
| 110 | /// generated, and the `unreachable` statement triggers a panic. | 109 | /// generated, and the `unreachable` statement triggers a panic. |
| 111 | /// In ReleaseFast and ReleaseSmall modes, calls to this function can be | 110 | /// In ReleaseFast and ReleaseSmall modes, calls to this function are |
| 112 | /// optimized away. | 111 | /// optimized away, and in fact the optimizer is able to use the assertion |
| 112 | /// in its heuristics. | ||
| 113 | /// Inside a test block, it is best to use the `std.testing` module rather | ||
| 114 | /// than this function, because this function may not detect a test failure | ||
| 115 | /// in ReleaseFast and ReleaseSafe mode. Outside of a test block, this assert | ||
| 116 | /// function is the correct function to use. | ||
| 113 | pub fn assert(ok: bool) void { | 117 | pub fn assert(ok: bool) void { |
| 114 | if (!ok) { | 118 | if (!ok) unreachable; // assertion failure |
| 115 | // In ReleaseFast test mode, we still want assert(false) to crash, so | ||
| 116 | // we insert an explicit call to @panic instead of unreachable. | ||
| 117 | // TODO we should use `assertOrPanic` in tests and remove this logic. | ||
| 118 | if (builtin.is_test) { | ||
| 119 | @panic("assertion failure"); | ||
| 120 | } else { | ||
| 121 | unreachable; // assertion failure | ||
| 122 | } | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | /// TODO: add `==` operator for `error_union == error_set`, and then | ||
| 127 | /// remove this function | ||
| 128 | pub fn assertError(value: var, expected_error: anyerror) void { | ||
| 129 | if (value) { | ||
| 130 | @panic("expected error"); | ||
| 131 | } else |actual_error| { | ||
| 132 | assert(actual_error == expected_error); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | /// Call this function when you want to panic if the condition is not true. | ||
| 137 | /// If `ok` is `false`, this function will panic in every release mode. | ||
| 138 | pub fn assertOrPanic(ok: bool) void { | ||
| 139 | if (!ok) { | ||
| 140 | @panic("assertion failure"); | ||
| 141 | } | ||
| 142 | } | 119 | } |
| 143 | 120 | ||
| 144 | pub fn panic(comptime format: []const u8, args: ...) noreturn { | 121 | pub fn panic(comptime format: []const u8, args: ...) noreturn { |
| ... | @@ -247,8 +224,7 @@ pub fn writeCurrentStackTraceWindows( | ... | @@ -247,8 +224,7 @@ pub fn writeCurrentStackTraceWindows( |
| 247 | start_addr: ?usize, | 224 | start_addr: ?usize, |
| 248 | ) !void { | 225 | ) !void { |
| 249 | var addr_buf: [1024]usize = undefined; | 226 | var addr_buf: [1024]usize = undefined; |
| 250 | const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast | 227 | const n = windows.RtlCaptureStackBackTrace(0, addr_buf.len, @ptrCast(**c_void, &addr_buf), null); |
| 251 | const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null); | ||
| 252 | const addrs = addr_buf[0..n]; | 228 | const addrs = addr_buf[0..n]; |
| 253 | var start_i: usize = if (start_addr) |saddr| blk: { | 229 | var start_i: usize = if (start_addr) |saddr| blk: { |
| 254 | for (addrs) |addr, i| { | 230 | for (addrs) |addr, i| { |
| ... | @@ -264,7 +240,7 @@ pub fn writeCurrentStackTraceWindows( | ... | @@ -264,7 +240,7 @@ pub fn writeCurrentStackTraceWindows( |
| 264 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { | 240 | pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { |
| 265 | switch (builtin.os) { | 241 | switch (builtin.os) { |
| 266 | builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color), | 242 | builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color), |
| 267 | builtin.Os.linux => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color), | 243 | builtin.Os.linux, builtin.Os.freebsd => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color), |
| 268 | builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color), | 244 | builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color), |
| 269 | else => return error.UnsupportedOperatingSystem, | 245 | else => return error.UnsupportedOperatingSystem, |
| 270 | } | 246 | } |
| ... | @@ -338,50 +314,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres | ... | @@ -338,50 +314,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 338 | 314 | ||
| 339 | switch (subsect_hdr.Kind) { | 315 | switch (subsect_hdr.Kind) { |
| 340 | pdb.DebugSubsectionKind.Lines => { | 316 | pdb.DebugSubsectionKind.Lines => { |
| 341 | var line_index: usize = sect_offset; | 317 | var line_index = sect_offset; |
| 342 | 318 | ||
| 343 | const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]); | 319 | const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]); |
| 344 | if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo; | 320 | if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo; |
| 345 | line_index += @sizeOf(pdb.LineFragmentHeader); | 321 | line_index += @sizeOf(pdb.LineFragmentHeader); |
| 346 | |||
| 347 | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); | ||
| 348 | line_index += @sizeOf(pdb.LineBlockFragmentHeader); | ||
| 349 | |||
| 350 | const has_column = line_hdr.Flags.LF_HaveColumns; | ||
| 351 | |||
| 352 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; | 322 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| 353 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; | 323 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; |
| 354 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { | 324 | |
| 355 | var line_i: usize = 0; | 325 | // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) |
| 326 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, | ||
| 327 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. | ||
| 328 | const subsection_end_index = sect_offset + subsect_hdr.Length; | ||
| 329 | while (line_index < subsection_end_index) { | ||
| 330 | const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]); | ||
| 331 | line_index += @sizeOf(pdb.LineBlockFragmentHeader); | ||
| 356 | const start_line_index = line_index; | 332 | const start_line_index = line_index; |
| 357 | while (line_i < block_hdr.NumLines) : (line_i += 1) { | 333 | |
| 358 | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]); | 334 | const has_column = line_hdr.Flags.LF_HaveColumns; |
| 359 | line_index += @sizeOf(pdb.LineNumberEntry); | 335 | |
| 360 | const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags); | 336 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { |
| 361 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; | 337 | // All line entries are stored inside their line block by ascending start address. |
| 362 | const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End; | 338 | // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address. |
| 363 | if (relative_address >= vaddr_start and relative_address < vaddr_end) { | 339 | // This is done with a simple linear search. |
| 340 | var line_i: u32 = 0; | ||
| 341 | while (line_i < block_hdr.NumLines) : (line_i += 1) { | ||
| 342 | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]); | ||
| 343 | line_index += @sizeOf(pdb.LineNumberEntry); | ||
| 344 | |||
| 345 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; | ||
| 346 | if (relative_address <= vaddr_start) { | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | // line_i == 0 would mean that no matching LineNumberEntry was found. | ||
| 352 | if (line_i > 0) { | ||
| 364 | const subsect_index = checksum_offset + block_hdr.NameIndex; | 353 | const subsect_index = checksum_offset + block_hdr.NameIndex; |
| 365 | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]); | 354 | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]); |
| 366 | const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset; | 355 | const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset; |
| 367 | try di.pdb.string_table.seekTo(strtab_offset); | 356 | try di.pdb.string_table.seekTo(strtab_offset); |
| 368 | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); | 357 | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); |
| 369 | const line = flags.Start; | 358 | |
| 359 | const line_entry_idx = line_i - 1; | ||
| 360 | |||
| 370 | const column = if (has_column) blk: { | 361 | const column = if (has_column) blk: { |
| 371 | line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines; | 362 | const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines; |
| 372 | line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i; | 363 | const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx; |
| 373 | const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]); | 364 | const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]); |
| 374 | break :blk col_num_entry.StartColumn; | 365 | break :blk col_num_entry.StartColumn; |
| 375 | } else 0; | 366 | } else 0; |
| 367 | |||
| 368 | const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry); | ||
| 369 | const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[found_line_index]); | ||
| 370 | const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags); | ||
| 371 | |||
| 376 | break :subsections LineInfo{ | 372 | break :subsections LineInfo{ |
| 377 | .allocator = allocator, | 373 | .allocator = allocator, |
| 378 | .file_name = source_file_name, | 374 | .file_name = source_file_name, |
| 379 | .line = line, | 375 | .line = flags.Start, |
| 380 | .column = column, | 376 | .column = column, |
| 381 | }; | 377 | }; |
| 382 | } | 378 | } |
| 383 | } | 379 | } |
| 384 | break :subsections null; | 380 | } |
| 381 | |||
| 382 | // Checking that we are not reading garbage after the (possibly) multiple block fragments. | ||
| 383 | if (line_index != subsection_end_index) { | ||
| 384 | return error.InvalidDebugInfo; | ||
| 385 | } | 385 | } |
| 386 | }, | 386 | }, |
| 387 | else => {}, | 387 | else => {}, |
| ... | @@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { | ... | @@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 523 | 523 | ||
| 524 | const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo; | 524 | const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo; |
| 525 | 525 | ||
| 526 | const signature = try modi.stream.readIntLe(u32); | 526 | const signature = try modi.stream.readIntLittle(u32); |
| 527 | if (signature != 4) | 527 | if (signature != 4) |
| 528 | return error.InvalidDebugInfo; | 528 | return error.InvalidDebugInfo; |
| 529 | 529 | ||
| ... | @@ -717,7 +717,7 @@ pub const OpenSelfDebugInfoError = error{ | ... | @@ -717,7 +717,7 @@ pub const OpenSelfDebugInfoError = error{ |
| 717 | 717 | ||
| 718 | pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { | 718 | pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { |
| 719 | switch (builtin.os) { | 719 | switch (builtin.os) { |
| 720 | builtin.Os.linux => return openSelfDebugInfoLinux(allocator), | 720 | builtin.Os.linux, builtin.Os.freebsd => return openSelfDebugInfoLinux(allocator), |
| 721 | builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator), | 721 | builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator), |
| 722 | builtin.Os.windows => return openSelfDebugInfoWindows(allocator), | 722 | builtin.Os.windows => return openSelfDebugInfoWindows(allocator), |
| 723 | else => return error.UnsupportedOperatingSystem, | 723 | else => return error.UnsupportedOperatingSystem, |
| ... | @@ -728,7 +728,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -728,7 +728,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 728 | const self_file = try os.openSelfExe(); | 728 | const self_file = try os.openSelfExe(); |
| 729 | defer self_file.close(); | 729 | defer self_file.close(); |
| 730 | 730 | ||
| 731 | const coff_obj = try allocator.createOne(coff.Coff); | 731 | const coff_obj = try allocator.create(coff.Coff); |
| 732 | coff_obj.* = coff.Coff{ | 732 | coff_obj.* = coff.Coff{ |
| 733 | .in_file = self_file, | 733 | .in_file = self_file, |
| 734 | .allocator = allocator, | 734 | .allocator = allocator, |
| ... | @@ -752,14 +752,14 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -752,14 +752,14 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 752 | const len = try di.coff.getPdbPath(path_buf[0..]); | 752 | const len = try di.coff.getPdbPath(path_buf[0..]); |
| 753 | const raw_path = path_buf[0..len]; | 753 | const raw_path = path_buf[0..len]; |
| 754 | 754 | ||
| 755 | const path = try os.path.resolve(allocator, raw_path); | 755 | const path = try os.path.resolve(allocator, [][]const u8{raw_path}); |
| 756 | 756 | ||
| 757 | try di.pdb.openFile(di.coff, path); | 757 | try di.pdb.openFile(di.coff, path); |
| 758 | 758 | ||
| 759 | var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo; | 759 | var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo; |
| 760 | const version = try pdb_stream.stream.readIntLe(u32); | 760 | const version = try pdb_stream.stream.readIntLittle(u32); |
| 761 | const signature = try pdb_stream.stream.readIntLe(u32); | 761 | const signature = try pdb_stream.stream.readIntLittle(u32); |
| 762 | const age = try pdb_stream.stream.readIntLe(u32); | 762 | const age = try pdb_stream.stream.readIntLittle(u32); |
| 763 | var guid: [16]u8 = undefined; | 763 | var guid: [16]u8 = undefined; |
| 764 | try pdb_stream.stream.readNoEof(guid[0..]); | 764 | try pdb_stream.stream.readNoEof(guid[0..]); |
| 765 | if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) | 765 | if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) |
| ... | @@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 767 | // We validated the executable and pdb match. | 767 | // We validated the executable and pdb match. |
| 768 | 768 | ||
| 769 | const string_table_index = str_tab_index: { | 769 | const string_table_index = str_tab_index: { |
| 770 | const name_bytes_len = try pdb_stream.stream.readIntLe(u32); | 770 | const name_bytes_len = try pdb_stream.stream.readIntLittle(u32); |
| 771 | const name_bytes = try allocator.alloc(u8, name_bytes_len); | 771 | const name_bytes = try allocator.alloc(u8, name_bytes_len); |
| 772 | try pdb_stream.stream.readNoEof(name_bytes); | 772 | try pdb_stream.stream.readNoEof(name_bytes); |
| 773 | 773 | ||
| ... | @@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 797 | }; | 797 | }; |
| 798 | const bucket_list = try allocator.alloc(Bucket, present.len); | 798 | const bucket_list = try allocator.alloc(Bucket, present.len); |
| 799 | for (present) |_| { | 799 | for (present) |_| { |
| 800 | const name_offset = try pdb_stream.stream.readIntLe(u32); | 800 | const name_offset = try pdb_stream.stream.readIntLittle(u32); |
| 801 | const name_index = try pdb_stream.stream.readIntLe(u32); | 801 | const name_index = try pdb_stream.stream.readIntLittle(u32); |
| 802 | const name = mem.toSlice(u8, name_bytes.ptr + name_offset); | 802 | const name = mem.toSlice(u8, name_bytes.ptr + name_offset); |
| 803 | if (mem.eql(u8, name, "/names")) { | 803 | if (mem.eql(u8, name, "/names")) { |
| 804 | break :str_tab_index name_index; | 804 | break :str_tab_index name_index; |
| ... | @@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 859 | var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); | 859 | var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); |
| 860 | var sect_cont_offset: usize = 0; | 860 | var sect_cont_offset: usize = 0; |
| 861 | if (section_contrib_size != 0) { | 861 | if (section_contrib_size != 0) { |
| 862 | const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32)); | 862 | const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32)); |
| 863 | if (ver != pdb.SectionContrSubstreamVersion.Ver60) | 863 | if (ver != pdb.SectionContrSubstreamVersion.Ver60) |
| 864 | return error.InvalidDebugInfo; | 864 | return error.InvalidDebugInfo; |
| 865 | sect_cont_offset += @sizeOf(u32); | 865 | sect_cont_offset += @sizeOf(u32); |
| ... | @@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 879 | } | 879 | } |
| 880 | 880 | ||
| 881 | fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { | 881 | fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 882 | const num_words = try stream.readIntLe(u32); | 882 | const num_words = try stream.readIntLittle(u32); |
| 883 | var word_i: usize = 0; | 883 | var word_i: usize = 0; |
| 884 | var list = ArrayList(usize).init(allocator); | 884 | var list = ArrayList(usize).init(allocator); |
| 885 | while (word_i != num_words) : (word_i += 1) { | 885 | while (word_i != num_words) : (word_i += 1) { |
| 886 | const word = try stream.readIntLe(u32); | 886 | const word = try stream.readIntLittle(u32); |
| 887 | var bit_i: u5 = 0; | 887 | var bit_i: u5 = 0; |
| 888 | while (true) : (bit_i += 1) { | 888 | while (true) : (bit_i += 1) { |
| 889 | if (word & (u32(1) << bit_i) != 0) { | 889 | if (word & (u32(1) << bit_i) != 0) { |
| ... | @@ -1013,7 +1013,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -1013,7 +1013,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| 1013 | } | 1013 | } |
| 1014 | } | 1014 | } |
| 1015 | } | 1015 | } |
| 1016 | const sentinel = try allocator.createOne(macho.nlist_64); | 1016 | const sentinel = try allocator.create(macho.nlist_64); |
| 1017 | sentinel.* = macho.nlist_64{ | 1017 | sentinel.* = macho.nlist_64{ |
| 1018 | .n_strx = 0, | 1018 | .n_strx = 0, |
| 1019 | .n_type = 36, | 1019 | .n_type = 36, |
| ... | @@ -1135,14 +1135,13 @@ pub const DebugInfo = switch (builtin.os) { | ... | @@ -1135,14 +1135,13 @@ pub const DebugInfo = switch (builtin.os) { |
| 1135 | return self.ofiles.allocator; | 1135 | return self.ofiles.allocator; |
| 1136 | } | 1136 | } |
| 1137 | }, | 1137 | }, |
| 1138 | builtin.Os.windows => struct { | 1138 | builtin.Os.uefi, builtin.Os.windows => struct { |
| 1139 | pdb: pdb.Pdb, | 1139 | pdb: pdb.Pdb, |
| 1140 | coff: *coff.Coff, | 1140 | coff: *coff.Coff, |
| 1141 | sect_contribs: []pdb.SectionContribEntry, | 1141 | sect_contribs: []pdb.SectionContribEntry, |
| 1142 | modules: []Module, | 1142 | modules: []Module, |
| 1143 | }, | 1143 | }, |
| 1144 | builtin.Os.linux => DwarfInfo, | 1144 | builtin.Os.linux, builtin.Os.freebsd => DwarfInfo, |
| 1145 | builtin.Os.freebsd => struct {}, | ||
| 1146 | else => @compileError("Unsupported OS"), | 1145 | else => @compileError("Unsupported OS"), |
| 1147 | }; | 1146 | }; |
| 1148 | 1147 | ||
| ... | @@ -1200,7 +1199,7 @@ const Constant = struct { | ... | @@ -1200,7 +1199,7 @@ const Constant = struct { |
| 1200 | fn asUnsignedLe(self: *const Constant) !u64 { | 1199 | fn asUnsignedLe(self: *const Constant) !u64 { |
| 1201 | if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; | 1200 | if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; |
| 1202 | if (self.signed) return error.InvalidDebugInfo; | 1201 | if (self.signed) return error.InvalidDebugInfo; |
| 1203 | return mem.readInt(self.payload, u64, builtin.Endian.Little); | 1202 | return mem.readVarInt(u64, self.payload, builtin.Endian.Little); |
| 1204 | } | 1203 | } |
| 1205 | }; | 1204 | }; |
| 1206 | 1205 | ||
| ... | @@ -1331,7 +1330,7 @@ const LineNumberProgram = struct { | ... | @@ -1331,7 +1330,7 @@ const LineNumberProgram = struct { |
| 1331 | return error.InvalidDebugInfo; | 1330 | return error.InvalidDebugInfo; |
| 1332 | } else | 1331 | } else |
| 1333 | self.include_dirs[file_entry.dir_index]; | 1332 | self.include_dirs[file_entry.dir_index]; |
| 1334 | const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); | 1333 | const file_name = try os.path.join(self.file_entries.allocator, [][]const u8{ dir_name, file_entry.file_name }); |
| 1335 | errdefer self.file_entries.allocator.free(file_name); | 1334 | errdefer self.file_entries.allocator.free(file_name); |
| 1336 | return LineInfo{ | 1335 | return LineInfo{ |
| 1337 | .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0, | 1336 | .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0, |
| ... | @@ -1381,7 +1380,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize | ... | @@ -1381,7 +1380,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize |
| 1381 | } | 1380 | } |
| 1382 | 1381 | ||
| 1383 | fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { | 1382 | fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { |
| 1384 | const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size); | 1383 | const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size); |
| 1385 | return parseFormValueBlockLen(allocator, in_stream, block_len); | 1384 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 1386 | } | 1385 | } |
| 1387 | 1386 | ||
| ... | @@ -1395,11 +1394,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo | ... | @@ -1395,11 +1394,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo |
| 1395 | } | 1394 | } |
| 1396 | 1395 | ||
| 1397 | fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { | 1396 | fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { |
| 1398 | return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32)); | 1397 | return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32)); |
| 1399 | } | 1398 | } |
| 1400 | 1399 | ||
| 1401 | fn parseFormValueTargetAddrSize(in_stream: var) !u64 { | 1400 | fn parseFormValueTargetAddrSize(in_stream: var) !u64 { |
| 1402 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable; | 1401 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable; |
| 1403 | } | 1402 | } |
| 1404 | 1403 | ||
| 1405 | fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { | 1404 | fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { |
| ... | @@ -1408,7 +1407,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) | ... | @@ -1408,7 +1407,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) |
| 1408 | } | 1407 | } |
| 1409 | 1408 | ||
| 1410 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { | 1409 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { |
| 1411 | const block_len = try in_stream.readIntLe(T); | 1410 | const block_len = try in_stream.readIntLittle(T); |
| 1412 | return parseFormValueRefLen(allocator, in_stream, block_len); | 1411 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 1413 | } | 1412 | } |
| 1414 | 1413 | ||
| ... | @@ -1450,7 +1449,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 | ... | @@ -1450,7 +1449,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1450 | }, | 1449 | }, |
| 1451 | 1450 | ||
| 1452 | DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, | 1451 | DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 1453 | DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) }, | 1452 | DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) }, |
| 1454 | 1453 | ||
| 1455 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, | 1454 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, |
| 1456 | DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, | 1455 | DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| ... | @@ -1747,11 +1746,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr | ... | @@ -1747,11 +1746,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1747 | continue; | 1746 | continue; |
| 1748 | } | 1747 | } |
| 1749 | 1748 | ||
| 1750 | const version = try di.dwarf_in_stream.readInt(di.endian, u16); | 1749 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1751 | // TODO support 3 and 5 | 1750 | // TODO support 3 and 5 |
| 1752 | if (version != 2 and version != 4) return error.InvalidDebugInfo; | 1751 | if (version != 2 and version != 4) return error.InvalidDebugInfo; |
| 1753 | 1752 | ||
| 1754 | const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32); | 1753 | const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); |
| 1755 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; | 1754 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; |
| 1756 | 1755 | ||
| 1757 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); | 1756 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); |
| ... | @@ -1820,7 +1819,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr | ... | @@ -1820,7 +1819,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1820 | return error.MissingDebugInfo; | 1819 | return error.MissingDebugInfo; |
| 1821 | }, | 1820 | }, |
| 1822 | DW.LNE_set_address => { | 1821 | DW.LNE_set_address => { |
| 1823 | const addr = try di.dwarf_in_stream.readInt(di.endian, usize); | 1822 | const addr = try di.dwarf_in_stream.readInt(usize, di.endian); |
| 1824 | prog.address = addr; | 1823 | prog.address = addr; |
| 1825 | }, | 1824 | }, |
| 1826 | DW.LNE_define_file => { | 1825 | DW.LNE_define_file => { |
| ... | @@ -1882,7 +1881,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr | ... | @@ -1882,7 +1881,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr |
| 1882 | prog.address += inc_addr; | 1881 | prog.address += inc_addr; |
| 1883 | }, | 1882 | }, |
| 1884 | DW.LNS_fixed_advance_pc => { | 1883 | DW.LNS_fixed_advance_pc => { |
| 1885 | const arg = try di.dwarf_in_stream.readInt(di.endian, u16); | 1884 | const arg = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1886 | prog.address += arg; | 1885 | prog.address += arg; |
| 1887 | }, | 1886 | }, |
| 1888 | DW.LNS_set_prologue_end => {}, | 1887 | DW.LNS_set_prologue_end => {}, |
| ... | @@ -1914,10 +1913,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { | ... | @@ -1914,10 +1913,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 1914 | if (unit_length == 0) return; | 1913 | if (unit_length == 0) return; |
| 1915 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 1914 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 1916 | 1915 | ||
| 1917 | const version = try di.dwarf_in_stream.readInt(di.endian, u16); | 1916 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1918 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | 1917 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 1919 | 1918 | ||
| 1920 | const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32); | 1919 | const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); |
| 1921 | 1920 | ||
| 1922 | const address_size = try di.dwarf_in_stream.readByte(); | 1921 | const address_size = try di.dwarf_in_stream.readByte(); |
| 1923 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; | 1922 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| ... | @@ -1927,7 +1926,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { | ... | @@ -1927,7 +1926,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 1927 | 1926 | ||
| 1928 | try di.dwarf_seekable_stream.seekTo(compile_unit_pos); | 1927 | try di.dwarf_seekable_stream.seekTo(compile_unit_pos); |
| 1929 | 1928 | ||
| 1930 | const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64)); | 1929 | const compile_unit_die = try di.allocator().create(Die); |
| 1930 | compile_unit_die.* = try parseDie(di, abbrev_table, is_64); | ||
| 1931 | 1931 | ||
| 1932 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; | 1932 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; |
| 1933 | 1933 | ||
| ... | @@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { | ... | @@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { |
| 1978 | if (di.debug_ranges) |debug_ranges| { | 1978 | if (di.debug_ranges) |debug_ranges| { |
| 1979 | try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); | 1979 | try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); |
| 1980 | while (true) { | 1980 | while (true) { |
| 1981 | const begin_addr = try di.dwarf_in_stream.readIntLe(usize); | 1981 | const begin_addr = try di.dwarf_in_stream.readIntLittle(usize); |
| 1982 | const end_addr = try di.dwarf_in_stream.readIntLe(usize); | 1982 | const end_addr = try di.dwarf_in_stream.readIntLittle(usize); |
| 1983 | if (begin_addr == 0 and end_addr == 0) { | 1983 | if (begin_addr == 0 and end_addr == 0) { |
| 1984 | break; | 1984 | break; |
| 1985 | } | 1985 | } |
| ... | @@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { | ... | @@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { |
| 2001 | } | 2001 | } |
| 2002 | 2002 | ||
| 2003 | fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T { | 2003 | fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T { |
| 2004 | const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian); | 2004 | // TODO https://github.com/ziglang/zig/issues/863 |
| 2005 | const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian); | ||
| 2005 | ptr.* += @sizeOf(T); | 2006 | ptr.* += @sizeOf(T); |
| 2006 | return result; | 2007 | return result; |
| 2007 | } | 2008 | } |
| ... | @@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 { | ... | @@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 { |
| 2017 | } | 2018 | } |
| 2018 | 2019 | ||
| 2019 | fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { | 2020 | fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { |
| 2020 | const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]); | 2021 | // TODO this code can be improved with https://github.com/ziglang/zig/issues/863 |
| 2022 | const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]); | ||
| 2021 | is_64.* = (first_32_bits == 0xffffffff); | 2023 | is_64.* = (first_32_bits == 0xffffffff); |
| 2022 | if (is_64.*) { | 2024 | if (is_64.*) { |
| 2023 | ptr.* += 4; | 2025 | ptr.* += 4; |
| 2024 | const result = mem.readIntLE(u64, ptr.*[0..8]); | 2026 | const result = mem.readIntSliceLittle(u64, ptr.*[0..8]); |
| 2025 | ptr.* += 8; | 2027 | ptr.* += 8; |
| 2026 | return result; | 2028 | return result; |
| 2027 | } else { | 2029 | } else { |
| ... | @@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { | ... | @@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { |
| 2084 | } | 2086 | } |
| 2085 | 2087 | ||
| 2086 | fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 { | 2088 | fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 { |
| 2087 | const first_32_bits = try in_stream.readIntLe(u32); | 2089 | const first_32_bits = try in_stream.readIntLittle(u32); |
| 2088 | is_64.* = (first_32_bits == 0xffffffff); | 2090 | is_64.* = (first_32_bits == 0xffffffff); |
| 2089 | if (is_64.*) { | 2091 | if (is_64.*) { |
| 2090 | return in_stream.readIntLe(u64); | 2092 | return in_stream.readIntLittle(u64); |
| 2091 | } else { | 2093 | } else { |
| 2092 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; | 2094 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; |
| 2093 | return u64(first_32_bits); | 2095 | return u64(first_32_bits); |
std/dynamic_library.zig+3-4| ... | @@ -6,6 +6,7 @@ const mem = std.mem; | ... | @@ -6,6 +6,7 @@ const mem = std.mem; |
| 6 | const cstr = std.cstr; | 6 | const cstr = std.cstr; |
| 7 | const os = std.os; | 7 | const os = std.os; |
| 8 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
| 9 | const testing = std.testing; | ||
| 9 | const elf = std.elf; | 10 | const elf = std.elf; |
| 10 | const linux = os.linux; | 11 | const linux = os.linux; |
| 11 | const windows = os.windows; | 12 | const windows = os.windows; |
| ... | @@ -19,7 +20,6 @@ pub const DynLib = switch (builtin.os) { | ... | @@ -19,7 +20,6 @@ pub const DynLib = switch (builtin.os) { |
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 21 | pub const LinuxDynLib = struct { | 22 | pub const LinuxDynLib = struct { |
| 22 | allocator: *mem.Allocator, | ||
| 23 | elf_lib: ElfLib, | 23 | elf_lib: ElfLib, |
| 24 | fd: i32, | 24 | fd: i32, |
| 25 | map_addr: usize, | 25 | map_addr: usize, |
| ... | @@ -27,7 +27,7 @@ pub const LinuxDynLib = struct { | ... | @@ -27,7 +27,7 @@ pub const LinuxDynLib = struct { |
| 27 | 27 | ||
| 28 | /// Trusts the file | 28 | /// Trusts the file |
| 29 | pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib { | 29 | pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib { |
| 30 | const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC); | 30 | const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC); |
| 31 | errdefer std.os.close(fd); | 31 | errdefer std.os.close(fd); |
| 32 | 32 | ||
| 33 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); | 33 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); |
| ... | @@ -45,7 +45,6 @@ pub const LinuxDynLib = struct { | ... | @@ -45,7 +45,6 @@ pub const LinuxDynLib = struct { |
| 45 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; | 45 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; |
| 46 | 46 | ||
| 47 | return DynLib{ | 47 | return DynLib{ |
| 48 | .allocator = allocator, | ||
| 49 | .elf_lib = try ElfLib.init(bytes), | 48 | .elf_lib = try ElfLib.init(bytes), |
| 50 | .fd = fd, | 49 | .fd = fd, |
| 51 | .map_addr = addr, | 50 | .map_addr = addr, |
| ... | @@ -208,7 +207,7 @@ test "dynamic_library" { | ... | @@ -208,7 +207,7 @@ test "dynamic_library" { |
| 208 | }; | 207 | }; |
| 209 | 208 | ||
| 210 | const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| { | 209 | const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| { |
| 211 | assert(err == error.FileNotFound); | 210 | testing.expect(err == error.FileNotFound); |
| 212 | return; | 211 | return; |
| 213 | }; | 212 | }; |
| 214 | @panic("Expected error from function"); | 213 | @panic("Expected error from function"); |
std/elf.zig+35-35| ... | @@ -412,7 +412,7 @@ pub const Elf = struct { | ... | @@ -412,7 +412,7 @@ pub const Elf = struct { |
| 412 | // skip over padding | 412 | // skip over padding |
| 413 | try seekable_stream.seekForward(9); | 413 | try seekable_stream.seekForward(9); |
| 414 | 414 | ||
| 415 | elf.file_type = switch (try in.readInt(elf.endian, u16)) { | 415 | elf.file_type = switch (try in.readInt(u16, elf.endian)) { |
| 416 | 1 => FileType.Relocatable, | 416 | 1 => FileType.Relocatable, |
| 417 | 2 => FileType.Executable, | 417 | 2 => FileType.Executable, |
| 418 | 3 => FileType.Shared, | 418 | 3 => FileType.Shared, |
| ... | @@ -420,7 +420,7 @@ pub const Elf = struct { | ... | @@ -420,7 +420,7 @@ pub const Elf = struct { |
| 420 | else => return error.InvalidFormat, | 420 | else => return error.InvalidFormat, |
| 421 | }; | 421 | }; |
| 422 | 422 | ||
| 423 | elf.arch = switch (try in.readInt(elf.endian, u16)) { | 423 | elf.arch = switch (try in.readInt(u16, elf.endian)) { |
| 424 | 0x02 => Arch.Sparc, | 424 | 0x02 => Arch.Sparc, |
| 425 | 0x03 => Arch.x86, | 425 | 0x03 => Arch.x86, |
| 426 | 0x08 => Arch.Mips, | 426 | 0x08 => Arch.Mips, |
| ... | @@ -433,32 +433,32 @@ pub const Elf = struct { | ... | @@ -433,32 +433,32 @@ pub const Elf = struct { |
| 433 | else => return error.InvalidFormat, | 433 | else => return error.InvalidFormat, |
| 434 | }; | 434 | }; |
| 435 | 435 | ||
| 436 | const elf_version = try in.readInt(elf.endian, u32); | 436 | const elf_version = try in.readInt(u32, elf.endian); |
| 437 | if (elf_version != 1) return error.InvalidFormat; | 437 | if (elf_version != 1) return error.InvalidFormat; |
| 438 | 438 | ||
| 439 | if (elf.is_64) { | 439 | if (elf.is_64) { |
| 440 | elf.entry_addr = try in.readInt(elf.endian, u64); | 440 | elf.entry_addr = try in.readInt(u64, elf.endian); |
| 441 | elf.program_header_offset = try in.readInt(elf.endian, u64); | 441 | elf.program_header_offset = try in.readInt(u64, elf.endian); |
| 442 | elf.section_header_offset = try in.readInt(elf.endian, u64); | 442 | elf.section_header_offset = try in.readInt(u64, elf.endian); |
| 443 | } else { | 443 | } else { |
| 444 | elf.entry_addr = u64(try in.readInt(elf.endian, u32)); | 444 | elf.entry_addr = u64(try in.readInt(u32, elf.endian)); |
| 445 | elf.program_header_offset = u64(try in.readInt(elf.endian, u32)); | 445 | elf.program_header_offset = u64(try in.readInt(u32, elf.endian)); |
| 446 | elf.section_header_offset = u64(try in.readInt(elf.endian, u32)); | 446 | elf.section_header_offset = u64(try in.readInt(u32, elf.endian)); |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | // skip over flags | 449 | // skip over flags |
| 450 | try seekable_stream.seekForward(4); | 450 | try seekable_stream.seekForward(4); |
| 451 | 451 | ||
| 452 | const header_size = try in.readInt(elf.endian, u16); | 452 | const header_size = try in.readInt(u16, elf.endian); |
| 453 | if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { | 453 | if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { |
| 454 | return error.InvalidFormat; | 454 | return error.InvalidFormat; |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | const ph_entry_size = try in.readInt(elf.endian, u16); | 457 | const ph_entry_size = try in.readInt(u16, elf.endian); |
| 458 | const ph_entry_count = try in.readInt(elf.endian, u16); | 458 | const ph_entry_count = try in.readInt(u16, elf.endian); |
| 459 | const sh_entry_size = try in.readInt(elf.endian, u16); | 459 | const sh_entry_size = try in.readInt(u16, elf.endian); |
| 460 | const sh_entry_count = try in.readInt(elf.endian, u16); | 460 | const sh_entry_count = try in.readInt(u16, elf.endian); |
| 461 | elf.string_section_index = u64(try in.readInt(elf.endian, u16)); | 461 | elf.string_section_index = u64(try in.readInt(u16, elf.endian)); |
| 462 | 462 | ||
| 463 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; | 463 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; |
| 464 | 464 | ||
| ... | @@ -481,32 +481,32 @@ pub const Elf = struct { | ... | @@ -481,32 +481,32 @@ pub const Elf = struct { |
| 481 | if (sh_entry_size != 64) return error.InvalidFormat; | 481 | if (sh_entry_size != 64) return error.InvalidFormat; |
| 482 | 482 | ||
| 483 | for (elf.section_headers) |*elf_section| { | 483 | for (elf.section_headers) |*elf_section| { |
| 484 | elf_section.name = try in.readInt(elf.endian, u32); | 484 | elf_section.name = try in.readInt(u32, elf.endian); |
| 485 | elf_section.sh_type = try in.readInt(elf.endian, u32); | 485 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 486 | elf_section.flags = try in.readInt(elf.endian, u64); | 486 | elf_section.flags = try in.readInt(u64, elf.endian); |
| 487 | elf_section.addr = try in.readInt(elf.endian, u64); | 487 | elf_section.addr = try in.readInt(u64, elf.endian); |
| 488 | elf_section.offset = try in.readInt(elf.endian, u64); | 488 | elf_section.offset = try in.readInt(u64, elf.endian); |
| 489 | elf_section.size = try in.readInt(elf.endian, u64); | 489 | elf_section.size = try in.readInt(u64, elf.endian); |
| 490 | elf_section.link = try in.readInt(elf.endian, u32); | 490 | elf_section.link = try in.readInt(u32, elf.endian); |
| 491 | elf_section.info = try in.readInt(elf.endian, u32); | 491 | elf_section.info = try in.readInt(u32, elf.endian); |
| 492 | elf_section.addr_align = try in.readInt(elf.endian, u64); | 492 | elf_section.addr_align = try in.readInt(u64, elf.endian); |
| 493 | elf_section.ent_size = try in.readInt(elf.endian, u64); | 493 | elf_section.ent_size = try in.readInt(u64, elf.endian); |
| 494 | } | 494 | } |
| 495 | } else { | 495 | } else { |
| 496 | if (sh_entry_size != 40) return error.InvalidFormat; | 496 | if (sh_entry_size != 40) return error.InvalidFormat; |
| 497 | 497 | ||
| 498 | for (elf.section_headers) |*elf_section| { | 498 | for (elf.section_headers) |*elf_section| { |
| 499 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? | 499 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? |
| 500 | elf_section.name = try in.readInt(elf.endian, u32); | 500 | elf_section.name = try in.readInt(u32, elf.endian); |
| 501 | elf_section.sh_type = try in.readInt(elf.endian, u32); | 501 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 502 | elf_section.flags = u64(try in.readInt(elf.endian, u32)); | 502 | elf_section.flags = u64(try in.readInt(u32, elf.endian)); |
| 503 | elf_section.addr = u64(try in.readInt(elf.endian, u32)); | 503 | elf_section.addr = u64(try in.readInt(u32, elf.endian)); |
| 504 | elf_section.offset = u64(try in.readInt(elf.endian, u32)); | 504 | elf_section.offset = u64(try in.readInt(u32, elf.endian)); |
| 505 | elf_section.size = u64(try in.readInt(elf.endian, u32)); | 505 | elf_section.size = u64(try in.readInt(u32, elf.endian)); |
| 506 | elf_section.link = try in.readInt(elf.endian, u32); | 506 | elf_section.link = try in.readInt(u32, elf.endian); |
| 507 | elf_section.info = try in.readInt(elf.endian, u32); | 507 | elf_section.info = try in.readInt(u32, elf.endian); |
| 508 | elf_section.addr_align = u64(try in.readInt(elf.endian, u32)); | 508 | elf_section.addr_align = u64(try in.readInt(u32, elf.endian)); |
| 509 | elf_section.ent_size = u64(try in.readInt(elf.endian, u32)); | 509 | elf_section.ent_size = u64(try in.readInt(u32, elf.endian)); |
| 510 | } | 510 | } |
| 511 | } | 511 | } |
| 512 | 512 |
std/event/channel.zig+11-6| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | const AtomicOrder = builtin.AtomicOrder; | 6 | const AtomicOrder = builtin.AtomicOrder; |
| 6 | const Loop = std.event.Loop; | 7 | const Loop = std.event.Loop; |
| ... | @@ -54,7 +55,8 @@ pub fn Channel(comptime T: type) type { | ... | @@ -54,7 +55,8 @@ pub fn Channel(comptime T: type) type { |
| 54 | const buffer_nodes = try loop.allocator.alloc(T, capacity); | 55 | const buffer_nodes = try loop.allocator.alloc(T, capacity); |
| 55 | errdefer loop.allocator.free(buffer_nodes); | 56 | errdefer loop.allocator.free(buffer_nodes); |
| 56 | 57 | ||
| 57 | const self = try loop.allocator.create(SelfChannel{ | 58 | const self = try loop.allocator.create(SelfChannel); |
| 59 | self.* = SelfChannel{ | ||
| 58 | .loop = loop, | 60 | .loop = loop, |
| 59 | .buffer_len = 0, | 61 | .buffer_len = 0, |
| 60 | .buffer_nodes = buffer_nodes, | 62 | .buffer_nodes = buffer_nodes, |
| ... | @@ -66,7 +68,7 @@ pub fn Channel(comptime T: type) type { | ... | @@ -66,7 +68,7 @@ pub fn Channel(comptime T: type) type { |
| 66 | .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(), | 68 | .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(), |
| 67 | .get_count = 0, | 69 | .get_count = 0, |
| 68 | .put_count = 0, | 70 | .put_count = 0, |
| 69 | }); | 71 | }; |
| 70 | errdefer loop.allocator.destroy(self); | 72 | errdefer loop.allocator.destroy(self); |
| 71 | 73 | ||
| 72 | return self; | 74 | return self; |
| ... | @@ -319,6 +321,9 @@ pub fn Channel(comptime T: type) type { | ... | @@ -319,6 +321,9 @@ pub fn Channel(comptime T: type) type { |
| 319 | } | 321 | } |
| 320 | 322 | ||
| 321 | test "std.event.Channel" { | 323 | test "std.event.Channel" { |
| 324 | // https://github.com/ziglang/zig/issues/1908 | ||
| 325 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 326 | |||
| 322 | var da = std.heap.DirectAllocator.init(); | 327 | var da = std.heap.DirectAllocator.init(); |
| 323 | defer da.deinit(); | 328 | defer da.deinit(); |
| 324 | 329 | ||
| ... | @@ -346,19 +351,19 @@ async fn testChannelGetter(loop: *Loop, channel: *Channel(i32)) void { | ... | @@ -346,19 +351,19 @@ async fn testChannelGetter(loop: *Loop, channel: *Channel(i32)) void { |
| 346 | 351 | ||
| 347 | const value1_promise = try async channel.get(); | 352 | const value1_promise = try async channel.get(); |
| 348 | const value1 = await value1_promise; | 353 | const value1 = await value1_promise; |
| 349 | assert(value1 == 1234); | 354 | testing.expect(value1 == 1234); |
| 350 | 355 | ||
| 351 | const value2_promise = try async channel.get(); | 356 | const value2_promise = try async channel.get(); |
| 352 | const value2 = await value2_promise; | 357 | const value2 = await value2_promise; |
| 353 | assert(value2 == 4567); | 358 | testing.expect(value2 == 4567); |
| 354 | 359 | ||
| 355 | const value3_promise = try async channel.getOrNull(); | 360 | const value3_promise = try async channel.getOrNull(); |
| 356 | const value3 = await value3_promise; | 361 | const value3 = await value3_promise; |
| 357 | assert(value3 == null); | 362 | testing.expect(value3 == null); |
| 358 | 363 | ||
| 359 | const last_put = try async testPut(channel, 4444); | 364 | const last_put = try async testPut(channel, 4444); |
| 360 | const value4 = await try async channel.getOrNull(); | 365 | const value4 = await try async channel.getOrNull(); |
| 361 | assert(value4.? == 4444); | 366 | testing.expect(value4.? == 4444); |
| 362 | await last_put; | 367 | await last_put; |
| 363 | } | 368 | } |
| 364 | 369 |
std/event/fs.zig+34-36| ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | const std = @import("../index.zig"); | 2 | const std = @import("../index.zig"); |
| 3 | const event = std.event; | 3 | const event = std.event; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const testing = std.testing; | ||
| 5 | const os = std.os; | 6 | const os = std.os; |
| 6 | const mem = std.mem; | 7 | const mem = std.mem; |
| 7 | const posix = os.posix; | 8 | const posix = os.posix; |
| ... | @@ -495,7 +496,7 @@ pub const CloseOperation = struct { | ... | @@ -495,7 +496,7 @@ pub const CloseOperation = struct { |
| 495 | }; | 496 | }; |
| 496 | 497 | ||
| 497 | pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) { | 498 | pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) { |
| 498 | const self = try loop.allocator.createOne(CloseOperation); | 499 | const self = try loop.allocator.create(CloseOperation); |
| 499 | self.* = CloseOperation{ | 500 | self.* = CloseOperation{ |
| 500 | .loop = loop, | 501 | .loop = loop, |
| 501 | .os_data = switch (builtin.os) { | 502 | .os_data = switch (builtin.os) { |
| ... | @@ -787,7 +788,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -787,7 +788,7 @@ pub fn Watch(comptime V: type) type { |
| 787 | }, | 788 | }, |
| 788 | 789 | ||
| 789 | builtin.Os.windows => { | 790 | builtin.Os.windows => { |
| 790 | const self = try loop.allocator.createOne(Self); | 791 | const self = try loop.allocator.create(Self); |
| 791 | errdefer loop.allocator.destroy(self); | 792 | errdefer loop.allocator.destroy(self); |
| 792 | self.* = Self{ | 793 | self.* = Self{ |
| 793 | .channel = channel, | 794 | .channel = channel, |
| ... | @@ -802,7 +803,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -802,7 +803,7 @@ pub fn Watch(comptime V: type) type { |
| 802 | }, | 803 | }, |
| 803 | 804 | ||
| 804 | builtin.Os.macosx, builtin.Os.freebsd => { | 805 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 805 | const self = try loop.allocator.createOne(Self); | 806 | const self = try loop.allocator.create(Self); |
| 806 | errdefer loop.allocator.destroy(self); | 807 | errdefer loop.allocator.destroy(self); |
| 807 | 808 | ||
| 808 | self.* = Self{ | 809 | self.* = Self{ |
| ... | @@ -871,7 +872,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -871,7 +872,7 @@ pub fn Watch(comptime V: type) type { |
| 871 | } | 872 | } |
| 872 | 873 | ||
| 873 | async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V { | 874 | async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V { |
| 874 | const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path); | 875 | const resolved_path = try os.path.resolve(self.channel.loop.allocator, [][]const u8{file_path}); |
| 875 | var resolved_path_consumed = false; | 876 | var resolved_path_consumed = false; |
| 876 | defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path); | 877 | defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path); |
| 877 | 878 | ||
| ... | @@ -1068,7 +1069,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -1068,7 +1069,7 @@ pub fn Watch(comptime V: type) type { |
| 1068 | } | 1069 | } |
| 1069 | } else { | 1070 | } else { |
| 1070 | errdefer _ = self.os_data.dir_table.remove(dirname); | 1071 | errdefer _ = self.os_data.dir_table.remove(dirname); |
| 1071 | const dir = try self.channel.loop.allocator.createOne(OsData.Dir); | 1072 | const dir = try self.channel.loop.allocator.create(OsData.Dir); |
| 1072 | errdefer self.channel.loop.allocator.destroy(dir); | 1073 | errdefer self.channel.loop.allocator.destroy(dir); |
| 1073 | 1074 | ||
| 1074 | dir.* = OsData.Dir{ | 1075 | dir.* = OsData.Dir{ |
| ... | @@ -1307,39 +1308,36 @@ pub fn Watch(comptime V: type) type { | ... | @@ -1307,39 +1308,36 @@ pub fn Watch(comptime V: type) type { |
| 1307 | 1308 | ||
| 1308 | const test_tmp_dir = "std_event_fs_test"; | 1309 | const test_tmp_dir = "std_event_fs_test"; |
| 1309 | 1310 | ||
| 1310 | test "write a file, watch it, write it again" { | 1311 | // TODO this test is disabled until the coroutine rewrite is finished. |
| 1311 | if (builtin.os == builtin.Os.windows) { | 1312 | //test "write a file, watch it, write it again" { |
| 1312 | // TODO this test is disabled on windows until the coroutine rewrite is finished. | 1313 | // return error.SkipZigTest; |
| 1313 | // https://github.com/ziglang/zig/issues/1363 | 1314 | // var da = std.heap.DirectAllocator.init(); |
| 1314 | return error.SkipZigTest; | 1315 | // defer da.deinit(); |
| 1315 | } | 1316 | // |
| 1316 | var da = std.heap.DirectAllocator.init(); | 1317 | // const allocator = &da.allocator; |
| 1317 | defer da.deinit(); | 1318 | // |
| 1318 | 1319 | // // TODO move this into event loop too | |
| 1319 | const allocator = &da.allocator; | 1320 | // try os.makePath(allocator, test_tmp_dir); |
| 1320 | 1321 | // defer os.deleteTree(allocator, test_tmp_dir) catch {}; | |
| 1321 | // TODO move this into event loop too | 1322 | // |
| 1322 | try os.makePath(allocator, test_tmp_dir); | 1323 | // var loop: Loop = undefined; |
| 1323 | defer os.deleteTree(allocator, test_tmp_dir) catch {}; | 1324 | // try loop.initMultiThreaded(allocator); |
| 1324 | 1325 | // defer loop.deinit(); | |
| 1325 | var loop: Loop = undefined; | 1326 | // |
| 1326 | try loop.initMultiThreaded(allocator); | 1327 | // var result: anyerror!void = error.ResultNeverWritten; |
| 1327 | defer loop.deinit(); | 1328 | // const handle = try async<allocator> testFsWatchCantFail(&loop, &result); |
| 1328 | 1329 | // defer cancel handle; | |
| 1329 | var result: anyerror!void = error.ResultNeverWritten; | 1330 | // |
| 1330 | const handle = try async<allocator> testFsWatchCantFail(&loop, &result); | 1331 | // loop.run(); |
| 1331 | defer cancel handle; | 1332 | // return result; |
| 1332 | 1333 | //} | |
| 1333 | loop.run(); | ||
| 1334 | return result; | ||
| 1335 | } | ||
| 1336 | 1334 | ||
| 1337 | async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void { | 1335 | async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void { |
| 1338 | result.* = await (async testFsWatch(loop) catch unreachable); | 1336 | result.* = await (async testFsWatch(loop) catch unreachable); |
| 1339 | } | 1337 | } |
| 1340 | 1338 | ||
| 1341 | async fn testFsWatch(loop: *Loop) !void { | 1339 | async fn testFsWatch(loop: *Loop) !void { |
| 1342 | const file_path = try os.path.join(loop.allocator, test_tmp_dir, "file.txt"); | 1340 | const file_path = try os.path.join(loop.allocator, [][]const u8{ test_tmp_dir, "file.txt" }); |
| 1343 | defer loop.allocator.free(file_path); | 1341 | defer loop.allocator.free(file_path); |
| 1344 | 1342 | ||
| 1345 | const contents = | 1343 | const contents = |
| ... | @@ -1352,13 +1350,13 @@ async fn testFsWatch(loop: *Loop) !void { | ... | @@ -1352,13 +1350,13 @@ async fn testFsWatch(loop: *Loop) !void { |
| 1352 | try await try async writeFile(loop, file_path, contents); | 1350 | try await try async writeFile(loop, file_path, contents); |
| 1353 | 1351 | ||
| 1354 | const read_contents = try await try async readFile(loop, file_path, 1024 * 1024); | 1352 | const read_contents = try await try async readFile(loop, file_path, 1024 * 1024); |
| 1355 | assert(mem.eql(u8, read_contents, contents)); | 1353 | testing.expectEqualSlices(u8, contents, read_contents); |
| 1356 | 1354 | ||
| 1357 | // now watch the file | 1355 | // now watch the file |
| 1358 | var watch = try Watch(void).create(loop, 0); | 1356 | var watch = try Watch(void).create(loop, 0); |
| 1359 | defer watch.destroy(); | 1357 | defer watch.destroy(); |
| 1360 | 1358 | ||
| 1361 | assert((try await try async watch.addFile(file_path, {})) == null); | 1359 | testing.expect((try await try async watch.addFile(file_path, {})) == null); |
| 1362 | 1360 | ||
| 1363 | const ev = try async watch.channel.get(); | 1361 | const ev = try async watch.channel.get(); |
| 1364 | var ev_consumed = false; | 1362 | var ev_consumed = false; |
| ... | @@ -1378,10 +1376,10 @@ async fn testFsWatch(loop: *Loop) !void { | ... | @@ -1378,10 +1376,10 @@ async fn testFsWatch(loop: *Loop) !void { |
| 1378 | WatchEventId.Delete => @panic("wrong event"), | 1376 | WatchEventId.Delete => @panic("wrong event"), |
| 1379 | } | 1377 | } |
| 1380 | const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024); | 1378 | const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024); |
| 1381 | assert(mem.eql(u8, contents_updated, | 1379 | testing.expectEqualSlices(u8, |
| 1382 | \\line 1 | 1380 | \\line 1 |
| 1383 | \\lorem ipsum | 1381 | \\lorem ipsum |
| 1384 | )); | 1382 | , contents_updated); |
| 1385 | 1383 | ||
| 1386 | // TODO test deleting the file and then re-adding it. we should get events for both | 1384 | // TODO test deleting the file and then re-adding it. we should get events for both |
| 1387 | } | 1385 | } |
std/event/future.zig+5-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | ||
| 3 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | const AtomicOrder = builtin.AtomicOrder; | 6 | const AtomicOrder = builtin.AtomicOrder; |
| ... | @@ -84,6 +85,9 @@ pub fn Future(comptime T: type) type { | ... | @@ -84,6 +85,9 @@ pub fn Future(comptime T: type) type { |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | test "std.event.Future" { | 87 | test "std.event.Future" { |
| 88 | // https://github.com/ziglang/zig/issues/1908 | ||
| 89 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 90 | |||
| 87 | var da = std.heap.DirectAllocator.init(); | 91 | var da = std.heap.DirectAllocator.init(); |
| 88 | defer da.deinit(); | 92 | defer da.deinit(); |
| 89 | 93 | ||
| ... | @@ -111,7 +115,7 @@ async fn testFuture(loop: *Loop) void { | ... | @@ -111,7 +115,7 @@ async fn testFuture(loop: *Loop) void { |
| 111 | 115 | ||
| 112 | const result = (await a) + (await b); | 116 | const result = (await a) + (await b); |
| 113 | cancel c; | 117 | cancel c; |
| 114 | assert(result == 12); | 118 | testing.expect(result == 12); |
| 115 | } | 119 | } |
| 116 | 120 | ||
| 117 | async fn waitOnFuture(future: *Future(i32)) i32 { | 121 | async fn waitOnFuture(future: *Future(i32)) i32 { |
std/event/group.zig+9-5| ... | @@ -4,7 +4,7 @@ const Lock = std.event.Lock; | ... | @@ -4,7 +4,7 @@ const Lock = std.event.Lock; |
| 4 | const Loop = std.event.Loop; | 4 | const Loop = std.event.Loop; |
| 5 | const AtomicRmwOp = builtin.AtomicRmwOp; | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 6 | const AtomicOrder = builtin.AtomicOrder; | 6 | const AtomicOrder = builtin.AtomicOrder; |
| 7 | const assert = std.debug.assert; | 7 | const testing = std.testing; |
| 8 | 8 | ||
| 9 | /// ReturnType must be `void` or `E!void` | 9 | /// ReturnType must be `void` or `E!void` |
| 10 | pub fn Group(comptime ReturnType: type) type { | 10 | pub fn Group(comptime ReturnType: type) type { |
| ... | @@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type { | ... | @@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type { |
| 42 | 42 | ||
| 43 | /// Add a promise to the group. Thread-safe. | 43 | /// Add a promise to the group. Thread-safe. |
| 44 | pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) { | 44 | pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) { |
| 45 | const node = try self.lock.loop.allocator.create(Stack.Node{ | 45 | const node = try self.lock.loop.allocator.create(Stack.Node); |
| 46 | node.* = Stack.Node{ | ||
| 46 | .next = undefined, | 47 | .next = undefined, |
| 47 | .data = handle, | 48 | .data = handle, |
| 48 | }); | 49 | }; |
| 49 | self.alloc_stack.push(node); | 50 | self.alloc_stack.push(node); |
| 50 | } | 51 | } |
| 51 | 52 | ||
| ... | @@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type { | ... | @@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type { |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 123 | test "std.event.Group" { | 124 | test "std.event.Group" { |
| 125 | // https://github.com/ziglang/zig/issues/1908 | ||
| 126 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 127 | |||
| 124 | var da = std.heap.DirectAllocator.init(); | 128 | var da = std.heap.DirectAllocator.init(); |
| 125 | defer da.deinit(); | 129 | defer da.deinit(); |
| 126 | 130 | ||
| ... | @@ -142,12 +146,12 @@ async fn testGroup(loop: *Loop) void { | ... | @@ -142,12 +146,12 @@ async fn testGroup(loop: *Loop) void { |
| 142 | group.add(async sleepALittle(&count) catch @panic("memory")) catch @panic("memory"); | 146 | group.add(async sleepALittle(&count) catch @panic("memory")) catch @panic("memory"); |
| 143 | group.call(increaseByTen, &count) catch @panic("memory"); | 147 | group.call(increaseByTen, &count) catch @panic("memory"); |
| 144 | await (async group.wait() catch @panic("memory")); | 148 | await (async group.wait() catch @panic("memory")); |
| 145 | assert(count == 11); | 149 | testing.expect(count == 11); |
| 146 | 150 | ||
| 147 | var another = Group(anyerror!void).init(loop); | 151 | var another = Group(anyerror!void).init(loop); |
| 148 | another.add(async somethingElse() catch @panic("memory")) catch @panic("memory"); | 152 | another.add(async somethingElse() catch @panic("memory")) catch @panic("memory"); |
| 149 | another.call(doSomethingThatFails) catch @panic("memory"); | 153 | another.call(doSomethingThatFails) catch @panic("memory"); |
| 150 | std.debug.assertError(await (async another.wait() catch @panic("memory")), error.ItBroke); | 154 | testing.expectError(error.ItBroke, await (async another.wait() catch @panic("memory"))); |
| 151 | } | 155 | } |
| 152 | 156 | ||
| 153 | async fn sleepALittle(count: *usize) void { | 157 | async fn sleepALittle(count: *usize) void { |
std/event/io.zig+9-5| ... | @@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type { |
| 39 | if (amt_read < buf.len) return error.EndOfStream; | 39 | if (amt_read < buf.len) return error.EndOfStream; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | pub async fn readIntLe(self: *Self, comptime T: type) !T { | 42 | pub async fn readIntLittle(self: *Self, comptime T: type) !T { |
| 43 | return await (async self.readInt(builtin.Endian.Little, T) catch unreachable); | 43 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 44 | try await (async self.readNoEof(bytes[0..]) catch unreachable); | ||
| 45 | return mem.readIntLittle(T, &bytes); | ||
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | pub async fn readIntBe(self: *Self, comptime T: type) !T { | 48 | pub async fn readIntBe(self: *Self, comptime T: type) !T { |
| 47 | return await (async self.readInt(builtin.Endian.Big, T) catch unreachable); | 49 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 50 | try await (async self.readNoEof(bytes[0..]) catch unreachable); | ||
| 51 | return mem.readIntBig(T, &bytes); | ||
| 48 | } | 52 | } |
| 49 | 53 | ||
| 50 | pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T { | 54 | pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { |
| 51 | var bytes: [@sizeOf(T)]u8 = undefined; | 55 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 52 | try await (async self.readNoEof(bytes[0..]) catch unreachable); | 56 | try await (async self.readNoEof(bytes[0..]) catch unreachable); |
| 53 | return mem.readInt(bytes, T, endian); | 57 | return mem.readInt(T, &bytes, endian); |
| 54 | } | 58 | } |
| 55 | 59 | ||
| 56 | pub async fn readStruct(self: *Self, comptime T: type) !T { | 60 | pub async fn readStruct(self: *Self, comptime T: type) !T { |
std/event/lock.zig+5-1| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const AtomicRmwOp = builtin.AtomicRmwOp; | 6 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 6 | const AtomicOrder = builtin.AtomicOrder; | 7 | const AtomicOrder = builtin.AtomicOrder; |
| ... | @@ -122,6 +123,9 @@ pub const Lock = struct { | ... | @@ -122,6 +123,9 @@ pub const Lock = struct { |
| 122 | }; | 123 | }; |
| 123 | 124 | ||
| 124 | test "std.event.Lock" { | 125 | test "std.event.Lock" { |
| 126 | // https://github.com/ziglang/zig/issues/1908 | ||
| 127 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 128 | |||
| 125 | var da = std.heap.DirectAllocator.init(); | 129 | var da = std.heap.DirectAllocator.init(); |
| 126 | defer da.deinit(); | 130 | defer da.deinit(); |
| 127 | 131 | ||
| ... | @@ -138,7 +142,7 @@ test "std.event.Lock" { | ... | @@ -138,7 +142,7 @@ test "std.event.Lock" { |
| 138 | defer cancel handle; | 142 | defer cancel handle; |
| 139 | loop.run(); | 143 | loop.run(); |
| 140 | 144 | ||
| 141 | assert(mem.eql(i32, shared_test_data, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len)); | 145 | testing.expectEqualSlices(i32, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len, shared_test_data); |
| 142 | } | 146 | } |
| 143 | 147 | ||
| 144 | async fn testLock(loop: *Loop, lock: *Lock) void { | 148 | async fn testLock(loop: *Loop, lock: *Lock) void { |
std/event/loop.zig+25-2| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const AtomicRmwOp = builtin.AtomicRmwOp; | 6 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 6 | const AtomicOrder = builtin.AtomicOrder; | 7 | const AtomicOrder = builtin.AtomicOrder; |
| ... | @@ -97,6 +98,7 @@ pub const Loop = struct { | ... | @@ -97,6 +98,7 @@ pub const Loop = struct { |
| 97 | /// TODO copy elision / named return values so that the threads referencing *Loop | 98 | /// TODO copy elision / named return values so that the threads referencing *Loop |
| 98 | /// have the correct pointer value. | 99 | /// have the correct pointer value. |
| 99 | pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void { | 100 | pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void { |
| 101 | if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode"); | ||
| 100 | const core_count = try os.cpuCount(allocator); | 102 | const core_count = try os.cpuCount(allocator); |
| 101 | return self.initInternal(allocator, core_count); | 103 | return self.initInternal(allocator, core_count); |
| 102 | } | 104 | } |
| ... | @@ -201,6 +203,11 @@ pub const Loop = struct { | ... | @@ -201,6 +203,11 @@ pub const Loop = struct { |
| 201 | self.os_data.fs_thread.wait(); | 203 | self.os_data.fs_thread.wait(); |
| 202 | } | 204 | } |
| 203 | 205 | ||
| 206 | if (builtin.single_threaded) { | ||
| 207 | assert(extra_thread_count == 0); | ||
| 208 | return; | ||
| 209 | } | ||
| 210 | |||
| 204 | var extra_thread_index: usize = 0; | 211 | var extra_thread_index: usize = 0; |
| 205 | errdefer { | 212 | errdefer { |
| 206 | // writing 8 bytes to an eventfd cannot fail | 213 | // writing 8 bytes to an eventfd cannot fail |
| ... | @@ -301,6 +308,11 @@ pub const Loop = struct { | ... | @@ -301,6 +308,11 @@ pub const Loop = struct { |
| 301 | self.os_data.fs_thread.wait(); | 308 | self.os_data.fs_thread.wait(); |
| 302 | } | 309 | } |
| 303 | 310 | ||
| 311 | if (builtin.single_threaded) { | ||
| 312 | assert(extra_thread_count == 0); | ||
| 313 | return; | ||
| 314 | } | ||
| 315 | |||
| 304 | var extra_thread_index: usize = 0; | 316 | var extra_thread_index: usize = 0; |
| 305 | errdefer { | 317 | errdefer { |
| 306 | _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable; | 318 | _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable; |
| ... | @@ -338,6 +350,11 @@ pub const Loop = struct { | ... | @@ -338,6 +350,11 @@ pub const Loop = struct { |
| 338 | self.available_eventfd_resume_nodes.push(eventfd_node); | 350 | self.available_eventfd_resume_nodes.push(eventfd_node); |
| 339 | } | 351 | } |
| 340 | 352 | ||
| 353 | if (builtin.single_threaded) { | ||
| 354 | assert(extra_thread_count == 0); | ||
| 355 | return; | ||
| 356 | } | ||
| 357 | |||
| 341 | var extra_thread_index: usize = 0; | 358 | var extra_thread_index: usize = 0; |
| 342 | errdefer { | 359 | errdefer { |
| 343 | var i: usize = 0; | 360 | var i: usize = 0; |
| ... | @@ -845,6 +862,9 @@ pub const Loop = struct { | ... | @@ -845,6 +862,9 @@ pub const Loop = struct { |
| 845 | }; | 862 | }; |
| 846 | 863 | ||
| 847 | test "std.event.Loop - basic" { | 864 | test "std.event.Loop - basic" { |
| 865 | // https://github.com/ziglang/zig/issues/1908 | ||
| 866 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 867 | |||
| 848 | var da = std.heap.DirectAllocator.init(); | 868 | var da = std.heap.DirectAllocator.init(); |
| 849 | defer da.deinit(); | 869 | defer da.deinit(); |
| 850 | 870 | ||
| ... | @@ -858,6 +878,9 @@ test "std.event.Loop - basic" { | ... | @@ -858,6 +878,9 @@ test "std.event.Loop - basic" { |
| 858 | } | 878 | } |
| 859 | 879 | ||
| 860 | test "std.event.Loop - call" { | 880 | test "std.event.Loop - call" { |
| 881 | // https://github.com/ziglang/zig/issues/1908 | ||
| 882 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 883 | |||
| 861 | var da = std.heap.DirectAllocator.init(); | 884 | var da = std.heap.DirectAllocator.init(); |
| 862 | defer da.deinit(); | 885 | defer da.deinit(); |
| 863 | 886 | ||
| ... | @@ -874,7 +897,7 @@ test "std.event.Loop - call" { | ... | @@ -874,7 +897,7 @@ test "std.event.Loop - call" { |
| 874 | 897 | ||
| 875 | loop.run(); | 898 | loop.run(); |
| 876 | 899 | ||
| 877 | assert(did_it); | 900 | testing.expect(did_it); |
| 878 | } | 901 | } |
| 879 | 902 | ||
| 880 | async fn testEventLoop() i32 { | 903 | async fn testEventLoop() i32 { |
| ... | @@ -883,6 +906,6 @@ async fn testEventLoop() i32 { | ... | @@ -883,6 +906,6 @@ async fn testEventLoop() i32 { |
| 883 | 906 | ||
| 884 | async fn testEventLoop2(h: promise->i32, did_it: *bool) void { | 907 | async fn testEventLoop2(h: promise->i32, did_it: *bool) void { |
| 885 | const value = await h; | 908 | const value = await h; |
| 886 | assert(value == 1234); | 909 | testing.expect(value == 1234); |
| 887 | did_it.* = true; | 910 | did_it.* = true; |
| 888 | } | 911 | } |
std/event/net.zig+5-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const testing = std.testing; |
| 4 | const event = std.event; | 4 | const event = std.event; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const os = std.os; | 6 | const os = std.os; |
| ... | @@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File { | ... | @@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File { |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | test "listen on a port, send bytes, receive bytes" { | 271 | test "listen on a port, send bytes, receive bytes" { |
| 272 | // https://github.com/ziglang/zig/issues/1908 | ||
| 273 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 274 | |||
| 272 | if (builtin.os != builtin.Os.linux) { | 275 | if (builtin.os != builtin.Os.linux) { |
| 273 | // TODO build abstractions for other operating systems | 276 | // TODO build abstractions for other operating systems |
| 274 | return error.SkipZigTest; | 277 | return error.SkipZigTest; |
| ... | @@ -323,7 +326,7 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv | ... | @@ -323,7 +326,7 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv |
| 323 | var buf: [512]u8 = undefined; | 326 | var buf: [512]u8 = undefined; |
| 324 | const amt_read = try socket_file.read(buf[0..]); | 327 | const amt_read = try socket_file.read(buf[0..]); |
| 325 | const msg = buf[0..amt_read]; | 328 | const msg = buf[0..amt_read]; |
| 326 | assert(mem.eql(u8, msg, "hello from server\n")); | 329 | testing.expect(mem.eql(u8, msg, "hello from server\n")); |
| 327 | server.close(); | 330 | server.close(); |
| 328 | } | 331 | } |
| 329 | 332 |
std/event/rwlock.zig+7-3| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const AtomicRmwOp = builtin.AtomicRmwOp; | 6 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 6 | const AtomicOrder = builtin.AtomicOrder; | 7 | const AtomicOrder = builtin.AtomicOrder; |
| ... | @@ -211,6 +212,9 @@ pub const RwLock = struct { | ... | @@ -211,6 +212,9 @@ pub const RwLock = struct { |
| 211 | }; | 212 | }; |
| 212 | 213 | ||
| 213 | test "std.event.RwLock" { | 214 | test "std.event.RwLock" { |
| 215 | // https://github.com/ziglang/zig/issues/1908 | ||
| 216 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 217 | |||
| 214 | var da = std.heap.DirectAllocator.init(); | 218 | var da = std.heap.DirectAllocator.init(); |
| 215 | defer da.deinit(); | 219 | defer da.deinit(); |
| 216 | 220 | ||
| ... | @@ -228,7 +232,7 @@ test "std.event.RwLock" { | ... | @@ -228,7 +232,7 @@ test "std.event.RwLock" { |
| 228 | loop.run(); | 232 | loop.run(); |
| 229 | 233 | ||
| 230 | const expected_result = [1]i32{shared_it_count * @intCast(i32, shared_test_data.len)} ** shared_test_data.len; | 234 | const expected_result = [1]i32{shared_it_count * @intCast(i32, shared_test_data.len)} ** shared_test_data.len; |
| 231 | assert(mem.eql(i32, shared_test_data, expected_result)); | 235 | testing.expectEqualSlices(i32, expected_result, shared_test_data); |
| 232 | } | 236 | } |
| 233 | 237 | ||
| 234 | async fn testLock(loop: *Loop, lock: *RwLock) void { | 238 | async fn testLock(loop: *Loop, lock: *RwLock) void { |
| ... | @@ -290,7 +294,7 @@ async fn readRunner(lock: *RwLock) void { | ... | @@ -290,7 +294,7 @@ async fn readRunner(lock: *RwLock) void { |
| 290 | const handle = await lock_promise; | 294 | const handle = await lock_promise; |
| 291 | defer handle.release(); | 295 | defer handle.release(); |
| 292 | 296 | ||
| 293 | assert(shared_test_index == 0); | 297 | testing.expect(shared_test_index == 0); |
| 294 | assert(shared_test_data[i] == @intCast(i32, shared_count)); | 298 | testing.expect(shared_test_data[i] == @intCast(i32, shared_count)); |
| 295 | } | 299 | } |
| 296 | } | 300 | } |
std/fmt/index.zig+125-83| ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const debug = std.debug; | 3 | const debug = std.debug; |
| 4 | const assert = debug.assert; | 4 | const assert = debug.assert; |
| 5 | const assertError = debug.assertError; | 5 | const testing = std.testing; |
| 6 | const mem = std.mem; | 6 | const mem = std.mem; |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const errol = @import("errol/index.zig"); | 8 | const errol = @import("errol/index.zig"); |
| ... | @@ -117,7 +117,7 @@ pub fn formatType( | ... | @@ -117,7 +117,7 @@ pub fn formatType( |
| 117 | return output(context, @errorName(value)); | 117 | return output(context, @errorName(value)); |
| 118 | } | 118 | } |
| 119 | switch (@typeInfo(T)) { | 119 | switch (@typeInfo(T)) { |
| 120 | builtin.TypeId.Int, builtin.TypeId.Float => { | 120 | builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => { |
| 121 | return formatValue(value, fmt, context, Errors, output); | 121 | return formatValue(value, fmt, context, Errors, output); |
| 122 | }, | 122 | }, |
| 123 | builtin.TypeId.Void => { | 123 | builtin.TypeId.Void => { |
| ... | @@ -236,6 +236,9 @@ pub fn formatType( | ... | @@ -236,6 +236,9 @@ pub fn formatType( |
| 236 | const casted_value = ([]const u8)(value); | 236 | const casted_value = ([]const u8)(value); |
| 237 | return output(context, casted_value); | 237 | return output(context, casted_value); |
| 238 | }, | 238 | }, |
| 239 | builtin.TypeInfo.Pointer.Size.C => { | ||
| 240 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); | ||
| 241 | }, | ||
| 239 | }, | 242 | }, |
| 240 | builtin.TypeId.Array => |info| { | 243 | builtin.TypeId.Array => |info| { |
| 241 | if (info.child == u8) { | 244 | if (info.child == u8) { |
| ... | @@ -243,6 +246,9 @@ pub fn formatType( | ... | @@ -243,6 +246,9 @@ pub fn formatType( |
| 243 | } | 246 | } |
| 244 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); | 247 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); |
| 245 | }, | 248 | }, |
| 249 | builtin.TypeId.Fn => { | ||
| 250 | return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value)); | ||
| 251 | }, | ||
| 246 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), | 252 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), |
| 247 | } | 253 | } |
| 248 | } | 254 | } |
| ... | @@ -268,11 +274,15 @@ fn formatValue( | ... | @@ -268,11 +274,15 @@ fn formatValue( |
| 268 | } | 274 | } |
| 269 | } | 275 | } |
| 270 | 276 | ||
| 271 | comptime var T = @typeOf(value); | 277 | const T = @typeOf(value); |
| 272 | switch (@typeId(T)) { | 278 | switch (@typeId(T)) { |
| 273 | builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output), | 279 | builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output), |
| 274 | builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output), | 280 | builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output), |
| 275 | else => unreachable, | 281 | builtin.TypeId.ComptimeInt => { |
| 282 | const Int = math.IntFittingRange(value, value); | ||
| 283 | return formatIntValue(Int(value), fmt, context, Errors, output); | ||
| 284 | }, | ||
| 285 | else => comptime unreachable, | ||
| 276 | } | 286 | } |
| 277 | } | 287 | } |
| 278 | 288 | ||
| ... | @@ -289,9 +299,10 @@ pub fn formatIntValue( | ... | @@ -289,9 +299,10 @@ pub fn formatIntValue( |
| 289 | if (fmt.len > 0) { | 299 | if (fmt.len > 0) { |
| 290 | switch (fmt[0]) { | 300 | switch (fmt[0]) { |
| 291 | 'c' => { | 301 | 'c' => { |
| 292 | if (@typeOf(value) == u8) { | 302 | if (@typeOf(value).bit_count <= 8) { |
| 293 | if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]}); | 303 | if (fmt.len > 1) |
| 294 | return formatAsciiChar(value, context, Errors, output); | 304 | @compileError("Unknown format character: " ++ []u8{fmt[1]}); |
| 305 | return formatAsciiChar(u8(value), context, Errors, output); | ||
| 295 | } | 306 | } |
| 296 | }, | 307 | }, |
| 297 | 'b' => { | 308 | 'b' => { |
| ... | @@ -580,7 +591,7 @@ pub fn formatFloatDecimal( | ... | @@ -580,7 +591,7 @@ pub fn formatFloatDecimal( |
| 580 | } | 591 | } |
| 581 | 592 | ||
| 582 | // Remaining fractional portion, zero-padding if insufficient. | 593 | // Remaining fractional portion, zero-padding if insufficient. |
| 583 | debug.assert(precision >= printed); | 594 | assert(precision >= printed); |
| 584 | if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) { | 595 | if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) { |
| 585 | try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]); | 596 | try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]); |
| 586 | return; | 597 | return; |
| ... | @@ -790,13 +801,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { | ... | @@ -790,13 +801,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { |
| 790 | } | 801 | } |
| 791 | 802 | ||
| 792 | test "fmt.parseInt" { | 803 | test "fmt.parseInt" { |
| 793 | assert((parseInt(i32, "-10", 10) catch unreachable) == -10); | 804 | testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10); |
| 794 | assert((parseInt(i32, "+10", 10) catch unreachable) == 10); | 805 | testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10); |
| 795 | assert(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter); | 806 | testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter); |
| 796 | assert(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter); | 807 | testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter); |
| 797 | assert(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter); | 808 | testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter); |
| 798 | assert((parseInt(u8, "255", 10) catch unreachable) == 255); | 809 | testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255); |
| 799 | assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); | 810 | testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); |
| 800 | } | 811 | } |
| 801 | 812 | ||
| 802 | const ParseUnsignedError = error{ | 813 | const ParseUnsignedError = error{ |
| ... | @@ -820,31 +831,37 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned | ... | @@ -820,31 +831,37 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned |
| 820 | return x; | 831 | return x; |
| 821 | } | 832 | } |
| 822 | 833 | ||
| 823 | test "parseUnsigned" { | 834 | test "fmt.parseUnsigned" { |
| 824 | assert((try parseUnsigned(u16, "050124", 10)) == 50124); | 835 | testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124); |
| 825 | assert((try parseUnsigned(u16, "65535", 10)) == 65535); | 836 | testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535); |
| 826 | assertError(parseUnsigned(u16, "65536", 10), error.Overflow); | 837 | testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10)); |
| 827 | 838 | ||
| 828 | assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff); | 839 | testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff); |
| 829 | assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow); | 840 | testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16)); |
| 830 | 841 | ||
| 831 | assert((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF); | 842 | testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF); |
| 832 | 843 | ||
| 833 | assert((try parseUnsigned(u7, "1", 10)) == 1); | 844 | testing.expect((try parseUnsigned(u7, "1", 10)) == 1); |
| 834 | assert((try parseUnsigned(u7, "1000", 2)) == 8); | 845 | testing.expect((try parseUnsigned(u7, "1000", 2)) == 8); |
| 835 | 846 | ||
| 836 | assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter); | 847 | testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10)); |
| 837 | assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter); | 848 | testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8)); |
| 838 | 849 | ||
| 839 | assert((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747); | 850 | testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747); |
| 840 | 851 | ||
| 841 | // these numbers should fit even though the radix itself doesn't fit in the destination type | 852 | // these numbers should fit even though the radix itself doesn't fit in the destination type |
| 842 | assert((try parseUnsigned(u1, "0", 10)) == 0); | 853 | testing.expect((try parseUnsigned(u1, "0", 10)) == 0); |
| 843 | assert((try parseUnsigned(u1, "1", 10)) == 1); | 854 | testing.expect((try parseUnsigned(u1, "1", 10)) == 1); |
| 844 | assertError(parseUnsigned(u1, "2", 10), error.Overflow); | 855 | testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10)); |
| 845 | assert((try parseUnsigned(u1, "001", 16)) == 1); | 856 | testing.expect((try parseUnsigned(u1, "001", 16)) == 1); |
| 846 | assert((try parseUnsigned(u2, "3", 16)) == 3); | 857 | testing.expect((try parseUnsigned(u2, "3", 16)) == 3); |
| 847 | assertError(parseUnsigned(u2, "4", 16), error.Overflow); | 858 | testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16)); |
| 859 | } | ||
| 860 | |||
| 861 | pub const parseFloat = @import("parse_float.zig").parseFloat; | ||
| 862 | |||
| 863 | test "fmt.parseFloat" { | ||
| 864 | _ = @import("parse_float.zig"); | ||
| 848 | } | 865 | } |
| 849 | 866 | ||
| 850 | pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { | 867 | pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { |
| ... | @@ -902,19 +919,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) { | ... | @@ -902,19 +919,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) { |
| 902 | test "buf print int" { | 919 | test "buf print int" { |
| 903 | var buffer: [max_int_digits]u8 = undefined; | 920 | var buffer: [max_int_digits]u8 = undefined; |
| 904 | const buf = buffer[0..]; | 921 | const buf = buffer[0..]; |
| 905 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110")); | 922 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110")); |
| 906 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678")); | 923 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678")); |
| 907 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e")); | 924 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e")); |
| 908 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E")); | 925 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E")); |
| 909 | 926 | ||
| 910 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678")); | 927 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678")); |
| 911 | 928 | ||
| 912 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666")); | 929 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666")); |
| 913 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234")); | 930 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234")); |
| 914 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234")); | 931 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234")); |
| 915 | 932 | ||
| 916 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42")); | 933 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42")); |
| 917 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42")); | 934 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42")); |
| 918 | } | 935 | } |
| 919 | 936 | ||
| 920 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 { | 937 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 { |
| ... | @@ -931,7 +948,7 @@ test "parse u64 digit too big" { | ... | @@ -931,7 +948,7 @@ test "parse u64 digit too big" { |
| 931 | 948 | ||
| 932 | test "parse unsigned comptime" { | 949 | test "parse unsigned comptime" { |
| 933 | comptime { | 950 | comptime { |
| 934 | assert((try parseUnsigned(usize, "2", 10)) == 2); | 951 | testing.expect((try parseUnsigned(usize, "2", 10)) == 2); |
| 935 | } | 952 | } |
| 936 | } | 953 | } |
| 937 | 954 | ||
| ... | @@ -964,6 +981,23 @@ test "fmt.format" { | ... | @@ -964,6 +981,23 @@ test "fmt.format" { |
| 964 | const value: u8 = 0b1100; | 981 | const value: u8 = 0b1100; |
| 965 | try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value); | 982 | try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value); |
| 966 | } | 983 | } |
| 984 | { | ||
| 985 | var buf1: [32]u8 = undefined; | ||
| 986 | var context = BufPrintContext{ .remaining = buf1[0..] }; | ||
| 987 | try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite); | ||
| 988 | var res = buf1[0 .. buf1.len - context.remaining.len]; | ||
| 989 | testing.expect(mem.eql(u8, res, "1234")); | ||
| 990 | |||
| 991 | context = BufPrintContext{ .remaining = buf1[0..] }; | ||
| 992 | try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite); | ||
| 993 | res = buf1[0 .. buf1.len - context.remaining.len]; | ||
| 994 | testing.expect(mem.eql(u8, res, "a")); | ||
| 995 | |||
| 996 | context = BufPrintContext{ .remaining = buf1[0..] }; | ||
| 997 | try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite); | ||
| 998 | res = buf1[0 .. buf1.len - context.remaining.len]; | ||
| 999 | testing.expect(mem.eql(u8, res, "1100")); | ||
| 1000 | } | ||
| 967 | { | 1001 | { |
| 968 | const value: [3]u8 = "abc"; | 1002 | const value: [3]u8 = "abc"; |
| 969 | try testFmt("array: abc\n", "array: {}\n", value); | 1003 | try testFmt("array: abc\n", "array: {}\n", value); |
| ... | @@ -985,6 +1019,14 @@ test "fmt.format" { | ... | @@ -985,6 +1019,14 @@ test "fmt.format" { |
| 985 | try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value); | 1019 | try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value); |
| 986 | try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value); | 1020 | try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value); |
| 987 | } | 1021 | } |
| 1022 | { | ||
| 1023 | const value = @intToPtr(fn () void, 0xdeadbeef); | ||
| 1024 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); | ||
| 1025 | } | ||
| 1026 | { | ||
| 1027 | const value = @intToPtr(fn () void, 0xdeadbeef); | ||
| 1028 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); | ||
| 1029 | } | ||
| 988 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); | 1030 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); |
| 989 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); | 1031 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); |
| 990 | try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C"); | 1032 | try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C"); |
| ... | @@ -1020,19 +1062,19 @@ test "fmt.format" { | ... | @@ -1020,19 +1062,19 @@ test "fmt.format" { |
| 1020 | var buf1: [32]u8 = undefined; | 1062 | var buf1: [32]u8 = undefined; |
| 1021 | const value: f32 = 1.34; | 1063 | const value: f32 = 1.34; |
| 1022 | const result = try bufPrint(buf1[0..], "f32: {e}\n", value); | 1064 | const result = try bufPrint(buf1[0..], "f32: {e}\n", value); |
| 1023 | assert(mem.eql(u8, result, "f32: 1.34000003e+00\n")); | 1065 | testing.expect(mem.eql(u8, result, "f32: 1.34000003e+00\n")); |
| 1024 | } | 1066 | } |
| 1025 | { | 1067 | { |
| 1026 | var buf1: [32]u8 = undefined; | 1068 | var buf1: [32]u8 = undefined; |
| 1027 | const value: f32 = 12.34; | 1069 | const value: f32 = 12.34; |
| 1028 | const result = try bufPrint(buf1[0..], "f32: {e}\n", value); | 1070 | const result = try bufPrint(buf1[0..], "f32: {e}\n", value); |
| 1029 | assert(mem.eql(u8, result, "f32: 1.23400001e+01\n")); | 1071 | testing.expect(mem.eql(u8, result, "f32: 1.23400001e+01\n")); |
| 1030 | } | 1072 | } |
| 1031 | { | 1073 | { |
| 1032 | var buf1: [32]u8 = undefined; | 1074 | var buf1: [32]u8 = undefined; |
| 1033 | const value: f64 = -12.34e10; | 1075 | const value: f64 = -12.34e10; |
| 1034 | const result = try bufPrint(buf1[0..], "f64: {e}\n", value); | 1076 | const result = try bufPrint(buf1[0..], "f64: {e}\n", value); |
| 1035 | assert(mem.eql(u8, result, "f64: -1.234e+11\n")); | 1077 | testing.expect(mem.eql(u8, result, "f64: -1.234e+11\n")); |
| 1036 | } | 1078 | } |
| 1037 | { | 1079 | { |
| 1038 | // This fails on release due to a minor rounding difference. | 1080 | // This fails on release due to a minor rounding difference. |
| ... | @@ -1042,26 +1084,26 @@ test "fmt.format" { | ... | @@ -1042,26 +1084,26 @@ test "fmt.format" { |
| 1042 | var buf1: [32]u8 = undefined; | 1084 | var buf1: [32]u8 = undefined; |
| 1043 | const value: f64 = 9.999960e-40; | 1085 | const value: f64 = 9.999960e-40; |
| 1044 | const result = try bufPrint(buf1[0..], "f64: {e}\n", value); | 1086 | const result = try bufPrint(buf1[0..], "f64: {e}\n", value); |
| 1045 | assert(mem.eql(u8, result, "f64: 9.99996e-40\n")); | 1087 | testing.expect(mem.eql(u8, result, "f64: 9.99996e-40\n")); |
| 1046 | } | 1088 | } |
| 1047 | } | 1089 | } |
| 1048 | { | 1090 | { |
| 1049 | var buf1: [32]u8 = undefined; | 1091 | var buf1: [32]u8 = undefined; |
| 1050 | const value: f64 = 1.409706e-42; | 1092 | const value: f64 = 1.409706e-42; |
| 1051 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); | 1093 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); |
| 1052 | assert(mem.eql(u8, result, "f64: 1.40971e-42\n")); | 1094 | testing.expect(mem.eql(u8, result, "f64: 1.40971e-42\n")); |
| 1053 | } | 1095 | } |
| 1054 | { | 1096 | { |
| 1055 | var buf1: [32]u8 = undefined; | 1097 | var buf1: [32]u8 = undefined; |
| 1056 | const value: f64 = @bitCast(f32, u32(814313563)); | 1098 | const value: f64 = @bitCast(f32, u32(814313563)); |
| 1057 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); | 1099 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); |
| 1058 | assert(mem.eql(u8, result, "f64: 1.00000e-09\n")); | 1100 | testing.expect(mem.eql(u8, result, "f64: 1.00000e-09\n")); |
| 1059 | } | 1101 | } |
| 1060 | { | 1102 | { |
| 1061 | var buf1: [32]u8 = undefined; | 1103 | var buf1: [32]u8 = undefined; |
| 1062 | const value: f64 = @bitCast(f32, u32(1006632960)); | 1104 | const value: f64 = @bitCast(f32, u32(1006632960)); |
| 1063 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); | 1105 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); |
| 1064 | assert(mem.eql(u8, result, "f64: 7.81250e-03\n")); | 1106 | testing.expect(mem.eql(u8, result, "f64: 7.81250e-03\n")); |
| 1065 | } | 1107 | } |
| 1066 | { | 1108 | { |
| 1067 | // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05. | 1109 | // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05. |
| ... | @@ -1069,47 +1111,47 @@ test "fmt.format" { | ... | @@ -1069,47 +1111,47 @@ test "fmt.format" { |
| 1069 | var buf1: [32]u8 = undefined; | 1111 | var buf1: [32]u8 = undefined; |
| 1070 | const value: f64 = @bitCast(f32, u32(1203982400)); | 1112 | const value: f64 = @bitCast(f32, u32(1203982400)); |
| 1071 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); | 1113 | const result = try bufPrint(buf1[0..], "f64: {e5}\n", value); |
| 1072 | assert(mem.eql(u8, result, "f64: 1.00001e+05\n")); | 1114 | testing.expect(mem.eql(u8, result, "f64: 1.00001e+05\n")); |
| 1073 | } | 1115 | } |
| 1074 | { | 1116 | { |
| 1075 | var buf1: [32]u8 = undefined; | 1117 | var buf1: [32]u8 = undefined; |
| 1076 | const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64); | 1118 | const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64); |
| 1077 | assert(mem.eql(u8, result, "f64: nan\n")); | 1119 | testing.expect(mem.eql(u8, result, "f64: nan\n")); |
| 1078 | } | 1120 | } |
| 1079 | if (builtin.arch != builtin.Arch.armv8) { | 1121 | if (builtin.arch != builtin.Arch.armv8) { |
| 1080 | // negative nan is not defined by IEE 754, | 1122 | // negative nan is not defined by IEE 754, |
| 1081 | // and ARM thus normalizes it to positive nan | 1123 | // and ARM thus normalizes it to positive nan |
| 1082 | var buf1: [32]u8 = undefined; | 1124 | var buf1: [32]u8 = undefined; |
| 1083 | const result = try bufPrint(buf1[0..], "f64: {}\n", -math.nan_f64); | 1125 | const result = try bufPrint(buf1[0..], "f64: {}\n", -math.nan_f64); |
| 1084 | assert(mem.eql(u8, result, "f64: -nan\n")); | 1126 | testing.expect(mem.eql(u8, result, "f64: -nan\n")); |
| 1085 | } | 1127 | } |
| 1086 | { | 1128 | { |
| 1087 | var buf1: [32]u8 = undefined; | 1129 | var buf1: [32]u8 = undefined; |
| 1088 | const result = try bufPrint(buf1[0..], "f64: {}\n", math.inf_f64); | 1130 | const result = try bufPrint(buf1[0..], "f64: {}\n", math.inf_f64); |
| 1089 | assert(mem.eql(u8, result, "f64: inf\n")); | 1131 | testing.expect(mem.eql(u8, result, "f64: inf\n")); |
| 1090 | } | 1132 | } |
| 1091 | { | 1133 | { |
| 1092 | var buf1: [32]u8 = undefined; | 1134 | var buf1: [32]u8 = undefined; |
| 1093 | const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64); | 1135 | const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64); |
| 1094 | assert(mem.eql(u8, result, "f64: -inf\n")); | 1136 | testing.expect(mem.eql(u8, result, "f64: -inf\n")); |
| 1095 | } | 1137 | } |
| 1096 | { | 1138 | { |
| 1097 | var buf1: [64]u8 = undefined; | 1139 | var buf1: [64]u8 = undefined; |
| 1098 | const value: f64 = 1.52314e+29; | 1140 | const value: f64 = 1.52314e+29; |
| 1099 | const result = try bufPrint(buf1[0..], "f64: {.}\n", value); | 1141 | const result = try bufPrint(buf1[0..], "f64: {.}\n", value); |
| 1100 | assert(mem.eql(u8, result, "f64: 152314000000000000000000000000\n")); | 1142 | testing.expect(mem.eql(u8, result, "f64: 152314000000000000000000000000\n")); |
| 1101 | } | 1143 | } |
| 1102 | { | 1144 | { |
| 1103 | var buf1: [32]u8 = undefined; | 1145 | var buf1: [32]u8 = undefined; |
| 1104 | const value: f32 = 1.1234; | 1146 | const value: f32 = 1.1234; |
| 1105 | const result = try bufPrint(buf1[0..], "f32: {.1}\n", value); | 1147 | const result = try bufPrint(buf1[0..], "f32: {.1}\n", value); |
| 1106 | assert(mem.eql(u8, result, "f32: 1.1\n")); | 1148 | testing.expect(mem.eql(u8, result, "f32: 1.1\n")); |
| 1107 | } | 1149 | } |
| 1108 | { | 1150 | { |
| 1109 | var buf1: [32]u8 = undefined; | 1151 | var buf1: [32]u8 = undefined; |
| 1110 | const value: f32 = 1234.567; | 1152 | const value: f32 = 1234.567; |
| 1111 | const result = try bufPrint(buf1[0..], "f32: {.2}\n", value); | 1153 | const result = try bufPrint(buf1[0..], "f32: {.2}\n", value); |
| 1112 | assert(mem.eql(u8, result, "f32: 1234.57\n")); | 1154 | testing.expect(mem.eql(u8, result, "f32: 1234.57\n")); |
| 1113 | } | 1155 | } |
| 1114 | { | 1156 | { |
| 1115 | var buf1: [32]u8 = undefined; | 1157 | var buf1: [32]u8 = undefined; |
| ... | @@ -1117,92 +1159,92 @@ test "fmt.format" { | ... | @@ -1117,92 +1159,92 @@ test "fmt.format" { |
| 1117 | const result = try bufPrint(buf1[0..], "f32: {.4}\n", value); | 1159 | const result = try bufPrint(buf1[0..], "f32: {.4}\n", value); |
| 1118 | // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). | 1160 | // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). |
| 1119 | // -11.12339... is rounded back up to -11.1234 | 1161 | // -11.12339... is rounded back up to -11.1234 |
| 1120 | assert(mem.eql(u8, result, "f32: -11.1234\n")); | 1162 | testing.expect(mem.eql(u8, result, "f32: -11.1234\n")); |
| 1121 | } | 1163 | } |
| 1122 | { | 1164 | { |
| 1123 | var buf1: [32]u8 = undefined; | 1165 | var buf1: [32]u8 = undefined; |
| 1124 | const value: f32 = 91.12345; | 1166 | const value: f32 = 91.12345; |
| 1125 | const result = try bufPrint(buf1[0..], "f32: {.5}\n", value); | 1167 | const result = try bufPrint(buf1[0..], "f32: {.5}\n", value); |
| 1126 | assert(mem.eql(u8, result, "f32: 91.12345\n")); | 1168 | testing.expect(mem.eql(u8, result, "f32: 91.12345\n")); |
| 1127 | } | 1169 | } |
| 1128 | { | 1170 | { |
| 1129 | var buf1: [32]u8 = undefined; | 1171 | var buf1: [32]u8 = undefined; |
| 1130 | const value: f64 = 91.12345678901235; | 1172 | const value: f64 = 91.12345678901235; |
| 1131 | const result = try bufPrint(buf1[0..], "f64: {.10}\n", value); | 1173 | const result = try bufPrint(buf1[0..], "f64: {.10}\n", value); |
| 1132 | assert(mem.eql(u8, result, "f64: 91.1234567890\n")); | 1174 | testing.expect(mem.eql(u8, result, "f64: 91.1234567890\n")); |
| 1133 | } | 1175 | } |
| 1134 | { | 1176 | { |
| 1135 | var buf1: [32]u8 = undefined; | 1177 | var buf1: [32]u8 = undefined; |
| 1136 | const value: f64 = 0.0; | 1178 | const value: f64 = 0.0; |
| 1137 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1179 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1138 | assert(mem.eql(u8, result, "f64: 0.00000\n")); | 1180 | testing.expect(mem.eql(u8, result, "f64: 0.00000\n")); |
| 1139 | } | 1181 | } |
| 1140 | { | 1182 | { |
| 1141 | var buf1: [32]u8 = undefined; | 1183 | var buf1: [32]u8 = undefined; |
| 1142 | const value: f64 = 5.700; | 1184 | const value: f64 = 5.700; |
| 1143 | const result = try bufPrint(buf1[0..], "f64: {.0}\n", value); | 1185 | const result = try bufPrint(buf1[0..], "f64: {.0}\n", value); |
| 1144 | assert(mem.eql(u8, result, "f64: 6\n")); | 1186 | testing.expect(mem.eql(u8, result, "f64: 6\n")); |
| 1145 | } | 1187 | } |
| 1146 | { | 1188 | { |
| 1147 | var buf1: [32]u8 = undefined; | 1189 | var buf1: [32]u8 = undefined; |
| 1148 | const value: f64 = 9.999; | 1190 | const value: f64 = 9.999; |
| 1149 | const result = try bufPrint(buf1[0..], "f64: {.1}\n", value); | 1191 | const result = try bufPrint(buf1[0..], "f64: {.1}\n", value); |
| 1150 | assert(mem.eql(u8, result, "f64: 10.0\n")); | 1192 | testing.expect(mem.eql(u8, result, "f64: 10.0\n")); |
| 1151 | } | 1193 | } |
| 1152 | { | 1194 | { |
| 1153 | var buf1: [32]u8 = undefined; | 1195 | var buf1: [32]u8 = undefined; |
| 1154 | const value: f64 = 1.0; | 1196 | const value: f64 = 1.0; |
| 1155 | const result = try bufPrint(buf1[0..], "f64: {.3}\n", value); | 1197 | const result = try bufPrint(buf1[0..], "f64: {.3}\n", value); |
| 1156 | assert(mem.eql(u8, result, "f64: 1.000\n")); | 1198 | testing.expect(mem.eql(u8, result, "f64: 1.000\n")); |
| 1157 | } | 1199 | } |
| 1158 | { | 1200 | { |
| 1159 | var buf1: [32]u8 = undefined; | 1201 | var buf1: [32]u8 = undefined; |
| 1160 | const value: f64 = 0.0003; | 1202 | const value: f64 = 0.0003; |
| 1161 | const result = try bufPrint(buf1[0..], "f64: {.8}\n", value); | 1203 | const result = try bufPrint(buf1[0..], "f64: {.8}\n", value); |
| 1162 | assert(mem.eql(u8, result, "f64: 0.00030000\n")); | 1204 | testing.expect(mem.eql(u8, result, "f64: 0.00030000\n")); |
| 1163 | } | 1205 | } |
| 1164 | { | 1206 | { |
| 1165 | var buf1: [32]u8 = undefined; | 1207 | var buf1: [32]u8 = undefined; |
| 1166 | const value: f64 = 1.40130e-45; | 1208 | const value: f64 = 1.40130e-45; |
| 1167 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1209 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1168 | assert(mem.eql(u8, result, "f64: 0.00000\n")); | 1210 | testing.expect(mem.eql(u8, result, "f64: 0.00000\n")); |
| 1169 | } | 1211 | } |
| 1170 | { | 1212 | { |
| 1171 | var buf1: [32]u8 = undefined; | 1213 | var buf1: [32]u8 = undefined; |
| 1172 | const value: f64 = 9.999960e-40; | 1214 | const value: f64 = 9.999960e-40; |
| 1173 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1215 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1174 | assert(mem.eql(u8, result, "f64: 0.00000\n")); | 1216 | testing.expect(mem.eql(u8, result, "f64: 0.00000\n")); |
| 1175 | } | 1217 | } |
| 1176 | // libc checks | 1218 | // libc checks |
| 1177 | { | 1219 | { |
| 1178 | var buf1: [32]u8 = undefined; | 1220 | var buf1: [32]u8 = undefined; |
| 1179 | const value: f64 = f64(@bitCast(f32, u32(916964781))); | 1221 | const value: f64 = f64(@bitCast(f32, u32(916964781))); |
| 1180 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1222 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1181 | assert(mem.eql(u8, result, "f64: 0.00001\n")); | 1223 | testing.expect(mem.eql(u8, result, "f64: 0.00001\n")); |
| 1182 | } | 1224 | } |
| 1183 | { | 1225 | { |
| 1184 | var buf1: [32]u8 = undefined; | 1226 | var buf1: [32]u8 = undefined; |
| 1185 | const value: f64 = f64(@bitCast(f32, u32(925353389))); | 1227 | const value: f64 = f64(@bitCast(f32, u32(925353389))); |
| 1186 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1228 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1187 | assert(mem.eql(u8, result, "f64: 0.00001\n")); | 1229 | testing.expect(mem.eql(u8, result, "f64: 0.00001\n")); |
| 1188 | } | 1230 | } |
| 1189 | { | 1231 | { |
| 1190 | var buf1: [32]u8 = undefined; | 1232 | var buf1: [32]u8 = undefined; |
| 1191 | const value: f64 = f64(@bitCast(f32, u32(1036831278))); | 1233 | const value: f64 = f64(@bitCast(f32, u32(1036831278))); |
| 1192 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1234 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1193 | assert(mem.eql(u8, result, "f64: 0.10000\n")); | 1235 | testing.expect(mem.eql(u8, result, "f64: 0.10000\n")); |
| 1194 | } | 1236 | } |
| 1195 | { | 1237 | { |
| 1196 | var buf1: [32]u8 = undefined; | 1238 | var buf1: [32]u8 = undefined; |
| 1197 | const value: f64 = f64(@bitCast(f32, u32(1065353133))); | 1239 | const value: f64 = f64(@bitCast(f32, u32(1065353133))); |
| 1198 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1240 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1199 | assert(mem.eql(u8, result, "f64: 1.00000\n")); | 1241 | testing.expect(mem.eql(u8, result, "f64: 1.00000\n")); |
| 1200 | } | 1242 | } |
| 1201 | { | 1243 | { |
| 1202 | var buf1: [32]u8 = undefined; | 1244 | var buf1: [32]u8 = undefined; |
| 1203 | const value: f64 = f64(@bitCast(f32, u32(1092616192))); | 1245 | const value: f64 = f64(@bitCast(f32, u32(1092616192))); |
| 1204 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1246 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1205 | assert(mem.eql(u8, result, "f64: 10.00000\n")); | 1247 | testing.expect(mem.eql(u8, result, "f64: 10.00000\n")); |
| 1206 | } | 1248 | } |
| 1207 | // libc differences | 1249 | // libc differences |
| 1208 | { | 1250 | { |
| ... | @@ -1212,7 +1254,7 @@ test "fmt.format" { | ... | @@ -1212,7 +1254,7 @@ test "fmt.format" { |
| 1212 | // floats of the form x.yyyy25 on a precision point. | 1254 | // floats of the form x.yyyy25 on a precision point. |
| 1213 | const value: f64 = f64(@bitCast(f32, u32(1015021568))); | 1255 | const value: f64 = f64(@bitCast(f32, u32(1015021568))); |
| 1214 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1256 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1215 | assert(mem.eql(u8, result, "f64: 0.01563\n")); | 1257 | testing.expect(mem.eql(u8, result, "f64: 0.01563\n")); |
| 1216 | } | 1258 | } |
| 1217 | // std-windows-x86_64-Debug-bare test case fails | 1259 | // std-windows-x86_64-Debug-bare test case fails |
| 1218 | { | 1260 | { |
| ... | @@ -1222,7 +1264,7 @@ test "fmt.format" { | ... | @@ -1222,7 +1264,7 @@ test "fmt.format" { |
| 1222 | var buf1: [32]u8 = undefined; | 1264 | var buf1: [32]u8 = undefined; |
| 1223 | const value: f64 = f64(@bitCast(f32, u32(1518338049))); | 1265 | const value: f64 = f64(@bitCast(f32, u32(1518338049))); |
| 1224 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); | 1266 | const result = try bufPrint(buf1[0..], "f64: {.5}\n", value); |
| 1225 | assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n")); | 1267 | testing.expect(mem.eql(u8, result, "f64: 18014400656965630.00000\n")); |
| 1226 | } | 1268 | } |
| 1227 | //custom type format | 1269 | //custom type format |
| 1228 | { | 1270 | { |
| ... | @@ -1303,10 +1345,10 @@ test "fmt.format" { | ... | @@ -1303,10 +1345,10 @@ test "fmt.format" { |
| 1303 | 1345 | ||
| 1304 | var buf: [100]u8 = undefined; | 1346 | var buf: [100]u8 = undefined; |
| 1305 | const uu_result = try bufPrint(buf[0..], "{}", uu_inst); | 1347 | const uu_result = try bufPrint(buf[0..], "{}", uu_inst); |
| 1306 | debug.assert(mem.eql(u8, uu_result[0..3], "UU@")); | 1348 | testing.expect(mem.eql(u8, uu_result[0..3], "UU@")); |
| 1307 | 1349 | ||
| 1308 | const eu_result = try bufPrint(buf[0..], "{}", eu_inst); | 1350 | const eu_result = try bufPrint(buf[0..], "{}", eu_inst); |
| 1309 | debug.assert(mem.eql(u8, uu_result[0..3], "EU@")); | 1351 | testing.expect(mem.eql(u8, uu_result[0..3], "EU@")); |
| 1310 | } | 1352 | } |
| 1311 | //enum format | 1353 | //enum format |
| 1312 | { | 1354 | { |
| ... | @@ -1365,11 +1407,11 @@ pub fn trim(buf: []const u8) []const u8 { | ... | @@ -1365,11 +1407,11 @@ pub fn trim(buf: []const u8) []const u8 { |
| 1365 | } | 1407 | } |
| 1366 | 1408 | ||
| 1367 | test "fmt.trim" { | 1409 | test "fmt.trim" { |
| 1368 | assert(mem.eql(u8, "abc", trim("\n abc \t"))); | 1410 | testing.expect(mem.eql(u8, "abc", trim("\n abc \t"))); |
| 1369 | assert(mem.eql(u8, "", trim(" "))); | 1411 | testing.expect(mem.eql(u8, "", trim(" "))); |
| 1370 | assert(mem.eql(u8, "", trim(""))); | 1412 | testing.expect(mem.eql(u8, "", trim(""))); |
| 1371 | assert(mem.eql(u8, "abc", trim(" abc"))); | 1413 | testing.expect(mem.eql(u8, "abc", trim(" abc"))); |
| 1372 | assert(mem.eql(u8, "abc", trim("abc "))); | 1414 | testing.expect(mem.eql(u8, "abc", trim("abc "))); |
| 1373 | } | 1415 | } |
| 1374 | 1416 | ||
| 1375 | pub fn isWhiteSpace(byte: u8) bool { | 1417 | pub fn isWhiteSpace(byte: u8) bool { |
std/fmt/parse_float.zig created+420| ... | @@ -0,0 +1,420 @@ | ||
| 1 | // Adapted from https://github.com/grzegorz-kraszewski/stringtofloat. | ||
| 2 | |||
| 3 | // MIT License | ||
| 4 | // | ||
| 5 | // Copyright (c) 2016 Grzegorz Kraszewski | ||
| 6 | // | ||
| 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 8 | // of this software and associated documentation files (the "Software"), to deal | ||
| 9 | // in the Software without restriction, including without limitation the rights | ||
| 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 11 | // copies of the Software, and to permit persons to whom the Software is | ||
| 12 | // furnished to do so, subject to the following conditions: | ||
| 13 | // | ||
| 14 | // The above copyright notice and this permission notice shall be included in all | ||
| 15 | // copies or substantial portions of the Software. | ||
| 16 | // | ||
| 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 23 | // SOFTWARE. | ||
| 24 | // | ||
| 25 | |||
| 26 | // Be aware that this implementation has the following limitations: | ||
| 27 | // | ||
| 28 | // - Is not round-trip accurate for all values | ||
| 29 | // - Only supports round-to-zero | ||
| 30 | // - Does not handle denormals | ||
| 31 | |||
| 32 | const std = @import("../index.zig"); | ||
| 33 | |||
| 34 | const max_digits = 25; | ||
| 35 | |||
| 36 | const f64_plus_zero: u64 = 0x0000000000000000; | ||
| 37 | const f64_minus_zero: u64 = 0x8000000000000000; | ||
| 38 | const f64_plus_infinity: u64 = 0x7FF0000000000000; | ||
| 39 | const f64_minus_infinity: u64 = 0xFFF0000000000000; | ||
| 40 | |||
| 41 | const Z96 = struct { | ||
| 42 | d0: u32, | ||
| 43 | d1: u32, | ||
| 44 | d2: u32, | ||
| 45 | |||
| 46 | // d = s >> 1 | ||
| 47 | inline fn shiftRight1(d: *Z96, s: Z96) void { | ||
| 48 | d.d0 = (s.d0 >> 1) | ((s.d1 & 1) << 31); | ||
| 49 | d.d1 = (s.d1 >> 1) | ((s.d2 & 1) << 31); | ||
| 50 | d.d2 = s.d2 >> 1; | ||
| 51 | } | ||
| 52 | |||
| 53 | // d = s << 1 | ||
| 54 | inline fn shiftLeft1(d: *Z96, s: Z96) void { | ||
| 55 | d.d2 = (s.d2 << 1) | ((s.d1 & (1 << 31)) >> 31); | ||
| 56 | d.d1 = (s.d1 << 1) | ((s.d0 & (1 << 31)) >> 31); | ||
| 57 | d.d0 = s.d0 << 1; | ||
| 58 | } | ||
| 59 | |||
| 60 | // d += s | ||
| 61 | inline fn add(d: *Z96, s: Z96) void { | ||
| 62 | var w = u64(d.d0) + u64(s.d0); | ||
| 63 | d.d0 = @truncate(u32, w); | ||
| 64 | |||
| 65 | w >>= 32; | ||
| 66 | w += u64(d.d1) + u64(s.d1); | ||
| 67 | d.d1 = @truncate(u32, w); | ||
| 68 | |||
| 69 | w >>= 32; | ||
| 70 | w += u64(d.d2) + u64(s.d2); | ||
| 71 | d.d2 = @truncate(u32, w); | ||
| 72 | } | ||
| 73 | |||
| 74 | // d -= s | ||
| 75 | inline fn sub(d: *Z96, s: Z96) void { | ||
| 76 | var w = u64(d.d0) -% u64(s.d0); | ||
| 77 | d.d0 = @truncate(u32, w); | ||
| 78 | |||
| 79 | w >>= 32; | ||
| 80 | w += u64(d.d1) -% u64(s.d1); | ||
| 81 | d.d1 = @truncate(u32, w); | ||
| 82 | |||
| 83 | w >>= 32; | ||
| 84 | w += u64(d.d2) -% u64(s.d2); | ||
| 85 | d.d2 = @truncate(u32, w); | ||
| 86 | } | ||
| 87 | }; | ||
| 88 | |||
| 89 | const FloatRepr = struct { | ||
| 90 | negative: bool, | ||
| 91 | exponent: i32, | ||
| 92 | mantissa: u64, | ||
| 93 | }; | ||
| 94 | |||
| 95 | fn convertRepr(comptime T: type, n: FloatRepr) T { | ||
| 96 | const mask28: u32 = 0xf << 28; | ||
| 97 | |||
| 98 | var s: Z96 = undefined; | ||
| 99 | var q: Z96 = undefined; | ||
| 100 | var r: Z96 = undefined; | ||
| 101 | |||
| 102 | s.d0 = @truncate(u32, n.mantissa); | ||
| 103 | s.d1 = @truncate(u32, n.mantissa >> 32); | ||
| 104 | s.d2 = 0; | ||
| 105 | |||
| 106 | var binary_exponent: u64 = 92; | ||
| 107 | var exp = n.exponent; | ||
| 108 | |||
| 109 | while (exp > 0) : (exp -= 1) { | ||
| 110 | q.shiftLeft1(s); // q = p << 1 | ||
| 111 | r.shiftLeft1(q); // r = p << 2 | ||
| 112 | s.shiftLeft1(r); // p = p << 3 | ||
| 113 | q.add(s); // p = (p << 3) + (p << 1) | ||
| 114 | |||
| 115 | exp -= 1; | ||
| 116 | |||
| 117 | while (s.d2 & mask28 != 0) { | ||
| 118 | q.shiftRight1(s); | ||
| 119 | binary_exponent += 1; | ||
| 120 | s = q; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | while (exp < 0) { | ||
| 125 | while (s.d2 & (1 << 31) == 0) { | ||
| 126 | q.shiftLeft1(s); | ||
| 127 | binary_exponent -= 1; | ||
| 128 | s = q; | ||
| 129 | } | ||
| 130 | |||
| 131 | q.d2 = s.d2 / 10; | ||
| 132 | r.d1 = s.d2 % 10; | ||
| 133 | r.d2 = (s.d1 >> 8) | (r.d1 << 24); | ||
| 134 | q.d1 = r.d2 / 10; | ||
| 135 | r.d1 = r.d2 % 10; | ||
| 136 | r.d2 = ((s.d1 & 0xff) << 16) | (s.d0 >> 16) | (r.d1 << 24); | ||
| 137 | r.d0 = r.d2 / 10; | ||
| 138 | r.d1 = r.d2 % 10; | ||
| 139 | q.d1 = (q.d1 << 8) | ((r.d0 & 0x00ff0000) >> 16); | ||
| 140 | q.d0 = r.d0 << 16; | ||
| 141 | r.d2 = (s.d0 *% 0xffff) | (r.d1 << 16); | ||
| 142 | q.d0 |= r.d2 / 10; | ||
| 143 | s = q; | ||
| 144 | |||
| 145 | exp += 1; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (s.d0 != 0 or s.d1 != 0 or s.d2 != 0) { | ||
| 149 | while (s.d2 & mask28 == 0) { | ||
| 150 | q.shiftLeft1(s); | ||
| 151 | binary_exponent -= 1; | ||
| 152 | s = q; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | binary_exponent += 1023; | ||
| 157 | |||
| 158 | const repr: u64 = blk: { | ||
| 159 | if (binary_exponent > 2046) { | ||
| 160 | break :blk if (n.negative) f64_minus_infinity else f64_plus_infinity; | ||
| 161 | } else if (binary_exponent < 1) { | ||
| 162 | break :blk if (n.negative) f64_minus_zero else f64_plus_zero; | ||
| 163 | } else if (s.d2 != 0) { | ||
| 164 | const binexs2 = u64(binary_exponent) << 52; | ||
| 165 | const rr = (u64(s.d2 & ~mask28) << 24) | ((u64(s.d1) + 128) >> 8) | binexs2; | ||
| 166 | break :blk if (n.negative) rr | (1 << 63) else rr; | ||
| 167 | } else { | ||
| 168 | break :blk 0; | ||
| 169 | } | ||
| 170 | }; | ||
| 171 | |||
| 172 | const f = @bitCast(f64, repr); | ||
| 173 | return @floatCast(T, f); | ||
| 174 | } | ||
| 175 | |||
| 176 | const State = enum { | ||
| 177 | MaybeSign, | ||
| 178 | LeadingMantissaZeros, | ||
| 179 | LeadingFractionalZeros, | ||
| 180 | MantissaIntegral, | ||
| 181 | MantissaFractional, | ||
| 182 | ExponentSign, | ||
| 183 | LeadingExponentZeros, | ||
| 184 | Exponent, | ||
| 185 | }; | ||
| 186 | |||
| 187 | const ParseResult = enum { | ||
| 188 | Ok, | ||
| 189 | PlusZero, | ||
| 190 | MinusZero, | ||
| 191 | PlusInf, | ||
| 192 | MinusInf, | ||
| 193 | }; | ||
| 194 | |||
| 195 | inline fn isDigit(c: u8) bool { | ||
| 196 | return c >= '0' and c <= '9'; | ||
| 197 | } | ||
| 198 | |||
| 199 | inline fn isSpace(c: u8) bool { | ||
| 200 | return (c >= 0x09 and c <= 0x13) or c == 0x20; | ||
| 201 | } | ||
| 202 | |||
| 203 | fn parseRepr(s: []const u8, n: *FloatRepr) !ParseResult { | ||
| 204 | var digit_index: usize = 0; | ||
| 205 | var negative = false; | ||
| 206 | var negative_exp = false; | ||
| 207 | var exponent: i32 = 0; | ||
| 208 | |||
| 209 | var state = State.MaybeSign; | ||
| 210 | |||
| 211 | var i: usize = 0; | ||
| 212 | loop: while (i < s.len) { | ||
| 213 | const c = s[i]; | ||
| 214 | |||
| 215 | switch (state) { | ||
| 216 | State.MaybeSign => { | ||
| 217 | state = State.LeadingMantissaZeros; | ||
| 218 | |||
| 219 | if (c == '+') { | ||
| 220 | i += 1; | ||
| 221 | } else if (c == '-') { | ||
| 222 | n.negative = true; | ||
| 223 | i += 1; | ||
| 224 | } else if (isDigit(c) or c == '.') { | ||
| 225 | // continue | ||
| 226 | } else { | ||
| 227 | return error.InvalidCharacter; | ||
| 228 | } | ||
| 229 | }, | ||
| 230 | |||
| 231 | State.LeadingMantissaZeros => { | ||
| 232 | if (c == '0') { | ||
| 233 | i += 1; | ||
| 234 | } else if (c == '.') { | ||
| 235 | i += 1; | ||
| 236 | state = State.LeadingFractionalZeros; | ||
| 237 | } else { | ||
| 238 | state = State.MantissaIntegral; | ||
| 239 | } | ||
| 240 | }, | ||
| 241 | |||
| 242 | State.LeadingFractionalZeros => { | ||
| 243 | if (c == '0') { | ||
| 244 | i += 1; | ||
| 245 | if (n.exponent > std.math.minInt(i32)) { | ||
| 246 | n.exponent -= 1; | ||
| 247 | } | ||
| 248 | } else { | ||
| 249 | state = State.MantissaFractional; | ||
| 250 | } | ||
| 251 | }, | ||
| 252 | |||
| 253 | State.MantissaIntegral => { | ||
| 254 | if (isDigit(c)) { | ||
| 255 | if (digit_index < max_digits) { | ||
| 256 | n.mantissa *%= 10; | ||
| 257 | n.mantissa += s[i] - '0'; | ||
| 258 | digit_index += 1; | ||
| 259 | } else if (n.exponent < std.math.maxInt(i32)) { | ||
| 260 | n.exponent += 1; | ||
| 261 | } | ||
| 262 | |||
| 263 | i += 1; | ||
| 264 | } else if (c == '.') { | ||
| 265 | i += 1; | ||
| 266 | state = State.MantissaFractional; | ||
| 267 | } else { | ||
| 268 | state = State.MantissaFractional; | ||
| 269 | } | ||
| 270 | }, | ||
| 271 | |||
| 272 | State.MantissaFractional => { | ||
| 273 | if (isDigit(c)) { | ||
| 274 | if (digit_index < max_digits) { | ||
| 275 | n.mantissa *%= 10; | ||
| 276 | n.mantissa += c - '0'; | ||
| 277 | n.exponent -%= 1; | ||
| 278 | digit_index += 1; | ||
| 279 | } | ||
| 280 | |||
| 281 | i += 1; | ||
| 282 | } else if (c == 'e' or c == 'E') { | ||
| 283 | i += 1; | ||
| 284 | state = State.ExponentSign; | ||
| 285 | } else { | ||
| 286 | state = State.ExponentSign; | ||
| 287 | } | ||
| 288 | }, | ||
| 289 | |||
| 290 | State.ExponentSign => { | ||
| 291 | if (c == '+') { | ||
| 292 | i += 1; | ||
| 293 | } else if (c == '-') { | ||
| 294 | negative_exp = true; | ||
| 295 | i += 1; | ||
| 296 | } | ||
| 297 | |||
| 298 | state = State.LeadingExponentZeros; | ||
| 299 | }, | ||
| 300 | |||
| 301 | State.LeadingExponentZeros => { | ||
| 302 | if (c == '0') { | ||
| 303 | i += 1; | ||
| 304 | } else { | ||
| 305 | state = State.Exponent; | ||
| 306 | } | ||
| 307 | }, | ||
| 308 | |||
| 309 | State.Exponent => { | ||
| 310 | if (isDigit(c)) { | ||
| 311 | if (exponent < std.math.maxInt(i32)) { | ||
| 312 | exponent *= 10; | ||
| 313 | exponent += @intCast(i32, c - '0'); | ||
| 314 | } | ||
| 315 | |||
| 316 | i += 1; | ||
| 317 | } else { | ||
| 318 | return error.InvalidCharacter; | ||
| 319 | } | ||
| 320 | }, | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | if (negative_exp) exponent = -exponent; | ||
| 325 | n.exponent += exponent; | ||
| 326 | |||
| 327 | if (n.mantissa == 0) { | ||
| 328 | return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero; | ||
| 329 | } else if (n.exponent > 309) { | ||
| 330 | return if (n.negative) ParseResult.MinusInf else ParseResult.PlusInf; | ||
| 331 | } else if (n.exponent < -328) { | ||
| 332 | return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero; | ||
| 333 | } | ||
| 334 | |||
| 335 | return ParseResult.Ok; | ||
| 336 | } | ||
| 337 | |||
| 338 | inline fn isLower(c: u8) bool { | ||
| 339 | return c -% 'a' < 26; | ||
| 340 | } | ||
| 341 | |||
| 342 | inline fn toUpper(c: u8) u8 { | ||
| 343 | return if (isLower(c)) (c & 0x5f) else c; | ||
| 344 | } | ||
| 345 | |||
| 346 | fn caseInEql(a: []const u8, b: []const u8) bool { | ||
| 347 | if (a.len != b.len) return false; | ||
| 348 | |||
| 349 | for (a) |_, i| { | ||
| 350 | if (toUpper(a[i]) != toUpper(b[i])) { | ||
| 351 | return false; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | return true; | ||
| 356 | } | ||
| 357 | |||
| 358 | pub fn parseFloat(comptime T: type, s: []const u8) !T { | ||
| 359 | if (s.len == 0) { | ||
| 360 | return error.InvalidCharacter; | ||
| 361 | } | ||
| 362 | |||
| 363 | if (caseInEql(s, "nan")) { | ||
| 364 | return std.math.nan(T); | ||
| 365 | } else if (caseInEql(s, "inf") or caseInEql(s, "+inf")) { | ||
| 366 | return std.math.inf(T); | ||
| 367 | } else if (caseInEql(s, "-inf")) { | ||
| 368 | return -std.math.inf(T); | ||
| 369 | } | ||
| 370 | |||
| 371 | var r = FloatRepr{ | ||
| 372 | .negative = false, | ||
| 373 | .exponent = 0, | ||
| 374 | .mantissa = 0, | ||
| 375 | }; | ||
| 376 | |||
| 377 | return switch (try parseRepr(s, &r)) { | ||
| 378 | ParseResult.Ok => convertRepr(T, r), | ||
| 379 | ParseResult.PlusZero => 0.0, | ||
| 380 | ParseResult.MinusZero => -T(0.0), | ||
| 381 | ParseResult.PlusInf => std.math.inf(T), | ||
| 382 | ParseResult.MinusInf => -std.math.inf(T), | ||
| 383 | }; | ||
| 384 | } | ||
| 385 | |||
| 386 | test "fmt.parseFloat" { | ||
| 387 | const testing = std.testing; | ||
| 388 | const expect = testing.expect; | ||
| 389 | const expectEqual = testing.expectEqual; | ||
| 390 | const approxEq = std.math.approxEq; | ||
| 391 | const epsilon = 1e-7; | ||
| 392 | |||
| 393 | inline for ([]type{ f16, f32, f64, f128 }) |T| { | ||
| 394 | const Z = @IntType(false, T.bit_count); | ||
| 395 | |||
| 396 | testing.expectError(error.InvalidCharacter, parseFloat(T, "")); | ||
| 397 | testing.expectError(error.InvalidCharacter, parseFloat(T, " 1")); | ||
| 398 | testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc")); | ||
| 399 | |||
| 400 | expectEqual(try parseFloat(T, "0"), 0.0); | ||
| 401 | expectEqual((try parseFloat(T, "0")), 0.0); | ||
| 402 | expectEqual((try parseFloat(T, "+0")), 0.0); | ||
| 403 | expectEqual((try parseFloat(T, "-0")), 0.0); | ||
| 404 | |||
| 405 | expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon)); | ||
| 406 | expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon)); | ||
| 407 | |||
| 408 | expectEqual((try parseFloat(T, "1e-700")), 0); | ||
| 409 | expectEqual((try parseFloat(T, "1e+700")), std.math.inf(T)); | ||
| 410 | |||
| 411 | expectEqual(@bitCast(Z, try parseFloat(T, "nAn")), @bitCast(Z, std.math.nan(T))); | ||
| 412 | expectEqual((try parseFloat(T, "inF")), std.math.inf(T)); | ||
| 413 | expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T)); | ||
| 414 | |||
| 415 | if (T != f16) { | ||
| 416 | expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon)); | ||
| 417 | expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon)); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
std/hash/adler.zig+6-6| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | // https://github.com/madler/zlib/blob/master/adler32.c | 4 | // https://github.com/madler/zlib/blob/master/adler32.c |
| 5 | 5 | ||
| 6 | const std = @import("../index.zig"); | 6 | const std = @import("../index.zig"); |
| 7 | const debug = std.debug; | 7 | const testing = std.testing; |
| 8 | 8 | ||
| 9 | pub const Adler32 = struct { | 9 | pub const Adler32 = struct { |
| 10 | const base = 65521; | 10 | const base = 65521; |
| ... | @@ -89,19 +89,19 @@ pub const Adler32 = struct { | ... | @@ -89,19 +89,19 @@ pub const Adler32 = struct { |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | test "adler32 sanity" { | 91 | test "adler32 sanity" { |
| 92 | debug.assert(Adler32.hash("a") == 0x620062); | 92 | testing.expect(Adler32.hash("a") == 0x620062); |
| 93 | debug.assert(Adler32.hash("example") == 0xbc002ed); | 93 | testing.expect(Adler32.hash("example") == 0xbc002ed); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | test "adler32 long" { | 96 | test "adler32 long" { |
| 97 | const long1 = []u8{1} ** 1024; | 97 | const long1 = []u8{1} ** 1024; |
| 98 | debug.assert(Adler32.hash(long1[0..]) == 0x06780401); | 98 | testing.expect(Adler32.hash(long1[0..]) == 0x06780401); |
| 99 | 99 | ||
| 100 | const long2 = []u8{1} ** 1025; | 100 | const long2 = []u8{1} ** 1025; |
| 101 | debug.assert(Adler32.hash(long2[0..]) == 0x0a7a0402); | 101 | testing.expect(Adler32.hash(long2[0..]) == 0x0a7a0402); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | test "adler32 very long" { | 104 | test "adler32 very long" { |
| 105 | const long = []u8{1} ** 5553; | 105 | const long = []u8{1} ** 5553; |
| 106 | debug.assert(Adler32.hash(long[0..]) == 0x707f15b2); | 106 | testing.expect(Adler32.hash(long[0..]) == 0x707f15b2); |
| 107 | } | 107 | } |
std/hash/crc.zig+13-12| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const debug = std.debug; | 9 | const debug = std.debug; |
| 10 | const testing = std.testing; | ||
| 10 | 11 | ||
| 11 | pub const Polynomial = struct { | 12 | pub const Polynomial = struct { |
| 12 | const IEEE = 0xedb88320; | 13 | const IEEE = 0xedb88320; |
| ... | @@ -101,17 +102,17 @@ pub fn Crc32WithPoly(comptime poly: u32) type { | ... | @@ -101,17 +102,17 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 101 | test "crc32 ieee" { | 102 | test "crc32 ieee" { |
| 102 | const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE); | 103 | const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE); |
| 103 | 104 | ||
| 104 | debug.assert(Crc32Ieee.hash("") == 0x00000000); | 105 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 105 | debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43); | 106 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| 106 | debug.assert(Crc32Ieee.hash("abc") == 0x352441c2); | 107 | testing.expect(Crc32Ieee.hash("abc") == 0x352441c2); |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | test "crc32 castagnoli" { | 110 | test "crc32 castagnoli" { |
| 110 | const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli); | 111 | const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli); |
| 111 | 112 | ||
| 112 | debug.assert(Crc32Castagnoli.hash("") == 0x00000000); | 113 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 113 | debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330); | 114 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
| 114 | debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7); | 115 | testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7); |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | // half-byte lookup table implementation. | 118 | // half-byte lookup table implementation. |
| ... | @@ -165,15 +166,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { | ... | @@ -165,15 +166,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 165 | test "small crc32 ieee" { | 166 | test "small crc32 ieee" { |
| 166 | const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE); | 167 | const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE); |
| 167 | 168 | ||
| 168 | debug.assert(Crc32Ieee.hash("") == 0x00000000); | 169 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 169 | debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43); | 170 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| 170 | debug.assert(Crc32Ieee.hash("abc") == 0x352441c2); | 171 | testing.expect(Crc32Ieee.hash("abc") == 0x352441c2); |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 173 | test "small crc32 castagnoli" { | 174 | test "small crc32 castagnoli" { |
| 174 | const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli); | 175 | const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli); |
| 175 | 176 | ||
| 176 | debug.assert(Crc32Castagnoli.hash("") == 0x00000000); | 177 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 177 | debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330); | 178 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
| 178 | debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7); | 179 | testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7); |
| 179 | } | 180 | } |
std/hash/fnv.zig+9-9| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | // https://tools.ietf.org/html/draft-eastlake-fnv-14 | 5 | // https://tools.ietf.org/html/draft-eastlake-fnv-14 |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const debug = std.debug; | 8 | const testing = std.testing; |
| 9 | 9 | ||
| 10 | pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5); | 10 | pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5); |
| 11 | pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325); | 11 | pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325); |
| ... | @@ -41,18 +41,18 @@ fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type { | ... | @@ -41,18 +41,18 @@ fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type { |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | test "fnv1a-32" { | 43 | test "fnv1a-32" { |
| 44 | debug.assert(Fnv1a_32.hash("") == 0x811c9dc5); | 44 | testing.expect(Fnv1a_32.hash("") == 0x811c9dc5); |
| 45 | debug.assert(Fnv1a_32.hash("a") == 0xe40c292c); | 45 | testing.expect(Fnv1a_32.hash("a") == 0xe40c292c); |
| 46 | debug.assert(Fnv1a_32.hash("foobar") == 0xbf9cf968); | 46 | testing.expect(Fnv1a_32.hash("foobar") == 0xbf9cf968); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | test "fnv1a-64" { | 49 | test "fnv1a-64" { |
| 50 | debug.assert(Fnv1a_64.hash("") == 0xcbf29ce484222325); | 50 | testing.expect(Fnv1a_64.hash("") == 0xcbf29ce484222325); |
| 51 | debug.assert(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c); | 51 | testing.expect(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c); |
| 52 | debug.assert(Fnv1a_64.hash("foobar") == 0x85944171f73967e8); | 52 | testing.expect(Fnv1a_64.hash("foobar") == 0x85944171f73967e8); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | test "fnv1a-128" { | 55 | test "fnv1a-128" { |
| 56 | debug.assert(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d); | 56 | testing.expect(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d); |
| 57 | debug.assert(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964); | 57 | testing.expect(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964); |
| 58 | } | 58 | } |
std/hash/siphash.zig+15-14| ... | @@ -6,7 +6,8 @@ | ... | @@ -6,7 +6,8 @@ |
| 6 | // https://131002.net/siphash/ | 6 | // https://131002.net/siphash/ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const debug = std.debug; | 9 | const assert = std.debug.assert; |
| 10 | const testing = std.testing; | ||
| 10 | const math = std.math; | 11 | const math = std.math; |
| 11 | const mem = std.mem; | 12 | const mem = std.mem; |
| 12 | 13 | ||
| ... | @@ -21,8 +22,8 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type { | ... | @@ -21,8 +22,8 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type { |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type { | 24 | fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type { |
| 24 | debug.assert(T == u64 or T == u128); | 25 | assert(T == u64 or T == u128); |
| 25 | debug.assert(c_rounds > 0 and d_rounds > 0); | 26 | assert(c_rounds > 0 and d_rounds > 0); |
| 26 | 27 | ||
| 27 | return struct { | 28 | return struct { |
| 28 | const Self = @This(); | 29 | const Self = @This(); |
| ... | @@ -40,10 +41,10 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -40,10 +41,10 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 40 | msg_len: u8, | 41 | msg_len: u8, |
| 41 | 42 | ||
| 42 | pub fn init(key: []const u8) Self { | 43 | pub fn init(key: []const u8) Self { |
| 43 | debug.assert(key.len >= 16); | 44 | assert(key.len >= 16); |
| 44 | 45 | ||
| 45 | const k0 = mem.readInt(key[0..8], u64, Endian.Little); | 46 | const k0 = mem.readIntSliceLittle(u64, key[0..8]); |
| 46 | const k1 = mem.readInt(key[8..16], u64, Endian.Little); | 47 | const k1 = mem.readIntSliceLittle(u64, key[8..16]); |
| 47 | 48 | ||
| 48 | var d = Self{ | 49 | var d = Self{ |
| 49 | .v0 = k0 ^ 0x736f6d6570736575, | 50 | .v0 = k0 ^ 0x736f6d6570736575, |
| ... | @@ -119,9 +120,9 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -119,9 +120,9 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | fn round(d: *Self, b: []const u8) void { | 122 | fn round(d: *Self, b: []const u8) void { |
| 122 | debug.assert(b.len == 8); | 123 | assert(b.len == 8); |
| 123 | 124 | ||
| 124 | const m = mem.readInt(b[0..], u64, Endian.Little); | 125 | const m = mem.readIntSliceLittle(u64, b[0..]); |
| 125 | d.v3 ^= m; | 126 | d.v3 ^= m; |
| 126 | 127 | ||
| 127 | comptime var i: usize = 0; | 128 | comptime var i: usize = 0; |
| ... | @@ -162,7 +163,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -162,7 +163,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 162 | const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; | 163 | const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; |
| 163 | 164 | ||
| 164 | test "siphash64-2-4 sanity" { | 165 | test "siphash64-2-4 sanity" { |
| 165 | const vectors = [][]const u8{ | 166 | const vectors = [][8]u8{ |
| 166 | "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" | 167 | "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" |
| 167 | "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" | 168 | "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" |
| 168 | "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc | 169 | "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc |
| ... | @@ -235,13 +236,13 @@ test "siphash64-2-4 sanity" { | ... | @@ -235,13 +236,13 @@ test "siphash64-2-4 sanity" { |
| 235 | for (vectors) |vector, i| { | 236 | for (vectors) |vector, i| { |
| 236 | buffer[i] = @intCast(u8, i); | 237 | buffer[i] = @intCast(u8, i); |
| 237 | 238 | ||
| 238 | const expected = mem.readInt(vector, u64, Endian.Little); | 239 | const expected = mem.readIntLittle(u64, &vector); |
| 239 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); | 240 | testing.expect(siphash.hash(test_key, buffer[0..i]) == expected); |
| 240 | } | 241 | } |
| 241 | } | 242 | } |
| 242 | 243 | ||
| 243 | test "siphash128-2-4 sanity" { | 244 | test "siphash128-2-4 sanity" { |
| 244 | const vectors = [][]const u8{ | 245 | const vectors = [][16]u8{ |
| 245 | "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93", | 246 | "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93", |
| 246 | "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45", | 247 | "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45", |
| 247 | "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4", | 248 | "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4", |
| ... | @@ -314,7 +315,7 @@ test "siphash128-2-4 sanity" { | ... | @@ -314,7 +315,7 @@ test "siphash128-2-4 sanity" { |
| 314 | for (vectors) |vector, i| { | 315 | for (vectors) |vector, i| { |
| 315 | buffer[i] = @intCast(u8, i); | 316 | buffer[i] = @intCast(u8, i); |
| 316 | 317 | ||
| 317 | const expected = mem.readInt(vector, u128, Endian.Little); | 318 | const expected = mem.readIntLittle(u128, &vector); |
| 318 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); | 319 | testing.expect(siphash.hash(test_key, buffer[0..i]) == expected); |
| 319 | } | 320 | } |
| 320 | } | 321 | } |
std/hash_map.zig+34-29| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const debug = std.debug; | 2 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 3 | const assert = debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const math = std.math; | 5 | const math = std.math; |
| 5 | const mem = std.mem; | 6 | const mem = std.mem; |
| 6 | const Allocator = mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| ... | @@ -342,37 +343,37 @@ test "basic hash map usage" { | ... | @@ -342,37 +343,37 @@ test "basic hash map usage" { |
| 342 | var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); | 343 | var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); |
| 343 | defer map.deinit(); | 344 | defer map.deinit(); |
| 344 | 345 | ||
| 345 | assert((try map.put(1, 11)) == null); | 346 | testing.expect((try map.put(1, 11)) == null); |
| 346 | assert((try map.put(2, 22)) == null); | 347 | testing.expect((try map.put(2, 22)) == null); |
| 347 | assert((try map.put(3, 33)) == null); | 348 | testing.expect((try map.put(3, 33)) == null); |
| 348 | assert((try map.put(4, 44)) == null); | 349 | testing.expect((try map.put(4, 44)) == null); |
| 349 | assert((try map.put(5, 55)) == null); | 350 | testing.expect((try map.put(5, 55)) == null); |
| 350 | 351 | ||
| 351 | assert((try map.put(5, 66)).?.value == 55); | 352 | testing.expect((try map.put(5, 66)).?.value == 55); |
| 352 | assert((try map.put(5, 55)).?.value == 66); | 353 | testing.expect((try map.put(5, 55)).?.value == 66); |
| 353 | 354 | ||
| 354 | const gop1 = try map.getOrPut(5); | 355 | const gop1 = try map.getOrPut(5); |
| 355 | assert(gop1.found_existing == true); | 356 | testing.expect(gop1.found_existing == true); |
| 356 | assert(gop1.kv.value == 55); | 357 | testing.expect(gop1.kv.value == 55); |
| 357 | gop1.kv.value = 77; | 358 | gop1.kv.value = 77; |
| 358 | assert(map.get(5).?.value == 77); | 359 | testing.expect(map.get(5).?.value == 77); |
| 359 | 360 | ||
| 360 | const gop2 = try map.getOrPut(99); | 361 | const gop2 = try map.getOrPut(99); |
| 361 | assert(gop2.found_existing == false); | 362 | testing.expect(gop2.found_existing == false); |
| 362 | gop2.kv.value = 42; | 363 | gop2.kv.value = 42; |
| 363 | assert(map.get(99).?.value == 42); | 364 | testing.expect(map.get(99).?.value == 42); |
| 364 | 365 | ||
| 365 | const gop3 = try map.getOrPutValue(5, 5); | 366 | const gop3 = try map.getOrPutValue(5, 5); |
| 366 | assert(gop3.value == 77); | 367 | testing.expect(gop3.value == 77); |
| 367 | 368 | ||
| 368 | const gop4 = try map.getOrPutValue(100, 41); | 369 | const gop4 = try map.getOrPutValue(100, 41); |
| 369 | assert(gop4.value == 41); | 370 | testing.expect(gop4.value == 41); |
| 370 | 371 | ||
| 371 | assert(map.contains(2)); | 372 | testing.expect(map.contains(2)); |
| 372 | assert(map.get(2).?.value == 22); | 373 | testing.expect(map.get(2).?.value == 22); |
| 373 | _ = map.remove(2); | 374 | _ = map.remove(2); |
| 374 | assert(map.remove(2) == null); | 375 | testing.expect(map.remove(2) == null); |
| 375 | assert(map.get(2) == null); | 376 | testing.expect(map.get(2) == null); |
| 376 | } | 377 | } |
| 377 | 378 | ||
| 378 | test "iterator hash map" { | 379 | test "iterator hash map" { |
| ... | @@ -382,9 +383,9 @@ test "iterator hash map" { | ... | @@ -382,9 +383,9 @@ test "iterator hash map" { |
| 382 | var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); | 383 | var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); |
| 383 | defer reset_map.deinit(); | 384 | defer reset_map.deinit(); |
| 384 | 385 | ||
| 385 | assert((try reset_map.put(1, 11)) == null); | 386 | testing.expect((try reset_map.put(1, 11)) == null); |
| 386 | assert((try reset_map.put(2, 22)) == null); | 387 | testing.expect((try reset_map.put(2, 22)) == null); |
| 387 | assert((try reset_map.put(3, 33)) == null); | 388 | testing.expect((try reset_map.put(3, 33)) == null); |
| 388 | 389 | ||
| 389 | var keys = []i32{ | 390 | var keys = []i32{ |
| 390 | 3, | 391 | 3, |
| ... | @@ -400,26 +401,26 @@ test "iterator hash map" { | ... | @@ -400,26 +401,26 @@ test "iterator hash map" { |
| 400 | var it = reset_map.iterator(); | 401 | var it = reset_map.iterator(); |
| 401 | var count: usize = 0; | 402 | var count: usize = 0; |
| 402 | while (it.next()) |next| { | 403 | while (it.next()) |next| { |
| 403 | assert(next.key == keys[count]); | 404 | testing.expect(next.key == keys[count]); |
| 404 | assert(next.value == values[count]); | 405 | testing.expect(next.value == values[count]); |
| 405 | count += 1; | 406 | count += 1; |
| 406 | } | 407 | } |
| 407 | 408 | ||
| 408 | assert(count == 3); | 409 | testing.expect(count == 3); |
| 409 | assert(it.next() == null); | 410 | testing.expect(it.next() == null); |
| 410 | it.reset(); | 411 | it.reset(); |
| 411 | count = 0; | 412 | count = 0; |
| 412 | while (it.next()) |next| { | 413 | while (it.next()) |next| { |
| 413 | assert(next.key == keys[count]); | 414 | testing.expect(next.key == keys[count]); |
| 414 | assert(next.value == values[count]); | 415 | testing.expect(next.value == values[count]); |
| 415 | count += 1; | 416 | count += 1; |
| 416 | if (count == 2) break; | 417 | if (count == 2) break; |
| 417 | } | 418 | } |
| 418 | 419 | ||
| 419 | it.reset(); | 420 | it.reset(); |
| 420 | var entry = it.next().?; | 421 | var entry = it.next().?; |
| 421 | assert(entry.key == keys[0]); | 422 | testing.expect(entry.key == keys[0]); |
| 422 | assert(entry.value == values[0]); | 423 | testing.expect(entry.value == values[0]); |
| 423 | } | 424 | } |
| 424 | 425 | ||
| 425 | pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) { | 426 | pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) { |
| ... | @@ -495,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type | ... | @@ -495,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type |
| 495 | builtin.TypeId.Pointer => |info| switch (info.size) { | 496 | builtin.TypeId.Pointer => |info| switch (info.size) { |
| 496 | builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"), | 497 | builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"), |
| 497 | builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"), | 498 | builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"), |
| 499 | builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto hash C pointers"), | ||
| 498 | builtin.TypeInfo.Pointer.Size.Slice => { | 500 | builtin.TypeInfo.Pointer.Size.Slice => { |
| 499 | const interval = std.math.max(1, key.len / 256); | 501 | const interval = std.math.max(1, key.len / 256); |
| 500 | var i: usize = 0; | 502 | var i: usize = 0; |
| ... | @@ -508,6 +510,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type | ... | @@ -508,6 +510,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type |
| 508 | 510 | ||
| 509 | builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"), | 511 | builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"), |
| 510 | builtin.TypeId.Array => @compileError("TODO auto hash for arrays"), | 512 | builtin.TypeId.Array => @compileError("TODO auto hash for arrays"), |
| 513 | builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"), | ||
| 511 | builtin.TypeId.Struct => @compileError("TODO auto hash for structs"), | 514 | builtin.TypeId.Struct => @compileError("TODO auto hash for structs"), |
| 512 | builtin.TypeId.Union => @compileError("TODO auto hash for unions"), | 515 | builtin.TypeId.Union => @compileError("TODO auto hash for unions"), |
| 513 | builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"), | 516 | builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"), |
| ... | @@ -541,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { | ... | @@ -541,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { |
| 541 | builtin.TypeId.Pointer => |info| switch (info.size) { | 544 | builtin.TypeId.Pointer => |info| switch (info.size) { |
| 542 | builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"), | 545 | builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"), |
| 543 | builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"), | 546 | builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"), |
| 547 | builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto eql for C pointers"), | ||
| 544 | builtin.TypeInfo.Pointer.Size.Slice => { | 548 | builtin.TypeInfo.Pointer.Size.Slice => { |
| 545 | if (a.len != b.len) return false; | 549 | if (a.len != b.len) return false; |
| 546 | for (a) |a_item, i| { | 550 | for (a) |a_item, i| { |
| ... | @@ -555,5 +559,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { | ... | @@ -555,5 +559,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { |
| 555 | builtin.TypeId.Struct => @compileError("TODO auto eql for structs"), | 559 | builtin.TypeId.Struct => @compileError("TODO auto eql for structs"), |
| 556 | builtin.TypeId.Union => @compileError("TODO auto eql for unions"), | 560 | builtin.TypeId.Union => @compileError("TODO auto eql for unions"), |
| 557 | builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"), | 561 | builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"), |
| 562 | builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"), | ||
| 558 | } | 563 | } |
| 559 | } | 564 | } |
std/heap.zig+79-74| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const debug = std.debug; | 2 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 3 | const assert = debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const os = std.os; | 6 | const os = std.os; |
| 6 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| ... | @@ -66,7 +67,7 @@ pub const DirectAllocator = struct { | ... | @@ -66,7 +67,7 @@ pub const DirectAllocator = struct { |
| 66 | } | 67 | } |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { | 70 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 { |
| 70 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); | 71 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 71 | 72 | ||
| 72 | switch (builtin.os) { | 73 | switch (builtin.os) { |
| ... | @@ -106,9 +107,7 @@ pub const DirectAllocator = struct { | ... | @@ -106,9 +107,7 @@ pub const DirectAllocator = struct { |
| 106 | }; | 107 | }; |
| 107 | const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory; | 108 | const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory; |
| 108 | const root_addr = @ptrToInt(ptr); | 109 | const root_addr = @ptrToInt(ptr); |
| 109 | const rem = @rem(root_addr, alignment); | 110 | const adjusted_addr = mem.alignForward(root_addr, alignment); |
| 110 | const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); | ||
| 111 | const adjusted_addr = root_addr + march_forward_bytes; | ||
| 112 | const record_addr = adjusted_addr + n; | 111 | const record_addr = adjusted_addr + n; |
| 113 | @intToPtr(*align(1) usize, record_addr).* = root_addr; | 112 | @intToPtr(*align(1) usize, record_addr).* = root_addr; |
| 114 | return @intToPtr([*]u8, adjusted_addr)[0..n]; | 113 | return @intToPtr([*]u8, adjusted_addr)[0..n]; |
| ... | @@ -126,8 +125,7 @@ pub const DirectAllocator = struct { | ... | @@ -126,8 +125,7 @@ pub const DirectAllocator = struct { |
| 126 | const base_addr = @ptrToInt(old_mem.ptr); | 125 | const base_addr = @ptrToInt(old_mem.ptr); |
| 127 | const old_addr_end = base_addr + old_mem.len; | 126 | const old_addr_end = base_addr + old_mem.len; |
| 128 | const new_addr_end = base_addr + new_size; | 127 | const new_addr_end = base_addr + new_size; |
| 129 | const rem = @rem(new_addr_end, os.page_size); | 128 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); |
| 130 | const new_addr_end_rounded = new_addr_end + if (rem == 0) 0 else (os.page_size - rem); | ||
| 131 | if (old_addr_end > new_addr_end_rounded) { | 129 | if (old_addr_end > new_addr_end_rounded) { |
| 132 | _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded); | 130 | _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded); |
| 133 | } | 131 | } |
| ... | @@ -324,51 +322,57 @@ pub const FixedBufferAllocator = struct { | ... | @@ -324,51 +322,57 @@ pub const FixedBufferAllocator = struct { |
| 324 | fn free(allocator: *Allocator, bytes: []u8) void {} | 322 | fn free(allocator: *Allocator, bytes: []u8) void {} |
| 325 | }; | 323 | }; |
| 326 | 324 | ||
| 327 | /// lock free | 325 | pub const ThreadSafeFixedBufferAllocator = blk: { |
| 328 | pub const ThreadSafeFixedBufferAllocator = struct { | 326 | if (builtin.single_threaded) { |
| 329 | allocator: Allocator, | 327 | break :blk FixedBufferAllocator; |
| 330 | end_index: usize, | 328 | } else { |
| 331 | buffer: []u8, | 329 | /// lock free |
| 330 | break :blk struct { | ||
| 331 | allocator: Allocator, | ||
| 332 | end_index: usize, | ||
| 333 | buffer: []u8, | ||
| 334 | |||
| 335 | pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator { | ||
| 336 | return ThreadSafeFixedBufferAllocator{ | ||
| 337 | .allocator = Allocator{ | ||
| 338 | .allocFn = alloc, | ||
| 339 | .reallocFn = realloc, | ||
| 340 | .freeFn = free, | ||
| 341 | }, | ||
| 342 | .buffer = buffer, | ||
| 343 | .end_index = 0, | ||
| 344 | }; | ||
| 345 | } | ||
| 332 | 346 | ||
| 333 | pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator { | 347 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { |
| 334 | return ThreadSafeFixedBufferAllocator{ | 348 | const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator); |
| 335 | .allocator = Allocator{ | 349 | var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst); |
| 336 | .allocFn = alloc, | 350 | while (true) { |
| 337 | .reallocFn = realloc, | 351 | const addr = @ptrToInt(self.buffer.ptr) + end_index; |
| 338 | .freeFn = free, | 352 | const rem = @rem(addr, alignment); |
| 339 | }, | 353 | const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); |
| 340 | .buffer = buffer, | 354 | const adjusted_index = end_index + march_forward_bytes; |
| 341 | .end_index = 0, | 355 | const new_end_index = adjusted_index + n; |
| 342 | }; | 356 | if (new_end_index > self.buffer.len) { |
| 343 | } | 357 | return error.OutOfMemory; |
| 358 | } | ||
| 359 | end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index]; | ||
| 360 | } | ||
| 361 | } | ||
| 344 | 362 | ||
| 345 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { | 363 | fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { |
| 346 | const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator); | 364 | if (new_size <= old_mem.len) { |
| 347 | var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst); | 365 | return old_mem[0..new_size]; |
| 348 | while (true) { | 366 | } else { |
| 349 | const addr = @ptrToInt(self.buffer.ptr) + end_index; | 367 | const result = try alloc(allocator, new_size, alignment); |
| 350 | const rem = @rem(addr, alignment); | 368 | mem.copy(u8, result, old_mem); |
| 351 | const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); | 369 | return result; |
| 352 | const adjusted_index = end_index + march_forward_bytes; | 370 | } |
| 353 | const new_end_index = adjusted_index + n; | ||
| 354 | if (new_end_index > self.buffer.len) { | ||
| 355 | return error.OutOfMemory; | ||
| 356 | } | 371 | } |
| 357 | end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index]; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | 372 | ||
| 361 | fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { | 373 | fn free(allocator: *Allocator, bytes: []u8) void {} |
| 362 | if (new_size <= old_mem.len) { | 374 | }; |
| 363 | return old_mem[0..new_size]; | ||
| 364 | } else { | ||
| 365 | const result = try alloc(allocator, new_size, alignment); | ||
| 366 | mem.copy(u8, result, old_mem); | ||
| 367 | return result; | ||
| 368 | } | ||
| 369 | } | 375 | } |
| 370 | |||
| 371 | fn free(allocator: *Allocator, bytes: []u8) void {} | ||
| 372 | }; | 376 | }; |
| 373 | 377 | ||
| 374 | pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) { | 378 | pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) { |
| ... | @@ -484,11 +488,11 @@ test "FixedBufferAllocator Reuse memory on realloc" { | ... | @@ -484,11 +488,11 @@ test "FixedBufferAllocator Reuse memory on realloc" { |
| 484 | var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]); | 488 | var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]); |
| 485 | 489 | ||
| 486 | var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5); | 490 | var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5); |
| 487 | assert(slice0.len == 5); | 491 | testing.expect(slice0.len == 5); |
| 488 | var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10); | 492 | var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10); |
| 489 | assert(slice1.ptr == slice0.ptr); | 493 | testing.expect(slice1.ptr == slice0.ptr); |
| 490 | assert(slice1.len == 10); | 494 | testing.expect(slice1.len == 10); |
| 491 | debug.assertError(fixed_buffer_allocator.allocator.realloc(u8, slice1, 11), error.OutOfMemory); | 495 | testing.expectError(error.OutOfMemory, fixed_buffer_allocator.allocator.realloc(u8, slice1, 11)); |
| 492 | } | 496 | } |
| 493 | // check that we don't re-use the memory if it's not the most recent block | 497 | // check that we don't re-use the memory if it's not the most recent block |
| 494 | { | 498 | { |
| ... | @@ -499,10 +503,10 @@ test "FixedBufferAllocator Reuse memory on realloc" { | ... | @@ -499,10 +503,10 @@ test "FixedBufferAllocator Reuse memory on realloc" { |
| 499 | slice0[1] = 2; | 503 | slice0[1] = 2; |
| 500 | var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2); | 504 | var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2); |
| 501 | var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4); | 505 | var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4); |
| 502 | assert(slice0.ptr != slice2.ptr); | 506 | testing.expect(slice0.ptr != slice2.ptr); |
| 503 | assert(slice1.ptr != slice2.ptr); | 507 | testing.expect(slice1.ptr != slice2.ptr); |
| 504 | assert(slice2[0] == 1); | 508 | testing.expect(slice2[0] == 1); |
| 505 | assert(slice2[1] == 2); | 509 | testing.expect(slice2[1] == 2); |
| 506 | } | 510 | } |
| 507 | } | 511 | } |
| 508 | 512 | ||
| ... | @@ -516,27 +520,28 @@ test "ThreadSafeFixedBufferAllocator" { | ... | @@ -516,27 +520,28 @@ test "ThreadSafeFixedBufferAllocator" { |
| 516 | 520 | ||
| 517 | fn testAllocator(allocator: *mem.Allocator) !void { | 521 | fn testAllocator(allocator: *mem.Allocator) !void { |
| 518 | var slice = try allocator.alloc(*i32, 100); | 522 | var slice = try allocator.alloc(*i32, 100); |
| 519 | assert(slice.len == 100); | 523 | testing.expect(slice.len == 100); |
| 520 | for (slice) |*item, i| { | 524 | for (slice) |*item, i| { |
| 521 | item.* = try allocator.create(@intCast(i32, i)); | 525 | item.* = try allocator.create(i32); |
| 526 | item.*.* = @intCast(i32, i); | ||
| 522 | } | 527 | } |
| 523 | 528 | ||
| 524 | slice = try allocator.realloc(*i32, slice, 20000); | 529 | slice = try allocator.realloc(*i32, slice, 20000); |
| 525 | assert(slice.len == 20000); | 530 | testing.expect(slice.len == 20000); |
| 526 | 531 | ||
| 527 | for (slice[0..100]) |item, i| { | 532 | for (slice[0..100]) |item, i| { |
| 528 | assert(item.* == @intCast(i32, i)); | 533 | testing.expect(item.* == @intCast(i32, i)); |
| 529 | allocator.destroy(item); | 534 | allocator.destroy(item); |
| 530 | } | 535 | } |
| 531 | 536 | ||
| 532 | slice = try allocator.realloc(*i32, slice, 50); | 537 | slice = try allocator.realloc(*i32, slice, 50); |
| 533 | assert(slice.len == 50); | 538 | testing.expect(slice.len == 50); |
| 534 | slice = try allocator.realloc(*i32, slice, 25); | 539 | slice = try allocator.realloc(*i32, slice, 25); |
| 535 | assert(slice.len == 25); | 540 | testing.expect(slice.len == 25); |
| 536 | slice = try allocator.realloc(*i32, slice, 0); | 541 | slice = try allocator.realloc(*i32, slice, 0); |
| 537 | assert(slice.len == 0); | 542 | testing.expect(slice.len == 0); |
| 538 | slice = try allocator.realloc(*i32, slice, 10); | 543 | slice = try allocator.realloc(*i32, slice, 10); |
| 539 | assert(slice.len == 10); | 544 | testing.expect(slice.len == 10); |
| 540 | 545 | ||
| 541 | allocator.free(slice); | 546 | allocator.free(slice); |
| 542 | } | 547 | } |
| ... | @@ -544,25 +549,25 @@ fn testAllocator(allocator: *mem.Allocator) !void { | ... | @@ -544,25 +549,25 @@ fn testAllocator(allocator: *mem.Allocator) !void { |
| 544 | fn testAllocatorAligned(allocator: *mem.Allocator, comptime alignment: u29) !void { | 549 | fn testAllocatorAligned(allocator: *mem.Allocator, comptime alignment: u29) !void { |
| 545 | // initial | 550 | // initial |
| 546 | var slice = try allocator.alignedAlloc(u8, alignment, 10); | 551 | var slice = try allocator.alignedAlloc(u8, alignment, 10); |
| 547 | assert(slice.len == 10); | 552 | testing.expect(slice.len == 10); |
| 548 | // grow | 553 | // grow |
| 549 | slice = try allocator.alignedRealloc(u8, alignment, slice, 100); | 554 | slice = try allocator.alignedRealloc(u8, alignment, slice, 100); |
| 550 | assert(slice.len == 100); | 555 | testing.expect(slice.len == 100); |
| 551 | // shrink | 556 | // shrink |
| 552 | slice = try allocator.alignedRealloc(u8, alignment, slice, 10); | 557 | slice = try allocator.alignedRealloc(u8, alignment, slice, 10); |
| 553 | assert(slice.len == 10); | 558 | testing.expect(slice.len == 10); |
| 554 | // go to zero | 559 | // go to zero |
| 555 | slice = try allocator.alignedRealloc(u8, alignment, slice, 0); | 560 | slice = try allocator.alignedRealloc(u8, alignment, slice, 0); |
| 556 | assert(slice.len == 0); | 561 | testing.expect(slice.len == 0); |
| 557 | // realloc from zero | 562 | // realloc from zero |
| 558 | slice = try allocator.alignedRealloc(u8, alignment, slice, 100); | 563 | slice = try allocator.alignedRealloc(u8, alignment, slice, 100); |
| 559 | assert(slice.len == 100); | 564 | testing.expect(slice.len == 100); |
| 560 | // shrink with shrink | 565 | // shrink with shrink |
| 561 | slice = allocator.alignedShrink(u8, alignment, slice, 10); | 566 | slice = allocator.alignedShrink(u8, alignment, slice, 10); |
| 562 | assert(slice.len == 10); | 567 | testing.expect(slice.len == 10); |
| 563 | // shrink to zero | 568 | // shrink to zero |
| 564 | slice = allocator.alignedShrink(u8, alignment, slice, 0); | 569 | slice = allocator.alignedShrink(u8, alignment, slice, 0); |
| 565 | assert(slice.len == 0); | 570 | testing.expect(slice.len == 0); |
| 566 | } | 571 | } |
| 567 | 572 | ||
| 568 | fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!void { | 573 | fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!void { |
| ... | @@ -577,19 +582,19 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo | ... | @@ -577,19 +582,19 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo |
| 577 | _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask); | 582 | _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask); |
| 578 | 583 | ||
| 579 | var slice = try allocator.allocFn(allocator, 500, large_align); | 584 | var slice = try allocator.allocFn(allocator, 500, large_align); |
| 580 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); | 585 | testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 581 | 586 | ||
| 582 | slice = try allocator.reallocFn(allocator, slice, 100, large_align); | 587 | slice = try allocator.reallocFn(allocator, slice, 100, large_align); |
| 583 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); | 588 | testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 584 | 589 | ||
| 585 | slice = try allocator.reallocFn(allocator, slice, 5000, large_align); | 590 | slice = try allocator.reallocFn(allocator, slice, 5000, large_align); |
| 586 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); | 591 | testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 587 | 592 | ||
| 588 | slice = try allocator.reallocFn(allocator, slice, 10, large_align); | 593 | slice = try allocator.reallocFn(allocator, slice, 10, large_align); |
| 589 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); | 594 | testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 590 | 595 | ||
| 591 | slice = try allocator.reallocFn(allocator, slice, 20000, large_align); | 596 | slice = try allocator.reallocFn(allocator, slice, 20000, large_align); |
| 592 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); | 597 | testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 593 | 598 | ||
| 594 | allocator.free(slice); | 599 | allocator.free(slice); |
| 595 | } | 600 | } |
std/index.zig+12-8| ... | @@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib; | ... | @@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib; |
| 9 | pub const HashMap = @import("hash_map.zig").HashMap; | 9 | pub const HashMap = @import("hash_map.zig").HashMap; |
| 10 | pub const LinkedList = @import("linked_list.zig").LinkedList; | 10 | pub const LinkedList = @import("linked_list.zig").LinkedList; |
| 11 | pub const Mutex = @import("mutex.zig").Mutex; | 11 | pub const Mutex = @import("mutex.zig").Mutex; |
| 12 | pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex; | ||
| 12 | pub const SegmentedList = @import("segmented_list.zig").SegmentedList; | 13 | pub const SegmentedList = @import("segmented_list.zig").SegmentedList; |
| 13 | pub const SpinLock = @import("spinlock.zig").SpinLock; | 14 | pub const SpinLock = @import("spinlock.zig").SpinLock; |
| 14 | 15 | ||
| ... | @@ -30,21 +31,21 @@ pub const hash_map = @import("hash_map.zig"); | ... | @@ -30,21 +31,21 @@ pub const hash_map = @import("hash_map.zig"); |
| 30 | pub const heap = @import("heap.zig"); | 31 | pub const heap = @import("heap.zig"); |
| 31 | pub const io = @import("io.zig"); | 32 | pub const io = @import("io.zig"); |
| 32 | pub const json = @import("json.zig"); | 33 | pub const json = @import("json.zig"); |
| 34 | pub const lazyInit = @import("lazy_init.zig").lazyInit; | ||
| 33 | pub const macho = @import("macho.zig"); | 35 | pub const macho = @import("macho.zig"); |
| 34 | pub const math = @import("math/index.zig"); | 36 | pub const math = @import("math/index.zig"); |
| 35 | pub const meta = @import("meta/index.zig"); | ||
| 36 | pub const mem = @import("mem.zig"); | 37 | pub const mem = @import("mem.zig"); |
| 38 | pub const meta = @import("meta/index.zig"); | ||
| 37 | pub const net = @import("net.zig"); | 39 | pub const net = @import("net.zig"); |
| 38 | pub const os = @import("os/index.zig"); | 40 | pub const os = @import("os/index.zig"); |
| 39 | pub const pdb = @import("pdb.zig"); | 41 | pub const pdb = @import("pdb.zig"); |
| 40 | pub const rand = @import("rand/index.zig"); | 42 | pub const rand = @import("rand/index.zig"); |
| 41 | pub const rb = @import("rb.zig"); | 43 | pub const rb = @import("rb.zig"); |
| 42 | pub const sort = @import("sort.zig"); | 44 | pub const sort = @import("sort.zig"); |
| 45 | pub const testing = @import("testing.zig"); | ||
| 43 | pub const unicode = @import("unicode.zig"); | 46 | pub const unicode = @import("unicode.zig"); |
| 44 | pub const zig = @import("zig/index.zig"); | 47 | pub const zig = @import("zig/index.zig"); |
| 45 | 48 | ||
| 46 | pub const lazyInit = @import("lazy_init.zig").lazyInit; | ||
| 47 | |||
| 48 | test "std" { | 49 | test "std" { |
| 49 | // run tests from these | 50 | // run tests from these |
| 50 | _ = @import("array_list.zig"); | 51 | _ = @import("array_list.zig"); |
| ... | @@ -55,9 +56,10 @@ test "std" { | ... | @@ -55,9 +56,10 @@ test "std" { |
| 55 | _ = @import("hash_map.zig"); | 56 | _ = @import("hash_map.zig"); |
| 56 | _ = @import("linked_list.zig"); | 57 | _ = @import("linked_list.zig"); |
| 57 | _ = @import("mutex.zig"); | 58 | _ = @import("mutex.zig"); |
| 59 | _ = @import("statically_initialized_mutex.zig"); | ||
| 58 | _ = @import("segmented_list.zig"); | 60 | _ = @import("segmented_list.zig"); |
| 59 | _ = @import("spinlock.zig"); | 61 | _ = @import("spinlock.zig"); |
| 60 | 62 | ||
| 61 | _ = @import("base64.zig"); | 63 | _ = @import("base64.zig"); |
| 62 | _ = @import("build.zig"); | 64 | _ = @import("build.zig"); |
| 63 | _ = @import("c/index.zig"); | 65 | _ = @import("c/index.zig"); |
| ... | @@ -66,24 +68,26 @@ test "std" { | ... | @@ -66,24 +68,26 @@ test "std" { |
| 66 | _ = @import("cstr.zig"); | 68 | _ = @import("cstr.zig"); |
| 67 | _ = @import("debug/index.zig"); | 69 | _ = @import("debug/index.zig"); |
| 68 | _ = @import("dwarf.zig"); | 70 | _ = @import("dwarf.zig"); |
| 71 | _ = @import("dynamic_library.zig"); | ||
| 69 | _ = @import("elf.zig"); | 72 | _ = @import("elf.zig"); |
| 70 | _ = @import("empty.zig"); | 73 | _ = @import("empty.zig"); |
| 71 | _ = @import("event.zig"); | 74 | _ = @import("event.zig"); |
| 72 | _ = @import("fmt/index.zig"); | 75 | _ = @import("fmt/index.zig"); |
| 73 | _ = @import("hash/index.zig"); | 76 | _ = @import("hash/index.zig"); |
| 77 | _ = @import("heap.zig"); | ||
| 74 | _ = @import("io.zig"); | 78 | _ = @import("io.zig"); |
| 75 | _ = @import("json.zig"); | 79 | _ = @import("json.zig"); |
| 80 | _ = @import("lazy_init.zig"); | ||
| 76 | _ = @import("macho.zig"); | 81 | _ = @import("macho.zig"); |
| 77 | _ = @import("math/index.zig"); | 82 | _ = @import("math/index.zig"); |
| 78 | _ = @import("meta/index.zig"); | ||
| 79 | _ = @import("mem.zig"); | 83 | _ = @import("mem.zig"); |
| 84 | _ = @import("meta/index.zig"); | ||
| 80 | _ = @import("net.zig"); | 85 | _ = @import("net.zig"); |
| 81 | _ = @import("heap.zig"); | ||
| 82 | _ = @import("os/index.zig"); | 86 | _ = @import("os/index.zig"); |
| 83 | _ = @import("rand/index.zig"); | ||
| 84 | _ = @import("pdb.zig"); | 87 | _ = @import("pdb.zig"); |
| 88 | _ = @import("rand/index.zig"); | ||
| 85 | _ = @import("sort.zig"); | 89 | _ = @import("sort.zig"); |
| 90 | _ = @import("testing.zig"); | ||
| 86 | _ = @import("unicode.zig"); | 91 | _ = @import("unicode.zig"); |
| 87 | _ = @import("zig/index.zig"); | 92 | _ = @import("zig/index.zig"); |
| 88 | _ = @import("lazy_init.zig"); | ||
| 89 | } | 93 | } |
std/io.zig+751-53| ... | @@ -8,9 +8,12 @@ const debug = std.debug; | ... | @@ -8,9 +8,12 @@ const debug = std.debug; |
| 8 | const assert = debug.assert; | 8 | const assert = debug.assert; |
| 9 | const os = std.os; | 9 | const os = std.os; |
| 10 | const mem = std.mem; | 10 | const mem = std.mem; |
| 11 | const meta = std.meta; | ||
| 12 | const trait = meta.trait; | ||
| 11 | const Buffer = std.Buffer; | 13 | const Buffer = std.Buffer; |
| 12 | const fmt = std.fmt; | 14 | const fmt = std.fmt; |
| 13 | const File = std.os.File; | 15 | const File = std.os.File; |
| 16 | const testing = std.testing; | ||
| 14 | 17 | ||
| 15 | const is_posix = builtin.os != builtin.Os.windows; | 18 | const is_posix = builtin.os != builtin.Os.windows; |
| 16 | const is_windows = builtin.os == builtin.Os.windows; | 19 | const is_windows = builtin.os == builtin.Os.windows; |
| ... | @@ -152,35 +155,43 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -152,35 +155,43 @@ pub fn InStream(comptime ReadError: type) type { |
| 152 | } | 155 | } |
| 153 | 156 | ||
| 154 | /// Reads a native-endian integer | 157 | /// Reads a native-endian integer |
| 155 | pub fn readIntNe(self: *Self, comptime T: type) !T { | 158 | pub fn readIntNative(self: *Self, comptime T: type) !T { |
| 156 | return self.readInt(builtin.endian, T); | 159 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 160 | try self.readNoEof(bytes[0..]); | ||
| 161 | return mem.readIntNative(T, &bytes); | ||
| 157 | } | 162 | } |
| 158 | 163 | ||
| 159 | pub fn readIntLe(self: *Self, comptime T: type) !T { | 164 | /// Reads a foreign-endian integer |
| 165 | pub fn readIntForeign(self: *Self, comptime T: type) !T { | ||
| 160 | var bytes: [@sizeOf(T)]u8 = undefined; | 166 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 161 | try self.readNoEof(bytes[0..]); | 167 | try self.readNoEof(bytes[0..]); |
| 162 | return mem.readIntLE(T, bytes); | 168 | return mem.readIntForeign(T, &bytes); |
| 163 | } | 169 | } |
| 164 | 170 | ||
| 165 | pub fn readIntBe(self: *Self, comptime T: type) !T { | 171 | pub fn readIntLittle(self: *Self, comptime T: type) !T { |
| 166 | var bytes: [@sizeOf(T)]u8 = undefined; | 172 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 167 | try self.readNoEof(bytes[0..]); | 173 | try self.readNoEof(bytes[0..]); |
| 168 | return mem.readIntBE(T, bytes); | 174 | return mem.readIntLittle(T, &bytes); |
| 169 | } | 175 | } |
| 170 | 176 | ||
| 171 | pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T { | 177 | pub fn readIntBig(self: *Self, comptime T: type) !T { |
| 172 | var bytes: [@sizeOf(T)]u8 = undefined; | 178 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 173 | try self.readNoEof(bytes[0..]); | 179 | try self.readNoEof(bytes[0..]); |
| 174 | return mem.readInt(bytes, T, endian); | 180 | return mem.readIntBig(T, &bytes); |
| 175 | } | 181 | } |
| 176 | 182 | ||
| 177 | pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T { | 183 | pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { |
| 178 | assert(size <= @sizeOf(T)); | 184 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 179 | assert(size <= 8); | 185 | try self.readNoEof(bytes[0..]); |
| 180 | var input_buf: [8]u8 = undefined; | 186 | return mem.readInt(T, &bytes, endian); |
| 181 | const input_slice = input_buf[0..size]; | 187 | } |
| 182 | try self.readNoEof(input_slice); | 188 | |
| 183 | return mem.readInt(input_slice, T, endian); | 189 | pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { |
| 190 | assert(size <= @sizeOf(ReturnType)); | ||
| 191 | var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; | ||
| 192 | const bytes = bytes_buf[0..size]; | ||
| 193 | try self.readNoEof(bytes); | ||
| 194 | return mem.readVarInt(ReturnType, bytes, endian); | ||
| 184 | } | 195 | } |
| 185 | 196 | ||
| 186 | pub fn skipBytes(self: *Self, num_bytes: usize) !void { | 197 | pub fn skipBytes(self: *Self, num_bytes: usize) !void { |
| ... | @@ -229,25 +240,34 @@ pub fn OutStream(comptime WriteError: type) type { | ... | @@ -229,25 +240,34 @@ pub fn OutStream(comptime WriteError: type) type { |
| 229 | } | 240 | } |
| 230 | 241 | ||
| 231 | /// Write a native-endian integer. | 242 | /// Write a native-endian integer. |
| 232 | pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void { | 243 | pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void { |
| 233 | return self.writeInt(builtin.endian, T, value); | 244 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 245 | mem.writeIntNative(T, &bytes, value); | ||
| 246 | return self.writeFn(self, bytes); | ||
| 247 | } | ||
| 248 | |||
| 249 | /// Write a foreign-endian integer. | ||
| 250 | pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void { | ||
| 251 | var bytes: [@sizeOf(T)]u8 = undefined; | ||
| 252 | mem.writeIntForeign(T, &bytes, value); | ||
| 253 | return self.writeFn(self, bytes); | ||
| 234 | } | 254 | } |
| 235 | 255 | ||
| 236 | pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void { | 256 | pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void { |
| 237 | var bytes: [@sizeOf(T)]u8 = undefined; | 257 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 238 | mem.writeIntLE(T, &bytes, value); | 258 | mem.writeIntLittle(T, &bytes, value); |
| 239 | return self.writeFn(self, bytes); | 259 | return self.writeFn(self, bytes); |
| 240 | } | 260 | } |
| 241 | 261 | ||
| 242 | pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void { | 262 | pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void { |
| 243 | var bytes: [@sizeOf(T)]u8 = undefined; | 263 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 244 | mem.writeIntBE(T, &bytes, value); | 264 | mem.writeIntBig(T, &bytes, value); |
| 245 | return self.writeFn(self, bytes); | 265 | return self.writeFn(self, bytes); |
| 246 | } | 266 | } |
| 247 | 267 | ||
| 248 | pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void { | 268 | pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void { |
| 249 | var bytes: [@sizeOf(T)]u8 = undefined; | 269 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 250 | mem.writeInt(bytes[0..], value, endian); | 270 | mem.writeInt(T, &bytes, value, endian); |
| 251 | return self.writeFn(self, bytes); | 271 | return self.writeFn(self, bytes); |
| 252 | } | 272 | } |
| 253 | }; | 273 | }; |
| ... | @@ -323,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) | ... | @@ -323,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) |
| 323 | const amt_buffered = self.end_index - self.start_index; | 343 | const amt_buffered = self.end_index - self.start_index; |
| 324 | if (amt_buffered == 0) { | 344 | if (amt_buffered == 0) { |
| 325 | assert(self.end_index <= buffer_size); | 345 | assert(self.end_index <= buffer_size); |
| 326 | if (self.end_index == buffer_size) { | 346 | // Make sure the last read actually gave us some data |
| 327 | // we can read more data from the unbuffered stream | 347 | if (self.end_index == 0) { |
| 328 | if (dest_space < buffer_size) { | 348 | // reading from the unbuffered stream returned nothing |
| 329 | self.start_index = 0; | 349 | // so we have nothing left to read. |
| 330 | self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]); | ||
| 331 | } else { | ||
| 332 | // asking for so much data that buffering is actually less efficient. | ||
| 333 | // forward the request directly to the unbuffered stream | ||
| 334 | const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]); | ||
| 335 | return dest_index + amt_read; | ||
| 336 | } | ||
| 337 | } else { | ||
| 338 | // reading from the unbuffered stream returned less than we asked for | ||
| 339 | // so we cannot read any more data. | ||
| 340 | return dest_index; | 350 | return dest_index; |
| 341 | } | 351 | } |
| 352 | // we can read more data from the unbuffered stream | ||
| 353 | if (dest_space < buffer_size) { | ||
| 354 | self.start_index = 0; | ||
| 355 | self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]); | ||
| 356 | } else { | ||
| 357 | // asking for so much data that buffering is actually less efficient. | ||
| 358 | // forward the request directly to the unbuffered stream | ||
| 359 | const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]); | ||
| 360 | return dest_index + amt_read; | ||
| 361 | } | ||
| 342 | } | 362 | } |
| 363 | |||
| 343 | const copy_amount = math.min(dest_space, amt_buffered); | 364 | const copy_amount = math.min(dest_space, amt_buffered); |
| 344 | const copy_end_index = self.start_index + copy_amount; | 365 | const copy_end_index = self.start_index + copy_amount; |
| 345 | mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]); | 366 | mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]); |
| ... | @@ -350,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) | ... | @@ -350,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) |
| 350 | }; | 371 | }; |
| 351 | } | 372 | } |
| 352 | 373 | ||
| 374 | test "io.BufferedInStream" { | ||
| 375 | const OneByteReadInStream = struct { | ||
| 376 | const Error = error{NoError}; | ||
| 377 | const Stream = InStream(Error); | ||
| 378 | |||
| 379 | stream: Stream, | ||
| 380 | str: []const u8, | ||
| 381 | curr: usize, | ||
| 382 | |||
| 383 | fn init(str: []const u8) @This() { | ||
| 384 | return @This(){ | ||
| 385 | .stream = Stream{ .readFn = readFn }, | ||
| 386 | .str = str, | ||
| 387 | .curr = 0, | ||
| 388 | }; | ||
| 389 | } | ||
| 390 | |||
| 391 | fn readFn(in_stream: *Stream, dest: []u8) Error!usize { | ||
| 392 | const self = @fieldParentPtr(@This(), "stream", in_stream); | ||
| 393 | if (self.str.len <= self.curr or dest.len == 0) | ||
| 394 | return 0; | ||
| 395 | |||
| 396 | dest[0] = self.str[self.curr]; | ||
| 397 | self.curr += 1; | ||
| 398 | return 1; | ||
| 399 | } | ||
| 400 | }; | ||
| 401 | |||
| 402 | var buf: [100]u8 = undefined; | ||
| 403 | const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; | ||
| 404 | |||
| 405 | const str = "This is a test"; | ||
| 406 | var one_byte_stream = OneByteReadInStream.init(str); | ||
| 407 | var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream); | ||
| 408 | const stream = &buf_in_stream.stream; | ||
| 409 | |||
| 410 | const res = try stream.readAllAlloc(allocator, str.len + 1); | ||
| 411 | testing.expectEqualSlices(u8, str, res); | ||
| 412 | } | ||
| 413 | |||
| 353 | /// Creates a stream which supports 'un-reading' data, so that it can be read again. | 414 | /// Creates a stream which supports 'un-reading' data, so that it can be read again. |
| 354 | /// This makes look-ahead style parsing much easier. | 415 | /// This makes look-ahead style parsing much easier. |
| 355 | pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type { | 416 | pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type { |
| ... | @@ -446,6 +507,153 @@ pub const SliceInStream = struct { | ... | @@ -446,6 +507,153 @@ pub const SliceInStream = struct { |
| 446 | } | 507 | } |
| 447 | }; | 508 | }; |
| 448 | 509 | ||
| 510 | /// Creates a stream which allows for reading bit fields from another stream | ||
| 511 | pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type { | ||
| 512 | return struct { | ||
| 513 | const Self = @This(); | ||
| 514 | |||
| 515 | in_stream: *Stream, | ||
| 516 | bit_buffer: u7, | ||
| 517 | bit_count: u3, | ||
| 518 | stream: Stream, | ||
| 519 | |||
| 520 | pub const Stream = InStream(Error); | ||
| 521 | const u8_bit_count = comptime meta.bitCount(u8); | ||
| 522 | const u7_bit_count = comptime meta.bitCount(u7); | ||
| 523 | const u4_bit_count = comptime meta.bitCount(u4); | ||
| 524 | |||
| 525 | pub fn init(in_stream: *Stream) Self { | ||
| 526 | return Self{ | ||
| 527 | .in_stream = in_stream, | ||
| 528 | .bit_buffer = 0, | ||
| 529 | .bit_count = 0, | ||
| 530 | .stream = Stream{ .readFn = read }, | ||
| 531 | }; | ||
| 532 | } | ||
| 533 | |||
| 534 | /// Reads `bits` bits from the stream and returns a specified unsigned int type | ||
| 535 | /// containing them in the least significant end, returning an error if the | ||
| 536 | /// specified number of bits could not be read. | ||
| 537 | pub fn readBitsNoEof(self: *Self, comptime U: type, bits: usize) !U { | ||
| 538 | var n: usize = undefined; | ||
| 539 | const result = try self.readBits(U, bits, &n); | ||
| 540 | if (n < bits) return error.EndOfStream; | ||
| 541 | return result; | ||
| 542 | } | ||
| 543 | |||
| 544 | /// Reads `bits` bits from the stream and returns a specified unsigned int type | ||
| 545 | /// containing them in the least significant end. The number of bits successfully | ||
| 546 | /// read is placed in `out_bits`, as reaching the end of the stream is not an error. | ||
| 547 | pub fn readBits(self: *Self, comptime U: type, bits: usize, out_bits: *usize) Error!U { | ||
| 548 | comptime assert(trait.isUnsignedInt(U)); | ||
| 549 | |||
| 550 | //by extending the buffer to a minimum of u8 we can cover a number of edge cases | ||
| 551 | // related to shifting and casting. | ||
| 552 | const u_bit_count = comptime meta.bitCount(U); | ||
| 553 | const buf_bit_count = bc: { | ||
| 554 | assert(u_bit_count >= bits); | ||
| 555 | break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count; | ||
| 556 | }; | ||
| 557 | const Buf = @IntType(false, buf_bit_count); | ||
| 558 | const BufShift = math.Log2Int(Buf); | ||
| 559 | |||
| 560 | out_bits.* = usize(0); | ||
| 561 | if (U == u0 or bits == 0) return 0; | ||
| 562 | var out_buffer = Buf(0); | ||
| 563 | |||
| 564 | if (self.bit_count > 0) { | ||
| 565 | const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count; | ||
| 566 | const shift = u7_bit_count - n; | ||
| 567 | switch (endian) { | ||
| 568 | builtin.Endian.Big => { | ||
| 569 | out_buffer = Buf(self.bit_buffer >> shift); | ||
| 570 | self.bit_buffer <<= n; | ||
| 571 | }, | ||
| 572 | builtin.Endian.Little => { | ||
| 573 | const value = (self.bit_buffer << shift) >> shift; | ||
| 574 | out_buffer = Buf(value); | ||
| 575 | self.bit_buffer >>= n; | ||
| 576 | }, | ||
| 577 | } | ||
| 578 | self.bit_count -= n; | ||
| 579 | out_bits.* = n; | ||
| 580 | } | ||
| 581 | //at this point we know bit_buffer is empty | ||
| 582 | |||
| 583 | //copy bytes until we have enough bits, then leave the rest in bit_buffer | ||
| 584 | while (out_bits.* < bits) { | ||
| 585 | const n = bits - out_bits.*; | ||
| 586 | const next_byte = self.in_stream.readByte() catch |err| { | ||
| 587 | if (err == error.EndOfStream) { | ||
| 588 | return @intCast(U, out_buffer); | ||
| 589 | } | ||
| 590 | //@BUG: See #1810. Not sure if the bug is that I have to do this for some | ||
| 591 | // streams, or that I don't for streams with emtpy errorsets. | ||
| 592 | return @errSetCast(Error, err); | ||
| 593 | }; | ||
| 594 | |||
| 595 | switch (endian) { | ||
| 596 | builtin.Endian.Big => { | ||
| 597 | if (n >= u8_bit_count) { | ||
| 598 | out_buffer <<= @intCast(u3, u8_bit_count - 1); | ||
| 599 | out_buffer <<= 1; | ||
| 600 | out_buffer |= Buf(next_byte); | ||
| 601 | out_bits.* += u8_bit_count; | ||
| 602 | continue; | ||
| 603 | } | ||
| 604 | |||
| 605 | const shift = @intCast(u3, u8_bit_count - n); | ||
| 606 | out_buffer <<= @intCast(BufShift, n); | ||
| 607 | out_buffer |= Buf(next_byte >> shift); | ||
| 608 | out_bits.* += n; | ||
| 609 | self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1)); | ||
| 610 | self.bit_count = shift; | ||
| 611 | }, | ||
| 612 | builtin.Endian.Little => { | ||
| 613 | if (n >= u8_bit_count) { | ||
| 614 | out_buffer |= Buf(next_byte) << @intCast(BufShift, out_bits.*); | ||
| 615 | out_bits.* += u8_bit_count; | ||
| 616 | continue; | ||
| 617 | } | ||
| 618 | |||
| 619 | const shift = @intCast(u3, u8_bit_count - n); | ||
| 620 | const value = (next_byte << shift) >> shift; | ||
| 621 | out_buffer |= Buf(value) << @intCast(BufShift, out_bits.*); | ||
| 622 | out_bits.* += n; | ||
| 623 | self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n)); | ||
| 624 | self.bit_count = shift; | ||
| 625 | }, | ||
| 626 | } | ||
| 627 | } | ||
| 628 | |||
| 629 | return @intCast(U, out_buffer); | ||
| 630 | } | ||
| 631 | |||
| 632 | pub fn alignToByte(self: *Self) void { | ||
| 633 | self.bit_buffer = 0; | ||
| 634 | self.bit_count = 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | pub fn read(self_stream: *Stream, buffer: []u8) Error!usize { | ||
| 638 | var self = @fieldParentPtr(Self, "stream", self_stream); | ||
| 639 | |||
| 640 | var out_bits: usize = undefined; | ||
| 641 | var out_bits_total = usize(0); | ||
| 642 | //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced | ||
| 643 | if (self.bit_count > 0) { | ||
| 644 | for (buffer) |*b, i| { | ||
| 645 | b.* = try self.readBits(u8, u8_bit_count, &out_bits); | ||
| 646 | out_bits_total += out_bits; | ||
| 647 | } | ||
| 648 | const incomplete_byte = @boolToInt(out_bits_total % u8_bit_count > 0); | ||
| 649 | return (out_bits_total / u8_bit_count) + incomplete_byte; | ||
| 650 | } | ||
| 651 | |||
| 652 | return self.in_stream.read(buffer); | ||
| 653 | } | ||
| 654 | }; | ||
| 655 | } | ||
| 656 | |||
| 449 | /// This is a simple OutStream that writes to a slice, and returns an error | 657 | /// This is a simple OutStream that writes to a slice, and returns an error |
| 450 | /// when it runs out of space. | 658 | /// when it runs out of space. |
| 451 | pub const SliceOutStream = struct { | 659 | pub const SliceOutStream = struct { |
| ... | @@ -498,7 +706,7 @@ test "io.SliceOutStream" { | ... | @@ -498,7 +706,7 @@ test "io.SliceOutStream" { |
| 498 | const stream = &slice_stream.stream; | 706 | const stream = &slice_stream.stream; |
| 499 | 707 | ||
| 500 | try stream.print("{}{}!", "Hello", "World"); | 708 | try stream.print("{}{}!", "Hello", "World"); |
| 501 | debug.assert(mem.eql(u8, "HelloWorld!", slice_stream.getWritten())); | 709 | testing.expectEqualSlices(u8, "HelloWorld!", slice_stream.getWritten()); |
| 502 | } | 710 | } |
| 503 | 711 | ||
| 504 | var null_out_stream_state = NullOutStream.init(); | 712 | var null_out_stream_state = NullOutStream.init(); |
| ... | @@ -560,7 +768,7 @@ test "io.CountingOutStream" { | ... | @@ -560,7 +768,7 @@ test "io.CountingOutStream" { |
| 560 | 768 | ||
| 561 | const bytes = "yay" ** 10000; | 769 | const bytes = "yay" ** 10000; |
| 562 | stream.write(bytes) catch unreachable; | 770 | stream.write(bytes) catch unreachable; |
| 563 | debug.assert(counting_stream.bytes_written == bytes.len); | 771 | testing.expect(counting_stream.bytes_written == bytes.len); |
| 564 | } | 772 | } |
| 565 | 773 | ||
| 566 | pub fn BufferedOutStream(comptime Error: type) type { | 774 | pub fn BufferedOutStream(comptime Error: type) type { |
| ... | @@ -639,6 +847,135 @@ pub const BufferOutStream = struct { | ... | @@ -639,6 +847,135 @@ pub const BufferOutStream = struct { |
| 639 | } | 847 | } |
| 640 | }; | 848 | }; |
| 641 | 849 | ||
| 850 | /// Creates a stream which allows for writing bit fields to another stream | ||
| 851 | pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type { | ||
| 852 | return struct { | ||
| 853 | const Self = @This(); | ||
| 854 | |||
| 855 | out_stream: *Stream, | ||
| 856 | bit_buffer: u8, | ||
| 857 | bit_count: u4, | ||
| 858 | stream: Stream, | ||
| 859 | |||
| 860 | pub const Stream = OutStream(Error); | ||
| 861 | const u8_bit_count = comptime meta.bitCount(u8); | ||
| 862 | const u4_bit_count = comptime meta.bitCount(u4); | ||
| 863 | |||
| 864 | pub fn init(out_stream: *Stream) Self { | ||
| 865 | return Self{ | ||
| 866 | .out_stream = out_stream, | ||
| 867 | .bit_buffer = 0, | ||
| 868 | .bit_count = 0, | ||
| 869 | .stream = Stream{ .writeFn = write }, | ||
| 870 | }; | ||
| 871 | } | ||
| 872 | |||
| 873 | /// Write the specified number of bits to the stream from the least significant bits of | ||
| 874 | /// the specified unsigned int value. Bits will only be written to the stream when there | ||
| 875 | /// are enough to fill a byte. | ||
| 876 | pub fn writeBits(self: *Self, value: var, bits: usize) Error!void { | ||
| 877 | if (bits == 0) return; | ||
| 878 | |||
| 879 | const U = @typeOf(value); | ||
| 880 | comptime assert(trait.isUnsignedInt(U)); | ||
| 881 | |||
| 882 | //by extending the buffer to a minimum of u8 we can cover a number of edge cases | ||
| 883 | // related to shifting and casting. | ||
| 884 | const u_bit_count = comptime meta.bitCount(U); | ||
| 885 | const buf_bit_count = bc: { | ||
| 886 | assert(u_bit_count >= bits); | ||
| 887 | break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count; | ||
| 888 | }; | ||
| 889 | const Buf = @IntType(false, buf_bit_count); | ||
| 890 | const BufShift = math.Log2Int(Buf); | ||
| 891 | |||
| 892 | const buf_value = @intCast(Buf, value); | ||
| 893 | |||
| 894 | const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count); | ||
| 895 | var in_buffer = switch (endian) { | ||
| 896 | builtin.Endian.Big => buf_value << @intCast(BufShift, buf_bit_count - bits), | ||
| 897 | builtin.Endian.Little => buf_value, | ||
| 898 | }; | ||
| 899 | var in_bits = bits; | ||
| 900 | |||
| 901 | if (self.bit_count > 0) { | ||
| 902 | const bits_remaining = u8_bit_count - self.bit_count; | ||
| 903 | const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining); | ||
| 904 | switch (endian) { | ||
| 905 | builtin.Endian.Big => { | ||
| 906 | const shift = @intCast(BufShift, high_byte_shift + self.bit_count); | ||
| 907 | const v = @intCast(u8, in_buffer >> shift); | ||
| 908 | self.bit_buffer |= v; | ||
| 909 | in_buffer <<= n; | ||
| 910 | }, | ||
| 911 | builtin.Endian.Little => { | ||
| 912 | const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count); | ||
| 913 | self.bit_buffer |= v; | ||
| 914 | in_buffer >>= n; | ||
| 915 | }, | ||
| 916 | } | ||
| 917 | self.bit_count += n; | ||
| 918 | in_bits -= n; | ||
| 919 | |||
| 920 | //if we didn't fill the buffer, it's because bits < bits_remaining; | ||
| 921 | if (self.bit_count != u8_bit_count) return; | ||
| 922 | try self.out_stream.writeByte(self.bit_buffer); | ||
| 923 | self.bit_buffer = 0; | ||
| 924 | self.bit_count = 0; | ||
| 925 | } | ||
| 926 | //at this point we know bit_buffer is empty | ||
| 927 | |||
| 928 | //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer | ||
| 929 | while (in_bits >= u8_bit_count) { | ||
| 930 | switch (endian) { | ||
| 931 | builtin.Endian.Big => { | ||
| 932 | const v = @intCast(u8, in_buffer >> high_byte_shift); | ||
| 933 | try self.out_stream.writeByte(v); | ||
| 934 | in_buffer <<= @intCast(u3, u8_bit_count - 1); | ||
| 935 | in_buffer <<= 1; | ||
| 936 | }, | ||
| 937 | builtin.Endian.Little => { | ||
| 938 | const v = @truncate(u8, in_buffer); | ||
| 939 | try self.out_stream.writeByte(v); | ||
| 940 | in_buffer >>= @intCast(u3, u8_bit_count - 1); | ||
| 941 | in_buffer >>= 1; | ||
| 942 | }, | ||
| 943 | } | ||
| 944 | in_bits -= u8_bit_count; | ||
| 945 | } | ||
| 946 | |||
| 947 | if (in_bits > 0) { | ||
| 948 | self.bit_count = @intCast(u4, in_bits); | ||
| 949 | self.bit_buffer = switch (endian) { | ||
| 950 | builtin.Endian.Big => @truncate(u8, in_buffer >> high_byte_shift), | ||
| 951 | builtin.Endian.Little => @truncate(u8, in_buffer), | ||
| 952 | }; | ||
| 953 | } | ||
| 954 | } | ||
| 955 | |||
| 956 | /// Flush any remaining bits to the stream. | ||
| 957 | pub fn flushBits(self: *Self) Error!void { | ||
| 958 | if (self.bit_count == 0) return; | ||
| 959 | try self.out_stream.writeByte(self.bit_buffer); | ||
| 960 | self.bit_buffer = 0; | ||
| 961 | self.bit_count = 0; | ||
| 962 | } | ||
| 963 | |||
| 964 | pub fn write(self_stream: *Stream, buffer: []const u8) Error!void { | ||
| 965 | var self = @fieldParentPtr(Self, "stream", self_stream); | ||
| 966 | |||
| 967 | //@NOTE: I'm not sure this is a good idea, maybe flushBits should be forced | ||
| 968 | if (self.bit_count > 0) { | ||
| 969 | for (buffer) |b, i| | ||
| 970 | try self.writeBits(b, u8_bit_count); | ||
| 971 | return; | ||
| 972 | } | ||
| 973 | |||
| 974 | return self.out_stream.write(buffer); | ||
| 975 | } | ||
| 976 | }; | ||
| 977 | } | ||
| 978 | |||
| 642 | pub const BufferedAtomicFile = struct { | 979 | pub const BufferedAtomicFile = struct { |
| 643 | atomic_file: os.AtomicFile, | 980 | atomic_file: os.AtomicFile, |
| 644 | file_stream: os.File.OutStream, | 981 | file_stream: os.File.OutStream, |
| ... | @@ -647,12 +984,13 @@ pub const BufferedAtomicFile = struct { | ... | @@ -647,12 +984,13 @@ pub const BufferedAtomicFile = struct { |
| 647 | 984 | ||
| 648 | pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile { | 985 | pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile { |
| 649 | // TODO with well defined copy elision we don't need this allocation | 986 | // TODO with well defined copy elision we don't need this allocation |
| 650 | var self = try allocator.create(BufferedAtomicFile{ | 987 | var self = try allocator.create(BufferedAtomicFile); |
| 988 | self.* = BufferedAtomicFile{ | ||
| 651 | .atomic_file = undefined, | 989 | .atomic_file = undefined, |
| 652 | .file_stream = undefined, | 990 | .file_stream = undefined, |
| 653 | .buffered_stream = undefined, | 991 | .buffered_stream = undefined, |
| 654 | .allocator = allocator, | 992 | .allocator = allocator, |
| 655 | }); | 993 | }; |
| 656 | errdefer allocator.destroy(self); | 994 | errdefer allocator.destroy(self); |
| 657 | 995 | ||
| 658 | self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode); | 996 | self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode); |
| ... | @@ -679,12 +1017,6 @@ pub const BufferedAtomicFile = struct { | ... | @@ -679,12 +1017,6 @@ pub const BufferedAtomicFile = struct { |
| 679 | } | 1017 | } |
| 680 | }; | 1018 | }; |
| 681 | 1019 | ||
| 682 | test "import io tests" { | ||
| 683 | comptime { | ||
| 684 | _ = @import("io_test.zig"); | ||
| 685 | } | ||
| 686 | } | ||
| 687 | |||
| 688 | pub fn readLine(buf: *std.Buffer) ![]u8 { | 1020 | pub fn readLine(buf: *std.Buffer) ![]u8 { |
| 689 | var stdin = try getStdIn(); | 1021 | var stdin = try getStdIn(); |
| 690 | var stdin_stream = stdin.inStream(); | 1022 | var stdin_stream = stdin.inStream(); |
| ... | @@ -721,10 +1053,10 @@ test "io.readLineFrom" { | ... | @@ -721,10 +1053,10 @@ test "io.readLineFrom" { |
| 721 | ); | 1053 | ); |
| 722 | const stream = &mem_stream.stream; | 1054 | const stream = &mem_stream.stream; |
| 723 | 1055 | ||
| 724 | debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf))); | 1056 | testing.expectEqualSlices(u8, "Line 1", try readLineFrom(stream, &buf)); |
| 725 | debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf))); | 1057 | testing.expectEqualSlices(u8, "Line 22", try readLineFrom(stream, &buf)); |
| 726 | debug.assertError(readLineFrom(stream, &buf), error.EndOfStream); | 1058 | testing.expectError(error.EndOfStream, readLineFrom(stream, &buf)); |
| 727 | debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333")); | 1059 | testing.expectEqualSlices(u8, "Line 1Line 22Line 333", buf.toSlice()); |
| 728 | } | 1060 | } |
| 729 | 1061 | ||
| 730 | pub fn readLineSlice(slice: []u8) ![]u8 { | 1062 | pub fn readLineSlice(slice: []u8) ![]u8 { |
| ... | @@ -752,6 +1084,372 @@ test "io.readLineSliceFrom" { | ... | @@ -752,6 +1084,372 @@ test "io.readLineSliceFrom" { |
| 752 | ); | 1084 | ); |
| 753 | const stream = &mem_stream.stream; | 1085 | const stream = &mem_stream.stream; |
| 754 | 1086 | ||
| 755 | debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..]))); | 1087 | testing.expectEqualSlices(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])); |
| 756 | debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory); | 1088 | testing.expectError(error.OutOfMemory, readLineSliceFrom(stream, buf[0..])); |
| 757 | } | 1089 | } |
| 1090 | |||
| 1091 | /// Creates a deserializer that deserializes types from any stream. | ||
| 1092 | /// If `is_packed` is true, the data stream is treated as bit-packed, | ||
| 1093 | /// otherwise data is expected to be packed to the smallest byte. | ||
| 1094 | /// Types may implement a custom deserialization routine with a | ||
| 1095 | /// function named `deserialize` in the form of: | ||
| 1096 | /// pub fn deserialize(self: *Self, deserializer: var) !void | ||
| 1097 | /// which will be called when the deserializer is used to deserialize | ||
| 1098 | /// that type. It will pass a pointer to the type instance to deserialize | ||
| 1099 | /// into and a pointer to the deserializer struct. | ||
| 1100 | pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime Error: type) type { | ||
| 1101 | return struct { | ||
| 1102 | const Self = @This(); | ||
| 1103 | |||
| 1104 | in_stream: if (is_packed) BitInStream(endian, Stream.Error) else *Stream, | ||
| 1105 | |||
| 1106 | pub const Stream = InStream(Error); | ||
| 1107 | |||
| 1108 | pub fn init(in_stream: *Stream) Self { | ||
| 1109 | return Self{ .in_stream = switch (is_packed) { | ||
| 1110 | true => BitInStream(endian, Stream.Error).init(in_stream), | ||
| 1111 | else => in_stream, | ||
| 1112 | } }; | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | pub fn alignToByte(self: *Self) void { | ||
| 1116 | if (!is_packed) return; | ||
| 1117 | self.in_stream.alignToByte(); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | //@BUG: inferred error issue. See: #1386 | ||
| 1121 | fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T { | ||
| 1122 | comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T)); | ||
| 1123 | |||
| 1124 | const u8_bit_count = 8; | ||
| 1125 | const t_bit_count = comptime meta.bitCount(T); | ||
| 1126 | |||
| 1127 | const U = @IntType(false, t_bit_count); | ||
| 1128 | const Log2U = math.Log2Int(U); | ||
| 1129 | const int_size = (U.bit_count + 7) / 8; | ||
| 1130 | |||
| 1131 | if (is_packed) { | ||
| 1132 | const result = try self.in_stream.readBitsNoEof(U, t_bit_count); | ||
| 1133 | return @bitCast(T, result); | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | var buffer: [int_size]u8 = undefined; | ||
| 1137 | const read_size = try self.in_stream.read(buffer[0..]); | ||
| 1138 | if (read_size < int_size) return error.EndOfStream; | ||
| 1139 | |||
| 1140 | if (int_size == 1) { | ||
| 1141 | if (t_bit_count == 8) return @bitCast(T, buffer[0]); | ||
| 1142 | const PossiblySignedByte = @IntType(T.is_signed, 8); | ||
| 1143 | return @truncate(T, @bitCast(PossiblySignedByte, buffer[0])); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | var result = U(0); | ||
| 1147 | for (buffer) |byte, i| { | ||
| 1148 | switch (endian) { | ||
| 1149 | builtin.Endian.Big => { | ||
| 1150 | result = (result << u8_bit_count) | byte; | ||
| 1151 | }, | ||
| 1152 | builtin.Endian.Little => { | ||
| 1153 | result |= U(byte) << @intCast(Log2U, u8_bit_count * i); | ||
| 1154 | }, | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | return @bitCast(T, result); | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | //@TODO: Replace this with @unionInit or whatever when it is added | ||
| 1162 | // see: #1315 | ||
| 1163 | fn setTag(ptr: var, tag: var) void { | ||
| 1164 | const T = @typeOf(ptr); | ||
| 1165 | comptime assert(trait.isPtrTo(builtin.TypeId.Union)(T)); | ||
| 1166 | const U = meta.Child(T); | ||
| 1167 | |||
| 1168 | const info = @typeInfo(U).Union; | ||
| 1169 | if (info.tag_type) |TagType| { | ||
| 1170 | comptime assert(TagType == @typeOf(tag)); | ||
| 1171 | |||
| 1172 | var ptr_tag = ptr: { | ||
| 1173 | if (@alignOf(TagType) >= @alignOf(U)) break :ptr @ptrCast(*TagType, ptr); | ||
| 1174 | const offset = comptime max: { | ||
| 1175 | var max_field_size: comptime_int = 0; | ||
| 1176 | for (info.fields) |field_info| { | ||
| 1177 | const field_size = @sizeOf(field_info.field_type); | ||
| 1178 | max_field_size = math.max(max_field_size, field_size); | ||
| 1179 | } | ||
| 1180 | break :max math.max(max_field_size, @alignOf(U)); | ||
| 1181 | }; | ||
| 1182 | break :ptr @intToPtr(*TagType, @ptrToInt(ptr) + offset); | ||
| 1183 | }; | ||
| 1184 | ptr_tag.* = tag; | ||
| 1185 | } | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | /// Deserializes and returns data of the specified type from the stream | ||
| 1189 | pub fn deserialize(self: *Self, comptime T: type) !T { | ||
| 1190 | var value: T = undefined; | ||
| 1191 | try self.deserializeInto(&value); | ||
| 1192 | return value; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | /// Deserializes data into the type pointed to by `ptr` | ||
| 1196 | pub fn deserializeInto(self: *Self, ptr: var) !void { | ||
| 1197 | const T = @typeOf(ptr); | ||
| 1198 | comptime assert(trait.is(builtin.TypeId.Pointer)(T)); | ||
| 1199 | |||
| 1200 | if (comptime trait.isSlice(T) or comptime trait.isPtrTo(builtin.TypeId.Array)(T)) { | ||
| 1201 | for (ptr) |*v| | ||
| 1202 | try self.deserializeInto(v); | ||
| 1203 | return; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | comptime assert(trait.isSingleItemPtr(T)); | ||
| 1207 | |||
| 1208 | const C = comptime meta.Child(T); | ||
| 1209 | const child_type_id = @typeId(C); | ||
| 1210 | |||
| 1211 | //custom deserializer: fn(self: *Self, deserializer: var) !void | ||
| 1212 | if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self); | ||
| 1213 | |||
| 1214 | if (comptime trait.isPacked(C) and !is_packed) { | ||
| 1215 | var packed_deserializer = Deserializer(endian, true, Error).init(self.in_stream); | ||
| 1216 | return packed_deserializer.deserializeInto(ptr); | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | switch (child_type_id) { | ||
| 1220 | builtin.TypeId.Void => return, | ||
| 1221 | builtin.TypeId.Bool => ptr.* = (try self.deserializeInt(u1)) > 0, | ||
| 1222 | builtin.TypeId.Float, builtin.TypeId.Int => ptr.* = try self.deserializeInt(C), | ||
| 1223 | builtin.TypeId.Struct => { | ||
| 1224 | const info = @typeInfo(C).Struct; | ||
| 1225 | |||
| 1226 | inline for (info.fields) |*field_info| { | ||
| 1227 | const name = field_info.name; | ||
| 1228 | const FieldType = field_info.field_type; | ||
| 1229 | |||
| 1230 | if (FieldType == void or FieldType == u0) continue; | ||
| 1231 | |||
| 1232 | //it doesn't make any sense to read pointers | ||
| 1233 | if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) { | ||
| 1234 | @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++ | ||
| 1235 | @typeName(C) ++ " because it " ++ "is of pointer-type " ++ | ||
| 1236 | @typeName(FieldType) ++ "."); | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | try self.deserializeInto(&@field(ptr, name)); | ||
| 1240 | } | ||
| 1241 | }, | ||
| 1242 | builtin.TypeId.Union => { | ||
| 1243 | const info = @typeInfo(C).Union; | ||
| 1244 | if (info.tag_type) |TagType| { | ||
| 1245 | //we avoid duplicate iteration over the enum tags | ||
| 1246 | // by getting the int directly and casting it without | ||
| 1247 | // safety. If it is bad, it will be caught anyway. | ||
| 1248 | const TagInt = @TagType(TagType); | ||
| 1249 | const tag = try self.deserializeInt(TagInt); | ||
| 1250 | |||
| 1251 | { | ||
| 1252 | @setRuntimeSafety(false); | ||
| 1253 | //See: #1315 | ||
| 1254 | setTag(ptr, @intToEnum(TagType, tag)); | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | inline for (info.fields) |field_info| { | ||
| 1258 | if (field_info.enum_field.?.value == tag) { | ||
| 1259 | const name = field_info.name; | ||
| 1260 | const FieldType = field_info.field_type; | ||
| 1261 | @field(ptr, name) = FieldType(undefined); | ||
| 1262 | try self.deserializeInto(&@field(ptr, name)); | ||
| 1263 | return; | ||
| 1264 | } | ||
| 1265 | } | ||
| 1266 | //This is reachable if the enum data is bad | ||
| 1267 | return error.InvalidEnumTag; | ||
| 1268 | } | ||
| 1269 | @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++ | ||
| 1270 | " because it is an untagged union Use a custom deserialize()."); | ||
| 1271 | }, | ||
| 1272 | builtin.TypeId.Optional => { | ||
| 1273 | const OC = comptime meta.Child(C); | ||
| 1274 | const exists = (try self.deserializeInt(u1)) > 0; | ||
| 1275 | if (!exists) { | ||
| 1276 | ptr.* = null; | ||
| 1277 | return; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | //The way non-pointer optionals are implemented ensures a pointer to them | ||
| 1281 | // will point to the value. The flag is stored at the end of that data. | ||
| 1282 | var val_ptr = @ptrCast(*OC, ptr); | ||
| 1283 | try self.deserializeInto(val_ptr); | ||
| 1284 | //This bit ensures the null flag isn't set. Any actual copying should be | ||
| 1285 | // optimized out... I hope. | ||
| 1286 | ptr.* = val_ptr.*; | ||
| 1287 | }, | ||
| 1288 | builtin.TypeId.Enum => { | ||
| 1289 | var value = try self.deserializeInt(@TagType(C)); | ||
| 1290 | ptr.* = try meta.intToEnum(C, value); | ||
| 1291 | }, | ||
| 1292 | else => { | ||
| 1293 | @compileError("Cannot deserialize " ++ @tagName(child_type_id) ++ " types (unimplemented)."); | ||
| 1294 | }, | ||
| 1295 | } | ||
| 1296 | } | ||
| 1297 | }; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | /// Creates a serializer that serializes types to any stream. | ||
| 1301 | /// If `is_packed` is true, the data will be bit-packed into the stream. | ||
| 1302 | /// Note that the you must call `serializer.flush()` when you are done | ||
| 1303 | /// writing bit-packed data in order ensure any unwritten bits are committed. | ||
| 1304 | /// If `is_packed` is false, data is packed to the smallest byte. In the case | ||
| 1305 | /// of packed structs, the struct will written bit-packed and with the specified | ||
| 1306 | /// endianess, after which data will resume being written at the next byte boundary. | ||
| 1307 | /// Types may implement a custom serialization routine with a | ||
| 1308 | /// function named `serialize` in the form of: | ||
| 1309 | /// pub fn serialize(self: Self, serializer: var) !void | ||
| 1310 | /// which will be called when the serializer is used to serialize that type. It will | ||
| 1311 | /// pass a const pointer to the type instance to be serialized and a pointer | ||
| 1312 | /// to the serializer struct. | ||
| 1313 | pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, comptime Error: type) type { | ||
| 1314 | return struct { | ||
| 1315 | const Self = @This(); | ||
| 1316 | |||
| 1317 | out_stream: if (is_packed) BitOutStream(endian, Stream.Error) else *Stream, | ||
| 1318 | |||
| 1319 | pub const Stream = OutStream(Error); | ||
| 1320 | |||
| 1321 | pub fn init(out_stream: *Stream) Self { | ||
| 1322 | return Self{ .out_stream = switch (is_packed) { | ||
| 1323 | true => BitOutStream(endian, Stream.Error).init(out_stream), | ||
| 1324 | else => out_stream, | ||
| 1325 | } }; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | /// Flushes any unwritten bits to the stream | ||
| 1329 | pub fn flush(self: *Self) Error!void { | ||
| 1330 | if (is_packed) return self.out_stream.flushBits(); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | fn serializeInt(self: *Self, value: var) Error!void { | ||
| 1334 | const T = @typeOf(value); | ||
| 1335 | comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T)); | ||
| 1336 | |||
| 1337 | const t_bit_count = comptime meta.bitCount(T); | ||
| 1338 | const u8_bit_count = comptime meta.bitCount(u8); | ||
| 1339 | |||
| 1340 | const U = @IntType(false, t_bit_count); | ||
| 1341 | const Log2U = math.Log2Int(U); | ||
| 1342 | const int_size = (U.bit_count + 7) / 8; | ||
| 1343 | |||
| 1344 | const u_value = @bitCast(U, value); | ||
| 1345 | |||
| 1346 | if (is_packed) return self.out_stream.writeBits(u_value, t_bit_count); | ||
| 1347 | |||
| 1348 | var buffer: [int_size]u8 = undefined; | ||
| 1349 | if (int_size == 1) buffer[0] = u_value; | ||
| 1350 | |||
| 1351 | for (buffer) |*byte, i| { | ||
| 1352 | const idx = switch (endian) { | ||
| 1353 | builtin.Endian.Big => int_size - i - 1, | ||
| 1354 | builtin.Endian.Little => i, | ||
| 1355 | }; | ||
| 1356 | const shift = @intCast(Log2U, idx * u8_bit_count); | ||
| 1357 | const v = u_value >> shift; | ||
| 1358 | byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v); | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | try self.out_stream.write(buffer); | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | /// Serializes the passed value into the stream | ||
| 1365 | pub fn serialize(self: *Self, value: var) Error!void { | ||
| 1366 | const T = comptime @typeOf(value); | ||
| 1367 | |||
| 1368 | if (comptime trait.isIndexable(T)) { | ||
| 1369 | for (value) |v| | ||
| 1370 | try self.serialize(v); | ||
| 1371 | return; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | //custom serializer: fn(self: Self, serializer: var) !void | ||
| 1375 | if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self); | ||
| 1376 | |||
| 1377 | if (comptime trait.isPacked(T) and !is_packed) { | ||
| 1378 | var packed_serializer = Serializer(endian, true, Error).init(self.out_stream); | ||
| 1379 | try packed_serializer.serialize(value); | ||
| 1380 | try packed_serializer.flush(); | ||
| 1381 | return; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | switch (@typeId(T)) { | ||
| 1385 | builtin.TypeId.Void => return, | ||
| 1386 | builtin.TypeId.Bool => try self.serializeInt(u1(@boolToInt(value))), | ||
| 1387 | builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value), | ||
| 1388 | builtin.TypeId.Struct => { | ||
| 1389 | const info = @typeInfo(T); | ||
| 1390 | |||
| 1391 | inline for (info.Struct.fields) |*field_info| { | ||
| 1392 | const name = field_info.name; | ||
| 1393 | const FieldType = field_info.field_type; | ||
| 1394 | |||
| 1395 | if (FieldType == void or FieldType == u0) continue; | ||
| 1396 | |||
| 1397 | //It doesn't make sense to write pointers | ||
| 1398 | if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) { | ||
| 1399 | @compileError("Will not " ++ "serialize field " ++ name ++ | ||
| 1400 | " of struct " ++ @typeName(T) ++ " because it " ++ | ||
| 1401 | "is of pointer-type " ++ @typeName(FieldType) ++ "."); | ||
| 1402 | } | ||
| 1403 | try self.serialize(@field(value, name)); | ||
| 1404 | } | ||
| 1405 | }, | ||
| 1406 | builtin.TypeId.Union => { | ||
| 1407 | const info = @typeInfo(T).Union; | ||
| 1408 | if (info.tag_type) |TagType| { | ||
| 1409 | const active_tag = meta.activeTag(value); | ||
| 1410 | try self.serialize(active_tag); | ||
| 1411 | //This inline loop is necessary because active_tag is a runtime | ||
| 1412 | // value, but @field requires a comptime value. Our alternative | ||
| 1413 | // is to check each field for a match | ||
| 1414 | inline for (info.fields) |field_info| { | ||
| 1415 | if (field_info.enum_field.?.value == @enumToInt(active_tag)) { | ||
| 1416 | const name = field_info.name; | ||
| 1417 | const FieldType = field_info.field_type; | ||
| 1418 | try self.serialize(@field(value, name)); | ||
| 1419 | return; | ||
| 1420 | } | ||
| 1421 | } | ||
| 1422 | unreachable; | ||
| 1423 | } | ||
| 1424 | @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++ | ||
| 1425 | " because it is an untagged union Use a custom serialize()."); | ||
| 1426 | }, | ||
| 1427 | builtin.TypeId.Optional => { | ||
| 1428 | if (value == null) { | ||
| 1429 | try self.serializeInt(u1(@boolToInt(false))); | ||
| 1430 | return; | ||
| 1431 | } | ||
| 1432 | try self.serializeInt(u1(@boolToInt(true))); | ||
| 1433 | |||
| 1434 | const OC = comptime meta.Child(T); | ||
| 1435 | |||
| 1436 | //The way non-pointer optionals are implemented ensures a pointer to them | ||
| 1437 | // will point to the value. The flag is stored at the end of that data. | ||
| 1438 | var val_ptr = @ptrCast(*const OC, &value); | ||
| 1439 | try self.serialize(val_ptr.*); | ||
| 1440 | }, | ||
| 1441 | builtin.TypeId.Enum => { | ||
| 1442 | try self.serializeInt(@enumToInt(value)); | ||
| 1443 | }, | ||
| 1444 | else => @compileError("Cannot serialize " ++ @tagName(@typeId(T)) ++ " types (unimplemented)."), | ||
| 1445 | } | ||
| 1446 | } | ||
| 1447 | }; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | test "import io tests" { | ||
| 1451 | comptime { | ||
| 1452 | _ = @import("io_test.zig"); | ||
| 1453 | } | ||
| 1454 | } | ||
| 1455 |
std/io_test.zig+476-30| ... | @@ -1,8 +1,10 @@ | ... | @@ -1,8 +1,10 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const io = std.io; | 2 | const io = std.io; |
| 3 | const meta = std.meta; | ||
| 4 | const trait = std.trait; | ||
| 3 | const DefaultPrng = std.rand.DefaultPrng; | 5 | const DefaultPrng = std.rand.DefaultPrng; |
| 4 | const assert = std.debug.assert; | 6 | const expect = std.testing.expect; |
| 5 | const assertError = std.debug.assertError; | 7 | const expectError = std.testing.expectError; |
| 6 | const mem = std.mem; | 8 | const mem = std.mem; |
| 7 | const os = std.os; | 9 | const os = std.os; |
| 8 | const builtin = @import("builtin"); | 10 | const builtin = @import("builtin"); |
| ... | @@ -33,7 +35,7 @@ test "write a file, read it, then delete it" { | ... | @@ -33,7 +35,7 @@ test "write a file, read it, then delete it" { |
| 33 | 35 | ||
| 34 | const file_size = try file.getEndPos(); | 36 | const file_size = try file.getEndPos(); |
| 35 | const expected_file_size = "begin".len + data.len + "end".len; | 37 | const expected_file_size = "begin".len + data.len + "end".len; |
| 36 | assert(file_size == expected_file_size); | 38 | expect(file_size == expected_file_size); |
| 37 | 39 | ||
| 38 | var file_in_stream = file.inStream(); | 40 | var file_in_stream = file.inStream(); |
| 39 | var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream); | 41 | var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream); |
| ... | @@ -41,9 +43,9 @@ test "write a file, read it, then delete it" { | ... | @@ -41,9 +43,9 @@ test "write a file, read it, then delete it" { |
| 41 | const contents = try st.readAllAlloc(allocator, 2 * 1024); | 43 | const contents = try st.readAllAlloc(allocator, 2 * 1024); |
| 42 | defer allocator.free(contents); | 44 | defer allocator.free(contents); |
| 43 | 45 | ||
| 44 | assert(mem.eql(u8, contents[0.."begin".len], "begin")); | 46 | expect(mem.eql(u8, contents[0.."begin".len], "begin")); |
| 45 | assert(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data)); | 47 | expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data)); |
| 46 | assert(mem.eql(u8, contents[contents.len - "end".len ..], "end")); | 48 | expect(mem.eql(u8, contents[contents.len - "end".len ..], "end")); |
| 47 | } | 49 | } |
| 48 | try os.deleteFile(tmp_file_name); | 50 | try os.deleteFile(tmp_file_name); |
| 49 | } | 51 | } |
| ... | @@ -59,7 +61,7 @@ test "BufferOutStream" { | ... | @@ -59,7 +61,7 @@ test "BufferOutStream" { |
| 59 | const y: i32 = 1234; | 61 | const y: i32 = 1234; |
| 60 | try buf_stream.print("x: {}\ny: {}\n", x, y); | 62 | try buf_stream.print("x: {}\ny: {}\n", x, y); |
| 61 | 63 | ||
| 62 | assert(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n")); | 64 | expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n")); |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | test "SliceInStream" { | 67 | test "SliceInStream" { |
| ... | @@ -69,15 +71,15 @@ test "SliceInStream" { | ... | @@ -69,15 +71,15 @@ test "SliceInStream" { |
| 69 | var dest: [4]u8 = undefined; | 71 | var dest: [4]u8 = undefined; |
| 70 | 72 | ||
| 71 | var read = try ss.stream.read(dest[0..4]); | 73 | var read = try ss.stream.read(dest[0..4]); |
| 72 | assert(read == 4); | 74 | expect(read == 4); |
| 73 | assert(mem.eql(u8, dest[0..4], bytes[0..4])); | 75 | expect(mem.eql(u8, dest[0..4], bytes[0..4])); |
| 74 | 76 | ||
| 75 | read = try ss.stream.read(dest[0..4]); | 77 | read = try ss.stream.read(dest[0..4]); |
| 76 | assert(read == 3); | 78 | expect(read == 3); |
| 77 | assert(mem.eql(u8, dest[0..3], bytes[4..7])); | 79 | expect(mem.eql(u8, dest[0..3], bytes[4..7])); |
| 78 | 80 | ||
| 79 | read = try ss.stream.read(dest[0..4]); | 81 | read = try ss.stream.read(dest[0..4]); |
| 80 | assert(read == 0); | 82 | expect(read == 0); |
| 81 | } | 83 | } |
| 82 | 84 | ||
| 83 | test "PeekStream" { | 85 | test "PeekStream" { |
| ... | @@ -91,26 +93,26 @@ test "PeekStream" { | ... | @@ -91,26 +93,26 @@ test "PeekStream" { |
| 91 | ps.putBackByte(10); | 93 | ps.putBackByte(10); |
| 92 | 94 | ||
| 93 | var read = try ps.stream.read(dest[0..4]); | 95 | var read = try ps.stream.read(dest[0..4]); |
| 94 | assert(read == 4); | 96 | expect(read == 4); |
| 95 | assert(dest[0] == 10); | 97 | expect(dest[0] == 10); |
| 96 | assert(dest[1] == 9); | 98 | expect(dest[1] == 9); |
| 97 | assert(mem.eql(u8, dest[2..4], bytes[0..2])); | 99 | expect(mem.eql(u8, dest[2..4], bytes[0..2])); |
| 98 | 100 | ||
| 99 | read = try ps.stream.read(dest[0..4]); | 101 | read = try ps.stream.read(dest[0..4]); |
| 100 | assert(read == 4); | 102 | expect(read == 4); |
| 101 | assert(mem.eql(u8, dest[0..4], bytes[2..6])); | 103 | expect(mem.eql(u8, dest[0..4], bytes[2..6])); |
| 102 | 104 | ||
| 103 | read = try ps.stream.read(dest[0..4]); | 105 | read = try ps.stream.read(dest[0..4]); |
| 104 | assert(read == 2); | 106 | expect(read == 2); |
| 105 | assert(mem.eql(u8, dest[0..2], bytes[6..8])); | 107 | expect(mem.eql(u8, dest[0..2], bytes[6..8])); |
| 106 | 108 | ||
| 107 | ps.putBackByte(11); | 109 | ps.putBackByte(11); |
| 108 | ps.putBackByte(12); | 110 | ps.putBackByte(12); |
| 109 | 111 | ||
| 110 | read = try ps.stream.read(dest[0..4]); | 112 | read = try ps.stream.read(dest[0..4]); |
| 111 | assert(read == 2); | 113 | expect(read == 2); |
| 112 | assert(dest[0] == 12); | 114 | expect(dest[0] == 12); |
| 113 | assert(dest[1] == 11); | 115 | expect(dest[1] == 11); |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | test "SliceOutStream" { | 118 | test "SliceOutStream" { |
| ... | @@ -118,17 +120,461 @@ test "SliceOutStream" { | ... | @@ -118,17 +120,461 @@ test "SliceOutStream" { |
| 118 | var ss = io.SliceOutStream.init(buffer[0..]); | 120 | var ss = io.SliceOutStream.init(buffer[0..]); |
| 119 | 121 | ||
| 120 | try ss.stream.write("Hello"); | 122 | try ss.stream.write("Hello"); |
| 121 | assert(mem.eql(u8, ss.getWritten(), "Hello")); | 123 | expect(mem.eql(u8, ss.getWritten(), "Hello")); |
| 122 | 124 | ||
| 123 | try ss.stream.write("world"); | 125 | try ss.stream.write("world"); |
| 124 | assert(mem.eql(u8, ss.getWritten(), "Helloworld")); | 126 | expect(mem.eql(u8, ss.getWritten(), "Helloworld")); |
| 125 | 127 | ||
| 126 | assertError(ss.stream.write("!"), error.OutOfSpace); | 128 | expectError(error.OutOfSpace, ss.stream.write("!")); |
| 127 | assert(mem.eql(u8, ss.getWritten(), "Helloworld")); | 129 | expect(mem.eql(u8, ss.getWritten(), "Helloworld")); |
| 128 | 130 | ||
| 129 | ss.reset(); | 131 | ss.reset(); |
| 130 | assert(ss.getWritten().len == 0); | 132 | expect(ss.getWritten().len == 0); |
| 131 | 133 | ||
| 132 | assertError(ss.stream.write("Hello world!"), error.OutOfSpace); | 134 | expectError(error.OutOfSpace, ss.stream.write("Hello world!")); |
| 133 | assert(mem.eql(u8, ss.getWritten(), "Hello worl")); | 135 | expect(mem.eql(u8, ss.getWritten(), "Hello worl")); |
| 136 | } | ||
| 137 | |||
| 138 | test "BitInStream" { | ||
| 139 | const mem_be = []u8{ 0b11001101, 0b00001011 }; | ||
| 140 | const mem_le = []u8{ 0b00011101, 0b10010101 }; | ||
| 141 | |||
| 142 | var mem_in_be = io.SliceInStream.init(mem_be[0..]); | ||
| 143 | const InError = io.SliceInStream.Error; | ||
| 144 | var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream); | ||
| 145 | |||
| 146 | var out_bits: usize = undefined; | ||
| 147 | |||
| 148 | expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits)); | ||
| 149 | expect(out_bits == 1); | ||
| 150 | expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits)); | ||
| 151 | expect(out_bits == 2); | ||
| 152 | expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits)); | ||
| 153 | expect(out_bits == 3); | ||
| 154 | expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits)); | ||
| 155 | expect(out_bits == 4); | ||
| 156 | expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits)); | ||
| 157 | expect(out_bits == 5); | ||
| 158 | expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits)); | ||
| 159 | expect(out_bits == 1); | ||
| 160 | |||
| 161 | mem_in_be.pos = 0; | ||
| 162 | bit_stream_be.bit_count = 0; | ||
| 163 | expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits)); | ||
| 164 | expect(out_bits == 15); | ||
| 165 | |||
| 166 | mem_in_be.pos = 0; | ||
| 167 | bit_stream_be.bit_count = 0; | ||
| 168 | expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits)); | ||
| 169 | expect(out_bits == 16); | ||
| 170 | |||
| 171 | _ = try bit_stream_be.readBits(u0, 0, &out_bits); | ||
| 172 | |||
| 173 | expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits)); | ||
| 174 | expect(out_bits == 0); | ||
| 175 | expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1)); | ||
| 176 | |||
| 177 | var mem_in_le = io.SliceInStream.init(mem_le[0..]); | ||
| 178 | var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream); | ||
| 179 | |||
| 180 | expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits)); | ||
| 181 | expect(out_bits == 1); | ||
| 182 | expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits)); | ||
| 183 | expect(out_bits == 2); | ||
| 184 | expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits)); | ||
| 185 | expect(out_bits == 3); | ||
| 186 | expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits)); | ||
| 187 | expect(out_bits == 4); | ||
| 188 | expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits)); | ||
| 189 | expect(out_bits == 5); | ||
| 190 | expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits)); | ||
| 191 | expect(out_bits == 1); | ||
| 192 | |||
| 193 | mem_in_le.pos = 0; | ||
| 194 | bit_stream_le.bit_count = 0; | ||
| 195 | expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits)); | ||
| 196 | expect(out_bits == 15); | ||
| 197 | |||
| 198 | mem_in_le.pos = 0; | ||
| 199 | bit_stream_le.bit_count = 0; | ||
| 200 | expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits)); | ||
| 201 | expect(out_bits == 16); | ||
| 202 | |||
| 203 | _ = try bit_stream_le.readBits(u0, 0, &out_bits); | ||
| 204 | |||
| 205 | expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits)); | ||
| 206 | expect(out_bits == 0); | ||
| 207 | expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1)); | ||
| 208 | } | ||
| 209 | |||
| 210 | test "BitOutStream" { | ||
| 211 | var mem_be = []u8{0} ** 2; | ||
| 212 | var mem_le = []u8{0} ** 2; | ||
| 213 | |||
| 214 | var mem_out_be = io.SliceOutStream.init(mem_be[0..]); | ||
| 215 | const OutError = io.SliceOutStream.Error; | ||
| 216 | var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream); | ||
| 217 | |||
| 218 | try bit_stream_be.writeBits(u2(1), 1); | ||
| 219 | try bit_stream_be.writeBits(u5(2), 2); | ||
| 220 | try bit_stream_be.writeBits(u128(3), 3); | ||
| 221 | try bit_stream_be.writeBits(u8(4), 4); | ||
| 222 | try bit_stream_be.writeBits(u9(5), 5); | ||
| 223 | try bit_stream_be.writeBits(u1(1), 1); | ||
| 224 | |||
| 225 | expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011); | ||
| 226 | |||
| 227 | mem_out_be.pos = 0; | ||
| 228 | |||
| 229 | try bit_stream_be.writeBits(u15(0b110011010000101), 15); | ||
| 230 | try bit_stream_be.flushBits(); | ||
| 231 | expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010); | ||
| 232 | |||
| 233 | mem_out_be.pos = 0; | ||
| 234 | try bit_stream_be.writeBits(u32(0b110011010000101), 16); | ||
| 235 | expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101); | ||
| 236 | |||
| 237 | try bit_stream_be.writeBits(u0(0), 0); | ||
| 238 | |||
| 239 | var mem_out_le = io.SliceOutStream.init(mem_le[0..]); | ||
| 240 | var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream); | ||
| 241 | |||
| 242 | try bit_stream_le.writeBits(u2(1), 1); | ||
| 243 | try bit_stream_le.writeBits(u5(2), 2); | ||
| 244 | try bit_stream_le.writeBits(u128(3), 3); | ||
| 245 | try bit_stream_le.writeBits(u8(4), 4); | ||
| 246 | try bit_stream_le.writeBits(u9(5), 5); | ||
| 247 | try bit_stream_le.writeBits(u1(1), 1); | ||
| 248 | |||
| 249 | expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101); | ||
| 250 | |||
| 251 | mem_out_le.pos = 0; | ||
| 252 | try bit_stream_le.writeBits(u15(0b110011010000101), 15); | ||
| 253 | try bit_stream_le.flushBits(); | ||
| 254 | expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110); | ||
| 255 | |||
| 256 | mem_out_le.pos = 0; | ||
| 257 | try bit_stream_le.writeBits(u32(0b1100110100001011), 16); | ||
| 258 | expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101); | ||
| 259 | |||
| 260 | try bit_stream_le.writeBits(u0(0), 0); | ||
| 261 | } | ||
| 262 | |||
| 263 | test "BitStreams with File Stream" { | ||
| 264 | const tmp_file_name = "temp_test_file.txt"; | ||
| 265 | { | ||
| 266 | var file = try os.File.openWrite(tmp_file_name); | ||
| 267 | defer file.close(); | ||
| 268 | |||
| 269 | var file_out = file.outStream(); | ||
| 270 | var file_out_stream = &file_out.stream; | ||
| 271 | const OutError = os.File.WriteError; | ||
| 272 | var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream); | ||
| 273 | |||
| 274 | try bit_stream.writeBits(u2(1), 1); | ||
| 275 | try bit_stream.writeBits(u5(2), 2); | ||
| 276 | try bit_stream.writeBits(u128(3), 3); | ||
| 277 | try bit_stream.writeBits(u8(4), 4); | ||
| 278 | try bit_stream.writeBits(u9(5), 5); | ||
| 279 | try bit_stream.writeBits(u1(1), 1); | ||
| 280 | try bit_stream.flushBits(); | ||
| 281 | } | ||
| 282 | { | ||
| 283 | var file = try os.File.openRead(tmp_file_name); | ||
| 284 | defer file.close(); | ||
| 285 | |||
| 286 | var file_in = file.inStream(); | ||
| 287 | var file_in_stream = &file_in.stream; | ||
| 288 | const InError = os.File.ReadError; | ||
| 289 | var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream); | ||
| 290 | |||
| 291 | var out_bits: usize = undefined; | ||
| 292 | |||
| 293 | expect(1 == try bit_stream.readBits(u2, 1, &out_bits)); | ||
| 294 | expect(out_bits == 1); | ||
| 295 | expect(2 == try bit_stream.readBits(u5, 2, &out_bits)); | ||
| 296 | expect(out_bits == 2); | ||
| 297 | expect(3 == try bit_stream.readBits(u128, 3, &out_bits)); | ||
| 298 | expect(out_bits == 3); | ||
| 299 | expect(4 == try bit_stream.readBits(u8, 4, &out_bits)); | ||
| 300 | expect(out_bits == 4); | ||
| 301 | expect(5 == try bit_stream.readBits(u9, 5, &out_bits)); | ||
| 302 | expect(out_bits == 5); | ||
| 303 | expect(1 == try bit_stream.readBits(u1, 1, &out_bits)); | ||
| 304 | expect(out_bits == 1); | ||
| 305 | |||
| 306 | expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1)); | ||
| 307 | } | ||
| 308 | try os.deleteFile(tmp_file_name); | ||
| 309 | } | ||
| 310 | |||
| 311 | fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void { | ||
| 312 | //@NOTE: if this test is taking too long, reduce the maximum tested bitsize | ||
| 313 | const max_test_bitsize = 128; | ||
| 314 | |||
| 315 | const total_bytes = comptime blk: { | ||
| 316 | var bytes = 0; | ||
| 317 | comptime var i = 0; | ||
| 318 | while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0); | ||
| 319 | break :blk bytes * 2; | ||
| 320 | }; | ||
| 321 | |||
| 322 | var data_mem: [total_bytes]u8 = undefined; | ||
| 323 | var out = io.SliceOutStream.init(data_mem[0..]); | ||
| 324 | const OutError = io.SliceOutStream.Error; | ||
| 325 | var out_stream = &out.stream; | ||
| 326 | var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream); | ||
| 327 | |||
| 328 | var in = io.SliceInStream.init(data_mem[0..]); | ||
| 329 | const InError = io.SliceInStream.Error; | ||
| 330 | var in_stream = &in.stream; | ||
| 331 | var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream); | ||
| 332 | |||
| 333 | comptime var i = 0; | ||
| 334 | inline while (i <= max_test_bitsize) : (i += 1) { | ||
| 335 | const U = @IntType(false, i); | ||
| 336 | const S = @IntType(true, i); | ||
| 337 | try serializer.serializeInt(U(i)); | ||
| 338 | if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0)); | ||
| 339 | } | ||
| 340 | try serializer.flush(); | ||
| 341 | |||
| 342 | i = 0; | ||
| 343 | inline while (i <= max_test_bitsize) : (i += 1) { | ||
| 344 | const U = @IntType(false, i); | ||
| 345 | const S = @IntType(true, i); | ||
| 346 | const x = try deserializer.deserializeInt(U); | ||
| 347 | const y = try deserializer.deserializeInt(S); | ||
| 348 | expect(x == U(i)); | ||
| 349 | if (i != 0) expect(y == S(-1)) else expect(y == 0); | ||
| 350 | } | ||
| 351 | |||
| 352 | const u8_bit_count = comptime meta.bitCount(u8); | ||
| 353 | //0 + 1 + 2 + ... n = (n * (n + 1)) / 2 | ||
| 354 | //and we have each for unsigned and signed, so * 2 | ||
| 355 | const total_bits = (max_test_bitsize * (max_test_bitsize + 1)); | ||
| 356 | const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0); | ||
| 357 | const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte; | ||
| 358 | |||
| 359 | expect(in.pos == if (is_packed) total_packed_bytes else total_bytes); | ||
| 360 | |||
| 361 | //Verify that empty error set works with serializer. | ||
| 362 | //deserializer is covered by SliceInStream | ||
| 363 | const NullError = io.NullOutStream.Error; | ||
| 364 | var null_out = io.NullOutStream.init(); | ||
| 365 | var null_out_stream = &null_out.stream; | ||
| 366 | var null_serializer = io.Serializer(endian, is_packed, NullError).init(null_out_stream); | ||
| 367 | try null_serializer.serialize(data_mem[0..]); | ||
| 368 | try null_serializer.flush(); | ||
| 369 | } | ||
| 370 | |||
| 371 | test "Serializer/Deserializer Int" { | ||
| 372 | try testIntSerializerDeserializer(builtin.Endian.Big, false); | ||
| 373 | try testIntSerializerDeserializer(builtin.Endian.Little, false); | ||
| 374 | try testIntSerializerDeserializer(builtin.Endian.Big, true); | ||
| 375 | try testIntSerializerDeserializer(builtin.Endian.Little, true); | ||
| 376 | } | ||
| 377 | |||
| 378 | fn testIntSerializerDeserializerInfNaN(comptime endian: builtin.Endian, | ||
| 379 | comptime is_packed: bool) !void | ||
| 380 | { | ||
| 381 | const mem_size = (16*2 + 32*2 + 64*2 + 128*2) / comptime meta.bitCount(u8); | ||
| 382 | var data_mem: [mem_size]u8 = undefined; | ||
| 383 | |||
| 384 | var out = io.SliceOutStream.init(data_mem[0..]); | ||
| 385 | const OutError = io.SliceOutStream.Error; | ||
| 386 | var out_stream = &out.stream; | ||
| 387 | var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream); | ||
| 388 | |||
| 389 | var in = io.SliceInStream.init(data_mem[0..]); | ||
| 390 | const InError = io.SliceInStream.Error; | ||
| 391 | var in_stream = &in.stream; | ||
| 392 | var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream); | ||
| 393 | |||
| 394 | //@TODO: isInf/isNan not currently implemented for f128. | ||
| 395 | try serializer.serialize(std.math.nan(f16)); | ||
| 396 | try serializer.serialize(std.math.inf(f16)); | ||
| 397 | try serializer.serialize(std.math.nan(f32)); | ||
| 398 | try serializer.serialize(std.math.inf(f32)); | ||
| 399 | try serializer.serialize(std.math.nan(f64)); | ||
| 400 | try serializer.serialize(std.math.inf(f64)); | ||
| 401 | //try serializer.serialize(std.math.nan(f128)); | ||
| 402 | //try serializer.serialize(std.math.inf(f128)); | ||
| 403 | const nan_check_f16 = try deserializer.deserialize(f16); | ||
| 404 | const inf_check_f16 = try deserializer.deserialize(f16); | ||
| 405 | const nan_check_f32 = try deserializer.deserialize(f32); | ||
| 406 | const inf_check_f32 = try deserializer.deserialize(f32); | ||
| 407 | const nan_check_f64 = try deserializer.deserialize(f64); | ||
| 408 | const inf_check_f64 = try deserializer.deserialize(f64); | ||
| 409 | //const nan_check_f128 = try deserializer.deserialize(f128); | ||
| 410 | //const inf_check_f128 = try deserializer.deserialize(f128); | ||
| 411 | expect(std.math.isNan(nan_check_f16)); | ||
| 412 | expect(std.math.isInf(inf_check_f16)); | ||
| 413 | expect(std.math.isNan(nan_check_f32)); | ||
| 414 | expect(std.math.isInf(inf_check_f32)); | ||
| 415 | expect(std.math.isNan(nan_check_f64)); | ||
| 416 | expect(std.math.isInf(inf_check_f64)); | ||
| 417 | //expect(std.math.isNan(nan_check_f128)); | ||
| 418 | //expect(std.math.isInf(inf_check_f128)); | ||
| 419 | } | ||
| 420 | |||
| 421 | test "Serializer/Deserializer Int: Inf/NaN" { | ||
| 422 | try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, false); | ||
| 423 | try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, false); | ||
| 424 | try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, true); | ||
| 425 | try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, true); | ||
| 426 | } | ||
| 427 | |||
| 428 | fn testAlternateSerializer(self: var, serializer: var) !void { | ||
| 429 | try serializer.serialize(self.f_f16); | ||
| 430 | } | ||
| 431 | |||
| 432 | fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void { | ||
| 433 | const ColorType = enum(u4) { | ||
| 434 | RGB8 = 1, | ||
| 435 | RA16 = 2, | ||
| 436 | R32 = 3, | ||
| 437 | }; | ||
| 438 | |||
| 439 | const TagAlign = union(enum(u32)) { | ||
| 440 | A: u8, | ||
| 441 | B: u8, | ||
| 442 | C: u8, | ||
| 443 | }; | ||
| 444 | |||
| 445 | const Color = union(ColorType) { | ||
| 446 | RGB8: struct { | ||
| 447 | r: u8, | ||
| 448 | g: u8, | ||
| 449 | b: u8, | ||
| 450 | a: u8, | ||
| 451 | }, | ||
| 452 | RA16: struct { | ||
| 453 | r: u16, | ||
| 454 | a: u16, | ||
| 455 | }, | ||
| 456 | R32: u32, | ||
| 457 | }; | ||
| 458 | |||
| 459 | const PackedStruct = packed struct { | ||
| 460 | f_i3: i3, | ||
| 461 | f_u2: u2, | ||
| 462 | }; | ||
| 463 | |||
| 464 | |||
| 465 | |||
| 466 | //to test custom serialization | ||
| 467 | const Custom = struct { | ||
| 468 | f_f16: f16, | ||
| 469 | f_unused_u32: u32, | ||
| 470 | |||
| 471 | pub fn deserialize(self: *@This(), deserializer: var) !void { | ||
| 472 | try deserializer.deserializeInto(&self.f_f16); | ||
| 473 | self.f_unused_u32 = 47; | ||
| 474 | } | ||
| 475 | |||
| 476 | pub const serialize = testAlternateSerializer; | ||
| 477 | }; | ||
| 478 | |||
| 479 | const MyStruct = struct { | ||
| 480 | f_i3: i3, | ||
| 481 | f_u8: u8, | ||
| 482 | f_tag_align: TagAlign, | ||
| 483 | f_u24: u24, | ||
| 484 | f_i19: i19, | ||
| 485 | f_void: void, | ||
| 486 | f_f32: f32, | ||
| 487 | f_f128: f128, | ||
| 488 | f_packed_0: PackedStruct, | ||
| 489 | f_i7arr: [10]i7, | ||
| 490 | f_of64n: ?f64, | ||
| 491 | f_of64v: ?f64, | ||
| 492 | f_color_type: ColorType, | ||
| 493 | f_packed_1: PackedStruct, | ||
| 494 | f_custom: Custom, | ||
| 495 | f_color: Color, | ||
| 496 | }; | ||
| 497 | |||
| 498 | const my_inst = MyStruct{ | ||
| 499 | .f_i3 = -1, | ||
| 500 | .f_u8 = 8, | ||
| 501 | .f_tag_align = TagAlign{ .B = 148 }, | ||
| 502 | .f_u24 = 24, | ||
| 503 | .f_i19 = 19, | ||
| 504 | .f_void = {}, | ||
| 505 | .f_f32 = 32.32, | ||
| 506 | .f_f128 = 128.128, | ||
| 507 | .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 }, | ||
| 508 | .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, | ||
| 509 | .f_of64n = null, | ||
| 510 | .f_of64v = 64.64, | ||
| 511 | .f_color_type = ColorType.R32, | ||
| 512 | .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 }, | ||
| 513 | .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 }, | ||
| 514 | .f_color = Color{ .R32 = 123822 }, | ||
| 515 | }; | ||
| 516 | |||
| 517 | var data_mem: [@sizeOf(MyStruct)]u8 = undefined; | ||
| 518 | var out = io.SliceOutStream.init(data_mem[0..]); | ||
| 519 | const OutError = io.SliceOutStream.Error; | ||
| 520 | var out_stream = &out.stream; | ||
| 521 | var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream); | ||
| 522 | |||
| 523 | var in = io.SliceInStream.init(data_mem[0..]); | ||
| 524 | const InError = io.SliceInStream.Error; | ||
| 525 | var in_stream = &in.stream; | ||
| 526 | var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream); | ||
| 527 | |||
| 528 | try serializer.serialize(my_inst); | ||
| 529 | |||
| 530 | const my_copy = try deserializer.deserialize(MyStruct); | ||
| 531 | expect(meta.eql(my_copy, my_inst)); | ||
| 532 | } | ||
| 533 | |||
| 534 | test "Serializer/Deserializer generic" { | ||
| 535 | try testSerializerDeserializer(builtin.Endian.Big, false); | ||
| 536 | try testSerializerDeserializer(builtin.Endian.Little, false); | ||
| 537 | try testSerializerDeserializer(builtin.Endian.Big, true); | ||
| 538 | try testSerializerDeserializer(builtin.Endian.Little, true); | ||
| 539 | } | ||
| 540 | |||
| 541 | fn testBadData(comptime endian: builtin.Endian, comptime is_packed: bool) !void { | ||
| 542 | const E = enum(u14) { | ||
| 543 | One = 1, | ||
| 544 | Two = 2, | ||
| 545 | }; | ||
| 546 | |||
| 547 | const A = struct { | ||
| 548 | e: E, | ||
| 549 | }; | ||
| 550 | |||
| 551 | const C = union(E) { | ||
| 552 | One: u14, | ||
| 553 | Two: f16, | ||
| 554 | }; | ||
| 555 | |||
| 556 | var data_mem: [4]u8 = undefined; | ||
| 557 | var out = io.SliceOutStream.init(data_mem[0..]); | ||
| 558 | const OutError = io.SliceOutStream.Error; | ||
| 559 | var out_stream = &out.stream; | ||
| 560 | var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream); | ||
| 561 | |||
| 562 | var in = io.SliceInStream.init(data_mem[0..]); | ||
| 563 | const InError = io.SliceInStream.Error; | ||
| 564 | var in_stream = &in.stream; | ||
| 565 | var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream); | ||
| 566 | |||
| 567 | try serializer.serialize(u14(3)); | ||
| 568 | expectError(error.InvalidEnumTag, deserializer.deserialize(A)); | ||
| 569 | out.pos = 0; | ||
| 570 | try serializer.serialize(u14(3)); | ||
| 571 | try serializer.serialize(u14(88)); | ||
| 572 | expectError(error.InvalidEnumTag, deserializer.deserialize(C)); | ||
| 573 | } | ||
| 574 | |||
| 575 | test "Deserializer bad data" { | ||
| 576 | try testBadData(builtin.Endian.Big, false); | ||
| 577 | try testBadData(builtin.Endian.Little, false); | ||
| 578 | try testBadData(builtin.Endian.Big, true); | ||
| 579 | try testBadData(builtin.Endian.Little, true); | ||
| 134 | } | 580 | } |
std/json.zig+15-10| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | ||
| 5 | const std = @import("index.zig"); | 5 | const std = @import("index.zig"); |
| 6 | const debug = std.debug; | 6 | const debug = std.debug; |
| 7 | const testing = std.testing; | ||
| 7 | const mem = std.mem; | 8 | const mem = std.mem; |
| 8 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| 9 | 10 | ||
| ... | @@ -960,7 +961,7 @@ test "json.token" { | ... | @@ -960,7 +961,7 @@ test "json.token" { |
| 960 | checkNext(&p, Token.Id.ObjectEnd); | 961 | checkNext(&p, Token.Id.ObjectEnd); |
| 961 | checkNext(&p, Token.Id.ObjectEnd); | 962 | checkNext(&p, Token.Id.ObjectEnd); |
| 962 | 963 | ||
| 963 | debug.assert((try p.next()) == null); | 964 | testing.expect((try p.next()) == null); |
| 964 | } | 965 | } |
| 965 | 966 | ||
| 966 | // Validate a JSON string. This does not limit number precision so a decoder may not necessarily | 967 | // Validate a JSON string. This does not limit number precision so a decoder may not necessarily |
| ... | @@ -981,7 +982,7 @@ pub fn validate(s: []const u8) bool { | ... | @@ -981,7 +982,7 @@ pub fn validate(s: []const u8) bool { |
| 981 | } | 982 | } |
| 982 | 983 | ||
| 983 | test "json.validate" { | 984 | test "json.validate" { |
| 984 | debug.assert(validate("{}")); | 985 | testing.expect(validate("{}")); |
| 985 | } | 986 | } |
| 986 | 987 | ||
| 987 | const Allocator = std.mem.Allocator; | 988 | const Allocator = std.mem.Allocator; |
| ... | @@ -1344,7 +1345,7 @@ pub const Parser = struct { | ... | @@ -1344,7 +1345,7 @@ pub const Parser = struct { |
| 1344 | return if (token.number_is_integer) | 1345 | return if (token.number_is_integer) |
| 1345 | Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } | 1346 | Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) } |
| 1346 | else | 1347 | else |
| 1347 | @panic("TODO: fmt.parseFloat not yet implemented"); | 1348 | Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) }; |
| 1348 | } | 1349 | } |
| 1349 | }; | 1350 | }; |
| 1350 | 1351 | ||
| ... | @@ -1365,7 +1366,8 @@ test "json.parser.dynamic" { | ... | @@ -1365,7 +1366,8 @@ test "json.parser.dynamic" { |
| 1365 | \\ }, | 1366 | \\ }, |
| 1366 | \\ "Animated" : false, | 1367 | \\ "Animated" : false, |
| 1367 | \\ "IDs": [116, 943, 234, 38793], | 1368 | \\ "IDs": [116, 943, 234, 38793], |
| 1368 | \\ "ArrayOfObject": [{"n": "m"}] | 1369 | \\ "ArrayOfObject": [{"n": "m"}], |
| 1370 | \\ "double": 1.3412 | ||
| 1369 | \\ } | 1371 | \\ } |
| 1370 | \\} | 1372 | \\} |
| 1371 | ; | 1373 | ; |
| ... | @@ -1378,20 +1380,23 @@ test "json.parser.dynamic" { | ... | @@ -1378,20 +1380,23 @@ test "json.parser.dynamic" { |
| 1378 | var image = root.Object.get("Image").?.value; | 1380 | var image = root.Object.get("Image").?.value; |
| 1379 | 1381 | ||
| 1380 | const width = image.Object.get("Width").?.value; | 1382 | const width = image.Object.get("Width").?.value; |
| 1381 | debug.assert(width.Integer == 800); | 1383 | testing.expect(width.Integer == 800); |
| 1382 | 1384 | ||
| 1383 | const height = image.Object.get("Height").?.value; | 1385 | const height = image.Object.get("Height").?.value; |
| 1384 | debug.assert(height.Integer == 600); | 1386 | testing.expect(height.Integer == 600); |
| 1385 | 1387 | ||
| 1386 | const title = image.Object.get("Title").?.value; | 1388 | const title = image.Object.get("Title").?.value; |
| 1387 | debug.assert(mem.eql(u8, title.String, "View from 15th Floor")); | 1389 | testing.expect(mem.eql(u8, title.String, "View from 15th Floor")); |
| 1388 | 1390 | ||
| 1389 | const animated = image.Object.get("Animated").?.value; | 1391 | const animated = image.Object.get("Animated").?.value; |
| 1390 | debug.assert(animated.Bool == false); | 1392 | testing.expect(animated.Bool == false); |
| 1391 | 1393 | ||
| 1392 | const array_of_object = image.Object.get("ArrayOfObject").?.value; | 1394 | const array_of_object = image.Object.get("ArrayOfObject").?.value; |
| 1393 | debug.assert(array_of_object.Array.len == 1); | 1395 | testing.expect(array_of_object.Array.len == 1); |
| 1394 | 1396 | ||
| 1395 | const obj0 = array_of_object.Array.at(0).Object.get("n").?.value; | 1397 | const obj0 = array_of_object.Array.at(0).Object.get("n").?.value; |
| 1396 | debug.assert(mem.eql(u8, obj0.String, "m")); | 1398 | testing.expect(mem.eql(u8, obj0.String, "m")); |
| 1399 | |||
| 1400 | const double = image.Object.get("double").?.value; | ||
| 1401 | testing.expect(double.Float == 1.3412); | ||
| 1397 | } | 1402 | } |
std/json_test.zig+3-3| ... | @@ -6,15 +6,15 @@ | ... | @@ -6,15 +6,15 @@ |
| 6 | const std = @import("index.zig"); | 6 | const std = @import("index.zig"); |
| 7 | 7 | ||
| 8 | fn ok(comptime s: []const u8) void { | 8 | fn ok(comptime s: []const u8) void { |
| 9 | std.debug.assert(std.json.validate(s)); | 9 | std.testing.expect(std.json.validate(s)); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | fn err(comptime s: []const u8) void { | 12 | fn err(comptime s: []const u8) void { |
| 13 | std.debug.assert(!std.json.validate(s)); | 13 | std.testing.expect(!std.json.validate(s)); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | fn any(comptime s: []const u8) void { | 16 | fn any(comptime s: []const u8) void { |
| 17 | std.debug.assert(true); | 17 | std.testing.expect(true); |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
std/lazy_init.zig+5-4| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | const AtomicOrder = builtin.AtomicOrder; | 6 | const AtomicOrder = builtin.AtomicOrder; |
| 6 | 7 | ||
| ... | @@ -63,12 +64,12 @@ test "std.lazyInit" { | ... | @@ -63,12 +64,12 @@ test "std.lazyInit" { |
| 63 | global_number.resolve(); | 64 | global_number.resolve(); |
| 64 | } | 65 | } |
| 65 | if (global_number.get()) |x| { | 66 | if (global_number.get()) |x| { |
| 66 | assert(x.* == 1234); | 67 | testing.expect(x.* == 1234); |
| 67 | } else { | 68 | } else { |
| 68 | @panic("bad"); | 69 | @panic("bad"); |
| 69 | } | 70 | } |
| 70 | if (global_number.get()) |x| { | 71 | if (global_number.get()) |x| { |
| 71 | assert(x.* == 1234); | 72 | testing.expect(x.* == 1234); |
| 72 | } else { | 73 | } else { |
| 73 | @panic("bad"); | 74 | @panic("bad"); |
| 74 | } | 75 | } |
| ... | @@ -80,6 +81,6 @@ test "std.lazyInit(void)" { | ... | @@ -80,6 +81,6 @@ test "std.lazyInit(void)" { |
| 80 | if (global_void.get()) |_| @panic("bad") else { | 81 | if (global_void.get()) |_| @panic("bad") else { |
| 81 | global_void.resolve(); | 82 | global_void.resolve(); |
| 82 | } | 83 | } |
| 83 | assert(global_void.get() != null); | 84 | testing.expect(global_void.get() != null); |
| 84 | assert(global_void.get() != null); | 85 | testing.expect(global_void.get() != null); |
| 85 | } | 86 | } |
std/linked_list.zig+16-15| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const debug = std.debug; | 2 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 3 | const assert = debug.assert; |
| 4 | const testing = std.testing; | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| 6 | 7 | ||
| ... | @@ -190,7 +191,7 @@ pub fn LinkedList(comptime T: type) type { | ... | @@ -190,7 +191,7 @@ pub fn LinkedList(comptime T: type) type { |
| 190 | /// Returns: | 191 | /// Returns: |
| 191 | /// A pointer to the new node. | 192 | /// A pointer to the new node. |
| 192 | pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node { | 193 | pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node { |
| 193 | return allocator.create(Node(undefined)); | 194 | return allocator.create(Node); |
| 194 | } | 195 | } |
| 195 | 196 | ||
| 196 | /// Deallocate a node. | 197 | /// Deallocate a node. |
| ... | @@ -246,7 +247,7 @@ test "basic linked list test" { | ... | @@ -246,7 +247,7 @@ test "basic linked list test" { |
| 246 | var it = list.first; | 247 | var it = list.first; |
| 247 | var index: u32 = 1; | 248 | var index: u32 = 1; |
| 248 | while (it) |node| : (it = node.next) { | 249 | while (it) |node| : (it = node.next) { |
| 249 | assert(node.data == index); | 250 | testing.expect(node.data == index); |
| 250 | index += 1; | 251 | index += 1; |
| 251 | } | 252 | } |
| 252 | } | 253 | } |
| ... | @@ -256,7 +257,7 @@ test "basic linked list test" { | ... | @@ -256,7 +257,7 @@ test "basic linked list test" { |
| 256 | var it = list.last; | 257 | var it = list.last; |
| 257 | var index: u32 = 1; | 258 | var index: u32 = 1; |
| 258 | while (it) |node| : (it = node.prev) { | 259 | while (it) |node| : (it = node.prev) { |
| 259 | assert(node.data == (6 - index)); | 260 | testing.expect(node.data == (6 - index)); |
| 260 | index += 1; | 261 | index += 1; |
| 261 | } | 262 | } |
| 262 | } | 263 | } |
| ... | @@ -265,9 +266,9 @@ test "basic linked list test" { | ... | @@ -265,9 +266,9 @@ test "basic linked list test" { |
| 265 | var last = list.pop(); // {2, 3, 4} | 266 | var last = list.pop(); // {2, 3, 4} |
| 266 | list.remove(three); // {2, 4} | 267 | list.remove(three); // {2, 4} |
| 267 | 268 | ||
| 268 | assert(list.first.?.data == 2); | 269 | testing.expect(list.first.?.data == 2); |
| 269 | assert(list.last.?.data == 4); | 270 | testing.expect(list.last.?.data == 4); |
| 270 | assert(list.len == 2); | 271 | testing.expect(list.len == 2); |
| 271 | } | 272 | } |
| 272 | 273 | ||
| 273 | test "linked list concatenation" { | 274 | test "linked list concatenation" { |
| ... | @@ -294,18 +295,18 @@ test "linked list concatenation" { | ... | @@ -294,18 +295,18 @@ test "linked list concatenation" { |
| 294 | 295 | ||
| 295 | list1.concatByMoving(&list2); | 296 | list1.concatByMoving(&list2); |
| 296 | 297 | ||
| 297 | assert(list1.last == five); | 298 | testing.expect(list1.last == five); |
| 298 | assert(list1.len == 5); | 299 | testing.expect(list1.len == 5); |
| 299 | assert(list2.first == null); | 300 | testing.expect(list2.first == null); |
| 300 | assert(list2.last == null); | 301 | testing.expect(list2.last == null); |
| 301 | assert(list2.len == 0); | 302 | testing.expect(list2.len == 0); |
| 302 | 303 | ||
| 303 | // Traverse forwards. | 304 | // Traverse forwards. |
| 304 | { | 305 | { |
| 305 | var it = list1.first; | 306 | var it = list1.first; |
| 306 | var index: u32 = 1; | 307 | var index: u32 = 1; |
| 307 | while (it) |node| : (it = node.next) { | 308 | while (it) |node| : (it = node.next) { |
| 308 | assert(node.data == index); | 309 | testing.expect(node.data == index); |
| 309 | index += 1; | 310 | index += 1; |
| 310 | } | 311 | } |
| 311 | } | 312 | } |
| ... | @@ -315,7 +316,7 @@ test "linked list concatenation" { | ... | @@ -315,7 +316,7 @@ test "linked list concatenation" { |
| 315 | var it = list1.last; | 316 | var it = list1.last; |
| 316 | var index: u32 = 1; | 317 | var index: u32 = 1; |
| 317 | while (it) |node| : (it = node.prev) { | 318 | while (it) |node| : (it = node.prev) { |
| 318 | assert(node.data == (6 - index)); | 319 | testing.expect(node.data == (6 - index)); |
| 319 | index += 1; | 320 | index += 1; |
| 320 | } | 321 | } |
| 321 | } | 322 | } |
| ... | @@ -328,7 +329,7 @@ test "linked list concatenation" { | ... | @@ -328,7 +329,7 @@ test "linked list concatenation" { |
| 328 | var it = list2.first; | 329 | var it = list2.first; |
| 329 | var index: u32 = 1; | 330 | var index: u32 = 1; |
| 330 | while (it) |node| : (it = node.next) { | 331 | while (it) |node| : (it = node.next) { |
| 331 | assert(node.data == index); | 332 | testing.expect(node.data == index); |
| 332 | index += 1; | 333 | index += 1; |
| 333 | } | 334 | } |
| 334 | } | 335 | } |
| ... | @@ -338,7 +339,7 @@ test "linked list concatenation" { | ... | @@ -338,7 +339,7 @@ test "linked list concatenation" { |
| 338 | var it = list2.last; | 339 | var it = list2.last; |
| 339 | var index: u32 = 1; | 340 | var index: u32 = 1; |
| 340 | while (it) |node| : (it = node.prev) { | 341 | while (it) |node| : (it = node.prev) { |
| 341 | assert(node.data == (6 - index)); | 342 | testing.expect(node.data == (6 - index)); |
| 342 | index += 1; | 343 | index += 1; |
| 343 | } | 344 | } |
| 344 | } | 345 | } |
std/math/acos.zig+19-19| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | ||
| 5 | const std = @import("../index.zig"); | 5 | const std = @import("../index.zig"); |
| 6 | const math = std.math; | 6 | const math = std.math; |
| 7 | const assert = std.debug.assert; | 7 | const expect = std.testing.expect; |
| 8 | 8 | ||
| 9 | pub fn acos(x: var) @typeOf(x) { | 9 | pub fn acos(x: var) @typeOf(x) { |
| 10 | const T = @typeOf(x); | 10 | const T = @typeOf(x); |
| ... | @@ -143,38 +143,38 @@ fn acos64(x: f64) f64 { | ... | @@ -143,38 +143,38 @@ fn acos64(x: f64) f64 { |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | test "math.acos" { | 145 | test "math.acos" { |
| 146 | assert(acos(f32(0.0)) == acos32(0.0)); | 146 | expect(acos(f32(0.0)) == acos32(0.0)); |
| 147 | assert(acos(f64(0.0)) == acos64(0.0)); | 147 | expect(acos(f64(0.0)) == acos64(0.0)); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | test "math.acos32" { | 150 | test "math.acos32" { |
| 151 | const epsilon = 0.000001; | 151 | const epsilon = 0.000001; |
| 152 | 152 | ||
| 153 | assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon)); | 153 | expect(math.approxEq(f32, acos32(0.0), 1.570796, epsilon)); |
| 154 | assert(math.approxEq(f32, acos32(0.2), 1.369438, epsilon)); | 154 | expect(math.approxEq(f32, acos32(0.2), 1.369438, epsilon)); |
| 155 | assert(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon)); | 155 | expect(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon)); |
| 156 | assert(math.approxEq(f32, acos32(0.5), 1.047198, epsilon)); | 156 | expect(math.approxEq(f32, acos32(0.5), 1.047198, epsilon)); |
| 157 | assert(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon)); | 157 | expect(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon)); |
| 158 | assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon)); | 158 | expect(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon)); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | test "math.acos64" { | 161 | test "math.acos64" { |
| 162 | const epsilon = 0.000001; | 162 | const epsilon = 0.000001; |
| 163 | 163 | ||
| 164 | assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon)); | 164 | expect(math.approxEq(f64, acos64(0.0), 1.570796, epsilon)); |
| 165 | assert(math.approxEq(f64, acos64(0.2), 1.369438, epsilon)); | 165 | expect(math.approxEq(f64, acos64(0.2), 1.369438, epsilon)); |
| 166 | assert(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon)); | 166 | expect(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon)); |
| 167 | assert(math.approxEq(f64, acos64(0.5), 1.047198, epsilon)); | 167 | expect(math.approxEq(f64, acos64(0.5), 1.047198, epsilon)); |
| 168 | assert(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon)); | 168 | expect(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon)); |
| 169 | assert(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon)); | 169 | expect(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon)); |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | test "math.acos32.special" { | 172 | test "math.acos32.special" { |
| 173 | assert(math.isNan(acos32(-2))); | 173 | expect(math.isNan(acos32(-2))); |
| 174 | assert(math.isNan(acos32(1.5))); | 174 | expect(math.isNan(acos32(1.5))); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | test "math.acos64.special" { | 177 | test "math.acos64.special" { |
| 178 | assert(math.isNan(acos64(-2))); | 178 | expect(math.isNan(acos64(-2))); |
| 179 | assert(math.isNan(acos64(1.5))); | 179 | expect(math.isNan(acos64(1.5))); |
| 180 | } | 180 | } |
std/math/acosh.zig+15-15| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | 10 | ||
| 11 | pub fn acosh(x: var) @typeOf(x) { | 11 | pub fn acosh(x: var) @typeOf(x) { |
| 12 | const T = @typeOf(x); | 12 | const T = @typeOf(x); |
| ... | @@ -55,34 +55,34 @@ fn acosh64(x: f64) f64 { | ... | @@ -55,34 +55,34 @@ fn acosh64(x: f64) f64 { |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | test "math.acosh" { | 57 | test "math.acosh" { |
| 58 | assert(acosh(f32(1.5)) == acosh32(1.5)); | 58 | expect(acosh(f32(1.5)) == acosh32(1.5)); |
| 59 | assert(acosh(f64(1.5)) == acosh64(1.5)); | 59 | expect(acosh(f64(1.5)) == acosh64(1.5)); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | test "math.acosh32" { | 62 | test "math.acosh32" { |
| 63 | const epsilon = 0.000001; | 63 | const epsilon = 0.000001; |
| 64 | 64 | ||
| 65 | assert(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon)); | 65 | expect(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon)); |
| 66 | assert(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon)); | 66 | expect(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon)); |
| 67 | assert(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon)); | 67 | expect(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon)); |
| 68 | assert(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon)); | 68 | expect(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon)); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | test "math.acosh64" { | 71 | test "math.acosh64" { |
| 72 | const epsilon = 0.000001; | 72 | const epsilon = 0.000001; |
| 73 | 73 | ||
| 74 | assert(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon)); | 74 | expect(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon)); |
| 75 | assert(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon)); | 75 | expect(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon)); |
| 76 | assert(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon)); | 76 | expect(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon)); |
| 77 | assert(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon)); | 77 | expect(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon)); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | test "math.acosh32.special" { | 80 | test "math.acosh32.special" { |
| 81 | assert(math.isNan(acosh32(math.nan(f32)))); | 81 | expect(math.isNan(acosh32(math.nan(f32)))); |
| 82 | assert(math.isSignalNan(acosh32(0.5))); | 82 | expect(math.isSignalNan(acosh32(0.5))); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | test "math.acosh64.special" { | 85 | test "math.acosh64.special" { |
| 86 | assert(math.isNan(acosh64(math.nan(f64)))); | 86 | expect(math.isNan(acosh64(math.nan(f64)))); |
| 87 | assert(math.isSignalNan(acosh64(0.5))); | 87 | expect(math.isSignalNan(acosh64(0.5))); |
| 88 | } | 88 | } |
std/math/asin.zig+23-23| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ||
| 6 | const std = @import("../index.zig"); | 6 | const std = @import("../index.zig"); |
| 7 | const math = std.math; | 7 | const math = std.math; |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | 9 | ||
| 10 | pub fn asin(x: var) @typeOf(x) { | 10 | pub fn asin(x: var) @typeOf(x) { |
| 11 | const T = @typeOf(x); | 11 | const T = @typeOf(x); |
| ... | @@ -136,42 +136,42 @@ fn asin64(x: f64) f64 { | ... | @@ -136,42 +136,42 @@ fn asin64(x: f64) f64 { |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | test "math.asin" { | 138 | test "math.asin" { |
| 139 | assert(asin(f32(0.0)) == asin32(0.0)); | 139 | expect(asin(f32(0.0)) == asin32(0.0)); |
| 140 | assert(asin(f64(0.0)) == asin64(0.0)); | 140 | expect(asin(f64(0.0)) == asin64(0.0)); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | test "math.asin32" { | 143 | test "math.asin32" { |
| 144 | const epsilon = 0.000001; | 144 | const epsilon = 0.000001; |
| 145 | 145 | ||
| 146 | assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon)); | 146 | expect(math.approxEq(f32, asin32(0.0), 0.0, epsilon)); |
| 147 | assert(math.approxEq(f32, asin32(0.2), 0.201358, epsilon)); | 147 | expect(math.approxEq(f32, asin32(0.2), 0.201358, epsilon)); |
| 148 | assert(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon)); | 148 | expect(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon)); |
| 149 | assert(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon)); | 149 | expect(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon)); |
| 150 | assert(math.approxEq(f32, asin32(0.5), 0.523599, epsilon)); | 150 | expect(math.approxEq(f32, asin32(0.5), 0.523599, epsilon)); |
| 151 | assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon)); | 151 | expect(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon)); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | test "math.asin64" { | 154 | test "math.asin64" { |
| 155 | const epsilon = 0.000001; | 155 | const epsilon = 0.000001; |
| 156 | 156 | ||
| 157 | assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon)); | 157 | expect(math.approxEq(f64, asin64(0.0), 0.0, epsilon)); |
| 158 | assert(math.approxEq(f64, asin64(0.2), 0.201358, epsilon)); | 158 | expect(math.approxEq(f64, asin64(0.2), 0.201358, epsilon)); |
| 159 | assert(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon)); | 159 | expect(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon)); |
| 160 | assert(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon)); | 160 | expect(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon)); |
| 161 | assert(math.approxEq(f64, asin64(0.5), 0.523599, epsilon)); | 161 | expect(math.approxEq(f64, asin64(0.5), 0.523599, epsilon)); |
| 162 | assert(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon)); | 162 | expect(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon)); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | test "math.asin32.special" { | 165 | test "math.asin32.special" { |
| 166 | assert(asin32(0.0) == 0.0); | 166 | expect(asin32(0.0) == 0.0); |
| 167 | assert(asin32(-0.0) == -0.0); | 167 | expect(asin32(-0.0) == -0.0); |
| 168 | assert(math.isNan(asin32(-2))); | 168 | expect(math.isNan(asin32(-2))); |
| 169 | assert(math.isNan(asin32(1.5))); | 169 | expect(math.isNan(asin32(1.5))); |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | test "math.asin64.special" { | 172 | test "math.asin64.special" { |
| 173 | assert(asin64(0.0) == 0.0); | 173 | expect(asin64(0.0) == 0.0); |
| 174 | assert(asin64(-0.0) == -0.0); | 174 | expect(asin64(-0.0) == -0.0); |
| 175 | assert(math.isNan(asin64(-2))); | 175 | expect(math.isNan(asin64(-2))); |
| 176 | assert(math.isNan(asin64(1.5))); | 176 | expect(math.isNan(asin64(1.5))); |
| 177 | } | 177 | } |
std/math/asinh.zig+27-27| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | const maxInt = std.math.maxInt; | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | ||
| 12 | pub fn asinh(x: var) @typeOf(x) { | 12 | pub fn asinh(x: var) @typeOf(x) { |
| ... | @@ -83,46 +83,46 @@ fn asinh64(x: f64) f64 { | ... | @@ -83,46 +83,46 @@ fn asinh64(x: f64) f64 { |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | test "math.asinh" { | 85 | test "math.asinh" { |
| 86 | assert(asinh(f32(0.0)) == asinh32(0.0)); | 86 | expect(asinh(f32(0.0)) == asinh32(0.0)); |
| 87 | assert(asinh(f64(0.0)) == asinh64(0.0)); | 87 | expect(asinh(f64(0.0)) == asinh64(0.0)); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | test "math.asinh32" { | 90 | test "math.asinh32" { |
| 91 | const epsilon = 0.000001; | 91 | const epsilon = 0.000001; |
| 92 | 92 | ||
| 93 | assert(math.approxEq(f32, asinh32(0.0), 0.0, epsilon)); | 93 | expect(math.approxEq(f32, asinh32(0.0), 0.0, epsilon)); |
| 94 | assert(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon)); | 94 | expect(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon)); |
| 95 | assert(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon)); | 95 | expect(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon)); |
| 96 | assert(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon)); | 96 | expect(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon)); |
| 97 | assert(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon)); | 97 | expect(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon)); |
| 98 | assert(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon)); | 98 | expect(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon)); |
| 99 | assert(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon)); | 99 | expect(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon)); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | test "math.asinh64" { | 102 | test "math.asinh64" { |
| 103 | const epsilon = 0.000001; | 103 | const epsilon = 0.000001; |
| 104 | 104 | ||
| 105 | assert(math.approxEq(f64, asinh64(0.0), 0.0, epsilon)); | 105 | expect(math.approxEq(f64, asinh64(0.0), 0.0, epsilon)); |
| 106 | assert(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon)); | 106 | expect(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon)); |
| 107 | assert(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon)); | 107 | expect(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon)); |
| 108 | assert(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon)); | 108 | expect(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon)); |
| 109 | assert(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon)); | 109 | expect(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon)); |
| 110 | assert(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon)); | 110 | expect(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon)); |
| 111 | assert(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon)); | 111 | expect(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon)); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | test "math.asinh32.special" { | 114 | test "math.asinh32.special" { |
| 115 | assert(asinh32(0.0) == 0.0); | 115 | expect(asinh32(0.0) == 0.0); |
| 116 | assert(asinh32(-0.0) == -0.0); | 116 | expect(asinh32(-0.0) == -0.0); |
| 117 | assert(math.isPositiveInf(asinh32(math.inf(f32)))); | 117 | expect(math.isPositiveInf(asinh32(math.inf(f32)))); |
| 118 | assert(math.isNegativeInf(asinh32(-math.inf(f32)))); | 118 | expect(math.isNegativeInf(asinh32(-math.inf(f32)))); |
| 119 | assert(math.isNan(asinh32(math.nan(f32)))); | 119 | expect(math.isNan(asinh32(math.nan(f32)))); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | test "math.asinh64.special" { | 122 | test "math.asinh64.special" { |
| 123 | assert(asinh64(0.0) == 0.0); | 123 | expect(asinh64(0.0) == 0.0); |
| 124 | assert(asinh64(-0.0) == -0.0); | 124 | expect(asinh64(-0.0) == -0.0); |
| 125 | assert(math.isPositiveInf(asinh64(math.inf(f64)))); | 125 | expect(math.isPositiveInf(asinh64(math.inf(f64)))); |
| 126 | assert(math.isNegativeInf(asinh64(-math.inf(f64)))); | 126 | expect(math.isNegativeInf(asinh64(-math.inf(f64)))); |
| 127 | assert(math.isNan(asinh64(math.nan(f64)))); | 127 | expect(math.isNan(asinh64(math.nan(f64)))); |
| 128 | } | 128 | } |
std/math/atan.zig+21-21| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ||
| 6 | const std = @import("../index.zig"); | 6 | const std = @import("../index.zig"); |
| 7 | const math = std.math; | 7 | const math = std.math; |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | 9 | ||
| 10 | pub fn atan(x: var) @typeOf(x) { | 10 | pub fn atan(x: var) @typeOf(x) { |
| 11 | const T = @typeOf(x); | 11 | const T = @typeOf(x); |
| ... | @@ -206,44 +206,44 @@ fn atan64(x_: f64) f64 { | ... | @@ -206,44 +206,44 @@ fn atan64(x_: f64) f64 { |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | test "math.atan" { | 208 | test "math.atan" { |
| 209 | assert(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2))); | 209 | expect(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2))); |
| 210 | assert(atan(f64(0.2)) == atan64(0.2)); | 210 | expect(atan(f64(0.2)) == atan64(0.2)); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | test "math.atan32" { | 213 | test "math.atan32" { |
| 214 | const epsilon = 0.000001; | 214 | const epsilon = 0.000001; |
| 215 | 215 | ||
| 216 | assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon)); | 216 | expect(math.approxEq(f32, atan32(0.2), 0.197396, epsilon)); |
| 217 | assert(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon)); | 217 | expect(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon)); |
| 218 | assert(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon)); | 218 | expect(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon)); |
| 219 | assert(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon)); | 219 | expect(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon)); |
| 220 | assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon)); | 220 | expect(math.approxEq(f32, atan32(1.5), 0.982794, epsilon)); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | test "math.atan64" { | 223 | test "math.atan64" { |
| 224 | const epsilon = 0.000001; | 224 | const epsilon = 0.000001; |
| 225 | 225 | ||
| 226 | assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon)); | 226 | expect(math.approxEq(f64, atan64(0.2), 0.197396, epsilon)); |
| 227 | assert(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon)); | 227 | expect(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon)); |
| 228 | assert(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon)); | 228 | expect(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon)); |
| 229 | assert(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon)); | 229 | expect(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon)); |
| 230 | assert(math.approxEq(f64, atan64(1.5), 0.982794, epsilon)); | 230 | expect(math.approxEq(f64, atan64(1.5), 0.982794, epsilon)); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | test "math.atan32.special" { | 233 | test "math.atan32.special" { |
| 234 | const epsilon = 0.000001; | 234 | const epsilon = 0.000001; |
| 235 | 235 | ||
| 236 | assert(atan32(0.0) == 0.0); | 236 | expect(atan32(0.0) == 0.0); |
| 237 | assert(atan32(-0.0) == -0.0); | 237 | expect(atan32(-0.0) == -0.0); |
| 238 | assert(math.approxEq(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon)); | 238 | expect(math.approxEq(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon)); |
| 239 | assert(math.approxEq(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon)); | 239 | expect(math.approxEq(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon)); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | test "math.atan64.special" { | 242 | test "math.atan64.special" { |
| 243 | const epsilon = 0.000001; | 243 | const epsilon = 0.000001; |
| 244 | 244 | ||
| 245 | assert(atan64(0.0) == 0.0); | 245 | expect(atan64(0.0) == 0.0); |
| 246 | assert(atan64(-0.0) == -0.0); | 246 | expect(atan64(-0.0) == -0.0); |
| 247 | assert(math.approxEq(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon)); | 247 | expect(math.approxEq(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon)); |
| 248 | assert(math.approxEq(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon)); | 248 | expect(math.approxEq(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon)); |
| 249 | } | 249 | } |
std/math/atan2.zig+58-58| ... | @@ -20,12 +20,12 @@ | ... | @@ -20,12 +20,12 @@ |
| 20 | 20 | ||
| 21 | const std = @import("../index.zig"); | 21 | const std = @import("../index.zig"); |
| 22 | const math = std.math; | 22 | const math = std.math; |
| 23 | const assert = std.debug.assert; | 23 | const expect = std.testing.expect; |
| 24 | 24 | ||
| 25 | pub fn atan2(comptime T: type, x: T, y: T) T { | 25 | pub fn atan2(comptime T: type, y: T, x: T) T { |
| 26 | return switch (T) { | 26 | return switch (T) { |
| 27 | f32 => atan2_32(x, y), | 27 | f32 => atan2_32(y, x), |
| 28 | f64 => atan2_64(x, y), | 28 | f64 => atan2_64(y, x), |
| 29 | else => @compileError("atan2 not implemented for " ++ @typeName(T)), | 29 | else => @compileError("atan2 not implemented for " ++ @typeName(T)), |
| 30 | }; | 30 | }; |
| 31 | } | 31 | } |
| ... | @@ -206,78 +206,78 @@ fn atan2_64(y: f64, x: f64) f64 { | ... | @@ -206,78 +206,78 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | test "math.atan2" { | 208 | test "math.atan2" { |
| 209 | assert(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21)); | 209 | expect(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21)); |
| 210 | assert(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21)); | 210 | expect(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21)); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | test "math.atan2_32" { | 213 | test "math.atan2_32" { |
| 214 | const epsilon = 0.000001; | 214 | const epsilon = 0.000001; |
| 215 | 215 | ||
| 216 | assert(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon)); | 216 | expect(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon)); |
| 217 | assert(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon)); | 217 | expect(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon)); |
| 218 | assert(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon)); | 218 | expect(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon)); |
| 219 | assert(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon)); | 219 | expect(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon)); |
| 220 | assert(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon)); | 220 | expect(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon)); |
| 221 | assert(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon)); | 221 | expect(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon)); |
| 222 | assert(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon)); | 222 | expect(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon)); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | test "math.atan2_64" { | 225 | test "math.atan2_64" { |
| 226 | const epsilon = 0.000001; | 226 | const epsilon = 0.000001; |
| 227 | 227 | ||
| 228 | assert(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon)); | 228 | expect(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon)); |
| 229 | assert(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon)); | 229 | expect(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon)); |
| 230 | assert(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon)); | 230 | expect(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon)); |
| 231 | assert(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon)); | 231 | expect(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon)); |
| 232 | assert(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon)); | 232 | expect(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon)); |
| 233 | assert(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon)); | 233 | expect(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon)); |
| 234 | assert(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon)); | 234 | expect(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon)); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | test "math.atan2_32.special" { | 237 | test "math.atan2_32.special" { |
| 238 | const epsilon = 0.000001; | 238 | const epsilon = 0.000001; |
| 239 | 239 | ||
| 240 | assert(math.isNan(atan2_32(1.0, math.nan(f32)))); | 240 | expect(math.isNan(atan2_32(1.0, math.nan(f32)))); |
| 241 | assert(math.isNan(atan2_32(math.nan(f32), 1.0))); | 241 | expect(math.isNan(atan2_32(math.nan(f32), 1.0))); |
| 242 | assert(atan2_32(0.0, 5.0) == 0.0); | 242 | expect(atan2_32(0.0, 5.0) == 0.0); |
| 243 | assert(atan2_32(-0.0, 5.0) == -0.0); | 243 | expect(atan2_32(-0.0, 5.0) == -0.0); |
| 244 | assert(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon)); | 244 | expect(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon)); |
| 245 | //assert(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero? | 245 | //expect(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero? |
| 246 | assert(math.approxEq(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon)); | 246 | expect(math.approxEq(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon)); |
| 247 | assert(math.approxEq(f32, atan2_32(1.0, -0.0), math.pi / 2.0, epsilon)); | 247 | expect(math.approxEq(f32, atan2_32(1.0, -0.0), math.pi / 2.0, epsilon)); |
| 248 | assert(math.approxEq(f32, atan2_32(-1.0, 0.0), -math.pi / 2.0, epsilon)); | 248 | expect(math.approxEq(f32, atan2_32(-1.0, 0.0), -math.pi / 2.0, epsilon)); |
| 249 | assert(math.approxEq(f32, atan2_32(-1.0, -0.0), -math.pi / 2.0, epsilon)); | 249 | expect(math.approxEq(f32, atan2_32(-1.0, -0.0), -math.pi / 2.0, epsilon)); |
| 250 | assert(math.approxEq(f32, atan2_32(math.inf(f32), math.inf(f32)), math.pi / 4.0, epsilon)); | 250 | expect(math.approxEq(f32, atan2_32(math.inf(f32), math.inf(f32)), math.pi / 4.0, epsilon)); |
| 251 | assert(math.approxEq(f32, atan2_32(-math.inf(f32), math.inf(f32)), -math.pi / 4.0, epsilon)); | 251 | expect(math.approxEq(f32, atan2_32(-math.inf(f32), math.inf(f32)), -math.pi / 4.0, epsilon)); |
| 252 | assert(math.approxEq(f32, atan2_32(math.inf(f32), -math.inf(f32)), 3.0 * math.pi / 4.0, epsilon)); | 252 | expect(math.approxEq(f32, atan2_32(math.inf(f32), -math.inf(f32)), 3.0 * math.pi / 4.0, epsilon)); |
| 253 | assert(math.approxEq(f32, atan2_32(-math.inf(f32), -math.inf(f32)), -3.0 * math.pi / 4.0, epsilon)); | 253 | expect(math.approxEq(f32, atan2_32(-math.inf(f32), -math.inf(f32)), -3.0 * math.pi / 4.0, epsilon)); |
| 254 | assert(atan2_32(1.0, math.inf(f32)) == 0.0); | 254 | expect(atan2_32(1.0, math.inf(f32)) == 0.0); |
| 255 | assert(math.approxEq(f32, atan2_32(1.0, -math.inf(f32)), math.pi, epsilon)); | 255 | expect(math.approxEq(f32, atan2_32(1.0, -math.inf(f32)), math.pi, epsilon)); |
| 256 | assert(math.approxEq(f32, atan2_32(-1.0, -math.inf(f32)), -math.pi, epsilon)); | 256 | expect(math.approxEq(f32, atan2_32(-1.0, -math.inf(f32)), -math.pi, epsilon)); |
| 257 | assert(math.approxEq(f32, atan2_32(math.inf(f32), 1.0), math.pi / 2.0, epsilon)); | 257 | expect(math.approxEq(f32, atan2_32(math.inf(f32), 1.0), math.pi / 2.0, epsilon)); |
| 258 | assert(math.approxEq(f32, atan2_32(-math.inf(f32), 1.0), -math.pi / 2.0, epsilon)); | 258 | expect(math.approxEq(f32, atan2_32(-math.inf(f32), 1.0), -math.pi / 2.0, epsilon)); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | test "math.atan2_64.special" { | 261 | test "math.atan2_64.special" { |
| 262 | const epsilon = 0.000001; | 262 | const epsilon = 0.000001; |
| 263 | 263 | ||
| 264 | assert(math.isNan(atan2_64(1.0, math.nan(f64)))); | 264 | expect(math.isNan(atan2_64(1.0, math.nan(f64)))); |
| 265 | assert(math.isNan(atan2_64(math.nan(f64), 1.0))); | 265 | expect(math.isNan(atan2_64(math.nan(f64), 1.0))); |
| 266 | assert(atan2_64(0.0, 5.0) == 0.0); | 266 | expect(atan2_64(0.0, 5.0) == 0.0); |
| 267 | assert(atan2_64(-0.0, 5.0) == -0.0); | 267 | expect(atan2_64(-0.0, 5.0) == -0.0); |
| 268 | assert(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon)); | 268 | expect(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon)); |
| 269 | //assert(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero? | 269 | //expect(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero? |
| 270 | assert(math.approxEq(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon)); | 270 | expect(math.approxEq(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon)); |
| 271 | assert(math.approxEq(f64, atan2_64(1.0, -0.0), math.pi / 2.0, epsilon)); | 271 | expect(math.approxEq(f64, atan2_64(1.0, -0.0), math.pi / 2.0, epsilon)); |
| 272 | assert(math.approxEq(f64, atan2_64(-1.0, 0.0), -math.pi / 2.0, epsilon)); | 272 | expect(math.approxEq(f64, atan2_64(-1.0, 0.0), -math.pi / 2.0, epsilon)); |
| 273 | assert(math.approxEq(f64, atan2_64(-1.0, -0.0), -math.pi / 2.0, epsilon)); | 273 | expect(math.approxEq(f64, atan2_64(-1.0, -0.0), -math.pi / 2.0, epsilon)); |
| 274 | assert(math.approxEq(f64, atan2_64(math.inf(f64), math.inf(f64)), math.pi / 4.0, epsilon)); | 274 | expect(math.approxEq(f64, atan2_64(math.inf(f64), math.inf(f64)), math.pi / 4.0, epsilon)); |
| 275 | assert(math.approxEq(f64, atan2_64(-math.inf(f64), math.inf(f64)), -math.pi / 4.0, epsilon)); | 275 | expect(math.approxEq(f64, atan2_64(-math.inf(f64), math.inf(f64)), -math.pi / 4.0, epsilon)); |
| 276 | assert(math.approxEq(f64, atan2_64(math.inf(f64), -math.inf(f64)), 3.0 * math.pi / 4.0, epsilon)); | 276 | expect(math.approxEq(f64, atan2_64(math.inf(f64), -math.inf(f64)), 3.0 * math.pi / 4.0, epsilon)); |
| 277 | assert(math.approxEq(f64, atan2_64(-math.inf(f64), -math.inf(f64)), -3.0 * math.pi / 4.0, epsilon)); | 277 | expect(math.approxEq(f64, atan2_64(-math.inf(f64), -math.inf(f64)), -3.0 * math.pi / 4.0, epsilon)); |
| 278 | assert(atan2_64(1.0, math.inf(f64)) == 0.0); | 278 | expect(atan2_64(1.0, math.inf(f64)) == 0.0); |
| 279 | assert(math.approxEq(f64, atan2_64(1.0, -math.inf(f64)), math.pi, epsilon)); | 279 | expect(math.approxEq(f64, atan2_64(1.0, -math.inf(f64)), math.pi, epsilon)); |
| 280 | assert(math.approxEq(f64, atan2_64(-1.0, -math.inf(f64)), -math.pi, epsilon)); | 280 | expect(math.approxEq(f64, atan2_64(-1.0, -math.inf(f64)), -math.pi, epsilon)); |
| 281 | assert(math.approxEq(f64, atan2_64(math.inf(f64), 1.0), math.pi / 2.0, epsilon)); | 281 | expect(math.approxEq(f64, atan2_64(math.inf(f64), 1.0), math.pi / 2.0, epsilon)); |
| 282 | assert(math.approxEq(f64, atan2_64(-math.inf(f64), 1.0), -math.pi / 2.0, epsilon)); | 282 | expect(math.approxEq(f64, atan2_64(-math.inf(f64), 1.0), -math.pi / 2.0, epsilon)); |
| 283 | } | 283 | } |
std/math/atanh.zig+19-19| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | const maxInt = std.math.maxInt; | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | ||
| 12 | pub fn atanh(x: var) @typeOf(x) { | 12 | pub fn atanh(x: var) @typeOf(x) { |
| ... | @@ -78,38 +78,38 @@ fn atanh_64(x: f64) f64 { | ... | @@ -78,38 +78,38 @@ fn atanh_64(x: f64) f64 { |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | test "math.atanh" { | 80 | test "math.atanh" { |
| 81 | assert(atanh(f32(0.0)) == atanh_32(0.0)); | 81 | expect(atanh(f32(0.0)) == atanh_32(0.0)); |
| 82 | assert(atanh(f64(0.0)) == atanh_64(0.0)); | 82 | expect(atanh(f64(0.0)) == atanh_64(0.0)); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | test "math.atanh_32" { | 85 | test "math.atanh_32" { |
| 86 | const epsilon = 0.000001; | 86 | const epsilon = 0.000001; |
| 87 | 87 | ||
| 88 | assert(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon)); | 88 | expect(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon)); |
| 89 | assert(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon)); | 89 | expect(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon)); |
| 90 | assert(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon)); | 90 | expect(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon)); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | test "math.atanh_64" { | 93 | test "math.atanh_64" { |
| 94 | const epsilon = 0.000001; | 94 | const epsilon = 0.000001; |
| 95 | 95 | ||
| 96 | assert(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon)); | 96 | expect(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon)); |
| 97 | assert(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon)); | 97 | expect(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon)); |
| 98 | assert(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon)); | 98 | expect(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon)); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | test "math.atanh32.special" { | 101 | test "math.atanh32.special" { |
| 102 | assert(math.isPositiveInf(atanh_32(1))); | 102 | expect(math.isPositiveInf(atanh_32(1))); |
| 103 | assert(math.isNegativeInf(atanh_32(-1))); | 103 | expect(math.isNegativeInf(atanh_32(-1))); |
| 104 | assert(math.isSignalNan(atanh_32(1.5))); | 104 | expect(math.isSignalNan(atanh_32(1.5))); |
| 105 | assert(math.isSignalNan(atanh_32(-1.5))); | 105 | expect(math.isSignalNan(atanh_32(-1.5))); |
| 106 | assert(math.isNan(atanh_32(math.nan(f32)))); | 106 | expect(math.isNan(atanh_32(math.nan(f32)))); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | test "math.atanh64.special" { | 109 | test "math.atanh64.special" { |
| 110 | assert(math.isPositiveInf(atanh_64(1))); | 110 | expect(math.isPositiveInf(atanh_64(1))); |
| 111 | assert(math.isNegativeInf(atanh_64(-1))); | 111 | expect(math.isNegativeInf(atanh_64(-1))); |
| 112 | assert(math.isSignalNan(atanh_64(1.5))); | 112 | expect(math.isSignalNan(atanh_64(1.5))); |
| 113 | assert(math.isSignalNan(atanh_64(-1.5))); | 113 | expect(math.isSignalNan(atanh_64(-1.5))); |
| 114 | assert(math.isNan(atanh_64(math.nan(f64)))); | 114 | expect(math.isNan(atanh_64(math.nan(f64)))); |
| 115 | } | 115 | } |
std/math/big/int.zig+180-187| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 3 | const debug = std.debug; |
| 4 | const testing = std.testing; | ||
| 4 | const math = std.math; | 5 | const math = std.math; |
| 5 | const mem = std.mem; | 6 | const mem = std.mem; |
| 6 | const Allocator = mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| ... | @@ -1086,44 +1087,40 @@ test "big.int comptime_int set" { | ... | @@ -1086,44 +1087,40 @@ test "big.int comptime_int set" { |
| 1086 | const result = Limb(s & maxInt(Limb)); | 1087 | const result = Limb(s & maxInt(Limb)); |
| 1087 | s >>= Limb.bit_count / 2; | 1088 | s >>= Limb.bit_count / 2; |
| 1088 | s >>= Limb.bit_count / 2; | 1089 | s >>= Limb.bit_count / 2; |
| 1089 | debug.assert(a.limbs[i] == result); | 1090 | testing.expect(a.limbs[i] == result); |
| 1090 | } | 1091 | } |
| 1091 | } | 1092 | } |
| 1092 | 1093 | ||
| 1093 | test "big.int comptime_int set negative" { | 1094 | test "big.int comptime_int set negative" { |
| 1094 | var a = try Int.initSet(al, -10); | 1095 | var a = try Int.initSet(al, -10); |
| 1095 | 1096 | ||
| 1096 | debug.assert(a.limbs[0] == 10); | 1097 | testing.expect(a.limbs[0] == 10); |
| 1097 | debug.assert(a.positive == false); | 1098 | testing.expect(a.positive == false); |
| 1098 | } | 1099 | } |
| 1099 | 1100 | ||
| 1100 | test "big.int int set unaligned small" { | 1101 | test "big.int int set unaligned small" { |
| 1101 | var a = try Int.initSet(al, u7(45)); | 1102 | var a = try Int.initSet(al, u7(45)); |
| 1102 | 1103 | ||
| 1103 | debug.assert(a.limbs[0] == 45); | 1104 | testing.expect(a.limbs[0] == 45); |
| 1104 | debug.assert(a.positive == true); | 1105 | testing.expect(a.positive == true); |
| 1105 | } | 1106 | } |
| 1106 | 1107 | ||
| 1107 | test "big.int comptime_int to" { | 1108 | test "big.int comptime_int to" { |
| 1108 | const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab); | 1109 | const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab); |
| 1109 | 1110 | ||
| 1110 | debug.assert((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab); | 1111 | testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab); |
| 1111 | } | 1112 | } |
| 1112 | 1113 | ||
| 1113 | test "big.int sub-limb to" { | 1114 | test "big.int sub-limb to" { |
| 1114 | const a = try Int.initSet(al, 10); | 1115 | const a = try Int.initSet(al, 10); |
| 1115 | 1116 | ||
| 1116 | debug.assert((try a.to(u8)) == 10); | 1117 | testing.expect((try a.to(u8)) == 10); |
| 1117 | } | 1118 | } |
| 1118 | 1119 | ||
| 1119 | test "big.int to target too small error" { | 1120 | test "big.int to target too small error" { |
| 1120 | const a = try Int.initSet(al, 0xffffffff); | 1121 | const a = try Int.initSet(al, 0xffffffff); |
| 1121 | 1122 | ||
| 1122 | if (a.to(u8)) |_| { | 1123 | testing.expectError(error.TargetTooSmall, a.to(u8)); |
| 1123 | unreachable; | ||
| 1124 | } else |err| { | ||
| 1125 | debug.assert(err == error.TargetTooSmall); | ||
| 1126 | } | ||
| 1127 | } | 1124 | } |
| 1128 | 1125 | ||
| 1129 | test "big.int norm1" { | 1126 | test "big.int norm1" { |
| ... | @@ -1135,22 +1132,22 @@ test "big.int norm1" { | ... | @@ -1135,22 +1132,22 @@ test "big.int norm1" { |
| 1135 | a.limbs[2] = 3; | 1132 | a.limbs[2] = 3; |
| 1136 | a.limbs[3] = 0; | 1133 | a.limbs[3] = 0; |
| 1137 | a.norm1(4); | 1134 | a.norm1(4); |
| 1138 | debug.assert(a.len == 3); | 1135 | testing.expect(a.len == 3); |
| 1139 | 1136 | ||
| 1140 | a.limbs[0] = 1; | 1137 | a.limbs[0] = 1; |
| 1141 | a.limbs[1] = 2; | 1138 | a.limbs[1] = 2; |
| 1142 | a.limbs[2] = 3; | 1139 | a.limbs[2] = 3; |
| 1143 | a.norm1(3); | 1140 | a.norm1(3); |
| 1144 | debug.assert(a.len == 3); | 1141 | testing.expect(a.len == 3); |
| 1145 | 1142 | ||
| 1146 | a.limbs[0] = 0; | 1143 | a.limbs[0] = 0; |
| 1147 | a.limbs[1] = 0; | 1144 | a.limbs[1] = 0; |
| 1148 | a.norm1(2); | 1145 | a.norm1(2); |
| 1149 | debug.assert(a.len == 1); | 1146 | testing.expect(a.len == 1); |
| 1150 | 1147 | ||
| 1151 | a.limbs[0] = 0; | 1148 | a.limbs[0] = 0; |
| 1152 | a.norm1(1); | 1149 | a.norm1(1); |
| 1153 | debug.assert(a.len == 1); | 1150 | testing.expect(a.len == 1); |
| 1154 | } | 1151 | } |
| 1155 | 1152 | ||
| 1156 | test "big.int normN" { | 1153 | test "big.int normN" { |
| ... | @@ -1162,144 +1159,144 @@ test "big.int normN" { | ... | @@ -1162,144 +1159,144 @@ test "big.int normN" { |
| 1162 | a.limbs[2] = 0; | 1159 | a.limbs[2] = 0; |
| 1163 | a.limbs[3] = 0; | 1160 | a.limbs[3] = 0; |
| 1164 | a.normN(4); | 1161 | a.normN(4); |
| 1165 | debug.assert(a.len == 2); | 1162 | testing.expect(a.len == 2); |
| 1166 | 1163 | ||
| 1167 | a.limbs[0] = 1; | 1164 | a.limbs[0] = 1; |
| 1168 | a.limbs[1] = 2; | 1165 | a.limbs[1] = 2; |
| 1169 | a.limbs[2] = 3; | 1166 | a.limbs[2] = 3; |
| 1170 | a.normN(3); | 1167 | a.normN(3); |
| 1171 | debug.assert(a.len == 3); | 1168 | testing.expect(a.len == 3); |
| 1172 | 1169 | ||
| 1173 | a.limbs[0] = 0; | 1170 | a.limbs[0] = 0; |
| 1174 | a.limbs[1] = 0; | 1171 | a.limbs[1] = 0; |
| 1175 | a.limbs[2] = 0; | 1172 | a.limbs[2] = 0; |
| 1176 | a.limbs[3] = 0; | 1173 | a.limbs[3] = 0; |
| 1177 | a.normN(4); | 1174 | a.normN(4); |
| 1178 | debug.assert(a.len == 1); | 1175 | testing.expect(a.len == 1); |
| 1179 | 1176 | ||
| 1180 | a.limbs[0] = 0; | 1177 | a.limbs[0] = 0; |
| 1181 | a.normN(1); | 1178 | a.normN(1); |
| 1182 | debug.assert(a.len == 1); | 1179 | testing.expect(a.len == 1); |
| 1183 | } | 1180 | } |
| 1184 | 1181 | ||
| 1185 | test "big.int parity" { | 1182 | test "big.int parity" { |
| 1186 | var a = try Int.init(al); | 1183 | var a = try Int.init(al); |
| 1187 | try a.set(0); | 1184 | try a.set(0); |
| 1188 | debug.assert(a.isEven()); | 1185 | testing.expect(a.isEven()); |
| 1189 | debug.assert(!a.isOdd()); | 1186 | testing.expect(!a.isOdd()); |
| 1190 | 1187 | ||
| 1191 | try a.set(7); | 1188 | try a.set(7); |
| 1192 | debug.assert(!a.isEven()); | 1189 | testing.expect(!a.isEven()); |
| 1193 | debug.assert(a.isOdd()); | 1190 | testing.expect(a.isOdd()); |
| 1194 | } | 1191 | } |
| 1195 | 1192 | ||
| 1196 | test "big.int bitcount + sizeInBase" { | 1193 | test "big.int bitcount + sizeInBase" { |
| 1197 | var a = try Int.init(al); | 1194 | var a = try Int.init(al); |
| 1198 | 1195 | ||
| 1199 | try a.set(0b100); | 1196 | try a.set(0b100); |
| 1200 | debug.assert(a.bitCountAbs() == 3); | 1197 | testing.expect(a.bitCountAbs() == 3); |
| 1201 | debug.assert(a.sizeInBase(2) >= 3); | 1198 | testing.expect(a.sizeInBase(2) >= 3); |
| 1202 | debug.assert(a.sizeInBase(10) >= 1); | 1199 | testing.expect(a.sizeInBase(10) >= 1); |
| 1203 | 1200 | ||
| 1204 | a.negate(); | 1201 | a.negate(); |
| 1205 | debug.assert(a.bitCountAbs() == 3); | 1202 | testing.expect(a.bitCountAbs() == 3); |
| 1206 | debug.assert(a.sizeInBase(2) >= 4); | 1203 | testing.expect(a.sizeInBase(2) >= 4); |
| 1207 | debug.assert(a.sizeInBase(10) >= 2); | 1204 | testing.expect(a.sizeInBase(10) >= 2); |
| 1208 | 1205 | ||
| 1209 | try a.set(0xffffffff); | 1206 | try a.set(0xffffffff); |
| 1210 | debug.assert(a.bitCountAbs() == 32); | 1207 | testing.expect(a.bitCountAbs() == 32); |
| 1211 | debug.assert(a.sizeInBase(2) >= 32); | 1208 | testing.expect(a.sizeInBase(2) >= 32); |
| 1212 | debug.assert(a.sizeInBase(10) >= 10); | 1209 | testing.expect(a.sizeInBase(10) >= 10); |
| 1213 | 1210 | ||
| 1214 | try a.shiftLeft(a, 5000); | 1211 | try a.shiftLeft(a, 5000); |
| 1215 | debug.assert(a.bitCountAbs() == 5032); | 1212 | testing.expect(a.bitCountAbs() == 5032); |
| 1216 | debug.assert(a.sizeInBase(2) >= 5032); | 1213 | testing.expect(a.sizeInBase(2) >= 5032); |
| 1217 | a.positive = false; | 1214 | a.positive = false; |
| 1218 | 1215 | ||
| 1219 | debug.assert(a.bitCountAbs() == 5032); | 1216 | testing.expect(a.bitCountAbs() == 5032); |
| 1220 | debug.assert(a.sizeInBase(2) >= 5033); | 1217 | testing.expect(a.sizeInBase(2) >= 5033); |
| 1221 | } | 1218 | } |
| 1222 | 1219 | ||
| 1223 | test "big.int bitcount/to" { | 1220 | test "big.int bitcount/to" { |
| 1224 | var a = try Int.init(al); | 1221 | var a = try Int.init(al); |
| 1225 | 1222 | ||
| 1226 | try a.set(0); | 1223 | try a.set(0); |
| 1227 | debug.assert(a.bitCountTwosComp() == 0); | 1224 | testing.expect(a.bitCountTwosComp() == 0); |
| 1228 | 1225 | ||
| 1229 | // TODO: stack smashing | 1226 | // TODO: stack smashing |
| 1230 | // debug.assert((try a.to(u0)) == 0); | 1227 | // testing.expect((try a.to(u0)) == 0); |
| 1231 | // TODO: sigsegv | 1228 | // TODO: sigsegv |
| 1232 | // debug.assert((try a.to(i0)) == 0); | 1229 | // testing.expect((try a.to(i0)) == 0); |
| 1233 | 1230 | ||
| 1234 | try a.set(-1); | 1231 | try a.set(-1); |
| 1235 | debug.assert(a.bitCountTwosComp() == 1); | 1232 | testing.expect(a.bitCountTwosComp() == 1); |
| 1236 | debug.assert((try a.to(i1)) == -1); | 1233 | testing.expect((try a.to(i1)) == -1); |
| 1237 | 1234 | ||
| 1238 | try a.set(-8); | 1235 | try a.set(-8); |
| 1239 | debug.assert(a.bitCountTwosComp() == 4); | 1236 | testing.expect(a.bitCountTwosComp() == 4); |
| 1240 | debug.assert((try a.to(i4)) == -8); | 1237 | testing.expect((try a.to(i4)) == -8); |
| 1241 | 1238 | ||
| 1242 | try a.set(127); | 1239 | try a.set(127); |
| 1243 | debug.assert(a.bitCountTwosComp() == 7); | 1240 | testing.expect(a.bitCountTwosComp() == 7); |
| 1244 | debug.assert((try a.to(u7)) == 127); | 1241 | testing.expect((try a.to(u7)) == 127); |
| 1245 | 1242 | ||
| 1246 | try a.set(-128); | 1243 | try a.set(-128); |
| 1247 | debug.assert(a.bitCountTwosComp() == 8); | 1244 | testing.expect(a.bitCountTwosComp() == 8); |
| 1248 | debug.assert((try a.to(i8)) == -128); | 1245 | testing.expect((try a.to(i8)) == -128); |
| 1249 | 1246 | ||
| 1250 | try a.set(-129); | 1247 | try a.set(-129); |
| 1251 | debug.assert(a.bitCountTwosComp() == 9); | 1248 | testing.expect(a.bitCountTwosComp() == 9); |
| 1252 | debug.assert((try a.to(i9)) == -129); | 1249 | testing.expect((try a.to(i9)) == -129); |
| 1253 | } | 1250 | } |
| 1254 | 1251 | ||
| 1255 | test "big.int fits" { | 1252 | test "big.int fits" { |
| 1256 | var a = try Int.init(al); | 1253 | var a = try Int.init(al); |
| 1257 | 1254 | ||
| 1258 | try a.set(0); | 1255 | try a.set(0); |
| 1259 | debug.assert(a.fits(u0)); | 1256 | testing.expect(a.fits(u0)); |
| 1260 | debug.assert(a.fits(i0)); | 1257 | testing.expect(a.fits(i0)); |
| 1261 | 1258 | ||
| 1262 | try a.set(255); | 1259 | try a.set(255); |
| 1263 | debug.assert(!a.fits(u0)); | 1260 | testing.expect(!a.fits(u0)); |
| 1264 | debug.assert(!a.fits(u1)); | 1261 | testing.expect(!a.fits(u1)); |
| 1265 | debug.assert(!a.fits(i8)); | 1262 | testing.expect(!a.fits(i8)); |
| 1266 | debug.assert(a.fits(u8)); | 1263 | testing.expect(a.fits(u8)); |
| 1267 | debug.assert(a.fits(u9)); | 1264 | testing.expect(a.fits(u9)); |
| 1268 | debug.assert(a.fits(i9)); | 1265 | testing.expect(a.fits(i9)); |
| 1269 | 1266 | ||
| 1270 | try a.set(-128); | 1267 | try a.set(-128); |
| 1271 | debug.assert(!a.fits(i7)); | 1268 | testing.expect(!a.fits(i7)); |
| 1272 | debug.assert(a.fits(i8)); | 1269 | testing.expect(a.fits(i8)); |
| 1273 | debug.assert(a.fits(i9)); | 1270 | testing.expect(a.fits(i9)); |
| 1274 | debug.assert(!a.fits(u9)); | 1271 | testing.expect(!a.fits(u9)); |
| 1275 | 1272 | ||
| 1276 | try a.set(0x1ffffffffeeeeeeee); | 1273 | try a.set(0x1ffffffffeeeeeeee); |
| 1277 | debug.assert(!a.fits(u32)); | 1274 | testing.expect(!a.fits(u32)); |
| 1278 | debug.assert(!a.fits(u64)); | 1275 | testing.expect(!a.fits(u64)); |
| 1279 | debug.assert(a.fits(u65)); | 1276 | testing.expect(a.fits(u65)); |
| 1280 | } | 1277 | } |
| 1281 | 1278 | ||
| 1282 | test "big.int string set" { | 1279 | test "big.int string set" { |
| 1283 | var a = try Int.init(al); | 1280 | var a = try Int.init(al); |
| 1284 | try a.setString(10, "120317241209124781241290847124"); | 1281 | try a.setString(10, "120317241209124781241290847124"); |
| 1285 | 1282 | ||
| 1286 | debug.assert((try a.to(u128)) == 120317241209124781241290847124); | 1283 | testing.expect((try a.to(u128)) == 120317241209124781241290847124); |
| 1287 | } | 1284 | } |
| 1288 | 1285 | ||
| 1289 | test "big.int string negative" { | 1286 | test "big.int string negative" { |
| 1290 | var a = try Int.init(al); | 1287 | var a = try Int.init(al); |
| 1291 | try a.setString(10, "-1023"); | 1288 | try a.setString(10, "-1023"); |
| 1292 | debug.assert((try a.to(i32)) == -1023); | 1289 | testing.expect((try a.to(i32)) == -1023); |
| 1293 | } | 1290 | } |
| 1294 | 1291 | ||
| 1295 | test "big.int string set bad char error" { | 1292 | test "big.int string set bad char error" { |
| 1296 | var a = try Int.init(al); | 1293 | var a = try Int.init(al); |
| 1297 | a.setString(10, "x") catch |err| debug.assert(err == error.InvalidCharForDigit); | 1294 | testing.expectError(error.InvalidCharForDigit, a.setString(10, "x")); |
| 1298 | } | 1295 | } |
| 1299 | 1296 | ||
| 1300 | test "big.int string set bad base error" { | 1297 | test "big.int string set bad base error" { |
| 1301 | var a = try Int.init(al); | 1298 | var a = try Int.init(al); |
| 1302 | a.setString(45, "10") catch |err| debug.assert(err == error.InvalidBase); | 1299 | testing.expectError(error.InvalidBase, a.setString(45, "10")); |
| 1303 | } | 1300 | } |
| 1304 | 1301 | ||
| 1305 | test "big.int string to" { | 1302 | test "big.int string to" { |
| ... | @@ -1308,17 +1305,13 @@ test "big.int string to" { | ... | @@ -1308,17 +1305,13 @@ test "big.int string to" { |
| 1308 | const as = try a.toString(al, 10); | 1305 | const as = try a.toString(al, 10); |
| 1309 | const es = "120317241209124781241290847124"; | 1306 | const es = "120317241209124781241290847124"; |
| 1310 | 1307 | ||
| 1311 | debug.assert(mem.eql(u8, as, es)); | 1308 | testing.expect(mem.eql(u8, as, es)); |
| 1312 | } | 1309 | } |
| 1313 | 1310 | ||
| 1314 | test "big.int string to base base error" { | 1311 | test "big.int string to base base error" { |
| 1315 | const a = try Int.initSet(al, 0xffffffff); | 1312 | const a = try Int.initSet(al, 0xffffffff); |
| 1316 | 1313 | ||
| 1317 | if (a.toString(al, 45)) |_| { | 1314 | testing.expectError(error.InvalidBase, a.toString(al, 45)); |
| 1318 | unreachable; | ||
| 1319 | } else |err| { | ||
| 1320 | debug.assert(err == error.InvalidBase); | ||
| 1321 | } | ||
| 1322 | } | 1315 | } |
| 1323 | 1316 | ||
| 1324 | test "big.int string to base 2" { | 1317 | test "big.int string to base 2" { |
| ... | @@ -1327,7 +1320,7 @@ test "big.int string to base 2" { | ... | @@ -1327,7 +1320,7 @@ test "big.int string to base 2" { |
| 1327 | const as = try a.toString(al, 2); | 1320 | const as = try a.toString(al, 2); |
| 1328 | const es = "-1011"; | 1321 | const es = "-1011"; |
| 1329 | 1322 | ||
| 1330 | debug.assert(mem.eql(u8, as, es)); | 1323 | testing.expect(mem.eql(u8, as, es)); |
| 1331 | } | 1324 | } |
| 1332 | 1325 | ||
| 1333 | test "big.int string to base 16" { | 1326 | test "big.int string to base 16" { |
| ... | @@ -1336,7 +1329,7 @@ test "big.int string to base 16" { | ... | @@ -1336,7 +1329,7 @@ test "big.int string to base 16" { |
| 1336 | const as = try a.toString(al, 16); | 1329 | const as = try a.toString(al, 16); |
| 1337 | const es = "efffffff00000001eeeeeeefaaaaaaab"; | 1330 | const es = "efffffff00000001eeeeeeefaaaaaaab"; |
| 1338 | 1331 | ||
| 1339 | debug.assert(mem.eql(u8, as, es)); | 1332 | testing.expect(mem.eql(u8, as, es)); |
| 1340 | } | 1333 | } |
| 1341 | 1334 | ||
| 1342 | test "big.int neg string to" { | 1335 | test "big.int neg string to" { |
| ... | @@ -1345,7 +1338,7 @@ test "big.int neg string to" { | ... | @@ -1345,7 +1338,7 @@ test "big.int neg string to" { |
| 1345 | const as = try a.toString(al, 10); | 1338 | const as = try a.toString(al, 10); |
| 1346 | const es = "-123907434"; | 1339 | const es = "-123907434"; |
| 1347 | 1340 | ||
| 1348 | debug.assert(mem.eql(u8, as, es)); | 1341 | testing.expect(mem.eql(u8, as, es)); |
| 1349 | } | 1342 | } |
| 1350 | 1343 | ||
| 1351 | test "big.int zero string to" { | 1344 | test "big.int zero string to" { |
| ... | @@ -1354,98 +1347,98 @@ test "big.int zero string to" { | ... | @@ -1354,98 +1347,98 @@ test "big.int zero string to" { |
| 1354 | const as = try a.toString(al, 10); | 1347 | const as = try a.toString(al, 10); |
| 1355 | const es = "0"; | 1348 | const es = "0"; |
| 1356 | 1349 | ||
| 1357 | debug.assert(mem.eql(u8, as, es)); | 1350 | testing.expect(mem.eql(u8, as, es)); |
| 1358 | } | 1351 | } |
| 1359 | 1352 | ||
| 1360 | test "big.int clone" { | 1353 | test "big.int clone" { |
| 1361 | var a = try Int.initSet(al, 1234); | 1354 | var a = try Int.initSet(al, 1234); |
| 1362 | const b = try a.clone(); | 1355 | const b = try a.clone(); |
| 1363 | 1356 | ||
| 1364 | debug.assert((try a.to(u32)) == 1234); | 1357 | testing.expect((try a.to(u32)) == 1234); |
| 1365 | debug.assert((try b.to(u32)) == 1234); | 1358 | testing.expect((try b.to(u32)) == 1234); |
| 1366 | 1359 | ||
| 1367 | try a.set(77); | 1360 | try a.set(77); |
| 1368 | debug.assert((try a.to(u32)) == 77); | 1361 | testing.expect((try a.to(u32)) == 77); |
| 1369 | debug.assert((try b.to(u32)) == 1234); | 1362 | testing.expect((try b.to(u32)) == 1234); |
| 1370 | } | 1363 | } |
| 1371 | 1364 | ||
| 1372 | test "big.int swap" { | 1365 | test "big.int swap" { |
| 1373 | var a = try Int.initSet(al, 1234); | 1366 | var a = try Int.initSet(al, 1234); |
| 1374 | var b = try Int.initSet(al, 5678); | 1367 | var b = try Int.initSet(al, 5678); |
| 1375 | 1368 | ||
| 1376 | debug.assert((try a.to(u32)) == 1234); | 1369 | testing.expect((try a.to(u32)) == 1234); |
| 1377 | debug.assert((try b.to(u32)) == 5678); | 1370 | testing.expect((try b.to(u32)) == 5678); |
| 1378 | 1371 | ||
| 1379 | a.swap(&b); | 1372 | a.swap(&b); |
| 1380 | 1373 | ||
| 1381 | debug.assert((try a.to(u32)) == 5678); | 1374 | testing.expect((try a.to(u32)) == 5678); |
| 1382 | debug.assert((try b.to(u32)) == 1234); | 1375 | testing.expect((try b.to(u32)) == 1234); |
| 1383 | } | 1376 | } |
| 1384 | 1377 | ||
| 1385 | test "big.int to negative" { | 1378 | test "big.int to negative" { |
| 1386 | var a = try Int.initSet(al, -10); | 1379 | var a = try Int.initSet(al, -10); |
| 1387 | 1380 | ||
| 1388 | debug.assert((try a.to(i32)) == -10); | 1381 | testing.expect((try a.to(i32)) == -10); |
| 1389 | } | 1382 | } |
| 1390 | 1383 | ||
| 1391 | test "big.int compare" { | 1384 | test "big.int compare" { |
| 1392 | var a = try Int.initSet(al, -11); | 1385 | var a = try Int.initSet(al, -11); |
| 1393 | var b = try Int.initSet(al, 10); | 1386 | var b = try Int.initSet(al, 10); |
| 1394 | 1387 | ||
| 1395 | debug.assert(a.cmpAbs(b) == 1); | 1388 | testing.expect(a.cmpAbs(b) == 1); |
| 1396 | debug.assert(a.cmp(b) == -1); | 1389 | testing.expect(a.cmp(b) == -1); |
| 1397 | } | 1390 | } |
| 1398 | 1391 | ||
| 1399 | test "big.int compare similar" { | 1392 | test "big.int compare similar" { |
| 1400 | var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee); | 1393 | var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee); |
| 1401 | var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef); | 1394 | var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef); |
| 1402 | 1395 | ||
| 1403 | debug.assert(a.cmpAbs(b) == -1); | 1396 | testing.expect(a.cmpAbs(b) == -1); |
| 1404 | debug.assert(b.cmpAbs(a) == 1); | 1397 | testing.expect(b.cmpAbs(a) == 1); |
| 1405 | } | 1398 | } |
| 1406 | 1399 | ||
| 1407 | test "big.int compare different limb size" { | 1400 | test "big.int compare different limb size" { |
| 1408 | var a = try Int.initSet(al, maxInt(Limb) + 1); | 1401 | var a = try Int.initSet(al, maxInt(Limb) + 1); |
| 1409 | var b = try Int.initSet(al, 1); | 1402 | var b = try Int.initSet(al, 1); |
| 1410 | 1403 | ||
| 1411 | debug.assert(a.cmpAbs(b) == 1); | 1404 | testing.expect(a.cmpAbs(b) == 1); |
| 1412 | debug.assert(b.cmpAbs(a) == -1); | 1405 | testing.expect(b.cmpAbs(a) == -1); |
| 1413 | } | 1406 | } |
| 1414 | 1407 | ||
| 1415 | test "big.int compare multi-limb" { | 1408 | test "big.int compare multi-limb" { |
| 1416 | var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef); | 1409 | var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef); |
| 1417 | var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee); | 1410 | var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee); |
| 1418 | 1411 | ||
| 1419 | debug.assert(a.cmpAbs(b) == 1); | 1412 | testing.expect(a.cmpAbs(b) == 1); |
| 1420 | debug.assert(a.cmp(b) == -1); | 1413 | testing.expect(a.cmp(b) == -1); |
| 1421 | } | 1414 | } |
| 1422 | 1415 | ||
| 1423 | test "big.int equality" { | 1416 | test "big.int equality" { |
| 1424 | var a = try Int.initSet(al, 0xffffffff1); | 1417 | var a = try Int.initSet(al, 0xffffffff1); |
| 1425 | var b = try Int.initSet(al, -0xffffffff1); | 1418 | var b = try Int.initSet(al, -0xffffffff1); |
| 1426 | 1419 | ||
| 1427 | debug.assert(a.eqAbs(b)); | 1420 | testing.expect(a.eqAbs(b)); |
| 1428 | debug.assert(!a.eq(b)); | 1421 | testing.expect(!a.eq(b)); |
| 1429 | } | 1422 | } |
| 1430 | 1423 | ||
| 1431 | test "big.int abs" { | 1424 | test "big.int abs" { |
| 1432 | var a = try Int.initSet(al, -5); | 1425 | var a = try Int.initSet(al, -5); |
| 1433 | 1426 | ||
| 1434 | a.abs(); | 1427 | a.abs(); |
| 1435 | debug.assert((try a.to(u32)) == 5); | 1428 | testing.expect((try a.to(u32)) == 5); |
| 1436 | 1429 | ||
| 1437 | a.abs(); | 1430 | a.abs(); |
| 1438 | debug.assert((try a.to(u32)) == 5); | 1431 | testing.expect((try a.to(u32)) == 5); |
| 1439 | } | 1432 | } |
| 1440 | 1433 | ||
| 1441 | test "big.int negate" { | 1434 | test "big.int negate" { |
| 1442 | var a = try Int.initSet(al, 5); | 1435 | var a = try Int.initSet(al, 5); |
| 1443 | 1436 | ||
| 1444 | a.negate(); | 1437 | a.negate(); |
| 1445 | debug.assert((try a.to(i32)) == -5); | 1438 | testing.expect((try a.to(i32)) == -5); |
| 1446 | 1439 | ||
| 1447 | a.negate(); | 1440 | a.negate(); |
| 1448 | debug.assert((try a.to(i32)) == 5); | 1441 | testing.expect((try a.to(i32)) == 5); |
| 1449 | } | 1442 | } |
| 1450 | 1443 | ||
| 1451 | test "big.int add single-single" { | 1444 | test "big.int add single-single" { |
| ... | @@ -1455,7 +1448,7 @@ test "big.int add single-single" { | ... | @@ -1455,7 +1448,7 @@ test "big.int add single-single" { |
| 1455 | var c = try Int.init(al); | 1448 | var c = try Int.init(al); |
| 1456 | try c.add(a, b); | 1449 | try c.add(a, b); |
| 1457 | 1450 | ||
| 1458 | debug.assert((try c.to(u32)) == 55); | 1451 | testing.expect((try c.to(u32)) == 55); |
| 1459 | } | 1452 | } |
| 1460 | 1453 | ||
| 1461 | test "big.int add multi-single" { | 1454 | test "big.int add multi-single" { |
| ... | @@ -1465,10 +1458,10 @@ test "big.int add multi-single" { | ... | @@ -1465,10 +1458,10 @@ test "big.int add multi-single" { |
| 1465 | var c = try Int.init(al); | 1458 | var c = try Int.init(al); |
| 1466 | 1459 | ||
| 1467 | try c.add(a, b); | 1460 | try c.add(a, b); |
| 1468 | debug.assert((try c.to(DoubleLimb)) == maxInt(Limb) + 2); | 1461 | testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2); |
| 1469 | 1462 | ||
| 1470 | try c.add(b, a); | 1463 | try c.add(b, a); |
| 1471 | debug.assert((try c.to(DoubleLimb)) == maxInt(Limb) + 2); | 1464 | testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2); |
| 1472 | } | 1465 | } |
| 1473 | 1466 | ||
| 1474 | test "big.int add multi-multi" { | 1467 | test "big.int add multi-multi" { |
| ... | @@ -1480,7 +1473,7 @@ test "big.int add multi-multi" { | ... | @@ -1480,7 +1473,7 @@ test "big.int add multi-multi" { |
| 1480 | var c = try Int.init(al); | 1473 | var c = try Int.init(al); |
| 1481 | try c.add(a, b); | 1474 | try c.add(a, b); |
| 1482 | 1475 | ||
| 1483 | debug.assert((try c.to(u128)) == op1 + op2); | 1476 | testing.expect((try c.to(u128)) == op1 + op2); |
| 1484 | } | 1477 | } |
| 1485 | 1478 | ||
| 1486 | test "big.int add zero-zero" { | 1479 | test "big.int add zero-zero" { |
| ... | @@ -1490,7 +1483,7 @@ test "big.int add zero-zero" { | ... | @@ -1490,7 +1483,7 @@ test "big.int add zero-zero" { |
| 1490 | var c = try Int.init(al); | 1483 | var c = try Int.init(al); |
| 1491 | try c.add(a, b); | 1484 | try c.add(a, b); |
| 1492 | 1485 | ||
| 1493 | debug.assert((try c.to(u32)) == 0); | 1486 | testing.expect((try c.to(u32)) == 0); |
| 1494 | } | 1487 | } |
| 1495 | 1488 | ||
| 1496 | test "big.int add alias multi-limb nonzero-zero" { | 1489 | test "big.int add alias multi-limb nonzero-zero" { |
| ... | @@ -1500,7 +1493,7 @@ test "big.int add alias multi-limb nonzero-zero" { | ... | @@ -1500,7 +1493,7 @@ test "big.int add alias multi-limb nonzero-zero" { |
| 1500 | 1493 | ||
| 1501 | try a.add(a, b); | 1494 | try a.add(a, b); |
| 1502 | 1495 | ||
| 1503 | debug.assert((try a.to(u128)) == op1); | 1496 | testing.expect((try a.to(u128)) == op1); |
| 1504 | } | 1497 | } |
| 1505 | 1498 | ||
| 1506 | test "big.int add sign" { | 1499 | test "big.int add sign" { |
| ... | @@ -1512,16 +1505,16 @@ test "big.int add sign" { | ... | @@ -1512,16 +1505,16 @@ test "big.int add sign" { |
| 1512 | const neg_two = try Int.initSet(al, -2); | 1505 | const neg_two = try Int.initSet(al, -2); |
| 1513 | 1506 | ||
| 1514 | try a.add(one, two); | 1507 | try a.add(one, two); |
| 1515 | debug.assert((try a.to(i32)) == 3); | 1508 | testing.expect((try a.to(i32)) == 3); |
| 1516 | 1509 | ||
| 1517 | try a.add(neg_one, two); | 1510 | try a.add(neg_one, two); |
| 1518 | debug.assert((try a.to(i32)) == 1); | 1511 | testing.expect((try a.to(i32)) == 1); |
| 1519 | 1512 | ||
| 1520 | try a.add(one, neg_two); | 1513 | try a.add(one, neg_two); |
| 1521 | debug.assert((try a.to(i32)) == -1); | 1514 | testing.expect((try a.to(i32)) == -1); |
| 1522 | 1515 | ||
| 1523 | try a.add(neg_one, neg_two); | 1516 | try a.add(neg_one, neg_two); |
| 1524 | debug.assert((try a.to(i32)) == -3); | 1517 | testing.expect((try a.to(i32)) == -3); |
| 1525 | } | 1518 | } |
| 1526 | 1519 | ||
| 1527 | test "big.int sub single-single" { | 1520 | test "big.int sub single-single" { |
| ... | @@ -1531,7 +1524,7 @@ test "big.int sub single-single" { | ... | @@ -1531,7 +1524,7 @@ test "big.int sub single-single" { |
| 1531 | var c = try Int.init(al); | 1524 | var c = try Int.init(al); |
| 1532 | try c.sub(a, b); | 1525 | try c.sub(a, b); |
| 1533 | 1526 | ||
| 1534 | debug.assert((try c.to(u32)) == 45); | 1527 | testing.expect((try c.to(u32)) == 45); |
| 1535 | } | 1528 | } |
| 1536 | 1529 | ||
| 1537 | test "big.int sub multi-single" { | 1530 | test "big.int sub multi-single" { |
| ... | @@ -1541,7 +1534,7 @@ test "big.int sub multi-single" { | ... | @@ -1541,7 +1534,7 @@ test "big.int sub multi-single" { |
| 1541 | var c = try Int.init(al); | 1534 | var c = try Int.init(al); |
| 1542 | try c.sub(a, b); | 1535 | try c.sub(a, b); |
| 1543 | 1536 | ||
| 1544 | debug.assert((try c.to(Limb)) == maxInt(Limb)); | 1537 | testing.expect((try c.to(Limb)) == maxInt(Limb)); |
| 1545 | } | 1538 | } |
| 1546 | 1539 | ||
| 1547 | test "big.int sub multi-multi" { | 1540 | test "big.int sub multi-multi" { |
| ... | @@ -1554,7 +1547,7 @@ test "big.int sub multi-multi" { | ... | @@ -1554,7 +1547,7 @@ test "big.int sub multi-multi" { |
| 1554 | var c = try Int.init(al); | 1547 | var c = try Int.init(al); |
| 1555 | try c.sub(a, b); | 1548 | try c.sub(a, b); |
| 1556 | 1549 | ||
| 1557 | debug.assert((try c.to(u128)) == op1 - op2); | 1550 | testing.expect((try c.to(u128)) == op1 - op2); |
| 1558 | } | 1551 | } |
| 1559 | 1552 | ||
| 1560 | test "big.int sub equal" { | 1553 | test "big.int sub equal" { |
| ... | @@ -1564,7 +1557,7 @@ test "big.int sub equal" { | ... | @@ -1564,7 +1557,7 @@ test "big.int sub equal" { |
| 1564 | var c = try Int.init(al); | 1557 | var c = try Int.init(al); |
| 1565 | try c.sub(a, b); | 1558 | try c.sub(a, b); |
| 1566 | 1559 | ||
| 1567 | debug.assert((try c.to(u32)) == 0); | 1560 | testing.expect((try c.to(u32)) == 0); |
| 1568 | } | 1561 | } |
| 1569 | 1562 | ||
| 1570 | test "big.int sub sign" { | 1563 | test "big.int sub sign" { |
| ... | @@ -1576,19 +1569,19 @@ test "big.int sub sign" { | ... | @@ -1576,19 +1569,19 @@ test "big.int sub sign" { |
| 1576 | const neg_two = try Int.initSet(al, -2); | 1569 | const neg_two = try Int.initSet(al, -2); |
| 1577 | 1570 | ||
| 1578 | try a.sub(one, two); | 1571 | try a.sub(one, two); |
| 1579 | debug.assert((try a.to(i32)) == -1); | 1572 | testing.expect((try a.to(i32)) == -1); |
| 1580 | 1573 | ||
| 1581 | try a.sub(neg_one, two); | 1574 | try a.sub(neg_one, two); |
| 1582 | debug.assert((try a.to(i32)) == -3); | 1575 | testing.expect((try a.to(i32)) == -3); |
| 1583 | 1576 | ||
| 1584 | try a.sub(one, neg_two); | 1577 | try a.sub(one, neg_two); |
| 1585 | debug.assert((try a.to(i32)) == 3); | 1578 | testing.expect((try a.to(i32)) == 3); |
| 1586 | 1579 | ||
| 1587 | try a.sub(neg_one, neg_two); | 1580 | try a.sub(neg_one, neg_two); |
| 1588 | debug.assert((try a.to(i32)) == 1); | 1581 | testing.expect((try a.to(i32)) == 1); |
| 1589 | 1582 | ||
| 1590 | try a.sub(neg_two, neg_one); | 1583 | try a.sub(neg_two, neg_one); |
| 1591 | debug.assert((try a.to(i32)) == -1); | 1584 | testing.expect((try a.to(i32)) == -1); |
| 1592 | } | 1585 | } |
| 1593 | 1586 | ||
| 1594 | test "big.int mul single-single" { | 1587 | test "big.int mul single-single" { |
| ... | @@ -1598,7 +1591,7 @@ test "big.int mul single-single" { | ... | @@ -1598,7 +1591,7 @@ test "big.int mul single-single" { |
| 1598 | var c = try Int.init(al); | 1591 | var c = try Int.init(al); |
| 1599 | try c.mul(a, b); | 1592 | try c.mul(a, b); |
| 1600 | 1593 | ||
| 1601 | debug.assert((try c.to(u64)) == 250); | 1594 | testing.expect((try c.to(u64)) == 250); |
| 1602 | } | 1595 | } |
| 1603 | 1596 | ||
| 1604 | test "big.int mul multi-single" { | 1597 | test "big.int mul multi-single" { |
| ... | @@ -1608,7 +1601,7 @@ test "big.int mul multi-single" { | ... | @@ -1608,7 +1601,7 @@ test "big.int mul multi-single" { |
| 1608 | var c = try Int.init(al); | 1601 | var c = try Int.init(al); |
| 1609 | try c.mul(a, b); | 1602 | try c.mul(a, b); |
| 1610 | 1603 | ||
| 1611 | debug.assert((try c.to(DoubleLimb)) == 2 * maxInt(Limb)); | 1604 | testing.expect((try c.to(DoubleLimb)) == 2 * maxInt(Limb)); |
| 1612 | } | 1605 | } |
| 1613 | 1606 | ||
| 1614 | test "big.int mul multi-multi" { | 1607 | test "big.int mul multi-multi" { |
| ... | @@ -1620,7 +1613,7 @@ test "big.int mul multi-multi" { | ... | @@ -1620,7 +1613,7 @@ test "big.int mul multi-multi" { |
| 1620 | var c = try Int.init(al); | 1613 | var c = try Int.init(al); |
| 1621 | try c.mul(a, b); | 1614 | try c.mul(a, b); |
| 1622 | 1615 | ||
| 1623 | debug.assert((try c.to(u256)) == op1 * op2); | 1616 | testing.expect((try c.to(u256)) == op1 * op2); |
| 1624 | } | 1617 | } |
| 1625 | 1618 | ||
| 1626 | test "big.int mul alias r with a" { | 1619 | test "big.int mul alias r with a" { |
| ... | @@ -1629,7 +1622,7 @@ test "big.int mul alias r with a" { | ... | @@ -1629,7 +1622,7 @@ test "big.int mul alias r with a" { |
| 1629 | 1622 | ||
| 1630 | try a.mul(a, b); | 1623 | try a.mul(a, b); |
| 1631 | 1624 | ||
| 1632 | debug.assert((try a.to(DoubleLimb)) == 2 * maxInt(Limb)); | 1625 | testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb)); |
| 1633 | } | 1626 | } |
| 1634 | 1627 | ||
| 1635 | test "big.int mul alias r with b" { | 1628 | test "big.int mul alias r with b" { |
| ... | @@ -1638,7 +1631,7 @@ test "big.int mul alias r with b" { | ... | @@ -1638,7 +1631,7 @@ test "big.int mul alias r with b" { |
| 1638 | 1631 | ||
| 1639 | try a.mul(b, a); | 1632 | try a.mul(b, a); |
| 1640 | 1633 | ||
| 1641 | debug.assert((try a.to(DoubleLimb)) == 2 * maxInt(Limb)); | 1634 | testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb)); |
| 1642 | } | 1635 | } |
| 1643 | 1636 | ||
| 1644 | test "big.int mul alias r with a and b" { | 1637 | test "big.int mul alias r with a and b" { |
| ... | @@ -1646,7 +1639,7 @@ test "big.int mul alias r with a and b" { | ... | @@ -1646,7 +1639,7 @@ test "big.int mul alias r with a and b" { |
| 1646 | 1639 | ||
| 1647 | try a.mul(a, a); | 1640 | try a.mul(a, a); |
| 1648 | 1641 | ||
| 1649 | debug.assert((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb)); | 1642 | testing.expect((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb)); |
| 1650 | } | 1643 | } |
| 1651 | 1644 | ||
| 1652 | test "big.int mul a*0" { | 1645 | test "big.int mul a*0" { |
| ... | @@ -1656,7 +1649,7 @@ test "big.int mul a*0" { | ... | @@ -1656,7 +1649,7 @@ test "big.int mul a*0" { |
| 1656 | var c = try Int.init(al); | 1649 | var c = try Int.init(al); |
| 1657 | try c.mul(a, b); | 1650 | try c.mul(a, b); |
| 1658 | 1651 | ||
| 1659 | debug.assert((try c.to(u32)) == 0); | 1652 | testing.expect((try c.to(u32)) == 0); |
| 1660 | } | 1653 | } |
| 1661 | 1654 | ||
| 1662 | test "big.int mul 0*0" { | 1655 | test "big.int mul 0*0" { |
| ... | @@ -1666,7 +1659,7 @@ test "big.int mul 0*0" { | ... | @@ -1666,7 +1659,7 @@ test "big.int mul 0*0" { |
| 1666 | var c = try Int.init(al); | 1659 | var c = try Int.init(al); |
| 1667 | try c.mul(a, b); | 1660 | try c.mul(a, b); |
| 1668 | 1661 | ||
| 1669 | debug.assert((try c.to(u32)) == 0); | 1662 | testing.expect((try c.to(u32)) == 0); |
| 1670 | } | 1663 | } |
| 1671 | 1664 | ||
| 1672 | test "big.int div single-single no rem" { | 1665 | test "big.int div single-single no rem" { |
| ... | @@ -1677,8 +1670,8 @@ test "big.int div single-single no rem" { | ... | @@ -1677,8 +1670,8 @@ test "big.int div single-single no rem" { |
| 1677 | var r = try Int.init(al); | 1670 | var r = try Int.init(al); |
| 1678 | try Int.divTrunc(&q, &r, a, b); | 1671 | try Int.divTrunc(&q, &r, a, b); |
| 1679 | 1672 | ||
| 1680 | debug.assert((try q.to(u32)) == 10); | 1673 | testing.expect((try q.to(u32)) == 10); |
| 1681 | debug.assert((try r.to(u32)) == 0); | 1674 | testing.expect((try r.to(u32)) == 0); |
| 1682 | } | 1675 | } |
| 1683 | 1676 | ||
| 1684 | test "big.int div single-single with rem" { | 1677 | test "big.int div single-single with rem" { |
| ... | @@ -1689,8 +1682,8 @@ test "big.int div single-single with rem" { | ... | @@ -1689,8 +1682,8 @@ test "big.int div single-single with rem" { |
| 1689 | var r = try Int.init(al); | 1682 | var r = try Int.init(al); |
| 1690 | try Int.divTrunc(&q, &r, a, b); | 1683 | try Int.divTrunc(&q, &r, a, b); |
| 1691 | 1684 | ||
| 1692 | debug.assert((try q.to(u32)) == 9); | 1685 | testing.expect((try q.to(u32)) == 9); |
| 1693 | debug.assert((try r.to(u32)) == 4); | 1686 | testing.expect((try r.to(u32)) == 4); |
| 1694 | } | 1687 | } |
| 1695 | 1688 | ||
| 1696 | test "big.int div multi-single no rem" { | 1689 | test "big.int div multi-single no rem" { |
| ... | @@ -1704,8 +1697,8 @@ test "big.int div multi-single no rem" { | ... | @@ -1704,8 +1697,8 @@ test "big.int div multi-single no rem" { |
| 1704 | var r = try Int.init(al); | 1697 | var r = try Int.init(al); |
| 1705 | try Int.divTrunc(&q, &r, a, b); | 1698 | try Int.divTrunc(&q, &r, a, b); |
| 1706 | 1699 | ||
| 1707 | debug.assert((try q.to(u64)) == op1 / op2); | 1700 | testing.expect((try q.to(u64)) == op1 / op2); |
| 1708 | debug.assert((try r.to(u64)) == 0); | 1701 | testing.expect((try r.to(u64)) == 0); |
| 1709 | } | 1702 | } |
| 1710 | 1703 | ||
| 1711 | test "big.int div multi-single with rem" { | 1704 | test "big.int div multi-single with rem" { |
| ... | @@ -1719,8 +1712,8 @@ test "big.int div multi-single with rem" { | ... | @@ -1719,8 +1712,8 @@ test "big.int div multi-single with rem" { |
| 1719 | var r = try Int.init(al); | 1712 | var r = try Int.init(al); |
| 1720 | try Int.divTrunc(&q, &r, a, b); | 1713 | try Int.divTrunc(&q, &r, a, b); |
| 1721 | 1714 | ||
| 1722 | debug.assert((try q.to(u64)) == op1 / op2); | 1715 | testing.expect((try q.to(u64)) == op1 / op2); |
| 1723 | debug.assert((try r.to(u64)) == 3); | 1716 | testing.expect((try r.to(u64)) == 3); |
| 1724 | } | 1717 | } |
| 1725 | 1718 | ||
| 1726 | test "big.int div multi>2-single" { | 1719 | test "big.int div multi>2-single" { |
| ... | @@ -1734,8 +1727,8 @@ test "big.int div multi>2-single" { | ... | @@ -1734,8 +1727,8 @@ test "big.int div multi>2-single" { |
| 1734 | var r = try Int.init(al); | 1727 | var r = try Int.init(al); |
| 1735 | try Int.divTrunc(&q, &r, a, b); | 1728 | try Int.divTrunc(&q, &r, a, b); |
| 1736 | 1729 | ||
| 1737 | debug.assert((try q.to(u128)) == op1 / op2); | 1730 | testing.expect((try q.to(u128)) == op1 / op2); |
| 1738 | debug.assert((try r.to(u32)) == 0x3e4e); | 1731 | testing.expect((try r.to(u32)) == 0x3e4e); |
| 1739 | } | 1732 | } |
| 1740 | 1733 | ||
| 1741 | test "big.int div single-single q < r" { | 1734 | test "big.int div single-single q < r" { |
| ... | @@ -1746,8 +1739,8 @@ test "big.int div single-single q < r" { | ... | @@ -1746,8 +1739,8 @@ test "big.int div single-single q < r" { |
| 1746 | var r = try Int.init(al); | 1739 | var r = try Int.init(al); |
| 1747 | try Int.divTrunc(&q, &r, a, b); | 1740 | try Int.divTrunc(&q, &r, a, b); |
| 1748 | 1741 | ||
| 1749 | debug.assert((try q.to(u64)) == 0); | 1742 | testing.expect((try q.to(u64)) == 0); |
| 1750 | debug.assert((try r.to(u64)) == 0x0078f432); | 1743 | testing.expect((try r.to(u64)) == 0x0078f432); |
| 1751 | } | 1744 | } |
| 1752 | 1745 | ||
| 1753 | test "big.int div single-single q == r" { | 1746 | test "big.int div single-single q == r" { |
| ... | @@ -1758,8 +1751,8 @@ test "big.int div single-single q == r" { | ... | @@ -1758,8 +1751,8 @@ test "big.int div single-single q == r" { |
| 1758 | var r = try Int.init(al); | 1751 | var r = try Int.init(al); |
| 1759 | try Int.divTrunc(&q, &r, a, b); | 1752 | try Int.divTrunc(&q, &r, a, b); |
| 1760 | 1753 | ||
| 1761 | debug.assert((try q.to(u64)) == 1); | 1754 | testing.expect((try q.to(u64)) == 1); |
| 1762 | debug.assert((try r.to(u64)) == 0); | 1755 | testing.expect((try r.to(u64)) == 0); |
| 1763 | } | 1756 | } |
| 1764 | 1757 | ||
| 1765 | test "big.int div q=0 alias" { | 1758 | test "big.int div q=0 alias" { |
| ... | @@ -1768,8 +1761,8 @@ test "big.int div q=0 alias" { | ... | @@ -1768,8 +1761,8 @@ test "big.int div q=0 alias" { |
| 1768 | 1761 | ||
| 1769 | try Int.divTrunc(&a, &b, a, b); | 1762 | try Int.divTrunc(&a, &b, a, b); |
| 1770 | 1763 | ||
| 1771 | debug.assert((try a.to(u64)) == 0); | 1764 | testing.expect((try a.to(u64)) == 0); |
| 1772 | debug.assert((try b.to(u64)) == 3); | 1765 | testing.expect((try b.to(u64)) == 3); |
| 1773 | } | 1766 | } |
| 1774 | 1767 | ||
| 1775 | test "big.int div multi-multi q < r" { | 1768 | test "big.int div multi-multi q < r" { |
| ... | @@ -1782,8 +1775,8 @@ test "big.int div multi-multi q < r" { | ... | @@ -1782,8 +1775,8 @@ test "big.int div multi-multi q < r" { |
| 1782 | var r = try Int.init(al); | 1775 | var r = try Int.init(al); |
| 1783 | try Int.divTrunc(&q, &r, a, b); | 1776 | try Int.divTrunc(&q, &r, a, b); |
| 1784 | 1777 | ||
| 1785 | debug.assert((try q.to(u128)) == 0); | 1778 | testing.expect((try q.to(u128)) == 0); |
| 1786 | debug.assert((try r.to(u128)) == op1); | 1779 | testing.expect((try r.to(u128)) == op1); |
| 1787 | } | 1780 | } |
| 1788 | 1781 | ||
| 1789 | test "big.int div trunc single-single +/+" { | 1782 | test "big.int div trunc single-single +/+" { |
| ... | @@ -1802,8 +1795,8 @@ test "big.int div trunc single-single +/+" { | ... | @@ -1802,8 +1795,8 @@ test "big.int div trunc single-single +/+" { |
| 1802 | const eq = @divTrunc(u, v); | 1795 | const eq = @divTrunc(u, v); |
| 1803 | const er = @mod(u, v); | 1796 | const er = @mod(u, v); |
| 1804 | 1797 | ||
| 1805 | debug.assert((try q.to(i32)) == eq); | 1798 | testing.expect((try q.to(i32)) == eq); |
| 1806 | debug.assert((try r.to(i32)) == er); | 1799 | testing.expect((try r.to(i32)) == er); |
| 1807 | } | 1800 | } |
| 1808 | 1801 | ||
| 1809 | test "big.int div trunc single-single -/+" { | 1802 | test "big.int div trunc single-single -/+" { |
| ... | @@ -1822,8 +1815,8 @@ test "big.int div trunc single-single -/+" { | ... | @@ -1822,8 +1815,8 @@ test "big.int div trunc single-single -/+" { |
| 1822 | const eq = -1; | 1815 | const eq = -1; |
| 1823 | const er = -2; | 1816 | const er = -2; |
| 1824 | 1817 | ||
| 1825 | debug.assert((try q.to(i32)) == eq); | 1818 | testing.expect((try q.to(i32)) == eq); |
| 1826 | debug.assert((try r.to(i32)) == er); | 1819 | testing.expect((try r.to(i32)) == er); |
| 1827 | } | 1820 | } |
| 1828 | 1821 | ||
| 1829 | test "big.int div trunc single-single +/-" { | 1822 | test "big.int div trunc single-single +/-" { |
| ... | @@ -1842,8 +1835,8 @@ test "big.int div trunc single-single +/-" { | ... | @@ -1842,8 +1835,8 @@ test "big.int div trunc single-single +/-" { |
| 1842 | const eq = -1; | 1835 | const eq = -1; |
| 1843 | const er = 2; | 1836 | const er = 2; |
| 1844 | 1837 | ||
| 1845 | debug.assert((try q.to(i32)) == eq); | 1838 | testing.expect((try q.to(i32)) == eq); |
| 1846 | debug.assert((try r.to(i32)) == er); | 1839 | testing.expect((try r.to(i32)) == er); |
| 1847 | } | 1840 | } |
| 1848 | 1841 | ||
| 1849 | test "big.int div trunc single-single -/-" { | 1842 | test "big.int div trunc single-single -/-" { |
| ... | @@ -1862,8 +1855,8 @@ test "big.int div trunc single-single -/-" { | ... | @@ -1862,8 +1855,8 @@ test "big.int div trunc single-single -/-" { |
| 1862 | const eq = 1; | 1855 | const eq = 1; |
| 1863 | const er = -2; | 1856 | const er = -2; |
| 1864 | 1857 | ||
| 1865 | debug.assert((try q.to(i32)) == eq); | 1858 | testing.expect((try q.to(i32)) == eq); |
| 1866 | debug.assert((try r.to(i32)) == er); | 1859 | testing.expect((try r.to(i32)) == er); |
| 1867 | } | 1860 | } |
| 1868 | 1861 | ||
| 1869 | test "big.int div floor single-single +/+" { | 1862 | test "big.int div floor single-single +/+" { |
| ... | @@ -1882,8 +1875,8 @@ test "big.int div floor single-single +/+" { | ... | @@ -1882,8 +1875,8 @@ test "big.int div floor single-single +/+" { |
| 1882 | const eq = 1; | 1875 | const eq = 1; |
| 1883 | const er = 2; | 1876 | const er = 2; |
| 1884 | 1877 | ||
| 1885 | debug.assert((try q.to(i32)) == eq); | 1878 | testing.expect((try q.to(i32)) == eq); |
| 1886 | debug.assert((try r.to(i32)) == er); | 1879 | testing.expect((try r.to(i32)) == er); |
| 1887 | } | 1880 | } |
| 1888 | 1881 | ||
| 1889 | test "big.int div floor single-single -/+" { | 1882 | test "big.int div floor single-single -/+" { |
| ... | @@ -1902,8 +1895,8 @@ test "big.int div floor single-single -/+" { | ... | @@ -1902,8 +1895,8 @@ test "big.int div floor single-single -/+" { |
| 1902 | const eq = -2; | 1895 | const eq = -2; |
| 1903 | const er = 1; | 1896 | const er = 1; |
| 1904 | 1897 | ||
| 1905 | debug.assert((try q.to(i32)) == eq); | 1898 | testing.expect((try q.to(i32)) == eq); |
| 1906 | debug.assert((try r.to(i32)) == er); | 1899 | testing.expect((try r.to(i32)) == er); |
| 1907 | } | 1900 | } |
| 1908 | 1901 | ||
| 1909 | test "big.int div floor single-single +/-" { | 1902 | test "big.int div floor single-single +/-" { |
| ... | @@ -1922,8 +1915,8 @@ test "big.int div floor single-single +/-" { | ... | @@ -1922,8 +1915,8 @@ test "big.int div floor single-single +/-" { |
| 1922 | const eq = -2; | 1915 | const eq = -2; |
| 1923 | const er = -1; | 1916 | const er = -1; |
| 1924 | 1917 | ||
| 1925 | debug.assert((try q.to(i32)) == eq); | 1918 | testing.expect((try q.to(i32)) == eq); |
| 1926 | debug.assert((try r.to(i32)) == er); | 1919 | testing.expect((try r.to(i32)) == er); |
| 1927 | } | 1920 | } |
| 1928 | 1921 | ||
| 1929 | test "big.int div floor single-single -/-" { | 1922 | test "big.int div floor single-single -/-" { |
| ... | @@ -1942,8 +1935,8 @@ test "big.int div floor single-single -/-" { | ... | @@ -1942,8 +1935,8 @@ test "big.int div floor single-single -/-" { |
| 1942 | const eq = 1; | 1935 | const eq = 1; |
| 1943 | const er = -2; | 1936 | const er = -2; |
| 1944 | 1937 | ||
| 1945 | debug.assert((try q.to(i32)) == eq); | 1938 | testing.expect((try q.to(i32)) == eq); |
| 1946 | debug.assert((try r.to(i32)) == er); | 1939 | testing.expect((try r.to(i32)) == er); |
| 1947 | } | 1940 | } |
| 1948 | 1941 | ||
| 1949 | test "big.int div multi-multi with rem" { | 1942 | test "big.int div multi-multi with rem" { |
| ... | @@ -1954,8 +1947,8 @@ test "big.int div multi-multi with rem" { | ... | @@ -1954,8 +1947,8 @@ test "big.int div multi-multi with rem" { |
| 1954 | var r = try Int.init(al); | 1947 | var r = try Int.init(al); |
| 1955 | try Int.divTrunc(&q, &r, a, b); | 1948 | try Int.divTrunc(&q, &r, a, b); |
| 1956 | 1949 | ||
| 1957 | debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b); | 1950 | testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b); |
| 1958 | debug.assert((try r.to(u128)) == 0x28de0acacd806823638); | 1951 | testing.expect((try r.to(u128)) == 0x28de0acacd806823638); |
| 1959 | } | 1952 | } |
| 1960 | 1953 | ||
| 1961 | test "big.int div multi-multi no rem" { | 1954 | test "big.int div multi-multi no rem" { |
| ... | @@ -1966,8 +1959,8 @@ test "big.int div multi-multi no rem" { | ... | @@ -1966,8 +1959,8 @@ test "big.int div multi-multi no rem" { |
| 1966 | var r = try Int.init(al); | 1959 | var r = try Int.init(al); |
| 1967 | try Int.divTrunc(&q, &r, a, b); | 1960 | try Int.divTrunc(&q, &r, a, b); |
| 1968 | 1961 | ||
| 1969 | debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b); | 1962 | testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b); |
| 1970 | debug.assert((try r.to(u128)) == 0); | 1963 | testing.expect((try r.to(u128)) == 0); |
| 1971 | } | 1964 | } |
| 1972 | 1965 | ||
| 1973 | test "big.int div multi-multi (2 branch)" { | 1966 | test "big.int div multi-multi (2 branch)" { |
| ... | @@ -1978,8 +1971,8 @@ test "big.int div multi-multi (2 branch)" { | ... | @@ -1978,8 +1971,8 @@ test "big.int div multi-multi (2 branch)" { |
| 1978 | var r = try Int.init(al); | 1971 | var r = try Int.init(al); |
| 1979 | try Int.divTrunc(&q, &r, a, b); | 1972 | try Int.divTrunc(&q, &r, a, b); |
| 1980 | 1973 | ||
| 1981 | debug.assert((try q.to(u128)) == 0x10000000000000000); | 1974 | testing.expect((try q.to(u128)) == 0x10000000000000000); |
| 1982 | debug.assert((try r.to(u128)) == 0x44444443444444431111111111111111); | 1975 | testing.expect((try r.to(u128)) == 0x44444443444444431111111111111111); |
| 1983 | } | 1976 | } |
| 1984 | 1977 | ||
| 1985 | test "big.int div multi-multi (3.1/3.3 branch)" { | 1978 | test "big.int div multi-multi (3.1/3.3 branch)" { |
| ... | @@ -1990,53 +1983,53 @@ test "big.int div multi-multi (3.1/3.3 branch)" { | ... | @@ -1990,53 +1983,53 @@ test "big.int div multi-multi (3.1/3.3 branch)" { |
| 1990 | var r = try Int.init(al); | 1983 | var r = try Int.init(al); |
| 1991 | try Int.divTrunc(&q, &r, a, b); | 1984 | try Int.divTrunc(&q, &r, a, b); |
| 1992 | 1985 | ||
| 1993 | debug.assert((try q.to(u128)) == 0xfffffffffffffffffff); | 1986 | testing.expect((try q.to(u128)) == 0xfffffffffffffffffff); |
| 1994 | debug.assert((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282); | 1987 | testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282); |
| 1995 | } | 1988 | } |
| 1996 | 1989 | ||
| 1997 | test "big.int shift-right single" { | 1990 | test "big.int shift-right single" { |
| 1998 | var a = try Int.initSet(al, 0xffff0000); | 1991 | var a = try Int.initSet(al, 0xffff0000); |
| 1999 | try a.shiftRight(a, 16); | 1992 | try a.shiftRight(a, 16); |
| 2000 | 1993 | ||
| 2001 | debug.assert((try a.to(u32)) == 0xffff); | 1994 | testing.expect((try a.to(u32)) == 0xffff); |
| 2002 | } | 1995 | } |
| 2003 | 1996 | ||
| 2004 | test "big.int shift-right multi" { | 1997 | test "big.int shift-right multi" { |
| 2005 | var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333); | 1998 | var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333); |
| 2006 | try a.shiftRight(a, 67); | 1999 | try a.shiftRight(a, 67); |
| 2007 | 2000 | ||
| 2008 | debug.assert((try a.to(u64)) == 0x1fffe0001dddc222); | 2001 | testing.expect((try a.to(u64)) == 0x1fffe0001dddc222); |
| 2009 | } | 2002 | } |
| 2010 | 2003 | ||
| 2011 | test "big.int shift-left single" { | 2004 | test "big.int shift-left single" { |
| 2012 | var a = try Int.initSet(al, 0xffff); | 2005 | var a = try Int.initSet(al, 0xffff); |
| 2013 | try a.shiftLeft(a, 16); | 2006 | try a.shiftLeft(a, 16); |
| 2014 | 2007 | ||
| 2015 | debug.assert((try a.to(u64)) == 0xffff0000); | 2008 | testing.expect((try a.to(u64)) == 0xffff0000); |
| 2016 | } | 2009 | } |
| 2017 | 2010 | ||
| 2018 | test "big.int shift-left multi" { | 2011 | test "big.int shift-left multi" { |
| 2019 | var a = try Int.initSet(al, 0x1fffe0001dddc222); | 2012 | var a = try Int.initSet(al, 0x1fffe0001dddc222); |
| 2020 | try a.shiftLeft(a, 67); | 2013 | try a.shiftLeft(a, 67); |
| 2021 | 2014 | ||
| 2022 | debug.assert((try a.to(u128)) == 0xffff0000eeee11100000000000000000); | 2015 | testing.expect((try a.to(u128)) == 0xffff0000eeee11100000000000000000); |
| 2023 | } | 2016 | } |
| 2024 | 2017 | ||
| 2025 | test "big.int shift-right negative" { | 2018 | test "big.int shift-right negative" { |
| 2026 | var a = try Int.init(al); | 2019 | var a = try Int.init(al); |
| 2027 | 2020 | ||
| 2028 | try a.shiftRight(try Int.initSet(al, -20), 2); | 2021 | try a.shiftRight(try Int.initSet(al, -20), 2); |
| 2029 | debug.assert((try a.to(i32)) == -20 >> 2); | 2022 | testing.expect((try a.to(i32)) == -20 >> 2); |
| 2030 | 2023 | ||
| 2031 | try a.shiftRight(try Int.initSet(al, -5), 10); | 2024 | try a.shiftRight(try Int.initSet(al, -5), 10); |
| 2032 | debug.assert((try a.to(i32)) == -5 >> 10); | 2025 | testing.expect((try a.to(i32)) == -5 >> 10); |
| 2033 | } | 2026 | } |
| 2034 | 2027 | ||
| 2035 | test "big.int shift-left negative" { | 2028 | test "big.int shift-left negative" { |
| 2036 | var a = try Int.init(al); | 2029 | var a = try Int.init(al); |
| 2037 | 2030 | ||
| 2038 | try a.shiftRight(try Int.initSet(al, -10), 1232); | 2031 | try a.shiftRight(try Int.initSet(al, -10), 1232); |
| 2039 | debug.assert((try a.to(i32)) == -10 >> 1232); | 2032 | testing.expect((try a.to(i32)) == -10 >> 1232); |
| 2040 | } | 2033 | } |
| 2041 | 2034 | ||
| 2042 | test "big.int bitwise and simple" { | 2035 | test "big.int bitwise and simple" { |
| ... | @@ -2045,7 +2038,7 @@ test "big.int bitwise and simple" { | ... | @@ -2045,7 +2038,7 @@ test "big.int bitwise and simple" { |
| 2045 | 2038 | ||
| 2046 | try a.bitAnd(a, b); | 2039 | try a.bitAnd(a, b); |
| 2047 | 2040 | ||
| 2048 | debug.assert((try a.to(u64)) == 0xeeeeeeee00000000); | 2041 | testing.expect((try a.to(u64)) == 0xeeeeeeee00000000); |
| 2049 | } | 2042 | } |
| 2050 | 2043 | ||
| 2051 | test "big.int bitwise and multi-limb" { | 2044 | test "big.int bitwise and multi-limb" { |
| ... | @@ -2054,7 +2047,7 @@ test "big.int bitwise and multi-limb" { | ... | @@ -2054,7 +2047,7 @@ test "big.int bitwise and multi-limb" { |
| 2054 | 2047 | ||
| 2055 | try a.bitAnd(a, b); | 2048 | try a.bitAnd(a, b); |
| 2056 | 2049 | ||
| 2057 | debug.assert((try a.to(u128)) == 0); | 2050 | testing.expect((try a.to(u128)) == 0); |
| 2058 | } | 2051 | } |
| 2059 | 2052 | ||
| 2060 | test "big.int bitwise xor simple" { | 2053 | test "big.int bitwise xor simple" { |
| ... | @@ -2063,7 +2056,7 @@ test "big.int bitwise xor simple" { | ... | @@ -2063,7 +2056,7 @@ test "big.int bitwise xor simple" { |
| 2063 | 2056 | ||
| 2064 | try a.bitXor(a, b); | 2057 | try a.bitXor(a, b); |
| 2065 | 2058 | ||
| 2066 | debug.assert((try a.to(u64)) == 0x1111111133333333); | 2059 | testing.expect((try a.to(u64)) == 0x1111111133333333); |
| 2067 | } | 2060 | } |
| 2068 | 2061 | ||
| 2069 | test "big.int bitwise xor multi-limb" { | 2062 | test "big.int bitwise xor multi-limb" { |
| ... | @@ -2072,7 +2065,7 @@ test "big.int bitwise xor multi-limb" { | ... | @@ -2072,7 +2065,7 @@ test "big.int bitwise xor multi-limb" { |
| 2072 | 2065 | ||
| 2073 | try a.bitXor(a, b); | 2066 | try a.bitXor(a, b); |
| 2074 | 2067 | ||
| 2075 | debug.assert((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb)); | 2068 | testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb)); |
| 2076 | } | 2069 | } |
| 2077 | 2070 | ||
| 2078 | test "big.int bitwise or simple" { | 2071 | test "big.int bitwise or simple" { |
| ... | @@ -2081,7 +2074,7 @@ test "big.int bitwise or simple" { | ... | @@ -2081,7 +2074,7 @@ test "big.int bitwise or simple" { |
| 2081 | 2074 | ||
| 2082 | try a.bitOr(a, b); | 2075 | try a.bitOr(a, b); |
| 2083 | 2076 | ||
| 2084 | debug.assert((try a.to(u64)) == 0xffffffff33333333); | 2077 | testing.expect((try a.to(u64)) == 0xffffffff33333333); |
| 2085 | } | 2078 | } |
| 2086 | 2079 | ||
| 2087 | test "big.int bitwise or multi-limb" { | 2080 | test "big.int bitwise or multi-limb" { |
| ... | @@ -2091,15 +2084,15 @@ test "big.int bitwise or multi-limb" { | ... | @@ -2091,15 +2084,15 @@ test "big.int bitwise or multi-limb" { |
| 2091 | try a.bitOr(a, b); | 2084 | try a.bitOr(a, b); |
| 2092 | 2085 | ||
| 2093 | // TODO: big.int.cpp or is wrong on multi-limb. | 2086 | // TODO: big.int.cpp or is wrong on multi-limb. |
| 2094 | debug.assert((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb)); | 2087 | testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb)); |
| 2095 | } | 2088 | } |
| 2096 | 2089 | ||
| 2097 | test "big.int var args" { | 2090 | test "big.int var args" { |
| 2098 | var a = try Int.initSet(al, 5); | 2091 | var a = try Int.initSet(al, 5); |
| 2099 | 2092 | ||
| 2100 | try a.add(a, try Int.initSet(al, 6)); | 2093 | try a.add(a, try Int.initSet(al, 6)); |
| 2101 | debug.assert((try a.to(u64)) == 11); | 2094 | testing.expect((try a.to(u64)) == 11); |
| 2102 | 2095 | ||
| 2103 | debug.assert(a.cmp(try Int.initSet(al, 11)) == 0); | 2096 | testing.expect(a.cmp(try Int.initSet(al, 11)) == 0); |
| 2104 | debug.assert(a.cmp(try Int.initSet(al, 14)) <= 0); | 2097 | testing.expect(a.cmp(try Int.initSet(al, 14)) <= 0); |
| 2105 | } | 2098 | } |
std/math/cbrt.zig+25-25| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | 10 | ||
| 11 | pub fn cbrt(x: var) @typeOf(x) { | 11 | pub fn cbrt(x: var) @typeOf(x) { |
| 12 | const T = @typeOf(x); | 12 | const T = @typeOf(x); |
| ... | @@ -114,44 +114,44 @@ fn cbrt64(x: f64) f64 { | ... | @@ -114,44 +114,44 @@ fn cbrt64(x: f64) f64 { |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | test "math.cbrt" { | 116 | test "math.cbrt" { |
| 117 | assert(cbrt(f32(0.0)) == cbrt32(0.0)); | 117 | expect(cbrt(f32(0.0)) == cbrt32(0.0)); |
| 118 | assert(cbrt(f64(0.0)) == cbrt64(0.0)); | 118 | expect(cbrt(f64(0.0)) == cbrt64(0.0)); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | test "math.cbrt32" { | 121 | test "math.cbrt32" { |
| 122 | const epsilon = 0.000001; | 122 | const epsilon = 0.000001; |
| 123 | 123 | ||
| 124 | assert(cbrt32(0.0) == 0.0); | 124 | expect(cbrt32(0.0) == 0.0); |
| 125 | assert(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon)); | 125 | expect(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon)); |
| 126 | assert(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon)); | 126 | expect(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon)); |
| 127 | assert(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon)); | 127 | expect(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon)); |
| 128 | assert(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon)); | 128 | expect(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon)); |
| 129 | assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon)); | 129 | expect(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon)); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | test "math.cbrt64" { | 132 | test "math.cbrt64" { |
| 133 | const epsilon = 0.000001; | 133 | const epsilon = 0.000001; |
| 134 | 134 | ||
| 135 | assert(cbrt64(0.0) == 0.0); | 135 | expect(cbrt64(0.0) == 0.0); |
| 136 | assert(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon)); | 136 | expect(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon)); |
| 137 | assert(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon)); | 137 | expect(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon)); |
| 138 | assert(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon)); | 138 | expect(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon)); |
| 139 | assert(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon)); | 139 | expect(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon)); |
| 140 | assert(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon)); | 140 | expect(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon)); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | test "math.cbrt.special" { | 143 | test "math.cbrt.special" { |
| 144 | assert(cbrt32(0.0) == 0.0); | 144 | expect(cbrt32(0.0) == 0.0); |
| 145 | assert(cbrt32(-0.0) == -0.0); | 145 | expect(cbrt32(-0.0) == -0.0); |
| 146 | assert(math.isPositiveInf(cbrt32(math.inf(f32)))); | 146 | expect(math.isPositiveInf(cbrt32(math.inf(f32)))); |
| 147 | assert(math.isNegativeInf(cbrt32(-math.inf(f32)))); | 147 | expect(math.isNegativeInf(cbrt32(-math.inf(f32)))); |
| 148 | assert(math.isNan(cbrt32(math.nan(f32)))); | 148 | expect(math.isNan(cbrt32(math.nan(f32)))); |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | test "math.cbrt64.special" { | 151 | test "math.cbrt64.special" { |
| 152 | assert(cbrt64(0.0) == 0.0); | 152 | expect(cbrt64(0.0) == 0.0); |
| 153 | assert(cbrt64(-0.0) == -0.0); | 153 | expect(cbrt64(-0.0) == -0.0); |
| 154 | assert(math.isPositiveInf(cbrt64(math.inf(f64)))); | 154 | expect(math.isPositiveInf(cbrt64(math.inf(f64)))); |
| 155 | assert(math.isNegativeInf(cbrt64(-math.inf(f64)))); | 155 | expect(math.isNegativeInf(cbrt64(-math.inf(f64)))); |
| 156 | assert(math.isNan(cbrt64(math.nan(f64)))); | 156 | expect(math.isNan(cbrt64(math.nan(f64)))); |
| 157 | } | 157 | } |
std/math/ceil.zig+19-19| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | 11 | ||
| 12 | pub fn ceil(x: var) @typeOf(x) { | 12 | pub fn ceil(x: var) @typeOf(x) { |
| 13 | const T = @typeOf(x); | 13 | const T = @typeOf(x); |
| ... | @@ -81,34 +81,34 @@ fn ceil64(x: f64) f64 { | ... | @@ -81,34 +81,34 @@ fn ceil64(x: f64) f64 { |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | test "math.ceil" { | 83 | test "math.ceil" { |
| 84 | assert(ceil(f32(0.0)) == ceil32(0.0)); | 84 | expect(ceil(f32(0.0)) == ceil32(0.0)); |
| 85 | assert(ceil(f64(0.0)) == ceil64(0.0)); | 85 | expect(ceil(f64(0.0)) == ceil64(0.0)); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | test "math.ceil32" { | 88 | test "math.ceil32" { |
| 89 | assert(ceil32(1.3) == 2.0); | 89 | expect(ceil32(1.3) == 2.0); |
| 90 | assert(ceil32(-1.3) == -1.0); | 90 | expect(ceil32(-1.3) == -1.0); |
| 91 | assert(ceil32(0.2) == 1.0); | 91 | expect(ceil32(0.2) == 1.0); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | test "math.ceil64" { | 94 | test "math.ceil64" { |
| 95 | assert(ceil64(1.3) == 2.0); | 95 | expect(ceil64(1.3) == 2.0); |
| 96 | assert(ceil64(-1.3) == -1.0); | 96 | expect(ceil64(-1.3) == -1.0); |
| 97 | assert(ceil64(0.2) == 1.0); | 97 | expect(ceil64(0.2) == 1.0); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | test "math.ceil32.special" { | 100 | test "math.ceil32.special" { |
| 101 | assert(ceil32(0.0) == 0.0); | 101 | expect(ceil32(0.0) == 0.0); |
| 102 | assert(ceil32(-0.0) == -0.0); | 102 | expect(ceil32(-0.0) == -0.0); |
| 103 | assert(math.isPositiveInf(ceil32(math.inf(f32)))); | 103 | expect(math.isPositiveInf(ceil32(math.inf(f32)))); |
| 104 | assert(math.isNegativeInf(ceil32(-math.inf(f32)))); | 104 | expect(math.isNegativeInf(ceil32(-math.inf(f32)))); |
| 105 | assert(math.isNan(ceil32(math.nan(f32)))); | 105 | expect(math.isNan(ceil32(math.nan(f32)))); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | test "math.ceil64.special" { | 108 | test "math.ceil64.special" { |
| 109 | assert(ceil64(0.0) == 0.0); | 109 | expect(ceil64(0.0) == 0.0); |
| 110 | assert(ceil64(-0.0) == -0.0); | 110 | expect(ceil64(-0.0) == -0.0); |
| 111 | assert(math.isPositiveInf(ceil64(math.inf(f64)))); | 111 | expect(math.isPositiveInf(ceil64(math.inf(f64)))); |
| 112 | assert(math.isNegativeInf(ceil64(-math.inf(f64)))); | 112 | expect(math.isNegativeInf(ceil64(-math.inf(f64)))); |
| 113 | assert(math.isNan(ceil64(math.nan(f64)))); | 113 | expect(math.isNan(ceil64(math.nan(f64)))); |
| 114 | } | 114 | } |
std/math/complex/abs.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -14,5 +14,5 @@ const epsilon = 0.0001; | ... | @@ -14,5 +14,5 @@ const epsilon = 0.0001; |
| 14 | test "complex.cabs" { | 14 | test "complex.cabs" { |
| 15 | const a = Complex(f32).new(5, 3); | 15 | const a = Complex(f32).new(5, 3); |
| 16 | const c = abs(a); | 16 | const c = abs(a); |
| 17 | debug.assert(math.approxEq(f32, c, 5.83095, epsilon)); | 17 | testing.expect(math.approxEq(f32, c, 5.83095, epsilon)); |
| 18 | } | 18 | } |
std/math/complex/acos.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -16,6 +16,6 @@ test "complex.cacos" { | ... | @@ -16,6 +16,6 @@ test "complex.cacos" { |
| 16 | const a = Complex(f32).new(5, 3); | 16 | const a = Complex(f32).new(5, 3); |
| 17 | const c = acos(a); | 17 | const c = acos(a); |
| 18 | 18 | ||
| 19 | debug.assert(math.approxEq(f32, c.re, 0.546975, epsilon)); | 19 | testing.expect(math.approxEq(f32, c.re, 0.546975, epsilon)); |
| 20 | debug.assert(math.approxEq(f32, c.im, -2.452914, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.im, -2.452914, epsilon)); |
| 21 | } | 21 | } |
std/math/complex/acosh.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -16,6 +16,6 @@ test "complex.cacosh" { | ... | @@ -16,6 +16,6 @@ test "complex.cacosh" { |
| 16 | const a = Complex(f32).new(5, 3); | 16 | const a = Complex(f32).new(5, 3); |
| 17 | const c = acosh(a); | 17 | const c = acosh(a); |
| 18 | 18 | ||
| 19 | debug.assert(math.approxEq(f32, c.re, 2.452914, epsilon)); | 19 | testing.expect(math.approxEq(f32, c.re, 2.452914, epsilon)); |
| 20 | debug.assert(math.approxEq(f32, c.im, 0.546975, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.im, 0.546975, epsilon)); |
| 21 | } | 21 | } |
std/math/complex/arg.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -14,5 +14,5 @@ const epsilon = 0.0001; | ... | @@ -14,5 +14,5 @@ const epsilon = 0.0001; |
| 14 | test "complex.carg" { | 14 | test "complex.carg" { |
| 15 | const a = Complex(f32).new(5, 3); | 15 | const a = Complex(f32).new(5, 3); |
| 16 | const c = arg(a); | 16 | const c = arg(a); |
| 17 | debug.assert(math.approxEq(f32, c, 0.540420, epsilon)); | 17 | testing.expect(math.approxEq(f32, c, 0.540420, epsilon)); |
| 18 | } | 18 | } |
std/math/complex/asin.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -22,6 +22,6 @@ test "complex.casin" { | ... | @@ -22,6 +22,6 @@ test "complex.casin" { |
| 22 | const a = Complex(f32).new(5, 3); | 22 | const a = Complex(f32).new(5, 3); |
| 23 | const c = asin(a); | 23 | const c = asin(a); |
| 24 | 24 | ||
| 25 | debug.assert(math.approxEq(f32, c.re, 1.023822, epsilon)); | 25 | testing.expect(math.approxEq(f32, c.re, 1.023822, epsilon)); |
| 26 | debug.assert(math.approxEq(f32, c.im, 2.452914, epsilon)); | 26 | testing.expect(math.approxEq(f32, c.im, 2.452914, epsilon)); |
| 27 | } | 27 | } |
std/math/complex/asinh.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -17,6 +17,6 @@ test "complex.casinh" { | ... | @@ -17,6 +17,6 @@ test "complex.casinh" { |
| 17 | const a = Complex(f32).new(5, 3); | 17 | const a = Complex(f32).new(5, 3); |
| 18 | const c = asinh(a); | 18 | const c = asinh(a); |
| 19 | 19 | ||
| 20 | debug.assert(math.approxEq(f32, c.re, 2.459831, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.re, 2.459831, epsilon)); |
| 21 | debug.assert(math.approxEq(f32, c.im, 0.533999, epsilon)); | 21 | testing.expect(math.approxEq(f32, c.im, 0.533999, epsilon)); |
| 22 | } | 22 | } |
std/math/complex/atan.zig+5-5| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -117,14 +117,14 @@ test "complex.catan32" { | ... | @@ -117,14 +117,14 @@ test "complex.catan32" { |
| 117 | const a = Complex(f32).new(5, 3); | 117 | const a = Complex(f32).new(5, 3); |
| 118 | const c = atan(a); | 118 | const c = atan(a); |
| 119 | 119 | ||
| 120 | debug.assert(math.approxEq(f32, c.re, 1.423679, epsilon)); | 120 | testing.expect(math.approxEq(f32, c.re, 1.423679, epsilon)); |
| 121 | debug.assert(math.approxEq(f32, c.im, 0.086569, epsilon)); | 121 | testing.expect(math.approxEq(f32, c.im, 0.086569, epsilon)); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | test "complex.catan64" { | 124 | test "complex.catan64" { |
| 125 | const a = Complex(f64).new(5, 3); | 125 | const a = Complex(f64).new(5, 3); |
| 126 | const c = atan(a); | 126 | const c = atan(a); |
| 127 | 127 | ||
| 128 | debug.assert(math.approxEq(f64, c.re, 1.423679, epsilon)); | 128 | testing.expect(math.approxEq(f64, c.re, 1.423679, epsilon)); |
| 129 | debug.assert(math.approxEq(f64, c.im, 0.086569, epsilon)); | 129 | testing.expect(math.approxEq(f64, c.im, 0.086569, epsilon)); |
| 130 | } | 130 | } |
std/math/complex/atanh.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -17,6 +17,6 @@ test "complex.catanh" { | ... | @@ -17,6 +17,6 @@ test "complex.catanh" { |
| 17 | const a = Complex(f32).new(5, 3); | 17 | const a = Complex(f32).new(5, 3); |
| 18 | const c = atanh(a); | 18 | const c = atanh(a); |
| 19 | 19 | ||
| 20 | debug.assert(math.approxEq(f32, c.re, 0.146947, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.re, 0.146947, epsilon)); |
| 21 | debug.assert(math.approxEq(f32, c.im, 1.480870, epsilon)); | 21 | testing.expect(math.approxEq(f32, c.im, 1.480870, epsilon)); |
| 22 | } | 22 | } |
std/math/complex/conj.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -13,5 +13,5 @@ test "complex.conj" { | ... | @@ -13,5 +13,5 @@ test "complex.conj" { |
| 13 | const a = Complex(f32).new(5, 3); | 13 | const a = Complex(f32).new(5, 3); |
| 14 | const c = a.conjugate(); | 14 | const c = a.conjugate(); |
| 15 | 15 | ||
| 16 | debug.assert(c.re == 5 and c.im == -3); | 16 | testing.expect(c.re == 5 and c.im == -3); |
| 17 | } | 17 | } |
std/math/complex/cos.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -16,6 +16,6 @@ test "complex.ccos" { | ... | @@ -16,6 +16,6 @@ test "complex.ccos" { |
| 16 | const a = Complex(f32).new(5, 3); | 16 | const a = Complex(f32).new(5, 3); |
| 17 | const c = cos(a); | 17 | const c = cos(a); |
| 18 | 18 | ||
| 19 | debug.assert(math.approxEq(f32, c.re, 2.855815, epsilon)); | 19 | testing.expect(math.approxEq(f32, c.re, 2.855815, epsilon)); |
| 20 | debug.assert(math.approxEq(f32, c.im, 9.606383, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.im, 9.606383, epsilon)); |
| 21 | } | 21 | } |
std/math/complex/cosh.zig+5-5| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -152,14 +152,14 @@ test "complex.ccosh32" { | ... | @@ -152,14 +152,14 @@ test "complex.ccosh32" { |
| 152 | const a = Complex(f32).new(5, 3); | 152 | const a = Complex(f32).new(5, 3); |
| 153 | const c = cosh(a); | 153 | const c = cosh(a); |
| 154 | 154 | ||
| 155 | debug.assert(math.approxEq(f32, c.re, -73.467300, epsilon)); | 155 | testing.expect(math.approxEq(f32, c.re, -73.467300, epsilon)); |
| 156 | debug.assert(math.approxEq(f32, c.im, 10.471557, epsilon)); | 156 | testing.expect(math.approxEq(f32, c.im, 10.471557, epsilon)); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | test "complex.ccosh64" { | 159 | test "complex.ccosh64" { |
| 160 | const a = Complex(f64).new(5, 3); | 160 | const a = Complex(f64).new(5, 3); |
| 161 | const c = cosh(a); | 161 | const c = cosh(a); |
| 162 | 162 | ||
| 163 | debug.assert(math.approxEq(f64, c.re, -73.467300, epsilon)); | 163 | testing.expect(math.approxEq(f64, c.re, -73.467300, epsilon)); |
| 164 | debug.assert(math.approxEq(f64, c.im, 10.471557, epsilon)); | 164 | testing.expect(math.approxEq(f64, c.im, 10.471557, epsilon)); |
| 165 | } | 165 | } |
std/math/complex/exp.zig+5-5| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -118,14 +118,14 @@ test "complex.cexp32" { | ... | @@ -118,14 +118,14 @@ test "complex.cexp32" { |
| 118 | const a = Complex(f32).new(5, 3); | 118 | const a = Complex(f32).new(5, 3); |
| 119 | const c = exp(a); | 119 | const c = exp(a); |
| 120 | 120 | ||
| 121 | debug.assert(math.approxEq(f32, c.re, -146.927917, epsilon)); | 121 | testing.expect(math.approxEq(f32, c.re, -146.927917, epsilon)); |
| 122 | debug.assert(math.approxEq(f32, c.im, 20.944065, epsilon)); | 122 | testing.expect(math.approxEq(f32, c.im, 20.944065, epsilon)); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | test "complex.cexp64" { | 125 | test "complex.cexp64" { |
| 126 | const a = Complex(f64).new(5, 3); | 126 | const a = Complex(f64).new(5, 3); |
| 127 | const c = exp(a); | 127 | const c = exp(a); |
| 128 | 128 | ||
| 129 | debug.assert(math.approxEq(f64, c.re, -146.927917, epsilon)); | 129 | testing.expect(math.approxEq(f64, c.re, -146.927917, epsilon)); |
| 130 | debug.assert(math.approxEq(f64, c.im, 20.944065, epsilon)); | 130 | testing.expect(math.approxEq(f64, c.im, 20.944065, epsilon)); |
| 131 | } | 131 | } |
std/math/complex/index.zig+8-8| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | 4 | ||
| 5 | pub const abs = @import("abs.zig").abs; | 5 | pub const abs = @import("abs.zig").abs; |
| ... | @@ -97,7 +97,7 @@ test "complex.add" { | ... | @@ -97,7 +97,7 @@ test "complex.add" { |
| 97 | const b = Complex(f32).new(2, 7); | 97 | const b = Complex(f32).new(2, 7); |
| 98 | const c = a.add(b); | 98 | const c = a.add(b); |
| 99 | 99 | ||
| 100 | debug.assert(c.re == 7 and c.im == 10); | 100 | testing.expect(c.re == 7 and c.im == 10); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | test "complex.sub" { | 103 | test "complex.sub" { |
| ... | @@ -105,7 +105,7 @@ test "complex.sub" { | ... | @@ -105,7 +105,7 @@ test "complex.sub" { |
| 105 | const b = Complex(f32).new(2, 7); | 105 | const b = Complex(f32).new(2, 7); |
| 106 | const c = a.sub(b); | 106 | const c = a.sub(b); |
| 107 | 107 | ||
| 108 | debug.assert(c.re == 3 and c.im == -4); | 108 | testing.expect(c.re == 3 and c.im == -4); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | test "complex.mul" { | 111 | test "complex.mul" { |
| ... | @@ -113,7 +113,7 @@ test "complex.mul" { | ... | @@ -113,7 +113,7 @@ test "complex.mul" { |
| 113 | const b = Complex(f32).new(2, 7); | 113 | const b = Complex(f32).new(2, 7); |
| 114 | const c = a.mul(b); | 114 | const c = a.mul(b); |
| 115 | 115 | ||
| 116 | debug.assert(c.re == -11 and c.im == 41); | 116 | testing.expect(c.re == -11 and c.im == 41); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | test "complex.div" { | 119 | test "complex.div" { |
| ... | @@ -121,7 +121,7 @@ test "complex.div" { | ... | @@ -121,7 +121,7 @@ test "complex.div" { |
| 121 | const b = Complex(f32).new(2, 7); | 121 | const b = Complex(f32).new(2, 7); |
| 122 | const c = a.div(b); | 122 | const c = a.div(b); |
| 123 | 123 | ||
| 124 | debug.assert(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and | 124 | testing.expect(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and |
| 125 | math.approxEq(f32, c.im, f32(-29) / 53, epsilon)); | 125 | math.approxEq(f32, c.im, f32(-29) / 53, epsilon)); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| ... | @@ -129,14 +129,14 @@ test "complex.conjugate" { | ... | @@ -129,14 +129,14 @@ test "complex.conjugate" { |
| 129 | const a = Complex(f32).new(5, 3); | 129 | const a = Complex(f32).new(5, 3); |
| 130 | const c = a.conjugate(); | 130 | const c = a.conjugate(); |
| 131 | 131 | ||
| 132 | debug.assert(c.re == 5 and c.im == -3); | 132 | testing.expect(c.re == 5 and c.im == -3); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | test "complex.reciprocal" { | 135 | test "complex.reciprocal" { |
| 136 | const a = Complex(f32).new(5, 3); | 136 | const a = Complex(f32).new(5, 3); |
| 137 | const c = a.reciprocal(); | 137 | const c = a.reciprocal(); |
| 138 | 138 | ||
| 139 | debug.assert(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and | 139 | testing.expect(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and |
| 140 | math.approxEq(f32, c.im, f32(-3) / 34, epsilon)); | 140 | math.approxEq(f32, c.im, f32(-3) / 34, epsilon)); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| ... | @@ -144,7 +144,7 @@ test "complex.magnitude" { | ... | @@ -144,7 +144,7 @@ test "complex.magnitude" { |
| 144 | const a = Complex(f32).new(5, 3); | 144 | const a = Complex(f32).new(5, 3); |
| 145 | const c = a.magnitude(); | 145 | const c = a.magnitude(); |
| 146 | 146 | ||
| 147 | debug.assert(math.approxEq(f32, c, 5.83095, epsilon)); | 147 | testing.expect(math.approxEq(f32, c, 5.83095, epsilon)); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | test "complex.cmath" { | 150 | test "complex.cmath" { |
std/math/complex/log.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -18,6 +18,6 @@ test "complex.clog" { | ... | @@ -18,6 +18,6 @@ test "complex.clog" { |
| 18 | const a = Complex(f32).new(5, 3); | 18 | const a = Complex(f32).new(5, 3); |
| 19 | const c = log(a); | 19 | const c = log(a); |
| 20 | 20 | ||
| 21 | debug.assert(math.approxEq(f32, c.re, 1.763180, epsilon)); | 21 | testing.expect(math.approxEq(f32, c.re, 1.763180, epsilon)); |
| 22 | debug.assert(math.approxEq(f32, c.im, 0.540419, epsilon)); | 22 | testing.expect(math.approxEq(f32, c.im, 0.540419, epsilon)); |
| 23 | } | 23 | } |
std/math/complex/pow.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -17,6 +17,6 @@ test "complex.cpow" { | ... | @@ -17,6 +17,6 @@ test "complex.cpow" { |
| 17 | const b = Complex(f32).new(2.3, -1.3); | 17 | const b = Complex(f32).new(2.3, -1.3); |
| 18 | const c = pow(Complex(f32), a, b); | 18 | const c = pow(Complex(f32), a, b); |
| 19 | 19 | ||
| 20 | debug.assert(math.approxEq(f32, c.re, 58.049110, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.re, 58.049110, epsilon)); |
| 21 | debug.assert(math.approxEq(f32, c.im, -101.003433, epsilon)); | 21 | testing.expect(math.approxEq(f32, c.im, -101.003433, epsilon)); |
| 22 | } | 22 | } |
std/math/complex/proj.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -20,5 +20,5 @@ test "complex.cproj" { | ... | @@ -20,5 +20,5 @@ test "complex.cproj" { |
| 20 | const a = Complex(f32).new(5, 3); | 20 | const a = Complex(f32).new(5, 3); |
| 21 | const c = proj(a); | 21 | const c = proj(a); |
| 22 | 22 | ||
| 23 | debug.assert(c.re == 5 and c.im == 3); | 23 | testing.expect(c.re == 5 and c.im == 3); |
| 24 | } | 24 | } |
std/math/complex/sin.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -17,6 +17,6 @@ test "complex.csin" { | ... | @@ -17,6 +17,6 @@ test "complex.csin" { |
| 17 | const a = Complex(f32).new(5, 3); | 17 | const a = Complex(f32).new(5, 3); |
| 18 | const c = sin(a); | 18 | const c = sin(a); |
| 19 | 19 | ||
| 20 | debug.assert(math.approxEq(f32, c.re, -9.654126, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.re, -9.654126, epsilon)); |
| 21 | debug.assert(math.approxEq(f32, c.im, 2.841692, epsilon)); | 21 | testing.expect(math.approxEq(f32, c.im, 2.841692, epsilon)); |
| 22 | } | 22 | } |
std/math/complex/sinh.zig+5-5| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -151,14 +151,14 @@ test "complex.csinh32" { | ... | @@ -151,14 +151,14 @@ test "complex.csinh32" { |
| 151 | const a = Complex(f32).new(5, 3); | 151 | const a = Complex(f32).new(5, 3); |
| 152 | const c = sinh(a); | 152 | const c = sinh(a); |
| 153 | 153 | ||
| 154 | debug.assert(math.approxEq(f32, c.re, -73.460617, epsilon)); | 154 | testing.expect(math.approxEq(f32, c.re, -73.460617, epsilon)); |
| 155 | debug.assert(math.approxEq(f32, c.im, 10.472508, epsilon)); | 155 | testing.expect(math.approxEq(f32, c.im, 10.472508, epsilon)); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | test "complex.csinh64" { | 158 | test "complex.csinh64" { |
| 159 | const a = Complex(f64).new(5, 3); | 159 | const a = Complex(f64).new(5, 3); |
| 160 | const c = sinh(a); | 160 | const c = sinh(a); |
| 161 | 161 | ||
| 162 | debug.assert(math.approxEq(f64, c.re, -73.460617, epsilon)); | 162 | testing.expect(math.approxEq(f64, c.re, -73.460617, epsilon)); |
| 163 | debug.assert(math.approxEq(f64, c.im, 10.472508, epsilon)); | 163 | testing.expect(math.approxEq(f64, c.im, 10.472508, epsilon)); |
| 164 | } | 164 | } |
std/math/complex/sqrt.zig+5-5| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -125,14 +125,14 @@ test "complex.csqrt32" { | ... | @@ -125,14 +125,14 @@ test "complex.csqrt32" { |
| 125 | const a = Complex(f32).new(5, 3); | 125 | const a = Complex(f32).new(5, 3); |
| 126 | const c = sqrt(a); | 126 | const c = sqrt(a); |
| 127 | 127 | ||
| 128 | debug.assert(math.approxEq(f32, c.re, 2.327117, epsilon)); | 128 | testing.expect(math.approxEq(f32, c.re, 2.327117, epsilon)); |
| 129 | debug.assert(math.approxEq(f32, c.im, 0.644574, epsilon)); | 129 | testing.expect(math.approxEq(f32, c.im, 0.644574, epsilon)); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | test "complex.csqrt64" { | 132 | test "complex.csqrt64" { |
| 133 | const a = Complex(f64).new(5, 3); | 133 | const a = Complex(f64).new(5, 3); |
| 134 | const c = sqrt(a); | 134 | const c = sqrt(a); |
| 135 | 135 | ||
| 136 | debug.assert(math.approxEq(f64, c.re, 2.3271175190399496, epsilon)); | 136 | testing.expect(math.approxEq(f64, c.re, 2.3271175190399496, epsilon)); |
| 137 | debug.assert(math.approxEq(f64, c.im, 0.6445742373246469, epsilon)); | 137 | testing.expect(math.approxEq(f64, c.im, 0.6445742373246469, epsilon)); |
| 138 | } | 138 | } |
std/math/complex/tan.zig+3-3| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -17,6 +17,6 @@ test "complex.ctan" { | ... | @@ -17,6 +17,6 @@ test "complex.ctan" { |
| 17 | const a = Complex(f32).new(5, 3); | 17 | const a = Complex(f32).new(5, 3); |
| 18 | const c = tan(a); | 18 | const c = tan(a); |
| 19 | 19 | ||
| 20 | debug.assert(math.approxEq(f32, c.re, -0.002708233, epsilon)); | 20 | testing.expect(math.approxEq(f32, c.re, -0.002708233, epsilon)); |
| 21 | debug.assert(math.approxEq(f32, c.im, 1.004165, epsilon)); | 21 | testing.expect(math.approxEq(f32, c.im, 1.004165, epsilon)); |
| 22 | } | 22 | } |
std/math/complex/tanh.zig+5-5| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const debug = std.debug; | 2 | const testing = std.testing; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const cmath = math.complex; | 4 | const cmath = math.complex; |
| 5 | const Complex = cmath.Complex; | 5 | const Complex = cmath.Complex; |
| ... | @@ -100,14 +100,14 @@ test "complex.ctanh32" { | ... | @@ -100,14 +100,14 @@ test "complex.ctanh32" { |
| 100 | const a = Complex(f32).new(5, 3); | 100 | const a = Complex(f32).new(5, 3); |
| 101 | const c = tanh(a); | 101 | const c = tanh(a); |
| 102 | 102 | ||
| 103 | debug.assert(math.approxEq(f32, c.re, 0.999913, epsilon)); | 103 | testing.expect(math.approxEq(f32, c.re, 0.999913, epsilon)); |
| 104 | debug.assert(math.approxEq(f32, c.im, -0.000025, epsilon)); | 104 | testing.expect(math.approxEq(f32, c.im, -0.000025, epsilon)); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | test "complex.ctanh64" { | 107 | test "complex.ctanh64" { |
| 108 | const a = Complex(f64).new(5, 3); | 108 | const a = Complex(f64).new(5, 3); |
| 109 | const c = tanh(a); | 109 | const c = tanh(a); |
| 110 | 110 | ||
| 111 | debug.assert(math.approxEq(f64, c.re, 0.999913, epsilon)); | 111 | testing.expect(math.approxEq(f64, c.re, 0.999913, epsilon)); |
| 112 | debug.assert(math.approxEq(f64, c.im, -0.000025, epsilon)); | 112 | testing.expect(math.approxEq(f64, c.im, -0.000025, epsilon)); |
| 113 | } | 113 | } |
std/math/copysign.zig+16-16| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | ||
| 6 | pub fn copysign(comptime T: type, x: T, y: T) T { | 6 | pub fn copysign(comptime T: type, x: T, y: T) T { |
| ... | @@ -40,28 +40,28 @@ fn copysign64(x: f64, y: f64) f64 { | ... | @@ -40,28 +40,28 @@ fn copysign64(x: f64, y: f64) f64 { |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | test "math.copysign" { | 42 | test "math.copysign" { |
| 43 | assert(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0)); | 43 | expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0)); |
| 44 | assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0)); | 44 | expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0)); |
| 45 | assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0)); | 45 | expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0)); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | test "math.copysign16" { | 48 | test "math.copysign16" { |
| 49 | assert(copysign16(5.0, 1.0) == 5.0); | 49 | expect(copysign16(5.0, 1.0) == 5.0); |
| 50 | assert(copysign16(5.0, -1.0) == -5.0); | 50 | expect(copysign16(5.0, -1.0) == -5.0); |
| 51 | assert(copysign16(-5.0, -1.0) == -5.0); | 51 | expect(copysign16(-5.0, -1.0) == -5.0); |
| 52 | assert(copysign16(-5.0, 1.0) == 5.0); | 52 | expect(copysign16(-5.0, 1.0) == 5.0); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | test "math.copysign32" { | 55 | test "math.copysign32" { |
| 56 | assert(copysign32(5.0, 1.0) == 5.0); | 56 | expect(copysign32(5.0, 1.0) == 5.0); |
| 57 | assert(copysign32(5.0, -1.0) == -5.0); | 57 | expect(copysign32(5.0, -1.0) == -5.0); |
| 58 | assert(copysign32(-5.0, -1.0) == -5.0); | 58 | expect(copysign32(-5.0, -1.0) == -5.0); |
| 59 | assert(copysign32(-5.0, 1.0) == 5.0); | 59 | expect(copysign32(-5.0, 1.0) == 5.0); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | test "math.copysign64" { | 62 | test "math.copysign64" { |
| 63 | assert(copysign64(5.0, 1.0) == 5.0); | 63 | expect(copysign64(5.0, 1.0) == 5.0); |
| 64 | assert(copysign64(5.0, -1.0) == -5.0); | 64 | expect(copysign64(5.0, -1.0) == -5.0); |
| 65 | assert(copysign64(-5.0, -1.0) == -5.0); | 65 | expect(copysign64(-5.0, -1.0) == -5.0); |
| 66 | assert(copysign64(-5.0, 1.0) == 5.0); | 66 | expect(copysign64(-5.0, 1.0) == 5.0); |
| 67 | } | 67 | } |
std/math/cos.zig+21-21| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | 10 | ||
| 11 | pub fn cos(x: var) @typeOf(x) { | 11 | pub fn cos(x: var) @typeOf(x) { |
| 12 | const T = @typeOf(x); | 12 | const T = @typeOf(x); |
| ... | @@ -139,40 +139,40 @@ fn cos64(x_: f64) f64 { | ... | @@ -139,40 +139,40 @@ fn cos64(x_: f64) f64 { |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | test "math.cos" { | 141 | test "math.cos" { |
| 142 | assert(cos(f32(0.0)) == cos32(0.0)); | 142 | expect(cos(f32(0.0)) == cos32(0.0)); |
| 143 | assert(cos(f64(0.0)) == cos64(0.0)); | 143 | expect(cos(f64(0.0)) == cos64(0.0)); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | test "math.cos32" { | 146 | test "math.cos32" { |
| 147 | const epsilon = 0.000001; | 147 | const epsilon = 0.000001; |
| 148 | 148 | ||
| 149 | assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon)); | 149 | expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon)); |
| 150 | assert(math.approxEq(f32, cos32(0.2), 0.980067, epsilon)); | 150 | expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon)); |
| 151 | assert(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon)); | 151 | expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon)); |
| 152 | assert(math.approxEq(f32, cos32(1.5), 0.070737, epsilon)); | 152 | expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon)); |
| 153 | assert(math.approxEq(f32, cos32(37.45), 0.969132, epsilon)); | 153 | expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon)); |
| 154 | assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon)); | 154 | expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon)); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | test "math.cos64" { | 157 | test "math.cos64" { |
| 158 | const epsilon = 0.000001; | 158 | const epsilon = 0.000001; |
| 159 | 159 | ||
| 160 | assert(math.approxEq(f64, cos64(0.0), 1.0, epsilon)); | 160 | expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon)); |
| 161 | assert(math.approxEq(f64, cos64(0.2), 0.980067, epsilon)); | 161 | expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon)); |
| 162 | assert(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon)); | 162 | expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon)); |
| 163 | assert(math.approxEq(f64, cos64(1.5), 0.070737, epsilon)); | 163 | expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon)); |
| 164 | assert(math.approxEq(f64, cos64(37.45), 0.969132, epsilon)); | 164 | expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon)); |
| 165 | assert(math.approxEq(f64, cos64(89.123), 0.40080, epsilon)); | 165 | expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon)); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | test "math.cos32.special" { | 168 | test "math.cos32.special" { |
| 169 | assert(math.isNan(cos32(math.inf(f32)))); | 169 | expect(math.isNan(cos32(math.inf(f32)))); |
| 170 | assert(math.isNan(cos32(-math.inf(f32)))); | 170 | expect(math.isNan(cos32(-math.inf(f32)))); |
| 171 | assert(math.isNan(cos32(math.nan(f32)))); | 171 | expect(math.isNan(cos32(math.nan(f32)))); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | test "math.cos64.special" { | 174 | test "math.cos64.special" { |
| 175 | assert(math.isNan(cos64(math.inf(f64)))); | 175 | expect(math.isNan(cos64(math.inf(f64)))); |
| 176 | assert(math.isNan(cos64(-math.inf(f64)))); | 176 | expect(math.isNan(cos64(-math.inf(f64)))); |
| 177 | assert(math.isNan(cos64(math.nan(f64)))); | 177 | expect(math.isNan(cos64(math.nan(f64)))); |
| 178 | } | 178 | } |
std/math/cosh.zig+21-21| ... | @@ -8,7 +8,7 @@ const builtin = @import("builtin"); | ... | @@ -8,7 +8,7 @@ const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const expo2 = @import("expo2.zig").expo2; | 10 | const expo2 = @import("expo2.zig").expo2; |
| 11 | const assert = std.debug.assert; | 11 | const expect = std.testing.expect; |
| 12 | const maxInt = std.math.maxInt; | 12 | const maxInt = std.math.maxInt; |
| 13 | 13 | ||
| 14 | pub fn cosh(x: var) @typeOf(x) { | 14 | pub fn cosh(x: var) @typeOf(x) { |
| ... | @@ -82,40 +82,40 @@ fn cosh64(x: f64) f64 { | ... | @@ -82,40 +82,40 @@ fn cosh64(x: f64) f64 { |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | test "math.cosh" { | 84 | test "math.cosh" { |
| 85 | assert(cosh(f32(1.5)) == cosh32(1.5)); | 85 | expect(cosh(f32(1.5)) == cosh32(1.5)); |
| 86 | assert(cosh(f64(1.5)) == cosh64(1.5)); | 86 | expect(cosh(f64(1.5)) == cosh64(1.5)); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | test "math.cosh32" { | 89 | test "math.cosh32" { |
| 90 | const epsilon = 0.000001; | 90 | const epsilon = 0.000001; |
| 91 | 91 | ||
| 92 | assert(math.approxEq(f32, cosh32(0.0), 1.0, epsilon)); | 92 | expect(math.approxEq(f32, cosh32(0.0), 1.0, epsilon)); |
| 93 | assert(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon)); | 93 | expect(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon)); |
| 94 | assert(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon)); | 94 | expect(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon)); |
| 95 | assert(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon)); | 95 | expect(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon)); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | test "math.cosh64" { | 98 | test "math.cosh64" { |
| 99 | const epsilon = 0.000001; | 99 | const epsilon = 0.000001; |
| 100 | 100 | ||
| 101 | assert(math.approxEq(f64, cosh64(0.0), 1.0, epsilon)); | 101 | expect(math.approxEq(f64, cosh64(0.0), 1.0, epsilon)); |
| 102 | assert(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon)); | 102 | expect(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon)); |
| 103 | assert(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon)); | 103 | expect(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon)); |
| 104 | assert(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon)); | 104 | expect(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon)); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | test "math.cosh32.special" { | 107 | test "math.cosh32.special" { |
| 108 | assert(cosh32(0.0) == 1.0); | 108 | expect(cosh32(0.0) == 1.0); |
| 109 | assert(cosh32(-0.0) == 1.0); | 109 | expect(cosh32(-0.0) == 1.0); |
| 110 | assert(math.isPositiveInf(cosh32(math.inf(f32)))); | 110 | expect(math.isPositiveInf(cosh32(math.inf(f32)))); |
| 111 | assert(math.isPositiveInf(cosh32(-math.inf(f32)))); | 111 | expect(math.isPositiveInf(cosh32(-math.inf(f32)))); |
| 112 | assert(math.isNan(cosh32(math.nan(f32)))); | 112 | expect(math.isNan(cosh32(math.nan(f32)))); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | test "math.cosh64.special" { | 115 | test "math.cosh64.special" { |
| 116 | assert(cosh64(0.0) == 1.0); | 116 | expect(cosh64(0.0) == 1.0); |
| 117 | assert(cosh64(-0.0) == 1.0); | 117 | expect(cosh64(-0.0) == 1.0); |
| 118 | assert(math.isPositiveInf(cosh64(math.inf(f64)))); | 118 | expect(math.isPositiveInf(cosh64(math.inf(f64)))); |
| 119 | assert(math.isPositiveInf(cosh64(-math.inf(f64)))); | 119 | expect(math.isPositiveInf(cosh64(-math.inf(f64)))); |
| 120 | assert(math.isNan(cosh64(math.nan(f64)))); | 120 | expect(math.isNan(cosh64(math.nan(f64)))); |
| 121 | } | 121 | } |
std/math/exp2.zig+16-16| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ||
| 6 | const std = @import("../index.zig"); | 6 | const std = @import("../index.zig"); |
| 7 | const math = std.math; | 7 | const math = std.math; |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | 9 | ||
| 10 | pub fn exp2(x: var) @typeOf(x) { | 10 | pub fn exp2(x: var) @typeOf(x) { |
| 11 | const T = @typeOf(x); | 11 | const T = @typeOf(x); |
| ... | @@ -415,35 +415,35 @@ fn exp2_64(x: f64) f64 { | ... | @@ -415,35 +415,35 @@ fn exp2_64(x: f64) f64 { |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | test "math.exp2" { | 417 | test "math.exp2" { |
| 418 | assert(exp2(f32(0.8923)) == exp2_32(0.8923)); | 418 | expect(exp2(f32(0.8923)) == exp2_32(0.8923)); |
| 419 | assert(exp2(f64(0.8923)) == exp2_64(0.8923)); | 419 | expect(exp2(f64(0.8923)) == exp2_64(0.8923)); |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | test "math.exp2_32" { | 422 | test "math.exp2_32" { |
| 423 | const epsilon = 0.000001; | 423 | const epsilon = 0.000001; |
| 424 | 424 | ||
| 425 | assert(exp2_32(0.0) == 1.0); | 425 | expect(exp2_32(0.0) == 1.0); |
| 426 | assert(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon)); | 426 | expect(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon)); |
| 427 | assert(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon)); | 427 | expect(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon)); |
| 428 | assert(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon)); | 428 | expect(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon)); |
| 429 | assert(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon)); | 429 | expect(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon)); |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | test "math.exp2_64" { | 432 | test "math.exp2_64" { |
| 433 | const epsilon = 0.000001; | 433 | const epsilon = 0.000001; |
| 434 | 434 | ||
| 435 | assert(exp2_64(0.0) == 1.0); | 435 | expect(exp2_64(0.0) == 1.0); |
| 436 | assert(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon)); | 436 | expect(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon)); |
| 437 | assert(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon)); | 437 | expect(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon)); |
| 438 | assert(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon)); | 438 | expect(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon)); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | test "math.exp2_32.special" { | 441 | test "math.exp2_32.special" { |
| 442 | assert(math.isPositiveInf(exp2_32(math.inf(f32)))); | 442 | expect(math.isPositiveInf(exp2_32(math.inf(f32)))); |
| 443 | assert(math.isNan(exp2_32(math.nan(f32)))); | 443 | expect(math.isNan(exp2_32(math.nan(f32)))); |
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | test "math.exp2_64.special" { | 446 | test "math.exp2_64.special" { |
| 447 | assert(math.isPositiveInf(exp2_64(math.inf(f64)))); | 447 | expect(math.isPositiveInf(exp2_64(math.inf(f64)))); |
| 448 | assert(math.isNan(exp2_64(math.nan(f64)))); | 448 | expect(math.isNan(exp2_64(math.nan(f64)))); |
| 449 | } | 449 | } |
std/math/expm1.zig+19-19| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | 11 | ||
| 12 | pub fn expm1(x: var) @typeOf(x) { | 12 | pub fn expm1(x: var) @typeOf(x) { |
| 13 | const T = @typeOf(x); | 13 | const T = @typeOf(x); |
| ... | @@ -278,42 +278,42 @@ fn expm1_64(x_: f64) f64 { | ... | @@ -278,42 +278,42 @@ fn expm1_64(x_: f64) f64 { |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | test "math.exp1m" { | 280 | test "math.exp1m" { |
| 281 | assert(expm1(f32(0.0)) == expm1_32(0.0)); | 281 | expect(expm1(f32(0.0)) == expm1_32(0.0)); |
| 282 | assert(expm1(f64(0.0)) == expm1_64(0.0)); | 282 | expect(expm1(f64(0.0)) == expm1_64(0.0)); |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | test "math.expm1_32" { | 285 | test "math.expm1_32" { |
| 286 | const epsilon = 0.000001; | 286 | const epsilon = 0.000001; |
| 287 | 287 | ||
| 288 | assert(expm1_32(0.0) == 0.0); | 288 | expect(expm1_32(0.0) == 0.0); |
| 289 | assert(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon)); | 289 | expect(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon)); |
| 290 | assert(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon)); | 290 | expect(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon)); |
| 291 | assert(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon)); | 291 | expect(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon)); |
| 292 | assert(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon)); | 292 | expect(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon)); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | test "math.expm1_64" { | 295 | test "math.expm1_64" { |
| 296 | const epsilon = 0.000001; | 296 | const epsilon = 0.000001; |
| 297 | 297 | ||
| 298 | assert(expm1_64(0.0) == 0.0); | 298 | expect(expm1_64(0.0) == 0.0); |
| 299 | assert(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon)); | 299 | expect(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon)); |
| 300 | assert(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon)); | 300 | expect(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon)); |
| 301 | assert(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon)); | 301 | expect(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon)); |
| 302 | assert(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon)); | 302 | expect(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon)); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | test "math.expm1_32.special" { | 305 | test "math.expm1_32.special" { |
| 306 | const epsilon = 0.000001; | 306 | const epsilon = 0.000001; |
| 307 | 307 | ||
| 308 | assert(math.isPositiveInf(expm1_32(math.inf(f32)))); | 308 | expect(math.isPositiveInf(expm1_32(math.inf(f32)))); |
| 309 | assert(expm1_32(-math.inf(f32)) == -1.0); | 309 | expect(expm1_32(-math.inf(f32)) == -1.0); |
| 310 | assert(math.isNan(expm1_32(math.nan(f32)))); | 310 | expect(math.isNan(expm1_32(math.nan(f32)))); |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | test "math.expm1_64.special" { | 313 | test "math.expm1_64.special" { |
| 314 | const epsilon = 0.000001; | 314 | const epsilon = 0.000001; |
| 315 | 315 | ||
| 316 | assert(math.isPositiveInf(expm1_64(math.inf(f64)))); | 316 | expect(math.isPositiveInf(expm1_64(math.inf(f64)))); |
| 317 | assert(expm1_64(-math.inf(f64)) == -1.0); | 317 | expect(expm1_64(-math.inf(f64)) == -1.0); |
| 318 | assert(math.isNan(expm1_64(math.nan(f64)))); | 318 | expect(math.isNan(expm1_64(math.nan(f64)))); |
| 319 | } | 319 | } |
std/math/fabs.zig+38-19| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ||
| 6 | const std = @import("../index.zig"); | 6 | const std = @import("../index.zig"); |
| 7 | const math = std.math; | 7 | const math = std.math; |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| 10 | 10 | ||
| 11 | pub fn fabs(x: var) @typeOf(x) { | 11 | pub fn fabs(x: var) @typeOf(x) { |
| ... | @@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) { | ... | @@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) { |
| 14 | f16 => fabs16(x), | 14 | f16 => fabs16(x), |
| 15 | f32 => fabs32(x), | 15 | f32 => fabs32(x), |
| 16 | f64 => fabs64(x), | 16 | f64 => fabs64(x), |
| 17 | f128 => fabs128(x), | ||
| 17 | else => @compileError("fabs not implemented for " ++ @typeName(T)), | 18 | else => @compileError("fabs not implemented for " ++ @typeName(T)), |
| 18 | }; | 19 | }; |
| 19 | } | 20 | } |
| ... | @@ -36,41 +37,59 @@ fn fabs64(x: f64) f64 { | ... | @@ -36,41 +37,59 @@ fn fabs64(x: f64) f64 { |
| 36 | return @bitCast(f64, u); | 37 | return @bitCast(f64, u); |
| 37 | } | 38 | } |
| 38 | 39 | ||
| 40 | fn fabs128(x: f128) f128 { | ||
| 41 | var u = @bitCast(u128, x); | ||
| 42 | u &= maxInt(u128) >> 1; | ||
| 43 | return @bitCast(f128, u); | ||
| 44 | } | ||
| 45 | |||
| 39 | test "math.fabs" { | 46 | test "math.fabs" { |
| 40 | assert(fabs(f16(1.0)) == fabs16(1.0)); | 47 | expect(fabs(f16(1.0)) == fabs16(1.0)); |
| 41 | assert(fabs(f32(1.0)) == fabs32(1.0)); | 48 | expect(fabs(f32(1.0)) == fabs32(1.0)); |
| 42 | assert(fabs(f64(1.0)) == fabs64(1.0)); | 49 | expect(fabs(f64(1.0)) == fabs64(1.0)); |
| 50 | expect(fabs(f128(1.0)) == fabs128(1.0)); | ||
| 43 | } | 51 | } |
| 44 | 52 | ||
| 45 | test "math.fabs16" { | 53 | test "math.fabs16" { |
| 46 | assert(fabs16(1.0) == 1.0); | 54 | expect(fabs16(1.0) == 1.0); |
| 47 | assert(fabs16(-1.0) == 1.0); | 55 | expect(fabs16(-1.0) == 1.0); |
| 48 | } | 56 | } |
| 49 | 57 | ||
| 50 | test "math.fabs32" { | 58 | test "math.fabs32" { |
| 51 | assert(fabs32(1.0) == 1.0); | 59 | expect(fabs32(1.0) == 1.0); |
| 52 | assert(fabs32(-1.0) == 1.0); | 60 | expect(fabs32(-1.0) == 1.0); |
| 53 | } | 61 | } |
| 54 | 62 | ||
| 55 | test "math.fabs64" { | 63 | test "math.fabs64" { |
| 56 | assert(fabs64(1.0) == 1.0); | 64 | expect(fabs64(1.0) == 1.0); |
| 57 | assert(fabs64(-1.0) == 1.0); | 65 | expect(fabs64(-1.0) == 1.0); |
| 66 | } | ||
| 67 | |||
| 68 | test "math.fabs128" { | ||
| 69 | expect(fabs128(1.0) == 1.0); | ||
| 70 | expect(fabs128(-1.0) == 1.0); | ||
| 58 | } | 71 | } |
| 59 | 72 | ||
| 60 | test "math.fabs16.special" { | 73 | test "math.fabs16.special" { |
| 61 | assert(math.isPositiveInf(fabs(math.inf(f16)))); | 74 | expect(math.isPositiveInf(fabs(math.inf(f16)))); |
| 62 | assert(math.isPositiveInf(fabs(-math.inf(f16)))); | 75 | expect(math.isPositiveInf(fabs(-math.inf(f16)))); |
| 63 | assert(math.isNan(fabs(math.nan(f16)))); | 76 | expect(math.isNan(fabs(math.nan(f16)))); |
| 64 | } | 77 | } |
| 65 | 78 | ||
| 66 | test "math.fabs32.special" { | 79 | test "math.fabs32.special" { |
| 67 | assert(math.isPositiveInf(fabs(math.inf(f32)))); | 80 | expect(math.isPositiveInf(fabs(math.inf(f32)))); |
| 68 | assert(math.isPositiveInf(fabs(-math.inf(f32)))); | 81 | expect(math.isPositiveInf(fabs(-math.inf(f32)))); |
| 69 | assert(math.isNan(fabs(math.nan(f32)))); | 82 | expect(math.isNan(fabs(math.nan(f32)))); |
| 70 | } | 83 | } |
| 71 | 84 | ||
| 72 | test "math.fabs64.special" { | 85 | test "math.fabs64.special" { |
| 73 | assert(math.isPositiveInf(fabs(math.inf(f64)))); | 86 | expect(math.isPositiveInf(fabs(math.inf(f64)))); |
| 74 | assert(math.isPositiveInf(fabs(-math.inf(f64)))); | 87 | expect(math.isPositiveInf(fabs(-math.inf(f64)))); |
| 75 | assert(math.isNan(fabs(math.nan(f64)))); | 88 | expect(math.isNan(fabs(math.nan(f64)))); |
| 89 | } | ||
| 90 | |||
| 91 | test "math.fabs128.special" { | ||
| 92 | expect(math.isPositiveInf(fabs(math.inf(f128)))); | ||
| 93 | expect(math.isPositiveInf(fabs(-math.inf(f128)))); | ||
| 94 | expect(math.isNan(fabs(math.nan(f128)))); | ||
| 76 | } | 95 | } |
std/math/floor.zig+28-28| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | // - floor(nan) = nan | 5 | // - floor(nan) = nan |
| 6 | 6 | ||
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | const std = @import("../index.zig"); | 9 | const std = @import("../index.zig"); |
| 10 | const math = std.math; | 10 | const math = std.math; |
| 11 | 11 | ||
| ... | @@ -117,49 +117,49 @@ fn floor64(x: f64) f64 { | ... | @@ -117,49 +117,49 @@ fn floor64(x: f64) f64 { |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | test "math.floor" { | 119 | test "math.floor" { |
| 120 | assert(floor(f16(1.3)) == floor16(1.3)); | 120 | expect(floor(f16(1.3)) == floor16(1.3)); |
| 121 | assert(floor(f32(1.3)) == floor32(1.3)); | 121 | expect(floor(f32(1.3)) == floor32(1.3)); |
| 122 | assert(floor(f64(1.3)) == floor64(1.3)); | 122 | expect(floor(f64(1.3)) == floor64(1.3)); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | test "math.floor16" { | 125 | test "math.floor16" { |
| 126 | assert(floor16(1.3) == 1.0); | 126 | expect(floor16(1.3) == 1.0); |
| 127 | assert(floor16(-1.3) == -2.0); | 127 | expect(floor16(-1.3) == -2.0); |
| 128 | assert(floor16(0.2) == 0.0); | 128 | expect(floor16(0.2) == 0.0); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | test "math.floor32" { | 131 | test "math.floor32" { |
| 132 | assert(floor32(1.3) == 1.0); | 132 | expect(floor32(1.3) == 1.0); |
| 133 | assert(floor32(-1.3) == -2.0); | 133 | expect(floor32(-1.3) == -2.0); |
| 134 | assert(floor32(0.2) == 0.0); | 134 | expect(floor32(0.2) == 0.0); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | test "math.floor64" { | 137 | test "math.floor64" { |
| 138 | assert(floor64(1.3) == 1.0); | 138 | expect(floor64(1.3) == 1.0); |
| 139 | assert(floor64(-1.3) == -2.0); | 139 | expect(floor64(-1.3) == -2.0); |
| 140 | assert(floor64(0.2) == 0.0); | 140 | expect(floor64(0.2) == 0.0); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | test "math.floor16.special" { | 143 | test "math.floor16.special" { |
| 144 | assert(floor16(0.0) == 0.0); | 144 | expect(floor16(0.0) == 0.0); |
| 145 | assert(floor16(-0.0) == -0.0); | 145 | expect(floor16(-0.0) == -0.0); |
| 146 | assert(math.isPositiveInf(floor16(math.inf(f16)))); | 146 | expect(math.isPositiveInf(floor16(math.inf(f16)))); |
| 147 | assert(math.isNegativeInf(floor16(-math.inf(f16)))); | 147 | expect(math.isNegativeInf(floor16(-math.inf(f16)))); |
| 148 | assert(math.isNan(floor16(math.nan(f16)))); | 148 | expect(math.isNan(floor16(math.nan(f16)))); |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | test "math.floor32.special" { | 151 | test "math.floor32.special" { |
| 152 | assert(floor32(0.0) == 0.0); | 152 | expect(floor32(0.0) == 0.0); |
| 153 | assert(floor32(-0.0) == -0.0); | 153 | expect(floor32(-0.0) == -0.0); |
| 154 | assert(math.isPositiveInf(floor32(math.inf(f32)))); | 154 | expect(math.isPositiveInf(floor32(math.inf(f32)))); |
| 155 | assert(math.isNegativeInf(floor32(-math.inf(f32)))); | 155 | expect(math.isNegativeInf(floor32(-math.inf(f32)))); |
| 156 | assert(math.isNan(floor32(math.nan(f32)))); | 156 | expect(math.isNan(floor32(math.nan(f32)))); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | test "math.floor64.special" { | 159 | test "math.floor64.special" { |
| 160 | assert(floor64(0.0) == 0.0); | 160 | expect(floor64(0.0) == 0.0); |
| 161 | assert(floor64(-0.0) == -0.0); | 161 | expect(floor64(-0.0) == -0.0); |
| 162 | assert(math.isPositiveInf(floor64(math.inf(f64)))); | 162 | expect(math.isPositiveInf(floor64(math.inf(f64)))); |
| 163 | assert(math.isNegativeInf(floor64(-math.inf(f64)))); | 163 | expect(math.isNegativeInf(floor64(-math.inf(f64)))); |
| 164 | assert(math.isNan(floor64(math.nan(f64)))); | 164 | expect(math.isNan(floor64(math.nan(f64)))); |
| 165 | } | 165 | } |
std/math/fma.zig+17-17| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) T { | 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) T { |
| 6 | return switch (T) { | 6 | return switch (T) { |
| ... | @@ -135,30 +135,30 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 { | ... | @@ -135,30 +135,30 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 { |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | test "math.fma" { | 137 | test "math.fma" { |
| 138 | assert(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0)); | 138 | expect(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0)); |
| 139 | assert(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0)); | 139 | expect(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0)); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | test "math.fma32" { | 142 | test "math.fma32" { |
| 143 | const epsilon = 0.000001; | 143 | const epsilon = 0.000001; |
| 144 | 144 | ||
| 145 | assert(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon)); | 145 | expect(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon)); |
| 146 | assert(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon)); | 146 | expect(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon)); |
| 147 | assert(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon)); | 147 | expect(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon)); |
| 148 | assert(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon)); | 148 | expect(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon)); |
| 149 | assert(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon)); | 149 | expect(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon)); |
| 150 | assert(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon)); | 150 | expect(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon)); |
| 151 | assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | 151 | expect(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | test "math.fma64" { | 154 | test "math.fma64" { |
| 155 | const epsilon = 0.000001; | 155 | const epsilon = 0.000001; |
| 156 | 156 | ||
| 157 | assert(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon)); | 157 | expect(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon)); |
| 158 | assert(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon)); | 158 | expect(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon)); |
| 159 | assert(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon)); | 159 | expect(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon)); |
| 160 | assert(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon)); | 160 | expect(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon)); |
| 161 | assert(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon)); | 161 | expect(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon)); |
| 162 | assert(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon)); | 162 | expect(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon)); |
| 163 | assert(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | 163 | expect(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); |
| 164 | } | 164 | } |
std/math/frexp.zig+17-17| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | 10 | ||
| 11 | fn frexp_result(comptime T: type) type { | 11 | fn frexp_result(comptime T: type) type { |
| 12 | return struct { | 12 | return struct { |
| ... | @@ -103,11 +103,11 @@ fn frexp64(x: f64) frexp64_result { | ... | @@ -103,11 +103,11 @@ fn frexp64(x: f64) frexp64_result { |
| 103 | test "math.frexp" { | 103 | test "math.frexp" { |
| 104 | const a = frexp(f32(1.3)); | 104 | const a = frexp(f32(1.3)); |
| 105 | const b = frexp32(1.3); | 105 | const b = frexp32(1.3); |
| 106 | assert(a.significand == b.significand and a.exponent == b.exponent); | 106 | expect(a.significand == b.significand and a.exponent == b.exponent); |
| 107 | 107 | ||
| 108 | const c = frexp(f64(1.3)); | 108 | const c = frexp(f64(1.3)); |
| 109 | const d = frexp64(1.3); | 109 | const d = frexp64(1.3); |
| 110 | assert(c.significand == d.significand and c.exponent == d.exponent); | 110 | expect(c.significand == d.significand and c.exponent == d.exponent); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | test "math.frexp32" { | 113 | test "math.frexp32" { |
| ... | @@ -115,10 +115,10 @@ test "math.frexp32" { | ... | @@ -115,10 +115,10 @@ test "math.frexp32" { |
| 115 | var r: frexp32_result = undefined; | 115 | var r: frexp32_result = undefined; |
| 116 | 116 | ||
| 117 | r = frexp32(1.3); | 117 | r = frexp32(1.3); |
| 118 | assert(math.approxEq(f32, r.significand, 0.65, epsilon) and r.exponent == 1); | 118 | expect(math.approxEq(f32, r.significand, 0.65, epsilon) and r.exponent == 1); |
| 119 | 119 | ||
| 120 | r = frexp32(78.0234); | 120 | r = frexp32(78.0234); |
| 121 | assert(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7); | 121 | expect(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | test "math.frexp64" { | 124 | test "math.frexp64" { |
| ... | @@ -126,46 +126,46 @@ test "math.frexp64" { | ... | @@ -126,46 +126,46 @@ test "math.frexp64" { |
| 126 | var r: frexp64_result = undefined; | 126 | var r: frexp64_result = undefined; |
| 127 | 127 | ||
| 128 | r = frexp64(1.3); | 128 | r = frexp64(1.3); |
| 129 | assert(math.approxEq(f64, r.significand, 0.65, epsilon) and r.exponent == 1); | 129 | expect(math.approxEq(f64, r.significand, 0.65, epsilon) and r.exponent == 1); |
| 130 | 130 | ||
| 131 | r = frexp64(78.0234); | 131 | r = frexp64(78.0234); |
| 132 | assert(math.approxEq(f64, r.significand, 0.609558, epsilon) and r.exponent == 7); | 132 | expect(math.approxEq(f64, r.significand, 0.609558, epsilon) and r.exponent == 7); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | test "math.frexp32.special" { | 135 | test "math.frexp32.special" { |
| 136 | var r: frexp32_result = undefined; | 136 | var r: frexp32_result = undefined; |
| 137 | 137 | ||
| 138 | r = frexp32(0.0); | 138 | r = frexp32(0.0); |
| 139 | assert(r.significand == 0.0 and r.exponent == 0); | 139 | expect(r.significand == 0.0 and r.exponent == 0); |
| 140 | 140 | ||
| 141 | r = frexp32(-0.0); | 141 | r = frexp32(-0.0); |
| 142 | assert(r.significand == -0.0 and r.exponent == 0); | 142 | expect(r.significand == -0.0 and r.exponent == 0); |
| 143 | 143 | ||
| 144 | r = frexp32(math.inf(f32)); | 144 | r = frexp32(math.inf(f32)); |
| 145 | assert(math.isPositiveInf(r.significand) and r.exponent == 0); | 145 | expect(math.isPositiveInf(r.significand) and r.exponent == 0); |
| 146 | 146 | ||
| 147 | r = frexp32(-math.inf(f32)); | 147 | r = frexp32(-math.inf(f32)); |
| 148 | assert(math.isNegativeInf(r.significand) and r.exponent == 0); | 148 | expect(math.isNegativeInf(r.significand) and r.exponent == 0); |
| 149 | 149 | ||
| 150 | r = frexp32(math.nan(f32)); | 150 | r = frexp32(math.nan(f32)); |
| 151 | assert(math.isNan(r.significand)); | 151 | expect(math.isNan(r.significand)); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | test "math.frexp64.special" { | 154 | test "math.frexp64.special" { |
| 155 | var r: frexp64_result = undefined; | 155 | var r: frexp64_result = undefined; |
| 156 | 156 | ||
| 157 | r = frexp64(0.0); | 157 | r = frexp64(0.0); |
| 158 | assert(r.significand == 0.0 and r.exponent == 0); | 158 | expect(r.significand == 0.0 and r.exponent == 0); |
| 159 | 159 | ||
| 160 | r = frexp64(-0.0); | 160 | r = frexp64(-0.0); |
| 161 | assert(r.significand == -0.0 and r.exponent == 0); | 161 | expect(r.significand == -0.0 and r.exponent == 0); |
| 162 | 162 | ||
| 163 | r = frexp64(math.inf(f64)); | 163 | r = frexp64(math.inf(f64)); |
| 164 | assert(math.isPositiveInf(r.significand) and r.exponent == 0); | 164 | expect(math.isPositiveInf(r.significand) and r.exponent == 0); |
| 165 | 165 | ||
| 166 | r = frexp64(-math.inf(f64)); | 166 | r = frexp64(-math.inf(f64)); |
| 167 | assert(math.isNegativeInf(r.significand) and r.exponent == 0); | 167 | expect(math.isNegativeInf(r.significand) and r.exponent == 0); |
| 168 | 168 | ||
| 169 | r = frexp64(math.nan(f64)); | 169 | r = frexp64(math.nan(f64)); |
| 170 | assert(math.isNan(r.significand)); | 170 | expect(math.isNan(r.significand)); |
| 171 | } | 171 | } |
std/math/hypot.zig+29-29| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | const maxInt = std.math.maxInt; | 11 | const maxInt = std.math.maxInt; |
| 12 | 12 | ||
| 13 | pub fn hypot(comptime T: type, x: T, y: T) T { | 13 | pub fn hypot(comptime T: type, x: T, y: T) T { |
| ... | @@ -115,48 +115,48 @@ fn hypot64(x: f64, y: f64) f64 { | ... | @@ -115,48 +115,48 @@ fn hypot64(x: f64, y: f64) f64 { |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | test "math.hypot" { | 117 | test "math.hypot" { |
| 118 | assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2)); | 118 | expect(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2)); |
| 119 | assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2)); | 119 | expect(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2)); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | test "math.hypot32" { | 122 | test "math.hypot32" { |
| 123 | const epsilon = 0.000001; | 123 | const epsilon = 0.000001; |
| 124 | 124 | ||
| 125 | assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon)); | 125 | expect(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon)); |
| 126 | assert(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon)); | 126 | expect(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon)); |
| 127 | assert(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon)); | 127 | expect(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon)); |
| 128 | assert(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon)); | 128 | expect(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon)); |
| 129 | assert(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon)); | 129 | expect(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon)); |
| 130 | assert(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon)); | 130 | expect(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon)); |
| 131 | assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon)); | 131 | expect(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon)); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | test "math.hypot64" { | 134 | test "math.hypot64" { |
| 135 | const epsilon = 0.000001; | 135 | const epsilon = 0.000001; |
| 136 | 136 | ||
| 137 | assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon)); | 137 | expect(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon)); |
| 138 | assert(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon)); | 138 | expect(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon)); |
| 139 | assert(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon)); | 139 | expect(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon)); |
| 140 | assert(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon)); | 140 | expect(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon)); |
| 141 | assert(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon)); | 141 | expect(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon)); |
| 142 | assert(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon)); | 142 | expect(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon)); |
| 143 | assert(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon)); | 143 | expect(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon)); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | test "math.hypot32.special" { | 146 | test "math.hypot32.special" { |
| 147 | assert(math.isPositiveInf(hypot32(math.inf(f32), 0.0))); | 147 | expect(math.isPositiveInf(hypot32(math.inf(f32), 0.0))); |
| 148 | assert(math.isPositiveInf(hypot32(-math.inf(f32), 0.0))); | 148 | expect(math.isPositiveInf(hypot32(-math.inf(f32), 0.0))); |
| 149 | assert(math.isPositiveInf(hypot32(0.0, math.inf(f32)))); | 149 | expect(math.isPositiveInf(hypot32(0.0, math.inf(f32)))); |
| 150 | assert(math.isPositiveInf(hypot32(0.0, -math.inf(f32)))); | 150 | expect(math.isPositiveInf(hypot32(0.0, -math.inf(f32)))); |
| 151 | assert(math.isNan(hypot32(math.nan(f32), 0.0))); | 151 | expect(math.isNan(hypot32(math.nan(f32), 0.0))); |
| 152 | assert(math.isNan(hypot32(0.0, math.nan(f32)))); | 152 | expect(math.isNan(hypot32(0.0, math.nan(f32)))); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | test "math.hypot64.special" { | 155 | test "math.hypot64.special" { |
| 156 | assert(math.isPositiveInf(hypot64(math.inf(f64), 0.0))); | 156 | expect(math.isPositiveInf(hypot64(math.inf(f64), 0.0))); |
| 157 | assert(math.isPositiveInf(hypot64(-math.inf(f64), 0.0))); | 157 | expect(math.isPositiveInf(hypot64(-math.inf(f64), 0.0))); |
| 158 | assert(math.isPositiveInf(hypot64(0.0, math.inf(f64)))); | 158 | expect(math.isPositiveInf(hypot64(0.0, math.inf(f64)))); |
| 159 | assert(math.isPositiveInf(hypot64(0.0, -math.inf(f64)))); | 159 | expect(math.isPositiveInf(hypot64(0.0, -math.inf(f64)))); |
| 160 | assert(math.isNan(hypot64(math.nan(f64), 0.0))); | 160 | expect(math.isNan(hypot64(math.nan(f64), 0.0))); |
| 161 | assert(math.isNan(hypot64(0.0, math.nan(f64)))); | 161 | expect(math.isNan(hypot64(0.0, math.nan(f64)))); |
| 162 | } | 162 | } |
std/math/ilogb.zig+23-23| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | const maxInt = std.math.maxInt; | 10 | const maxInt = std.math.maxInt; |
| 11 | const minInt = std.math.minInt; | 11 | const minInt = std.math.minInt; |
| 12 | 12 | ||
| ... | @@ -95,38 +95,38 @@ fn ilogb64(x: f64) i32 { | ... | @@ -95,38 +95,38 @@ fn ilogb64(x: f64) i32 { |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | test "math.ilogb" { | 97 | test "math.ilogb" { |
| 98 | assert(ilogb(f32(0.2)) == ilogb32(0.2)); | 98 | expect(ilogb(f32(0.2)) == ilogb32(0.2)); |
| 99 | assert(ilogb(f64(0.2)) == ilogb64(0.2)); | 99 | expect(ilogb(f64(0.2)) == ilogb64(0.2)); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | test "math.ilogb32" { | 102 | test "math.ilogb32" { |
| 103 | assert(ilogb32(0.0) == fp_ilogb0); | 103 | expect(ilogb32(0.0) == fp_ilogb0); |
| 104 | assert(ilogb32(0.5) == -1); | 104 | expect(ilogb32(0.5) == -1); |
| 105 | assert(ilogb32(0.8923) == -1); | 105 | expect(ilogb32(0.8923) == -1); |
| 106 | assert(ilogb32(10.0) == 3); | 106 | expect(ilogb32(10.0) == 3); |
| 107 | assert(ilogb32(-123984) == 16); | 107 | expect(ilogb32(-123984) == 16); |
| 108 | assert(ilogb32(2398.23) == 11); | 108 | expect(ilogb32(2398.23) == 11); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | test "math.ilogb64" { | 111 | test "math.ilogb64" { |
| 112 | assert(ilogb64(0.0) == fp_ilogb0); | 112 | expect(ilogb64(0.0) == fp_ilogb0); |
| 113 | assert(ilogb64(0.5) == -1); | 113 | expect(ilogb64(0.5) == -1); |
| 114 | assert(ilogb64(0.8923) == -1); | 114 | expect(ilogb64(0.8923) == -1); |
| 115 | assert(ilogb64(10.0) == 3); | 115 | expect(ilogb64(10.0) == 3); |
| 116 | assert(ilogb64(-123984) == 16); | 116 | expect(ilogb64(-123984) == 16); |
| 117 | assert(ilogb64(2398.23) == 11); | 117 | expect(ilogb64(2398.23) == 11); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | test "math.ilogb32.special" { | 120 | test "math.ilogb32.special" { |
| 121 | assert(ilogb32(math.inf(f32)) == maxInt(i32)); | 121 | expect(ilogb32(math.inf(f32)) == maxInt(i32)); |
| 122 | assert(ilogb32(-math.inf(f32)) == maxInt(i32)); | 122 | expect(ilogb32(-math.inf(f32)) == maxInt(i32)); |
| 123 | assert(ilogb32(0.0) == minInt(i32)); | 123 | expect(ilogb32(0.0) == minInt(i32)); |
| 124 | assert(ilogb32(math.nan(f32)) == maxInt(i32)); | 124 | expect(ilogb32(math.nan(f32)) == maxInt(i32)); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | test "math.ilogb64.special" { | 127 | test "math.ilogb64.special" { |
| 128 | assert(ilogb64(math.inf(f64)) == maxInt(i32)); | 128 | expect(ilogb64(math.inf(f64)) == maxInt(i32)); |
| 129 | assert(ilogb64(-math.inf(f64)) == maxInt(i32)); | 129 | expect(ilogb64(-math.inf(f64)) == maxInt(i32)); |
| 130 | assert(ilogb64(0.0) == minInt(i32)); | 130 | expect(ilogb64(0.0) == minInt(i32)); |
| 131 | assert(ilogb64(math.nan(f64)) == maxInt(i32)); | 131 | expect(ilogb64(math.nan(f64)) == maxInt(i32)); |
| 132 | } | 132 | } |
std/math/index.zig+190-172| ... | @@ -2,10 +2,18 @@ const builtin = @import("builtin"); | ... | @@ -2,10 +2,18 @@ const builtin = @import("builtin"); |
| 2 | const std = @import("../index.zig"); | 2 | const std = @import("../index.zig"); |
| 3 | const TypeId = builtin.TypeId; | 3 | const TypeId = builtin.TypeId; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const testing = std.testing; | ||
| 5 | 6 | ||
| 6 | pub const e = 2.71828182845904523536028747135266249775724709369995; | 7 | pub const e = 2.71828182845904523536028747135266249775724709369995; |
| 7 | pub const pi = 3.14159265358979323846264338327950288419716939937510; | 8 | pub const pi = 3.14159265358979323846264338327950288419716939937510; |
| 8 | 9 | ||
| 10 | // From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128) | ||
| 11 | pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001)); | ||
| 12 | pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000)); | ||
| 13 | pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); | ||
| 14 | pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000)); | ||
| 15 | pub const f128_toint = 1.0 / f128_epsilon; | ||
| 16 | |||
| 9 | // float.h details | 17 | // float.h details |
| 10 | pub const f64_true_min = 4.94065645841246544177e-324; | 18 | pub const f64_true_min = 4.94065645841246544177e-324; |
| 11 | pub const f64_min = 2.2250738585072014e-308; | 19 | pub const f64_min = 2.2250738585072014e-308; |
| ... | @@ -43,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64); | ... | @@ -43,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64); |
| 43 | pub const inf_u64 = u64(0x7FF << 52); | 51 | pub const inf_u64 = u64(0x7FF << 52); |
| 44 | pub const inf_f64 = @bitCast(f64, inf_u64); | 52 | pub const inf_f64 = @bitCast(f64, inf_u64); |
| 45 | 53 | ||
| 54 | pub const nan_u128 = u128(0x7fff0000000000000000000000000001); | ||
| 55 | pub const nan_f128 = @bitCast(f128, nan_u128); | ||
| 56 | |||
| 57 | pub const inf_u128 = u128(0x7fff0000000000000000000000000000); | ||
| 58 | pub const inf_f128 = @bitCast(f128, inf_u128); | ||
| 59 | |||
| 46 | pub const nan = @import("nan.zig").nan; | 60 | pub const nan = @import("nan.zig").nan; |
| 47 | pub const snan = @import("nan.zig").snan; | 61 | pub const snan = @import("nan.zig").snan; |
| 48 | pub const inf = @import("inf.zig").inf; | 62 | pub const inf = @import("inf.zig").inf; |
| ... | @@ -233,7 +247,7 @@ pub fn min(x: var, y: var) @typeOf(x + y) { | ... | @@ -233,7 +247,7 @@ pub fn min(x: var, y: var) @typeOf(x + y) { |
| 233 | } | 247 | } |
| 234 | 248 | ||
| 235 | test "math.min" { | 249 | test "math.min" { |
| 236 | assert(min(i32(-1), i32(2)) == -1); | 250 | testing.expect(min(i32(-1), i32(2)) == -1); |
| 237 | } | 251 | } |
| 238 | 252 | ||
| 239 | pub fn max(x: var, y: var) @typeOf(x + y) { | 253 | pub fn max(x: var, y: var) @typeOf(x + y) { |
| ... | @@ -241,7 +255,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) { | ... | @@ -241,7 +255,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) { |
| 241 | } | 255 | } |
| 242 | 256 | ||
| 243 | test "math.max" { | 257 | test "math.max" { |
| 244 | assert(max(i32(-1), i32(2)) == 2); | 258 | testing.expect(max(i32(-1), i32(2)) == 2); |
| 245 | } | 259 | } |
| 246 | 260 | ||
| 247 | pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) { | 261 | pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) { |
| ... | @@ -286,10 +300,10 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T { | ... | @@ -286,10 +300,10 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T { |
| 286 | } | 300 | } |
| 287 | 301 | ||
| 288 | test "math.shl" { | 302 | test "math.shl" { |
| 289 | assert(shl(u8, 0b11111111, usize(3)) == 0b11111000); | 303 | testing.expect(shl(u8, 0b11111111, usize(3)) == 0b11111000); |
| 290 | assert(shl(u8, 0b11111111, usize(8)) == 0); | 304 | testing.expect(shl(u8, 0b11111111, usize(8)) == 0); |
| 291 | assert(shl(u8, 0b11111111, usize(9)) == 0); | 305 | testing.expect(shl(u8, 0b11111111, usize(9)) == 0); |
| 292 | assert(shl(u8, 0b11111111, isize(-2)) == 0b00111111); | 306 | testing.expect(shl(u8, 0b11111111, isize(-2)) == 0b00111111); |
| 293 | } | 307 | } |
| 294 | 308 | ||
| 295 | /// Shifts right. Overflowed bits are truncated. | 309 | /// Shifts right. Overflowed bits are truncated. |
| ... | @@ -310,10 +324,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T { | ... | @@ -310,10 +324,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T { |
| 310 | } | 324 | } |
| 311 | 325 | ||
| 312 | test "math.shr" { | 326 | test "math.shr" { |
| 313 | assert(shr(u8, 0b11111111, usize(3)) == 0b00011111); | 327 | testing.expect(shr(u8, 0b11111111, usize(3)) == 0b00011111); |
| 314 | assert(shr(u8, 0b11111111, usize(8)) == 0); | 328 | testing.expect(shr(u8, 0b11111111, usize(8)) == 0); |
| 315 | assert(shr(u8, 0b11111111, usize(9)) == 0); | 329 | testing.expect(shr(u8, 0b11111111, usize(9)) == 0); |
| 316 | assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100); | 330 | testing.expect(shr(u8, 0b11111111, isize(-2)) == 0b11111100); |
| 317 | } | 331 | } |
| 318 | 332 | ||
| 319 | /// Rotates right. Only unsigned values can be rotated. | 333 | /// Rotates right. Only unsigned values can be rotated. |
| ... | @@ -328,11 +342,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T { | ... | @@ -328,11 +342,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T { |
| 328 | } | 342 | } |
| 329 | 343 | ||
| 330 | test "math.rotr" { | 344 | test "math.rotr" { |
| 331 | assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001); | 345 | testing.expect(rotr(u8, 0b00000001, usize(0)) == 0b00000001); |
| 332 | assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000); | 346 | testing.expect(rotr(u8, 0b00000001, usize(9)) == 0b10000000); |
| 333 | assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001); | 347 | testing.expect(rotr(u8, 0b00000001, usize(8)) == 0b00000001); |
| 334 | assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000); | 348 | testing.expect(rotr(u8, 0b00000001, usize(4)) == 0b00010000); |
| 335 | assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010); | 349 | testing.expect(rotr(u8, 0b00000001, isize(-1)) == 0b00000010); |
| 336 | } | 350 | } |
| 337 | 351 | ||
| 338 | /// Rotates left. Only unsigned values can be rotated. | 352 | /// Rotates left. Only unsigned values can be rotated. |
| ... | @@ -347,11 +361,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T { | ... | @@ -347,11 +361,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T { |
| 347 | } | 361 | } |
| 348 | 362 | ||
| 349 | test "math.rotl" { | 363 | test "math.rotl" { |
| 350 | assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001); | 364 | testing.expect(rotl(u8, 0b00000001, usize(0)) == 0b00000001); |
| 351 | assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010); | 365 | testing.expect(rotl(u8, 0b00000001, usize(9)) == 0b00000010); |
| 352 | assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001); | 366 | testing.expect(rotl(u8, 0b00000001, usize(8)) == 0b00000001); |
| 353 | assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000); | 367 | testing.expect(rotl(u8, 0b00000001, usize(4)) == 0b00010000); |
| 354 | assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000); | 368 | testing.expect(rotl(u8, 0b00000001, isize(-1)) == 0b10000000); |
| 355 | } | 369 | } |
| 356 | 370 | ||
| 357 | pub fn Log2Int(comptime T: type) type { | 371 | pub fn Log2Int(comptime T: type) type { |
| ... | @@ -371,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t | ... | @@ -371,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t |
| 371 | return u0; | 385 | return u0; |
| 372 | } | 386 | } |
| 373 | const is_signed = from < 0; | 387 | const is_signed = from < 0; |
| 374 | const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement | 388 | const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement |
| 375 | const base = log2(largest_positive_integer); | 389 | const base = log2(largest_positive_integer); |
| 376 | const upper = (1 << base) - 1; | 390 | const upper = (1 << base) - 1; |
| 377 | var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1; | 391 | var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1; |
| ... | @@ -382,50 +396,50 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t | ... | @@ -382,50 +396,50 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t |
| 382 | } | 396 | } |
| 383 | 397 | ||
| 384 | test "math.IntFittingRange" { | 398 | test "math.IntFittingRange" { |
| 385 | assert(IntFittingRange(0, 0) == u0); | 399 | testing.expect(IntFittingRange(0, 0) == u0); |
| 386 | assert(IntFittingRange(0, 1) == u1); | 400 | testing.expect(IntFittingRange(0, 1) == u1); |
| 387 | assert(IntFittingRange(0, 2) == u2); | 401 | testing.expect(IntFittingRange(0, 2) == u2); |
| 388 | assert(IntFittingRange(0, 3) == u2); | 402 | testing.expect(IntFittingRange(0, 3) == u2); |
| 389 | assert(IntFittingRange(0, 4) == u3); | 403 | testing.expect(IntFittingRange(0, 4) == u3); |
| 390 | assert(IntFittingRange(0, 7) == u3); | 404 | testing.expect(IntFittingRange(0, 7) == u3); |
| 391 | assert(IntFittingRange(0, 8) == u4); | 405 | testing.expect(IntFittingRange(0, 8) == u4); |
| 392 | assert(IntFittingRange(0, 9) == u4); | 406 | testing.expect(IntFittingRange(0, 9) == u4); |
| 393 | assert(IntFittingRange(0, 15) == u4); | 407 | testing.expect(IntFittingRange(0, 15) == u4); |
| 394 | assert(IntFittingRange(0, 16) == u5); | 408 | testing.expect(IntFittingRange(0, 16) == u5); |
| 395 | assert(IntFittingRange(0, 17) == u5); | 409 | testing.expect(IntFittingRange(0, 17) == u5); |
| 396 | assert(IntFittingRange(0, 4095) == u12); | 410 | testing.expect(IntFittingRange(0, 4095) == u12); |
| 397 | assert(IntFittingRange(2000, 4095) == u12); | 411 | testing.expect(IntFittingRange(2000, 4095) == u12); |
| 398 | assert(IntFittingRange(0, 4096) == u13); | 412 | testing.expect(IntFittingRange(0, 4096) == u13); |
| 399 | assert(IntFittingRange(2000, 4096) == u13); | 413 | testing.expect(IntFittingRange(2000, 4096) == u13); |
| 400 | assert(IntFittingRange(0, 4097) == u13); | 414 | testing.expect(IntFittingRange(0, 4097) == u13); |
| 401 | assert(IntFittingRange(2000, 4097) == u13); | 415 | testing.expect(IntFittingRange(2000, 4097) == u13); |
| 402 | assert(IntFittingRange(0, 123456789123456798123456789) == u87); | 416 | testing.expect(IntFittingRange(0, 123456789123456798123456789) == u87); |
| 403 | assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177); | 417 | testing.expect(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177); |
| 404 | 418 | ||
| 405 | assert(IntFittingRange(-1, -1) == i1); | 419 | testing.expect(IntFittingRange(-1, -1) == i1); |
| 406 | assert(IntFittingRange(-1, 0) == i1); | 420 | testing.expect(IntFittingRange(-1, 0) == i1); |
| 407 | assert(IntFittingRange(-1, 1) == i2); | 421 | testing.expect(IntFittingRange(-1, 1) == i2); |
| 408 | assert(IntFittingRange(-2, -2) == i2); | 422 | testing.expect(IntFittingRange(-2, -2) == i2); |
| 409 | assert(IntFittingRange(-2, -1) == i2); | 423 | testing.expect(IntFittingRange(-2, -1) == i2); |
| 410 | assert(IntFittingRange(-2, 0) == i2); | 424 | testing.expect(IntFittingRange(-2, 0) == i2); |
| 411 | assert(IntFittingRange(-2, 1) == i2); | 425 | testing.expect(IntFittingRange(-2, 1) == i2); |
| 412 | assert(IntFittingRange(-2, 2) == i3); | 426 | testing.expect(IntFittingRange(-2, 2) == i3); |
| 413 | assert(IntFittingRange(-1, 2) == i3); | 427 | testing.expect(IntFittingRange(-1, 2) == i3); |
| 414 | assert(IntFittingRange(-1, 3) == i3); | 428 | testing.expect(IntFittingRange(-1, 3) == i3); |
| 415 | assert(IntFittingRange(-1, 4) == i4); | 429 | testing.expect(IntFittingRange(-1, 4) == i4); |
| 416 | assert(IntFittingRange(-1, 7) == i4); | 430 | testing.expect(IntFittingRange(-1, 7) == i4); |
| 417 | assert(IntFittingRange(-1, 8) == i5); | 431 | testing.expect(IntFittingRange(-1, 8) == i5); |
| 418 | assert(IntFittingRange(-1, 9) == i5); | 432 | testing.expect(IntFittingRange(-1, 9) == i5); |
| 419 | assert(IntFittingRange(-1, 15) == i5); | 433 | testing.expect(IntFittingRange(-1, 15) == i5); |
| 420 | assert(IntFittingRange(-1, 16) == i6); | 434 | testing.expect(IntFittingRange(-1, 16) == i6); |
| 421 | assert(IntFittingRange(-1, 17) == i6); | 435 | testing.expect(IntFittingRange(-1, 17) == i6); |
| 422 | assert(IntFittingRange(-1, 4095) == i13); | 436 | testing.expect(IntFittingRange(-1, 4095) == i13); |
| 423 | assert(IntFittingRange(-4096, 4095) == i13); | 437 | testing.expect(IntFittingRange(-4096, 4095) == i13); |
| 424 | assert(IntFittingRange(-1, 4096) == i14); | 438 | testing.expect(IntFittingRange(-1, 4096) == i14); |
| 425 | assert(IntFittingRange(-4097, 4095) == i14); | 439 | testing.expect(IntFittingRange(-4097, 4095) == i14); |
| 426 | assert(IntFittingRange(-1, 4097) == i14); | 440 | testing.expect(IntFittingRange(-1, 4097) == i14); |
| 427 | assert(IntFittingRange(-1, 123456789123456798123456789) == i88); | 441 | testing.expect(IntFittingRange(-1, 123456789123456798123456789) == i88); |
| 428 | assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178); | 442 | testing.expect(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178); |
| 429 | } | 443 | } |
| 430 | 444 | ||
| 431 | test "math overflow functions" { | 445 | test "math overflow functions" { |
| ... | @@ -434,10 +448,10 @@ test "math overflow functions" { | ... | @@ -434,10 +448,10 @@ test "math overflow functions" { |
| 434 | } | 448 | } |
| 435 | 449 | ||
| 436 | fn testOverflow() void { | 450 | fn testOverflow() void { |
| 437 | assert((mul(i32, 3, 4) catch unreachable) == 12); | 451 | testing.expect((mul(i32, 3, 4) catch unreachable) == 12); |
| 438 | assert((add(i32, 3, 4) catch unreachable) == 7); | 452 | testing.expect((add(i32, 3, 4) catch unreachable) == 7); |
| 439 | assert((sub(i32, 3, 4) catch unreachable) == -1); | 453 | testing.expect((sub(i32, 3, 4) catch unreachable) == -1); |
| 440 | assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000); | 454 | testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000); |
| 441 | } | 455 | } |
| 442 | 456 | ||
| 443 | pub fn absInt(x: var) !@typeOf(x) { | 457 | pub fn absInt(x: var) !@typeOf(x) { |
| ... | @@ -458,8 +472,8 @@ test "math.absInt" { | ... | @@ -458,8 +472,8 @@ test "math.absInt" { |
| 458 | comptime testAbsInt(); | 472 | comptime testAbsInt(); |
| 459 | } | 473 | } |
| 460 | fn testAbsInt() void { | 474 | fn testAbsInt() void { |
| 461 | assert((absInt(i32(-10)) catch unreachable) == 10); | 475 | testing.expect((absInt(i32(-10)) catch unreachable) == 10); |
| 462 | assert((absInt(i32(10)) catch unreachable) == 10); | 476 | testing.expect((absInt(i32(10)) catch unreachable) == 10); |
| 463 | } | 477 | } |
| 464 | 478 | ||
| 465 | pub const absFloat = @import("fabs.zig").fabs; | 479 | pub const absFloat = @import("fabs.zig").fabs; |
| ... | @@ -476,13 +490,13 @@ test "math.divTrunc" { | ... | @@ -476,13 +490,13 @@ test "math.divTrunc" { |
| 476 | comptime testDivTrunc(); | 490 | comptime testDivTrunc(); |
| 477 | } | 491 | } |
| 478 | fn testDivTrunc() void { | 492 | fn testDivTrunc() void { |
| 479 | assert((divTrunc(i32, 5, 3) catch unreachable) == 1); | 493 | testing.expect((divTrunc(i32, 5, 3) catch unreachable) == 1); |
| 480 | assert((divTrunc(i32, -5, 3) catch unreachable) == -1); | 494 | testing.expect((divTrunc(i32, -5, 3) catch unreachable) == -1); |
| 481 | if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 495 | testing.expectError(error.DivisionByZero, divTrunc(i8, -5, 0)); |
| 482 | if (divTrunc(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow); | 496 | testing.expectError(error.Overflow, divTrunc(i8, -128, -1)); |
| 483 | 497 | ||
| 484 | assert((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0); | 498 | testing.expect((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0); |
| 485 | assert((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0); | 499 | testing.expect((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0); |
| 486 | } | 500 | } |
| 487 | 501 | ||
| 488 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T { | 502 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T { |
| ... | @@ -497,13 +511,13 @@ test "math.divFloor" { | ... | @@ -497,13 +511,13 @@ test "math.divFloor" { |
| 497 | comptime testDivFloor(); | 511 | comptime testDivFloor(); |
| 498 | } | 512 | } |
| 499 | fn testDivFloor() void { | 513 | fn testDivFloor() void { |
| 500 | assert((divFloor(i32, 5, 3) catch unreachable) == 1); | 514 | testing.expect((divFloor(i32, 5, 3) catch unreachable) == 1); |
| 501 | assert((divFloor(i32, -5, 3) catch unreachable) == -2); | 515 | testing.expect((divFloor(i32, -5, 3) catch unreachable) == -2); |
| 502 | if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 516 | testing.expectError(error.DivisionByZero, divFloor(i8, -5, 0)); |
| 503 | if (divFloor(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow); | 517 | testing.expectError(error.Overflow, divFloor(i8, -128, -1)); |
| 504 | 518 | ||
| 505 | assert((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0); | 519 | testing.expect((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0); |
| 506 | assert((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0); | 520 | testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0); |
| 507 | } | 521 | } |
| 508 | 522 | ||
| 509 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { | 523 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { |
| ... | @@ -520,15 +534,15 @@ test "math.divExact" { | ... | @@ -520,15 +534,15 @@ test "math.divExact" { |
| 520 | comptime testDivExact(); | 534 | comptime testDivExact(); |
| 521 | } | 535 | } |
| 522 | fn testDivExact() void { | 536 | fn testDivExact() void { |
| 523 | assert((divExact(i32, 10, 5) catch unreachable) == 2); | 537 | testing.expect((divExact(i32, 10, 5) catch unreachable) == 2); |
| 524 | assert((divExact(i32, -10, 5) catch unreachable) == -2); | 538 | testing.expect((divExact(i32, -10, 5) catch unreachable) == -2); |
| 525 | if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 539 | testing.expectError(error.DivisionByZero, divExact(i8, -5, 0)); |
| 526 | if (divExact(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow); | 540 | testing.expectError(error.Overflow, divExact(i8, -128, -1)); |
| 527 | if (divExact(i32, 5, 2)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder); | 541 | testing.expectError(error.UnexpectedRemainder, divExact(i32, 5, 2)); |
| 528 | 542 | ||
| 529 | assert((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0); | 543 | testing.expect((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0); |
| 530 | assert((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0); | 544 | testing.expect((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0); |
| 531 | if (divExact(f32, 5.0, 2.0)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder); | 545 | testing.expectError(error.UnexpectedRemainder, divExact(f32, 5.0, 2.0)); |
| 532 | } | 546 | } |
| 533 | 547 | ||
| 534 | pub fn mod(comptime T: type, numerator: T, denominator: T) !T { | 548 | pub fn mod(comptime T: type, numerator: T, denominator: T) !T { |
| ... | @@ -543,15 +557,15 @@ test "math.mod" { | ... | @@ -543,15 +557,15 @@ test "math.mod" { |
| 543 | comptime testMod(); | 557 | comptime testMod(); |
| 544 | } | 558 | } |
| 545 | fn testMod() void { | 559 | fn testMod() void { |
| 546 | assert((mod(i32, -5, 3) catch unreachable) == 1); | 560 | testing.expect((mod(i32, -5, 3) catch unreachable) == 1); |
| 547 | assert((mod(i32, 5, 3) catch unreachable) == 2); | 561 | testing.expect((mod(i32, 5, 3) catch unreachable) == 2); |
| 548 | if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | 562 | testing.expectError(error.NegativeDenominator, mod(i32, 10, -1)); |
| 549 | if (mod(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 563 | testing.expectError(error.DivisionByZero, mod(i32, 10, 0)); |
| 550 | 564 | ||
| 551 | assert((mod(f32, -5, 3) catch unreachable) == 1); | 565 | testing.expect((mod(f32, -5, 3) catch unreachable) == 1); |
| 552 | assert((mod(f32, 5, 3) catch unreachable) == 2); | 566 | testing.expect((mod(f32, 5, 3) catch unreachable) == 2); |
| 553 | if (mod(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | 567 | testing.expectError(error.NegativeDenominator, mod(f32, 10, -1)); |
| 554 | if (mod(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 568 | testing.expectError(error.DivisionByZero, mod(f32, 10, 0)); |
| 555 | } | 569 | } |
| 556 | 570 | ||
| 557 | pub fn rem(comptime T: type, numerator: T, denominator: T) !T { | 571 | pub fn rem(comptime T: type, numerator: T, denominator: T) !T { |
| ... | @@ -566,15 +580,15 @@ test "math.rem" { | ... | @@ -566,15 +580,15 @@ test "math.rem" { |
| 566 | comptime testRem(); | 580 | comptime testRem(); |
| 567 | } | 581 | } |
| 568 | fn testRem() void { | 582 | fn testRem() void { |
| 569 | assert((rem(i32, -5, 3) catch unreachable) == -2); | 583 | testing.expect((rem(i32, -5, 3) catch unreachable) == -2); |
| 570 | assert((rem(i32, 5, 3) catch unreachable) == 2); | 584 | testing.expect((rem(i32, 5, 3) catch unreachable) == 2); |
| 571 | if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | 585 | testing.expectError(error.NegativeDenominator, rem(i32, 10, -1)); |
| 572 | if (rem(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 586 | testing.expectError(error.DivisionByZero, rem(i32, 10, 0)); |
| 573 | 587 | ||
| 574 | assert((rem(f32, -5, 3) catch unreachable) == -2); | 588 | testing.expect((rem(f32, -5, 3) catch unreachable) == -2); |
| 575 | assert((rem(f32, 5, 3) catch unreachable) == 2); | 589 | testing.expect((rem(f32, 5, 3) catch unreachable) == 2); |
| 576 | if (rem(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); | 590 | testing.expectError(error.NegativeDenominator, rem(f32, 10, -1)); |
| 577 | if (rem(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); | 591 | testing.expectError(error.DivisionByZero, rem(f32, 10, 0)); |
| 578 | } | 592 | } |
| 579 | 593 | ||
| 580 | /// Returns the absolute value of the integer parameter. | 594 | /// Returns the absolute value of the integer parameter. |
| ... | @@ -587,14 +601,14 @@ pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) { | ... | @@ -587,14 +601,14 @@ pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) { |
| 587 | } | 601 | } |
| 588 | 602 | ||
| 589 | test "math.absCast" { | 603 | test "math.absCast" { |
| 590 | assert(absCast(i32(-999)) == 999); | 604 | testing.expect(absCast(i32(-999)) == 999); |
| 591 | assert(@typeOf(absCast(i32(-999))) == u32); | 605 | testing.expect(@typeOf(absCast(i32(-999))) == u32); |
| 592 | 606 | ||
| 593 | assert(absCast(i32(999)) == 999); | 607 | testing.expect(absCast(i32(999)) == 999); |
| 594 | assert(@typeOf(absCast(i32(999))) == u32); | 608 | testing.expect(@typeOf(absCast(i32(999))) == u32); |
| 595 | 609 | ||
| 596 | assert(absCast(i32(minInt(i32))) == -minInt(i32)); | 610 | testing.expect(absCast(i32(minInt(i32))) == -minInt(i32)); |
| 597 | assert(@typeOf(absCast(i32(minInt(i32)))) == u32); | 611 | testing.expect(@typeOf(absCast(i32(minInt(i32)))) == u32); |
| 598 | } | 612 | } |
| 599 | 613 | ||
| 600 | /// Returns the negation of the integer parameter. | 614 | /// Returns the negation of the integer parameter. |
| ... | @@ -611,13 +625,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) { | ... | @@ -611,13 +625,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) { |
| 611 | } | 625 | } |
| 612 | 626 | ||
| 613 | test "math.negateCast" { | 627 | test "math.negateCast" { |
| 614 | assert((negateCast(u32(999)) catch unreachable) == -999); | 628 | testing.expect((negateCast(u32(999)) catch unreachable) == -999); |
| 615 | assert(@typeOf(negateCast(u32(999)) catch unreachable) == i32); | 629 | testing.expect(@typeOf(negateCast(u32(999)) catch unreachable) == i32); |
| 616 | 630 | ||
| 617 | assert((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32)); | 631 | testing.expect((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32)); |
| 618 | assert(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32); | 632 | testing.expect(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32); |
| 619 | 633 | ||
| 620 | if (negateCast(u32(maxInt(i32) + 10))) |_| unreachable else |err| assert(err == error.Overflow); | 634 | testing.expectError(error.Overflow, negateCast(u32(maxInt(i32) + 10))); |
| 621 | } | 635 | } |
| 622 | 636 | ||
| 623 | /// Cast an integer to a different integer type. If the value doesn't fit, | 637 | /// Cast an integer to a different integer type. If the value doesn't fit, |
| ... | @@ -635,13 +649,13 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) { | ... | @@ -635,13 +649,13 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) { |
| 635 | } | 649 | } |
| 636 | 650 | ||
| 637 | test "math.cast" { | 651 | test "math.cast" { |
| 638 | if (cast(u8, u32(300))) |_| @panic("fail") else |err| assert(err == error.Overflow); | 652 | testing.expectError(error.Overflow, cast(u8, u32(300))); |
| 639 | if (cast(i8, i32(-200))) |_| @panic("fail") else |err| assert(err == error.Overflow); | 653 | testing.expectError(error.Overflow, cast(i8, i32(-200))); |
| 640 | if (cast(u8, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow); | 654 | testing.expectError(error.Overflow, cast(u8, i8(-1))); |
| 641 | if (cast(u64, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow); | 655 | testing.expectError(error.Overflow, cast(u64, i8(-1))); |
| 642 | 656 | ||
| 643 | assert((try cast(u8, u32(255))) == u8(255)); | 657 | testing.expect((try cast(u8, u32(255))) == u8(255)); |
| 644 | assert(@typeOf(try cast(u8, u32(255))) == u8); | 658 | testing.expect(@typeOf(try cast(u8, u32(255))) == u8); |
| 645 | } | 659 | } |
| 646 | 660 | ||
| 647 | pub const AlignCastError = error{UnalignedMemory}; | 661 | pub const AlignCastError = error{UnalignedMemory}; |
| ... | @@ -685,25 +699,25 @@ pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) { | ... | @@ -685,25 +699,25 @@ pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) { |
| 685 | } | 699 | } |
| 686 | 700 | ||
| 687 | test "std.math.log2_int_ceil" { | 701 | test "std.math.log2_int_ceil" { |
| 688 | assert(log2_int_ceil(u32, 1) == 0); | 702 | testing.expect(log2_int_ceil(u32, 1) == 0); |
| 689 | assert(log2_int_ceil(u32, 2) == 1); | 703 | testing.expect(log2_int_ceil(u32, 2) == 1); |
| 690 | assert(log2_int_ceil(u32, 3) == 2); | 704 | testing.expect(log2_int_ceil(u32, 3) == 2); |
| 691 | assert(log2_int_ceil(u32, 4) == 2); | 705 | testing.expect(log2_int_ceil(u32, 4) == 2); |
| 692 | assert(log2_int_ceil(u32, 5) == 3); | 706 | testing.expect(log2_int_ceil(u32, 5) == 3); |
| 693 | assert(log2_int_ceil(u32, 6) == 3); | 707 | testing.expect(log2_int_ceil(u32, 6) == 3); |
| 694 | assert(log2_int_ceil(u32, 7) == 3); | 708 | testing.expect(log2_int_ceil(u32, 7) == 3); |
| 695 | assert(log2_int_ceil(u32, 8) == 3); | 709 | testing.expect(log2_int_ceil(u32, 8) == 3); |
| 696 | assert(log2_int_ceil(u32, 9) == 4); | 710 | testing.expect(log2_int_ceil(u32, 9) == 4); |
| 697 | assert(log2_int_ceil(u32, 10) == 4); | 711 | testing.expect(log2_int_ceil(u32, 10) == 4); |
| 698 | } | 712 | } |
| 699 | 713 | ||
| 700 | fn testFloorPowerOfTwo() void { | 714 | fn testFloorPowerOfTwo() void { |
| 701 | assert(floorPowerOfTwo(u32, 63) == 32); | 715 | testing.expect(floorPowerOfTwo(u32, 63) == 32); |
| 702 | assert(floorPowerOfTwo(u32, 64) == 64); | 716 | testing.expect(floorPowerOfTwo(u32, 64) == 64); |
| 703 | assert(floorPowerOfTwo(u32, 65) == 64); | 717 | testing.expect(floorPowerOfTwo(u32, 65) == 64); |
| 704 | assert(floorPowerOfTwo(u4, 7) == 4); | 718 | testing.expect(floorPowerOfTwo(u4, 7) == 4); |
| 705 | assert(floorPowerOfTwo(u4, 8) == 8); | 719 | testing.expect(floorPowerOfTwo(u4, 8) == 8); |
| 706 | assert(floorPowerOfTwo(u4, 9) == 8); | 720 | testing.expect(floorPowerOfTwo(u4, 9) == 8); |
| 707 | } | 721 | } |
| 708 | 722 | ||
| 709 | pub fn lossyCast(comptime T: type, value: var) T { | 723 | pub fn lossyCast(comptime T: type, value: var) T { |
| ... | @@ -719,7 +733,7 @@ pub fn lossyCast(comptime T: type, value: var) T { | ... | @@ -719,7 +733,7 @@ pub fn lossyCast(comptime T: type, value: var) T { |
| 719 | test "math.f64_min" { | 733 | test "math.f64_min" { |
| 720 | const f64_min_u64 = 0x0010000000000000; | 734 | const f64_min_u64 = 0x0010000000000000; |
| 721 | const fmin: f64 = f64_min; | 735 | const fmin: f64 = f64_min; |
| 722 | assert(@bitCast(u64, fmin) == f64_min_u64); | 736 | testing.expect(@bitCast(u64, fmin) == f64_min_u64); |
| 723 | } | 737 | } |
| 724 | 738 | ||
| 725 | pub fn maxInt(comptime T: type) comptime_int { | 739 | pub fn maxInt(comptime T: type) comptime_int { |
| ... | @@ -738,36 +752,40 @@ pub fn minInt(comptime T: type) comptime_int { | ... | @@ -738,36 +752,40 @@ pub fn minInt(comptime T: type) comptime_int { |
| 738 | } | 752 | } |
| 739 | 753 | ||
| 740 | test "minInt and maxInt" { | 754 | test "minInt and maxInt" { |
| 741 | assert(maxInt(u0) == 0); | 755 | testing.expect(maxInt(u0) == 0); |
| 742 | assert(maxInt(u1) == 1); | 756 | testing.expect(maxInt(u1) == 1); |
| 743 | assert(maxInt(u8) == 255); | 757 | testing.expect(maxInt(u8) == 255); |
| 744 | assert(maxInt(u16) == 65535); | 758 | testing.expect(maxInt(u16) == 65535); |
| 745 | assert(maxInt(u32) == 4294967295); | 759 | testing.expect(maxInt(u32) == 4294967295); |
| 746 | assert(maxInt(u64) == 18446744073709551615); | 760 | testing.expect(maxInt(u64) == 18446744073709551615); |
| 747 | 761 | testing.expect(maxInt(u128) == 340282366920938463463374607431768211455); | |
| 748 | assert(maxInt(i0) == 0); | 762 | |
| 749 | assert(maxInt(i1) == 0); | 763 | testing.expect(maxInt(i0) == 0); |
| 750 | assert(maxInt(i8) == 127); | 764 | testing.expect(maxInt(i1) == 0); |
| 751 | assert(maxInt(i16) == 32767); | 765 | testing.expect(maxInt(i8) == 127); |
| 752 | assert(maxInt(i32) == 2147483647); | 766 | testing.expect(maxInt(i16) == 32767); |
| 753 | assert(maxInt(i63) == 4611686018427387903); | 767 | testing.expect(maxInt(i32) == 2147483647); |
| 754 | assert(maxInt(i64) == 9223372036854775807); | 768 | testing.expect(maxInt(i63) == 4611686018427387903); |
| 755 | 769 | testing.expect(maxInt(i64) == 9223372036854775807); | |
| 756 | assert(minInt(u0) == 0); | 770 | testing.expect(maxInt(i128) == 170141183460469231731687303715884105727); |
| 757 | assert(minInt(u1) == 0); | 771 | |
| 758 | assert(minInt(u8) == 0); | 772 | testing.expect(minInt(u0) == 0); |
| 759 | assert(minInt(u16) == 0); | 773 | testing.expect(minInt(u1) == 0); |
| 760 | assert(minInt(u32) == 0); | 774 | testing.expect(minInt(u8) == 0); |
| 761 | assert(minInt(u63) == 0); | 775 | testing.expect(minInt(u16) == 0); |
| 762 | assert(minInt(u64) == 0); | 776 | testing.expect(minInt(u32) == 0); |
| 763 | 777 | testing.expect(minInt(u63) == 0); | |
| 764 | assert(minInt(i0) == 0); | 778 | testing.expect(minInt(u64) == 0); |
| 765 | assert(minInt(i1) == -1); | 779 | testing.expect(minInt(u128) == 0); |
| 766 | assert(minInt(i8) == -128); | 780 | |
| 767 | assert(minInt(i16) == -32768); | 781 | testing.expect(minInt(i0) == 0); |
| 768 | assert(minInt(i32) == -2147483648); | 782 | testing.expect(minInt(i1) == -1); |
| 769 | assert(minInt(i63) == -4611686018427387904); | 783 | testing.expect(minInt(i8) == -128); |
| 770 | assert(minInt(i64) == -9223372036854775808); | 784 | testing.expect(minInt(i16) == -32768); |
| 785 | testing.expect(minInt(i32) == -2147483648); | ||
| 786 | testing.expect(minInt(i63) == -4611686018427387904); | ||
| 787 | testing.expect(minInt(i64) == -9223372036854775808); | ||
| 788 | testing.expect(minInt(i128) == -170141183460469231731687303715884105728); | ||
| 771 | } | 789 | } |
| 772 | 790 | ||
| 773 | test "max value type" { | 791 | test "max value type" { |
| ... | @@ -775,5 +793,5 @@ test "max value type" { | ... | @@ -775,5 +793,5 @@ test "max value type" { |
| 775 | // u32 would not work. But since the value is a number literal, | 793 | // u32 would not work. But since the value is a number literal, |
| 776 | // it works fine. | 794 | // it works fine. |
| 777 | const x: u32 = maxInt(i32); | 795 | const x: u32 = maxInt(i32); |
| 778 | assert(x == 2147483647); | 796 | testing.expect(x == 2147483647); |
| 779 | } | 797 | } |
std/math/inf.zig+4-3| ... | @@ -3,9 +3,10 @@ const math = std.math; | ... | @@ -3,9 +3,10 @@ const math = std.math; |
| 3 | 3 | ||
| 4 | pub fn inf(comptime T: type) T { | 4 | pub fn inf(comptime T: type) T { |
| 5 | return switch (T) { | 5 | return switch (T) { |
| 6 | f16 => @bitCast(f16, math.inf_u16), | 6 | f16 => math.inf_f16, |
| 7 | f32 => @bitCast(f32, math.inf_u32), | 7 | f32 => math.inf_f32, |
| 8 | f64 => @bitCast(f64, math.inf_u64), | 8 | f64 => math.inf_f64, |
| 9 | f128 => math.inf_f128, | ||
| 9 | else => @compileError("inf not implemented for " ++ @typeName(T)), | 10 | else => @compileError("inf not implemented for " ++ @typeName(T)), |
| 10 | }; | 11 | }; |
| 11 | } | 12 | } |
std/math/isfinite.zig+13-13| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | ||
| 6 | pub fn isFinite(x: var) bool { | 6 | pub fn isFinite(x: var) bool { |
| ... | @@ -25,16 +25,16 @@ pub fn isFinite(x: var) bool { | ... | @@ -25,16 +25,16 @@ pub fn isFinite(x: var) bool { |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | test "math.isFinite" { | 27 | test "math.isFinite" { |
| 28 | assert(isFinite(f16(0.0))); | 28 | expect(isFinite(f16(0.0))); |
| 29 | assert(isFinite(f16(-0.0))); | 29 | expect(isFinite(f16(-0.0))); |
| 30 | assert(isFinite(f32(0.0))); | 30 | expect(isFinite(f32(0.0))); |
| 31 | assert(isFinite(f32(-0.0))); | 31 | expect(isFinite(f32(-0.0))); |
| 32 | assert(isFinite(f64(0.0))); | 32 | expect(isFinite(f64(0.0))); |
| 33 | assert(isFinite(f64(-0.0))); | 33 | expect(isFinite(f64(-0.0))); |
| 34 | assert(!isFinite(math.inf(f16))); | 34 | expect(!isFinite(math.inf(f16))); |
| 35 | assert(!isFinite(-math.inf(f16))); | 35 | expect(!isFinite(-math.inf(f16))); |
| 36 | assert(!isFinite(math.inf(f32))); | 36 | expect(!isFinite(math.inf(f32))); |
| 37 | assert(!isFinite(-math.inf(f32))); | 37 | expect(!isFinite(-math.inf(f32))); |
| 38 | assert(!isFinite(math.inf(f64))); | 38 | expect(!isFinite(math.inf(f64))); |
| 39 | assert(!isFinite(-math.inf(f64))); | 39 | expect(!isFinite(-math.inf(f64))); |
| 40 | } | 40 | } |
std/math/isinf.zig+59-37| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | ||
| 6 | pub fn isInf(x: var) bool { | 6 | pub fn isInf(x: var) bool { |
| ... | @@ -18,6 +18,10 @@ pub fn isInf(x: var) bool { | ... | @@ -18,6 +18,10 @@ pub fn isInf(x: var) bool { |
| 18 | const bits = @bitCast(u64, x); | 18 | const bits = @bitCast(u64, x); |
| 19 | return bits & (maxInt(u64) >> 1) == (0x7FF << 52); | 19 | return bits & (maxInt(u64) >> 1) == (0x7FF << 52); |
| 20 | }, | 20 | }, |
| 21 | f128 => { | ||
| 22 | const bits = @bitCast(u128, x); | ||
| 23 | return bits & (maxInt(u128) >> 1) == (0x7FFF << 112); | ||
| 24 | }, | ||
| 21 | else => { | 25 | else => { |
| 22 | @compileError("isInf not implemented for " ++ @typeName(T)); | 26 | @compileError("isInf not implemented for " ++ @typeName(T)); |
| 23 | }, | 27 | }, |
| ... | @@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool { | ... | @@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool { |
| 36 | f64 => { | 40 | f64 => { |
| 37 | return @bitCast(u64, x) == 0x7FF << 52; | 41 | return @bitCast(u64, x) == 0x7FF << 52; |
| 38 | }, | 42 | }, |
| 43 | f128 => { | ||
| 44 | return @bitCast(u128, x) == 0x7FFF << 112; | ||
| 45 | }, | ||
| 39 | else => { | 46 | else => { |
| 40 | @compileError("isPositiveInf not implemented for " ++ @typeName(T)); | 47 | @compileError("isPositiveInf not implemented for " ++ @typeName(T)); |
| 41 | }, | 48 | }, |
| ... | @@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool { | ... | @@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool { |
| 54 | f64 => { | 61 | f64 => { |
| 55 | return @bitCast(u64, x) == 0xFFF << 52; | 62 | return @bitCast(u64, x) == 0xFFF << 52; |
| 56 | }, | 63 | }, |
| 64 | f128 => { | ||
| 65 | return @bitCast(u128, x) == 0xFFFF << 112; | ||
| 66 | }, | ||
| 57 | else => { | 67 | else => { |
| 58 | @compileError("isNegativeInf not implemented for " ++ @typeName(T)); | 68 | @compileError("isNegativeInf not implemented for " ++ @typeName(T)); |
| 59 | }, | 69 | }, |
| ... | @@ -61,46 +71,58 @@ pub fn isNegativeInf(x: var) bool { | ... | @@ -61,46 +71,58 @@ pub fn isNegativeInf(x: var) bool { |
| 61 | } | 71 | } |
| 62 | 72 | ||
| 63 | test "math.isInf" { | 73 | test "math.isInf" { |
| 64 | assert(!isInf(f16(0.0))); | 74 | expect(!isInf(f16(0.0))); |
| 65 | assert(!isInf(f16(-0.0))); | 75 | expect(!isInf(f16(-0.0))); |
| 66 | assert(!isInf(f32(0.0))); | 76 | expect(!isInf(f32(0.0))); |
| 67 | assert(!isInf(f32(-0.0))); | 77 | expect(!isInf(f32(-0.0))); |
| 68 | assert(!isInf(f64(0.0))); | 78 | expect(!isInf(f64(0.0))); |
| 69 | assert(!isInf(f64(-0.0))); | 79 | expect(!isInf(f64(-0.0))); |
| 70 | assert(isInf(math.inf(f16))); | 80 | expect(!isInf(f128(0.0))); |
| 71 | assert(isInf(-math.inf(f16))); | 81 | expect(!isInf(f128(-0.0))); |
| 72 | assert(isInf(math.inf(f32))); | 82 | expect(isInf(math.inf(f16))); |
| 73 | assert(isInf(-math.inf(f32))); | 83 | expect(isInf(-math.inf(f16))); |
| 74 | assert(isInf(math.inf(f64))); | 84 | expect(isInf(math.inf(f32))); |
| 75 | assert(isInf(-math.inf(f64))); | 85 | expect(isInf(-math.inf(f32))); |
| 86 | expect(isInf(math.inf(f64))); | ||
| 87 | expect(isInf(-math.inf(f64))); | ||
| 88 | expect(isInf(math.inf(f128))); | ||
| 89 | expect(isInf(-math.inf(f128))); | ||
| 76 | } | 90 | } |
| 77 | 91 | ||
| 78 | test "math.isPositiveInf" { | 92 | test "math.isPositiveInf" { |
| 79 | assert(!isPositiveInf(f16(0.0))); | 93 | expect(!isPositiveInf(f16(0.0))); |
| 80 | assert(!isPositiveInf(f16(-0.0))); | 94 | expect(!isPositiveInf(f16(-0.0))); |
| 81 | assert(!isPositiveInf(f32(0.0))); | 95 | expect(!isPositiveInf(f32(0.0))); |
| 82 | assert(!isPositiveInf(f32(-0.0))); | 96 | expect(!isPositiveInf(f32(-0.0))); |
| 83 | assert(!isPositiveInf(f64(0.0))); | 97 | expect(!isPositiveInf(f64(0.0))); |
| 84 | assert(!isPositiveInf(f64(-0.0))); | 98 | expect(!isPositiveInf(f64(-0.0))); |
| 85 | assert(isPositiveInf(math.inf(f16))); | 99 | expect(!isPositiveInf(f128(0.0))); |
| 86 | assert(!isPositiveInf(-math.inf(f16))); | 100 | expect(!isPositiveInf(f128(-0.0))); |
| 87 | assert(isPositiveInf(math.inf(f32))); | 101 | expect(isPositiveInf(math.inf(f16))); |
| 88 | assert(!isPositiveInf(-math.inf(f32))); | 102 | expect(!isPositiveInf(-math.inf(f16))); |
| 89 | assert(isPositiveInf(math.inf(f64))); | 103 | expect(isPositiveInf(math.inf(f32))); |
| 90 | assert(!isPositiveInf(-math.inf(f64))); | 104 | expect(!isPositiveInf(-math.inf(f32))); |
| 105 | expect(isPositiveInf(math.inf(f64))); | ||
| 106 | expect(!isPositiveInf(-math.inf(f64))); | ||
| 107 | expect(isPositiveInf(math.inf(f128))); | ||
| 108 | expect(!isPositiveInf(-math.inf(f128))); | ||
| 91 | } | 109 | } |
| 92 | 110 | ||
| 93 | test "math.isNegativeInf" { | 111 | test "math.isNegativeInf" { |
| 94 | assert(!isNegativeInf(f16(0.0))); | 112 | expect(!isNegativeInf(f16(0.0))); |
| 95 | assert(!isNegativeInf(f16(-0.0))); | 113 | expect(!isNegativeInf(f16(-0.0))); |
| 96 | assert(!isNegativeInf(f32(0.0))); | 114 | expect(!isNegativeInf(f32(0.0))); |
| 97 | assert(!isNegativeInf(f32(-0.0))); | 115 | expect(!isNegativeInf(f32(-0.0))); |
| 98 | assert(!isNegativeInf(f64(0.0))); | 116 | expect(!isNegativeInf(f64(0.0))); |
| 99 | assert(!isNegativeInf(f64(-0.0))); | 117 | expect(!isNegativeInf(f64(-0.0))); |
| 100 | assert(!isNegativeInf(math.inf(f16))); | 118 | expect(!isNegativeInf(f128(0.0))); |
| 101 | assert(isNegativeInf(-math.inf(f16))); | 119 | expect(!isNegativeInf(f128(-0.0))); |
| 102 | assert(!isNegativeInf(math.inf(f32))); | 120 | expect(!isNegativeInf(math.inf(f16))); |
| 103 | assert(isNegativeInf(-math.inf(f32))); | 121 | expect(isNegativeInf(-math.inf(f16))); |
| 104 | assert(!isNegativeInf(math.inf(f64))); | 122 | expect(!isNegativeInf(math.inf(f32))); |
| 105 | assert(isNegativeInf(-math.inf(f64))); | 123 | expect(isNegativeInf(-math.inf(f32))); |
| 124 | expect(!isNegativeInf(math.inf(f64))); | ||
| 125 | expect(isNegativeInf(-math.inf(f64))); | ||
| 126 | expect(!isNegativeInf(math.inf(f128))); | ||
| 127 | expect(isNegativeInf(-math.inf(f128))); | ||
| 106 | } | 128 | } |
std/math/isnan.zig+13-7| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | ||
| 6 | pub fn isNan(x: var) bool { | 6 | pub fn isNan(x: var) bool { |
| ... | @@ -18,6 +18,10 @@ pub fn isNan(x: var) bool { | ... | @@ -18,6 +18,10 @@ pub fn isNan(x: var) bool { |
| 18 | const bits = @bitCast(u64, x); | 18 | const bits = @bitCast(u64, x); |
| 19 | return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52); | 19 | return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52); |
| 20 | }, | 20 | }, |
| 21 | f128 => { | ||
| 22 | const bits = @bitCast(u128, x); | ||
| 23 | return (bits & (maxInt(u128) >> 1)) > (u128(0x7FFF) << 112); | ||
| 24 | }, | ||
| 21 | else => { | 25 | else => { |
| 22 | @compileError("isNan not implemented for " ++ @typeName(T)); | 26 | @compileError("isNan not implemented for " ++ @typeName(T)); |
| 23 | }, | 27 | }, |
| ... | @@ -31,10 +35,12 @@ pub fn isSignalNan(x: var) bool { | ... | @@ -31,10 +35,12 @@ pub fn isSignalNan(x: var) bool { |
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | test "math.isNan" { | 37 | test "math.isNan" { |
| 34 | assert(isNan(math.nan(f16))); | 38 | expect(isNan(math.nan(f16))); |
| 35 | assert(isNan(math.nan(f32))); | 39 | expect(isNan(math.nan(f32))); |
| 36 | assert(isNan(math.nan(f64))); | 40 | expect(isNan(math.nan(f64))); |
| 37 | assert(!isNan(f16(1.0))); | 41 | expect(isNan(math.nan(f128))); |
| 38 | assert(!isNan(f32(1.0))); | 42 | expect(!isNan(f16(1.0))); |
| 39 | assert(!isNan(f64(1.0))); | 43 | expect(!isNan(f32(1.0))); |
| 44 | expect(!isNan(f64(1.0))); | ||
| 45 | expect(!isNan(f128(1.0))); | ||
| 40 | } | 46 | } |
std/math/isnormal.zig+10-10| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| 5 | 5 | ||
| 6 | pub fn isNormal(x: var) bool { | 6 | pub fn isNormal(x: var) bool { |
| ... | @@ -25,13 +25,13 @@ pub fn isNormal(x: var) bool { | ... | @@ -25,13 +25,13 @@ pub fn isNormal(x: var) bool { |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | test "math.isNormal" { | 27 | test "math.isNormal" { |
| 28 | assert(!isNormal(math.nan(f16))); | 28 | expect(!isNormal(math.nan(f16))); |
| 29 | assert(!isNormal(math.nan(f32))); | 29 | expect(!isNormal(math.nan(f32))); |
| 30 | assert(!isNormal(math.nan(f64))); | 30 | expect(!isNormal(math.nan(f64))); |
| 31 | assert(!isNormal(f16(0))); | 31 | expect(!isNormal(f16(0))); |
| 32 | assert(!isNormal(f32(0))); | 32 | expect(!isNormal(f32(0))); |
| 33 | assert(!isNormal(f64(0))); | 33 | expect(!isNormal(f64(0))); |
| 34 | assert(isNormal(f16(1.0))); | 34 | expect(isNormal(f16(1.0))); |
| 35 | assert(isNormal(f32(1.0))); | 35 | expect(isNormal(f32(1.0))); |
| 36 | assert(isNormal(f64(1.0))); | 36 | expect(isNormal(f64(1.0))); |
| 37 | } | 37 | } |
std/math/ln.zig+23-23| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | const builtin = @import("builtin"); | 11 | const builtin = @import("builtin"); |
| 12 | const TypeId = builtin.TypeId; | 12 | const TypeId = builtin.TypeId; |
| 13 | 13 | ||
| ... | @@ -143,42 +143,42 @@ pub fn ln_64(x_: f64) f64 { | ... | @@ -143,42 +143,42 @@ pub fn ln_64(x_: f64) f64 { |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | test "math.ln" { | 145 | test "math.ln" { |
| 146 | assert(ln(f32(0.2)) == ln_32(0.2)); | 146 | expect(ln(f32(0.2)) == ln_32(0.2)); |
| 147 | assert(ln(f64(0.2)) == ln_64(0.2)); | 147 | expect(ln(f64(0.2)) == ln_64(0.2)); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | test "math.ln32" { | 150 | test "math.ln32" { |
| 151 | const epsilon = 0.000001; | 151 | const epsilon = 0.000001; |
| 152 | 152 | ||
| 153 | assert(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon)); | 153 | expect(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon)); |
| 154 | assert(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon)); | 154 | expect(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon)); |
| 155 | assert(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon)); | 155 | expect(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon)); |
| 156 | assert(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon)); | 156 | expect(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon)); |
| 157 | assert(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon)); | 157 | expect(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon)); |
| 158 | assert(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon)); | 158 | expect(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon)); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | test "math.ln64" { | 161 | test "math.ln64" { |
| 162 | const epsilon = 0.000001; | 162 | const epsilon = 0.000001; |
| 163 | 163 | ||
| 164 | assert(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon)); | 164 | expect(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon)); |
| 165 | assert(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon)); | 165 | expect(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon)); |
| 166 | assert(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon)); | 166 | expect(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon)); |
| 167 | assert(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon)); | 167 | expect(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon)); |
| 168 | assert(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon)); | 168 | expect(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon)); |
| 169 | assert(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon)); | 169 | expect(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon)); |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | test "math.ln32.special" { | 172 | test "math.ln32.special" { |
| 173 | assert(math.isPositiveInf(ln_32(math.inf(f32)))); | 173 | expect(math.isPositiveInf(ln_32(math.inf(f32)))); |
| 174 | assert(math.isNegativeInf(ln_32(0.0))); | 174 | expect(math.isNegativeInf(ln_32(0.0))); |
| 175 | assert(math.isNan(ln_32(-1.0))); | 175 | expect(math.isNan(ln_32(-1.0))); |
| 176 | assert(math.isNan(ln_32(math.nan(f32)))); | 176 | expect(math.isNan(ln_32(math.nan(f32)))); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | test "math.ln64.special" { | 179 | test "math.ln64.special" { |
| 180 | assert(math.isPositiveInf(ln_64(math.inf(f64)))); | 180 | expect(math.isPositiveInf(ln_64(math.inf(f64)))); |
| 181 | assert(math.isNegativeInf(ln_64(0.0))); | 181 | expect(math.isNegativeInf(ln_64(0.0))); |
| 182 | assert(math.isNan(ln_64(-1.0))); | 182 | expect(math.isNan(ln_64(-1.0))); |
| 183 | assert(math.isNan(ln_64(math.nan(f64)))); | 183 | expect(math.isNan(ln_64(math.nan(f64)))); |
| 184 | } | 184 | } |
std/math/log.zig+13-13| ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const TypeId = builtin.TypeId; | 4 | const TypeId = builtin.TypeId; |
| 5 | const assert = std.debug.assert; | 5 | const expect = std.testing.expect; |
| 6 | 6 | ||
| 7 | pub fn log(comptime T: type, base: T, x: T) T { | 7 | pub fn log(comptime T: type, base: T, x: T) T { |
| 8 | if (base == 2) { | 8 | if (base == 2) { |
| ... | @@ -41,25 +41,25 @@ pub fn log(comptime T: type, base: T, x: T) T { | ... | @@ -41,25 +41,25 @@ pub fn log(comptime T: type, base: T, x: T) T { |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | test "math.log integer" { | 43 | test "math.log integer" { |
| 44 | assert(log(u8, 2, 0x1) == 0); | 44 | expect(log(u8, 2, 0x1) == 0); |
| 45 | assert(log(u8, 2, 0x2) == 1); | 45 | expect(log(u8, 2, 0x2) == 1); |
| 46 | assert(log(i16, 2, 0x72) == 6); | 46 | expect(log(i16, 2, 0x72) == 6); |
| 47 | assert(log(u32, 2, 0xFFFFFF) == 23); | 47 | expect(log(u32, 2, 0xFFFFFF) == 23); |
| 48 | assert(log(u64, 2, 0x7FF0123456789ABC) == 62); | 48 | expect(log(u64, 2, 0x7FF0123456789ABC) == 62); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | test "math.log float" { | 51 | test "math.log float" { |
| 52 | const epsilon = 0.000001; | 52 | const epsilon = 0.000001; |
| 53 | 53 | ||
| 54 | assert(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon)); | 54 | expect(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon)); |
| 55 | assert(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon)); | 55 | expect(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon)); |
| 56 | assert(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon)); | 56 | expect(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | test "math.log float_special" { | 59 | test "math.log float_special" { |
| 60 | assert(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974))); | 60 | expect(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974))); |
| 61 | assert(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974))); | 61 | expect(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974))); |
| 62 | 62 | ||
| 63 | assert(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993))); | 63 | expect(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993))); |
| 64 | assert(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993))); | 64 | expect(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993))); |
| 65 | } | 65 | } |
std/math/log10.zig+23-23| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const testing = std.testing; |
| 11 | const builtin = @import("builtin"); | 11 | const builtin = @import("builtin"); |
| 12 | const TypeId = builtin.TypeId; | 12 | const TypeId = builtin.TypeId; |
| 13 | const maxInt = std.math.maxInt; | 13 | const maxInt = std.math.maxInt; |
| ... | @@ -171,42 +171,42 @@ pub fn log10_64(x_: f64) f64 { | ... | @@ -171,42 +171,42 @@ pub fn log10_64(x_: f64) f64 { |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | test "math.log10" { | 173 | test "math.log10" { |
| 174 | assert(log10(f32(0.2)) == log10_32(0.2)); | 174 | testing.expect(log10(f32(0.2)) == log10_32(0.2)); |
| 175 | assert(log10(f64(0.2)) == log10_64(0.2)); | 175 | testing.expect(log10(f64(0.2)) == log10_64(0.2)); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | test "math.log10_32" { | 178 | test "math.log10_32" { |
| 179 | const epsilon = 0.000001; | 179 | const epsilon = 0.000001; |
| 180 | 180 | ||
| 181 | assert(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon)); | 181 | testing.expect(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon)); |
| 182 | assert(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon)); | 182 | testing.expect(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon)); |
| 183 | assert(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon)); | 183 | testing.expect(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon)); |
| 184 | assert(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon)); | 184 | testing.expect(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon)); |
| 185 | assert(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon)); | 185 | testing.expect(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon)); |
| 186 | assert(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon)); | 186 | testing.expect(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon)); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | test "math.log10_64" { | 189 | test "math.log10_64" { |
| 190 | const epsilon = 0.000001; | 190 | const epsilon = 0.000001; |
| 191 | 191 | ||
| 192 | assert(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon)); | 192 | testing.expect(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon)); |
| 193 | assert(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon)); | 193 | testing.expect(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon)); |
| 194 | assert(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon)); | 194 | testing.expect(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon)); |
| 195 | assert(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon)); | 195 | testing.expect(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon)); |
| 196 | assert(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon)); | 196 | testing.expect(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon)); |
| 197 | assert(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon)); | 197 | testing.expect(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon)); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | test "math.log10_32.special" { | 200 | test "math.log10_32.special" { |
| 201 | assert(math.isPositiveInf(log10_32(math.inf(f32)))); | 201 | testing.expect(math.isPositiveInf(log10_32(math.inf(f32)))); |
| 202 | assert(math.isNegativeInf(log10_32(0.0))); | 202 | testing.expect(math.isNegativeInf(log10_32(0.0))); |
| 203 | assert(math.isNan(log10_32(-1.0))); | 203 | testing.expect(math.isNan(log10_32(-1.0))); |
| 204 | assert(math.isNan(log10_32(math.nan(f32)))); | 204 | testing.expect(math.isNan(log10_32(math.nan(f32)))); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | test "math.log10_64.special" { | 207 | test "math.log10_64.special" { |
| 208 | assert(math.isPositiveInf(log10_64(math.inf(f64)))); | 208 | testing.expect(math.isPositiveInf(log10_64(math.inf(f64)))); |
| 209 | assert(math.isNegativeInf(log10_64(0.0))); | 209 | testing.expect(math.isNegativeInf(log10_64(0.0))); |
| 210 | assert(math.isNan(log10_64(-1.0))); | 210 | testing.expect(math.isNan(log10_64(-1.0))); |
| 211 | assert(math.isNan(log10_64(math.nan(f64)))); | 211 | testing.expect(math.isNan(log10_64(math.nan(f64)))); |
| 212 | } | 212 | } |
std/math/log1p.zig+29-29| ... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
| 9 | const builtin = @import("builtin"); | 9 | const builtin = @import("builtin"); |
| 10 | const std = @import("../index.zig"); | 10 | const std = @import("../index.zig"); |
| 11 | const math = std.math; | 11 | const math = std.math; |
| 12 | const assert = std.debug.assert; | 12 | const expect = std.testing.expect; |
| 13 | 13 | ||
| 14 | pub fn log1p(x: var) @typeOf(x) { | 14 | pub fn log1p(x: var) @typeOf(x) { |
| 15 | const T = @typeOf(x); | 15 | const T = @typeOf(x); |
| ... | @@ -177,48 +177,48 @@ fn log1p_64(x: f64) f64 { | ... | @@ -177,48 +177,48 @@ fn log1p_64(x: f64) f64 { |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | test "math.log1p" { | 179 | test "math.log1p" { |
| 180 | assert(log1p(f32(0.0)) == log1p_32(0.0)); | 180 | expect(log1p(f32(0.0)) == log1p_32(0.0)); |
| 181 | assert(log1p(f64(0.0)) == log1p_64(0.0)); | 181 | expect(log1p(f64(0.0)) == log1p_64(0.0)); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | test "math.log1p_32" { | 184 | test "math.log1p_32" { |
| 185 | const epsilon = 0.000001; | 185 | const epsilon = 0.000001; |
| 186 | 186 | ||
| 187 | assert(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon)); | 187 | expect(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon)); |
| 188 | assert(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon)); | 188 | expect(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon)); |
| 189 | assert(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon)); | 189 | expect(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon)); |
| 190 | assert(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon)); | 190 | expect(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon)); |
| 191 | assert(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon)); | 191 | expect(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon)); |
| 192 | assert(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon)); | 192 | expect(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon)); |
| 193 | assert(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon)); | 193 | expect(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon)); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | test "math.log1p_64" { | 196 | test "math.log1p_64" { |
| 197 | const epsilon = 0.000001; | 197 | const epsilon = 0.000001; |
| 198 | 198 | ||
| 199 | assert(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon)); | 199 | expect(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon)); |
| 200 | assert(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon)); | 200 | expect(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon)); |
| 201 | assert(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon)); | 201 | expect(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon)); |
| 202 | assert(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon)); | 202 | expect(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon)); |
| 203 | assert(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon)); | 203 | expect(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon)); |
| 204 | assert(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon)); | 204 | expect(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon)); |
| 205 | assert(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon)); | 205 | expect(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon)); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | test "math.log1p_32.special" { | 208 | test "math.log1p_32.special" { |
| 209 | assert(math.isPositiveInf(log1p_32(math.inf(f32)))); | 209 | expect(math.isPositiveInf(log1p_32(math.inf(f32)))); |
| 210 | assert(log1p_32(0.0) == 0.0); | 210 | expect(log1p_32(0.0) == 0.0); |
| 211 | assert(log1p_32(-0.0) == -0.0); | 211 | expect(log1p_32(-0.0) == -0.0); |
| 212 | assert(math.isNegativeInf(log1p_32(-1.0))); | 212 | expect(math.isNegativeInf(log1p_32(-1.0))); |
| 213 | assert(math.isNan(log1p_32(-2.0))); | 213 | expect(math.isNan(log1p_32(-2.0))); |
| 214 | assert(math.isNan(log1p_32(math.nan(f32)))); | 214 | expect(math.isNan(log1p_32(math.nan(f32)))); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | test "math.log1p_64.special" { | 217 | test "math.log1p_64.special" { |
| 218 | assert(math.isPositiveInf(log1p_64(math.inf(f64)))); | 218 | expect(math.isPositiveInf(log1p_64(math.inf(f64)))); |
| 219 | assert(log1p_64(0.0) == 0.0); | 219 | expect(log1p_64(0.0) == 0.0); |
| 220 | assert(log1p_64(-0.0) == -0.0); | 220 | expect(log1p_64(-0.0) == -0.0); |
| 221 | assert(math.isNegativeInf(log1p_64(-1.0))); | 221 | expect(math.isNegativeInf(log1p_64(-1.0))); |
| 222 | assert(math.isNan(log1p_64(-2.0))); | 222 | expect(math.isNan(log1p_64(-2.0))); |
| 223 | assert(math.isNan(log1p_64(math.nan(f64)))); | 223 | expect(math.isNan(log1p_64(math.nan(f64)))); |
| 224 | } | 224 | } |
std/math/log2.zig+21-21| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | const builtin = @import("builtin"); | 11 | const builtin = @import("builtin"); |
| 12 | const TypeId = builtin.TypeId; | 12 | const TypeId = builtin.TypeId; |
| 13 | const maxInt = std.math.maxInt; | 13 | const maxInt = std.math.maxInt; |
| ... | @@ -169,40 +169,40 @@ pub fn log2_64(x_: f64) f64 { | ... | @@ -169,40 +169,40 @@ pub fn log2_64(x_: f64) f64 { |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | test "math.log2" { | 171 | test "math.log2" { |
| 172 | assert(log2(f32(0.2)) == log2_32(0.2)); | 172 | expect(log2(f32(0.2)) == log2_32(0.2)); |
| 173 | assert(log2(f64(0.2)) == log2_64(0.2)); | 173 | expect(log2(f64(0.2)) == log2_64(0.2)); |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | test "math.log2_32" { | 176 | test "math.log2_32" { |
| 177 | const epsilon = 0.000001; | 177 | const epsilon = 0.000001; |
| 178 | 178 | ||
| 179 | assert(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon)); | 179 | expect(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon)); |
| 180 | assert(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon)); | 180 | expect(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon)); |
| 181 | assert(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon)); | 181 | expect(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon)); |
| 182 | assert(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon)); | 182 | expect(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon)); |
| 183 | assert(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon)); | 183 | expect(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon)); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | test "math.log2_64" { | 186 | test "math.log2_64" { |
| 187 | const epsilon = 0.000001; | 187 | const epsilon = 0.000001; |
| 188 | 188 | ||
| 189 | assert(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon)); | 189 | expect(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon)); |
| 190 | assert(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon)); | 190 | expect(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon)); |
| 191 | assert(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon)); | 191 | expect(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon)); |
| 192 | assert(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon)); | 192 | expect(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon)); |
| 193 | assert(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon)); | 193 | expect(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon)); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | test "math.log2_32.special" { | 196 | test "math.log2_32.special" { |
| 197 | assert(math.isPositiveInf(log2_32(math.inf(f32)))); | 197 | expect(math.isPositiveInf(log2_32(math.inf(f32)))); |
| 198 | assert(math.isNegativeInf(log2_32(0.0))); | 198 | expect(math.isNegativeInf(log2_32(0.0))); |
| 199 | assert(math.isNan(log2_32(-1.0))); | 199 | expect(math.isNan(log2_32(-1.0))); |
| 200 | assert(math.isNan(log2_32(math.nan(f32)))); | 200 | expect(math.isNan(log2_32(math.nan(f32)))); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | test "math.log2_64.special" { | 203 | test "math.log2_64.special" { |
| 204 | assert(math.isPositiveInf(log2_64(math.inf(f64)))); | 204 | expect(math.isPositiveInf(log2_64(math.inf(f64)))); |
| 205 | assert(math.isNegativeInf(log2_64(0.0))); | 205 | expect(math.isNegativeInf(log2_64(0.0))); |
| 206 | assert(math.isNan(log2_64(-1.0))); | 206 | expect(math.isNan(log2_64(-1.0))); |
| 207 | assert(math.isNan(log2_64(math.nan(f64)))); | 207 | expect(math.isNan(log2_64(math.nan(f64)))); |
| 208 | } | 208 | } |
std/math/modf.zig+29-29| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ||
| 6 | const std = @import("../index.zig"); | 6 | const std = @import("../index.zig"); |
| 7 | const math = std.math; | 7 | const math = std.math; |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| 10 | 10 | ||
| 11 | fn modf_result(comptime T: type) type { | 11 | fn modf_result(comptime T: type) type { |
| ... | @@ -119,11 +119,11 @@ test "math.modf" { | ... | @@ -119,11 +119,11 @@ test "math.modf" { |
| 119 | const a = modf(f32(1.0)); | 119 | const a = modf(f32(1.0)); |
| 120 | const b = modf32(1.0); | 120 | const b = modf32(1.0); |
| 121 | // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still. | 121 | // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still. |
| 122 | assert(a.ipart == b.ipart and a.fpart == b.fpart); | 122 | expect(a.ipart == b.ipart and a.fpart == b.fpart); |
| 123 | 123 | ||
| 124 | const c = modf(f64(1.0)); | 124 | const c = modf(f64(1.0)); |
| 125 | const d = modf64(1.0); | 125 | const d = modf64(1.0); |
| 126 | assert(a.ipart == b.ipart and a.fpart == b.fpart); | 126 | expect(a.ipart == b.ipart and a.fpart == b.fpart); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | test "math.modf32" { | 129 | test "math.modf32" { |
| ... | @@ -131,24 +131,24 @@ test "math.modf32" { | ... | @@ -131,24 +131,24 @@ test "math.modf32" { |
| 131 | var r: modf32_result = undefined; | 131 | var r: modf32_result = undefined; |
| 132 | 132 | ||
| 133 | r = modf32(1.0); | 133 | r = modf32(1.0); |
| 134 | assert(math.approxEq(f32, r.ipart, 1.0, epsilon)); | 134 | expect(math.approxEq(f32, r.ipart, 1.0, epsilon)); |
| 135 | assert(math.approxEq(f32, r.fpart, 0.0, epsilon)); | 135 | expect(math.approxEq(f32, r.fpart, 0.0, epsilon)); |
| 136 | 136 | ||
| 137 | r = modf32(2.545); | 137 | r = modf32(2.545); |
| 138 | assert(math.approxEq(f32, r.ipart, 2.0, epsilon)); | 138 | expect(math.approxEq(f32, r.ipart, 2.0, epsilon)); |
| 139 | assert(math.approxEq(f32, r.fpart, 0.545, epsilon)); | 139 | expect(math.approxEq(f32, r.fpart, 0.545, epsilon)); |
| 140 | 140 | ||
| 141 | r = modf32(3.978123); | 141 | r = modf32(3.978123); |
| 142 | assert(math.approxEq(f32, r.ipart, 3.0, epsilon)); | 142 | expect(math.approxEq(f32, r.ipart, 3.0, epsilon)); |
| 143 | assert(math.approxEq(f32, r.fpart, 0.978123, epsilon)); | 143 | expect(math.approxEq(f32, r.fpart, 0.978123, epsilon)); |
| 144 | 144 | ||
| 145 | r = modf32(43874.3); | 145 | r = modf32(43874.3); |
| 146 | assert(math.approxEq(f32, r.ipart, 43874, epsilon)); | 146 | expect(math.approxEq(f32, r.ipart, 43874, epsilon)); |
| 147 | assert(math.approxEq(f32, r.fpart, 0.300781, epsilon)); | 147 | expect(math.approxEq(f32, r.fpart, 0.300781, epsilon)); |
| 148 | 148 | ||
| 149 | r = modf32(1234.340780); | 149 | r = modf32(1234.340780); |
| 150 | assert(math.approxEq(f32, r.ipart, 1234, epsilon)); | 150 | expect(math.approxEq(f32, r.ipart, 1234, epsilon)); |
| 151 | assert(math.approxEq(f32, r.fpart, 0.340820, epsilon)); | 151 | expect(math.approxEq(f32, r.fpart, 0.340820, epsilon)); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | test "math.modf64" { | 154 | test "math.modf64" { |
| ... | @@ -156,48 +156,48 @@ test "math.modf64" { | ... | @@ -156,48 +156,48 @@ test "math.modf64" { |
| 156 | var r: modf64_result = undefined; | 156 | var r: modf64_result = undefined; |
| 157 | 157 | ||
| 158 | r = modf64(1.0); | 158 | r = modf64(1.0); |
| 159 | assert(math.approxEq(f64, r.ipart, 1.0, epsilon)); | 159 | expect(math.approxEq(f64, r.ipart, 1.0, epsilon)); |
| 160 | assert(math.approxEq(f64, r.fpart, 0.0, epsilon)); | 160 | expect(math.approxEq(f64, r.fpart, 0.0, epsilon)); |
| 161 | 161 | ||
| 162 | r = modf64(2.545); | 162 | r = modf64(2.545); |
| 163 | assert(math.approxEq(f64, r.ipart, 2.0, epsilon)); | 163 | expect(math.approxEq(f64, r.ipart, 2.0, epsilon)); |
| 164 | assert(math.approxEq(f64, r.fpart, 0.545, epsilon)); | 164 | expect(math.approxEq(f64, r.fpart, 0.545, epsilon)); |
| 165 | 165 | ||
| 166 | r = modf64(3.978123); | 166 | r = modf64(3.978123); |
| 167 | assert(math.approxEq(f64, r.ipart, 3.0, epsilon)); | 167 | expect(math.approxEq(f64, r.ipart, 3.0, epsilon)); |
| 168 | assert(math.approxEq(f64, r.fpart, 0.978123, epsilon)); | 168 | expect(math.approxEq(f64, r.fpart, 0.978123, epsilon)); |
| 169 | 169 | ||
| 170 | r = modf64(43874.3); | 170 | r = modf64(43874.3); |
| 171 | assert(math.approxEq(f64, r.ipart, 43874, epsilon)); | 171 | expect(math.approxEq(f64, r.ipart, 43874, epsilon)); |
| 172 | assert(math.approxEq(f64, r.fpart, 0.3, epsilon)); | 172 | expect(math.approxEq(f64, r.fpart, 0.3, epsilon)); |
| 173 | 173 | ||
| 174 | r = modf64(1234.340780); | 174 | r = modf64(1234.340780); |
| 175 | assert(math.approxEq(f64, r.ipart, 1234, epsilon)); | 175 | expect(math.approxEq(f64, r.ipart, 1234, epsilon)); |
| 176 | assert(math.approxEq(f64, r.fpart, 0.340780, epsilon)); | 176 | expect(math.approxEq(f64, r.fpart, 0.340780, epsilon)); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | test "math.modf32.special" { | 179 | test "math.modf32.special" { |
| 180 | var r: modf32_result = undefined; | 180 | var r: modf32_result = undefined; |
| 181 | 181 | ||
| 182 | r = modf32(math.inf(f32)); | 182 | r = modf32(math.inf(f32)); |
| 183 | assert(math.isPositiveInf(r.ipart) and math.isNan(r.fpart)); | 183 | expect(math.isPositiveInf(r.ipart) and math.isNan(r.fpart)); |
| 184 | 184 | ||
| 185 | r = modf32(-math.inf(f32)); | 185 | r = modf32(-math.inf(f32)); |
| 186 | assert(math.isNegativeInf(r.ipart) and math.isNan(r.fpart)); | 186 | expect(math.isNegativeInf(r.ipart) and math.isNan(r.fpart)); |
| 187 | 187 | ||
| 188 | r = modf32(math.nan(f32)); | 188 | r = modf32(math.nan(f32)); |
| 189 | assert(math.isNan(r.ipart) and math.isNan(r.fpart)); | 189 | expect(math.isNan(r.ipart) and math.isNan(r.fpart)); |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | test "math.modf64.special" { | 192 | test "math.modf64.special" { |
| 193 | var r: modf64_result = undefined; | 193 | var r: modf64_result = undefined; |
| 194 | 194 | ||
| 195 | r = modf64(math.inf(f64)); | 195 | r = modf64(math.inf(f64)); |
| 196 | assert(math.isPositiveInf(r.ipart) and math.isNan(r.fpart)); | 196 | expect(math.isPositiveInf(r.ipart) and math.isNan(r.fpart)); |
| 197 | 197 | ||
| 198 | r = modf64(-math.inf(f64)); | 198 | r = modf64(-math.inf(f64)); |
| 199 | assert(math.isNegativeInf(r.ipart) and math.isNan(r.fpart)); | 199 | expect(math.isNegativeInf(r.ipart) and math.isNan(r.fpart)); |
| 200 | 200 | ||
| 201 | r = modf64(math.nan(f64)); | 201 | r = modf64(math.nan(f64)); |
| 202 | assert(math.isNan(r.ipart) and math.isNan(r.fpart)); | 202 | expect(math.isNan(r.ipart) and math.isNan(r.fpart)); |
| 203 | } | 203 | } |
std/math/nan.zig+4-3| ... | @@ -2,9 +2,10 @@ const math = @import("index.zig"); | ... | @@ -2,9 +2,10 @@ const math = @import("index.zig"); |
| 2 | 2 | ||
| 3 | pub fn nan(comptime T: type) T { | 3 | pub fn nan(comptime T: type) T { |
| 4 | return switch (T) { | 4 | return switch (T) { |
| 5 | f16 => @bitCast(f16, math.nan_u16), | 5 | f16 => math.nan_f16, |
| 6 | f32 => @bitCast(f32, math.nan_u32), | 6 | f32 => math.nan_f32, |
| 7 | f64 => @bitCast(f64, math.nan_u64), | 7 | f64 => math.nan_f64, |
| 8 | f128 => math.nan_f128, | ||
| 8 | else => @compileError("nan not implemented for " ++ @typeName(T)), | 9 | else => @compileError("nan not implemented for " ++ @typeName(T)), |
| 9 | }; | 10 | }; |
| 10 | } | 11 | } |
std/math/pow.zig+48-48| ... | @@ -24,7 +24,7 @@ | ... | @@ -24,7 +24,7 @@ |
| 24 | const builtin = @import("builtin"); | 24 | const builtin = @import("builtin"); |
| 25 | const std = @import("../index.zig"); | 25 | const std = @import("../index.zig"); |
| 26 | const math = std.math; | 26 | const math = std.math; |
| 27 | const assert = std.debug.assert; | 27 | const expect = std.testing.expect; |
| 28 | 28 | ||
| 29 | // This implementation is taken from the go stlib, musl is a bit more complex. | 29 | // This implementation is taken from the go stlib, musl is a bit more complex. |
| 30 | pub fn pow(comptime T: type, x: T, y: T) T { | 30 | pub fn pow(comptime T: type, x: T, y: T) T { |
| ... | @@ -179,56 +179,56 @@ fn isOddInteger(x: f64) bool { | ... | @@ -179,56 +179,56 @@ fn isOddInteger(x: f64) bool { |
| 179 | test "math.pow" { | 179 | test "math.pow" { |
| 180 | const epsilon = 0.000001; | 180 | const epsilon = 0.000001; |
| 181 | 181 | ||
| 182 | assert(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon)); | 182 | expect(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon)); |
| 183 | assert(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon)); | 183 | expect(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon)); |
| 184 | assert(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon)); | 184 | expect(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon)); |
| 185 | assert(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon)); | 185 | expect(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon)); |
| 186 | assert(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon)); | 186 | expect(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon)); |
| 187 | assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon)); | 187 | expect(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon)); |
| 188 | 188 | ||
| 189 | assert(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon)); | 189 | expect(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon)); |
| 190 | assert(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon)); | 190 | expect(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon)); |
| 191 | assert(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon)); | 191 | expect(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon)); |
| 192 | assert(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon)); | 192 | expect(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon)); |
| 193 | assert(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon)); | 193 | expect(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon)); |
| 194 | assert(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon)); | 194 | expect(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon)); |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | test "math.pow.special" { | 197 | test "math.pow.special" { |
| 198 | const epsilon = 0.000001; | 198 | const epsilon = 0.000001; |
| 199 | 199 | ||
| 200 | assert(pow(f32, 4, 0.0) == 1.0); | 200 | expect(pow(f32, 4, 0.0) == 1.0); |
| 201 | assert(pow(f32, 7, -0.0) == 1.0); | 201 | expect(pow(f32, 7, -0.0) == 1.0); |
| 202 | assert(pow(f32, 45, 1.0) == 45); | 202 | expect(pow(f32, 45, 1.0) == 45); |
| 203 | assert(pow(f32, -45, 1.0) == -45); | 203 | expect(pow(f32, -45, 1.0) == -45); |
| 204 | assert(math.isNan(pow(f32, math.nan(f32), 5.0))); | 204 | expect(math.isNan(pow(f32, math.nan(f32), 5.0))); |
| 205 | assert(math.isNan(pow(f32, 5.0, math.nan(f32)))); | 205 | expect(math.isNan(pow(f32, 5.0, math.nan(f32)))); |
| 206 | assert(math.isPositiveInf(pow(f32, 0.0, -1.0))); | 206 | expect(math.isPositiveInf(pow(f32, 0.0, -1.0))); |
| 207 | //assert(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required? | 207 | //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required? |
| 208 | assert(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32)))); | 208 | expect(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32)))); |
| 209 | assert(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32)))); | 209 | expect(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32)))); |
| 210 | assert(pow(f32, 0.0, math.inf(f32)) == 0.0); | 210 | expect(pow(f32, 0.0, math.inf(f32)) == 0.0); |
| 211 | assert(pow(f32, -0.0, math.inf(f32)) == 0.0); | 211 | expect(pow(f32, -0.0, math.inf(f32)) == 0.0); |
| 212 | assert(math.isPositiveInf(pow(f32, 0.0, -2.0))); | 212 | expect(math.isPositiveInf(pow(f32, 0.0, -2.0))); |
| 213 | assert(math.isPositiveInf(pow(f32, -0.0, -2.0))); | 213 | expect(math.isPositiveInf(pow(f32, -0.0, -2.0))); |
| 214 | assert(pow(f32, 0.0, 1.0) == 0.0); | 214 | expect(pow(f32, 0.0, 1.0) == 0.0); |
| 215 | assert(pow(f32, -0.0, 1.0) == -0.0); | 215 | expect(pow(f32, -0.0, 1.0) == -0.0); |
| 216 | assert(pow(f32, 0.0, 2.0) == 0.0); | 216 | expect(pow(f32, 0.0, 2.0) == 0.0); |
| 217 | assert(pow(f32, -0.0, 2.0) == 0.0); | 217 | expect(pow(f32, -0.0, 2.0) == 0.0); |
| 218 | assert(math.approxEq(f32, pow(f32, -1.0, math.inf(f32)), 1.0, epsilon)); | 218 | expect(math.approxEq(f32, pow(f32, -1.0, math.inf(f32)), 1.0, epsilon)); |
| 219 | assert(math.approxEq(f32, pow(f32, -1.0, -math.inf(f32)), 1.0, epsilon)); | 219 | expect(math.approxEq(f32, pow(f32, -1.0, -math.inf(f32)), 1.0, epsilon)); |
| 220 | assert(math.isPositiveInf(pow(f32, 1.2, math.inf(f32)))); | 220 | expect(math.isPositiveInf(pow(f32, 1.2, math.inf(f32)))); |
| 221 | assert(math.isPositiveInf(pow(f32, -1.2, math.inf(f32)))); | 221 | expect(math.isPositiveInf(pow(f32, -1.2, math.inf(f32)))); |
| 222 | assert(pow(f32, 1.2, -math.inf(f32)) == 0.0); | 222 | expect(pow(f32, 1.2, -math.inf(f32)) == 0.0); |
| 223 | assert(pow(f32, -1.2, -math.inf(f32)) == 0.0); | 223 | expect(pow(f32, -1.2, -math.inf(f32)) == 0.0); |
| 224 | assert(pow(f32, 0.2, math.inf(f32)) == 0.0); | 224 | expect(pow(f32, 0.2, math.inf(f32)) == 0.0); |
| 225 | assert(pow(f32, -0.2, math.inf(f32)) == 0.0); | 225 | expect(pow(f32, -0.2, math.inf(f32)) == 0.0); |
| 226 | assert(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32)))); | 226 | expect(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32)))); |
| 227 | assert(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32)))); | 227 | expect(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32)))); |
| 228 | assert(math.isPositiveInf(pow(f32, math.inf(f32), 1.0))); | 228 | expect(math.isPositiveInf(pow(f32, math.inf(f32), 1.0))); |
| 229 | assert(pow(f32, math.inf(f32), -1.0) == 0.0); | 229 | expect(pow(f32, math.inf(f32), -1.0) == 0.0); |
| 230 | //assert(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0? | 230 | //expect(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0? |
| 231 | assert(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2)); | 231 | expect(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2)); |
| 232 | assert(math.isNan(pow(f32, -1.0, 1.2))); | 232 | expect(math.isNan(pow(f32, -1.0, 1.2))); |
| 233 | assert(math.isNan(pow(f32, -12.4, 78.5))); | 233 | expect(math.isNan(pow(f32, -12.4, 78.5))); |
| 234 | } | 234 | } |
std/math/powi.zig+69-69| ... | @@ -12,7 +12,7 @@ const builtin = @import("builtin"); | ... | @@ -12,7 +12,7 @@ const builtin = @import("builtin"); |
| 12 | const std = @import("../index.zig"); | 12 | const std = @import("../index.zig"); |
| 13 | const math = std.math; | 13 | const math = std.math; |
| 14 | const assert = std.debug.assert; | 14 | const assert = std.debug.assert; |
| 15 | const assertError = std.debug.assertError; | 15 | const testing = std.testing; |
| 16 | 16 | ||
| 17 | // This implementation is based on that from the rust stlib | 17 | // This implementation is based on that from the rust stlib |
| 18 | pub fn powi(comptime T: type, x: T, y: T) (error{ | 18 | pub fn powi(comptime T: type, x: T, y: T) (error{ |
| ... | @@ -103,75 +103,75 @@ pub fn powi(comptime T: type, x: T, y: T) (error{ | ... | @@ -103,75 +103,75 @@ pub fn powi(comptime T: type, x: T, y: T) (error{ |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | test "math.powi" { | 105 | test "math.powi" { |
| 106 | assertError(powi(i8, -66, 6), error.Underflow); | 106 | testing.expectError(error.Underflow, powi(i8, -66, 6)); |
| 107 | assertError(powi(i16, -13, 13), error.Underflow); | 107 | testing.expectError(error.Underflow, powi(i16, -13, 13)); |
| 108 | assertError(powi(i32, -32, 21), error.Underflow); | 108 | testing.expectError(error.Underflow, powi(i32, -32, 21)); |
| 109 | assertError(powi(i64, -24, 61), error.Underflow); | 109 | testing.expectError(error.Underflow, powi(i64, -24, 61)); |
| 110 | assertError(powi(i17, -15, 15), error.Underflow); | 110 | testing.expectError(error.Underflow, powi(i17, -15, 15)); |
| 111 | assertError(powi(i42, -6, 40), error.Underflow); | 111 | testing.expectError(error.Underflow, powi(i42, -6, 40)); |
| 112 | 112 | ||
| 113 | assert((try powi(i8, -5, 3)) == -125); | 113 | testing.expect((try powi(i8, -5, 3)) == -125); |
| 114 | assert((try powi(i16, -16, 3)) == -4096); | 114 | testing.expect((try powi(i16, -16, 3)) == -4096); |
| 115 | assert((try powi(i32, -91, 3)) == -753571); | 115 | testing.expect((try powi(i32, -91, 3)) == -753571); |
| 116 | assert((try powi(i64, -36, 6)) == 2176782336); | 116 | testing.expect((try powi(i64, -36, 6)) == 2176782336); |
| 117 | assert((try powi(i17, -2, 15)) == -32768); | 117 | testing.expect((try powi(i17, -2, 15)) == -32768); |
| 118 | assert((try powi(i42, -5, 7)) == -78125); | 118 | testing.expect((try powi(i42, -5, 7)) == -78125); |
| 119 | 119 | ||
| 120 | assert((try powi(u8, 6, 2)) == 36); | 120 | testing.expect((try powi(u8, 6, 2)) == 36); |
| 121 | assert((try powi(u16, 5, 4)) == 625); | 121 | testing.expect((try powi(u16, 5, 4)) == 625); |
| 122 | assert((try powi(u32, 12, 6)) == 2985984); | 122 | testing.expect((try powi(u32, 12, 6)) == 2985984); |
| 123 | assert((try powi(u64, 34, 2)) == 1156); | 123 | testing.expect((try powi(u64, 34, 2)) == 1156); |
| 124 | assert((try powi(u17, 16, 3)) == 4096); | 124 | testing.expect((try powi(u17, 16, 3)) == 4096); |
| 125 | assert((try powi(u42, 34, 6)) == 1544804416); | 125 | testing.expect((try powi(u42, 34, 6)) == 1544804416); |
| 126 | 126 | ||
| 127 | assertError(powi(i8, 120, 7), error.Overflow); | 127 | testing.expectError(error.Overflow, powi(i8, 120, 7)); |
| 128 | assertError(powi(i16, 73, 15), error.Overflow); | 128 | testing.expectError(error.Overflow, powi(i16, 73, 15)); |
| 129 | assertError(powi(i32, 23, 31), error.Overflow); | 129 | testing.expectError(error.Overflow, powi(i32, 23, 31)); |
| 130 | assertError(powi(i64, 68, 61), error.Overflow); | 130 | testing.expectError(error.Overflow, powi(i64, 68, 61)); |
| 131 | assertError(powi(i17, 15, 15), error.Overflow); | 131 | testing.expectError(error.Overflow, powi(i17, 15, 15)); |
| 132 | assertError(powi(i42, 121312, 41), error.Overflow); | 132 | testing.expectError(error.Overflow, powi(i42, 121312, 41)); |
| 133 | 133 | ||
| 134 | assertError(powi(u8, 123, 7), error.Overflow); | 134 | testing.expectError(error.Overflow, powi(u8, 123, 7)); |
| 135 | assertError(powi(u16, 2313, 15), error.Overflow); | 135 | testing.expectError(error.Overflow, powi(u16, 2313, 15)); |
| 136 | assertError(powi(u32, 8968, 31), error.Overflow); | 136 | testing.expectError(error.Overflow, powi(u32, 8968, 31)); |
| 137 | assertError(powi(u64, 2342, 63), error.Overflow); | 137 | testing.expectError(error.Overflow, powi(u64, 2342, 63)); |
| 138 | assertError(powi(u17, 2723, 16), error.Overflow); | 138 | testing.expectError(error.Overflow, powi(u17, 2723, 16)); |
| 139 | assertError(powi(u42, 8234, 41), error.Overflow); | 139 | testing.expectError(error.Overflow, powi(u42, 8234, 41)); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | test "math.powi.special" { | 142 | test "math.powi.special" { |
| 143 | assertError(powi(i8, -2, 8), error.Underflow); | 143 | testing.expectError(error.Underflow, powi(i8, -2, 8)); |
| 144 | assertError(powi(i16, -2, 16), error.Underflow); | 144 | testing.expectError(error.Underflow, powi(i16, -2, 16)); |
| 145 | assertError(powi(i32, -2, 32), error.Underflow); | 145 | testing.expectError(error.Underflow, powi(i32, -2, 32)); |
| 146 | assertError(powi(i64, -2, 64), error.Underflow); | 146 | testing.expectError(error.Underflow, powi(i64, -2, 64)); |
| 147 | assertError(powi(i17, -2, 17), error.Underflow); | 147 | testing.expectError(error.Underflow, powi(i17, -2, 17)); |
| 148 | assertError(powi(i42, -2, 42), error.Underflow); | 148 | testing.expectError(error.Underflow, powi(i42, -2, 42)); |
| 149 | 149 | ||
| 150 | assert((try powi(i8, -1, 3)) == -1); | 150 | testing.expect((try powi(i8, -1, 3)) == -1); |
| 151 | assert((try powi(i16, -1, 2)) == 1); | 151 | testing.expect((try powi(i16, -1, 2)) == 1); |
| 152 | assert((try powi(i32, -1, 16)) == 1); | 152 | testing.expect((try powi(i32, -1, 16)) == 1); |
| 153 | assert((try powi(i64, -1, 6)) == 1); | 153 | testing.expect((try powi(i64, -1, 6)) == 1); |
| 154 | assert((try powi(i17, -1, 15)) == -1); | 154 | testing.expect((try powi(i17, -1, 15)) == -1); |
| 155 | assert((try powi(i42, -1, 7)) == -1); | 155 | testing.expect((try powi(i42, -1, 7)) == -1); |
| 156 | 156 | ||
| 157 | assert((try powi(u8, 1, 2)) == 1); | 157 | testing.expect((try powi(u8, 1, 2)) == 1); |
| 158 | assert((try powi(u16, 1, 4)) == 1); | 158 | testing.expect((try powi(u16, 1, 4)) == 1); |
| 159 | assert((try powi(u32, 1, 6)) == 1); | 159 | testing.expect((try powi(u32, 1, 6)) == 1); |
| 160 | assert((try powi(u64, 1, 2)) == 1); | 160 | testing.expect((try powi(u64, 1, 2)) == 1); |
| 161 | assert((try powi(u17, 1, 3)) == 1); | 161 | testing.expect((try powi(u17, 1, 3)) == 1); |
| 162 | assert((try powi(u42, 1, 6)) == 1); | 162 | testing.expect((try powi(u42, 1, 6)) == 1); |
| 163 | 163 | ||
| 164 | assertError(powi(i8, 2, 7), error.Overflow); | 164 | testing.expectError(error.Overflow, powi(i8, 2, 7)); |
| 165 | assertError(powi(i16, 2, 15), error.Overflow); | 165 | testing.expectError(error.Overflow, powi(i16, 2, 15)); |
| 166 | assertError(powi(i32, 2, 31), error.Overflow); | 166 | testing.expectError(error.Overflow, powi(i32, 2, 31)); |
| 167 | assertError(powi(i64, 2, 63), error.Overflow); | 167 | testing.expectError(error.Overflow, powi(i64, 2, 63)); |
| 168 | assertError(powi(i17, 2, 16), error.Overflow); | 168 | testing.expectError(error.Overflow, powi(i17, 2, 16)); |
| 169 | assertError(powi(i42, 2, 41), error.Overflow); | 169 | testing.expectError(error.Overflow, powi(i42, 2, 41)); |
| 170 | 170 | ||
| 171 | assertError(powi(u8, 2, 8), error.Overflow); | 171 | testing.expectError(error.Overflow, powi(u8, 2, 8)); |
| 172 | assertError(powi(u16, 2, 16), error.Overflow); | 172 | testing.expectError(error.Overflow, powi(u16, 2, 16)); |
| 173 | assertError(powi(u32, 2, 32), error.Overflow); | 173 | testing.expectError(error.Overflow, powi(u32, 2, 32)); |
| 174 | assertError(powi(u64, 2, 64), error.Overflow); | 174 | testing.expectError(error.Overflow, powi(u64, 2, 64)); |
| 175 | assertError(powi(u17, 2, 17), error.Overflow); | 175 | testing.expectError(error.Overflow, powi(u17, 2, 17)); |
| 176 | assertError(powi(u42, 2, 42), error.Overflow); | 176 | testing.expectError(error.Overflow, powi(u42, 2, 42)); |
| 177 | } | 177 | } |
std/math/round.zig+21-21| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | // - round(nan) = nan | 5 | // - round(nan) = nan |
| 6 | 6 | ||
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const assert = std.debug.assert; | 8 | const expect = std.testing.expect; |
| 9 | const std = @import("../index.zig"); | 9 | const std = @import("../index.zig"); |
| 10 | const math = std.math; | 10 | const math = std.math; |
| 11 | 11 | ||
| ... | @@ -85,36 +85,36 @@ fn round64(x_: f64) f64 { | ... | @@ -85,36 +85,36 @@ fn round64(x_: f64) f64 { |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | test "math.round" { | 87 | test "math.round" { |
| 88 | assert(round(f32(1.3)) == round32(1.3)); | 88 | expect(round(f32(1.3)) == round32(1.3)); |
| 89 | assert(round(f64(1.3)) == round64(1.3)); | 89 | expect(round(f64(1.3)) == round64(1.3)); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | test "math.round32" { | 92 | test "math.round32" { |
| 93 | assert(round32(1.3) == 1.0); | 93 | expect(round32(1.3) == 1.0); |
| 94 | assert(round32(-1.3) == -1.0); | 94 | expect(round32(-1.3) == -1.0); |
| 95 | assert(round32(0.2) == 0.0); | 95 | expect(round32(0.2) == 0.0); |
| 96 | assert(round32(1.8) == 2.0); | 96 | expect(round32(1.8) == 2.0); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | test "math.round64" { | 99 | test "math.round64" { |
| 100 | assert(round64(1.3) == 1.0); | 100 | expect(round64(1.3) == 1.0); |
| 101 | assert(round64(-1.3) == -1.0); | 101 | expect(round64(-1.3) == -1.0); |
| 102 | assert(round64(0.2) == 0.0); | 102 | expect(round64(0.2) == 0.0); |
| 103 | assert(round64(1.8) == 2.0); | 103 | expect(round64(1.8) == 2.0); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | test "math.round32.special" { | 106 | test "math.round32.special" { |
| 107 | assert(round32(0.0) == 0.0); | 107 | expect(round32(0.0) == 0.0); |
| 108 | assert(round32(-0.0) == -0.0); | 108 | expect(round32(-0.0) == -0.0); |
| 109 | assert(math.isPositiveInf(round32(math.inf(f32)))); | 109 | expect(math.isPositiveInf(round32(math.inf(f32)))); |
| 110 | assert(math.isNegativeInf(round32(-math.inf(f32)))); | 110 | expect(math.isNegativeInf(round32(-math.inf(f32)))); |
| 111 | assert(math.isNan(round32(math.nan(f32)))); | 111 | expect(math.isNan(round32(math.nan(f32)))); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | test "math.round64.special" { | 114 | test "math.round64.special" { |
| 115 | assert(round64(0.0) == 0.0); | 115 | expect(round64(0.0) == 0.0); |
| 116 | assert(round64(-0.0) == -0.0); | 116 | expect(round64(-0.0) == -0.0); |
| 117 | assert(math.isPositiveInf(round64(math.inf(f64)))); | 117 | expect(math.isPositiveInf(round64(math.inf(f64)))); |
| 118 | assert(math.isNegativeInf(round64(-math.inf(f64)))); | 118 | expect(math.isNegativeInf(round64(-math.inf(f64)))); |
| 119 | assert(math.isNan(round64(math.nan(f64)))); | 119 | expect(math.isNan(round64(math.nan(f64)))); |
| 120 | } | 120 | } |
std/math/scalbn.zig+5-5| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | pub fn scalbn(x: var, n: i32) @typeOf(x) { | 5 | pub fn scalbn(x: var, n: i32) @typeOf(x) { |
| 6 | const T = @typeOf(x); | 6 | const T = @typeOf(x); |
| ... | @@ -72,14 +72,14 @@ fn scalbn64(x: f64, n_: i32) f64 { | ... | @@ -72,14 +72,14 @@ fn scalbn64(x: f64, n_: i32) f64 { |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | test "math.scalbn" { | 74 | test "math.scalbn" { |
| 75 | assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4)); | 75 | expect(scalbn(f32(1.5), 4) == scalbn32(1.5, 4)); |
| 76 | assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4)); | 76 | expect(scalbn(f64(1.5), 4) == scalbn64(1.5, 4)); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | test "math.scalbn32" { | 79 | test "math.scalbn32" { |
| 80 | assert(scalbn32(1.5, 4) == 24.0); | 80 | expect(scalbn32(1.5, 4) == 24.0); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | test "math.scalbn64" { | 83 | test "math.scalbn64" { |
| 84 | assert(scalbn64(1.5, 4) == 24.0); | 84 | expect(scalbn64(1.5, 4) == 24.0); |
| 85 | } | 85 | } |
std/math/signbit.zig+10-10| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | 4 | ||
| 5 | pub fn signbit(x: var) bool { | 5 | pub fn signbit(x: var) bool { |
| 6 | const T = @typeOf(x); | 6 | const T = @typeOf(x); |
| ... | @@ -28,22 +28,22 @@ fn signbit64(x: f64) bool { | ... | @@ -28,22 +28,22 @@ fn signbit64(x: f64) bool { |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | test "math.signbit" { | 30 | test "math.signbit" { |
| 31 | assert(signbit(f16(4.0)) == signbit16(4.0)); | 31 | expect(signbit(f16(4.0)) == signbit16(4.0)); |
| 32 | assert(signbit(f32(4.0)) == signbit32(4.0)); | 32 | expect(signbit(f32(4.0)) == signbit32(4.0)); |
| 33 | assert(signbit(f64(4.0)) == signbit64(4.0)); | 33 | expect(signbit(f64(4.0)) == signbit64(4.0)); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | test "math.signbit16" { | 36 | test "math.signbit16" { |
| 37 | assert(!signbit16(4.0)); | 37 | expect(!signbit16(4.0)); |
| 38 | assert(signbit16(-3.0)); | 38 | expect(signbit16(-3.0)); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | test "math.signbit32" { | 41 | test "math.signbit32" { |
| 42 | assert(!signbit32(4.0)); | 42 | expect(!signbit32(4.0)); |
| 43 | assert(signbit32(-3.0)); | 43 | expect(signbit32(-3.0)); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | test "math.signbit64" { | 46 | test "math.signbit64" { |
| 47 | assert(!signbit64(4.0)); | 47 | expect(!signbit64(4.0)); |
| 48 | assert(signbit64(-3.0)); | 48 | expect(signbit64(-3.0)); |
| 49 | } | 49 | } |
std/math/sin.zig+26-26| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | 11 | ||
| 12 | pub fn sin(x: var) @typeOf(x) { | 12 | pub fn sin(x: var) @typeOf(x) { |
| 13 | const T = @typeOf(x); | 13 | const T = @typeOf(x); |
| ... | @@ -142,45 +142,45 @@ fn sin64(x_: f64) f64 { | ... | @@ -142,45 +142,45 @@ fn sin64(x_: f64) f64 { |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | test "math.sin" { | 144 | test "math.sin" { |
| 145 | assert(sin(f32(0.0)) == sin32(0.0)); | 145 | expect(sin(f32(0.0)) == sin32(0.0)); |
| 146 | assert(sin(f64(0.0)) == sin64(0.0)); | 146 | expect(sin(f64(0.0)) == sin64(0.0)); |
| 147 | assert(comptime (math.sin(f64(2))) == math.sin(f64(2))); | 147 | expect(comptime (math.sin(f64(2))) == math.sin(f64(2))); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | test "math.sin32" { | 150 | test "math.sin32" { |
| 151 | const epsilon = 0.000001; | 151 | const epsilon = 0.000001; |
| 152 | 152 | ||
| 153 | assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon)); | 153 | expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon)); |
| 154 | assert(math.approxEq(f32, sin32(0.2), 0.198669, epsilon)); | 154 | expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon)); |
| 155 | assert(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon)); | 155 | expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon)); |
| 156 | assert(math.approxEq(f32, sin32(1.5), 0.997495, epsilon)); | 156 | expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon)); |
| 157 | assert(math.approxEq(f32, sin32(37.45), -0.246544, epsilon)); | 157 | expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon)); |
| 158 | assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon)); | 158 | expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon)); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | test "math.sin64" { | 161 | test "math.sin64" { |
| 162 | const epsilon = 0.000001; | 162 | const epsilon = 0.000001; |
| 163 | 163 | ||
| 164 | assert(math.approxEq(f64, sin64(0.0), 0.0, epsilon)); | 164 | expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon)); |
| 165 | assert(math.approxEq(f64, sin64(0.2), 0.198669, epsilon)); | 165 | expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon)); |
| 166 | assert(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon)); | 166 | expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon)); |
| 167 | assert(math.approxEq(f64, sin64(1.5), 0.997495, epsilon)); | 167 | expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon)); |
| 168 | assert(math.approxEq(f64, sin64(37.45), -0.246543, epsilon)); | 168 | expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon)); |
| 169 | assert(math.approxEq(f64, sin64(89.123), 0.916166, epsilon)); | 169 | expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon)); |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | test "math.sin32.special" { | 172 | test "math.sin32.special" { |
| 173 | assert(sin32(0.0) == 0.0); | 173 | expect(sin32(0.0) == 0.0); |
| 174 | assert(sin32(-0.0) == -0.0); | 174 | expect(sin32(-0.0) == -0.0); |
| 175 | assert(math.isNan(sin32(math.inf(f32)))); | 175 | expect(math.isNan(sin32(math.inf(f32)))); |
| 176 | assert(math.isNan(sin32(-math.inf(f32)))); | 176 | expect(math.isNan(sin32(-math.inf(f32)))); |
| 177 | assert(math.isNan(sin32(math.nan(f32)))); | 177 | expect(math.isNan(sin32(math.nan(f32)))); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | test "math.sin64.special" { | 180 | test "math.sin64.special" { |
| 181 | assert(sin64(0.0) == 0.0); | 181 | expect(sin64(0.0) == 0.0); |
| 182 | assert(sin64(-0.0) == -0.0); | 182 | expect(sin64(-0.0) == -0.0); |
| 183 | assert(math.isNan(sin64(math.inf(f64)))); | 183 | expect(math.isNan(sin64(math.inf(f64)))); |
| 184 | assert(math.isNan(sin64(-math.inf(f64)))); | 184 | expect(math.isNan(sin64(-math.inf(f64)))); |
| 185 | assert(math.isNan(sin64(math.nan(f64)))); | 185 | expect(math.isNan(sin64(math.nan(f64)))); |
| 186 | } | 186 | } |
std/math/sinh.zig+21-21| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | const expo2 = @import("expo2.zig").expo2; | 11 | const expo2 = @import("expo2.zig").expo2; |
| 12 | const maxInt = std.math.maxInt; | 12 | const maxInt = std.math.maxInt; |
| 13 | 13 | ||
| ... | @@ -87,40 +87,40 @@ fn sinh64(x: f64) f64 { | ... | @@ -87,40 +87,40 @@ fn sinh64(x: f64) f64 { |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | test "math.sinh" { | 89 | test "math.sinh" { |
| 90 | assert(sinh(f32(1.5)) == sinh32(1.5)); | 90 | expect(sinh(f32(1.5)) == sinh32(1.5)); |
| 91 | assert(sinh(f64(1.5)) == sinh64(1.5)); | 91 | expect(sinh(f64(1.5)) == sinh64(1.5)); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | test "math.sinh32" { | 94 | test "math.sinh32" { |
| 95 | const epsilon = 0.000001; | 95 | const epsilon = 0.000001; |
| 96 | 96 | ||
| 97 | assert(math.approxEq(f32, sinh32(0.0), 0.0, epsilon)); | 97 | expect(math.approxEq(f32, sinh32(0.0), 0.0, epsilon)); |
| 98 | assert(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon)); | 98 | expect(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon)); |
| 99 | assert(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon)); | 99 | expect(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon)); |
| 100 | assert(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon)); | 100 | expect(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon)); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | test "math.sinh64" { | 103 | test "math.sinh64" { |
| 104 | const epsilon = 0.000001; | 104 | const epsilon = 0.000001; |
| 105 | 105 | ||
| 106 | assert(math.approxEq(f64, sinh64(0.0), 0.0, epsilon)); | 106 | expect(math.approxEq(f64, sinh64(0.0), 0.0, epsilon)); |
| 107 | assert(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon)); | 107 | expect(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon)); |
| 108 | assert(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon)); | 108 | expect(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon)); |
| 109 | assert(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon)); | 109 | expect(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon)); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | test "math.sinh32.special" { | 112 | test "math.sinh32.special" { |
| 113 | assert(sinh32(0.0) == 0.0); | 113 | expect(sinh32(0.0) == 0.0); |
| 114 | assert(sinh32(-0.0) == -0.0); | 114 | expect(sinh32(-0.0) == -0.0); |
| 115 | assert(math.isPositiveInf(sinh32(math.inf(f32)))); | 115 | expect(math.isPositiveInf(sinh32(math.inf(f32)))); |
| 116 | assert(math.isNegativeInf(sinh32(-math.inf(f32)))); | 116 | expect(math.isNegativeInf(sinh32(-math.inf(f32)))); |
| 117 | assert(math.isNan(sinh32(math.nan(f32)))); | 117 | expect(math.isNan(sinh32(math.nan(f32)))); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | test "math.sinh64.special" { | 120 | test "math.sinh64.special" { |
| 121 | assert(sinh64(0.0) == 0.0); | 121 | expect(sinh64(0.0) == 0.0); |
| 122 | assert(sinh64(-0.0) == -0.0); | 122 | expect(sinh64(-0.0) == -0.0); |
| 123 | assert(math.isPositiveInf(sinh64(math.inf(f64)))); | 123 | expect(math.isPositiveInf(sinh64(math.inf(f64)))); |
| 124 | assert(math.isNegativeInf(sinh64(-math.inf(f64)))); | 124 | expect(math.isNegativeInf(sinh64(-math.inf(f64)))); |
| 125 | assert(math.isNan(sinh64(math.nan(f64)))); | 125 | expect(math.isNan(sinh64(math.nan(f64)))); |
| 126 | } | 126 | } |
std/math/sqrt.zig+52-52| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | ||
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | const builtin = @import("builtin"); | 11 | const builtin = @import("builtin"); |
| 12 | const TypeId = builtin.TypeId; | 12 | const TypeId = builtin.TypeId; |
| 13 | const maxInt = std.math.maxInt; | 13 | const maxInt = std.math.maxInt; |
| ... | @@ -32,75 +32,75 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ | ... | @@ -32,75 +32,75 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | test "math.sqrt" { | 34 | test "math.sqrt" { |
| 35 | assert(sqrt(f16(0.0)) == @sqrt(f16, 0.0)); | 35 | expect(sqrt(f16(0.0)) == @sqrt(f16, 0.0)); |
| 36 | assert(sqrt(f32(0.0)) == @sqrt(f32, 0.0)); | 36 | expect(sqrt(f32(0.0)) == @sqrt(f32, 0.0)); |
| 37 | assert(sqrt(f64(0.0)) == @sqrt(f64, 0.0)); | 37 | expect(sqrt(f64(0.0)) == @sqrt(f64, 0.0)); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | test "math.sqrt16" { | 40 | test "math.sqrt16" { |
| 41 | const epsilon = 0.000001; | 41 | const epsilon = 0.000001; |
| 42 | 42 | ||
| 43 | assert(@sqrt(f16, 0.0) == 0.0); | 43 | expect(@sqrt(f16, 0.0) == 0.0); |
| 44 | assert(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon)); | 44 | expect(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon)); |
| 45 | assert(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon)); | 45 | expect(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon)); |
| 46 | assert(@sqrt(f16, 4.0) == 2.0); | 46 | expect(@sqrt(f16, 4.0) == 2.0); |
| 47 | assert(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon)); | 47 | expect(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon)); |
| 48 | assert(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon)); | 48 | expect(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon)); |
| 49 | assert(@sqrt(f16, 64.0) == 8.0); | 49 | expect(@sqrt(f16, 64.0) == 8.0); |
| 50 | assert(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon)); | 50 | expect(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon)); |
| 51 | assert(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon)); | 51 | expect(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon)); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | test "math.sqrt32" { | 54 | test "math.sqrt32" { |
| 55 | const epsilon = 0.000001; | 55 | const epsilon = 0.000001; |
| 56 | 56 | ||
| 57 | assert(@sqrt(f32, 0.0) == 0.0); | 57 | expect(@sqrt(f32, 0.0) == 0.0); |
| 58 | assert(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon)); | 58 | expect(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon)); |
| 59 | assert(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon)); | 59 | expect(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon)); |
| 60 | assert(@sqrt(f32, 4.0) == 2.0); | 60 | expect(@sqrt(f32, 4.0) == 2.0); |
| 61 | assert(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon)); | 61 | expect(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon)); |
| 62 | assert(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon)); | 62 | expect(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon)); |
| 63 | assert(@sqrt(f32, 64.0) == 8.0); | 63 | expect(@sqrt(f32, 64.0) == 8.0); |
| 64 | assert(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon)); | 64 | expect(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon)); |
| 65 | assert(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon)); | 65 | expect(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon)); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | test "math.sqrt64" { | 68 | test "math.sqrt64" { |
| 69 | const epsilon = 0.000001; | 69 | const epsilon = 0.000001; |
| 70 | 70 | ||
| 71 | assert(@sqrt(f64, 0.0) == 0.0); | 71 | expect(@sqrt(f64, 0.0) == 0.0); |
| 72 | assert(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon)); | 72 | expect(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon)); |
| 73 | assert(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon)); | 73 | expect(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon)); |
| 74 | assert(@sqrt(f64, 4.0) == 2.0); | 74 | expect(@sqrt(f64, 4.0) == 2.0); |
| 75 | assert(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon)); | 75 | expect(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon)); |
| 76 | assert(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon)); | 76 | expect(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon)); |
| 77 | assert(@sqrt(f64, 64.0) == 8.0); | 77 | expect(@sqrt(f64, 64.0) == 8.0); |
| 78 | assert(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon)); | 78 | expect(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon)); |
| 79 | assert(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon)); | 79 | expect(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon)); |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | test "math.sqrt16.special" { | 82 | test "math.sqrt16.special" { |
| 83 | assert(math.isPositiveInf(@sqrt(f16, math.inf(f16)))); | 83 | expect(math.isPositiveInf(@sqrt(f16, math.inf(f16)))); |
| 84 | assert(@sqrt(f16, 0.0) == 0.0); | 84 | expect(@sqrt(f16, 0.0) == 0.0); |
| 85 | assert(@sqrt(f16, -0.0) == -0.0); | 85 | expect(@sqrt(f16, -0.0) == -0.0); |
| 86 | assert(math.isNan(@sqrt(f16, -1.0))); | 86 | expect(math.isNan(@sqrt(f16, -1.0))); |
| 87 | assert(math.isNan(@sqrt(f16, math.nan(f16)))); | 87 | expect(math.isNan(@sqrt(f16, math.nan(f16)))); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | test "math.sqrt32.special" { | 90 | test "math.sqrt32.special" { |
| 91 | assert(math.isPositiveInf(@sqrt(f32, math.inf(f32)))); | 91 | expect(math.isPositiveInf(@sqrt(f32, math.inf(f32)))); |
| 92 | assert(@sqrt(f32, 0.0) == 0.0); | 92 | expect(@sqrt(f32, 0.0) == 0.0); |
| 93 | assert(@sqrt(f32, -0.0) == -0.0); | 93 | expect(@sqrt(f32, -0.0) == -0.0); |
| 94 | assert(math.isNan(@sqrt(f32, -1.0))); | 94 | expect(math.isNan(@sqrt(f32, -1.0))); |
| 95 | assert(math.isNan(@sqrt(f32, math.nan(f32)))); | 95 | expect(math.isNan(@sqrt(f32, math.nan(f32)))); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | test "math.sqrt64.special" { | 98 | test "math.sqrt64.special" { |
| 99 | assert(math.isPositiveInf(@sqrt(f64, math.inf(f64)))); | 99 | expect(math.isPositiveInf(@sqrt(f64, math.inf(f64)))); |
| 100 | assert(@sqrt(f64, 0.0) == 0.0); | 100 | expect(@sqrt(f64, 0.0) == 0.0); |
| 101 | assert(@sqrt(f64, -0.0) == -0.0); | 101 | expect(@sqrt(f64, -0.0) == -0.0); |
| 102 | assert(math.isNan(@sqrt(f64, -1.0))); | 102 | expect(math.isNan(@sqrt(f64, -1.0))); |
| 103 | assert(math.isNan(@sqrt(f64, math.nan(f64)))); | 103 | expect(math.isNan(@sqrt(f64, math.nan(f64)))); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { | 106 | fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { |
| ... | @@ -127,10 +127,10 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { | ... | @@ -127,10 +127,10 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | test "math.sqrt_int" { | 129 | test "math.sqrt_int" { |
| 130 | assert(sqrt_int(u32, 3) == 1); | 130 | expect(sqrt_int(u32, 3) == 1); |
| 131 | assert(sqrt_int(u32, 4) == 2); | 131 | expect(sqrt_int(u32, 4) == 2); |
| 132 | assert(sqrt_int(u32, 5) == 2); | 132 | expect(sqrt_int(u32, 5) == 2); |
| 133 | assert(sqrt_int(u32, 8) == 2); | 133 | expect(sqrt_int(u32, 8) == 2); |
| 134 | assert(sqrt_int(u32, 9) == 3); | 134 | expect(sqrt_int(u32, 9) == 3); |
| 135 | assert(sqrt_int(u32, 10) == 3); | 135 | expect(sqrt_int(u32, 10) == 3); |
| 136 | } | 136 | } |
std/math/tan.zig+25-25| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | 11 | ||
| 12 | pub fn tan(x: var) @typeOf(x) { | 12 | pub fn tan(x: var) @typeOf(x) { |
| 13 | const T = @typeOf(x); | 13 | const T = @typeOf(x); |
| ... | @@ -129,44 +129,44 @@ fn tan64(x_: f64) f64 { | ... | @@ -129,44 +129,44 @@ fn tan64(x_: f64) f64 { |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | test "math.tan" { | 131 | test "math.tan" { |
| 132 | assert(tan(f32(0.0)) == tan32(0.0)); | 132 | expect(tan(f32(0.0)) == tan32(0.0)); |
| 133 | assert(tan(f64(0.0)) == tan64(0.0)); | 133 | expect(tan(f64(0.0)) == tan64(0.0)); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | test "math.tan32" { | 136 | test "math.tan32" { |
| 137 | const epsilon = 0.000001; | 137 | const epsilon = 0.000001; |
| 138 | 138 | ||
| 139 | assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon)); | 139 | expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon)); |
| 140 | assert(math.approxEq(f32, tan32(0.2), 0.202710, epsilon)); | 140 | expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon)); |
| 141 | assert(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon)); | 141 | expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon)); |
| 142 | assert(math.approxEq(f32, tan32(1.5), 14.101420, epsilon)); | 142 | expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon)); |
| 143 | assert(math.approxEq(f32, tan32(37.45), -0.254397, epsilon)); | 143 | expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon)); |
| 144 | assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon)); | 144 | expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon)); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | test "math.tan64" { | 147 | test "math.tan64" { |
| 148 | const epsilon = 0.000001; | 148 | const epsilon = 0.000001; |
| 149 | 149 | ||
| 150 | assert(math.approxEq(f64, tan64(0.0), 0.0, epsilon)); | 150 | expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon)); |
| 151 | assert(math.approxEq(f64, tan64(0.2), 0.202710, epsilon)); | 151 | expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon)); |
| 152 | assert(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon)); | 152 | expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon)); |
| 153 | assert(math.approxEq(f64, tan64(1.5), 14.101420, epsilon)); | 153 | expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon)); |
| 154 | assert(math.approxEq(f64, tan64(37.45), -0.254397, epsilon)); | 154 | expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon)); |
| 155 | assert(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon)); | 155 | expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon)); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | test "math.tan32.special" { | 158 | test "math.tan32.special" { |
| 159 | assert(tan32(0.0) == 0.0); | 159 | expect(tan32(0.0) == 0.0); |
| 160 | assert(tan32(-0.0) == -0.0); | 160 | expect(tan32(-0.0) == -0.0); |
| 161 | assert(math.isNan(tan32(math.inf(f32)))); | 161 | expect(math.isNan(tan32(math.inf(f32)))); |
| 162 | assert(math.isNan(tan32(-math.inf(f32)))); | 162 | expect(math.isNan(tan32(-math.inf(f32)))); |
| 163 | assert(math.isNan(tan32(math.nan(f32)))); | 163 | expect(math.isNan(tan32(math.nan(f32)))); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | test "math.tan64.special" { | 166 | test "math.tan64.special" { |
| 167 | assert(tan64(0.0) == 0.0); | 167 | expect(tan64(0.0) == 0.0); |
| 168 | assert(tan64(-0.0) == -0.0); | 168 | expect(tan64(-0.0) == -0.0); |
| 169 | assert(math.isNan(tan64(math.inf(f64)))); | 169 | expect(math.isNan(tan64(math.inf(f64)))); |
| 170 | assert(math.isNan(tan64(-math.inf(f64)))); | 170 | expect(math.isNan(tan64(-math.inf(f64)))); |
| 171 | assert(math.isNan(tan64(math.nan(f64)))); | 171 | expect(math.isNan(tan64(math.nan(f64)))); |
| 172 | } | 172 | } |
std/math/tanh.zig+23-23| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const std = @import("../index.zig"); | 8 | const std = @import("../index.zig"); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const assert = std.debug.assert; | 10 | const expect = std.testing.expect; |
| 11 | const expo2 = @import("expo2.zig").expo2; | 11 | const expo2 = @import("expo2.zig").expo2; |
| 12 | const maxInt = std.math.maxInt; | 12 | const maxInt = std.math.maxInt; |
| 13 | 13 | ||
| ... | @@ -113,42 +113,42 @@ fn tanh64(x: f64) f64 { | ... | @@ -113,42 +113,42 @@ fn tanh64(x: f64) f64 { |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | test "math.tanh" { | 115 | test "math.tanh" { |
| 116 | assert(tanh(f32(1.5)) == tanh32(1.5)); | 116 | expect(tanh(f32(1.5)) == tanh32(1.5)); |
| 117 | assert(tanh(f64(1.5)) == tanh64(1.5)); | 117 | expect(tanh(f64(1.5)) == tanh64(1.5)); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | test "math.tanh32" { | 120 | test "math.tanh32" { |
| 121 | const epsilon = 0.000001; | 121 | const epsilon = 0.000001; |
| 122 | 122 | ||
| 123 | assert(math.approxEq(f32, tanh32(0.0), 0.0, epsilon)); | 123 | expect(math.approxEq(f32, tanh32(0.0), 0.0, epsilon)); |
| 124 | assert(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon)); | 124 | expect(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon)); |
| 125 | assert(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon)); | 125 | expect(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon)); |
| 126 | assert(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon)); | 126 | expect(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon)); |
| 127 | assert(math.approxEq(f32, tanh32(37.45), 1.0, epsilon)); | 127 | expect(math.approxEq(f32, tanh32(37.45), 1.0, epsilon)); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | test "math.tanh64" { | 130 | test "math.tanh64" { |
| 131 | const epsilon = 0.000001; | 131 | const epsilon = 0.000001; |
| 132 | 132 | ||
| 133 | assert(math.approxEq(f64, tanh64(0.0), 0.0, epsilon)); | 133 | expect(math.approxEq(f64, tanh64(0.0), 0.0, epsilon)); |
| 134 | assert(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon)); | 134 | expect(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon)); |
| 135 | assert(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon)); | 135 | expect(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon)); |
| 136 | assert(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon)); | 136 | expect(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon)); |
| 137 | assert(math.approxEq(f64, tanh64(37.45), 1.0, epsilon)); | 137 | expect(math.approxEq(f64, tanh64(37.45), 1.0, epsilon)); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | test "math.tanh32.special" { | 140 | test "math.tanh32.special" { |
| 141 | assert(tanh32(0.0) == 0.0); | 141 | expect(tanh32(0.0) == 0.0); |
| 142 | assert(tanh32(-0.0) == -0.0); | 142 | expect(tanh32(-0.0) == -0.0); |
| 143 | assert(tanh32(math.inf(f32)) == 1.0); | 143 | expect(tanh32(math.inf(f32)) == 1.0); |
| 144 | assert(tanh32(-math.inf(f32)) == -1.0); | 144 | expect(tanh32(-math.inf(f32)) == -1.0); |
| 145 | assert(math.isNan(tanh32(math.nan(f32)))); | 145 | expect(math.isNan(tanh32(math.nan(f32)))); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | test "math.tanh64.special" { | 148 | test "math.tanh64.special" { |
| 149 | assert(tanh64(0.0) == 0.0); | 149 | expect(tanh64(0.0) == 0.0); |
| 150 | assert(tanh64(-0.0) == -0.0); | 150 | expect(tanh64(-0.0) == -0.0); |
| 151 | assert(tanh64(math.inf(f64)) == 1.0); | 151 | expect(tanh64(math.inf(f64)) == 1.0); |
| 152 | assert(tanh64(-math.inf(f64)) == -1.0); | 152 | expect(tanh64(-math.inf(f64)) == -1.0); |
| 153 | assert(math.isNan(tanh64(math.nan(f64)))); | 153 | expect(math.isNan(tanh64(math.nan(f64)))); |
| 154 | } | 154 | } |
std/math/trunc.zig+19-19| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ||
| 7 | const std = @import("../index.zig"); | 7 | const std = @import("../index.zig"); |
| 8 | const math = std.math; | 8 | const math = std.math; |
| 9 | const assert = std.debug.assert; | 9 | const expect = std.testing.expect; |
| 10 | const maxInt = std.math.maxInt; | 10 | const maxInt = std.math.maxInt; |
| 11 | 11 | ||
| 12 | pub fn trunc(x: var) @typeOf(x) { | 12 | pub fn trunc(x: var) @typeOf(x) { |
| ... | @@ -61,34 +61,34 @@ fn trunc64(x: f64) f64 { | ... | @@ -61,34 +61,34 @@ fn trunc64(x: f64) f64 { |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | test "math.trunc" { | 63 | test "math.trunc" { |
| 64 | assert(trunc(f32(1.3)) == trunc32(1.3)); | 64 | expect(trunc(f32(1.3)) == trunc32(1.3)); |
| 65 | assert(trunc(f64(1.3)) == trunc64(1.3)); | 65 | expect(trunc(f64(1.3)) == trunc64(1.3)); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | test "math.trunc32" { | 68 | test "math.trunc32" { |
| 69 | assert(trunc32(1.3) == 1.0); | 69 | expect(trunc32(1.3) == 1.0); |
| 70 | assert(trunc32(-1.3) == -1.0); | 70 | expect(trunc32(-1.3) == -1.0); |
| 71 | assert(trunc32(0.2) == 0.0); | 71 | expect(trunc32(0.2) == 0.0); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | test "math.trunc64" { | 74 | test "math.trunc64" { |
| 75 | assert(trunc64(1.3) == 1.0); | 75 | expect(trunc64(1.3) == 1.0); |
| 76 | assert(trunc64(-1.3) == -1.0); | 76 | expect(trunc64(-1.3) == -1.0); |
| 77 | assert(trunc64(0.2) == 0.0); | 77 | expect(trunc64(0.2) == 0.0); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | test "math.trunc32.special" { | 80 | test "math.trunc32.special" { |
| 81 | assert(trunc32(0.0) == 0.0); // 0x3F800000 | 81 | expect(trunc32(0.0) == 0.0); // 0x3F800000 |
| 82 | assert(trunc32(-0.0) == -0.0); | 82 | expect(trunc32(-0.0) == -0.0); |
| 83 | assert(math.isPositiveInf(trunc32(math.inf(f32)))); | 83 | expect(math.isPositiveInf(trunc32(math.inf(f32)))); |
| 84 | assert(math.isNegativeInf(trunc32(-math.inf(f32)))); | 84 | expect(math.isNegativeInf(trunc32(-math.inf(f32)))); |
| 85 | assert(math.isNan(trunc32(math.nan(f32)))); | 85 | expect(math.isNan(trunc32(math.nan(f32)))); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | test "math.trunc64.special" { | 88 | test "math.trunc64.special" { |
| 89 | assert(trunc64(0.0) == 0.0); | 89 | expect(trunc64(0.0) == 0.0); |
| 90 | assert(trunc64(-0.0) == -0.0); | 90 | expect(trunc64(-0.0) == -0.0); |
| 91 | assert(math.isPositiveInf(trunc64(math.inf(f64)))); | 91 | expect(math.isPositiveInf(trunc64(math.inf(f64)))); |
| 92 | assert(math.isNegativeInf(trunc64(-math.inf(f64)))); | 92 | expect(math.isNegativeInf(trunc64(-math.inf(f64)))); |
| 93 | assert(math.isNan(trunc64(math.nan(f64)))); | 93 | expect(math.isNan(trunc64(math.nan(f64)))); |
| 94 | } | 94 | } |
std/mem.zig+526-278| ... | @@ -6,6 +6,7 @@ const builtin = @import("builtin"); | ... | @@ -6,6 +6,7 @@ const builtin = @import("builtin"); |
| 6 | const mem = @This(); | 6 | const mem = @This(); |
| 7 | const meta = std.meta; | 7 | const meta = std.meta; |
| 8 | const trait = meta.trait; | 8 | const trait = meta.trait; |
| 9 | const testing = std.testing; | ||
| 9 | 10 | ||
| 10 | pub const Allocator = struct { | 11 | pub const Allocator = struct { |
| 11 | pub const Error = error{OutOfMemory}; | 12 | pub const Error = error{OutOfMemory}; |
| ... | @@ -36,20 +37,9 @@ pub const Allocator = struct { | ... | @@ -36,20 +37,9 @@ pub const Allocator = struct { |
| 36 | /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` | 37 | /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` |
| 37 | freeFn: fn (self: *Allocator, old_mem: []u8) void, | 38 | freeFn: fn (self: *Allocator, old_mem: []u8) void, |
| 38 | 39 | ||
| 39 | /// Call `destroy` with the result | ||
| 40 | /// TODO this is deprecated. use createOne instead | ||
| 41 | pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) { | ||
| 42 | const T = @typeOf(init); | ||
| 43 | if (@sizeOf(T) == 0) return &(T{}); | ||
| 44 | const slice = try self.alloc(T, 1); | ||
| 45 | const ptr = &slice[0]; | ||
| 46 | ptr.* = init; | ||
| 47 | return ptr; | ||
| 48 | } | ||
| 49 | |||
| 50 | /// Call `destroy` with the result. | 40 | /// Call `destroy` with the result. |
| 51 | /// Returns undefined memory. | 41 | /// Returns undefined memory. |
| 52 | pub fn createOne(self: *Allocator, comptime T: type) Error!*T { | 42 | pub fn create(self: *Allocator, comptime T: type) Error!*T { |
| 53 | if (@sizeOf(T) == 0) return &(T{}); | 43 | if (@sizeOf(T) == 0) return &(T{}); |
| 54 | const slice = try self.alloc(T, 1); | 44 | const slice = try self.alloc(T, 1); |
| 55 | return &slice[0]; | 45 | return &slice[0]; |
| ... | @@ -192,7 +182,7 @@ test "mem.secureZero" { | ... | @@ -192,7 +182,7 @@ test "mem.secureZero" { |
| 192 | set(u8, a[0..], 0); | 182 | set(u8, a[0..], 0); |
| 193 | secureZero(u8, b[0..]); | 183 | secureZero(u8, b[0..]); |
| 194 | 184 | ||
| 195 | assert(eql(u8, a[0..], b[0..])); | 185 | testing.expectEqualSlices(u8, a[0..], b[0..]); |
| 196 | } | 186 | } |
| 197 | 187 | ||
| 198 | pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare { | 188 | pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare { |
| ... | @@ -221,11 +211,11 @@ pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare { | ... | @@ -221,11 +211,11 @@ pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare { |
| 221 | } | 211 | } |
| 222 | 212 | ||
| 223 | test "mem.compare" { | 213 | test "mem.compare" { |
| 224 | assert(compare(u8, "abcd", "bee") == Compare.LessThan); | 214 | testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan); |
| 225 | assert(compare(u8, "abc", "abc") == Compare.Equal); | 215 | testing.expect(compare(u8, "abc", "abc") == Compare.Equal); |
| 226 | assert(compare(u8, "abc", "abc0") == Compare.LessThan); | 216 | testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan); |
| 227 | assert(compare(u8, "", "") == Compare.Equal); | 217 | testing.expect(compare(u8, "", "") == Compare.Equal); |
| 228 | assert(compare(u8, "", "a") == Compare.LessThan); | 218 | testing.expect(compare(u8, "", "a") == Compare.LessThan); |
| 229 | } | 219 | } |
| 230 | 220 | ||
| 231 | /// Returns true if lhs < rhs, false otherwise | 221 | /// Returns true if lhs < rhs, false otherwise |
| ... | @@ -238,11 +228,11 @@ pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool { | ... | @@ -238,11 +228,11 @@ pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool { |
| 238 | } | 228 | } |
| 239 | 229 | ||
| 240 | test "mem.lessThan" { | 230 | test "mem.lessThan" { |
| 241 | assert(lessThan(u8, "abcd", "bee")); | 231 | testing.expect(lessThan(u8, "abcd", "bee")); |
| 242 | assert(!lessThan(u8, "abc", "abc")); | 232 | testing.expect(!lessThan(u8, "abc", "abc")); |
| 243 | assert(lessThan(u8, "abc", "abc0")); | 233 | testing.expect(lessThan(u8, "abc", "abc0")); |
| 244 | assert(!lessThan(u8, "", "")); | 234 | testing.expect(!lessThan(u8, "", "")); |
| 245 | assert(lessThan(u8, "", "a")); | 235 | testing.expect(lessThan(u8, "", "a")); |
| 246 | } | 236 | } |
| 247 | 237 | ||
| 248 | /// Compares two slices and returns whether they are equal. | 238 | /// Compares two slices and returns whether they are equal. |
| ... | @@ -307,10 +297,10 @@ pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []co | ... | @@ -307,10 +297,10 @@ pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []co |
| 307 | } | 297 | } |
| 308 | 298 | ||
| 309 | test "mem.trim" { | 299 | test "mem.trim" { |
| 310 | assert(eql(u8, trimLeft(u8, " foo\n ", " \n"), "foo\n ")); | 300 | testing.expectEqualSlices(u8, "foo\n ", trimLeft(u8, " foo\n ", " \n")); |
| 311 | assert(eql(u8, trimRight(u8, " foo\n ", " \n"), " foo")); | 301 | testing.expectEqualSlices(u8, " foo", trimRight(u8, " foo\n ", " \n")); |
| 312 | assert(eql(u8, trim(u8, " foo\n ", " \n"), "foo")); | 302 | testing.expectEqualSlices(u8, "foo", trim(u8, " foo\n ", " \n")); |
| 313 | assert(eql(u8, trim(u8, "foo", " \n"), "foo")); | 303 | testing.expectEqualSlices(u8, "foo", trim(u8, "foo", " \n")); |
| 314 | } | 304 | } |
| 315 | 305 | ||
| 316 | /// Linear search for the index of a scalar value inside a slice. | 306 | /// Linear search for the index of a scalar value inside a slice. |
| ... | @@ -391,31 +381,27 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee | ... | @@ -391,31 +381,27 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee |
| 391 | } | 381 | } |
| 392 | 382 | ||
| 393 | test "mem.indexOf" { | 383 | test "mem.indexOf" { |
| 394 | assert(indexOf(u8, "one two three four", "four").? == 14); | 384 | testing.expect(indexOf(u8, "one two three four", "four").? == 14); |
| 395 | assert(lastIndexOf(u8, "one two three two four", "two").? == 14); | 385 | testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14); |
| 396 | assert(indexOf(u8, "one two three four", "gour") == null); | 386 | testing.expect(indexOf(u8, "one two three four", "gour") == null); |
| 397 | assert(lastIndexOf(u8, "one two three four", "gour") == null); | 387 | testing.expect(lastIndexOf(u8, "one two three four", "gour") == null); |
| 398 | assert(indexOf(u8, "foo", "foo").? == 0); | 388 | testing.expect(indexOf(u8, "foo", "foo").? == 0); |
| 399 | assert(lastIndexOf(u8, "foo", "foo").? == 0); | 389 | testing.expect(lastIndexOf(u8, "foo", "foo").? == 0); |
| 400 | assert(indexOf(u8, "foo", "fool") == null); | 390 | testing.expect(indexOf(u8, "foo", "fool") == null); |
| 401 | assert(lastIndexOf(u8, "foo", "lfoo") == null); | 391 | testing.expect(lastIndexOf(u8, "foo", "lfoo") == null); |
| 402 | assert(lastIndexOf(u8, "foo", "fool") == null); | 392 | testing.expect(lastIndexOf(u8, "foo", "fool") == null); |
| 403 | 393 | ||
| 404 | assert(indexOf(u8, "foo foo", "foo").? == 0); | 394 | testing.expect(indexOf(u8, "foo foo", "foo").? == 0); |
| 405 | assert(lastIndexOf(u8, "foo foo", "foo").? == 4); | 395 | testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4); |
| 406 | assert(lastIndexOfAny(u8, "boo, cat", "abo").? == 6); | 396 | testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6); |
| 407 | assert(lastIndexOfScalar(u8, "boo", 'o').? == 2); | 397 | testing.expect(lastIndexOfScalar(u8, "boo", 'o').? == 2); |
| 408 | } | 398 | } |
| 409 | 399 | ||
| 410 | /// Reads an integer from memory with size equal to bytes.len. | 400 | /// Reads an integer from memory with size equal to bytes.len. |
| 411 | /// T specifies the return type, which must be large enough to store | 401 | /// T specifies the return type, which must be large enough to store |
| 412 | /// the result. | 402 | /// the result. |
| 413 | /// See also ::readIntBE or ::readIntLE. | 403 | pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType { |
| 414 | pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { | 404 | var result: ReturnType = 0; |
| 415 | if (T.bit_count == 8) { | ||
| 416 | return bytes[0]; | ||
| 417 | } | ||
| 418 | var result: T = 0; | ||
| 419 | switch (endian) { | 405 | switch (endian) { |
| 420 | builtin.Endian.Big => { | 406 | builtin.Endian.Big => { |
| 421 | for (bytes) |b| { | 407 | for (bytes) |b| { |
| ... | @@ -423,171 +409,262 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { | ... | @@ -423,171 +409,262 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { |
| 423 | } | 409 | } |
| 424 | }, | 410 | }, |
| 425 | builtin.Endian.Little => { | 411 | builtin.Endian.Little => { |
| 426 | const ShiftType = math.Log2Int(T); | 412 | const ShiftType = math.Log2Int(ReturnType); |
| 427 | for (bytes) |b, index| { | 413 | for (bytes) |b, index| { |
| 428 | result = result | (T(b) << @intCast(ShiftType, index * 8)); | 414 | result = result | (ReturnType(b) << @intCast(ShiftType, index * 8)); |
| 429 | } | 415 | } |
| 430 | }, | 416 | }, |
| 431 | } | 417 | } |
| 432 | return result; | 418 | return result; |
| 433 | } | 419 | } |
| 434 | 420 | ||
| 435 | /// Reads a big-endian int of type T from bytes. | 421 | /// Reads an integer from memory with bit count specified by T. |
| 436 | /// bytes.len must be exactly @sizeOf(T). | 422 | /// The bit count of T must be evenly divisible by 8. |
| 437 | pub fn readIntBE(comptime T: type, bytes: []const u8) T { | 423 | /// This function cannot fail and cannot cause undefined behavior. |
| 438 | if (T.is_signed) { | 424 | /// Assumes the endianness of memory is native. This means the function can |
| 439 | return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); | 425 | /// simply pointer cast memory. |
| 440 | } | 426 | pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T { |
| 441 | assert(bytes.len == @sizeOf(T)); | 427 | return @ptrCast(*align(1) const T, bytes).*; |
| 442 | if (T == u8) return bytes[0]; | 428 | } |
| 443 | var result: T = 0; | 429 | |
| 444 | { | 430 | /// Reads an integer from memory with bit count specified by T. |
| 445 | comptime var i = 0; | 431 | /// The bit count of T must be evenly divisible by 8. |
| 446 | inline while (i < @sizeOf(T)) : (i += 1) { | 432 | /// This function cannot fail and cannot cause undefined behavior. |
| 447 | result = (result << 8) | T(bytes[i]); | 433 | /// Assumes the endianness of memory is foreign, so it must byte-swap. |
| 448 | } | 434 | pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T { |
| 435 | return @bswap(T, readIntNative(T, bytes)); | ||
| 436 | } | ||
| 437 | |||
| 438 | pub const readIntLittle = switch (builtin.endian) { | ||
| 439 | builtin.Endian.Little => readIntNative, | ||
| 440 | builtin.Endian.Big => readIntForeign, | ||
| 441 | }; | ||
| 442 | |||
| 443 | pub const readIntBig = switch (builtin.endian) { | ||
| 444 | builtin.Endian.Little => readIntForeign, | ||
| 445 | builtin.Endian.Big => readIntNative, | ||
| 446 | }; | ||
| 447 | |||
| 448 | /// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0 | ||
| 449 | /// and ignores extra bytes. | ||
| 450 | /// The bit count of T must be evenly divisible by 8. | ||
| 451 | /// Assumes the endianness of memory is native. This means the function can | ||
| 452 | /// simply pointer cast memory. | ||
| 453 | pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T { | ||
| 454 | const n = @divExact(T.bit_count, 8); | ||
| 455 | assert(bytes.len >= n); | ||
| 456 | // TODO https://github.com/ziglang/zig/issues/863 | ||
| 457 | return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr)); | ||
| 458 | } | ||
| 459 | |||
| 460 | /// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0 | ||
| 461 | /// and ignores extra bytes. | ||
| 462 | /// The bit count of T must be evenly divisible by 8. | ||
| 463 | /// Assumes the endianness of memory is foreign, so it must byte-swap. | ||
| 464 | pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T { | ||
| 465 | return @bswap(T, readIntSliceNative(T, bytes)); | ||
| 466 | } | ||
| 467 | |||
| 468 | pub const readIntSliceLittle = switch (builtin.endian) { | ||
| 469 | builtin.Endian.Little => readIntSliceNative, | ||
| 470 | builtin.Endian.Big => readIntSliceForeign, | ||
| 471 | }; | ||
| 472 | |||
| 473 | pub const readIntSliceBig = switch (builtin.endian) { | ||
| 474 | builtin.Endian.Little => readIntSliceForeign, | ||
| 475 | builtin.Endian.Big => readIntSliceNative, | ||
| 476 | }; | ||
| 477 | |||
| 478 | /// Reads an integer from memory with bit count specified by T. | ||
| 479 | /// The bit count of T must be evenly divisible by 8. | ||
| 480 | /// This function cannot fail and cannot cause undefined behavior. | ||
| 481 | pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T { | ||
| 482 | if (endian == builtin.endian) { | ||
| 483 | return readIntNative(T, bytes); | ||
| 484 | } else { | ||
| 485 | return readIntForeign(T, bytes); | ||
| 449 | } | 486 | } |
| 450 | return result; | ||
| 451 | } | 487 | } |
| 452 | 488 | ||
| 453 | /// Reads a little-endian int of type T from bytes. | 489 | /// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0 |
| 454 | /// bytes.len must be exactly @sizeOf(T). | 490 | /// and ignores extra bytes. |
| 455 | pub fn readIntLE(comptime T: type, bytes: []const u8) T { | 491 | /// The bit count of T must be evenly divisible by 8. |
| 456 | if (T.is_signed) { | 492 | pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T { |
| 457 | return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); | 493 | const n = @divExact(T.bit_count, 8); |
| 494 | assert(bytes.len >= n); | ||
| 495 | // TODO https://github.com/ziglang/zig/issues/863 | ||
| 496 | return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian); | ||
| 497 | } | ||
| 498 | |||
| 499 | test "comptime read/write int" { | ||
| 500 | comptime { | ||
| 501 | var bytes: [2]u8 = undefined; | ||
| 502 | std.mem.writeIntLittle(u16, &bytes, 0x1234); | ||
| 503 | const result = std.mem.readIntBig(u16, &bytes); | ||
| 504 | testing.expect(result == 0x3412); | ||
| 458 | } | 505 | } |
| 459 | assert(bytes.len == @sizeOf(T)); | 506 | comptime { |
| 460 | if (T == u8) return bytes[0]; | 507 | var bytes: [2]u8 = undefined; |
| 461 | var result: T = 0; | 508 | std.mem.writeIntBig(u16, &bytes, 0x1234); |
| 462 | { | 509 | const result = std.mem.readIntLittle(u16, &bytes); |
| 463 | comptime var i = 0; | 510 | testing.expect(result == 0x3412); |
| 464 | inline while (i < @sizeOf(T)) : (i += 1) { | ||
| 465 | result |= T(bytes[i]) << i * 8; | ||
| 466 | } | ||
| 467 | } | 511 | } |
| 468 | return result; | ||
| 469 | } | 512 | } |
| 470 | 513 | ||
| 471 | test "readIntBE/LE" { | 514 | test "readIntBig and readIntLittle" { |
| 472 | assert(readIntBE(u0, []u8{}) == 0x0); | 515 | testing.expect(readIntSliceBig(u0, []u8{}) == 0x0); |
| 473 | assert(readIntLE(u0, []u8{}) == 0x0); | 516 | testing.expect(readIntSliceLittle(u0, []u8{}) == 0x0); |
| 474 | 517 | ||
| 475 | assert(readIntBE(u8, []u8{0x32}) == 0x32); | 518 | testing.expect(readIntSliceBig(u8, []u8{0x32}) == 0x32); |
| 476 | assert(readIntLE(u8, []u8{0x12}) == 0x12); | 519 | testing.expect(readIntSliceLittle(u8, []u8{0x12}) == 0x12); |
| 477 | 520 | ||
| 478 | assert(readIntBE(u16, []u8{ 0x12, 0x34 }) == 0x1234); | 521 | testing.expect(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234); |
| 479 | assert(readIntLE(u16, []u8{ 0x12, 0x34 }) == 0x3412); | 522 | testing.expect(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412); |
| 480 | 523 | ||
| 481 | assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024); | 524 | testing.expect(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024); |
| 482 | assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); | 525 | testing.expect(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); |
| 483 | 526 | ||
| 484 | assert(readIntBE(i8, []u8{0xff}) == -1); | 527 | testing.expect(readIntSliceBig(i8, []u8{0xff}) == -1); |
| 485 | assert(readIntLE(i8, []u8{0xfe}) == -2); | 528 | testing.expect(readIntSliceLittle(i8, []u8{0xfe}) == -2); |
| 486 | 529 | ||
| 487 | assert(readIntBE(i16, []u8{ 0xff, 0xfd }) == -3); | 530 | testing.expect(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3); |
| 488 | assert(readIntLE(i16, []u8{ 0xfc, 0xff }) == -4); | 531 | testing.expect(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4); |
| 489 | } | 532 | } |
| 490 | 533 | ||
| 491 | /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes | 534 | /// Writes an integer to memory, storing it in twos-complement. |
| 492 | /// to fill the entire buffer provided. | 535 | /// This function always succeeds, has defined behavior for all inputs, and |
| 493 | /// value must be an integer. | 536 | /// accepts any integer bit width. |
| 494 | pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { | 537 | /// This function stores in native endian, which means it is implemented as a simple |
| 495 | const uint = @IntType(false, @typeOf(value).bit_count); | 538 | /// memory store. |
| 496 | var bits = @truncate(uint, value); | 539 | pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void { |
| 497 | switch (endian) { | 540 | @ptrCast(*align(1) T, buf).* = value; |
| 498 | builtin.Endian.Big => { | 541 | } |
| 499 | var index: usize = buf.len; | ||
| 500 | while (index != 0) { | ||
| 501 | index -= 1; | ||
| 502 | 542 | ||
| 503 | buf[index] = @truncate(u8, bits); | 543 | /// Writes an integer to memory, storing it in twos-complement. |
| 504 | bits >>= 8; | 544 | /// This function always succeeds, has defined behavior for all inputs, but |
| 505 | } | 545 | /// the integer bit width must be divisible by 8. |
| 506 | }, | 546 | /// This function stores in foreign endian, which means it does a @bswap first. |
| 507 | builtin.Endian.Little => { | 547 | pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void { |
| 508 | for (buf) |*b| { | 548 | writeIntNative(T, buf, @bswap(T, value)); |
| 509 | b.* = @truncate(u8, bits); | 549 | } |
| 510 | bits >>= 8; | 550 | |
| 511 | } | 551 | pub const writeIntLittle = switch (builtin.endian) { |
| 512 | }, | 552 | builtin.Endian.Little => writeIntNative, |
| 553 | builtin.Endian.Big => writeIntForeign, | ||
| 554 | }; | ||
| 555 | |||
| 556 | pub const writeIntBig = switch (builtin.endian) { | ||
| 557 | builtin.Endian.Little => writeIntForeign, | ||
| 558 | builtin.Endian.Big => writeIntNative, | ||
| 559 | }; | ||
| 560 | |||
| 561 | /// Writes an integer to memory, storing it in twos-complement. | ||
| 562 | /// This function always succeeds, has defined behavior for all inputs, but | ||
| 563 | /// the integer bit width must be divisible by 8. | ||
| 564 | pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void { | ||
| 565 | if (endian == builtin.endian) { | ||
| 566 | return writeIntNative(T, buffer, value); | ||
| 567 | } else { | ||
| 568 | return writeIntForeign(T, buffer, value); | ||
| 513 | } | 569 | } |
| 514 | assert(bits == 0); | ||
| 515 | } | 570 | } |
| 516 | 571 | ||
| 517 | pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | 572 | /// Writes a twos-complement little-endian integer to memory. |
| 518 | assert(T.bit_count % 8 == 0); | 573 | /// Asserts that buf.len >= T.bit_count / 8. |
| 574 | /// The bit count of T must be divisible by 8. | ||
| 575 | /// Any extra bytes in buffer after writing the integer are set to zero. To | ||
| 576 | /// avoid the branch to check for extra buffer bytes, use writeIntLittle | ||
| 577 | /// instead. | ||
| 578 | pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { | ||
| 579 | assert(buffer.len >= @divExact(T.bit_count, 8)); | ||
| 580 | |||
| 581 | // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough | ||
| 519 | const uint = @IntType(false, T.bit_count); | 582 | const uint = @IntType(false, T.bit_count); |
| 520 | if (uint == u0) { | 583 | var bits = @truncate(uint, value); |
| 521 | return; | 584 | for (buffer) |*b| { |
| 522 | } | 585 | b.* = @truncate(u8, bits); |
| 523 | var bits = @bitCast(uint, value); | 586 | bits >>= 8; |
| 524 | if (uint == u8) { | ||
| 525 | buf[0] = bits; | ||
| 526 | return; | ||
| 527 | } | 587 | } |
| 528 | var index: usize = buf.len; | 588 | } |
| 589 | |||
| 590 | /// Writes a twos-complement big-endian integer to memory. | ||
| 591 | /// Asserts that buffer.len >= T.bit_count / 8. | ||
| 592 | /// The bit count of T must be divisible by 8. | ||
| 593 | /// Any extra bytes in buffer before writing the integer are set to zero. To | ||
| 594 | /// avoid the branch to check for extra buffer bytes, use writeIntBig instead. | ||
| 595 | pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { | ||
| 596 | assert(buffer.len >= @divExact(T.bit_count, 8)); | ||
| 597 | |||
| 598 | // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough | ||
| 599 | const uint = @IntType(false, T.bit_count); | ||
| 600 | var bits = @truncate(uint, value); | ||
| 601 | var index: usize = buffer.len; | ||
| 529 | while (index != 0) { | 602 | while (index != 0) { |
| 530 | index -= 1; | 603 | index -= 1; |
| 531 | 604 | buffer[index] = @truncate(u8, bits); | |
| 532 | buf[index] = @truncate(u8, bits); | ||
| 533 | bits >>= 8; | 605 | bits >>= 8; |
| 534 | } | 606 | } |
| 535 | assert(bits == 0); | ||
| 536 | } | 607 | } |
| 537 | 608 | ||
| 538 | pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | 609 | pub const writeIntSliceNative = switch (builtin.endian) { |
| 539 | assert(T.bit_count % 8 == 0); | 610 | builtin.Endian.Little => writeIntSliceLittle, |
| 540 | const uint = @IntType(false, T.bit_count); | 611 | builtin.Endian.Big => writeIntSliceBig, |
| 541 | if (uint == u0) { | 612 | }; |
| 542 | return; | 613 | |
| 543 | } | 614 | pub const writeIntSliceForeign = switch (builtin.endian) { |
| 544 | var bits = @bitCast(uint, value); | 615 | builtin.Endian.Little => writeIntSliceBig, |
| 545 | if (uint == u8) { | 616 | builtin.Endian.Big => writeIntSliceLittle, |
| 546 | buf[0] = bits; | 617 | }; |
| 547 | return; | 618 | |
| 548 | } | 619 | /// Writes a twos-complement integer to memory, with the specified endianness. |
| 549 | for (buf) |*b| { | 620 | /// Asserts that buf.len >= T.bit_count / 8. |
| 550 | b.* = @truncate(u8, bits); | 621 | /// The bit count of T must be evenly divisible by 8. |
| 551 | bits >>= 8; | 622 | /// Any extra bytes in buffer not part of the integer are set to zero, with |
| 623 | /// respect to endianness. To avoid the branch to check for extra buffer bytes, | ||
| 624 | /// use writeInt instead. | ||
| 625 | pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void { | ||
| 626 | comptime assert(T.bit_count % 8 == 0); | ||
| 627 | switch (endian) { | ||
| 628 | builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value), | ||
| 629 | builtin.Endian.Big => return writeIntSliceBig(T, buffer, value), | ||
| 552 | } | 630 | } |
| 553 | assert(bits == 0); | ||
| 554 | } | 631 | } |
| 555 | 632 | ||
| 556 | test "writeIntBE/LE" { | 633 | test "writeIntBig and writeIntLittle" { |
| 557 | var buf0: [0]u8 = undefined; | 634 | var buf0: [0]u8 = undefined; |
| 558 | var buf1: [1]u8 = undefined; | 635 | var buf1: [1]u8 = undefined; |
| 559 | var buf2: [2]u8 = undefined; | 636 | var buf2: [2]u8 = undefined; |
| 560 | var buf9: [9]u8 = undefined; | 637 | var buf9: [9]u8 = undefined; |
| 561 | 638 | ||
| 562 | writeIntBE(u0, &buf0, 0x0); | 639 | writeIntBig(u0, &buf0, 0x0); |
| 563 | assert(eql_slice_u8(buf0[0..], []u8{})); | 640 | testing.expect(eql_slice_u8(buf0[0..], []u8{})); |
| 564 | writeIntLE(u0, &buf0, 0x0); | 641 | writeIntLittle(u0, &buf0, 0x0); |
| 565 | assert(eql_slice_u8(buf0[0..], []u8{})); | 642 | testing.expect(eql_slice_u8(buf0[0..], []u8{})); |
| 566 | 643 | ||
| 567 | writeIntBE(u8, &buf1, 0x12); | 644 | writeIntBig(u8, &buf1, 0x12); |
| 568 | assert(eql_slice_u8(buf1[0..], []u8{0x12})); | 645 | testing.expect(eql_slice_u8(buf1[0..], []u8{0x12})); |
| 569 | writeIntLE(u8, &buf1, 0x34); | 646 | writeIntLittle(u8, &buf1, 0x34); |
| 570 | assert(eql_slice_u8(buf1[0..], []u8{0x34})); | 647 | testing.expect(eql_slice_u8(buf1[0..], []u8{0x34})); |
| 571 | 648 | ||
| 572 | writeIntBE(u16, &buf2, 0x1234); | 649 | writeIntBig(u16, &buf2, 0x1234); |
| 573 | assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 })); | 650 | testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 })); |
| 574 | writeIntLE(u16, &buf2, 0x5678); | 651 | writeIntLittle(u16, &buf2, 0x5678); |
| 575 | assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 })); | 652 | testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 })); |
| 576 | 653 | ||
| 577 | writeIntBE(u72, &buf9, 0x123456789abcdef024); | 654 | writeIntBig(u72, &buf9, 0x123456789abcdef024); |
| 578 | assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); | 655 | testing.expect(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); |
| 579 | writeIntLE(u72, &buf9, 0xfedcba9876543210ec); | 656 | writeIntLittle(u72, &buf9, 0xfedcba9876543210ec); |
| 580 | assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); | 657 | testing.expect(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); |
| 581 | 658 | ||
| 582 | writeIntBE(i8, &buf1, -1); | 659 | writeIntBig(i8, &buf1, -1); |
| 583 | assert(eql_slice_u8(buf1[0..], []u8{0xff})); | 660 | testing.expect(eql_slice_u8(buf1[0..], []u8{0xff})); |
| 584 | writeIntLE(i8, &buf1, -2); | 661 | writeIntLittle(i8, &buf1, -2); |
| 585 | assert(eql_slice_u8(buf1[0..], []u8{0xfe})); | 662 | testing.expect(eql_slice_u8(buf1[0..], []u8{0xfe})); |
| 586 | 663 | ||
| 587 | writeIntBE(i16, &buf2, -3); | 664 | writeIntBig(i16, &buf2, -3); |
| 588 | assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd })); | 665 | testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd })); |
| 589 | writeIntLE(i16, &buf2, -4); | 666 | writeIntLittle(i16, &buf2, -4); |
| 590 | assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff })); | 667 | testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff })); |
| 591 | } | 668 | } |
| 592 | 669 | ||
| 593 | pub fn hash_slice_u8(k: []const u8) u32 { | 670 | pub fn hash_slice_u8(k: []const u8) u32 { |
| ... | @@ -604,23 +681,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { | ... | @@ -604,23 +681,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { |
| 604 | } | 681 | } |
| 605 | 682 | ||
| 606 | /// Returns an iterator that iterates over the slices of `buffer` that are not | 683 | /// Returns an iterator that iterates over the slices of `buffer` that are not |
| 607 | /// any of the bytes in `split_bytes`. | 684 | /// any of the bytes in `delimiter_bytes`. |
| 608 | /// split(" abc def ghi ", " ") | 685 | /// tokenize(" abc def ghi ", " ") |
| 609 | /// Will return slices for "abc", "def", "ghi", null, in that order. | 686 | /// Will return slices for "abc", "def", "ghi", null, in that order. |
| 610 | pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator { | 687 | /// If `buffer` is empty, the iterator will return null. |
| 688 | /// If `delimiter_bytes` does not exist in buffer, | ||
| 689 | /// the iterator will return `buffer`, null, in that order. | ||
| 690 | /// See also the related function `separate`. | ||
| 691 | pub fn tokenize(buffer: []const u8, delimiter_bytes: []const u8) TokenIterator { | ||
| 692 | return TokenIterator{ | ||
| 693 | .index = 0, | ||
| 694 | .buffer = buffer, | ||
| 695 | .delimiter_bytes = delimiter_bytes, | ||
| 696 | }; | ||
| 697 | } | ||
| 698 | |||
| 699 | test "mem.tokenize" { | ||
| 700 | var it = tokenize(" abc def ghi ", " "); | ||
| 701 | testing.expect(eql(u8, it.next().?, "abc")); | ||
| 702 | testing.expect(eql(u8, it.next().?, "def")); | ||
| 703 | testing.expect(eql(u8, it.next().?, "ghi")); | ||
| 704 | testing.expect(it.next() == null); | ||
| 705 | |||
| 706 | it = tokenize("..\\bob", "\\"); | ||
| 707 | testing.expect(eql(u8, it.next().?, "..")); | ||
| 708 | testing.expect(eql(u8, "..", "..\\bob"[0..it.index])); | ||
| 709 | testing.expect(eql(u8, it.next().?, "bob")); | ||
| 710 | testing.expect(it.next() == null); | ||
| 711 | |||
| 712 | it = tokenize("//a/b", "/"); | ||
| 713 | testing.expect(eql(u8, it.next().?, "a")); | ||
| 714 | testing.expect(eql(u8, it.next().?, "b")); | ||
| 715 | testing.expect(eql(u8, "//a/b", "//a/b"[0..it.index])); | ||
| 716 | testing.expect(it.next() == null); | ||
| 717 | |||
| 718 | it = tokenize("|", "|"); | ||
| 719 | testing.expect(it.next() == null); | ||
| 720 | |||
| 721 | it = tokenize("", "|"); | ||
| 722 | testing.expect(it.next() == null); | ||
| 723 | |||
| 724 | it = tokenize("hello", ""); | ||
| 725 | testing.expect(eql(u8, it.next().?, "hello")); | ||
| 726 | testing.expect(it.next() == null); | ||
| 727 | |||
| 728 | it = tokenize("hello", " "); | ||
| 729 | testing.expect(eql(u8, it.next().?, "hello")); | ||
| 730 | testing.expect(it.next() == null); | ||
| 731 | } | ||
| 732 | |||
| 733 | test "mem.tokenize (multibyte)" { | ||
| 734 | var it = tokenize("a|b,c/d e", " /,|"); | ||
| 735 | testing.expect(eql(u8, it.next().?, "a")); | ||
| 736 | testing.expect(eql(u8, it.next().?, "b")); | ||
| 737 | testing.expect(eql(u8, it.next().?, "c")); | ||
| 738 | testing.expect(eql(u8, it.next().?, "d")); | ||
| 739 | testing.expect(eql(u8, it.next().?, "e")); | ||
| 740 | testing.expect(it.next() == null); | ||
| 741 | } | ||
| 742 | |||
| 743 | /// Returns an iterator that iterates over the slices of `buffer` that | ||
| 744 | /// are separated by bytes in `delimiter`. | ||
| 745 | /// separate("abc|def||ghi", "|") | ||
| 746 | /// will return slices for "abc", "def", "", "ghi", null, in that order. | ||
| 747 | /// If `delimiter` does not exist in buffer, | ||
| 748 | /// the iterator will return `buffer`, null, in that order. | ||
| 749 | /// The delimiter length must not be zero. | ||
| 750 | /// See also the related function `tokenize`. | ||
| 751 | /// It is planned to rename this function to `split` before 1.0.0, like this: | ||
| 752 | /// pub fn split(buffer: []const u8, delimiter: []const u8) SplitIterator { | ||
| 753 | pub fn separate(buffer: []const u8, delimiter: []const u8) SplitIterator { | ||
| 754 | assert(delimiter.len != 0); | ||
| 611 | return SplitIterator{ | 755 | return SplitIterator{ |
| 612 | .index = 0, | 756 | .index = 0, |
| 613 | .buffer = buffer, | 757 | .buffer = buffer, |
| 614 | .split_bytes = split_bytes, | 758 | .delimiter = delimiter, |
| 615 | }; | 759 | }; |
| 616 | } | 760 | } |
| 617 | 761 | ||
| 618 | test "mem.split" { | 762 | test "mem.separate" { |
| 619 | var it = split(" abc def ghi ", " "); | 763 | var it = separate("abc|def||ghi", "|"); |
| 620 | assert(eql(u8, it.next().?, "abc")); | 764 | testing.expect(eql(u8, it.next().?, "abc")); |
| 621 | assert(eql(u8, it.next().?, "def")); | 765 | testing.expect(eql(u8, it.next().?, "def")); |
| 622 | assert(eql(u8, it.next().?, "ghi")); | 766 | testing.expect(eql(u8, it.next().?, "")); |
| 623 | assert(it.next() == null); | 767 | testing.expect(eql(u8, it.next().?, "ghi")); |
| 768 | testing.expect(it.next() == null); | ||
| 769 | |||
| 770 | it = separate("", "|"); | ||
| 771 | testing.expect(eql(u8, it.next().?, "")); | ||
| 772 | testing.expect(it.next() == null); | ||
| 773 | |||
| 774 | it = separate("|", "|"); | ||
| 775 | testing.expect(eql(u8, it.next().?, "")); | ||
| 776 | testing.expect(eql(u8, it.next().?, "")); | ||
| 777 | testing.expect(it.next() == null); | ||
| 778 | |||
| 779 | it = separate("hello", " "); | ||
| 780 | testing.expect(eql(u8, it.next().?, "hello")); | ||
| 781 | testing.expect(it.next() == null); | ||
| 782 | } | ||
| 783 | |||
| 784 | test "mem.separate (multibyte)" { | ||
| 785 | var it = separate("a, b ,, c, d, e", ", "); | ||
| 786 | testing.expect(eql(u8, it.next().?, "a")); | ||
| 787 | testing.expect(eql(u8, it.next().?, "b ,")); | ||
| 788 | testing.expect(eql(u8, it.next().?, "c")); | ||
| 789 | testing.expect(eql(u8, it.next().?, "d")); | ||
| 790 | testing.expect(eql(u8, it.next().?, "e")); | ||
| 791 | testing.expect(it.next() == null); | ||
| 624 | } | 792 | } |
| 625 | 793 | ||
| 626 | pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool { | 794 | pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool { |
| ... | @@ -628,8 +796,8 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool | ... | @@ -628,8 +796,8 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool |
| 628 | } | 796 | } |
| 629 | 797 | ||
| 630 | test "mem.startsWith" { | 798 | test "mem.startsWith" { |
| 631 | assert(startsWith(u8, "Bob", "Bo")); | 799 | testing.expect(startsWith(u8, "Bob", "Bo")); |
| 632 | assert(!startsWith(u8, "Needle in haystack", "haystack")); | 800 | testing.expect(!startsWith(u8, "Needle in haystack", "haystack")); |
| 633 | } | 801 | } |
| 634 | 802 | ||
| 635 | pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool { | 803 | pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool { |
| ... | @@ -637,16 +805,17 @@ pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool { | ... | @@ -637,16 +805,17 @@ pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool { |
| 637 | } | 805 | } |
| 638 | 806 | ||
| 639 | test "mem.endsWith" { | 807 | test "mem.endsWith" { |
| 640 | assert(endsWith(u8, "Needle in haystack", "haystack")); | 808 | testing.expect(endsWith(u8, "Needle in haystack", "haystack")); |
| 641 | assert(!endsWith(u8, "Bob", "Bo")); | 809 | testing.expect(!endsWith(u8, "Bob", "Bo")); |
| 642 | } | 810 | } |
| 643 | 811 | ||
| 644 | pub const SplitIterator = struct { | 812 | pub const TokenIterator = struct { |
| 645 | buffer: []const u8, | 813 | buffer: []const u8, |
| 646 | split_bytes: []const u8, | 814 | delimiter_bytes: []const u8, |
| 647 | index: usize, | 815 | index: usize, |
| 648 | 816 | ||
| 649 | pub fn next(self: *SplitIterator) ?[]const u8 { | 817 | /// Returns a slice of the next token, or null if tokenization is complete. |
| 818 | pub fn next(self: *TokenIterator) ?[]const u8 { | ||
| 650 | // move to beginning of token | 819 | // move to beginning of token |
| 651 | while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {} | 820 | while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {} |
| 652 | const start = self.index; | 821 | const start = self.index; |
| ... | @@ -662,16 +831,16 @@ pub const SplitIterator = struct { | ... | @@ -662,16 +831,16 @@ pub const SplitIterator = struct { |
| 662 | } | 831 | } |
| 663 | 832 | ||
| 664 | /// Returns a slice of the remaining bytes. Does not affect iterator state. | 833 | /// Returns a slice of the remaining bytes. Does not affect iterator state. |
| 665 | pub fn rest(self: *const SplitIterator) []const u8 { | 834 | pub fn rest(self: TokenIterator) []const u8 { |
| 666 | // move to beginning of token | 835 | // move to beginning of token |
| 667 | var index: usize = self.index; | 836 | var index: usize = self.index; |
| 668 | while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {} | 837 | while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {} |
| 669 | return self.buffer[index..]; | 838 | return self.buffer[index..]; |
| 670 | } | 839 | } |
| 671 | 840 | ||
| 672 | fn isSplitByte(self: *const SplitIterator, byte: u8) bool { | 841 | fn isSplitByte(self: TokenIterator, byte: u8) bool { |
| 673 | for (self.split_bytes) |split_byte| { | 842 | for (self.delimiter_bytes) |delimiter_byte| { |
| 674 | if (byte == split_byte) { | 843 | if (byte == delimiter_byte) { |
| 675 | return true; | 844 | return true; |
| 676 | } | 845 | } |
| 677 | } | 846 | } |
| ... | @@ -679,48 +848,72 @@ pub const SplitIterator = struct { | ... | @@ -679,48 +848,72 @@ pub const SplitIterator = struct { |
| 679 | } | 848 | } |
| 680 | }; | 849 | }; |
| 681 | 850 | ||
| 682 | /// Naively combines a series of strings with a separator. | 851 | pub const SplitIterator = struct { |
| 683 | /// Allocates memory for the result, which must be freed by the caller. | 852 | buffer: []const u8, |
| 684 | pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 { | 853 | index: ?usize, |
| 685 | comptime assert(strings.len >= 1); | 854 | delimiter: []const u8, |
| 686 | var total_strings_len: usize = strings.len; // 1 sep per string | 855 | |
| 687 | { | 856 | /// Returns a slice of the next field, or null if splitting is complete. |
| 688 | comptime var string_i = 0; | 857 | pub fn next(self: *SplitIterator) ?[]const u8 { |
| 689 | inline while (string_i < strings.len) : (string_i += 1) { | 858 | const start = self.index orelse return null; |
| 690 | const arg = ([]const u8)(strings[string_i]); | 859 | const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: { |
| 691 | total_strings_len += arg.len; | 860 | self.index = delim_start + self.delimiter.len; |
| 692 | } | 861 | break :blk delim_start; |
| 862 | } else blk: { | ||
| 863 | self.index = null; | ||
| 864 | break :blk self.buffer.len; | ||
| 865 | }; | ||
| 866 | return self.buffer[start..end]; | ||
| 693 | } | 867 | } |
| 694 | 868 | ||
| 695 | const buf = try allocator.alloc(u8, total_strings_len); | 869 | /// Returns a slice of the remaining bytes. Does not affect iterator state. |
| 870 | pub fn rest(self: SplitIterator) []const u8 { | ||
| 871 | const end = self.buffer.len; | ||
| 872 | const start = self.index orelse end; | ||
| 873 | return self.buffer[start..end]; | ||
| 874 | } | ||
| 875 | }; | ||
| 876 | |||
| 877 | /// Naively combines a series of slices with a separator. | ||
| 878 | /// Allocates memory for the result, which must be freed by the caller. | ||
| 879 | pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![]u8 { | ||
| 880 | if (slices.len == 0) return (([*]u8)(undefined))[0..0]; | ||
| 881 | |||
| 882 | const total_len = blk: { | ||
| 883 | var sum: usize = separator.len * (slices.len - 1); | ||
| 884 | for (slices) |slice| | ||
| 885 | sum += slice.len; | ||
| 886 | break :blk sum; | ||
| 887 | }; | ||
| 888 | |||
| 889 | const buf = try allocator.alloc(u8, total_len); | ||
| 696 | errdefer allocator.free(buf); | 890 | errdefer allocator.free(buf); |
| 697 | 891 | ||
| 698 | var buf_index: usize = 0; | 892 | copy(u8, buf, slices[0]); |
| 699 | comptime var string_i = 0; | 893 | var buf_index: usize = slices[0].len; |
| 700 | inline while (true) { | 894 | for (slices[1..]) |slice| { |
| 701 | const arg = ([]const u8)(strings[string_i]); | 895 | copy(u8, buf[buf_index..], separator); |
| 702 | string_i += 1; | 896 | buf_index += separator.len; |
| 703 | copy(u8, buf[buf_index..], arg); | 897 | copy(u8, buf[buf_index..], slice); |
| 704 | buf_index += arg.len; | 898 | buf_index += slice.len; |
| 705 | if (string_i >= strings.len) break; | ||
| 706 | if (buf[buf_index - 1] != sep) { | ||
| 707 | buf[buf_index] = sep; | ||
| 708 | buf_index += 1; | ||
| 709 | } | ||
| 710 | } | 899 | } |
| 711 | 900 | ||
| 712 | return allocator.shrink(u8, buf, buf_index); | 901 | // No need for shrink since buf is exactly the correct size. |
| 902 | return buf; | ||
| 713 | } | 903 | } |
| 714 | 904 | ||
| 715 | test "mem.join" { | 905 | test "mem.join" { |
| 716 | assert(eql(u8, try join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c")); | 906 | var buf: [1024]u8 = undefined; |
| 717 | assert(eql(u8, try join(debug.global_allocator, ',', "a"), "a")); | 907 | const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; |
| 908 | testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "b", "c" }), "a,b,c")); | ||
| 909 | testing.expect(eql(u8, try join(a, ",", [][]const u8{"a"}), "a")); | ||
| 910 | testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c")); | ||
| 718 | } | 911 | } |
| 719 | 912 | ||
| 720 | test "testStringEquality" { | 913 | test "testStringEquality" { |
| 721 | assert(eql(u8, "abcd", "abcd")); | 914 | testing.expect(eql(u8, "abcd", "abcd")); |
| 722 | assert(!eql(u8, "abcdef", "abZdef")); | 915 | testing.expect(!eql(u8, "abcdef", "abZdef")); |
| 723 | assert(!eql(u8, "abcdefg", "abcdef")); | 916 | testing.expect(!eql(u8, "abcdefg", "abcdef")); |
| 724 | } | 917 | } |
| 725 | 918 | ||
| 726 | test "testReadInt" { | 919 | test "testReadInt" { |
| ... | @@ -735,12 +928,12 @@ fn testReadIntImpl() void { | ... | @@ -735,12 +928,12 @@ fn testReadIntImpl() void { |
| 735 | 0x56, | 928 | 0x56, |
| 736 | 0x78, | 929 | 0x78, |
| 737 | }; | 930 | }; |
| 738 | assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); | 931 | testing.expect(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678); |
| 739 | assert(readIntBE(u32, bytes) == 0x12345678); | 932 | testing.expect(readIntBig(u32, &bytes) == 0x12345678); |
| 740 | assert(readIntBE(i32, bytes) == 0x12345678); | 933 | testing.expect(readIntBig(i32, &bytes) == 0x12345678); |
| 741 | assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412); | 934 | testing.expect(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412); |
| 742 | assert(readIntLE(u32, bytes) == 0x78563412); | 935 | testing.expect(readIntLittle(u32, &bytes) == 0x78563412); |
| 743 | assert(readIntLE(i32, bytes) == 0x78563412); | 936 | testing.expect(readIntLittle(i32, &bytes) == 0x78563412); |
| 744 | } | 937 | } |
| 745 | { | 938 | { |
| 746 | const buf = []u8{ | 939 | const buf = []u8{ |
| ... | @@ -749,8 +942,8 @@ fn testReadIntImpl() void { | ... | @@ -749,8 +942,8 @@ fn testReadIntImpl() void { |
| 749 | 0x12, | 942 | 0x12, |
| 750 | 0x34, | 943 | 0x34, |
| 751 | }; | 944 | }; |
| 752 | const answer = readInt(buf, u64, builtin.Endian.Big); | 945 | const answer = readInt(u32, &buf, builtin.Endian.Big); |
| 753 | assert(answer == 0x00001234); | 946 | testing.expect(answer == 0x00001234); |
| 754 | } | 947 | } |
| 755 | { | 948 | { |
| 756 | const buf = []u8{ | 949 | const buf = []u8{ |
| ... | @@ -759,30 +952,42 @@ fn testReadIntImpl() void { | ... | @@ -759,30 +952,42 @@ fn testReadIntImpl() void { |
| 759 | 0x00, | 952 | 0x00, |
| 760 | 0x00, | 953 | 0x00, |
| 761 | }; | 954 | }; |
| 762 | const answer = readInt(buf, u64, builtin.Endian.Little); | 955 | const answer = readInt(u32, &buf, builtin.Endian.Little); |
| 763 | assert(answer == 0x00003412); | 956 | testing.expect(answer == 0x00003412); |
| 764 | } | 957 | } |
| 765 | { | 958 | { |
| 766 | const bytes = []u8{ | 959 | const bytes = []u8{ |
| 767 | 0xff, | 960 | 0xff, |
| 768 | 0xfe, | 961 | 0xfe, |
| 769 | }; | 962 | }; |
| 770 | assert(readIntBE(u16, bytes) == 0xfffe); | 963 | testing.expect(readIntBig(u16, &bytes) == 0xfffe); |
| 771 | assert(readIntBE(i16, bytes) == -0x0002); | 964 | testing.expect(readIntBig(i16, &bytes) == -0x0002); |
| 772 | assert(readIntLE(u16, bytes) == 0xfeff); | 965 | testing.expect(readIntLittle(u16, &bytes) == 0xfeff); |
| 773 | assert(readIntLE(i16, bytes) == -0x0101); | 966 | testing.expect(readIntLittle(i16, &bytes) == -0x0101); |
| 774 | } | 967 | } |
| 775 | } | 968 | } |
| 776 | 969 | ||
| 777 | test "testWriteInt" { | 970 | test "std.mem.writeIntSlice" { |
| 778 | testWriteIntImpl(); | 971 | testWriteIntImpl(); |
| 779 | comptime testWriteIntImpl(); | 972 | comptime testWriteIntImpl(); |
| 780 | } | 973 | } |
| 781 | fn testWriteIntImpl() void { | 974 | fn testWriteIntImpl() void { |
| 782 | var bytes: [8]u8 = undefined; | 975 | var bytes: [8]u8 = undefined; |
| 783 | 976 | ||
| 784 | writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big); | 977 | writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big); |
| 785 | assert(eql(u8, bytes, []u8{ | 978 | testing.expect(eql(u8, bytes, []u8{ |
| 979 | 0x00, 0x00, 0x00, 0x00, | ||
| 980 | 0x00, 0x00, 0x00, 0x00, | ||
| 981 | })); | ||
| 982 | |||
| 983 | writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little); | ||
| 984 | testing.expect(eql(u8, bytes, []u8{ | ||
| 985 | 0x00, 0x00, 0x00, 0x00, | ||
| 986 | 0x00, 0x00, 0x00, 0x00, | ||
| 987 | })); | ||
| 988 | |||
| 989 | writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big); | ||
| 990 | testing.expect(eql(u8, bytes, []u8{ | ||
| 786 | 0x12, | 991 | 0x12, |
| 787 | 0x34, | 992 | 0x34, |
| 788 | 0x56, | 993 | 0x56, |
| ... | @@ -793,8 +998,8 @@ fn testWriteIntImpl() void { | ... | @@ -793,8 +998,8 @@ fn testWriteIntImpl() void { |
| 793 | 0xBE, | 998 | 0xBE, |
| 794 | })); | 999 | })); |
| 795 | 1000 | ||
| 796 | writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little); | 1001 | writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little); |
| 797 | assert(eql(u8, bytes, []u8{ | 1002 | testing.expect(eql(u8, bytes, []u8{ |
| 798 | 0x12, | 1003 | 0x12, |
| 799 | 0x34, | 1004 | 0x34, |
| 800 | 0x56, | 1005 | 0x56, |
| ... | @@ -805,8 +1010,8 @@ fn testWriteIntImpl() void { | ... | @@ -805,8 +1010,8 @@ fn testWriteIntImpl() void { |
| 805 | 0xBE, | 1010 | 0xBE, |
| 806 | })); | 1011 | })); |
| 807 | 1012 | ||
| 808 | writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big); | 1013 | writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big); |
| 809 | assert(eql(u8, bytes, []u8{ | 1014 | testing.expect(eql(u8, bytes, []u8{ |
| 810 | 0x00, | 1015 | 0x00, |
| 811 | 0x00, | 1016 | 0x00, |
| 812 | 0x00, | 1017 | 0x00, |
| ... | @@ -817,8 +1022,8 @@ fn testWriteIntImpl() void { | ... | @@ -817,8 +1022,8 @@ fn testWriteIntImpl() void { |
| 817 | 0x78, | 1022 | 0x78, |
| 818 | })); | 1023 | })); |
| 819 | 1024 | ||
| 820 | writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little); | 1025 | writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little); |
| 821 | assert(eql(u8, bytes, []u8{ | 1026 | testing.expect(eql(u8, bytes, []u8{ |
| 822 | 0x12, | 1027 | 0x12, |
| 823 | 0x34, | 1028 | 0x34, |
| 824 | 0x56, | 1029 | 0x56, |
| ... | @@ -829,8 +1034,8 @@ fn testWriteIntImpl() void { | ... | @@ -829,8 +1034,8 @@ fn testWriteIntImpl() void { |
| 829 | 0x00, | 1034 | 0x00, |
| 830 | })); | 1035 | })); |
| 831 | 1036 | ||
| 832 | writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big); | 1037 | writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big); |
| 833 | assert(eql(u8, bytes, []u8{ | 1038 | testing.expect(eql(u8, bytes, []u8{ |
| 834 | 0x00, | 1039 | 0x00, |
| 835 | 0x00, | 1040 | 0x00, |
| 836 | 0x00, | 1041 | 0x00, |
| ... | @@ -841,8 +1046,8 @@ fn testWriteIntImpl() void { | ... | @@ -841,8 +1046,8 @@ fn testWriteIntImpl() void { |
| 841 | 0x34, | 1046 | 0x34, |
| 842 | })); | 1047 | })); |
| 843 | 1048 | ||
| 844 | writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little); | 1049 | writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little); |
| 845 | assert(eql(u8, bytes, []u8{ | 1050 | testing.expect(eql(u8, bytes, []u8{ |
| 846 | 0x34, | 1051 | 0x34, |
| 847 | 0x12, | 1052 | 0x12, |
| 848 | 0x00, | 1053 | 0x00, |
| ... | @@ -863,7 +1068,7 @@ pub fn min(comptime T: type, slice: []const T) T { | ... | @@ -863,7 +1068,7 @@ pub fn min(comptime T: type, slice: []const T) T { |
| 863 | } | 1068 | } |
| 864 | 1069 | ||
| 865 | test "mem.min" { | 1070 | test "mem.min" { |
| 866 | assert(min(u8, "abcdefg") == 'a'); | 1071 | testing.expect(min(u8, "abcdefg") == 'a'); |
| 867 | } | 1072 | } |
| 868 | 1073 | ||
| 869 | pub fn max(comptime T: type, slice: []const T) T { | 1074 | pub fn max(comptime T: type, slice: []const T) T { |
| ... | @@ -875,7 +1080,7 @@ pub fn max(comptime T: type, slice: []const T) T { | ... | @@ -875,7 +1080,7 @@ pub fn max(comptime T: type, slice: []const T) T { |
| 875 | } | 1080 | } |
| 876 | 1081 | ||
| 877 | test "mem.max" { | 1082 | test "mem.max" { |
| 878 | assert(max(u8, "abcdefg") == 'g'); | 1083 | testing.expect(max(u8, "abcdefg") == 'g'); |
| 879 | } | 1084 | } |
| 880 | 1085 | ||
| 881 | pub fn swap(comptime T: type, a: *T, b: *T) void { | 1086 | pub fn swap(comptime T: type, a: *T, b: *T) void { |
| ... | @@ -903,7 +1108,7 @@ test "std.mem.reverse" { | ... | @@ -903,7 +1108,7 @@ test "std.mem.reverse" { |
| 903 | }; | 1108 | }; |
| 904 | reverse(i32, arr[0..]); | 1109 | reverse(i32, arr[0..]); |
| 905 | 1110 | ||
| 906 | assert(eql(i32, arr, []i32{ | 1111 | testing.expect(eql(i32, arr, []i32{ |
| 907 | 4, | 1112 | 4, |
| 908 | 2, | 1113 | 2, |
| 909 | 1, | 1114 | 1, |
| ... | @@ -930,7 +1135,7 @@ test "std.mem.rotate" { | ... | @@ -930,7 +1135,7 @@ test "std.mem.rotate" { |
| 930 | }; | 1135 | }; |
| 931 | rotate(i32, arr[0..], 2); | 1136 | rotate(i32, arr[0..], 2); |
| 932 | 1137 | ||
| 933 | assert(eql(i32, arr, []i32{ | 1138 | testing.expect(eql(i32, arr, []i32{ |
| 934 | 1, | 1139 | 1, |
| 935 | 2, | 1140 | 2, |
| 936 | 4, | 1141 | 4, |
| ... | @@ -939,29 +1144,52 @@ test "std.mem.rotate" { | ... | @@ -939,29 +1144,52 @@ test "std.mem.rotate" { |
| 939 | })); | 1144 | })); |
| 940 | } | 1145 | } |
| 941 | 1146 | ||
| 942 | // TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by | 1147 | /// Converts a little-endian integer to host endianness. |
| 943 | // endian-casting the pointer and then dereferencing | 1148 | pub fn littleToNative(comptime T: type, x: T) T { |
| 1149 | return switch (builtin.endian) { | ||
| 1150 | builtin.Endian.Little => x, | ||
| 1151 | builtin.Endian.Big => @bswap(T, x), | ||
| 1152 | }; | ||
| 1153 | } | ||
| 944 | 1154 | ||
| 945 | pub fn endianSwapIfLe(comptime T: type, x: T) T { | 1155 | /// Converts a big-endian integer to host endianness. |
| 946 | return endianSwapIf(builtin.Endian.Little, T, x); | 1156 | pub fn bigToNative(comptime T: type, x: T) T { |
| 1157 | return switch (builtin.endian) { | ||
| 1158 | builtin.Endian.Little => @bswap(T, x), | ||
| 1159 | builtin.Endian.Big => x, | ||
| 1160 | }; | ||
| 947 | } | 1161 | } |
| 948 | 1162 | ||
| 949 | pub fn endianSwapIfBe(comptime T: type, x: T) T { | 1163 | /// Converts an integer from specified endianness to host endianness. |
| 950 | return endianSwapIf(builtin.Endian.Big, T, x); | 1164 | pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T { |
| 1165 | return switch (endianness_of_x) { | ||
| 1166 | builtin.Endian.Little => littleToNative(T, x), | ||
| 1167 | builtin.Endian.Big => bigToNative(T, x), | ||
| 1168 | }; | ||
| 951 | } | 1169 | } |
| 952 | 1170 | ||
| 953 | pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T { | 1171 | /// Converts an integer which has host endianness to the desired endianness. |
| 954 | return if (builtin.endian == endian) endianSwap(T, x) else x; | 1172 | pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T { |
| 1173 | return switch (desired_endianness) { | ||
| 1174 | builtin.Endian.Little => nativeToLittle(T, x), | ||
| 1175 | builtin.Endian.Big => nativeToBig(T, x), | ||
| 1176 | }; | ||
| 955 | } | 1177 | } |
| 956 | 1178 | ||
| 957 | pub fn endianSwap(comptime T: type, x: T) T { | 1179 | /// Converts an integer which has host endianness to little endian. |
| 958 | var buf: [@sizeOf(T)]u8 = undefined; | 1180 | pub fn nativeToLittle(comptime T: type, x: T) T { |
| 959 | mem.writeInt(buf[0..], x, builtin.Endian.Little); | 1181 | return switch (builtin.endian) { |
| 960 | return mem.readInt(buf, T, builtin.Endian.Big); | 1182 | builtin.Endian.Little => x, |
| 1183 | builtin.Endian.Big => @bswap(T, x), | ||
| 1184 | }; | ||
| 961 | } | 1185 | } |
| 962 | 1186 | ||
| 963 | test "std.mem.endianSwap" { | 1187 | /// Converts an integer which has host endianness to big endian. |
| 964 | assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE); | 1188 | pub fn nativeToBig(comptime T: type, x: T) T { |
| 1189 | return switch (builtin.endian) { | ||
| 1190 | builtin.Endian.Little => @bswap(T, x), | ||
| 1191 | builtin.Endian.Big => x, | ||
| 1192 | }; | ||
| 965 | } | 1193 | } |
| 966 | 1194 | ||
| 967 | fn AsBytesReturnType(comptime P: type) type { | 1195 | fn AsBytesReturnType(comptime P: type) type { |
| ... | @@ -989,12 +1217,12 @@ test "std.mem.asBytes" { | ... | @@ -989,12 +1217,12 @@ test "std.mem.asBytes" { |
| 989 | builtin.Endian.Little => "\xEF\xBE\xAD\xDE", | 1217 | builtin.Endian.Little => "\xEF\xBE\xAD\xDE", |
| 990 | }; | 1218 | }; |
| 991 | 1219 | ||
| 992 | debug.assert(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes)); | 1220 | testing.expect(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes)); |
| 993 | 1221 | ||
| 994 | var codeface = u32(0xC0DEFACE); | 1222 | var codeface = u32(0xC0DEFACE); |
| 995 | for (asBytes(&codeface).*) |*b| | 1223 | for (asBytes(&codeface).*) |*b| |
| 996 | b.* = 0; | 1224 | b.* = 0; |
| 997 | debug.assert(codeface == 0); | 1225 | testing.expect(codeface == 0); |
| 998 | 1226 | ||
| 999 | const S = packed struct { | 1227 | const S = packed struct { |
| 1000 | a: u8, | 1228 | a: u8, |
| ... | @@ -1009,7 +1237,7 @@ test "std.mem.asBytes" { | ... | @@ -1009,7 +1237,7 @@ test "std.mem.asBytes" { |
| 1009 | .c = 0xDE, | 1237 | .c = 0xDE, |
| 1010 | .d = 0xA1, | 1238 | .d = 0xA1, |
| 1011 | }; | 1239 | }; |
| 1012 | debug.assert(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1")); | 1240 | testing.expect(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1")); |
| 1013 | } | 1241 | } |
| 1014 | 1242 | ||
| 1015 | ///Given any value, returns a copy of its bytes in an array. | 1243 | ///Given any value, returns a copy of its bytes in an array. |
| ... | @@ -1020,14 +1248,14 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 { | ... | @@ -1020,14 +1248,14 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 { |
| 1020 | test "std.mem.toBytes" { | 1248 | test "std.mem.toBytes" { |
| 1021 | var my_bytes = toBytes(u32(0x12345678)); | 1249 | var my_bytes = toBytes(u32(0x12345678)); |
| 1022 | switch (builtin.endian) { | 1250 | switch (builtin.endian) { |
| 1023 | builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")), | 1251 | builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")), |
| 1024 | builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")), | 1252 | builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")), |
| 1025 | } | 1253 | } |
| 1026 | 1254 | ||
| 1027 | my_bytes[0] = '\x99'; | 1255 | my_bytes[0] = '\x99'; |
| 1028 | switch (builtin.endian) { | 1256 | switch (builtin.endian) { |
| 1029 | builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")), | 1257 | builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")), |
| 1030 | builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")), | 1258 | builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")), |
| 1031 | } | 1259 | } |
| 1032 | } | 1260 | } |
| 1033 | 1261 | ||
| ... | @@ -1056,17 +1284,17 @@ test "std.mem.bytesAsValue" { | ... | @@ -1056,17 +1284,17 @@ test "std.mem.bytesAsValue" { |
| 1056 | builtin.Endian.Little => "\xEF\xBE\xAD\xDE", | 1284 | builtin.Endian.Little => "\xEF\xBE\xAD\xDE", |
| 1057 | }; | 1285 | }; |
| 1058 | 1286 | ||
| 1059 | debug.assert(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*); | 1287 | testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*); |
| 1060 | 1288 | ||
| 1061 | var codeface_bytes = switch (builtin.endian) { | 1289 | var codeface_bytes = switch (builtin.endian) { |
| 1062 | builtin.Endian.Big => "\xC0\xDE\xFA\xCE", | 1290 | builtin.Endian.Big => "\xC0\xDE\xFA\xCE", |
| 1063 | builtin.Endian.Little => "\xCE\xFA\xDE\xC0", | 1291 | builtin.Endian.Little => "\xCE\xFA\xDE\xC0", |
| 1064 | }; | 1292 | }; |
| 1065 | var codeface = bytesAsValue(u32, &codeface_bytes); | 1293 | var codeface = bytesAsValue(u32, &codeface_bytes); |
| 1066 | debug.assert(codeface.* == 0xC0DEFACE); | 1294 | testing.expect(codeface.* == 0xC0DEFACE); |
| 1067 | codeface.* = 0; | 1295 | codeface.* = 0; |
| 1068 | for (codeface_bytes) |b| | 1296 | for (codeface_bytes) |b| |
| 1069 | debug.assert(b == 0); | 1297 | testing.expect(b == 0); |
| 1070 | 1298 | ||
| 1071 | const S = packed struct { | 1299 | const S = packed struct { |
| 1072 | a: u8, | 1300 | a: u8, |
| ... | @@ -1083,7 +1311,7 @@ test "std.mem.bytesAsValue" { | ... | @@ -1083,7 +1311,7 @@ test "std.mem.bytesAsValue" { |
| 1083 | }; | 1311 | }; |
| 1084 | const inst_bytes = "\xBE\xEF\xDE\xA1"; | 1312 | const inst_bytes = "\xBE\xEF\xDE\xA1"; |
| 1085 | const inst2 = bytesAsValue(S, &inst_bytes); | 1313 | const inst2 = bytesAsValue(S, &inst_bytes); |
| 1086 | debug.assert(meta.eql(inst, inst2.*)); | 1314 | testing.expect(meta.eql(inst, inst2.*)); |
| 1087 | } | 1315 | } |
| 1088 | 1316 | ||
| 1089 | ///Given a pointer to an array of bytes, returns a value of the specified type backed by a | 1317 | ///Given a pointer to an array of bytes, returns a value of the specified type backed by a |
| ... | @@ -1098,7 +1326,7 @@ test "std.mem.bytesToValue" { | ... | @@ -1098,7 +1326,7 @@ test "std.mem.bytesToValue" { |
| 1098 | }; | 1326 | }; |
| 1099 | 1327 | ||
| 1100 | const deadbeef = bytesToValue(u32, deadbeef_bytes); | 1328 | const deadbeef = bytesToValue(u32, deadbeef_bytes); |
| 1101 | debug.assert(deadbeef == u32(0xDEADBEEF)); | 1329 | testing.expect(deadbeef == u32(0xDEADBEEF)); |
| 1102 | } | 1330 | } |
| 1103 | 1331 | ||
| 1104 | fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { | 1332 | fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { |
| ... | @@ -1109,7 +1337,7 @@ fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { | ... | @@ -1109,7 +1337,7 @@ fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { |
| 1109 | 1337 | ||
| 1110 | ///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness. | 1338 | ///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness. |
| 1111 | pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubArrayPtrReturnType(@typeOf(ptr), length) { | 1339 | pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubArrayPtrReturnType(@typeOf(ptr), length) { |
| 1112 | debug.assert(start + length <= ptr.*.len); | 1340 | assert(start + length <= ptr.*.len); |
| 1113 | 1341 | ||
| 1114 | const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length); | 1342 | const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length); |
| 1115 | const T = meta.Child(meta.Child(@typeOf(ptr))); | 1343 | const T = meta.Child(meta.Child(@typeOf(ptr))); |
| ... | @@ -1119,12 +1347,32 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA | ... | @@ -1119,12 +1347,32 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA |
| 1119 | test "std.mem.subArrayPtr" { | 1347 | test "std.mem.subArrayPtr" { |
| 1120 | const a1 = "abcdef"; | 1348 | const a1 = "abcdef"; |
| 1121 | const sub1 = subArrayPtr(&a1, 2, 3); | 1349 | const sub1 = subArrayPtr(&a1, 2, 3); |
| 1122 | debug.assert(std.mem.eql(u8, sub1.*, "cde")); | 1350 | testing.expect(std.mem.eql(u8, sub1.*, "cde")); |
| 1123 | 1351 | ||
| 1124 | var a2 = "abcdef"; | 1352 | var a2 = "abcdef"; |
| 1125 | var sub2 = subArrayPtr(&a2, 2, 3); | 1353 | var sub2 = subArrayPtr(&a2, 2, 3); |
| 1126 | 1354 | ||
| 1127 | debug.assert(std.mem.eql(u8, sub2, "cde")); | 1355 | testing.expect(std.mem.eql(u8, sub2, "cde")); |
| 1128 | sub2[1] = 'X'; | 1356 | sub2[1] = 'X'; |
| 1129 | debug.assert(std.mem.eql(u8, a2, "abcXef")); | 1357 | testing.expect(std.mem.eql(u8, a2, "abcXef")); |
| 1358 | } | ||
| 1359 | |||
| 1360 | /// Round an address up to the nearest aligned address | ||
| 1361 | pub fn alignForward(addr: usize, alignment: usize) usize { | ||
| 1362 | return (addr + alignment - 1) & ~(alignment - 1); | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | test "std.mem.alignForward" { | ||
| 1366 | testing.expect(alignForward(1, 1) == 1); | ||
| 1367 | testing.expect(alignForward(2, 1) == 2); | ||
| 1368 | testing.expect(alignForward(1, 2) == 2); | ||
| 1369 | testing.expect(alignForward(2, 2) == 2); | ||
| 1370 | testing.expect(alignForward(3, 2) == 4); | ||
| 1371 | testing.expect(alignForward(4, 2) == 4); | ||
| 1372 | testing.expect(alignForward(7, 8) == 8); | ||
| 1373 | testing.expect(alignForward(8, 8) == 8); | ||
| 1374 | testing.expect(alignForward(9, 8) == 16); | ||
| 1375 | testing.expect(alignForward(15, 8) == 16); | ||
| 1376 | testing.expect(alignForward(16, 8) == 16); | ||
| 1377 | testing.expect(alignForward(17, 8) == 24); | ||
| 1130 | } | 1378 | } |
std/meta/index.zig+112-76| ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 3 | const debug = std.debug; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const math = std.math; | 5 | const math = std.math; |
| 6 | const testing = std.testing; | ||
| 6 | 7 | ||
| 7 | pub const trait = @import("trait.zig"); | 8 | pub const trait = @import("trait.zig"); |
| 8 | 9 | ||
| ... | @@ -64,16 +65,16 @@ test "std.meta.tagName" { | ... | @@ -64,16 +65,16 @@ test "std.meta.tagName" { |
| 64 | var u2a = U2{ .C = 0 }; | 65 | var u2a = U2{ .C = 0 }; |
| 65 | var u2b = U2{ .D = 0 }; | 66 | var u2b = U2{ .D = 0 }; |
| 66 | 67 | ||
| 67 | debug.assert(mem.eql(u8, tagName(E1.A), "A")); | 68 | testing.expect(mem.eql(u8, tagName(E1.A), "A")); |
| 68 | debug.assert(mem.eql(u8, tagName(E1.B), "B")); | 69 | testing.expect(mem.eql(u8, tagName(E1.B), "B")); |
| 69 | debug.assert(mem.eql(u8, tagName(E2.C), "C")); | 70 | testing.expect(mem.eql(u8, tagName(E2.C), "C")); |
| 70 | debug.assert(mem.eql(u8, tagName(E2.D), "D")); | 71 | testing.expect(mem.eql(u8, tagName(E2.D), "D")); |
| 71 | debug.assert(mem.eql(u8, tagName(error.E), "E")); | 72 | testing.expect(mem.eql(u8, tagName(error.E), "E")); |
| 72 | debug.assert(mem.eql(u8, tagName(error.F), "F")); | 73 | testing.expect(mem.eql(u8, tagName(error.F), "F")); |
| 73 | debug.assert(mem.eql(u8, tagName(u1g), "G")); | 74 | testing.expect(mem.eql(u8, tagName(u1g), "G")); |
| 74 | debug.assert(mem.eql(u8, tagName(u1h), "H")); | 75 | testing.expect(mem.eql(u8, tagName(u1h), "H")); |
| 75 | debug.assert(mem.eql(u8, tagName(u2a), "C")); | 76 | testing.expect(mem.eql(u8, tagName(u2a), "C")); |
| 76 | debug.assert(mem.eql(u8, tagName(u2b), "D")); | 77 | testing.expect(mem.eql(u8, tagName(u2b), "D")); |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | pub fn stringToEnum(comptime T: type, str: []const u8) ?T { | 80 | pub fn stringToEnum(comptime T: type, str: []const u8) ?T { |
| ... | @@ -90,12 +91,12 @@ test "std.meta.stringToEnum" { | ... | @@ -90,12 +91,12 @@ test "std.meta.stringToEnum" { |
| 90 | A, | 91 | A, |
| 91 | B, | 92 | B, |
| 92 | }; | 93 | }; |
| 93 | debug.assert(E1.A == stringToEnum(E1, "A").?); | 94 | testing.expect(E1.A == stringToEnum(E1, "A").?); |
| 94 | debug.assert(E1.B == stringToEnum(E1, "B").?); | 95 | testing.expect(E1.B == stringToEnum(E1, "B").?); |
| 95 | debug.assert(null == stringToEnum(E1, "C")); | 96 | testing.expect(null == stringToEnum(E1, "C")); |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | pub fn bitCount(comptime T: type) u32 { | 99 | pub fn bitCount(comptime T: type) comptime_int { |
| 99 | return switch (@typeInfo(T)) { | 100 | return switch (@typeInfo(T)) { |
| 100 | TypeId.Int => |info| info.bits, | 101 | TypeId.Int => |info| info.bits, |
| 101 | TypeId.Float => |info| info.bits, | 102 | TypeId.Float => |info| info.bits, |
| ... | @@ -104,22 +105,22 @@ pub fn bitCount(comptime T: type) u32 { | ... | @@ -104,22 +105,22 @@ pub fn bitCount(comptime T: type) u32 { |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | test "std.meta.bitCount" { | 107 | test "std.meta.bitCount" { |
| 107 | debug.assert(bitCount(u8) == 8); | 108 | testing.expect(bitCount(u8) == 8); |
| 108 | debug.assert(bitCount(f32) == 32); | 109 | testing.expect(bitCount(f32) == 32); |
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | pub fn alignment(comptime T: type) u29 { | 112 | pub fn alignment(comptime T: type) comptime_int { |
| 112 | //@alignOf works on non-pointer types | 113 | //@alignOf works on non-pointer types |
| 113 | const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T; | 114 | const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T; |
| 114 | return @typeInfo(P).Pointer.alignment; | 115 | return @typeInfo(P).Pointer.alignment; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | test "std.meta.alignment" { | 118 | test "std.meta.alignment" { |
| 118 | debug.assert(alignment(u8) == 1); | 119 | testing.expect(alignment(u8) == 1); |
| 119 | debug.assert(alignment(*align(1) u8) == 1); | 120 | testing.expect(alignment(*align(1) u8) == 1); |
| 120 | debug.assert(alignment(*align(2) u8) == 2); | 121 | testing.expect(alignment(*align(2) u8) == 2); |
| 121 | debug.assert(alignment([]align(1) u8) == 1); | 122 | testing.expect(alignment([]align(1) u8) == 1); |
| 122 | debug.assert(alignment([]align(2) u8) == 2); | 123 | testing.expect(alignment([]align(2) u8) == 2); |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | pub fn Child(comptime T: type) type { | 126 | pub fn Child(comptime T: type) type { |
| ... | @@ -133,11 +134,11 @@ pub fn Child(comptime T: type) type { | ... | @@ -133,11 +134,11 @@ pub fn Child(comptime T: type) type { |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | test "std.meta.Child" { | 136 | test "std.meta.Child" { |
| 136 | debug.assert(Child([1]u8) == u8); | 137 | testing.expect(Child([1]u8) == u8); |
| 137 | debug.assert(Child(*u8) == u8); | 138 | testing.expect(Child(*u8) == u8); |
| 138 | debug.assert(Child([]u8) == u8); | 139 | testing.expect(Child([]u8) == u8); |
| 139 | debug.assert(Child(?u8) == u8); | 140 | testing.expect(Child(?u8) == u8); |
| 140 | debug.assert(Child(promise->u8) == u8); | 141 | testing.expect(Child(promise->u8) == u8); |
| 141 | } | 142 | } |
| 142 | 143 | ||
| 143 | pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { | 144 | pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { |
| ... | @@ -172,15 +173,15 @@ test "std.meta.containerLayout" { | ... | @@ -172,15 +173,15 @@ test "std.meta.containerLayout" { |
| 172 | a: u8, | 173 | a: u8, |
| 173 | }; | 174 | }; |
| 174 | 175 | ||
| 175 | debug.assert(containerLayout(E1) == TypeInfo.ContainerLayout.Auto); | 176 | testing.expect(containerLayout(E1) == TypeInfo.ContainerLayout.Auto); |
| 176 | debug.assert(containerLayout(E2) == TypeInfo.ContainerLayout.Packed); | 177 | testing.expect(containerLayout(E2) == TypeInfo.ContainerLayout.Packed); |
| 177 | debug.assert(containerLayout(E3) == TypeInfo.ContainerLayout.Extern); | 178 | testing.expect(containerLayout(E3) == TypeInfo.ContainerLayout.Extern); |
| 178 | debug.assert(containerLayout(S1) == TypeInfo.ContainerLayout.Auto); | 179 | testing.expect(containerLayout(S1) == TypeInfo.ContainerLayout.Auto); |
| 179 | debug.assert(containerLayout(S2) == TypeInfo.ContainerLayout.Packed); | 180 | testing.expect(containerLayout(S2) == TypeInfo.ContainerLayout.Packed); |
| 180 | debug.assert(containerLayout(S3) == TypeInfo.ContainerLayout.Extern); | 181 | testing.expect(containerLayout(S3) == TypeInfo.ContainerLayout.Extern); |
| 181 | debug.assert(containerLayout(U1) == TypeInfo.ContainerLayout.Auto); | 182 | testing.expect(containerLayout(U1) == TypeInfo.ContainerLayout.Auto); |
| 182 | debug.assert(containerLayout(U2) == TypeInfo.ContainerLayout.Packed); | 183 | testing.expect(containerLayout(U2) == TypeInfo.ContainerLayout.Packed); |
| 183 | debug.assert(containerLayout(U3) == TypeInfo.ContainerLayout.Extern); | 184 | testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern); |
| 184 | } | 185 | } |
| 185 | 186 | ||
| 186 | pub fn definitions(comptime T: type) []TypeInfo.Definition { | 187 | pub fn definitions(comptime T: type) []TypeInfo.Definition { |
| ... | @@ -214,8 +215,8 @@ test "std.meta.definitions" { | ... | @@ -214,8 +215,8 @@ test "std.meta.definitions" { |
| 214 | }; | 215 | }; |
| 215 | 216 | ||
| 216 | inline for (defs) |def| { | 217 | inline for (defs) |def| { |
| 217 | debug.assert(def.len == 1); | 218 | testing.expect(def.len == 1); |
| 218 | debug.assert(comptime mem.eql(u8, def[0].name, "a")); | 219 | testing.expect(comptime mem.eql(u8, def[0].name, "a")); |
| 219 | } | 220 | } |
| 220 | } | 221 | } |
| 221 | 222 | ||
| ... | @@ -250,8 +251,8 @@ test "std.meta.definitionInfo" { | ... | @@ -250,8 +251,8 @@ test "std.meta.definitionInfo" { |
| 250 | }; | 251 | }; |
| 251 | 252 | ||
| 252 | inline for (infos) |info| { | 253 | inline for (infos) |info| { |
| 253 | debug.assert(comptime mem.eql(u8, info.name, "a")); | 254 | testing.expect(comptime mem.eql(u8, info.name, "a")); |
| 254 | debug.assert(!info.is_pub); | 255 | testing.expect(!info.is_pub); |
| 255 | } | 256 | } |
| 256 | } | 257 | } |
| 257 | 258 | ||
| ... | @@ -288,16 +289,16 @@ test "std.meta.fields" { | ... | @@ -288,16 +289,16 @@ test "std.meta.fields" { |
| 288 | const sf = comptime fields(S1); | 289 | const sf = comptime fields(S1); |
| 289 | const uf = comptime fields(U1); | 290 | const uf = comptime fields(U1); |
| 290 | 291 | ||
| 291 | debug.assert(e1f.len == 1); | 292 | testing.expect(e1f.len == 1); |
| 292 | debug.assert(e2f.len == 1); | 293 | testing.expect(e2f.len == 1); |
| 293 | debug.assert(sf.len == 1); | 294 | testing.expect(sf.len == 1); |
| 294 | debug.assert(uf.len == 1); | 295 | testing.expect(uf.len == 1); |
| 295 | debug.assert(mem.eql(u8, e1f[0].name, "A")); | 296 | testing.expect(mem.eql(u8, e1f[0].name, "A")); |
| 296 | debug.assert(mem.eql(u8, e2f[0].name, "A")); | 297 | testing.expect(mem.eql(u8, e2f[0].name, "A")); |
| 297 | debug.assert(mem.eql(u8, sf[0].name, "a")); | 298 | testing.expect(mem.eql(u8, sf[0].name, "a")); |
| 298 | debug.assert(mem.eql(u8, uf[0].name, "a")); | 299 | testing.expect(mem.eql(u8, uf[0].name, "a")); |
| 299 | debug.assert(comptime sf[0].field_type == u8); | 300 | testing.expect(comptime sf[0].field_type == u8); |
| 300 | debug.assert(comptime uf[0].field_type == u8); | 301 | testing.expect(comptime uf[0].field_type == u8); |
| 301 | } | 302 | } |
| 302 | 303 | ||
| 303 | pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) { | 304 | pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) { |
| ... | @@ -332,12 +333,12 @@ test "std.meta.fieldInfo" { | ... | @@ -332,12 +333,12 @@ test "std.meta.fieldInfo" { |
| 332 | const sf = comptime fieldInfo(S1, "a"); | 333 | const sf = comptime fieldInfo(S1, "a"); |
| 333 | const uf = comptime fieldInfo(U1, "a"); | 334 | const uf = comptime fieldInfo(U1, "a"); |
| 334 | 335 | ||
| 335 | debug.assert(mem.eql(u8, e1f.name, "A")); | 336 | testing.expect(mem.eql(u8, e1f.name, "A")); |
| 336 | debug.assert(mem.eql(u8, e2f.name, "A")); | 337 | testing.expect(mem.eql(u8, e2f.name, "A")); |
| 337 | debug.assert(mem.eql(u8, sf.name, "a")); | 338 | testing.expect(mem.eql(u8, sf.name, "a")); |
| 338 | debug.assert(mem.eql(u8, uf.name, "a")); | 339 | testing.expect(mem.eql(u8, uf.name, "a")); |
| 339 | debug.assert(comptime sf.field_type == u8); | 340 | testing.expect(comptime sf.field_type == u8); |
| 340 | debug.assert(comptime uf.field_type == u8); | 341 | testing.expect(comptime uf.field_type == u8); |
| 341 | } | 342 | } |
| 342 | 343 | ||
| 343 | pub fn TagType(comptime T: type) type { | 344 | pub fn TagType(comptime T: type) type { |
| ... | @@ -358,8 +359,8 @@ test "std.meta.TagType" { | ... | @@ -358,8 +359,8 @@ test "std.meta.TagType" { |
| 358 | D: u16, | 359 | D: u16, |
| 359 | }; | 360 | }; |
| 360 | 361 | ||
| 361 | debug.assert(TagType(E) == u8); | 362 | testing.expect(TagType(E) == u8); |
| 362 | debug.assert(TagType(U) == E); | 363 | testing.expect(TagType(U) == E); |
| 363 | } | 364 | } |
| 364 | 365 | ||
| 365 | ///Returns the active tag of a tagged union | 366 | ///Returns the active tag of a tagged union |
| ... | @@ -380,10 +381,37 @@ test "std.meta.activeTag" { | ... | @@ -380,10 +381,37 @@ test "std.meta.activeTag" { |
| 380 | }; | 381 | }; |
| 381 | 382 | ||
| 382 | var u = U{ .Int = 32 }; | 383 | var u = U{ .Int = 32 }; |
| 383 | debug.assert(activeTag(u) == UE.Int); | 384 | testing.expect(activeTag(u) == UE.Int); |
| 384 | 385 | ||
| 385 | u = U{ .Float = 112.9876 }; | 386 | u = U{ .Float = 112.9876 }; |
| 386 | debug.assert(activeTag(u) == UE.Float); | 387 | testing.expect(activeTag(u) == UE.Float); |
| 388 | } | ||
| 389 | |||
| 390 | ///Given a tagged union type, and an enum, return the type of the union | ||
| 391 | /// field corresponding to the enum tag. | ||
| 392 | pub fn TagPayloadType(comptime U: type, tag: var) type { | ||
| 393 | const Tag = @typeOf(tag); | ||
| 394 | testing.expect(trait.is(builtin.TypeId.Union)(U)); | ||
| 395 | testing.expect(trait.is(builtin.TypeId.Enum)(Tag)); | ||
| 396 | |||
| 397 | const info = @typeInfo(U).Union; | ||
| 398 | |||
| 399 | inline for (info.fields) |field_info| { | ||
| 400 | if (field_info.enum_field.?.value == @enumToInt(tag)) return field_info.field_type; | ||
| 401 | } | ||
| 402 | unreachable; | ||
| 403 | } | ||
| 404 | |||
| 405 | test "std.meta.TagPayloadType" { | ||
| 406 | const Event = union(enum) { | ||
| 407 | Moved: struct { | ||
| 408 | from: i32, | ||
| 409 | to: i32, | ||
| 410 | }, | ||
| 411 | }; | ||
| 412 | const MovedEvent = TagPayloadType(Event, Event.Moved); | ||
| 413 | var e: Event = undefined; | ||
| 414 | testing.expect(MovedEvent == @typeOf(e.Moved)); | ||
| 387 | } | 415 | } |
| 388 | 416 | ||
| 389 | ///Compares two of any type for equality. Containers are compared on a field-by-field basis, | 417 | ///Compares two of any type for equality. Containers are compared on a field-by-field basis, |
| ... | @@ -435,10 +463,18 @@ pub fn eql(a: var, b: @typeOf(a)) bool { | ... | @@ -435,10 +463,18 @@ pub fn eql(a: var, b: @typeOf(a)) bool { |
| 435 | builtin.TypeId.Pointer => { | 463 | builtin.TypeId.Pointer => { |
| 436 | const info = @typeInfo(T).Pointer; | 464 | const info = @typeInfo(T).Pointer; |
| 437 | switch (info.size) { | 465 | switch (info.size) { |
| 438 | builtin.TypeInfo.Pointer.Size.One, builtin.TypeInfo.Pointer.Size.Many => return a == b, | 466 | builtin.TypeInfo.Pointer.Size.One, |
| 467 | builtin.TypeInfo.Pointer.Size.Many, | ||
| 468 | builtin.TypeInfo.Pointer.Size.C, | ||
| 469 | => return a == b, | ||
| 439 | builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len, | 470 | builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len, |
| 440 | } | 471 | } |
| 441 | }, | 472 | }, |
| 473 | builtin.TypeId.Optional => { | ||
| 474 | if (a == null and b == null) return true; | ||
| 475 | if (a == null or b == null) return false; | ||
| 476 | return eql(a.?, b.?); | ||
| 477 | }, | ||
| 442 | else => return a == b, | 478 | else => return a == b, |
| 443 | } | 479 | } |
| 444 | } | 480 | } |
| ... | @@ -452,7 +488,7 @@ test "std.meta.eql" { | ... | @@ -452,7 +488,7 @@ test "std.meta.eql" { |
| 452 | 488 | ||
| 453 | const U = union(enum) { | 489 | const U = union(enum) { |
| 454 | s: S, | 490 | s: S, |
| 455 | f: f32, | 491 | f: ?f32, |
| 456 | }; | 492 | }; |
| 457 | 493 | ||
| 458 | const s_1 = S{ | 494 | const s_1 = S{ |
| ... | @@ -477,19 +513,19 @@ test "std.meta.eql" { | ... | @@ -477,19 +513,19 @@ test "std.meta.eql" { |
| 477 | const u_2 = U{ .s = s_1 }; | 513 | const u_2 = U{ .s = s_1 }; |
| 478 | const u_3 = U{ .f = 24 }; | 514 | const u_3 = U{ .f = 24 }; |
| 479 | 515 | ||
| 480 | debug.assert(eql(s_1, s_3)); | 516 | testing.expect(eql(s_1, s_3)); |
| 481 | debug.assert(eql(&s_1, &s_1)); | 517 | testing.expect(eql(&s_1, &s_1)); |
| 482 | debug.assert(!eql(&s_1, &s_3)); | 518 | testing.expect(!eql(&s_1, &s_3)); |
| 483 | debug.assert(eql(u_1, u_3)); | 519 | testing.expect(eql(u_1, u_3)); |
| 484 | debug.assert(!eql(u_1, u_2)); | 520 | testing.expect(!eql(u_1, u_2)); |
| 485 | 521 | ||
| 486 | var a1 = "abcdef"; | 522 | var a1 = "abcdef"; |
| 487 | var a2 = "abcdef"; | 523 | var a2 = "abcdef"; |
| 488 | var a3 = "ghijkl"; | 524 | var a3 = "ghijkl"; |
| 489 | 525 | ||
| 490 | debug.assert(eql(a1, a2)); | 526 | testing.expect(eql(a1, a2)); |
| 491 | debug.assert(!eql(a1, a3)); | 527 | testing.expect(!eql(a1, a3)); |
| 492 | debug.assert(!eql(a1[0..], a2[0..])); | 528 | testing.expect(!eql(a1[0..], a2[0..])); |
| 493 | 529 | ||
| 494 | const EU = struct { | 530 | const EU = struct { |
| 495 | fn tst(err: bool) !u8 { | 531 | fn tst(err: bool) !u8 { |
| ... | @@ -498,9 +534,9 @@ test "std.meta.eql" { | ... | @@ -498,9 +534,9 @@ test "std.meta.eql" { |
| 498 | } | 534 | } |
| 499 | }; | 535 | }; |
| 500 | 536 | ||
| 501 | debug.assert(eql(EU.tst(true), EU.tst(true))); | 537 | testing.expect(eql(EU.tst(true), EU.tst(true))); |
| 502 | debug.assert(eql(EU.tst(false), EU.tst(false))); | 538 | testing.expect(eql(EU.tst(false), EU.tst(false))); |
| 503 | debug.assert(!eql(EU.tst(false), EU.tst(true))); | 539 | testing.expect(!eql(EU.tst(false), EU.tst(true))); |
| 504 | } | 540 | } |
| 505 | 541 | ||
| 506 | test "intToEnum with error return" { | 542 | test "intToEnum with error return" { |
| ... | @@ -514,9 +550,9 @@ test "intToEnum with error return" { | ... | @@ -514,9 +550,9 @@ test "intToEnum with error return" { |
| 514 | 550 | ||
| 515 | var zero: u8 = 0; | 551 | var zero: u8 = 0; |
| 516 | var one: u16 = 1; | 552 | var one: u16 = 1; |
| 517 | debug.assert(intToEnum(E1, zero) catch unreachable == E1.A); | 553 | testing.expect(intToEnum(E1, zero) catch unreachable == E1.A); |
| 518 | debug.assert(intToEnum(E2, one) catch unreachable == E2.B); | 554 | testing.expect(intToEnum(E2, one) catch unreachable == E2.B); |
| 519 | debug.assertError(intToEnum(E1, one), error.InvalidEnumTag); | 555 | testing.expectError(error.InvalidEnumTag, intToEnum(E1, one)); |
| 520 | } | 556 | } |
| 521 | 557 | ||
| 522 | pub const IntToEnumError = error{InvalidEnumTag}; | 558 | pub const IntToEnumError = error{InvalidEnumTag}; |
std/meta/trait.zig+90-58| ... | @@ -2,6 +2,7 @@ const std = @import("../index.zig"); | ... | @@ -2,6 +2,7 @@ const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const debug = std.debug; | 4 | const debug = std.debug; |
| 5 | const testing = std.testing; | ||
| 5 | const warn = debug.warn; | 6 | const warn = debug.warn; |
| 6 | 7 | ||
| 7 | const meta = @import("index.zig"); | 8 | const meta = @import("index.zig"); |
| ... | @@ -50,8 +51,8 @@ test "std.meta.trait.multiTrait" { | ... | @@ -50,8 +51,8 @@ test "std.meta.trait.multiTrait" { |
| 50 | hasField("x"), | 51 | hasField("x"), |
| 51 | hasField("y"), | 52 | hasField("y"), |
| 52 | }); | 53 | }); |
| 53 | debug.assert(isVector(Vector2)); | 54 | testing.expect(isVector(Vector2)); |
| 54 | debug.assert(!isVector(u8)); | 55 | testing.expect(!isVector(u8)); |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | /// | 58 | /// |
| ... | @@ -85,12 +86,12 @@ test "std.meta.trait.hasDef" { | ... | @@ -85,12 +86,12 @@ test "std.meta.trait.hasDef" { |
| 85 | const value = u8(16); | 86 | const value = u8(16); |
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| 88 | debug.assert(hasDef("value")(TestStruct)); | 89 | testing.expect(hasDef("value")(TestStruct)); |
| 89 | debug.assert(!hasDef("value")(TestStructFail)); | 90 | testing.expect(!hasDef("value")(TestStructFail)); |
| 90 | debug.assert(!hasDef("value")(*TestStruct)); | 91 | testing.expect(!hasDef("value")(*TestStruct)); |
| 91 | debug.assert(!hasDef("value")(**TestStructFail)); | 92 | testing.expect(!hasDef("value")(**TestStructFail)); |
| 92 | debug.assert(!hasDef("x")(TestStruct)); | 93 | testing.expect(!hasDef("x")(TestStruct)); |
| 93 | debug.assert(!hasDef("value")(u8)); | 94 | testing.expect(!hasDef("value")(u8)); |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | /// | 97 | /// |
| ... | @@ -111,9 +112,9 @@ test "std.meta.trait.hasFn" { | ... | @@ -111,9 +112,9 @@ test "std.meta.trait.hasFn" { |
| 111 | pub fn useless() void {} | 112 | pub fn useless() void {} |
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| 114 | debug.assert(hasFn("useless")(TestStruct)); | 115 | testing.expect(hasFn("useless")(TestStruct)); |
| 115 | debug.assert(!hasFn("append")(TestStruct)); | 116 | testing.expect(!hasFn("append")(TestStruct)); |
| 116 | debug.assert(!hasFn("useless")(u8)); | 117 | testing.expect(!hasFn("useless")(u8)); |
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | /// | 120 | /// |
| ... | @@ -143,11 +144,11 @@ test "std.meta.trait.hasField" { | ... | @@ -143,11 +144,11 @@ test "std.meta.trait.hasField" { |
| 143 | value: u32, | 144 | value: u32, |
| 144 | }; | 145 | }; |
| 145 | 146 | ||
| 146 | debug.assert(hasField("value")(TestStruct)); | 147 | testing.expect(hasField("value")(TestStruct)); |
| 147 | debug.assert(!hasField("value")(*TestStruct)); | 148 | testing.expect(!hasField("value")(*TestStruct)); |
| 148 | debug.assert(!hasField("x")(TestStruct)); | 149 | testing.expect(!hasField("x")(TestStruct)); |
| 149 | debug.assert(!hasField("x")(**TestStruct)); | 150 | testing.expect(!hasField("x")(**TestStruct)); |
| 150 | debug.assert(!hasField("value")(u8)); | 151 | testing.expect(!hasField("value")(u8)); |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | /// | 154 | /// |
| ... | @@ -161,11 +162,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn { | ... | @@ -161,11 +162,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn { |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | test "std.meta.trait.is" { | 164 | test "std.meta.trait.is" { |
| 164 | debug.assert(is(builtin.TypeId.Int)(u8)); | 165 | testing.expect(is(builtin.TypeId.Int)(u8)); |
| 165 | debug.assert(!is(builtin.TypeId.Int)(f32)); | 166 | testing.expect(!is(builtin.TypeId.Int)(f32)); |
| 166 | debug.assert(is(builtin.TypeId.Pointer)(*u8)); | 167 | testing.expect(is(builtin.TypeId.Pointer)(*u8)); |
| 167 | debug.assert(is(builtin.TypeId.Void)(void)); | 168 | testing.expect(is(builtin.TypeId.Void)(void)); |
| 168 | debug.assert(!is(builtin.TypeId.Optional)(anyerror)); | 169 | testing.expect(!is(builtin.TypeId.Optional)(anyerror)); |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | /// | 172 | /// |
| ... | @@ -180,9 +181,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { | ... | @@ -180,9 +181,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 182 | test "std.meta.trait.isPtrTo" { | 183 | test "std.meta.trait.isPtrTo" { |
| 183 | debug.assert(!isPtrTo(builtin.TypeId.Struct)(struct {})); | 184 | testing.expect(!isPtrTo(builtin.TypeId.Struct)(struct {})); |
| 184 | debug.assert(isPtrTo(builtin.TypeId.Struct)(*struct {})); | 185 | testing.expect(isPtrTo(builtin.TypeId.Struct)(*struct {})); |
| 185 | debug.assert(!isPtrTo(builtin.TypeId.Struct)(**struct {})); | 186 | testing.expect(!isPtrTo(builtin.TypeId.Struct)(**struct {})); |
| 186 | } | 187 | } |
| 187 | 188 | ||
| 188 | ///////////Strait trait Fns | 189 | ///////////Strait trait Fns |
| ... | @@ -205,9 +206,9 @@ test "std.meta.trait.isExtern" { | ... | @@ -205,9 +206,9 @@ test "std.meta.trait.isExtern" { |
| 205 | const TestExStruct = extern struct {}; | 206 | const TestExStruct = extern struct {}; |
| 206 | const TestStruct = struct {}; | 207 | const TestStruct = struct {}; |
| 207 | 208 | ||
| 208 | debug.assert(isExtern(TestExStruct)); | 209 | testing.expect(isExtern(TestExStruct)); |
| 209 | debug.assert(!isExtern(TestStruct)); | 210 | testing.expect(!isExtern(TestStruct)); |
| 210 | debug.assert(!isExtern(u8)); | 211 | testing.expect(!isExtern(u8)); |
| 211 | } | 212 | } |
| 212 | 213 | ||
| 213 | /// | 214 | /// |
| ... | @@ -226,9 +227,40 @@ test "std.meta.trait.isPacked" { | ... | @@ -226,9 +227,40 @@ test "std.meta.trait.isPacked" { |
| 226 | const TestPStruct = packed struct {}; | 227 | const TestPStruct = packed struct {}; |
| 227 | const TestStruct = struct {}; | 228 | const TestStruct = struct {}; |
| 228 | 229 | ||
| 229 | debug.assert(isPacked(TestPStruct)); | 230 | testing.expect(isPacked(TestPStruct)); |
| 230 | debug.assert(!isPacked(TestStruct)); | 231 | testing.expect(!isPacked(TestStruct)); |
| 231 | debug.assert(!isPacked(u8)); | 232 | testing.expect(!isPacked(u8)); |
| 233 | } | ||
| 234 | |||
| 235 | /// | ||
| 236 | pub fn isUnsignedInt(comptime T: type) bool { | ||
| 237 | return switch (@typeId(T)) { | ||
| 238 | builtin.TypeId.Int => !@typeInfo(T).Int.is_signed, | ||
| 239 | else => false, | ||
| 240 | }; | ||
| 241 | } | ||
| 242 | |||
| 243 | test "isUnsignedInt" { | ||
| 244 | testing.expect(isUnsignedInt(u32) == true); | ||
| 245 | testing.expect(isUnsignedInt(comptime_int) == false); | ||
| 246 | testing.expect(isUnsignedInt(i64) == false); | ||
| 247 | testing.expect(isUnsignedInt(f64) == false); | ||
| 248 | } | ||
| 249 | |||
| 250 | /// | ||
| 251 | pub fn isSignedInt(comptime T: type) bool { | ||
| 252 | return switch (@typeId(T)) { | ||
| 253 | builtin.TypeId.ComptimeInt => true, | ||
| 254 | builtin.TypeId.Int => @typeInfo(T).Int.is_signed, | ||
| 255 | else => false, | ||
| 256 | }; | ||
| 257 | } | ||
| 258 | |||
| 259 | test "isSignedInt" { | ||
| 260 | testing.expect(isSignedInt(u32) == false); | ||
| 261 | testing.expect(isSignedInt(comptime_int) == true); | ||
| 262 | testing.expect(isSignedInt(i64) == true); | ||
| 263 | testing.expect(isSignedInt(f64) == false); | ||
| 232 | } | 264 | } |
| 233 | 265 | ||
| 234 | /// | 266 | /// |
| ... | @@ -242,9 +274,9 @@ pub fn isSingleItemPtr(comptime T: type) bool { | ... | @@ -242,9 +274,9 @@ pub fn isSingleItemPtr(comptime T: type) bool { |
| 242 | 274 | ||
| 243 | test "std.meta.trait.isSingleItemPtr" { | 275 | test "std.meta.trait.isSingleItemPtr" { |
| 244 | const array = []u8{0} ** 10; | 276 | const array = []u8{0} ** 10; |
| 245 | debug.assert(isSingleItemPtr(@typeOf(&array[0]))); | 277 | testing.expect(isSingleItemPtr(@typeOf(&array[0]))); |
| 246 | debug.assert(!isSingleItemPtr(@typeOf(array))); | 278 | testing.expect(!isSingleItemPtr(@typeOf(array))); |
| 247 | debug.assert(!isSingleItemPtr(@typeOf(array[0..1]))); | 279 | testing.expect(!isSingleItemPtr(@typeOf(array[0..1]))); |
| 248 | } | 280 | } |
| 249 | 281 | ||
| 250 | /// | 282 | /// |
| ... | @@ -259,9 +291,9 @@ pub fn isManyItemPtr(comptime T: type) bool { | ... | @@ -259,9 +291,9 @@ pub fn isManyItemPtr(comptime T: type) bool { |
| 259 | test "std.meta.trait.isManyItemPtr" { | 291 | test "std.meta.trait.isManyItemPtr" { |
| 260 | const array = []u8{0} ** 10; | 292 | const array = []u8{0} ** 10; |
| 261 | const mip = @ptrCast([*]const u8, &array[0]); | 293 | const mip = @ptrCast([*]const u8, &array[0]); |
| 262 | debug.assert(isManyItemPtr(@typeOf(mip))); | 294 | testing.expect(isManyItemPtr(@typeOf(mip))); |
| 263 | debug.assert(!isManyItemPtr(@typeOf(array))); | 295 | testing.expect(!isManyItemPtr(@typeOf(array))); |
| 264 | debug.assert(!isManyItemPtr(@typeOf(array[0..1]))); | 296 | testing.expect(!isManyItemPtr(@typeOf(array[0..1]))); |
| 265 | } | 297 | } |
| 266 | 298 | ||
| 267 | /// | 299 | /// |
| ... | @@ -275,9 +307,9 @@ pub fn isSlice(comptime T: type) bool { | ... | @@ -275,9 +307,9 @@ pub fn isSlice(comptime T: type) bool { |
| 275 | 307 | ||
| 276 | test "std.meta.trait.isSlice" { | 308 | test "std.meta.trait.isSlice" { |
| 277 | const array = []u8{0} ** 10; | 309 | const array = []u8{0} ** 10; |
| 278 | debug.assert(isSlice(@typeOf(array[0..]))); | 310 | testing.expect(isSlice(@typeOf(array[0..]))); |
| 279 | debug.assert(!isSlice(@typeOf(array))); | 311 | testing.expect(!isSlice(@typeOf(array))); |
| 280 | debug.assert(!isSlice(@typeOf(&array[0]))); | 312 | testing.expect(!isSlice(@typeOf(&array[0]))); |
| 281 | } | 313 | } |
| 282 | 314 | ||
| 283 | /// | 315 | /// |
| ... | @@ -297,10 +329,10 @@ test "std.meta.trait.isIndexable" { | ... | @@ -297,10 +329,10 @@ test "std.meta.trait.isIndexable" { |
| 297 | const array = []u8{0} ** 10; | 329 | const array = []u8{0} ** 10; |
| 298 | const slice = array[0..]; | 330 | const slice = array[0..]; |
| 299 | 331 | ||
| 300 | debug.assert(isIndexable(@typeOf(array))); | 332 | testing.expect(isIndexable(@typeOf(array))); |
| 301 | debug.assert(isIndexable(@typeOf(&array))); | 333 | testing.expect(isIndexable(@typeOf(&array))); |
| 302 | debug.assert(isIndexable(@typeOf(slice))); | 334 | testing.expect(isIndexable(@typeOf(slice))); |
| 303 | debug.assert(!isIndexable(meta.Child(@typeOf(slice)))); | 335 | testing.expect(!isIndexable(meta.Child(@typeOf(slice)))); |
| 304 | } | 336 | } |
| 305 | 337 | ||
| 306 | /// | 338 | /// |
| ... | @@ -316,13 +348,13 @@ test "std.meta.trait.isNumber" { | ... | @@ -316,13 +348,13 @@ test "std.meta.trait.isNumber" { |
| 316 | number: u8, | 348 | number: u8, |
| 317 | }; | 349 | }; |
| 318 | 350 | ||
| 319 | debug.assert(isNumber(u32)); | 351 | testing.expect(isNumber(u32)); |
| 320 | debug.assert(isNumber(f32)); | 352 | testing.expect(isNumber(f32)); |
| 321 | debug.assert(isNumber(u64)); | 353 | testing.expect(isNumber(u64)); |
| 322 | debug.assert(isNumber(@typeOf(102))); | 354 | testing.expect(isNumber(@typeOf(102))); |
| 323 | debug.assert(isNumber(@typeOf(102.123))); | 355 | testing.expect(isNumber(@typeOf(102.123))); |
| 324 | debug.assert(!isNumber([]u8)); | 356 | testing.expect(!isNumber([]u8)); |
| 325 | debug.assert(!isNumber(NotANumber)); | 357 | testing.expect(!isNumber(NotANumber)); |
| 326 | } | 358 | } |
| 327 | 359 | ||
| 328 | /// | 360 | /// |
| ... | @@ -335,10 +367,10 @@ pub fn isConstPtr(comptime T: type) bool { | ... | @@ -335,10 +367,10 @@ pub fn isConstPtr(comptime T: type) bool { |
| 335 | test "std.meta.trait.isConstPtr" { | 367 | test "std.meta.trait.isConstPtr" { |
| 336 | var t = u8(0); | 368 | var t = u8(0); |
| 337 | const c = u8(0); | 369 | const c = u8(0); |
| 338 | debug.assert(isConstPtr(*const @typeOf(t))); | 370 | testing.expect(isConstPtr(*const @typeOf(t))); |
| 339 | debug.assert(isConstPtr(@typeOf(&c))); | 371 | testing.expect(isConstPtr(@typeOf(&c))); |
| 340 | debug.assert(!isConstPtr(*@typeOf(t))); | 372 | testing.expect(!isConstPtr(*@typeOf(t))); |
| 341 | debug.assert(!isConstPtr(@typeOf(6))); | 373 | testing.expect(!isConstPtr(@typeOf(6))); |
| 342 | } | 374 | } |
| 343 | 375 | ||
| 344 | /// | 376 | /// |
| ... | @@ -362,8 +394,8 @@ test "std.meta.trait.isContainer" { | ... | @@ -362,8 +394,8 @@ test "std.meta.trait.isContainer" { |
| 362 | B, | 394 | B, |
| 363 | }; | 395 | }; |
| 364 | 396 | ||
| 365 | debug.assert(isContainer(TestStruct)); | 397 | testing.expect(isContainer(TestStruct)); |
| 366 | debug.assert(isContainer(TestUnion)); | 398 | testing.expect(isContainer(TestUnion)); |
| 367 | debug.assert(isContainer(TestEnum)); | 399 | testing.expect(isContainer(TestEnum)); |
| 368 | debug.assert(!isContainer(u8)); | 400 | testing.expect(!isContainer(u8)); |
| 369 | } | 401 | } |
std/mutex.zig+105-48| ... | @@ -2,77 +2,127 @@ const std = @import("index.zig"); | ... | @@ -2,77 +2,127 @@ const std = @import("index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const AtomicOrder = builtin.AtomicOrder; | 3 | const AtomicOrder = builtin.AtomicOrder; |
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | 4 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | const assert = std.debug.assert; | 5 | const testing = std.testing; |
| 6 | const SpinLock = std.SpinLock; | 6 | const SpinLock = std.SpinLock; |
| 7 | const linux = std.os.linux; | 7 | const linux = std.os.linux; |
| 8 | const windows = std.os.windows; | ||
| 8 | 9 | ||
| 9 | /// Lock may be held only once. If the same thread | 10 | /// Lock may be held only once. If the same thread |
| 10 | /// tries to acquire the same mutex twice, it deadlocks. | 11 | /// tries to acquire the same mutex twice, it deadlocks. |
| 12 | /// This type must be initialized at runtime, and then deinitialized when no | ||
| 13 | /// longer needed, to free resources. | ||
| 14 | /// If you need static initialization, use std.StaticallyInitializedMutex. | ||
| 11 | /// The Linux implementation is based on mutex3 from | 15 | /// The Linux implementation is based on mutex3 from |
| 12 | /// https://www.akkadia.org/drepper/futex.pdf | 16 | /// https://www.akkadia.org/drepper/futex.pdf |
| 13 | pub const Mutex = struct { | 17 | /// When an application is built in single threaded release mode, all the functions are |
| 14 | /// 0: unlocked | 18 | /// no-ops. In single threaded debug mode, there is deadlock detection. |
| 15 | /// 1: locked, no waiters | 19 | pub const Mutex = if (builtin.single_threaded) |
| 16 | /// 2: locked, one or more waiters | 20 | struct { |
| 17 | linux_lock: @typeOf(linux_lock_init), | 21 | lock: @typeOf(lock_init), |
| 18 | 22 | ||
| 19 | /// TODO better implementation than spin lock | 23 | const lock_init = if (std.debug.runtime_safety) false else {}; |
| 20 | spin_lock: @typeOf(spin_lock_init), | ||
| 21 | 24 | ||
| 22 | const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {}; | 25 | pub const Held = struct { |
| 23 | const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {}; | 26 | mutex: *Mutex, |
| 24 | 27 | ||
| 25 | pub const Held = struct { | 28 | pub fn release(self: Held) void { |
| 26 | mutex: *Mutex, | 29 | if (std.debug.runtime_safety) { |
| 30 | self.mutex.lock = false; | ||
| 31 | } | ||
| 32 | } | ||
| 33 | }; | ||
| 34 | pub fn init() Mutex { | ||
| 35 | return Mutex{ .lock = lock_init }; | ||
| 36 | } | ||
| 37 | pub fn deinit(self: *Mutex) void {} | ||
| 27 | 38 | ||
| 28 | pub fn release(self: Held) void { | 39 | pub fn acquire(self: *Mutex) Held { |
| 29 | if (builtin.os == builtin.Os.linux) { | 40 | if (std.debug.runtime_safety and self.lock) { |
| 30 | const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release); | 41 | @panic("deadlock detected"); |
| 42 | } | ||
| 43 | return Held{ .mutex = self }; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | else switch (builtin.os) { | ||
| 47 | builtin.Os.linux => struct { | ||
| 48 | /// 0: unlocked | ||
| 49 | /// 1: locked, no waiters | ||
| 50 | /// 2: locked, one or more waiters | ||
| 51 | lock: i32, | ||
| 52 | |||
| 53 | pub const Held = struct { | ||
| 54 | mutex: *Mutex, | ||
| 55 | |||
| 56 | pub fn release(self: Held) void { | ||
| 57 | const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release); | ||
| 31 | if (c != 1) { | 58 | if (c != 1) { |
| 32 | _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release); | 59 | _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release); |
| 33 | const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1); | 60 | const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1); |
| 34 | switch (linux.getErrno(rc)) { | 61 | switch (linux.getErrno(rc)) { |
| 35 | 0 => {}, | 62 | 0 => {}, |
| 36 | linux.EINVAL => unreachable, | 63 | linux.EINVAL => unreachable, |
| 37 | else => unreachable, | 64 | else => unreachable, |
| 38 | } | 65 | } |
| 39 | } | 66 | } |
| 40 | } else { | ||
| 41 | SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock }); | ||
| 42 | } | 67 | } |
| 68 | }; | ||
| 69 | |||
| 70 | pub fn init() Mutex { | ||
| 71 | return Mutex{ .lock = 0 }; | ||
| 43 | } | 72 | } |
| 44 | }; | ||
| 45 | 73 | ||
| 46 | pub fn init() Mutex { | 74 | pub fn deinit(self: *Mutex) void {} |
| 47 | return Mutex{ | ||
| 48 | .linux_lock = linux_lock_init, | ||
| 49 | .spin_lock = spin_lock_init, | ||
| 50 | }; | ||
| 51 | } | ||
| 52 | 75 | ||
| 53 | pub fn acquire(self: *Mutex) Held { | 76 | pub fn acquire(self: *Mutex) Held { |
| 54 | if (builtin.os == builtin.Os.linux) { | 77 | var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse |
| 55 | var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse | ||
| 56 | return Held{ .mutex = self }; | 78 | return Held{ .mutex = self }; |
| 57 | if (c != 2) | 79 | if (c != 2) |
| 58 | c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire); | 80 | c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire); |
| 59 | while (c != 0) { | 81 | while (c != 0) { |
| 60 | const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null); | 82 | const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null); |
| 61 | switch (linux.getErrno(rc)) { | 83 | switch (linux.getErrno(rc)) { |
| 62 | 0, linux.EINTR, linux.EAGAIN => {}, | 84 | 0, linux.EINTR, linux.EAGAIN => {}, |
| 63 | linux.EINVAL => unreachable, | 85 | linux.EINVAL => unreachable, |
| 64 | else => unreachable, | 86 | else => unreachable, |
| 65 | } | 87 | } |
| 66 | c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire); | 88 | c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire); |
| 67 | } | 89 | } |
| 68 | } else { | 90 | return Held{ .mutex = self }; |
| 69 | _ = self.spin_lock.acquire(); | ||
| 70 | } | 91 | } |
| 71 | return Held{ .mutex = self }; | 92 | }, |
| 72 | } | 93 | // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a |
| 94 | // better implementation of this. The problem is we need the init() function to have access to | ||
| 95 | // the address of the CRITICAL_SECTION, and then have it not move. | ||
| 96 | builtin.Os.windows => std.StaticallyInitializedMutex, | ||
| 97 | else => struct { | ||
| 98 | /// TODO better implementation than spin lock. | ||
| 99 | /// When changing this, one must also change the corresponding | ||
| 100 | /// std.StaticallyInitializedMutex code, since it aliases this type, | ||
| 101 | /// under the assumption that it works both statically and at runtime. | ||
| 102 | lock: SpinLock, | ||
| 103 | |||
| 104 | pub const Held = struct { | ||
| 105 | mutex: *Mutex, | ||
| 106 | |||
| 107 | pub fn release(self: Held) void { | ||
| 108 | SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock }); | ||
| 109 | } | ||
| 110 | }; | ||
| 111 | |||
| 112 | pub fn init() Mutex { | ||
| 113 | return Mutex{ .lock = SpinLock.init() }; | ||
| 114 | } | ||
| 115 | |||
| 116 | pub fn deinit(self: *Mutex) void {} | ||
| 117 | |||
| 118 | pub fn acquire(self: *Mutex) Held { | ||
| 119 | _ = self.lock.acquire(); | ||
| 120 | return Held{ .mutex = self }; | ||
| 121 | } | ||
| 122 | }, | ||
| 73 | }; | 123 | }; |
| 74 | 124 | ||
| 75 | const Context = struct { | 125 | const TestContext = struct { |
| 76 | mutex: *Mutex, | 126 | mutex: *Mutex, |
| 77 | data: i128, | 127 | data: i128, |
| 78 | 128 | ||
| ... | @@ -90,25 +140,32 @@ test "std.Mutex" { | ... | @@ -90,25 +140,32 @@ test "std.Mutex" { |
| 90 | var a = &fixed_buffer_allocator.allocator; | 140 | var a = &fixed_buffer_allocator.allocator; |
| 91 | 141 | ||
| 92 | var mutex = Mutex.init(); | 142 | var mutex = Mutex.init(); |
| 93 | var context = Context{ | 143 | defer mutex.deinit(); |
| 144 | |||
| 145 | var context = TestContext{ | ||
| 94 | .mutex = &mutex, | 146 | .mutex = &mutex, |
| 95 | .data = 0, | 147 | .data = 0, |
| 96 | }; | 148 | }; |
| 97 | 149 | ||
| 98 | const thread_count = 10; | 150 | if (builtin.single_threaded) { |
| 99 | var threads: [thread_count]*std.os.Thread = undefined; | 151 | worker(&context); |
| 100 | for (threads) |*t| { | 152 | testing.expect(context.data == TestContext.incr_count); |
| 101 | t.* = try std.os.spawnThread(&context, worker); | 153 | } else { |
| 102 | } | 154 | const thread_count = 10; |
| 103 | for (threads) |t| | 155 | var threads: [thread_count]*std.os.Thread = undefined; |
| 104 | t.wait(); | 156 | for (threads) |*t| { |
| 157 | t.* = try std.os.spawnThread(&context, worker); | ||
| 158 | } | ||
| 159 | for (threads) |t| | ||
| 160 | t.wait(); | ||
| 105 | 161 | ||
| 106 | std.debug.assertOrPanic(context.data == thread_count * Context.incr_count); | 162 | testing.expect(context.data == thread_count * TestContext.incr_count); |
| 163 | } | ||
| 107 | } | 164 | } |
| 108 | 165 | ||
| 109 | fn worker(ctx: *Context) void { | 166 | fn worker(ctx: *TestContext) void { |
| 110 | var i: usize = 0; | 167 | var i: usize = 0; |
| 111 | while (i != Context.incr_count) : (i += 1) { | 168 | while (i != TestContext.incr_count) : (i += 1) { |
| 112 | const held = ctx.mutex.acquire(); | 169 | const held = ctx.mutex.acquire(); |
| 113 | defer held.release(); | 170 | defer held.release(); |
| 114 | 171 |
std/net.zig+6-6| ... | @@ -23,7 +23,7 @@ pub const Address = struct { | ... | @@ -23,7 +23,7 @@ pub const Address = struct { |
| 23 | .os_addr = posix.sockaddr{ | 23 | .os_addr = posix.sockaddr{ |
| 24 | .in = posix.sockaddr_in{ | 24 | .in = posix.sockaddr_in{ |
| 25 | .family = posix.AF_INET, | 25 | .family = posix.AF_INET, |
| 26 | .port = std.mem.endianSwapIfLe(u16, _port), | 26 | .port = mem.nativeToBig(u16, _port), |
| 27 | .addr = ip4, | 27 | .addr = ip4, |
| 28 | .zero = []u8{0} ** 8, | 28 | .zero = []u8{0} ** 8, |
| 29 | }, | 29 | }, |
| ... | @@ -37,7 +37,7 @@ pub const Address = struct { | ... | @@ -37,7 +37,7 @@ pub const Address = struct { |
| 37 | .os_addr = posix.sockaddr{ | 37 | .os_addr = posix.sockaddr{ |
| 38 | .in6 = posix.sockaddr_in6{ | 38 | .in6 = posix.sockaddr_in6{ |
| 39 | .family = posix.AF_INET6, | 39 | .family = posix.AF_INET6, |
| 40 | .port = std.mem.endianSwapIfLe(u16, _port), | 40 | .port = mem.nativeToBig(u16, _port), |
| 41 | .flowinfo = 0, | 41 | .flowinfo = 0, |
| 42 | .addr = ip6.addr, | 42 | .addr = ip6.addr, |
| 43 | .scope_id = ip6.scope_id, | 43 | .scope_id = ip6.scope_id, |
| ... | @@ -47,7 +47,7 @@ pub const Address = struct { | ... | @@ -47,7 +47,7 @@ pub const Address = struct { |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | pub fn port(self: Address) u16 { | 49 | pub fn port(self: Address) u16 { |
| 50 | return std.mem.endianSwapIfLe(u16, self.os_addr.in.port); | 50 | return mem.bigToNative(u16, self.os_addr.in.port); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | pub fn initPosix(addr: posix.sockaddr) Address { | 53 | pub fn initPosix(addr: posix.sockaddr) Address { |
| ... | @@ -57,12 +57,12 @@ pub const Address = struct { | ... | @@ -57,12 +57,12 @@ pub const Address = struct { |
| 57 | pub fn format(self: *const Address, out_stream: var) !void { | 57 | pub fn format(self: *const Address, out_stream: var) !void { |
| 58 | switch (self.os_addr.in.family) { | 58 | switch (self.os_addr.in.family) { |
| 59 | posix.AF_INET => { | 59 | posix.AF_INET => { |
| 60 | const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port); | 60 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port); |
| 61 | const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); | 61 | const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); |
| 62 | try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); | 62 | try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); |
| 63 | }, | 63 | }, |
| 64 | posix.AF_INET6 => { | 64 | posix.AF_INET6 => { |
| 65 | const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port); | 65 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port); |
| 66 | try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); | 66 | try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); |
| 67 | }, | 67 | }, |
| 68 | else => try out_stream.write("(unrecognized address family)"), | 68 | else => try out_stream.write("(unrecognized address family)"), |
| ... | @@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr { | ... | @@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr { |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | test "std.net.parseIp4" { | 195 | test "std.net.parseIp4" { |
| 196 | assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001)); | 196 | assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001)); |
| 197 | 197 | ||
| 198 | testParseIp4Fail("256.0.0.1", error.Overflow); | 198 | testParseIp4Fail("256.0.0.1", error.Overflow); |
| 199 | testParseIp4Fail("x.0.0.1", error.InvalidCharacter); | 199 | testParseIp4Fail("x.0.0.1", error.InvalidCharacter); |
std/os/child_process.zig+12-9| ... | @@ -7,7 +7,6 @@ const posix = os.posix; | ... | @@ -7,7 +7,6 @@ const posix = os.posix; |
| 7 | const windows = os.windows; | 7 | const windows = os.windows; |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const debug = std.debug; | 9 | const debug = std.debug; |
| 10 | const assert = debug.assert; | ||
| 11 | const BufMap = std.BufMap; | 10 | const BufMap = std.BufMap; |
| 12 | const Buffer = std.Buffer; | 11 | const Buffer = std.Buffer; |
| 13 | const builtin = @import("builtin"); | 12 | const builtin = @import("builtin"); |
| ... | @@ -88,7 +87,8 @@ pub const ChildProcess = struct { | ... | @@ -88,7 +87,8 @@ pub const ChildProcess = struct { |
| 88 | /// First argument in argv is the executable. | 87 | /// First argument in argv is the executable. |
| 89 | /// On success must call deinit. | 88 | /// On success must call deinit. |
| 90 | pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess { | 89 | pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess { |
| 91 | const child = try allocator.create(ChildProcess{ | 90 | const child = try allocator.create(ChildProcess); |
| 91 | child.* = ChildProcess{ | ||
| 92 | .allocator = allocator, | 92 | .allocator = allocator, |
| 93 | .argv = argv, | 93 | .argv = argv, |
| 94 | .pid = undefined, | 94 | .pid = undefined, |
| ... | @@ -109,7 +109,7 @@ pub const ChildProcess = struct { | ... | @@ -109,7 +109,7 @@ pub const ChildProcess = struct { |
| 109 | .stdin_behavior = StdIo.Inherit, | 109 | .stdin_behavior = StdIo.Inherit, |
| 110 | .stdout_behavior = StdIo.Inherit, | 110 | .stdout_behavior = StdIo.Inherit, |
| 111 | .stderr_behavior = StdIo.Inherit, | 111 | .stderr_behavior = StdIo.Inherit, |
| 112 | }); | 112 | }; |
| 113 | errdefer allocator.destroy(child); | 113 | errdefer allocator.destroy(child); |
| 114 | return child; | 114 | return child; |
| 115 | } | 115 | } |
| ... | @@ -573,7 +573,7 @@ pub const ChildProcess = struct { | ... | @@ -573,7 +573,7 @@ pub const ChildProcess = struct { |
| 573 | // to match posix semantics | 573 | // to match posix semantics |
| 574 | const app_name = x: { | 574 | const app_name = x: { |
| 575 | if (self.cwd) |cwd| { | 575 | if (self.cwd) |cwd| { |
| 576 | const resolved = try os.path.resolve(self.allocator, cwd, self.argv[0]); | 576 | const resolved = try os.path.resolve(self.allocator, [][]const u8{ cwd, self.argv[0] }); |
| 577 | defer self.allocator.free(resolved); | 577 | defer self.allocator.free(resolved); |
| 578 | break :x try cstr.addNullByte(self.allocator, resolved); | 578 | break :x try cstr.addNullByte(self.allocator, resolved); |
| 579 | } else { | 579 | } else { |
| ... | @@ -594,12 +594,12 @@ pub const ChildProcess = struct { | ... | @@ -594,12 +594,12 @@ pub const ChildProcess = struct { |
| 594 | const PATH = try os.getEnvVarOwned(self.allocator, "PATH"); | 594 | const PATH = try os.getEnvVarOwned(self.allocator, "PATH"); |
| 595 | defer self.allocator.free(PATH); | 595 | defer self.allocator.free(PATH); |
| 596 | 596 | ||
| 597 | var it = mem.split(PATH, ";"); | 597 | var it = mem.tokenize(PATH, ";"); |
| 598 | while (it.next()) |search_path| { | 598 | while (it.next()) |search_path| { |
| 599 | const joined_path = try os.path.join(self.allocator, search_path, app_name); | 599 | const joined_path = try os.path.join(self.allocator, [][]const u8{ search_path, app_name }); |
| 600 | defer self.allocator.free(joined_path); | 600 | defer self.allocator.free(joined_path); |
| 601 | 601 | ||
| 602 | const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, app_name); | 602 | const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path); |
| 603 | defer self.allocator.free(joined_path_w); | 603 | defer self.allocator.free(joined_path_w); |
| 604 | 604 | ||
| 605 | if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| { | 605 | if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| { |
| ... | @@ -609,6 +609,9 @@ pub const ChildProcess = struct { | ... | @@ -609,6 +609,9 @@ pub const ChildProcess = struct { |
| 609 | } else { | 609 | } else { |
| 610 | return err; | 610 | return err; |
| 611 | } | 611 | } |
| 612 | } else { | ||
| 613 | // Every other error would have been returned earlier. | ||
| 614 | return error.FileNotFound; | ||
| 612 | } | 615 | } |
| 613 | }; | 616 | }; |
| 614 | 617 | ||
| ... | @@ -807,10 +810,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); | ... | @@ -807,10 +810,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); |
| 807 | 810 | ||
| 808 | fn writeIntFd(fd: i32, value: ErrInt) !void { | 811 | fn writeIntFd(fd: i32, value: ErrInt) !void { |
| 809 | const stream = &os.File.openHandle(fd).outStream().stream; | 812 | const stream = &os.File.openHandle(fd).outStream().stream; |
| 810 | stream.writeIntNe(ErrInt, value) catch return error.SystemResources; | 813 | stream.writeIntNative(ErrInt, value) catch return error.SystemResources; |
| 811 | } | 814 | } |
| 812 | 815 | ||
| 813 | fn readIntFd(fd: i32) !ErrInt { | 816 | fn readIntFd(fd: i32) !ErrInt { |
| 814 | const stream = &os.File.openHandle(fd).inStream().stream; | 817 | const stream = &os.File.openHandle(fd).inStream().stream; |
| 815 | return stream.readIntNe(ErrInt) catch return error.SystemResources; | 818 | return stream.readIntNative(ErrInt) catch return error.SystemResources; |
| 816 | } | 819 | } |
std/os/darwin.zig+1-1| ... | @@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize { | ... | @@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize { |
| 665 | 665 | ||
| 666 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { | 666 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { |
| 667 | const ptr_result = c.mmap( | 667 | const ptr_result = c.mmap( |
| 668 | @ptrCast(*c_void, address), | 668 | @ptrCast(?*c_void, address), |
| 669 | length, | 669 | length, |
| 670 | @bitCast(c_int, @intCast(c_uint, prot)), | 670 | @bitCast(c_int, @intCast(c_uint, prot)), |
| 671 | @bitCast(c_int, c_uint(flags)), | 671 | @bitCast(c_int, c_uint(flags)), |
std/os/freebsd/index.zig+171-120| ... | @@ -1,16 +1,20 @@ | ... | @@ -1,16 +1,20 @@ |
| 1 | const assert = @import("../debug.zig").assert; | ||
| 2 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 3 | const arch = switch (builtin.arch) { | 2 | |
| 4 | builtin.Arch.x86_64 => @import("x86_64.zig"), | ||
| 5 | else => @compileError("unsupported arch"), | ||
| 6 | }; | ||
| 7 | pub use @import("syscall.zig"); | ||
| 8 | pub use @import("errno.zig"); | 3 | pub use @import("errno.zig"); |
| 9 | 4 | ||
| 10 | const std = @import("../../index.zig"); | 5 | const std = @import("../../index.zig"); |
| 11 | const c = std.c; | 6 | const c = std.c; |
| 7 | |||
| 8 | const assert = std.debug.assert; | ||
| 9 | const maxInt = std.math.maxInt; | ||
| 12 | pub const Kevent = c.Kevent; | 10 | pub const Kevent = c.Kevent; |
| 13 | 11 | ||
| 12 | pub const CTL_KERN = 1; | ||
| 13 | pub const CTL_DEBUG = 5; | ||
| 14 | |||
| 15 | pub const KERN_PROC = 14; // struct: process entries | ||
| 16 | pub const KERN_PROC_PATHNAME = 12; // path to executable | ||
| 17 | |||
| 14 | pub const PATH_MAX = 1024; | 18 | pub const PATH_MAX = 1024; |
| 15 | 19 | ||
| 16 | pub const STDIN_FILENO = 0; | 20 | pub const STDIN_FILENO = 0; |
| ... | @@ -22,7 +26,22 @@ pub const PROT_READ = 1; | ... | @@ -22,7 +26,22 @@ pub const PROT_READ = 1; |
| 22 | pub const PROT_WRITE = 2; | 26 | pub const PROT_WRITE = 2; |
| 23 | pub const PROT_EXEC = 4; | 27 | pub const PROT_EXEC = 4; |
| 24 | 28 | ||
| 25 | pub const MAP_FAILED = @maxValue(usize); | 29 | pub const CLOCK_REALTIME = 0; |
| 30 | pub const CLOCK_VIRTUAL = 1; | ||
| 31 | pub const CLOCK_PROF = 2; | ||
| 32 | pub const CLOCK_MONOTONIC = 4; | ||
| 33 | pub const CLOCK_UPTIME = 5; | ||
| 34 | pub const CLOCK_UPTIME_PRECISE = 7; | ||
| 35 | pub const CLOCK_UPTIME_FAST = 8; | ||
| 36 | pub const CLOCK_REALTIME_PRECISE = 9; | ||
| 37 | pub const CLOCK_REALTIME_FAST = 10; | ||
| 38 | pub const CLOCK_MONOTONIC_PRECISE = 11; | ||
| 39 | pub const CLOCK_MONOTONIC_FAST = 12; | ||
| 40 | pub const CLOCK_SECOND = 13; | ||
| 41 | pub const CLOCK_THREAD_CPUTIME_ID = 14; | ||
| 42 | pub const CLOCK_PROCESS_CPUTIME_ID = 15; | ||
| 43 | |||
| 44 | pub const MAP_FAILED = maxInt(usize); | ||
| 26 | pub const MAP_SHARED = 0x0001; | 45 | pub const MAP_SHARED = 0x0001; |
| 27 | pub const MAP_PRIVATE = 0x0002; | 46 | pub const MAP_PRIVATE = 0x0002; |
| 28 | pub const MAP_FIXED = 0x0010; | 47 | pub const MAP_FIXED = 0x0010; |
| ... | @@ -94,26 +113,33 @@ pub const SIGLIBRT = 33; | ... | @@ -94,26 +113,33 @@ pub const SIGLIBRT = 33; |
| 94 | pub const SIGRTMIN = 65; | 113 | pub const SIGRTMIN = 65; |
| 95 | pub const SIGRTMAX = 126; | 114 | pub const SIGRTMAX = 126; |
| 96 | 115 | ||
| 97 | pub const O_RDONLY = 0o0; | 116 | // access function |
| 98 | pub const O_WRONLY = 0o1; | 117 | pub const F_OK = 0; // test for existence of file |
| 99 | pub const O_RDWR = 0o2; | 118 | pub const X_OK = 1; // test for execute or search permission |
| 100 | pub const O_ACCMODE = 0o3; | 119 | pub const W_OK = 2; // test for write permission |
| 101 | 120 | pub const R_OK = 4; // test for read permission | |
| 102 | pub const O_CREAT = 0o100; | 121 | |
| 103 | pub const O_EXCL = 0o200; | 122 | |
| 104 | pub const O_NOCTTY = 0o400; | 123 | pub const O_RDONLY = 0x0000; |
| 105 | pub const O_TRUNC = 0o1000; | 124 | pub const O_WRONLY = 0x0001; |
| 106 | pub const O_APPEND = 0o2000; | 125 | pub const O_RDWR = 0x0002; |
| 107 | pub const O_NONBLOCK = 0o4000; | 126 | pub const O_ACCMODE = 0x0003; |
| 127 | |||
| 128 | pub const O_CREAT = 0x0200; | ||
| 129 | pub const O_EXCL = 0x0800; | ||
| 130 | pub const O_NOCTTY = 0x8000; | ||
| 131 | pub const O_TRUNC = 0x0400; | ||
| 132 | pub const O_APPEND = 0x0008; | ||
| 133 | pub const O_NONBLOCK = 0x0004; | ||
| 108 | pub const O_DSYNC = 0o10000; | 134 | pub const O_DSYNC = 0o10000; |
| 109 | pub const O_SYNC = 0o4010000; | 135 | pub const O_SYNC = 0x0080; |
| 110 | pub const O_RSYNC = 0o4010000; | 136 | pub const O_RSYNC = 0o4010000; |
| 111 | pub const O_DIRECTORY = 0o200000; | 137 | pub const O_DIRECTORY = 0o200000; |
| 112 | pub const O_NOFOLLOW = 0o400000; | 138 | pub const O_NOFOLLOW = 0x0100; |
| 113 | pub const O_CLOEXEC = 0o2000000; | 139 | pub const O_CLOEXEC = 0x00100000; |
| 114 | 140 | ||
| 115 | pub const O_ASYNC = 0o20000; | 141 | pub const O_ASYNC = 0x0040; |
| 116 | pub const O_DIRECT = 0o40000; | 142 | pub const O_DIRECT = 0x00010000; |
| 117 | pub const O_LARGEFILE = 0; | 143 | pub const O_LARGEFILE = 0; |
| 118 | pub const O_NOATIME = 0o1000000; | 144 | pub const O_NOATIME = 0o1000000; |
| 119 | pub const O_PATH = 0o10000000; | 145 | pub const O_PATH = 0o10000000; |
| ... | @@ -157,7 +183,6 @@ pub const SOCK_SEQPACKET = 5; | ... | @@ -157,7 +183,6 @@ pub const SOCK_SEQPACKET = 5; |
| 157 | pub const SOCK_CLOEXEC = 0x10000000; | 183 | pub const SOCK_CLOEXEC = 0x10000000; |
| 158 | pub const SOCK_NONBLOCK = 0x20000000; | 184 | pub const SOCK_NONBLOCK = 0x20000000; |
| 159 | 185 | ||
| 160 | // TODO: From here | ||
| 161 | pub const PROTO_ip = 0o000; | 186 | pub const PROTO_ip = 0o000; |
| 162 | pub const PROTO_icmp = 0o001; | 187 | pub const PROTO_icmp = 0o001; |
| 163 | pub const PROTO_igmp = 0o002; | 188 | pub const PROTO_igmp = 0o002; |
| ... | @@ -500,6 +525,10 @@ pub const TIOCGPKT = 0x80045438; | ... | @@ -500,6 +525,10 @@ pub const TIOCGPKT = 0x80045438; |
| 500 | pub const TIOCGPTLCK = 0x80045439; | 525 | pub const TIOCGPTLCK = 0x80045439; |
| 501 | pub const TIOCGEXCL = 0x80045440; | 526 | pub const TIOCGEXCL = 0x80045440; |
| 502 | 527 | ||
| 528 | pub const sockaddr = c.sockaddr; | ||
| 529 | pub const sockaddr_in = c.sockaddr_in; | ||
| 530 | pub const sockaddr_in6 = c.sockaddr_in6; | ||
| 531 | |||
| 503 | fn unsigned(s: i32) u32 { | 532 | fn unsigned(s: i32) u32 { |
| 504 | return @bitCast(u32, s); | 533 | return @bitCast(u32, s); |
| 505 | } | 534 | } |
| ... | @@ -539,96 +568,117 @@ pub fn getErrno(r: usize) usize { | ... | @@ -539,96 +568,117 @@ pub fn getErrno(r: usize) usize { |
| 539 | } | 568 | } |
| 540 | 569 | ||
| 541 | pub fn dup2(old: i32, new: i32) usize { | 570 | pub fn dup2(old: i32, new: i32) usize { |
| 542 | return arch.syscall2(SYS_dup2, @intCast(usize, old), @intCast(usize, new)); | 571 | return errnoWrap(c.dup2(old, new)); |
| 543 | } | 572 | } |
| 544 | 573 | ||
| 545 | pub fn chdir(path: [*]const u8) usize { | 574 | pub fn chdir(path: [*]const u8) usize { |
| 546 | return arch.syscall1(SYS_chdir, @ptrToInt(path)); | 575 | return errnoWrap(c.chdir(path)); |
| 547 | } | 576 | } |
| 548 | 577 | ||
| 549 | pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize { | 578 | pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize { |
| 550 | return arch.syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp)); | 579 | return errnoWrap(c.execve(path, argv, envp)); |
| 551 | } | 580 | } |
| 552 | 581 | ||
| 553 | pub fn fork() usize { | 582 | pub fn fork() usize { |
| 554 | return arch.syscall0(SYS_fork); | 583 | return errnoWrap(c.fork()); |
| 584 | } | ||
| 585 | |||
| 586 | pub fn access(path: [*]const u8, mode: u32) usize { | ||
| 587 | return errnoWrap(c.access(path, mode)); | ||
| 555 | } | 588 | } |
| 556 | 589 | ||
| 557 | pub fn getcwd(buf: [*]u8, size: usize) usize { | 590 | pub fn getcwd(buf: [*]u8, size: usize) usize { |
| 558 | return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size); | 591 | return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0; |
| 559 | } | 592 | } |
| 560 | 593 | ||
| 561 | pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize { | 594 | pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize { |
| 562 | return arch.syscall3(SYS_getdents, @intCast(usize, fd), @ptrToInt(dirp), count); | 595 | return errnoWrap(@bitCast(isize, c.getdents(fd, drip, count))); |
| 596 | } | ||
| 597 | |||
| 598 | pub fn getdirentries(fd: i32, buf_ptr: [*]u8, buf_len: usize, basep: *i64) usize { | ||
| 599 | return errnoWrap(@bitCast(isize, c.getdirentries(fd, buf_ptr, buf_len, basep))); | ||
| 600 | } | ||
| 601 | |||
| 602 | pub fn realpath(noalias filename: [*]const u8, noalias resolved_name: [*]u8) usize { | ||
| 603 | return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0; | ||
| 563 | } | 604 | } |
| 564 | 605 | ||
| 565 | pub fn isatty(fd: i32) bool { | 606 | pub fn isatty(fd: i32) bool { |
| 566 | var wsz: winsize = undefined; | 607 | return c.isatty(fd) != 0; |
| 567 | return arch.syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; | ||
| 568 | } | 608 | } |
| 569 | 609 | ||
| 570 | pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { | 610 | pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { |
| 571 | return arch.syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); | 611 | return errnoWrap(c.readlink(path, buf_ptr, buf_len)); |
| 572 | } | 612 | } |
| 573 | 613 | ||
| 574 | pub fn mkdir(path: [*]const u8, mode: u32) usize { | 614 | pub fn mkdir(path: [*]const u8, mode: u32) usize { |
| 575 | return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode); | 615 | return errnoWrap(c.mkdir(path, mode)); |
| 576 | } | 616 | } |
| 577 | 617 | ||
| 578 | pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize { | 618 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { |
| 579 | return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset)); | 619 | const ptr_result = c.mmap( |
| 620 | @ptrCast(?*c_void, address), | ||
| 621 | length, | ||
| 622 | @bitCast(c_int, @intCast(c_uint, prot)), | ||
| 623 | @bitCast(c_int, c_uint(flags)), | ||
| 624 | fd, | ||
| 625 | offset, | ||
| 626 | ); | ||
| 627 | const isize_result = @bitCast(isize, @ptrToInt(ptr_result)); | ||
| 628 | return errnoWrap(isize_result); | ||
| 580 | } | 629 | } |
| 581 | 630 | ||
| 582 | pub fn munmap(address: usize, length: usize) usize { | 631 | pub fn munmap(address: usize, length: usize) usize { |
| 583 | return arch.syscall2(SYS_munmap, address, length); | 632 | return errnoWrap(c.munmap(@intToPtr(*c_void, address), length)); |
| 584 | } | 633 | } |
| 585 | 634 | ||
| 586 | pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | 635 | pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize { |
| 587 | return arch.syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count); | 636 | return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte)); |
| 588 | } | 637 | } |
| 589 | 638 | ||
| 590 | pub fn rmdir(path: [*]const u8) usize { | 639 | pub fn rmdir(path: [*]const u8) usize { |
| 591 | return arch.syscall1(SYS_rmdir, @ptrToInt(path)); | 640 | return errnoWrap(c.rmdir(path)); |
| 592 | } | 641 | } |
| 593 | 642 | ||
| 594 | pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { | 643 | pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { |
| 595 | return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new)); | 644 | return errnoWrap(c.symlink(existing, new)); |
| 596 | } | 645 | } |
| 597 | 646 | ||
| 598 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize { | 647 | pub fn pread(fd: i32, buf: [*]u8, nbyte: usize, offset: u64) usize { |
| 599 | return arch.syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset); | 648 | return errnoWrap(c.pread(fd, @ptrCast(*c_void, buf), nbyte, offset)); |
| 600 | } | 649 | } |
| 601 | 650 | ||
| 602 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize { | 651 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize { |
| 603 | return arch.syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset); | 652 | return errnoWrap(c.preadv(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset)); |
| 604 | } | 653 | } |
| 605 | 654 | ||
| 606 | pub fn pipe(fd: *[2]i32) usize { | 655 | pub fn pipe(fd: *[2]i32) usize { |
| 607 | return pipe2(fd, 0); | 656 | return pipe2(fd, 0); |
| 608 | } | 657 | } |
| 609 | 658 | ||
| 610 | pub fn pipe2(fd: *[2]i32, flags: usize) usize { | 659 | pub fn pipe2(fd: *[2]i32, flags: u32) usize { |
| 611 | return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags); | 660 | comptime assert(i32.bit_count == c_int.bit_count); |
| 661 | return errnoWrap(c.pipe2(@ptrCast(*[2]c_int, fd), flags)); | ||
| 612 | } | 662 | } |
| 613 | 663 | ||
| 614 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | 664 | pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize { |
| 615 | return arch.syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count); | 665 | return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte)); |
| 616 | } | 666 | } |
| 617 | 667 | ||
| 618 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { | 668 | pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize { |
| 619 | return arch.syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset); | 669 | return errnoWrap(c.pwrite(fd, @ptrCast(*const c_void, buf), nbyte, offset)); |
| 620 | } | 670 | } |
| 621 | 671 | ||
| 622 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize { | 672 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize { |
| 623 | return arch.syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset); | 673 | return errnoWrap(c.pwritev(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset)); |
| 624 | } | 674 | } |
| 625 | 675 | ||
| 626 | pub fn rename(old: [*]const u8, new: [*]const u8) usize { | 676 | pub fn rename(old: [*]const u8, new: [*]const u8) usize { |
| 627 | return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new)); | 677 | return errnoWrap(c.rename(old, new)); |
| 628 | } | 678 | } |
| 629 | 679 | ||
| 630 | pub fn open(path: [*]const u8, flags: u32, perm: usize) usize { | 680 | pub fn open(path: [*]const u8, flags: u32, mode: usize) usize { |
| 631 | return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm); | 681 | return errnoWrap(c.open(path, @bitCast(c_int, flags), mode)); |
| 632 | } | 682 | } |
| 633 | 683 | ||
| 634 | pub fn create(path: [*]const u8, perm: usize) usize { | 684 | pub fn create(path: [*]const u8, perm: usize) usize { |
| ... | @@ -636,120 +686,114 @@ pub fn create(path: [*]const u8, perm: usize) usize { | ... | @@ -636,120 +686,114 @@ pub fn create(path: [*]const u8, perm: usize) usize { |
| 636 | } | 686 | } |
| 637 | 687 | ||
| 638 | pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize { | 688 | pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize { |
| 639 | return arch.syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode); | 689 | return errnoWrap(c.openat(@bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode)); |
| 640 | } | 690 | } |
| 641 | 691 | ||
| 642 | pub fn close(fd: i32) usize { | 692 | pub fn close(fd: i32) usize { |
| 643 | return arch.syscall1(SYS_close, @intCast(usize, fd)); | 693 | return errnoWrap(c.close(fd)); |
| 644 | } | 694 | } |
| 645 | 695 | ||
| 646 | pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize { | 696 | pub fn lseek(fd: i32, offset: isize, whence: c_int) usize { |
| 647 | return arch.syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos); | 697 | return errnoWrap(c.lseek(fd, offset, whence)); |
| 648 | } | 698 | } |
| 649 | 699 | ||
| 650 | pub fn exit(status: i32) noreturn { | 700 | pub fn exit(code: i32) noreturn { |
| 651 | _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status))); | 701 | c.exit(code); |
| 652 | unreachable; | ||
| 653 | } | ||
| 654 | |||
| 655 | pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { | ||
| 656 | return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags)); | ||
| 657 | } | 702 | } |
| 658 | 703 | ||
| 659 | pub fn kill(pid: i32, sig: i32) usize { | 704 | pub fn kill(pid: i32, sig: i32) usize { |
| 660 | return arch.syscall2(SYS_kill, @bitCast(usize, @intCast(isize, pid)), @intCast(usize, sig)); | 705 | return errnoWrap(c.kill(pid, sig)); |
| 661 | } | 706 | } |
| 662 | 707 | ||
| 663 | pub fn unlink(path: [*]const u8) usize { | 708 | pub fn unlink(path: [*]const u8) usize { |
| 664 | return arch.syscall1(SYS_unlink, @ptrToInt(path)); | 709 | return errnoWrap(c.unlink(path)); |
| 665 | } | 710 | } |
| 666 | 711 | ||
| 667 | pub fn waitpid(pid: i32, status: *i32, options: i32) usize { | 712 | pub fn waitpid(pid: i32, status: *i32, options: u32) usize { |
| 668 | return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0); | 713 | comptime assert(i32.bit_count == c_int.bit_count); |
| 714 | return errnoWrap(c.waitpid(pid, @ptrCast(*c_int, status), @bitCast(c_int, options))); | ||
| 669 | } | 715 | } |
| 670 | 716 | ||
| 671 | pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { | 717 | pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { |
| 672 | return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); | 718 | return errnoWrap(c.nanosleep(req, rem)); |
| 719 | } | ||
| 720 | |||
| 721 | pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { | ||
| 722 | return errnoWrap(c.clock_gettime(clk_id, tp)); | ||
| 723 | } | ||
| 724 | |||
| 725 | pub fn clock_getres(clk_id: i32, tp: *timespec) usize { | ||
| 726 | return errnoWrap(c.clock_getres(clk_id, tp)); | ||
| 673 | } | 727 | } |
| 674 | 728 | ||
| 675 | pub fn setuid(uid: u32) usize { | 729 | pub fn setuid(uid: u32) usize { |
| 676 | return arch.syscall1(SYS_setuid, uid); | 730 | return errnoWrap(c.setuid(uid)); |
| 677 | } | 731 | } |
| 678 | 732 | ||
| 679 | pub fn setgid(gid: u32) usize { | 733 | pub fn setgid(gid: u32) usize { |
| 680 | return arch.syscall1(SYS_setgid, gid); | 734 | return errnoWrap(c.setgid(gid)); |
| 681 | } | 735 | } |
| 682 | 736 | ||
| 683 | pub fn setreuid(ruid: u32, euid: u32) usize { | 737 | pub fn setreuid(ruid: u32, euid: u32) usize { |
| 684 | return arch.syscall2(SYS_setreuid, ruid, euid); | 738 | return errnoWrap(c.setreuid(ruid, euid)); |
| 685 | } | 739 | } |
| 686 | 740 | ||
| 687 | pub fn setregid(rgid: u32, egid: u32) usize { | 741 | pub fn setregid(rgid: u32, egid: u32) usize { |
| 688 | return arch.syscall2(SYS_setregid, rgid, egid); | 742 | return errnoWrap(c.setregid(rgid, egid)); |
| 689 | } | 743 | } |
| 690 | 744 | ||
| 691 | pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize { | 745 | const NSIG = 32; |
| 692 | // TODO: Implement | ||
| 693 | return 0; | ||
| 694 | } | ||
| 695 | |||
| 696 | pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize { | ||
| 697 | // TODO: Implement | ||
| 698 | return 0; | ||
| 699 | } | ||
| 700 | 746 | ||
| 701 | const NSIG = 65; | 747 | pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize)); |
| 702 | const sigset_t = [128 / @sizeOf(usize)]usize; | 748 | pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); |
| 703 | const all_mask = []usize{@maxValue(usize)}; | 749 | pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); |
| 704 | const app_mask = []usize{0xfffffffc7fffffff}; | ||
| 705 | 750 | ||
| 706 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 751 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 707 | pub const Sigaction = struct { | 752 | pub const Sigaction = extern struct { |
| 708 | // TODO: Adjust to use freebsd struct layout | 753 | /// signal handler |
| 709 | handler: extern fn (i32) void, | 754 | __sigaction_u: extern union { |
| 710 | mask: sigset_t, | 755 | __sa_handler: extern fn (i32) void, |
| 711 | flags: u32, | 756 | __sa_sigaction: extern fn (i32, *__siginfo, usize) void, |
| 757 | }, | ||
| 758 | |||
| 759 | /// see signal options | ||
| 760 | sa_flags: u32, | ||
| 761 | |||
| 762 | /// signal mask to apply | ||
| 763 | sa_mask: sigset_t, | ||
| 712 | }; | 764 | }; |
| 713 | 765 | ||
| 714 | pub const SIG_ERR = @intToPtr(extern fn (i32) void, @maxValue(usize)); | 766 | pub const _SIG_WORDS = 4; |
| 715 | pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); | 767 | pub const _SIG_MAXSIG = 128; |
| 716 | pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); | ||
| 717 | pub const empty_sigset = []usize{0} ** sigset_t.len; | ||
| 718 | 768 | ||
| 719 | pub fn raise(sig: i32) usize { | 769 | pub inline fn _SIG_IDX(sig: usize) usize { |
| 720 | // TODO implement, see linux equivalent for what we want to try and do | 770 | return sig - 1; |
| 721 | return 0; | ||
| 722 | } | 771 | } |
| 723 | 772 | pub inline fn _SIG_WORD(sig: usize) usize { | |
| 724 | fn blockAllSignals(set: *sigset_t) void { | 773 | return_SIG_IDX(sig) >> 5; |
| 725 | // TODO implement | ||
| 726 | } | 774 | } |
| 727 | 775 | pub inline fn _SIG_BIT(sig: usize) usize { | |
| 728 | fn blockAppSignals(set: *sigset_t) void { | 776 | return 1 << (_SIG_IDX(sig) & 31); |
| 729 | // TODO implement | ||
| 730 | } | 777 | } |
| 731 | 778 | pub inline fn _SIG_VALID(sig: usize) usize { | |
| 732 | fn restoreSignals(set: *sigset_t) void { | 779 | return sig <= _SIG_MAXSIG and sig > 0; |
| 733 | // TODO implement | ||
| 734 | } | 780 | } |
| 735 | 781 | ||
| 736 | pub fn sigaddset(set: *sigset_t, sig: u6) void { | 782 | pub const sigset_t = extern struct { |
| 737 | const s = sig - 1; | 783 | __bits: [_SIG_WORDS]u32, |
| 738 | (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1)); | 784 | }; |
| 739 | } | ||
| 740 | 785 | ||
| 741 | pub fn sigismember(set: *const sigset_t, sig: u6) bool { | 786 | pub fn raise(sig: i32) usize { |
| 742 | const s = sig - 1; | 787 | return errnoWrap(c.raise(sig)); |
| 743 | return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0; | ||
| 744 | } | 788 | } |
| 745 | 789 | ||
| 746 | pub const Stat = arch.Stat; | 790 | pub const Stat = c.Stat; |
| 747 | pub const timespec = arch.timespec; | 791 | pub const dirent = c.dirent; |
| 792 | pub const timespec = c.timespec; | ||
| 748 | 793 | ||
| 749 | pub fn fstat(fd: i32, stat_buf: *Stat) usize { | 794 | pub fn fstat(fd: i32, buf: *c.Stat) usize { |
| 750 | return arch.syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf)); | 795 | return errnoWrap(c.fstat(fd, buf)); |
| 751 | } | 796 | } |
| 752 | |||
| 753 | pub const iovec = extern struct { | 797 | pub const iovec = extern struct { |
| 754 | iov_base: [*]u8, | 798 | iov_base: [*]u8, |
| 755 | iov_len: usize, | 799 | iov_len: usize, |
| ... | @@ -760,10 +804,12 @@ pub const iovec_const = extern struct { | ... | @@ -760,10 +804,12 @@ pub const iovec_const = extern struct { |
| 760 | iov_len: usize, | 804 | iov_len: usize, |
| 761 | }; | 805 | }; |
| 762 | 806 | ||
| 807 | // TODO avoid libc dependency | ||
| 763 | pub fn kqueue() usize { | 808 | pub fn kqueue() usize { |
| 764 | return errnoWrap(c.kqueue()); | 809 | return errnoWrap(c.kqueue()); |
| 765 | } | 810 | } |
| 766 | 811 | ||
| 812 | // TODO avoid libc dependency | ||
| 767 | pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize { | 813 | pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize { |
| 768 | return errnoWrap(c.kevent( | 814 | return errnoWrap(c.kevent( |
| 769 | kq, | 815 | kq, |
| ... | @@ -775,18 +821,23 @@ pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: | ... | @@ -775,18 +821,23 @@ pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: |
| 775 | )); | 821 | )); |
| 776 | } | 822 | } |
| 777 | 823 | ||
| 824 | // TODO avoid libc dependency | ||
| 778 | pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { | 825 | pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { |
| 779 | return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen)); | 826 | return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen)); |
| 780 | } | 827 | } |
| 781 | 828 | ||
| 829 | // TODO avoid libc dependency | ||
| 782 | pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { | 830 | pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { |
| 783 | return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen)); | 831 | return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen)); |
| 784 | } | 832 | } |
| 785 | 833 | ||
| 834 | // TODO avoid libc dependency | ||
| 786 | pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize { | 835 | pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize { |
| 787 | return errnoWrap(c.sysctlnametomib(name, wibp, sizep)); | 836 | return errnoWrap(c.sysctlnametomib(name, wibp, sizep)); |
| 788 | } | 837 | } |
| 789 | 838 | ||
| 839 | // TODO avoid libc dependency | ||
| 840 | |||
| 790 | /// Takes the return value from a syscall and formats it back in the way | 841 | /// Takes the return value from a syscall and formats it back in the way |
| 791 | /// that the kernel represents it to libc. Errno was a mistake, let's make | 842 | /// that the kernel represents it to libc. Errno was a mistake, let's make |
| 792 | /// it go away forever. | 843 | /// it go away forever. |
std/os/freebsd/syscall.zig deleted-493| ... | @@ -1,493 +0,0 @@ | ||
| 1 | pub const SYS_syscall = 0; | ||
| 2 | pub const SYS_exit = 1; | ||
| 3 | pub const SYS_fork = 2; | ||
| 4 | pub const SYS_read = 3; | ||
| 5 | pub const SYS_write = 4; | ||
| 6 | pub const SYS_open = 5; | ||
| 7 | pub const SYS_close = 6; | ||
| 8 | pub const SYS_wait4 = 7; | ||
| 9 | // 8 is old creat | ||
| 10 | pub const SYS_link = 9; | ||
| 11 | pub const SYS_unlink = 10; | ||
| 12 | // 11 is obsolete execv | ||
| 13 | pub const SYS_chdir = 12; | ||
| 14 | pub const SYS_fchdir = 13; | ||
| 15 | pub const SYS_freebsd11_mknod = 14; | ||
| 16 | pub const SYS_chmod = 15; | ||
| 17 | pub const SYS_chown = 16; | ||
| 18 | pub const SYS_break = 17; | ||
| 19 | // 18 is freebsd4 getfsstat | ||
| 20 | // 19 is old lseek | ||
| 21 | pub const SYS_getpid = 20; | ||
| 22 | pub const SYS_mount = 21; | ||
| 23 | pub const SYS_unmount = 22; | ||
| 24 | pub const SYS_setuid = 23; | ||
| 25 | pub const SYS_getuid = 24; | ||
| 26 | pub const SYS_geteuid = 25; | ||
| 27 | pub const SYS_ptrace = 26; | ||
| 28 | pub const SYS_recvmsg = 27; | ||
| 29 | pub const SYS_sendmsg = 28; | ||
| 30 | pub const SYS_recvfrom = 29; | ||
| 31 | pub const SYS_accept = 30; | ||
| 32 | pub const SYS_getpeername = 31; | ||
| 33 | pub const SYS_getsockname = 32; | ||
| 34 | pub const SYS_access = 33; | ||
| 35 | pub const SYS_chflags = 34; | ||
| 36 | pub const SYS_fchflags = 35; | ||
| 37 | pub const SYS_sync = 36; | ||
| 38 | pub const SYS_kill = 37; | ||
| 39 | // 38 is old stat | ||
| 40 | pub const SYS_getppid = 39; | ||
| 41 | // 40 is old lstat | ||
| 42 | pub const SYS_dup = 41; | ||
| 43 | pub const SYS_freebsd10_pipe = 42; | ||
| 44 | pub const SYS_getegid = 43; | ||
| 45 | pub const SYS_profil = 44; | ||
| 46 | pub const SYS_ktrace = 45; | ||
| 47 | // 46 is old sigaction | ||
| 48 | pub const SYS_getgid = 47; | ||
| 49 | // 48 is old sigprocmask | ||
| 50 | pub const SYS_getlogin = 49; | ||
| 51 | pub const SYS_setlogin = 50; | ||
| 52 | pub const SYS_acct = 51; | ||
| 53 | // 52 is old sigpending | ||
| 54 | pub const SYS_sigaltstack = 53; | ||
| 55 | pub const SYS_ioctl = 54; | ||
| 56 | pub const SYS_reboot = 55; | ||
| 57 | pub const SYS_revoke = 56; | ||
| 58 | pub const SYS_symlink = 57; | ||
| 59 | pub const SYS_readlink = 58; | ||
| 60 | pub const SYS_execve = 59; | ||
| 61 | pub const SYS_umask = 60; | ||
| 62 | pub const SYS_chroot = 61; | ||
| 63 | // 62 is old fstat | ||
| 64 | // 63 is old getkerninfo | ||
| 65 | // 64 is old getpagesize | ||
| 66 | pub const SYS_msync = 65; | ||
| 67 | pub const SYS_vfork = 66; | ||
| 68 | // 67 is obsolete vread | ||
| 69 | // 68 is obsolete vwrite | ||
| 70 | // 69 is obsolete sbrk (still present on some platforms) | ||
| 71 | pub const SYS_sstk = 70; | ||
| 72 | // 71 is old mmap | ||
| 73 | pub const SYS_vadvise = 72; | ||
| 74 | pub const SYS_munmap = 73; | ||
| 75 | pub const SYS_mprotect = 74; | ||
| 76 | pub const SYS_madvise = 75; | ||
| 77 | // 76 is obsolete vhangup | ||
| 78 | // 77 is obsolete vlimit | ||
| 79 | pub const SYS_mincore = 78; | ||
| 80 | pub const SYS_getgroups = 79; | ||
| 81 | pub const SYS_setgroups = 80; | ||
| 82 | pub const SYS_getpgrp = 81; | ||
| 83 | pub const SYS_setpgid = 82; | ||
| 84 | pub const SYS_setitimer = 83; | ||
| 85 | // 84 is old wait | ||
| 86 | pub const SYS_swapon = 85; | ||
| 87 | pub const SYS_getitimer = 86; | ||
| 88 | // 87 is old gethostname | ||
| 89 | // 88 is old sethostname | ||
| 90 | pub const SYS_getdtablesize = 89; | ||
| 91 | pub const SYS_dup2 = 90; | ||
| 92 | pub const SYS_fcntl = 92; | ||
| 93 | pub const SYS_select = 93; | ||
| 94 | pub const SYS_fsync = 95; | ||
| 95 | pub const SYS_setpriority = 96; | ||
| 96 | pub const SYS_socket = 97; | ||
| 97 | pub const SYS_connect = 98; | ||
| 98 | // 99 is old accept | ||
| 99 | pub const SYS_getpriority = 100; | ||
| 100 | // 101 is old send | ||
| 101 | // 102 is old recv | ||
| 102 | // 103 is old sigreturn | ||
| 103 | pub const SYS_bind = 104; | ||
| 104 | pub const SYS_setsockopt = 105; | ||
| 105 | pub const SYS_listen = 106; | ||
| 106 | // 107 is obsolete vtimes | ||
| 107 | // 108 is old sigvec | ||
| 108 | // 109 is old sigblock | ||
| 109 | // 110 is old sigsetmask | ||
| 110 | // 111 is old sigsuspend | ||
| 111 | // 112 is old sigstack | ||
| 112 | // 113 is old recvmsg | ||
| 113 | // 114 is old sendmsg | ||
| 114 | // 115 is obsolete vtrace | ||
| 115 | pub const SYS_gettimeofday = 116; | ||
| 116 | pub const SYS_getrusage = 117; | ||
| 117 | pub const SYS_getsockopt = 118; | ||
| 118 | pub const SYS_readv = 120; | ||
| 119 | pub const SYS_writev = 121; | ||
| 120 | pub const SYS_settimeofday = 122; | ||
| 121 | pub const SYS_fchown = 123; | ||
| 122 | pub const SYS_fchmod = 124; | ||
| 123 | // 125 is old recvfrom | ||
| 124 | pub const SYS_setreuid = 126; | ||
| 125 | pub const SYS_setregid = 127; | ||
| 126 | pub const SYS_rename = 128; | ||
| 127 | // 129 is old truncate | ||
| 128 | // 130 is old ftruncate | ||
| 129 | pub const SYS_flock = 131; | ||
| 130 | pub const SYS_mkfifo = 132; | ||
| 131 | pub const SYS_sendto = 133; | ||
| 132 | pub const SYS_shutdown = 134; | ||
| 133 | pub const SYS_socketpair = 135; | ||
| 134 | pub const SYS_mkdir = 136; | ||
| 135 | pub const SYS_rmdir = 137; | ||
| 136 | pub const SYS_utimes = 138; | ||
| 137 | // 139 is obsolete 4.2 sigreturn | ||
| 138 | pub const SYS_adjtime = 140; | ||
| 139 | // 141 is old getpeername | ||
| 140 | // 142 is old gethostid | ||
| 141 | // 143 is old sethostid | ||
| 142 | // 144 is old getrlimit | ||
| 143 | // 145 is old setrlimit | ||
| 144 | // 146 is old killpg | ||
| 145 | pub const SYS_setsid = 147; | ||
| 146 | pub const SYS_quotactl = 148; | ||
| 147 | // 149 is old quota | ||
| 148 | // 150 is old getsockname | ||
| 149 | pub const SYS_nlm_syscall = 154; | ||
| 150 | pub const SYS_nfssvc = 155; | ||
| 151 | // 156 is old getdirentries | ||
| 152 | // 157 is freebsd4 statfs | ||
| 153 | // 158 is freebsd4 fstatfs | ||
| 154 | pub const SYS_lgetfh = 160; | ||
| 155 | pub const SYS_getfh = 161; | ||
| 156 | // 162 is freebsd4 getdomainname | ||
| 157 | // 163 is freebsd4 setdomainname | ||
| 158 | // 164 is freebsd4 uname | ||
| 159 | pub const SYS_sysarch = 165; | ||
| 160 | pub const SYS_rtprio = 166; | ||
| 161 | pub const SYS_semsys = 169; | ||
| 162 | pub const SYS_msgsys = 170; | ||
| 163 | pub const SYS_shmsys = 171; | ||
| 164 | // 173 is freebsd6 pread | ||
| 165 | // 174 is freebsd6 pwrite | ||
| 166 | pub const SYS_setfib = 175; | ||
| 167 | pub const SYS_ntp_adjtime = 176; | ||
| 168 | pub const SYS_setgid = 181; | ||
| 169 | pub const SYS_setegid = 182; | ||
| 170 | pub const SYS_seteuid = 183; | ||
| 171 | // 184 is obsolete lfs_bmapv | ||
| 172 | // 185 is obsolete lfs_markv | ||
| 173 | // 186 is obsolete lfs_segclean | ||
| 174 | // 187 is obsolete lfs_segwait | ||
| 175 | pub const SYS_freebsd11_stat = 188; | ||
| 176 | pub const SYS_freebsd11_fstat = 189; | ||
| 177 | pub const SYS_freebsd11_lstat = 190; | ||
| 178 | pub const SYS_pathconf = 191; | ||
| 179 | pub const SYS_fpathconf = 192; | ||
| 180 | pub const SYS_getrlimit = 194; | ||
| 181 | pub const SYS_setrlimit = 195; | ||
| 182 | pub const SYS_freebsd11_getdirentries = 196; | ||
| 183 | // 197 is freebsd6 mmap | ||
| 184 | pub const SYS___syscall = 198; | ||
| 185 | // 199 is freebsd6 lseek | ||
| 186 | // 200 is freebsd6 truncate | ||
| 187 | // 201 is freebsd6 ftruncate | ||
| 188 | pub const SYS___sysctl = 202; | ||
| 189 | pub const SYS_mlock = 203; | ||
| 190 | pub const SYS_munlock = 204; | ||
| 191 | pub const SYS_undelete = 205; | ||
| 192 | pub const SYS_futimes = 206; | ||
| 193 | pub const SYS_getpgid = 207; | ||
| 194 | pub const SYS_poll = 209; | ||
| 195 | pub const SYS_freebsd7___semctl = 220; | ||
| 196 | pub const SYS_semget = 221; | ||
| 197 | pub const SYS_semop = 222; | ||
| 198 | pub const SYS_freebsd7_msgctl = 224; | ||
| 199 | pub const SYS_msgget = 225; | ||
| 200 | pub const SYS_msgsnd = 226; | ||
| 201 | pub const SYS_msgrcv = 227; | ||
| 202 | pub const SYS_shmat = 228; | ||
| 203 | pub const SYS_freebsd7_shmctl = 229; | ||
| 204 | pub const SYS_shmdt = 230; | ||
| 205 | pub const SYS_shmget = 231; | ||
| 206 | pub const SYS_clock_gettime = 232; | ||
| 207 | pub const SYS_clock_settime = 233; | ||
| 208 | pub const SYS_clock_getres = 234; | ||
| 209 | pub const SYS_ktimer_create = 235; | ||
| 210 | pub const SYS_ktimer_delete = 236; | ||
| 211 | pub const SYS_ktimer_settime = 237; | ||
| 212 | pub const SYS_ktimer_gettime = 238; | ||
| 213 | pub const SYS_ktimer_getoverrun = 239; | ||
| 214 | pub const SYS_nanosleep = 240; | ||
| 215 | pub const SYS_ffclock_getcounter = 241; | ||
| 216 | pub const SYS_ffclock_setestimate = 242; | ||
| 217 | pub const SYS_ffclock_getestimate = 243; | ||
| 218 | pub const SYS_clock_nanosleep = 244; | ||
| 219 | pub const SYS_clock_getcpuclockid2 = 247; | ||
| 220 | pub const SYS_ntp_gettime = 248; | ||
| 221 | pub const SYS_minherit = 250; | ||
| 222 | pub const SYS_rfork = 251; | ||
| 223 | // 252 is obsolete openbsd_poll | ||
| 224 | pub const SYS_issetugid = 253; | ||
| 225 | pub const SYS_lchown = 254; | ||
| 226 | pub const SYS_aio_read = 255; | ||
| 227 | pub const SYS_aio_write = 256; | ||
| 228 | pub const SYS_lio_listio = 257; | ||
| 229 | pub const SYS_freebsd11_getdents = 272; | ||
| 230 | pub const SYS_lchmod = 274; | ||
| 231 | // 275 is obsolete netbsd_lchown | ||
| 232 | pub const SYS_lutimes = 276; | ||
| 233 | // 277 is obsolete netbsd_msync | ||
| 234 | pub const SYS_freebsd11_nstat = 278; | ||
| 235 | pub const SYS_freebsd11_nfstat = 279; | ||
| 236 | pub const SYS_freebsd11_nlstat = 280; | ||
| 237 | pub const SYS_preadv = 289; | ||
| 238 | pub const SYS_pwritev = 290; | ||
| 239 | // 297 is freebsd4 fhstatfs | ||
| 240 | pub const SYS_fhopen = 298; | ||
| 241 | pub const SYS_freebsd11_fhstat = 299; | ||
| 242 | pub const SYS_modnext = 300; | ||
| 243 | pub const SYS_modstat = 301; | ||
| 244 | pub const SYS_modfnext = 302; | ||
| 245 | pub const SYS_modfind = 303; | ||
| 246 | pub const SYS_kldload = 304; | ||
| 247 | pub const SYS_kldunload = 305; | ||
| 248 | pub const SYS_kldfind = 306; | ||
| 249 | pub const SYS_kldnext = 307; | ||
| 250 | pub const SYS_kldstat = 308; | ||
| 251 | pub const SYS_kldfirstmod = 309; | ||
| 252 | pub const SYS_getsid = 310; | ||
| 253 | pub const SYS_setresuid = 311; | ||
| 254 | pub const SYS_setresgid = 312; | ||
| 255 | // 313 is obsolete signanosleep | ||
| 256 | pub const SYS_aio_return = 314; | ||
| 257 | pub const SYS_aio_suspend = 315; | ||
| 258 | pub const SYS_aio_cancel = 316; | ||
| 259 | pub const SYS_aio_error = 317; | ||
| 260 | // 318 is freebsd6 aio_read | ||
| 261 | // 319 is freebsd6 aio_write | ||
| 262 | // 320 is freebsd6 lio_listio | ||
| 263 | pub const SYS_yield = 321; | ||
| 264 | // 322 is obsolete thr_sleep | ||
| 265 | // 323 is obsolete thr_wakeup | ||
| 266 | pub const SYS_mlockall = 324; | ||
| 267 | pub const SYS_munlockall = 325; | ||
| 268 | pub const SYS___getcwd = 326; | ||
| 269 | pub const SYS_sched_setparam = 327; | ||
| 270 | pub const SYS_sched_getparam = 328; | ||
| 271 | pub const SYS_sched_setscheduler = 329; | ||
| 272 | pub const SYS_sched_getscheduler = 330; | ||
| 273 | pub const SYS_sched_yield = 331; | ||
| 274 | pub const SYS_sched_get_priority_max = 332; | ||
| 275 | pub const SYS_sched_get_priority_min = 333; | ||
| 276 | pub const SYS_sched_rr_get_interval = 334; | ||
| 277 | pub const SYS_utrace = 335; | ||
| 278 | // 336 is freebsd4 sendfile | ||
| 279 | pub const SYS_kldsym = 337; | ||
| 280 | pub const SYS_jail = 338; | ||
| 281 | pub const SYS_nnpfs_syscall = 339; | ||
| 282 | pub const SYS_sigprocmask = 340; | ||
| 283 | pub const SYS_sigsuspend = 341; | ||
| 284 | // 342 is freebsd4 sigaction | ||
| 285 | pub const SYS_sigpending = 343; | ||
| 286 | // 344 is freebsd4 sigreturn | ||
| 287 | pub const SYS_sigtimedwait = 345; | ||
| 288 | pub const SYS_sigwaitinfo = 346; | ||
| 289 | pub const SYS___acl_get_file = 347; | ||
| 290 | pub const SYS___acl_set_file = 348; | ||
| 291 | pub const SYS___acl_get_fd = 349; | ||
| 292 | pub const SYS___acl_set_fd = 350; | ||
| 293 | pub const SYS___acl_delete_file = 351; | ||
| 294 | pub const SYS___acl_delete_fd = 352; | ||
| 295 | pub const SYS___acl_aclcheck_file = 353; | ||
| 296 | pub const SYS___acl_aclcheck_fd = 354; | ||
| 297 | pub const SYS_extattrctl = 355; | ||
| 298 | pub const SYS_extattr_set_file = 356; | ||
| 299 | pub const SYS_extattr_get_file = 357; | ||
| 300 | pub const SYS_extattr_delete_file = 358; | ||
| 301 | pub const SYS_aio_waitcomplete = 359; | ||
| 302 | pub const SYS_getresuid = 360; | ||
| 303 | pub const SYS_getresgid = 361; | ||
| 304 | pub const SYS_kqueue = 362; | ||
| 305 | pub const SYS_freebsd11_kevent = 363; | ||
| 306 | // 364 is obsolete __cap_get_proc | ||
| 307 | // 365 is obsolete __cap_set_proc | ||
| 308 | // 366 is obsolete __cap_get_fd | ||
| 309 | // 367 is obsolete __cap_get_file | ||
| 310 | // 368 is obsolete __cap_set_fd | ||
| 311 | // 369 is obsolete __cap_set_file | ||
| 312 | pub const SYS_extattr_set_fd = 371; | ||
| 313 | pub const SYS_extattr_get_fd = 372; | ||
| 314 | pub const SYS_extattr_delete_fd = 373; | ||
| 315 | pub const SYS___setugid = 374; | ||
| 316 | pub const SYS_eaccess = 376; | ||
| 317 | pub const SYS_afs3_syscall = 377; | ||
| 318 | pub const SYS_nmount = 378; | ||
| 319 | // 379 is obsolete kse_exit | ||
| 320 | // 380 is obsolete kse_wakeup | ||
| 321 | // 381 is obsolete kse_create | ||
| 322 | // 382 is obsolete kse_thr_interrupt | ||
| 323 | // 383 is obsolete kse_release | ||
| 324 | pub const SYS___mac_get_proc = 384; | ||
| 325 | pub const SYS___mac_set_proc = 385; | ||
| 326 | pub const SYS___mac_get_fd = 386; | ||
| 327 | pub const SYS___mac_get_file = 387; | ||
| 328 | pub const SYS___mac_set_fd = 388; | ||
| 329 | pub const SYS___mac_set_file = 389; | ||
| 330 | pub const SYS_kenv = 390; | ||
| 331 | pub const SYS_lchflags = 391; | ||
| 332 | pub const SYS_uuidgen = 392; | ||
| 333 | pub const SYS_sendfile = 393; | ||
| 334 | pub const SYS_mac_syscall = 394; | ||
| 335 | pub const SYS_freebsd11_getfsstat = 395; | ||
| 336 | pub const SYS_freebsd11_statfs = 396; | ||
| 337 | pub const SYS_freebsd11_fstatfs = 397; | ||
| 338 | pub const SYS_freebsd11_fhstatfs = 398; | ||
| 339 | pub const SYS_ksem_close = 400; | ||
| 340 | pub const SYS_ksem_post = 401; | ||
| 341 | pub const SYS_ksem_wait = 402; | ||
| 342 | pub const SYS_ksem_trywait = 403; | ||
| 343 | pub const SYS_ksem_init = 404; | ||
| 344 | pub const SYS_ksem_open = 405; | ||
| 345 | pub const SYS_ksem_unlink = 406; | ||
| 346 | pub const SYS_ksem_getvalue = 407; | ||
| 347 | pub const SYS_ksem_destroy = 408; | ||
| 348 | pub const SYS___mac_get_pid = 409; | ||
| 349 | pub const SYS___mac_get_link = 410; | ||
| 350 | pub const SYS___mac_set_link = 411; | ||
| 351 | pub const SYS_extattr_set_link = 412; | ||
| 352 | pub const SYS_extattr_get_link = 413; | ||
| 353 | pub const SYS_extattr_delete_link = 414; | ||
| 354 | pub const SYS___mac_execve = 415; | ||
| 355 | pub const SYS_sigaction = 416; | ||
| 356 | pub const SYS_sigreturn = 417; | ||
| 357 | pub const SYS_getcontext = 421; | ||
| 358 | pub const SYS_setcontext = 422; | ||
| 359 | pub const SYS_swapcontext = 423; | ||
| 360 | pub const SYS_swapoff = 424; | ||
| 361 | pub const SYS___acl_get_link = 425; | ||
| 362 | pub const SYS___acl_set_link = 426; | ||
| 363 | pub const SYS___acl_delete_link = 427; | ||
| 364 | pub const SYS___acl_aclcheck_link = 428; | ||
| 365 | pub const SYS_sigwait = 429; | ||
| 366 | pub const SYS_thr_create = 430; | ||
| 367 | pub const SYS_thr_exit = 431; | ||
| 368 | pub const SYS_thr_self = 432; | ||
| 369 | pub const SYS_thr_kill = 433; | ||
| 370 | pub const SYS_jail_attach = 436; | ||
| 371 | pub const SYS_extattr_list_fd = 437; | ||
| 372 | pub const SYS_extattr_list_file = 438; | ||
| 373 | pub const SYS_extattr_list_link = 439; | ||
| 374 | // 440 is obsolete kse_switchin | ||
| 375 | pub const SYS_ksem_timedwait = 441; | ||
| 376 | pub const SYS_thr_suspend = 442; | ||
| 377 | pub const SYS_thr_wake = 443; | ||
| 378 | pub const SYS_kldunloadf = 444; | ||
| 379 | pub const SYS_audit = 445; | ||
| 380 | pub const SYS_auditon = 446; | ||
| 381 | pub const SYS_getauid = 447; | ||
| 382 | pub const SYS_setauid = 448; | ||
| 383 | pub const SYS_getaudit = 449; | ||
| 384 | pub const SYS_setaudit = 450; | ||
| 385 | pub const SYS_getaudit_addr = 451; | ||
| 386 | pub const SYS_setaudit_addr = 452; | ||
| 387 | pub const SYS_auditctl = 453; | ||
| 388 | pub const SYS__umtx_op = 454; | ||
| 389 | pub const SYS_thr_new = 455; | ||
| 390 | pub const SYS_sigqueue = 456; | ||
| 391 | pub const SYS_kmq_open = 457; | ||
| 392 | pub const SYS_kmq_setattr = 458; | ||
| 393 | pub const SYS_kmq_timedreceive = 459; | ||
| 394 | pub const SYS_kmq_timedsend = 460; | ||
| 395 | pub const SYS_kmq_notify = 461; | ||
| 396 | pub const SYS_kmq_unlink = 462; | ||
| 397 | pub const SYS_abort2 = 463; | ||
| 398 | pub const SYS_thr_set_name = 464; | ||
| 399 | pub const SYS_aio_fsync = 465; | ||
| 400 | pub const SYS_rtprio_thread = 466; | ||
| 401 | pub const SYS_sctp_peeloff = 471; | ||
| 402 | pub const SYS_sctp_generic_sendmsg = 472; | ||
| 403 | pub const SYS_sctp_generic_sendmsg_iov = 473; | ||
| 404 | pub const SYS_sctp_generic_recvmsg = 474; | ||
| 405 | pub const SYS_pread = 475; | ||
| 406 | pub const SYS_pwrite = 476; | ||
| 407 | pub const SYS_mmap = 477; | ||
| 408 | pub const SYS_lseek = 478; | ||
| 409 | pub const SYS_truncate = 479; | ||
| 410 | pub const SYS_ftruncate = 480; | ||
| 411 | pub const SYS_thr_kill2 = 481; | ||
| 412 | pub const SYS_shm_open = 482; | ||
| 413 | pub const SYS_shm_unlink = 483; | ||
| 414 | pub const SYS_cpuset = 484; | ||
| 415 | pub const SYS_cpuset_setid = 485; | ||
| 416 | pub const SYS_cpuset_getid = 486; | ||
| 417 | pub const SYS_cpuset_getaffinity = 487; | ||
| 418 | pub const SYS_cpuset_setaffinity = 488; | ||
| 419 | pub const SYS_faccessat = 489; | ||
| 420 | pub const SYS_fchmodat = 490; | ||
| 421 | pub const SYS_fchownat = 491; | ||
| 422 | pub const SYS_fexecve = 492; | ||
| 423 | pub const SYS_freebsd11_fstatat = 493; | ||
| 424 | pub const SYS_futimesat = 494; | ||
| 425 | pub const SYS_linkat = 495; | ||
| 426 | pub const SYS_mkdirat = 496; | ||
| 427 | pub const SYS_mkfifoat = 497; | ||
| 428 | pub const SYS_freebsd11_mknodat = 498; | ||
| 429 | pub const SYS_openat = 499; | ||
| 430 | pub const SYS_readlinkat = 500; | ||
| 431 | pub const SYS_renameat = 501; | ||
| 432 | pub const SYS_symlinkat = 502; | ||
| 433 | pub const SYS_unlinkat = 503; | ||
| 434 | pub const SYS_posix_openpt = 504; | ||
| 435 | pub const SYS_gssd_syscall = 505; | ||
| 436 | pub const SYS_jail_get = 506; | ||
| 437 | pub const SYS_jail_set = 507; | ||
| 438 | pub const SYS_jail_remove = 508; | ||
| 439 | pub const SYS_closefrom = 509; | ||
| 440 | pub const SYS___semctl = 510; | ||
| 441 | pub const SYS_msgctl = 511; | ||
| 442 | pub const SYS_shmctl = 512; | ||
| 443 | pub const SYS_lpathconf = 513; | ||
| 444 | // 514 is obsolete cap_new | ||
| 445 | pub const SYS___cap_rights_get = 515; | ||
| 446 | pub const SYS_cap_enter = 516; | ||
| 447 | pub const SYS_cap_getmode = 517; | ||
| 448 | pub const SYS_pdfork = 518; | ||
| 449 | pub const SYS_pdkill = 519; | ||
| 450 | pub const SYS_pdgetpid = 520; | ||
| 451 | pub const SYS_pselect = 522; | ||
| 452 | pub const SYS_getloginclass = 523; | ||
| 453 | pub const SYS_setloginclass = 524; | ||
| 454 | pub const SYS_rctl_get_racct = 525; | ||
| 455 | pub const SYS_rctl_get_rules = 526; | ||
| 456 | pub const SYS_rctl_get_limits = 527; | ||
| 457 | pub const SYS_rctl_add_rule = 528; | ||
| 458 | pub const SYS_rctl_remove_rule = 529; | ||
| 459 | pub const SYS_posix_fallocate = 530; | ||
| 460 | pub const SYS_posix_fadvise = 531; | ||
| 461 | pub const SYS_wait6 = 532; | ||
| 462 | pub const SYS_cap_rights_limit = 533; | ||
| 463 | pub const SYS_cap_ioctls_limit = 534; | ||
| 464 | pub const SYS_cap_ioctls_get = 535; | ||
| 465 | pub const SYS_cap_fcntls_limit = 536; | ||
| 466 | pub const SYS_cap_fcntls_get = 537; | ||
| 467 | pub const SYS_bindat = 538; | ||
| 468 | pub const SYS_connectat = 539; | ||
| 469 | pub const SYS_chflagsat = 540; | ||
| 470 | pub const SYS_accept4 = 541; | ||
| 471 | pub const SYS_pipe2 = 542; | ||
| 472 | pub const SYS_aio_mlock = 543; | ||
| 473 | pub const SYS_procctl = 544; | ||
| 474 | pub const SYS_ppoll = 545; | ||
| 475 | pub const SYS_futimens = 546; | ||
| 476 | pub const SYS_utimensat = 547; | ||
| 477 | // 548 is obsolete numa_getaffinity | ||
| 478 | // 549 is obsolete numa_setaffinity | ||
| 479 | pub const SYS_fdatasync = 550; | ||
| 480 | pub const SYS_fstat = 551; | ||
| 481 | pub const SYS_fstatat = 552; | ||
| 482 | pub const SYS_fhstat = 553; | ||
| 483 | pub const SYS_getdirentries = 554; | ||
| 484 | pub const SYS_statfs = 555; | ||
| 485 | pub const SYS_fstatfs = 556; | ||
| 486 | pub const SYS_getfsstat = 557; | ||
| 487 | pub const SYS_fhstatfs = 558; | ||
| 488 | pub const SYS_mknodat = 559; | ||
| 489 | pub const SYS_kevent = 560; | ||
| 490 | pub const SYS_cpuset_getdomain = 561; | ||
| 491 | pub const SYS_cpuset_setdomain = 562; | ||
| 492 | pub const SYS_getrandom = 563; | ||
| 493 | pub const SYS_MAXSYSCALL = 564; | ||
std/os/freebsd/x86_64.zig deleted-136| ... | @@ -1,136 +0,0 @@ | ||
| 1 | const freebsd = @import("index.zig"); | ||
| 2 | const socklen_t = freebsd.socklen_t; | ||
| 3 | const iovec = freebsd.iovec; | ||
| 4 | |||
| 5 | pub const SYS_sbrk = 69; | ||
| 6 | |||
| 7 | pub fn syscall0(number: usize) usize { | ||
| 8 | return asm volatile ("syscall" | ||
| 9 | : [ret] "={rax}" (-> usize) | ||
| 10 | : [number] "{rax}" (number) | ||
| 11 | : "rcx", "r11" | ||
| 12 | ); | ||
| 13 | } | ||
| 14 | |||
| 15 | pub fn syscall1(number: usize, arg1: usize) usize { | ||
| 16 | return asm volatile ("syscall" | ||
| 17 | : [ret] "={rax}" (-> usize) | ||
| 18 | : [number] "{rax}" (number), | ||
| 19 | [arg1] "{rdi}" (arg1) | ||
| 20 | : "rcx", "r11" | ||
| 21 | ); | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize { | ||
| 25 | return asm volatile ("syscall" | ||
| 26 | : [ret] "={rax}" (-> usize) | ||
| 27 | : [number] "{rax}" (number), | ||
| 28 | [arg1] "{rdi}" (arg1), | ||
| 29 | [arg2] "{rsi}" (arg2) | ||
| 30 | : "rcx", "r11" | ||
| 31 | ); | ||
| 32 | } | ||
| 33 | |||
| 34 | pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { | ||
| 35 | return asm volatile ("syscall" | ||
| 36 | : [ret] "={rax}" (-> usize) | ||
| 37 | : [number] "{rax}" (number), | ||
| 38 | [arg1] "{rdi}" (arg1), | ||
| 39 | [arg2] "{rsi}" (arg2), | ||
| 40 | [arg3] "{rdx}" (arg3) | ||
| 41 | : "rcx", "r11" | ||
| 42 | ); | ||
| 43 | } | ||
| 44 | |||
| 45 | pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { | ||
| 46 | return asm volatile ("syscall" | ||
| 47 | : [ret] "={rax}" (-> usize) | ||
| 48 | : [number] "{rax}" (number), | ||
| 49 | [arg1] "{rdi}" (arg1), | ||
| 50 | [arg2] "{rsi}" (arg2), | ||
| 51 | [arg3] "{rdx}" (arg3), | ||
| 52 | [arg4] "{r10}" (arg4) | ||
| 53 | : "rcx", "r11" | ||
| 54 | ); | ||
| 55 | } | ||
| 56 | |||
| 57 | pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { | ||
| 58 | return asm volatile ("syscall" | ||
| 59 | : [ret] "={rax}" (-> usize) | ||
| 60 | : [number] "{rax}" (number), | ||
| 61 | [arg1] "{rdi}" (arg1), | ||
| 62 | [arg2] "{rsi}" (arg2), | ||
| 63 | [arg3] "{rdx}" (arg3), | ||
| 64 | [arg4] "{r10}" (arg4), | ||
| 65 | [arg5] "{r8}" (arg5) | ||
| 66 | : "rcx", "r11" | ||
| 67 | ); | ||
| 68 | } | ||
| 69 | |||
| 70 | pub fn syscall6( | ||
| 71 | number: usize, | ||
| 72 | arg1: usize, | ||
| 73 | arg2: usize, | ||
| 74 | arg3: usize, | ||
| 75 | arg4: usize, | ||
| 76 | arg5: usize, | ||
| 77 | arg6: usize, | ||
| 78 | ) usize { | ||
| 79 | return asm volatile ("syscall" | ||
| 80 | : [ret] "={rax}" (-> usize) | ||
| 81 | : [number] "{rax}" (number), | ||
| 82 | [arg1] "{rdi}" (arg1), | ||
| 83 | [arg2] "{rsi}" (arg2), | ||
| 84 | [arg3] "{rdx}" (arg3), | ||
| 85 | [arg4] "{r10}" (arg4), | ||
| 86 | [arg5] "{r8}" (arg5), | ||
| 87 | [arg6] "{r9}" (arg6) | ||
| 88 | : "rcx", "r11" | ||
| 89 | ); | ||
| 90 | } | ||
| 91 | |||
| 92 | pub nakedcc fn restore_rt() void { | ||
| 93 | asm volatile ("syscall" | ||
| 94 | : | ||
| 95 | : [number] "{rax}" (usize(SYS_rt_sigreturn)) | ||
| 96 | : "rcx", "r11" | ||
| 97 | ); | ||
| 98 | } | ||
| 99 | |||
| 100 | pub const msghdr = extern struct { | ||
| 101 | msg_name: &u8, | ||
| 102 | msg_namelen: socklen_t, | ||
| 103 | msg_iov: &iovec, | ||
| 104 | msg_iovlen: i32, | ||
| 105 | __pad1: i32, | ||
| 106 | msg_control: &u8, | ||
| 107 | msg_controllen: socklen_t, | ||
| 108 | __pad2: socklen_t, | ||
| 109 | msg_flags: i32, | ||
| 110 | }; | ||
| 111 | |||
| 112 | /// Renamed to Stat to not conflict with the stat function. | ||
| 113 | pub const Stat = extern struct { | ||
| 114 | dev: u64, | ||
| 115 | ino: u64, | ||
| 116 | nlink: usize, | ||
| 117 | |||
| 118 | mode: u32, | ||
| 119 | uid: u32, | ||
| 120 | gid: u32, | ||
| 121 | __pad0: u32, | ||
| 122 | rdev: u64, | ||
| 123 | size: i64, | ||
| 124 | blksize: isize, | ||
| 125 | blocks: i64, | ||
| 126 | |||
| 127 | atim: timespec, | ||
| 128 | mtim: timespec, | ||
| 129 | ctim: timespec, | ||
| 130 | __unused: [3]isize, | ||
| 131 | }; | ||
| 132 | |||
| 133 | pub const timespec = extern struct { | ||
| 134 | tv_sec: isize, | ||
| 135 | tv_nsec: isize, | ||
| 136 | }; | ||
std/os/get_app_data_dir.zig+3-4| ... | @@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD | ... | @@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD |
| 30 | error.OutOfMemory => return error.OutOfMemory, | 30 | error.OutOfMemory => return error.OutOfMemory, |
| 31 | }; | 31 | }; |
| 32 | defer allocator.free(global_dir); | 32 | defer allocator.free(global_dir); |
| 33 | return os.path.join(allocator, global_dir, appname); | 33 | return os.path.join(allocator, [][]const u8{ global_dir, appname }); |
| 34 | }, | 34 | }, |
| 35 | os.windows.E_OUTOFMEMORY => return error.OutOfMemory, | 35 | os.windows.E_OUTOFMEMORY => return error.OutOfMemory, |
| 36 | else => return error.AppDataDirUnavailable, | 36 | else => return error.AppDataDirUnavailable, |
| ... | @@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD | ... | @@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD |
| 41 | // TODO look in /etc/passwd | 41 | // TODO look in /etc/passwd |
| 42 | return error.AppDataDirUnavailable; | 42 | return error.AppDataDirUnavailable; |
| 43 | }; | 43 | }; |
| 44 | return os.path.join(allocator, home_dir, "Library", "Application Support", appname); | 44 | return os.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname }); |
| 45 | }, | 45 | }, |
| 46 | builtin.Os.linux, builtin.Os.freebsd => { | 46 | builtin.Os.linux, builtin.Os.freebsd => { |
| 47 | const home_dir = os.getEnvPosix("HOME") orelse { | 47 | const home_dir = os.getEnvPosix("HOME") orelse { |
| 48 | // TODO look in /etc/passwd | 48 | // TODO look in /etc/passwd |
| 49 | return error.AppDataDirUnavailable; | 49 | return error.AppDataDirUnavailable; |
| 50 | }; | 50 | }; |
| 51 | return os.path.join(allocator, home_dir, ".local", "share", appname); | 51 | return os.path.join(allocator, [][]const u8{ home_dir, ".local", "share", appname }); |
| 52 | }, | 52 | }, |
| 53 | else => @compileError("Unsupported OS"), | 53 | else => @compileError("Unsupported OS"), |
| 54 | } | 54 | } |
| ... | @@ -67,4 +67,3 @@ test "std.os.getAppDataDir" { | ... | @@ -67,4 +67,3 @@ test "std.os.getAppDataDir" { |
| 67 | // We can't actually validate the result | 67 | // We can't actually validate the result |
| 68 | _ = getAppDataDir(allocator, "zig") catch return; | 68 | _ = getAppDataDir(allocator, "zig") catch return; |
| 69 | } | 69 | } |
| 70 |
std/os/index.zig+187-64| ... | @@ -8,6 +8,10 @@ const is_posix = switch (builtin.os) { | ... | @@ -8,6 +8,10 @@ const is_posix = switch (builtin.os) { |
| 8 | }; | 8 | }; |
| 9 | const os = @This(); | 9 | const os = @This(); |
| 10 | 10 | ||
| 11 | comptime { | ||
| 12 | assert(@import("std") == std); // You have to run the std lib tests with --override-std-dir | ||
| 13 | } | ||
| 14 | |||
| 11 | test "std.os" { | 15 | test "std.os" { |
| 12 | _ = @import("child_process.zig"); | 16 | _ = @import("child_process.zig"); |
| 13 | _ = @import("darwin.zig"); | 17 | _ = @import("darwin.zig"); |
| ... | @@ -18,6 +22,7 @@ test "std.os" { | ... | @@ -18,6 +22,7 @@ test "std.os" { |
| 18 | _ = @import("test.zig"); | 22 | _ = @import("test.zig"); |
| 19 | _ = @import("time.zig"); | 23 | _ = @import("time.zig"); |
| 20 | _ = @import("windows/index.zig"); | 24 | _ = @import("windows/index.zig"); |
| 25 | _ = @import("uefi.zig"); | ||
| 21 | _ = @import("get_app_data_dir.zig"); | 26 | _ = @import("get_app_data_dir.zig"); |
| 22 | } | 27 | } |
| 23 | 28 | ||
| ... | @@ -26,6 +31,8 @@ pub const darwin = @import("darwin.zig"); | ... | @@ -26,6 +31,8 @@ pub const darwin = @import("darwin.zig"); |
| 26 | pub const linux = @import("linux/index.zig"); | 31 | pub const linux = @import("linux/index.zig"); |
| 27 | pub const freebsd = @import("freebsd/index.zig"); | 32 | pub const freebsd = @import("freebsd/index.zig"); |
| 28 | pub const zen = @import("zen.zig"); | 33 | pub const zen = @import("zen.zig"); |
| 34 | pub const uefi = @import("uefi.zig"); | ||
| 35 | |||
| 29 | pub const posix = switch (builtin.os) { | 36 | pub const posix = switch (builtin.os) { |
| 30 | Os.linux => linux, | 37 | Os.linux => linux, |
| 31 | Os.macosx, Os.ios => darwin, | 38 | Os.macosx, Os.ios => darwin, |
| ... | @@ -33,6 +40,7 @@ pub const posix = switch (builtin.os) { | ... | @@ -33,6 +40,7 @@ pub const posix = switch (builtin.os) { |
| 33 | Os.zen => zen, | 40 | Os.zen => zen, |
| 34 | else => @compileError("Unsupported OS"), | 41 | else => @compileError("Unsupported OS"), |
| 35 | }; | 42 | }; |
| 43 | |||
| 36 | pub const net = @import("net.zig"); | 44 | pub const net = @import("net.zig"); |
| 37 | 45 | ||
| 38 | pub const ChildProcess = @import("child_process.zig").ChildProcess; | 46 | pub const ChildProcess = @import("child_process.zig").ChildProcess; |
| ... | @@ -83,6 +91,7 @@ pub const GetAppDataDirError = @import("get_app_data_dir.zig").GetAppDataDirErro | ... | @@ -83,6 +91,7 @@ pub const GetAppDataDirError = @import("get_app_data_dir.zig").GetAppDataDirErro |
| 83 | 91 | ||
| 84 | const debug = std.debug; | 92 | const debug = std.debug; |
| 85 | const assert = debug.assert; | 93 | const assert = debug.assert; |
| 94 | const testing = std.testing; | ||
| 86 | 95 | ||
| 87 | const c = std.c; | 96 | const c = std.c; |
| 88 | 97 | ||
| ... | @@ -103,7 +112,7 @@ const math = std.math; | ... | @@ -103,7 +112,7 @@ const math = std.math; |
| 103 | /// library implementation. | 112 | /// library implementation. |
| 104 | pub fn getRandomBytes(buf: []u8) !void { | 113 | pub fn getRandomBytes(buf: []u8) !void { |
| 105 | switch (builtin.os) { | 114 | switch (builtin.os) { |
| 106 | Os.linux, Os.freebsd => while (true) { | 115 | Os.linux => while (true) { |
| 107 | // TODO check libc version and potentially call c.getrandom. | 116 | // TODO check libc version and potentially call c.getrandom. |
| 108 | // See #397 | 117 | // See #397 |
| 109 | const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0)); | 118 | const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0)); |
| ... | @@ -116,7 +125,7 @@ pub fn getRandomBytes(buf: []u8) !void { | ... | @@ -116,7 +125,7 @@ pub fn getRandomBytes(buf: []u8) !void { |
| 116 | else => return unexpectedErrorPosix(errno), | 125 | else => return unexpectedErrorPosix(errno), |
| 117 | } | 126 | } |
| 118 | }, | 127 | }, |
| 119 | Os.macosx, Os.ios => return getRandomBytesDevURandom(buf), | 128 | Os.macosx, Os.ios, Os.freebsd => return getRandomBytesDevURandom(buf), |
| 120 | Os.windows => { | 129 | Os.windows => { |
| 121 | // Call RtlGenRandom() instead of CryptGetRandom() on Windows | 130 | // Call RtlGenRandom() instead of CryptGetRandom() on Windows |
| 122 | // https://github.com/rust-lang-nursery/rand/issues/111 | 131 | // https://github.com/rust-lang-nursery/rand/issues/111 |
| ... | @@ -164,7 +173,7 @@ test "os.getRandomBytes" { | ... | @@ -164,7 +173,7 @@ test "os.getRandomBytes" { |
| 164 | try getRandomBytes(buf_b[0..]); | 173 | try getRandomBytes(buf_b[0..]); |
| 165 | 174 | ||
| 166 | // Check if random (not 100% conclusive) | 175 | // Check if random (not 100% conclusive) |
| 167 | assert(!mem.eql(u8, buf_a, buf_b)); | 176 | testing.expect(!mem.eql(u8, buf_a, buf_b)); |
| 168 | } | 177 | } |
| 169 | 178 | ||
| 170 | /// Raises a signal in the current kernel thread, ending its execution. | 179 | /// Raises a signal in the current kernel thread, ending its execution. |
| ... | @@ -187,6 +196,10 @@ pub fn abort() noreturn { | ... | @@ -187,6 +196,10 @@ pub fn abort() noreturn { |
| 187 | } | 196 | } |
| 188 | windows.ExitProcess(3); | 197 | windows.ExitProcess(3); |
| 189 | }, | 198 | }, |
| 199 | Os.uefi => { | ||
| 200 | // TODO there's gotta be a better thing to do here than loop forever | ||
| 201 | while (true) {} | ||
| 202 | }, | ||
| 190 | else => @compileError("Unsupported OS"), | 203 | else => @compileError("Unsupported OS"), |
| 191 | } | 204 | } |
| 192 | } | 205 | } |
| ... | @@ -459,6 +472,7 @@ pub const PosixOpenError = error{ | ... | @@ -459,6 +472,7 @@ pub const PosixOpenError = error{ |
| 459 | NoSpaceLeft, | 472 | NoSpaceLeft, |
| 460 | NotDir, | 473 | NotDir, |
| 461 | PathAlreadyExists, | 474 | PathAlreadyExists, |
| 475 | DeviceBusy, | ||
| 462 | 476 | ||
| 463 | /// See https://github.com/ziglang/zig/issues/1396 | 477 | /// See https://github.com/ziglang/zig/issues/1396 |
| 464 | Unexpected, | 478 | Unexpected, |
| ... | @@ -497,6 +511,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { | ... | @@ -497,6 +511,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { |
| 497 | posix.ENOTDIR => return PosixOpenError.NotDir, | 511 | posix.ENOTDIR => return PosixOpenError.NotDir, |
| 498 | posix.EPERM => return PosixOpenError.AccessDenied, | 512 | posix.EPERM => return PosixOpenError.AccessDenied, |
| 499 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, | 513 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, |
| 514 | posix.EBUSY => return PosixOpenError.DeviceBusy, | ||
| 500 | else => return unexpectedErrorPosix(err), | 515 | else => return unexpectedErrorPosix(err), |
| 501 | } | 516 | } |
| 502 | } | 517 | } |
| ... | @@ -598,7 +613,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator: | ... | @@ -598,7 +613,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator: |
| 598 | // +1 for the null terminating byte | 613 | // +1 for the null terminating byte |
| 599 | const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2); | 614 | const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2); |
| 600 | defer allocator.free(path_buf); | 615 | defer allocator.free(path_buf); |
| 601 | var it = mem.split(PATH, ":"); | 616 | var it = mem.tokenize(PATH, ":"); |
| 602 | var seen_eacces = false; | 617 | var seen_eacces = false; |
| 603 | var err: usize = undefined; | 618 | var err: usize = undefined; |
| 604 | while (it.next()) |search_path| { | 619 | while (it.next()) |search_path| { |
| ... | @@ -682,12 +697,7 @@ pub fn getBaseAddress() usize { | ... | @@ -682,12 +697,7 @@ pub fn getBaseAddress() usize { |
| 682 | return base; | 697 | return base; |
| 683 | } | 698 | } |
| 684 | const phdr = linuxGetAuxVal(std.elf.AT_PHDR); | 699 | const phdr = linuxGetAuxVal(std.elf.AT_PHDR); |
| 685 | const ElfHeader = switch (@sizeOf(usize)) { | 700 | return phdr - @sizeOf(std.elf.Ehdr); |
| 686 | 4 => std.elf.Elf32_Ehdr, | ||
| 687 | 8 => std.elf.Elf64_Ehdr, | ||
| 688 | else => @compileError("Unsupported architecture"), | ||
| 689 | }; | ||
| 690 | return phdr - @sizeOf(ElfHeader); | ||
| 691 | }, | 701 | }, |
| 692 | builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header), | 702 | builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header), |
| 693 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), | 703 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), |
| ... | @@ -702,8 +712,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -702,8 +712,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 702 | errdefer result.deinit(); | 712 | errdefer result.deinit(); |
| 703 | 713 | ||
| 704 | if (is_windows) { | 714 | if (is_windows) { |
| 705 | const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory; | 715 | const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory; |
| 706 | defer assert(windows.FreeEnvironmentStringsA(ptr) != 0); | 716 | defer assert(windows.FreeEnvironmentStringsW(ptr) != 0); |
| 707 | 717 | ||
| 708 | var i: usize = 0; | 718 | var i: usize = 0; |
| 709 | while (true) { | 719 | while (true) { |
| ... | @@ -712,17 +722,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -712,17 +722,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 712 | const key_start = i; | 722 | const key_start = i; |
| 713 | 723 | ||
| 714 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} | 724 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| 715 | const key = ptr[key_start..i]; | 725 | const key_w = ptr[key_start..i]; |
| 726 | const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w); | ||
| 727 | errdefer allocator.free(key); | ||
| 716 | 728 | ||
| 717 | if (ptr[i] == '=') i += 1; | 729 | if (ptr[i] == '=') i += 1; |
| 718 | 730 | ||
| 719 | const value_start = i; | 731 | const value_start = i; |
| 720 | while (ptr[i] != 0) : (i += 1) {} | 732 | while (ptr[i] != 0) : (i += 1) {} |
| 721 | const value = ptr[value_start..i]; | 733 | const value_w = ptr[value_start..i]; |
| 734 | const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w); | ||
| 735 | errdefer allocator.free(value); | ||
| 722 | 736 | ||
| 723 | i += 1; // skip over null byte | 737 | i += 1; // skip over null byte |
| 724 | 738 | ||
| 725 | try result.set(key, value); | 739 | try result.setMove(key, value); |
| 726 | } | 740 | } |
| 727 | } else { | 741 | } else { |
| 728 | for (posix_environ_raw) |ptr| { | 742 | for (posix_environ_raw) |ptr| { |
| ... | @@ -740,6 +754,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -740,6 +754,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 740 | } | 754 | } |
| 741 | } | 755 | } |
| 742 | 756 | ||
| 757 | test "os.getEnvMap" { | ||
| 758 | var env = try getEnvMap(std.debug.global_allocator); | ||
| 759 | defer env.deinit(); | ||
| 760 | } | ||
| 761 | |||
| 743 | /// TODO make this go through libc when we have it | 762 | /// TODO make this go through libc when we have it |
| 744 | pub fn getEnvPosix(key: []const u8) ?[]const u8 { | 763 | pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 745 | for (posix_environ_raw) |ptr| { | 764 | for (posix_environ_raw) |ptr| { |
| ... | @@ -760,21 +779,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { | ... | @@ -760,21 +779,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 760 | pub const GetEnvVarOwnedError = error{ | 779 | pub const GetEnvVarOwnedError = error{ |
| 761 | OutOfMemory, | 780 | OutOfMemory, |
| 762 | EnvironmentVariableNotFound, | 781 | EnvironmentVariableNotFound, |
| 782 | |||
| 783 | /// See https://github.com/ziglang/zig/issues/1774 | ||
| 784 | InvalidUtf8, | ||
| 763 | }; | 785 | }; |
| 764 | 786 | ||
| 765 | /// Caller must free returned memory. | 787 | /// Caller must free returned memory. |
| 766 | /// TODO make this go through libc when we have it | 788 | /// TODO make this go through libc when we have it |
| 767 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { | 789 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 768 | if (is_windows) { | 790 | if (is_windows) { |
| 769 | const key_with_null = try cstr.addNullByte(allocator, key); | 791 | const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); |
| 770 | defer allocator.free(key_with_null); | 792 | defer allocator.free(key_with_null); |
| 771 | 793 | ||
| 772 | var buf = try allocator.alloc(u8, 256); | 794 | var buf = try allocator.alloc(u16, 256); |
| 773 | errdefer allocator.free(buf); | 795 | defer allocator.free(buf); |
| 774 | 796 | ||
| 775 | while (true) { | 797 | while (true) { |
| 776 | const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory; | 798 | const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory; |
| 777 | const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len); | 799 | const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len); |
| 778 | 800 | ||
| 779 | if (result == 0) { | 801 | if (result == 0) { |
| 780 | const err = windows.GetLastError(); | 802 | const err = windows.GetLastError(); |
| ... | @@ -788,11 +810,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned | ... | @@ -788,11 +810,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned |
| 788 | } | 810 | } |
| 789 | 811 | ||
| 790 | if (result > buf.len) { | 812 | if (result > buf.len) { |
| 791 | buf = try allocator.realloc(u8, buf, result); | 813 | buf = try allocator.realloc(u16, buf, result); |
| 792 | continue; | 814 | continue; |
| 793 | } | 815 | } |
| 794 | 816 | ||
| 795 | return allocator.shrink(u8, buf, result); | 817 | return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) { |
| 818 | error.DanglingSurrogateHalf => return error.InvalidUtf8, | ||
| 819 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, | ||
| 820 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, | ||
| 821 | error.OutOfMemory => return error.OutOfMemory, | ||
| 822 | }; | ||
| 796 | } | 823 | } |
| 797 | } else { | 824 | } else { |
| 798 | const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound; | 825 | const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound; |
| ... | @@ -800,6 +827,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned | ... | @@ -800,6 +827,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned |
| 800 | } | 827 | } |
| 801 | } | 828 | } |
| 802 | 829 | ||
| 830 | test "os.getEnvVarOwned" { | ||
| 831 | var ga = debug.global_allocator; | ||
| 832 | testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV")); | ||
| 833 | } | ||
| 834 | |||
| 803 | /// Caller must free the returned memory. | 835 | /// Caller must free the returned memory. |
| 804 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { | 836 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { |
| 805 | var buf: [MAX_PATH_BYTES]u8 = undefined; | 837 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| ... | @@ -1253,7 +1285,7 @@ pub fn makeDirPosix(dir_path: []const u8) !void { | ... | @@ -1253,7 +1285,7 @@ pub fn makeDirPosix(dir_path: []const u8) !void { |
| 1253 | /// already exists and is a directory. | 1285 | /// already exists and is a directory. |
| 1254 | /// TODO determine if we can remove the allocator requirement from this function | 1286 | /// TODO determine if we can remove the allocator requirement from this function |
| 1255 | pub fn makePath(allocator: *Allocator, full_path: []const u8) !void { | 1287 | pub fn makePath(allocator: *Allocator, full_path: []const u8) !void { |
| 1256 | const resolved_path = try path.resolve(allocator, full_path); | 1288 | const resolved_path = try path.resolve(allocator, [][]const u8{full_path}); |
| 1257 | defer allocator.free(resolved_path); | 1289 | defer allocator.free(resolved_path); |
| 1258 | 1290 | ||
| 1259 | var end_index: usize = resolved_path.len; | 1291 | var end_index: usize = resolved_path.len; |
| ... | @@ -1380,6 +1412,7 @@ const DeleteTreeError = error{ | ... | @@ -1380,6 +1412,7 @@ const DeleteTreeError = error{ |
| 1380 | FileSystem, | 1412 | FileSystem, |
| 1381 | FileBusy, | 1413 | FileBusy, |
| 1382 | DirNotEmpty, | 1414 | DirNotEmpty, |
| 1415 | DeviceBusy, | ||
| 1383 | 1416 | ||
| 1384 | /// On Windows, file paths must be valid Unicode. | 1417 | /// On Windows, file paths must be valid Unicode. |
| 1385 | InvalidUtf8, | 1418 | InvalidUtf8, |
| ... | @@ -1441,6 +1474,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -1441,6 +1474,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 1441 | error.Unexpected, | 1474 | error.Unexpected, |
| 1442 | error.InvalidUtf8, | 1475 | error.InvalidUtf8, |
| 1443 | error.BadPathName, | 1476 | error.BadPathName, |
| 1477 | error.DeviceBusy, | ||
| 1444 | => return err, | 1478 | => return err, |
| 1445 | }; | 1479 | }; |
| 1446 | defer dir.close(); | 1480 | defer dir.close(); |
| ... | @@ -1523,6 +1557,7 @@ pub const Dir = struct { | ... | @@ -1523,6 +1557,7 @@ pub const Dir = struct { |
| 1523 | OutOfMemory, | 1557 | OutOfMemory, |
| 1524 | InvalidUtf8, | 1558 | InvalidUtf8, |
| 1525 | BadPathName, | 1559 | BadPathName, |
| 1560 | DeviceBusy, | ||
| 1526 | 1561 | ||
| 1527 | /// See https://github.com/ziglang/zig/issues/1396 | 1562 | /// See https://github.com/ziglang/zig/issues/1396 |
| 1528 | Unexpected, | 1563 | Unexpected, |
| ... | @@ -1731,8 +1766,57 @@ pub const Dir = struct { | ... | @@ -1731,8 +1766,57 @@ pub const Dir = struct { |
| 1731 | } | 1766 | } |
| 1732 | 1767 | ||
| 1733 | fn nextFreebsd(self: *Dir) !?Entry { | 1768 | fn nextFreebsd(self: *Dir) !?Entry { |
| 1734 | //self.handle.buf = try self.allocator.alloc(u8, page_size); | 1769 | start_over: while (true) { |
| 1735 | @compileError("TODO implement dirs for FreeBSD"); | 1770 | if (self.handle.index >= self.handle.end_index) { |
| 1771 | if (self.handle.buf.len == 0) { | ||
| 1772 | self.handle.buf = try self.allocator.alloc(u8, page_size); | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | while (true) { | ||
| 1776 | const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek); | ||
| 1777 | const err = posix.getErrno(result); | ||
| 1778 | if (err > 0) { | ||
| 1779 | switch (err) { | ||
| 1780 | posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable, | ||
| 1781 | posix.EINVAL => { | ||
| 1782 | self.handle.buf = try self.allocator.realloc(u8, self.handle.buf, self.handle.buf.len * 2); | ||
| 1783 | continue; | ||
| 1784 | }, | ||
| 1785 | else => return unexpectedErrorPosix(err), | ||
| 1786 | } | ||
| 1787 | } | ||
| 1788 | if (result == 0) return null; | ||
| 1789 | self.handle.index = 0; | ||
| 1790 | self.handle.end_index = result; | ||
| 1791 | break; | ||
| 1792 | } | ||
| 1793 | } | ||
| 1794 | const freebsd_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]); | ||
| 1795 | const next_index = self.handle.index + freebsd_entry.d_reclen; | ||
| 1796 | self.handle.index = next_index; | ||
| 1797 | |||
| 1798 | const name = @ptrCast([*]u8, &freebsd_entry.d_name)[0..freebsd_entry.d_namlen]; | ||
| 1799 | |||
| 1800 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { | ||
| 1801 | continue :start_over; | ||
| 1802 | } | ||
| 1803 | |||
| 1804 | const entry_kind = switch (freebsd_entry.d_type) { | ||
| 1805 | posix.DT_BLK => Entry.Kind.BlockDevice, | ||
| 1806 | posix.DT_CHR => Entry.Kind.CharacterDevice, | ||
| 1807 | posix.DT_DIR => Entry.Kind.Directory, | ||
| 1808 | posix.DT_FIFO => Entry.Kind.NamedPipe, | ||
| 1809 | posix.DT_LNK => Entry.Kind.SymLink, | ||
| 1810 | posix.DT_REG => Entry.Kind.File, | ||
| 1811 | posix.DT_SOCK => Entry.Kind.UnixDomainSocket, | ||
| 1812 | posix.DT_WHT => Entry.Kind.Whiteout, | ||
| 1813 | else => Entry.Kind.Unknown, | ||
| 1814 | }; | ||
| 1815 | return Entry{ | ||
| 1816 | .name = name, | ||
| 1817 | .kind = entry_kind, | ||
| 1818 | }; | ||
| 1819 | } | ||
| 1736 | } | 1820 | } |
| 1737 | }; | 1821 | }; |
| 1738 | 1822 | ||
| ... | @@ -2136,9 +2220,9 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons | ... | @@ -2136,9 +2220,9 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons |
| 2136 | var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line); | 2220 | var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line); |
| 2137 | for (expected_args) |expected_arg| { | 2221 | for (expected_args) |expected_arg| { |
| 2138 | const arg = it.next(debug.global_allocator).? catch unreachable; | 2222 | const arg = it.next(debug.global_allocator).? catch unreachable; |
| 2139 | assert(mem.eql(u8, arg, expected_arg)); | 2223 | testing.expectEqualSlices(u8, expected_arg, arg); |
| 2140 | } | 2224 | } |
| 2141 | assert(it.next(debug.global_allocator) == null); | 2225 | testing.expect(it.next(debug.global_allocator) == null); |
| 2142 | } | 2226 | } |
| 2143 | 2227 | ||
| 2144 | // TODO make this a build variable that you can set | 2228 | // TODO make this a build variable that you can set |
| ... | @@ -2220,7 +2304,19 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 { | ... | @@ -2220,7 +2304,19 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 { |
| 2220 | pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 { | 2304 | pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 { |
| 2221 | switch (builtin.os) { | 2305 | switch (builtin.os) { |
| 2222 | Os.linux => return readLink(out_buffer, "/proc/self/exe"), | 2306 | Os.linux => return readLink(out_buffer, "/proc/self/exe"), |
| 2223 | Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"), | 2307 | Os.freebsd => { |
| 2308 | var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 }; | ||
| 2309 | var out_len: usize = out_buffer.len; | ||
| 2310 | const err = posix.getErrno(posix.sysctl(&mib, 4, out_buffer, &out_len, null, 0)); | ||
| 2311 | |||
| 2312 | if (err == 0) return mem.toSlice(u8, out_buffer); | ||
| 2313 | |||
| 2314 | return switch (err) { | ||
| 2315 | posix.EFAULT => error.BadAdress, | ||
| 2316 | posix.EPERM => error.PermissionDenied, | ||
| 2317 | else => unexpectedErrorPosix(err), | ||
| 2318 | }; | ||
| 2319 | }, | ||
| 2224 | Os.windows => { | 2320 | Os.windows => { |
| 2225 | var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined; | 2321 | var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined; |
| 2226 | const utf16le_slice = try selfExePathW(&utf16le_buf); | 2322 | const utf16le_slice = try selfExePathW(&utf16le_buf); |
| ... | @@ -2811,14 +2907,15 @@ pub const Thread = struct { | ... | @@ -2811,14 +2907,15 @@ pub const Thread = struct { |
| 2811 | pub const Data = if (use_pthreads) | 2907 | pub const Data = if (use_pthreads) |
| 2812 | struct { | 2908 | struct { |
| 2813 | handle: Thread.Handle, | 2909 | handle: Thread.Handle, |
| 2814 | stack_addr: usize, | 2910 | mmap_addr: usize, |
| 2815 | stack_len: usize, | 2911 | mmap_len: usize, |
| 2816 | } | 2912 | } |
| 2817 | else switch (builtin.os) { | 2913 | else switch (builtin.os) { |
| 2818 | builtin.Os.linux => struct { | 2914 | builtin.Os.linux => struct { |
| 2819 | handle: Thread.Handle, | 2915 | handle: Thread.Handle, |
| 2820 | stack_addr: usize, | 2916 | mmap_addr: usize, |
| 2821 | stack_len: usize, | 2917 | mmap_len: usize, |
| 2918 | tls_end_addr: usize, | ||
| 2822 | }, | 2919 | }, |
| 2823 | builtin.Os.windows => struct { | 2920 | builtin.Os.windows => struct { |
| 2824 | handle: Thread.Handle, | 2921 | handle: Thread.Handle, |
| ... | @@ -2858,7 +2955,7 @@ pub const Thread = struct { | ... | @@ -2858,7 +2955,7 @@ pub const Thread = struct { |
| 2858 | posix.EDEADLK => unreachable, | 2955 | posix.EDEADLK => unreachable, |
| 2859 | else => unreachable, | 2956 | else => unreachable, |
| 2860 | } | 2957 | } |
| 2861 | assert(posix.munmap(self.data.stack_addr, self.data.stack_len) == 0); | 2958 | assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0); |
| 2862 | } else switch (builtin.os) { | 2959 | } else switch (builtin.os) { |
| 2863 | builtin.Os.linux => { | 2960 | builtin.Os.linux => { |
| 2864 | while (true) { | 2961 | while (true) { |
| ... | @@ -2872,7 +2969,7 @@ pub const Thread = struct { | ... | @@ -2872,7 +2969,7 @@ pub const Thread = struct { |
| 2872 | else => unreachable, | 2969 | else => unreachable, |
| 2873 | } | 2970 | } |
| 2874 | } | 2971 | } |
| 2875 | assert(posix.munmap(self.data.stack_addr, self.data.stack_len) == 0); | 2972 | assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0); |
| 2876 | }, | 2973 | }, |
| 2877 | builtin.Os.windows => { | 2974 | builtin.Os.windows => { |
| 2878 | assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0); | 2975 | assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0); |
| ... | @@ -2911,11 +3008,15 @@ pub const SpawnThreadError = error{ | ... | @@ -2911,11 +3008,15 @@ pub const SpawnThreadError = error{ |
| 2911 | Unexpected, | 3008 | Unexpected, |
| 2912 | }; | 3009 | }; |
| 2913 | 3010 | ||
| 3011 | pub var linux_tls_phdr: ?*std.elf.Phdr = null; | ||
| 3012 | pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is | ||
| 3013 | |||
| 2914 | /// caller must call wait on the returned thread | 3014 | /// caller must call wait on the returned thread |
| 2915 | /// fn startFn(@typeOf(context)) T | 3015 | /// fn startFn(@typeOf(context)) T |
| 2916 | /// where T is u8, noreturn, void, or !void | 3016 | /// where T is u8, noreturn, void, or !void |
| 2917 | /// caller must call wait on the returned thread | 3017 | /// caller must call wait on the returned thread |
| 2918 | pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread { | 3018 | pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread { |
| 3019 | if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode"); | ||
| 2919 | // TODO compile-time call graph analysis to determine stack upper bound | 3020 | // TODO compile-time call graph analysis to determine stack upper bound |
| 2920 | // https://github.com/ziglang/zig/issues/157 | 3021 | // https://github.com/ziglang/zig/issues/157 |
| 2921 | const default_stack_size = 8 * 1024 * 1024; | 3022 | const default_stack_size = 8 * 1024 * 1024; |
| ... | @@ -2949,7 +3050,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread | ... | @@ -2949,7 +3050,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 2949 | const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory; | 3050 | const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory; |
| 2950 | errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0); | 3051 | errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0); |
| 2951 | const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count]; | 3052 | const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count]; |
| 2952 | const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext{ | 3053 | const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable; |
| 3054 | outer_context.* = WinThread.OuterContext{ | ||
| 2953 | .thread = Thread{ | 3055 | .thread = Thread{ |
| 2954 | .data = Thread.Data{ | 3056 | .data = Thread.Data{ |
| 2955 | .heap_handle = heap_handle, | 3057 | .heap_handle = heap_handle, |
| ... | @@ -2958,7 +3060,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread | ... | @@ -2958,7 +3060,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 2958 | }, | 3060 | }, |
| 2959 | }, | 3061 | }, |
| 2960 | .inner = context, | 3062 | .inner = context, |
| 2961 | }) catch unreachable; | 3063 | }; |
| 2962 | 3064 | ||
| 2963 | const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner); | 3065 | const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner); |
| 2964 | outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse { | 3066 | outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse { |
| ... | @@ -2998,42 +3100,56 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread | ... | @@ -2998,42 +3100,56 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 2998 | 3100 | ||
| 2999 | const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0; | 3101 | const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0; |
| 3000 | 3102 | ||
| 3001 | const mmap_len = default_stack_size; | 3103 | var stack_end_offset: usize = undefined; |
| 3002 | const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); | 3104 | var thread_start_offset: usize = undefined; |
| 3003 | if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory; | 3105 | var context_start_offset: usize = undefined; |
| 3004 | errdefer assert(posix.munmap(stack_addr, mmap_len) == 0); | 3106 | var tls_start_offset: usize = undefined; |
| 3107 | const mmap_len = blk: { | ||
| 3108 | // First in memory will be the stack, which grows downwards. | ||
| 3109 | var l: usize = mem.alignForward(default_stack_size, os.page_size); | ||
| 3110 | stack_end_offset = l; | ||
| 3111 | // Above the stack, so that it can be in the same mmap call, put the Thread object. | ||
| 3112 | l = mem.alignForward(l, @alignOf(Thread)); | ||
| 3113 | thread_start_offset = l; | ||
| 3114 | l += @sizeOf(Thread); | ||
| 3115 | // Next, the Context object. | ||
| 3116 | if (@sizeOf(Context) != 0) { | ||
| 3117 | l = mem.alignForward(l, @alignOf(Context)); | ||
| 3118 | context_start_offset = l; | ||
| 3119 | l += @sizeOf(Context); | ||
| 3120 | } | ||
| 3121 | // Finally, the Thread Local Storage, if any. | ||
| 3122 | if (!Thread.use_pthreads) { | ||
| 3123 | if (linux_tls_phdr) |tls_phdr| { | ||
| 3124 | l = mem.alignForward(l, tls_phdr.p_align); | ||
| 3125 | tls_start_offset = l; | ||
| 3126 | l += tls_phdr.p_memsz; | ||
| 3127 | } | ||
| 3128 | } | ||
| 3129 | break :blk l; | ||
| 3130 | }; | ||
| 3131 | const mmap_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); | ||
| 3132 | if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory; | ||
| 3133 | errdefer assert(posix.munmap(mmap_addr, mmap_len) == 0); | ||
| 3134 | |||
| 3135 | const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset)); | ||
| 3136 | thread_ptr.data.mmap_addr = mmap_addr; | ||
| 3137 | thread_ptr.data.mmap_len = mmap_len; | ||
| 3005 | 3138 | ||
| 3006 | var stack_end: usize = stack_addr + mmap_len; | ||
| 3007 | var arg: usize = undefined; | 3139 | var arg: usize = undefined; |
| 3008 | if (@sizeOf(Context) != 0) { | 3140 | if (@sizeOf(Context) != 0) { |
| 3009 | stack_end -= @sizeOf(Context); | 3141 | arg = mmap_addr + context_start_offset; |
| 3010 | stack_end -= stack_end % @alignOf(Context); | 3142 | const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, arg)); |
| 3011 | assert(stack_end >= stack_addr); | ||
| 3012 | const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, stack_end)); | ||
| 3013 | context_ptr.* = context; | 3143 | context_ptr.* = context; |
| 3014 | arg = stack_end; | ||
| 3015 | } | 3144 | } |
| 3016 | 3145 | ||
| 3017 | stack_end -= @sizeOf(Thread); | 3146 | if (Thread.use_pthreads) { |
| 3018 | stack_end -= stack_end % @alignOf(Thread); | ||
| 3019 | assert(stack_end >= stack_addr); | ||
| 3020 | const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, stack_end)); | ||
| 3021 | |||
| 3022 | thread_ptr.data.stack_addr = stack_addr; | ||
| 3023 | thread_ptr.data.stack_len = mmap_len; | ||
| 3024 | |||
| 3025 | if (builtin.os == builtin.Os.windows) { | ||
| 3026 | // use windows API directly | ||
| 3027 | @compileError("TODO support spawnThread for Windows"); | ||
| 3028 | } else if (Thread.use_pthreads) { | ||
| 3029 | // use pthreads | 3147 | // use pthreads |
| 3030 | var attr: c.pthread_attr_t = undefined; | 3148 | var attr: c.pthread_attr_t = undefined; |
| 3031 | if (c.pthread_attr_init(&attr) != 0) return SpawnThreadError.SystemResources; | 3149 | if (c.pthread_attr_init(&attr) != 0) return SpawnThreadError.SystemResources; |
| 3032 | defer assert(c.pthread_attr_destroy(&attr) == 0); | 3150 | defer assert(c.pthread_attr_destroy(&attr) == 0); |
| 3033 | 3151 | ||
| 3034 | // align to page | 3152 | assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, mmap_addr), stack_end_offset) == 0); |
| 3035 | stack_end -= stack_end % os.page_size; | ||
| 3036 | assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, stack_addr), stack_end - stack_addr) == 0); | ||
| 3037 | 3153 | ||
| 3038 | const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg)); | 3154 | const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg)); |
| 3039 | switch (err) { | 3155 | switch (err) { |
| ... | @@ -3044,10 +3160,17 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread | ... | @@ -3044,10 +3160,17 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread |
| 3044 | else => return unexpectedErrorPosix(@intCast(usize, err)), | 3160 | else => return unexpectedErrorPosix(@intCast(usize, err)), |
| 3045 | } | 3161 | } |
| 3046 | } else if (builtin.os == builtin.Os.linux) { | 3162 | } else if (builtin.os == builtin.Os.linux) { |
| 3047 | // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly | 3163 | var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | |
| 3048 | const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED; | 3164 | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | |
| 3049 | const newtls: usize = 0; | 3165 | posix.CLONE_DETACHED; |
| 3050 | const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); | 3166 | var newtls: usize = undefined; |
| 3167 | if (linux_tls_phdr) |tls_phdr| { | ||
| 3168 | @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz); | ||
| 3169 | thread_ptr.data.tls_end_addr = mmap_addr + mmap_len; | ||
| 3170 | newtls = @ptrToInt(&thread_ptr.data.tls_end_addr); | ||
| 3171 | flags |= posix.CLONE_SETTLS; | ||
| 3172 | } | ||
| 3173 | const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); | ||
| 3051 | const err = posix.getErrno(rc); | 3174 | const err = posix.getErrno(rc); |
| 3052 | switch (err) { | 3175 | switch (err) { |
| 3053 | 0 => return thread_ptr, | 3176 | 0 => return thread_ptr, |
std/os/linux/test.zig+6-6| ... | @@ -1,19 +1,19 @@ | ... | @@ -1,19 +1,19 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const linux = std.os.linux; | 3 | const linux = std.os.linux; |
| 4 | const assert = std.debug.assert; | 4 | const expect = std.testing.expect; |
| 5 | 5 | ||
| 6 | test "getpid" { | 6 | test "getpid" { |
| 7 | assert(linux.getpid() != 0); | 7 | expect(linux.getpid() != 0); |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | test "timer" { | 10 | test "timer" { |
| 11 | const epoll_fd = linux.epoll_create(); | 11 | const epoll_fd = linux.epoll_create(); |
| 12 | var err = linux.getErrno(epoll_fd); | 12 | var err = linux.getErrno(epoll_fd); |
| 13 | assert(err == 0); | 13 | expect(err == 0); |
| 14 | 14 | ||
| 15 | const timer_fd = linux.timerfd_create(linux.CLOCK_MONOTONIC, 0); | 15 | const timer_fd = linux.timerfd_create(linux.CLOCK_MONOTONIC, 0); |
| 16 | assert(linux.getErrno(timer_fd) == 0); | 16 | expect(linux.getErrno(timer_fd) == 0); |
| 17 | 17 | ||
| 18 | const time_interval = linux.timespec{ | 18 | const time_interval = linux.timespec{ |
| 19 | .tv_sec = 0, | 19 | .tv_sec = 0, |
| ... | @@ -26,7 +26,7 @@ test "timer" { | ... | @@ -26,7 +26,7 @@ test "timer" { |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null); | 28 | err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null); |
| 29 | assert(err == 0); | 29 | expect(err == 0); |
| 30 | 30 | ||
| 31 | var event = linux.epoll_event{ | 31 | var event = linux.epoll_event{ |
| 32 | .events = linux.EPOLLIN | linux.EPOLLOUT | linux.EPOLLET, | 32 | .events = linux.EPOLLIN | linux.EPOLLOUT | linux.EPOLLET, |
| ... | @@ -34,7 +34,7 @@ test "timer" { | ... | @@ -34,7 +34,7 @@ test "timer" { |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | err = linux.epoll_ctl(@intCast(i32, epoll_fd), linux.EPOLL_CTL_ADD, @intCast(i32, timer_fd), &event); | 36 | err = linux.epoll_ctl(@intCast(i32, epoll_fd), linux.EPOLL_CTL_ADD, @intCast(i32, timer_fd), &event); |
| 37 | assert(err == 0); | 37 | expect(err == 0); |
| 38 | 38 | ||
| 39 | const events_one: linux.epoll_event = undefined; | 39 | const events_one: linux.epoll_event = undefined; |
| 40 | var events = []linux.epoll_event{events_one} ** 8; | 40 | var events = []linux.epoll_event{events_one} ** 8; |
std/os/path.zig+168-112| ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const Os = builtin.Os; | 3 | const Os = builtin.Os; |
| 4 | const debug = std.debug; | 4 | const debug = std.debug; |
| 5 | const assert = debug.assert; | 5 | const assert = debug.assert; |
| 6 | const testing = std.testing; | ||
| 6 | const mem = std.mem; | 7 | const mem = std.mem; |
| 7 | const fmt = std.fmt; | 8 | const fmt = std.fmt; |
| 8 | const Allocator = mem.Allocator; | 9 | const Allocator = mem.Allocator; |
| ... | @@ -33,40 +34,103 @@ pub fn isSep(byte: u8) bool { | ... | @@ -33,40 +34,103 @@ pub fn isSep(byte: u8) bool { |
| 33 | } | 34 | } |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 37 | /// This is different from mem.join in that the separator will not be repeated if | ||
| 38 | /// it is found at the end or beginning of a pair of consecutive paths. | ||
| 39 | fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u8 { | ||
| 40 | if (paths.len == 0) return (([*]u8)(undefined))[0..0]; | ||
| 41 | |||
| 42 | const total_len = blk: { | ||
| 43 | var sum: usize = paths[0].len; | ||
| 44 | var i: usize = 1; | ||
| 45 | while (i < paths.len) : (i += 1) { | ||
| 46 | const prev_path = paths[i - 1]; | ||
| 47 | const this_path = paths[i]; | ||
| 48 | const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator); | ||
| 49 | const this_sep = (this_path.len != 0 and this_path[0] == separator); | ||
| 50 | sum += @boolToInt(!prev_sep and !this_sep); | ||
| 51 | sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len; | ||
| 52 | } | ||
| 53 | break :blk sum; | ||
| 54 | }; | ||
| 55 | |||
| 56 | const buf = try allocator.alloc(u8, total_len); | ||
| 57 | errdefer allocator.free(buf); | ||
| 58 | |||
| 59 | mem.copy(u8, buf, paths[0]); | ||
| 60 | var buf_index: usize = paths[0].len; | ||
| 61 | var i: usize = 1; | ||
| 62 | while (i < paths.len) : (i += 1) { | ||
| 63 | const prev_path = paths[i - 1]; | ||
| 64 | const this_path = paths[i]; | ||
| 65 | const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator); | ||
| 66 | const this_sep = (this_path.len != 0 and this_path[0] == separator); | ||
| 67 | if (!prev_sep and !this_sep) { | ||
| 68 | buf[buf_index] = separator; | ||
| 69 | buf_index += 1; | ||
| 70 | } | ||
| 71 | const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path; | ||
| 72 | mem.copy(u8, buf[buf_index..], adjusted_path); | ||
| 73 | buf_index += adjusted_path.len; | ||
| 74 | } | ||
| 75 | |||
| 76 | // No need for shrink since buf is exactly the correct size. | ||
| 77 | return buf; | ||
| 78 | } | ||
| 79 | |||
| 80 | pub const join = if (is_windows) joinWindows else joinPosix; | ||
| 81 | |||
| 36 | /// Naively combines a series of paths with the native path seperator. | 82 | /// Naively combines a series of paths with the native path seperator. |
| 37 | /// Allocates memory for the result, which must be freed by the caller. | 83 | /// Allocates memory for the result, which must be freed by the caller. |
| 38 | pub fn join(allocator: *Allocator, paths: ...) ![]u8 { | 84 | pub fn joinWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 39 | if (is_windows) { | 85 | return joinSep(allocator, sep_windows, paths); |
| 40 | return joinWindows(allocator, paths); | 86 | } |
| 41 | } else { | 87 | |
| 42 | return joinPosix(allocator, paths); | 88 | /// Naively combines a series of paths with the native path seperator. |
| 43 | } | 89 | /// Allocates memory for the result, which must be freed by the caller. |
| 90 | pub fn joinPosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ||
| 91 | return joinSep(allocator, sep_posix, paths); | ||
| 44 | } | 92 | } |
| 45 | 93 | ||
| 46 | pub fn joinWindows(allocator: *Allocator, paths: ...) ![]u8 { | 94 | fn testJoinWindows(paths: []const []const u8, expected: []const u8) void { |
| 47 | return mem.join(allocator, sep_windows, paths); | 95 | var buf: [1024]u8 = undefined; |
| 96 | const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; | ||
| 97 | const actual = joinWindows(a, paths) catch @panic("fail"); | ||
| 98 | testing.expectEqualSlices(u8, expected, actual); | ||
| 48 | } | 99 | } |
| 49 | 100 | ||
| 50 | pub fn joinPosix(allocator: *Allocator, paths: ...) ![]u8 { | 101 | fn testJoinPosix(paths: []const []const u8, expected: []const u8) void { |
| 51 | return mem.join(allocator, sep_posix, paths); | 102 | var buf: [1024]u8 = undefined; |
| 103 | const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; | ||
| 104 | const actual = joinPosix(a, paths) catch @panic("fail"); | ||
| 105 | testing.expectEqualSlices(u8, expected, actual); | ||
| 52 | } | 106 | } |
| 53 | 107 | ||
| 54 | test "os.path.join" { | 108 | test "os.path.join" { |
| 55 | assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c")); | 109 | testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c"); |
| 56 | assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c")); | 110 | testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c"); |
| 111 | testJoinWindows([][]const u8{ "c:\\a\\b\\", "c" }, "c:\\a\\b\\c"); | ||
| 57 | 112 | ||
| 58 | assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c")); | 113 | testJoinWindows([][]const u8{ "c:\\", "a", "b\\", "c" }, "c:\\a\\b\\c"); |
| 59 | assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c")); | 114 | testJoinWindows([][]const u8{ "c:\\a\\", "b\\", "c" }, "c:\\a\\b\\c"); |
| 60 | 115 | ||
| 61 | assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig"), "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig")); | 116 | testJoinWindows( |
| 117 | [][]const u8{ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig" }, | ||
| 118 | "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig", | ||
| 119 | ); | ||
| 62 | 120 | ||
| 63 | assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c")); | 121 | testJoinPosix([][]const u8{ "/a/b", "c" }, "/a/b/c"); |
| 64 | assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c")); | 122 | testJoinPosix([][]const u8{ "/a/b/", "c" }, "/a/b/c"); |
| 65 | 123 | ||
| 66 | assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c")); | 124 | testJoinPosix([][]const u8{ "/", "a", "b/", "c" }, "/a/b/c"); |
| 67 | assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/", "b/", "c"), "/a/b/c")); | 125 | testJoinPosix([][]const u8{ "/a/", "b/", "c" }, "/a/b/c"); |
| 68 | 126 | ||
| 69 | assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"), "/home/andy/dev/zig/build/lib/zig/std/io.zig")); | 127 | testJoinPosix( |
| 128 | [][]const u8{ "/home/andy/dev/zig/build/lib/zig/std", "io.zig" }, | ||
| 129 | "/home/andy/dev/zig/build/lib/zig/std/io.zig", | ||
| 130 | ); | ||
| 131 | |||
| 132 | testJoinPosix([][]const u8{ "a", "/c" }, "a/c"); | ||
| 133 | testJoinPosix([][]const u8{ "a/", "/c" }, "a/c"); | ||
| 70 | } | 134 | } |
| 71 | 135 | ||
| 72 | pub fn isAbsolute(path: []const u8) bool { | 136 | pub fn isAbsolute(path: []const u8) bool { |
| ... | @@ -130,11 +194,11 @@ test "os.path.isAbsolutePosix" { | ... | @@ -130,11 +194,11 @@ test "os.path.isAbsolutePosix" { |
| 130 | } | 194 | } |
| 131 | 195 | ||
| 132 | fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void { | 196 | fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void { |
| 133 | assert(isAbsoluteWindows(path) == expected_result); | 197 | testing.expectEqual(expected_result, isAbsoluteWindows(path)); |
| 134 | } | 198 | } |
| 135 | 199 | ||
| 136 | fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void { | 200 | fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void { |
| 137 | assert(isAbsolutePosix(path) == expected_result); | 201 | testing.expectEqual(expected_result, isAbsolutePosix(path)); |
| 138 | } | 202 | } |
| 139 | 203 | ||
| 140 | pub const WindowsPath = struct { | 204 | pub const WindowsPath = struct { |
| ... | @@ -184,7 +248,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { | ... | @@ -184,7 +248,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { |
| 184 | return relative_path; | 248 | return relative_path; |
| 185 | } | 249 | } |
| 186 | 250 | ||
| 187 | var it = mem.split(path, []u8{this_sep}); | 251 | var it = mem.tokenize(path, []u8{this_sep}); |
| 188 | _ = (it.next() orelse return relative_path); | 252 | _ = (it.next() orelse return relative_path); |
| 189 | _ = (it.next() orelse return relative_path); | 253 | _ = (it.next() orelse return relative_path); |
| 190 | return WindowsPath{ | 254 | return WindowsPath{ |
| ... | @@ -202,7 +266,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { | ... | @@ -202,7 +266,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { |
| 202 | return relative_path; | 266 | return relative_path; |
| 203 | } | 267 | } |
| 204 | 268 | ||
| 205 | var it = mem.split(path, []u8{this_sep}); | 269 | var it = mem.tokenize(path, []u8{this_sep}); |
| 206 | _ = (it.next() orelse return relative_path); | 270 | _ = (it.next() orelse return relative_path); |
| 207 | _ = (it.next() orelse return relative_path); | 271 | _ = (it.next() orelse return relative_path); |
| 208 | return WindowsPath{ | 272 | return WindowsPath{ |
| ... | @@ -218,33 +282,33 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { | ... | @@ -218,33 +282,33 @@ pub fn windowsParsePath(path: []const u8) WindowsPath { |
| 218 | test "os.path.windowsParsePath" { | 282 | test "os.path.windowsParsePath" { |
| 219 | { | 283 | { |
| 220 | const parsed = windowsParsePath("//a/b"); | 284 | const parsed = windowsParsePath("//a/b"); |
| 221 | assert(parsed.is_abs); | 285 | testing.expect(parsed.is_abs); |
| 222 | assert(parsed.kind == WindowsPath.Kind.NetworkShare); | 286 | testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare); |
| 223 | assert(mem.eql(u8, parsed.disk_designator, "//a/b")); | 287 | testing.expect(mem.eql(u8, parsed.disk_designator, "//a/b")); |
| 224 | } | 288 | } |
| 225 | { | 289 | { |
| 226 | const parsed = windowsParsePath("\\\\a\\b"); | 290 | const parsed = windowsParsePath("\\\\a\\b"); |
| 227 | assert(parsed.is_abs); | 291 | testing.expect(parsed.is_abs); |
| 228 | assert(parsed.kind == WindowsPath.Kind.NetworkShare); | 292 | testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare); |
| 229 | assert(mem.eql(u8, parsed.disk_designator, "\\\\a\\b")); | 293 | testing.expect(mem.eql(u8, parsed.disk_designator, "\\\\a\\b")); |
| 230 | } | 294 | } |
| 231 | { | 295 | { |
| 232 | const parsed = windowsParsePath("\\\\a\\"); | 296 | const parsed = windowsParsePath("\\\\a\\"); |
| 233 | assert(!parsed.is_abs); | 297 | testing.expect(!parsed.is_abs); |
| 234 | assert(parsed.kind == WindowsPath.Kind.None); | 298 | testing.expect(parsed.kind == WindowsPath.Kind.None); |
| 235 | assert(mem.eql(u8, parsed.disk_designator, "")); | 299 | testing.expect(mem.eql(u8, parsed.disk_designator, "")); |
| 236 | } | 300 | } |
| 237 | { | 301 | { |
| 238 | const parsed = windowsParsePath("/usr/local"); | 302 | const parsed = windowsParsePath("/usr/local"); |
| 239 | assert(parsed.is_abs); | 303 | testing.expect(parsed.is_abs); |
| 240 | assert(parsed.kind == WindowsPath.Kind.None); | 304 | testing.expect(parsed.kind == WindowsPath.Kind.None); |
| 241 | assert(mem.eql(u8, parsed.disk_designator, "")); | 305 | testing.expect(mem.eql(u8, parsed.disk_designator, "")); |
| 242 | } | 306 | } |
| 243 | { | 307 | { |
| 244 | const parsed = windowsParsePath("c:../"); | 308 | const parsed = windowsParsePath("c:../"); |
| 245 | assert(!parsed.is_abs); | 309 | testing.expect(!parsed.is_abs); |
| 246 | assert(parsed.kind == WindowsPath.Kind.Drive); | 310 | testing.expect(parsed.kind == WindowsPath.Kind.Drive); |
| 247 | assert(mem.eql(u8, parsed.disk_designator, "c:")); | 311 | testing.expect(mem.eql(u8, parsed.disk_designator, "c:")); |
| 248 | } | 312 | } |
| 249 | } | 313 | } |
| 250 | 314 | ||
| ... | @@ -264,8 +328,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool { | ... | @@ -264,8 +328,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool { |
| 264 | const sep1 = ns1[0]; | 328 | const sep1 = ns1[0]; |
| 265 | const sep2 = ns2[0]; | 329 | const sep2 = ns2[0]; |
| 266 | 330 | ||
| 267 | var it1 = mem.split(ns1, []u8{sep1}); | 331 | var it1 = mem.tokenize(ns1, []u8{sep1}); |
| 268 | var it2 = mem.split(ns2, []u8{sep2}); | 332 | var it2 = mem.tokenize(ns2, []u8{sep2}); |
| 269 | 333 | ||
| 270 | // TODO ASCII is wrong, we actually need full unicode support to compare paths. | 334 | // TODO ASCII is wrong, we actually need full unicode support to compare paths. |
| 271 | return asciiEqlIgnoreCase(it1.next().?, it2.next().?); | 335 | return asciiEqlIgnoreCase(it1.next().?, it2.next().?); |
| ... | @@ -285,8 +349,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8 | ... | @@ -285,8 +349,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8 |
| 285 | const sep1 = p1[0]; | 349 | const sep1 = p1[0]; |
| 286 | const sep2 = p2[0]; | 350 | const sep2 = p2[0]; |
| 287 | 351 | ||
| 288 | var it1 = mem.split(p1, []u8{sep1}); | 352 | var it1 = mem.tokenize(p1, []u8{sep1}); |
| 289 | var it2 = mem.split(p2, []u8{sep2}); | 353 | var it2 = mem.tokenize(p2, []u8{sep2}); |
| 290 | 354 | ||
| 291 | // TODO ASCII is wrong, we actually need full unicode support to compare paths. | 355 | // TODO ASCII is wrong, we actually need full unicode support to compare paths. |
| 292 | return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?); | 356 | return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?); |
| ... | @@ -312,18 +376,8 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool { | ... | @@ -312,18 +376,8 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool { |
| 312 | return true; | 376 | return true; |
| 313 | } | 377 | } |
| 314 | 378 | ||
| 315 | /// Converts the command line arguments into a slice and calls `resolveSlice`. | ||
| 316 | pub fn resolve(allocator: *Allocator, args: ...) ![]u8 { | ||
| 317 | var paths: [args.len][]const u8 = undefined; | ||
| 318 | comptime var arg_i = 0; | ||
| 319 | inline while (arg_i < args.len) : (arg_i += 1) { | ||
| 320 | paths[arg_i] = args[arg_i]; | ||
| 321 | } | ||
| 322 | return resolveSlice(allocator, paths); | ||
| 323 | } | ||
| 324 | |||
| 325 | /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`. | 379 | /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`. |
| 326 | pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 { | 380 | pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 327 | if (is_windows) { | 381 | if (is_windows) { |
| 328 | return resolveWindows(allocator, paths); | 382 | return resolveWindows(allocator, paths); |
| 329 | } else { | 383 | } else { |
| ... | @@ -337,6 +391,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -337,6 +391,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 337 | /// If all paths are relative it uses the current working directory as a starting point. | 391 | /// If all paths are relative it uses the current working directory as a starting point. |
| 338 | /// Each drive has its own current working directory. | 392 | /// Each drive has its own current working directory. |
| 339 | /// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters. | 393 | /// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters. |
| 394 | /// Note: all usage of this function should be audited due to the existence of symlinks. | ||
| 395 | /// Without performing actual syscalls, resolving `..` could be incorrect. | ||
| 340 | pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | 396 | pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 341 | if (paths.len == 0) { | 397 | if (paths.len == 0) { |
| 342 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | 398 | assert(is_windows); // resolveWindows called on non windows can't use getCwd |
| ... | @@ -416,7 +472,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -416,7 +472,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 416 | }, | 472 | }, |
| 417 | WindowsPath.Kind.NetworkShare => { | 473 | WindowsPath.Kind.NetworkShare => { |
| 418 | result = try allocator.alloc(u8, max_size); | 474 | result = try allocator.alloc(u8, max_size); |
| 419 | var it = mem.split(paths[first_index], "/\\"); | 475 | var it = mem.tokenize(paths[first_index], "/\\"); |
| 420 | const server_name = it.next().?; | 476 | const server_name = it.next().?; |
| 421 | const other_name = it.next().?; | 477 | const other_name = it.next().?; |
| 422 | 478 | ||
| ... | @@ -483,7 +539,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -483,7 +539,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 483 | if (!correct_disk_designator) { | 539 | if (!correct_disk_designator) { |
| 484 | continue; | 540 | continue; |
| 485 | } | 541 | } |
| 486 | var it = mem.split(p[parsed.disk_designator.len..], "/\\"); | 542 | var it = mem.tokenize(p[parsed.disk_designator.len..], "/\\"); |
| 487 | while (it.next()) |component| { | 543 | while (it.next()) |component| { |
| 488 | if (mem.eql(u8, component, ".")) { | 544 | if (mem.eql(u8, component, ".")) { |
| 489 | continue; | 545 | continue; |
| ... | @@ -516,6 +572,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -516,6 +572,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 516 | /// It resolves "." and "..". | 572 | /// It resolves "." and "..". |
| 517 | /// The result does not have a trailing path separator. | 573 | /// The result does not have a trailing path separator. |
| 518 | /// If all paths are relative it uses the current working directory as a starting point. | 574 | /// If all paths are relative it uses the current working directory as a starting point. |
| 575 | /// Note: all usage of this function should be audited due to the existence of symlinks. | ||
| 576 | /// Without performing actual syscalls, resolving `..` could be incorrect. | ||
| 519 | pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { | 577 | pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 520 | if (paths.len == 0) { | 578 | if (paths.len == 0) { |
| 521 | assert(!is_windows); // resolvePosix called on windows can't use getCwd | 579 | assert(!is_windows); // resolvePosix called on windows can't use getCwd |
| ... | @@ -550,7 +608,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -550,7 +608,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 550 | errdefer allocator.free(result); | 608 | errdefer allocator.free(result); |
| 551 | 609 | ||
| 552 | for (paths[first_index..]) |p, i| { | 610 | for (paths[first_index..]) |p, i| { |
| 553 | var it = mem.split(p, "/"); | 611 | var it = mem.tokenize(p, "/"); |
| 554 | while (it.next()) |component| { | 612 | while (it.next()) |component| { |
| 555 | if (mem.eql(u8, component, ".")) { | 613 | if (mem.eql(u8, component, ".")) { |
| 556 | continue; | 614 | continue; |
| ... | @@ -585,10 +643,10 @@ test "os.path.resolve" { | ... | @@ -585,10 +643,10 @@ test "os.path.resolve" { |
| 585 | if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) { | 643 | if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) { |
| 586 | cwd[0] = asciiUpper(cwd[0]); | 644 | cwd[0] = asciiUpper(cwd[0]); |
| 587 | } | 645 | } |
| 588 | assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd)); | 646 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd)); |
| 589 | } else { | 647 | } else { |
| 590 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd)); | 648 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd)); |
| 591 | assert(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd)); | 649 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd)); |
| 592 | } | 650 | } |
| 593 | } | 651 | } |
| 594 | 652 | ||
| ... | @@ -598,48 +656,54 @@ test "os.path.resolveWindows" { | ... | @@ -598,48 +656,54 @@ test "os.path.resolveWindows" { |
| 598 | const parsed_cwd = windowsParsePath(cwd); | 656 | const parsed_cwd = windowsParsePath(cwd); |
| 599 | { | 657 | { |
| 600 | const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" }); | 658 | const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" }); |
| 601 | const expected = try join(debug.global_allocator, parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig"); | 659 | const expected = try join(debug.global_allocator, [][]const u8{ |
| 660 | parsed_cwd.disk_designator, | ||
| 661 | "usr\\local\\lib\\zig\\std\\array_list.zig", | ||
| 662 | }); | ||
| 602 | if (parsed_cwd.kind == WindowsPath.Kind.Drive) { | 663 | if (parsed_cwd.kind == WindowsPath.Kind.Drive) { |
| 603 | expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); | 664 | expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); |
| 604 | } | 665 | } |
| 605 | assert(mem.eql(u8, result, expected)); | 666 | testing.expect(mem.eql(u8, result, expected)); |
| 606 | } | 667 | } |
| 607 | { | 668 | { |
| 608 | const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" }); | 669 | const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" }); |
| 609 | const expected = try join(debug.global_allocator, cwd, "usr\\local\\lib\\zig"); | 670 | const expected = try join(debug.global_allocator, [][]const u8{ |
| 671 | cwd, | ||
| 672 | "usr\\local\\lib\\zig", | ||
| 673 | }); | ||
| 610 | if (parsed_cwd.kind == WindowsPath.Kind.Drive) { | 674 | if (parsed_cwd.kind == WindowsPath.Kind.Drive) { |
| 611 | expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); | 675 | expected[0] = asciiUpper(parsed_cwd.disk_designator[0]); |
| 612 | } | 676 | } |
| 613 | assert(mem.eql(u8, result, expected)); | 677 | testing.expect(mem.eql(u8, result, expected)); |
| 614 | } | 678 | } |
| 615 | } | 679 | } |
| 616 | 680 | ||
| 617 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok")); | 681 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok")); |
| 618 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a")); | 682 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a")); |
| 619 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a")); | 683 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a")); |
| 620 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe")); | 684 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe")); |
| 621 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file")); | 685 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file")); |
| 622 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir")); | 686 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir")); |
| 623 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative")); | 687 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative")); |
| 624 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\")); | 688 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\")); |
| 625 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir")); | 689 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir")); |
| 626 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\")); | 690 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\")); |
| 627 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\")); | 691 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\")); |
| 628 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir")); | 692 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir")); |
| 629 | assert(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js")); | 693 | testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js")); |
| 630 | } | 694 | } |
| 631 | 695 | ||
| 632 | test "os.path.resolvePosix" { | 696 | test "os.path.resolvePosix" { |
| 633 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c")); | 697 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c")); |
| 634 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e")); | 698 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e")); |
| 635 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a")); | 699 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a")); |
| 636 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/")); | 700 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/")); |
| 637 | assert(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c")); | 701 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c")); |
| 638 | 702 | ||
| 639 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file")); | 703 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file")); |
| 640 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file")); | 704 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file")); |
| 641 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute")); | 705 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute")); |
| 642 | assert(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js")); | 706 | testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js")); |
| 643 | } | 707 | } |
| 644 | 708 | ||
| 645 | fn testResolveWindows(paths: []const []const u8) []u8 { | 709 | fn testResolveWindows(paths: []const []const u8) []u8 { |
| ... | @@ -770,17 +834,17 @@ test "os.path.dirnameWindows" { | ... | @@ -770,17 +834,17 @@ test "os.path.dirnameWindows" { |
| 770 | 834 | ||
| 771 | fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void { | 835 | fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void { |
| 772 | if (dirnamePosix(input)) |output| { | 836 | if (dirnamePosix(input)) |output| { |
| 773 | assert(mem.eql(u8, output, expected_output.?)); | 837 | testing.expect(mem.eql(u8, output, expected_output.?)); |
| 774 | } else { | 838 | } else { |
| 775 | assert(expected_output == null); | 839 | testing.expect(expected_output == null); |
| 776 | } | 840 | } |
| 777 | } | 841 | } |
| 778 | 842 | ||
| 779 | fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void { | 843 | fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void { |
| 780 | if (dirnameWindows(input)) |output| { | 844 | if (dirnameWindows(input)) |output| { |
| 781 | assert(mem.eql(u8, output, expected_output.?)); | 845 | testing.expect(mem.eql(u8, output, expected_output.?)); |
| 782 | } else { | 846 | } else { |
| 783 | assert(expected_output == null); | 847 | testing.expect(expected_output == null); |
| 784 | } | 848 | } |
| 785 | } | 849 | } |
| 786 | 850 | ||
| ... | @@ -885,15 +949,15 @@ test "os.path.basename" { | ... | @@ -885,15 +949,15 @@ test "os.path.basename" { |
| 885 | } | 949 | } |
| 886 | 950 | ||
| 887 | fn testBasename(input: []const u8, expected_output: []const u8) void { | 951 | fn testBasename(input: []const u8, expected_output: []const u8) void { |
| 888 | assert(mem.eql(u8, basename(input), expected_output)); | 952 | testing.expectEqualSlices(u8, expected_output, basename(input)); |
| 889 | } | 953 | } |
| 890 | 954 | ||
| 891 | fn testBasenamePosix(input: []const u8, expected_output: []const u8) void { | 955 | fn testBasenamePosix(input: []const u8, expected_output: []const u8) void { |
| 892 | assert(mem.eql(u8, basenamePosix(input), expected_output)); | 956 | testing.expectEqualSlices(u8, expected_output, basenamePosix(input)); |
| 893 | } | 957 | } |
| 894 | 958 | ||
| 895 | fn testBasenameWindows(input: []const u8, expected_output: []const u8) void { | 959 | fn testBasenameWindows(input: []const u8, expected_output: []const u8) void { |
| 896 | assert(mem.eql(u8, basenameWindows(input), expected_output)); | 960 | testing.expectEqualSlices(u8, expected_output, basenameWindows(input)); |
| 897 | } | 961 | } |
| 898 | 962 | ||
| 899 | /// Returns the relative path from `from` to `to`. If `from` and `to` each | 963 | /// Returns the relative path from `from` to `to`. If `from` and `to` each |
| ... | @@ -937,8 +1001,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8) | ... | @@ -937,8 +1001,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8) |
| 937 | return resolved_to; | 1001 | return resolved_to; |
| 938 | } | 1002 | } |
| 939 | 1003 | ||
| 940 | var from_it = mem.split(resolved_from, "/\\"); | 1004 | var from_it = mem.tokenize(resolved_from, "/\\"); |
| 941 | var to_it = mem.split(resolved_to, "/\\"); | 1005 | var to_it = mem.tokenize(resolved_to, "/\\"); |
| 942 | while (true) { | 1006 | while (true) { |
| 943 | const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest()); | 1007 | const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest()); |
| 944 | const to_rest = to_it.rest(); | 1008 | const to_rest = to_it.rest(); |
| ... | @@ -967,7 +1031,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8) | ... | @@ -967,7 +1031,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8) |
| 967 | // shave off the trailing slash | 1031 | // shave off the trailing slash |
| 968 | result_index -= 1; | 1032 | result_index -= 1; |
| 969 | 1033 | ||
| 970 | var rest_it = mem.split(to_rest, "/\\"); | 1034 | var rest_it = mem.tokenize(to_rest, "/\\"); |
| 971 | while (rest_it.next()) |to_component| { | 1035 | while (rest_it.next()) |to_component| { |
| 972 | result[result_index] = '\\'; | 1036 | result[result_index] = '\\'; |
| 973 | result_index += 1; | 1037 | result_index += 1; |
| ... | @@ -988,8 +1052,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![ | ... | @@ -988,8 +1052,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![ |
| 988 | const resolved_to = try resolvePosix(allocator, [][]const u8{to}); | 1052 | const resolved_to = try resolvePosix(allocator, [][]const u8{to}); |
| 989 | defer allocator.free(resolved_to); | 1053 | defer allocator.free(resolved_to); |
| 990 | 1054 | ||
| 991 | var from_it = mem.split(resolved_from, "/"); | 1055 | var from_it = mem.tokenize(resolved_from, "/"); |
| 992 | var to_it = mem.split(resolved_to, "/"); | 1056 | var to_it = mem.tokenize(resolved_to, "/"); |
| 993 | while (true) { | 1057 | while (true) { |
| 994 | const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest()); | 1058 | const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest()); |
| 995 | const to_rest = to_it.rest(); | 1059 | const to_rest = to_it.rest(); |
| ... | @@ -1068,12 +1132,12 @@ test "os.path.relative" { | ... | @@ -1068,12 +1132,12 @@ test "os.path.relative" { |
| 1068 | 1132 | ||
| 1069 | fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void { | 1133 | fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void { |
| 1070 | const result = relativePosix(debug.global_allocator, from, to) catch unreachable; | 1134 | const result = relativePosix(debug.global_allocator, from, to) catch unreachable; |
| 1071 | assert(mem.eql(u8, result, expected_output)); | 1135 | testing.expectEqualSlices(u8, expected_output, result); |
| 1072 | } | 1136 | } |
| 1073 | 1137 | ||
| 1074 | fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void { | 1138 | fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void { |
| 1075 | const result = relativeWindows(debug.global_allocator, from, to) catch unreachable; | 1139 | const result = relativeWindows(debug.global_allocator, from, to) catch unreachable; |
| 1076 | assert(mem.eql(u8, result, expected_output)); | 1140 | testing.expectEqualSlices(u8, expected_output, result); |
| 1077 | } | 1141 | } |
| 1078 | 1142 | ||
| 1079 | pub const RealError = error{ | 1143 | pub const RealError = error{ |
| ... | @@ -1093,6 +1157,7 @@ pub const RealError = error{ | ... | @@ -1093,6 +1157,7 @@ pub const RealError = error{ |
| 1093 | NoSpaceLeft, | 1157 | NoSpaceLeft, |
| 1094 | FileSystem, | 1158 | FileSystem, |
| 1095 | BadPathName, | 1159 | BadPathName, |
| 1160 | DeviceBusy, | ||
| 1096 | 1161 | ||
| 1097 | /// On Windows, file paths must be valid Unicode. | 1162 | /// On Windows, file paths must be valid Unicode. |
| 1098 | InvalidUtf8, | 1163 | InvalidUtf8, |
| ... | @@ -1161,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro | ... | @@ -1161,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro |
| 1161 | const pathname_w = try windows_util.cStrToPrefixedFileW(pathname); | 1226 | const pathname_w = try windows_util.cStrToPrefixedFileW(pathname); |
| 1162 | return realW(out_buffer, pathname_w); | 1227 | return realW(out_buffer, pathname_w); |
| 1163 | }, | 1228 | }, |
| 1164 | Os.macosx, Os.ios => { | 1229 | Os.freebsd, Os.macosx, Os.ios => { |
| 1165 | // TODO instead of calling the libc function here, port the implementation to Zig | 1230 | // TODO instead of calling the libc function here, port the implementation to Zig |
| 1166 | const err = posix.getErrno(posix.realpath(pathname, out_buffer)); | 1231 | const err = posix.getErrno(posix.realpath(pathname, out_buffer)); |
| 1167 | switch (err) { | 1232 | switch (err) { |
| ... | @@ -1188,15 +1253,6 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro | ... | @@ -1188,15 +1253,6 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro |
| 1188 | 1253 | ||
| 1189 | return os.readLinkC(out_buffer, proc_path.ptr); | 1254 | return os.readLinkC(out_buffer, proc_path.ptr); |
| 1190 | }, | 1255 | }, |
| 1191 | Os.freebsd => { // XXX requires fdescfs | ||
| 1192 | const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0); | ||
| 1193 | defer os.close(fd); | ||
| 1194 | |||
| 1195 | var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined; | ||
| 1196 | const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable; | ||
| 1197 | |||
| 1198 | return os.readLinkC(out_buffer, proc_path.ptr); | ||
| 1199 | }, | ||
| 1200 | else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)), | 1256 | else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)), |
| 1201 | } | 1257 | } |
| 1202 | } | 1258 | } |
| ... | @@ -1228,5 +1284,5 @@ pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 { | ... | @@ -1228,5 +1284,5 @@ pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 { |
| 1228 | test "os.path.real" { | 1284 | test "os.path.real" { |
| 1229 | // at least call it so it gets compiled | 1285 | // at least call it so it gets compiled |
| 1230 | var buf: [os.MAX_PATH_BYTES]u8 = undefined; | 1286 | var buf: [os.MAX_PATH_BYTES]u8 = undefined; |
| 1231 | std.debug.assertError(real(&buf, "definitely_bogus_does_not_exist1234"), error.FileNotFound); | 1287 | testing.expectError(error.FileNotFound, real(&buf, "definitely_bogus_does_not_exist1234")); |
| 1232 | } | 1288 | } |
std/os/test.zig+28-8| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const os = std.os; | 2 | const os = std.os; |
| 3 | const assert = std.debug.assert; | 3 | const expect = std.testing.expect; |
| 4 | const io = std.io; | 4 | const io = std.io; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | 6 | ||
| ... | @@ -18,7 +18,7 @@ test "makePath, put some files in it, deleteTree" { | ... | @@ -18,7 +18,7 @@ test "makePath, put some files in it, deleteTree" { |
| 18 | if (os.Dir.open(a, "os_test_tmp")) |dir| { | 18 | if (os.Dir.open(a, "os_test_tmp")) |dir| { |
| 19 | @panic("expected error"); | 19 | @panic("expected error"); |
| 20 | } else |err| { | 20 | } else |err| { |
| 21 | assert(err == error.FileNotFound); | 21 | expect(err == error.FileNotFound); |
| 22 | } | 22 | } |
| 23 | } | 23 | } |
| 24 | 24 | ||
| ... | @@ -27,7 +27,7 @@ test "access file" { | ... | @@ -27,7 +27,7 @@ test "access file" { |
| 27 | if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| { | 27 | if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| { |
| 28 | @panic("expected error"); | 28 | @panic("expected error"); |
| 29 | } else |err| { | 29 | } else |err| { |
| 30 | assert(err == error.FileNotFound); | 30 | expect(err == error.FileNotFound); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", ""); | 33 | try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", ""); |
| ... | @@ -40,19 +40,23 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void { | ... | @@ -40,19 +40,23 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void { |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | test "std.os.Thread.getCurrentId" { | 42 | test "std.os.Thread.getCurrentId" { |
| 43 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 44 | |||
| 43 | var thread_current_id: os.Thread.Id = undefined; | 45 | var thread_current_id: os.Thread.Id = undefined; |
| 44 | const thread = try os.spawnThread(&thread_current_id, testThreadIdFn); | 46 | const thread = try os.spawnThread(&thread_current_id, testThreadIdFn); |
| 45 | const thread_id = thread.handle(); | 47 | const thread_id = thread.handle(); |
| 46 | thread.wait(); | 48 | thread.wait(); |
| 47 | switch (builtin.os) { | 49 | switch (builtin.os) { |
| 48 | builtin.Os.windows => assert(os.Thread.getCurrentId() != thread_current_id), | 50 | builtin.Os.windows => expect(os.Thread.getCurrentId() != thread_current_id), |
| 49 | else => { | 51 | else => { |
| 50 | assert(thread_current_id == thread_id); | 52 | expect(thread_current_id == thread_id); |
| 51 | }, | 53 | }, |
| 52 | } | 54 | } |
| 53 | } | 55 | } |
| 54 | 56 | ||
| 55 | test "spawn threads" { | 57 | test "spawn threads" { |
| 58 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 59 | |||
| 56 | var shared_ctx: i32 = 1; | 60 | var shared_ctx: i32 = 1; |
| 57 | 61 | ||
| 58 | const thread1 = try std.os.spawnThread({}, start1); | 62 | const thread1 = try std.os.spawnThread({}, start1); |
| ... | @@ -65,7 +69,7 @@ test "spawn threads" { | ... | @@ -65,7 +69,7 @@ test "spawn threads" { |
| 65 | thread3.wait(); | 69 | thread3.wait(); |
| 66 | thread4.wait(); | 70 | thread4.wait(); |
| 67 | 71 | ||
| 68 | assert(shared_ctx == 4); | 72 | expect(shared_ctx == 4); |
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | fn start1(ctx: void) u8 { | 75 | fn start1(ctx: void) u8 { |
| ... | @@ -79,7 +83,7 @@ fn start2(ctx: *i32) u8 { | ... | @@ -79,7 +83,7 @@ fn start2(ctx: *i32) u8 { |
| 79 | 83 | ||
| 80 | test "cpu count" { | 84 | test "cpu count" { |
| 81 | const cpu_count = try std.os.cpuCount(a); | 85 | const cpu_count = try std.os.cpuCount(a); |
| 82 | assert(cpu_count >= 1); | 86 | expect(cpu_count >= 1); |
| 83 | } | 87 | } |
| 84 | 88 | ||
| 85 | test "AtomicFile" { | 89 | test "AtomicFile" { |
| ... | @@ -97,7 +101,23 @@ test "AtomicFile" { | ... | @@ -97,7 +101,23 @@ test "AtomicFile" { |
| 97 | try af.finish(); | 101 | try af.finish(); |
| 98 | } | 102 | } |
| 99 | const content = try io.readFileAlloc(allocator, test_out_file); | 103 | const content = try io.readFileAlloc(allocator, test_out_file); |
| 100 | assert(mem.eql(u8, content, test_content)); | 104 | expect(mem.eql(u8, content, test_content)); |
| 101 | 105 | ||
| 102 | try os.deleteFile(test_out_file); | 106 | try os.deleteFile(test_out_file); |
| 103 | } | 107 | } |
| 108 | |||
| 109 | test "thread local storage" { | ||
| 110 | if (builtin.single_threaded) return error.SkipZigTest; | ||
| 111 | const thread1 = try std.os.spawnThread({}, testTls); | ||
| 112 | const thread2 = try std.os.spawnThread({}, testTls); | ||
| 113 | testTls({}); | ||
| 114 | thread1.wait(); | ||
| 115 | thread2.wait(); | ||
| 116 | } | ||
| 117 | |||
| 118 | threadlocal var x: i32 = 1234; | ||
| 119 | fn testTls(context: void) void { | ||
| 120 | if (x != 1234) @panic("bad start value"); | ||
| 121 | x += 1; | ||
| 122 | if (x != 1235) @panic("bad end value"); | ||
| 123 | } |
std/os/time.zig+13-14| ... | @@ -2,6 +2,7 @@ const std = @import("../index.zig"); | ... | @@ -2,6 +2,7 @@ const std = @import("../index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const Os = builtin.Os; | 3 | const Os = builtin.Os; |
| 4 | const debug = std.debug; | 4 | const debug = std.debug; |
| 5 | const testing = std.testing; | ||
| 5 | 6 | ||
| 6 | const windows = std.os.windows; | 7 | const windows = std.os.windows; |
| 7 | const linux = std.os.linux; | 8 | const linux = std.os.linux; |
| ... | @@ -13,7 +14,7 @@ pub const epoch = @import("epoch.zig"); | ... | @@ -13,7 +14,7 @@ pub const epoch = @import("epoch.zig"); |
| 13 | /// Sleep for the specified duration | 14 | /// Sleep for the specified duration |
| 14 | pub fn sleep(nanoseconds: u64) void { | 15 | pub fn sleep(nanoseconds: u64) void { |
| 15 | switch (builtin.os) { | 16 | switch (builtin.os) { |
| 16 | Os.linux, Os.macosx, Os.ios => { | 17 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 17 | const s = nanoseconds / ns_per_s; | 18 | const s = nanoseconds / ns_per_s; |
| 18 | const ns = nanoseconds % ns_per_s; | 19 | const ns = nanoseconds % ns_per_s; |
| 19 | posixSleep(@intCast(u63, s), @intCast(u63, ns)); | 20 | posixSleep(@intCast(u63, s), @intCast(u63, ns)); |
| ... | @@ -61,7 +62,7 @@ pub fn timestamp() u64 { | ... | @@ -61,7 +62,7 @@ pub fn timestamp() u64 { |
| 61 | /// Get the posix timestamp, UTC, in milliseconds | 62 | /// Get the posix timestamp, UTC, in milliseconds |
| 62 | pub const milliTimestamp = switch (builtin.os) { | 63 | pub const milliTimestamp = switch (builtin.os) { |
| 63 | Os.windows => milliTimestampWindows, | 64 | Os.windows => milliTimestampWindows, |
| 64 | Os.linux => milliTimestampPosix, | 65 | Os.linux, Os.freebsd => milliTimestampPosix, |
| 65 | Os.macosx, Os.ios => milliTimestampDarwin, | 66 | Os.macosx, Os.ios => milliTimestampDarwin, |
| 66 | else => @compileError("Unsupported OS"), | 67 | else => @compileError("Unsupported OS"), |
| 67 | }; | 68 | }; |
| ... | @@ -79,14 +80,12 @@ fn milliTimestampWindows() u64 { | ... | @@ -79,14 +80,12 @@ fn milliTimestampWindows() u64 { |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | fn milliTimestampDarwin() u64 { | 82 | fn milliTimestampDarwin() u64 { |
| 82 | //Sources suggest MacOS 10.12 has support for | ||
| 83 | // posix clock_gettime. | ||
| 84 | var tv: darwin.timeval = undefined; | 83 | var tv: darwin.timeval = undefined; |
| 85 | var err = darwin.gettimeofday(&tv, null); | 84 | var err = darwin.gettimeofday(&tv, null); |
| 86 | debug.assert(err == 0); | 85 | debug.assert(err == 0); |
| 87 | const sec_ms = @intCast(u64, tv.tv_sec) * ms_per_s; | 86 | const sec_ms = tv.tv_sec * ms_per_s; |
| 88 | const usec_ms = @divFloor(@intCast(u64, tv.tv_usec), us_per_s / ms_per_s); | 87 | const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s); |
| 89 | return u64(sec_ms) + u64(usec_ms); | 88 | return @intCast(u64, sec_ms + usec_ms); |
| 90 | } | 89 | } |
| 91 | 90 | ||
| 92 | fn milliTimestampPosix() u64 { | 91 | fn milliTimestampPosix() u64 { |
| ... | @@ -179,7 +178,7 @@ pub const Timer = struct { | ... | @@ -179,7 +178,7 @@ pub const Timer = struct { |
| 179 | debug.assert(err != windows.FALSE); | 178 | debug.assert(err != windows.FALSE); |
| 180 | self.start_time = @intCast(u64, start_time); | 179 | self.start_time = @intCast(u64, start_time); |
| 181 | }, | 180 | }, |
| 182 | Os.linux => { | 181 | Os.linux, Os.freebsd => { |
| 183 | //On Linux, seccomp can do arbitrary things to our ability to call | 182 | //On Linux, seccomp can do arbitrary things to our ability to call |
| 184 | // syscalls, including return any errno value it wants and | 183 | // syscalls, including return any errno value it wants and |
| 185 | // inconsistently throwing errors. Since we can't account for | 184 | // inconsistently throwing errors. Since we can't account for |
| ... | @@ -215,7 +214,7 @@ pub const Timer = struct { | ... | @@ -215,7 +214,7 @@ pub const Timer = struct { |
| 215 | var clock = clockNative() - self.start_time; | 214 | var clock = clockNative() - self.start_time; |
| 216 | return switch (builtin.os) { | 215 | return switch (builtin.os) { |
| 217 | Os.windows => @divFloor(clock * ns_per_s, self.frequency), | 216 | Os.windows => @divFloor(clock * ns_per_s, self.frequency), |
| 218 | Os.linux => clock, | 217 | Os.linux, Os.freebsd => clock, |
| 219 | Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom), | 218 | Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom), |
| 220 | else => @compileError("Unsupported OS"), | 219 | else => @compileError("Unsupported OS"), |
| 221 | }; | 220 | }; |
| ... | @@ -236,7 +235,7 @@ pub const Timer = struct { | ... | @@ -236,7 +235,7 @@ pub const Timer = struct { |
| 236 | 235 | ||
| 237 | const clockNative = switch (builtin.os) { | 236 | const clockNative = switch (builtin.os) { |
| 238 | Os.windows => clockWindows, | 237 | Os.windows => clockWindows, |
| 239 | Os.linux => clockLinux, | 238 | Os.linux, Os.freebsd => clockLinux, |
| 240 | Os.macosx, Os.ios => clockDarwin, | 239 | Os.macosx, Os.ios => clockDarwin, |
| 241 | else => @compileError("Unsupported OS"), | 240 | else => @compileError("Unsupported OS"), |
| 242 | }; | 241 | }; |
| ... | @@ -272,7 +271,7 @@ test "os.time.timestamp" { | ... | @@ -272,7 +271,7 @@ test "os.time.timestamp" { |
| 272 | sleep(ns_per_ms); | 271 | sleep(ns_per_ms); |
| 273 | const time_1 = milliTimestamp(); | 272 | const time_1 = milliTimestamp(); |
| 274 | const interval = time_1 - time_0; | 273 | const interval = time_1 - time_0; |
| 275 | debug.assert(interval > 0 and interval < margin); | 274 | testing.expect(interval > 0 and interval < margin); |
| 276 | } | 275 | } |
| 277 | 276 | ||
| 278 | test "os.time.Timer" { | 277 | test "os.time.Timer" { |
| ... | @@ -282,11 +281,11 @@ test "os.time.Timer" { | ... | @@ -282,11 +281,11 @@ test "os.time.Timer" { |
| 282 | var timer = try Timer.start(); | 281 | var timer = try Timer.start(); |
| 283 | sleep(10 * ns_per_ms); | 282 | sleep(10 * ns_per_ms); |
| 284 | const time_0 = timer.read(); | 283 | const time_0 = timer.read(); |
| 285 | debug.assert(time_0 > 0 and time_0 < margin); | 284 | testing.expect(time_0 > 0 and time_0 < margin); |
| 286 | 285 | ||
| 287 | const time_1 = timer.lap(); | 286 | const time_1 = timer.lap(); |
| 288 | debug.assert(time_1 >= time_0); | 287 | testing.expect(time_1 >= time_0); |
| 289 | 288 | ||
| 290 | timer.reset(); | 289 | timer.reset(); |
| 291 | debug.assert(timer.read() < time_1); | 290 | testing.expect(timer.read() < time_1); |
| 292 | } | 291 | } |
std/os/uefi.zig created+2| ... | @@ -0,0 +1,2 @@ | ||
| 1 | // TODO this is where the extern declarations go. For example, see | ||
| 2 | // inc/efilib.h in gnu-efi-code | ||
std/os/windows/index.zig+18| ... | @@ -49,6 +49,10 @@ pub const UNICODE = false; | ... | @@ -49,6 +49,10 @@ pub const UNICODE = false; |
| 49 | pub const WCHAR = u16; | 49 | pub const WCHAR = u16; |
| 50 | pub const WORD = u16; | 50 | pub const WORD = u16; |
| 51 | pub const LARGE_INTEGER = i64; | 51 | pub const LARGE_INTEGER = i64; |
| 52 | pub const ULONG = u32; | ||
| 53 | pub const LONG = i32; | ||
| 54 | pub const ULONGLONG = u64; | ||
| 55 | pub const LONGLONG = i64; | ||
| 52 | 56 | ||
| 53 | pub const TRUE = 1; | 57 | pub const TRUE = 1; |
| 54 | pub const FALSE = 0; | 58 | pub const FALSE = 0; |
| ... | @@ -379,3 +383,17 @@ pub const COORD = extern struct { | ... | @@ -379,3 +383,17 @@ pub const COORD = extern struct { |
| 379 | }; | 383 | }; |
| 380 | 384 | ||
| 381 | pub const CREATE_UNICODE_ENVIRONMENT = 1024; | 385 | pub const CREATE_UNICODE_ENVIRONMENT = 1024; |
| 386 | |||
| 387 | pub const TLS_OUT_OF_INDEXES = 4294967295; | ||
| 388 | pub const IMAGE_TLS_DIRECTORY = extern struct { | ||
| 389 | StartAddressOfRawData: usize, | ||
| 390 | EndAddressOfRawData: usize, | ||
| 391 | AddressOfIndex: usize, | ||
| 392 | AddressOfCallBacks: usize, | ||
| 393 | SizeOfZeroFill: u32, | ||
| 394 | Characteristics: u32, | ||
| 395 | }; | ||
| 396 | pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY; | ||
| 397 | pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY; | ||
| 398 | |||
| 399 | pub const PIMAGE_TLS_CALLBACK = ?extern fn(PVOID, DWORD, PVOID) void; |
std/os/windows/kernel32.zig+54-3| ... | @@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi | ... | @@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi |
| 50 | pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL; | 50 | pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL; |
| 51 | pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL; | 51 | pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL; |
| 52 | 52 | ||
| 53 | pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL; | 53 | pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL; |
| 54 | 54 | ||
| 55 | pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR; | 55 | pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR; |
| 56 | 56 | ||
| ... | @@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp | ... | @@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp |
| 63 | pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE; | 63 | pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE; |
| 64 | pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD; | 64 | pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD; |
| 65 | 65 | ||
| 66 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8; | 66 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16; |
| 67 | 67 | ||
| 68 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD; | 68 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD; |
| 69 | 69 | ||
| 70 | pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL; | 70 | pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL; |
| 71 | 71 | ||
| ... | @@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void; | ... | @@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void; |
| 164 | 164 | ||
| 165 | pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL; | 165 | pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL; |
| 166 | 166 | ||
| 167 | pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD; | ||
| 168 | |||
| 169 | pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL; | ||
| 170 | |||
| 167 | pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD; | 171 | pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD; |
| 168 | 172 | ||
| 169 | pub extern "kernel32" stdcallcc fn WriteFile( | 173 | pub extern "kernel32" stdcallcc fn WriteFile( |
| ... | @@ -220,3 +224,50 @@ pub const FOREGROUND_BLUE = 1; | ... | @@ -220,3 +224,50 @@ pub const FOREGROUND_BLUE = 1; |
| 220 | pub const FOREGROUND_GREEN = 2; | 224 | pub const FOREGROUND_GREEN = 2; |
| 221 | pub const FOREGROUND_RED = 4; | 225 | pub const FOREGROUND_RED = 4; |
| 222 | pub const FOREGROUND_INTENSITY = 8; | 226 | pub const FOREGROUND_INTENSITY = 8; |
| 227 | |||
| 228 | pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void; | ||
| 229 | pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void; | ||
| 230 | pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void; | ||
| 231 | pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void; | ||
| 232 | |||
| 233 | pub const LIST_ENTRY = extern struct { | ||
| 234 | Flink: *LIST_ENTRY, | ||
| 235 | Blink: *LIST_ENTRY, | ||
| 236 | }; | ||
| 237 | |||
| 238 | pub const RTL_CRITICAL_SECTION_DEBUG = extern struct { | ||
| 239 | Type: WORD, | ||
| 240 | CreatorBackTraceIndex: WORD, | ||
| 241 | CriticalSection: *RTL_CRITICAL_SECTION, | ||
| 242 | ProcessLocksList: LIST_ENTRY, | ||
| 243 | EntryCount: DWORD, | ||
| 244 | ContentionCount: DWORD, | ||
| 245 | Flags: DWORD, | ||
| 246 | CreatorBackTraceIndexHigh: WORD, | ||
| 247 | SpareWORD: WORD, | ||
| 248 | }; | ||
| 249 | |||
| 250 | pub const RTL_CRITICAL_SECTION = extern struct { | ||
| 251 | DebugInfo: *RTL_CRITICAL_SECTION_DEBUG, | ||
| 252 | LockCount: LONG, | ||
| 253 | RecursionCount: LONG, | ||
| 254 | OwningThread: HANDLE, | ||
| 255 | LockSemaphore: HANDLE, | ||
| 256 | SpinCount: ULONG_PTR, | ||
| 257 | }; | ||
| 258 | |||
| 259 | pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION; | ||
| 260 | pub const INIT_ONCE = RTL_RUN_ONCE; | ||
| 261 | pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT; | ||
| 262 | |||
| 263 | pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) BOOL; | ||
| 264 | |||
| 265 | pub const INIT_ONCE_FN = extern fn(InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) BOOL; | ||
| 266 | |||
| 267 | pub const RTL_RUN_ONCE = extern struct { | ||
| 268 | Ptr: ?*c_void, | ||
| 269 | }; | ||
| 270 | |||
| 271 | pub const RTL_RUN_ONCE_INIT = RTL_RUN_ONCE { | ||
| 272 | .Ptr = null, | ||
| 273 | }; |
std/os/windows/tls.zig created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | const std = @import("../../index.zig"); | ||
| 2 | |||
| 3 | export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; | ||
| 4 | export var _tls_start: u8 linksection(".tls") = 0; | ||
| 5 | export var _tls_end: u8 linksection(".tls$ZZZ") = 0; | ||
| 6 | export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; | ||
| 7 | export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; | ||
| 8 | |||
| 9 | // TODO this is how I would like it to be expressed | ||
| 10 | // TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate | ||
| 11 | // why they do that. | ||
| 12 | //export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY { | ||
| 13 | // .StartAddressOfRawData = @ptrToInt(&_tls_start), | ||
| 14 | // .EndAddressOfRawData = @ptrToInt(&_tls_end), | ||
| 15 | // .AddressOfIndex = @ptrToInt(&_tls_index), | ||
| 16 | // .AddressOfCallBacks = @ptrToInt(__xl_a), | ||
| 17 | // .SizeOfZeroFill = 0, | ||
| 18 | // .Characteristics = 0, | ||
| 19 | //}; | ||
| 20 | // This is the workaround because we can't do @ptrToInt at comptime like that. | ||
| 21 | pub const IMAGE_TLS_DIRECTORY = extern struct { | ||
| 22 | StartAddressOfRawData: *c_void, | ||
| 23 | EndAddressOfRawData: *c_void, | ||
| 24 | AddressOfIndex: *c_void, | ||
| 25 | AddressOfCallBacks: *c_void, | ||
| 26 | SizeOfZeroFill: u32, | ||
| 27 | Characteristics: u32, | ||
| 28 | }; | ||
| 29 | export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY { | ||
| 30 | .StartAddressOfRawData = &_tls_start, | ||
| 31 | .EndAddressOfRawData = &_tls_end, | ||
| 32 | .AddressOfIndex = &_tls_index, | ||
| 33 | .AddressOfCallBacks = &__xl_a, | ||
| 34 | .SizeOfZeroFill = 0, | ||
| 35 | .Characteristics = 0, | ||
| 36 | }; | ||
std/pdb.zig+15-3| ... | @@ -9,6 +9,10 @@ const coff = std.coff; | ... | @@ -9,6 +9,10 @@ const coff = std.coff; |
| 9 | 9 | ||
| 10 | const ArrayList = std.ArrayList; | 10 | const ArrayList = std.ArrayList; |
| 11 | 11 | ||
| 12 | // Note: most of this is based on information gathered from LLVM source code, | ||
| 13 | // documentation and/or contributors. | ||
| 14 | |||
| 15 | |||
| 12 | // https://llvm.org/docs/PDB/DbiStream.html#stream-header | 16 | // https://llvm.org/docs/PDB/DbiStream.html#stream-header |
| 13 | pub const DbiStreamHeader = packed struct { | 17 | pub const DbiStreamHeader = packed struct { |
| 14 | VersionSignature: i32, | 18 | VersionSignature: i32, |
| ... | @@ -345,6 +349,10 @@ pub const RecordPrefix = packed struct { | ... | @@ -345,6 +349,10 @@ pub const RecordPrefix = packed struct { |
| 345 | RecordKind: SymbolKind, | 349 | RecordKind: SymbolKind, |
| 346 | }; | 350 | }; |
| 347 | 351 | ||
| 352 | /// The following variable length array appears immediately after the header. | ||
| 353 | /// The structure definition follows. | ||
| 354 | /// LineBlockFragmentHeader Blocks[] | ||
| 355 | /// Each `LineBlockFragmentHeader` as specified below. | ||
| 348 | pub const LineFragmentHeader = packed struct { | 356 | pub const LineFragmentHeader = packed struct { |
| 349 | /// Code offset of line contribution. | 357 | /// Code offset of line contribution. |
| 350 | RelocOffset: u32, | 358 | RelocOffset: u32, |
| ... | @@ -386,7 +394,11 @@ pub const LineNumberEntry = packed struct { | ... | @@ -386,7 +394,11 @@ pub const LineNumberEntry = packed struct { |
| 386 | 394 | ||
| 387 | /// TODO runtime crash when I make the actual type of Flags this | 395 | /// TODO runtime crash when I make the actual type of Flags this |
| 388 | const Flags = packed struct { | 396 | const Flags = packed struct { |
| 397 | /// Start line number | ||
| 389 | Start: u24, | 398 | Start: u24, |
| 399 | |||
| 400 | /// Delta of lines to the end of the expression. Still unclear. | ||
| 401 | // TODO figure out the point of this field. | ||
| 390 | End: u7, | 402 | End: u7, |
| 391 | IsStatement: bool, | 403 | IsStatement: bool, |
| 392 | }; | 404 | }; |
| ... | @@ -508,11 +520,11 @@ const Msf = struct { | ... | @@ -508,11 +520,11 @@ const Msf = struct { |
| 508 | allocator, | 520 | allocator, |
| 509 | ); | 521 | ); |
| 510 | 522 | ||
| 511 | const stream_count = try self.directory.stream.readIntLe(u32); | 523 | const stream_count = try self.directory.stream.readIntLittle(u32); |
| 512 | 524 | ||
| 513 | const stream_sizes = try allocator.alloc(u32, stream_count); | 525 | const stream_sizes = try allocator.alloc(u32, stream_count); |
| 514 | for (stream_sizes) |*s| { | 526 | for (stream_sizes) |*s| { |
| 515 | const size = try self.directory.stream.readIntLe(u32); | 527 | const size = try self.directory.stream.readIntLittle(u32); |
| 516 | s.* = blockCountFromSize(size, superblock.BlockSize); | 528 | s.* = blockCountFromSize(size, superblock.BlockSize); |
| 517 | } | 529 | } |
| 518 | 530 | ||
| ... | @@ -603,7 +615,7 @@ const MsfStream = struct { | ... | @@ -603,7 +615,7 @@ const MsfStream = struct { |
| 603 | 615 | ||
| 604 | var i: u32 = 0; | 616 | var i: u32 = 0; |
| 605 | while (i < block_count) : (i += 1) { | 617 | while (i < block_count) : (i += 1) { |
| 606 | stream.blocks[i] = try in.readIntLe(u32); | 618 | stream.blocks[i] = try in.readIntLittle(u32); |
| 607 | } | 619 | } |
| 608 | 620 | ||
| 609 | return stream; | 621 | return stream; |
std/rand/index.zig+87-82| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | // ``` | 5 | // ``` |
| 6 | // var buf: [8]u8 = undefined; | 6 | // var buf: [8]u8 = undefined; |
| 7 | // try std.os.getRandomBytes(buf[0..]); | 7 | // try std.os.getRandomBytes(buf[0..]); |
| 8 | // const seed = mem.readIntLE(u64, buf[0..8]); | 8 | // const seed = mem.readIntSliceLittle(u64, buf[0..8]); |
| 9 | // | 9 | // |
| 10 | // var r = DefaultPrng.init(seed); | 10 | // var r = DefaultPrng.init(seed); |
| 11 | // | 11 | // |
| ... | @@ -17,6 +17,7 @@ | ... | @@ -17,6 +17,7 @@ |
| 17 | const std = @import("../index.zig"); | 17 | const std = @import("../index.zig"); |
| 18 | const builtin = @import("builtin"); | 18 | const builtin = @import("builtin"); |
| 19 | const assert = std.debug.assert; | 19 | const assert = std.debug.assert; |
| 20 | const expect = std.testing.expect; | ||
| 20 | const mem = std.mem; | 21 | const mem = std.mem; |
| 21 | const math = std.math; | 22 | const math = std.math; |
| 22 | const ziggurat = @import("ziggurat.zig"); | 23 | const ziggurat = @import("ziggurat.zig"); |
| ... | @@ -52,7 +53,7 @@ pub const Random = struct { | ... | @@ -52,7 +53,7 @@ pub const Random = struct { |
| 52 | // use LE instead of native endian for better portability maybe? | 53 | // use LE instead of native endian for better portability maybe? |
| 53 | // TODO: endian portability is pointless if the underlying prng isn't endian portable. | 54 | // TODO: endian portability is pointless if the underlying prng isn't endian portable. |
| 54 | // TODO: document the endian portability of this library. | 55 | // TODO: document the endian portability of this library. |
| 55 | const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes); | 56 | const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes); |
| 56 | const unsigned_result = @truncate(UnsignedT, byte_aligned_result); | 57 | const unsigned_result = @truncate(UnsignedT, byte_aligned_result); |
| 57 | return @bitCast(T, unsigned_result); | 58 | return @bitCast(T, unsigned_result); |
| 58 | } | 59 | } |
| ... | @@ -69,6 +70,7 @@ pub const Random = struct { | ... | @@ -69,6 +70,7 @@ pub const Random = struct { |
| 69 | return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than)); | 70 | return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than)); |
| 70 | } | 71 | } |
| 71 | } | 72 | } |
| 73 | |||
| 72 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. | 74 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. |
| 73 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. | 75 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. |
| 74 | /// Within this assumption, the runtime of this function is exponentially distributed. | 76 | /// Within this assumption, the runtime of this function is exponentially distributed. |
| ... | @@ -123,6 +125,7 @@ pub const Random = struct { | ... | @@ -123,6 +125,7 @@ pub const Random = struct { |
| 123 | } | 125 | } |
| 124 | return r.uintLessThanBiased(T, at_most + 1); | 126 | return r.uintLessThanBiased(T, at_most + 1); |
| 125 | } | 127 | } |
| 128 | |||
| 126 | /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. | 129 | /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. |
| 127 | /// See ::uintLessThan, which this function uses in most cases, | 130 | /// See ::uintLessThan, which this function uses in most cases, |
| 128 | /// for commentary on the runtime of this function. | 131 | /// for commentary on the runtime of this function. |
| ... | @@ -151,6 +154,7 @@ pub const Random = struct { | ... | @@ -151,6 +154,7 @@ pub const Random = struct { |
| 151 | return at_least + r.uintLessThanBiased(T, less_than - at_least); | 154 | return at_least + r.uintLessThanBiased(T, less_than - at_least); |
| 152 | } | 155 | } |
| 153 | } | 156 | } |
| 157 | |||
| 154 | /// Returns an evenly distributed random integer `at_least <= i < less_than`. | 158 | /// Returns an evenly distributed random integer `at_least <= i < less_than`. |
| 155 | /// See ::uintLessThan, which this function uses in most cases, | 159 | /// See ::uintLessThan, which this function uses in most cases, |
| 156 | /// for commentary on the runtime of this function. | 160 | /// for commentary on the runtime of this function. |
| ... | @@ -185,6 +189,7 @@ pub const Random = struct { | ... | @@ -185,6 +189,7 @@ pub const Random = struct { |
| 185 | return at_least + r.uintAtMostBiased(T, at_most - at_least); | 189 | return at_least + r.uintAtMostBiased(T, at_most - at_least); |
| 186 | } | 190 | } |
| 187 | } | 191 | } |
| 192 | |||
| 188 | /// Returns an evenly distributed random integer `at_least <= i <= at_most`. | 193 | /// Returns an evenly distributed random integer `at_least <= i <= at_most`. |
| 189 | /// See ::uintLessThan, which this function uses in most cases, | 194 | /// See ::uintLessThan, which this function uses in most cases, |
| 190 | /// for commentary on the runtime of this function. | 195 | /// for commentary on the runtime of this function. |
| ... | @@ -312,43 +317,43 @@ test "Random int" { | ... | @@ -312,43 +317,43 @@ test "Random int" { |
| 312 | fn testRandomInt() void { | 317 | fn testRandomInt() void { |
| 313 | var r = SequentialPrng.init(); | 318 | var r = SequentialPrng.init(); |
| 314 | 319 | ||
| 315 | assert(r.random.int(u0) == 0); | 320 | expect(r.random.int(u0) == 0); |
| 316 | 321 | ||
| 317 | r.next_value = 0; | 322 | r.next_value = 0; |
| 318 | assert(r.random.int(u1) == 0); | 323 | expect(r.random.int(u1) == 0); |
| 319 | assert(r.random.int(u1) == 1); | 324 | expect(r.random.int(u1) == 1); |
| 320 | assert(r.random.int(u2) == 2); | 325 | expect(r.random.int(u2) == 2); |
| 321 | assert(r.random.int(u2) == 3); | 326 | expect(r.random.int(u2) == 3); |
| 322 | assert(r.random.int(u2) == 0); | 327 | expect(r.random.int(u2) == 0); |
| 323 | 328 | ||
| 324 | r.next_value = 0xff; | 329 | r.next_value = 0xff; |
| 325 | assert(r.random.int(u8) == 0xff); | 330 | expect(r.random.int(u8) == 0xff); |
| 326 | r.next_value = 0x11; | 331 | r.next_value = 0x11; |
| 327 | assert(r.random.int(u8) == 0x11); | 332 | expect(r.random.int(u8) == 0x11); |
| 328 | 333 | ||
| 329 | r.next_value = 0xff; | 334 | r.next_value = 0xff; |
| 330 | assert(r.random.int(u32) == 0xffffffff); | 335 | expect(r.random.int(u32) == 0xffffffff); |
| 331 | r.next_value = 0x11; | 336 | r.next_value = 0x11; |
| 332 | assert(r.random.int(u32) == 0x11111111); | 337 | expect(r.random.int(u32) == 0x11111111); |
| 333 | 338 | ||
| 334 | r.next_value = 0xff; | 339 | r.next_value = 0xff; |
| 335 | assert(r.random.int(i32) == -1); | 340 | expect(r.random.int(i32) == -1); |
| 336 | r.next_value = 0x11; | 341 | r.next_value = 0x11; |
| 337 | assert(r.random.int(i32) == 0x11111111); | 342 | expect(r.random.int(i32) == 0x11111111); |
| 338 | 343 | ||
| 339 | r.next_value = 0xff; | 344 | r.next_value = 0xff; |
| 340 | assert(r.random.int(i8) == -1); | 345 | expect(r.random.int(i8) == -1); |
| 341 | r.next_value = 0x11; | 346 | r.next_value = 0x11; |
| 342 | assert(r.random.int(i8) == 0x11); | 347 | expect(r.random.int(i8) == 0x11); |
| 343 | 348 | ||
| 344 | r.next_value = 0xff; | 349 | r.next_value = 0xff; |
| 345 | assert(r.random.int(u33) == 0x1ffffffff); | 350 | expect(r.random.int(u33) == 0x1ffffffff); |
| 346 | r.next_value = 0xff; | 351 | r.next_value = 0xff; |
| 347 | assert(r.random.int(i1) == -1); | 352 | expect(r.random.int(i1) == -1); |
| 348 | r.next_value = 0xff; | 353 | r.next_value = 0xff; |
| 349 | assert(r.random.int(i2) == -1); | 354 | expect(r.random.int(i2) == -1); |
| 350 | r.next_value = 0xff; | 355 | r.next_value = 0xff; |
| 351 | assert(r.random.int(i33) == -1); | 356 | expect(r.random.int(i33) == -1); |
| 352 | } | 357 | } |
| 353 | 358 | ||
| 354 | test "Random boolean" { | 359 | test "Random boolean" { |
| ... | @@ -357,10 +362,10 @@ test "Random boolean" { | ... | @@ -357,10 +362,10 @@ test "Random boolean" { |
| 357 | } | 362 | } |
| 358 | fn testRandomBoolean() void { | 363 | fn testRandomBoolean() void { |
| 359 | var r = SequentialPrng.init(); | 364 | var r = SequentialPrng.init(); |
| 360 | assert(r.random.boolean() == false); | 365 | expect(r.random.boolean() == false); |
| 361 | assert(r.random.boolean() == true); | 366 | expect(r.random.boolean() == true); |
| 362 | assert(r.random.boolean() == false); | 367 | expect(r.random.boolean() == false); |
| 363 | assert(r.random.boolean() == true); | 368 | expect(r.random.boolean() == true); |
| 364 | } | 369 | } |
| 365 | 370 | ||
| 366 | test "Random intLessThan" { | 371 | test "Random intLessThan" { |
| ... | @@ -371,36 +376,36 @@ test "Random intLessThan" { | ... | @@ -371,36 +376,36 @@ test "Random intLessThan" { |
| 371 | fn testRandomIntLessThan() void { | 376 | fn testRandomIntLessThan() void { |
| 372 | var r = SequentialPrng.init(); | 377 | var r = SequentialPrng.init(); |
| 373 | r.next_value = 0xff; | 378 | r.next_value = 0xff; |
| 374 | assert(r.random.uintLessThan(u8, 4) == 3); | 379 | expect(r.random.uintLessThan(u8, 4) == 3); |
| 375 | assert(r.next_value == 0); | 380 | expect(r.next_value == 0); |
| 376 | assert(r.random.uintLessThan(u8, 4) == 0); | 381 | expect(r.random.uintLessThan(u8, 4) == 0); |
| 377 | assert(r.next_value == 1); | 382 | expect(r.next_value == 1); |
| 378 | 383 | ||
| 379 | r.next_value = 0; | 384 | r.next_value = 0; |
| 380 | assert(r.random.uintLessThan(u64, 32) == 0); | 385 | expect(r.random.uintLessThan(u64, 32) == 0); |
| 381 | 386 | ||
| 382 | // trigger the bias rejection code path | 387 | // trigger the bias rejection code path |
| 383 | r.next_value = 0; | 388 | r.next_value = 0; |
| 384 | assert(r.random.uintLessThan(u8, 3) == 0); | 389 | expect(r.random.uintLessThan(u8, 3) == 0); |
| 385 | // verify we incremented twice | 390 | // verify we incremented twice |
| 386 | assert(r.next_value == 2); | 391 | expect(r.next_value == 2); |
| 387 | 392 | ||
| 388 | r.next_value = 0xff; | 393 | r.next_value = 0xff; |
| 389 | assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f); | 394 | expect(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f); |
| 390 | r.next_value = 0xff; | 395 | r.next_value = 0xff; |
| 391 | assert(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe); | 396 | expect(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe); |
| 392 | 397 | ||
| 393 | r.next_value = 0xff; | 398 | r.next_value = 0xff; |
| 394 | assert(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f); | 399 | expect(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f); |
| 395 | r.next_value = 0xff; | 400 | r.next_value = 0xff; |
| 396 | assert(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f); | 401 | expect(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f); |
| 397 | r.next_value = 0xff; | 402 | r.next_value = 0xff; |
| 398 | assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1); | 403 | expect(r.random.intRangeLessThan(i8, -0x80, 0) == -1); |
| 399 | 404 | ||
| 400 | r.next_value = 0xff; | 405 | r.next_value = 0xff; |
| 401 | assert(r.random.intRangeLessThan(i3, -4, 0) == -1); | 406 | expect(r.random.intRangeLessThan(i3, -4, 0) == -1); |
| 402 | r.next_value = 0xff; | 407 | r.next_value = 0xff; |
| 403 | assert(r.random.intRangeLessThan(i3, -2, 2) == 1); | 408 | expect(r.random.intRangeLessThan(i3, -2, 2) == 1); |
| 404 | } | 409 | } |
| 405 | 410 | ||
| 406 | test "Random intAtMost" { | 411 | test "Random intAtMost" { |
| ... | @@ -411,34 +416,34 @@ test "Random intAtMost" { | ... | @@ -411,34 +416,34 @@ test "Random intAtMost" { |
| 411 | fn testRandomIntAtMost() void { | 416 | fn testRandomIntAtMost() void { |
| 412 | var r = SequentialPrng.init(); | 417 | var r = SequentialPrng.init(); |
| 413 | r.next_value = 0xff; | 418 | r.next_value = 0xff; |
| 414 | assert(r.random.uintAtMost(u8, 3) == 3); | 419 | expect(r.random.uintAtMost(u8, 3) == 3); |
| 415 | assert(r.next_value == 0); | 420 | expect(r.next_value == 0); |
| 416 | assert(r.random.uintAtMost(u8, 3) == 0); | 421 | expect(r.random.uintAtMost(u8, 3) == 0); |
| 417 | 422 | ||
| 418 | // trigger the bias rejection code path | 423 | // trigger the bias rejection code path |
| 419 | r.next_value = 0; | 424 | r.next_value = 0; |
| 420 | assert(r.random.uintAtMost(u8, 2) == 0); | 425 | expect(r.random.uintAtMost(u8, 2) == 0); |
| 421 | // verify we incremented twice | 426 | // verify we incremented twice |
| 422 | assert(r.next_value == 2); | 427 | expect(r.next_value == 2); |
| 423 | 428 | ||
| 424 | r.next_value = 0xff; | 429 | r.next_value = 0xff; |
| 425 | assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f); | 430 | expect(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f); |
| 426 | r.next_value = 0xff; | 431 | r.next_value = 0xff; |
| 427 | assert(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe); | 432 | expect(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe); |
| 428 | 433 | ||
| 429 | r.next_value = 0xff; | 434 | r.next_value = 0xff; |
| 430 | assert(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f); | 435 | expect(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f); |
| 431 | r.next_value = 0xff; | 436 | r.next_value = 0xff; |
| 432 | assert(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f); | 437 | expect(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f); |
| 433 | r.next_value = 0xff; | 438 | r.next_value = 0xff; |
| 434 | assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1); | 439 | expect(r.random.intRangeAtMost(i8, -0x80, -1) == -1); |
| 435 | 440 | ||
| 436 | r.next_value = 0xff; | 441 | r.next_value = 0xff; |
| 437 | assert(r.random.intRangeAtMost(i3, -4, -1) == -1); | 442 | expect(r.random.intRangeAtMost(i3, -4, -1) == -1); |
| 438 | r.next_value = 0xff; | 443 | r.next_value = 0xff; |
| 439 | assert(r.random.intRangeAtMost(i3, -2, 1) == 1); | 444 | expect(r.random.intRangeAtMost(i3, -2, 1) == 1); |
| 440 | 445 | ||
| 441 | assert(r.random.uintAtMost(u0, 0) == 0); | 446 | expect(r.random.uintAtMost(u0, 0) == 0); |
| 442 | } | 447 | } |
| 443 | 448 | ||
| 444 | test "Random Biased" { | 449 | test "Random Biased" { |
| ... | @@ -446,30 +451,30 @@ test "Random Biased" { | ... | @@ -446,30 +451,30 @@ test "Random Biased" { |
| 446 | // Not thoroughly checking the logic here. | 451 | // Not thoroughly checking the logic here. |
| 447 | // Just want to execute all the paths with different types. | 452 | // Just want to execute all the paths with different types. |
| 448 | 453 | ||
| 449 | assert(r.random.uintLessThanBiased(u1, 1) == 0); | 454 | expect(r.random.uintLessThanBiased(u1, 1) == 0); |
| 450 | assert(r.random.uintLessThanBiased(u32, 10) < 10); | 455 | expect(r.random.uintLessThanBiased(u32, 10) < 10); |
| 451 | assert(r.random.uintLessThanBiased(u64, 20) < 20); | 456 | expect(r.random.uintLessThanBiased(u64, 20) < 20); |
| 452 | 457 | ||
| 453 | assert(r.random.uintAtMostBiased(u0, 0) == 0); | 458 | expect(r.random.uintAtMostBiased(u0, 0) == 0); |
| 454 | assert(r.random.uintAtMostBiased(u1, 0) <= 0); | 459 | expect(r.random.uintAtMostBiased(u1, 0) <= 0); |
| 455 | assert(r.random.uintAtMostBiased(u32, 10) <= 10); | 460 | expect(r.random.uintAtMostBiased(u32, 10) <= 10); |
| 456 | assert(r.random.uintAtMostBiased(u64, 20) <= 20); | 461 | expect(r.random.uintAtMostBiased(u64, 20) <= 20); |
| 457 | 462 | ||
| 458 | assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0); | 463 | expect(r.random.intRangeLessThanBiased(u1, 0, 1) == 0); |
| 459 | assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1); | 464 | expect(r.random.intRangeLessThanBiased(i1, -1, 0) == -1); |
| 460 | assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10); | 465 | expect(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10); |
| 461 | assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10); | 466 | expect(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10); |
| 462 | assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20); | 467 | expect(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20); |
| 463 | assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20); | 468 | expect(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20); |
| 464 | 469 | ||
| 465 | // uncomment for broken module error: | 470 | // uncomment for broken module error: |
| 466 | //assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0); | 471 | //expect(r.random.intRangeAtMostBiased(u0, 0, 0) == 0); |
| 467 | assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0); | 472 | expect(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0); |
| 468 | assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1); | 473 | expect(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1); |
| 469 | assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10); | 474 | expect(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10); |
| 470 | assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10); | 475 | expect(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10); |
| 471 | assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20); | 476 | expect(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20); |
| 472 | assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20); | 477 | expect(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20); |
| 473 | } | 478 | } |
| 474 | 479 | ||
| 475 | // Generator to extend 64-bit seed values into longer sequences. | 480 | // Generator to extend 64-bit seed values into longer sequences. |
| ... | @@ -506,7 +511,7 @@ test "splitmix64 sequence" { | ... | @@ -506,7 +511,7 @@ test "splitmix64 sequence" { |
| 506 | }; | 511 | }; |
| 507 | 512 | ||
| 508 | for (seq) |s| { | 513 | for (seq) |s| { |
| 509 | std.debug.assert(s == r.next()); | 514 | expect(s == r.next()); |
| 510 | } | 515 | } |
| 511 | } | 516 | } |
| 512 | 517 | ||
| ... | @@ -599,7 +604,7 @@ test "pcg sequence" { | ... | @@ -599,7 +604,7 @@ test "pcg sequence" { |
| 599 | }; | 604 | }; |
| 600 | 605 | ||
| 601 | for (seq) |s| { | 606 | for (seq) |s| { |
| 602 | std.debug.assert(s == r.next()); | 607 | expect(s == r.next()); |
| 603 | } | 608 | } |
| 604 | } | 609 | } |
| 605 | 610 | ||
| ... | @@ -708,7 +713,7 @@ test "xoroshiro sequence" { | ... | @@ -708,7 +713,7 @@ test "xoroshiro sequence" { |
| 708 | }; | 713 | }; |
| 709 | 714 | ||
| 710 | for (seq1) |s| { | 715 | for (seq1) |s| { |
| 711 | std.debug.assert(s == r.next()); | 716 | expect(s == r.next()); |
| 712 | } | 717 | } |
| 713 | 718 | ||
| 714 | r.jump(); | 719 | r.jump(); |
| ... | @@ -723,7 +728,7 @@ test "xoroshiro sequence" { | ... | @@ -723,7 +728,7 @@ test "xoroshiro sequence" { |
| 723 | }; | 728 | }; |
| 724 | 729 | ||
| 725 | for (seq2) |s| { | 730 | for (seq2) |s| { |
| 726 | std.debug.assert(s == r.next()); | 731 | expect(s == r.next()); |
| 727 | } | 732 | } |
| 728 | } | 733 | } |
| 729 | 734 | ||
| ... | @@ -926,7 +931,7 @@ test "isaac64 sequence" { | ... | @@ -926,7 +931,7 @@ test "isaac64 sequence" { |
| 926 | }; | 931 | }; |
| 927 | 932 | ||
| 928 | for (seq) |s| { | 933 | for (seq) |s| { |
| 929 | std.debug.assert(s == r.next()); | 934 | expect(s == r.next()); |
| 930 | } | 935 | } |
| 931 | } | 936 | } |
| 932 | 937 | ||
| ... | @@ -937,12 +942,12 @@ test "Random float" { | ... | @@ -937,12 +942,12 @@ test "Random float" { |
| 937 | var i: usize = 0; | 942 | var i: usize = 0; |
| 938 | while (i < 1000) : (i += 1) { | 943 | while (i < 1000) : (i += 1) { |
| 939 | const val1 = prng.random.float(f32); | 944 | const val1 = prng.random.float(f32); |
| 940 | std.debug.assert(val1 >= 0.0); | 945 | expect(val1 >= 0.0); |
| 941 | std.debug.assert(val1 < 1.0); | 946 | expect(val1 < 1.0); |
| 942 | 947 | ||
| 943 | const val2 = prng.random.float(f64); | 948 | const val2 = prng.random.float(f64); |
| 944 | std.debug.assert(val2 >= 0.0); | 949 | expect(val2 >= 0.0); |
| 945 | std.debug.assert(val2 < 1.0); | 950 | expect(val2 < 1.0); |
| 946 | } | 951 | } |
| 947 | } | 952 | } |
| 948 | 953 | ||
| ... | @@ -956,12 +961,12 @@ test "Random shuffle" { | ... | @@ -956,12 +961,12 @@ test "Random shuffle" { |
| 956 | while (i < 1000) : (i += 1) { | 961 | while (i < 1000) : (i += 1) { |
| 957 | prng.random.shuffle(u8, seq[0..]); | 962 | prng.random.shuffle(u8, seq[0..]); |
| 958 | seen[seq[0]] = true; | 963 | seen[seq[0]] = true; |
| 959 | std.debug.assert(sumArray(seq[0..]) == 10); | 964 | expect(sumArray(seq[0..]) == 10); |
| 960 | } | 965 | } |
| 961 | 966 | ||
| 962 | // we should see every entry at the head at least once | 967 | // we should see every entry at the head at least once |
| 963 | for (seen) |e| { | 968 | for (seen) |e| { |
| 964 | std.debug.assert(e == true); | 969 | expect(e == true); |
| 965 | } | 970 | } |
| 966 | } | 971 | } |
| 967 | 972 |
std/rb.zig+3-2| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | ||
| 3 | const mem = std.mem; // For mem.Compare | 4 | const mem = std.mem; // For mem.Compare |
| 4 | 5 | ||
| 5 | const Color = enum(u1) { | 6 | const Color = enum(u1) { |
| ... | @@ -533,13 +534,13 @@ test "rb" { | ... | @@ -533,13 +534,13 @@ test "rb" { |
| 533 | _ = tree.insert(&ns[8].node); | 534 | _ = tree.insert(&ns[8].node); |
| 534 | _ = tree.insert(&ns[9].node); | 535 | _ = tree.insert(&ns[9].node); |
| 535 | tree.remove(&ns[3].node); | 536 | tree.remove(&ns[3].node); |
| 536 | assert(tree.insert(&dup.node) == &ns[7].node); | 537 | testing.expect(tree.insert(&dup.node) == &ns[7].node); |
| 537 | try tree.replace(&ns[7].node, &dup.node); | 538 | try tree.replace(&ns[7].node, &dup.node); |
| 538 | 539 | ||
| 539 | var num: *testNumber = undefined; | 540 | var num: *testNumber = undefined; |
| 540 | num = testGetNumber(tree.first().?); | 541 | num = testGetNumber(tree.first().?); |
| 541 | while (num.node.next() != null) { | 542 | while (num.node.next() != null) { |
| 542 | assert(testGetNumber(num.node.next().?).value > num.value); | 543 | testing.expect(testGetNumber(num.node.next().?).value > num.value); |
| 543 | num = testGetNumber(num.node.next().?); | 544 | num = testGetNumber(num.node.next().?); |
| 544 | } | 545 | } |
| 545 | } | 546 | } |
std/segmented_list.zig+16-15| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | ||
| 3 | const Allocator = std.mem.Allocator; | 4 | const Allocator = std.mem.Allocator; |
| 4 | 5 | ||
| 5 | // Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box | 6 | // Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box |
| ... | @@ -352,14 +353,14 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { | ... | @@ -352,14 +353,14 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { |
| 352 | var i: usize = 0; | 353 | var i: usize = 0; |
| 353 | while (i < 100) : (i += 1) { | 354 | while (i < 100) : (i += 1) { |
| 354 | try list.push(@intCast(i32, i + 1)); | 355 | try list.push(@intCast(i32, i + 1)); |
| 355 | assert(list.len == i + 1); | 356 | testing.expect(list.len == i + 1); |
| 356 | } | 357 | } |
| 357 | } | 358 | } |
| 358 | 359 | ||
| 359 | { | 360 | { |
| 360 | var i: usize = 0; | 361 | var i: usize = 0; |
| 361 | while (i < 100) : (i += 1) { | 362 | while (i < 100) : (i += 1) { |
| 362 | assert(list.at(i).* == @intCast(i32, i + 1)); | 363 | testing.expect(list.at(i).* == @intCast(i32, i + 1)); |
| 363 | } | 364 | } |
| 364 | } | 365 | } |
| 365 | 366 | ||
| ... | @@ -368,35 +369,35 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { | ... | @@ -368,35 +369,35 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { |
| 368 | var x: i32 = 0; | 369 | var x: i32 = 0; |
| 369 | while (it.next()) |item| { | 370 | while (it.next()) |item| { |
| 370 | x += 1; | 371 | x += 1; |
| 371 | assert(item.* == x); | 372 | testing.expect(item.* == x); |
| 372 | } | 373 | } |
| 373 | assert(x == 100); | 374 | testing.expect(x == 100); |
| 374 | while (it.prev()) |item| : (x -= 1) { | 375 | while (it.prev()) |item| : (x -= 1) { |
| 375 | assert(item.* == x); | 376 | testing.expect(item.* == x); |
| 376 | } | 377 | } |
| 377 | assert(x == 0); | 378 | testing.expect(x == 0); |
| 378 | } | 379 | } |
| 379 | 380 | ||
| 380 | assert(list.pop().? == 100); | 381 | testing.expect(list.pop().? == 100); |
| 381 | assert(list.len == 99); | 382 | testing.expect(list.len == 99); |
| 382 | 383 | ||
| 383 | try list.pushMany([]i32{ | 384 | try list.pushMany([]i32{ |
| 384 | 1, | 385 | 1, |
| 385 | 2, | 386 | 2, |
| 386 | 3, | 387 | 3, |
| 387 | }); | 388 | }); |
| 388 | assert(list.len == 102); | 389 | testing.expect(list.len == 102); |
| 389 | assert(list.pop().? == 3); | 390 | testing.expect(list.pop().? == 3); |
| 390 | assert(list.pop().? == 2); | 391 | testing.expect(list.pop().? == 2); |
| 391 | assert(list.pop().? == 1); | 392 | testing.expect(list.pop().? == 1); |
| 392 | assert(list.len == 99); | 393 | testing.expect(list.len == 99); |
| 393 | 394 | ||
| 394 | try list.pushMany([]const i32{}); | 395 | try list.pushMany([]const i32{}); |
| 395 | assert(list.len == 99); | 396 | testing.expect(list.len == 99); |
| 396 | 397 | ||
| 397 | var i: i32 = 99; | 398 | var i: i32 = 99; |
| 398 | while (list.pop()) |item| : (i -= 1) { | 399 | while (list.pop()) |item| : (i -= 1) { |
| 399 | assert(item == i); | 400 | testing.expect(item == i); |
| 400 | list.shrinkCapacity(list.len); | 401 | list.shrinkCapacity(list.len); |
| 401 | } | 402 | } |
| 402 | } | 403 | } |
std/sort.zig+9-8| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("index.zig"); | 1 | const std = @import("index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | ||
| 3 | const mem = std.mem; | 4 | const mem = std.mem; |
| 4 | const math = std.math; | 5 | const math = std.math; |
| 5 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| ... | @@ -1031,8 +1032,8 @@ fn testStableSort() void { | ... | @@ -1031,8 +1032,8 @@ fn testStableSort() void { |
| 1031 | for (cases) |*case| { | 1032 | for (cases) |*case| { |
| 1032 | insertionSort(IdAndValue, (case.*)[0..], cmpByValue); | 1033 | insertionSort(IdAndValue, (case.*)[0..], cmpByValue); |
| 1033 | for (case.*) |item, i| { | 1034 | for (case.*) |item, i| { |
| 1034 | assert(item.id == expected[i].id); | 1035 | testing.expect(item.id == expected[i].id); |
| 1035 | assert(item.value == expected[i].value); | 1036 | testing.expect(item.value == expected[i].value); |
| 1036 | } | 1037 | } |
| 1037 | } | 1038 | } |
| 1038 | } | 1039 | } |
| ... | @@ -1077,7 +1078,7 @@ test "std.sort" { | ... | @@ -1077,7 +1078,7 @@ test "std.sort" { |
| 1077 | const slice = buf[0..case[0].len]; | 1078 | const slice = buf[0..case[0].len]; |
| 1078 | mem.copy(u8, slice, case[0]); | 1079 | mem.copy(u8, slice, case[0]); |
| 1079 | sort(u8, slice, asc(u8)); | 1080 | sort(u8, slice, asc(u8)); |
| 1080 | assert(mem.eql(u8, slice, case[1])); | 1081 | testing.expect(mem.eql(u8, slice, case[1])); |
| 1081 | } | 1082 | } |
| 1082 | 1083 | ||
| 1083 | const i32cases = [][]const []const i32{ | 1084 | const i32cases = [][]const []const i32{ |
| ... | @@ -1112,7 +1113,7 @@ test "std.sort" { | ... | @@ -1112,7 +1113,7 @@ test "std.sort" { |
| 1112 | const slice = buf[0..case[0].len]; | 1113 | const slice = buf[0..case[0].len]; |
| 1113 | mem.copy(i32, slice, case[0]); | 1114 | mem.copy(i32, slice, case[0]); |
| 1114 | sort(i32, slice, asc(i32)); | 1115 | sort(i32, slice, asc(i32)); |
| 1115 | assert(mem.eql(i32, slice, case[1])); | 1116 | testing.expect(mem.eql(i32, slice, case[1])); |
| 1116 | } | 1117 | } |
| 1117 | } | 1118 | } |
| 1118 | 1119 | ||
| ... | @@ -1149,7 +1150,7 @@ test "std.sort descending" { | ... | @@ -1149,7 +1150,7 @@ test "std.sort descending" { |
| 1149 | const slice = buf[0..case[0].len]; | 1150 | const slice = buf[0..case[0].len]; |
| 1150 | mem.copy(i32, slice, case[0]); | 1151 | mem.copy(i32, slice, case[0]); |
| 1151 | sort(i32, slice, desc(i32)); | 1152 | sort(i32, slice, desc(i32)); |
| 1152 | assert(mem.eql(i32, slice, case[1])); | 1153 | testing.expect(mem.eql(i32, slice, case[1])); |
| 1153 | } | 1154 | } |
| 1154 | } | 1155 | } |
| 1155 | 1156 | ||
| ... | @@ -1157,7 +1158,7 @@ test "another sort case" { | ... | @@ -1157,7 +1158,7 @@ test "another sort case" { |
| 1157 | var arr = []i32{ 5, 3, 1, 2, 4 }; | 1158 | var arr = []i32{ 5, 3, 1, 2, 4 }; |
| 1158 | sort(i32, arr[0..], asc(i32)); | 1159 | sort(i32, arr[0..], asc(i32)); |
| 1159 | 1160 | ||
| 1160 | assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 })); | 1161 | testing.expect(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 })); |
| 1161 | } | 1162 | } |
| 1162 | 1163 | ||
| 1163 | test "sort fuzz testing" { | 1164 | test "sort fuzz testing" { |
| ... | @@ -1185,9 +1186,9 @@ fn fuzzTest(rng: *std.rand.Random) void { | ... | @@ -1185,9 +1186,9 @@ fn fuzzTest(rng: *std.rand.Random) void { |
| 1185 | var index: usize = 1; | 1186 | var index: usize = 1; |
| 1186 | while (index < array.len) : (index += 1) { | 1187 | while (index < array.len) : (index += 1) { |
| 1187 | if (array[index].value == array[index - 1].value) { | 1188 | if (array[index].value == array[index - 1].value) { |
| 1188 | assert(array[index].id > array[index - 1].id); | 1189 | testing.expect(array[index].id > array[index - 1].id); |
| 1189 | } else { | 1190 | } else { |
| 1190 | assert(array[index].value > array[index - 1].value); | 1191 | testing.expect(array[index].value > array[index - 1].value); |
| 1191 | } | 1192 | } |
| 1192 | } | 1193 | } |
| 1193 | } | 1194 | } |
std/special/bootstrap.zig+63-15| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | const root = @import("@root"); | 4 | const root = @import("@root"); |
| 5 | const std = @import("std"); | 5 | const std = @import("std"); |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const assert = std.debug.assert; | ||
| 7 | 8 | ||
| 8 | var argc_ptr: [*]usize = undefined; | 9 | var argc_ptr: [*]usize = undefined; |
| 9 | 10 | ||
| ... | @@ -20,17 +21,10 @@ comptime { | ... | @@ -20,17 +21,10 @@ comptime { |
| 20 | 21 | ||
| 21 | nakedcc fn _start() noreturn { | 22 | nakedcc fn _start() noreturn { |
| 22 | switch (builtin.arch) { | 23 | switch (builtin.arch) { |
| 23 | builtin.Arch.x86_64 => switch (builtin.os) { | 24 | builtin.Arch.x86_64 => { |
| 24 | builtin.Os.freebsd => { | 25 | argc_ptr = asm ("lea (%%rsp), %[argc]" |
| 25 | argc_ptr = asm ("lea (%%rdi), %[argc]" | 26 | : [argc] "=r" (-> [*]usize) |
| 26 | : [argc] "=r" (-> [*]usize) | 27 | ); |
| 27 | ); | ||
| 28 | }, | ||
| 29 | else => { | ||
| 30 | argc_ptr = asm ("lea (%%rsp), %[argc]" | ||
| 31 | : [argc] "=r" (-> [*]usize) | ||
| 32 | ); | ||
| 33 | }, | ||
| 34 | }, | 28 | }, |
| 35 | builtin.Arch.i386 => { | 29 | builtin.Arch.i386 => { |
| 36 | argc_ptr = asm ("lea (%%esp), %[argc]" | 30 | argc_ptr = asm ("lea (%%esp), %[argc]" |
| ... | @@ -51,7 +45,9 @@ nakedcc fn _start() noreturn { | ... | @@ -51,7 +45,9 @@ nakedcc fn _start() noreturn { |
| 51 | 45 | ||
| 52 | extern fn WinMainCRTStartup() noreturn { | 46 | extern fn WinMainCRTStartup() noreturn { |
| 53 | @setAlignStack(16); | 47 | @setAlignStack(16); |
| 54 | 48 | if (!builtin.single_threaded) { | |
| 49 | _ = @import("../os/windows/tls.zig"); | ||
| 50 | } | ||
| 55 | std.os.windows.ExitProcess(callMain()); | 51 | std.os.windows.ExitProcess(callMain()); |
| 56 | } | 52 | } |
| 57 | 53 | ||
| ... | @@ -68,9 +64,23 @@ fn posixCallMainAndExit() noreturn { | ... | @@ -68,9 +64,23 @@ fn posixCallMainAndExit() noreturn { |
| 68 | while (envp_optional[envp_count]) |_| : (envp_count += 1) {} | 64 | while (envp_optional[envp_count]) |_| : (envp_count += 1) {} |
| 69 | const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count]; | 65 | const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count]; |
| 70 | if (builtin.os == builtin.Os.linux) { | 66 | if (builtin.os == builtin.Os.linux) { |
| 71 | const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1); | 67 | // Scan auxiliary vector. |
| 72 | std.os.linux_elf_aux_maybe = @ptrCast([*]std.elf.Auxv, auxv); | 68 | const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1); |
| 73 | std.debug.assert(std.os.linuxGetAuxVal(std.elf.AT_PAGESZ) == std.os.page_size); | 69 | std.os.linux_elf_aux_maybe = auxv; |
| 70 | var i: usize = 0; | ||
| 71 | var at_phdr: usize = 0; | ||
| 72 | var at_phnum: usize = 0; | ||
| 73 | var at_phent: usize = 0; | ||
| 74 | while (auxv[i].a_un.a_val != 0) : (i += 1) { | ||
| 75 | switch (auxv[i].a_type) { | ||
| 76 | std.elf.AT_PAGESZ => assert(auxv[i].a_un.a_val == std.os.page_size), | ||
| 77 | std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val, | ||
| 78 | std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val, | ||
| 79 | std.elf.AT_PHENT => at_phent = auxv[i].a_un.a_val, | ||
| 80 | else => {}, | ||
| 81 | } | ||
| 82 | } | ||
| 83 | if (!builtin.single_threaded) linuxInitializeThreadLocalStorage(at_phdr, at_phnum, at_phent); | ||
| 74 | } | 84 | } |
| 75 | 85 | ||
| 76 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); | 86 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); |
| ... | @@ -123,3 +133,41 @@ inline fn callMain() u8 { | ... | @@ -123,3 +133,41 @@ inline fn callMain() u8 { |
| 123 | else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"), | 133 | else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"), |
| 124 | } | 134 | } |
| 125 | } | 135 | } |
| 136 | |||
| 137 | var tls_end_addr: usize = undefined; | ||
| 138 | const main_thread_tls_align = 32; | ||
| 139 | var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64; | ||
| 140 | |||
| 141 | fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: usize) void { | ||
| 142 | var phdr_addr = at_phdr; | ||
| 143 | var n = at_phnum; | ||
| 144 | var base: usize = 0; | ||
| 145 | while (n != 0) : ({n -= 1; phdr_addr += at_phent;}) { | ||
| 146 | const phdr = @intToPtr(*std.elf.Phdr, phdr_addr); | ||
| 147 | // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917 | ||
| 148 | switch (phdr.p_type) { | ||
| 149 | std.elf.PT_PHDR => base = at_phdr - phdr.p_vaddr, | ||
| 150 | std.elf.PT_TLS => std.os.linux_tls_phdr = phdr, | ||
| 151 | else => continue, | ||
| 152 | } | ||
| 153 | } | ||
| 154 | const tls_phdr = std.os.linux_tls_phdr orelse return; | ||
| 155 | std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr); | ||
| 156 | assert(main_thread_tls_bytes.len >= tls_phdr.p_memsz); // not enough preallocated Thread Local Storage | ||
| 157 | assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough | ||
| 158 | @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz); | ||
| 159 | tls_end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz; | ||
| 160 | linuxSetThreadArea(@ptrToInt(&tls_end_addr)); | ||
| 161 | } | ||
| 162 | |||
| 163 | fn linuxSetThreadArea(addr: usize) void { | ||
| 164 | switch (builtin.arch) { | ||
| 165 | builtin.Arch.x86_64 => { | ||
| 166 | const ARCH_SET_FS = 0x1002; | ||
| 167 | const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl, ARCH_SET_FS, addr); | ||
| 168 | // acrh_prctl is documented to never fail | ||
| 169 | assert(rc == 0); | ||
| 170 | }, | ||
| 171 | else => @compileError("Unsupported architecture"), | ||
| 172 | } | ||
| 173 | } |
std/special/compiler_rt/addXf3.zig created+191| ... | @@ -0,0 +1,191 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc | ||
| 4 | |||
| 5 | const std = @import("std"); | ||
| 6 | const builtin = @import("builtin"); | ||
| 7 | const compiler_rt = @import("index.zig"); | ||
| 8 | |||
| 9 | pub extern fn __addtf3(a: f128, b: f128) f128 { | ||
| 10 | return addXf3(f128, a, b); | ||
| 11 | } | ||
| 12 | |||
| 13 | pub extern fn __subtf3(a: f128, b: f128) f128 { | ||
| 14 | const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127)); | ||
| 15 | return addXf3(f128, a, neg_b); | ||
| 16 | } | ||
| 17 | |||
| 18 | inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { | ||
| 19 | const Z = @IntType(false, T.bit_count); | ||
| 20 | const significandBits = std.math.floatMantissaBits(T); | ||
| 21 | const implicitBit = Z(1) << significandBits; | ||
| 22 | |||
| 23 | const shift = @clz(significand.*) - @clz(implicitBit); | ||
| 24 | significand.* <<= @intCast(u7, shift); | ||
| 25 | return 1 - shift; | ||
| 26 | } | ||
| 27 | |||
| 28 | inline fn addXf3(comptime T: type, a: T, b: T) T { | ||
| 29 | const Z = @IntType(false, T.bit_count); | ||
| 30 | |||
| 31 | const typeWidth = T.bit_count; | ||
| 32 | const significandBits = std.math.floatMantissaBits(T); | ||
| 33 | const exponentBits = std.math.floatExponentBits(T); | ||
| 34 | |||
| 35 | const signBit = (Z(1) << (significandBits + exponentBits)); | ||
| 36 | const maxExponent = ((1 << exponentBits) - 1); | ||
| 37 | const exponentBias = (maxExponent >> 1); | ||
| 38 | |||
| 39 | const implicitBit = (Z(1) << significandBits); | ||
| 40 | const quietBit = implicitBit >> 1; | ||
| 41 | const significandMask = implicitBit - 1; | ||
| 42 | |||
| 43 | const absMask = signBit - 1; | ||
| 44 | const exponentMask = absMask ^ significandMask; | ||
| 45 | const qnanRep = exponentMask | quietBit; | ||
| 46 | |||
| 47 | var aRep = @bitCast(Z, a); | ||
| 48 | var bRep = @bitCast(Z, b); | ||
| 49 | const aAbs = aRep & absMask; | ||
| 50 | const bAbs = bRep & absMask; | ||
| 51 | |||
| 52 | const negative = (aRep & signBit) != 0; | ||
| 53 | const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias; | ||
| 54 | const significand = (aAbs & significandMask) | implicitBit; | ||
| 55 | |||
| 56 | const infRep = @bitCast(Z, std.math.inf(T)); | ||
| 57 | |||
| 58 | // Detect if a or b is zero, infinity, or NaN. | ||
| 59 | if (aAbs - Z(1) >= infRep - Z(1) or | ||
| 60 | bAbs - Z(1) >= infRep - Z(1)) | ||
| 61 | { | ||
| 62 | // NaN + anything = qNaN | ||
| 63 | if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); | ||
| 64 | // anything + NaN = qNaN | ||
| 65 | if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit); | ||
| 66 | |||
| 67 | if (aAbs == infRep) { | ||
| 68 | // +/-infinity + -/+infinity = qNaN | ||
| 69 | if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) { | ||
| 70 | return @bitCast(T, qnanRep); | ||
| 71 | } | ||
| 72 | // +/-infinity + anything remaining = +/- infinity | ||
| 73 | else { | ||
| 74 | return a; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | // anything remaining + +/-infinity = +/-infinity | ||
| 79 | if (bAbs == infRep) return b; | ||
| 80 | |||
| 81 | // zero + anything = anything | ||
| 82 | if (aAbs == 0) { | ||
| 83 | // but we need to get the sign right for zero + zero | ||
| 84 | if (bAbs == 0) { | ||
| 85 | return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b)); | ||
| 86 | } else { | ||
| 87 | return b; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | // anything + zero = anything | ||
| 92 | if (bAbs == 0) return a; | ||
| 93 | } | ||
| 94 | |||
| 95 | // Swap a and b if necessary so that a has the larger absolute value. | ||
| 96 | if (bAbs > aAbs) { | ||
| 97 | const temp = aRep; | ||
| 98 | aRep = bRep; | ||
| 99 | bRep = temp; | ||
| 100 | } | ||
| 101 | |||
| 102 | // Extract the exponent and significand from the (possibly swapped) a and b. | ||
| 103 | var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent); | ||
| 104 | var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent); | ||
| 105 | var aSignificand = aRep & significandMask; | ||
| 106 | var bSignificand = bRep & significandMask; | ||
| 107 | |||
| 108 | // Normalize any denormals, and adjust the exponent accordingly. | ||
| 109 | if (aExponent == 0) aExponent = normalize(T, &aSignificand); | ||
| 110 | if (bExponent == 0) bExponent = normalize(T, &bSignificand); | ||
| 111 | |||
| 112 | // The sign of the result is the sign of the larger operand, a. If they | ||
| 113 | // have opposite signs, we are performing a subtraction; otherwise addition. | ||
| 114 | const resultSign = aRep & signBit; | ||
| 115 | const subtraction = (aRep ^ bRep) & signBit != 0; | ||
| 116 | |||
| 117 | // Shift the significands to give us round, guard and sticky, and or in the | ||
| 118 | // implicit significand bit. (If we fell through from the denormal path it | ||
| 119 | // was already set by normalize( ), but setting it twice won't hurt | ||
| 120 | // anything.) | ||
| 121 | aSignificand = (aSignificand | implicitBit) << 3; | ||
| 122 | bSignificand = (bSignificand | implicitBit) << 3; | ||
| 123 | |||
| 124 | // Shift the significand of b by the difference in exponents, with a sticky | ||
| 125 | // bottom bit to get rounding correct. | ||
| 126 | const @"align" = @intCast(Z, aExponent - bExponent); | ||
| 127 | if (@"align" != 0) { | ||
| 128 | if (@"align" < typeWidth) { | ||
| 129 | const sticky = if (bSignificand << @intCast(u7, typeWidth - @"align") != 0) Z(1) else 0; | ||
| 130 | bSignificand = (bSignificand >> @truncate(u7, @"align")) | sticky; | ||
| 131 | } else { | ||
| 132 | bSignificand = 1; // sticky; b is known to be non-zero. | ||
| 133 | } | ||
| 134 | } | ||
| 135 | if (subtraction) { | ||
| 136 | aSignificand -= bSignificand; | ||
| 137 | // If a == -b, return +zero. | ||
| 138 | if (aSignificand == 0) return @bitCast(T, Z(0)); | ||
| 139 | |||
| 140 | // If partial cancellation occured, we need to left-shift the result | ||
| 141 | // and adjust the exponent: | ||
| 142 | if (aSignificand < implicitBit << 3) { | ||
| 143 | const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3)); | ||
| 144 | aSignificand <<= @intCast(u7, shift); | ||
| 145 | aExponent -= shift; | ||
| 146 | } | ||
| 147 | } else { // addition | ||
| 148 | aSignificand += bSignificand; | ||
| 149 | |||
| 150 | // If the addition carried up, we need to right-shift the result and | ||
| 151 | // adjust the exponent: | ||
| 152 | if (aSignificand & (implicitBit << 4) != 0) { | ||
| 153 | const sticky = aSignificand & 1; | ||
| 154 | aSignificand = aSignificand >> 1 | sticky; | ||
| 155 | aExponent += 1; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | // If we have overflowed the type, return +/- infinity: | ||
| 160 | if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign); | ||
| 161 | |||
| 162 | if (aExponent <= 0) { | ||
| 163 | // Result is denormal before rounding; the exponent is zero and we | ||
| 164 | // need to shift the significand. | ||
| 165 | const shift = @intCast(Z, 1 - aExponent); | ||
| 166 | const sticky = if (aSignificand << @intCast(u7, typeWidth - shift) != 0) Z(1) else 0; | ||
| 167 | aSignificand = aSignificand >> @intCast(u7, shift | sticky); | ||
| 168 | aExponent = 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | // Low three bits are round, guard, and sticky. | ||
| 172 | const roundGuardSticky = aSignificand & 0x7; | ||
| 173 | |||
| 174 | // Shift the significand into place, and mask off the implicit bit. | ||
| 175 | var result = (aSignificand >> 3) & significandMask; | ||
| 176 | |||
| 177 | // Insert the exponent and sign. | ||
| 178 | result |= @intCast(Z, aExponent) << significandBits; | ||
| 179 | result |= resultSign; | ||
| 180 | |||
| 181 | // Final rounding. The result may overflow to infinity, but that is the | ||
| 182 | // correct result in that case. | ||
| 183 | if (roundGuardSticky > 0x4) result += 1; | ||
| 184 | if (roundGuardSticky == 0x4) result += result & 1; | ||
| 185 | |||
| 186 | return @bitCast(T, result); | ||
| 187 | } | ||
| 188 | |||
| 189 | test "import addXf3" { | ||
| 190 | _ = @import("addXf3_test.zig"); | ||
| 191 | } | ||
std/special/compiler_rt/addXf3_test.zig created+85| ... | @@ -0,0 +1,85 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c | ||
| 4 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c | ||
| 5 | |||
| 6 | const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64); | ||
| 7 | const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64); | ||
| 8 | |||
| 9 | const __addtf3 = @import("addXf3.zig").__addtf3; | ||
| 10 | |||
| 11 | fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { | ||
| 12 | const x = __addtf3(a, b); | ||
| 13 | |||
| 14 | const rep = @bitCast(u128, x); | ||
| 15 | const hi = @intCast(u64, rep >> 64); | ||
| 16 | const lo = @truncate(u64, rep); | ||
| 17 | |||
| 18 | if (hi == expected_hi and lo == expected_lo) { | ||
| 19 | return; | ||
| 20 | } | ||
| 21 | // test other possible NaN representation (signal NaN) | ||
| 22 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | ||
| 23 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | ||
| 24 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | ||
| 25 | { | ||
| 26 | return; | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | @panic("__addtf3 test failure"); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "addtf3" { | ||
| 34 | test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | ||
| 35 | |||
| 36 | // NaN + any = NaN | ||
| 37 | test__addtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | ||
| 38 | |||
| 39 | // inf + inf = inf | ||
| 40 | test__addtf3(inf128, inf128, 0x7fff000000000000, 0x0); | ||
| 41 | |||
| 42 | // inf + any = inf | ||
| 43 | test__addtf3(inf128, 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0); | ||
| 44 | |||
| 45 | // any + any | ||
| 46 | test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c); | ||
| 47 | } | ||
| 48 | |||
| 49 | const __subtf3 = @import("addXf3.zig").__subtf3; | ||
| 50 | |||
| 51 | fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { | ||
| 52 | const x = __subtf3(a, b); | ||
| 53 | |||
| 54 | const rep = @bitCast(u128, x); | ||
| 55 | const hi = @intCast(u64, rep >> 64); | ||
| 56 | const lo = @truncate(u64, rep); | ||
| 57 | |||
| 58 | if (hi == expected_hi and lo == expected_lo) { | ||
| 59 | return; | ||
| 60 | } | ||
| 61 | // test other possible NaN representation (signal NaN) | ||
| 62 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | ||
| 63 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | ||
| 64 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | ||
| 65 | { | ||
| 66 | return; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | @panic("__subtf3 test failure"); | ||
| 71 | } | ||
| 72 | |||
| 73 | test "subtf3" { | ||
| 74 | // qNaN - any = qNaN | ||
| 75 | test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | ||
| 76 | |||
| 77 | // NaN + any = NaN | ||
| 78 | test__subtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | ||
| 79 | |||
| 80 | // inf - any = inf | ||
| 81 | test__subtf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | ||
| 82 | |||
| 83 | // any + any | ||
| 84 | test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c); | ||
| 85 | } | ||
std/special/compiler_rt/divti3_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __divti3 = @import("divti3.zig").__divti3; | 1 | const __divti3 = @import("divti3.zig").__divti3; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__divti3(a: i128, b: i128, expected: i128) void { | 4 | fn test__divti3(a: i128, b: i128, expected: i128) void { |
| 5 | const x = __divti3(a, b); | 5 | const x = __divti3(a, b); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "divti3" { | 9 | test "divti3" { |
std/special/compiler_rt/extendXfYf2_test.zig-1| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; | 1 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; |
| 2 | const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; | 2 | const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; |
| 3 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; | 3 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; |
| 4 | const assert = @import("std").debug.assert; | ||
| 5 | 4 | ||
| 6 | fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void { | 5 | fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void { |
| 7 | const x = __extenddftf2(a); | 6 | const x = __extenddftf2(a); |
std/special/compiler_rt/fixdfdi.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixdfdi(a: f64) i64 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f64, i64, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixdfdi" { | ||
| 10 | _ = @import("fixdfdi_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixdfdi_test.zig created+66| ... | @@ -0,0 +1,66 @@ | ||
| 1 | const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixdfdi(a: f64, expected: i64) void { | ||
| 8 | const x = __fixdfdi(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixdfdi" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixdfdi(-math.f64_max, math.minInt(i64)); | ||
| 17 | |||
| 18 | test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | ||
| 19 | test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | ||
| 20 | |||
| 21 | test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000); | ||
| 22 | test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | ||
| 23 | test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | ||
| 24 | |||
| 25 | test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000); | ||
| 26 | test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000); | ||
| 27 | test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | ||
| 28 | test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | ||
| 29 | |||
| 30 | test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | ||
| 31 | test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | ||
| 32 | |||
| 33 | test__fixdfdi(-2.01, -2); | ||
| 34 | test__fixdfdi(-2.0, -2); | ||
| 35 | test__fixdfdi(-1.99, -1); | ||
| 36 | test__fixdfdi(-1.0, -1); | ||
| 37 | test__fixdfdi(-0.99, 0); | ||
| 38 | test__fixdfdi(-0.5, 0); | ||
| 39 | test__fixdfdi(-math.f64_min, 0); | ||
| 40 | test__fixdfdi(0.0, 0); | ||
| 41 | test__fixdfdi(math.f64_min, 0); | ||
| 42 | test__fixdfdi(0.5, 0); | ||
| 43 | test__fixdfdi(0.99, 0); | ||
| 44 | test__fixdfdi(1.0, 1); | ||
| 45 | test__fixdfdi(1.5, 1); | ||
| 46 | test__fixdfdi(1.99, 1); | ||
| 47 | test__fixdfdi(2.0, 2); | ||
| 48 | test__fixdfdi(2.01, 2); | ||
| 49 | |||
| 50 | test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | ||
| 51 | test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | ||
| 52 | |||
| 53 | test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | ||
| 54 | test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | ||
| 55 | test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | ||
| 56 | test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | ||
| 57 | |||
| 58 | test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | ||
| 59 | test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | ||
| 60 | test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | ||
| 61 | |||
| 62 | test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | ||
| 63 | test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | ||
| 64 | |||
| 65 | test__fixdfdi(math.f64_max, math.maxInt(i64)); | ||
| 66 | } | ||
std/special/compiler_rt/fixdfsi.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixdfsi(a: f64) i32 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f64, i32, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixdfsi" { | ||
| 10 | _ = @import("fixdfsi_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixdfsi_test.zig created+74| ... | @@ -0,0 +1,74 @@ | ||
| 1 | const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixdfsi(a: f64, expected: i32) void { | ||
| 8 | const x = __fixdfsi(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixdfsi" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixdfsi(-math.f64_max, math.minInt(i32)); | ||
| 17 | |||
| 18 | test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | ||
| 19 | test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | ||
| 20 | |||
| 21 | test__fixdfsi(-0x1.0000000000000p+127, -0x80000000); | ||
| 22 | test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | ||
| 23 | test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | ||
| 24 | |||
| 25 | test__fixdfsi(-0x1.0000000000001p+63, -0x80000000); | ||
| 26 | test__fixdfsi(-0x1.0000000000000p+63, -0x80000000); | ||
| 27 | test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | ||
| 28 | test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | ||
| 29 | |||
| 30 | test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000); | ||
| 31 | test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000); | ||
| 32 | |||
| 33 | test__fixdfsi(-0x1.000000p+31, -0x80000000); | ||
| 34 | test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | ||
| 35 | test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | ||
| 36 | |||
| 37 | test__fixdfsi(-2.01, -2); | ||
| 38 | test__fixdfsi(-2.0, -2); | ||
| 39 | test__fixdfsi(-1.99, -1); | ||
| 40 | test__fixdfsi(-1.0, -1); | ||
| 41 | test__fixdfsi(-0.99, 0); | ||
| 42 | test__fixdfsi(-0.5, 0); | ||
| 43 | test__fixdfsi(-math.f64_min, 0); | ||
| 44 | test__fixdfsi(0.0, 0); | ||
| 45 | test__fixdfsi(math.f64_min, 0); | ||
| 46 | test__fixdfsi(0.5, 0); | ||
| 47 | test__fixdfsi(0.99, 0); | ||
| 48 | test__fixdfsi(1.0, 1); | ||
| 49 | test__fixdfsi(1.5, 1); | ||
| 50 | test__fixdfsi(1.99, 1); | ||
| 51 | test__fixdfsi(2.0, 2); | ||
| 52 | test__fixdfsi(2.01, 2); | ||
| 53 | |||
| 54 | test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | ||
| 55 | test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | ||
| 56 | test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF); | ||
| 57 | |||
| 58 | test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | ||
| 59 | test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | ||
| 60 | |||
| 61 | test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | ||
| 62 | test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | ||
| 63 | test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | ||
| 64 | test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | ||
| 65 | |||
| 66 | test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | ||
| 67 | test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | ||
| 68 | test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | ||
| 69 | |||
| 70 | test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | ||
| 71 | test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | ||
| 72 | |||
| 73 | test__fixdfsi(math.f64_max, math.maxInt(i32)); | ||
| 74 | } | ||
std/special/compiler_rt/fixdfti.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixdfti(a: f64) i128 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f64, i128, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixdfti" { | ||
| 10 | _ = @import("fixdfti_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixdfti_test.zig created+66| ... | @@ -0,0 +1,66 @@ | ||
| 1 | const __fixdfti = @import("fixdfti.zig").__fixdfti; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixdfti(a: f64, expected: i128) void { | ||
| 8 | const x = __fixdfti(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixdfti" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixdfti(-math.f64_max, math.minInt(i128)); | ||
| 17 | |||
| 18 | test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | ||
| 19 | test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | ||
| 20 | |||
| 21 | test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | ||
| 22 | test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | ||
| 23 | test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | ||
| 24 | |||
| 25 | test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800); | ||
| 26 | test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000); | ||
| 27 | test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | ||
| 28 | test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | ||
| 29 | |||
| 30 | test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | ||
| 31 | test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | ||
| 32 | |||
| 33 | test__fixdfti(-2.01, -2); | ||
| 34 | test__fixdfti(-2.0, -2); | ||
| 35 | test__fixdfti(-1.99, -1); | ||
| 36 | test__fixdfti(-1.0, -1); | ||
| 37 | test__fixdfti(-0.99, 0); | ||
| 38 | test__fixdfti(-0.5, 0); | ||
| 39 | test__fixdfti(-math.f64_min, 0); | ||
| 40 | test__fixdfti(0.0, 0); | ||
| 41 | test__fixdfti(math.f64_min, 0); | ||
| 42 | test__fixdfti(0.5, 0); | ||
| 43 | test__fixdfti(0.99, 0); | ||
| 44 | test__fixdfti(1.0, 1); | ||
| 45 | test__fixdfti(1.5, 1); | ||
| 46 | test__fixdfti(1.99, 1); | ||
| 47 | test__fixdfti(2.0, 2); | ||
| 48 | test__fixdfti(2.01, 2); | ||
| 49 | |||
| 50 | test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | ||
| 51 | test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | ||
| 52 | |||
| 53 | test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | ||
| 54 | test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | ||
| 55 | test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000); | ||
| 56 | test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800); | ||
| 57 | |||
| 58 | test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | ||
| 59 | test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | ||
| 60 | test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 61 | |||
| 62 | test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 63 | test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | ||
| 64 | |||
| 65 | test__fixdfti(math.f64_max, math.maxInt(i128)); | ||
| 66 | } | ||
std/special/compiler_rt/fixint.zig created+74| ... | @@ -0,0 +1,74 @@ | ||
| 1 | const is_test = @import("builtin").is_test; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const Log2Int = std.math.Log2Int; | ||
| 5 | const maxInt = std.math.maxInt; | ||
| 6 | const minInt = std.math.minInt; | ||
| 7 | |||
| 8 | const DBG = false; | ||
| 9 | |||
| 10 | pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t { | ||
| 11 | @setRuntimeSafety(is_test); | ||
| 12 | |||
| 13 | const rep_t = switch (fp_t) { | ||
| 14 | f32 => u32, | ||
| 15 | f64 => u64, | ||
| 16 | f128 => u128, | ||
| 17 | else => unreachable, | ||
| 18 | }; | ||
| 19 | const significandBits = switch (fp_t) { | ||
| 20 | f32 => 23, | ||
| 21 | f64 => 52, | ||
| 22 | f128 => 112, | ||
| 23 | else => unreachable, | ||
| 24 | }; | ||
| 25 | |||
| 26 | const typeWidth = rep_t.bit_count; | ||
| 27 | const exponentBits = (typeWidth - significandBits - 1); | ||
| 28 | const signBit = (rep_t(1) << (significandBits + exponentBits)); | ||
| 29 | const maxExponent = ((1 << exponentBits) - 1); | ||
| 30 | const exponentBias = (maxExponent >> 1); | ||
| 31 | |||
| 32 | const implicitBit = (rep_t(1) << significandBits); | ||
| 33 | const significandMask = (implicitBit - 1); | ||
| 34 | |||
| 35 | // Break a into sign, exponent, significand | ||
| 36 | const aRep: rep_t = @bitCast(rep_t, a); | ||
| 37 | const absMask = signBit - 1; | ||
| 38 | const aAbs: rep_t = aRep & absMask; | ||
| 39 | |||
| 40 | const negative = (aRep & signBit) != 0; | ||
| 41 | const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias; | ||
| 42 | const significand: rep_t = (aAbs & significandMask) | implicitBit; | ||
| 43 | |||
| 44 | // If exponent is negative, the uint_result is zero. | ||
| 45 | if (exponent < 0) return 0; | ||
| 46 | |||
| 47 | // The unsigned result needs to be large enough to handle an fixint_t or rep_t | ||
| 48 | const fixuint_t = @IntType(false, fixint_t.bit_count); | ||
| 49 | const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t; | ||
| 50 | var uint_result: UintResultType = undefined; | ||
| 51 | |||
| 52 | // If the value is too large for the integer type, saturate. | ||
| 53 | if (@intCast(usize, exponent) >= fixint_t.bit_count) { | ||
| 54 | return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t)); | ||
| 55 | } | ||
| 56 | |||
| 57 | // If 0 <= exponent < significandBits, right shift else left shift | ||
| 58 | if (exponent < significandBits) { | ||
| 59 | uint_result = @intCast(UintResultType, significand) >> @intCast(Log2Int(UintResultType), significandBits - exponent); | ||
| 60 | } else { | ||
| 61 | uint_result = @intCast(UintResultType, significand) << @intCast(Log2Int(UintResultType), exponent - significandBits); | ||
| 62 | } | ||
| 63 | |||
| 64 | // Cast to final signed result | ||
| 65 | if (negative) { | ||
| 66 | return if (uint_result >= -math.minInt(fixint_t)) math.minInt(fixint_t) else -@intCast(fixint_t, uint_result); | ||
| 67 | } else { | ||
| 68 | return if (uint_result >= math.maxInt(fixint_t)) math.maxInt(fixint_t) else @intCast(fixint_t, uint_result); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | test "import fixint" { | ||
| 73 | _ = @import("fixint_test.zig"); | ||
| 74 | } | ||
std/special/compiler_rt/fixint_test.zig created+152| ... | @@ -0,0 +1,152 @@ | ||
| 1 | const is_test = @import("builtin").is_test; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | const fixint = @import("fixint.zig").fixint; | ||
| 8 | |||
| 9 | fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) void { | ||
| 10 | const x = fixint(fp_t, fixint_t, a); | ||
| 11 | //warn("a={} x={}:{x} expected={}:{x})\n", a, x, x, expected, expected); | ||
| 12 | testing.expect(x == expected); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "fixint.i1" { | ||
| 16 | test__fixint(f32, i1, -math.inf_f32, -1); | ||
| 17 | test__fixint(f32, i1, -math.f32_max, -1); | ||
| 18 | test__fixint(f32, i1, -2.0, -1); | ||
| 19 | test__fixint(f32, i1, -1.1, -1); | ||
| 20 | test__fixint(f32, i1, -1.0, -1); | ||
| 21 | test__fixint(f32, i1, -0.9, 0); | ||
| 22 | test__fixint(f32, i1, -0.1, 0); | ||
| 23 | test__fixint(f32, i1, -math.f32_min, 0); | ||
| 24 | test__fixint(f32, i1, -0.0, 0); | ||
| 25 | test__fixint(f32, i1, 0.0, 0); | ||
| 26 | test__fixint(f32, i1, math.f32_min, 0); | ||
| 27 | test__fixint(f32, i1, 0.1, 0); | ||
| 28 | test__fixint(f32, i1, 0.9, 0); | ||
| 29 | test__fixint(f32, i1, 1.0, 0); | ||
| 30 | test__fixint(f32, i1, 2.0, 0); | ||
| 31 | test__fixint(f32, i1, math.f32_max, 0); | ||
| 32 | test__fixint(f32, i1, math.inf_f32, 0); | ||
| 33 | } | ||
| 34 | |||
| 35 | test "fixint.i2" { | ||
| 36 | test__fixint(f32, i2, -math.inf_f32, -2); | ||
| 37 | test__fixint(f32, i2, -math.f32_max, -2); | ||
| 38 | test__fixint(f32, i2, -2.0, -2); | ||
| 39 | test__fixint(f32, i2, -1.9, -1); | ||
| 40 | test__fixint(f32, i2, -1.1, -1); | ||
| 41 | test__fixint(f32, i2, -1.0, -1); | ||
| 42 | test__fixint(f32, i2, -0.9, 0); | ||
| 43 | test__fixint(f32, i2, -0.1, 0); | ||
| 44 | test__fixint(f32, i2, -math.f32_min, 0); | ||
| 45 | test__fixint(f32, i2, -0.0, 0); | ||
| 46 | test__fixint(f32, i2, 0.0, 0); | ||
| 47 | test__fixint(f32, i2, math.f32_min, 0); | ||
| 48 | test__fixint(f32, i2, 0.1, 0); | ||
| 49 | test__fixint(f32, i2, 0.9, 0); | ||
| 50 | test__fixint(f32, i2, 1.0, 1); | ||
| 51 | test__fixint(f32, i2, 2.0, 1); | ||
| 52 | test__fixint(f32, i2, math.f32_max, 1); | ||
| 53 | test__fixint(f32, i2, math.inf_f32, 1); | ||
| 54 | } | ||
| 55 | |||
| 56 | test "fixint.i3" { | ||
| 57 | test__fixint(f32, i3, -math.inf_f32, -4); | ||
| 58 | test__fixint(f32, i3, -math.f32_max, -4); | ||
| 59 | test__fixint(f32, i3, -4.0, -4); | ||
| 60 | test__fixint(f32, i3, -3.0, -3); | ||
| 61 | test__fixint(f32, i3, -2.0, -2); | ||
| 62 | test__fixint(f32, i3, -1.9, -1); | ||
| 63 | test__fixint(f32, i3, -1.1, -1); | ||
| 64 | test__fixint(f32, i3, -1.0, -1); | ||
| 65 | test__fixint(f32, i3, -0.9, 0); | ||
| 66 | test__fixint(f32, i3, -0.1, 0); | ||
| 67 | test__fixint(f32, i3, -math.f32_min, 0); | ||
| 68 | test__fixint(f32, i3, -0.0, 0); | ||
| 69 | test__fixint(f32, i3, 0.0, 0); | ||
| 70 | test__fixint(f32, i3, math.f32_min, 0); | ||
| 71 | test__fixint(f32, i3, 0.1, 0); | ||
| 72 | test__fixint(f32, i3, 0.9, 0); | ||
| 73 | test__fixint(f32, i3, 1.0, 1); | ||
| 74 | test__fixint(f32, i3, 2.0, 2); | ||
| 75 | test__fixint(f32, i3, 3.0, 3); | ||
| 76 | test__fixint(f32, i3, 4.0, 3); | ||
| 77 | test__fixint(f32, i3, math.f32_max, 3); | ||
| 78 | test__fixint(f32, i3, math.inf_f32, 3); | ||
| 79 | } | ||
| 80 | |||
| 81 | test "fixint.i32" { | ||
| 82 | test__fixint(f64, i32, -math.inf_f64, math.minInt(i32)); | ||
| 83 | test__fixint(f64, i32, -math.f64_max, math.minInt(i32)); | ||
| 84 | test__fixint(f64, i32, f64(math.minInt(i32)), math.minInt(i32)); | ||
| 85 | test__fixint(f64, i32, f64(math.minInt(i32))+1, math.minInt(i32)+1); | ||
| 86 | test__fixint(f64, i32, -2.0, -2); | ||
| 87 | test__fixint(f64, i32, -1.9, -1); | ||
| 88 | test__fixint(f64, i32, -1.1, -1); | ||
| 89 | test__fixint(f64, i32, -1.0, -1); | ||
| 90 | test__fixint(f64, i32, -0.9, 0); | ||
| 91 | test__fixint(f64, i32, -0.1, 0); | ||
| 92 | test__fixint(f64, i32, -math.f32_min, 0); | ||
| 93 | test__fixint(f64, i32, -0.0, 0); | ||
| 94 | test__fixint(f64, i32, 0.0, 0); | ||
| 95 | test__fixint(f64, i32, math.f32_min, 0); | ||
| 96 | test__fixint(f64, i32, 0.1, 0); | ||
| 97 | test__fixint(f64, i32, 0.9, 0); | ||
| 98 | test__fixint(f64, i32, 1.0, 1); | ||
| 99 | test__fixint(f64, i32, f64(math.maxInt(i32))-1, math.maxInt(i32)-1); | ||
| 100 | test__fixint(f64, i32, f64(math.maxInt(i32)), math.maxInt(i32)); | ||
| 101 | test__fixint(f64, i32, math.f64_max, math.maxInt(i32)); | ||
| 102 | test__fixint(f64, i32, math.inf_f64, math.maxInt(i32)); | ||
| 103 | } | ||
| 104 | |||
| 105 | test "fixint.i64" { | ||
| 106 | test__fixint(f64, i64, -math.inf_f64, math.minInt(i64)); | ||
| 107 | test__fixint(f64, i64, -math.f64_max, math.minInt(i64)); | ||
| 108 | test__fixint(f64, i64, f64(math.minInt(i64)), math.minInt(i64)); | ||
| 109 | test__fixint(f64, i64, f64(math.minInt(i64))+1, math.minInt(i64)); | ||
| 110 | test__fixint(f64, i64, f64(math.minInt(i64)/2), math.minInt(i64)/2); | ||
| 111 | test__fixint(f64, i64, -2.0, -2); | ||
| 112 | test__fixint(f64, i64, -1.9, -1); | ||
| 113 | test__fixint(f64, i64, -1.1, -1); | ||
| 114 | test__fixint(f64, i64, -1.0, -1); | ||
| 115 | test__fixint(f64, i64, -0.9, 0); | ||
| 116 | test__fixint(f64, i64, -0.1, 0); | ||
| 117 | test__fixint(f64, i64, -math.f32_min, 0); | ||
| 118 | test__fixint(f64, i64, -0.0, 0); | ||
| 119 | test__fixint(f64, i64, 0.0, 0); | ||
| 120 | test__fixint(f64, i64, math.f32_min, 0); | ||
| 121 | test__fixint(f64, i64, 0.1, 0); | ||
| 122 | test__fixint(f64, i64, 0.9, 0); | ||
| 123 | test__fixint(f64, i64, 1.0, 1); | ||
| 124 | test__fixint(f64, i64, f64(math.maxInt(i64))-1, math.maxInt(i64)); | ||
| 125 | test__fixint(f64, i64, f64(math.maxInt(i64)), math.maxInt(i64)); | ||
| 126 | test__fixint(f64, i64, math.f64_max, math.maxInt(i64)); | ||
| 127 | test__fixint(f64, i64, math.inf_f64, math.maxInt(i64)); | ||
| 128 | } | ||
| 129 | |||
| 130 | test "fixint.i128" { | ||
| 131 | test__fixint(f64, i128, -math.inf_f64, math.minInt(i128)); | ||
| 132 | test__fixint(f64, i128, -math.f64_max, math.minInt(i128)); | ||
| 133 | test__fixint(f64, i128, f64(math.minInt(i128)), math.minInt(i128)); | ||
| 134 | test__fixint(f64, i128, f64(math.minInt(i128))+1, math.minInt(i128)); | ||
| 135 | test__fixint(f64, i128, -2.0, -2); | ||
| 136 | test__fixint(f64, i128, -1.9, -1); | ||
| 137 | test__fixint(f64, i128, -1.1, -1); | ||
| 138 | test__fixint(f64, i128, -1.0, -1); | ||
| 139 | test__fixint(f64, i128, -0.9, 0); | ||
| 140 | test__fixint(f64, i128, -0.1, 0); | ||
| 141 | test__fixint(f64, i128, -math.f32_min, 0); | ||
| 142 | test__fixint(f64, i128, -0.0, 0); | ||
| 143 | test__fixint(f64, i128, 0.0, 0); | ||
| 144 | test__fixint(f64, i128, math.f32_min, 0); | ||
| 145 | test__fixint(f64, i128, 0.1, 0); | ||
| 146 | test__fixint(f64, i128, 0.9, 0); | ||
| 147 | test__fixint(f64, i128, 1.0, 1); | ||
| 148 | test__fixint(f64, i128, f64(math.maxInt(i128))-1, math.maxInt(i128)); | ||
| 149 | test__fixint(f64, i128, f64(math.maxInt(i128)), math.maxInt(i128)); | ||
| 150 | test__fixint(f64, i128, math.f64_max, math.maxInt(i128)); | ||
| 151 | test__fixint(f64, i128, math.inf_f64, math.maxInt(i128)); | ||
| 152 | } | ||
std/special/compiler_rt/fixsfdi.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixsfdi(a: f32) i64 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f32, i64, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixsfdi" { | ||
| 10 | _ = @import("fixsfdi_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixsfdi_test.zig created+68| ... | @@ -0,0 +1,68 @@ | ||
| 1 | const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixsfdi(a: f32, expected: i64) void { | ||
| 8 | const x = __fixsfdi(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u64, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixsfdi" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixsfdi(-math.f32_max, math.minInt(i64)); | ||
| 17 | |||
| 18 | test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | ||
| 19 | test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | ||
| 20 | |||
| 21 | test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000); | ||
| 22 | test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | ||
| 23 | test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | ||
| 24 | |||
| 25 | test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000); | ||
| 26 | test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000); | ||
| 27 | test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | ||
| 28 | test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | ||
| 29 | |||
| 30 | test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000); | ||
| 31 | test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | ||
| 32 | test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | ||
| 33 | |||
| 34 | test__fixsfdi(-2.01, -2); | ||
| 35 | test__fixsfdi(-2.0, -2); | ||
| 36 | test__fixsfdi(-1.99, -1); | ||
| 37 | test__fixsfdi(-1.0, -1); | ||
| 38 | test__fixsfdi(-0.99, 0); | ||
| 39 | test__fixsfdi(-0.5, 0); | ||
| 40 | test__fixsfdi(-math.f32_min, 0); | ||
| 41 | test__fixsfdi(0.0, 0); | ||
| 42 | test__fixsfdi(math.f32_min, 0); | ||
| 43 | test__fixsfdi(0.5, 0); | ||
| 44 | test__fixsfdi(0.99, 0); | ||
| 45 | test__fixsfdi(1.0, 1); | ||
| 46 | test__fixsfdi(1.5, 1); | ||
| 47 | test__fixsfdi(1.99, 1); | ||
| 48 | test__fixsfdi(2.0, 2); | ||
| 49 | test__fixsfdi(2.01, 2); | ||
| 50 | |||
| 51 | test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | ||
| 52 | test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | ||
| 53 | test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | ||
| 54 | |||
| 55 | test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); | ||
| 56 | test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | ||
| 57 | test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | ||
| 58 | test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | ||
| 59 | |||
| 60 | test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | ||
| 61 | test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | ||
| 62 | test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | ||
| 63 | |||
| 64 | test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | ||
| 65 | test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | ||
| 66 | |||
| 67 | test__fixsfdi(math.f64_max, math.maxInt(i64)); | ||
| 68 | } | ||
std/special/compiler_rt/fixsfsi.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixsfsi(a: f32) i32 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f32, i32, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixsfsi" { | ||
| 10 | _ = @import("fixsfsi_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixsfsi_test.zig created+76| ... | @@ -0,0 +1,76 @@ | ||
| 1 | const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixsfsi(a: f32, expected: i32) void { | ||
| 8 | const x = __fixsfsi(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u32, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixsfsi" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixsfsi(-math.f32_max, math.minInt(i32)); | ||
| 17 | |||
| 18 | test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | ||
| 19 | test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | ||
| 20 | |||
| 21 | test__fixsfsi(-0x1.0000000000000p+127, -0x80000000); | ||
| 22 | test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | ||
| 23 | test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | ||
| 24 | |||
| 25 | test__fixsfsi(-0x1.0000000000001p+63, -0x80000000); | ||
| 26 | test__fixsfsi(-0x1.0000000000000p+63, -0x80000000); | ||
| 27 | test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | ||
| 28 | test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | ||
| 29 | |||
| 30 | test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000); | ||
| 31 | test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000); | ||
| 32 | |||
| 33 | test__fixsfsi(-0x1.000000p+31, -0x80000000); | ||
| 34 | test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000); | ||
| 35 | test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | ||
| 36 | test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | ||
| 37 | |||
| 38 | test__fixsfsi(-2.01, -2); | ||
| 39 | test__fixsfsi(-2.0, -2); | ||
| 40 | test__fixsfsi(-1.99, -1); | ||
| 41 | test__fixsfsi(-1.0, -1); | ||
| 42 | test__fixsfsi(-0.99, 0); | ||
| 43 | test__fixsfsi(-0.5, 0); | ||
| 44 | test__fixsfsi(-math.f32_min, 0); | ||
| 45 | test__fixsfsi(0.0, 0); | ||
| 46 | test__fixsfsi(math.f32_min, 0); | ||
| 47 | test__fixsfsi(0.5, 0); | ||
| 48 | test__fixsfsi(0.99, 0); | ||
| 49 | test__fixsfsi(1.0, 1); | ||
| 50 | test__fixsfsi(1.5, 1); | ||
| 51 | test__fixsfsi(1.99, 1); | ||
| 52 | test__fixsfsi(2.0, 2); | ||
| 53 | test__fixsfsi(2.01, 2); | ||
| 54 | |||
| 55 | test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | ||
| 56 | test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | ||
| 57 | test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF); | ||
| 58 | test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF); | ||
| 59 | |||
| 60 | test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | ||
| 61 | test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | ||
| 62 | |||
| 63 | test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | ||
| 64 | test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | ||
| 65 | test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | ||
| 66 | test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | ||
| 67 | |||
| 68 | test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | ||
| 69 | test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | ||
| 70 | test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | ||
| 71 | |||
| 72 | test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | ||
| 73 | test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | ||
| 74 | |||
| 75 | test__fixsfsi(math.f32_max, math.maxInt(i32)); | ||
| 76 | } | ||
std/special/compiler_rt/fixsfti.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixsfti(a: f32) i128 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f32, i128, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixsfti" { | ||
| 10 | _ = @import("fixsfti_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixsfti_test.zig created+84| ... | @@ -0,0 +1,84 @@ | ||
| 1 | const __fixsfti = @import("fixsfti.zig").__fixsfti; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixsfti(a: f32, expected: i128) void { | ||
| 8 | const x = __fixsfti(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u128, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixsfti" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixsfti(-math.f32_max, math.minInt(i128)); | ||
| 17 | |||
| 18 | test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | ||
| 19 | test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | ||
| 20 | |||
| 21 | test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | ||
| 22 | test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); | ||
| 23 | test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); | ||
| 24 | test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); | ||
| 25 | test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); | ||
| 26 | test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); | ||
| 27 | |||
| 28 | test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000); | ||
| 29 | test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000); | ||
| 30 | test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | ||
| 31 | test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | ||
| 32 | |||
| 33 | test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000); | ||
| 34 | test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | ||
| 35 | test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | ||
| 36 | |||
| 37 | test__fixsfti(-0x1.000000p+31, -0x80000000); | ||
| 38 | test__fixsfti(-0x1.FFFFFFp+30, -0x80000000); | ||
| 39 | test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80); | ||
| 40 | test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00); | ||
| 41 | |||
| 42 | test__fixsfti(-2.01, -2); | ||
| 43 | test__fixsfti(-2.0, -2); | ||
| 44 | test__fixsfti(-1.99, -1); | ||
| 45 | test__fixsfti(-1.0, -1); | ||
| 46 | test__fixsfti(-0.99, 0); | ||
| 47 | test__fixsfti(-0.5, 0); | ||
| 48 | test__fixsfti(-math.f32_min, 0); | ||
| 49 | test__fixsfti(0.0, 0); | ||
| 50 | test__fixsfti(math.f32_min, 0); | ||
| 51 | test__fixsfti(0.5, 0); | ||
| 52 | test__fixsfti(0.99, 0); | ||
| 53 | test__fixsfti(1.0, 1); | ||
| 54 | test__fixsfti(1.5, 1); | ||
| 55 | test__fixsfti(1.99, 1); | ||
| 56 | test__fixsfti(2.0, 2); | ||
| 57 | test__fixsfti(2.01, 2); | ||
| 58 | |||
| 59 | test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00); | ||
| 60 | test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80); | ||
| 61 | test__fixsfti(0x1.FFFFFFp+30, 0x80000000); | ||
| 62 | test__fixsfti(0x1.000000p+31, 0x80000000); | ||
| 63 | |||
| 64 | test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | ||
| 65 | test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | ||
| 66 | test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000); | ||
| 67 | |||
| 68 | test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); | ||
| 69 | test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); | ||
| 70 | test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000); | ||
| 71 | test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000); | ||
| 72 | |||
| 73 | test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); | ||
| 74 | test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); | ||
| 75 | test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 76 | test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 77 | test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 78 | test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 79 | |||
| 80 | test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 81 | test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | ||
| 82 | |||
| 83 | test__fixsfti(math.f32_max, math.maxInt(i128)); | ||
| 84 | } | ||
std/special/compiler_rt/fixtfdi.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixtfdi(a: f128) i64 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f128, i64, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixtfdi" { | ||
| 10 | _ = @import("fixtfdi_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixtfdi_test.zig created+76| ... | @@ -0,0 +1,76 @@ | ||
| 1 | const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixtfdi(a: f128, expected: i64) void { | ||
| 8 | const x = __fixtfdi(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u64, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixtfdi" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixtfdi(-math.f128_max, math.minInt(i64)); | ||
| 17 | |||
| 18 | test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | ||
| 19 | test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | ||
| 20 | |||
| 21 | test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000); | ||
| 22 | test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | ||
| 23 | test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | ||
| 24 | |||
| 25 | test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000); | ||
| 26 | test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000); | ||
| 27 | test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | ||
| 28 | test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | ||
| 29 | |||
| 30 | test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); | ||
| 31 | test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); | ||
| 32 | |||
| 33 | test__fixtfdi(-0x1.000000p+31, -0x80000000); | ||
| 34 | test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | ||
| 35 | test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80); | ||
| 36 | test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00); | ||
| 37 | |||
| 38 | test__fixtfdi(-2.01, -2); | ||
| 39 | test__fixtfdi(-2.0, -2); | ||
| 40 | test__fixtfdi(-1.99, -1); | ||
| 41 | test__fixtfdi(-1.0, -1); | ||
| 42 | test__fixtfdi(-0.99, 0); | ||
| 43 | test__fixtfdi(-0.5, 0); | ||
| 44 | test__fixtfdi(-math.f64_min, 0); | ||
| 45 | test__fixtfdi(0.0, 0); | ||
| 46 | test__fixtfdi(math.f64_min, 0); | ||
| 47 | test__fixtfdi(0.5, 0); | ||
| 48 | test__fixtfdi(0.99, 0); | ||
| 49 | test__fixtfdi(1.0, 1); | ||
| 50 | test__fixtfdi(1.5, 1); | ||
| 51 | test__fixtfdi(1.99, 1); | ||
| 52 | test__fixtfdi(2.0, 2); | ||
| 53 | test__fixtfdi(2.01, 2); | ||
| 54 | |||
| 55 | test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00); | ||
| 56 | test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80); | ||
| 57 | test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0); | ||
| 58 | test__fixtfdi(0x1.000000p+31, 0x80000000); | ||
| 59 | |||
| 60 | test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | ||
| 61 | test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | ||
| 62 | |||
| 63 | test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | ||
| 64 | test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | ||
| 65 | test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | ||
| 66 | test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | ||
| 67 | |||
| 68 | test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | ||
| 69 | test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | ||
| 70 | test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | ||
| 71 | |||
| 72 | test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | ||
| 73 | test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | ||
| 74 | |||
| 75 | test__fixtfdi(math.f128_max, math.maxInt(i64)); | ||
| 76 | } | ||
std/special/compiler_rt/fixtfsi.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixtfsi(a: f128) i32 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f128, i32, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixtfsi" { | ||
| 10 | _ = @import("fixtfsi_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixtfsi_test.zig created+76| ... | @@ -0,0 +1,76 @@ | ||
| 1 | const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixtfsi(a: f128, expected: i32) void { | ||
| 8 | const x = __fixtfsi(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u32, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixtfsi" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixtfsi(-math.f128_max, math.minInt(i32)); | ||
| 17 | |||
| 18 | test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | ||
| 19 | test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | ||
| 20 | |||
| 21 | test__fixtfsi(-0x1.0000000000000p+127, -0x80000000); | ||
| 22 | test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | ||
| 23 | test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | ||
| 24 | |||
| 25 | test__fixtfsi(-0x1.0000000000001p+63, -0x80000000); | ||
| 26 | test__fixtfsi(-0x1.0000000000000p+63, -0x80000000); | ||
| 27 | test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | ||
| 28 | test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | ||
| 29 | |||
| 30 | test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000); | ||
| 31 | test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000); | ||
| 32 | |||
| 33 | test__fixtfsi(-0x1.000000p+31, -0x80000000); | ||
| 34 | test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | ||
| 35 | test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | ||
| 36 | test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | ||
| 37 | |||
| 38 | test__fixtfsi(-2.01, -2); | ||
| 39 | test__fixtfsi(-2.0, -2); | ||
| 40 | test__fixtfsi(-1.99, -1); | ||
| 41 | test__fixtfsi(-1.0, -1); | ||
| 42 | test__fixtfsi(-0.99, 0); | ||
| 43 | test__fixtfsi(-0.5, 0); | ||
| 44 | test__fixtfsi(-math.f32_min, 0); | ||
| 45 | test__fixtfsi(0.0, 0); | ||
| 46 | test__fixtfsi(math.f32_min, 0); | ||
| 47 | test__fixtfsi(0.5, 0); | ||
| 48 | test__fixtfsi(0.99, 0); | ||
| 49 | test__fixtfsi(1.0, 1); | ||
| 50 | test__fixtfsi(1.5, 1); | ||
| 51 | test__fixtfsi(1.99, 1); | ||
| 52 | test__fixtfsi(2.0, 2); | ||
| 53 | test__fixtfsi(2.01, 2); | ||
| 54 | |||
| 55 | test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | ||
| 56 | test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | ||
| 57 | test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | ||
| 58 | test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF); | ||
| 59 | |||
| 60 | test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | ||
| 61 | test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | ||
| 62 | |||
| 63 | test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | ||
| 64 | test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | ||
| 65 | test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | ||
| 66 | test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | ||
| 67 | |||
| 68 | test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | ||
| 69 | test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | ||
| 70 | test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | ||
| 71 | |||
| 72 | test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | ||
| 73 | test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | ||
| 74 | |||
| 75 | test__fixtfsi(math.f128_max, math.maxInt(i32)); | ||
| 76 | } | ||
std/special/compiler_rt/fixtfti.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const fixint = @import("fixint.zig").fixint; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub extern fn __fixtfti(a: f128) i128 { | ||
| 5 | @setRuntimeSafety(builtin.is_test); | ||
| 6 | return fixint(f128, i128, a); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "import fixtfti" { | ||
| 10 | _ = @import("fixtfti_test.zig"); | ||
| 11 | } | ||
std/special/compiler_rt/fixtfti_test.zig created+66| ... | @@ -0,0 +1,66 @@ | ||
| 1 | const __fixtfti = @import("fixtfti.zig").__fixtfti; | ||
| 2 | const std = @import("std"); | ||
| 3 | const math = std.math; | ||
| 4 | const testing = std.testing; | ||
| 5 | const warn = std.debug.warn; | ||
| 6 | |||
| 7 | fn test__fixtfti(a: f128, expected: i128) void { | ||
| 8 | const x = __fixtfti(a); | ||
| 9 | //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u128, expected)); | ||
| 10 | testing.expect(x == expected); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "fixtfti" { | ||
| 14 | //warn("\n"); | ||
| 15 | |||
| 16 | test__fixtfti(-math.f128_max, math.minInt(i128)); | ||
| 17 | |||
| 18 | test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | ||
| 19 | test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | ||
| 20 | |||
| 21 | test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | ||
| 22 | test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | ||
| 23 | test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | ||
| 24 | |||
| 25 | test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800); | ||
| 26 | test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000); | ||
| 27 | test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | ||
| 28 | test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | ||
| 29 | |||
| 30 | test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | ||
| 31 | test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | ||
| 32 | |||
| 33 | test__fixtfti(-2.01, -2); | ||
| 34 | test__fixtfti(-2.0, -2); | ||
| 35 | test__fixtfti(-1.99, -1); | ||
| 36 | test__fixtfti(-1.0, -1); | ||
| 37 | test__fixtfti(-0.99, 0); | ||
| 38 | test__fixtfti(-0.5, 0); | ||
| 39 | test__fixtfti(-math.f128_min, 0); | ||
| 40 | test__fixtfti(0.0, 0); | ||
| 41 | test__fixtfti(math.f128_min, 0); | ||
| 42 | test__fixtfti(0.5, 0); | ||
| 43 | test__fixtfti(0.99, 0); | ||
| 44 | test__fixtfti(1.0, 1); | ||
| 45 | test__fixtfti(1.5, 1); | ||
| 46 | test__fixtfti(1.99, 1); | ||
| 47 | test__fixtfti(2.0, 2); | ||
| 48 | test__fixtfti(2.01, 2); | ||
| 49 | |||
| 50 | test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | ||
| 51 | test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | ||
| 52 | |||
| 53 | test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | ||
| 54 | test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | ||
| 55 | test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000); | ||
| 56 | test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800); | ||
| 57 | |||
| 58 | test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | ||
| 59 | test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | ||
| 60 | test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 61 | |||
| 62 | test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 63 | test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | ||
| 64 | |||
| 65 | test__fixtfti(math.f128_max, math.maxInt(i128)); | ||
| 66 | } | ||
std/special/compiler_rt/fixunsdfdi_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; | 1 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunsdfdi(a: f64, expected: u64) void { | 4 | fn test__fixunsdfdi(a: f64, expected: u64) void { |
| 5 | const x = __fixunsdfdi(a); | 5 | const x = __fixunsdfdi(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunsdfdi" { | 9 | test "fixunsdfdi" { |
std/special/compiler_rt/fixunsdfsi_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; | 1 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunsdfsi(a: f64, expected: u32) void { | 4 | fn test__fixunsdfsi(a: f64, expected: u32) void { |
| 5 | const x = __fixunsdfsi(a); | 5 | const x = __fixunsdfsi(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunsdfsi" { | 9 | test "fixunsdfsi" { |
std/special/compiler_rt/fixunsdfti_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; | 1 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunsdfti(a: f64, expected: u128) void { | 4 | fn test__fixunsdfti(a: f64, expected: u128) void { |
| 5 | const x = __fixunsdfti(a); | 5 | const x = __fixunsdfti(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunsdfti" { | 9 | test "fixunsdfti" { |
std/special/compiler_rt/fixunssfdi_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; | 1 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunssfdi(a: f32, expected: u64) void { | 4 | fn test__fixunssfdi(a: f32, expected: u64) void { |
| 5 | const x = __fixunssfdi(a); | 5 | const x = __fixunssfdi(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunssfdi" { | 9 | test "fixunssfdi" { |
std/special/compiler_rt/fixunssfsi_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; | 1 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunssfsi(a: f32, expected: u32) void { | 4 | fn test__fixunssfsi(a: f32, expected: u32) void { |
| 5 | const x = __fixunssfsi(a); | 5 | const x = __fixunssfsi(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunssfsi" { | 9 | test "fixunssfsi" { |
std/special/compiler_rt/fixunssfti_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; | 1 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunssfti(a: f32, expected: u128) void { | 4 | fn test__fixunssfti(a: f32, expected: u128) void { |
| 5 | const x = __fixunssfti(a); | 5 | const x = __fixunssfti(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunssfti" { | 9 | test "fixunssfti" { |
std/special/compiler_rt/fixunstfdi_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; | 1 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunstfdi(a: f128, expected: u64) void { | 4 | fn test__fixunstfdi(a: f128, expected: u64) void { |
| 5 | const x = __fixunstfdi(a); | 5 | const x = __fixunstfdi(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "fixunstfdi" { | 9 | test "fixunstfdi" { |
std/special/compiler_rt/fixunstfsi_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; | 1 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunstfsi(a: f128, expected: u32) void { | 4 | fn test__fixunstfsi(a: f128, expected: u32) void { |
| 5 | const x = __fixunstfsi(a); | 5 | const x = __fixunstfsi(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); | 9 | const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); |
std/special/compiler_rt/fixunstfti_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; | 1 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__fixunstfti(a: f128, expected: u128) void { | 4 | fn test__fixunstfti(a: f128, expected: u128) void { |
| 5 | const x = __fixunstfti(a); | 5 | const x = __fixunstfti(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); | 9 | const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); |
std/special/compiler_rt/floattidf_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __floattidf = @import("floattidf.zig").__floattidf; | 1 | const __floattidf = @import("floattidf.zig").__floattidf; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__floattidf(a: i128, expected: f64) void { | 4 | fn test__floattidf(a: i128, expected: f64) void { |
| 5 | const x = __floattidf(a); | 5 | const x = __floattidf(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "floattidf" { | 9 | test "floattidf" { |
std/special/compiler_rt/floattisf_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __floattisf = @import("floattisf.zig").__floattisf; | 1 | const __floattisf = @import("floattisf.zig").__floattisf; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__floattisf(a: i128, expected: f32) void { | 4 | fn test__floattisf(a: i128, expected: f32) void { |
| 5 | const x = __floattisf(a); | 5 | const x = __floattisf(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "floattisf" { | 9 | test "floattisf" { |
std/special/compiler_rt/floattitf_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __floattitf = @import("floattitf.zig").__floattitf; | 1 | const __floattitf = @import("floattitf.zig").__floattitf; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__floattitf(a: i128, expected: f128) void { | 4 | fn test__floattitf(a: i128, expected: f128) void { |
| 5 | const x = __floattitf(a); | 5 | const x = __floattitf(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "floattitf" { | 9 | test "floattitf" { |
std/special/compiler_rt/floatunditf_test.zig-1| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | const __floatunditf = @import("floatunditf.zig").__floatunditf; | 1 | const __floatunditf = @import("floatunditf.zig").__floatunditf; |
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | 2 | ||
| 4 | fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void { | 3 | fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void { |
| 5 | const x = __floatunditf(a); | 4 | const x = __floatunditf(a); |
std/special/compiler_rt/floatunsitf_test.zig-1| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; | 1 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; |
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | 2 | ||
| 4 | fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void { | 3 | fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void { |
| 5 | const x = __floatunsitf(a); | 4 | const x = __floatunsitf(a); |
std/special/compiler_rt/floatuntidf_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; | 1 | const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__floatuntidf(a: u128, expected: f64) void { | 4 | fn test__floatuntidf(a: u128, expected: f64) void { |
| 5 | const x = __floatuntidf(a); | 5 | const x = __floatuntidf(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "floatuntidf" { | 9 | test "floatuntidf" { |
std/special/compiler_rt/floatuntisf_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; | 1 | const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__floatuntisf(a: u128, expected: f32) void { | 4 | fn test__floatuntisf(a: u128, expected: f32) void { |
| 5 | const x = __floatuntisf(a); | 5 | const x = __floatuntisf(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "floatuntisf" { | 9 | test "floatuntisf" { |
std/special/compiler_rt/floatuntitf_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; | 1 | const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__floatuntitf(a: u128, expected: f128) void { | 4 | fn test__floatuntitf(a: u128, expected: f128) void { |
| 5 | const x = __floatuntitf(a); | 5 | const x = __floatuntitf(a); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "floatuntitf" { | 9 | test "floatuntitf" { |
std/special/compiler_rt/index.zig+17-2| ... | @@ -21,6 +21,9 @@ comptime { | ... | @@ -21,6 +21,9 @@ comptime { |
| 21 | 21 | ||
| 22 | @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); | 22 | @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); |
| 23 | 23 | ||
| 24 | @export("__addtf3", @import("addXf3.zig").__addtf3, linkage); | ||
| 25 | @export("__subtf3", @import("addXf3.zig").__subtf3, linkage); | ||
| 26 | |||
| 24 | @export("__floattitf", @import("floattitf.zig").__floattitf, linkage); | 27 | @export("__floattitf", @import("floattitf.zig").__floattitf, linkage); |
| 25 | @export("__floattidf", @import("floattidf.zig").__floattidf, linkage); | 28 | @export("__floattidf", @import("floattidf.zig").__floattidf, linkage); |
| 26 | @export("__floattisf", @import("floattisf.zig").__floattisf, linkage); | 29 | @export("__floattisf", @import("floattisf.zig").__floattisf, linkage); |
| ... | @@ -37,6 +40,7 @@ comptime { | ... | @@ -37,6 +40,7 @@ comptime { |
| 37 | @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage); | 40 | @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage); |
| 38 | 41 | ||
| 39 | @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage); | 42 | @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage); |
| 43 | @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage); | ||
| 40 | @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage); | 44 | @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage); |
| 41 | @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage); | 45 | @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage); |
| 42 | 46 | ||
| ... | @@ -52,6 +56,16 @@ comptime { | ... | @@ -52,6 +56,16 @@ comptime { |
| 52 | @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); | 56 | @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); |
| 53 | @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); | 57 | @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); |
| 54 | 58 | ||
| 59 | @export("__fixdfdi", @import("fixdfdi.zig").__fixdfdi, linkage); | ||
| 60 | @export("__fixdfsi", @import("fixdfsi.zig").__fixdfsi, linkage); | ||
| 61 | @export("__fixdfti", @import("fixdfti.zig").__fixdfti, linkage); | ||
| 62 | @export("__fixsfdi", @import("fixsfdi.zig").__fixsfdi, linkage); | ||
| 63 | @export("__fixsfsi", @import("fixsfsi.zig").__fixsfsi, linkage); | ||
| 64 | @export("__fixsfti", @import("fixsfti.zig").__fixsfti, linkage); | ||
| 65 | @export("__fixtfdi", @import("fixtfdi.zig").__fixtfdi, linkage); | ||
| 66 | @export("__fixtfsi", @import("fixtfsi.zig").__fixtfsi, linkage); | ||
| 67 | @export("__fixtfti", @import("fixtfti.zig").__fixtfti, linkage); | ||
| 68 | |||
| 55 | @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); | 69 | @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); |
| 56 | 70 | ||
| 57 | @export("__udivsi3", __udivsi3, linkage); | 71 | @export("__udivsi3", __udivsi3, linkage); |
| ... | @@ -100,6 +114,7 @@ comptime { | ... | @@ -100,6 +114,7 @@ comptime { |
| 100 | 114 | ||
| 101 | const std = @import("std"); | 115 | const std = @import("std"); |
| 102 | const assert = std.debug.assert; | 116 | const assert = std.debug.assert; |
| 117 | const testing = std.testing; | ||
| 103 | 118 | ||
| 104 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; | 119 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 105 | 120 | ||
| ... | @@ -407,7 +422,7 @@ test "test_umoddi3" { | ... | @@ -407,7 +422,7 @@ test "test_umoddi3" { |
| 407 | 422 | ||
| 408 | fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { | 423 | fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { |
| 409 | const r = __umoddi3(a, b); | 424 | const r = __umoddi3(a, b); |
| 410 | assert(r == expected_r); | 425 | testing.expect(r == expected_r); |
| 411 | } | 426 | } |
| 412 | 427 | ||
| 413 | test "test_udivsi3" { | 428 | test "test_udivsi3" { |
| ... | @@ -1081,5 +1096,5 @@ test "test_udivsi3" { | ... | @@ -1081,5 +1096,5 @@ test "test_udivsi3" { |
| 1081 | 1096 | ||
| 1082 | fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { | 1097 | fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { |
| 1083 | const q: u32 = __udivsi3(a, b); | 1098 | const q: u32 = __udivsi3(a, b); |
| 1084 | assert(q == expected_q); | 1099 | testing.expect(q == expected_q); |
| 1085 | } | 1100 | } |
std/special/compiler_rt/muloti4_test.zig+2-2| ... | @@ -1,10 +1,10 @@ | ... | @@ -1,10 +1,10 @@ |
| 1 | const __muloti4 = @import("muloti4.zig").__muloti4; | 1 | const __muloti4 = @import("muloti4.zig").__muloti4; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void { | 4 | fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void { |
| 5 | var overflow: c_int = undefined; | 5 | var overflow: c_int = undefined; |
| 6 | const x = __muloti4(a, b, &overflow); | 6 | const x = __muloti4(a, b, &overflow); |
| 7 | assert(overflow == expected_overflow and (expected_overflow != 0 or x == expected)); | 7 | testing.expect(overflow == expected_overflow and (expected_overflow != 0 or x == expected)); |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | test "muloti4" { | 10 | test "muloti4" { |
std/special/compiler_rt/multi3_test.zig+2-2| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | const __multi3 = @import("multi3.zig").__multi3; | 1 | const __multi3 = @import("multi3.zig").__multi3; |
| 2 | const assert = @import("std").debug.assert; | 2 | const testing = @import("std").testing; |
| 3 | 3 | ||
| 4 | fn test__multi3(a: i128, b: i128, expected: i128) void { | 4 | fn test__multi3(a: i128, b: i128, expected: i128) void { |
| 5 | const x = __multi3(a, b); | 5 | const x = __multi3(a, b); |
| 6 | assert(x == expected); | 6 | testing.expect(x == expected); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | test "multi3" { | 9 | test "multi3" { |
std/special/compiler_rt/truncXfYf2.zig+4| ... | @@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 { | ... | @@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 { |
| 4 | return @bitCast(u16, truncXfYf2(f16, f32, a)); | 4 | return @bitCast(u16, truncXfYf2(f16, f32, a)); |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | pub extern fn __truncdfhf2(a: f64) u16 { | ||
| 8 | return @bitCast(u16, truncXfYf2(f16, f64, a)); | ||
| 9 | } | ||
| 10 | |||
| 7 | pub extern fn __trunctfsf2(a: f128) f32 { | 11 | pub extern fn __trunctfsf2(a: f128) f32 { |
| 8 | return truncXfYf2(f32, f128, a); | 12 | return truncXfYf2(f32, f128, a); |
| 9 | } | 13 | } |
std/special/compiler_rt/truncXfYf2_test.zig+68| ... | @@ -63,6 +63,74 @@ test "truncsfhf2" { | ... | @@ -63,6 +63,74 @@ test "truncsfhf2" { |
| 63 | test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero | 63 | test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2; | ||
| 67 | |||
| 68 | fn test__truncdfhf2(a: f64, expected: u16) void { | ||
| 69 | const rep = @bitCast(u16, __truncdfhf2(a)); | ||
| 70 | |||
| 71 | if (rep == expected) { | ||
| 72 | return; | ||
| 73 | } | ||
| 74 | // test other possible NaN representation(signal NaN) | ||
| 75 | else if (expected == 0x7e00) { | ||
| 76 | if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) { | ||
| 77 | return; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | @panic("__truncdfhf2 test failure"); | ||
| 82 | } | ||
| 83 | |||
| 84 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { | ||
| 85 | const actual = __truncdfhf2(@bitCast(f64, a)); | ||
| 86 | |||
| 87 | if (actual == expected) { | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | |||
| 91 | @panic("__truncdfhf2 test failure"); | ||
| 92 | } | ||
| 93 | |||
| 94 | test "truncdfhf2" { | ||
| 95 | test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN | ||
| 96 | test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN | ||
| 97 | |||
| 98 | test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf | ||
| 99 | test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf | ||
| 100 | |||
| 101 | test__truncdfhf2(0.0, 0x0); // zero | ||
| 102 | test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero | ||
| 103 | |||
| 104 | test__truncdfhf2(3.1415926535, 0x4248); | ||
| 105 | test__truncdfhf2(-3.1415926535, 0xc248); | ||
| 106 | |||
| 107 | test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); | ||
| 108 | test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); | ||
| 109 | test__truncdfhf2(0x1.0p+0, 0x3c00); | ||
| 110 | test__truncdfhf2(0x1.0p-14, 0x0400); | ||
| 111 | |||
| 112 | // denormal | ||
| 113 | test__truncdfhf2(0x1.0p-20, 0x0010); | ||
| 114 | test__truncdfhf2(0x1.0p-24, 0x0001); | ||
| 115 | test__truncdfhf2(-0x1.0p-24, 0x8001); | ||
| 116 | test__truncdfhf2(0x1.5p-25, 0x0001); | ||
| 117 | |||
| 118 | // and back to zero | ||
| 119 | test__truncdfhf2(0x1.0p-25, 0x0000); | ||
| 120 | test__truncdfhf2(-0x1.0p-25, 0x8000); | ||
| 121 | |||
| 122 | // max (precise) | ||
| 123 | test__truncdfhf2(65504.0, 0x7bff); | ||
| 124 | |||
| 125 | // max (rounded) | ||
| 126 | test__truncdfhf2(65519.0, 0x7bff); | ||
| 127 | |||
| 128 | // max (to +inf) | ||
| 129 | test__truncdfhf2(65520.0, 0x7c00); | ||
| 130 | test__truncdfhf2(-65520.0, 0xfc00); | ||
| 131 | test__truncdfhf2(65536.0, 0x7c00); | ||
| 132 | } | ||
| 133 | |||
| 66 | const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2; | 134 | const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2; |
| 67 | 135 | ||
| 68 | fn test__trunctfsf2(a: f128, expected: u32) void { | 136 | fn test__trunctfsf2(a: f128, expected: u32) void { |
std/special/compiler_rt/udivmoddi4_test.zig+3-3| ... | @@ -1,13 +1,13 @@ | ... | @@ -1,13 +1,13 @@ |
| 1 | // Disable formatting to avoid unnecessary source repository bloat. | 1 | // Disable formatting to avoid unnecessary source repository bloat. |
| 2 | // zig fmt: off | 2 | // zig fmt: off |
| 3 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; | 3 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 4 | const assert = @import("std").debug.assert; | 4 | const testing = @import("std").testing; |
| 5 | 5 | ||
| 6 | fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void { | 6 | fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void { |
| 7 | var r: u64 = undefined; | 7 | var r: u64 = undefined; |
| 8 | const q = __udivmoddi4(a, b, &r); | 8 | const q = __udivmoddi4(a, b, &r); |
| 9 | assert(q == expected_q); | 9 | testing.expect(q == expected_q); |
| 10 | assert(r == expected_r); | 10 | testing.expect(r == expected_r); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | test "udivmoddi4" { | 13 | test "udivmoddi4" { |
std/special/compiler_rt/udivmodti4_test.zig+3-3| ... | @@ -1,13 +1,13 @@ | ... | @@ -1,13 +1,13 @@ |
| 1 | // Disable formatting to avoid unnecessary source repository bloat. | 1 | // Disable formatting to avoid unnecessary source repository bloat. |
| 2 | // zig fmt: off | 2 | // zig fmt: off |
| 3 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; | 3 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
| 4 | const assert = @import("std").debug.assert; | 4 | const testing = @import("std").testing; |
| 5 | 5 | ||
| 6 | fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void { | 6 | fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void { |
| 7 | var r: u128 = undefined; | 7 | var r: u128 = undefined; |
| 8 | const q = __udivmodti4(a, b, &r); | 8 | const q = __udivmodti4(a, b, &r); |
| 9 | assert(q == expected_q); | 9 | testing.expect(q == expected_q); |
| 10 | assert(r == expected_r); | 10 | testing.expect(r == expected_r); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | test "udivmodti4" { | 13 | test "udivmodti4" { |
std/special/fmt_runner.zig created+260| ... | @@ -0,0 +1,260 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | const os = std.os; | ||
| 5 | const io = std.io; | ||
| 6 | const mem = std.mem; | ||
| 7 | const Allocator = mem.Allocator; | ||
| 8 | const ArrayList = std.ArrayList; | ||
| 9 | const Buffer = std.Buffer; | ||
| 10 | const ast = std.zig.ast; | ||
| 11 | |||
| 12 | const arg = @import("fmt/arg.zig"); | ||
| 13 | const self_hosted_main = @import("fmt/main.zig"); | ||
| 14 | const Args = arg.Args; | ||
| 15 | const Flag = arg.Flag; | ||
| 16 | const errmsg = @import("fmt/errmsg.zig"); | ||
| 17 | |||
| 18 | var stderr_file: os.File = undefined; | ||
| 19 | var stderr: *io.OutStream(os.File.WriteError) = undefined; | ||
| 20 | var stdout: *io.OutStream(os.File.WriteError) = undefined; | ||
| 21 | |||
| 22 | // This brings `zig fmt` to stage 1. | ||
| 23 | pub fn main() !void { | ||
| 24 | // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived, | ||
| 25 | // one shot program. We don't need to waste time freeing memory and finding places to squish | ||
| 26 | // bytes into. So we free everything all at once at the very end. | ||
| 27 | var direct_allocator = std.heap.DirectAllocator.init(); | ||
| 28 | var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator); | ||
| 29 | const allocator = &arena.allocator; | ||
| 30 | |||
| 31 | var stdout_file = try std.io.getStdOut(); | ||
| 32 | var stdout_out_stream = stdout_file.outStream(); | ||
| 33 | stdout = &stdout_out_stream.stream; | ||
| 34 | |||
| 35 | stderr_file = try std.io.getStdErr(); | ||
| 36 | var stderr_out_stream = stderr_file.outStream(); | ||
| 37 | stderr = &stderr_out_stream.stream; | ||
| 38 | const args = try std.os.argsAlloc(allocator); | ||
| 39 | |||
| 40 | var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args); | ||
| 41 | defer flags.deinit(); | ||
| 42 | |||
| 43 | if (flags.present("help")) { | ||
| 44 | try stdout.write(self_hosted_main.usage_fmt); | ||
| 45 | os.exit(0); | ||
| 46 | } | ||
| 47 | |||
| 48 | const color = blk: { | ||
| 49 | if (flags.single("color")) |color_flag| { | ||
| 50 | if (mem.eql(u8, color_flag, "auto")) { | ||
| 51 | break :blk errmsg.Color.Auto; | ||
| 52 | } else if (mem.eql(u8, color_flag, "on")) { | ||
| 53 | break :blk errmsg.Color.On; | ||
| 54 | } else if (mem.eql(u8, color_flag, "off")) { | ||
| 55 | break :blk errmsg.Color.Off; | ||
| 56 | } else unreachable; | ||
| 57 | } else { | ||
| 58 | break :blk errmsg.Color.Auto; | ||
| 59 | } | ||
| 60 | }; | ||
| 61 | |||
| 62 | if (flags.present("stdin")) { | ||
| 63 | if (flags.positionals.len != 0) { | ||
| 64 | try stderr.write("cannot use --stdin with positional arguments\n"); | ||
| 65 | os.exit(1); | ||
| 66 | } | ||
| 67 | |||
| 68 | var stdin_file = try io.getStdIn(); | ||
| 69 | var stdin = stdin_file.inStream(); | ||
| 70 | |||
| 71 | const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size); | ||
| 72 | defer allocator.free(source_code); | ||
| 73 | |||
| 74 | var tree = std.zig.parse(allocator, source_code) catch |err| { | ||
| 75 | try stderr.print("error parsing stdin: {}\n", err); | ||
| 76 | os.exit(1); | ||
| 77 | }; | ||
| 78 | defer tree.deinit(); | ||
| 79 | |||
| 80 | var error_it = tree.errors.iterator(0); | ||
| 81 | while (error_it.next()) |parse_error| { | ||
| 82 | try printErrMsgToFile(allocator, parse_error, &tree, "<stdin>", stderr_file, color); | ||
| 83 | } | ||
| 84 | if (tree.errors.len != 0) { | ||
| 85 | os.exit(1); | ||
| 86 | } | ||
| 87 | if (flags.present("check")) { | ||
| 88 | const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree); | ||
| 89 | const code = if (anything_changed) u8(1) else u8(0); | ||
| 90 | os.exit(code); | ||
| 91 | } | ||
| 92 | |||
| 93 | _ = try std.zig.render(allocator, stdout, &tree); | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | |||
| 97 | if (flags.positionals.len == 0) { | ||
| 98 | try stderr.write("expected at least one source file argument\n"); | ||
| 99 | os.exit(1); | ||
| 100 | } | ||
| 101 | |||
| 102 | var fmt = Fmt{ | ||
| 103 | .seen = Fmt.SeenMap.init(allocator), | ||
| 104 | .any_error = false, | ||
| 105 | .color = color, | ||
| 106 | .allocator = allocator, | ||
| 107 | }; | ||
| 108 | |||
| 109 | const check_mode = flags.present("check"); | ||
| 110 | |||
| 111 | for (flags.positionals.toSliceConst()) |file_path| { | ||
| 112 | try fmtPath(&fmt, file_path, check_mode); | ||
| 113 | } | ||
| 114 | if (fmt.any_error) { | ||
| 115 | os.exit(1); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | const FmtError = error{ | ||
| 120 | SystemResources, | ||
| 121 | OperationAborted, | ||
| 122 | IoPending, | ||
| 123 | BrokenPipe, | ||
| 124 | Unexpected, | ||
| 125 | WouldBlock, | ||
| 126 | FileClosed, | ||
| 127 | DestinationAddressRequired, | ||
| 128 | DiskQuota, | ||
| 129 | FileTooBig, | ||
| 130 | InputOutput, | ||
| 131 | NoSpaceLeft, | ||
| 132 | AccessDenied, | ||
| 133 | OutOfMemory, | ||
| 134 | RenameAcrossMountPoints, | ||
| 135 | ReadOnlyFileSystem, | ||
| 136 | LinkQuotaExceeded, | ||
| 137 | FileBusy, | ||
| 138 | } || os.File.OpenError; | ||
| 139 | |||
| 140 | fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void { | ||
| 141 | const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref); | ||
| 142 | defer fmt.allocator.free(file_path); | ||
| 143 | |||
| 144 | if (try fmt.seen.put(file_path, {})) |_| return; | ||
| 145 | |||
| 146 | const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) { | ||
| 147 | error.IsDir, error.AccessDenied => { | ||
| 148 | // TODO make event based (and dir.next()) | ||
| 149 | var dir = try std.os.Dir.open(fmt.allocator, file_path); | ||
| 150 | defer dir.close(); | ||
| 151 | |||
| 152 | while (try dir.next()) |entry| { | ||
| 153 | if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { | ||
| 154 | const full_path = try os.path.join(fmt.allocator, [][]const u8{ file_path, entry.name }); | ||
| 155 | try fmtPath(fmt, full_path, check_mode); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | return; | ||
| 159 | }, | ||
| 160 | else => { | ||
| 161 | // TODO lock stderr printing | ||
| 162 | try stderr.print("unable to open '{}': {}\n", file_path, err); | ||
| 163 | fmt.any_error = true; | ||
| 164 | return; | ||
| 165 | }, | ||
| 166 | }; | ||
| 167 | defer fmt.allocator.free(source_code); | ||
| 168 | |||
| 169 | var tree = std.zig.parse(fmt.allocator, source_code) catch |err| { | ||
| 170 | try stderr.print("error parsing file '{}': {}\n", file_path, err); | ||
| 171 | fmt.any_error = true; | ||
| 172 | return; | ||
| 173 | }; | ||
| 174 | defer tree.deinit(); | ||
| 175 | |||
| 176 | var error_it = tree.errors.iterator(0); | ||
| 177 | while (error_it.next()) |parse_error| { | ||
| 178 | try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color); | ||
| 179 | } | ||
| 180 | if (tree.errors.len != 0) { | ||
| 181 | fmt.any_error = true; | ||
| 182 | return; | ||
| 183 | } | ||
| 184 | |||
| 185 | if (check_mode) { | ||
| 186 | const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree); | ||
| 187 | if (anything_changed) { | ||
| 188 | try stderr.print("{}\n", file_path); | ||
| 189 | fmt.any_error = true; | ||
| 190 | } | ||
| 191 | } else { | ||
| 192 | // TODO make this evented | ||
| 193 | const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path); | ||
| 194 | defer baf.destroy(); | ||
| 195 | |||
| 196 | const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree); | ||
| 197 | if (anything_changed) { | ||
| 198 | try stderr.print("{}\n", file_path); | ||
| 199 | try baf.finish(); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | const Fmt = struct { | ||
| 205 | seen: SeenMap, | ||
| 206 | any_error: bool, | ||
| 207 | color: errmsg.Color, | ||
| 208 | allocator: *mem.Allocator, | ||
| 209 | |||
| 210 | const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); | ||
| 211 | }; | ||
| 212 | |||
| 213 | fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree, | ||
| 214 | path: []const u8, file: os.File, color: errmsg.Color,) !void | ||
| 215 | { | ||
| 216 | const color_on = switch (color) { | ||
| 217 | errmsg.Color.Auto => file.isTty(), | ||
| 218 | errmsg.Color.On => true, | ||
| 219 | errmsg.Color.Off => false, | ||
| 220 | }; | ||
| 221 | const lok_token = parse_error.loc(); | ||
| 222 | const span = errmsg.Span{ | ||
| 223 | .first = lok_token, | ||
| 224 | .last = lok_token, | ||
| 225 | }; | ||
| 226 | |||
| 227 | const first_token = tree.tokens.at(span.first); | ||
| 228 | const last_token = tree.tokens.at(span.last); | ||
| 229 | const start_loc = tree.tokenLocationPtr(0, first_token); | ||
| 230 | const end_loc = tree.tokenLocationPtr(first_token.end, last_token); | ||
| 231 | |||
| 232 | var text_buf = try std.Buffer.initSize(allocator, 0); | ||
| 233 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; | ||
| 234 | try parse_error.render(&tree.tokens, out_stream); | ||
| 235 | const text = text_buf.toOwnedSlice(); | ||
| 236 | |||
| 237 | const stream = &file.outStream().stream; | ||
| 238 | if (!color_on) { | ||
| 239 | try stream.print( | ||
| 240 | "{}:{}:{}: error: {}\n", | ||
| 241 | path, | ||
| 242 | start_loc.line + 1, | ||
| 243 | start_loc.column + 1, | ||
| 244 | text, | ||
| 245 | ); | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 249 | try stream.print( | ||
| 250 | "{}:{}:{}: error: {}\n{}\n", | ||
| 251 | path, | ||
| 252 | start_loc.line + 1, | ||
| 253 | start_loc.column + 1, | ||
| 254 | text, | ||
| 255 | tree.source[start_loc.line_start..start_loc.line_end], | ||
| 256 | ); | ||
| 257 | try stream.writeByteNTimes(' ', start_loc.column); | ||
| 258 | try stream.writeByteNTimes('~', last_token.end - first_token.start); | ||
| 259 | try stream.write("\n"); | ||
| 260 | } | ||
std/special/init-lib/src/main.zig+2-2| ... | @@ -1,10 +1,10 @@ | ... | @@ -1,10 +1,10 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | 2 | const testing = std.testing; |
| 3 | 3 | ||
| 4 | export fn add(a: i32, b: i32) i32 { | 4 | export fn add(a: i32, b: i32) i32 { |
| 5 | return a + b; | 5 | return a + b; |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | test "basic add functionality" { | 8 | test "basic add functionality" { |
| 9 | assertOrPanic(add(3, 7) == 10); | 9 | testing.expect(add(3, 7) == 10); |
| 10 | } | 10 | } |
std/special/panic.zig+4| ... | @@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn | ... | @@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn |
| 13 | builtin.Os.freestanding, builtin.Os.zen => { | 13 | builtin.Os.freestanding, builtin.Os.zen => { |
| 14 | while (true) {} | 14 | while (true) {} |
| 15 | }, | 15 | }, |
| 16 | builtin.Os.uefi => { | ||
| 17 | // TODO look into using the debug info and logging helpful messages | ||
| 18 | std.os.abort(); | ||
| 19 | }, | ||
| 16 | else => { | 20 | else => { |
| 17 | const first_trace_addr = @ptrToInt(@returnAddress()); | 21 | const first_trace_addr = @ptrToInt(@returnAddress()); |
| 18 | std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg); | 22 | std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg); |
std/statically_initialized_mutex.zig created+111| ... | @@ -0,0 +1,111 @@ | ||
| 1 | const std = @import("index.zig"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const AtomicOrder = builtin.AtomicOrder; | ||
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | ||
| 5 | const assert = std.debug.assert; | ||
| 6 | const expect = std.testing.expect; | ||
| 7 | const windows = std.os.windows; | ||
| 8 | |||
| 9 | /// Lock may be held only once. If the same thread | ||
| 10 | /// tries to acquire the same mutex twice, it deadlocks. | ||
| 11 | /// This type is intended to be initialized statically. If you don't | ||
| 12 | /// require static initialization, use std.Mutex. | ||
| 13 | /// On Windows, this mutex allocates resources when it is | ||
| 14 | /// first used, and the resources cannot be freed. | ||
| 15 | /// On Linux, this is an alias of std.Mutex. | ||
| 16 | pub const StaticallyInitializedMutex = switch(builtin.os) { | ||
| 17 | builtin.Os.linux => std.Mutex, | ||
| 18 | builtin.Os.windows => struct { | ||
| 19 | lock: windows.CRITICAL_SECTION, | ||
| 20 | init_once: windows.RTL_RUN_ONCE, | ||
| 21 | |||
| 22 | pub const Held = struct { | ||
| 23 | mutex: *StaticallyInitializedMutex, | ||
| 24 | |||
| 25 | pub fn release(self: Held) void { | ||
| 26 | windows.LeaveCriticalSection(&self.mutex.lock); | ||
| 27 | } | ||
| 28 | }; | ||
| 29 | |||
| 30 | pub fn init() StaticallyInitializedMutex { | ||
| 31 | return StaticallyInitializedMutex { | ||
| 32 | .lock = undefined, | ||
| 33 | .init_once = windows.INIT_ONCE_STATIC_INIT, | ||
| 34 | }; | ||
| 35 | } | ||
| 36 | |||
| 37 | extern fn initCriticalSection( | ||
| 38 | InitOnce: *windows.RTL_RUN_ONCE, | ||
| 39 | Parameter: ?*c_void, | ||
| 40 | Context: ?*c_void, | ||
| 41 | ) windows.BOOL { | ||
| 42 | const lock = @ptrCast(*windows.CRITICAL_SECTION, @alignCast(@alignOf(windows.CRITICAL_SECTION), Parameter)); | ||
| 43 | windows.InitializeCriticalSection(lock); | ||
| 44 | return windows.TRUE; | ||
| 45 | } | ||
| 46 | |||
| 47 | /// TODO: once https://github.com/ziglang/zig/issues/287 is solved and std.Mutex has a better | ||
| 48 | /// implementation of a runtime initialized mutex, remove this function. | ||
| 49 | pub fn deinit(self: *StaticallyInitializedMutex) void { | ||
| 50 | assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0); | ||
| 51 | windows.DeleteCriticalSection(&self.lock); | ||
| 52 | } | ||
| 53 | |||
| 54 | pub fn acquire(self: *StaticallyInitializedMutex) Held { | ||
| 55 | assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0); | ||
| 56 | windows.EnterCriticalSection(&self.lock); | ||
| 57 | return Held { .mutex = self }; | ||
| 58 | } | ||
| 59 | }, | ||
| 60 | else => std.Mutex, | ||
| 61 | }; | ||
| 62 | |||
| 63 | test "std.StaticallyInitializedMutex" { | ||
| 64 | const TestContext = struct { | ||
| 65 | data: i128, | ||
| 66 | |||
| 67 | const TestContext = @This(); | ||
| 68 | const incr_count = 10000; | ||
| 69 | |||
| 70 | var mutex = StaticallyInitializedMutex.init(); | ||
| 71 | |||
| 72 | fn worker(ctx: *TestContext) void { | ||
| 73 | var i: usize = 0; | ||
| 74 | while (i != TestContext.incr_count) : (i += 1) { | ||
| 75 | const held = mutex.acquire(); | ||
| 76 | defer held.release(); | ||
| 77 | |||
| 78 | ctx.data += 1; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | |||
| 83 | var direct_allocator = std.heap.DirectAllocator.init(); | ||
| 84 | defer direct_allocator.deinit(); | ||
| 85 | |||
| 86 | var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024); | ||
| 87 | defer direct_allocator.allocator.free(plenty_of_memory); | ||
| 88 | |||
| 89 | var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory); | ||
| 90 | var a = &fixed_buffer_allocator.allocator; | ||
| 91 | |||
| 92 | |||
| 93 | var context = TestContext{ | ||
| 94 | .data = 0, | ||
| 95 | }; | ||
| 96 | |||
| 97 | if (builtin.single_threaded) { | ||
| 98 | TestContext.worker(&context); | ||
| 99 | expect(context.data == TestContext.incr_count); | ||
| 100 | } else { | ||
| 101 | const thread_count = 10; | ||
| 102 | var threads: [thread_count]*std.os.Thread = undefined; | ||
| 103 | for (threads) |*t| { | ||
| 104 | t.* = try std.os.spawnThread(&context, TestContext.worker); | ||
| 105 | } | ||
| 106 | for (threads) |t| | ||
| 107 | t.wait(); | ||
| 108 | |||
| 109 | expect(context.data == thread_count * TestContext.incr_count); | ||
| 110 | } | ||
| 111 | } | ||
std/testing.zig created+147| ... | @@ -0,0 +1,147 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const TypeId = builtin.TypeId; | ||
| 3 | const std = @import("index.zig"); | ||
| 4 | |||
| 5 | /// This function is intended to be used only in tests. It prints diagnostics to stderr | ||
| 6 | /// and then aborts when actual_error_union is not expected_error. | ||
| 7 | pub fn expectError(expected_error: anyerror, actual_error_union: var) void { | ||
| 8 | // TODO remove the workaround here for https://github.com/ziglang/zig/issues/1936 | ||
| 9 | if (actual_error_union) |actual_payload| { | ||
| 10 | // TODO remove workaround here for https://github.com/ziglang/zig/issues/557 | ||
| 11 | if (@sizeOf(@typeOf(actual_payload)) == 0) { | ||
| 12 | std.debug.panic("expected error.{}, found {} value", @errorName(expected_error), @typeName(@typeOf(actual_payload))); | ||
| 13 | } else { | ||
| 14 | std.debug.panic("expected error.{}, found {}", @errorName(expected_error), actual_payload); | ||
| 15 | } | ||
| 16 | } else |actual_error| { | ||
| 17 | if (expected_error != actual_error) { | ||
| 18 | std.debug.panic("expected error.{}, found error.{}", @errorName(expected_error), @errorName(actual_error)); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | /// This function is intended to be used only in tests. When the two values are not | ||
| 24 | /// equal, prints diagnostics to stderr to show exactly how they are not equal, | ||
| 25 | /// then aborts. | ||
| 26 | /// The types must match exactly. | ||
| 27 | pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { | ||
| 28 | switch (@typeInfo(@typeOf(actual))) { | ||
| 29 | TypeId.NoReturn, | ||
| 30 | TypeId.BoundFn, | ||
| 31 | TypeId.ArgTuple, | ||
| 32 | TypeId.Opaque, | ||
| 33 | => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"), | ||
| 34 | |||
| 35 | TypeId.Undefined, | ||
| 36 | TypeId.Null, | ||
| 37 | TypeId.Void, | ||
| 38 | => return, | ||
| 39 | |||
| 40 | TypeId.Type, | ||
| 41 | TypeId.Bool, | ||
| 42 | TypeId.Int, | ||
| 43 | TypeId.Float, | ||
| 44 | TypeId.ComptimeFloat, | ||
| 45 | TypeId.ComptimeInt, | ||
| 46 | TypeId.Enum, | ||
| 47 | TypeId.Namespace, | ||
| 48 | TypeId.Fn, | ||
| 49 | TypeId.Promise, | ||
| 50 | TypeId.Vector, | ||
| 51 | TypeId.ErrorSet, | ||
| 52 | => { | ||
| 53 | if (actual != expected) { | ||
| 54 | std.debug.panic("expected {}, found {}", expected, actual); | ||
| 55 | } | ||
| 56 | }, | ||
| 57 | |||
| 58 | TypeId.Pointer => |pointer| { | ||
| 59 | switch (pointer.size) { | ||
| 60 | builtin.TypeInfo.Pointer.Size.One, | ||
| 61 | builtin.TypeInfo.Pointer.Size.Many, | ||
| 62 | => { | ||
| 63 | if (actual != expected) { | ||
| 64 | std.debug.panic("expected {}, found {}", expected, actual); | ||
| 65 | } | ||
| 66 | }, | ||
| 67 | |||
| 68 | builtin.TypeInfo.Pointer.Size.Slice => { | ||
| 69 | if (actual.ptr != expected.ptr) { | ||
| 70 | std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr); | ||
| 71 | } | ||
| 72 | if (actual.len != expected.len) { | ||
| 73 | std.debug.panic("expected slice len {}, found {}", expected.len, actual.len); | ||
| 74 | } | ||
| 75 | }, | ||
| 76 | } | ||
| 77 | }, | ||
| 78 | |||
| 79 | TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual), | ||
| 80 | |||
| 81 | TypeId.Struct => { | ||
| 82 | @compileError("TODO implement testing.expectEqual for structs"); | ||
| 83 | }, | ||
| 84 | |||
| 85 | TypeId.Union => |union_info| { | ||
| 86 | if (union_info.tag_type == null) { | ||
| 87 | @compileError("Unable to compare untagged union values"); | ||
| 88 | } | ||
| 89 | @compileError("TODO implement testing.expectEqual for tagged unions"); | ||
| 90 | }, | ||
| 91 | |||
| 92 | TypeId.Optional => { | ||
| 93 | if (expected) |expected_payload| { | ||
| 94 | if (actual) |actual_payload| { | ||
| 95 | expectEqual(expected_payload, actual_payload); | ||
| 96 | } else { | ||
| 97 | std.debug.panic("expected {}, found null", expected_payload); | ||
| 98 | } | ||
| 99 | } else { | ||
| 100 | if (actual) |actual_payload| { | ||
| 101 | std.debug.panic("expected null, found {}", actual_payload); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | }, | ||
| 105 | |||
| 106 | TypeId.ErrorUnion => { | ||
| 107 | if (expected) |expected_payload| { | ||
| 108 | if (actual) |actual_payload| { | ||
| 109 | expectEqual(expected_payload, actual_payload); | ||
| 110 | } else |actual_err| { | ||
| 111 | std.debug.panic("expected {}, found {}", expected_payload, actual_err); | ||
| 112 | } | ||
| 113 | } else |expected_err| { | ||
| 114 | if (actual) |actual_payload| { | ||
| 115 | std.debug.panic("expected {}, found {}", expected_err, actual_payload); | ||
| 116 | } else |actual_err| { | ||
| 117 | expectEqual(expected_err, actual_err); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | }, | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | /// This function is intended to be used only in tests. When the two slices are not | ||
| 125 | /// equal, prints diagnostics to stderr to show exactly how they are not equal, | ||
| 126 | /// then aborts. | ||
| 127 | pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) void { | ||
| 128 | // TODO better printing of the difference | ||
| 129 | // If the arrays are small enough we could print the whole thing | ||
| 130 | // If the child type is u8 and no weird bytes, we could print it as strings | ||
| 131 | // Even for the length difference, it would be useful to see the values of the slices probably. | ||
| 132 | if (expected.len != actual.len) { | ||
| 133 | std.debug.panic("slice lengths differ. expected {}, found {}", expected.len, actual.len); | ||
| 134 | } | ||
| 135 | var i: usize = 0; | ||
| 136 | while (i < expected.len) : (i += 1) { | ||
| 137 | if (expected[i] != actual[i]) { | ||
| 138 | std.debug.panic("index {} incorrect. expected {}, found {}", i, expected[i], actual[i]); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /// This function is intended to be used only in tests. When `ok` is false, the test fails. | ||
| 144 | /// A message is printed to stderr and then abort is called. | ||
| 145 | pub fn expect(ok: bool) void { | ||
| 146 | if (!ok) @panic("test failure"); | ||
| 147 | } | ||
std/unicode.zig+68-81| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const std = @import("./index.zig"); | 1 | const std = @import("./index.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | ||
| 4 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | ||
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | 6 | ||
| 7 | /// Returns how many bytes the UTF-8 representation would require | 7 | /// Returns how many bytes the UTF-8 representation would require |
| ... | @@ -32,7 +32,7 @@ pub fn utf8ByteSequenceLength(first_byte: u8) !u3 { | ... | @@ -32,7 +32,7 @@ pub fn utf8ByteSequenceLength(first_byte: u8) !u3 { |
| 32 | /// Returns: the number of bytes written to out. | 32 | /// Returns: the number of bytes written to out. |
| 33 | pub fn utf8Encode(c: u32, out: []u8) !u3 { | 33 | pub fn utf8Encode(c: u32, out: []u8) !u3 { |
| 34 | const length = try utf8CodepointSequenceLength(c); | 34 | const length = try utf8CodepointSequenceLength(c); |
| 35 | debug.assert(out.len >= length); | 35 | assert(out.len >= length); |
| 36 | switch (length) { | 36 | switch (length) { |
| 37 | // The pattern for each is the same | 37 | // The pattern for each is the same |
| 38 | // - Increasing the initial shift by 6 each time | 38 | // - Increasing the initial shift by 6 each time |
| ... | @@ -81,8 +81,8 @@ const Utf8Decode2Error = error{ | ... | @@ -81,8 +81,8 @@ const Utf8Decode2Error = error{ |
| 81 | Utf8OverlongEncoding, | 81 | Utf8OverlongEncoding, |
| 82 | }; | 82 | }; |
| 83 | pub fn utf8Decode2(bytes: []const u8) Utf8Decode2Error!u32 { | 83 | pub fn utf8Decode2(bytes: []const u8) Utf8Decode2Error!u32 { |
| 84 | debug.assert(bytes.len == 2); | 84 | assert(bytes.len == 2); |
| 85 | debug.assert(bytes[0] & 0b11100000 == 0b11000000); | 85 | assert(bytes[0] & 0b11100000 == 0b11000000); |
| 86 | var value: u32 = bytes[0] & 0b00011111; | 86 | var value: u32 = bytes[0] & 0b00011111; |
| 87 | 87 | ||
| 88 | if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation; | 88 | if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation; |
| ... | @@ -100,8 +100,8 @@ const Utf8Decode3Error = error{ | ... | @@ -100,8 +100,8 @@ const Utf8Decode3Error = error{ |
| 100 | Utf8EncodesSurrogateHalf, | 100 | Utf8EncodesSurrogateHalf, |
| 101 | }; | 101 | }; |
| 102 | pub fn utf8Decode3(bytes: []const u8) Utf8Decode3Error!u32 { | 102 | pub fn utf8Decode3(bytes: []const u8) Utf8Decode3Error!u32 { |
| 103 | debug.assert(bytes.len == 3); | 103 | assert(bytes.len == 3); |
| 104 | debug.assert(bytes[0] & 0b11110000 == 0b11100000); | 104 | assert(bytes[0] & 0b11110000 == 0b11100000); |
| 105 | var value: u32 = bytes[0] & 0b00001111; | 105 | var value: u32 = bytes[0] & 0b00001111; |
| 106 | 106 | ||
| 107 | if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation; | 107 | if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation; |
| ... | @@ -124,8 +124,8 @@ const Utf8Decode4Error = error{ | ... | @@ -124,8 +124,8 @@ const Utf8Decode4Error = error{ |
| 124 | Utf8CodepointTooLarge, | 124 | Utf8CodepointTooLarge, |
| 125 | }; | 125 | }; |
| 126 | pub fn utf8Decode4(bytes: []const u8) Utf8Decode4Error!u32 { | 126 | pub fn utf8Decode4(bytes: []const u8) Utf8Decode4Error!u32 { |
| 127 | debug.assert(bytes.len == 4); | 127 | assert(bytes.len == 4); |
| 128 | debug.assert(bytes[0] & 0b11111000 == 0b11110000); | 128 | assert(bytes[0] & 0b11111000 == 0b11110000); |
| 129 | var value: u32 = bytes[0] & 0b00000111; | 129 | var value: u32 = bytes[0] & 0b00000111; |
| 130 | 130 | ||
| 131 | if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation; | 131 | if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation; |
| ... | @@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct { | ... | @@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct { |
| 249 | pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 { | 249 | pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 { |
| 250 | assert(it.i <= it.bytes.len); | 250 | assert(it.i <= it.bytes.len); |
| 251 | if (it.i == it.bytes.len) return null; | 251 | if (it.i == it.bytes.len) return null; |
| 252 | const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]); | 252 | const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]); |
| 253 | if (c0 & ~u32(0x03ff) == 0xd800) { | 253 | if (c0 & ~u32(0x03ff) == 0xd800) { |
| 254 | // surrogate pair | 254 | // surrogate pair |
| 255 | it.i += 2; | 255 | it.i += 2; |
| 256 | if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf; | 256 | if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf; |
| 257 | const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]); | 257 | const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]); |
| 258 | if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf; | 258 | if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf; |
| 259 | it.i += 2; | 259 | it.i += 2; |
| 260 | return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)); | 260 | return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)); |
| ... | @@ -274,23 +274,23 @@ test "utf8 encode" { | ... | @@ -274,23 +274,23 @@ test "utf8 encode" { |
| 274 | fn testUtf8Encode() !void { | 274 | fn testUtf8Encode() !void { |
| 275 | // A few taken from wikipedia a few taken elsewhere | 275 | // A few taken from wikipedia a few taken elsewhere |
| 276 | var array: [4]u8 = undefined; | 276 | var array: [4]u8 = undefined; |
| 277 | debug.assert((try utf8Encode(try utf8Decode("€"), array[0..])) == 3); | 277 | testing.expect((try utf8Encode(try utf8Decode("€"), array[0..])) == 3); |
| 278 | debug.assert(array[0] == 0b11100010); | 278 | testing.expect(array[0] == 0b11100010); |
| 279 | debug.assert(array[1] == 0b10000010); | 279 | testing.expect(array[1] == 0b10000010); |
| 280 | debug.assert(array[2] == 0b10101100); | 280 | testing.expect(array[2] == 0b10101100); |
| 281 | 281 | ||
| 282 | debug.assert((try utf8Encode(try utf8Decode("$"), array[0..])) == 1); | 282 | testing.expect((try utf8Encode(try utf8Decode("$"), array[0..])) == 1); |
| 283 | debug.assert(array[0] == 0b00100100); | 283 | testing.expect(array[0] == 0b00100100); |
| 284 | 284 | ||
| 285 | debug.assert((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2); | 285 | testing.expect((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2); |
| 286 | debug.assert(array[0] == 0b11000010); | 286 | testing.expect(array[0] == 0b11000010); |
| 287 | debug.assert(array[1] == 0b10100010); | 287 | testing.expect(array[1] == 0b10100010); |
| 288 | 288 | ||
| 289 | debug.assert((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4); | 289 | testing.expect((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4); |
| 290 | debug.assert(array[0] == 0b11110000); | 290 | testing.expect(array[0] == 0b11110000); |
| 291 | debug.assert(array[1] == 0b10010000); | 291 | testing.expect(array[1] == 0b10010000); |
| 292 | debug.assert(array[2] == 0b10001101); | 292 | testing.expect(array[2] == 0b10001101); |
| 293 | debug.assert(array[3] == 0b10001000); | 293 | testing.expect(array[3] == 0b10001000); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | test "utf8 encode error" { | 296 | test "utf8 encode error" { |
| ... | @@ -306,11 +306,7 @@ fn testUtf8EncodeError() void { | ... | @@ -306,11 +306,7 @@ fn testUtf8EncodeError() void { |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | fn testErrorEncode(codePoint: u32, array: []u8, expectedErr: anyerror) void { | 308 | fn testErrorEncode(codePoint: u32, array: []u8, expectedErr: anyerror) void { |
| 309 | if (utf8Encode(codePoint, array)) |_| { | 309 | testing.expectError(expectedErr, utf8Encode(codePoint, array)); |
| 310 | unreachable; | ||
| 311 | } else |err| { | ||
| 312 | debug.assert(err == expectedErr); | ||
| 313 | } | ||
| 314 | } | 310 | } |
| 315 | 311 | ||
| 316 | test "utf8 iterator on ascii" { | 312 | test "utf8 iterator on ascii" { |
| ... | @@ -321,16 +317,16 @@ fn testUtf8IteratorOnAscii() void { | ... | @@ -321,16 +317,16 @@ fn testUtf8IteratorOnAscii() void { |
| 321 | const s = Utf8View.initComptime("abc"); | 317 | const s = Utf8View.initComptime("abc"); |
| 322 | 318 | ||
| 323 | var it1 = s.iterator(); | 319 | var it1 = s.iterator(); |
| 324 | debug.assert(std.mem.eql(u8, "a", it1.nextCodepointSlice().?)); | 320 | testing.expect(std.mem.eql(u8, "a", it1.nextCodepointSlice().?)); |
| 325 | debug.assert(std.mem.eql(u8, "b", it1.nextCodepointSlice().?)); | 321 | testing.expect(std.mem.eql(u8, "b", it1.nextCodepointSlice().?)); |
| 326 | debug.assert(std.mem.eql(u8, "c", it1.nextCodepointSlice().?)); | 322 | testing.expect(std.mem.eql(u8, "c", it1.nextCodepointSlice().?)); |
| 327 | debug.assert(it1.nextCodepointSlice() == null); | 323 | testing.expect(it1.nextCodepointSlice() == null); |
| 328 | 324 | ||
| 329 | var it2 = s.iterator(); | 325 | var it2 = s.iterator(); |
| 330 | debug.assert(it2.nextCodepoint().? == 'a'); | 326 | testing.expect(it2.nextCodepoint().? == 'a'); |
| 331 | debug.assert(it2.nextCodepoint().? == 'b'); | 327 | testing.expect(it2.nextCodepoint().? == 'b'); |
| 332 | debug.assert(it2.nextCodepoint().? == 'c'); | 328 | testing.expect(it2.nextCodepoint().? == 'c'); |
| 333 | debug.assert(it2.nextCodepoint() == null); | 329 | testing.expect(it2.nextCodepoint() == null); |
| 334 | } | 330 | } |
| 335 | 331 | ||
| 336 | test "utf8 view bad" { | 332 | test "utf8 view bad" { |
| ... | @@ -340,12 +336,7 @@ test "utf8 view bad" { | ... | @@ -340,12 +336,7 @@ test "utf8 view bad" { |
| 340 | fn testUtf8ViewBad() void { | 336 | fn testUtf8ViewBad() void { |
| 341 | // Compile-time error. | 337 | // Compile-time error. |
| 342 | // const s3 = Utf8View.initComptime("\xfe\xf2"); | 338 | // const s3 = Utf8View.initComptime("\xfe\xf2"); |
| 343 | const s = Utf8View.init("hel\xadlo"); | 339 | testing.expectError(error.InvalidUtf8, Utf8View.init("hel\xadlo")); |
| 344 | if (s) |_| { | ||
| 345 | unreachable; | ||
| 346 | } else |err| { | ||
| 347 | debug.assert(err == error.InvalidUtf8); | ||
| 348 | } | ||
| 349 | } | 340 | } |
| 350 | 341 | ||
| 351 | test "utf8 view ok" { | 342 | test "utf8 view ok" { |
| ... | @@ -356,16 +347,16 @@ fn testUtf8ViewOk() void { | ... | @@ -356,16 +347,16 @@ fn testUtf8ViewOk() void { |
| 356 | const s = Utf8View.initComptime("東京市"); | 347 | const s = Utf8View.initComptime("東京市"); |
| 357 | 348 | ||
| 358 | var it1 = s.iterator(); | 349 | var it1 = s.iterator(); |
| 359 | debug.assert(std.mem.eql(u8, "東", it1.nextCodepointSlice().?)); | 350 | testing.expect(std.mem.eql(u8, "東", it1.nextCodepointSlice().?)); |
| 360 | debug.assert(std.mem.eql(u8, "京", it1.nextCodepointSlice().?)); | 351 | testing.expect(std.mem.eql(u8, "京", it1.nextCodepointSlice().?)); |
| 361 | debug.assert(std.mem.eql(u8, "市", it1.nextCodepointSlice().?)); | 352 | testing.expect(std.mem.eql(u8, "市", it1.nextCodepointSlice().?)); |
| 362 | debug.assert(it1.nextCodepointSlice() == null); | 353 | testing.expect(it1.nextCodepointSlice() == null); |
| 363 | 354 | ||
| 364 | var it2 = s.iterator(); | 355 | var it2 = s.iterator(); |
| 365 | debug.assert(it2.nextCodepoint().? == 0x6771); | 356 | testing.expect(it2.nextCodepoint().? == 0x6771); |
| 366 | debug.assert(it2.nextCodepoint().? == 0x4eac); | 357 | testing.expect(it2.nextCodepoint().? == 0x4eac); |
| 367 | debug.assert(it2.nextCodepoint().? == 0x5e02); | 358 | testing.expect(it2.nextCodepoint().? == 0x5e02); |
| 368 | debug.assert(it2.nextCodepoint() == null); | 359 | testing.expect(it2.nextCodepoint() == null); |
| 369 | } | 360 | } |
| 370 | 361 | ||
| 371 | test "bad utf8 slice" { | 362 | test "bad utf8 slice" { |
| ... | @@ -373,10 +364,10 @@ test "bad utf8 slice" { | ... | @@ -373,10 +364,10 @@ test "bad utf8 slice" { |
| 373 | testBadUtf8Slice(); | 364 | testBadUtf8Slice(); |
| 374 | } | 365 | } |
| 375 | fn testBadUtf8Slice() void { | 366 | fn testBadUtf8Slice() void { |
| 376 | debug.assert(utf8ValidateSlice("abc")); | 367 | testing.expect(utf8ValidateSlice("abc")); |
| 377 | debug.assert(!utf8ValidateSlice("abc\xc0")); | 368 | testing.expect(!utf8ValidateSlice("abc\xc0")); |
| 378 | debug.assert(!utf8ValidateSlice("abc\xc0abc")); | 369 | testing.expect(!utf8ValidateSlice("abc\xc0abc")); |
| 379 | debug.assert(utf8ValidateSlice("abc\xdf\xbf")); | 370 | testing.expect(utf8ValidateSlice("abc\xdf\xbf")); |
| 380 | } | 371 | } |
| 381 | 372 | ||
| 382 | test "valid utf8" { | 373 | test "valid utf8" { |
| ... | @@ -459,21 +450,17 @@ fn testMiscInvalidUtf8() void { | ... | @@ -459,21 +450,17 @@ fn testMiscInvalidUtf8() void { |
| 459 | } | 450 | } |
| 460 | 451 | ||
| 461 | fn testError(bytes: []const u8, expected_err: anyerror) void { | 452 | fn testError(bytes: []const u8, expected_err: anyerror) void { |
| 462 | if (testDecode(bytes)) |_| { | 453 | testing.expectError(expected_err, testDecode(bytes)); |
| 463 | unreachable; | ||
| 464 | } else |err| { | ||
| 465 | debug.assert(err == expected_err); | ||
| 466 | } | ||
| 467 | } | 454 | } |
| 468 | 455 | ||
| 469 | fn testValid(bytes: []const u8, expected_codepoint: u32) void { | 456 | fn testValid(bytes: []const u8, expected_codepoint: u32) void { |
| 470 | debug.assert((testDecode(bytes) catch unreachable) == expected_codepoint); | 457 | testing.expect((testDecode(bytes) catch unreachable) == expected_codepoint); |
| 471 | } | 458 | } |
| 472 | 459 | ||
| 473 | fn testDecode(bytes: []const u8) !u32 { | 460 | fn testDecode(bytes: []const u8) !u32 { |
| 474 | const length = try utf8ByteSequenceLength(bytes[0]); | 461 | const length = try utf8ByteSequenceLength(bytes[0]); |
| 475 | if (bytes.len < length) return error.UnexpectedEof; | 462 | if (bytes.len < length) return error.UnexpectedEof; |
| 476 | debug.assert(bytes.len == length); | 463 | testing.expect(bytes.len == length); |
| 477 | return utf8Decode(bytes); | 464 | return utf8Decode(bytes); |
| 478 | } | 465 | } |
| 479 | 466 | ||
| ... | @@ -510,48 +497,48 @@ test "utf16leToUtf8" { | ... | @@ -510,48 +497,48 @@ test "utf16leToUtf8" { |
| 510 | const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); | 497 | const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); |
| 511 | 498 | ||
| 512 | { | 499 | { |
| 513 | mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little); | 500 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A'); |
| 514 | mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little); | 501 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a'); |
| 515 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 502 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 516 | assert(mem.eql(u8, utf8, "Aa")); | 503 | testing.expect(mem.eql(u8, utf8, "Aa")); |
| 517 | } | 504 | } |
| 518 | 505 | ||
| 519 | { | 506 | { |
| 520 | mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little); | 507 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80); |
| 521 | mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little); | 508 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff); |
| 522 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 509 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 523 | assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf")); | 510 | testing.expect(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf")); |
| 524 | } | 511 | } |
| 525 | 512 | ||
| 526 | { | 513 | { |
| 527 | // the values just outside the surrogate half range | 514 | // the values just outside the surrogate half range |
| 528 | mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little); | 515 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff); |
| 529 | mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little); | 516 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000); |
| 530 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 517 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 531 | assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80")); | 518 | testing.expect(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80")); |
| 532 | } | 519 | } |
| 533 | 520 | ||
| 534 | { | 521 | { |
| 535 | // smallest surrogate pair | 522 | // smallest surrogate pair |
| 536 | mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little); | 523 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800); |
| 537 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); | 524 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); |
| 538 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 525 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 539 | assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80")); | 526 | testing.expect(mem.eql(u8, utf8, "\xf0\x90\x80\x80")); |
| 540 | } | 527 | } |
| 541 | 528 | ||
| 542 | { | 529 | { |
| 543 | // largest surrogate pair | 530 | // largest surrogate pair |
| 544 | mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); | 531 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); |
| 545 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little); | 532 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff); |
| 546 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 533 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 547 | assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf")); | 534 | testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf")); |
| 548 | } | 535 | } |
| 549 | 536 | ||
| 550 | { | 537 | { |
| 551 | mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); | 538 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); |
| 552 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); | 539 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); |
| 553 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 540 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 554 | assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80")); | 541 | testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80")); |
| 555 | } | 542 | } |
| 556 | } | 543 | } |
| 557 | 544 | ||
| ... | @@ -583,7 +570,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize { | ... | @@ -583,7 +570,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize { |
| 583 | while (it.nextCodepoint()) |codepoint| { | 570 | while (it.nextCodepoint()) |codepoint| { |
| 584 | if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1; | 571 | if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1; |
| 585 | // TODO surrogate pairs | 572 | // TODO surrogate pairs |
| 586 | mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little); | 573 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint)); |
| 587 | end_index += 2; | 574 | end_index += 2; |
| 588 | } | 575 | } |
| 589 | return end_index / 2; | 576 | return end_index / 2; |
std/zig/ast.zig+8-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("../index.zig"); | 1 | const std = @import("../index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | ||
| 3 | const SegmentedList = std.SegmentedList; | 4 | const SegmentedList = std.SegmentedList; |
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const Token = std.zig.Token; | 6 | const Token = std.zig.Token; |
| ... | @@ -109,6 +110,7 @@ pub const Tree = struct { | ... | @@ -109,6 +110,7 @@ pub const Tree = struct { |
| 109 | pub const Error = union(enum) { | 110 | pub const Error = union(enum) { |
| 110 | InvalidToken: InvalidToken, | 111 | InvalidToken: InvalidToken, |
| 111 | ExpectedVarDeclOrFn: ExpectedVarDeclOrFn, | 112 | ExpectedVarDeclOrFn: ExpectedVarDeclOrFn, |
| 113 | ExpectedVarDecl: ExpectedVarDecl, | ||
| 112 | ExpectedAggregateKw: ExpectedAggregateKw, | 114 | ExpectedAggregateKw: ExpectedAggregateKw, |
| 113 | UnattachedDocComment: UnattachedDocComment, | 115 | UnattachedDocComment: UnattachedDocComment, |
| 114 | ExpectedEqOrSemi: ExpectedEqOrSemi, | 116 | ExpectedEqOrSemi: ExpectedEqOrSemi, |
| ... | @@ -132,6 +134,7 @@ pub const Error = union(enum) { | ... | @@ -132,6 +134,7 @@ pub const Error = union(enum) { |
| 132 | // TODO https://github.com/ziglang/zig/issues/683 | 134 | // TODO https://github.com/ziglang/zig/issues/683 |
| 133 | @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream), | 135 | @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream), |
| 134 | @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), | 136 | @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), |
| 137 | @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream), | ||
| 135 | @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream), | 138 | @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream), |
| 136 | @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream), | 139 | @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream), |
| 137 | @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream), | 140 | @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream), |
| ... | @@ -157,6 +160,7 @@ pub const Error = union(enum) { | ... | @@ -157,6 +160,7 @@ pub const Error = union(enum) { |
| 157 | // TODO https://github.com/ziglang/zig/issues/683 | 160 | // TODO https://github.com/ziglang/zig/issues/683 |
| 158 | @TagType(Error).InvalidToken => |x| return x.token, | 161 | @TagType(Error).InvalidToken => |x| return x.token, |
| 159 | @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token, | 162 | @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token, |
| 163 | @TagType(Error).ExpectedVarDecl => |x| return x.token, | ||
| 160 | @TagType(Error).ExpectedAggregateKw => |x| return x.token, | 164 | @TagType(Error).ExpectedAggregateKw => |x| return x.token, |
| 161 | @TagType(Error).UnattachedDocComment => |x| return x.token, | 165 | @TagType(Error).UnattachedDocComment => |x| return x.token, |
| 162 | @TagType(Error).ExpectedEqOrSemi => |x| return x.token, | 166 | @TagType(Error).ExpectedEqOrSemi => |x| return x.token, |
| ... | @@ -179,6 +183,7 @@ pub const Error = union(enum) { | ... | @@ -179,6 +183,7 @@ pub const Error = union(enum) { |
| 179 | 183 | ||
| 180 | pub const InvalidToken = SingleTokenError("Invalid token {}"); | 184 | pub const InvalidToken = SingleTokenError("Invalid token {}"); |
| 181 | pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}"); | 185 | pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}"); |
| 186 | pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}"); | ||
| 182 | pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}"); | 187 | pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}"); |
| 183 | pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}"); | 188 | pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}"); |
| 184 | pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}"); | 189 | pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}"); |
| ... | @@ -495,6 +500,7 @@ pub const Node = struct { | ... | @@ -495,6 +500,7 @@ pub const Node = struct { |
| 495 | base: Node, | 500 | base: Node, |
| 496 | doc_comments: ?*DocComment, | 501 | doc_comments: ?*DocComment, |
| 497 | visib_token: ?TokenIndex, | 502 | visib_token: ?TokenIndex, |
| 503 | thread_local_token: ?TokenIndex, | ||
| 498 | name_token: TokenIndex, | 504 | name_token: TokenIndex, |
| 499 | eq_token: TokenIndex, | 505 | eq_token: TokenIndex, |
| 500 | mut_token: TokenIndex, | 506 | mut_token: TokenIndex, |
| ... | @@ -535,6 +541,7 @@ pub const Node = struct { | ... | @@ -535,6 +541,7 @@ pub const Node = struct { |
| 535 | 541 | ||
| 536 | pub fn firstToken(self: *const VarDecl) TokenIndex { | 542 | pub fn firstToken(self: *const VarDecl) TokenIndex { |
| 537 | if (self.visib_token) |visib_token| return visib_token; | 543 | if (self.visib_token) |visib_token| return visib_token; |
| 544 | if (self.thread_local_token) |thread_local_token| return thread_local_token; | ||
| 538 | if (self.comptime_token) |comptime_token| return comptime_token; | 545 | if (self.comptime_token) |comptime_token| return comptime_token; |
| 539 | if (self.extern_export_token) |extern_export_token| return extern_export_token; | 546 | if (self.extern_export_token) |extern_export_token| return extern_export_token; |
| 540 | assert(self.lib_name == null); | 547 | assert(self.lib_name == null); |
| ... | @@ -2224,5 +2231,5 @@ test "iterate" { | ... | @@ -2224,5 +2231,5 @@ test "iterate" { |
| 2224 | .shebang = null, | 2231 | .shebang = null, |
| 2225 | }; | 2232 | }; |
| 2226 | var base = &root.base; | 2233 | var base = &root.base; |
| 2227 | assert(base.iterate(0) == null); | 2234 | testing.expect(base.iterate(0) == null); |
| 2228 | } | 2235 | } |
std/zig/parse.zig+286-151| ... | @@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 17 | defer stack.deinit(); | 17 | defer stack.deinit(); |
| 18 | 18 | ||
| 19 | const arena = &tree_arena.allocator; | 19 | const arena = &tree_arena.allocator; |
| 20 | const root_node = try arena.create(ast.Node.Root{ | 20 | const root_node = try arena.create(ast.Node.Root); |
| 21 | root_node.* = ast.Node.Root{ | ||
| 21 | .base = ast.Node{ .id = ast.Node.Id.Root }, | 22 | .base = ast.Node{ .id = ast.Node.Id.Root }, |
| 22 | .decls = ast.Node.Root.DeclList.init(arena), | 23 | .decls = ast.Node.Root.DeclList.init(arena), |
| 23 | .doc_comments = null, | 24 | .doc_comments = null, |
| 24 | .shebang = null, | 25 | .shebang = null, |
| 25 | // initialized when we get the eof token | 26 | // initialized when we get the eof token |
| 26 | .eof_token = undefined, | 27 | .eof_token = undefined, |
| 27 | }); | 28 | }; |
| 28 | 29 | ||
| 29 | var tree = ast.Tree{ | 30 | var tree = ast.Tree{ |
| 30 | .source = source, | 31 | .source = source, |
| ... | @@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 75 | Token.Id.Keyword_test => { | 76 | Token.Id.Keyword_test => { |
| 76 | stack.append(State.TopLevel) catch unreachable; | 77 | stack.append(State.TopLevel) catch unreachable; |
| 77 | 78 | ||
| 78 | const block = try arena.create(ast.Node.Block{ | 79 | const block = try arena.create(ast.Node.Block); |
| 80 | block.* = ast.Node.Block{ | ||
| 79 | .base = ast.Node{ .id = ast.Node.Id.Block }, | 81 | .base = ast.Node{ .id = ast.Node.Id.Block }, |
| 80 | .label = null, | 82 | .label = null, |
| 81 | .lbrace = undefined, | 83 | .lbrace = undefined, |
| 82 | .statements = ast.Node.Block.StatementList.init(arena), | 84 | .statements = ast.Node.Block.StatementList.init(arena), |
| 83 | .rbrace = undefined, | 85 | .rbrace = undefined, |
| 84 | }); | 86 | }; |
| 85 | const test_node = try arena.create(ast.Node.TestDecl{ | 87 | const test_node = try arena.create(ast.Node.TestDecl); |
| 88 | test_node.* = ast.Node.TestDecl{ | ||
| 86 | .base = ast.Node{ .id = ast.Node.Id.TestDecl }, | 89 | .base = ast.Node{ .id = ast.Node.Id.TestDecl }, |
| 87 | .doc_comments = comments, | 90 | .doc_comments = comments, |
| 88 | .test_token = token_index, | 91 | .test_token = token_index, |
| 89 | .name = undefined, | 92 | .name = undefined, |
| 90 | .body_node = &block.base, | 93 | .body_node = &block.base, |
| 91 | }); | 94 | }; |
| 92 | try root_node.decls.push(&test_node.base); | 95 | try root_node.decls.push(&test_node.base); |
| 93 | try stack.append(State{ .Block = block }); | 96 | try stack.append(State{ .Block = block }); |
| 94 | try stack.append(State{ | 97 | try stack.append(State{ |
| ... | @@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 119 | continue; | 122 | continue; |
| 120 | }, | 123 | }, |
| 121 | Token.Id.Keyword_comptime => { | 124 | Token.Id.Keyword_comptime => { |
| 122 | const block = try arena.create(ast.Node.Block{ | 125 | const block = try arena.create(ast.Node.Block); |
| 126 | block.* = ast.Node.Block{ | ||
| 123 | .base = ast.Node{ .id = ast.Node.Id.Block }, | 127 | .base = ast.Node{ .id = ast.Node.Id.Block }, |
| 124 | .label = null, | 128 | .label = null, |
| 125 | .lbrace = undefined, | 129 | .lbrace = undefined, |
| 126 | .statements = ast.Node.Block.StatementList.init(arena), | 130 | .statements = ast.Node.Block.StatementList.init(arena), |
| 127 | .rbrace = undefined, | 131 | .rbrace = undefined, |
| 128 | }); | 132 | }; |
| 129 | const node = try arena.create(ast.Node.Comptime{ | 133 | const node = try arena.create(ast.Node.Comptime); |
| 134 | node.* = ast.Node.Comptime{ | ||
| 130 | .base = ast.Node{ .id = ast.Node.Id.Comptime }, | 135 | .base = ast.Node{ .id = ast.Node.Id.Comptime }, |
| 131 | .comptime_token = token_index, | 136 | .comptime_token = token_index, |
| 132 | .expr = &block.base, | 137 | .expr = &block.base, |
| 133 | .doc_comments = comments, | 138 | .doc_comments = comments, |
| 134 | }); | 139 | }; |
| 135 | try root_node.decls.push(&node.base); | 140 | try root_node.decls.push(&node.base); |
| 136 | 141 | ||
| 137 | stack.append(State.TopLevel) catch unreachable; | 142 | stack.append(State.TopLevel) catch unreachable; |
| ... | @@ -224,6 +229,32 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -224,6 +229,32 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 224 | }) catch unreachable; | 229 | }) catch unreachable; |
| 225 | continue; | 230 | continue; |
| 226 | }, | 231 | }, |
| 232 | State.ThreadLocal => |ctx| { | ||
| 233 | const token = nextToken(&tok_it, &tree); | ||
| 234 | const token_index = token.index; | ||
| 235 | const token_ptr = token.ptr; | ||
| 236 | switch (token_ptr.id) { | ||
| 237 | Token.Id.Keyword_var, Token.Id.Keyword_const => { | ||
| 238 | try stack.append(State{ | ||
| 239 | .VarDecl = VarDeclCtx{ | ||
| 240 | .comments = ctx.comments, | ||
| 241 | .visib_token = ctx.visib_token, | ||
| 242 | .thread_local_token = ctx.thread_local_token, | ||
| 243 | .lib_name = ctx.lib_name, | ||
| 244 | .comptime_token = ctx.comptime_token, | ||
| 245 | .extern_export_token = ctx.extern_export_token, | ||
| 246 | .mut_token = token_index, | ||
| 247 | .list = ctx.list, | ||
| 248 | }, | ||
| 249 | }); | ||
| 250 | continue; | ||
| 251 | }, | ||
| 252 | else => { | ||
| 253 | ((try tree.errors.addOne())).* = Error{ .ExpectedVarDecl = Error.ExpectedVarDecl{ .token = token_index } }; | ||
| 254 | return tree; | ||
| 255 | }, | ||
| 256 | } | ||
| 257 | }, | ||
| 227 | State.TopLevelDecl => |ctx| { | 258 | State.TopLevelDecl => |ctx| { |
| 228 | const token = nextToken(&tok_it, &tree); | 259 | const token = nextToken(&tok_it, &tree); |
| 229 | const token_index = token.index; | 260 | const token_index = token.index; |
| ... | @@ -235,14 +266,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -235,14 +266,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 235 | return tree; | 266 | return tree; |
| 236 | } | 267 | } |
| 237 | 268 | ||
| 238 | const node = try arena.create(ast.Node.Use{ | 269 | const node = try arena.create(ast.Node.Use); |
| 270 | node.* = ast.Node.Use{ | ||
| 239 | .base = ast.Node{ .id = ast.Node.Id.Use }, | 271 | .base = ast.Node{ .id = ast.Node.Id.Use }, |
| 240 | .use_token = token_index, | 272 | .use_token = token_index, |
| 241 | .visib_token = ctx.visib_token, | 273 | .visib_token = ctx.visib_token, |
| 242 | .expr = undefined, | 274 | .expr = undefined, |
| 243 | .semicolon_token = undefined, | 275 | .semicolon_token = undefined, |
| 244 | .doc_comments = ctx.comments, | 276 | .doc_comments = ctx.comments, |
| 245 | }); | 277 | }; |
| 246 | try ctx.decls.push(&node.base); | 278 | try ctx.decls.push(&node.base); |
| 247 | 279 | ||
| 248 | stack.append(State{ | 280 | stack.append(State{ |
| ... | @@ -254,6 +286,28 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -254,6 +286,28 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 254 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | 286 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); |
| 255 | continue; | 287 | continue; |
| 256 | }, | 288 | }, |
| 289 | Token.Id.Keyword_threadlocal => { | ||
| 290 | if (ctx.extern_export_inline_token) |annotated_token| { | ||
| 291 | if (annotated_token.ptr.id == Token.Id.Keyword_inline) { | ||
| 292 | ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } }; | ||
| 293 | return tree; | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | try stack.append(State{ | ||
| 298 | .ThreadLocal = VarDeclCtx{ | ||
| 299 | .comments = ctx.comments, | ||
| 300 | .visib_token = ctx.visib_token, | ||
| 301 | .thread_local_token = token_index, | ||
| 302 | .lib_name = ctx.lib_name, | ||
| 303 | .comptime_token = null, | ||
| 304 | .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, | ||
| 305 | .mut_token = undefined, | ||
| 306 | .list = ctx.decls, | ||
| 307 | }, | ||
| 308 | }); | ||
| 309 | continue; | ||
| 310 | }, | ||
| 257 | Token.Id.Keyword_var, Token.Id.Keyword_const => { | 311 | Token.Id.Keyword_var, Token.Id.Keyword_const => { |
| 258 | if (ctx.extern_export_inline_token) |annotated_token| { | 312 | if (ctx.extern_export_inline_token) |annotated_token| { |
| 259 | if (annotated_token.ptr.id == Token.Id.Keyword_inline) { | 313 | if (annotated_token.ptr.id == Token.Id.Keyword_inline) { |
| ... | @@ -266,6 +320,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -266,6 +320,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 266 | .VarDecl = VarDeclCtx{ | 320 | .VarDecl = VarDeclCtx{ |
| 267 | .comments = ctx.comments, | 321 | .comments = ctx.comments, |
| 268 | .visib_token = ctx.visib_token, | 322 | .visib_token = ctx.visib_token, |
| 323 | .thread_local_token = null, | ||
| 269 | .lib_name = ctx.lib_name, | 324 | .lib_name = ctx.lib_name, |
| 270 | .comptime_token = null, | 325 | .comptime_token = null, |
| 271 | .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, | 326 | .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, |
| ... | @@ -276,7 +331,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -276,7 +331,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 276 | continue; | 331 | continue; |
| 277 | }, | 332 | }, |
| 278 | Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => { | 333 | Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => { |
| 279 | const fn_proto = try arena.create(ast.Node.FnProto{ | 334 | const fn_proto = try arena.create(ast.Node.FnProto); |
| 335 | fn_proto.* = ast.Node.FnProto{ | ||
| 280 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | 336 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, |
| 281 | .doc_comments = ctx.comments, | 337 | .doc_comments = ctx.comments, |
| 282 | .visib_token = ctx.visib_token, | 338 | .visib_token = ctx.visib_token, |
| ... | @@ -292,7 +348,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -292,7 +348,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 292 | .lib_name = ctx.lib_name, | 348 | .lib_name = ctx.lib_name, |
| 293 | .align_expr = null, | 349 | .align_expr = null, |
| 294 | .section_expr = null, | 350 | .section_expr = null, |
| 295 | }); | 351 | }; |
| 296 | try ctx.decls.push(&fn_proto.base); | 352 | try ctx.decls.push(&fn_proto.base); |
| 297 | stack.append(State{ .FnDef = fn_proto }) catch unreachable; | 353 | stack.append(State{ .FnDef = fn_proto }) catch unreachable; |
| 298 | try stack.append(State{ .FnProto = fn_proto }); | 354 | try stack.append(State{ .FnProto = fn_proto }); |
| ... | @@ -309,12 +365,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -309,12 +365,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 309 | continue; | 365 | continue; |
| 310 | }, | 366 | }, |
| 311 | Token.Id.Keyword_async => { | 367 | Token.Id.Keyword_async => { |
| 312 | const async_node = try arena.create(ast.Node.AsyncAttribute{ | 368 | const async_node = try arena.create(ast.Node.AsyncAttribute); |
| 369 | async_node.* = ast.Node.AsyncAttribute{ | ||
| 313 | .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, | 370 | .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, |
| 314 | .async_token = token_index, | 371 | .async_token = token_index, |
| 315 | .allocator_type = null, | 372 | .allocator_type = null, |
| 316 | .rangle_bracket = null, | 373 | .rangle_bracket = null, |
| 317 | }); | 374 | }; |
| 318 | fn_proto.async_attr = async_node; | 375 | fn_proto.async_attr = async_node; |
| 319 | 376 | ||
| 320 | try stack.append(State{ | 377 | try stack.append(State{ |
| ... | @@ -341,13 +398,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -341,13 +398,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 341 | }, | 398 | }, |
| 342 | State.TopLevelExternOrField => |ctx| { | 399 | State.TopLevelExternOrField => |ctx| { |
| 343 | if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| { | 400 | if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| { |
| 344 | const node = try arena.create(ast.Node.StructField{ | 401 | const node = try arena.create(ast.Node.StructField); |
| 402 | node.* = ast.Node.StructField{ | ||
| 345 | .base = ast.Node{ .id = ast.Node.Id.StructField }, | 403 | .base = ast.Node{ .id = ast.Node.Id.StructField }, |
| 346 | .doc_comments = ctx.comments, | 404 | .doc_comments = ctx.comments, |
| 347 | .visib_token = ctx.visib_token, | 405 | .visib_token = ctx.visib_token, |
| 348 | .name_token = identifier, | 406 | .name_token = identifier, |
| 349 | .type_expr = undefined, | 407 | .type_expr = undefined, |
| 350 | }); | 408 | }; |
| 351 | const node_ptr = try ctx.container_decl.fields_and_decls.addOne(); | 409 | const node_ptr = try ctx.container_decl.fields_and_decls.addOne(); |
| 352 | node_ptr.* = &node.base; | 410 | node_ptr.* = &node.base; |
| 353 | 411 | ||
| ... | @@ -391,7 +449,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -391,7 +449,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 391 | const token = nextToken(&tok_it, &tree); | 449 | const token = nextToken(&tok_it, &tree); |
| 392 | const token_index = token.index; | 450 | const token_index = token.index; |
| 393 | const token_ptr = token.ptr; | 451 | const token_ptr = token.ptr; |
| 394 | const node = try arena.create(ast.Node.ContainerDecl{ | 452 | const node = try arena.create(ast.Node.ContainerDecl); |
| 453 | node.* = ast.Node.ContainerDecl{ | ||
| 395 | .base = ast.Node{ .id = ast.Node.Id.ContainerDecl }, | 454 | .base = ast.Node{ .id = ast.Node.Id.ContainerDecl }, |
| 396 | .layout_token = ctx.layout_token, | 455 | .layout_token = ctx.layout_token, |
| 397 | .kind_token = switch (token_ptr.id) { | 456 | .kind_token = switch (token_ptr.id) { |
| ... | @@ -405,7 +464,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -405,7 +464,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 405 | .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena), | 464 | .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena), |
| 406 | .lbrace_token = undefined, | 465 | .lbrace_token = undefined, |
| 407 | .rbrace_token = undefined, | 466 | .rbrace_token = undefined, |
| 408 | }); | 467 | }; |
| 409 | ctx.opt_ctx.store(&node.base); | 468 | ctx.opt_ctx.store(&node.base); |
| 410 | 469 | ||
| 411 | stack.append(State{ .ContainerDecl = node }) catch unreachable; | 470 | stack.append(State{ .ContainerDecl = node }) catch unreachable; |
| ... | @@ -464,13 +523,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -464,13 +523,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 464 | Token.Id.Identifier => { | 523 | Token.Id.Identifier => { |
| 465 | switch (tree.tokens.at(container_decl.kind_token).id) { | 524 | switch (tree.tokens.at(container_decl.kind_token).id) { |
| 466 | Token.Id.Keyword_struct => { | 525 | Token.Id.Keyword_struct => { |
| 467 | const node = try arena.create(ast.Node.StructField{ | 526 | const node = try arena.create(ast.Node.StructField); |
| 527 | node.* = ast.Node.StructField{ | ||
| 468 | .base = ast.Node{ .id = ast.Node.Id.StructField }, | 528 | .base = ast.Node{ .id = ast.Node.Id.StructField }, |
| 469 | .doc_comments = comments, | 529 | .doc_comments = comments, |
| 470 | .visib_token = null, | 530 | .visib_token = null, |
| 471 | .name_token = token_index, | 531 | .name_token = token_index, |
| 472 | .type_expr = undefined, | 532 | .type_expr = undefined, |
| 473 | }); | 533 | }; |
| 474 | const node_ptr = try container_decl.fields_and_decls.addOne(); | 534 | const node_ptr = try container_decl.fields_and_decls.addOne(); |
| 475 | node_ptr.* = &node.base; | 535 | node_ptr.* = &node.base; |
| 476 | 536 | ||
| ... | @@ -485,13 +545,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -485,13 +545,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 485 | continue; | 545 | continue; |
| 486 | }, | 546 | }, |
| 487 | Token.Id.Keyword_union => { | 547 | Token.Id.Keyword_union => { |
| 488 | const node = try arena.create(ast.Node.UnionTag{ | 548 | const node = try arena.create(ast.Node.UnionTag); |
| 549 | node.* = ast.Node.UnionTag{ | ||
| 489 | .base = ast.Node{ .id = ast.Node.Id.UnionTag }, | 550 | .base = ast.Node{ .id = ast.Node.Id.UnionTag }, |
| 490 | .name_token = token_index, | 551 | .name_token = token_index, |
| 491 | .type_expr = null, | 552 | .type_expr = null, |
| 492 | .value_expr = null, | 553 | .value_expr = null, |
| 493 | .doc_comments = comments, | 554 | .doc_comments = comments, |
| 494 | }); | 555 | }; |
| 495 | try container_decl.fields_and_decls.push(&node.base); | 556 | try container_decl.fields_and_decls.push(&node.base); |
| 496 | 557 | ||
| 497 | try stack.append(State{ | 558 | try stack.append(State{ |
| ... | @@ -506,12 +567,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -506,12 +567,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 506 | continue; | 567 | continue; |
| 507 | }, | 568 | }, |
| 508 | Token.Id.Keyword_enum => { | 569 | Token.Id.Keyword_enum => { |
| 509 | const node = try arena.create(ast.Node.EnumTag{ | 570 | const node = try arena.create(ast.Node.EnumTag); |
| 571 | node.* = ast.Node.EnumTag{ | ||
| 510 | .base = ast.Node{ .id = ast.Node.Id.EnumTag }, | 572 | .base = ast.Node{ .id = ast.Node.Id.EnumTag }, |
| 511 | .name_token = token_index, | 573 | .name_token = token_index, |
| 512 | .value = null, | 574 | .value = null, |
| 513 | .doc_comments = comments, | 575 | .doc_comments = comments, |
| 514 | }); | 576 | }; |
| 515 | try container_decl.fields_and_decls.push(&node.base); | 577 | try container_decl.fields_and_decls.push(&node.base); |
| 516 | 578 | ||
| 517 | try stack.append(State{ | 579 | try stack.append(State{ |
| ... | @@ -593,10 +655,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -593,10 +655,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 593 | }, | 655 | }, |
| 594 | 656 | ||
| 595 | State.VarDecl => |ctx| { | 657 | State.VarDecl => |ctx| { |
| 596 | const var_decl = try arena.create(ast.Node.VarDecl{ | 658 | const var_decl = try arena.create(ast.Node.VarDecl); |
| 659 | var_decl.* = ast.Node.VarDecl{ | ||
| 597 | .base = ast.Node{ .id = ast.Node.Id.VarDecl }, | 660 | .base = ast.Node{ .id = ast.Node.Id.VarDecl }, |
| 598 | .doc_comments = ctx.comments, | 661 | .doc_comments = ctx.comments, |
| 599 | .visib_token = ctx.visib_token, | 662 | .visib_token = ctx.visib_token, |
| 663 | .thread_local_token = ctx.thread_local_token, | ||
| 600 | .mut_token = ctx.mut_token, | 664 | .mut_token = ctx.mut_token, |
| 601 | .comptime_token = ctx.comptime_token, | 665 | .comptime_token = ctx.comptime_token, |
| 602 | .extern_export_token = ctx.extern_export_token, | 666 | .extern_export_token = ctx.extern_export_token, |
| ... | @@ -609,7 +673,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -609,7 +673,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 609 | .name_token = undefined, | 673 | .name_token = undefined, |
| 610 | .eq_token = undefined, | 674 | .eq_token = undefined, |
| 611 | .semicolon_token = undefined, | 675 | .semicolon_token = undefined, |
| 612 | }); | 676 | }; |
| 613 | try ctx.list.push(&var_decl.base); | 677 | try ctx.list.push(&var_decl.base); |
| 614 | 678 | ||
| 615 | try stack.append(State{ .VarDeclAlign = var_decl }); | 679 | try stack.append(State{ .VarDeclAlign = var_decl }); |
| ... | @@ -708,13 +772,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -708,13 +772,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 708 | const token_ptr = token.ptr; | 772 | const token_ptr = token.ptr; |
| 709 | switch (token_ptr.id) { | 773 | switch (token_ptr.id) { |
| 710 | Token.Id.LBrace => { | 774 | Token.Id.LBrace => { |
| 711 | const block = try arena.create(ast.Node.Block{ | 775 | const block = try arena.create(ast.Node.Block); |
| 776 | block.* = ast.Node.Block{ | ||
| 712 | .base = ast.Node{ .id = ast.Node.Id.Block }, | 777 | .base = ast.Node{ .id = ast.Node.Id.Block }, |
| 713 | .label = null, | 778 | .label = null, |
| 714 | .lbrace = token_index, | 779 | .lbrace = token_index, |
| 715 | .statements = ast.Node.Block.StatementList.init(arena), | 780 | .statements = ast.Node.Block.StatementList.init(arena), |
| 716 | .rbrace = undefined, | 781 | .rbrace = undefined, |
| 717 | }); | 782 | }; |
| 718 | fn_proto.body_node = &block.base; | 783 | fn_proto.body_node = &block.base; |
| 719 | stack.append(State{ .Block = block }) catch unreachable; | 784 | stack.append(State{ .Block = block }) catch unreachable; |
| 720 | continue; | 785 | continue; |
| ... | @@ -770,10 +835,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -770,10 +835,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 770 | // TODO: this is a special case. Remove this when #760 is fixed | 835 | // TODO: this is a special case. Remove this when #760 is fixed |
| 771 | if (token_ptr.id == Token.Id.Keyword_anyerror) { | 836 | if (token_ptr.id == Token.Id.Keyword_anyerror) { |
| 772 | if (tok_it.peek().?.id == Token.Id.LBrace) { | 837 | if (tok_it.peek().?.id == Token.Id.LBrace) { |
| 773 | const error_type_node = try arena.create(ast.Node.ErrorType{ | 838 | const error_type_node = try arena.create(ast.Node.ErrorType); |
| 839 | error_type_node.* = ast.Node.ErrorType{ | ||
| 774 | .base = ast.Node{ .id = ast.Node.Id.ErrorType }, | 840 | .base = ast.Node{ .id = ast.Node.Id.ErrorType }, |
| 775 | .token = token_index, | 841 | .token = token_index, |
| 776 | }); | 842 | }; |
| 777 | fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base }; | 843 | fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base }; |
| 778 | continue; | 844 | continue; |
| 779 | } | 845 | } |
| ... | @@ -791,14 +857,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -791,14 +857,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 791 | if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| { | 857 | if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| { |
| 792 | continue; | 858 | continue; |
| 793 | } | 859 | } |
| 794 | const param_decl = try arena.create(ast.Node.ParamDecl{ | 860 | const param_decl = try arena.create(ast.Node.ParamDecl); |
| 861 | param_decl.* = ast.Node.ParamDecl{ | ||
| 795 | .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, | 862 | .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, |
| 796 | .comptime_token = null, | 863 | .comptime_token = null, |
| 797 | .noalias_token = null, | 864 | .noalias_token = null, |
| 798 | .name_token = null, | 865 | .name_token = null, |
| 799 | .type_node = undefined, | 866 | .type_node = undefined, |
| 800 | .var_args_token = null, | 867 | .var_args_token = null, |
| 801 | }); | 868 | }; |
| 802 | try fn_proto.params.push(&param_decl.base); | 869 | try fn_proto.params.push(&param_decl.base); |
| 803 | 870 | ||
| 804 | stack.append(State{ | 871 | stack.append(State{ |
| ... | @@ -877,13 +944,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -877,13 +944,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 877 | const token_ptr = token.ptr; | 944 | const token_ptr = token.ptr; |
| 878 | switch (token_ptr.id) { | 945 | switch (token_ptr.id) { |
| 879 | Token.Id.LBrace => { | 946 | Token.Id.LBrace => { |
| 880 | const block = try arena.create(ast.Node.Block{ | 947 | const block = try arena.create(ast.Node.Block); |
| 948 | block.* = ast.Node.Block{ | ||
| 881 | .base = ast.Node{ .id = ast.Node.Id.Block }, | 949 | .base = ast.Node{ .id = ast.Node.Id.Block }, |
| 882 | .label = ctx.label, | 950 | .label = ctx.label, |
| 883 | .lbrace = token_index, | 951 | .lbrace = token_index, |
| 884 | .statements = ast.Node.Block.StatementList.init(arena), | 952 | .statements = ast.Node.Block.StatementList.init(arena), |
| 885 | .rbrace = undefined, | 953 | .rbrace = undefined, |
| 886 | }); | 954 | }; |
| 887 | ctx.opt_ctx.store(&block.base); | 955 | ctx.opt_ctx.store(&block.base); |
| 888 | stack.append(State{ .Block = block }) catch unreachable; | 956 | stack.append(State{ .Block = block }) catch unreachable; |
| 889 | continue; | 957 | continue; |
| ... | @@ -970,7 +1038,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -970,7 +1038,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 970 | } | 1038 | } |
| 971 | }, | 1039 | }, |
| 972 | State.While => |ctx| { | 1040 | State.While => |ctx| { |
| 973 | const node = try arena.create(ast.Node.While{ | 1041 | const node = try arena.create(ast.Node.While); |
| 1042 | node.* = ast.Node.While{ | ||
| 974 | .base = ast.Node{ .id = ast.Node.Id.While }, | 1043 | .base = ast.Node{ .id = ast.Node.Id.While }, |
| 975 | .label = ctx.label, | 1044 | .label = ctx.label, |
| 976 | .inline_token = ctx.inline_token, | 1045 | .inline_token = ctx.inline_token, |
| ... | @@ -980,7 +1049,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -980,7 +1049,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 980 | .continue_expr = null, | 1049 | .continue_expr = null, |
| 981 | .body = undefined, | 1050 | .body = undefined, |
| 982 | .@"else" = null, | 1051 | .@"else" = null, |
| 983 | }); | 1052 | }; |
| 984 | ctx.opt_ctx.store(&node.base); | 1053 | ctx.opt_ctx.store(&node.base); |
| 985 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; | 1054 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; |
| 986 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); | 1055 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); |
| ... | @@ -999,7 +1068,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -999,7 +1068,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 999 | continue; | 1068 | continue; |
| 1000 | }, | 1069 | }, |
| 1001 | State.For => |ctx| { | 1070 | State.For => |ctx| { |
| 1002 | const node = try arena.create(ast.Node.For{ | 1071 | const node = try arena.create(ast.Node.For); |
| 1072 | node.* = ast.Node.For{ | ||
| 1003 | .base = ast.Node{ .id = ast.Node.Id.For }, | 1073 | .base = ast.Node{ .id = ast.Node.Id.For }, |
| 1004 | .label = ctx.label, | 1074 | .label = ctx.label, |
| 1005 | .inline_token = ctx.inline_token, | 1075 | .inline_token = ctx.inline_token, |
| ... | @@ -1008,7 +1078,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1008,7 +1078,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1008 | .payload = null, | 1078 | .payload = null, |
| 1009 | .body = undefined, | 1079 | .body = undefined, |
| 1010 | .@"else" = null, | 1080 | .@"else" = null, |
| 1011 | }); | 1081 | }; |
| 1012 | ctx.opt_ctx.store(&node.base); | 1082 | ctx.opt_ctx.store(&node.base); |
| 1013 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; | 1083 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; |
| 1014 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); | 1084 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); |
| ... | @@ -1020,12 +1090,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1020,12 +1090,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1020 | }, | 1090 | }, |
| 1021 | State.Else => |dest| { | 1091 | State.Else => |dest| { |
| 1022 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { | 1092 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { |
| 1023 | const node = try arena.create(ast.Node.Else{ | 1093 | const node = try arena.create(ast.Node.Else); |
| 1094 | node.* = ast.Node.Else{ | ||
| 1024 | .base = ast.Node{ .id = ast.Node.Id.Else }, | 1095 | .base = ast.Node{ .id = ast.Node.Id.Else }, |
| 1025 | .else_token = else_token, | 1096 | .else_token = else_token, |
| 1026 | .payload = null, | 1097 | .payload = null, |
| 1027 | .body = undefined, | 1098 | .body = undefined, |
| 1028 | }); | 1099 | }; |
| 1029 | dest.* = node; | 1100 | dest.* = node; |
| 1030 | 1101 | ||
| 1031 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable; | 1102 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable; |
| ... | @@ -1073,6 +1144,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1073,6 +1144,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1073 | .VarDecl = VarDeclCtx{ | 1144 | .VarDecl = VarDeclCtx{ |
| 1074 | .comments = null, | 1145 | .comments = null, |
| 1075 | .visib_token = null, | 1146 | .visib_token = null, |
| 1147 | .thread_local_token = null, | ||
| 1076 | .comptime_token = null, | 1148 | .comptime_token = null, |
| 1077 | .extern_export_token = null, | 1149 | .extern_export_token = null, |
| 1078 | .lib_name = null, | 1150 | .lib_name = null, |
| ... | @@ -1083,11 +1155,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1083,11 +1155,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1083 | continue; | 1155 | continue; |
| 1084 | }, | 1156 | }, |
| 1085 | Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => { | 1157 | Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => { |
| 1086 | const node = try arena.create(ast.Node.Defer{ | 1158 | const node = try arena.create(ast.Node.Defer); |
| 1159 | node.* = ast.Node.Defer{ | ||
| 1087 | .base = ast.Node{ .id = ast.Node.Id.Defer }, | 1160 | .base = ast.Node{ .id = ast.Node.Id.Defer }, |
| 1088 | .defer_token = token_index, | 1161 | .defer_token = token_index, |
| 1089 | .expr = undefined, | 1162 | .expr = undefined, |
| 1090 | }); | 1163 | }; |
| 1091 | const node_ptr = try block.statements.addOne(); | 1164 | const node_ptr = try block.statements.addOne(); |
| 1092 | node_ptr.* = &node.base; | 1165 | node_ptr.* = &node.base; |
| 1093 | 1166 | ||
| ... | @@ -1096,13 +1169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1096,13 +1169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1096 | continue; | 1169 | continue; |
| 1097 | }, | 1170 | }, |
| 1098 | Token.Id.LBrace => { | 1171 | Token.Id.LBrace => { |
| 1099 | const inner_block = try arena.create(ast.Node.Block{ | 1172 | const inner_block = try arena.create(ast.Node.Block); |
| 1173 | inner_block.* = ast.Node.Block{ | ||
| 1100 | .base = ast.Node{ .id = ast.Node.Id.Block }, | 1174 | .base = ast.Node{ .id = ast.Node.Id.Block }, |
| 1101 | .label = null, | 1175 | .label = null, |
| 1102 | .lbrace = token_index, | 1176 | .lbrace = token_index, |
| 1103 | .statements = ast.Node.Block.StatementList.init(arena), | 1177 | .statements = ast.Node.Block.StatementList.init(arena), |
| 1104 | .rbrace = undefined, | 1178 | .rbrace = undefined, |
| 1105 | }); | 1179 | }; |
| 1106 | try block.statements.push(&inner_block.base); | 1180 | try block.statements.push(&inner_block.base); |
| 1107 | 1181 | ||
| 1108 | stack.append(State{ .Block = inner_block }) catch unreachable; | 1182 | stack.append(State{ .Block = inner_block }) catch unreachable; |
| ... | @@ -1127,6 +1201,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1127,6 +1201,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1127 | .VarDecl = VarDeclCtx{ | 1201 | .VarDecl = VarDeclCtx{ |
| 1128 | .comments = null, | 1202 | .comments = null, |
| 1129 | .visib_token = null, | 1203 | .visib_token = null, |
| 1204 | .thread_local_token = null, | ||
| 1130 | .comptime_token = ctx.comptime_token, | 1205 | .comptime_token = ctx.comptime_token, |
| 1131 | .extern_export_token = null, | 1206 | .extern_export_token = null, |
| 1132 | .lib_name = null, | 1207 | .lib_name = null, |
| ... | @@ -1164,14 +1239,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1164,14 +1239,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1164 | continue; | 1239 | continue; |
| 1165 | } | 1240 | } |
| 1166 | 1241 | ||
| 1167 | const node = try arena.create(ast.Node.AsmOutput{ | 1242 | const node = try arena.create(ast.Node.AsmOutput); |
| 1243 | node.* = ast.Node.AsmOutput{ | ||
| 1168 | .base = ast.Node{ .id = ast.Node.Id.AsmOutput }, | 1244 | .base = ast.Node{ .id = ast.Node.Id.AsmOutput }, |
| 1169 | .lbracket = lbracket_index, | 1245 | .lbracket = lbracket_index, |
| 1170 | .symbolic_name = undefined, | 1246 | .symbolic_name = undefined, |
| 1171 | .constraint = undefined, | 1247 | .constraint = undefined, |
| 1172 | .kind = undefined, | 1248 | .kind = undefined, |
| 1173 | .rparen = undefined, | 1249 | .rparen = undefined, |
| 1174 | }); | 1250 | }; |
| 1175 | try items.push(node); | 1251 | try items.push(node); |
| 1176 | 1252 | ||
| 1177 | stack.append(State{ .AsmOutputItems = items }) catch unreachable; | 1253 | stack.append(State{ .AsmOutputItems = items }) catch unreachable; |
| ... | @@ -1218,14 +1294,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1218,14 +1294,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1218 | continue; | 1294 | continue; |
| 1219 | } | 1295 | } |
| 1220 | 1296 | ||
| 1221 | const node = try arena.create(ast.Node.AsmInput{ | 1297 | const node = try arena.create(ast.Node.AsmInput); |
| 1298 | node.* = ast.Node.AsmInput{ | ||
| 1222 | .base = ast.Node{ .id = ast.Node.Id.AsmInput }, | 1299 | .base = ast.Node{ .id = ast.Node.Id.AsmInput }, |
| 1223 | .lbracket = lbracket_index, | 1300 | .lbracket = lbracket_index, |
| 1224 | .symbolic_name = undefined, | 1301 | .symbolic_name = undefined, |
| 1225 | .constraint = undefined, | 1302 | .constraint = undefined, |
| 1226 | .expr = undefined, | 1303 | .expr = undefined, |
| 1227 | .rparen = undefined, | 1304 | .rparen = undefined, |
| 1228 | }); | 1305 | }; |
| 1229 | try items.push(node); | 1306 | try items.push(node); |
| 1230 | 1307 | ||
| 1231 | stack.append(State{ .AsmInputItems = items }) catch unreachable; | 1308 | stack.append(State{ .AsmInputItems = items }) catch unreachable; |
| ... | @@ -1283,12 +1360,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1283,12 +1360,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1283 | continue; | 1360 | continue; |
| 1284 | } | 1361 | } |
| 1285 | 1362 | ||
| 1286 | const node = try arena.create(ast.Node.FieldInitializer{ | 1363 | const node = try arena.create(ast.Node.FieldInitializer); |
| 1364 | node.* = ast.Node.FieldInitializer{ | ||
| 1287 | .base = ast.Node{ .id = ast.Node.Id.FieldInitializer }, | 1365 | .base = ast.Node{ .id = ast.Node.Id.FieldInitializer }, |
| 1288 | .period_token = undefined, | 1366 | .period_token = undefined, |
| 1289 | .name_token = undefined, | 1367 | .name_token = undefined, |
| 1290 | .expr = undefined, | 1368 | .expr = undefined, |
| 1291 | }); | 1369 | }; |
| 1292 | try list_state.list.push(&node.base); | 1370 | try list_state.list.push(&node.base); |
| 1293 | 1371 | ||
| 1294 | stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable; | 1372 | stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable; |
| ... | @@ -1390,13 +1468,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1390,13 +1468,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1390 | } | 1468 | } |
| 1391 | 1469 | ||
| 1392 | const comments = try eatDocComments(arena, &tok_it, &tree); | 1470 | const comments = try eatDocComments(arena, &tok_it, &tree); |
| 1393 | const node = try arena.create(ast.Node.SwitchCase{ | 1471 | const node = try arena.create(ast.Node.SwitchCase); |
| 1472 | node.* = ast.Node.SwitchCase{ | ||
| 1394 | .base = ast.Node{ .id = ast.Node.Id.SwitchCase }, | 1473 | .base = ast.Node{ .id = ast.Node.Id.SwitchCase }, |
| 1395 | .items = ast.Node.SwitchCase.ItemList.init(arena), | 1474 | .items = ast.Node.SwitchCase.ItemList.init(arena), |
| 1396 | .payload = null, | 1475 | .payload = null, |
| 1397 | .expr = undefined, | 1476 | .expr = undefined, |
| 1398 | .arrow_token = undefined, | 1477 | .arrow_token = undefined, |
| 1399 | }); | 1478 | }; |
| 1400 | try list_state.list.push(&node.base); | 1479 | try list_state.list.push(&node.base); |
| 1401 | try stack.append(State{ .SwitchCaseCommaOrEnd = list_state }); | 1480 | try stack.append(State{ .SwitchCaseCommaOrEnd = list_state }); |
| 1402 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); | 1481 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); |
| ... | @@ -1427,10 +1506,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1427,10 +1506,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1427 | const token_index = token.index; | 1506 | const token_index = token.index; |
| 1428 | const token_ptr = token.ptr; | 1507 | const token_ptr = token.ptr; |
| 1429 | if (token_ptr.id == Token.Id.Keyword_else) { | 1508 | if (token_ptr.id == Token.Id.Keyword_else) { |
| 1430 | const else_node = try arena.create(ast.Node.SwitchElse{ | 1509 | const else_node = try arena.create(ast.Node.SwitchElse); |
| 1510 | else_node.* = ast.Node.SwitchElse{ | ||
| 1431 | .base = ast.Node{ .id = ast.Node.Id.SwitchElse }, | 1511 | .base = ast.Node{ .id = ast.Node.Id.SwitchElse }, |
| 1432 | .token = token_index, | 1512 | .token = token_index, |
| 1433 | }); | 1513 | }; |
| 1434 | try switch_case.items.push(&else_node.base); | 1514 | try switch_case.items.push(&else_node.base); |
| 1435 | 1515 | ||
| 1436 | try stack.append(State{ | 1516 | try stack.append(State{ |
| ... | @@ -1537,7 +1617,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1537,7 +1617,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1537 | 1617 | ||
| 1538 | State.ExternType => |ctx| { | 1618 | State.ExternType => |ctx| { |
| 1539 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| { | 1619 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| { |
| 1540 | const fn_proto = try arena.create(ast.Node.FnProto{ | 1620 | const fn_proto = try arena.create(ast.Node.FnProto); |
| 1621 | fn_proto.* = ast.Node.FnProto{ | ||
| 1541 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | 1622 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, |
| 1542 | .doc_comments = ctx.comments, | 1623 | .doc_comments = ctx.comments, |
| 1543 | .visib_token = null, | 1624 | .visib_token = null, |
| ... | @@ -1553,7 +1634,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1553,7 +1634,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1553 | .lib_name = null, | 1634 | .lib_name = null, |
| 1554 | .align_expr = null, | 1635 | .align_expr = null, |
| 1555 | .section_expr = null, | 1636 | .section_expr = null, |
| 1556 | }); | 1637 | }; |
| 1557 | ctx.opt_ctx.store(&fn_proto.base); | 1638 | ctx.opt_ctx.store(&fn_proto.base); |
| 1558 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; | 1639 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; |
| 1559 | continue; | 1640 | continue; |
| ... | @@ -1711,12 +1792,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1711,12 +1792,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1711 | continue; | 1792 | continue; |
| 1712 | } | 1793 | } |
| 1713 | 1794 | ||
| 1714 | const node = try arena.create(ast.Node.Payload{ | 1795 | const node = try arena.create(ast.Node.Payload); |
| 1796 | node.* = ast.Node.Payload{ | ||
| 1715 | .base = ast.Node{ .id = ast.Node.Id.Payload }, | 1797 | .base = ast.Node{ .id = ast.Node.Id.Payload }, |
| 1716 | .lpipe = token_index, | 1798 | .lpipe = token_index, |
| 1717 | .error_symbol = undefined, | 1799 | .error_symbol = undefined, |
| 1718 | .rpipe = undefined, | 1800 | .rpipe = undefined, |
| 1719 | }); | 1801 | }; |
| 1720 | opt_ctx.store(&node.base); | 1802 | opt_ctx.store(&node.base); |
| 1721 | 1803 | ||
| 1722 | stack.append(State{ | 1804 | stack.append(State{ |
| ... | @@ -1747,13 +1829,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1747,13 +1829,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1747 | continue; | 1829 | continue; |
| 1748 | } | 1830 | } |
| 1749 | 1831 | ||
| 1750 | const node = try arena.create(ast.Node.PointerPayload{ | 1832 | const node = try arena.create(ast.Node.PointerPayload); |
| 1833 | node.* = ast.Node.PointerPayload{ | ||
| 1751 | .base = ast.Node{ .id = ast.Node.Id.PointerPayload }, | 1834 | .base = ast.Node{ .id = ast.Node.Id.PointerPayload }, |
| 1752 | .lpipe = token_index, | 1835 | .lpipe = token_index, |
| 1753 | .ptr_token = null, | 1836 | .ptr_token = null, |
| 1754 | .value_symbol = undefined, | 1837 | .value_symbol = undefined, |
| 1755 | .rpipe = undefined, | 1838 | .rpipe = undefined, |
| 1756 | }); | 1839 | }; |
| 1757 | opt_ctx.store(&node.base); | 1840 | opt_ctx.store(&node.base); |
| 1758 | 1841 | ||
| 1759 | try stack.append(State{ | 1842 | try stack.append(State{ |
| ... | @@ -1790,14 +1873,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1790,14 +1873,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1790 | continue; | 1873 | continue; |
| 1791 | } | 1874 | } |
| 1792 | 1875 | ||
| 1793 | const node = try arena.create(ast.Node.PointerIndexPayload{ | 1876 | const node = try arena.create(ast.Node.PointerIndexPayload); |
| 1877 | node.* = ast.Node.PointerIndexPayload{ | ||
| 1794 | .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload }, | 1878 | .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload }, |
| 1795 | .lpipe = token_index, | 1879 | .lpipe = token_index, |
| 1796 | .ptr_token = null, | 1880 | .ptr_token = null, |
| 1797 | .value_symbol = undefined, | 1881 | .value_symbol = undefined, |
| 1798 | .index_symbol = null, | 1882 | .index_symbol = null, |
| 1799 | .rpipe = undefined, | 1883 | .rpipe = undefined, |
| 1800 | }); | 1884 | }; |
| 1801 | opt_ctx.store(&node.base); | 1885 | opt_ctx.store(&node.base); |
| 1802 | 1886 | ||
| 1803 | stack.append(State{ | 1887 | stack.append(State{ |
| ... | @@ -1824,12 +1908,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1824,12 +1908,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1824 | const token_ptr = token.ptr; | 1908 | const token_ptr = token.ptr; |
| 1825 | switch (token_ptr.id) { | 1909 | switch (token_ptr.id) { |
| 1826 | Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => { | 1910 | Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => { |
| 1827 | const node = try arena.create(ast.Node.ControlFlowExpression{ | 1911 | const node = try arena.create(ast.Node.ControlFlowExpression); |
| 1912 | node.* = ast.Node.ControlFlowExpression{ | ||
| 1828 | .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression }, | 1913 | .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression }, |
| 1829 | .ltoken = token_index, | 1914 | .ltoken = token_index, |
| 1830 | .kind = undefined, | 1915 | .kind = undefined, |
| 1831 | .rhs = null, | 1916 | .rhs = null, |
| 1832 | }); | 1917 | }; |
| 1833 | opt_ctx.store(&node.base); | 1918 | opt_ctx.store(&node.base); |
| 1834 | 1919 | ||
| 1835 | stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable; | 1920 | stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable; |
| ... | @@ -1853,7 +1938,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1853,7 +1938,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1853 | continue; | 1938 | continue; |
| 1854 | }, | 1939 | }, |
| 1855 | Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => { | 1940 | Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => { |
| 1856 | const node = try arena.create(ast.Node.PrefixOp{ | 1941 | const node = try arena.create(ast.Node.PrefixOp); |
| 1942 | node.* = ast.Node.PrefixOp{ | ||
| 1857 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | 1943 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, |
| 1858 | .op_token = token_index, | 1944 | .op_token = token_index, |
| 1859 | .op = switch (token_ptr.id) { | 1945 | .op = switch (token_ptr.id) { |
| ... | @@ -1863,7 +1949,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1863,7 +1949,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1863 | else => unreachable, | 1949 | else => unreachable, |
| 1864 | }, | 1950 | }, |
| 1865 | .rhs = undefined, | 1951 | .rhs = undefined, |
| 1866 | }); | 1952 | }; |
| 1867 | opt_ctx.store(&node.base); | 1953 | opt_ctx.store(&node.base); |
| 1868 | 1954 | ||
| 1869 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | 1955 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; |
| ... | @@ -1887,13 +1973,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1887,13 +1973,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1887 | const lhs = opt_ctx.get() orelse continue; | 1973 | const lhs = opt_ctx.get() orelse continue; |
| 1888 | 1974 | ||
| 1889 | if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { | 1975 | if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { |
| 1890 | const node = try arena.create(ast.Node.InfixOp{ | 1976 | const node = try arena.create(ast.Node.InfixOp); |
| 1977 | node.* = ast.Node.InfixOp{ | ||
| 1891 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 1978 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 1892 | .lhs = lhs, | 1979 | .lhs = lhs, |
| 1893 | .op_token = ellipsis3, | 1980 | .op_token = ellipsis3, |
| 1894 | .op = ast.Node.InfixOp.Op.Range, | 1981 | .op = ast.Node.InfixOp.Op.Range, |
| 1895 | .rhs = undefined, | 1982 | .rhs = undefined, |
| 1896 | }); | 1983 | }; |
| 1897 | opt_ctx.store(&node.base); | 1984 | opt_ctx.store(&node.base); |
| 1898 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | 1985 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; |
| 1899 | continue; | 1986 | continue; |
| ... | @@ -1912,13 +1999,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1912,13 +1999,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1912 | const token_index = token.index; | 1999 | const token_index = token.index; |
| 1913 | const token_ptr = token.ptr; | 2000 | const token_ptr = token.ptr; |
| 1914 | if (tokenIdToAssignment(token_ptr.id)) |ass_id| { | 2001 | if (tokenIdToAssignment(token_ptr.id)) |ass_id| { |
| 1915 | const node = try arena.create(ast.Node.InfixOp{ | 2002 | const node = try arena.create(ast.Node.InfixOp); |
| 2003 | node.* = ast.Node.InfixOp{ | ||
| 1916 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2004 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 1917 | .lhs = lhs, | 2005 | .lhs = lhs, |
| 1918 | .op_token = token_index, | 2006 | .op_token = token_index, |
| 1919 | .op = ass_id, | 2007 | .op = ass_id, |
| 1920 | .rhs = undefined, | 2008 | .rhs = undefined, |
| 1921 | }); | 2009 | }; |
| 1922 | opt_ctx.store(&node.base); | 2010 | opt_ctx.store(&node.base); |
| 1923 | stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2011 | stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 1924 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); | 2012 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -1942,13 +2030,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1942,13 +2030,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1942 | const token_index = token.index; | 2030 | const token_index = token.index; |
| 1943 | const token_ptr = token.ptr; | 2031 | const token_ptr = token.ptr; |
| 1944 | if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| { | 2032 | if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| { |
| 1945 | const node = try arena.create(ast.Node.InfixOp{ | 2033 | const node = try arena.create(ast.Node.InfixOp); |
| 2034 | node.* = ast.Node.InfixOp{ | ||
| 1946 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2035 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 1947 | .lhs = lhs, | 2036 | .lhs = lhs, |
| 1948 | .op_token = token_index, | 2037 | .op_token = token_index, |
| 1949 | .op = unwrap_id, | 2038 | .op = unwrap_id, |
| 1950 | .rhs = undefined, | 2039 | .rhs = undefined, |
| 1951 | }); | 2040 | }; |
| 1952 | opt_ctx.store(&node.base); | 2041 | opt_ctx.store(&node.base); |
| 1953 | 2042 | ||
| 1954 | stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2043 | stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| ... | @@ -1974,13 +2063,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1974,13 +2063,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1974 | const lhs = opt_ctx.get() orelse continue; | 2063 | const lhs = opt_ctx.get() orelse continue; |
| 1975 | 2064 | ||
| 1976 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| { | 2065 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| { |
| 1977 | const node = try arena.create(ast.Node.InfixOp{ | 2066 | const node = try arena.create(ast.Node.InfixOp); |
| 2067 | node.* = ast.Node.InfixOp{ | ||
| 1978 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2068 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 1979 | .lhs = lhs, | 2069 | .lhs = lhs, |
| 1980 | .op_token = or_token, | 2070 | .op_token = or_token, |
| 1981 | .op = ast.Node.InfixOp.Op.BoolOr, | 2071 | .op = ast.Node.InfixOp.Op.BoolOr, |
| 1982 | .rhs = undefined, | 2072 | .rhs = undefined, |
| 1983 | }); | 2073 | }; |
| 1984 | opt_ctx.store(&node.base); | 2074 | opt_ctx.store(&node.base); |
| 1985 | stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2075 | stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 1986 | try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2076 | try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -1998,13 +2088,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -1998,13 +2088,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 1998 | const lhs = opt_ctx.get() orelse continue; | 2088 | const lhs = opt_ctx.get() orelse continue; |
| 1999 | 2089 | ||
| 2000 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| { | 2090 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| { |
| 2001 | const node = try arena.create(ast.Node.InfixOp{ | 2091 | const node = try arena.create(ast.Node.InfixOp); |
| 2092 | node.* = ast.Node.InfixOp{ | ||
| 2002 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2093 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2003 | .lhs = lhs, | 2094 | .lhs = lhs, |
| 2004 | .op_token = and_token, | 2095 | .op_token = and_token, |
| 2005 | .op = ast.Node.InfixOp.Op.BoolAnd, | 2096 | .op = ast.Node.InfixOp.Op.BoolAnd, |
| 2006 | .rhs = undefined, | 2097 | .rhs = undefined, |
| 2007 | }); | 2098 | }; |
| 2008 | opt_ctx.store(&node.base); | 2099 | opt_ctx.store(&node.base); |
| 2009 | stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2100 | stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2010 | try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2101 | try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2025,13 +2116,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2025,13 +2116,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2025 | const token_index = token.index; | 2116 | const token_index = token.index; |
| 2026 | const token_ptr = token.ptr; | 2117 | const token_ptr = token.ptr; |
| 2027 | if (tokenIdToComparison(token_ptr.id)) |comp_id| { | 2118 | if (tokenIdToComparison(token_ptr.id)) |comp_id| { |
| 2028 | const node = try arena.create(ast.Node.InfixOp{ | 2119 | const node = try arena.create(ast.Node.InfixOp); |
| 2120 | node.* = ast.Node.InfixOp{ | ||
| 2029 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2121 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2030 | .lhs = lhs, | 2122 | .lhs = lhs, |
| 2031 | .op_token = token_index, | 2123 | .op_token = token_index, |
| 2032 | .op = comp_id, | 2124 | .op = comp_id, |
| 2033 | .rhs = undefined, | 2125 | .rhs = undefined, |
| 2034 | }); | 2126 | }; |
| 2035 | opt_ctx.store(&node.base); | 2127 | opt_ctx.store(&node.base); |
| 2036 | stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2128 | stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2037 | try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2129 | try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2052,13 +2144,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2052,13 +2144,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2052 | const lhs = opt_ctx.get() orelse continue; | 2144 | const lhs = opt_ctx.get() orelse continue; |
| 2053 | 2145 | ||
| 2054 | if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| { | 2146 | if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| { |
| 2055 | const node = try arena.create(ast.Node.InfixOp{ | 2147 | const node = try arena.create(ast.Node.InfixOp); |
| 2148 | node.* = ast.Node.InfixOp{ | ||
| 2056 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2149 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2057 | .lhs = lhs, | 2150 | .lhs = lhs, |
| 2058 | .op_token = pipe, | 2151 | .op_token = pipe, |
| 2059 | .op = ast.Node.InfixOp.Op.BitOr, | 2152 | .op = ast.Node.InfixOp.Op.BitOr, |
| 2060 | .rhs = undefined, | 2153 | .rhs = undefined, |
| 2061 | }); | 2154 | }; |
| 2062 | opt_ctx.store(&node.base); | 2155 | opt_ctx.store(&node.base); |
| 2063 | stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2156 | stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2064 | try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2157 | try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2076,13 +2169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2076,13 +2169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2076 | const lhs = opt_ctx.get() orelse continue; | 2169 | const lhs = opt_ctx.get() orelse continue; |
| 2077 | 2170 | ||
| 2078 | if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| { | 2171 | if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| { |
| 2079 | const node = try arena.create(ast.Node.InfixOp{ | 2172 | const node = try arena.create(ast.Node.InfixOp); |
| 2173 | node.* = ast.Node.InfixOp{ | ||
| 2080 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2174 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2081 | .lhs = lhs, | 2175 | .lhs = lhs, |
| 2082 | .op_token = caret, | 2176 | .op_token = caret, |
| 2083 | .op = ast.Node.InfixOp.Op.BitXor, | 2177 | .op = ast.Node.InfixOp.Op.BitXor, |
| 2084 | .rhs = undefined, | 2178 | .rhs = undefined, |
| 2085 | }); | 2179 | }; |
| 2086 | opt_ctx.store(&node.base); | 2180 | opt_ctx.store(&node.base); |
| 2087 | stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2181 | stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2088 | try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2182 | try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2100,13 +2194,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2100,13 +2194,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2100 | const lhs = opt_ctx.get() orelse continue; | 2194 | const lhs = opt_ctx.get() orelse continue; |
| 2101 | 2195 | ||
| 2102 | if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| { | 2196 | if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| { |
| 2103 | const node = try arena.create(ast.Node.InfixOp{ | 2197 | const node = try arena.create(ast.Node.InfixOp); |
| 2198 | node.* = ast.Node.InfixOp{ | ||
| 2104 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2199 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2105 | .lhs = lhs, | 2200 | .lhs = lhs, |
| 2106 | .op_token = ampersand, | 2201 | .op_token = ampersand, |
| 2107 | .op = ast.Node.InfixOp.Op.BitAnd, | 2202 | .op = ast.Node.InfixOp.Op.BitAnd, |
| 2108 | .rhs = undefined, | 2203 | .rhs = undefined, |
| 2109 | }); | 2204 | }; |
| 2110 | opt_ctx.store(&node.base); | 2205 | opt_ctx.store(&node.base); |
| 2111 | stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2206 | stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2112 | try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2207 | try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2127,13 +2222,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2127,13 +2222,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2127 | const token_index = token.index; | 2222 | const token_index = token.index; |
| 2128 | const token_ptr = token.ptr; | 2223 | const token_ptr = token.ptr; |
| 2129 | if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| { | 2224 | if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| { |
| 2130 | const node = try arena.create(ast.Node.InfixOp{ | 2225 | const node = try arena.create(ast.Node.InfixOp); |
| 2226 | node.* = ast.Node.InfixOp{ | ||
| 2131 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2227 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2132 | .lhs = lhs, | 2228 | .lhs = lhs, |
| 2133 | .op_token = token_index, | 2229 | .op_token = token_index, |
| 2134 | .op = bitshift_id, | 2230 | .op = bitshift_id, |
| 2135 | .rhs = undefined, | 2231 | .rhs = undefined, |
| 2136 | }); | 2232 | }; |
| 2137 | opt_ctx.store(&node.base); | 2233 | opt_ctx.store(&node.base); |
| 2138 | stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2234 | stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2139 | try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2235 | try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2157,13 +2253,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2157,13 +2253,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2157 | const token_index = token.index; | 2253 | const token_index = token.index; |
| 2158 | const token_ptr = token.ptr; | 2254 | const token_ptr = token.ptr; |
| 2159 | if (tokenIdToAddition(token_ptr.id)) |add_id| { | 2255 | if (tokenIdToAddition(token_ptr.id)) |add_id| { |
| 2160 | const node = try arena.create(ast.Node.InfixOp{ | 2256 | const node = try arena.create(ast.Node.InfixOp); |
| 2257 | node.* = ast.Node.InfixOp{ | ||
| 2161 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2258 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2162 | .lhs = lhs, | 2259 | .lhs = lhs, |
| 2163 | .op_token = token_index, | 2260 | .op_token = token_index, |
| 2164 | .op = add_id, | 2261 | .op = add_id, |
| 2165 | .rhs = undefined, | 2262 | .rhs = undefined, |
| 2166 | }); | 2263 | }; |
| 2167 | opt_ctx.store(&node.base); | 2264 | opt_ctx.store(&node.base); |
| 2168 | stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2265 | stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2169 | try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2266 | try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2187,13 +2284,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2187,13 +2284,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2187 | const token_index = token.index; | 2284 | const token_index = token.index; |
| 2188 | const token_ptr = token.ptr; | 2285 | const token_ptr = token.ptr; |
| 2189 | if (tokenIdToMultiply(token_ptr.id)) |mult_id| { | 2286 | if (tokenIdToMultiply(token_ptr.id)) |mult_id| { |
| 2190 | const node = try arena.create(ast.Node.InfixOp{ | 2287 | const node = try arena.create(ast.Node.InfixOp); |
| 2288 | node.* = ast.Node.InfixOp{ | ||
| 2191 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2289 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2192 | .lhs = lhs, | 2290 | .lhs = lhs, |
| 2193 | .op_token = token_index, | 2291 | .op_token = token_index, |
| 2194 | .op = mult_id, | 2292 | .op = mult_id, |
| 2195 | .rhs = undefined, | 2293 | .rhs = undefined, |
| 2196 | }); | 2294 | }; |
| 2197 | opt_ctx.store(&node.base); | 2295 | opt_ctx.store(&node.base); |
| 2198 | stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2296 | stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2199 | try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | 2297 | try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2215,12 +2313,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2215,12 +2313,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2215 | const lhs = opt_ctx.get() orelse continue; | 2313 | const lhs = opt_ctx.get() orelse continue; |
| 2216 | 2314 | ||
| 2217 | if (tok_it.peek().?.id == Token.Id.Period) { | 2315 | if (tok_it.peek().?.id == Token.Id.Period) { |
| 2218 | const node = try arena.create(ast.Node.SuffixOp{ | 2316 | const node = try arena.create(ast.Node.SuffixOp); |
| 2317 | node.* = ast.Node.SuffixOp{ | ||
| 2219 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | 2318 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, |
| 2220 | .lhs = lhs, | 2319 | .lhs = lhs, |
| 2221 | .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, | 2320 | .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, |
| 2222 | .rtoken = undefined, | 2321 | .rtoken = undefined, |
| 2223 | }); | 2322 | }; |
| 2224 | opt_ctx.store(&node.base); | 2323 | opt_ctx.store(&node.base); |
| 2225 | 2324 | ||
| 2226 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2325 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| ... | @@ -2234,12 +2333,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2234,12 +2333,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2234 | continue; | 2333 | continue; |
| 2235 | } | 2334 | } |
| 2236 | 2335 | ||
| 2237 | const node = try arena.create(ast.Node.SuffixOp{ | 2336 | const node = try arena.create(ast.Node.SuffixOp); |
| 2337 | node.* = ast.Node.SuffixOp{ | ||
| 2238 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | 2338 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, |
| 2239 | .lhs = lhs, | 2339 | .lhs = lhs, |
| 2240 | .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, | 2340 | .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, |
| 2241 | .rtoken = undefined, | 2341 | .rtoken = undefined, |
| 2242 | }); | 2342 | }; |
| 2243 | opt_ctx.store(&node.base); | 2343 | opt_ctx.store(&node.base); |
| 2244 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2344 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2245 | try stack.append(State{ .IfToken = Token.Id.LBrace }); | 2345 | try stack.append(State{ .IfToken = Token.Id.LBrace }); |
| ... | @@ -2263,13 +2363,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2263,13 +2363,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2263 | const lhs = opt_ctx.get() orelse continue; | 2363 | const lhs = opt_ctx.get() orelse continue; |
| 2264 | 2364 | ||
| 2265 | if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| { | 2365 | if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| { |
| 2266 | const node = try arena.create(ast.Node.InfixOp{ | 2366 | const node = try arena.create(ast.Node.InfixOp); |
| 2367 | node.* = ast.Node.InfixOp{ | ||
| 2267 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2368 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2268 | .lhs = lhs, | 2369 | .lhs = lhs, |
| 2269 | .op_token = bang, | 2370 | .op_token = bang, |
| 2270 | .op = ast.Node.InfixOp.Op.ErrorUnion, | 2371 | .op = ast.Node.InfixOp.Op.ErrorUnion, |
| 2271 | .rhs = undefined, | 2372 | .rhs = undefined, |
| 2272 | }); | 2373 | }; |
| 2273 | opt_ctx.store(&node.base); | 2374 | opt_ctx.store(&node.base); |
| 2274 | stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; | 2375 | stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2275 | try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } }); | 2376 | try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } }); |
| ... | @@ -2282,22 +2383,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2282,22 +2383,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2282 | const token_index = token.index; | 2383 | const token_index = token.index; |
| 2283 | const token_ptr = token.ptr; | 2384 | const token_ptr = token.ptr; |
| 2284 | if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| { | 2385 | if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| { |
| 2285 | var node = try arena.create(ast.Node.PrefixOp{ | 2386 | var node = try arena.create(ast.Node.PrefixOp); |
| 2387 | node.* = ast.Node.PrefixOp{ | ||
| 2286 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | 2388 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, |
| 2287 | .op_token = token_index, | 2389 | .op_token = token_index, |
| 2288 | .op = prefix_id, | 2390 | .op = prefix_id, |
| 2289 | .rhs = undefined, | 2391 | .rhs = undefined, |
| 2290 | }); | 2392 | }; |
| 2291 | opt_ctx.store(&node.base); | 2393 | opt_ctx.store(&node.base); |
| 2292 | 2394 | ||
| 2293 | // Treat '**' token as two pointer types | 2395 | // Treat '**' token as two pointer types |
| 2294 | if (token_ptr.id == Token.Id.AsteriskAsterisk) { | 2396 | if (token_ptr.id == Token.Id.AsteriskAsterisk) { |
| 2295 | const child = try arena.create(ast.Node.PrefixOp{ | 2397 | const child = try arena.create(ast.Node.PrefixOp); |
| 2398 | child.* = ast.Node.PrefixOp{ | ||
| 2296 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | 2399 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, |
| 2297 | .op_token = token_index, | 2400 | .op_token = token_index, |
| 2298 | .op = prefix_id, | 2401 | .op = prefix_id, |
| 2299 | .rhs = undefined, | 2402 | .rhs = undefined, |
| 2300 | }); | 2403 | }; |
| 2301 | node.rhs = &child.base; | 2404 | node.rhs = &child.base; |
| 2302 | node = child; | 2405 | node = child; |
| 2303 | } | 2406 | } |
| ... | @@ -2316,12 +2419,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2316,12 +2419,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2316 | 2419 | ||
| 2317 | State.SuffixOpExpressionBegin => |opt_ctx| { | 2420 | State.SuffixOpExpressionBegin => |opt_ctx| { |
| 2318 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| { | 2421 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| { |
| 2319 | const async_node = try arena.create(ast.Node.AsyncAttribute{ | 2422 | const async_node = try arena.create(ast.Node.AsyncAttribute); |
| 2423 | async_node.* = ast.Node.AsyncAttribute{ | ||
| 2320 | .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, | 2424 | .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, |
| 2321 | .async_token = async_token, | 2425 | .async_token = async_token, |
| 2322 | .allocator_type = null, | 2426 | .allocator_type = null, |
| 2323 | .rangle_bracket = null, | 2427 | .rangle_bracket = null, |
| 2324 | }); | 2428 | }; |
| 2325 | stack.append(State{ | 2429 | stack.append(State{ |
| 2326 | .AsyncEnd = AsyncEndCtx{ | 2430 | .AsyncEnd = AsyncEndCtx{ |
| 2327 | .ctx = opt_ctx, | 2431 | .ctx = opt_ctx, |
| ... | @@ -2347,7 +2451,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2347,7 +2451,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2347 | const token_ptr = token.ptr; | 2451 | const token_ptr = token.ptr; |
| 2348 | switch (token_ptr.id) { | 2452 | switch (token_ptr.id) { |
| 2349 | Token.Id.LParen => { | 2453 | Token.Id.LParen => { |
| 2350 | const node = try arena.create(ast.Node.SuffixOp{ | 2454 | const node = try arena.create(ast.Node.SuffixOp); |
| 2455 | node.* = ast.Node.SuffixOp{ | ||
| 2351 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | 2456 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, |
| 2352 | .lhs = lhs, | 2457 | .lhs = lhs, |
| 2353 | .op = ast.Node.SuffixOp.Op{ | 2458 | .op = ast.Node.SuffixOp.Op{ |
| ... | @@ -2357,7 +2462,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2357,7 +2462,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2357 | }, | 2462 | }, |
| 2358 | }, | 2463 | }, |
| 2359 | .rtoken = undefined, | 2464 | .rtoken = undefined, |
| 2360 | }); | 2465 | }; |
| 2361 | opt_ctx.store(&node.base); | 2466 | opt_ctx.store(&node.base); |
| 2362 | 2467 | ||
| 2363 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2468 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| ... | @@ -2371,12 +2476,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2371,12 +2476,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2371 | continue; | 2476 | continue; |
| 2372 | }, | 2477 | }, |
| 2373 | Token.Id.LBracket => { | 2478 | Token.Id.LBracket => { |
| 2374 | const node = try arena.create(ast.Node.SuffixOp{ | 2479 | const node = try arena.create(ast.Node.SuffixOp); |
| 2480 | node.* = ast.Node.SuffixOp{ | ||
| 2375 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | 2481 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, |
| 2376 | .lhs = lhs, | 2482 | .lhs = lhs, |
| 2377 | .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined }, | 2483 | .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined }, |
| 2378 | .rtoken = undefined, | 2484 | .rtoken = undefined, |
| 2379 | }); | 2485 | }; |
| 2380 | opt_ctx.store(&node.base); | 2486 | opt_ctx.store(&node.base); |
| 2381 | 2487 | ||
| 2382 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2488 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| ... | @@ -2386,34 +2492,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2386,34 +2492,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2386 | }, | 2492 | }, |
| 2387 | Token.Id.Period => { | 2493 | Token.Id.Period => { |
| 2388 | if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| { | 2494 | if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| { |
| 2389 | const node = try arena.create(ast.Node.SuffixOp{ | 2495 | const node = try arena.create(ast.Node.SuffixOp); |
| 2496 | node.* = ast.Node.SuffixOp{ | ||
| 2390 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | 2497 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, |
| 2391 | .lhs = lhs, | 2498 | .lhs = lhs, |
| 2392 | .op = ast.Node.SuffixOp.Op.Deref, | 2499 | .op = ast.Node.SuffixOp.Op.Deref, |
| 2393 | .rtoken = asterisk_token, | 2500 | .rtoken = asterisk_token, |
| 2394 | }); | 2501 | }; |
| 2395 | opt_ctx.store(&node.base); | 2502 | opt_ctx.store(&node.base); |
| 2396 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2503 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2397 | continue; | 2504 | continue; |
| 2398 | } | 2505 | } |
| 2399 | if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| { | 2506 | if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| { |
| 2400 | const node = try arena.create(ast.Node.SuffixOp{ | 2507 | const node = try arena.create(ast.Node.SuffixOp); |
| 2508 | node.* = ast.Node.SuffixOp{ | ||
| 2401 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | 2509 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, |
| 2402 | .lhs = lhs, | 2510 | .lhs = lhs, |
| 2403 | .op = ast.Node.SuffixOp.Op.UnwrapOptional, | 2511 | .op = ast.Node.SuffixOp.Op.UnwrapOptional, |
| 2404 | .rtoken = question_token, | 2512 | .rtoken = question_token, |
| 2405 | }); | 2513 | }; |
| 2406 | opt_ctx.store(&node.base); | 2514 | opt_ctx.store(&node.base); |
| 2407 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2515 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| 2408 | continue; | 2516 | continue; |
| 2409 | } | 2517 | } |
| 2410 | const node = try arena.create(ast.Node.InfixOp{ | 2518 | const node = try arena.create(ast.Node.InfixOp); |
| 2519 | node.* = ast.Node.InfixOp{ | ||
| 2411 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2520 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2412 | .lhs = lhs, | 2521 | .lhs = lhs, |
| 2413 | .op_token = token_index, | 2522 | .op_token = token_index, |
| 2414 | .op = ast.Node.InfixOp.Op.Period, | 2523 | .op = ast.Node.InfixOp.Op.Period, |
| 2415 | .rhs = undefined, | 2524 | .rhs = undefined, |
| 2416 | }); | 2525 | }; |
| 2417 | opt_ctx.store(&node.base); | 2526 | opt_ctx.store(&node.base); |
| 2418 | 2527 | ||
| 2419 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | 2528 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; |
| ... | @@ -2467,11 +2576,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2467,11 +2576,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2467 | continue; | 2576 | continue; |
| 2468 | }, | 2577 | }, |
| 2469 | Token.Id.Keyword_promise => { | 2578 | Token.Id.Keyword_promise => { |
| 2470 | const node = try arena.create(ast.Node.PromiseType{ | 2579 | const node = try arena.create(ast.Node.PromiseType); |
| 2580 | node.* = ast.Node.PromiseType{ | ||
| 2471 | .base = ast.Node{ .id = ast.Node.Id.PromiseType }, | 2581 | .base = ast.Node{ .id = ast.Node.Id.PromiseType }, |
| 2472 | .promise_token = token.index, | 2582 | .promise_token = token.index, |
| 2473 | .result = null, | 2583 | .result = null, |
| 2474 | }); | 2584 | }; |
| 2475 | opt_ctx.store(&node.base); | 2585 | opt_ctx.store(&node.base); |
| 2476 | const next_token = nextToken(&tok_it, &tree); | 2586 | const next_token = nextToken(&tok_it, &tree); |
| 2477 | const next_token_index = next_token.index; | 2587 | const next_token_index = next_token.index; |
| ... | @@ -2493,12 +2603,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2493,12 +2603,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2493 | continue; | 2603 | continue; |
| 2494 | }, | 2604 | }, |
| 2495 | Token.Id.LParen => { | 2605 | Token.Id.LParen => { |
| 2496 | const node = try arena.create(ast.Node.GroupedExpression{ | 2606 | const node = try arena.create(ast.Node.GroupedExpression); |
| 2607 | node.* = ast.Node.GroupedExpression{ | ||
| 2497 | .base = ast.Node{ .id = ast.Node.Id.GroupedExpression }, | 2608 | .base = ast.Node{ .id = ast.Node.Id.GroupedExpression }, |
| 2498 | .lparen = token.index, | 2609 | .lparen = token.index, |
| 2499 | .expr = undefined, | 2610 | .expr = undefined, |
| 2500 | .rparen = undefined, | 2611 | .rparen = undefined, |
| 2501 | }); | 2612 | }; |
| 2502 | opt_ctx.store(&node.base); | 2613 | opt_ctx.store(&node.base); |
| 2503 | 2614 | ||
| 2504 | stack.append(State{ | 2615 | stack.append(State{ |
| ... | @@ -2511,12 +2622,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2511,12 +2622,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2511 | continue; | 2622 | continue; |
| 2512 | }, | 2623 | }, |
| 2513 | Token.Id.Builtin => { | 2624 | Token.Id.Builtin => { |
| 2514 | const node = try arena.create(ast.Node.BuiltinCall{ | 2625 | const node = try arena.create(ast.Node.BuiltinCall); |
| 2626 | node.* = ast.Node.BuiltinCall{ | ||
| 2515 | .base = ast.Node{ .id = ast.Node.Id.BuiltinCall }, | 2627 | .base = ast.Node{ .id = ast.Node.Id.BuiltinCall }, |
| 2516 | .builtin_token = token.index, | 2628 | .builtin_token = token.index, |
| 2517 | .params = ast.Node.BuiltinCall.ParamList.init(arena), | 2629 | .params = ast.Node.BuiltinCall.ParamList.init(arena), |
| 2518 | .rparen_token = undefined, | 2630 | .rparen_token = undefined, |
| 2519 | }); | 2631 | }; |
| 2520 | opt_ctx.store(&node.base); | 2632 | opt_ctx.store(&node.base); |
| 2521 | 2633 | ||
| 2522 | stack.append(State{ | 2634 | stack.append(State{ |
| ... | @@ -2530,12 +2642,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2530,12 +2642,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2530 | continue; | 2642 | continue; |
| 2531 | }, | 2643 | }, |
| 2532 | Token.Id.LBracket => { | 2644 | Token.Id.LBracket => { |
| 2533 | const node = try arena.create(ast.Node.PrefixOp{ | 2645 | const node = try arena.create(ast.Node.PrefixOp); |
| 2646 | node.* = ast.Node.PrefixOp{ | ||
| 2534 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | 2647 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, |
| 2535 | .op_token = token.index, | 2648 | .op_token = token.index, |
| 2536 | .op = undefined, | 2649 | .op = undefined, |
| 2537 | .rhs = undefined, | 2650 | .rhs = undefined, |
| 2538 | }); | 2651 | }; |
| 2539 | opt_ctx.store(&node.base); | 2652 | opt_ctx.store(&node.base); |
| 2540 | 2653 | ||
| 2541 | stack.append(State{ .SliceOrArrayType = node }) catch unreachable; | 2654 | stack.append(State{ .SliceOrArrayType = node }) catch unreachable; |
| ... | @@ -2593,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2593,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2593 | continue; | 2706 | continue; |
| 2594 | }, | 2707 | }, |
| 2595 | Token.Id.Keyword_fn => { | 2708 | Token.Id.Keyword_fn => { |
| 2596 | const fn_proto = try arena.create(ast.Node.FnProto{ | 2709 | const fn_proto = try arena.create(ast.Node.FnProto); |
| 2710 | fn_proto.* = ast.Node.FnProto{ | ||
| 2597 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | 2711 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, |
| 2598 | .doc_comments = null, | 2712 | .doc_comments = null, |
| 2599 | .visib_token = null, | 2713 | .visib_token = null, |
| ... | @@ -2609,13 +2723,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2609,13 +2723,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2609 | .lib_name = null, | 2723 | .lib_name = null, |
| 2610 | .align_expr = null, | 2724 | .align_expr = null, |
| 2611 | .section_expr = null, | 2725 | .section_expr = null, |
| 2612 | }); | 2726 | }; |
| 2613 | opt_ctx.store(&fn_proto.base); | 2727 | opt_ctx.store(&fn_proto.base); |
| 2614 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; | 2728 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; |
| 2615 | continue; | 2729 | continue; |
| 2616 | }, | 2730 | }, |
| 2617 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { | 2731 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { |
| 2618 | const fn_proto = try arena.create(ast.Node.FnProto{ | 2732 | const fn_proto = try arena.create(ast.Node.FnProto); |
| 2733 | fn_proto.* = ast.Node.FnProto{ | ||
| 2619 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | 2734 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, |
| 2620 | .doc_comments = null, | 2735 | .doc_comments = null, |
| 2621 | .visib_token = null, | 2736 | .visib_token = null, |
| ... | @@ -2631,7 +2746,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2631,7 +2746,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2631 | .lib_name = null, | 2746 | .lib_name = null, |
| 2632 | .align_expr = null, | 2747 | .align_expr = null, |
| 2633 | .section_expr = null, | 2748 | .section_expr = null, |
| 2634 | }); | 2749 | }; |
| 2635 | opt_ctx.store(&fn_proto.base); | 2750 | opt_ctx.store(&fn_proto.base); |
| 2636 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; | 2751 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; |
| 2637 | try stack.append(State{ | 2752 | try stack.append(State{ |
| ... | @@ -2643,7 +2758,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2643,7 +2758,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2643 | continue; | 2758 | continue; |
| 2644 | }, | 2759 | }, |
| 2645 | Token.Id.Keyword_asm => { | 2760 | Token.Id.Keyword_asm => { |
| 2646 | const node = try arena.create(ast.Node.Asm{ | 2761 | const node = try arena.create(ast.Node.Asm); |
| 2762 | node.* = ast.Node.Asm{ | ||
| 2647 | .base = ast.Node{ .id = ast.Node.Id.Asm }, | 2763 | .base = ast.Node{ .id = ast.Node.Id.Asm }, |
| 2648 | .asm_token = token.index, | 2764 | .asm_token = token.index, |
| 2649 | .volatile_token = null, | 2765 | .volatile_token = null, |
| ... | @@ -2652,7 +2768,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2652,7 +2768,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2652 | .inputs = ast.Node.Asm.InputList.init(arena), | 2768 | .inputs = ast.Node.Asm.InputList.init(arena), |
| 2653 | .clobbers = ast.Node.Asm.ClobberList.init(arena), | 2769 | .clobbers = ast.Node.Asm.ClobberList.init(arena), |
| 2654 | .rparen = undefined, | 2770 | .rparen = undefined, |
| 2655 | }); | 2771 | }; |
| 2656 | opt_ctx.store(&node.base); | 2772 | opt_ctx.store(&node.base); |
| 2657 | 2773 | ||
| 2658 | stack.append(State{ | 2774 | stack.append(State{ |
| ... | @@ -2701,13 +2817,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2701,13 +2817,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2701 | 2817 | ||
| 2702 | State.ErrorTypeOrSetDecl => |ctx| { | 2818 | State.ErrorTypeOrSetDecl => |ctx| { |
| 2703 | if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) { | 2819 | if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) { |
| 2704 | const node = try arena.create(ast.Node.InfixOp{ | 2820 | const node = try arena.create(ast.Node.InfixOp); |
| 2821 | node.* = ast.Node.InfixOp{ | ||
| 2705 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | 2822 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, |
| 2706 | .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base, | 2823 | .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base, |
| 2707 | .op_token = undefined, | 2824 | .op_token = undefined, |
| 2708 | .op = ast.Node.InfixOp.Op.Period, | 2825 | .op = ast.Node.InfixOp.Op.Period, |
| 2709 | .rhs = undefined, | 2826 | .rhs = undefined, |
| 2710 | }); | 2827 | }; |
| 2711 | ctx.opt_ctx.store(&node.base); | 2828 | ctx.opt_ctx.store(&node.base); |
| 2712 | stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | 2829 | stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; |
| 2713 | try stack.append(State{ | 2830 | try stack.append(State{ |
| ... | @@ -2719,12 +2836,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2719,12 +2836,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2719 | continue; | 2836 | continue; |
| 2720 | } | 2837 | } |
| 2721 | 2838 | ||
| 2722 | const node = try arena.create(ast.Node.ErrorSetDecl{ | 2839 | const node = try arena.create(ast.Node.ErrorSetDecl); |
| 2840 | node.* = ast.Node.ErrorSetDecl{ | ||
| 2723 | .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl }, | 2841 | .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl }, |
| 2724 | .error_token = ctx.error_token, | 2842 | .error_token = ctx.error_token, |
| 2725 | .decls = ast.Node.ErrorSetDecl.DeclList.init(arena), | 2843 | .decls = ast.Node.ErrorSetDecl.DeclList.init(arena), |
| 2726 | .rbrace_token = undefined, | 2844 | .rbrace_token = undefined, |
| 2727 | }); | 2845 | }; |
| 2728 | ctx.opt_ctx.store(&node.base); | 2846 | ctx.opt_ctx.store(&node.base); |
| 2729 | 2847 | ||
| 2730 | stack.append(State{ | 2848 | stack.append(State{ |
| ... | @@ -2785,11 +2903,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { | ... | @@ -2785,11 +2903,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { |
| 2785 | return tree; | 2903 | return tree; |
| 2786 | } | 2904 | } |
| 2787 | 2905 | ||
| 2788 | const node = try arena.create(ast.Node.ErrorTag{ | 2906 | const node = try arena.create(ast.Node.ErrorTag); |
| 2907 | node.* = ast.Node.ErrorTag{ | ||
| 2789 | .base = ast.Node{ .id = ast.Node.Id.ErrorTag }, | 2908 | .base = ast.Node{ .id = ast.Node.Id.ErrorTag }, |
| 2790 | .doc_comments = comments, | 2909 | .doc_comments = comments, |
| 2791 | .name_token = ident_token_index, | 2910 | .name_token = ident_token_index, |
| 2792 | }); | 2911 | }; |
| 2793 | node_ptr.* = &node.base; | 2912 | node_ptr.* = &node.base; |
| 2794 | continue; | 2913 | continue; |
| 2795 | }, | 2914 | }, |
| ... | @@ -2870,6 +2989,7 @@ const TopLevelDeclCtx = struct { | ... | @@ -2870,6 +2989,7 @@ const TopLevelDeclCtx = struct { |
| 2870 | const VarDeclCtx = struct { | 2989 | const VarDeclCtx = struct { |
| 2871 | mut_token: TokenIndex, | 2990 | mut_token: TokenIndex, |
| 2872 | visib_token: ?TokenIndex, | 2991 | visib_token: ?TokenIndex, |
| 2992 | thread_local_token: ?TokenIndex, | ||
| 2873 | comptime_token: ?TokenIndex, | 2993 | comptime_token: ?TokenIndex, |
| 2874 | extern_export_token: ?TokenIndex, | 2994 | extern_export_token: ?TokenIndex, |
| 2875 | lib_name: ?*ast.Node, | 2995 | lib_name: ?*ast.Node, |
| ... | @@ -3014,6 +3134,7 @@ const State = union(enum) { | ... | @@ -3014,6 +3134,7 @@ const State = union(enum) { |
| 3014 | ContainerInitArg: *ast.Node.ContainerDecl, | 3134 | ContainerInitArg: *ast.Node.ContainerDecl, |
| 3015 | ContainerDecl: *ast.Node.ContainerDecl, | 3135 | ContainerDecl: *ast.Node.ContainerDecl, |
| 3016 | 3136 | ||
| 3137 | ThreadLocal: VarDeclCtx, | ||
| 3017 | VarDecl: VarDeclCtx, | 3138 | VarDecl: VarDeclCtx, |
| 3018 | VarDeclAlign: *ast.Node.VarDecl, | 3139 | VarDeclAlign: *ast.Node.VarDecl, |
| 3019 | VarDeclSection: *ast.Node.VarDecl, | 3140 | VarDeclSection: *ast.Node.VarDecl, |
| ... | @@ -3129,10 +3250,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as | ... | @@ -3129,10 +3250,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as |
| 3129 | if (result.*) |comment_node| { | 3250 | if (result.*) |comment_node| { |
| 3130 | break :blk comment_node; | 3251 | break :blk comment_node; |
| 3131 | } else { | 3252 | } else { |
| 3132 | const comment_node = try arena.create(ast.Node.DocComment{ | 3253 | const comment_node = try arena.create(ast.Node.DocComment); |
| 3254 | comment_node.* = ast.Node.DocComment{ | ||
| 3133 | .base = ast.Node{ .id = ast.Node.Id.DocComment }, | 3255 | .base = ast.Node{ .id = ast.Node.Id.DocComment }, |
| 3134 | .lines = ast.Node.DocComment.LineList.init(arena), | 3256 | .lines = ast.Node.DocComment.LineList.init(arena), |
| 3135 | }); | 3257 | }; |
| 3136 | result.* = comment_node; | 3258 | result.* = comment_node; |
| 3137 | break :blk comment_node; | 3259 | break :blk comment_node; |
| 3138 | } | 3260 | } |
| ... | @@ -3158,10 +3280,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato | ... | @@ -3158,10 +3280,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato |
| 3158 | return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base; | 3280 | return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base; |
| 3159 | }, | 3281 | }, |
| 3160 | Token.Id.MultilineStringLiteralLine => { | 3282 | Token.Id.MultilineStringLiteralLine => { |
| 3161 | const node = try arena.create(ast.Node.MultilineStringLiteral{ | 3283 | const node = try arena.create(ast.Node.MultilineStringLiteral); |
| 3284 | node.* = ast.Node.MultilineStringLiteral{ | ||
| 3162 | .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral }, | 3285 | .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral }, |
| 3163 | .lines = ast.Node.MultilineStringLiteral.LineList.init(arena), | 3286 | .lines = ast.Node.MultilineStringLiteral.LineList.init(arena), |
| 3164 | }); | 3287 | }; |
| 3165 | try node.lines.push(token_index); | 3288 | try node.lines.push(token_index); |
| 3166 | while (true) { | 3289 | while (true) { |
| 3167 | const multiline_str = nextToken(tok_it, tree); | 3290 | const multiline_str = nextToken(tok_it, tree); |
| ... | @@ -3186,25 +3309,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato | ... | @@ -3186,25 +3309,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato |
| 3186 | fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool { | 3309 | fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool { |
| 3187 | switch (token_ptr.id) { | 3310 | switch (token_ptr.id) { |
| 3188 | Token.Id.Keyword_suspend => { | 3311 | Token.Id.Keyword_suspend => { |
| 3189 | const node = try arena.create(ast.Node.Suspend{ | 3312 | const node = try arena.create(ast.Node.Suspend); |
| 3313 | node.* = ast.Node.Suspend{ | ||
| 3190 | .base = ast.Node{ .id = ast.Node.Id.Suspend }, | 3314 | .base = ast.Node{ .id = ast.Node.Id.Suspend }, |
| 3191 | .suspend_token = token_index, | 3315 | .suspend_token = token_index, |
| 3192 | .body = null, | 3316 | .body = null, |
| 3193 | }); | 3317 | }; |
| 3194 | ctx.store(&node.base); | 3318 | ctx.store(&node.base); |
| 3195 | 3319 | ||
| 3196 | stack.append(State{ .SuspendBody = node }) catch unreachable; | 3320 | stack.append(State{ .SuspendBody = node }) catch unreachable; |
| 3197 | return true; | 3321 | return true; |
| 3198 | }, | 3322 | }, |
| 3199 | Token.Id.Keyword_if => { | 3323 | Token.Id.Keyword_if => { |
| 3200 | const node = try arena.create(ast.Node.If{ | 3324 | const node = try arena.create(ast.Node.If); |
| 3325 | node.* = ast.Node.If{ | ||
| 3201 | .base = ast.Node{ .id = ast.Node.Id.If }, | 3326 | .base = ast.Node{ .id = ast.Node.Id.If }, |
| 3202 | .if_token = token_index, | 3327 | .if_token = token_index, |
| 3203 | .condition = undefined, | 3328 | .condition = undefined, |
| 3204 | .payload = null, | 3329 | .payload = null, |
| 3205 | .body = undefined, | 3330 | .body = undefined, |
| 3206 | .@"else" = null, | 3331 | .@"else" = null, |
| 3207 | }); | 3332 | }; |
| 3208 | ctx.store(&node.base); | 3333 | ctx.store(&node.base); |
| 3209 | 3334 | ||
| 3210 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; | 3335 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; |
| ... | @@ -3238,13 +3363,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti | ... | @@ -3238,13 +3363,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti |
| 3238 | return true; | 3363 | return true; |
| 3239 | }, | 3364 | }, |
| 3240 | Token.Id.Keyword_switch => { | 3365 | Token.Id.Keyword_switch => { |
| 3241 | const node = try arena.create(ast.Node.Switch{ | 3366 | const node = try arena.create(ast.Node.Switch); |
| 3367 | node.* = ast.Node.Switch{ | ||
| 3242 | .base = ast.Node{ .id = ast.Node.Id.Switch }, | 3368 | .base = ast.Node{ .id = ast.Node.Id.Switch }, |
| 3243 | .switch_token = token_index, | 3369 | .switch_token = token_index, |
| 3244 | .expr = undefined, | 3370 | .expr = undefined, |
| 3245 | .cases = ast.Node.Switch.CaseList.init(arena), | 3371 | .cases = ast.Node.Switch.CaseList.init(arena), |
| 3246 | .rbrace = undefined, | 3372 | .rbrace = undefined, |
| 3247 | }); | 3373 | }; |
| 3248 | ctx.store(&node.base); | 3374 | ctx.store(&node.base); |
| 3249 | 3375 | ||
| 3250 | stack.append(State{ | 3376 | stack.append(State{ |
| ... | @@ -3260,25 +3386,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti | ... | @@ -3260,25 +3386,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti |
| 3260 | return true; | 3386 | return true; |
| 3261 | }, | 3387 | }, |
| 3262 | Token.Id.Keyword_comptime => { | 3388 | Token.Id.Keyword_comptime => { |
| 3263 | const node = try arena.create(ast.Node.Comptime{ | 3389 | const node = try arena.create(ast.Node.Comptime); |
| 3390 | node.* = ast.Node.Comptime{ | ||
| 3264 | .base = ast.Node{ .id = ast.Node.Id.Comptime }, | 3391 | .base = ast.Node{ .id = ast.Node.Id.Comptime }, |
| 3265 | .comptime_token = token_index, | 3392 | .comptime_token = token_index, |
| 3266 | .expr = undefined, | 3393 | .expr = undefined, |
| 3267 | .doc_comments = null, | 3394 | .doc_comments = null, |
| 3268 | }); | 3395 | }; |
| 3269 | ctx.store(&node.base); | 3396 | ctx.store(&node.base); |
| 3270 | 3397 | ||
| 3271 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | 3398 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); |
| 3272 | return true; | 3399 | return true; |
| 3273 | }, | 3400 | }, |
| 3274 | Token.Id.LBrace => { | 3401 | Token.Id.LBrace => { |
| 3275 | const block = try arena.create(ast.Node.Block{ | 3402 | const block = try arena.create(ast.Node.Block); |
| 3403 | block.* = ast.Node.Block{ | ||
| 3276 | .base = ast.Node{ .id = ast.Node.Id.Block }, | 3404 | .base = ast.Node{ .id = ast.Node.Id.Block }, |
| 3277 | .label = null, | 3405 | .label = null, |
| 3278 | .lbrace = token_index, | 3406 | .lbrace = token_index, |
| 3279 | .statements = ast.Node.Block.StatementList.init(arena), | 3407 | .statements = ast.Node.Block.StatementList.init(arena), |
| 3280 | .rbrace = undefined, | 3408 | .rbrace = undefined, |
| 3281 | }); | 3409 | }; |
| 3282 | ctx.store(&block.base); | 3410 | ctx.store(&block.base); |
| 3283 | stack.append(State{ .Block = block }) catch unreachable; | 3411 | stack.append(State{ .Block = block }) catch unreachable; |
| 3284 | return true; | 3412 | return true; |
| ... | @@ -3397,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op { | ... | @@ -3397,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op { |
| 3397 | Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} }, | 3525 | Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} }, |
| 3398 | Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} }, | 3526 | Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} }, |
| 3399 | Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} }, | 3527 | Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} }, |
| 3400 | Token.Id.Asterisk, Token.Id.AsteriskAsterisk, Token.Id.BracketStarBracket => ast.Node.PrefixOp.Op{ | 3528 | |
| 3529 | Token.Id.Asterisk, | ||
| 3530 | Token.Id.AsteriskAsterisk, | ||
| 3531 | Token.Id.BracketStarBracket, | ||
| 3532 | Token.Id.BracketStarCBracket, | ||
| 3533 | => ast.Node.PrefixOp.Op{ | ||
| 3401 | .PtrType = ast.Node.PrefixOp.PtrInfo{ | 3534 | .PtrType = ast.Node.PrefixOp.PtrInfo{ |
| 3402 | .align_info = null, | 3535 | .align_info = null, |
| 3403 | .const_token = null, | 3536 | .const_token = null, |
| ... | @@ -3412,10 +3545,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op { | ... | @@ -3412,10 +3545,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op { |
| 3412 | } | 3545 | } |
| 3413 | 3546 | ||
| 3414 | fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T { | 3547 | fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T { |
| 3415 | return arena.create(T{ | 3548 | const result = try arena.create(T); |
| 3549 | result.* = T{ | ||
| 3416 | .base = ast.Node{ .id = ast.Node.typeToId(T) }, | 3550 | .base = ast.Node{ .id = ast.Node.typeToId(T) }, |
| 3417 | .token = token_index, | 3551 | .token = token_index, |
| 3418 | }); | 3552 | }; |
| 3553 | return result; | ||
| 3419 | } | 3554 | } |
| 3420 | 3555 | ||
| 3421 | fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T { | 3556 | fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T { |
std/zig/parser_test.zig+16-1| ... | @@ -1,3 +1,17 @@ | ... | @@ -1,3 +1,17 @@ |
| 1 | test "zig fmt: C pointers" { | ||
| 2 | try testCanonical( | ||
| 3 | \\const Ptr = [*c]i32; | ||
| 4 | \\ | ||
| 5 | ); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "zig fmt: threadlocal" { | ||
| 9 | try testCanonical( | ||
| 10 | \\threadlocal var x: i32 = 1234; | ||
| 11 | \\ | ||
| 12 | ); | ||
| 13 | } | ||
| 14 | |||
| 1 | test "zig fmt: linksection" { | 15 | test "zig fmt: linksection" { |
| 2 | try testCanonical( | 16 | try testCanonical( |
| 3 | \\export var aoeu: u64 linksection(".text.derp") = 1234; | 17 | \\export var aoeu: u64 linksection(".text.derp") = 1234; |
| ... | @@ -5,6 +19,7 @@ test "zig fmt: linksection" { | ... | @@ -5,6 +19,7 @@ test "zig fmt: linksection" { |
| 5 | \\ | 19 | \\ |
| 6 | ); | 20 | ); |
| 7 | } | 21 | } |
| 22 | |||
| 8 | test "zig fmt: shebang line" { | 23 | test "zig fmt: shebang line" { |
| 9 | try testCanonical( | 24 | try testCanonical( |
| 10 | \\#!/usr/bin/env zig | 25 | \\#!/usr/bin/env zig |
| ... | @@ -1940,7 +1955,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { | ... | @@ -1940,7 +1955,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { |
| 1940 | warn("std.zig.render returned {} instead of {}\n", anything_changed, changes_expected); | 1955 | warn("std.zig.render returned {} instead of {}\n", anything_changed, changes_expected); |
| 1941 | return error.TestFailed; | 1956 | return error.TestFailed; |
| 1942 | } | 1957 | } |
| 1943 | std.debug.assert(anything_changed == changes_expected); | 1958 | std.testing.expect(anything_changed == changes_expected); |
| 1944 | failing_allocator.allocator.free(result_source); | 1959 | failing_allocator.allocator.free(result_source); |
| 1945 | break :x failing_allocator.index; | 1960 | break :x failing_allocator.index; |
| 1946 | }; | 1961 | }; |
std/zig/render.zig+3| ... | @@ -1706,6 +1706,9 @@ fn renderVarDecl( | ... | @@ -1706,6 +1706,9 @@ fn renderVarDecl( |
| 1706 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime | 1706 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime |
| 1707 | } | 1707 | } |
| 1708 | 1708 | ||
| 1709 | if (var_decl.thread_local_token) |thread_local_token| { | ||
| 1710 | try renderToken(tree, stream, thread_local_token, indent, start_col, Space.Space); // threadlocal | ||
| 1711 | } | ||
| 1709 | try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var | 1712 | try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var |
| 1710 | 1713 | ||
| 1711 | const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or | 1714 | const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or |
std/zig/tokenizer.zig+25-2| ... | @@ -53,6 +53,7 @@ pub const Token = struct { | ... | @@ -53,6 +53,7 @@ pub const Token = struct { |
| 53 | Keyword{ .bytes = "switch", .id = Id.Keyword_switch }, | 53 | Keyword{ .bytes = "switch", .id = Id.Keyword_switch }, |
| 54 | Keyword{ .bytes = "test", .id = Id.Keyword_test }, | 54 | Keyword{ .bytes = "test", .id = Id.Keyword_test }, |
| 55 | Keyword{ .bytes = "this", .id = Id.Keyword_this }, | 55 | Keyword{ .bytes = "this", .id = Id.Keyword_this }, |
| 56 | Keyword{ .bytes = "threadlocal", .id = Id.Keyword_threadlocal }, | ||
| 56 | Keyword{ .bytes = "true", .id = Id.Keyword_true }, | 57 | Keyword{ .bytes = "true", .id = Id.Keyword_true }, |
| 57 | Keyword{ .bytes = "try", .id = Id.Keyword_try }, | 58 | Keyword{ .bytes = "try", .id = Id.Keyword_try }, |
| 58 | Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined }, | 59 | Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined }, |
| ... | @@ -140,6 +141,7 @@ pub const Token = struct { | ... | @@ -140,6 +141,7 @@ pub const Token = struct { |
| 140 | LineComment, | 141 | LineComment, |
| 141 | DocComment, | 142 | DocComment, |
| 142 | BracketStarBracket, | 143 | BracketStarBracket, |
| 144 | BracketStarCBracket, | ||
| 143 | ShebangLine, | 145 | ShebangLine, |
| 144 | Keyword_align, | 146 | Keyword_align, |
| 145 | Keyword_and, | 147 | Keyword_and, |
| ... | @@ -182,6 +184,7 @@ pub const Token = struct { | ... | @@ -182,6 +184,7 @@ pub const Token = struct { |
| 182 | Keyword_switch, | 184 | Keyword_switch, |
| 183 | Keyword_test, | 185 | Keyword_test, |
| 184 | Keyword_this, | 186 | Keyword_this, |
| 187 | Keyword_threadlocal, | ||
| 185 | Keyword_true, | 188 | Keyword_true, |
| 186 | Keyword_try, | 189 | Keyword_try, |
| 187 | Keyword_undefined, | 190 | Keyword_undefined, |
| ... | @@ -277,6 +280,7 @@ pub const Tokenizer = struct { | ... | @@ -277,6 +280,7 @@ pub const Tokenizer = struct { |
| 277 | SawAtSign, | 280 | SawAtSign, |
| 278 | LBracket, | 281 | LBracket, |
| 279 | LBracketStar, | 282 | LBracketStar, |
| 283 | LBracketStarC, | ||
| 280 | }; | 284 | }; |
| 281 | 285 | ||
| 282 | pub fn next(self: *Tokenizer) Token { | 286 | pub fn next(self: *Tokenizer) Token { |
| ... | @@ -454,6 +458,9 @@ pub const Tokenizer = struct { | ... | @@ -454,6 +458,9 @@ pub const Tokenizer = struct { |
| 454 | }, | 458 | }, |
| 455 | 459 | ||
| 456 | State.LBracketStar => switch (c) { | 460 | State.LBracketStar => switch (c) { |
| 461 | 'c' => { | ||
| 462 | state = State.LBracketStarC; | ||
| 463 | }, | ||
| 457 | ']' => { | 464 | ']' => { |
| 458 | result.id = Token.Id.BracketStarBracket; | 465 | result.id = Token.Id.BracketStarBracket; |
| 459 | self.index += 1; | 466 | self.index += 1; |
| ... | @@ -465,6 +472,18 @@ pub const Tokenizer = struct { | ... | @@ -465,6 +472,18 @@ pub const Tokenizer = struct { |
| 465 | }, | 472 | }, |
| 466 | }, | 473 | }, |
| 467 | 474 | ||
| 475 | State.LBracketStarC => switch (c) { | ||
| 476 | ']' => { | ||
| 477 | result.id = Token.Id.BracketStarCBracket; | ||
| 478 | self.index += 1; | ||
| 479 | break; | ||
| 480 | }, | ||
| 481 | else => { | ||
| 482 | result.id = Token.Id.Invalid; | ||
| 483 | break; | ||
| 484 | }, | ||
| 485 | }, | ||
| 486 | |||
| 468 | State.Ampersand => switch (c) { | 487 | State.Ampersand => switch (c) { |
| 469 | '=' => { | 488 | '=' => { |
| 470 | result.id = Token.Id.AmpersandEqual; | 489 | result.id = Token.Id.AmpersandEqual; |
| ... | @@ -1033,6 +1052,7 @@ pub const Tokenizer = struct { | ... | @@ -1033,6 +1052,7 @@ pub const Tokenizer = struct { |
| 1033 | State.CharLiteralEnd, | 1052 | State.CharLiteralEnd, |
| 1034 | State.StringLiteralBackslash, | 1053 | State.StringLiteralBackslash, |
| 1035 | State.LBracketStar, | 1054 | State.LBracketStar, |
| 1055 | State.LBracketStarC, | ||
| 1036 | => { | 1056 | => { |
| 1037 | result.id = Token.Id.Invalid; | 1057 | result.id = Token.Id.Invalid; |
| 1038 | }, | 1058 | }, |
| ... | @@ -1167,12 +1187,15 @@ test "tokenizer" { | ... | @@ -1167,12 +1187,15 @@ test "tokenizer" { |
| 1167 | testTokenize("test", []Token.Id{Token.Id.Keyword_test}); | 1187 | testTokenize("test", []Token.Id{Token.Id.Keyword_test}); |
| 1168 | } | 1188 | } |
| 1169 | 1189 | ||
| 1170 | test "tokenizer - unknown length pointer" { | 1190 | test "tokenizer - unknown length pointer and then c pointer" { |
| 1171 | testTokenize( | 1191 | testTokenize( |
| 1172 | \\[*]u8 | 1192 | \\[*]u8 |
| 1193 | \\[*c]u8 | ||
| 1173 | , []Token.Id{ | 1194 | , []Token.Id{ |
| 1174 | Token.Id.BracketStarBracket, | 1195 | Token.Id.BracketStarBracket, |
| 1175 | Token.Id.Identifier, | 1196 | Token.Id.Identifier, |
| 1197 | Token.Id.BracketStarCBracket, | ||
| 1198 | Token.Id.Identifier, | ||
| 1176 | }); | 1199 | }); |
| 1177 | } | 1200 | } |
| 1178 | 1201 | ||
| ... | @@ -1345,5 +1368,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { | ... | @@ -1345,5 +1368,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { |
| 1345 | } | 1368 | } |
| 1346 | } | 1369 | } |
| 1347 | const last_token = tokenizer.next(); | 1370 | const last_token = tokenizer.next(); |
| 1348 | std.debug.assert(last_token.id == Token.Id.Eof); | 1371 | std.testing.expect(last_token.id == Token.Id.Eof); |
| 1349 | } | 1372 | } |
test/behavior.zig deleted-77| ... | @@ -1,77 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | |||
| 3 | comptime { | ||
| 4 | _ = @import("cases/align.zig"); | ||
| 5 | _ = @import("cases/alignof.zig"); | ||
| 6 | _ = @import("cases/array.zig"); | ||
| 7 | _ = @import("cases/asm.zig"); | ||
| 8 | _ = @import("cases/atomics.zig"); | ||
| 9 | _ = @import("cases/bitcast.zig"); | ||
| 10 | _ = @import("cases/bool.zig"); | ||
| 11 | _ = @import("cases/bugs/1076.zig"); | ||
| 12 | _ = @import("cases/bugs/1111.zig"); | ||
| 13 | _ = @import("cases/bugs/1277.zig"); | ||
| 14 | _ = @import("cases/bugs/1322.zig"); | ||
| 15 | _ = @import("cases/bugs/1381.zig"); | ||
| 16 | _ = @import("cases/bugs/1421.zig"); | ||
| 17 | _ = @import("cases/bugs/1442.zig"); | ||
| 18 | _ = @import("cases/bugs/1486.zig"); | ||
| 19 | _ = @import("cases/bugs/394.zig"); | ||
| 20 | _ = @import("cases/bugs/655.zig"); | ||
| 21 | _ = @import("cases/bugs/656.zig"); | ||
| 22 | _ = @import("cases/bugs/726.zig"); | ||
| 23 | _ = @import("cases/bugs/828.zig"); | ||
| 24 | _ = @import("cases/bugs/920.zig"); | ||
| 25 | _ = @import("cases/byval_arg_var.zig"); | ||
| 26 | _ = @import("cases/cancel.zig"); | ||
| 27 | _ = @import("cases/cast.zig"); | ||
| 28 | _ = @import("cases/const_slice_child.zig"); | ||
| 29 | _ = @import("cases/coroutine_await_struct.zig"); | ||
| 30 | _ = @import("cases/coroutines.zig"); | ||
| 31 | _ = @import("cases/defer.zig"); | ||
| 32 | _ = @import("cases/enum.zig"); | ||
| 33 | _ = @import("cases/enum_with_members.zig"); | ||
| 34 | _ = @import("cases/error.zig"); | ||
| 35 | _ = @import("cases/eval.zig"); | ||
| 36 | _ = @import("cases/field_parent_ptr.zig"); | ||
| 37 | _ = @import("cases/fn.zig"); | ||
| 38 | _ = @import("cases/fn_in_struct_in_comptime.zig"); | ||
| 39 | _ = @import("cases/for.zig"); | ||
| 40 | _ = @import("cases/generics.zig"); | ||
| 41 | _ = @import("cases/if.zig"); | ||
| 42 | _ = @import("cases/import.zig"); | ||
| 43 | _ = @import("cases/incomplete_struct_param_tld.zig"); | ||
| 44 | _ = @import("cases/ir_block_deps.zig"); | ||
| 45 | _ = @import("cases/math.zig"); | ||
| 46 | _ = @import("cases/merge_error_sets.zig"); | ||
| 47 | _ = @import("cases/misc.zig"); | ||
| 48 | _ = @import("cases/namespace_depends_on_compile_var/index.zig"); | ||
| 49 | _ = @import("cases/new_stack_call.zig"); | ||
| 50 | _ = @import("cases/null.zig"); | ||
| 51 | _ = @import("cases/optional.zig"); | ||
| 52 | _ = @import("cases/pointers.zig"); | ||
| 53 | _ = @import("cases/popcount.zig"); | ||
| 54 | _ = @import("cases/pub_enum/index.zig"); | ||
| 55 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); | ||
| 56 | _ = @import("cases/reflection.zig"); | ||
| 57 | _ = @import("cases/sizeof_and_typeof.zig"); | ||
| 58 | _ = @import("cases/slice.zig"); | ||
| 59 | _ = @import("cases/struct.zig"); | ||
| 60 | _ = @import("cases/struct_contains_null_ptr_itself.zig"); | ||
| 61 | _ = @import("cases/struct_contains_slice_of_itself.zig"); | ||
| 62 | _ = @import("cases/switch.zig"); | ||
| 63 | _ = @import("cases/switch_prong_err_enum.zig"); | ||
| 64 | _ = @import("cases/switch_prong_implicit_cast.zig"); | ||
| 65 | _ = @import("cases/syntax.zig"); | ||
| 66 | _ = @import("cases/this.zig"); | ||
| 67 | _ = @import("cases/try.zig"); | ||
| 68 | _ = @import("cases/type_info.zig"); | ||
| 69 | _ = @import("cases/undefined.zig"); | ||
| 70 | _ = @import("cases/underscore.zig"); | ||
| 71 | _ = @import("cases/union.zig"); | ||
| 72 | _ = @import("cases/var_args.zig"); | ||
| 73 | _ = @import("cases/void.zig"); | ||
| 74 | _ = @import("cases/while.zig"); | ||
| 75 | _ = @import("cases/widening.zig"); | ||
| 76 | _ = @import("cases/bit_shifting.zig"); | ||
| 77 | } | ||
test/cases/align.zig deleted-230| ... | @@ -1,230 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | var foo: u8 align(4) = 100; | ||
| 5 | |||
| 6 | test "global variable alignment" { | ||
| 7 | assert(@typeOf(&foo).alignment == 4); | ||
| 8 | assert(@typeOf(&foo) == *align(4) u8); | ||
| 9 | const slice = (*[1]u8)(&foo)[0..]; | ||
| 10 | assert(@typeOf(slice) == []align(4) u8); | ||
| 11 | } | ||
| 12 | |||
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { | ||
| 14 | return 1234; | ||
| 15 | } | ||
| 16 | fn noop1() align(1) void {} | ||
| 17 | fn noop4() align(4) void {} | ||
| 18 | |||
| 19 | test "function alignment" { | ||
| 20 | assert(derp() == 1234); | ||
| 21 | assert(@typeOf(noop1) == fn () align(1) void); | ||
| 22 | assert(@typeOf(noop4) == fn () align(4) void); | ||
| 23 | noop1(); | ||
| 24 | noop4(); | ||
| 25 | } | ||
| 26 | |||
| 27 | var baz: packed struct { | ||
| 28 | a: u32, | ||
| 29 | b: u32, | ||
| 30 | } = undefined; | ||
| 31 | |||
| 32 | test "packed struct alignment" { | ||
| 33 | assert(@typeOf(&baz.b) == *align(1) u32); | ||
| 34 | } | ||
| 35 | |||
| 36 | const blah: packed struct { | ||
| 37 | a: u3, | ||
| 38 | b: u3, | ||
| 39 | c: u2, | ||
| 40 | } = undefined; | ||
| 41 | |||
| 42 | test "bit field alignment" { | ||
| 43 | assert(@typeOf(&blah.b) == *align(1:3:1) const u3); | ||
| 44 | } | ||
| 45 | |||
| 46 | test "default alignment allows unspecified in type syntax" { | ||
| 47 | assert(*u32 == *align(@alignOf(u32)) u32); | ||
| 48 | } | ||
| 49 | |||
| 50 | test "implicitly decreasing pointer alignment" { | ||
| 51 | const a: u32 align(4) = 3; | ||
| 52 | const b: u32 align(8) = 4; | ||
| 53 | assert(addUnaligned(&a, &b) == 7); | ||
| 54 | } | ||
| 55 | |||
| 56 | fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | ||
| 57 | return a.* + b.*; | ||
| 58 | } | ||
| 59 | |||
| 60 | test "implicitly decreasing slice alignment" { | ||
| 61 | const a: u32 align(4) = 3; | ||
| 62 | const b: u32 align(8) = 4; | ||
| 63 | assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); | ||
| 64 | } | ||
| 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { | ||
| 66 | return a[0] + b[0]; | ||
| 67 | } | ||
| 68 | |||
| 69 | test "specifying alignment allows pointer cast" { | ||
| 70 | testBytesAlign(0x33); | ||
| 71 | } | ||
| 72 | fn testBytesAlign(b: u8) void { | ||
| 73 | var bytes align(4) = []u8{ | ||
| 74 | b, | ||
| 75 | b, | ||
| 76 | b, | ||
| 77 | b, | ||
| 78 | }; | ||
| 79 | const ptr = @ptrCast(*u32, &bytes[0]); | ||
| 80 | assert(ptr.* == 0x33333333); | ||
| 81 | } | ||
| 82 | |||
| 83 | test "specifying alignment allows slice cast" { | ||
| 84 | testBytesAlignSlice(0x33); | ||
| 85 | } | ||
| 86 | fn testBytesAlignSlice(b: u8) void { | ||
| 87 | var bytes align(4) = []u8{ | ||
| 88 | b, | ||
| 89 | b, | ||
| 90 | b, | ||
| 91 | b, | ||
| 92 | }; | ||
| 93 | const slice: []u32 = @bytesToSlice(u32, bytes[0..]); | ||
| 94 | assert(slice[0] == 0x33333333); | ||
| 95 | } | ||
| 96 | |||
| 97 | test "@alignCast pointers" { | ||
| 98 | var x: u32 align(4) = 1; | ||
| 99 | expectsOnly1(&x); | ||
| 100 | assert(x == 2); | ||
| 101 | } | ||
| 102 | fn expectsOnly1(x: *align(1) u32) void { | ||
| 103 | expects4(@alignCast(4, x)); | ||
| 104 | } | ||
| 105 | fn expects4(x: *align(4) u32) void { | ||
| 106 | x.* += 1; | ||
| 107 | } | ||
| 108 | |||
| 109 | test "@alignCast slices" { | ||
| 110 | var array align(4) = []u32{ | ||
| 111 | 1, | ||
| 112 | 1, | ||
| 113 | }; | ||
| 114 | const slice = array[0..]; | ||
| 115 | sliceExpectsOnly1(slice); | ||
| 116 | assert(slice[0] == 2); | ||
| 117 | } | ||
| 118 | fn sliceExpectsOnly1(slice: []align(1) u32) void { | ||
| 119 | sliceExpects4(@alignCast(4, slice)); | ||
| 120 | } | ||
| 121 | fn sliceExpects4(slice: []align(4) u32) void { | ||
| 122 | slice[0] += 1; | ||
| 123 | } | ||
| 124 | |||
| 125 | test "implicitly decreasing fn alignment" { | ||
| 126 | testImplicitlyDecreaseFnAlign(alignedSmall, 1234); | ||
| 127 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); | ||
| 128 | } | ||
| 129 | |||
| 130 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { | ||
| 131 | assert(ptr() == answer); | ||
| 132 | } | ||
| 133 | |||
| 134 | fn alignedSmall() align(8) i32 { | ||
| 135 | return 1234; | ||
| 136 | } | ||
| 137 | fn alignedBig() align(16) i32 { | ||
| 138 | return 5678; | ||
| 139 | } | ||
| 140 | |||
| 141 | test "@alignCast functions" { | ||
| 142 | assert(fnExpectsOnly1(simple4) == 0x19); | ||
| 143 | } | ||
| 144 | fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 { | ||
| 145 | return fnExpects4(@alignCast(4, ptr)); | ||
| 146 | } | ||
| 147 | fn fnExpects4(ptr: fn () align(4) i32) i32 { | ||
| 148 | return ptr(); | ||
| 149 | } | ||
| 150 | fn simple4() align(4) i32 { | ||
| 151 | return 0x19; | ||
| 152 | } | ||
| 153 | |||
| 154 | test "generic function with align param" { | ||
| 155 | assert(whyWouldYouEverDoThis(1) == 0x1); | ||
| 156 | assert(whyWouldYouEverDoThis(4) == 0x1); | ||
| 157 | assert(whyWouldYouEverDoThis(8) == 0x1); | ||
| 158 | } | ||
| 159 | |||
| 160 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { | ||
| 161 | return 0x1; | ||
| 162 | } | ||
| 163 | |||
| 164 | test "@ptrCast preserves alignment of bigger source" { | ||
| 165 | var x: u32 align(16) = 1234; | ||
| 166 | const ptr = @ptrCast(*u8, &x); | ||
| 167 | assert(@typeOf(ptr) == *align(16) u8); | ||
| 168 | } | ||
| 169 | |||
| 170 | test "runtime known array index has best alignment possible" { | ||
| 171 | // take full advantage of over-alignment | ||
| 172 | var array align(4) = []u8{ 1, 2, 3, 4 }; | ||
| 173 | assert(@typeOf(&array[0]) == *align(4) u8); | ||
| 174 | assert(@typeOf(&array[1]) == *u8); | ||
| 175 | assert(@typeOf(&array[2]) == *align(2) u8); | ||
| 176 | assert(@typeOf(&array[3]) == *u8); | ||
| 177 | |||
| 178 | // because align is too small but we still figure out to use 2 | ||
| 179 | var bigger align(2) = []u64{ 1, 2, 3, 4 }; | ||
| 180 | assert(@typeOf(&bigger[0]) == *align(2) u64); | ||
| 181 | assert(@typeOf(&bigger[1]) == *align(2) u64); | ||
| 182 | assert(@typeOf(&bigger[2]) == *align(2) u64); | ||
| 183 | assert(@typeOf(&bigger[3]) == *align(2) u64); | ||
| 184 | |||
| 185 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 | ||
| 186 | var smaller align(2) = []u32{ 1, 2, 3, 4 }; | ||
| 187 | comptime assert(@typeOf(smaller[0..]) == []align(2) u32); | ||
| 188 | comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32); | ||
| 189 | testIndex(smaller[0..].ptr, 0, *align(2) u32); | ||
| 190 | testIndex(smaller[0..].ptr, 1, *align(2) u32); | ||
| 191 | testIndex(smaller[0..].ptr, 2, *align(2) u32); | ||
| 192 | testIndex(smaller[0..].ptr, 3, *align(2) u32); | ||
| 193 | |||
| 194 | // has to use ABI alignment because index known at runtime only | ||
| 195 | testIndex2(array[0..].ptr, 0, *u8); | ||
| 196 | testIndex2(array[0..].ptr, 1, *u8); | ||
| 197 | testIndex2(array[0..].ptr, 2, *u8); | ||
| 198 | testIndex2(array[0..].ptr, 3, *u8); | ||
| 199 | } | ||
| 200 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { | ||
| 201 | comptime assert(@typeOf(&smaller[index]) == T); | ||
| 202 | } | ||
| 203 | fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void { | ||
| 204 | comptime assert(@typeOf(&ptr[index]) == T); | ||
| 205 | } | ||
| 206 | |||
| 207 | test "alignstack" { | ||
| 208 | assert(fnWithAlignedStack() == 1234); | ||
| 209 | } | ||
| 210 | |||
| 211 | fn fnWithAlignedStack() i32 { | ||
| 212 | @setAlignStack(256); | ||
| 213 | return 1234; | ||
| 214 | } | ||
| 215 | |||
| 216 | test "alignment of structs" { | ||
| 217 | assert(@alignOf(struct { | ||
| 218 | a: i32, | ||
| 219 | b: *i32, | ||
| 220 | }) == @alignOf(usize)); | ||
| 221 | } | ||
| 222 | |||
| 223 | test "alignment of extern() void" { | ||
| 224 | var runtime_nothing = nothing; | ||
| 225 | const casted1 = @ptrCast(*const u8, runtime_nothing); | ||
| 226 | const casted2 = @ptrCast(extern fn () void, casted1); | ||
| 227 | casted2(); | ||
| 228 | } | ||
| 229 | |||
| 230 | extern fn nothing() void {} | ||
test/cases/alignof.zig deleted-17| ... | @@ -1,17 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const maxInt = std.math.maxInt; | ||
| 5 | |||
| 6 | const Foo = struct { | ||
| 7 | x: u32, | ||
| 8 | y: u32, | ||
| 9 | z: u32, | ||
| 10 | }; | ||
| 11 | |||
| 12 | test "@alignOf(T) before referencing T" { | ||
| 13 | comptime assert(@alignOf(Foo) != maxInt(usize)); | ||
| 14 | if (builtin.arch == builtin.Arch.x86_64) { | ||
| 15 | comptime assert(@alignOf(Foo) == 4); | ||
| 16 | } | ||
| 17 | } | ||
test/cases/array.zig deleted-173| ... | @@ -1,173 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | test "arrays" { | ||
| 5 | var array: [5]u32 = undefined; | ||
| 6 | |||
| 7 | var i: u32 = 0; | ||
| 8 | while (i < 5) { | ||
| 9 | array[i] = i + 1; | ||
| 10 | i = array[i]; | ||
| 11 | } | ||
| 12 | |||
| 13 | i = 0; | ||
| 14 | var accumulator = u32(0); | ||
| 15 | while (i < 5) { | ||
| 16 | accumulator += array[i]; | ||
| 17 | |||
| 18 | i += 1; | ||
| 19 | } | ||
| 20 | |||
| 21 | assert(accumulator == 15); | ||
| 22 | assert(getArrayLen(array) == 5); | ||
| 23 | } | ||
| 24 | fn getArrayLen(a: []const u32) usize { | ||
| 25 | return a.len; | ||
| 26 | } | ||
| 27 | |||
| 28 | test "void arrays" { | ||
| 29 | var array: [4]void = undefined; | ||
| 30 | array[0] = void{}; | ||
| 31 | array[1] = array[2]; | ||
| 32 | assert(@sizeOf(@typeOf(array)) == 0); | ||
| 33 | assert(array.len == 4); | ||
| 34 | } | ||
| 35 | |||
| 36 | test "array literal" { | ||
| 37 | const hex_mult = []u16{ | ||
| 38 | 4096, | ||
| 39 | 256, | ||
| 40 | 16, | ||
| 41 | 1, | ||
| 42 | }; | ||
| 43 | |||
| 44 | assert(hex_mult.len == 4); | ||
| 45 | assert(hex_mult[1] == 256); | ||
| 46 | } | ||
| 47 | |||
| 48 | test "array dot len const expr" { | ||
| 49 | assert(comptime x: { | ||
| 50 | break :x some_array.len == 4; | ||
| 51 | }); | ||
| 52 | } | ||
| 53 | |||
| 54 | const ArrayDotLenConstExpr = struct { | ||
| 55 | y: [some_array.len]u8, | ||
| 56 | }; | ||
| 57 | const some_array = []u8{ | ||
| 58 | 0, | ||
| 59 | 1, | ||
| 60 | 2, | ||
| 61 | 3, | ||
| 62 | }; | ||
| 63 | |||
| 64 | test "nested arrays" { | ||
| 65 | const array_of_strings = [][]const u8{ | ||
| 66 | "hello", | ||
| 67 | "this", | ||
| 68 | "is", | ||
| 69 | "my", | ||
| 70 | "thing", | ||
| 71 | }; | ||
| 72 | for (array_of_strings) |s, i| { | ||
| 73 | if (i == 0) assert(mem.eql(u8, s, "hello")); | ||
| 74 | if (i == 1) assert(mem.eql(u8, s, "this")); | ||
| 75 | if (i == 2) assert(mem.eql(u8, s, "is")); | ||
| 76 | if (i == 3) assert(mem.eql(u8, s, "my")); | ||
| 77 | if (i == 4) assert(mem.eql(u8, s, "thing")); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | var s_array: [8]Sub = undefined; | ||
| 82 | const Sub = struct { | ||
| 83 | b: u8, | ||
| 84 | }; | ||
| 85 | const Str = struct { | ||
| 86 | a: []Sub, | ||
| 87 | }; | ||
| 88 | test "set global var array via slice embedded in struct" { | ||
| 89 | var s = Str{ .a = s_array[0..] }; | ||
| 90 | |||
| 91 | s.a[0].b = 1; | ||
| 92 | s.a[1].b = 2; | ||
| 93 | s.a[2].b = 3; | ||
| 94 | |||
| 95 | assert(s_array[0].b == 1); | ||
| 96 | assert(s_array[1].b == 2); | ||
| 97 | assert(s_array[2].b == 3); | ||
| 98 | } | ||
| 99 | |||
| 100 | test "array literal with specified size" { | ||
| 101 | var array = [2]u8{ | ||
| 102 | 1, | ||
| 103 | 2, | ||
| 104 | }; | ||
| 105 | assert(array[0] == 1); | ||
| 106 | assert(array[1] == 2); | ||
| 107 | } | ||
| 108 | |||
| 109 | test "array child property" { | ||
| 110 | var x: [5]i32 = undefined; | ||
| 111 | assert(@typeOf(x).Child == i32); | ||
| 112 | } | ||
| 113 | |||
| 114 | test "array len property" { | ||
| 115 | var x: [5]i32 = undefined; | ||
| 116 | assert(@typeOf(x).len == 5); | ||
| 117 | } | ||
| 118 | |||
| 119 | test "array len field" { | ||
| 120 | var arr = [4]u8{ 0, 0, 0, 0 }; | ||
| 121 | var ptr = &arr; | ||
| 122 | assert(arr.len == 4); | ||
| 123 | comptime assert(arr.len == 4); | ||
| 124 | assert(ptr.len == 4); | ||
| 125 | comptime assert(ptr.len == 4); | ||
| 126 | } | ||
| 127 | |||
| 128 | test "single-item pointer to array indexing and slicing" { | ||
| 129 | testSingleItemPtrArrayIndexSlice(); | ||
| 130 | comptime testSingleItemPtrArrayIndexSlice(); | ||
| 131 | } | ||
| 132 | |||
| 133 | fn testSingleItemPtrArrayIndexSlice() void { | ||
| 134 | var array = "aaaa"; | ||
| 135 | doSomeMangling(&array); | ||
| 136 | assert(mem.eql(u8, "azya", array)); | ||
| 137 | } | ||
| 138 | |||
| 139 | fn doSomeMangling(array: *[4]u8) void { | ||
| 140 | array[1] = 'z'; | ||
| 141 | array[2..3][0] = 'y'; | ||
| 142 | } | ||
| 143 | |||
| 144 | test "implicit cast single-item pointer" { | ||
| 145 | testImplicitCastSingleItemPtr(); | ||
| 146 | comptime testImplicitCastSingleItemPtr(); | ||
| 147 | } | ||
| 148 | |||
| 149 | fn testImplicitCastSingleItemPtr() void { | ||
| 150 | var byte: u8 = 100; | ||
| 151 | const slice = (*[1]u8)(&byte)[0..]; | ||
| 152 | slice[0] += 1; | ||
| 153 | assert(byte == 101); | ||
| 154 | } | ||
| 155 | |||
| 156 | fn testArrayByValAtComptime(b: [2]u8) u8 { | ||
| 157 | return b[0]; | ||
| 158 | } | ||
| 159 | |||
| 160 | test "comptime evalutating function that takes array by value" { | ||
| 161 | const arr = []u8{ 0, 1 }; | ||
| 162 | _ = comptime testArrayByValAtComptime(arr); | ||
| 163 | _ = comptime testArrayByValAtComptime(arr); | ||
| 164 | } | ||
| 165 | |||
| 166 | test "implicit comptime in array type size" { | ||
| 167 | var arr: [plusOne(10)]bool = undefined; | ||
| 168 | assert(arr.len == 11); | ||
| 169 | } | ||
| 170 | |||
| 171 | fn plusOne(x: u32) u32 { | ||
| 172 | return x + 1; | ||
| 173 | } | ||
test/cases/asm.zig deleted-48| ... | @@ -1,48 +0,0 @@ | ||
| 1 | const config = @import("builtin"); | ||
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | |||
| 4 | comptime { | ||
| 5 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | ||
| 6 | asm volatile ( | ||
| 7 | \\.globl aoeu; | ||
| 8 | \\.type aoeu, @function; | ||
| 9 | \\.set aoeu, derp; | ||
| 10 | ); | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | test "module level assembly" { | ||
| 15 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | ||
| 16 | assert(aoeu() == 1234); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | test "output constraint modifiers" { | ||
| 21 | // This is only testing compilation. | ||
| 22 | var a: u32 = 3; | ||
| 23 | asm volatile ("" : [_]"=m,r"(a) : : ""); | ||
| 24 | asm volatile ("" : [_]"=r,m"(a) : : ""); | ||
| 25 | } | ||
| 26 | |||
| 27 | test "alternative constraints" { | ||
| 28 | // Make sure we allow commas as a separator for alternative constraints. | ||
| 29 | var a: u32 = 3; | ||
| 30 | asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : ""); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "sized integer/float in asm input" { | ||
| 34 | asm volatile ("" : : [_]"m"(usize(3)) : ""); | ||
| 35 | asm volatile ("" : : [_]"m"(i15(-3)) : ""); | ||
| 36 | asm volatile ("" : : [_]"m"(u3(3)) : ""); | ||
| 37 | asm volatile ("" : : [_]"m"(i3(3)) : ""); | ||
| 38 | asm volatile ("" : : [_]"m"(u121(3)) : ""); | ||
| 39 | asm volatile ("" : : [_]"m"(i121(3)) : ""); | ||
| 40 | asm volatile ("" : : [_]"m"(f32(3.17)) : ""); | ||
| 41 | asm volatile ("" : : [_]"m"(f64(3.17)) : ""); | ||
| 42 | } | ||
| 43 | |||
| 44 | extern fn aoeu() i32; | ||
| 45 | |||
| 46 | export fn derp() i32 { | ||
| 47 | return 1234; | ||
| 48 | } | ||
test/cases/atomics.zig deleted-71| ... | @@ -1,71 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | ||
| 5 | const AtomicOrder = builtin.AtomicOrder; | ||
| 6 | |||
| 7 | test "cmpxchg" { | ||
| 8 | var x: i32 = 1234; | ||
| 9 | if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 10 | assert(x1 == 1234); | ||
| 11 | } else { | ||
| 12 | @panic("cmpxchg should have failed"); | ||
| 13 | } | ||
| 14 | |||
| 15 | while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 16 | assert(x1 == 1234); | ||
| 17 | } | ||
| 18 | assert(x == 5678); | ||
| 19 | |||
| 20 | assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | ||
| 21 | assert(x == 42); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "fence" { | ||
| 25 | var x: i32 = 1234; | ||
| 26 | @fence(AtomicOrder.SeqCst); | ||
| 27 | x = 5678; | ||
| 28 | } | ||
| 29 | |||
| 30 | test "atomicrmw and atomicload" { | ||
| 31 | var data: u8 = 200; | ||
| 32 | testAtomicRmw(&data); | ||
| 33 | assert(data == 42); | ||
| 34 | testAtomicLoad(&data); | ||
| 35 | } | ||
| 36 | |||
| 37 | fn testAtomicRmw(ptr: *u8) void { | ||
| 38 | const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); | ||
| 39 | assert(prev_value == 200); | ||
| 40 | comptime { | ||
| 41 | var x: i32 = 1234; | ||
| 42 | const y: i32 = 12345; | ||
| 43 | assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); | ||
| 44 | assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | fn testAtomicLoad(ptr: *u8) void { | ||
| 49 | const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); | ||
| 50 | assert(x == 42); | ||
| 51 | } | ||
| 52 | |||
| 53 | test "cmpxchg with ptr" { | ||
| 54 | var data1: i32 = 1234; | ||
| 55 | var data2: i32 = 5678; | ||
| 56 | var data3: i32 = 9101; | ||
| 57 | var x: *i32 = &data1; | ||
| 58 | if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 59 | assert(x1 == &data1); | ||
| 60 | } else { | ||
| 61 | @panic("cmpxchg should have failed"); | ||
| 62 | } | ||
| 63 | |||
| 64 | while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 65 | assert(x1 == &data1); | ||
| 66 | } | ||
| 67 | assert(x == &data3); | ||
| 68 | |||
| 69 | assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | ||
| 70 | assert(x == &data2); | ||
| 71 | } | ||
test/cases/bit_shifting.zig deleted-88| ... | @@ -1,88 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | |||
| 4 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { | ||
| 5 | assert(Key == @IntType(false, Key.bit_count)); | ||
| 6 | assert(Key.bit_count >= mask_bit_count); | ||
| 7 | const ShardKey = @IntType(false, mask_bit_count); | ||
| 8 | const shift_amount = Key.bit_count - ShardKey.bit_count; | ||
| 9 | return struct { | ||
| 10 | const Self = @This(); | ||
| 11 | shards: [1 << ShardKey.bit_count]?*Node, | ||
| 12 | |||
| 13 | pub fn create() Self { | ||
| 14 | return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) }; | ||
| 15 | } | ||
| 16 | |||
| 17 | fn getShardKey(key: Key) ShardKey { | ||
| 18 | // https://github.com/ziglang/zig/issues/1544 | ||
| 19 | // this special case is needed because you can't u32 >> 32. | ||
| 20 | if (ShardKey == u0) return 0; | ||
| 21 | |||
| 22 | // this can be u1 >> u0 | ||
| 23 | const shard_key = key >> shift_amount; | ||
| 24 | |||
| 25 | // TODO: https://github.com/ziglang/zig/issues/1544 | ||
| 26 | // This cast could be implicit if we teach the compiler that | ||
| 27 | // u32 >> 30 -> u2 | ||
| 28 | return @intCast(ShardKey, shard_key); | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn put(self: *Self, node: *Node) void { | ||
| 32 | const shard_key = Self.getShardKey(node.key); | ||
| 33 | node.next = self.shards[shard_key]; | ||
| 34 | self.shards[shard_key] = node; | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn get(self: *Self, key: Key) ?*Node { | ||
| 38 | const shard_key = Self.getShardKey(key); | ||
| 39 | var maybe_node = self.shards[shard_key]; | ||
| 40 | while (maybe_node) |node| : (maybe_node = node.next) { | ||
| 41 | if (node.key == key) return node; | ||
| 42 | } | ||
| 43 | return null; | ||
| 44 | } | ||
| 45 | |||
| 46 | pub const Node = struct { | ||
| 47 | key: Key, | ||
| 48 | value: V, | ||
| 49 | next: ?*Node, | ||
| 50 | |||
| 51 | pub fn init(self: *Node, key: Key, value: V) void { | ||
| 52 | self.key = key; | ||
| 53 | self.value = value; | ||
| 54 | self.next = null; | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | }; | ||
| 58 | } | ||
| 59 | |||
| 60 | test "sharded table" { | ||
| 61 | // realistic 16-way sharding | ||
| 62 | testShardedTable(u32, 4, 8); | ||
| 63 | |||
| 64 | testShardedTable(u5, 0, 32); // ShardKey == u0 | ||
| 65 | testShardedTable(u5, 2, 32); | ||
| 66 | testShardedTable(u5, 5, 32); | ||
| 67 | |||
| 68 | testShardedTable(u1, 0, 2); | ||
| 69 | testShardedTable(u1, 1, 2); // this does u1 >> u0 | ||
| 70 | |||
| 71 | testShardedTable(u0, 0, 1); | ||
| 72 | } | ||
| 73 | fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void { | ||
| 74 | const Table = ShardedTable(Key, mask_bit_count, void); | ||
| 75 | |||
| 76 | var table = Table.create(); | ||
| 77 | var node_buffer: [node_count]Table.Node = undefined; | ||
| 78 | for (node_buffer) |*node, i| { | ||
| 79 | const key = @intCast(Key, i); | ||
| 80 | assert(table.get(key) == null); | ||
| 81 | node.init(key, {}); | ||
| 82 | table.put(node); | ||
| 83 | } | ||
| 84 | |||
| 85 | for (node_buffer) |*node, i| { | ||
| 86 | assert(table.get(@intCast(Key, i)) == node); | ||
| 87 | } | ||
| 88 | } | ||
test/cases/bitcast.zig deleted-37| ... | @@ -1,37 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const maxInt = std.math.maxInt; | ||
| 4 | |||
| 5 | test "@bitCast i32 -> u32" { | ||
| 6 | testBitCast_i32_u32(); | ||
| 7 | comptime testBitCast_i32_u32(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testBitCast_i32_u32() void { | ||
| 11 | assert(conv(-1) == maxInt(u32)); | ||
| 12 | assert(conv2(maxInt(u32)) == -1); | ||
| 13 | } | ||
| 14 | |||
| 15 | fn conv(x: i32) u32 { | ||
| 16 | return @bitCast(u32, x); | ||
| 17 | } | ||
| 18 | fn conv2(x: u32) i32 { | ||
| 19 | return @bitCast(i32, x); | ||
| 20 | } | ||
| 21 | |||
| 22 | test "@bitCast extern enum to its integer type" { | ||
| 23 | const SOCK = extern enum { | ||
| 24 | A, | ||
| 25 | B, | ||
| 26 | |||
| 27 | fn testBitCastExternEnum() void { | ||
| 28 | var SOCK_DGRAM = @This().B; | ||
| 29 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | ||
| 30 | assert(sock_dgram == 1); | ||
| 31 | } | ||
| 32 | }; | ||
| 33 | |||
| 34 | SOCK.testBitCastExternEnum(); | ||
| 35 | comptime SOCK.testBitCastExternEnum(); | ||
| 36 | } | ||
| 37 | |||
test/cases/bool.zig deleted-35| ... | @@ -1,35 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "bool literals" { | ||
| 4 | assert(true); | ||
| 5 | assert(!false); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "cast bool to int" { | ||
| 9 | const t = true; | ||
| 10 | const f = false; | ||
| 11 | assert(@boolToInt(t) == u32(1)); | ||
| 12 | assert(@boolToInt(f) == u32(0)); | ||
| 13 | nonConstCastBoolToInt(t, f); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn nonConstCastBoolToInt(t: bool, f: bool) void { | ||
| 17 | assert(@boolToInt(t) == u32(1)); | ||
| 18 | assert(@boolToInt(f) == u32(0)); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "bool cmp" { | ||
| 22 | assert(testBoolCmp(true, false) == false); | ||
| 23 | } | ||
| 24 | fn testBoolCmp(a: bool, b: bool) bool { | ||
| 25 | return a == b; | ||
| 26 | } | ||
| 27 | |||
| 28 | const global_f = false; | ||
| 29 | const global_t = true; | ||
| 30 | const not_global_f = !global_f; | ||
| 31 | const not_global_t = !global_t; | ||
| 32 | test "compile time bool not" { | ||
| 33 | assert(not_global_f); | ||
| 34 | assert(!not_global_t); | ||
| 35 | } | ||
test/cases/bugs/1076.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | |||
| 5 | test "comptime code should not modify constant data" { | ||
| 6 | testCastPtrOfArrayToSliceAndPtr(); | ||
| 7 | comptime testCastPtrOfArrayToSliceAndPtr(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testCastPtrOfArrayToSliceAndPtr() void { | ||
| 11 | var array = "aoeu"; | ||
| 12 | const x: [*]u8 = &array; | ||
| 13 | x[0] += 1; | ||
| 14 | assert(mem.eql(u8, array[0..], "boeu")); | ||
| 15 | } | ||
| 16 | |||
test/cases/bugs/1111.zig deleted-12| ... | @@ -1,12 +0,0 @@ | ||
| 1 | const Foo = extern enum { | ||
| 2 | Bar = -1, | ||
| 3 | }; | ||
| 4 | |||
| 5 | test "issue 1111 fixed" { | ||
| 6 | const v = Foo.Bar; | ||
| 7 | |||
| 8 | switch (v) { | ||
| 9 | Foo.Bar => return, | ||
| 10 | else => return, | ||
| 11 | } | ||
| 12 | } | ||
test/cases/bugs/1277.zig deleted-15| ... | @@ -1,15 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const S = struct { | ||
| 4 | f: ?fn () i32, | ||
| 5 | }; | ||
| 6 | |||
| 7 | const s = S{ .f = f }; | ||
| 8 | |||
| 9 | fn f() i32 { | ||
| 10 | return 1234; | ||
| 11 | } | ||
| 12 | |||
| 13 | test "don't emit an LLVM global for a const function when it's in an optional in a struct" { | ||
| 14 | std.debug.assertOrPanic(s.f.?() == 1234); | ||
| 15 | } | ||
test/cases/bugs/1322.zig deleted-19| ... | @@ -1,19 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const B = union(enum) { | ||
| 4 | c: C, | ||
| 5 | None, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const A = struct { | ||
| 9 | b: B, | ||
| 10 | }; | ||
| 11 | |||
| 12 | const C = struct {}; | ||
| 13 | |||
| 14 | test "tagged union with all void fields but a meaningful tag" { | ||
| 15 | var a: A = A{ .b = B{ .c = C{} } }; | ||
| 16 | std.debug.assert(@TagType(B)(a.b) == @TagType(B).c); | ||
| 17 | a = A{ .b = B.None }; | ||
| 18 | std.debug.assert(@TagType(B)(a.b) == @TagType(B).None); | ||
| 19 | } | ||
test/cases/bugs/1381.zig deleted-21| ... | @@ -1,21 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const B = union(enum) { | ||
| 4 | D: u8, | ||
| 5 | E: u16, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const A = union(enum) { | ||
| 9 | B: B, | ||
| 10 | C: u8, | ||
| 11 | }; | ||
| 12 | |||
| 13 | test "union that needs padding bytes inside an array" { | ||
| 14 | var as = []A{ | ||
| 15 | A{ .B = B{ .D = 1 } }, | ||
| 16 | A{ .B = B{ .D = 1 } }, | ||
| 17 | }; | ||
| 18 | |||
| 19 | const a = as[0].B; | ||
| 20 | std.debug.assertOrPanic(a.D == 1); | ||
| 21 | } | ||
test/cases/bugs/1421.zig deleted-14| ... | @@ -1,14 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | |||
| 5 | const S = struct { | ||
| 6 | fn method() builtin.TypeInfo { | ||
| 7 | return @typeInfo(S); | ||
| 8 | } | ||
| 9 | }; | ||
| 10 | |||
| 11 | test "functions with return type required to be comptime are generic" { | ||
| 12 | const ti = S.method(); | ||
| 13 | assert(builtin.TypeId(ti) == builtin.TypeId.Struct); | ||
| 14 | } | ||
test/cases/bugs/1442.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const Union = union(enum) { | ||
| 4 | Text: []const u8, | ||
| 5 | Color: u32, | ||
| 6 | }; | ||
| 7 | |||
| 8 | test "const error union field alignment" { | ||
| 9 | var union_or_err: anyerror!Union = Union{ .Color = 1234 }; | ||
| 10 | std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234); | ||
| 11 | } | ||
test/cases/bugs/1486.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const ptr = &global; | ||
| 4 | var global: u64 = 123; | ||
| 5 | |||
| 6 | test "constant pointer to global variable causes runtime load" { | ||
| 7 | global = 1234; | ||
| 8 | assert(&global == ptr); | ||
| 9 | assert(ptr.* == 1234); | ||
| 10 | } | ||
| 11 | |||
test/cases/bugs/394.zig deleted-18| ... | @@ -1,18 +0,0 @@ | ||
| 1 | const E = union(enum) { | ||
| 2 | A: [9]u8, | ||
| 3 | B: u64, | ||
| 4 | }; | ||
| 5 | const S = struct { | ||
| 6 | x: u8, | ||
| 7 | y: E, | ||
| 8 | }; | ||
| 9 | |||
| 10 | const assert = @import("std").debug.assert; | ||
| 11 | |||
| 12 | test "bug 394 fixed" { | ||
| 13 | const x = S{ | ||
| 14 | .x = 3, | ||
| 15 | .y = E{ .B = 1 }, | ||
| 16 | }; | ||
| 17 | assert(x.x == 3); | ||
| 18 | } | ||
test/cases/bugs/655.zig deleted-12| ... | @@ -1,12 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const other_file = @import("655_other_file.zig"); | ||
| 3 | |||
| 4 | test "function with *const parameter with type dereferenced by namespace" { | ||
| 5 | const x: other_file.Integer = 1234; | ||
| 6 | comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer); | ||
| 7 | foo(&x); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn foo(x: *const other_file.Integer) void { | ||
| 11 | std.debug.assert(x.* == 1234); | ||
| 12 | } | ||
test/cases/bugs/655_other_file.zig deleted-1| ... | @@ -1 +0,0 @@ | ||
| 1 | pub const Integer = u32; | ||
test/cases/bugs/656.zig deleted-31| ... | @@ -1,31 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const PrefixOp = union(enum) { | ||
| 4 | Return, | ||
| 5 | AddrOf: Value, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const Value = struct { | ||
| 9 | align_expr: ?u32, | ||
| 10 | }; | ||
| 11 | |||
| 12 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { | ||
| 13 | foo(false, true); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn foo(a: bool, b: bool) void { | ||
| 17 | var prefix_op = PrefixOp{ | ||
| 18 | .AddrOf = Value{ .align_expr = 1234 }, | ||
| 19 | }; | ||
| 20 | if (a) {} else { | ||
| 21 | switch (prefix_op) { | ||
| 22 | PrefixOp.AddrOf => |addr_of_info| { | ||
| 23 | if (b) {} | ||
| 24 | if (addr_of_info.align_expr) |align_expr| { | ||
| 25 | assert(align_expr == 1234); | ||
| 26 | } | ||
| 27 | }, | ||
| 28 | PrefixOp.Return => {}, | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
test/cases/bugs/726.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "@ptrCast from const to nullable" { | ||
| 4 | const c: u8 = 4; | ||
| 5 | var x: ?*const u8 = @ptrCast(?*const u8, &c); | ||
| 6 | assert(x.?.* == 4); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "@ptrCast from var in empty struct to nullable" { | ||
| 10 | const container = struct { | ||
| 11 | var c: u8 = 4; | ||
| 12 | }; | ||
| 13 | var x: ?*const u8 = @ptrCast(?*const u8, &container.c); | ||
| 14 | assert(x.?.* == 4); | ||
| 15 | } | ||
| 16 | |||
test/cases/bugs/828.zig deleted-33| ... | @@ -1,33 +0,0 @@ | ||
| 1 | const CountBy = struct { | ||
| 2 | a: usize, | ||
| 3 | |||
| 4 | const One = CountBy{ .a = 1 }; | ||
| 5 | |||
| 6 | pub fn counter(self: *const CountBy) Counter { | ||
| 7 | return Counter{ .i = 0 }; | ||
| 8 | } | ||
| 9 | }; | ||
| 10 | |||
| 11 | const Counter = struct { | ||
| 12 | i: usize, | ||
| 13 | |||
| 14 | pub fn count(self: *Counter) bool { | ||
| 15 | self.i += 1; | ||
| 16 | return self.i <= 10; | ||
| 17 | } | ||
| 18 | }; | ||
| 19 | |||
| 20 | fn constCount(comptime cb: *const CountBy, comptime unused: u32) void { | ||
| 21 | comptime { | ||
| 22 | var cnt = cb.counter(); | ||
| 23 | if (cnt.i != 0) @compileError("Counter instance reused!"); | ||
| 24 | while (cnt.count()) {} | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | test "comptime struct return should not return the same instance" { | ||
| 29 | //the first parameter must be passed by reference to trigger the bug | ||
| 30 | //a second parameter is required to trigger the bug | ||
| 31 | const ValA = constCount(&CountBy.One, 12); | ||
| 32 | const ValB = constCount(&CountBy.One, 15); | ||
| 33 | } | ||
test/cases/bugs/920.zig deleted-65| ... | @@ -1,65 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const math = std.math; | ||
| 3 | const Random = std.rand.Random; | ||
| 4 | |||
| 5 | const ZigTable = struct { | ||
| 6 | r: f64, | ||
| 7 | x: [257]f64, | ||
| 8 | f: [257]f64, | ||
| 9 | |||
| 10 | pdf: fn (f64) f64, | ||
| 11 | is_symmetric: bool, | ||
| 12 | zero_case: fn (*Random, f64) f64, | ||
| 13 | }; | ||
| 14 | |||
| 15 | fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable { | ||
| 16 | var tables: ZigTable = undefined; | ||
| 17 | |||
| 18 | tables.is_symmetric = is_symmetric; | ||
| 19 | tables.r = r; | ||
| 20 | tables.pdf = f; | ||
| 21 | tables.zero_case = zero_case; | ||
| 22 | |||
| 23 | tables.x[0] = v / f(r); | ||
| 24 | tables.x[1] = r; | ||
| 25 | |||
| 26 | for (tables.x[2..256]) |*entry, i| { | ||
| 27 | const last = tables.x[2 + i - 1]; | ||
| 28 | entry.* = f_inv(v / last + f(last)); | ||
| 29 | } | ||
| 30 | tables.x[256] = 0; | ||
| 31 | |||
| 32 | for (tables.f[0..]) |*entry, i| { | ||
| 33 | entry.* = f(tables.x[i]); | ||
| 34 | } | ||
| 35 | |||
| 36 | return tables; | ||
| 37 | } | ||
| 38 | |||
| 39 | const norm_r = 3.6541528853610088; | ||
| 40 | const norm_v = 0.00492867323399; | ||
| 41 | |||
| 42 | fn norm_f(x: f64) f64 { | ||
| 43 | return math.exp(-x * x / 2.0); | ||
| 44 | } | ||
| 45 | fn norm_f_inv(y: f64) f64 { | ||
| 46 | return math.sqrt(-2.0 * math.ln(y)); | ||
| 47 | } | ||
| 48 | fn norm_zero_case(random: *Random, u: f64) f64 { | ||
| 49 | return 0.0; | ||
| 50 | } | ||
| 51 | |||
| 52 | const NormalDist = blk: { | ||
| 53 | @setEvalBranchQuota(30000); | ||
| 54 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | ||
| 55 | }; | ||
| 56 | |||
| 57 | test "bug 920 fixed" { | ||
| 58 | const NormalDist1 = blk: { | ||
| 59 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | ||
| 60 | }; | ||
| 61 | |||
| 62 | for (NormalDist1.f) |_, i| { | ||
| 63 | std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]); | ||
| 64 | } | ||
| 65 | } | ||
test/cases/byval_arg_var.zig deleted-27| ... | @@ -1,27 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | var result: []const u8 = "wrong"; | ||
| 4 | |||
| 5 | test "aoeu" { | ||
| 6 | start(); | ||
| 7 | blowUpStack(10); | ||
| 8 | |||
| 9 | std.debug.assert(std.mem.eql(u8, result, "string literal")); | ||
| 10 | } | ||
| 11 | |||
| 12 | fn start() void { | ||
| 13 | foo("string literal"); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn foo(x: var) void { | ||
| 17 | bar(x); | ||
| 18 | } | ||
| 19 | |||
| 20 | fn bar(x: var) void { | ||
| 21 | result = x; | ||
| 22 | } | ||
| 23 | |||
| 24 | fn blowUpStack(x: u32) void { | ||
| 25 | if (x == 0) return; | ||
| 26 | blowUpStack(x - 1); | ||
| 27 | } | ||
test/cases/cancel.zig deleted-92| ... | @@ -1,92 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | var defer_f1: bool = false; | ||
| 4 | var defer_f2: bool = false; | ||
| 5 | var defer_f3: bool = false; | ||
| 6 | |||
| 7 | test "cancel forwards" { | ||
| 8 | var da = std.heap.DirectAllocator.init(); | ||
| 9 | defer da.deinit(); | ||
| 10 | |||
| 11 | const p = async<&da.allocator> f1() catch unreachable; | ||
| 12 | cancel p; | ||
| 13 | std.debug.assert(defer_f1); | ||
| 14 | std.debug.assert(defer_f2); | ||
| 15 | std.debug.assert(defer_f3); | ||
| 16 | } | ||
| 17 | |||
| 18 | async fn f1() void { | ||
| 19 | defer { | ||
| 20 | defer_f1 = true; | ||
| 21 | } | ||
| 22 | await (async f2() catch unreachable); | ||
| 23 | } | ||
| 24 | |||
| 25 | async fn f2() void { | ||
| 26 | defer { | ||
| 27 | defer_f2 = true; | ||
| 28 | } | ||
| 29 | await (async f3() catch unreachable); | ||
| 30 | } | ||
| 31 | |||
| 32 | async fn f3() void { | ||
| 33 | defer { | ||
| 34 | defer_f3 = true; | ||
| 35 | } | ||
| 36 | suspend; | ||
| 37 | } | ||
| 38 | |||
| 39 | var defer_b1: bool = false; | ||
| 40 | var defer_b2: bool = false; | ||
| 41 | var defer_b3: bool = false; | ||
| 42 | var defer_b4: bool = false; | ||
| 43 | |||
| 44 | test "cancel backwards" { | ||
| 45 | var da = std.heap.DirectAllocator.init(); | ||
| 46 | defer da.deinit(); | ||
| 47 | |||
| 48 | const p = async<&da.allocator> b1() catch unreachable; | ||
| 49 | cancel p; | ||
| 50 | std.debug.assert(defer_b1); | ||
| 51 | std.debug.assert(defer_b2); | ||
| 52 | std.debug.assert(defer_b3); | ||
| 53 | std.debug.assert(defer_b4); | ||
| 54 | } | ||
| 55 | |||
| 56 | async fn b1() void { | ||
| 57 | defer { | ||
| 58 | defer_b1 = true; | ||
| 59 | } | ||
| 60 | await (async b2() catch unreachable); | ||
| 61 | } | ||
| 62 | |||
| 63 | var b4_handle: promise = undefined; | ||
| 64 | |||
| 65 | async fn b2() void { | ||
| 66 | const b3_handle = async b3() catch unreachable; | ||
| 67 | resume b4_handle; | ||
| 68 | cancel b4_handle; | ||
| 69 | defer { | ||
| 70 | defer_b2 = true; | ||
| 71 | } | ||
| 72 | const value = await b3_handle; | ||
| 73 | @panic("unreachable"); | ||
| 74 | } | ||
| 75 | |||
| 76 | async fn b3() i32 { | ||
| 77 | defer { | ||
| 78 | defer_b3 = true; | ||
| 79 | } | ||
| 80 | await (async b4() catch unreachable); | ||
| 81 | return 1234; | ||
| 82 | } | ||
| 83 | |||
| 84 | async fn b4() void { | ||
| 85 | defer { | ||
| 86 | defer_b4 = true; | ||
| 87 | } | ||
| 88 | suspend { | ||
| 89 | b4_handle = @handle(); | ||
| 90 | } | ||
| 91 | suspend; | ||
| 92 | } | ||
test/cases/cast.zig deleted-472| ... | @@ -1,472 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | const maxInt = std.math.maxInt; | ||
| 5 | |||
| 6 | test "int to ptr cast" { | ||
| 7 | const x = usize(13); | ||
| 8 | const y = @intToPtr(*u8, x); | ||
| 9 | const z = @ptrToInt(y); | ||
| 10 | assert(z == 13); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "integer literal to pointer cast" { | ||
| 14 | const vga_mem = @intToPtr(*u16, 0xB8000); | ||
| 15 | assert(@ptrToInt(vga_mem) == 0xB8000); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "pointer reinterpret const float to int" { | ||
| 19 | const float: f64 = 5.99999999999994648725e-01; | ||
| 20 | const float_ptr = &float; | ||
| 21 | const int_ptr = @ptrCast(*const i32, float_ptr); | ||
| 22 | const int_val = int_ptr.*; | ||
| 23 | assert(int_val == 858993411); | ||
| 24 | } | ||
| 25 | |||
| 26 | test "implicitly cast indirect pointer to maybe-indirect pointer" { | ||
| 27 | const S = struct { | ||
| 28 | const Self = @This(); | ||
| 29 | x: u8, | ||
| 30 | fn constConst(p: *const *const Self) u8 { | ||
| 31 | return p.*.x; | ||
| 32 | } | ||
| 33 | fn maybeConstConst(p: ?*const *const Self) u8 { | ||
| 34 | return p.?.*.x; | ||
| 35 | } | ||
| 36 | fn constConstConst(p: *const *const *const Self) u8 { | ||
| 37 | return p.*.*.x; | ||
| 38 | } | ||
| 39 | fn maybeConstConstConst(p: ?*const *const *const Self) u8 { | ||
| 40 | return p.?.*.*.x; | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | const s = S{ .x = 42 }; | ||
| 44 | const p = &s; | ||
| 45 | const q = &p; | ||
| 46 | const r = &q; | ||
| 47 | assert(42 == S.constConst(q)); | ||
| 48 | assert(42 == S.maybeConstConst(q)); | ||
| 49 | assert(42 == S.constConstConst(r)); | ||
| 50 | assert(42 == S.maybeConstConstConst(r)); | ||
| 51 | } | ||
| 52 | |||
| 53 | test "explicit cast from integer to error type" { | ||
| 54 | testCastIntToErr(error.ItBroke); | ||
| 55 | comptime testCastIntToErr(error.ItBroke); | ||
| 56 | } | ||
| 57 | fn testCastIntToErr(err: anyerror) void { | ||
| 58 | const x = @errorToInt(err); | ||
| 59 | const y = @intToError(x); | ||
| 60 | assert(error.ItBroke == y); | ||
| 61 | } | ||
| 62 | |||
| 63 | test "peer resolve arrays of different size to const slice" { | ||
| 64 | assert(mem.eql(u8, boolToStr(true), "true")); | ||
| 65 | assert(mem.eql(u8, boolToStr(false), "false")); | ||
| 66 | comptime assert(mem.eql(u8, boolToStr(true), "true")); | ||
| 67 | comptime assert(mem.eql(u8, boolToStr(false), "false")); | ||
| 68 | } | ||
| 69 | fn boolToStr(b: bool) []const u8 { | ||
| 70 | return if (b) "true" else "false"; | ||
| 71 | } | ||
| 72 | |||
| 73 | test "peer resolve array and const slice" { | ||
| 74 | testPeerResolveArrayConstSlice(true); | ||
| 75 | comptime testPeerResolveArrayConstSlice(true); | ||
| 76 | } | ||
| 77 | fn testPeerResolveArrayConstSlice(b: bool) void { | ||
| 78 | const value1 = if (b) "aoeu" else ([]const u8)("zz"); | ||
| 79 | const value2 = if (b) ([]const u8)("zz") else "aoeu"; | ||
| 80 | assert(mem.eql(u8, value1, "aoeu")); | ||
| 81 | assert(mem.eql(u8, value2, "zz")); | ||
| 82 | } | ||
| 83 | |||
| 84 | test "implicitly cast from T to anyerror!?T" { | ||
| 85 | castToOptionalTypeError(1); | ||
| 86 | comptime castToOptionalTypeError(1); | ||
| 87 | } | ||
| 88 | const A = struct { | ||
| 89 | a: i32, | ||
| 90 | }; | ||
| 91 | fn castToOptionalTypeError(z: i32) void { | ||
| 92 | const x = i32(1); | ||
| 93 | const y: anyerror!?i32 = x; | ||
| 94 | assert((try y).? == 1); | ||
| 95 | |||
| 96 | const f = z; | ||
| 97 | const g: anyerror!?i32 = f; | ||
| 98 | |||
| 99 | const a = A{ .a = z }; | ||
| 100 | const b: anyerror!?A = a; | ||
| 101 | assert((b catch unreachable).?.a == 1); | ||
| 102 | } | ||
| 103 | |||
| 104 | test "implicitly cast from int to anyerror!?T" { | ||
| 105 | implicitIntLitToOptional(); | ||
| 106 | comptime implicitIntLitToOptional(); | ||
| 107 | } | ||
| 108 | fn implicitIntLitToOptional() void { | ||
| 109 | const f: ?i32 = 1; | ||
| 110 | const g: anyerror!?i32 = 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | test "return null from fn() anyerror!?&T" { | ||
| 114 | const a = returnNullFromOptionalTypeErrorRef(); | ||
| 115 | const b = returnNullLitFromOptionalTypeErrorRef(); | ||
| 116 | assert((try a) == null and (try b) == null); | ||
| 117 | } | ||
| 118 | fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { | ||
| 119 | const a: ?*A = null; | ||
| 120 | return a; | ||
| 121 | } | ||
| 122 | fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | ||
| 123 | return null; | ||
| 124 | } | ||
| 125 | |||
| 126 | test "peer type resolution: ?T and T" { | ||
| 127 | assert(peerTypeTAndOptionalT(true, false).? == 0); | ||
| 128 | assert(peerTypeTAndOptionalT(false, false).? == 3); | ||
| 129 | comptime { | ||
| 130 | assert(peerTypeTAndOptionalT(true, false).? == 0); | ||
| 131 | assert(peerTypeTAndOptionalT(false, false).? == 3); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { | ||
| 135 | if (c) { | ||
| 136 | return if (b) null else usize(0); | ||
| 137 | } | ||
| 138 | |||
| 139 | return usize(3); | ||
| 140 | } | ||
| 141 | |||
| 142 | test "peer type resolution: [0]u8 and []const u8" { | ||
| 143 | assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | ||
| 144 | assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | ||
| 145 | comptime { | ||
| 146 | assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | ||
| 147 | assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | ||
| 151 | if (a) { | ||
| 152 | return []const u8{}; | ||
| 153 | } | ||
| 154 | |||
| 155 | return slice[0..1]; | ||
| 156 | } | ||
| 157 | |||
| 158 | test "implicitly cast from [N]T to ?[]const T" { | ||
| 159 | assert(mem.eql(u8, castToOptionalSlice().?, "hi")); | ||
| 160 | comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi")); | ||
| 161 | } | ||
| 162 | |||
| 163 | fn castToOptionalSlice() ?[]const u8 { | ||
| 164 | return "hi"; | ||
| 165 | } | ||
| 166 | |||
| 167 | test "implicitly cast from [0]T to anyerror![]T" { | ||
| 168 | testCastZeroArrayToErrSliceMut(); | ||
| 169 | comptime testCastZeroArrayToErrSliceMut(); | ||
| 170 | } | ||
| 171 | |||
| 172 | fn testCastZeroArrayToErrSliceMut() void { | ||
| 173 | assert((gimmeErrOrSlice() catch unreachable).len == 0); | ||
| 174 | } | ||
| 175 | |||
| 176 | fn gimmeErrOrSlice() anyerror![]u8 { | ||
| 177 | return []u8{}; | ||
| 178 | } | ||
| 179 | |||
| 180 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | ||
| 181 | { | ||
| 182 | var data = "hi"; | ||
| 183 | const slice = data[0..]; | ||
| 184 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | ||
| 185 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | ||
| 186 | } | ||
| 187 | comptime { | ||
| 188 | var data = "hi"; | ||
| 189 | const slice = data[0..]; | ||
| 190 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | ||
| 191 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { | ||
| 195 | if (a) { | ||
| 196 | return []u8{}; | ||
| 197 | } | ||
| 198 | |||
| 199 | return slice[0..1]; | ||
| 200 | } | ||
| 201 | |||
| 202 | test "resolve undefined with integer" { | ||
| 203 | testResolveUndefWithInt(true, 1234); | ||
| 204 | comptime testResolveUndefWithInt(true, 1234); | ||
| 205 | } | ||
| 206 | fn testResolveUndefWithInt(b: bool, x: i32) void { | ||
| 207 | const value = if (b) x else undefined; | ||
| 208 | if (b) { | ||
| 209 | assert(value == x); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | test "implicit cast from &const [N]T to []const T" { | ||
| 214 | testCastConstArrayRefToConstSlice(); | ||
| 215 | comptime testCastConstArrayRefToConstSlice(); | ||
| 216 | } | ||
| 217 | |||
| 218 | fn testCastConstArrayRefToConstSlice() void { | ||
| 219 | const blah = "aoeu"; | ||
| 220 | const const_array_ref = &blah; | ||
| 221 | assert(@typeOf(const_array_ref) == *const [4]u8); | ||
| 222 | const slice: []const u8 = const_array_ref; | ||
| 223 | assert(mem.eql(u8, slice, "aoeu")); | ||
| 224 | } | ||
| 225 | |||
| 226 | test "peer type resolution: error and [N]T" { | ||
| 227 | // TODO: implicit error!T to error!U where T can implicitly cast to U | ||
| 228 | //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | ||
| 229 | //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | ||
| 230 | assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | ||
| 231 | comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | ||
| 232 | } | ||
| 233 | |||
| 234 | //fn testPeerErrorAndArray(x: u8) error![]const u8 { | ||
| 235 | // return switch (x) { | ||
| 236 | // 0x00 => "OK", | ||
| 237 | // else => error.BadValue, | ||
| 238 | // }; | ||
| 239 | //} | ||
| 240 | fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 { | ||
| 241 | return switch (x) { | ||
| 242 | 0x00 => "OK", | ||
| 243 | 0x01 => "OKK", | ||
| 244 | else => error.BadValue, | ||
| 245 | }; | ||
| 246 | } | ||
| 247 | |||
| 248 | test "@floatToInt" { | ||
| 249 | testFloatToInts(); | ||
| 250 | comptime testFloatToInts(); | ||
| 251 | } | ||
| 252 | |||
| 253 | fn testFloatToInts() void { | ||
| 254 | const x = i32(1e4); | ||
| 255 | assert(x == 10000); | ||
| 256 | const y = @floatToInt(i32, f32(1e4)); | ||
| 257 | assert(y == 10000); | ||
| 258 | expectFloatToInt(f16, 255.1, u8, 255); | ||
| 259 | expectFloatToInt(f16, 127.2, i8, 127); | ||
| 260 | expectFloatToInt(f16, -128.2, i8, -128); | ||
| 261 | expectFloatToInt(f32, 255.1, u8, 255); | ||
| 262 | expectFloatToInt(f32, 127.2, i8, 127); | ||
| 263 | expectFloatToInt(f32, -128.2, i8, -128); | ||
| 264 | expectFloatToInt(comptime_int, 1234, i16, 1234); | ||
| 265 | } | ||
| 266 | |||
| 267 | fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { | ||
| 268 | assert(@floatToInt(I, f) == i); | ||
| 269 | } | ||
| 270 | |||
| 271 | test "cast u128 to f128 and back" { | ||
| 272 | comptime testCast128(); | ||
| 273 | testCast128(); | ||
| 274 | } | ||
| 275 | |||
| 276 | fn testCast128() void { | ||
| 277 | assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | ||
| 278 | } | ||
| 279 | |||
| 280 | fn cast128Int(x: f128) u128 { | ||
| 281 | return @bitCast(u128, x); | ||
| 282 | } | ||
| 283 | |||
| 284 | fn cast128Float(x: u128) f128 { | ||
| 285 | return @bitCast(f128, x); | ||
| 286 | } | ||
| 287 | |||
| 288 | test "const slice widen cast" { | ||
| 289 | const bytes align(4) = []u8{ | ||
| 290 | 0x12, | ||
| 291 | 0x12, | ||
| 292 | 0x12, | ||
| 293 | 0x12, | ||
| 294 | }; | ||
| 295 | |||
| 296 | const u32_value = @bytesToSlice(u32, bytes[0..])[0]; | ||
| 297 | assert(u32_value == 0x12121212); | ||
| 298 | |||
| 299 | assert(@bitCast(u32, bytes) == 0x12121212); | ||
| 300 | } | ||
| 301 | |||
| 302 | test "single-item pointer of array to slice and to unknown length pointer" { | ||
| 303 | testCastPtrOfArrayToSliceAndPtr(); | ||
| 304 | comptime testCastPtrOfArrayToSliceAndPtr(); | ||
| 305 | } | ||
| 306 | |||
| 307 | fn testCastPtrOfArrayToSliceAndPtr() void { | ||
| 308 | var array = "aoeu"; | ||
| 309 | const x: [*]u8 = &array; | ||
| 310 | x[0] += 1; | ||
| 311 | assert(mem.eql(u8, array[0..], "boeu")); | ||
| 312 | const y: []u8 = &array; | ||
| 313 | y[0] += 1; | ||
| 314 | assert(mem.eql(u8, array[0..], "coeu")); | ||
| 315 | } | ||
| 316 | |||
| 317 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | ||
| 318 | const window_name = [1][*]const u8{c"window name"}; | ||
| 319 | const x: [*]const ?[*]const u8 = &window_name; | ||
| 320 | assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); | ||
| 321 | } | ||
| 322 | |||
| 323 | test "@intCast comptime_int" { | ||
| 324 | const result = @intCast(i32, 1234); | ||
| 325 | assert(@typeOf(result) == i32); | ||
| 326 | assert(result == 1234); | ||
| 327 | } | ||
| 328 | |||
| 329 | test "@floatCast comptime_int and comptime_float" { | ||
| 330 | { | ||
| 331 | const result = @floatCast(f16, 1234); | ||
| 332 | assert(@typeOf(result) == f16); | ||
| 333 | assert(result == 1234.0); | ||
| 334 | } | ||
| 335 | { | ||
| 336 | const result = @floatCast(f16, 1234.0); | ||
| 337 | assert(@typeOf(result) == f16); | ||
| 338 | assert(result == 1234.0); | ||
| 339 | } | ||
| 340 | { | ||
| 341 | const result = @floatCast(f32, 1234); | ||
| 342 | assert(@typeOf(result) == f32); | ||
| 343 | assert(result == 1234.0); | ||
| 344 | } | ||
| 345 | { | ||
| 346 | const result = @floatCast(f32, 1234.0); | ||
| 347 | assert(@typeOf(result) == f32); | ||
| 348 | assert(result == 1234.0); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | test "comptime_int @intToFloat" { | ||
| 353 | { | ||
| 354 | const result = @intToFloat(f16, 1234); | ||
| 355 | assert(@typeOf(result) == f16); | ||
| 356 | assert(result == 1234.0); | ||
| 357 | } | ||
| 358 | { | ||
| 359 | const result = @intToFloat(f32, 1234); | ||
| 360 | assert(@typeOf(result) == f32); | ||
| 361 | assert(result == 1234.0); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | test "@bytesToSlice keeps pointer alignment" { | ||
| 366 | var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 }; | ||
| 367 | const numbers = @bytesToSlice(u32, bytes[0..]); | ||
| 368 | comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); | ||
| 369 | } | ||
| 370 | |||
| 371 | test "@intCast i32 to u7" { | ||
| 372 | var x: u128 = maxInt(u128); | ||
| 373 | var y: i32 = 120; | ||
| 374 | var z = x >> @intCast(u7, y); | ||
| 375 | assert(z == 0xff); | ||
| 376 | } | ||
| 377 | |||
| 378 | test "implicit cast undefined to optional" { | ||
| 379 | assert(MakeType(void).getNull() == null); | ||
| 380 | assert(MakeType(void).getNonNull() != null); | ||
| 381 | } | ||
| 382 | |||
| 383 | fn MakeType(comptime T: type) type { | ||
| 384 | return struct { | ||
| 385 | fn getNull() ?T { | ||
| 386 | return null; | ||
| 387 | } | ||
| 388 | |||
| 389 | fn getNonNull() ?T { | ||
| 390 | return T(undefined); | ||
| 391 | } | ||
| 392 | }; | ||
| 393 | } | ||
| 394 | |||
| 395 | test "implicit cast from *[N]T to ?[*]T" { | ||
| 396 | var x: ?[*]u16 = null; | ||
| 397 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | ||
| 398 | |||
| 399 | x = &y; | ||
| 400 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 401 | x.?[0] = 8; | ||
| 402 | y[3] = 6; | ||
| 403 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 404 | } | ||
| 405 | |||
| 406 | test "implicit cast from *T to ?*c_void" { | ||
| 407 | var a: u8 = 1; | ||
| 408 | incrementVoidPtrValue(&a); | ||
| 409 | std.debug.assert(a == 2); | ||
| 410 | } | ||
| 411 | |||
| 412 | fn incrementVoidPtrValue(value: ?*c_void) void { | ||
| 413 | @ptrCast(*u8, value.?).* += 1; | ||
| 414 | } | ||
| 415 | |||
| 416 | test "implicit cast from [*]T to ?*c_void" { | ||
| 417 | var a = []u8{ 3, 2, 1 }; | ||
| 418 | incrementVoidPtrArray(a[0..].ptr, 3); | ||
| 419 | assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); | ||
| 420 | } | ||
| 421 | |||
| 422 | fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { | ||
| 423 | var n: usize = 0; | ||
| 424 | while (n < len) : (n += 1) { | ||
| 425 | @ptrCast([*]u8, array.?)[n] += 1; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | test "*usize to *void" { | ||
| 430 | var i = usize(0); | ||
| 431 | var v = @ptrCast(*void, &i); | ||
| 432 | v.* = {}; | ||
| 433 | } | ||
| 434 | |||
| 435 | test "compile time int to ptr of function" { | ||
| 436 | foobar(FUNCTION_CONSTANT); | ||
| 437 | } | ||
| 438 | |||
| 439 | pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); | ||
| 440 | pub const PFN_void = extern fn (*c_void) void; | ||
| 441 | |||
| 442 | fn foobar(func: PFN_void) void { | ||
| 443 | std.debug.assert(@ptrToInt(func) == maxInt(usize)); | ||
| 444 | } | ||
| 445 | |||
| 446 | test "implicit ptr to *c_void" { | ||
| 447 | var a: u32 = 1; | ||
| 448 | var ptr: *c_void = &a; | ||
| 449 | var b: *u32 = @ptrCast(*u32, ptr); | ||
| 450 | assert(b.* == 1); | ||
| 451 | var ptr2: ?*c_void = &a; | ||
| 452 | var c: *u32 = @ptrCast(*u32, ptr2.?); | ||
| 453 | assert(c.* == 1); | ||
| 454 | } | ||
| 455 | |||
| 456 | test "@intCast to comptime_int" { | ||
| 457 | assert(@intCast(comptime_int, 0) == 0); | ||
| 458 | } | ||
| 459 | |||
| 460 | test "implicit cast comptime numbers to any type when the value fits" { | ||
| 461 | const a: u64 = 255; | ||
| 462 | var b: u8 = a; | ||
| 463 | assert(b == 255); | ||
| 464 | } | ||
| 465 | |||
| 466 | test "@intToEnum passed a comptime_int to an enum with one item" { | ||
| 467 | const E = enum { | ||
| 468 | A, | ||
| 469 | }; | ||
| 470 | const x = @intToEnum(E, 0); | ||
| 471 | assert(x == E.A); | ||
| 472 | } | ||
test/cases/const_slice_child.zig deleted-45| ... | @@ -1,45 +0,0 @@ | ||
| 1 | const debug = @import("std").debug; | ||
| 2 | const assert = debug.assert; | ||
| 3 | |||
| 4 | var argv: [*]const [*]const u8 = undefined; | ||
| 5 | |||
| 6 | test "const slice child" { | ||
| 7 | const strs = ([][*]const u8){ | ||
| 8 | c"one", | ||
| 9 | c"two", | ||
| 10 | c"three", | ||
| 11 | }; | ||
| 12 | // TODO this should implicitly cast | ||
| 13 | argv = @ptrCast([*]const [*]const u8, &strs); | ||
| 14 | bar(strs.len); | ||
| 15 | } | ||
| 16 | |||
| 17 | fn foo(args: [][]const u8) void { | ||
| 18 | assert(args.len == 3); | ||
| 19 | assert(streql(args[0], "one")); | ||
| 20 | assert(streql(args[1], "two")); | ||
| 21 | assert(streql(args[2], "three")); | ||
| 22 | } | ||
| 23 | |||
| 24 | fn bar(argc: usize) void { | ||
| 25 | const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable; | ||
| 26 | for (args) |_, i| { | ||
| 27 | const ptr = argv[i]; | ||
| 28 | args[i] = ptr[0..strlen(ptr)]; | ||
| 29 | } | ||
| 30 | foo(args); | ||
| 31 | } | ||
| 32 | |||
| 33 | fn strlen(ptr: [*]const u8) usize { | ||
| 34 | var count: usize = 0; | ||
| 35 | while (ptr[count] != 0) : (count += 1) {} | ||
| 36 | return count; | ||
| 37 | } | ||
| 38 | |||
| 39 | fn streql(a: []const u8, b: []const u8) bool { | ||
| 40 | if (a.len != b.len) return false; | ||
| 41 | for (a) |item, index| { | ||
| 42 | if (b[index] != item) return false; | ||
| 43 | } | ||
| 44 | return true; | ||
| 45 | } | ||
test/cases/coroutine_await_struct.zig deleted-47| ... | @@ -1,47 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | |||
| 5 | const Foo = struct { | ||
| 6 | x: i32, | ||
| 7 | }; | ||
| 8 | |||
| 9 | var await_a_promise: promise = undefined; | ||
| 10 | var await_final_result = Foo{ .x = 0 }; | ||
| 11 | |||
| 12 | test "coroutine await struct" { | ||
| 13 | var da = std.heap.DirectAllocator.init(); | ||
| 14 | defer da.deinit(); | ||
| 15 | |||
| 16 | await_seq('a'); | ||
| 17 | const p = async<&da.allocator> await_amain() catch unreachable; | ||
| 18 | await_seq('f'); | ||
| 19 | resume await_a_promise; | ||
| 20 | await_seq('i'); | ||
| 21 | assert(await_final_result.x == 1234); | ||
| 22 | assert(std.mem.eql(u8, await_points, "abcdefghi")); | ||
| 23 | } | ||
| 24 | async fn await_amain() void { | ||
| 25 | await_seq('b'); | ||
| 26 | const p = async await_another() catch unreachable; | ||
| 27 | await_seq('e'); | ||
| 28 | await_final_result = await p; | ||
| 29 | await_seq('h'); | ||
| 30 | } | ||
| 31 | async fn await_another() Foo { | ||
| 32 | await_seq('c'); | ||
| 33 | suspend { | ||
| 34 | await_seq('d'); | ||
| 35 | await_a_promise = @handle(); | ||
| 36 | } | ||
| 37 | await_seq('g'); | ||
| 38 | return Foo{ .x = 1234 }; | ||
| 39 | } | ||
| 40 | |||
| 41 | var await_points = []u8{0} ** "abcdefghi".len; | ||
| 42 | var await_seq_index: usize = 0; | ||
| 43 | |||
| 44 | fn await_seq(c: u8) void { | ||
| 45 | await_points[await_seq_index] = c; | ||
| 46 | await_seq_index += 1; | ||
| 47 | } | ||
test/cases/coroutines.zig deleted-258| ... | @@ -1,258 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | |||
| 5 | var x: i32 = 1; | ||
| 6 | |||
| 7 | test "create a coroutine and cancel it" { | ||
| 8 | var da = std.heap.DirectAllocator.init(); | ||
| 9 | defer da.deinit(); | ||
| 10 | |||
| 11 | const p = try async<&da.allocator> simpleAsyncFn(); | ||
| 12 | comptime assert(@typeOf(p) == promise->void); | ||
| 13 | cancel p; | ||
| 14 | assert(x == 2); | ||
| 15 | } | ||
| 16 | async fn simpleAsyncFn() void { | ||
| 17 | x += 1; | ||
| 18 | suspend; | ||
| 19 | x += 1; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "coroutine suspend, resume, cancel" { | ||
| 23 | var da = std.heap.DirectAllocator.init(); | ||
| 24 | defer da.deinit(); | ||
| 25 | |||
| 26 | seq('a'); | ||
| 27 | const p = try async<&da.allocator> testAsyncSeq(); | ||
| 28 | seq('c'); | ||
| 29 | resume p; | ||
| 30 | seq('f'); | ||
| 31 | cancel p; | ||
| 32 | seq('g'); | ||
| 33 | |||
| 34 | assert(std.mem.eql(u8, points, "abcdefg")); | ||
| 35 | } | ||
| 36 | async fn testAsyncSeq() void { | ||
| 37 | defer seq('e'); | ||
| 38 | |||
| 39 | seq('b'); | ||
| 40 | suspend; | ||
| 41 | seq('d'); | ||
| 42 | } | ||
| 43 | var points = []u8{0} ** "abcdefg".len; | ||
| 44 | var index: usize = 0; | ||
| 45 | |||
| 46 | fn seq(c: u8) void { | ||
| 47 | points[index] = c; | ||
| 48 | index += 1; | ||
| 49 | } | ||
| 50 | |||
| 51 | test "coroutine suspend with block" { | ||
| 52 | var da = std.heap.DirectAllocator.init(); | ||
| 53 | defer da.deinit(); | ||
| 54 | |||
| 55 | const p = try async<&da.allocator> testSuspendBlock(); | ||
| 56 | std.debug.assert(!result); | ||
| 57 | resume a_promise; | ||
| 58 | std.debug.assert(result); | ||
| 59 | cancel p; | ||
| 60 | } | ||
| 61 | |||
| 62 | var a_promise: promise = undefined; | ||
| 63 | var result = false; | ||
| 64 | async fn testSuspendBlock() void { | ||
| 65 | suspend { | ||
| 66 | comptime assert(@typeOf(@handle()) == promise->void); | ||
| 67 | a_promise = @handle(); | ||
| 68 | } | ||
| 69 | |||
| 70 | //Test to make sure that @handle() works as advertised (issue #1296) | ||
| 71 | //var our_handle: promise = @handle(); | ||
| 72 | assert( a_promise == @handle() ); | ||
| 73 | |||
| 74 | result = true; | ||
| 75 | } | ||
| 76 | |||
| 77 | var await_a_promise: promise = undefined; | ||
| 78 | var await_final_result: i32 = 0; | ||
| 79 | |||
| 80 | test "coroutine await" { | ||
| 81 | var da = std.heap.DirectAllocator.init(); | ||
| 82 | defer da.deinit(); | ||
| 83 | |||
| 84 | await_seq('a'); | ||
| 85 | const p = async<&da.allocator> await_amain() catch unreachable; | ||
| 86 | await_seq('f'); | ||
| 87 | resume await_a_promise; | ||
| 88 | await_seq('i'); | ||
| 89 | assert(await_final_result == 1234); | ||
| 90 | assert(std.mem.eql(u8, await_points, "abcdefghi")); | ||
| 91 | } | ||
| 92 | async fn await_amain() void { | ||
| 93 | await_seq('b'); | ||
| 94 | const p = async await_another() catch unreachable; | ||
| 95 | await_seq('e'); | ||
| 96 | await_final_result = await p; | ||
| 97 | await_seq('h'); | ||
| 98 | } | ||
| 99 | async fn await_another() i32 { | ||
| 100 | await_seq('c'); | ||
| 101 | suspend { | ||
| 102 | await_seq('d'); | ||
| 103 | await_a_promise = @handle(); | ||
| 104 | } | ||
| 105 | await_seq('g'); | ||
| 106 | return 1234; | ||
| 107 | } | ||
| 108 | |||
| 109 | var await_points = []u8{0} ** "abcdefghi".len; | ||
| 110 | var await_seq_index: usize = 0; | ||
| 111 | |||
| 112 | fn await_seq(c: u8) void { | ||
| 113 | await_points[await_seq_index] = c; | ||
| 114 | await_seq_index += 1; | ||
| 115 | } | ||
| 116 | |||
| 117 | var early_final_result: i32 = 0; | ||
| 118 | |||
| 119 | test "coroutine await early return" { | ||
| 120 | var da = std.heap.DirectAllocator.init(); | ||
| 121 | defer da.deinit(); | ||
| 122 | |||
| 123 | early_seq('a'); | ||
| 124 | const p = async<&da.allocator> early_amain() catch @panic("out of memory"); | ||
| 125 | early_seq('f'); | ||
| 126 | assert(early_final_result == 1234); | ||
| 127 | assert(std.mem.eql(u8, early_points, "abcdef")); | ||
| 128 | } | ||
| 129 | async fn early_amain() void { | ||
| 130 | early_seq('b'); | ||
| 131 | const p = async early_another() catch @panic("out of memory"); | ||
| 132 | early_seq('d'); | ||
| 133 | early_final_result = await p; | ||
| 134 | early_seq('e'); | ||
| 135 | } | ||
| 136 | async fn early_another() i32 { | ||
| 137 | early_seq('c'); | ||
| 138 | return 1234; | ||
| 139 | } | ||
| 140 | |||
| 141 | var early_points = []u8{0} ** "abcdef".len; | ||
| 142 | var early_seq_index: usize = 0; | ||
| 143 | |||
| 144 | fn early_seq(c: u8) void { | ||
| 145 | early_points[early_seq_index] = c; | ||
| 146 | early_seq_index += 1; | ||
| 147 | } | ||
| 148 | |||
| 149 | test "coro allocation failure" { | ||
| 150 | var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0); | ||
| 151 | if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) { | ||
| 152 | @panic("expected allocation failure"); | ||
| 153 | } else |err| switch (err) { | ||
| 154 | error.OutOfMemory => {}, | ||
| 155 | } | ||
| 156 | } | ||
| 157 | async fn asyncFuncThatNeverGetsRun() void { | ||
| 158 | @panic("coro frame allocation should fail"); | ||
| 159 | } | ||
| 160 | |||
| 161 | test "async function with dot syntax" { | ||
| 162 | const S = struct { | ||
| 163 | var y: i32 = 1; | ||
| 164 | async fn foo() void { | ||
| 165 | y += 1; | ||
| 166 | suspend; | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | var da = std.heap.DirectAllocator.init(); | ||
| 170 | defer da.deinit(); | ||
| 171 | const p = try async<&da.allocator> S.foo(); | ||
| 172 | cancel p; | ||
| 173 | assert(S.y == 2); | ||
| 174 | } | ||
| 175 | |||
| 176 | test "async fn pointer in a struct field" { | ||
| 177 | var data: i32 = 1; | ||
| 178 | const Foo = struct { | ||
| 179 | bar: async<*std.mem.Allocator> fn (*i32) void, | ||
| 180 | }; | ||
| 181 | var foo = Foo{ .bar = simpleAsyncFn2 }; | ||
| 182 | var da = std.heap.DirectAllocator.init(); | ||
| 183 | defer da.deinit(); | ||
| 184 | const p = (async<&da.allocator> foo.bar(&data)) catch unreachable; | ||
| 185 | assert(data == 2); | ||
| 186 | cancel p; | ||
| 187 | assert(data == 4); | ||
| 188 | } | ||
| 189 | async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { | ||
| 190 | defer y.* += 2; | ||
| 191 | y.* += 1; | ||
| 192 | suspend; | ||
| 193 | } | ||
| 194 | |||
| 195 | test "async fn with inferred error set" { | ||
| 196 | var da = std.heap.DirectAllocator.init(); | ||
| 197 | defer da.deinit(); | ||
| 198 | const p = (async<&da.allocator> failing()) catch unreachable; | ||
| 199 | resume p; | ||
| 200 | cancel p; | ||
| 201 | } | ||
| 202 | async fn failing() !void { | ||
| 203 | suspend; | ||
| 204 | return error.Fail; | ||
| 205 | } | ||
| 206 | |||
| 207 | test "error return trace across suspend points - early return" { | ||
| 208 | const p = nonFailing(); | ||
| 209 | resume p; | ||
| 210 | var da = std.heap.DirectAllocator.init(); | ||
| 211 | defer da.deinit(); | ||
| 212 | const p2 = try async<&da.allocator> printTrace(p); | ||
| 213 | cancel p2; | ||
| 214 | } | ||
| 215 | |||
| 216 | test "error return trace across suspend points - async return" { | ||
| 217 | const p = nonFailing(); | ||
| 218 | const p2 = try async<std.debug.global_allocator> printTrace(p); | ||
| 219 | resume p; | ||
| 220 | cancel p2; | ||
| 221 | } | ||
| 222 | |||
| 223 | // TODO https://github.com/ziglang/zig/issues/760 | ||
| 224 | fn nonFailing() promise->(anyerror!void) { | ||
| 225 | return async<std.debug.global_allocator> suspendThenFail() catch unreachable; | ||
| 226 | } | ||
| 227 | async fn suspendThenFail() anyerror!void { | ||
| 228 | suspend; | ||
| 229 | return error.Fail; | ||
| 230 | } | ||
| 231 | async fn printTrace(p: promise->(anyerror!void)) void { | ||
| 232 | (await p) catch |e| { | ||
| 233 | std.debug.assert(e == error.Fail); | ||
| 234 | if (@errorReturnTrace()) |trace| { | ||
| 235 | assert(trace.index == 1); | ||
| 236 | } else switch (builtin.mode) { | ||
| 237 | builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"), | ||
| 238 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {}, | ||
| 239 | } | ||
| 240 | }; | ||
| 241 | } | ||
| 242 | |||
| 243 | test "break from suspend" { | ||
| 244 | var buf: [500]u8 = undefined; | ||
| 245 | var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; | ||
| 246 | var my_result: i32 = 1; | ||
| 247 | const p = try async<a> testBreakFromSuspend(&my_result); | ||
| 248 | cancel p; | ||
| 249 | std.debug.assert(my_result == 2); | ||
| 250 | } | ||
| 251 | async fn testBreakFromSuspend(my_result: *i32) void { | ||
| 252 | suspend { | ||
| 253 | resume @handle(); | ||
| 254 | } | ||
| 255 | my_result.* += 1; | ||
| 256 | suspend; | ||
| 257 | my_result.* += 1; | ||
| 258 | } | ||
test/cases/defer.zig deleted-78| ... | @@ -1,78 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | var result: [3]u8 = undefined; | ||
| 4 | var index: usize = undefined; | ||
| 5 | |||
| 6 | fn runSomeErrorDefers(x: bool) !bool { | ||
| 7 | index = 0; | ||
| 8 | defer { | ||
| 9 | result[index] = 'a'; | ||
| 10 | index += 1; | ||
| 11 | } | ||
| 12 | errdefer { | ||
| 13 | result[index] = 'b'; | ||
| 14 | index += 1; | ||
| 15 | } | ||
| 16 | defer { | ||
| 17 | result[index] = 'c'; | ||
| 18 | index += 1; | ||
| 19 | } | ||
| 20 | return if (x) x else error.FalseNotAllowed; | ||
| 21 | } | ||
| 22 | |||
| 23 | test "mixing normal and error defers" { | ||
| 24 | assert(runSomeErrorDefers(true) catch unreachable); | ||
| 25 | assert(result[0] == 'c'); | ||
| 26 | assert(result[1] == 'a'); | ||
| 27 | |||
| 28 | const ok = runSomeErrorDefers(false) catch |err| x: { | ||
| 29 | assert(err == error.FalseNotAllowed); | ||
| 30 | break :x true; | ||
| 31 | }; | ||
| 32 | assert(ok); | ||
| 33 | assert(result[0] == 'c'); | ||
| 34 | assert(result[1] == 'b'); | ||
| 35 | assert(result[2] == 'a'); | ||
| 36 | } | ||
| 37 | |||
| 38 | test "break and continue inside loop inside defer expression" { | ||
| 39 | testBreakContInDefer(10); | ||
| 40 | comptime testBreakContInDefer(10); | ||
| 41 | } | ||
| 42 | |||
| 43 | fn testBreakContInDefer(x: usize) void { | ||
| 44 | defer { | ||
| 45 | var i: usize = 0; | ||
| 46 | while (i < x) : (i += 1) { | ||
| 47 | if (i < 5) continue; | ||
| 48 | if (i == 5) break; | ||
| 49 | } | ||
| 50 | assert(i == 5); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | test "defer and labeled break" { | ||
| 55 | var i = usize(0); | ||
| 56 | |||
| 57 | blk: { | ||
| 58 | defer i += 1; | ||
| 59 | break :blk; | ||
| 60 | } | ||
| 61 | |||
| 62 | assert(i == 1); | ||
| 63 | } | ||
| 64 | |||
| 65 | test "errdefer does not apply to fn inside fn" { | ||
| 66 | if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn testNestedFnErrDefer() anyerror!void { | ||
| 70 | var a: i32 = 0; | ||
| 71 | errdefer a += 1; | ||
| 72 | const S = struct { | ||
| 73 | fn baz() anyerror { | ||
| 74 | return error.Bad; | ||
| 75 | } | ||
| 76 | }; | ||
| 77 | return S.baz(); | ||
| 78 | } | ||
test/cases/enum.zig deleted-894| ... | @@ -1,894 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | test "enum type" { | ||
| 5 | const foo1 = Foo{ .One = 13 }; | ||
| 6 | const foo2 = Foo{ | ||
| 7 | .Two = Point{ | ||
| 8 | .x = 1234, | ||
| 9 | .y = 5678, | ||
| 10 | }, | ||
| 11 | }; | ||
| 12 | const bar = Bar.B; | ||
| 13 | |||
| 14 | assert(bar == Bar.B); | ||
| 15 | assert(@memberCount(Foo) == 3); | ||
| 16 | assert(@memberCount(Bar) == 4); | ||
| 17 | assert(@sizeOf(Foo) == @sizeOf(FooNoVoid)); | ||
| 18 | assert(@sizeOf(Bar) == 1); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "enum as return value" { | ||
| 22 | switch (returnAnInt(13)) { | ||
| 23 | Foo.One => |value| assert(value == 13), | ||
| 24 | else => unreachable, | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | const Point = struct { | ||
| 29 | x: u64, | ||
| 30 | y: u64, | ||
| 31 | }; | ||
| 32 | const Foo = union(enum) { | ||
| 33 | One: i32, | ||
| 34 | Two: Point, | ||
| 35 | Three: void, | ||
| 36 | }; | ||
| 37 | const FooNoVoid = union(enum) { | ||
| 38 | One: i32, | ||
| 39 | Two: Point, | ||
| 40 | }; | ||
| 41 | const Bar = enum { | ||
| 42 | A, | ||
| 43 | B, | ||
| 44 | C, | ||
| 45 | D, | ||
| 46 | }; | ||
| 47 | |||
| 48 | fn returnAnInt(x: i32) Foo { | ||
| 49 | return Foo{ .One = x }; | ||
| 50 | } | ||
| 51 | |||
| 52 | test "constant enum with payload" { | ||
| 53 | var empty = AnEnumWithPayload{ .Empty = {} }; | ||
| 54 | var full = AnEnumWithPayload{ .Full = 13 }; | ||
| 55 | shouldBeEmpty(empty); | ||
| 56 | shouldBeNotEmpty(full); | ||
| 57 | } | ||
| 58 | |||
| 59 | fn shouldBeEmpty(x: AnEnumWithPayload) void { | ||
| 60 | switch (x) { | ||
| 61 | AnEnumWithPayload.Empty => {}, | ||
| 62 | else => unreachable, | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | fn shouldBeNotEmpty(x: AnEnumWithPayload) void { | ||
| 67 | switch (x) { | ||
| 68 | AnEnumWithPayload.Empty => unreachable, | ||
| 69 | else => {}, | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | const AnEnumWithPayload = union(enum) { | ||
| 74 | Empty: void, | ||
| 75 | Full: i32, | ||
| 76 | }; | ||
| 77 | |||
| 78 | const Number = enum { | ||
| 79 | Zero, | ||
| 80 | One, | ||
| 81 | Two, | ||
| 82 | Three, | ||
| 83 | Four, | ||
| 84 | }; | ||
| 85 | |||
| 86 | test "enum to int" { | ||
| 87 | shouldEqual(Number.Zero, 0); | ||
| 88 | shouldEqual(Number.One, 1); | ||
| 89 | shouldEqual(Number.Two, 2); | ||
| 90 | shouldEqual(Number.Three, 3); | ||
| 91 | shouldEqual(Number.Four, 4); | ||
| 92 | } | ||
| 93 | |||
| 94 | fn shouldEqual(n: Number, expected: u3) void { | ||
| 95 | assert(@enumToInt(n) == expected); | ||
| 96 | } | ||
| 97 | |||
| 98 | test "int to enum" { | ||
| 99 | testIntToEnumEval(3); | ||
| 100 | } | ||
| 101 | fn testIntToEnumEval(x: i32) void { | ||
| 102 | assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); | ||
| 103 | } | ||
| 104 | const IntToEnumNumber = enum { | ||
| 105 | Zero, | ||
| 106 | One, | ||
| 107 | Two, | ||
| 108 | Three, | ||
| 109 | Four, | ||
| 110 | }; | ||
| 111 | |||
| 112 | test "@tagName" { | ||
| 113 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | ||
| 114 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | ||
| 115 | } | ||
| 116 | |||
| 117 | fn testEnumTagNameBare(n: BareNumber) []const u8 { | ||
| 118 | return @tagName(n); | ||
| 119 | } | ||
| 120 | |||
| 121 | const BareNumber = enum { | ||
| 122 | One, | ||
| 123 | Two, | ||
| 124 | Three, | ||
| 125 | }; | ||
| 126 | |||
| 127 | test "enum alignment" { | ||
| 128 | comptime { | ||
| 129 | assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); | ||
| 130 | assert(@alignOf(AlignTestEnum) >= @alignOf(u64)); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | const AlignTestEnum = union(enum) { | ||
| 135 | A: [9]u8, | ||
| 136 | B: u64, | ||
| 137 | }; | ||
| 138 | |||
| 139 | const ValueCount1 = enum { | ||
| 140 | I0, | ||
| 141 | }; | ||
| 142 | const ValueCount2 = enum { | ||
| 143 | I0, | ||
| 144 | I1, | ||
| 145 | }; | ||
| 146 | const ValueCount256 = enum { | ||
| 147 | I0, | ||
| 148 | I1, | ||
| 149 | I2, | ||
| 150 | I3, | ||
| 151 | I4, | ||
| 152 | I5, | ||
| 153 | I6, | ||
| 154 | I7, | ||
| 155 | I8, | ||
| 156 | I9, | ||
| 157 | I10, | ||
| 158 | I11, | ||
| 159 | I12, | ||
| 160 | I13, | ||
| 161 | I14, | ||
| 162 | I15, | ||
| 163 | I16, | ||
| 164 | I17, | ||
| 165 | I18, | ||
| 166 | I19, | ||
| 167 | I20, | ||
| 168 | I21, | ||
| 169 | I22, | ||
| 170 | I23, | ||
| 171 | I24, | ||
| 172 | I25, | ||
| 173 | I26, | ||
| 174 | I27, | ||
| 175 | I28, | ||
| 176 | I29, | ||
| 177 | I30, | ||
| 178 | I31, | ||
| 179 | I32, | ||
| 180 | I33, | ||
| 181 | I34, | ||
| 182 | I35, | ||
| 183 | I36, | ||
| 184 | I37, | ||
| 185 | I38, | ||
| 186 | I39, | ||
| 187 | I40, | ||
| 188 | I41, | ||
| 189 | I42, | ||
| 190 | I43, | ||
| 191 | I44, | ||
| 192 | I45, | ||
| 193 | I46, | ||
| 194 | I47, | ||
| 195 | I48, | ||
| 196 | I49, | ||
| 197 | I50, | ||
| 198 | I51, | ||
| 199 | I52, | ||
| 200 | I53, | ||
| 201 | I54, | ||
| 202 | I55, | ||
| 203 | I56, | ||
| 204 | I57, | ||
| 205 | I58, | ||
| 206 | I59, | ||
| 207 | I60, | ||
| 208 | I61, | ||
| 209 | I62, | ||
| 210 | I63, | ||
| 211 | I64, | ||
| 212 | I65, | ||
| 213 | I66, | ||
| 214 | I67, | ||
| 215 | I68, | ||
| 216 | I69, | ||
| 217 | I70, | ||
| 218 | I71, | ||
| 219 | I72, | ||
| 220 | I73, | ||
| 221 | I74, | ||
| 222 | I75, | ||
| 223 | I76, | ||
| 224 | I77, | ||
| 225 | I78, | ||
| 226 | I79, | ||
| 227 | I80, | ||
| 228 | I81, | ||
| 229 | I82, | ||
| 230 | I83, | ||
| 231 | I84, | ||
| 232 | I85, | ||
| 233 | I86, | ||
| 234 | I87, | ||
| 235 | I88, | ||
| 236 | I89, | ||
| 237 | I90, | ||
| 238 | I91, | ||
| 239 | I92, | ||
| 240 | I93, | ||
| 241 | I94, | ||
| 242 | I95, | ||
| 243 | I96, | ||
| 244 | I97, | ||
| 245 | I98, | ||
| 246 | I99, | ||
| 247 | I100, | ||
| 248 | I101, | ||
| 249 | I102, | ||
| 250 | I103, | ||
| 251 | I104, | ||
| 252 | I105, | ||
| 253 | I106, | ||
| 254 | I107, | ||
| 255 | I108, | ||
| 256 | I109, | ||
| 257 | I110, | ||
| 258 | I111, | ||
| 259 | I112, | ||
| 260 | I113, | ||
| 261 | I114, | ||
| 262 | I115, | ||
| 263 | I116, | ||
| 264 | I117, | ||
| 265 | I118, | ||
| 266 | I119, | ||
| 267 | I120, | ||
| 268 | I121, | ||
| 269 | I122, | ||
| 270 | I123, | ||
| 271 | I124, | ||
| 272 | I125, | ||
| 273 | I126, | ||
| 274 | I127, | ||
| 275 | I128, | ||
| 276 | I129, | ||
| 277 | I130, | ||
| 278 | I131, | ||
| 279 | I132, | ||
| 280 | I133, | ||
| 281 | I134, | ||
| 282 | I135, | ||
| 283 | I136, | ||
| 284 | I137, | ||
| 285 | I138, | ||
| 286 | I139, | ||
| 287 | I140, | ||
| 288 | I141, | ||
| 289 | I142, | ||
| 290 | I143, | ||
| 291 | I144, | ||
| 292 | I145, | ||
| 293 | I146, | ||
| 294 | I147, | ||
| 295 | I148, | ||
| 296 | I149, | ||
| 297 | I150, | ||
| 298 | I151, | ||
| 299 | I152, | ||
| 300 | I153, | ||
| 301 | I154, | ||
| 302 | I155, | ||
| 303 | I156, | ||
| 304 | I157, | ||
| 305 | I158, | ||
| 306 | I159, | ||
| 307 | I160, | ||
| 308 | I161, | ||
| 309 | I162, | ||
| 310 | I163, | ||
| 311 | I164, | ||
| 312 | I165, | ||
| 313 | I166, | ||
| 314 | I167, | ||
| 315 | I168, | ||
| 316 | I169, | ||
| 317 | I170, | ||
| 318 | I171, | ||
| 319 | I172, | ||
| 320 | I173, | ||
| 321 | I174, | ||
| 322 | I175, | ||
| 323 | I176, | ||
| 324 | I177, | ||
| 325 | I178, | ||
| 326 | I179, | ||
| 327 | I180, | ||
| 328 | I181, | ||
| 329 | I182, | ||
| 330 | I183, | ||
| 331 | I184, | ||
| 332 | I185, | ||
| 333 | I186, | ||
| 334 | I187, | ||
| 335 | I188, | ||
| 336 | I189, | ||
| 337 | I190, | ||
| 338 | I191, | ||
| 339 | I192, | ||
| 340 | I193, | ||
| 341 | I194, | ||
| 342 | I195, | ||
| 343 | I196, | ||
| 344 | I197, | ||
| 345 | I198, | ||
| 346 | I199, | ||
| 347 | I200, | ||
| 348 | I201, | ||
| 349 | I202, | ||
| 350 | I203, | ||
| 351 | I204, | ||
| 352 | I205, | ||
| 353 | I206, | ||
| 354 | I207, | ||
| 355 | I208, | ||
| 356 | I209, | ||
| 357 | I210, | ||
| 358 | I211, | ||
| 359 | I212, | ||
| 360 | I213, | ||
| 361 | I214, | ||
| 362 | I215, | ||
| 363 | I216, | ||
| 364 | I217, | ||
| 365 | I218, | ||
| 366 | I219, | ||
| 367 | I220, | ||
| 368 | I221, | ||
| 369 | I222, | ||
| 370 | I223, | ||
| 371 | I224, | ||
| 372 | I225, | ||
| 373 | I226, | ||
| 374 | I227, | ||
| 375 | I228, | ||
| 376 | I229, | ||
| 377 | I230, | ||
| 378 | I231, | ||
| 379 | I232, | ||
| 380 | I233, | ||
| 381 | I234, | ||
| 382 | I235, | ||
| 383 | I236, | ||
| 384 | I237, | ||
| 385 | I238, | ||
| 386 | I239, | ||
| 387 | I240, | ||
| 388 | I241, | ||
| 389 | I242, | ||
| 390 | I243, | ||
| 391 | I244, | ||
| 392 | I245, | ||
| 393 | I246, | ||
| 394 | I247, | ||
| 395 | I248, | ||
| 396 | I249, | ||
| 397 | I250, | ||
| 398 | I251, | ||
| 399 | I252, | ||
| 400 | I253, | ||
| 401 | I254, | ||
| 402 | I255, | ||
| 403 | }; | ||
| 404 | const ValueCount257 = enum { | ||
| 405 | I0, | ||
| 406 | I1, | ||
| 407 | I2, | ||
| 408 | I3, | ||
| 409 | I4, | ||
| 410 | I5, | ||
| 411 | I6, | ||
| 412 | I7, | ||
| 413 | I8, | ||
| 414 | I9, | ||
| 415 | I10, | ||
| 416 | I11, | ||
| 417 | I12, | ||
| 418 | I13, | ||
| 419 | I14, | ||
| 420 | I15, | ||
| 421 | I16, | ||
| 422 | I17, | ||
| 423 | I18, | ||
| 424 | I19, | ||
| 425 | I20, | ||
| 426 | I21, | ||
| 427 | I22, | ||
| 428 | I23, | ||
| 429 | I24, | ||
| 430 | I25, | ||
| 431 | I26, | ||
| 432 | I27, | ||
| 433 | I28, | ||
| 434 | I29, | ||
| 435 | I30, | ||
| 436 | I31, | ||
| 437 | I32, | ||
| 438 | I33, | ||
| 439 | I34, | ||
| 440 | I35, | ||
| 441 | I36, | ||
| 442 | I37, | ||
| 443 | I38, | ||
| 444 | I39, | ||
| 445 | I40, | ||
| 446 | I41, | ||
| 447 | I42, | ||
| 448 | I43, | ||
| 449 | I44, | ||
| 450 | I45, | ||
| 451 | I46, | ||
| 452 | I47, | ||
| 453 | I48, | ||
| 454 | I49, | ||
| 455 | I50, | ||
| 456 | I51, | ||
| 457 | I52, | ||
| 458 | I53, | ||
| 459 | I54, | ||
| 460 | I55, | ||
| 461 | I56, | ||
| 462 | I57, | ||
| 463 | I58, | ||
| 464 | I59, | ||
| 465 | I60, | ||
| 466 | I61, | ||
| 467 | I62, | ||
| 468 | I63, | ||
| 469 | I64, | ||
| 470 | I65, | ||
| 471 | I66, | ||
| 472 | I67, | ||
| 473 | I68, | ||
| 474 | I69, | ||
| 475 | I70, | ||
| 476 | I71, | ||
| 477 | I72, | ||
| 478 | I73, | ||
| 479 | I74, | ||
| 480 | I75, | ||
| 481 | I76, | ||
| 482 | I77, | ||
| 483 | I78, | ||
| 484 | I79, | ||
| 485 | I80, | ||
| 486 | I81, | ||
| 487 | I82, | ||
| 488 | I83, | ||
| 489 | I84, | ||
| 490 | I85, | ||
| 491 | I86, | ||
| 492 | I87, | ||
| 493 | I88, | ||
| 494 | I89, | ||
| 495 | I90, | ||
| 496 | I91, | ||
| 497 | I92, | ||
| 498 | I93, | ||
| 499 | I94, | ||
| 500 | I95, | ||
| 501 | I96, | ||
| 502 | I97, | ||
| 503 | I98, | ||
| 504 | I99, | ||
| 505 | I100, | ||
| 506 | I101, | ||
| 507 | I102, | ||
| 508 | I103, | ||
| 509 | I104, | ||
| 510 | I105, | ||
| 511 | I106, | ||
| 512 | I107, | ||
| 513 | I108, | ||
| 514 | I109, | ||
| 515 | I110, | ||
| 516 | I111, | ||
| 517 | I112, | ||
| 518 | I113, | ||
| 519 | I114, | ||
| 520 | I115, | ||
| 521 | I116, | ||
| 522 | I117, | ||
| 523 | I118, | ||
| 524 | I119, | ||
| 525 | I120, | ||
| 526 | I121, | ||
| 527 | I122, | ||
| 528 | I123, | ||
| 529 | I124, | ||
| 530 | I125, | ||
| 531 | I126, | ||
| 532 | I127, | ||
| 533 | I128, | ||
| 534 | I129, | ||
| 535 | I130, | ||
| 536 | I131, | ||
| 537 | I132, | ||
| 538 | I133, | ||
| 539 | I134, | ||
| 540 | I135, | ||
| 541 | I136, | ||
| 542 | I137, | ||
| 543 | I138, | ||
| 544 | I139, | ||
| 545 | I140, | ||
| 546 | I141, | ||
| 547 | I142, | ||
| 548 | I143, | ||
| 549 | I144, | ||
| 550 | I145, | ||
| 551 | I146, | ||
| 552 | I147, | ||
| 553 | I148, | ||
| 554 | I149, | ||
| 555 | I150, | ||
| 556 | I151, | ||
| 557 | I152, | ||
| 558 | I153, | ||
| 559 | I154, | ||
| 560 | I155, | ||
| 561 | I156, | ||
| 562 | I157, | ||
| 563 | I158, | ||
| 564 | I159, | ||
| 565 | I160, | ||
| 566 | I161, | ||
| 567 | I162, | ||
| 568 | I163, | ||
| 569 | I164, | ||
| 570 | I165, | ||
| 571 | I166, | ||
| 572 | I167, | ||
| 573 | I168, | ||
| 574 | I169, | ||
| 575 | I170, | ||
| 576 | I171, | ||
| 577 | I172, | ||
| 578 | I173, | ||
| 579 | I174, | ||
| 580 | I175, | ||
| 581 | I176, | ||
| 582 | I177, | ||
| 583 | I178, | ||
| 584 | I179, | ||
| 585 | I180, | ||
| 586 | I181, | ||
| 587 | I182, | ||
| 588 | I183, | ||
| 589 | I184, | ||
| 590 | I185, | ||
| 591 | I186, | ||
| 592 | I187, | ||
| 593 | I188, | ||
| 594 | I189, | ||
| 595 | I190, | ||
| 596 | I191, | ||
| 597 | I192, | ||
| 598 | I193, | ||
| 599 | I194, | ||
| 600 | I195, | ||
| 601 | I196, | ||
| 602 | I197, | ||
| 603 | I198, | ||
| 604 | I199, | ||
| 605 | I200, | ||
| 606 | I201, | ||
| 607 | I202, | ||
| 608 | I203, | ||
| 609 | I204, | ||
| 610 | I205, | ||
| 611 | I206, | ||
| 612 | I207, | ||
| 613 | I208, | ||
| 614 | I209, | ||
| 615 | I210, | ||
| 616 | I211, | ||
| 617 | I212, | ||
| 618 | I213, | ||
| 619 | I214, | ||
| 620 | I215, | ||
| 621 | I216, | ||
| 622 | I217, | ||
| 623 | I218, | ||
| 624 | I219, | ||
| 625 | I220, | ||
| 626 | I221, | ||
| 627 | I222, | ||
| 628 | I223, | ||
| 629 | I224, | ||
| 630 | I225, | ||
| 631 | I226, | ||
| 632 | I227, | ||
| 633 | I228, | ||
| 634 | I229, | ||
| 635 | I230, | ||
| 636 | I231, | ||
| 637 | I232, | ||
| 638 | I233, | ||
| 639 | I234, | ||
| 640 | I235, | ||
| 641 | I236, | ||
| 642 | I237, | ||
| 643 | I238, | ||
| 644 | I239, | ||
| 645 | I240, | ||
| 646 | I241, | ||
| 647 | I242, | ||
| 648 | I243, | ||
| 649 | I244, | ||
| 650 | I245, | ||
| 651 | I246, | ||
| 652 | I247, | ||
| 653 | I248, | ||
| 654 | I249, | ||
| 655 | I250, | ||
| 656 | I251, | ||
| 657 | I252, | ||
| 658 | I253, | ||
| 659 | I254, | ||
| 660 | I255, | ||
| 661 | I256, | ||
| 662 | }; | ||
| 663 | |||
| 664 | test "enum sizes" { | ||
| 665 | comptime { | ||
| 666 | assert(@sizeOf(ValueCount1) == 0); | ||
| 667 | assert(@sizeOf(ValueCount2) == 1); | ||
| 668 | assert(@sizeOf(ValueCount256) == 1); | ||
| 669 | assert(@sizeOf(ValueCount257) == 2); | ||
| 670 | } | ||
| 671 | } | ||
| 672 | |||
| 673 | const Small2 = enum(u2) { | ||
| 674 | One, | ||
| 675 | Two, | ||
| 676 | }; | ||
| 677 | const Small = enum(u2) { | ||
| 678 | One, | ||
| 679 | Two, | ||
| 680 | Three, | ||
| 681 | Four, | ||
| 682 | }; | ||
| 683 | |||
| 684 | test "set enum tag type" { | ||
| 685 | { | ||
| 686 | var x = Small.One; | ||
| 687 | x = Small.Two; | ||
| 688 | comptime assert(@TagType(Small) == u2); | ||
| 689 | } | ||
| 690 | { | ||
| 691 | var x = Small2.One; | ||
| 692 | x = Small2.Two; | ||
| 693 | comptime assert(@TagType(Small2) == u2); | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 697 | const A = enum(u3) { | ||
| 698 | One, | ||
| 699 | Two, | ||
| 700 | Three, | ||
| 701 | Four, | ||
| 702 | One2, | ||
| 703 | Two2, | ||
| 704 | Three2, | ||
| 705 | Four2, | ||
| 706 | }; | ||
| 707 | |||
| 708 | const B = enum(u3) { | ||
| 709 | One3, | ||
| 710 | Two3, | ||
| 711 | Three3, | ||
| 712 | Four3, | ||
| 713 | One23, | ||
| 714 | Two23, | ||
| 715 | Three23, | ||
| 716 | Four23, | ||
| 717 | }; | ||
| 718 | |||
| 719 | const C = enum(u2) { | ||
| 720 | One4, | ||
| 721 | Two4, | ||
| 722 | Three4, | ||
| 723 | Four4, | ||
| 724 | }; | ||
| 725 | |||
| 726 | const BitFieldOfEnums = packed struct { | ||
| 727 | a: A, | ||
| 728 | b: B, | ||
| 729 | c: C, | ||
| 730 | }; | ||
| 731 | |||
| 732 | const bit_field_1 = BitFieldOfEnums{ | ||
| 733 | .a = A.Two, | ||
| 734 | .b = B.Three3, | ||
| 735 | .c = C.Four4, | ||
| 736 | }; | ||
| 737 | |||
| 738 | test "bit field access with enum fields" { | ||
| 739 | var data = bit_field_1; | ||
| 740 | assert(getA(&data) == A.Two); | ||
| 741 | assert(getB(&data) == B.Three3); | ||
| 742 | assert(getC(&data) == C.Four4); | ||
| 743 | comptime assert(@sizeOf(BitFieldOfEnums) == 1); | ||
| 744 | |||
| 745 | data.b = B.Four3; | ||
| 746 | assert(data.b == B.Four3); | ||
| 747 | |||
| 748 | data.a = A.Three; | ||
| 749 | assert(data.a == A.Three); | ||
| 750 | assert(data.b == B.Four3); | ||
| 751 | } | ||
| 752 | |||
| 753 | fn getA(data: *const BitFieldOfEnums) A { | ||
| 754 | return data.a; | ||
| 755 | } | ||
| 756 | |||
| 757 | fn getB(data: *const BitFieldOfEnums) B { | ||
| 758 | return data.b; | ||
| 759 | } | ||
| 760 | |||
| 761 | fn getC(data: *const BitFieldOfEnums) C { | ||
| 762 | return data.c; | ||
| 763 | } | ||
| 764 | |||
| 765 | test "casting enum to its tag type" { | ||
| 766 | testCastEnumToTagType(Small2.Two); | ||
| 767 | comptime testCastEnumToTagType(Small2.Two); | ||
| 768 | } | ||
| 769 | |||
| 770 | fn testCastEnumToTagType(value: Small2) void { | ||
| 771 | assert(@enumToInt(value) == 1); | ||
| 772 | } | ||
| 773 | |||
| 774 | const MultipleChoice = enum(u32) { | ||
| 775 | A = 20, | ||
| 776 | B = 40, | ||
| 777 | C = 60, | ||
| 778 | D = 1000, | ||
| 779 | }; | ||
| 780 | |||
| 781 | test "enum with specified tag values" { | ||
| 782 | testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 783 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 784 | } | ||
| 785 | |||
| 786 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { | ||
| 787 | assert(@enumToInt(x) == 60); | ||
| 788 | assert(1234 == switch (x) { | ||
| 789 | MultipleChoice.A => 1, | ||
| 790 | MultipleChoice.B => 2, | ||
| 791 | MultipleChoice.C => u32(1234), | ||
| 792 | MultipleChoice.D => 4, | ||
| 793 | }); | ||
| 794 | } | ||
| 795 | |||
| 796 | const MultipleChoice2 = enum(u32) { | ||
| 797 | Unspecified1, | ||
| 798 | A = 20, | ||
| 799 | Unspecified2, | ||
| 800 | B = 40, | ||
| 801 | Unspecified3, | ||
| 802 | C = 60, | ||
| 803 | Unspecified4, | ||
| 804 | D = 1000, | ||
| 805 | Unspecified5, | ||
| 806 | }; | ||
| 807 | |||
| 808 | test "enum with specified and unspecified tag values" { | ||
| 809 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 810 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 811 | } | ||
| 812 | |||
| 813 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | ||
| 814 | assert(@enumToInt(x) == 1000); | ||
| 815 | assert(1234 == switch (x) { | ||
| 816 | MultipleChoice2.A => 1, | ||
| 817 | MultipleChoice2.B => 2, | ||
| 818 | MultipleChoice2.C => 3, | ||
| 819 | MultipleChoice2.D => u32(1234), | ||
| 820 | MultipleChoice2.Unspecified1 => 5, | ||
| 821 | MultipleChoice2.Unspecified2 => 6, | ||
| 822 | MultipleChoice2.Unspecified3 => 7, | ||
| 823 | MultipleChoice2.Unspecified4 => 8, | ||
| 824 | MultipleChoice2.Unspecified5 => 9, | ||
| 825 | }); | ||
| 826 | } | ||
| 827 | |||
| 828 | test "cast integer literal to enum" { | ||
| 829 | assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); | ||
| 830 | assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); | ||
| 831 | } | ||
| 832 | |||
| 833 | const EnumWithOneMember = enum { | ||
| 834 | Eof, | ||
| 835 | }; | ||
| 836 | |||
| 837 | fn doALoopThing(id: EnumWithOneMember) void { | ||
| 838 | while (true) { | ||
| 839 | if (id == EnumWithOneMember.Eof) { | ||
| 840 | break; | ||
| 841 | } | ||
| 842 | @compileError("above if condition should be comptime"); | ||
| 843 | } | ||
| 844 | } | ||
| 845 | |||
| 846 | test "comparison operator on enum with one member is comptime known" { | ||
| 847 | doALoopThing(EnumWithOneMember.Eof); | ||
| 848 | } | ||
| 849 | |||
| 850 | const State = enum { | ||
| 851 | Start, | ||
| 852 | }; | ||
| 853 | test "switch on enum with one member is comptime known" { | ||
| 854 | var state = State.Start; | ||
| 855 | switch (state) { | ||
| 856 | State.Start => return, | ||
| 857 | } | ||
| 858 | @compileError("analysis should not reach here"); | ||
| 859 | } | ||
| 860 | |||
| 861 | const EnumWithTagValues = enum(u4) { | ||
| 862 | A = 1 << 0, | ||
| 863 | B = 1 << 1, | ||
| 864 | C = 1 << 2, | ||
| 865 | D = 1 << 3, | ||
| 866 | }; | ||
| 867 | test "enum with tag values don't require parens" { | ||
| 868 | assert(@enumToInt(EnumWithTagValues.C) == 0b0100); | ||
| 869 | } | ||
| 870 | |||
| 871 | test "enum with 1 field but explicit tag type should still have the tag type" { | ||
| 872 | const Enum = enum(u8) { | ||
| 873 | B = 2, | ||
| 874 | }; | ||
| 875 | comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8)); | ||
| 876 | } | ||
| 877 | |||
| 878 | test "empty extern enum with members" { | ||
| 879 | const E = extern enum { | ||
| 880 | A, | ||
| 881 | B, | ||
| 882 | C, | ||
| 883 | }; | ||
| 884 | assert(@sizeOf(E) == @sizeOf(c_int)); | ||
| 885 | } | ||
| 886 | |||
| 887 | test "aoeu" { | ||
| 888 | const LocalFoo = enum { | ||
| 889 | A = 1, | ||
| 890 | B = 0, | ||
| 891 | }; | ||
| 892 | var b = LocalFoo.B; | ||
| 893 | assert(mem.eql(u8, @tagName(b), "B")); | ||
| 894 | } | ||
test/cases/enum_with_members.zig deleted-27| ... | @@ -1,27 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | const fmt = @import("std").fmt; | ||
| 4 | |||
| 5 | const ET = union(enum) { | ||
| 6 | SINT: i32, | ||
| 7 | UINT: u32, | ||
| 8 | |||
| 9 | pub fn print(a: *const ET, buf: []u8) anyerror!usize { | ||
| 10 | return switch (a.*) { | ||
| 11 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | ||
| 12 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | |||
| 17 | test "enum with members" { | ||
| 18 | const a = ET{ .SINT = -42 }; | ||
| 19 | const b = ET{ .UINT = 42 }; | ||
| 20 | var buf: [20]u8 = undefined; | ||
| 21 | |||
| 22 | assert((a.print(buf[0..]) catch unreachable) == 3); | ||
| 23 | assert(mem.eql(u8, buf[0..3], "-42")); | ||
| 24 | |||
| 25 | assert((b.print(buf[0..]) catch unreachable) == 2); | ||
| 26 | assert(mem.eql(u8, buf[0..2], "42")); | ||
| 27 | } | ||
test/cases/error.zig deleted-245| ... | @@ -1,245 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | const builtin = @import("builtin"); | ||
| 5 | |||
| 6 | pub fn foo() anyerror!i32 { | ||
| 7 | const x = try bar(); | ||
| 8 | return x + 1; | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn bar() anyerror!i32 { | ||
| 12 | return 13; | ||
| 13 | } | ||
| 14 | |||
| 15 | pub fn baz() anyerror!i32 { | ||
| 16 | const y = foo() catch 1234; | ||
| 17 | return y + 1; | ||
| 18 | } | ||
| 19 | |||
| 20 | test "error wrapping" { | ||
| 21 | assert((baz() catch unreachable) == 15); | ||
| 22 | } | ||
| 23 | |||
| 24 | fn gimmeItBroke() []const u8 { | ||
| 25 | return @errorName(error.ItBroke); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "@errorName" { | ||
| 29 | assert(mem.eql(u8, @errorName(error.AnError), "AnError")); | ||
| 30 | assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "error values" { | ||
| 34 | const a = @errorToInt(error.err1); | ||
| 35 | const b = @errorToInt(error.err2); | ||
| 36 | assert(a != b); | ||
| 37 | } | ||
| 38 | |||
| 39 | test "redefinition of error values allowed" { | ||
| 40 | shouldBeNotEqual(error.AnError, error.SecondError); | ||
| 41 | } | ||
| 42 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { | ||
| 43 | if (a == b) unreachable; | ||
| 44 | } | ||
| 45 | |||
| 46 | test "error binary operator" { | ||
| 47 | const a = errBinaryOperatorG(true) catch 3; | ||
| 48 | const b = errBinaryOperatorG(false) catch 3; | ||
| 49 | assert(a == 3); | ||
| 50 | assert(b == 10); | ||
| 51 | } | ||
| 52 | fn errBinaryOperatorG(x: bool) anyerror!isize { | ||
| 53 | return if (x) error.ItBroke else isize(10); | ||
| 54 | } | ||
| 55 | |||
| 56 | test "unwrap simple value from error" { | ||
| 57 | const i = unwrapSimpleValueFromErrorDo() catch unreachable; | ||
| 58 | assert(i == 13); | ||
| 59 | } | ||
| 60 | fn unwrapSimpleValueFromErrorDo() anyerror!isize { | ||
| 61 | return 13; | ||
| 62 | } | ||
| 63 | |||
| 64 | test "error return in assignment" { | ||
| 65 | doErrReturnInAssignment() catch unreachable; | ||
| 66 | } | ||
| 67 | |||
| 68 | fn doErrReturnInAssignment() anyerror!void { | ||
| 69 | var x: i32 = undefined; | ||
| 70 | x = try makeANonErr(); | ||
| 71 | } | ||
| 72 | |||
| 73 | fn makeANonErr() anyerror!i32 { | ||
| 74 | return 1; | ||
| 75 | } | ||
| 76 | |||
| 77 | test "error union type " { | ||
| 78 | testErrorUnionType(); | ||
| 79 | comptime testErrorUnionType(); | ||
| 80 | } | ||
| 81 | |||
| 82 | fn testErrorUnionType() void { | ||
| 83 | const x: anyerror!i32 = 1234; | ||
| 84 | if (x) |value| assert(value == 1234) else |_| unreachable; | ||
| 85 | assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion); | ||
| 86 | assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); | ||
| 87 | assert(@typeOf(x).ErrorSet == anyerror); | ||
| 88 | } | ||
| 89 | |||
| 90 | test "error set type " { | ||
| 91 | testErrorSetType(); | ||
| 92 | comptime testErrorSetType(); | ||
| 93 | } | ||
| 94 | |||
| 95 | const MyErrSet = error{ | ||
| 96 | OutOfMemory, | ||
| 97 | FileNotFound, | ||
| 98 | }; | ||
| 99 | |||
| 100 | fn testErrorSetType() void { | ||
| 101 | assert(@memberCount(MyErrSet) == 2); | ||
| 102 | |||
| 103 | const a: MyErrSet!i32 = 5678; | ||
| 104 | const b: MyErrSet!i32 = MyErrSet.OutOfMemory; | ||
| 105 | |||
| 106 | if (a) |value| assert(value == 5678) else |err| switch (err) { | ||
| 107 | error.OutOfMemory => unreachable, | ||
| 108 | error.FileNotFound => unreachable, | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | test "explicit error set cast" { | ||
| 113 | testExplicitErrorSetCast(Set1.A); | ||
| 114 | comptime testExplicitErrorSetCast(Set1.A); | ||
| 115 | } | ||
| 116 | |||
| 117 | const Set1 = error{ | ||
| 118 | A, | ||
| 119 | B, | ||
| 120 | }; | ||
| 121 | const Set2 = error{ | ||
| 122 | A, | ||
| 123 | C, | ||
| 124 | }; | ||
| 125 | |||
| 126 | fn testExplicitErrorSetCast(set1: Set1) void { | ||
| 127 | var x = @errSetCast(Set2, set1); | ||
| 128 | var y = @errSetCast(Set1, x); | ||
| 129 | assert(y == error.A); | ||
| 130 | } | ||
| 131 | |||
| 132 | test "comptime test error for empty error set" { | ||
| 133 | testComptimeTestErrorEmptySet(1234); | ||
| 134 | comptime testComptimeTestErrorEmptySet(1234); | ||
| 135 | } | ||
| 136 | |||
| 137 | const EmptyErrorSet = error{}; | ||
| 138 | |||
| 139 | fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { | ||
| 140 | if (x) |v| assert(v == 1234) else |err| @compileError("bad"); | ||
| 141 | } | ||
| 142 | |||
| 143 | test "syntax: optional operator in front of error union operator" { | ||
| 144 | comptime { | ||
| 145 | assert(?(anyerror!i32) == ?(anyerror!i32)); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | test "comptime err to int of error set with only 1 possible value" { | ||
| 150 | testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | ||
| 151 | comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | ||
| 152 | } | ||
| 153 | fn testErrToIntWithOnePossibleValue( | ||
| 154 | x: error{A}, | ||
| 155 | comptime value: u32, | ||
| 156 | ) void { | ||
| 157 | if (@errorToInt(x) != value) { | ||
| 158 | @compileError("bad"); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | test "error union peer type resolution" { | ||
| 163 | testErrorUnionPeerTypeResolution(1); | ||
| 164 | comptime testErrorUnionPeerTypeResolution(1); | ||
| 165 | } | ||
| 166 | |||
| 167 | fn testErrorUnionPeerTypeResolution(x: i32) void { | ||
| 168 | const y = switch (x) { | ||
| 169 | 1 => bar_1(), | ||
| 170 | 2 => baz_1(), | ||
| 171 | else => quux_1(), | ||
| 172 | }; | ||
| 173 | } | ||
| 174 | |||
| 175 | fn bar_1() anyerror { | ||
| 176 | return error.A; | ||
| 177 | } | ||
| 178 | |||
| 179 | fn baz_1() !i32 { | ||
| 180 | return error.B; | ||
| 181 | } | ||
| 182 | |||
| 183 | fn quux_1() !i32 { | ||
| 184 | return error.C; | ||
| 185 | } | ||
| 186 | |||
| 187 | test "error: fn returning empty error set can be passed as fn returning any error" { | ||
| 188 | entry(); | ||
| 189 | comptime entry(); | ||
| 190 | } | ||
| 191 | |||
| 192 | fn entry() void { | ||
| 193 | foo2(bar2); | ||
| 194 | } | ||
| 195 | |||
| 196 | fn foo2(f: fn () anyerror!void) void { | ||
| 197 | const x = f(); | ||
| 198 | } | ||
| 199 | |||
| 200 | fn bar2() (error{}!void) {} | ||
| 201 | |||
| 202 | test "error: Zero sized error set returned with value payload crash" { | ||
| 203 | _ = foo3(0); | ||
| 204 | _ = comptime foo3(0); | ||
| 205 | } | ||
| 206 | |||
| 207 | const Error = error{}; | ||
| 208 | fn foo3(b: usize) Error!usize { | ||
| 209 | return b; | ||
| 210 | } | ||
| 211 | |||
| 212 | test "error: Infer error set from literals" { | ||
| 213 | _ = nullLiteral("n") catch |err| handleErrors(err); | ||
| 214 | _ = floatLiteral("n") catch |err| handleErrors(err); | ||
| 215 | _ = intLiteral("n") catch |err| handleErrors(err); | ||
| 216 | _ = comptime nullLiteral("n") catch |err| handleErrors(err); | ||
| 217 | _ = comptime floatLiteral("n") catch |err| handleErrors(err); | ||
| 218 | _ = comptime intLiteral("n") catch |err| handleErrors(err); | ||
| 219 | } | ||
| 220 | |||
| 221 | fn handleErrors(err: var) noreturn { | ||
| 222 | switch (err) { | ||
| 223 | error.T => {}, | ||
| 224 | } | ||
| 225 | |||
| 226 | unreachable; | ||
| 227 | } | ||
| 228 | |||
| 229 | fn nullLiteral(str: []const u8) !?i64 { | ||
| 230 | if (str[0] == 'n') return null; | ||
| 231 | |||
| 232 | return error.T; | ||
| 233 | } | ||
| 234 | |||
| 235 | fn floatLiteral(str: []const u8) !?f64 { | ||
| 236 | if (str[0] == 'n') return 1.0; | ||
| 237 | |||
| 238 | return error.T; | ||
| 239 | } | ||
| 240 | |||
| 241 | fn intLiteral(str: []const u8) !?i64 { | ||
| 242 | if (str[0] == 'n') return 1; | ||
| 243 | |||
| 244 | return error.T; | ||
| 245 | } | ||
test/cases/eval.zig deleted-782| ... | @@ -1,782 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | |||
| 5 | test "compile time recursion" { | ||
| 6 | assert(some_data.len == 21); | ||
| 7 | } | ||
| 8 | var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined; | ||
| 9 | fn fibonacci(x: i32) i32 { | ||
| 10 | if (x <= 1) return 1; | ||
| 11 | return fibonacci(x - 1) + fibonacci(x - 2); | ||
| 12 | } | ||
| 13 | |||
| 14 | fn unwrapAndAddOne(blah: ?i32) i32 { | ||
| 15 | return blah.? + 1; | ||
| 16 | } | ||
| 17 | const should_be_1235 = unwrapAndAddOne(1234); | ||
| 18 | test "static add one" { | ||
| 19 | assert(should_be_1235 == 1235); | ||
| 20 | } | ||
| 21 | |||
| 22 | test "inlined loop" { | ||
| 23 | comptime var i = 0; | ||
| 24 | comptime var sum = 0; | ||
| 25 | inline while (i <= 5) : (i += 1) | ||
| 26 | sum += i; | ||
| 27 | assert(sum == 15); | ||
| 28 | } | ||
| 29 | |||
| 30 | fn gimme1or2(comptime a: bool) i32 { | ||
| 31 | const x: i32 = 1; | ||
| 32 | const y: i32 = 2; | ||
| 33 | comptime var z: i32 = if (a) x else y; | ||
| 34 | return z; | ||
| 35 | } | ||
| 36 | test "inline variable gets result of const if" { | ||
| 37 | assert(gimme1or2(true) == 1); | ||
| 38 | assert(gimme1or2(false) == 2); | ||
| 39 | } | ||
| 40 | |||
| 41 | test "static function evaluation" { | ||
| 42 | assert(statically_added_number == 3); | ||
| 43 | } | ||
| 44 | const statically_added_number = staticAdd(1, 2); | ||
| 45 | fn staticAdd(a: i32, b: i32) i32 { | ||
| 46 | return a + b; | ||
| 47 | } | ||
| 48 | |||
| 49 | test "const expr eval on single expr blocks" { | ||
| 50 | assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); | ||
| 51 | } | ||
| 52 | |||
| 53 | fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { | ||
| 54 | const literal = 3; | ||
| 55 | |||
| 56 | const result = if (b) b: { | ||
| 57 | break :b literal; | ||
| 58 | } else b: { | ||
| 59 | break :b x; | ||
| 60 | }; | ||
| 61 | |||
| 62 | return result; | ||
| 63 | } | ||
| 64 | |||
| 65 | test "statically initialized list" { | ||
| 66 | assert(static_point_list[0].x == 1); | ||
| 67 | assert(static_point_list[0].y == 2); | ||
| 68 | assert(static_point_list[1].x == 3); | ||
| 69 | assert(static_point_list[1].y == 4); | ||
| 70 | } | ||
| 71 | const Point = struct { | ||
| 72 | x: i32, | ||
| 73 | y: i32, | ||
| 74 | }; | ||
| 75 | const static_point_list = []Point{ | ||
| 76 | makePoint(1, 2), | ||
| 77 | makePoint(3, 4), | ||
| 78 | }; | ||
| 79 | fn makePoint(x: i32, y: i32) Point { | ||
| 80 | return Point{ | ||
| 81 | .x = x, | ||
| 82 | .y = y, | ||
| 83 | }; | ||
| 84 | } | ||
| 85 | |||
| 86 | test "static eval list init" { | ||
| 87 | assert(static_vec3.data[2] == 1.0); | ||
| 88 | assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); | ||
| 89 | } | ||
| 90 | const static_vec3 = vec3(0.0, 0.0, 1.0); | ||
| 91 | pub const Vec3 = struct { | ||
| 92 | data: [3]f32, | ||
| 93 | }; | ||
| 94 | pub fn vec3(x: f32, y: f32, z: f32) Vec3 { | ||
| 95 | return Vec3{ .data = []f32{ | ||
| 96 | x, | ||
| 97 | y, | ||
| 98 | z, | ||
| 99 | } }; | ||
| 100 | } | ||
| 101 | |||
| 102 | test "constant expressions" { | ||
| 103 | var array: [array_size]u8 = undefined; | ||
| 104 | assert(@sizeOf(@typeOf(array)) == 20); | ||
| 105 | } | ||
| 106 | const array_size: u8 = 20; | ||
| 107 | |||
| 108 | test "constant struct with negation" { | ||
| 109 | assert(vertices[0].x == -0.6); | ||
| 110 | } | ||
| 111 | const Vertex = struct { | ||
| 112 | x: f32, | ||
| 113 | y: f32, | ||
| 114 | r: f32, | ||
| 115 | g: f32, | ||
| 116 | b: f32, | ||
| 117 | }; | ||
| 118 | const vertices = []Vertex{ | ||
| 119 | Vertex{ | ||
| 120 | .x = -0.6, | ||
| 121 | .y = -0.4, | ||
| 122 | .r = 1.0, | ||
| 123 | .g = 0.0, | ||
| 124 | .b = 0.0, | ||
| 125 | }, | ||
| 126 | Vertex{ | ||
| 127 | .x = 0.6, | ||
| 128 | .y = -0.4, | ||
| 129 | .r = 0.0, | ||
| 130 | .g = 1.0, | ||
| 131 | .b = 0.0, | ||
| 132 | }, | ||
| 133 | Vertex{ | ||
| 134 | .x = 0.0, | ||
| 135 | .y = 0.6, | ||
| 136 | .r = 0.0, | ||
| 137 | .g = 0.0, | ||
| 138 | .b = 1.0, | ||
| 139 | }, | ||
| 140 | }; | ||
| 141 | |||
| 142 | test "statically initialized struct" { | ||
| 143 | st_init_str_foo.x += 1; | ||
| 144 | assert(st_init_str_foo.x == 14); | ||
| 145 | } | ||
| 146 | const StInitStrFoo = struct { | ||
| 147 | x: i32, | ||
| 148 | y: bool, | ||
| 149 | }; | ||
| 150 | var st_init_str_foo = StInitStrFoo{ | ||
| 151 | .x = 13, | ||
| 152 | .y = true, | ||
| 153 | }; | ||
| 154 | |||
| 155 | test "statically initalized array literal" { | ||
| 156 | const y: [4]u8 = st_init_arr_lit_x; | ||
| 157 | assert(y[3] == 4); | ||
| 158 | } | ||
| 159 | const st_init_arr_lit_x = []u8{ | ||
| 160 | 1, | ||
| 161 | 2, | ||
| 162 | 3, | ||
| 163 | 4, | ||
| 164 | }; | ||
| 165 | |||
| 166 | test "const slice" { | ||
| 167 | comptime { | ||
| 168 | const a = "1234567890"; | ||
| 169 | assert(a.len == 10); | ||
| 170 | const b = a[1..2]; | ||
| 171 | assert(b.len == 1); | ||
| 172 | assert(b[0] == '2'); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | test "try to trick eval with runtime if" { | ||
| 177 | assert(testTryToTrickEvalWithRuntimeIf(true) == 10); | ||
| 178 | } | ||
| 179 | |||
| 180 | fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { | ||
| 181 | comptime var i: usize = 0; | ||
| 182 | inline while (i < 10) : (i += 1) { | ||
| 183 | const result = if (b) false else true; | ||
| 184 | } | ||
| 185 | comptime { | ||
| 186 | return i; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | fn max(comptime T: type, a: T, b: T) T { | ||
| 191 | if (T == bool) { | ||
| 192 | return a or b; | ||
| 193 | } else if (a > b) { | ||
| 194 | return a; | ||
| 195 | } else { | ||
| 196 | return b; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | fn letsTryToCompareBools(a: bool, b: bool) bool { | ||
| 200 | return max(bool, a, b); | ||
| 201 | } | ||
| 202 | test "inlined block and runtime block phi" { | ||
| 203 | assert(letsTryToCompareBools(true, true)); | ||
| 204 | assert(letsTryToCompareBools(true, false)); | ||
| 205 | assert(letsTryToCompareBools(false, true)); | ||
| 206 | assert(!letsTryToCompareBools(false, false)); | ||
| 207 | |||
| 208 | comptime { | ||
| 209 | assert(letsTryToCompareBools(true, true)); | ||
| 210 | assert(letsTryToCompareBools(true, false)); | ||
| 211 | assert(letsTryToCompareBools(false, true)); | ||
| 212 | assert(!letsTryToCompareBools(false, false)); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | const CmdFn = struct { | ||
| 217 | name: []const u8, | ||
| 218 | func: fn (i32) i32, | ||
| 219 | }; | ||
| 220 | |||
| 221 | const cmd_fns = []CmdFn{ | ||
| 222 | CmdFn{ | ||
| 223 | .name = "one", | ||
| 224 | .func = one, | ||
| 225 | }, | ||
| 226 | CmdFn{ | ||
| 227 | .name = "two", | ||
| 228 | .func = two, | ||
| 229 | }, | ||
| 230 | CmdFn{ | ||
| 231 | .name = "three", | ||
| 232 | .func = three, | ||
| 233 | }, | ||
| 234 | }; | ||
| 235 | fn one(value: i32) i32 { | ||
| 236 | return value + 1; | ||
| 237 | } | ||
| 238 | fn two(value: i32) i32 { | ||
| 239 | return value + 2; | ||
| 240 | } | ||
| 241 | fn three(value: i32) i32 { | ||
| 242 | return value + 3; | ||
| 243 | } | ||
| 244 | |||
| 245 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { | ||
| 246 | var result: i32 = start_value; | ||
| 247 | comptime var i = 0; | ||
| 248 | inline while (i < cmd_fns.len) : (i += 1) { | ||
| 249 | if (cmd_fns[i].name[0] == prefix_char) { | ||
| 250 | result = cmd_fns[i].func(result); | ||
| 251 | } | ||
| 252 | } | ||
| 253 | return result; | ||
| 254 | } | ||
| 255 | |||
| 256 | test "comptime iterate over fn ptr list" { | ||
| 257 | assert(performFn('t', 1) == 6); | ||
| 258 | assert(performFn('o', 0) == 1); | ||
| 259 | assert(performFn('w', 99) == 99); | ||
| 260 | } | ||
| 261 | |||
| 262 | test "eval @setRuntimeSafety at compile-time" { | ||
| 263 | const result = comptime fnWithSetRuntimeSafety(); | ||
| 264 | assert(result == 1234); | ||
| 265 | } | ||
| 266 | |||
| 267 | fn fnWithSetRuntimeSafety() i32 { | ||
| 268 | @setRuntimeSafety(true); | ||
| 269 | return 1234; | ||
| 270 | } | ||
| 271 | |||
| 272 | test "eval @setFloatMode at compile-time" { | ||
| 273 | const result = comptime fnWithFloatMode(); | ||
| 274 | assert(result == 1234.0); | ||
| 275 | } | ||
| 276 | |||
| 277 | fn fnWithFloatMode() f32 { | ||
| 278 | @setFloatMode(builtin.FloatMode.Strict); | ||
| 279 | return 1234.0; | ||
| 280 | } | ||
| 281 | |||
| 282 | const SimpleStruct = struct { | ||
| 283 | field: i32, | ||
| 284 | |||
| 285 | fn method(self: *const SimpleStruct) i32 { | ||
| 286 | return self.field + 3; | ||
| 287 | } | ||
| 288 | }; | ||
| 289 | |||
| 290 | var simple_struct = SimpleStruct{ .field = 1234 }; | ||
| 291 | |||
| 292 | const bound_fn = simple_struct.method; | ||
| 293 | |||
| 294 | test "call method on bound fn referring to var instance" { | ||
| 295 | assert(bound_fn() == 1237); | ||
| 296 | } | ||
| 297 | |||
| 298 | test "ptr to local array argument at comptime" { | ||
| 299 | comptime { | ||
| 300 | var bytes: [10]u8 = undefined; | ||
| 301 | modifySomeBytes(bytes[0..]); | ||
| 302 | assert(bytes[0] == 'a'); | ||
| 303 | assert(bytes[9] == 'b'); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | fn modifySomeBytes(bytes: []u8) void { | ||
| 308 | bytes[0] = 'a'; | ||
| 309 | bytes[9] = 'b'; | ||
| 310 | } | ||
| 311 | |||
| 312 | test "comparisons 0 <= uint and 0 > uint should be comptime" { | ||
| 313 | testCompTimeUIntComparisons(1234); | ||
| 314 | } | ||
| 315 | fn testCompTimeUIntComparisons(x: u32) void { | ||
| 316 | if (!(0 <= x)) { | ||
| 317 | @compileError("this condition should be comptime known"); | ||
| 318 | } | ||
| 319 | if (0 > x) { | ||
| 320 | @compileError("this condition should be comptime known"); | ||
| 321 | } | ||
| 322 | if (!(x >= 0)) { | ||
| 323 | @compileError("this condition should be comptime known"); | ||
| 324 | } | ||
| 325 | if (x < 0) { | ||
| 326 | @compileError("this condition should be comptime known"); | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | test "const ptr to variable data changes at runtime" { | ||
| 331 | assert(foo_ref.name[0] == 'a'); | ||
| 332 | foo_ref.name = "b"; | ||
| 333 | assert(foo_ref.name[0] == 'b'); | ||
| 334 | } | ||
| 335 | |||
| 336 | const Foo = struct { | ||
| 337 | name: []const u8, | ||
| 338 | }; | ||
| 339 | |||
| 340 | var foo_contents = Foo{ .name = "a" }; | ||
| 341 | const foo_ref = &foo_contents; | ||
| 342 | |||
| 343 | test "create global array with for loop" { | ||
| 344 | assert(global_array[5] == 5 * 5); | ||
| 345 | assert(global_array[9] == 9 * 9); | ||
| 346 | } | ||
| 347 | |||
| 348 | const global_array = x: { | ||
| 349 | var result: [10]usize = undefined; | ||
| 350 | for (result) |*item, index| { | ||
| 351 | item.* = index * index; | ||
| 352 | } | ||
| 353 | break :x result; | ||
| 354 | }; | ||
| 355 | |||
| 356 | test "compile-time downcast when the bits fit" { | ||
| 357 | comptime { | ||
| 358 | const spartan_count: u16 = 255; | ||
| 359 | const byte = @intCast(u8, spartan_count); | ||
| 360 | assert(byte == 255); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | const hi1 = "hi"; | ||
| 365 | const hi2 = hi1; | ||
| 366 | test "const global shares pointer with other same one" { | ||
| 367 | assertEqualPtrs(&hi1[0], &hi2[0]); | ||
| 368 | comptime assert(&hi1[0] == &hi2[0]); | ||
| 369 | } | ||
| 370 | fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void { | ||
| 371 | assert(ptr1 == ptr2); | ||
| 372 | } | ||
| 373 | |||
| 374 | test "@setEvalBranchQuota" { | ||
| 375 | comptime { | ||
| 376 | // 1001 for the loop and then 1 more for the assert fn call | ||
| 377 | @setEvalBranchQuota(1002); | ||
| 378 | var i = 0; | ||
| 379 | var sum = 0; | ||
| 380 | while (i < 1001) : (i += 1) { | ||
| 381 | sum += i; | ||
| 382 | } | ||
| 383 | assert(sum == 500500); | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | // TODO test "float literal at compile time not lossy" { | ||
| 388 | // TODO assert(16777216.0 + 1.0 == 16777217.0); | ||
| 389 | // TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0); | ||
| 390 | // TODO } | ||
| 391 | |||
| 392 | test "f32 at compile time is lossy" { | ||
| 393 | assert(f32(1 << 24) + 1 == 1 << 24); | ||
| 394 | } | ||
| 395 | |||
| 396 | test "f64 at compile time is lossy" { | ||
| 397 | assert(f64(1 << 53) + 1 == 1 << 53); | ||
| 398 | } | ||
| 399 | |||
| 400 | test "f128 at compile time is lossy" { | ||
| 401 | assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); | ||
| 402 | } | ||
| 403 | |||
| 404 | // TODO need a better implementation of bigfloat_init_bigint | ||
| 405 | // assert(f128(1 << 113) == 10384593717069655257060992658440192); | ||
| 406 | |||
| 407 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { | ||
| 408 | return struct { | ||
| 409 | pub const Node = struct {}; | ||
| 410 | }; | ||
| 411 | } | ||
| 412 | |||
| 413 | test "string literal used as comptime slice is memoized" { | ||
| 414 | const a = "link"; | ||
| 415 | const b = "link"; | ||
| 416 | comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); | ||
| 417 | comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); | ||
| 418 | } | ||
| 419 | |||
| 420 | test "comptime slice of undefined pointer of length 0" { | ||
| 421 | const slice1 = ([*]i32)(undefined)[0..0]; | ||
| 422 | assert(slice1.len == 0); | ||
| 423 | const slice2 = ([*]i32)(undefined)[100..100]; | ||
| 424 | assert(slice2.len == 0); | ||
| 425 | } | ||
| 426 | |||
| 427 | fn copyWithPartialInline(s: []u32, b: []u8) void { | ||
| 428 | comptime var i: usize = 0; | ||
| 429 | inline while (i < 4) : (i += 1) { | ||
| 430 | s[i] = 0; | ||
| 431 | s[i] |= u32(b[i * 4 + 0]) << 24; | ||
| 432 | s[i] |= u32(b[i * 4 + 1]) << 16; | ||
| 433 | s[i] |= u32(b[i * 4 + 2]) << 8; | ||
| 434 | s[i] |= u32(b[i * 4 + 3]) << 0; | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | test "binary math operator in partially inlined function" { | ||
| 439 | var s: [4]u32 = undefined; | ||
| 440 | var b: [16]u8 = undefined; | ||
| 441 | |||
| 442 | for (b) |*r, i| | ||
| 443 | r.* = @intCast(u8, i + 1); | ||
| 444 | |||
| 445 | copyWithPartialInline(s[0..], b[0..]); | ||
| 446 | assert(s[0] == 0x1020304); | ||
| 447 | assert(s[1] == 0x5060708); | ||
| 448 | assert(s[2] == 0x90a0b0c); | ||
| 449 | assert(s[3] == 0xd0e0f10); | ||
| 450 | } | ||
| 451 | |||
| 452 | test "comptime function with the same args is memoized" { | ||
| 453 | comptime { | ||
| 454 | assert(MakeType(i32) == MakeType(i32)); | ||
| 455 | assert(MakeType(i32) != MakeType(f64)); | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | fn MakeType(comptime T: type) type { | ||
| 460 | return struct { | ||
| 461 | field: T, | ||
| 462 | }; | ||
| 463 | } | ||
| 464 | |||
| 465 | test "comptime function with mutable pointer is not memoized" { | ||
| 466 | comptime { | ||
| 467 | var x: i32 = 1; | ||
| 468 | const ptr = &x; | ||
| 469 | increment(ptr); | ||
| 470 | increment(ptr); | ||
| 471 | assert(x == 3); | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | fn increment(value: *i32) void { | ||
| 476 | value.* += 1; | ||
| 477 | } | ||
| 478 | |||
| 479 | fn generateTable(comptime T: type) [1010]T { | ||
| 480 | var res: [1010]T = undefined; | ||
| 481 | var i: usize = 0; | ||
| 482 | while (i < 1010) : (i += 1) { | ||
| 483 | res[i] = @intCast(T, i); | ||
| 484 | } | ||
| 485 | return res; | ||
| 486 | } | ||
| 487 | |||
| 488 | fn doesAlotT(comptime T: type, value: usize) T { | ||
| 489 | @setEvalBranchQuota(5000); | ||
| 490 | const table = comptime blk: { | ||
| 491 | break :blk generateTable(T); | ||
| 492 | }; | ||
| 493 | return table[value]; | ||
| 494 | } | ||
| 495 | |||
| 496 | test "@setEvalBranchQuota at same scope as generic function call" { | ||
| 497 | assert(doesAlotT(u32, 2) == 2); | ||
| 498 | } | ||
| 499 | |||
| 500 | test "comptime slice of slice preserves comptime var" { | ||
| 501 | comptime { | ||
| 502 | var buff: [10]u8 = undefined; | ||
| 503 | buff[0..][0..][0] = 1; | ||
| 504 | assert(buff[0..][0..][0] == 1); | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | test "comptime slice of pointer preserves comptime var" { | ||
| 509 | comptime { | ||
| 510 | var buff: [10]u8 = undefined; | ||
| 511 | var a = buff[0..].ptr; | ||
| 512 | a[0..1][0] = 1; | ||
| 513 | assert(buff[0..][0..][0] == 1); | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | const SingleFieldStruct = struct { | ||
| 518 | x: i32, | ||
| 519 | |||
| 520 | fn read_x(self: *const SingleFieldStruct) i32 { | ||
| 521 | return self.x; | ||
| 522 | } | ||
| 523 | }; | ||
| 524 | test "const ptr to comptime mutable data is not memoized" { | ||
| 525 | comptime { | ||
| 526 | var foo = SingleFieldStruct{ .x = 1 }; | ||
| 527 | assert(foo.read_x() == 1); | ||
| 528 | foo.x = 2; | ||
| 529 | assert(foo.read_x() == 2); | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | test "array concat of slices gives slice" { | ||
| 534 | comptime { | ||
| 535 | var a: []const u8 = "aoeu"; | ||
| 536 | var b: []const u8 = "asdf"; | ||
| 537 | const c = a ++ b; | ||
| 538 | assert(std.mem.eql(u8, c, "aoeuasdf")); | ||
| 539 | } | ||
| 540 | } | ||
| 541 | |||
| 542 | test "comptime shlWithOverflow" { | ||
| 543 | const ct_shifted: u64 = comptime amt: { | ||
| 544 | var amt = u64(0); | ||
| 545 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | ||
| 546 | break :amt amt; | ||
| 547 | }; | ||
| 548 | |||
| 549 | const rt_shifted: u64 = amt: { | ||
| 550 | var amt = u64(0); | ||
| 551 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | ||
| 552 | break :amt amt; | ||
| 553 | }; | ||
| 554 | |||
| 555 | assert(ct_shifted == rt_shifted); | ||
| 556 | } | ||
| 557 | |||
| 558 | test "runtime 128 bit integer division" { | ||
| 559 | var a: u128 = 152313999999999991610955792383; | ||
| 560 | var b: u128 = 10000000000000000000; | ||
| 561 | var c = a / b; | ||
| 562 | assert(c == 15231399999); | ||
| 563 | } | ||
| 564 | |||
| 565 | pub const Info = struct { | ||
| 566 | version: u8, | ||
| 567 | }; | ||
| 568 | |||
| 569 | pub const diamond_info = Info{ .version = 0 }; | ||
| 570 | |||
| 571 | test "comptime modification of const struct field" { | ||
| 572 | comptime { | ||
| 573 | var res = diamond_info; | ||
| 574 | res.version = 1; | ||
| 575 | assert(diamond_info.version == 0); | ||
| 576 | assert(res.version == 1); | ||
| 577 | } | ||
| 578 | } | ||
| 579 | |||
| 580 | test "pointer to type" { | ||
| 581 | comptime { | ||
| 582 | var T: type = i32; | ||
| 583 | assert(T == i32); | ||
| 584 | var ptr = &T; | ||
| 585 | assert(@typeOf(ptr) == *type); | ||
| 586 | ptr.* = f32; | ||
| 587 | assert(T == f32); | ||
| 588 | assert(*T == *f32); | ||
| 589 | } | ||
| 590 | } | ||
| 591 | |||
| 592 | test "slice of type" { | ||
| 593 | comptime { | ||
| 594 | var types_array = []type{ i32, f64, type }; | ||
| 595 | for (types_array) |T, i| { | ||
| 596 | switch (i) { | ||
| 597 | 0 => assert(T == i32), | ||
| 598 | 1 => assert(T == f64), | ||
| 599 | 2 => assert(T == type), | ||
| 600 | else => unreachable, | ||
| 601 | } | ||
| 602 | } | ||
| 603 | for (types_array[0..]) |T, i| { | ||
| 604 | switch (i) { | ||
| 605 | 0 => assert(T == i32), | ||
| 606 | 1 => assert(T == f64), | ||
| 607 | 2 => assert(T == type), | ||
| 608 | else => unreachable, | ||
| 609 | } | ||
| 610 | } | ||
| 611 | } | ||
| 612 | } | ||
| 613 | |||
| 614 | const Wrapper = struct { | ||
| 615 | T: type, | ||
| 616 | }; | ||
| 617 | |||
| 618 | fn wrap(comptime T: type) Wrapper { | ||
| 619 | return Wrapper{ .T = T }; | ||
| 620 | } | ||
| 621 | |||
| 622 | test "function which returns struct with type field causes implicit comptime" { | ||
| 623 | const ty = wrap(i32).T; | ||
| 624 | assert(ty == i32); | ||
| 625 | } | ||
| 626 | |||
| 627 | test "call method with comptime pass-by-non-copying-value self parameter" { | ||
| 628 | const S = struct { | ||
| 629 | a: u8, | ||
| 630 | |||
| 631 | fn b(comptime s: @This()) u8 { | ||
| 632 | return s.a; | ||
| 633 | } | ||
| 634 | }; | ||
| 635 | |||
| 636 | const s = S{ .a = 2 }; | ||
| 637 | var b = s.b(); | ||
| 638 | assert(b == 2); | ||
| 639 | } | ||
| 640 | |||
| 641 | test "@tagName of @typeId" { | ||
| 642 | const str = @tagName(@typeId(u8)); | ||
| 643 | assert(std.mem.eql(u8, str, "Int")); | ||
| 644 | } | ||
| 645 | |||
| 646 | test "setting backward branch quota just before a generic fn call" { | ||
| 647 | @setEvalBranchQuota(1001); | ||
| 648 | loopNTimes(1001); | ||
| 649 | } | ||
| 650 | |||
| 651 | fn loopNTimes(comptime n: usize) void { | ||
| 652 | comptime var i = 0; | ||
| 653 | inline while (i < n) : (i += 1) {} | ||
| 654 | } | ||
| 655 | |||
| 656 | test "variable inside inline loop that has different types on different iterations" { | ||
| 657 | testVarInsideInlineLoop(true, u32(42)); | ||
| 658 | } | ||
| 659 | |||
| 660 | fn testVarInsideInlineLoop(args: ...) void { | ||
| 661 | comptime var i = 0; | ||
| 662 | inline while (i < args.len) : (i += 1) { | ||
| 663 | const x = args[i]; | ||
| 664 | if (i == 0) assert(x); | ||
| 665 | if (i == 1) assert(x == 42); | ||
| 666 | } | ||
| 667 | } | ||
| 668 | |||
| 669 | test "inline for with same type but different values" { | ||
| 670 | var res: usize = 0; | ||
| 671 | inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| { | ||
| 672 | var a: T = undefined; | ||
| 673 | res += a.len; | ||
| 674 | } | ||
| 675 | assert(res == 5); | ||
| 676 | } | ||
| 677 | |||
| 678 | test "refer to the type of a generic function" { | ||
| 679 | const Func = fn (type) void; | ||
| 680 | const f: Func = doNothingWithType; | ||
| 681 | f(i32); | ||
| 682 | } | ||
| 683 | |||
| 684 | fn doNothingWithType(comptime T: type) void {} | ||
| 685 | |||
| 686 | test "zero extend from u0 to u1" { | ||
| 687 | var zero_u0: u0 = 0; | ||
| 688 | var zero_u1: u1 = zero_u0; | ||
| 689 | assert(zero_u1 == 0); | ||
| 690 | } | ||
| 691 | |||
| 692 | test "bit shift a u1" { | ||
| 693 | var x: u1 = 1; | ||
| 694 | var y = x << 0; | ||
| 695 | assert(y == 1); | ||
| 696 | } | ||
| 697 | |||
| 698 | test "@intCast to a u0" { | ||
| 699 | var x: u8 = 0; | ||
| 700 | var y: u0 = @intCast(u0, x); | ||
| 701 | assert(y == 0); | ||
| 702 | } | ||
| 703 | |||
| 704 | test "@bytesToslice on a packed struct" { | ||
| 705 | const F = packed struct { | ||
| 706 | a: u8, | ||
| 707 | }; | ||
| 708 | |||
| 709 | var b = [1]u8{9}; | ||
| 710 | var f = @bytesToSlice(F, b); | ||
| 711 | assert(f[0].a == 9); | ||
| 712 | } | ||
| 713 | |||
| 714 | test "comptime pointer cast array and then slice" { | ||
| 715 | const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; | ||
| 716 | |||
| 717 | const ptrA: [*]const u8 = @ptrCast([*]const u8, &array); | ||
| 718 | const sliceA: []const u8 = ptrA[0..2]; | ||
| 719 | |||
| 720 | const ptrB: [*]const u8 = &array; | ||
| 721 | const sliceB: []const u8 = ptrB[0..2]; | ||
| 722 | |||
| 723 | assert(sliceA[1] == 2); | ||
| 724 | assert(sliceB[1] == 2); | ||
| 725 | } | ||
| 726 | |||
| 727 | test "slice bounds in comptime concatenation" { | ||
| 728 | const bs = comptime blk: { | ||
| 729 | const b = c"11"; | ||
| 730 | break :blk b[0..1]; | ||
| 731 | }; | ||
| 732 | const str = "" ++ bs; | ||
| 733 | assert(str.len == 1); | ||
| 734 | assert(std.mem.eql(u8, str, "1")); | ||
| 735 | |||
| 736 | const str2 = bs ++ ""; | ||
| 737 | assert(str2.len == 1); | ||
| 738 | assert(std.mem.eql(u8, str2, "1")); | ||
| 739 | } | ||
| 740 | |||
| 741 | test "comptime bitwise operators" { | ||
| 742 | comptime { | ||
| 743 | assert(3 & 1 == 1); | ||
| 744 | assert(3 & -1 == 3); | ||
| 745 | assert(-3 & -1 == -3); | ||
| 746 | assert(3 | -1 == -1); | ||
| 747 | assert(-3 | -1 == -1); | ||
| 748 | assert(3 ^ -1 == -4); | ||
| 749 | assert(-3 ^ -1 == 2); | ||
| 750 | assert(~i8(-1) == 0); | ||
| 751 | assert(~i128(-1) == 0); | ||
| 752 | assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611); | ||
| 753 | assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); | ||
| 754 | assert(~u128(0) == 0xffffffffffffffffffffffffffffffff); | ||
| 755 | } | ||
| 756 | } | ||
| 757 | |||
| 758 | test "*align(1) u16 is the same as *align(1:0:2) u16" { | ||
| 759 | comptime { | ||
| 760 | assert(*align(1:0:2) u16 == *align(1) u16); | ||
| 761 | // TODO add parsing support for this syntax | ||
| 762 | //assert(*align(:0:2) u16 == *u16); | ||
| 763 | } | ||
| 764 | } | ||
| 765 | |||
| 766 | test "array concatenation forces comptime" { | ||
| 767 | var a = oneItem(3) ++ oneItem(4); | ||
| 768 | assert(std.mem.eql(i32, a, []i32{3, 4})); | ||
| 769 | } | ||
| 770 | |||
| 771 | test "array multiplication forces comptime" { | ||
| 772 | var a = oneItem(3) ** scalar(2); | ||
| 773 | assert(std.mem.eql(i32, a, []i32{3, 3})); | ||
| 774 | } | ||
| 775 | |||
| 776 | fn oneItem(x: i32) [1]i32 { | ||
| 777 | return []i32{x}; | ||
| 778 | } | ||
| 779 | |||
| 780 | fn scalar(x: u32) u32 { | ||
| 781 | return x; | ||
| 782 | } | ||
test/cases/field_parent_ptr.zig deleted-41| ... | @@ -1,41 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "@fieldParentPtr non-first field" { | ||
| 4 | testParentFieldPtr(&foo.c); | ||
| 5 | comptime testParentFieldPtr(&foo.c); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "@fieldParentPtr first field" { | ||
| 9 | testParentFieldPtrFirst(&foo.a); | ||
| 10 | comptime testParentFieldPtrFirst(&foo.a); | ||
| 11 | } | ||
| 12 | |||
| 13 | const Foo = struct { | ||
| 14 | a: bool, | ||
| 15 | b: f32, | ||
| 16 | c: i32, | ||
| 17 | d: i32, | ||
| 18 | }; | ||
| 19 | |||
| 20 | const foo = Foo{ | ||
| 21 | .a = true, | ||
| 22 | .b = 0.123, | ||
| 23 | .c = 1234, | ||
| 24 | .d = -10, | ||
| 25 | }; | ||
| 26 | |||
| 27 | fn testParentFieldPtr(c: *const i32) void { | ||
| 28 | assert(c == &foo.c); | ||
| 29 | |||
| 30 | const base = @fieldParentPtr(Foo, "c", c); | ||
| 31 | assert(base == &foo); | ||
| 32 | assert(&base.c == c); | ||
| 33 | } | ||
| 34 | |||
| 35 | fn testParentFieldPtrFirst(a: *const bool) void { | ||
| 36 | assert(a == &foo.a); | ||
| 37 | |||
| 38 | const base = @fieldParentPtr(Foo, "a", a); | ||
| 39 | assert(base == &foo); | ||
| 40 | assert(&base.a == a); | ||
| 41 | } | ||
test/cases/fn.zig deleted-207| ... | @@ -1,207 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "params" { | ||
| 4 | assert(testParamsAdd(22, 11) == 33); | ||
| 5 | } | ||
| 6 | fn testParamsAdd(a: i32, b: i32) i32 { | ||
| 7 | return a + b; | ||
| 8 | } | ||
| 9 | |||
| 10 | test "local variables" { | ||
| 11 | testLocVars(2); | ||
| 12 | } | ||
| 13 | fn testLocVars(b: i32) void { | ||
| 14 | const a: i32 = 1; | ||
| 15 | if (a + b != 3) unreachable; | ||
| 16 | } | ||
| 17 | |||
| 18 | test "void parameters" { | ||
| 19 | voidFun(1, void{}, 2, {}); | ||
| 20 | } | ||
| 21 | fn voidFun(a: i32, b: void, c: i32, d: void) void { | ||
| 22 | const v = b; | ||
| 23 | const vv: void = if (a == 1) v else {}; | ||
| 24 | assert(a + c == 3); | ||
| 25 | return vv; | ||
| 26 | } | ||
| 27 | |||
| 28 | test "mutable local variables" { | ||
| 29 | var zero: i32 = 0; | ||
| 30 | assert(zero == 0); | ||
| 31 | |||
| 32 | var i = i32(0); | ||
| 33 | while (i != 3) { | ||
| 34 | i += 1; | ||
| 35 | } | ||
| 36 | assert(i == 3); | ||
| 37 | } | ||
| 38 | |||
| 39 | test "separate block scopes" { | ||
| 40 | { | ||
| 41 | const no_conflict: i32 = 5; | ||
| 42 | assert(no_conflict == 5); | ||
| 43 | } | ||
| 44 | |||
| 45 | const c = x: { | ||
| 46 | const no_conflict = i32(10); | ||
| 47 | break :x no_conflict; | ||
| 48 | }; | ||
| 49 | assert(c == 10); | ||
| 50 | } | ||
| 51 | |||
| 52 | test "call function with empty string" { | ||
| 53 | acceptsString(""); | ||
| 54 | } | ||
| 55 | |||
| 56 | fn acceptsString(foo: []u8) void {} | ||
| 57 | |||
| 58 | fn @"weird function name"() i32 { | ||
| 59 | return 1234; | ||
| 60 | } | ||
| 61 | test "weird function name" { | ||
| 62 | assert(@"weird function name"() == 1234); | ||
| 63 | } | ||
| 64 | |||
| 65 | test "implicit cast function unreachable return" { | ||
| 66 | wantsFnWithVoid(fnWithUnreachable); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn wantsFnWithVoid(f: fn () void) void {} | ||
| 70 | |||
| 71 | fn fnWithUnreachable() noreturn { | ||
| 72 | unreachable; | ||
| 73 | } | ||
| 74 | |||
| 75 | test "function pointers" { | ||
| 76 | const fns = []@typeOf(fn1){ | ||
| 77 | fn1, | ||
| 78 | fn2, | ||
| 79 | fn3, | ||
| 80 | fn4, | ||
| 81 | }; | ||
| 82 | for (fns) |f, i| { | ||
| 83 | assert(f() == @intCast(u32, i) + 5); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | fn fn1() u32 { | ||
| 87 | return 5; | ||
| 88 | } | ||
| 89 | fn fn2() u32 { | ||
| 90 | return 6; | ||
| 91 | } | ||
| 92 | fn fn3() u32 { | ||
| 93 | return 7; | ||
| 94 | } | ||
| 95 | fn fn4() u32 { | ||
| 96 | return 8; | ||
| 97 | } | ||
| 98 | |||
| 99 | test "inline function call" { | ||
| 100 | assert(@inlineCall(add, 3, 9) == 12); | ||
| 101 | } | ||
| 102 | |||
| 103 | fn add(a: i32, b: i32) i32 { | ||
| 104 | return a + b; | ||
| 105 | } | ||
| 106 | |||
| 107 | test "number literal as an argument" { | ||
| 108 | numberLiteralArg(3); | ||
| 109 | comptime numberLiteralArg(3); | ||
| 110 | } | ||
| 111 | |||
| 112 | fn numberLiteralArg(a: var) void { | ||
| 113 | assert(a == 3); | ||
| 114 | } | ||
| 115 | |||
| 116 | test "assign inline fn to const variable" { | ||
| 117 | const a = inlineFn; | ||
| 118 | a(); | ||
| 119 | } | ||
| 120 | |||
| 121 | inline fn inlineFn() void {} | ||
| 122 | |||
| 123 | test "pass by non-copying value" { | ||
| 124 | assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); | ||
| 125 | } | ||
| 126 | |||
| 127 | const Point = struct { | ||
| 128 | x: i32, | ||
| 129 | y: i32, | ||
| 130 | }; | ||
| 131 | |||
| 132 | fn addPointCoords(pt: Point) i32 { | ||
| 133 | return pt.x + pt.y; | ||
| 134 | } | ||
| 135 | |||
| 136 | test "pass by non-copying value through var arg" { | ||
| 137 | assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); | ||
| 138 | } | ||
| 139 | |||
| 140 | fn addPointCoordsVar(pt: var) i32 { | ||
| 141 | comptime assert(@typeOf(pt) == Point); | ||
| 142 | return pt.x + pt.y; | ||
| 143 | } | ||
| 144 | |||
| 145 | test "pass by non-copying value as method" { | ||
| 146 | var pt = Point2{ .x = 1, .y = 2 }; | ||
| 147 | assert(pt.addPointCoords() == 3); | ||
| 148 | } | ||
| 149 | |||
| 150 | const Point2 = struct { | ||
| 151 | x: i32, | ||
| 152 | y: i32, | ||
| 153 | |||
| 154 | fn addPointCoords(self: Point2) i32 { | ||
| 155 | return self.x + self.y; | ||
| 156 | } | ||
| 157 | }; | ||
| 158 | |||
| 159 | test "pass by non-copying value as method, which is generic" { | ||
| 160 | var pt = Point3{ .x = 1, .y = 2 }; | ||
| 161 | assert(pt.addPointCoords(i32) == 3); | ||
| 162 | } | ||
| 163 | |||
| 164 | const Point3 = struct { | ||
| 165 | x: i32, | ||
| 166 | y: i32, | ||
| 167 | |||
| 168 | fn addPointCoords(self: Point3, comptime T: type) i32 { | ||
| 169 | return self.x + self.y; | ||
| 170 | } | ||
| 171 | }; | ||
| 172 | |||
| 173 | test "pass by non-copying value as method, at comptime" { | ||
| 174 | comptime { | ||
| 175 | var pt = Point2{ .x = 1, .y = 2 }; | ||
| 176 | assert(pt.addPointCoords() == 3); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | fn outer(y: u32) fn (u32) u32 { | ||
| 181 | const Y = @typeOf(y); | ||
| 182 | const st = struct { | ||
| 183 | fn get(z: u32) u32 { | ||
| 184 | return z + @sizeOf(Y); | ||
| 185 | } | ||
| 186 | }; | ||
| 187 | return st.get; | ||
| 188 | } | ||
| 189 | |||
| 190 | test "return inner function which references comptime variable of outer function" { | ||
| 191 | var func = outer(10); | ||
| 192 | assert(func(3) == 7); | ||
| 193 | } | ||
| 194 | |||
| 195 | test "extern struct with stdcallcc fn pointer" { | ||
| 196 | const S = extern struct { | ||
| 197 | ptr: stdcallcc fn () i32, | ||
| 198 | |||
| 199 | stdcallcc fn foo() i32 { | ||
| 200 | return 1234; | ||
| 201 | } | ||
| 202 | }; | ||
| 203 | |||
| 204 | var s: S = undefined; | ||
| 205 | s.ptr = S.foo; | ||
| 206 | assert(s.ptr() == 1234); | ||
| 207 | } | ||
test/cases/fn_in_struct_in_comptime.zig deleted-17| ... | @@ -1,17 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | fn get_foo() fn (*u8) usize { | ||
| 4 | comptime { | ||
| 5 | return struct { | ||
| 6 | fn func(ptr: *u8) usize { | ||
| 7 | var u = @ptrToInt(ptr); | ||
| 8 | return u; | ||
| 9 | } | ||
| 10 | }.func; | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | test "define a function in an anonymous struct in comptime" { | ||
| 15 | const foo = get_foo(); | ||
| 16 | assert(foo(@intToPtr(*u8, 12345)) == 12345); | ||
| 17 | } | ||
test/cases/for.zig deleted-106| ... | @@ -1,106 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | test "continue in for loop" { | ||
| 6 | const array = []i32{ | ||
| 7 | 1, | ||
| 8 | 2, | ||
| 9 | 3, | ||
| 10 | 4, | ||
| 11 | 5, | ||
| 12 | }; | ||
| 13 | var sum: i32 = 0; | ||
| 14 | for (array) |x| { | ||
| 15 | sum += x; | ||
| 16 | if (x < 3) { | ||
| 17 | continue; | ||
| 18 | } | ||
| 19 | break; | ||
| 20 | } | ||
| 21 | if (sum != 6) unreachable; | ||
| 22 | } | ||
| 23 | |||
| 24 | test "for loop with pointer elem var" { | ||
| 25 | const source = "abcdefg"; | ||
| 26 | var target: [source.len]u8 = undefined; | ||
| 27 | mem.copy(u8, target[0..], source); | ||
| 28 | mangleString(target[0..]); | ||
| 29 | assert(mem.eql(u8, target, "bcdefgh")); | ||
| 30 | } | ||
| 31 | fn mangleString(s: []u8) void { | ||
| 32 | for (s) |*c| { | ||
| 33 | c.* += 1; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | test "basic for loop" { | ||
| 38 | const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; | ||
| 39 | |||
| 40 | var buffer: [expected_result.len]u8 = undefined; | ||
| 41 | var buf_index: usize = 0; | ||
| 42 | |||
| 43 | const array = []u8{ 9, 8, 7, 6 }; | ||
| 44 | for (array) |item| { | ||
| 45 | buffer[buf_index] = item; | ||
| 46 | buf_index += 1; | ||
| 47 | } | ||
| 48 | for (array) |item, index| { | ||
| 49 | buffer[buf_index] = @intCast(u8, index); | ||
| 50 | buf_index += 1; | ||
| 51 | } | ||
| 52 | const array_ptr = &array; | ||
| 53 | for (array_ptr) |item| { | ||
| 54 | buffer[buf_index] = item; | ||
| 55 | buf_index += 1; | ||
| 56 | } | ||
| 57 | for (array_ptr) |item, index| { | ||
| 58 | buffer[buf_index] = @intCast(u8, index); | ||
| 59 | buf_index += 1; | ||
| 60 | } | ||
| 61 | const unknown_size: []const u8 = array; | ||
| 62 | for (unknown_size) |item| { | ||
| 63 | buffer[buf_index] = item; | ||
| 64 | buf_index += 1; | ||
| 65 | } | ||
| 66 | for (unknown_size) |item, index| { | ||
| 67 | buffer[buf_index] = @intCast(u8, index); | ||
| 68 | buf_index += 1; | ||
| 69 | } | ||
| 70 | |||
| 71 | assert(mem.eql(u8, buffer[0..buf_index], expected_result)); | ||
| 72 | } | ||
| 73 | |||
| 74 | test "break from outer for loop" { | ||
| 75 | testBreakOuter(); | ||
| 76 | comptime testBreakOuter(); | ||
| 77 | } | ||
| 78 | |||
| 79 | fn testBreakOuter() void { | ||
| 80 | var array = "aoeu"; | ||
| 81 | var count: usize = 0; | ||
| 82 | outer: for (array) |_| { | ||
| 83 | for (array) |_| { | ||
| 84 | count += 1; | ||
| 85 | break :outer; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | assert(count == 1); | ||
| 89 | } | ||
| 90 | |||
| 91 | test "continue outer for loop" { | ||
| 92 | testContinueOuter(); | ||
| 93 | comptime testContinueOuter(); | ||
| 94 | } | ||
| 95 | |||
| 96 | fn testContinueOuter() void { | ||
| 97 | var array = "aoeu"; | ||
| 98 | var counter: usize = 0; | ||
| 99 | outer: for (array) |_| { | ||
| 100 | for (array) |_| { | ||
| 101 | counter += 1; | ||
| 102 | continue :outer; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | assert(counter == array.len); | ||
| 106 | } | ||
test/cases/generics.zig deleted-151| ... | @@ -1,151 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "simple generic fn" { | ||
| 4 | assert(max(i32, 3, -1) == 3); | ||
| 5 | assert(max(f32, 0.123, 0.456) == 0.456); | ||
| 6 | assert(add(2, 3) == 5); | ||
| 7 | } | ||
| 8 | |||
| 9 | fn max(comptime T: type, a: T, b: T) T { | ||
| 10 | return if (a > b) a else b; | ||
| 11 | } | ||
| 12 | |||
| 13 | fn add(comptime a: i32, b: i32) i32 { | ||
| 14 | return (comptime a) + b; | ||
| 15 | } | ||
| 16 | |||
| 17 | const the_max = max(u32, 1234, 5678); | ||
| 18 | test "compile time generic eval" { | ||
| 19 | assert(the_max == 5678); | ||
| 20 | } | ||
| 21 | |||
| 22 | fn gimmeTheBigOne(a: u32, b: u32) u32 { | ||
| 23 | return max(u32, a, b); | ||
| 24 | } | ||
| 25 | |||
| 26 | fn shouldCallSameInstance(a: u32, b: u32) u32 { | ||
| 27 | return max(u32, a, b); | ||
| 28 | } | ||
| 29 | |||
| 30 | fn sameButWithFloats(a: f64, b: f64) f64 { | ||
| 31 | return max(f64, a, b); | ||
| 32 | } | ||
| 33 | |||
| 34 | test "fn with comptime args" { | ||
| 35 | assert(gimmeTheBigOne(1234, 5678) == 5678); | ||
| 36 | assert(shouldCallSameInstance(34, 12) == 34); | ||
| 37 | assert(sameButWithFloats(0.43, 0.49) == 0.49); | ||
| 38 | } | ||
| 39 | |||
| 40 | test "var params" { | ||
| 41 | assert(max_i32(12, 34) == 34); | ||
| 42 | assert(max_f64(1.2, 3.4) == 3.4); | ||
| 43 | } | ||
| 44 | |||
| 45 | comptime { | ||
| 46 | assert(max_i32(12, 34) == 34); | ||
| 47 | assert(max_f64(1.2, 3.4) == 3.4); | ||
| 48 | } | ||
| 49 | |||
| 50 | fn max_var(a: var, b: var) @typeOf(a + b) { | ||
| 51 | return if (a > b) a else b; | ||
| 52 | } | ||
| 53 | |||
| 54 | fn max_i32(a: i32, b: i32) i32 { | ||
| 55 | return max_var(a, b); | ||
| 56 | } | ||
| 57 | |||
| 58 | fn max_f64(a: f64, b: f64) f64 { | ||
| 59 | return max_var(a, b); | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn List(comptime T: type) type { | ||
| 63 | return SmallList(T, 8); | ||
| 64 | } | ||
| 65 | |||
| 66 | pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { | ||
| 67 | return struct { | ||
| 68 | items: []T, | ||
| 69 | length: usize, | ||
| 70 | prealloc_items: [STATIC_SIZE]T, | ||
| 71 | }; | ||
| 72 | } | ||
| 73 | |||
| 74 | test "function with return type type" { | ||
| 75 | var list: List(i32) = undefined; | ||
| 76 | var list2: List(i32) = undefined; | ||
| 77 | list.length = 10; | ||
| 78 | list2.length = 10; | ||
| 79 | assert(list.prealloc_items.len == 8); | ||
| 80 | assert(list2.prealloc_items.len == 8); | ||
| 81 | } | ||
| 82 | |||
| 83 | test "generic struct" { | ||
| 84 | var a1 = GenNode(i32){ | ||
| 85 | .value = 13, | ||
| 86 | .next = null, | ||
| 87 | }; | ||
| 88 | var b1 = GenNode(bool){ | ||
| 89 | .value = true, | ||
| 90 | .next = null, | ||
| 91 | }; | ||
| 92 | assert(a1.value == 13); | ||
| 93 | assert(a1.value == a1.getVal()); | ||
| 94 | assert(b1.getVal()); | ||
| 95 | } | ||
| 96 | fn GenNode(comptime T: type) type { | ||
| 97 | return struct { | ||
| 98 | value: T, | ||
| 99 | next: ?*GenNode(T), | ||
| 100 | fn getVal(n: *const GenNode(T)) T { | ||
| 101 | return n.value; | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | test "const decls in struct" { | ||
| 107 | assert(GenericDataThing(3).count_plus_one == 4); | ||
| 108 | } | ||
| 109 | fn GenericDataThing(comptime count: isize) type { | ||
| 110 | return struct { | ||
| 111 | const count_plus_one = count + 1; | ||
| 112 | }; | ||
| 113 | } | ||
| 114 | |||
| 115 | test "use generic param in generic param" { | ||
| 116 | assert(aGenericFn(i32, 3, 4) == 7); | ||
| 117 | } | ||
| 118 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { | ||
| 119 | return a + b; | ||
| 120 | } | ||
| 121 | |||
| 122 | test "generic fn with implicit cast" { | ||
| 123 | assert(getFirstByte(u8, []u8{13}) == 13); | ||
| 124 | assert(getFirstByte(u16, []u16{ | ||
| 125 | 0, | ||
| 126 | 13, | ||
| 127 | }) == 0); | ||
| 128 | } | ||
| 129 | fn getByte(ptr: ?*const u8) u8 { | ||
| 130 | return ptr.?.*; | ||
| 131 | } | ||
| 132 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | ||
| 133 | return getByte(@ptrCast(*const u8, &mem[0])); | ||
| 134 | } | ||
| 135 | |||
| 136 | const foos = []fn (var) bool{ | ||
| 137 | foo1, | ||
| 138 | foo2, | ||
| 139 | }; | ||
| 140 | |||
| 141 | fn foo1(arg: var) bool { | ||
| 142 | return arg; | ||
| 143 | } | ||
| 144 | fn foo2(arg: var) bool { | ||
| 145 | return !arg; | ||
| 146 | } | ||
| 147 | |||
| 148 | test "array of generic fns" { | ||
| 149 | assert(foos[0](true)); | ||
| 150 | assert(!foos[1](true)); | ||
| 151 | } | ||
test/cases/if.zig deleted-37| ... | @@ -1,37 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "if statements" { | ||
| 4 | shouldBeEqual(1, 1); | ||
| 5 | firstEqlThird(2, 1, 2); | ||
| 6 | } | ||
| 7 | fn shouldBeEqual(a: i32, b: i32) void { | ||
| 8 | if (a != b) { | ||
| 9 | unreachable; | ||
| 10 | } else { | ||
| 11 | return; | ||
| 12 | } | ||
| 13 | } | ||
| 14 | fn firstEqlThird(a: i32, b: i32, c: i32) void { | ||
| 15 | if (a == b) { | ||
| 16 | unreachable; | ||
| 17 | } else if (b == c) { | ||
| 18 | unreachable; | ||
| 19 | } else if (a == c) { | ||
| 20 | return; | ||
| 21 | } else { | ||
| 22 | unreachable; | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | test "else if expression" { | ||
| 27 | assert(elseIfExpressionF(1) == 1); | ||
| 28 | } | ||
| 29 | fn elseIfExpressionF(c: u8) u8 { | ||
| 30 | if (c == 0) { | ||
| 31 | return 0; | ||
| 32 | } else if (c == 1) { | ||
| 33 | return 1; | ||
| 34 | } else { | ||
| 35 | return u8(2); | ||
| 36 | } | ||
| 37 | } | ||
test/cases/import.zig deleted-10| ... | @@ -1,10 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const a_namespace = @import("import/a_namespace.zig"); | ||
| 3 | |||
| 4 | test "call fn via namespace lookup" { | ||
| 5 | assert(a_namespace.foo() == 1234); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "importing the same thing gives the same import" { | ||
| 9 | assert(@import("std") == @import("std")); | ||
| 10 | } | ||
test/cases/import/a_namespace.zig deleted-3| ... | @@ -1,3 +0,0 @@ | ||
| 1 | pub fn foo() i32 { | ||
| 2 | return 1234; | ||
| 3 | } | ||
test/cases/incomplete_struct_param_tld.zig deleted-30| ... | @@ -1,30 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const A = struct { | ||
| 4 | b: B, | ||
| 5 | }; | ||
| 6 | |||
| 7 | const B = struct { | ||
| 8 | c: C, | ||
| 9 | }; | ||
| 10 | |||
| 11 | const C = struct { | ||
| 12 | x: i32, | ||
| 13 | |||
| 14 | fn d(c: *const C) i32 { | ||
| 15 | return c.x; | ||
| 16 | } | ||
| 17 | }; | ||
| 18 | |||
| 19 | fn foo(a: A) i32 { | ||
| 20 | return a.b.c.d(); | ||
| 21 | } | ||
| 22 | |||
| 23 | test "incomplete struct param top level declaration" { | ||
| 24 | const a = A{ | ||
| 25 | .b = B{ | ||
| 26 | .c = C{ .x = 13 }, | ||
| 27 | }, | ||
| 28 | }; | ||
| 29 | assert(foo(a) == 13); | ||
| 30 | } | ||
test/cases/ir_block_deps.zig deleted-21| ... | @@ -1,21 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | fn foo(id: u64) !i32 { | ||
| 4 | return switch (id) { | ||
| 5 | 1 => getErrInt(), | ||
| 6 | 2 => { | ||
| 7 | const size = try getErrInt(); | ||
| 8 | return try getErrInt(); | ||
| 9 | }, | ||
| 10 | else => error.ItBroke, | ||
| 11 | }; | ||
| 12 | } | ||
| 13 | |||
| 14 | fn getErrInt() anyerror!i32 { | ||
| 15 | return 0; | ||
| 16 | } | ||
| 17 | |||
| 18 | test "ir block deps" { | ||
| 19 | assert((foo(1) catch unreachable) == 0); | ||
| 20 | assert((foo(2) catch unreachable) == 0); | ||
| 21 | } | ||
test/cases/math.zig deleted-500| ... | @@ -1,500 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const maxInt = std.math.maxInt; | ||
| 4 | const minInt = std.math.minInt; | ||
| 5 | |||
| 6 | test "division" { | ||
| 7 | testDivision(); | ||
| 8 | comptime testDivision(); | ||
| 9 | } | ||
| 10 | fn testDivision() void { | ||
| 11 | assert(div(u32, 13, 3) == 4); | ||
| 12 | assert(div(f16, 1.0, 2.0) == 0.5); | ||
| 13 | assert(div(f32, 1.0, 2.0) == 0.5); | ||
| 14 | |||
| 15 | assert(divExact(u32, 55, 11) == 5); | ||
| 16 | assert(divExact(i32, -55, 11) == -5); | ||
| 17 | assert(divExact(f16, 55.0, 11.0) == 5.0); | ||
| 18 | assert(divExact(f16, -55.0, 11.0) == -5.0); | ||
| 19 | assert(divExact(f32, 55.0, 11.0) == 5.0); | ||
| 20 | assert(divExact(f32, -55.0, 11.0) == -5.0); | ||
| 21 | |||
| 22 | assert(divFloor(i32, 5, 3) == 1); | ||
| 23 | assert(divFloor(i32, -5, 3) == -2); | ||
| 24 | assert(divFloor(f16, 5.0, 3.0) == 1.0); | ||
| 25 | assert(divFloor(f16, -5.0, 3.0) == -2.0); | ||
| 26 | assert(divFloor(f32, 5.0, 3.0) == 1.0); | ||
| 27 | assert(divFloor(f32, -5.0, 3.0) == -2.0); | ||
| 28 | assert(divFloor(i32, -0x80000000, -2) == 0x40000000); | ||
| 29 | assert(divFloor(i32, 0, -0x80000000) == 0); | ||
| 30 | assert(divFloor(i32, -0x40000001, 0x40000000) == -2); | ||
| 31 | assert(divFloor(i32, -0x80000000, 1) == -0x80000000); | ||
| 32 | |||
| 33 | assert(divTrunc(i32, 5, 3) == 1); | ||
| 34 | assert(divTrunc(i32, -5, 3) == -1); | ||
| 35 | assert(divTrunc(f16, 5.0, 3.0) == 1.0); | ||
| 36 | assert(divTrunc(f16, -5.0, 3.0) == -1.0); | ||
| 37 | assert(divTrunc(f32, 5.0, 3.0) == 1.0); | ||
| 38 | assert(divTrunc(f32, -5.0, 3.0) == -1.0); | ||
| 39 | assert(divTrunc(f64, 5.0, 3.0) == 1.0); | ||
| 40 | assert(divTrunc(f64, -5.0, 3.0) == -1.0); | ||
| 41 | |||
| 42 | comptime { | ||
| 43 | assert( | ||
| 44 | 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, | ||
| 45 | ); | ||
| 46 | assert( | ||
| 47 | @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600, | ||
| 48 | ); | ||
| 49 | assert( | ||
| 50 | 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2, | ||
| 51 | ); | ||
| 52 | assert( | ||
| 53 | @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2, | ||
| 54 | ); | ||
| 55 | assert( | ||
| 56 | @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2, | ||
| 57 | ); | ||
| 58 | assert( | ||
| 59 | @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2, | ||
| 60 | ); | ||
| 61 | assert( | ||
| 62 | 4126227191251978491697987544882340798050766755606969681711 % 10 == 1, | ||
| 63 | ); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | fn div(comptime T: type, a: T, b: T) T { | ||
| 67 | return a / b; | ||
| 68 | } | ||
| 69 | fn divExact(comptime T: type, a: T, b: T) T { | ||
| 70 | return @divExact(a, b); | ||
| 71 | } | ||
| 72 | fn divFloor(comptime T: type, a: T, b: T) T { | ||
| 73 | return @divFloor(a, b); | ||
| 74 | } | ||
| 75 | fn divTrunc(comptime T: type, a: T, b: T) T { | ||
| 76 | return @divTrunc(a, b); | ||
| 77 | } | ||
| 78 | |||
| 79 | test "@addWithOverflow" { | ||
| 80 | var result: u8 = undefined; | ||
| 81 | assert(@addWithOverflow(u8, 250, 100, &result)); | ||
| 82 | assert(!@addWithOverflow(u8, 100, 150, &result)); | ||
| 83 | assert(result == 250); | ||
| 84 | } | ||
| 85 | |||
| 86 | // TODO test mulWithOverflow | ||
| 87 | // TODO test subWithOverflow | ||
| 88 | |||
| 89 | test "@shlWithOverflow" { | ||
| 90 | var result: u16 = undefined; | ||
| 91 | assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); | ||
| 92 | assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); | ||
| 93 | assert(result == 0b1011111111111100); | ||
| 94 | } | ||
| 95 | |||
| 96 | test "@clz" { | ||
| 97 | testClz(); | ||
| 98 | comptime testClz(); | ||
| 99 | } | ||
| 100 | |||
| 101 | fn testClz() void { | ||
| 102 | assert(clz(u8(0b00001010)) == 4); | ||
| 103 | assert(clz(u8(0b10001010)) == 0); | ||
| 104 | assert(clz(u8(0b00000000)) == 8); | ||
| 105 | assert(clz(u128(0xffffffffffffffff)) == 64); | ||
| 106 | assert(clz(u128(0x10000000000000000)) == 63); | ||
| 107 | } | ||
| 108 | |||
| 109 | fn clz(x: var) usize { | ||
| 110 | return @clz(x); | ||
| 111 | } | ||
| 112 | |||
| 113 | test "@ctz" { | ||
| 114 | testCtz(); | ||
| 115 | comptime testCtz(); | ||
| 116 | } | ||
| 117 | |||
| 118 | fn testCtz() void { | ||
| 119 | assert(ctz(u8(0b10100000)) == 5); | ||
| 120 | assert(ctz(u8(0b10001010)) == 1); | ||
| 121 | assert(ctz(u8(0b00000000)) == 8); | ||
| 122 | } | ||
| 123 | |||
| 124 | fn ctz(x: var) usize { | ||
| 125 | return @ctz(x); | ||
| 126 | } | ||
| 127 | |||
| 128 | test "assignment operators" { | ||
| 129 | var i: u32 = 0; | ||
| 130 | i += 5; | ||
| 131 | assert(i == 5); | ||
| 132 | i -= 2; | ||
| 133 | assert(i == 3); | ||
| 134 | i *= 20; | ||
| 135 | assert(i == 60); | ||
| 136 | i /= 3; | ||
| 137 | assert(i == 20); | ||
| 138 | i %= 11; | ||
| 139 | assert(i == 9); | ||
| 140 | i <<= 1; | ||
| 141 | assert(i == 18); | ||
| 142 | i >>= 2; | ||
| 143 | assert(i == 4); | ||
| 144 | i = 6; | ||
| 145 | i &= 5; | ||
| 146 | assert(i == 4); | ||
| 147 | i ^= 6; | ||
| 148 | assert(i == 2); | ||
| 149 | i = 6; | ||
| 150 | i |= 3; | ||
| 151 | assert(i == 7); | ||
| 152 | } | ||
| 153 | |||
| 154 | test "three expr in a row" { | ||
| 155 | testThreeExprInARow(false, true); | ||
| 156 | comptime testThreeExprInARow(false, true); | ||
| 157 | } | ||
| 158 | fn testThreeExprInARow(f: bool, t: bool) void { | ||
| 159 | assertFalse(f or f or f); | ||
| 160 | assertFalse(t and t and f); | ||
| 161 | assertFalse(1 | 2 | 4 != 7); | ||
| 162 | assertFalse(3 ^ 6 ^ 8 != 13); | ||
| 163 | assertFalse(7 & 14 & 28 != 4); | ||
| 164 | assertFalse(9 << 1 << 2 != 9 << 3); | ||
| 165 | assertFalse(90 >> 1 >> 2 != 90 >> 3); | ||
| 166 | assertFalse(100 - 1 + 1000 != 1099); | ||
| 167 | assertFalse(5 * 4 / 2 % 3 != 1); | ||
| 168 | assertFalse(i32(i32(5)) != 5); | ||
| 169 | assertFalse(!!false); | ||
| 170 | assertFalse(i32(7) != --(i32(7))); | ||
| 171 | } | ||
| 172 | fn assertFalse(b: bool) void { | ||
| 173 | assert(!b); | ||
| 174 | } | ||
| 175 | |||
| 176 | test "const number literal" { | ||
| 177 | const one = 1; | ||
| 178 | const eleven = ten + one; | ||
| 179 | |||
| 180 | assert(eleven == 11); | ||
| 181 | } | ||
| 182 | const ten = 10; | ||
| 183 | |||
| 184 | test "unsigned wrapping" { | ||
| 185 | testUnsignedWrappingEval(maxInt(u32)); | ||
| 186 | comptime testUnsignedWrappingEval(maxInt(u32)); | ||
| 187 | } | ||
| 188 | fn testUnsignedWrappingEval(x: u32) void { | ||
| 189 | const zero = x +% 1; | ||
| 190 | assert(zero == 0); | ||
| 191 | const orig = zero -% 1; | ||
| 192 | assert(orig == maxInt(u32)); | ||
| 193 | } | ||
| 194 | |||
| 195 | test "signed wrapping" { | ||
| 196 | testSignedWrappingEval(maxInt(i32)); | ||
| 197 | comptime testSignedWrappingEval(maxInt(i32)); | ||
| 198 | } | ||
| 199 | fn testSignedWrappingEval(x: i32) void { | ||
| 200 | const min_val = x +% 1; | ||
| 201 | assert(min_val == minInt(i32)); | ||
| 202 | const max_val = min_val -% 1; | ||
| 203 | assert(max_val == maxInt(i32)); | ||
| 204 | } | ||
| 205 | |||
| 206 | test "negation wrapping" { | ||
| 207 | testNegationWrappingEval(minInt(i16)); | ||
| 208 | comptime testNegationWrappingEval(minInt(i16)); | ||
| 209 | } | ||
| 210 | fn testNegationWrappingEval(x: i16) void { | ||
| 211 | assert(x == -32768); | ||
| 212 | const neg = -%x; | ||
| 213 | assert(neg == -32768); | ||
| 214 | } | ||
| 215 | |||
| 216 | test "unsigned 64-bit division" { | ||
| 217 | test_u64_div(); | ||
| 218 | comptime test_u64_div(); | ||
| 219 | } | ||
| 220 | fn test_u64_div() void { | ||
| 221 | const result = divWithResult(1152921504606846976, 34359738365); | ||
| 222 | assert(result.quotient == 33554432); | ||
| 223 | assert(result.remainder == 100663296); | ||
| 224 | } | ||
| 225 | fn divWithResult(a: u64, b: u64) DivResult { | ||
| 226 | return DivResult{ | ||
| 227 | .quotient = a / b, | ||
| 228 | .remainder = a % b, | ||
| 229 | }; | ||
| 230 | } | ||
| 231 | const DivResult = struct { | ||
| 232 | quotient: u64, | ||
| 233 | remainder: u64, | ||
| 234 | }; | ||
| 235 | |||
| 236 | test "binary not" { | ||
| 237 | assert(comptime x: { | ||
| 238 | break :x ~u16(0b1010101010101010) == 0b0101010101010101; | ||
| 239 | }); | ||
| 240 | assert(comptime x: { | ||
| 241 | break :x ~u64(2147483647) == 18446744071562067968; | ||
| 242 | }); | ||
| 243 | testBinaryNot(0b1010101010101010); | ||
| 244 | } | ||
| 245 | |||
| 246 | fn testBinaryNot(x: u16) void { | ||
| 247 | assert(~x == 0b0101010101010101); | ||
| 248 | } | ||
| 249 | |||
| 250 | test "small int addition" { | ||
| 251 | var x: @IntType(false, 2) = 0; | ||
| 252 | assert(x == 0); | ||
| 253 | |||
| 254 | x += 1; | ||
| 255 | assert(x == 1); | ||
| 256 | |||
| 257 | x += 1; | ||
| 258 | assert(x == 2); | ||
| 259 | |||
| 260 | x += 1; | ||
| 261 | assert(x == 3); | ||
| 262 | |||
| 263 | var result: @typeOf(x) = 3; | ||
| 264 | assert(@addWithOverflow(@typeOf(x), x, 1, &result)); | ||
| 265 | |||
| 266 | assert(result == 0); | ||
| 267 | } | ||
| 268 | |||
| 269 | test "float equality" { | ||
| 270 | const x: f64 = 0.012; | ||
| 271 | const y: f64 = x + 1.0; | ||
| 272 | |||
| 273 | testFloatEqualityImpl(x, y); | ||
| 274 | comptime testFloatEqualityImpl(x, y); | ||
| 275 | } | ||
| 276 | |||
| 277 | fn testFloatEqualityImpl(x: f64, y: f64) void { | ||
| 278 | const y2 = x + 1.0; | ||
| 279 | assert(y == y2); | ||
| 280 | } | ||
| 281 | |||
| 282 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | ||
| 283 | assert(5 / 3 == 1); | ||
| 284 | assert(-5 / -3 == 1); | ||
| 285 | assert(-6 / 3 == -2); | ||
| 286 | |||
| 287 | assert(5 % 3 == 2); | ||
| 288 | assert(-6 % 3 == 0); | ||
| 289 | } | ||
| 290 | |||
| 291 | test "hex float literal parsing" { | ||
| 292 | comptime assert(0x1.0 == 1.0); | ||
| 293 | } | ||
| 294 | |||
| 295 | test "quad hex float literal parsing in range" { | ||
| 296 | const a = 0x1.af23456789bbaaab347645365cdep+5; | ||
| 297 | const b = 0x1.dedafcff354b6ae9758763545432p-9; | ||
| 298 | const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534; | ||
| 299 | const d = 0x1.edcbff8ad76ab5bf46463233214fp-435; | ||
| 300 | } | ||
| 301 | |||
| 302 | test "quad hex float literal parsing accurate" { | ||
| 303 | const a: f128 = 0x1.1111222233334444555566667777p+0; | ||
| 304 | |||
| 305 | // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. | ||
| 306 | const expected: u128 = 0x3fff1111222233334444555566667777; | ||
| 307 | assert(@bitCast(u128, a) == expected); | ||
| 308 | } | ||
| 309 | |||
| 310 | test "hex float literal within range" { | ||
| 311 | const a = 0x1.0p16383; | ||
| 312 | const b = 0x0.1p16387; | ||
| 313 | const c = 0x1.0p-16382; | ||
| 314 | } | ||
| 315 | |||
| 316 | test "truncating shift left" { | ||
| 317 | testShlTrunc(maxInt(u16)); | ||
| 318 | comptime testShlTrunc(maxInt(u16)); | ||
| 319 | } | ||
| 320 | fn testShlTrunc(x: u16) void { | ||
| 321 | const shifted = x << 1; | ||
| 322 | assert(shifted == 65534); | ||
| 323 | } | ||
| 324 | |||
| 325 | test "truncating shift right" { | ||
| 326 | testShrTrunc(maxInt(u16)); | ||
| 327 | comptime testShrTrunc(maxInt(u16)); | ||
| 328 | } | ||
| 329 | fn testShrTrunc(x: u16) void { | ||
| 330 | const shifted = x >> 1; | ||
| 331 | assert(shifted == 32767); | ||
| 332 | } | ||
| 333 | |||
| 334 | test "exact shift left" { | ||
| 335 | testShlExact(0b00110101); | ||
| 336 | comptime testShlExact(0b00110101); | ||
| 337 | } | ||
| 338 | fn testShlExact(x: u8) void { | ||
| 339 | const shifted = @shlExact(x, 2); | ||
| 340 | assert(shifted == 0b11010100); | ||
| 341 | } | ||
| 342 | |||
| 343 | test "exact shift right" { | ||
| 344 | testShrExact(0b10110100); | ||
| 345 | comptime testShrExact(0b10110100); | ||
| 346 | } | ||
| 347 | fn testShrExact(x: u8) void { | ||
| 348 | const shifted = @shrExact(x, 2); | ||
| 349 | assert(shifted == 0b00101101); | ||
| 350 | } | ||
| 351 | |||
| 352 | test "comptime_int addition" { | ||
| 353 | comptime { | ||
| 354 | assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); | ||
| 355 | assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | test "comptime_int multiplication" { | ||
| 360 | comptime { | ||
| 361 | assert( | ||
| 362 | 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567, | ||
| 363 | ); | ||
| 364 | assert( | ||
| 365 | 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016, | ||
| 366 | ); | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 370 | test "comptime_int shifting" { | ||
| 371 | comptime { | ||
| 372 | assert((u128(1) << 127) == 0x80000000000000000000000000000000); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | test "comptime_int multi-limb shift and mask" { | ||
| 377 | comptime { | ||
| 378 | var a = 0xefffffffa0000001eeeeeeefaaaaaaab; | ||
| 379 | |||
| 380 | assert(u32(a & 0xffffffff) == 0xaaaaaaab); | ||
| 381 | a >>= 32; | ||
| 382 | assert(u32(a & 0xffffffff) == 0xeeeeeeef); | ||
| 383 | a >>= 32; | ||
| 384 | assert(u32(a & 0xffffffff) == 0xa0000001); | ||
| 385 | a >>= 32; | ||
| 386 | assert(u32(a & 0xffffffff) == 0xefffffff); | ||
| 387 | a >>= 32; | ||
| 388 | |||
| 389 | assert(a == 0); | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | test "comptime_int multi-limb partial shift right" { | ||
| 394 | comptime { | ||
| 395 | var a = 0x1ffffffffeeeeeeee; | ||
| 396 | a >>= 16; | ||
| 397 | assert(a == 0x1ffffffffeeee); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | test "xor" { | ||
| 402 | test_xor(); | ||
| 403 | comptime test_xor(); | ||
| 404 | } | ||
| 405 | |||
| 406 | fn test_xor() void { | ||
| 407 | assert(0xFF ^ 0x00 == 0xFF); | ||
| 408 | assert(0xF0 ^ 0x0F == 0xFF); | ||
| 409 | assert(0xFF ^ 0xF0 == 0x0F); | ||
| 410 | assert(0xFF ^ 0x0F == 0xF0); | ||
| 411 | assert(0xFF ^ 0xFF == 0x00); | ||
| 412 | } | ||
| 413 | |||
| 414 | test "comptime_int xor" { | ||
| 415 | comptime { | ||
| 416 | assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 417 | assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 418 | assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF); | ||
| 419 | assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000); | ||
| 420 | assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000); | ||
| 421 | assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 422 | assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF); | ||
| 423 | assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000); | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | test "f128" { | ||
| 428 | test_f128(); | ||
| 429 | comptime test_f128(); | ||
| 430 | } | ||
| 431 | |||
| 432 | fn make_f128(x: f128) f128 { | ||
| 433 | return x; | ||
| 434 | } | ||
| 435 | |||
| 436 | fn test_f128() void { | ||
| 437 | assert(@sizeOf(f128) == 16); | ||
| 438 | assert(make_f128(1.0) == 1.0); | ||
| 439 | assert(make_f128(1.0) != 1.1); | ||
| 440 | assert(make_f128(1.0) > 0.9); | ||
| 441 | assert(make_f128(1.0) >= 0.9); | ||
| 442 | assert(make_f128(1.0) >= 1.0); | ||
| 443 | should_not_be_zero(1.0); | ||
| 444 | } | ||
| 445 | |||
| 446 | fn should_not_be_zero(x: f128) void { | ||
| 447 | assert(x != 0.0); | ||
| 448 | } | ||
| 449 | |||
| 450 | test "comptime float rem int" { | ||
| 451 | comptime { | ||
| 452 | var x = f32(1) % 2; | ||
| 453 | assert(x == 1.0); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | test "remainder division" { | ||
| 458 | comptime remdiv(f16); | ||
| 459 | comptime remdiv(f32); | ||
| 460 | comptime remdiv(f64); | ||
| 461 | comptime remdiv(f128); | ||
| 462 | remdiv(f16); | ||
| 463 | remdiv(f64); | ||
| 464 | remdiv(f128); | ||
| 465 | } | ||
| 466 | |||
| 467 | fn remdiv(comptime T: type) void { | ||
| 468 | assert(T(1) == T(1) % T(2)); | ||
| 469 | assert(T(1) == T(7) % T(3)); | ||
| 470 | } | ||
| 471 | |||
| 472 | test "@sqrt" { | ||
| 473 | testSqrt(f64, 12.0); | ||
| 474 | comptime testSqrt(f64, 12.0); | ||
| 475 | testSqrt(f32, 13.0); | ||
| 476 | comptime testSqrt(f32, 13.0); | ||
| 477 | testSqrt(f16, 13.0); | ||
| 478 | comptime testSqrt(f16, 13.0); | ||
| 479 | |||
| 480 | const x = 14.0; | ||
| 481 | const y = x * x; | ||
| 482 | const z = @sqrt(@typeOf(y), y); | ||
| 483 | comptime assert(z == x); | ||
| 484 | } | ||
| 485 | |||
| 486 | fn testSqrt(comptime T: type, x: T) void { | ||
| 487 | assert(@sqrt(T, x * x) == x); | ||
| 488 | } | ||
| 489 | |||
| 490 | test "comptime_int param and return" { | ||
| 491 | const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); | ||
| 492 | assert(a == 137114567242441932203689521744947848950); | ||
| 493 | |||
| 494 | const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768); | ||
| 495 | assert(b == 985095453608931032642182098849559179469148836107390954364380); | ||
| 496 | } | ||
| 497 | |||
| 498 | fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int { | ||
| 499 | return a + b; | ||
| 500 | } | ||
test/cases/merge_error_sets.zig deleted-21| ... | @@ -1,21 +0,0 @@ | ||
| 1 | const A = error{ | ||
| 2 | FileNotFound, | ||
| 3 | NotDir, | ||
| 4 | }; | ||
| 5 | const B = error{OutOfMemory}; | ||
| 6 | |||
| 7 | const C = A || B; | ||
| 8 | |||
| 9 | fn foo() C!void { | ||
| 10 | return error.NotDir; | ||
| 11 | } | ||
| 12 | |||
| 13 | test "merge error sets" { | ||
| 14 | if (foo()) { | ||
| 15 | @panic("unexpected"); | ||
| 16 | } else |err| switch (err) { | ||
| 17 | error.OutOfMemory => @panic("unexpected"), | ||
| 18 | error.FileNotFound => @panic("unexpected"), | ||
| 19 | error.NotDir => {}, | ||
| 20 | } | ||
| 21 | } | ||
test/cases/misc.zig deleted-681| ... | @@ -1,681 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | const cstr = std.cstr; | ||
| 5 | const builtin = @import("builtin"); | ||
| 6 | const maxInt = std.math.maxInt; | ||
| 7 | |||
| 8 | // normal comment | ||
| 9 | |||
| 10 | /// this is a documentation comment | ||
| 11 | /// doc comment line 2 | ||
| 12 | fn emptyFunctionWithComments() void {} | ||
| 13 | |||
| 14 | test "empty function with comments" { | ||
| 15 | emptyFunctionWithComments(); | ||
| 16 | } | ||
| 17 | |||
| 18 | comptime { | ||
| 19 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); | ||
| 20 | } | ||
| 21 | |||
| 22 | extern fn disabledExternFn() void {} | ||
| 23 | |||
| 24 | test "call disabled extern fn" { | ||
| 25 | disabledExternFn(); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "@IntType builtin" { | ||
| 29 | assert(@IntType(true, 8) == i8); | ||
| 30 | assert(@IntType(true, 16) == i16); | ||
| 31 | assert(@IntType(true, 32) == i32); | ||
| 32 | assert(@IntType(true, 64) == i64); | ||
| 33 | |||
| 34 | assert(@IntType(false, 8) == u8); | ||
| 35 | assert(@IntType(false, 16) == u16); | ||
| 36 | assert(@IntType(false, 32) == u32); | ||
| 37 | assert(@IntType(false, 64) == u64); | ||
| 38 | |||
| 39 | assert(i8.bit_count == 8); | ||
| 40 | assert(i16.bit_count == 16); | ||
| 41 | assert(i32.bit_count == 32); | ||
| 42 | assert(i64.bit_count == 64); | ||
| 43 | |||
| 44 | assert(i8.is_signed); | ||
| 45 | assert(i16.is_signed); | ||
| 46 | assert(i32.is_signed); | ||
| 47 | assert(i64.is_signed); | ||
| 48 | assert(isize.is_signed); | ||
| 49 | |||
| 50 | assert(!u8.is_signed); | ||
| 51 | assert(!u16.is_signed); | ||
| 52 | assert(!u32.is_signed); | ||
| 53 | assert(!u64.is_signed); | ||
| 54 | assert(!usize.is_signed); | ||
| 55 | } | ||
| 56 | |||
| 57 | test "floating point primitive bit counts" { | ||
| 58 | assert(f16.bit_count == 16); | ||
| 59 | assert(f32.bit_count == 32); | ||
| 60 | assert(f64.bit_count == 64); | ||
| 61 | } | ||
| 62 | |||
| 63 | test "short circuit" { | ||
| 64 | testShortCircuit(false, true); | ||
| 65 | comptime testShortCircuit(false, true); | ||
| 66 | } | ||
| 67 | |||
| 68 | fn testShortCircuit(f: bool, t: bool) void { | ||
| 69 | var hit_1 = f; | ||
| 70 | var hit_2 = f; | ||
| 71 | var hit_3 = f; | ||
| 72 | var hit_4 = f; | ||
| 73 | |||
| 74 | if (t or x: { | ||
| 75 | assert(f); | ||
| 76 | break :x f; | ||
| 77 | }) { | ||
| 78 | hit_1 = t; | ||
| 79 | } | ||
| 80 | if (f or x: { | ||
| 81 | hit_2 = t; | ||
| 82 | break :x f; | ||
| 83 | }) { | ||
| 84 | assert(f); | ||
| 85 | } | ||
| 86 | |||
| 87 | if (t and x: { | ||
| 88 | hit_3 = t; | ||
| 89 | break :x f; | ||
| 90 | }) { | ||
| 91 | assert(f); | ||
| 92 | } | ||
| 93 | if (f and x: { | ||
| 94 | assert(f); | ||
| 95 | break :x f; | ||
| 96 | }) { | ||
| 97 | assert(f); | ||
| 98 | } else { | ||
| 99 | hit_4 = t; | ||
| 100 | } | ||
| 101 | assert(hit_1); | ||
| 102 | assert(hit_2); | ||
| 103 | assert(hit_3); | ||
| 104 | assert(hit_4); | ||
| 105 | } | ||
| 106 | |||
| 107 | test "truncate" { | ||
| 108 | assert(testTruncate(0x10fd) == 0xfd); | ||
| 109 | } | ||
| 110 | fn testTruncate(x: u32) u8 { | ||
| 111 | return @truncate(u8, x); | ||
| 112 | } | ||
| 113 | |||
| 114 | fn first4KeysOfHomeRow() []const u8 { | ||
| 115 | return "aoeu"; | ||
| 116 | } | ||
| 117 | |||
| 118 | test "return string from function" { | ||
| 119 | assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); | ||
| 120 | } | ||
| 121 | |||
| 122 | const g1: i32 = 1233 + 1; | ||
| 123 | var g2: i32 = 0; | ||
| 124 | |||
| 125 | test "global variables" { | ||
| 126 | assert(g2 == 0); | ||
| 127 | g2 = g1; | ||
| 128 | assert(g2 == 1234); | ||
| 129 | } | ||
| 130 | |||
| 131 | test "memcpy and memset intrinsics" { | ||
| 132 | var foo: [20]u8 = undefined; | ||
| 133 | var bar: [20]u8 = undefined; | ||
| 134 | |||
| 135 | @memset(foo[0..].ptr, 'A', foo.len); | ||
| 136 | @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); | ||
| 137 | |||
| 138 | if (bar[11] != 'A') unreachable; | ||
| 139 | } | ||
| 140 | |||
| 141 | test "builtin static eval" { | ||
| 142 | const x: i32 = comptime x: { | ||
| 143 | break :x 1 + 2 + 3; | ||
| 144 | }; | ||
| 145 | assert(x == comptime 6); | ||
| 146 | } | ||
| 147 | |||
| 148 | test "slicing" { | ||
| 149 | var array: [20]i32 = undefined; | ||
| 150 | |||
| 151 | array[5] = 1234; | ||
| 152 | |||
| 153 | var slice = array[5..10]; | ||
| 154 | |||
| 155 | if (slice.len != 5) unreachable; | ||
| 156 | |||
| 157 | const ptr = &slice[0]; | ||
| 158 | if (ptr.* != 1234) unreachable; | ||
| 159 | |||
| 160 | var slice_rest = array[10..]; | ||
| 161 | if (slice_rest.len != 10) unreachable; | ||
| 162 | } | ||
| 163 | |||
| 164 | test "constant equal function pointers" { | ||
| 165 | const alias = emptyFn; | ||
| 166 | assert(comptime x: { | ||
| 167 | break :x emptyFn == alias; | ||
| 168 | }); | ||
| 169 | } | ||
| 170 | |||
| 171 | fn emptyFn() void {} | ||
| 172 | |||
| 173 | test "hex escape" { | ||
| 174 | assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); | ||
| 175 | } | ||
| 176 | |||
| 177 | test "string concatenation" { | ||
| 178 | assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | ||
| 179 | } | ||
| 180 | |||
| 181 | test "array mult operator" { | ||
| 182 | assert(mem.eql(u8, "ab" ** 5, "ababababab")); | ||
| 183 | } | ||
| 184 | |||
| 185 | test "string escapes" { | ||
| 186 | assert(mem.eql(u8, "\"", "\x22")); | ||
| 187 | assert(mem.eql(u8, "\'", "\x27")); | ||
| 188 | assert(mem.eql(u8, "\n", "\x0a")); | ||
| 189 | assert(mem.eql(u8, "\r", "\x0d")); | ||
| 190 | assert(mem.eql(u8, "\t", "\x09")); | ||
| 191 | assert(mem.eql(u8, "\\", "\x5c")); | ||
| 192 | assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); | ||
| 193 | } | ||
| 194 | |||
| 195 | test "multiline string" { | ||
| 196 | const s1 = | ||
| 197 | \\one | ||
| 198 | \\two) | ||
| 199 | \\three | ||
| 200 | ; | ||
| 201 | const s2 = "one\ntwo)\nthree"; | ||
| 202 | assert(mem.eql(u8, s1, s2)); | ||
| 203 | } | ||
| 204 | |||
| 205 | test "multiline C string" { | ||
| 206 | const s1 = | ||
| 207 | c\\one | ||
| 208 | c\\two) | ||
| 209 | c\\three | ||
| 210 | ; | ||
| 211 | const s2 = c"one\ntwo)\nthree"; | ||
| 212 | assert(cstr.cmp(s1, s2) == 0); | ||
| 213 | } | ||
| 214 | |||
| 215 | test "type equality" { | ||
| 216 | assert(*const u8 != *u8); | ||
| 217 | } | ||
| 218 | |||
| 219 | const global_a: i32 = 1234; | ||
| 220 | const global_b: *const i32 = &global_a; | ||
| 221 | const global_c: *const f32 = @ptrCast(*const f32, global_b); | ||
| 222 | test "compile time global reinterpret" { | ||
| 223 | const d = @ptrCast(*const i32, global_c); | ||
| 224 | assert(d.* == 1234); | ||
| 225 | } | ||
| 226 | |||
| 227 | test "explicit cast maybe pointers" { | ||
| 228 | const a: ?*i32 = undefined; | ||
| 229 | const b: ?*f32 = @ptrCast(?*f32, a); | ||
| 230 | } | ||
| 231 | |||
| 232 | test "generic malloc free" { | ||
| 233 | const a = memAlloc(u8, 10) catch unreachable; | ||
| 234 | memFree(u8, a); | ||
| 235 | } | ||
| 236 | var some_mem: [100]u8 = undefined; | ||
| 237 | fn memAlloc(comptime T: type, n: usize) anyerror![]T { | ||
| 238 | return @ptrCast([*]T, &some_mem[0])[0..n]; | ||
| 239 | } | ||
| 240 | fn memFree(comptime T: type, memory: []T) void {} | ||
| 241 | |||
| 242 | test "cast undefined" { | ||
| 243 | const array: [100]u8 = undefined; | ||
| 244 | const slice = ([]const u8)(array); | ||
| 245 | testCastUndefined(slice); | ||
| 246 | } | ||
| 247 | fn testCastUndefined(x: []const u8) void {} | ||
| 248 | |||
| 249 | test "cast small unsigned to larger signed" { | ||
| 250 | assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); | ||
| 251 | assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); | ||
| 252 | } | ||
| 253 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | ||
| 254 | return x; | ||
| 255 | } | ||
| 256 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | ||
| 257 | return x; | ||
| 258 | } | ||
| 259 | |||
| 260 | test "implicit cast after unreachable" { | ||
| 261 | assert(outer() == 1234); | ||
| 262 | } | ||
| 263 | fn inner() i32 { | ||
| 264 | return 1234; | ||
| 265 | } | ||
| 266 | fn outer() i64 { | ||
| 267 | return inner(); | ||
| 268 | } | ||
| 269 | |||
| 270 | test "pointer dereferencing" { | ||
| 271 | var x = i32(3); | ||
| 272 | const y = &x; | ||
| 273 | |||
| 274 | y.* += 1; | ||
| 275 | |||
| 276 | assert(x == 4); | ||
| 277 | assert(y.* == 4); | ||
| 278 | } | ||
| 279 | |||
| 280 | test "call result of if else expression" { | ||
| 281 | assert(mem.eql(u8, f2(true), "a")); | ||
| 282 | assert(mem.eql(u8, f2(false), "b")); | ||
| 283 | } | ||
| 284 | fn f2(x: bool) []const u8 { | ||
| 285 | return (if (x) fA else fB)(); | ||
| 286 | } | ||
| 287 | fn fA() []const u8 { | ||
| 288 | return "a"; | ||
| 289 | } | ||
| 290 | fn fB() []const u8 { | ||
| 291 | return "b"; | ||
| 292 | } | ||
| 293 | |||
| 294 | test "const expression eval handling of variables" { | ||
| 295 | var x = true; | ||
| 296 | while (x) { | ||
| 297 | x = false; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | test "constant enum initialization with differing sizes" { | ||
| 302 | test3_1(test3_foo); | ||
| 303 | test3_2(test3_bar); | ||
| 304 | } | ||
| 305 | const Test3Foo = union(enum) { | ||
| 306 | One: void, | ||
| 307 | Two: f32, | ||
| 308 | Three: Test3Point, | ||
| 309 | }; | ||
| 310 | const Test3Point = struct { | ||
| 311 | x: i32, | ||
| 312 | y: i32, | ||
| 313 | }; | ||
| 314 | const test3_foo = Test3Foo{ | ||
| 315 | .Three = Test3Point{ | ||
| 316 | .x = 3, | ||
| 317 | .y = 4, | ||
| 318 | }, | ||
| 319 | }; | ||
| 320 | const test3_bar = Test3Foo{ .Two = 13 }; | ||
| 321 | fn test3_1(f: Test3Foo) void { | ||
| 322 | switch (f) { | ||
| 323 | Test3Foo.Three => |pt| { | ||
| 324 | assert(pt.x == 3); | ||
| 325 | assert(pt.y == 4); | ||
| 326 | }, | ||
| 327 | else => unreachable, | ||
| 328 | } | ||
| 329 | } | ||
| 330 | fn test3_2(f: Test3Foo) void { | ||
| 331 | switch (f) { | ||
| 332 | Test3Foo.Two => |x| { | ||
| 333 | assert(x == 13); | ||
| 334 | }, | ||
| 335 | else => unreachable, | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | test "character literals" { | ||
| 340 | assert('\'' == single_quote); | ||
| 341 | } | ||
| 342 | const single_quote = '\''; | ||
| 343 | |||
| 344 | test "take address of parameter" { | ||
| 345 | testTakeAddressOfParameter(12.34); | ||
| 346 | } | ||
| 347 | fn testTakeAddressOfParameter(f: f32) void { | ||
| 348 | const f_ptr = &f; | ||
| 349 | assert(f_ptr.* == 12.34); | ||
| 350 | } | ||
| 351 | |||
| 352 | test "pointer comparison" { | ||
| 353 | const a = ([]const u8)("a"); | ||
| 354 | const b = &a; | ||
| 355 | assert(ptrEql(b, b)); | ||
| 356 | } | ||
| 357 | fn ptrEql(a: *const []const u8, b: *const []const u8) bool { | ||
| 358 | return a == b; | ||
| 359 | } | ||
| 360 | |||
| 361 | test "C string concatenation" { | ||
| 362 | const a = c"OK" ++ c" IT " ++ c"WORKED"; | ||
| 363 | const b = c"OK IT WORKED"; | ||
| 364 | |||
| 365 | const len = cstr.len(b); | ||
| 366 | const len_with_null = len + 1; | ||
| 367 | { | ||
| 368 | var i: u32 = 0; | ||
| 369 | while (i < len_with_null) : (i += 1) { | ||
| 370 | assert(a[i] == b[i]); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | assert(a[len] == 0); | ||
| 374 | assert(b[len] == 0); | ||
| 375 | } | ||
| 376 | |||
| 377 | test "cast slice to u8 slice" { | ||
| 378 | assert(@sizeOf(i32) == 4); | ||
| 379 | var big_thing_array = []i32{ | ||
| 380 | 1, | ||
| 381 | 2, | ||
| 382 | 3, | ||
| 383 | 4, | ||
| 384 | }; | ||
| 385 | const big_thing_slice: []i32 = big_thing_array[0..]; | ||
| 386 | const bytes = @sliceToBytes(big_thing_slice); | ||
| 387 | assert(bytes.len == 4 * 4); | ||
| 388 | bytes[4] = 0; | ||
| 389 | bytes[5] = 0; | ||
| 390 | bytes[6] = 0; | ||
| 391 | bytes[7] = 0; | ||
| 392 | assert(big_thing_slice[1] == 0); | ||
| 393 | const big_thing_again = @bytesToSlice(i32, bytes); | ||
| 394 | assert(big_thing_again[2] == 3); | ||
| 395 | big_thing_again[2] = -1; | ||
| 396 | assert(bytes[8] == maxInt(u8)); | ||
| 397 | assert(bytes[9] == maxInt(u8)); | ||
| 398 | assert(bytes[10] == maxInt(u8)); | ||
| 399 | assert(bytes[11] == maxInt(u8)); | ||
| 400 | } | ||
| 401 | |||
| 402 | test "pointer to void return type" { | ||
| 403 | testPointerToVoidReturnType() catch unreachable; | ||
| 404 | } | ||
| 405 | fn testPointerToVoidReturnType() anyerror!void { | ||
| 406 | const a = testPointerToVoidReturnType2(); | ||
| 407 | return a.*; | ||
| 408 | } | ||
| 409 | const test_pointer_to_void_return_type_x = void{}; | ||
| 410 | fn testPointerToVoidReturnType2() *const void { | ||
| 411 | return &test_pointer_to_void_return_type_x; | ||
| 412 | } | ||
| 413 | |||
| 414 | test "non const ptr to aliased type" { | ||
| 415 | const int = i32; | ||
| 416 | assert(?*int == ?*i32); | ||
| 417 | } | ||
| 418 | |||
| 419 | test "array 2D const double ptr" { | ||
| 420 | const rect_2d_vertexes = [][1]f32{ | ||
| 421 | []f32{1.0}, | ||
| 422 | []f32{2.0}, | ||
| 423 | }; | ||
| 424 | testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); | ||
| 425 | } | ||
| 426 | |||
| 427 | fn testArray2DConstDoublePtr(ptr: *const f32) void { | ||
| 428 | const ptr2 = @ptrCast([*]const f32, ptr); | ||
| 429 | assert(ptr2[0] == 1.0); | ||
| 430 | assert(ptr2[1] == 2.0); | ||
| 431 | } | ||
| 432 | |||
| 433 | const Tid = builtin.TypeId; | ||
| 434 | const AStruct = struct { | ||
| 435 | x: i32, | ||
| 436 | }; | ||
| 437 | const AnEnum = enum { | ||
| 438 | One, | ||
| 439 | Two, | ||
| 440 | }; | ||
| 441 | const AUnionEnum = union(enum) { | ||
| 442 | One: i32, | ||
| 443 | Two: void, | ||
| 444 | }; | ||
| 445 | const AUnion = union { | ||
| 446 | One: void, | ||
| 447 | Two: void, | ||
| 448 | }; | ||
| 449 | |||
| 450 | test "@typeId" { | ||
| 451 | comptime { | ||
| 452 | assert(@typeId(type) == Tid.Type); | ||
| 453 | assert(@typeId(void) == Tid.Void); | ||
| 454 | assert(@typeId(bool) == Tid.Bool); | ||
| 455 | assert(@typeId(noreturn) == Tid.NoReturn); | ||
| 456 | assert(@typeId(i8) == Tid.Int); | ||
| 457 | assert(@typeId(u8) == Tid.Int); | ||
| 458 | assert(@typeId(i64) == Tid.Int); | ||
| 459 | assert(@typeId(u64) == Tid.Int); | ||
| 460 | assert(@typeId(f32) == Tid.Float); | ||
| 461 | assert(@typeId(f64) == Tid.Float); | ||
| 462 | assert(@typeId(*f32) == Tid.Pointer); | ||
| 463 | assert(@typeId([2]u8) == Tid.Array); | ||
| 464 | assert(@typeId(AStruct) == Tid.Struct); | ||
| 465 | assert(@typeId(@typeOf(1)) == Tid.ComptimeInt); | ||
| 466 | assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); | ||
| 467 | assert(@typeId(@typeOf(undefined)) == Tid.Undefined); | ||
| 468 | assert(@typeId(@typeOf(null)) == Tid.Null); | ||
| 469 | assert(@typeId(?i32) == Tid.Optional); | ||
| 470 | assert(@typeId(anyerror!i32) == Tid.ErrorUnion); | ||
| 471 | assert(@typeId(anyerror) == Tid.ErrorSet); | ||
| 472 | assert(@typeId(AnEnum) == Tid.Enum); | ||
| 473 | assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); | ||
| 474 | assert(@typeId(AUnionEnum) == Tid.Union); | ||
| 475 | assert(@typeId(AUnion) == Tid.Union); | ||
| 476 | assert(@typeId(fn () void) == Tid.Fn); | ||
| 477 | assert(@typeId(@typeOf(builtin)) == Tid.Namespace); | ||
| 478 | // TODO bound fn | ||
| 479 | // TODO arg tuple | ||
| 480 | // TODO opaque | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | test "@typeName" { | ||
| 485 | const Struct = struct {}; | ||
| 486 | const Union = union { | ||
| 487 | unused: u8, | ||
| 488 | }; | ||
| 489 | const Enum = enum { | ||
| 490 | Unused, | ||
| 491 | }; | ||
| 492 | comptime { | ||
| 493 | assert(mem.eql(u8, @typeName(i64), "i64")); | ||
| 494 | assert(mem.eql(u8, @typeName(*usize), "*usize")); | ||
| 495 | // https://github.com/ziglang/zig/issues/675 | ||
| 496 | assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); | ||
| 497 | assert(mem.eql(u8, @typeName(Struct), "Struct")); | ||
| 498 | assert(mem.eql(u8, @typeName(Union), "Union")); | ||
| 499 | assert(mem.eql(u8, @typeName(Enum), "Enum")); | ||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | fn TypeFromFn(comptime T: type) type { | ||
| 504 | return struct {}; | ||
| 505 | } | ||
| 506 | |||
| 507 | test "volatile load and store" { | ||
| 508 | var number: i32 = 1234; | ||
| 509 | const ptr = (*volatile i32)(&number); | ||
| 510 | ptr.* += 1; | ||
| 511 | assert(ptr.* == 1235); | ||
| 512 | } | ||
| 513 | |||
| 514 | test "slice string literal has type []const u8" { | ||
| 515 | comptime { | ||
| 516 | assert(@typeOf("aoeu"[0..]) == []const u8); | ||
| 517 | const array = []i32{ | ||
| 518 | 1, | ||
| 519 | 2, | ||
| 520 | 3, | ||
| 521 | 4, | ||
| 522 | }; | ||
| 523 | assert(@typeOf(array[0..]) == []const i32); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | test "global variable initialized to global variable array element" { | ||
| 528 | assert(global_ptr == &gdt[0]); | ||
| 529 | } | ||
| 530 | const GDTEntry = struct { | ||
| 531 | field: i32, | ||
| 532 | }; | ||
| 533 | var gdt = []GDTEntry{ | ||
| 534 | GDTEntry{ .field = 1 }, | ||
| 535 | GDTEntry{ .field = 2 }, | ||
| 536 | }; | ||
| 537 | var global_ptr = &gdt[0]; | ||
| 538 | |||
| 539 | // can't really run this test but we can make sure it has no compile error | ||
| 540 | // and generates code | ||
| 541 | const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000]; | ||
| 542 | export fn writeToVRam() void { | ||
| 543 | vram[0] = 'X'; | ||
| 544 | } | ||
| 545 | |||
| 546 | test "pointer child field" { | ||
| 547 | assert((*u32).Child == u32); | ||
| 548 | } | ||
| 549 | |||
| 550 | const OpaqueA = @OpaqueType(); | ||
| 551 | const OpaqueB = @OpaqueType(); | ||
| 552 | test "@OpaqueType" { | ||
| 553 | assert(*OpaqueA != *OpaqueB); | ||
| 554 | assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); | ||
| 555 | assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); | ||
| 556 | } | ||
| 557 | |||
| 558 | test "variable is allowed to be a pointer to an opaque type" { | ||
| 559 | var x: i32 = 1234; | ||
| 560 | _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); | ||
| 561 | } | ||
| 562 | fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { | ||
| 563 | var a = ptr; | ||
| 564 | return a; | ||
| 565 | } | ||
| 566 | |||
| 567 | test "comptime if inside runtime while which unconditionally breaks" { | ||
| 568 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | ||
| 569 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | ||
| 570 | } | ||
| 571 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | ||
| 572 | while (cond) { | ||
| 573 | if (false) {} | ||
| 574 | break; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | test "implicit comptime while" { | ||
| 579 | while (false) { | ||
| 580 | @compileError("bad"); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 584 | test "struct inside function" { | ||
| 585 | testStructInFn(); | ||
| 586 | comptime testStructInFn(); | ||
| 587 | } | ||
| 588 | |||
| 589 | fn testStructInFn() void { | ||
| 590 | const BlockKind = u32; | ||
| 591 | |||
| 592 | const Block = struct { | ||
| 593 | kind: BlockKind, | ||
| 594 | }; | ||
| 595 | |||
| 596 | var block = Block{ .kind = 1234 }; | ||
| 597 | |||
| 598 | block.kind += 1; | ||
| 599 | |||
| 600 | assert(block.kind == 1235); | ||
| 601 | } | ||
| 602 | |||
| 603 | fn fnThatClosesOverLocalConst() type { | ||
| 604 | const c = 1; | ||
| 605 | return struct { | ||
| 606 | fn g() i32 { | ||
| 607 | return c; | ||
| 608 | } | ||
| 609 | }; | ||
| 610 | } | ||
| 611 | |||
| 612 | test "function closes over local const" { | ||
| 613 | const x = fnThatClosesOverLocalConst().g(); | ||
| 614 | assert(x == 1); | ||
| 615 | } | ||
| 616 | |||
| 617 | test "cold function" { | ||
| 618 | thisIsAColdFn(); | ||
| 619 | comptime thisIsAColdFn(); | ||
| 620 | } | ||
| 621 | |||
| 622 | fn thisIsAColdFn() void { | ||
| 623 | @setCold(true); | ||
| 624 | } | ||
| 625 | |||
| 626 | const PackedStruct = packed struct { | ||
| 627 | a: u8, | ||
| 628 | b: u8, | ||
| 629 | }; | ||
| 630 | const PackedUnion = packed union { | ||
| 631 | a: u8, | ||
| 632 | b: u32, | ||
| 633 | }; | ||
| 634 | const PackedEnum = packed enum { | ||
| 635 | A, | ||
| 636 | B, | ||
| 637 | }; | ||
| 638 | |||
| 639 | test "packed struct, enum, union parameters in extern function" { | ||
| 640 | testPackedStuff(&(PackedStruct{ | ||
| 641 | .a = 1, | ||
| 642 | .b = 2, | ||
| 643 | }), &(PackedUnion{ .a = 1 }), PackedEnum.A); | ||
| 644 | } | ||
| 645 | |||
| 646 | export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {} | ||
| 647 | |||
| 648 | test "slicing zero length array" { | ||
| 649 | const s1 = ""[0..]; | ||
| 650 | const s2 = ([]u32{})[0..]; | ||
| 651 | assert(s1.len == 0); | ||
| 652 | assert(s2.len == 0); | ||
| 653 | assert(mem.eql(u8, s1, "")); | ||
| 654 | assert(mem.eql(u32, s2, []u32{})); | ||
| 655 | } | ||
| 656 | |||
| 657 | const addr1 = @ptrCast(*const u8, emptyFn); | ||
| 658 | test "comptime cast fn to ptr" { | ||
| 659 | const addr2 = @ptrCast(*const u8, emptyFn); | ||
| 660 | comptime assert(addr1 == addr2); | ||
| 661 | } | ||
| 662 | |||
| 663 | test "equality compare fn ptrs" { | ||
| 664 | var a = emptyFn; | ||
| 665 | assert(a == a); | ||
| 666 | } | ||
| 667 | |||
| 668 | test "self reference through fn ptr field" { | ||
| 669 | const S = struct { | ||
| 670 | const A = struct { | ||
| 671 | f: fn (A) u8, | ||
| 672 | }; | ||
| 673 | |||
| 674 | fn foo(a: A) u8 { | ||
| 675 | return 12; | ||
| 676 | } | ||
| 677 | }; | ||
| 678 | var a: S.A = undefined; | ||
| 679 | a.f = S.foo; | ||
| 680 | assert(a.f(a) == 12); | ||
| 681 | } | ||
test/cases/namespace_depends_on_compile_var/a.zig deleted-1| ... | @@ -1 +0,0 @@ | ||
| 1 | pub const a_bool = true; | ||
test/cases/namespace_depends_on_compile_var/b.zig deleted-1| ... | @@ -1 +0,0 @@ | ||
| 1 | pub const a_bool = false; | ||
test/cases/namespace_depends_on_compile_var/index.zig deleted-14| ... | @@ -1,14 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | |||
| 4 | test "namespace depends on compile var" { | ||
| 5 | if (some_namespace.a_bool) { | ||
| 6 | assert(some_namespace.a_bool); | ||
| 7 | } else { | ||
| 8 | assert(!some_namespace.a_bool); | ||
| 9 | } | ||
| 10 | } | ||
| 11 | const some_namespace = switch (builtin.os) { | ||
| 12 | builtin.Os.linux => @import("a.zig"), | ||
| 13 | else => @import("b.zig"), | ||
| 14 | }; | ||
test/cases/new_stack_call.zig deleted-26| ... | @@ -1,26 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | |||
| 4 | var new_stack_bytes: [1024]u8 = undefined; | ||
| 5 | |||
| 6 | test "calling a function with a new stack" { | ||
| 7 | const arg = 1234; | ||
| 8 | |||
| 9 | const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); | ||
| 10 | const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); | ||
| 11 | _ = targetFunction(arg); | ||
| 12 | |||
| 13 | assert(arg == 1234); | ||
| 14 | assert(a < b); | ||
| 15 | } | ||
| 16 | |||
| 17 | fn targetFunction(x: i32) usize { | ||
| 18 | assert(x == 1234); | ||
| 19 | |||
| 20 | var local_variable: i32 = 42; | ||
| 21 | const ptr = &local_variable; | ||
| 22 | ptr.* += 1; | ||
| 23 | |||
| 24 | assert(local_variable == 43); | ||
| 25 | return @ptrToInt(ptr); | ||
| 26 | } | ||
test/cases/null.zig deleted-162| ... | @@ -1,162 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "optional type" { | ||
| 4 | const x: ?bool = true; | ||
| 5 | |||
| 6 | if (x) |y| { | ||
| 7 | if (y) { | ||
| 8 | // OK | ||
| 9 | } else { | ||
| 10 | unreachable; | ||
| 11 | } | ||
| 12 | } else { | ||
| 13 | unreachable; | ||
| 14 | } | ||
| 15 | |||
| 16 | const next_x: ?i32 = null; | ||
| 17 | |||
| 18 | const z = next_x orelse 1234; | ||
| 19 | |||
| 20 | assert(z == 1234); | ||
| 21 | |||
| 22 | const final_x: ?i32 = 13; | ||
| 23 | |||
| 24 | const num = final_x orelse unreachable; | ||
| 25 | |||
| 26 | assert(num == 13); | ||
| 27 | } | ||
| 28 | |||
| 29 | test "test maybe object and get a pointer to the inner value" { | ||
| 30 | var maybe_bool: ?bool = true; | ||
| 31 | |||
| 32 | if (maybe_bool) |*b| { | ||
| 33 | b.* = false; | ||
| 34 | } | ||
| 35 | |||
| 36 | assert(maybe_bool.? == false); | ||
| 37 | } | ||
| 38 | |||
| 39 | test "rhs maybe unwrap return" { | ||
| 40 | const x: ?bool = true; | ||
| 41 | const y = x orelse return; | ||
| 42 | } | ||
| 43 | |||
| 44 | test "maybe return" { | ||
| 45 | maybeReturnImpl(); | ||
| 46 | comptime maybeReturnImpl(); | ||
| 47 | } | ||
| 48 | |||
| 49 | fn maybeReturnImpl() void { | ||
| 50 | assert(foo(1235).?); | ||
| 51 | if (foo(null) != null) unreachable; | ||
| 52 | assert(!foo(1234).?); | ||
| 53 | } | ||
| 54 | |||
| 55 | fn foo(x: ?i32) ?bool { | ||
| 56 | const value = x orelse return null; | ||
| 57 | return value > 1234; | ||
| 58 | } | ||
| 59 | |||
| 60 | test "if var maybe pointer" { | ||
| 61 | assert(shouldBeAPlus1(Particle{ | ||
| 62 | .a = 14, | ||
| 63 | .b = 1, | ||
| 64 | .c = 1, | ||
| 65 | .d = 1, | ||
| 66 | }) == 15); | ||
| 67 | } | ||
| 68 | fn shouldBeAPlus1(p: Particle) u64 { | ||
| 69 | var maybe_particle: ?Particle = p; | ||
| 70 | if (maybe_particle) |*particle| { | ||
| 71 | particle.a += 1; | ||
| 72 | } | ||
| 73 | if (maybe_particle) |particle| { | ||
| 74 | return particle.a; | ||
| 75 | } | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | const Particle = struct { | ||
| 79 | a: u64, | ||
| 80 | b: u64, | ||
| 81 | c: u64, | ||
| 82 | d: u64, | ||
| 83 | }; | ||
| 84 | |||
| 85 | test "null literal outside function" { | ||
| 86 | const is_null = here_is_a_null_literal.context == null; | ||
| 87 | assert(is_null); | ||
| 88 | |||
| 89 | const is_non_null = here_is_a_null_literal.context != null; | ||
| 90 | assert(!is_non_null); | ||
| 91 | } | ||
| 92 | const SillyStruct = struct { | ||
| 93 | context: ?i32, | ||
| 94 | }; | ||
| 95 | const here_is_a_null_literal = SillyStruct{ .context = null }; | ||
| 96 | |||
| 97 | test "test null runtime" { | ||
| 98 | testTestNullRuntime(null); | ||
| 99 | } | ||
| 100 | fn testTestNullRuntime(x: ?i32) void { | ||
| 101 | assert(x == null); | ||
| 102 | assert(!(x != null)); | ||
| 103 | } | ||
| 104 | |||
| 105 | test "optional void" { | ||
| 106 | optionalVoidImpl(); | ||
| 107 | comptime optionalVoidImpl(); | ||
| 108 | } | ||
| 109 | |||
| 110 | fn optionalVoidImpl() void { | ||
| 111 | assert(bar(null) == null); | ||
| 112 | assert(bar({}) != null); | ||
| 113 | } | ||
| 114 | |||
| 115 | fn bar(x: ?void) ?void { | ||
| 116 | if (x) |_| { | ||
| 117 | return {}; | ||
| 118 | } else { | ||
| 119 | return null; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | const StructWithOptional = struct { | ||
| 124 | field: ?i32, | ||
| 125 | }; | ||
| 126 | |||
| 127 | var struct_with_optional: StructWithOptional = undefined; | ||
| 128 | |||
| 129 | test "unwrap optional which is field of global var" { | ||
| 130 | struct_with_optional.field = null; | ||
| 131 | if (struct_with_optional.field) |payload| { | ||
| 132 | unreachable; | ||
| 133 | } | ||
| 134 | struct_with_optional.field = 1234; | ||
| 135 | if (struct_with_optional.field) |payload| { | ||
| 136 | assert(payload == 1234); | ||
| 137 | } else { | ||
| 138 | unreachable; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | test "null with default unwrap" { | ||
| 143 | const x: i32 = null orelse 1; | ||
| 144 | assert(x == 1); | ||
| 145 | } | ||
| 146 | |||
| 147 | test "optional types" { | ||
| 148 | comptime { | ||
| 149 | const opt_type_struct = StructWithOptionalType{ .t = u8 }; | ||
| 150 | assert(opt_type_struct.t != null and opt_type_struct.t.? == u8); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | const StructWithOptionalType = struct { | ||
| 155 | t: ?type, | ||
| 156 | }; | ||
| 157 | |||
| 158 | test "optional pointer to 0 bit type null value at runtime" { | ||
| 159 | const EmptyStruct = struct {}; | ||
| 160 | var x: ?*EmptyStruct = null; | ||
| 161 | assert(x == null); | ||
| 162 | } | ||
test/cases/optional.zig deleted-30| ... | @@ -1,30 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | pub const EmptyStruct = struct {}; | ||
| 4 | |||
| 5 | test "optional pointer to size zero struct" { | ||
| 6 | var e = EmptyStruct{}; | ||
| 7 | var o: ?*EmptyStruct = &e; | ||
| 8 | assert(o != null); | ||
| 9 | } | ||
| 10 | |||
| 11 | test "equality compare nullable pointers" { | ||
| 12 | testNullPtrsEql(); | ||
| 13 | comptime testNullPtrsEql(); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn testNullPtrsEql() void { | ||
| 17 | var number: i32 = 1234; | ||
| 18 | |||
| 19 | var x: ?*i32 = null; | ||
| 20 | var y: ?*i32 = null; | ||
| 21 | assert(x == y); | ||
| 22 | y = &number; | ||
| 23 | assert(x != y); | ||
| 24 | assert(x != &number); | ||
| 25 | assert(&number != x); | ||
| 26 | x = &number; | ||
| 27 | assert(x == y); | ||
| 28 | assert(x == &number); | ||
| 29 | assert(&number == x); | ||
| 30 | } | ||
test/cases/pointers.zig deleted-44| ... | @@ -1,44 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | |||
| 4 | test "dereference pointer" { | ||
| 5 | comptime testDerefPtr(); | ||
| 6 | testDerefPtr(); | ||
| 7 | } | ||
| 8 | |||
| 9 | fn testDerefPtr() void { | ||
| 10 | var x: i32 = 1234; | ||
| 11 | var y = &x; | ||
| 12 | y.* += 1; | ||
| 13 | assert(x == 1235); | ||
| 14 | } | ||
| 15 | |||
| 16 | test "pointer arithmetic" { | ||
| 17 | var ptr = c"abcd"; | ||
| 18 | |||
| 19 | assert(ptr[0] == 'a'); | ||
| 20 | ptr += 1; | ||
| 21 | assert(ptr[0] == 'b'); | ||
| 22 | ptr += 1; | ||
| 23 | assert(ptr[0] == 'c'); | ||
| 24 | ptr += 1; | ||
| 25 | assert(ptr[0] == 'd'); | ||
| 26 | ptr += 1; | ||
| 27 | assert(ptr[0] == 0); | ||
| 28 | ptr -= 1; | ||
| 29 | assert(ptr[0] == 'd'); | ||
| 30 | ptr -= 1; | ||
| 31 | assert(ptr[0] == 'c'); | ||
| 32 | ptr -= 1; | ||
| 33 | assert(ptr[0] == 'b'); | ||
| 34 | ptr -= 1; | ||
| 35 | assert(ptr[0] == 'a'); | ||
| 36 | } | ||
| 37 | |||
| 38 | test "double pointer parsing" { | ||
| 39 | comptime assert(PtrOf(PtrOf(i32)) == **i32); | ||
| 40 | } | ||
| 41 | |||
| 42 | fn PtrOf(comptime T: type) type { | ||
| 43 | return *T; | ||
| 44 | } | ||
test/cases/popcount.zig deleted-24| ... | @@ -1,24 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "@popCount" { | ||
| 4 | comptime testPopCount(); | ||
| 5 | testPopCount(); | ||
| 6 | } | ||
| 7 | |||
| 8 | fn testPopCount() void { | ||
| 9 | { | ||
| 10 | var x: u32 = 0xaa; | ||
| 11 | assert(@popCount(x) == 4); | ||
| 12 | } | ||
| 13 | { | ||
| 14 | var x: u32 = 0xaaaaaaaa; | ||
| 15 | assert(@popCount(x) == 16); | ||
| 16 | } | ||
| 17 | { | ||
| 18 | var x: i16 = -1; | ||
| 19 | assert(@popCount(x) == 16); | ||
| 20 | } | ||
| 21 | comptime { | ||
| 22 | assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); | ||
| 23 | } | ||
| 24 | } | ||
test/cases/pub_enum/index.zig deleted-13| ... | @@ -1,13 +0,0 @@ | ||
| 1 | const other = @import("other.zig"); | ||
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | |||
| 4 | test "pub enum" { | ||
| 5 | pubEnumTest(other.APubEnum.Two); | ||
| 6 | } | ||
| 7 | fn pubEnumTest(foo: other.APubEnum) void { | ||
| 8 | assert(foo == other.APubEnum.Two); | ||
| 9 | } | ||
| 10 | |||
| 11 | test "cast with imported symbol" { | ||
| 12 | assert(other.size_t(42) == 42); | ||
| 13 | } | ||
test/cases/pub_enum/other.zig deleted-6| ... | @@ -1,6 +0,0 @@ | ||
| 1 | pub const APubEnum = enum { | ||
| 2 | One, | ||
| 3 | Two, | ||
| 4 | Three, | ||
| 5 | }; | ||
| 6 | pub const size_t = u64; | ||
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig deleted-37| ... | @@ -1,37 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | var ok: bool = false; | ||
| 5 | test "reference a variable in an if after an if in the 2nd switch prong" { | ||
| 6 | foo(true, Num.Two, false, "aoeu"); | ||
| 7 | assert(!ok); | ||
| 8 | foo(false, Num.One, false, "aoeu"); | ||
| 9 | assert(!ok); | ||
| 10 | foo(true, Num.One, false, "aoeu"); | ||
| 11 | assert(ok); | ||
| 12 | } | ||
| 13 | |||
| 14 | const Num = enum { | ||
| 15 | One, | ||
| 16 | Two, | ||
| 17 | }; | ||
| 18 | |||
| 19 | fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { | ||
| 20 | switch (k) { | ||
| 21 | Num.Two => {}, | ||
| 22 | Num.One => { | ||
| 23 | if (c) { | ||
| 24 | const output_path = b; | ||
| 25 | |||
| 26 | if (c2) {} | ||
| 27 | |||
| 28 | a(output_path); | ||
| 29 | } | ||
| 30 | }, | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | fn a(x: []const u8) void { | ||
| 35 | assert(mem.eql(u8, x, "aoeu")); | ||
| 36 | ok = true; | ||
| 37 | } | ||
test/cases/reflection.zig deleted-95| ... | @@ -1,95 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | const reflection = @This(); | ||
| 4 | |||
| 5 | test "reflection: array, pointer, optional, error union type child" { | ||
| 6 | comptime { | ||
| 7 | assert(([10]u8).Child == u8); | ||
| 8 | assert((*u8).Child == u8); | ||
| 9 | assert((anyerror!u8).Payload == u8); | ||
| 10 | assert((?u8).Child == u8); | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | test "reflection: function return type, var args, and param types" { | ||
| 15 | comptime { | ||
| 16 | assert(@typeOf(dummy).ReturnType == i32); | ||
| 17 | assert(!@typeOf(dummy).is_var_args); | ||
| 18 | assert(@typeOf(dummy_varargs).is_var_args); | ||
| 19 | assert(@typeOf(dummy).arg_count == 3); | ||
| 20 | assert(@ArgType(@typeOf(dummy), 0) == bool); | ||
| 21 | assert(@ArgType(@typeOf(dummy), 1) == i32); | ||
| 22 | assert(@ArgType(@typeOf(dummy), 2) == f32); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | fn dummy(a: bool, b: i32, c: f32) i32 { | ||
| 27 | return 1234; | ||
| 28 | } | ||
| 29 | fn dummy_varargs(args: ...) void {} | ||
| 30 | |||
| 31 | test "reflection: struct member types and names" { | ||
| 32 | comptime { | ||
| 33 | assert(@memberCount(Foo) == 3); | ||
| 34 | |||
| 35 | assert(@memberType(Foo, 0) == i32); | ||
| 36 | assert(@memberType(Foo, 1) == bool); | ||
| 37 | assert(@memberType(Foo, 2) == void); | ||
| 38 | |||
| 39 | assert(mem.eql(u8, @memberName(Foo, 0), "one")); | ||
| 40 | assert(mem.eql(u8, @memberName(Foo, 1), "two")); | ||
| 41 | assert(mem.eql(u8, @memberName(Foo, 2), "three")); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | test "reflection: enum member types and names" { | ||
| 46 | comptime { | ||
| 47 | assert(@memberCount(Bar) == 4); | ||
| 48 | |||
| 49 | assert(@memberType(Bar, 0) == void); | ||
| 50 | assert(@memberType(Bar, 1) == i32); | ||
| 51 | assert(@memberType(Bar, 2) == bool); | ||
| 52 | assert(@memberType(Bar, 3) == f64); | ||
| 53 | |||
| 54 | assert(mem.eql(u8, @memberName(Bar, 0), "One")); | ||
| 55 | assert(mem.eql(u8, @memberName(Bar, 1), "Two")); | ||
| 56 | assert(mem.eql(u8, @memberName(Bar, 2), "Three")); | ||
| 57 | assert(mem.eql(u8, @memberName(Bar, 3), "Four")); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | test "reflection: @field" { | ||
| 62 | var f = Foo{ | ||
| 63 | .one = 42, | ||
| 64 | .two = true, | ||
| 65 | .three = void{}, | ||
| 66 | }; | ||
| 67 | |||
| 68 | assert(f.one == f.one); | ||
| 69 | assert(@field(f, "o" ++ "ne") == f.one); | ||
| 70 | assert(@field(f, "t" ++ "wo") == f.two); | ||
| 71 | assert(@field(f, "th" ++ "ree") == f.three); | ||
| 72 | assert(@field(Foo, "const" ++ "ant") == Foo.constant); | ||
| 73 | assert(@field(Bar, "O" ++ "ne") == Bar.One); | ||
| 74 | assert(@field(Bar, "T" ++ "wo") == Bar.Two); | ||
| 75 | assert(@field(Bar, "Th" ++ "ree") == Bar.Three); | ||
| 76 | assert(@field(Bar, "F" ++ "our") == Bar.Four); | ||
| 77 | assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); | ||
| 78 | @field(f, "o" ++ "ne") = 4; | ||
| 79 | assert(f.one == 4); | ||
| 80 | } | ||
| 81 | |||
| 82 | const Foo = struct { | ||
| 83 | const constant = 52; | ||
| 84 | |||
| 85 | one: i32, | ||
| 86 | two: bool, | ||
| 87 | three: void, | ||
| 88 | }; | ||
| 89 | |||
| 90 | const Bar = union(enum) { | ||
| 91 | One: void, | ||
| 92 | Two: i32, | ||
| 93 | Three: bool, | ||
| 94 | Four: f64, | ||
| 95 | }; | ||
test/cases/sizeof_and_typeof.zig deleted-69| ... | @@ -1,69 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const assert = @import("std").debug.assert; | ||
| 3 | |||
| 4 | test "@sizeOf and @typeOf" { | ||
| 5 | const y: @typeOf(x) = 120; | ||
| 6 | assert(@sizeOf(@typeOf(y)) == 2); | ||
| 7 | } | ||
| 8 | const x: u16 = 13; | ||
| 9 | const z: @typeOf(x) = 19; | ||
| 10 | |||
| 11 | const A = struct { | ||
| 12 | a: u8, | ||
| 13 | b: u32, | ||
| 14 | c: u8, | ||
| 15 | d: u3, | ||
| 16 | e: u5, | ||
| 17 | f: u16, | ||
| 18 | g: u16, | ||
| 19 | }; | ||
| 20 | |||
| 21 | const P = packed struct { | ||
| 22 | a: u8, | ||
| 23 | b: u32, | ||
| 24 | c: u8, | ||
| 25 | d: u3, | ||
| 26 | e: u5, | ||
| 27 | f: u16, | ||
| 28 | g: u16, | ||
| 29 | }; | ||
| 30 | |||
| 31 | test "@byteOffsetOf" { | ||
| 32 | // Packed structs have fixed memory layout | ||
| 33 | assert(@byteOffsetOf(P, "a") == 0); | ||
| 34 | assert(@byteOffsetOf(P, "b") == 1); | ||
| 35 | assert(@byteOffsetOf(P, "c") == 5); | ||
| 36 | assert(@byteOffsetOf(P, "d") == 6); | ||
| 37 | assert(@byteOffsetOf(P, "e") == 6); | ||
| 38 | assert(@byteOffsetOf(P, "f") == 7); | ||
| 39 | assert(@byteOffsetOf(P, "g") == 9); | ||
| 40 | |||
| 41 | // Normal struct fields can be moved/padded | ||
| 42 | var a: A = undefined; | ||
| 43 | assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a")); | ||
| 44 | assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b")); | ||
| 45 | assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c")); | ||
| 46 | assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d")); | ||
| 47 | assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e")); | ||
| 48 | assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f")); | ||
| 49 | assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g")); | ||
| 50 | } | ||
| 51 | |||
| 52 | test "@bitOffsetOf" { | ||
| 53 | // Packed structs have fixed memory layout | ||
| 54 | assert(@bitOffsetOf(P, "a") == 0); | ||
| 55 | assert(@bitOffsetOf(P, "b") == 8); | ||
| 56 | assert(@bitOffsetOf(P, "c") == 40); | ||
| 57 | assert(@bitOffsetOf(P, "d") == 48); | ||
| 58 | assert(@bitOffsetOf(P, "e") == 51); | ||
| 59 | assert(@bitOffsetOf(P, "f") == 56); | ||
| 60 | assert(@bitOffsetOf(P, "g") == 72); | ||
| 61 | |||
| 62 | assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); | ||
| 63 | assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); | ||
| 64 | assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); | ||
| 65 | assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); | ||
| 66 | assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); | ||
| 67 | assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); | ||
| 68 | assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); | ||
| 69 | } | ||
test/cases/slice.zig deleted-40| ... | @@ -1,40 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | ||
| 5 | const y = x[0x100..]; | ||
| 6 | test "compile time slice of pointer to hard coded address" { | ||
| 7 | assert(@ptrToInt(x.ptr) == 0x1000); | ||
| 8 | assert(x.len == 0x500); | ||
| 9 | |||
| 10 | assert(@ptrToInt(y.ptr) == 0x1100); | ||
| 11 | assert(y.len == 0x400); | ||
| 12 | } | ||
| 13 | |||
| 14 | test "slice child property" { | ||
| 15 | var array: [5]i32 = undefined; | ||
| 16 | var slice = array[0..]; | ||
| 17 | assert(@typeOf(slice).Child == i32); | ||
| 18 | } | ||
| 19 | |||
| 20 | test "runtime safety lets us slice from len..len" { | ||
| 21 | var an_array = []u8{ | ||
| 22 | 1, | ||
| 23 | 2, | ||
| 24 | 3, | ||
| 25 | }; | ||
| 26 | assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); | ||
| 27 | } | ||
| 28 | |||
| 29 | fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { | ||
| 30 | return a_slice[start..end]; | ||
| 31 | } | ||
| 32 | |||
| 33 | test "implicitly cast array of size 0 to slice" { | ||
| 34 | var msg = []u8{}; | ||
| 35 | assertLenIsZero(msg); | ||
| 36 | } | ||
| 37 | |||
| 38 | fn assertLenIsZero(msg: []const u8) void { | ||
| 39 | assert(msg.len == 0); | ||
| 40 | } | ||
test/cases/struct.zig deleted-470| ... | @@ -1,470 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const maxInt = std.math.maxInt; | ||
| 5 | |||
| 6 | const StructWithNoFields = struct { | ||
| 7 | fn add(a: i32, b: i32) i32 { | ||
| 8 | return a + b; | ||
| 9 | } | ||
| 10 | }; | ||
| 11 | const empty_global_instance = StructWithNoFields{}; | ||
| 12 | |||
| 13 | test "call struct static method" { | ||
| 14 | const result = StructWithNoFields.add(3, 4); | ||
| 15 | assert(result == 7); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "return empty struct instance" { | ||
| 19 | _ = returnEmptyStructInstance(); | ||
| 20 | } | ||
| 21 | fn returnEmptyStructInstance() StructWithNoFields { | ||
| 22 | return empty_global_instance; | ||
| 23 | } | ||
| 24 | |||
| 25 | const should_be_11 = StructWithNoFields.add(5, 6); | ||
| 26 | |||
| 27 | test "invake static method in global scope" { | ||
| 28 | assert(should_be_11 == 11); | ||
| 29 | } | ||
| 30 | |||
| 31 | test "void struct fields" { | ||
| 32 | const foo = VoidStructFieldsFoo{ | ||
| 33 | .a = void{}, | ||
| 34 | .b = 1, | ||
| 35 | .c = void{}, | ||
| 36 | }; | ||
| 37 | assert(foo.b == 1); | ||
| 38 | assert(@sizeOf(VoidStructFieldsFoo) == 4); | ||
| 39 | } | ||
| 40 | const VoidStructFieldsFoo = struct { | ||
| 41 | a: void, | ||
| 42 | b: i32, | ||
| 43 | c: void, | ||
| 44 | }; | ||
| 45 | |||
| 46 | test "structs" { | ||
| 47 | var foo: StructFoo = undefined; | ||
| 48 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | ||
| 49 | foo.a += 1; | ||
| 50 | foo.b = foo.a == 1; | ||
| 51 | testFoo(foo); | ||
| 52 | testMutation(&foo); | ||
| 53 | assert(foo.c == 100); | ||
| 54 | } | ||
| 55 | const StructFoo = struct { | ||
| 56 | a: i32, | ||
| 57 | b: bool, | ||
| 58 | c: f32, | ||
| 59 | }; | ||
| 60 | fn testFoo(foo: StructFoo) void { | ||
| 61 | assert(foo.b); | ||
| 62 | } | ||
| 63 | fn testMutation(foo: *StructFoo) void { | ||
| 64 | foo.c = 100; | ||
| 65 | } | ||
| 66 | |||
| 67 | const Node = struct { | ||
| 68 | val: Val, | ||
| 69 | next: *Node, | ||
| 70 | }; | ||
| 71 | |||
| 72 | const Val = struct { | ||
| 73 | x: i32, | ||
| 74 | }; | ||
| 75 | |||
| 76 | test "struct point to self" { | ||
| 77 | var root: Node = undefined; | ||
| 78 | root.val.x = 1; | ||
| 79 | |||
| 80 | var node: Node = undefined; | ||
| 81 | node.next = &root; | ||
| 82 | node.val.x = 2; | ||
| 83 | |||
| 84 | root.next = &node; | ||
| 85 | |||
| 86 | assert(node.next.next.next.val.x == 1); | ||
| 87 | } | ||
| 88 | |||
| 89 | test "struct byval assign" { | ||
| 90 | var foo1: StructFoo = undefined; | ||
| 91 | var foo2: StructFoo = undefined; | ||
| 92 | |||
| 93 | foo1.a = 1234; | ||
| 94 | foo2.a = 0; | ||
| 95 | assert(foo2.a == 0); | ||
| 96 | foo2 = foo1; | ||
| 97 | assert(foo2.a == 1234); | ||
| 98 | } | ||
| 99 | |||
| 100 | fn structInitializer() void { | ||
| 101 | const val = Val{ .x = 42 }; | ||
| 102 | assert(val.x == 42); | ||
| 103 | } | ||
| 104 | |||
| 105 | test "fn call of struct field" { | ||
| 106 | assert(callStructField(Foo{ .ptr = aFunc }) == 13); | ||
| 107 | } | ||
| 108 | |||
| 109 | const Foo = struct { | ||
| 110 | ptr: fn () i32, | ||
| 111 | }; | ||
| 112 | |||
| 113 | fn aFunc() i32 { | ||
| 114 | return 13; | ||
| 115 | } | ||
| 116 | |||
| 117 | fn callStructField(foo: Foo) i32 { | ||
| 118 | return foo.ptr(); | ||
| 119 | } | ||
| 120 | |||
| 121 | test "store member function in variable" { | ||
| 122 | const instance = MemberFnTestFoo{ .x = 1234 }; | ||
| 123 | const memberFn = MemberFnTestFoo.member; | ||
| 124 | const result = memberFn(instance); | ||
| 125 | assert(result == 1234); | ||
| 126 | } | ||
| 127 | const MemberFnTestFoo = struct { | ||
| 128 | x: i32, | ||
| 129 | fn member(foo: MemberFnTestFoo) i32 { | ||
| 130 | return foo.x; | ||
| 131 | } | ||
| 132 | }; | ||
| 133 | |||
| 134 | test "call member function directly" { | ||
| 135 | const instance = MemberFnTestFoo{ .x = 1234 }; | ||
| 136 | const result = MemberFnTestFoo.member(instance); | ||
| 137 | assert(result == 1234); | ||
| 138 | } | ||
| 139 | |||
| 140 | test "member functions" { | ||
| 141 | const r = MemberFnRand{ .seed = 1234 }; | ||
| 142 | assert(r.getSeed() == 1234); | ||
| 143 | } | ||
| 144 | const MemberFnRand = struct { | ||
| 145 | seed: u32, | ||
| 146 | pub fn getSeed(r: *const MemberFnRand) u32 { | ||
| 147 | return r.seed; | ||
| 148 | } | ||
| 149 | }; | ||
| 150 | |||
| 151 | test "return struct byval from function" { | ||
| 152 | const bar = makeBar(1234, 5678); | ||
| 153 | assert(bar.y == 5678); | ||
| 154 | } | ||
| 155 | const Bar = struct { | ||
| 156 | x: i32, | ||
| 157 | y: i32, | ||
| 158 | }; | ||
| 159 | fn makeBar(x: i32, y: i32) Bar { | ||
| 160 | return Bar{ | ||
| 161 | .x = x, | ||
| 162 | .y = y, | ||
| 163 | }; | ||
| 164 | } | ||
| 165 | |||
| 166 | test "empty struct method call" { | ||
| 167 | const es = EmptyStruct{}; | ||
| 168 | assert(es.method() == 1234); | ||
| 169 | } | ||
| 170 | const EmptyStruct = struct { | ||
| 171 | fn method(es: *const EmptyStruct) i32 { | ||
| 172 | return 1234; | ||
| 173 | } | ||
| 174 | }; | ||
| 175 | |||
| 176 | test "return empty struct from fn" { | ||
| 177 | _ = testReturnEmptyStructFromFn(); | ||
| 178 | } | ||
| 179 | const EmptyStruct2 = struct {}; | ||
| 180 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | ||
| 181 | return EmptyStruct2{}; | ||
| 182 | } | ||
| 183 | |||
| 184 | test "pass slice of empty struct to fn" { | ||
| 185 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); | ||
| 186 | } | ||
| 187 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | ||
| 188 | return slice.len; | ||
| 189 | } | ||
| 190 | |||
| 191 | const APackedStruct = packed struct { | ||
| 192 | x: u8, | ||
| 193 | y: u8, | ||
| 194 | }; | ||
| 195 | |||
| 196 | test "packed struct" { | ||
| 197 | var foo = APackedStruct{ | ||
| 198 | .x = 1, | ||
| 199 | .y = 2, | ||
| 200 | }; | ||
| 201 | foo.y += 1; | ||
| 202 | const four = foo.x + foo.y; | ||
| 203 | assert(four == 4); | ||
| 204 | } | ||
| 205 | |||
| 206 | const BitField1 = packed struct { | ||
| 207 | a: u3, | ||
| 208 | b: u3, | ||
| 209 | c: u2, | ||
| 210 | }; | ||
| 211 | |||
| 212 | const bit_field_1 = BitField1{ | ||
| 213 | .a = 1, | ||
| 214 | .b = 2, | ||
| 215 | .c = 3, | ||
| 216 | }; | ||
| 217 | |||
| 218 | test "bit field access" { | ||
| 219 | var data = bit_field_1; | ||
| 220 | assert(getA(&data) == 1); | ||
| 221 | assert(getB(&data) == 2); | ||
| 222 | assert(getC(&data) == 3); | ||
| 223 | comptime assert(@sizeOf(BitField1) == 1); | ||
| 224 | |||
| 225 | data.b += 1; | ||
| 226 | assert(data.b == 3); | ||
| 227 | |||
| 228 | data.a += 1; | ||
| 229 | assert(data.a == 2); | ||
| 230 | assert(data.b == 3); | ||
| 231 | } | ||
| 232 | |||
| 233 | fn getA(data: *const BitField1) u3 { | ||
| 234 | return data.a; | ||
| 235 | } | ||
| 236 | |||
| 237 | fn getB(data: *const BitField1) u3 { | ||
| 238 | return data.b; | ||
| 239 | } | ||
| 240 | |||
| 241 | fn getC(data: *const BitField1) u2 { | ||
| 242 | return data.c; | ||
| 243 | } | ||
| 244 | |||
| 245 | const Foo24Bits = packed struct { | ||
| 246 | field: u24, | ||
| 247 | }; | ||
| 248 | const Foo96Bits = packed struct { | ||
| 249 | a: u24, | ||
| 250 | b: u24, | ||
| 251 | c: u24, | ||
| 252 | d: u24, | ||
| 253 | }; | ||
| 254 | |||
| 255 | test "packed struct 24bits" { | ||
| 256 | comptime { | ||
| 257 | assert(@sizeOf(Foo24Bits) == 3); | ||
| 258 | assert(@sizeOf(Foo96Bits) == 12); | ||
| 259 | } | ||
| 260 | |||
| 261 | var value = Foo96Bits{ | ||
| 262 | .a = 0, | ||
| 263 | .b = 0, | ||
| 264 | .c = 0, | ||
| 265 | .d = 0, | ||
| 266 | }; | ||
| 267 | value.a += 1; | ||
| 268 | assert(value.a == 1); | ||
| 269 | assert(value.b == 0); | ||
| 270 | assert(value.c == 0); | ||
| 271 | assert(value.d == 0); | ||
| 272 | |||
| 273 | value.b += 1; | ||
| 274 | assert(value.a == 1); | ||
| 275 | assert(value.b == 1); | ||
| 276 | assert(value.c == 0); | ||
| 277 | assert(value.d == 0); | ||
| 278 | |||
| 279 | value.c += 1; | ||
| 280 | assert(value.a == 1); | ||
| 281 | assert(value.b == 1); | ||
| 282 | assert(value.c == 1); | ||
| 283 | assert(value.d == 0); | ||
| 284 | |||
| 285 | value.d += 1; | ||
| 286 | assert(value.a == 1); | ||
| 287 | assert(value.b == 1); | ||
| 288 | assert(value.c == 1); | ||
| 289 | assert(value.d == 1); | ||
| 290 | } | ||
| 291 | |||
| 292 | const FooArray24Bits = packed struct { | ||
| 293 | a: u16, | ||
| 294 | b: [2]Foo24Bits, | ||
| 295 | c: u16, | ||
| 296 | }; | ||
| 297 | |||
| 298 | test "packed array 24bits" { | ||
| 299 | comptime { | ||
| 300 | assert(@sizeOf([9]Foo24Bits) == 9 * 3); | ||
| 301 | assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); | ||
| 302 | } | ||
| 303 | |||
| 304 | var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); | ||
| 305 | bytes[bytes.len - 1] = 0xaa; | ||
| 306 | const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; | ||
| 307 | assert(ptr.a == 0); | ||
| 308 | assert(ptr.b[0].field == 0); | ||
| 309 | assert(ptr.b[1].field == 0); | ||
| 310 | assert(ptr.c == 0); | ||
| 311 | |||
| 312 | ptr.a = maxInt(u16); | ||
| 313 | assert(ptr.a == maxInt(u16)); | ||
| 314 | assert(ptr.b[0].field == 0); | ||
| 315 | assert(ptr.b[1].field == 0); | ||
| 316 | assert(ptr.c == 0); | ||
| 317 | |||
| 318 | ptr.b[0].field = maxInt(u24); | ||
| 319 | assert(ptr.a == maxInt(u16)); | ||
| 320 | assert(ptr.b[0].field == maxInt(u24)); | ||
| 321 | assert(ptr.b[1].field == 0); | ||
| 322 | assert(ptr.c == 0); | ||
| 323 | |||
| 324 | ptr.b[1].field = maxInt(u24); | ||
| 325 | assert(ptr.a == maxInt(u16)); | ||
| 326 | assert(ptr.b[0].field == maxInt(u24)); | ||
| 327 | assert(ptr.b[1].field == maxInt(u24)); | ||
| 328 | assert(ptr.c == 0); | ||
| 329 | |||
| 330 | ptr.c = maxInt(u16); | ||
| 331 | assert(ptr.a == maxInt(u16)); | ||
| 332 | assert(ptr.b[0].field == maxInt(u24)); | ||
| 333 | assert(ptr.b[1].field == maxInt(u24)); | ||
| 334 | assert(ptr.c == maxInt(u16)); | ||
| 335 | |||
| 336 | assert(bytes[bytes.len - 1] == 0xaa); | ||
| 337 | } | ||
| 338 | |||
| 339 | const FooStructAligned = packed struct { | ||
| 340 | a: u8, | ||
| 341 | b: u8, | ||
| 342 | }; | ||
| 343 | |||
| 344 | const FooArrayOfAligned = packed struct { | ||
| 345 | a: [2]FooStructAligned, | ||
| 346 | }; | ||
| 347 | |||
| 348 | test "aligned array of packed struct" { | ||
| 349 | comptime { | ||
| 350 | assert(@sizeOf(FooStructAligned) == 2); | ||
| 351 | assert(@sizeOf(FooArrayOfAligned) == 2 * 2); | ||
| 352 | } | ||
| 353 | |||
| 354 | var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); | ||
| 355 | const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; | ||
| 356 | |||
| 357 | assert(ptr.a[0].a == 0xbb); | ||
| 358 | assert(ptr.a[0].b == 0xbb); | ||
| 359 | assert(ptr.a[1].a == 0xbb); | ||
| 360 | assert(ptr.a[1].b == 0xbb); | ||
| 361 | } | ||
| 362 | |||
| 363 | test "runtime struct initialization of bitfield" { | ||
| 364 | const s1 = Nibbles{ | ||
| 365 | .x = x1, | ||
| 366 | .y = x1, | ||
| 367 | }; | ||
| 368 | const s2 = Nibbles{ | ||
| 369 | .x = @intCast(u4, x2), | ||
| 370 | .y = @intCast(u4, x2), | ||
| 371 | }; | ||
| 372 | |||
| 373 | assert(s1.x == x1); | ||
| 374 | assert(s1.y == x1); | ||
| 375 | assert(s2.x == @intCast(u4, x2)); | ||
| 376 | assert(s2.y == @intCast(u4, x2)); | ||
| 377 | } | ||
| 378 | |||
| 379 | var x1 = u4(1); | ||
| 380 | var x2 = u8(2); | ||
| 381 | |||
| 382 | const Nibbles = packed struct { | ||
| 383 | x: u4, | ||
| 384 | y: u4, | ||
| 385 | }; | ||
| 386 | |||
| 387 | const Bitfields = packed struct { | ||
| 388 | f1: u16, | ||
| 389 | f2: u16, | ||
| 390 | f3: u8, | ||
| 391 | f4: u8, | ||
| 392 | f5: u4, | ||
| 393 | f6: u4, | ||
| 394 | f7: u8, | ||
| 395 | }; | ||
| 396 | |||
| 397 | test "native bit field understands endianness" { | ||
| 398 | var all: u64 = 0x7765443322221111; | ||
| 399 | var bytes: [8]u8 = undefined; | ||
| 400 | @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); | ||
| 401 | var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; | ||
| 402 | |||
| 403 | assert(bitfields.f1 == 0x1111); | ||
| 404 | assert(bitfields.f2 == 0x2222); | ||
| 405 | assert(bitfields.f3 == 0x33); | ||
| 406 | assert(bitfields.f4 == 0x44); | ||
| 407 | assert(bitfields.f5 == 0x5); | ||
| 408 | assert(bitfields.f6 == 0x6); | ||
| 409 | assert(bitfields.f7 == 0x77); | ||
| 410 | } | ||
| 411 | |||
| 412 | test "align 1 field before self referential align 8 field as slice return type" { | ||
| 413 | const result = alloc(Expr); | ||
| 414 | assert(result.len == 0); | ||
| 415 | } | ||
| 416 | |||
| 417 | const Expr = union(enum) { | ||
| 418 | Literal: u8, | ||
| 419 | Question: *Expr, | ||
| 420 | }; | ||
| 421 | |||
| 422 | fn alloc(comptime T: type) []T { | ||
| 423 | return []T{}; | ||
| 424 | } | ||
| 425 | |||
| 426 | test "call method with mutable reference to struct with no fields" { | ||
| 427 | const S = struct { | ||
| 428 | fn doC(s: *const @This()) bool { | ||
| 429 | return true; | ||
| 430 | } | ||
| 431 | fn do(s: *@This()) bool { | ||
| 432 | return true; | ||
| 433 | } | ||
| 434 | }; | ||
| 435 | |||
| 436 | var s = S{}; | ||
| 437 | assert(S.doC(&s)); | ||
| 438 | assert(s.doC()); | ||
| 439 | assert(S.do(&s)); | ||
| 440 | assert(s.do()); | ||
| 441 | } | ||
| 442 | |||
| 443 | test "implicit cast packed struct field to const ptr" { | ||
| 444 | const LevelUpMove = packed struct { | ||
| 445 | move_id: u9, | ||
| 446 | level: u7, | ||
| 447 | |||
| 448 | fn toInt(value: u7) u7 { | ||
| 449 | return value; | ||
| 450 | } | ||
| 451 | }; | ||
| 452 | |||
| 453 | var lup: LevelUpMove = undefined; | ||
| 454 | lup.level = 12; | ||
| 455 | const res = LevelUpMove.toInt(lup.level); | ||
| 456 | assert(res == 12); | ||
| 457 | } | ||
| 458 | |||
| 459 | test "pointer to packed struct member in a stack variable" { | ||
| 460 | const S = packed struct { | ||
| 461 | a: u2, | ||
| 462 | b: u2, | ||
| 463 | }; | ||
| 464 | |||
| 465 | var s = S{ .a = 2, .b = 0 }; | ||
| 466 | var b_ptr = &s.b; | ||
| 467 | assert(s.b == 0); | ||
| 468 | b_ptr.* = 2; | ||
| 469 | assert(s.b == 2); | ||
| 470 | } | ||
test/cases/struct_contains_null_ptr_itself.zig deleted-21| ... | @@ -1,21 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | |||
| 4 | test "struct contains null pointer which contains original struct" { | ||
| 5 | var x: ?*NodeLineComment = null; | ||
| 6 | assert(x == null); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub const Node = struct { | ||
| 10 | id: Id, | ||
| 11 | comment: ?*NodeLineComment, | ||
| 12 | |||
| 13 | pub const Id = enum { | ||
| 14 | Root, | ||
| 15 | LineComment, | ||
| 16 | }; | ||
| 17 | }; | ||
| 18 | |||
| 19 | pub const NodeLineComment = struct { | ||
| 20 | base: Node, | ||
| 21 | }; | ||
test/cases/struct_contains_slice_of_itself.zig deleted-43| ... | @@ -1,43 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const Node = struct { | ||
| 4 | payload: i32, | ||
| 5 | children: []Node, | ||
| 6 | }; | ||
| 7 | |||
| 8 | test "struct contains slice of itself" { | ||
| 9 | var other_nodes = []Node{ | ||
| 10 | Node{ | ||
| 11 | .payload = 31, | ||
| 12 | .children = []Node{}, | ||
| 13 | }, | ||
| 14 | Node{ | ||
| 15 | .payload = 32, | ||
| 16 | .children = []Node{}, | ||
| 17 | }, | ||
| 18 | }; | ||
| 19 | var nodes = []Node{ | ||
| 20 | Node{ | ||
| 21 | .payload = 1, | ||
| 22 | .children = []Node{}, | ||
| 23 | }, | ||
| 24 | Node{ | ||
| 25 | .payload = 2, | ||
| 26 | .children = []Node{}, | ||
| 27 | }, | ||
| 28 | Node{ | ||
| 29 | .payload = 3, | ||
| 30 | .children = other_nodes[0..], | ||
| 31 | }, | ||
| 32 | }; | ||
| 33 | const root = Node{ | ||
| 34 | .payload = 1234, | ||
| 35 | .children = nodes[0..], | ||
| 36 | }; | ||
| 37 | assert(root.payload == 1234); | ||
| 38 | assert(root.children[0].payload == 1); | ||
| 39 | assert(root.children[1].payload == 2); | ||
| 40 | assert(root.children[2].payload == 3); | ||
| 41 | assert(root.children[2].children[0].payload == 31); | ||
| 42 | assert(root.children[2].children[1].payload == 32); | ||
| 43 | } | ||
test/cases/switch.zig deleted-234| ... | @@ -1,234 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "switch with numbers" { | ||
| 4 | testSwitchWithNumbers(13); | ||
| 5 | } | ||
| 6 | |||
| 7 | fn testSwitchWithNumbers(x: u32) void { | ||
| 8 | const result = switch (x) { | ||
| 9 | 1, 2, 3, 4...8 => false, | ||
| 10 | 13 => true, | ||
| 11 | else => false, | ||
| 12 | }; | ||
| 13 | assert(result); | ||
| 14 | } | ||
| 15 | |||
| 16 | test "switch with all ranges" { | ||
| 17 | assert(testSwitchWithAllRanges(50, 3) == 1); | ||
| 18 | assert(testSwitchWithAllRanges(101, 0) == 2); | ||
| 19 | assert(testSwitchWithAllRanges(300, 5) == 3); | ||
| 20 | assert(testSwitchWithAllRanges(301, 6) == 6); | ||
| 21 | } | ||
| 22 | |||
| 23 | fn testSwitchWithAllRanges(x: u32, y: u32) u32 { | ||
| 24 | return switch (x) { | ||
| 25 | 0...100 => 1, | ||
| 26 | 101...200 => 2, | ||
| 27 | 201...300 => 3, | ||
| 28 | else => y, | ||
| 29 | }; | ||
| 30 | } | ||
| 31 | |||
| 32 | test "implicit comptime switch" { | ||
| 33 | const x = 3 + 4; | ||
| 34 | const result = switch (x) { | ||
| 35 | 3 => 10, | ||
| 36 | 4 => 11, | ||
| 37 | 5, 6 => 12, | ||
| 38 | 7, 8 => 13, | ||
| 39 | else => 14, | ||
| 40 | }; | ||
| 41 | |||
| 42 | comptime { | ||
| 43 | assert(result + 1 == 14); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | test "switch on enum" { | ||
| 48 | const fruit = Fruit.Orange; | ||
| 49 | nonConstSwitchOnEnum(fruit); | ||
| 50 | } | ||
| 51 | const Fruit = enum { | ||
| 52 | Apple, | ||
| 53 | Orange, | ||
| 54 | Banana, | ||
| 55 | }; | ||
| 56 | fn nonConstSwitchOnEnum(fruit: Fruit) void { | ||
| 57 | switch (fruit) { | ||
| 58 | Fruit.Apple => unreachable, | ||
| 59 | Fruit.Orange => {}, | ||
| 60 | Fruit.Banana => unreachable, | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | test "switch statement" { | ||
| 65 | nonConstSwitch(SwitchStatmentFoo.C); | ||
| 66 | } | ||
| 67 | fn nonConstSwitch(foo: SwitchStatmentFoo) void { | ||
| 68 | const val = switch (foo) { | ||
| 69 | SwitchStatmentFoo.A => i32(1), | ||
| 70 | SwitchStatmentFoo.B => 2, | ||
| 71 | SwitchStatmentFoo.C => 3, | ||
| 72 | SwitchStatmentFoo.D => 4, | ||
| 73 | }; | ||
| 74 | assert(val == 3); | ||
| 75 | } | ||
| 76 | const SwitchStatmentFoo = enum { | ||
| 77 | A, | ||
| 78 | B, | ||
| 79 | C, | ||
| 80 | D, | ||
| 81 | }; | ||
| 82 | |||
| 83 | test "switch prong with variable" { | ||
| 84 | switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 }); | ||
| 85 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 }); | ||
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} }); | ||
| 87 | } | ||
| 88 | const SwitchProngWithVarEnum = union(enum) { | ||
| 89 | One: i32, | ||
| 90 | Two: f32, | ||
| 91 | Meh: void, | ||
| 92 | }; | ||
| 93 | fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void { | ||
| 94 | switch (a) { | ||
| 95 | SwitchProngWithVarEnum.One => |x| { | ||
| 96 | assert(x == 13); | ||
| 97 | }, | ||
| 98 | SwitchProngWithVarEnum.Two => |x| { | ||
| 99 | assert(x == 13.0); | ||
| 100 | }, | ||
| 101 | SwitchProngWithVarEnum.Meh => |x| { | ||
| 102 | const v: void = x; | ||
| 103 | }, | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | test "switch on enum using pointer capture" { | ||
| 108 | testSwitchEnumPtrCapture(); | ||
| 109 | comptime testSwitchEnumPtrCapture(); | ||
| 110 | } | ||
| 111 | |||
| 112 | fn testSwitchEnumPtrCapture() void { | ||
| 113 | var value = SwitchProngWithVarEnum{ .One = 1234 }; | ||
| 114 | switch (value) { | ||
| 115 | SwitchProngWithVarEnum.One => |*x| x.* += 1, | ||
| 116 | else => unreachable, | ||
| 117 | } | ||
| 118 | switch (value) { | ||
| 119 | SwitchProngWithVarEnum.One => |x| assert(x == 1235), | ||
| 120 | else => unreachable, | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | test "switch with multiple expressions" { | ||
| 125 | const x = switch (returnsFive()) { | ||
| 126 | 1, 2, 3 => 1, | ||
| 127 | 4, 5, 6 => 2, | ||
| 128 | else => i32(3), | ||
| 129 | }; | ||
| 130 | assert(x == 2); | ||
| 131 | } | ||
| 132 | fn returnsFive() i32 { | ||
| 133 | return 5; | ||
| 134 | } | ||
| 135 | |||
| 136 | const Number = union(enum) { | ||
| 137 | One: u64, | ||
| 138 | Two: u8, | ||
| 139 | Three: f32, | ||
| 140 | }; | ||
| 141 | |||
| 142 | const number = Number{ .Three = 1.23 }; | ||
| 143 | |||
| 144 | fn returnsFalse() bool { | ||
| 145 | switch (number) { | ||
| 146 | Number.One => |x| return x > 1234, | ||
| 147 | Number.Two => |x| return x == 'a', | ||
| 148 | Number.Three => |x| return x > 12.34, | ||
| 149 | } | ||
| 150 | } | ||
| 151 | test "switch on const enum with var" { | ||
| 152 | assert(!returnsFalse()); | ||
| 153 | } | ||
| 154 | |||
| 155 | test "switch on type" { | ||
| 156 | assert(trueIfBoolFalseOtherwise(bool)); | ||
| 157 | assert(!trueIfBoolFalseOtherwise(i32)); | ||
| 158 | } | ||
| 159 | |||
| 160 | fn trueIfBoolFalseOtherwise(comptime T: type) bool { | ||
| 161 | return switch (T) { | ||
| 162 | bool => true, | ||
| 163 | else => false, | ||
| 164 | }; | ||
| 165 | } | ||
| 166 | |||
| 167 | test "switch handles all cases of number" { | ||
| 168 | testSwitchHandleAllCases(); | ||
| 169 | comptime testSwitchHandleAllCases(); | ||
| 170 | } | ||
| 171 | |||
| 172 | fn testSwitchHandleAllCases() void { | ||
| 173 | assert(testSwitchHandleAllCasesExhaustive(0) == 3); | ||
| 174 | assert(testSwitchHandleAllCasesExhaustive(1) == 2); | ||
| 175 | assert(testSwitchHandleAllCasesExhaustive(2) == 1); | ||
| 176 | assert(testSwitchHandleAllCasesExhaustive(3) == 0); | ||
| 177 | |||
| 178 | assert(testSwitchHandleAllCasesRange(100) == 0); | ||
| 179 | assert(testSwitchHandleAllCasesRange(200) == 1); | ||
| 180 | assert(testSwitchHandleAllCasesRange(201) == 2); | ||
| 181 | assert(testSwitchHandleAllCasesRange(202) == 4); | ||
| 182 | assert(testSwitchHandleAllCasesRange(230) == 3); | ||
| 183 | } | ||
| 184 | |||
| 185 | fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { | ||
| 186 | return switch (x) { | ||
| 187 | 0 => u2(3), | ||
| 188 | 1 => 2, | ||
| 189 | 2 => 1, | ||
| 190 | 3 => 0, | ||
| 191 | }; | ||
| 192 | } | ||
| 193 | |||
| 194 | fn testSwitchHandleAllCasesRange(x: u8) u8 { | ||
| 195 | return switch (x) { | ||
| 196 | 0...100 => u8(0), | ||
| 197 | 101...200 => 1, | ||
| 198 | 201, 203 => 2, | ||
| 199 | 202 => 4, | ||
| 200 | 204...255 => 3, | ||
| 201 | }; | ||
| 202 | } | ||
| 203 | |||
| 204 | test "switch all prongs unreachable" { | ||
| 205 | testAllProngsUnreachable(); | ||
| 206 | comptime testAllProngsUnreachable(); | ||
| 207 | } | ||
| 208 | |||
| 209 | fn testAllProngsUnreachable() void { | ||
| 210 | assert(switchWithUnreachable(1) == 2); | ||
| 211 | assert(switchWithUnreachable(2) == 10); | ||
| 212 | } | ||
| 213 | |||
| 214 | fn switchWithUnreachable(x: i32) i32 { | ||
| 215 | while (true) { | ||
| 216 | switch (x) { | ||
| 217 | 1 => return 2, | ||
| 218 | 2 => break, | ||
| 219 | else => continue, | ||
| 220 | } | ||
| 221 | } | ||
| 222 | return 10; | ||
| 223 | } | ||
| 224 | |||
| 225 | fn return_a_number() anyerror!i32 { | ||
| 226 | return 1; | ||
| 227 | } | ||
| 228 | |||
| 229 | test "capture value of switch with all unreachable prongs" { | ||
| 230 | const x = return_a_number() catch |err| switch (err) { | ||
| 231 | else => unreachable, | ||
| 232 | }; | ||
| 233 | assert(x == 1); | ||
| 234 | } | ||
test/cases/switch_prong_err_enum.zig deleted-30| ... | @@ -1,30 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | var read_count: u64 = 0; | ||
| 4 | |||
| 5 | fn readOnce() anyerror!u64 { | ||
| 6 | read_count += 1; | ||
| 7 | return read_count; | ||
| 8 | } | ||
| 9 | |||
| 10 | const FormValue = union(enum) { | ||
| 11 | Address: u64, | ||
| 12 | Other: bool, | ||
| 13 | }; | ||
| 14 | |||
| 15 | fn doThing(form_id: u64) anyerror!FormValue { | ||
| 16 | return switch (form_id) { | ||
| 17 | 17 => FormValue{ .Address = try readOnce() }, | ||
| 18 | else => error.InvalidDebugInfo, | ||
| 19 | }; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "switch prong returns error enum" { | ||
| 23 | switch (doThing(17) catch unreachable) { | ||
| 24 | FormValue.Address => |payload| { | ||
| 25 | assert(payload == 1); | ||
| 26 | }, | ||
| 27 | else => unreachable, | ||
| 28 | } | ||
| 29 | assert(read_count == 1); | ||
| 30 | } | ||
test/cases/switch_prong_implicit_cast.zig deleted-22| ... | @@ -1,22 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const FormValue = union(enum) { | ||
| 4 | One: void, | ||
| 5 | Two: bool, | ||
| 6 | }; | ||
| 7 | |||
| 8 | fn foo(id: u64) !FormValue { | ||
| 9 | return switch (id) { | ||
| 10 | 2 => FormValue{ .Two = true }, | ||
| 11 | 1 => FormValue{ .One = {} }, | ||
| 12 | else => return error.Whatever, | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | |||
| 16 | test "switch prong implicit cast" { | ||
| 17 | const result = switch (foo(2) catch unreachable) { | ||
| 18 | FormValue.One => false, | ||
| 19 | FormValue.Two => |x| x, | ||
| 20 | }; | ||
| 21 | assert(result); | ||
| 22 | } | ||
test/cases/syntax.zig deleted-59| ... | @@ -1,59 +0,0 @@ | ||
| 1 | // Test trailing comma syntax | ||
| 2 | // zig fmt: off | ||
| 3 | |||
| 4 | const struct_trailing_comma = struct { x: i32, y: i32, }; | ||
| 5 | const struct_no_comma = struct { x: i32, y: i32 }; | ||
| 6 | const struct_fn_no_comma = struct { fn m() void {} y: i32 }; | ||
| 7 | |||
| 8 | const enum_no_comma = enum { A, B }; | ||
| 9 | |||
| 10 | fn container_init() void { | ||
| 11 | const S = struct { x: i32, y: i32 }; | ||
| 12 | _ = S { .x = 1, .y = 2 }; | ||
| 13 | _ = S { .x = 1, .y = 2, }; | ||
| 14 | } | ||
| 15 | |||
| 16 | fn type_expr_return1() if (true) A {} | ||
| 17 | fn type_expr_return2() for (true) |_| A {} | ||
| 18 | fn type_expr_return3() while (true) A {} | ||
| 19 | fn type_expr_return4() comptime A {} | ||
| 20 | |||
| 21 | fn switch_cases(x: i32) void { | ||
| 22 | switch (x) { | ||
| 23 | 1,2,3 => {}, | ||
| 24 | 4,5, => {}, | ||
| 25 | 6...8, => {}, | ||
| 26 | else => {}, | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | fn switch_prongs(x: i32) void { | ||
| 31 | switch (x) { | ||
| 32 | 0 => {}, | ||
| 33 | else => {}, | ||
| 34 | } | ||
| 35 | switch (x) { | ||
| 36 | 0 => {}, | ||
| 37 | else => {} | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | const fn_no_comma = fn(i32, i32)void; | ||
| 42 | const fn_trailing_comma = fn(i32, i32,)void; | ||
| 43 | |||
| 44 | fn fn_calls() void { | ||
| 45 | fn add(x: i32, y: i32,) i32 { x + y }; | ||
| 46 | _ = add(1, 2); | ||
| 47 | _ = add(1, 2,); | ||
| 48 | } | ||
| 49 | |||
| 50 | fn asm_lists() void { | ||
| 51 | if (false) { // Build AST but don't analyze | ||
| 52 | asm ("not real assembly" | ||
| 53 | :[a] "x" (x),); | ||
| 54 | asm ("not real assembly" | ||
| 55 | :[a] "x" (->i32),:[a] "x" (1),); | ||
| 56 | asm ("still not real assembly" | ||
| 57 | :::"a","b",); | ||
| 58 | } | ||
| 59 | } | ||
test/cases/this.zig deleted-34| ... | @@ -1,34 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const module = @This(); | ||
| 4 | |||
| 5 | fn Point(comptime T: type) type { | ||
| 6 | return struct { | ||
| 7 | const Self = @This(); | ||
| 8 | x: T, | ||
| 9 | y: T, | ||
| 10 | |||
| 11 | fn addOne(self: *Self) void { | ||
| 12 | self.x += 1; | ||
| 13 | self.y += 1; | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | fn add(x: i32, y: i32) i32 { | ||
| 19 | return x + y; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "this refer to module call private fn" { | ||
| 23 | assert(module.add(1, 2) == 3); | ||
| 24 | } | ||
| 25 | |||
| 26 | test "this refer to container" { | ||
| 27 | var pt = Point(i32){ | ||
| 28 | .x = 12, | ||
| 29 | .y = 34, | ||
| 30 | }; | ||
| 31 | pt.addOne(); | ||
| 32 | assert(pt.x == 13); | ||
| 33 | assert(pt.y == 35); | ||
| 34 | } | ||
test/cases/try.zig deleted-43| ... | @@ -1,43 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "try on error union" { | ||
| 4 | tryOnErrorUnionImpl(); | ||
| 5 | comptime tryOnErrorUnionImpl(); | ||
| 6 | } | ||
| 7 | |||
| 8 | fn tryOnErrorUnionImpl() void { | ||
| 9 | const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { | ||
| 10 | error.ItBroke, error.NoMem => 1, | ||
| 11 | error.CrappedOut => i32(2), | ||
| 12 | else => unreachable, | ||
| 13 | }; | ||
| 14 | assert(x == 11); | ||
| 15 | } | ||
| 16 | |||
| 17 | fn returnsTen() anyerror!i32 { | ||
| 18 | return 10; | ||
| 19 | } | ||
| 20 | |||
| 21 | test "try without vars" { | ||
| 22 | const result1 = if (failIfTrue(true)) 1 else |_| i32(2); | ||
| 23 | assert(result1 == 2); | ||
| 24 | |||
| 25 | const result2 = if (failIfTrue(false)) 1 else |_| i32(2); | ||
| 26 | assert(result2 == 1); | ||
| 27 | } | ||
| 28 | |||
| 29 | fn failIfTrue(ok: bool) anyerror!void { | ||
| 30 | if (ok) { | ||
| 31 | return error.ItBroke; | ||
| 32 | } else { | ||
| 33 | return; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | test "try then not executed with assignment" { | ||
| 38 | if (failIfTrue(true)) { | ||
| 39 | unreachable; | ||
| 40 | } else |err| { | ||
| 41 | assert(err == error.ItBroke); | ||
| 42 | } | ||
| 43 | } | ||
test/cases/type_info.zig deleted-259| ... | @@ -1,259 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | const TypeInfo = @import("builtin").TypeInfo; | ||
| 4 | const TypeId = @import("builtin").TypeId; | ||
| 5 | |||
| 6 | test "type info: tag type, void info" { | ||
| 7 | testBasic(); | ||
| 8 | comptime testBasic(); | ||
| 9 | } | ||
| 10 | |||
| 11 | fn testBasic() void { | ||
| 12 | assert(@TagType(TypeInfo) == TypeId); | ||
| 13 | const void_info = @typeInfo(void); | ||
| 14 | assert(TypeId(void_info) == TypeId.Void); | ||
| 15 | assert(void_info.Void == {}); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "type info: integer, floating point type info" { | ||
| 19 | testIntFloat(); | ||
| 20 | comptime testIntFloat(); | ||
| 21 | } | ||
| 22 | |||
| 23 | fn testIntFloat() void { | ||
| 24 | const u8_info = @typeInfo(u8); | ||
| 25 | assert(TypeId(u8_info) == TypeId.Int); | ||
| 26 | assert(!u8_info.Int.is_signed); | ||
| 27 | assert(u8_info.Int.bits == 8); | ||
| 28 | |||
| 29 | const f64_info = @typeInfo(f64); | ||
| 30 | assert(TypeId(f64_info) == TypeId.Float); | ||
| 31 | assert(f64_info.Float.bits == 64); | ||
| 32 | } | ||
| 33 | |||
| 34 | test "type info: pointer type info" { | ||
| 35 | testPointer(); | ||
| 36 | comptime testPointer(); | ||
| 37 | } | ||
| 38 | |||
| 39 | fn testPointer() void { | ||
| 40 | const u32_ptr_info = @typeInfo(*u32); | ||
| 41 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); | ||
| 42 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); | ||
| 43 | assert(u32_ptr_info.Pointer.is_const == false); | ||
| 44 | assert(u32_ptr_info.Pointer.is_volatile == false); | ||
| 45 | assert(u32_ptr_info.Pointer.alignment == @alignOf(u32)); | ||
| 46 | assert(u32_ptr_info.Pointer.child == u32); | ||
| 47 | } | ||
| 48 | |||
| 49 | test "type info: unknown length pointer type info" { | ||
| 50 | testUnknownLenPtr(); | ||
| 51 | comptime testUnknownLenPtr(); | ||
| 52 | } | ||
| 53 | |||
| 54 | fn testUnknownLenPtr() void { | ||
| 55 | const u32_ptr_info = @typeInfo([*]const volatile f64); | ||
| 56 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); | ||
| 57 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); | ||
| 58 | assert(u32_ptr_info.Pointer.is_const == true); | ||
| 59 | assert(u32_ptr_info.Pointer.is_volatile == true); | ||
| 60 | assert(u32_ptr_info.Pointer.alignment == @alignOf(f64)); | ||
| 61 | assert(u32_ptr_info.Pointer.child == f64); | ||
| 62 | } | ||
| 63 | |||
| 64 | test "type info: slice type info" { | ||
| 65 | testSlice(); | ||
| 66 | comptime testSlice(); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn testSlice() void { | ||
| 70 | const u32_slice_info = @typeInfo([]u32); | ||
| 71 | assert(TypeId(u32_slice_info) == TypeId.Pointer); | ||
| 72 | assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); | ||
| 73 | assert(u32_slice_info.Pointer.is_const == false); | ||
| 74 | assert(u32_slice_info.Pointer.is_volatile == false); | ||
| 75 | assert(u32_slice_info.Pointer.alignment == 4); | ||
| 76 | assert(u32_slice_info.Pointer.child == u32); | ||
| 77 | } | ||
| 78 | |||
| 79 | test "type info: array type info" { | ||
| 80 | testArray(); | ||
| 81 | comptime testArray(); | ||
| 82 | } | ||
| 83 | |||
| 84 | fn testArray() void { | ||
| 85 | const arr_info = @typeInfo([42]bool); | ||
| 86 | assert(TypeId(arr_info) == TypeId.Array); | ||
| 87 | assert(arr_info.Array.len == 42); | ||
| 88 | assert(arr_info.Array.child == bool); | ||
| 89 | } | ||
| 90 | |||
| 91 | test "type info: optional type info" { | ||
| 92 | testOptional(); | ||
| 93 | comptime testOptional(); | ||
| 94 | } | ||
| 95 | |||
| 96 | fn testOptional() void { | ||
| 97 | const null_info = @typeInfo(?void); | ||
| 98 | assert(TypeId(null_info) == TypeId.Optional); | ||
| 99 | assert(null_info.Optional.child == void); | ||
| 100 | } | ||
| 101 | |||
| 102 | test "type info: promise info" { | ||
| 103 | testPromise(); | ||
| 104 | comptime testPromise(); | ||
| 105 | } | ||
| 106 | |||
| 107 | fn testPromise() void { | ||
| 108 | const null_promise_info = @typeInfo(promise); | ||
| 109 | assert(TypeId(null_promise_info) == TypeId.Promise); | ||
| 110 | assert(null_promise_info.Promise.child == null); | ||
| 111 | |||
| 112 | const promise_info = @typeInfo(promise->usize); | ||
| 113 | assert(TypeId(promise_info) == TypeId.Promise); | ||
| 114 | assert(promise_info.Promise.child.? == usize); | ||
| 115 | } | ||
| 116 | |||
| 117 | test "type info: error set, error union info" { | ||
| 118 | testErrorSet(); | ||
| 119 | comptime testErrorSet(); | ||
| 120 | } | ||
| 121 | |||
| 122 | fn testErrorSet() void { | ||
| 123 | const TestErrorSet = error{ | ||
| 124 | First, | ||
| 125 | Second, | ||
| 126 | Third, | ||
| 127 | }; | ||
| 128 | |||
| 129 | const error_set_info = @typeInfo(TestErrorSet); | ||
| 130 | assert(TypeId(error_set_info) == TypeId.ErrorSet); | ||
| 131 | assert(error_set_info.ErrorSet.errors.len == 3); | ||
| 132 | assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); | ||
| 133 | assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); | ||
| 134 | |||
| 135 | const error_union_info = @typeInfo(TestErrorSet!usize); | ||
| 136 | assert(TypeId(error_union_info) == TypeId.ErrorUnion); | ||
| 137 | assert(error_union_info.ErrorUnion.error_set == TestErrorSet); | ||
| 138 | assert(error_union_info.ErrorUnion.payload == usize); | ||
| 139 | } | ||
| 140 | |||
| 141 | test "type info: enum info" { | ||
| 142 | testEnum(); | ||
| 143 | comptime testEnum(); | ||
| 144 | } | ||
| 145 | |||
| 146 | fn testEnum() void { | ||
| 147 | const Os = @import("builtin").Os; | ||
| 148 | |||
| 149 | const os_info = @typeInfo(Os); | ||
| 150 | assert(TypeId(os_info) == TypeId.Enum); | ||
| 151 | assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); | ||
| 152 | assert(os_info.Enum.fields.len == 32); | ||
| 153 | assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); | ||
| 154 | assert(os_info.Enum.fields[10].value == 10); | ||
| 155 | assert(os_info.Enum.tag_type == u5); | ||
| 156 | assert(os_info.Enum.defs.len == 0); | ||
| 157 | } | ||
| 158 | |||
| 159 | test "type info: union info" { | ||
| 160 | testUnion(); | ||
| 161 | comptime testUnion(); | ||
| 162 | } | ||
| 163 | |||
| 164 | fn testUnion() void { | ||
| 165 | const typeinfo_info = @typeInfo(TypeInfo); | ||
| 166 | assert(TypeId(typeinfo_info) == TypeId.Union); | ||
| 167 | assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); | ||
| 168 | assert(typeinfo_info.Union.tag_type.? == TypeId); | ||
| 169 | assert(typeinfo_info.Union.fields.len == 24); | ||
| 170 | assert(typeinfo_info.Union.fields[4].enum_field != null); | ||
| 171 | assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4); | ||
| 172 | assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); | ||
| 173 | assert(typeinfo_info.Union.defs.len == 20); | ||
| 174 | |||
| 175 | const TestNoTagUnion = union { | ||
| 176 | Foo: void, | ||
| 177 | Bar: u32, | ||
| 178 | }; | ||
| 179 | |||
| 180 | const notag_union_info = @typeInfo(TestNoTagUnion); | ||
| 181 | assert(TypeId(notag_union_info) == TypeId.Union); | ||
| 182 | assert(notag_union_info.Union.tag_type == null); | ||
| 183 | assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); | ||
| 184 | assert(notag_union_info.Union.fields.len == 2); | ||
| 185 | assert(notag_union_info.Union.fields[0].enum_field == null); | ||
| 186 | assert(notag_union_info.Union.fields[1].field_type == u32); | ||
| 187 | |||
| 188 | const TestExternUnion = extern union { | ||
| 189 | foo: *c_void, | ||
| 190 | }; | ||
| 191 | |||
| 192 | const extern_union_info = @typeInfo(TestExternUnion); | ||
| 193 | assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); | ||
| 194 | assert(extern_union_info.Union.tag_type == null); | ||
| 195 | assert(extern_union_info.Union.fields[0].enum_field == null); | ||
| 196 | assert(extern_union_info.Union.fields[0].field_type == *c_void); | ||
| 197 | } | ||
| 198 | |||
| 199 | test "type info: struct info" { | ||
| 200 | testStruct(); | ||
| 201 | comptime testStruct(); | ||
| 202 | } | ||
| 203 | |||
| 204 | fn testStruct() void { | ||
| 205 | const struct_info = @typeInfo(TestStruct); | ||
| 206 | assert(TypeId(struct_info) == TypeId.Struct); | ||
| 207 | assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); | ||
| 208 | assert(struct_info.Struct.fields.len == 3); | ||
| 209 | assert(struct_info.Struct.fields[1].offset == null); | ||
| 210 | assert(struct_info.Struct.fields[2].field_type == *TestStruct); | ||
| 211 | assert(struct_info.Struct.defs.len == 2); | ||
| 212 | assert(struct_info.Struct.defs[0].is_pub); | ||
| 213 | assert(!struct_info.Struct.defs[0].data.Fn.is_extern); | ||
| 214 | assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); | ||
| 215 | assert(struct_info.Struct.defs[0].data.Fn.return_type == void); | ||
| 216 | assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); | ||
| 217 | } | ||
| 218 | |||
| 219 | const TestStruct = packed struct { | ||
| 220 | const Self = @This(); | ||
| 221 | |||
| 222 | fieldA: usize, | ||
| 223 | fieldB: void, | ||
| 224 | fieldC: *Self, | ||
| 225 | |||
| 226 | pub fn foo(self: *const Self) void {} | ||
| 227 | }; | ||
| 228 | |||
| 229 | test "type info: function type info" { | ||
| 230 | testFunction(); | ||
| 231 | comptime testFunction(); | ||
| 232 | } | ||
| 233 | |||
| 234 | fn testFunction() void { | ||
| 235 | const fn_info = @typeInfo(@typeOf(foo)); | ||
| 236 | assert(TypeId(fn_info) == TypeId.Fn); | ||
| 237 | assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); | ||
| 238 | assert(fn_info.Fn.is_generic); | ||
| 239 | assert(fn_info.Fn.args.len == 2); | ||
| 240 | assert(fn_info.Fn.is_var_args); | ||
| 241 | assert(fn_info.Fn.return_type == null); | ||
| 242 | assert(fn_info.Fn.async_allocator_type == null); | ||
| 243 | |||
| 244 | const test_instance: TestStruct = undefined; | ||
| 245 | const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); | ||
| 246 | assert(TypeId(bound_fn_info) == TypeId.BoundFn); | ||
| 247 | assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); | ||
| 248 | } | ||
| 249 | |||
| 250 | fn foo(comptime a: usize, b: bool, args: ...) usize { | ||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | test "typeInfo with comptime parameter in struct fn def" { | ||
| 255 | const S = struct { | ||
| 256 | pub fn func(comptime x: f32) void {} | ||
| 257 | }; | ||
| 258 | comptime var info = @typeInfo(S); | ||
| 259 | } | ||
test/cases/undefined.zig deleted-68| ... | @@ -1,68 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | fn initStaticArray() [10]i32 { | ||
| 5 | var array: [10]i32 = undefined; | ||
| 6 | array[0] = 1; | ||
| 7 | array[4] = 2; | ||
| 8 | array[7] = 3; | ||
| 9 | array[9] = 4; | ||
| 10 | return array; | ||
| 11 | } | ||
| 12 | const static_array = initStaticArray(); | ||
| 13 | test "init static array to undefined" { | ||
| 14 | assert(static_array[0] == 1); | ||
| 15 | assert(static_array[4] == 2); | ||
| 16 | assert(static_array[7] == 3); | ||
| 17 | assert(static_array[9] == 4); | ||
| 18 | |||
| 19 | comptime { | ||
| 20 | assert(static_array[0] == 1); | ||
| 21 | assert(static_array[4] == 2); | ||
| 22 | assert(static_array[7] == 3); | ||
| 23 | assert(static_array[9] == 4); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | const Foo = struct { | ||
| 28 | x: i32, | ||
| 29 | |||
| 30 | fn setFooXMethod(foo: *Foo) void { | ||
| 31 | foo.x = 3; | ||
| 32 | } | ||
| 33 | }; | ||
| 34 | |||
| 35 | fn setFooX(foo: *Foo) void { | ||
| 36 | foo.x = 2; | ||
| 37 | } | ||
| 38 | |||
| 39 | test "assign undefined to struct" { | ||
| 40 | comptime { | ||
| 41 | var foo: Foo = undefined; | ||
| 42 | setFooX(&foo); | ||
| 43 | assert(foo.x == 2); | ||
| 44 | } | ||
| 45 | { | ||
| 46 | var foo: Foo = undefined; | ||
| 47 | setFooX(&foo); | ||
| 48 | assert(foo.x == 2); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | test "assign undefined to struct with method" { | ||
| 53 | comptime { | ||
| 54 | var foo: Foo = undefined; | ||
| 55 | foo.setFooXMethod(); | ||
| 56 | assert(foo.x == 3); | ||
| 57 | } | ||
| 58 | { | ||
| 59 | var foo: Foo = undefined; | ||
| 60 | foo.setFooXMethod(); | ||
| 61 | assert(foo.x == 3); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | test "type name of undefined" { | ||
| 66 | const x = undefined; | ||
| 67 | assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); | ||
| 68 | } | ||
test/cases/underscore.zig deleted-28| ... | @@ -1,28 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | |||
| 4 | test "ignore lval with underscore" { | ||
| 5 | _ = false; | ||
| 6 | } | ||
| 7 | |||
| 8 | test "ignore lval with underscore (for loop)" { | ||
| 9 | for ([]void{}) |_, i| { | ||
| 10 | for ([]void{}) |_, j| { | ||
| 11 | break; | ||
| 12 | } | ||
| 13 | break; | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | test "ignore lval with underscore (while loop)" { | ||
| 18 | while (optionalReturnError()) |_| { | ||
| 19 | while (optionalReturnError()) |_| { | ||
| 20 | break; | ||
| 21 | } else |_| {} | ||
| 22 | break; | ||
| 23 | } else |_| {} | ||
| 24 | } | ||
| 25 | |||
| 26 | fn optionalReturnError() !?u32 { | ||
| 27 | return error.optionalReturnError; | ||
| 28 | } | ||
test/cases/union.zig deleted-352| ... | @@ -1,352 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const Value = union(enum) { | ||
| 4 | Int: u64, | ||
| 5 | Array: [9]u8, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const Agg = struct { | ||
| 9 | val1: Value, | ||
| 10 | val2: Value, | ||
| 11 | }; | ||
| 12 | |||
| 13 | const v1 = Value{ .Int = 1234 }; | ||
| 14 | const v2 = Value{ .Array = []u8{3} ** 9 }; | ||
| 15 | |||
| 16 | const err = (anyerror!Agg)(Agg{ | ||
| 17 | .val1 = v1, | ||
| 18 | .val2 = v2, | ||
| 19 | }); | ||
| 20 | |||
| 21 | const array = []Value{ | ||
| 22 | v1, | ||
| 23 | v2, | ||
| 24 | v1, | ||
| 25 | v2, | ||
| 26 | }; | ||
| 27 | |||
| 28 | test "unions embedded in aggregate types" { | ||
| 29 | switch (array[1]) { | ||
| 30 | Value.Array => |arr| assert(arr[4] == 3), | ||
| 31 | else => unreachable, | ||
| 32 | } | ||
| 33 | switch ((err catch unreachable).val1) { | ||
| 34 | Value.Int => |x| assert(x == 1234), | ||
| 35 | else => unreachable, | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | const Foo = union { | ||
| 40 | float: f64, | ||
| 41 | int: i32, | ||
| 42 | }; | ||
| 43 | |||
| 44 | test "basic unions" { | ||
| 45 | var foo = Foo{ .int = 1 }; | ||
| 46 | assert(foo.int == 1); | ||
| 47 | foo = Foo{ .float = 12.34 }; | ||
| 48 | assert(foo.float == 12.34); | ||
| 49 | } | ||
| 50 | |||
| 51 | test "comptime union field access" { | ||
| 52 | comptime { | ||
| 53 | var foo = Foo{ .int = 0 }; | ||
| 54 | assert(foo.int == 0); | ||
| 55 | |||
| 56 | foo = Foo{ .float = 42.42 }; | ||
| 57 | assert(foo.float == 42.42); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | test "init union with runtime value" { | ||
| 62 | var foo: Foo = undefined; | ||
| 63 | |||
| 64 | setFloat(&foo, 12.34); | ||
| 65 | assert(foo.float == 12.34); | ||
| 66 | |||
| 67 | setInt(&foo, 42); | ||
| 68 | assert(foo.int == 42); | ||
| 69 | } | ||
| 70 | |||
| 71 | fn setFloat(foo: *Foo, x: f64) void { | ||
| 72 | foo.* = Foo{ .float = x }; | ||
| 73 | } | ||
| 74 | |||
| 75 | fn setInt(foo: *Foo, x: i32) void { | ||
| 76 | foo.* = Foo{ .int = x }; | ||
| 77 | } | ||
| 78 | |||
| 79 | const FooExtern = extern union { | ||
| 80 | float: f64, | ||
| 81 | int: i32, | ||
| 82 | }; | ||
| 83 | |||
| 84 | test "basic extern unions" { | ||
| 85 | var foo = FooExtern{ .int = 1 }; | ||
| 86 | assert(foo.int == 1); | ||
| 87 | foo.float = 12.34; | ||
| 88 | assert(foo.float == 12.34); | ||
| 89 | } | ||
| 90 | |||
| 91 | const Letter = enum { | ||
| 92 | A, | ||
| 93 | B, | ||
| 94 | C, | ||
| 95 | }; | ||
| 96 | const Payload = union(Letter) { | ||
| 97 | A: i32, | ||
| 98 | B: f64, | ||
| 99 | C: bool, | ||
| 100 | }; | ||
| 101 | |||
| 102 | test "union with specified enum tag" { | ||
| 103 | doTest(); | ||
| 104 | comptime doTest(); | ||
| 105 | } | ||
| 106 | |||
| 107 | fn doTest() void { | ||
| 108 | assert(bar(Payload{ .A = 1234 }) == -10); | ||
| 109 | } | ||
| 110 | |||
| 111 | fn bar(value: Payload) i32 { | ||
| 112 | assert(Letter(value) == Letter.A); | ||
| 113 | return switch (value) { | ||
| 114 | Payload.A => |x| return x - 1244, | ||
| 115 | Payload.B => |x| if (x == 12.34) i32(20) else 21, | ||
| 116 | Payload.C => |x| if (x) i32(30) else 31, | ||
| 117 | }; | ||
| 118 | } | ||
| 119 | |||
| 120 | const MultipleChoice = union(enum(u32)) { | ||
| 121 | A = 20, | ||
| 122 | B = 40, | ||
| 123 | C = 60, | ||
| 124 | D = 1000, | ||
| 125 | }; | ||
| 126 | test "simple union(enum(u32))" { | ||
| 127 | var x = MultipleChoice.C; | ||
| 128 | assert(x == MultipleChoice.C); | ||
| 129 | assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60); | ||
| 130 | } | ||
| 131 | |||
| 132 | const MultipleChoice2 = union(enum(u32)) { | ||
| 133 | Unspecified1: i32, | ||
| 134 | A: f32 = 20, | ||
| 135 | Unspecified2: void, | ||
| 136 | B: bool = 40, | ||
| 137 | Unspecified3: i32, | ||
| 138 | C: i8 = 60, | ||
| 139 | Unspecified4: void, | ||
| 140 | D: void = 1000, | ||
| 141 | Unspecified5: i32, | ||
| 142 | }; | ||
| 143 | |||
| 144 | test "union(enum(u32)) with specified and unspecified tag values" { | ||
| 145 | comptime assert(@TagType(@TagType(MultipleChoice2)) == u32); | ||
| 146 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 147 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 148 | } | ||
| 149 | |||
| 150 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | ||
| 151 | assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); | ||
| 152 | assert(1123 == switch (x) { | ||
| 153 | MultipleChoice2.A => 1, | ||
| 154 | MultipleChoice2.B => 2, | ||
| 155 | MultipleChoice2.C => |v| i32(1000) + v, | ||
| 156 | MultipleChoice2.D => 4, | ||
| 157 | MultipleChoice2.Unspecified1 => 5, | ||
| 158 | MultipleChoice2.Unspecified2 => 6, | ||
| 159 | MultipleChoice2.Unspecified3 => 7, | ||
| 160 | MultipleChoice2.Unspecified4 => 8, | ||
| 161 | MultipleChoice2.Unspecified5 => 9, | ||
| 162 | }); | ||
| 163 | } | ||
| 164 | |||
| 165 | const ExternPtrOrInt = extern union { | ||
| 166 | ptr: *u8, | ||
| 167 | int: u64, | ||
| 168 | }; | ||
| 169 | test "extern union size" { | ||
| 170 | comptime assert(@sizeOf(ExternPtrOrInt) == 8); | ||
| 171 | } | ||
| 172 | |||
| 173 | const PackedPtrOrInt = packed union { | ||
| 174 | ptr: *u8, | ||
| 175 | int: u64, | ||
| 176 | }; | ||
| 177 | test "extern union size" { | ||
| 178 | comptime assert(@sizeOf(PackedPtrOrInt) == 8); | ||
| 179 | } | ||
| 180 | |||
| 181 | const ZeroBits = union { | ||
| 182 | OnlyField: void, | ||
| 183 | }; | ||
| 184 | test "union with only 1 field which is void should be zero bits" { | ||
| 185 | comptime assert(@sizeOf(ZeroBits) == 0); | ||
| 186 | } | ||
| 187 | |||
| 188 | const TheTag = enum { | ||
| 189 | A, | ||
| 190 | B, | ||
| 191 | C, | ||
| 192 | }; | ||
| 193 | const TheUnion = union(TheTag) { | ||
| 194 | A: i32, | ||
| 195 | B: i32, | ||
| 196 | C: i32, | ||
| 197 | }; | ||
| 198 | test "union field access gives the enum values" { | ||
| 199 | assert(TheUnion.A == TheTag.A); | ||
| 200 | assert(TheUnion.B == TheTag.B); | ||
| 201 | assert(TheUnion.C == TheTag.C); | ||
| 202 | } | ||
| 203 | |||
| 204 | test "cast union to tag type of union" { | ||
| 205 | testCastUnionToTagType(TheUnion{ .B = 1234 }); | ||
| 206 | comptime testCastUnionToTagType(TheUnion{ .B = 1234 }); | ||
| 207 | } | ||
| 208 | |||
| 209 | fn testCastUnionToTagType(x: TheUnion) void { | ||
| 210 | assert(TheTag(x) == TheTag.B); | ||
| 211 | } | ||
| 212 | |||
| 213 | test "cast tag type of union to union" { | ||
| 214 | var x: Value2 = Letter2.B; | ||
| 215 | assert(Letter2(x) == Letter2.B); | ||
| 216 | } | ||
| 217 | const Letter2 = enum { | ||
| 218 | A, | ||
| 219 | B, | ||
| 220 | C, | ||
| 221 | }; | ||
| 222 | const Value2 = union(Letter2) { | ||
| 223 | A: i32, | ||
| 224 | B, | ||
| 225 | C, | ||
| 226 | }; | ||
| 227 | |||
| 228 | test "implicit cast union to its tag type" { | ||
| 229 | var x: Value2 = Letter2.B; | ||
| 230 | assert(x == Letter2.B); | ||
| 231 | giveMeLetterB(x); | ||
| 232 | } | ||
| 233 | fn giveMeLetterB(x: Letter2) void { | ||
| 234 | assert(x == Value2.B); | ||
| 235 | } | ||
| 236 | |||
| 237 | pub const PackThis = union(enum) { | ||
| 238 | Invalid: bool, | ||
| 239 | StringLiteral: u2, | ||
| 240 | }; | ||
| 241 | |||
| 242 | test "constant packed union" { | ||
| 243 | testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); | ||
| 244 | } | ||
| 245 | |||
| 246 | fn testConstPackedUnion(expected_tokens: []const PackThis) void { | ||
| 247 | assert(expected_tokens[0].StringLiteral == 1); | ||
| 248 | } | ||
| 249 | |||
| 250 | test "switch on union with only 1 field" { | ||
| 251 | var r: PartialInst = undefined; | ||
| 252 | r = PartialInst.Compiled; | ||
| 253 | switch (r) { | ||
| 254 | PartialInst.Compiled => { | ||
| 255 | var z: PartialInstWithPayload = undefined; | ||
| 256 | z = PartialInstWithPayload{ .Compiled = 1234 }; | ||
| 257 | switch (z) { | ||
| 258 | PartialInstWithPayload.Compiled => |x| { | ||
| 259 | assert(x == 1234); | ||
| 260 | return; | ||
| 261 | }, | ||
| 262 | } | ||
| 263 | }, | ||
| 264 | } | ||
| 265 | unreachable; | ||
| 266 | } | ||
| 267 | |||
| 268 | const PartialInst = union(enum) { | ||
| 269 | Compiled, | ||
| 270 | }; | ||
| 271 | |||
| 272 | const PartialInstWithPayload = union(enum) { | ||
| 273 | Compiled: i32, | ||
| 274 | }; | ||
| 275 | |||
| 276 | test "access a member of tagged union with conflicting enum tag name" { | ||
| 277 | const Bar = union(enum) { | ||
| 278 | A: A, | ||
| 279 | B: B, | ||
| 280 | |||
| 281 | const A = u8; | ||
| 282 | const B = void; | ||
| 283 | }; | ||
| 284 | |||
| 285 | comptime assert(Bar.A == u8); | ||
| 286 | } | ||
| 287 | |||
| 288 | test "tagged union initialization with runtime void" { | ||
| 289 | assert(testTaggedUnionInit({})); | ||
| 290 | } | ||
| 291 | |||
| 292 | const TaggedUnionWithAVoid = union(enum) { | ||
| 293 | A, | ||
| 294 | B: i32, | ||
| 295 | }; | ||
| 296 | |||
| 297 | fn testTaggedUnionInit(x: var) bool { | ||
| 298 | const y = TaggedUnionWithAVoid{ .A = x }; | ||
| 299 | return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; | ||
| 300 | } | ||
| 301 | |||
| 302 | pub const UnionEnumNoPayloads = union(enum) { | ||
| 303 | A, | ||
| 304 | B, | ||
| 305 | }; | ||
| 306 | |||
| 307 | test "tagged union with no payloads" { | ||
| 308 | const a = UnionEnumNoPayloads{ .B = {} }; | ||
| 309 | switch (a) { | ||
| 310 | @TagType(UnionEnumNoPayloads).A => @panic("wrong"), | ||
| 311 | @TagType(UnionEnumNoPayloads).B => {}, | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | test "union with only 1 field casted to its enum type" { | ||
| 316 | const Literal = union(enum) { | ||
| 317 | Number: f64, | ||
| 318 | Bool: bool, | ||
| 319 | }; | ||
| 320 | |||
| 321 | const Expr = union(enum) { | ||
| 322 | Literal: Literal, | ||
| 323 | }; | ||
| 324 | |||
| 325 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 326 | const Tag = @TagType(Expr); | ||
| 327 | comptime assert(@TagType(Tag) == comptime_int); | ||
| 328 | var t = Tag(e); | ||
| 329 | assert(t == Expr.Literal); | ||
| 330 | } | ||
| 331 | |||
| 332 | test "union with only 1 field casted to its enum type which has enum value specified" { | ||
| 333 | const Literal = union(enum) { | ||
| 334 | Number: f64, | ||
| 335 | Bool: bool, | ||
| 336 | }; | ||
| 337 | |||
| 338 | const Tag = enum { | ||
| 339 | Literal = 33, | ||
| 340 | }; | ||
| 341 | |||
| 342 | const Expr = union(Tag) { | ||
| 343 | Literal: Literal, | ||
| 344 | }; | ||
| 345 | |||
| 346 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 347 | comptime assert(@TagType(Tag) == comptime_int); | ||
| 348 | var t = Tag(e); | ||
| 349 | assert(t == Expr.Literal); | ||
| 350 | assert(@enumToInt(t) == 33); | ||
| 351 | comptime assert(@enumToInt(t) == 33); | ||
| 352 | } | ||
test/cases/var_args.zig deleted-84| ... | @@ -1,84 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | fn add(args: ...) i32 { | ||
| 4 | var sum = i32(0); | ||
| 5 | { | ||
| 6 | comptime var i: usize = 0; | ||
| 7 | inline while (i < args.len) : (i += 1) { | ||
| 8 | sum += args[i]; | ||
| 9 | } | ||
| 10 | } | ||
| 11 | return sum; | ||
| 12 | } | ||
| 13 | |||
| 14 | test "add arbitrary args" { | ||
| 15 | assert(add(i32(1), i32(2), i32(3), i32(4)) == 10); | ||
| 16 | assert(add(i32(1234)) == 1234); | ||
| 17 | assert(add() == 0); | ||
| 18 | } | ||
| 19 | |||
| 20 | fn readFirstVarArg(args: ...) void { | ||
| 21 | const value = args[0]; | ||
| 22 | } | ||
| 23 | |||
| 24 | test "send void arg to var args" { | ||
| 25 | readFirstVarArg({}); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "pass args directly" { | ||
| 29 | assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); | ||
| 30 | assert(addSomeStuff(i32(1234)) == 1234); | ||
| 31 | assert(addSomeStuff() == 0); | ||
| 32 | } | ||
| 33 | |||
| 34 | fn addSomeStuff(args: ...) i32 { | ||
| 35 | return add(args); | ||
| 36 | } | ||
| 37 | |||
| 38 | test "runtime parameter before var args" { | ||
| 39 | assert(extraFn(10) == 0); | ||
| 40 | assert(extraFn(10, false) == 1); | ||
| 41 | assert(extraFn(10, false, true) == 2); | ||
| 42 | |||
| 43 | // TODO issue #313 | ||
| 44 | //comptime { | ||
| 45 | // assert(extraFn(10) == 0); | ||
| 46 | // assert(extraFn(10, false) == 1); | ||
| 47 | // assert(extraFn(10, false, true) == 2); | ||
| 48 | //} | ||
| 49 | } | ||
| 50 | |||
| 51 | fn extraFn(extra: u32, args: ...) usize { | ||
| 52 | if (args.len >= 1) { | ||
| 53 | assert(args[0] == false); | ||
| 54 | } | ||
| 55 | if (args.len >= 2) { | ||
| 56 | assert(args[1] == true); | ||
| 57 | } | ||
| 58 | return args.len; | ||
| 59 | } | ||
| 60 | |||
| 61 | const foos = []fn (...) bool{ | ||
| 62 | foo1, | ||
| 63 | foo2, | ||
| 64 | }; | ||
| 65 | |||
| 66 | fn foo1(args: ...) bool { | ||
| 67 | return true; | ||
| 68 | } | ||
| 69 | fn foo2(args: ...) bool { | ||
| 70 | return false; | ||
| 71 | } | ||
| 72 | |||
| 73 | test "array of var args functions" { | ||
| 74 | assert(foos[0]()); | ||
| 75 | assert(!foos[1]()); | ||
| 76 | } | ||
| 77 | |||
| 78 | test "pass zero length array to var args param" { | ||
| 79 | doNothingWithFirstArg(""); | ||
| 80 | } | ||
| 81 | |||
| 82 | fn doNothingWithFirstArg(args: ...) void { | ||
| 83 | const a = args[0]; | ||
| 84 | } | ||
test/cases/void.zig deleted-30| ... | @@ -1,30 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const Foo = struct { | ||
| 4 | a: void, | ||
| 5 | b: i32, | ||
| 6 | c: void, | ||
| 7 | }; | ||
| 8 | |||
| 9 | test "compare void with void compile time known" { | ||
| 10 | comptime { | ||
| 11 | const foo = Foo{ | ||
| 12 | .a = {}, | ||
| 13 | .b = 1, | ||
| 14 | .c = {}, | ||
| 15 | }; | ||
| 16 | assert(foo.a == {}); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | test "iterate over a void slice" { | ||
| 21 | var j: usize = 0; | ||
| 22 | for (times(10)) |_, i| { | ||
| 23 | assert(i == j); | ||
| 24 | j += 1; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | fn times(n: usize) []const void { | ||
| 29 | return ([*]void)(undefined)[0..n]; | ||
| 30 | } | ||
test/cases/while.zig deleted-227| ... | @@ -1,227 +0,0 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | test "while loop" { | ||
| 4 | var i: i32 = 0; | ||
| 5 | while (i < 4) { | ||
| 6 | i += 1; | ||
| 7 | } | ||
| 8 | assert(i == 4); | ||
| 9 | assert(whileLoop1() == 1); | ||
| 10 | } | ||
| 11 | fn whileLoop1() i32 { | ||
| 12 | return whileLoop2(); | ||
| 13 | } | ||
| 14 | fn whileLoop2() i32 { | ||
| 15 | while (true) { | ||
| 16 | return 1; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | test "static eval while" { | ||
| 20 | assert(static_eval_while_number == 1); | ||
| 21 | } | ||
| 22 | const static_eval_while_number = staticWhileLoop1(); | ||
| 23 | fn staticWhileLoop1() i32 { | ||
| 24 | return whileLoop2(); | ||
| 25 | } | ||
| 26 | fn staticWhileLoop2() i32 { | ||
| 27 | while (true) { | ||
| 28 | return 1; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | test "continue and break" { | ||
| 33 | runContinueAndBreakTest(); | ||
| 34 | assert(continue_and_break_counter == 8); | ||
| 35 | } | ||
| 36 | var continue_and_break_counter: i32 = 0; | ||
| 37 | fn runContinueAndBreakTest() void { | ||
| 38 | var i: i32 = 0; | ||
| 39 | while (true) { | ||
| 40 | continue_and_break_counter += 2; | ||
| 41 | i += 1; | ||
| 42 | if (i < 4) { | ||
| 43 | continue; | ||
| 44 | } | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | assert(i == 4); | ||
| 48 | } | ||
| 49 | |||
| 50 | test "return with implicit cast from while loop" { | ||
| 51 | returnWithImplicitCastFromWhileLoopTest() catch unreachable; | ||
| 52 | } | ||
| 53 | fn returnWithImplicitCastFromWhileLoopTest() anyerror!void { | ||
| 54 | while (true) { | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | test "while with continue expression" { | ||
| 60 | var sum: i32 = 0; | ||
| 61 | { | ||
| 62 | var i: i32 = 0; | ||
| 63 | while (i < 10) : (i += 1) { | ||
| 64 | if (i == 5) continue; | ||
| 65 | sum += i; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | assert(sum == 40); | ||
| 69 | } | ||
| 70 | |||
| 71 | test "while with else" { | ||
| 72 | var sum: i32 = 0; | ||
| 73 | var i: i32 = 0; | ||
| 74 | var got_else: i32 = 0; | ||
| 75 | while (i < 10) : (i += 1) { | ||
| 76 | sum += 1; | ||
| 77 | } else { | ||
| 78 | got_else += 1; | ||
| 79 | } | ||
| 80 | assert(sum == 10); | ||
| 81 | assert(got_else == 1); | ||
| 82 | } | ||
| 83 | |||
| 84 | test "while with optional as condition" { | ||
| 85 | numbers_left = 10; | ||
| 86 | var sum: i32 = 0; | ||
| 87 | while (getNumberOrNull()) |value| { | ||
| 88 | sum += value; | ||
| 89 | } | ||
| 90 | assert(sum == 45); | ||
| 91 | } | ||
| 92 | |||
| 93 | test "while with optional as condition with else" { | ||
| 94 | numbers_left = 10; | ||
| 95 | var sum: i32 = 0; | ||
| 96 | var got_else: i32 = 0; | ||
| 97 | while (getNumberOrNull()) |value| { | ||
| 98 | sum += value; | ||
| 99 | assert(got_else == 0); | ||
| 100 | } else { | ||
| 101 | got_else += 1; | ||
| 102 | } | ||
| 103 | assert(sum == 45); | ||
| 104 | assert(got_else == 1); | ||
| 105 | } | ||
| 106 | |||
| 107 | test "while with error union condition" { | ||
| 108 | numbers_left = 10; | ||
| 109 | var sum: i32 = 0; | ||
| 110 | var got_else: i32 = 0; | ||
| 111 | while (getNumberOrErr()) |value| { | ||
| 112 | sum += value; | ||
| 113 | } else |err| { | ||
| 114 | assert(err == error.OutOfNumbers); | ||
| 115 | got_else += 1; | ||
| 116 | } | ||
| 117 | assert(sum == 45); | ||
| 118 | assert(got_else == 1); | ||
| 119 | } | ||
| 120 | |||
| 121 | var numbers_left: i32 = undefined; | ||
| 122 | fn getNumberOrErr() anyerror!i32 { | ||
| 123 | return if (numbers_left == 0) error.OutOfNumbers else x: { | ||
| 124 | numbers_left -= 1; | ||
| 125 | break :x numbers_left; | ||
| 126 | }; | ||
| 127 | } | ||
| 128 | fn getNumberOrNull() ?i32 { | ||
| 129 | return if (numbers_left == 0) null else x: { | ||
| 130 | numbers_left -= 1; | ||
| 131 | break :x numbers_left; | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | |||
| 135 | test "while on optional with else result follow else prong" { | ||
| 136 | const result = while (returnNull()) |value| { | ||
| 137 | break value; | ||
| 138 | } else | ||
| 139 | i32(2); | ||
| 140 | assert(result == 2); | ||
| 141 | } | ||
| 142 | |||
| 143 | test "while on optional with else result follow break prong" { | ||
| 144 | const result = while (returnOptional(10)) |value| { | ||
| 145 | break value; | ||
| 146 | } else | ||
| 147 | i32(2); | ||
| 148 | assert(result == 10); | ||
| 149 | } | ||
| 150 | |||
| 151 | test "while on error union with else result follow else prong" { | ||
| 152 | const result = while (returnError()) |value| { | ||
| 153 | break value; | ||
| 154 | } else |err| | ||
| 155 | i32(2); | ||
| 156 | assert(result == 2); | ||
| 157 | } | ||
| 158 | |||
| 159 | test "while on error union with else result follow break prong" { | ||
| 160 | const result = while (returnSuccess(10)) |value| { | ||
| 161 | break value; | ||
| 162 | } else |err| | ||
| 163 | i32(2); | ||
| 164 | assert(result == 10); | ||
| 165 | } | ||
| 166 | |||
| 167 | test "while on bool with else result follow else prong" { | ||
| 168 | const result = while (returnFalse()) { | ||
| 169 | break i32(10); | ||
| 170 | } else | ||
| 171 | i32(2); | ||
| 172 | assert(result == 2); | ||
| 173 | } | ||
| 174 | |||
| 175 | test "while on bool with else result follow break prong" { | ||
| 176 | const result = while (returnTrue()) { | ||
| 177 | break i32(10); | ||
| 178 | } else | ||
| 179 | i32(2); | ||
| 180 | assert(result == 10); | ||
| 181 | } | ||
| 182 | |||
| 183 | test "break from outer while loop" { | ||
| 184 | testBreakOuter(); | ||
| 185 | comptime testBreakOuter(); | ||
| 186 | } | ||
| 187 | |||
| 188 | fn testBreakOuter() void { | ||
| 189 | outer: while (true) { | ||
| 190 | while (true) { | ||
| 191 | break :outer; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | test "continue outer while loop" { | ||
| 197 | testContinueOuter(); | ||
| 198 | comptime testContinueOuter(); | ||
| 199 | } | ||
| 200 | |||
| 201 | fn testContinueOuter() void { | ||
| 202 | var i: usize = 0; | ||
| 203 | outer: while (i < 10) : (i += 1) { | ||
| 204 | while (true) { | ||
| 205 | continue :outer; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | fn returnNull() ?i32 { | ||
| 211 | return null; | ||
| 212 | } | ||
| 213 | fn returnOptional(x: i32) ?i32 { | ||
| 214 | return x; | ||
| 215 | } | ||
| 216 | fn returnError() anyerror!i32 { | ||
| 217 | return error.YouWantedAnError; | ||
| 218 | } | ||
| 219 | fn returnSuccess(x: i32) anyerror!i32 { | ||
| 220 | return x; | ||
| 221 | } | ||
| 222 | fn returnFalse() bool { | ||
| 223 | return false; | ||
| 224 | } | ||
| 225 | fn returnTrue() bool { | ||
| 226 | return true; | ||
| 227 | } | ||
test/cases/widening.zig deleted-27| ... | @@ -1,27 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | test "integer widening" { | ||
| 6 | var a: u8 = 250; | ||
| 7 | var b: u16 = a; | ||
| 8 | var c: u32 = b; | ||
| 9 | var d: u64 = c; | ||
| 10 | var e: u64 = d; | ||
| 11 | var f: u128 = e; | ||
| 12 | assert(f == a); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "implicit unsigned integer to signed integer" { | ||
| 16 | var a: u8 = 250; | ||
| 17 | var b: i16 = a; | ||
| 18 | assert(b == 250); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "float widening" { | ||
| 22 | var a: f16 = 12.34; | ||
| 23 | var b: f32 = a; | ||
| 24 | var c: f64 = b; | ||
| 25 | var d: f128 = c; | ||
| 26 | assert(d == a); | ||
| 27 | } | ||
test/cli.zig+9-9| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const os = std.os; | 3 | const os = std.os; |
| 4 | const assertOrPanic = std.debug.assertOrPanic; | 4 | const testing = std.testing; |
| 5 | 5 | ||
| 6 | var a: *std.mem.Allocator = undefined; | 6 | var a: *std.mem.Allocator = undefined; |
| 7 | 7 | ||
| ... | @@ -27,9 +27,9 @@ pub fn main() !void { | ... | @@ -27,9 +27,9 @@ pub fn main() !void { |
| 27 | std.debug.warn("Expected second argument to be cache root directory path\n"); | 27 | std.debug.warn("Expected second argument to be cache root directory path\n"); |
| 28 | return error.InvalidArgs; | 28 | return error.InvalidArgs; |
| 29 | }); | 29 | }); |
| 30 | const zig_exe = try os.path.resolve(a, zig_exe_rel); | 30 | const zig_exe = try os.path.resolve(a, [][]const u8{zig_exe_rel}); |
| 31 | 31 | ||
| 32 | const dir_path = try os.path.join(a, cache_root, "clitest"); | 32 | const dir_path = try os.path.join(a, [][]const u8{ cache_root, "clitest" }); |
| 33 | const TestFn = fn ([]const u8, []const u8) anyerror!void; | 33 | const TestFn = fn ([]const u8, []const u8) anyerror!void; |
| 34 | const test_fns = []TestFn{ | 34 | const test_fns = []TestFn{ |
| 35 | testZigInitLib, | 35 | testZigInitLib, |
| ... | @@ -87,20 +87,20 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult { | ... | @@ -87,20 +87,20 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult { |
| 87 | fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void { | 87 | fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void { |
| 88 | _ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" }); | 88 | _ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" }); |
| 89 | const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" }); | 89 | const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" }); |
| 90 | assertOrPanic(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n")); | 90 | testing.expect(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n")); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void { | 93 | fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void { |
| 94 | _ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" }); | 94 | _ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" }); |
| 95 | const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" }); | 95 | const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" }); |
| 96 | assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n")); | 96 | testing.expect(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n")); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { | 99 | fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { |
| 100 | if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return; | 100 | if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return; |
| 101 | 101 | ||
| 102 | const example_zig_path = try os.path.join(a, dir_path, "example.zig"); | 102 | const example_zig_path = try os.path.join(a, [][]const u8{ dir_path, "example.zig" }); |
| 103 | const example_s_path = try os.path.join(a, dir_path, "example.s"); | 103 | const example_s_path = try os.path.join(a, [][]const u8{ dir_path, "example.s" }); |
| 104 | 104 | ||
| 105 | try std.io.writeFile(example_zig_path, | 105 | try std.io.writeFile(example_zig_path, |
| 106 | \\// Type your code here, or load an example. | 106 | \\// Type your code here, or load an example. |
| ... | @@ -126,6 +126,6 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { | ... | @@ -126,6 +126,6 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { |
| 126 | _ = try exec(dir_path, args); | 126 | _ = try exec(dir_path, args); |
| 127 | 127 | ||
| 128 | const out_asm = try std.io.readFileAlloc(a, example_s_path); | 128 | const out_asm = try std.io.readFileAlloc(a, example_s_path); |
| 129 | assertOrPanic(std.mem.indexOf(u8, out_asm, "square:") != null); | 129 | testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null); |
| 130 | assertOrPanic(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null); | 130 | testing.expect(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null); |
| 131 | } | 131 | } |
test/compile_errors.zig+366-66| ... | @@ -1,6 +1,270 @@ | ... | @@ -1,6 +1,270 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4 | cases.addTest( | ||
| 5 | "C pointer to c_void", | ||
| 6 | \\export fn a() void { | ||
| 7 | \\ var x: *c_void = undefined; | ||
| 8 | \\ var y: [*c]c_void = x; | ||
| 9 | \\} | ||
| 10 | , | ||
| 11 | ".tmp_source.zig:3:12: error: C pointers cannot point opaque types", | ||
| 12 | ); | ||
| 13 | |||
| 14 | cases.addTest( | ||
| 15 | "directly embedding opaque type in struct and union", | ||
| 16 | \\const O = @OpaqueType(); | ||
| 17 | \\const Foo = struct { | ||
| 18 | \\ o: O, | ||
| 19 | \\}; | ||
| 20 | \\const Bar = union { | ||
| 21 | \\ One: i32, | ||
| 22 | \\ Two: O, | ||
| 23 | \\}; | ||
| 24 | \\export fn a() void { | ||
| 25 | \\ var foo: Foo = undefined; | ||
| 26 | \\} | ||
| 27 | \\export fn b() void { | ||
| 28 | \\ var bar: Bar = undefined; | ||
| 29 | \\} | ||
| 30 | , | ||
| 31 | ".tmp_source.zig:3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs", | ||
| 32 | ".tmp_source.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions", | ||
| 33 | ); | ||
| 34 | |||
| 35 | cases.addTest( | ||
| 36 | "implicit cast between C pointer and Zig pointer - bad const/align/child", | ||
| 37 | \\export fn a() void { | ||
| 38 | \\ var x: [*c]u8 = undefined; | ||
| 39 | \\ var y: *align(4) u8 = x; | ||
| 40 | \\} | ||
| 41 | \\export fn b() void { | ||
| 42 | \\ var x: [*c]const u8 = undefined; | ||
| 43 | \\ var y: *u8 = x; | ||
| 44 | \\} | ||
| 45 | \\export fn c() void { | ||
| 46 | \\ var x: [*c]u8 = undefined; | ||
| 47 | \\ var y: *u32 = x; | ||
| 48 | \\} | ||
| 49 | \\export fn d() void { | ||
| 50 | \\ var y: *align(1) u32 = undefined; | ||
| 51 | \\ var x: [*c]u32 = y; | ||
| 52 | \\} | ||
| 53 | \\export fn e() void { | ||
| 54 | \\ var y: *const u8 = undefined; | ||
| 55 | \\ var x: [*c]u8 = y; | ||
| 56 | \\} | ||
| 57 | \\export fn f() void { | ||
| 58 | \\ var y: *u8 = undefined; | ||
| 59 | \\ var x: [*c]u32 = y; | ||
| 60 | \\} | ||
| 61 | , | ||
| 62 | ".tmp_source.zig:3:27: error: cast increases pointer alignment", | ||
| 63 | ".tmp_source.zig:7:18: error: cast discards const qualifier", | ||
| 64 | ".tmp_source.zig:11:19: error: expected type '*u32', found '[*c]u8'", | ||
| 65 | ".tmp_source.zig:11:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'", | ||
| 66 | ".tmp_source.zig:15:22: error: cast increases pointer alignment", | ||
| 67 | ".tmp_source.zig:19:21: error: cast discards const qualifier", | ||
| 68 | ".tmp_source.zig:23:22: error: expected type '[*c]u32', found '*u8'", | ||
| 69 | ); | ||
| 70 | |||
| 71 | cases.addTest( | ||
| 72 | "implicit casting null c pointer to zig pointer", | ||
| 73 | \\comptime { | ||
| 74 | \\ var c_ptr: [*c]u8 = 0; | ||
| 75 | \\ var zig_ptr: *u8 = c_ptr; | ||
| 76 | \\} | ||
| 77 | , | ||
| 78 | ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'", | ||
| 79 | ); | ||
| 80 | |||
| 81 | cases.addTest( | ||
| 82 | "implicit casting undefined c pointer to zig pointer", | ||
| 83 | \\comptime { | ||
| 84 | \\ var c_ptr: [*c]u8 = undefined; | ||
| 85 | \\ var zig_ptr: *u8 = c_ptr; | ||
| 86 | \\} | ||
| 87 | , | ||
| 88 | ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior", | ||
| 89 | ); | ||
| 90 | |||
| 91 | cases.addTest( | ||
| 92 | "implicit casting C pointers which would mess up null semantics", | ||
| 93 | \\export fn entry() void { | ||
| 94 | \\ var slice: []const u8 = "aoeu"; | ||
| 95 | \\ const opt_many_ptr: [*]const u8 = slice.ptr; | ||
| 96 | \\ var ptr_opt_many_ptr = &opt_many_ptr; | ||
| 97 | \\ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr; | ||
| 98 | \\ ptr_opt_many_ptr = c_ptr; | ||
| 99 | \\} | ||
| 100 | \\export fn entry2() void { | ||
| 101 | \\ var buf: [4]u8 = "aoeu"; | ||
| 102 | \\ var slice: []u8 = &buf; | ||
| 103 | \\ var opt_many_ptr: [*]u8 = slice.ptr; | ||
| 104 | \\ var ptr_opt_many_ptr = &opt_many_ptr; | ||
| 105 | \\ var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr; | ||
| 106 | \\} | ||
| 107 | , | ||
| 108 | ".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'", | ||
| 109 | ".tmp_source.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'", | ||
| 110 | ".tmp_source.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'", | ||
| 111 | ".tmp_source.zig:13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'", | ||
| 112 | ".tmp_source.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'", | ||
| 113 | ".tmp_source.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'", | ||
| 114 | ); | ||
| 115 | |||
| 116 | cases.addTest( | ||
| 117 | "implicit casting too big integers to C pointers", | ||
| 118 | \\export fn a() void { | ||
| 119 | \\ var ptr: [*c]u8 = (1 << 64) + 1; | ||
| 120 | \\} | ||
| 121 | \\export fn b() void { | ||
| 122 | \\ var x: @IntType(false, 65) = 0x1234; | ||
| 123 | \\ var ptr: [*c]u8 = x; | ||
| 124 | \\} | ||
| 125 | , | ||
| 126 | ".tmp_source.zig:2:33: error: integer value 71615590737044764481 cannot be implicitly casted to type 'usize'", | ||
| 127 | ".tmp_source.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'", | ||
| 128 | ); | ||
| 129 | |||
| 130 | cases.addTest( | ||
| 131 | "C pointer pointing to non C ABI compatible type or has align attr", | ||
| 132 | \\const Foo = struct {}; | ||
| 133 | \\export fn a() void { | ||
| 134 | \\ const T = [*c]Foo; | ||
| 135 | \\} | ||
| 136 | , | ||
| 137 | ".tmp_source.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'", | ||
| 138 | ); | ||
| 139 | |||
| 140 | cases.addTest( | ||
| 141 | "@truncate undefined value", | ||
| 142 | \\export fn entry() void { | ||
| 143 | \\ var z = @truncate(u8, u16(undefined)); | ||
| 144 | \\} | ||
| 145 | , | ||
| 146 | ".tmp_source.zig:2:30: error: use of undefined value here causes undefined behavior", | ||
| 147 | ); | ||
| 148 | |||
| 149 | cases.addTest( | ||
| 150 | "return invalid type from test", | ||
| 151 | \\test "example" { return 1; } | ||
| 152 | , | ||
| 153 | ".tmp_source.zig:1:25: error: integer value 1 cannot be implicitly casted to type 'void'", | ||
| 154 | ); | ||
| 155 | |||
| 156 | cases.add( | ||
| 157 | "threadlocal qualifier on const", | ||
| 158 | \\threadlocal const x: i32 = 1234; | ||
| 159 | \\export fn entry() i32 { | ||
| 160 | \\ return x; | ||
| 161 | \\} | ||
| 162 | , | ||
| 163 | ".tmp_source.zig:1:13: error: threadlocal variable cannot be constant", | ||
| 164 | ); | ||
| 165 | |||
| 166 | cases.add( | ||
| 167 | "threadlocal qualifier on local variable", | ||
| 168 | \\export fn entry() void { | ||
| 169 | \\ threadlocal var x: i32 = 1234; | ||
| 170 | \\} | ||
| 171 | , | ||
| 172 | ".tmp_source.zig:2:5: error: function-local variable 'x' cannot be threadlocal", | ||
| 173 | ); | ||
| 174 | |||
| 175 | cases.add( | ||
| 176 | "@bitCast same size but bit count mismatch", | ||
| 177 | \\export fn entry(byte: u8) void { | ||
| 178 | \\ var oops = @bitCast(u7, byte); | ||
| 179 | \\} | ||
| 180 | , | ||
| 181 | ".tmp_source.zig:2:16: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits", | ||
| 182 | ); | ||
| 183 | |||
| 184 | cases.add( | ||
| 185 | "attempted `&&`", | ||
| 186 | \\export fn entry(a: bool, b: bool) i32 { | ||
| 187 | \\ if (a && b) { | ||
| 188 | \\ return 1234; | ||
| 189 | \\ } | ||
| 190 | \\ return 5678; | ||
| 191 | \\} | ||
| 192 | , | ||
| 193 | ".tmp_source.zig:2:12: error: `&&` is invalid. Note that `and` is boolean AND.", | ||
| 194 | ); | ||
| 195 | |||
| 196 | cases.add( | ||
| 197 | "attempted `||` on boolean values", | ||
| 198 | \\export fn entry(a: bool, b: bool) i32 { | ||
| 199 | \\ if (a || b) { | ||
| 200 | \\ return 1234; | ||
| 201 | \\ } | ||
| 202 | \\ return 5678; | ||
| 203 | \\} | ||
| 204 | , | ||
| 205 | ".tmp_source.zig:2:9: error: expected error set type, found 'bool'", | ||
| 206 | ".tmp_source.zig:2:11: note: `||` merges error sets; `or` performs boolean OR", | ||
| 207 | ); | ||
| 208 | |||
| 209 | cases.add( | ||
| 210 | "compile log a pointer to an opaque value", | ||
| 211 | \\export fn entry() void { | ||
| 212 | \\ @compileLog(@ptrCast(*const c_void, &entry)); | ||
| 213 | \\} | ||
| 214 | , | ||
| 215 | ".tmp_source.zig:2:5: error: found compile log statement", | ||
| 216 | ); | ||
| 217 | |||
| 218 | cases.add( | ||
| 219 | "duplicate boolean switch value", | ||
| 220 | \\comptime { | ||
| 221 | \\ const x = switch (true) { | ||
| 222 | \\ true => false, | ||
| 223 | \\ false => true, | ||
| 224 | \\ true => false, | ||
| 225 | \\ }; | ||
| 226 | \\} | ||
| 227 | \\comptime { | ||
| 228 | \\ const x = switch (true) { | ||
| 229 | \\ false => true, | ||
| 230 | \\ true => false, | ||
| 231 | \\ false => true, | ||
| 232 | \\ }; | ||
| 233 | \\} | ||
| 234 | , | ||
| 235 | ".tmp_source.zig:5:9: error: duplicate switch value", | ||
| 236 | ".tmp_source.zig:12:9: error: duplicate switch value", | ||
| 237 | ); | ||
| 238 | |||
| 239 | cases.add( | ||
| 240 | "missing boolean switch value", | ||
| 241 | \\comptime { | ||
| 242 | \\ const x = switch (true) { | ||
| 243 | \\ true => false, | ||
| 244 | \\ }; | ||
| 245 | \\} | ||
| 246 | \\comptime { | ||
| 247 | \\ const x = switch (true) { | ||
| 248 | \\ false => true, | ||
| 249 | \\ }; | ||
| 250 | \\} | ||
| 251 | , | ||
| 252 | ".tmp_source.zig:2:15: error: switch must handle all possibilities", | ||
| 253 | ".tmp_source.zig:7:15: error: switch must handle all possibilities", | ||
| 254 | ); | ||
| 255 | |||
| 256 | cases.add( | ||
| 257 | "reading past end of pointer casted array", | ||
| 258 | \\comptime { | ||
| 259 | \\ const array = "aoeu"; | ||
| 260 | \\ const slice = array[2..]; | ||
| 261 | \\ const int_ptr = @ptrCast(*const u24, slice.ptr); | ||
| 262 | \\ const deref = int_ptr.*; | ||
| 263 | \\} | ||
| 264 | , | ||
| 265 | ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes", | ||
| 266 | ); | ||
| 267 | |||
| 4 | cases.add( | 268 | cases.add( |
| 5 | "error note for function parameter incompatibility", | 269 | "error note for function parameter incompatibility", |
| 6 | \\fn do_the_thing(func: fn (arg: i32) void) void {} | 270 | \\fn do_the_thing(func: fn (arg: i32) void) void {} |
| ... | @@ -82,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -82,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 82 | ); | 346 | ); |
| 83 | 347 | ||
| 84 | cases.add( | 348 | cases.add( |
| 85 | "Panic declared with wrong type signature in tests", | 349 | "wrong panic signature, runtime function", |
| 86 | \\test "" {} | 350 | \\test "" {} |
| 87 | \\ | 351 | \\ |
| 88 | \\pub fn panic() void {} | 352 | \\pub fn panic() void {} |
| 89 | \\ | 353 | \\ |
| 90 | , | 354 | , |
| 91 | ".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'", | 355 | ".tmp_source.zig:3:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn() void'", |
| 356 | ); | ||
| 357 | |||
| 358 | cases.add( | ||
| 359 | "wrong panic signature, generic function", | ||
| 360 | \\pub fn panic(comptime msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { | ||
| 361 | \\ while (true) {} | ||
| 362 | \\} | ||
| 363 | , | ||
| 364 | ".tmp_source.zig:1:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn([]const u8,var)var'", | ||
| 365 | ".tmp_source.zig:1:5: note: only one of the functions is generic", | ||
| 92 | ); | 366 | ); |
| 93 | 367 | ||
| 94 | cases.add( | 368 | cases.add( |
| ... | @@ -208,8 +482,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -208,8 +482,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 208 | \\ const Errors = error{} || u16; | 482 | \\ const Errors = error{} || u16; |
| 209 | \\} | 483 | \\} |
| 210 | , | 484 | , |
| 211 | ".tmp_source.zig:2:20: error: expected error set type, found 'u8'", | 485 | ".tmp_source.zig:2:20: error: expected error set type, found type 'u8'", |
| 212 | ".tmp_source.zig:5:31: error: expected error set type, found 'u16'", | 486 | ".tmp_source.zig:2:23: note: `||` merges error sets; `or` performs boolean OR", |
| 487 | ".tmp_source.zig:5:31: error: expected error set type, found type 'u16'", | ||
| 488 | ".tmp_source.zig:5:28: note: `||` merges error sets; `or` performs boolean OR", | ||
| 213 | ); | 489 | ); |
| 214 | 490 | ||
| 215 | cases.add( | 491 | cases.add( |
| ... | @@ -238,7 +514,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -238,7 +514,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 238 | \\ f(i32); | 514 | \\ f(i32); |
| 239 | \\} | 515 | \\} |
| 240 | , | 516 | , |
| 241 | ".tmp_source.zig:4:5: error: use of undefined value", | 517 | ".tmp_source.zig:4:5: error: use of undefined value here causes undefined behavior", |
| 242 | ); | 518 | ); |
| 243 | 519 | ||
| 244 | cases.add( | 520 | cases.add( |
| ... | @@ -638,7 +914,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -638,7 +914,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 638 | \\ command.exec(); | 914 | \\ command.exec(); |
| 639 | \\} | 915 | \\} |
| 640 | , | 916 | , |
| 641 | ".tmp_source.zig:6:12: error: use of undefined value", | 917 | ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior", |
| 642 | ); | 918 | ); |
| 643 | 919 | ||
| 644 | cases.add( | 920 | cases.add( |
| ... | @@ -651,7 +927,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -651,7 +927,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 651 | \\ command.exec(); | 927 | \\ command.exec(); |
| 652 | \\} | 928 | \\} |
| 653 | , | 929 | , |
| 654 | ".tmp_source.zig:6:12: error: use of undefined value", | 930 | ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior", |
| 655 | ); | 931 | ); |
| 656 | 932 | ||
| 657 | cases.add( | 933 | cases.add( |
| ... | @@ -2559,7 +2835,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2559,7 +2835,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2559 | \\ | 2835 | \\ |
| 2560 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | 2836 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } |
| 2561 | , | 2837 | , |
| 2562 | ".tmp_source.zig:1:13: error: newline not allowed in string literal", | 2838 | ".tmp_source.zig:1:15: error: newline not allowed in string literal", |
| 2563 | ); | 2839 | ); |
| 2564 | 2840 | ||
| 2565 | cases.add( | 2841 | cases.add( |
| ... | @@ -2622,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2622,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2622 | \\ | 2898 | \\ |
| 2623 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } | 2899 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } |
| 2624 | , | 2900 | , |
| 2625 | ".tmp_source.zig:1:15: error: use of undefined value", | 2901 | ".tmp_source.zig:1:15: error: use of undefined value here causes undefined behavior", |
| 2626 | ); | 2902 | ); |
| 2627 | 2903 | ||
| 2628 | cases.add( | 2904 | cases.add( |
| ... | @@ -2632,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2632,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2632 | \\ _ = a / a; | 2908 | \\ _ = a / a; |
| 2633 | \\} | 2909 | \\} |
| 2634 | , | 2910 | , |
| 2635 | ".tmp_source.zig:3:9: error: use of undefined value", | 2911 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2636 | ); | 2912 | ); |
| 2637 | 2913 | ||
| 2638 | cases.add( | 2914 | cases.add( |
| ... | @@ -2642,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2642,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2642 | \\ a /= a; | 2918 | \\ a /= a; |
| 2643 | \\} | 2919 | \\} |
| 2644 | , | 2920 | , |
| 2645 | ".tmp_source.zig:3:5: error: use of undefined value", | 2921 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2646 | ); | 2922 | ); |
| 2647 | 2923 | ||
| 2648 | cases.add( | 2924 | cases.add( |
| ... | @@ -2652,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2652,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2652 | \\ _ = a % a; | 2928 | \\ _ = a % a; |
| 2653 | \\} | 2929 | \\} |
| 2654 | , | 2930 | , |
| 2655 | ".tmp_source.zig:3:9: error: use of undefined value", | 2931 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2656 | ); | 2932 | ); |
| 2657 | 2933 | ||
| 2658 | cases.add( | 2934 | cases.add( |
| ... | @@ -2662,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2662,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2662 | \\ a %= a; | 2938 | \\ a %= a; |
| 2663 | \\} | 2939 | \\} |
| 2664 | , | 2940 | , |
| 2665 | ".tmp_source.zig:3:5: error: use of undefined value", | 2941 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2666 | ); | 2942 | ); |
| 2667 | 2943 | ||
| 2668 | cases.add( | 2944 | cases.add( |
| ... | @@ -2672,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2672,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2672 | \\ _ = a + a; | 2948 | \\ _ = a + a; |
| 2673 | \\} | 2949 | \\} |
| 2674 | , | 2950 | , |
| 2675 | ".tmp_source.zig:3:9: error: use of undefined value", | 2951 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2676 | ); | 2952 | ); |
| 2677 | 2953 | ||
| 2678 | cases.add( | 2954 | cases.add( |
| ... | @@ -2682,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2682,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2682 | \\ a += a; | 2958 | \\ a += a; |
| 2683 | \\} | 2959 | \\} |
| 2684 | , | 2960 | , |
| 2685 | ".tmp_source.zig:3:5: error: use of undefined value", | 2961 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2686 | ); | 2962 | ); |
| 2687 | 2963 | ||
| 2688 | cases.add( | 2964 | cases.add( |
| ... | @@ -2692,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2692,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2692 | \\ _ = a +% a; | 2968 | \\ _ = a +% a; |
| 2693 | \\} | 2969 | \\} |
| 2694 | , | 2970 | , |
| 2695 | ".tmp_source.zig:3:9: error: use of undefined value", | 2971 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2696 | ); | 2972 | ); |
| 2697 | 2973 | ||
| 2698 | cases.add( | 2974 | cases.add( |
| ... | @@ -2702,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2702,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2702 | \\ a +%= a; | 2978 | \\ a +%= a; |
| 2703 | \\} | 2979 | \\} |
| 2704 | , | 2980 | , |
| 2705 | ".tmp_source.zig:3:5: error: use of undefined value", | 2981 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2706 | ); | 2982 | ); |
| 2707 | 2983 | ||
| 2708 | cases.add( | 2984 | cases.add( |
| ... | @@ -2712,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2712,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2712 | \\ _ = a - a; | 2988 | \\ _ = a - a; |
| 2713 | \\} | 2989 | \\} |
| 2714 | , | 2990 | , |
| 2715 | ".tmp_source.zig:3:9: error: use of undefined value", | 2991 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2716 | ); | 2992 | ); |
| 2717 | 2993 | ||
| 2718 | cases.add( | 2994 | cases.add( |
| ... | @@ -2722,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2722,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2722 | \\ a -= a; | 2998 | \\ a -= a; |
| 2723 | \\} | 2999 | \\} |
| 2724 | , | 3000 | , |
| 2725 | ".tmp_source.zig:3:5: error: use of undefined value", | 3001 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2726 | ); | 3002 | ); |
| 2727 | 3003 | ||
| 2728 | cases.add( | 3004 | cases.add( |
| ... | @@ -2732,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2732,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2732 | \\ _ = a -% a; | 3008 | \\ _ = a -% a; |
| 2733 | \\} | 3009 | \\} |
| 2734 | , | 3010 | , |
| 2735 | ".tmp_source.zig:3:9: error: use of undefined value", | 3011 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2736 | ); | 3012 | ); |
| 2737 | 3013 | ||
| 2738 | cases.add( | 3014 | cases.add( |
| ... | @@ -2742,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2742,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2742 | \\ a -%= a; | 3018 | \\ a -%= a; |
| 2743 | \\} | 3019 | \\} |
| 2744 | , | 3020 | , |
| 2745 | ".tmp_source.zig:3:5: error: use of undefined value", | 3021 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2746 | ); | 3022 | ); |
| 2747 | 3023 | ||
| 2748 | cases.add( | 3024 | cases.add( |
| ... | @@ -2752,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2752,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2752 | \\ _ = a * a; | 3028 | \\ _ = a * a; |
| 2753 | \\} | 3029 | \\} |
| 2754 | , | 3030 | , |
| 2755 | ".tmp_source.zig:3:9: error: use of undefined value", | 3031 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2756 | ); | 3032 | ); |
| 2757 | 3033 | ||
| 2758 | cases.add( | 3034 | cases.add( |
| ... | @@ -2762,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2762,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2762 | \\ a *= a; | 3038 | \\ a *= a; |
| 2763 | \\} | 3039 | \\} |
| 2764 | , | 3040 | , |
| 2765 | ".tmp_source.zig:3:5: error: use of undefined value", | 3041 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2766 | ); | 3042 | ); |
| 2767 | 3043 | ||
| 2768 | cases.add( | 3044 | cases.add( |
| ... | @@ -2772,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2772,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2772 | \\ _ = a *% a; | 3048 | \\ _ = a *% a; |
| 2773 | \\} | 3049 | \\} |
| 2774 | , | 3050 | , |
| 2775 | ".tmp_source.zig:3:9: error: use of undefined value", | 3051 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2776 | ); | 3052 | ); |
| 2777 | 3053 | ||
| 2778 | cases.add( | 3054 | cases.add( |
| ... | @@ -2782,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2782,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2782 | \\ a *%= a; | 3058 | \\ a *%= a; |
| 2783 | \\} | 3059 | \\} |
| 2784 | , | 3060 | , |
| 2785 | ".tmp_source.zig:3:5: error: use of undefined value", | 3061 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2786 | ); | 3062 | ); |
| 2787 | 3063 | ||
| 2788 | cases.add( | 3064 | cases.add( |
| ... | @@ -2792,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2792,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2792 | \\ _ = a << 2; | 3068 | \\ _ = a << 2; |
| 2793 | \\} | 3069 | \\} |
| 2794 | , | 3070 | , |
| 2795 | ".tmp_source.zig:3:9: error: use of undefined value", | 3071 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2796 | ); | 3072 | ); |
| 2797 | 3073 | ||
| 2798 | cases.add( | 3074 | cases.add( |
| ... | @@ -2802,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2802,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2802 | \\ a <<= 2; | 3078 | \\ a <<= 2; |
| 2803 | \\} | 3079 | \\} |
| 2804 | , | 3080 | , |
| 2805 | ".tmp_source.zig:3:5: error: use of undefined value", | 3081 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2806 | ); | 3082 | ); |
| 2807 | 3083 | ||
| 2808 | cases.add( | 3084 | cases.add( |
| ... | @@ -2812,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2812,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2812 | \\ _ = a >> 2; | 3088 | \\ _ = a >> 2; |
| 2813 | \\} | 3089 | \\} |
| 2814 | , | 3090 | , |
| 2815 | ".tmp_source.zig:3:9: error: use of undefined value", | 3091 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2816 | ); | 3092 | ); |
| 2817 | 3093 | ||
| 2818 | cases.add( | 3094 | cases.add( |
| ... | @@ -2822,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2822,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2822 | \\ a >>= 2; | 3098 | \\ a >>= 2; |
| 2823 | \\} | 3099 | \\} |
| 2824 | , | 3100 | , |
| 2825 | ".tmp_source.zig:3:5: error: use of undefined value", | 3101 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2826 | ); | 3102 | ); |
| 2827 | 3103 | ||
| 2828 | cases.add( | 3104 | cases.add( |
| ... | @@ -2832,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2832,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2832 | \\ _ = a & a; | 3108 | \\ _ = a & a; |
| 2833 | \\} | 3109 | \\} |
| 2834 | , | 3110 | , |
| 2835 | ".tmp_source.zig:3:9: error: use of undefined value", | 3111 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2836 | ); | 3112 | ); |
| 2837 | 3113 | ||
| 2838 | cases.add( | 3114 | cases.add( |
| ... | @@ -2842,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2842,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2842 | \\ a &= a; | 3118 | \\ a &= a; |
| 2843 | \\} | 3119 | \\} |
| 2844 | , | 3120 | , |
| 2845 | ".tmp_source.zig:3:5: error: use of undefined value", | 3121 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2846 | ); | 3122 | ); |
| 2847 | 3123 | ||
| 2848 | cases.add( | 3124 | cases.add( |
| ... | @@ -2852,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2852,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2852 | \\ _ = a | a; | 3128 | \\ _ = a | a; |
| 2853 | \\} | 3129 | \\} |
| 2854 | , | 3130 | , |
| 2855 | ".tmp_source.zig:3:9: error: use of undefined value", | 3131 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2856 | ); | 3132 | ); |
| 2857 | 3133 | ||
| 2858 | cases.add( | 3134 | cases.add( |
| ... | @@ -2862,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2862,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2862 | \\ a |= a; | 3138 | \\ a |= a; |
| 2863 | \\} | 3139 | \\} |
| 2864 | , | 3140 | , |
| 2865 | ".tmp_source.zig:3:5: error: use of undefined value", | 3141 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2866 | ); | 3142 | ); |
| 2867 | 3143 | ||
| 2868 | cases.add( | 3144 | cases.add( |
| ... | @@ -2872,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2872,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2872 | \\ _ = a ^ a; | 3148 | \\ _ = a ^ a; |
| 2873 | \\} | 3149 | \\} |
| 2874 | , | 3150 | , |
| 2875 | ".tmp_source.zig:3:9: error: use of undefined value", | 3151 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2876 | ); | 3152 | ); |
| 2877 | 3153 | ||
| 2878 | cases.add( | 3154 | cases.add( |
| ... | @@ -2882,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2882,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2882 | \\ a ^= a; | 3158 | \\ a ^= a; |
| 2883 | \\} | 3159 | \\} |
| 2884 | , | 3160 | , |
| 2885 | ".tmp_source.zig:3:5: error: use of undefined value", | 3161 | ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior", |
| 2886 | ); | 3162 | ); |
| 2887 | 3163 | ||
| 2888 | cases.add( | 3164 | cases.add( |
| ... | @@ -2892,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2892,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2892 | \\ _ = a == a; | 3168 | \\ _ = a == a; |
| 2893 | \\} | 3169 | \\} |
| 2894 | , | 3170 | , |
| 2895 | ".tmp_source.zig:3:9: error: use of undefined value", | 3171 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2896 | ); | 3172 | ); |
| 2897 | 3173 | ||
| 2898 | cases.add( | 3174 | cases.add( |
| ... | @@ -2902,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2902,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2902 | \\ _ = a != a; | 3178 | \\ _ = a != a; |
| 2903 | \\} | 3179 | \\} |
| 2904 | , | 3180 | , |
| 2905 | ".tmp_source.zig:3:9: error: use of undefined value", | 3181 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2906 | ); | 3182 | ); |
| 2907 | 3183 | ||
| 2908 | cases.add( | 3184 | cases.add( |
| ... | @@ -2912,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2912,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2912 | \\ _ = a > a; | 3188 | \\ _ = a > a; |
| 2913 | \\} | 3189 | \\} |
| 2914 | , | 3190 | , |
| 2915 | ".tmp_source.zig:3:9: error: use of undefined value", | 3191 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2916 | ); | 3192 | ); |
| 2917 | 3193 | ||
| 2918 | cases.add( | 3194 | cases.add( |
| ... | @@ -2922,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2922,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2922 | \\ _ = a >= a; | 3198 | \\ _ = a >= a; |
| 2923 | \\} | 3199 | \\} |
| 2924 | , | 3200 | , |
| 2925 | ".tmp_source.zig:3:9: error: use of undefined value", | 3201 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2926 | ); | 3202 | ); |
| 2927 | 3203 | ||
| 2928 | cases.add( | 3204 | cases.add( |
| ... | @@ -2932,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2932,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2932 | \\ _ = a < a; | 3208 | \\ _ = a < a; |
| 2933 | \\} | 3209 | \\} |
| 2934 | , | 3210 | , |
| 2935 | ".tmp_source.zig:3:9: error: use of undefined value", | 3211 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2936 | ); | 3212 | ); |
| 2937 | 3213 | ||
| 2938 | cases.add( | 3214 | cases.add( |
| ... | @@ -2942,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2942,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2942 | \\ _ = a <= a; | 3218 | \\ _ = a <= a; |
| 2943 | \\} | 3219 | \\} |
| 2944 | , | 3220 | , |
| 2945 | ".tmp_source.zig:3:9: error: use of undefined value", | 3221 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2946 | ); | 3222 | ); |
| 2947 | 3223 | ||
| 2948 | cases.add( | 3224 | cases.add( |
| ... | @@ -2952,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2952,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2952 | \\ _ = a and a; | 3228 | \\ _ = a and a; |
| 2953 | \\} | 3229 | \\} |
| 2954 | , | 3230 | , |
| 2955 | ".tmp_source.zig:3:9: error: use of undefined value", | 3231 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2956 | ); | 3232 | ); |
| 2957 | 3233 | ||
| 2958 | cases.add( | 3234 | cases.add( |
| ... | @@ -2962,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2962,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2962 | \\ _ = a or a; | 3238 | \\ _ = a or a; |
| 2963 | \\} | 3239 | \\} |
| 2964 | , | 3240 | , |
| 2965 | ".tmp_source.zig:3:9: error: use of undefined value", | 3241 | ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior", |
| 2966 | ); | 3242 | ); |
| 2967 | 3243 | ||
| 2968 | cases.add( | 3244 | cases.add( |
| ... | @@ -2972,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2972,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2972 | \\ _ = -a; | 3248 | \\ _ = -a; |
| 2973 | \\} | 3249 | \\} |
| 2974 | , | 3250 | , |
| 2975 | ".tmp_source.zig:3:10: error: use of undefined value", | 3251 | ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior", |
| 2976 | ); | 3252 | ); |
| 2977 | 3253 | ||
| 2978 | cases.add( | 3254 | cases.add( |
| ... | @@ -2982,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2982,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2982 | \\ _ = -%a; | 3258 | \\ _ = -%a; |
| 2983 | \\} | 3259 | \\} |
| 2984 | , | 3260 | , |
| 2985 | ".tmp_source.zig:3:11: error: use of undefined value", | 3261 | ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior", |
| 2986 | ); | 3262 | ); |
| 2987 | 3263 | ||
| 2988 | cases.add( | 3264 | cases.add( |
| ... | @@ -2992,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2992,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2992 | \\ _ = ~a; | 3268 | \\ _ = ~a; |
| 2993 | \\} | 3269 | \\} |
| 2994 | , | 3270 | , |
| 2995 | ".tmp_source.zig:3:10: error: use of undefined value", | 3271 | ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior", |
| 2996 | ); | 3272 | ); |
| 2997 | 3273 | ||
| 2998 | cases.add( | 3274 | cases.add( |
| ... | @@ -3002,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3002,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3002 | \\ _ = !a; | 3278 | \\ _ = !a; |
| 3003 | \\} | 3279 | \\} |
| 3004 | , | 3280 | , |
| 3005 | ".tmp_source.zig:3:10: error: use of undefined value", | 3281 | ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior", |
| 3006 | ); | 3282 | ); |
| 3007 | 3283 | ||
| 3008 | cases.add( | 3284 | cases.add( |
| ... | @@ -3012,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3012,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3012 | \\ _ = a orelse false; | 3288 | \\ _ = a orelse false; |
| 3013 | \\} | 3289 | \\} |
| 3014 | , | 3290 | , |
| 3015 | ".tmp_source.zig:3:11: error: use of undefined value", | 3291 | ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior", |
| 3016 | ); | 3292 | ); |
| 3017 | 3293 | ||
| 3018 | cases.add( | 3294 | cases.add( |
| ... | @@ -3022,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3022,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3022 | \\ _ = a catch |err| false; | 3298 | \\ _ = a catch |err| false; |
| 3023 | \\} | 3299 | \\} |
| 3024 | , | 3300 | , |
| 3025 | ".tmp_source.zig:3:11: error: use of undefined value", | 3301 | ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior", |
| 3026 | ); | 3302 | ); |
| 3027 | 3303 | ||
| 3028 | cases.add( | 3304 | cases.add( |
| ... | @@ -3134,7 +3410,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3134,7 +3410,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3134 | \\ return 2; | 3410 | \\ return 2; |
| 3135 | \\} | 3411 | \\} |
| 3136 | , | 3412 | , |
| 3137 | ".tmp_source.zig:2:15: error: unable to infer expression type", | 3413 | ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known", |
| 3138 | ); | 3414 | ); |
| 3139 | 3415 | ||
| 3140 | cases.add( | 3416 | cases.add( |
| ... | @@ -3214,7 +3490,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3214,7 +3490,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3214 | cases.add( | 3490 | cases.add( |
| 3215 | "truncate sign mismatch", | 3491 | "truncate sign mismatch", |
| 3216 | \\fn f() i8 { | 3492 | \\fn f() i8 { |
| 3217 | \\ const x: u32 = 10; | 3493 | \\ var x: u32 = 10; |
| 3218 | \\ return @truncate(i8, x); | 3494 | \\ return @truncate(i8, x); |
| 3219 | \\} | 3495 | \\} |
| 3220 | \\ | 3496 | \\ |
| ... | @@ -3480,7 +3756,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3480,7 +3756,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3480 | \\ | 3756 | \\ |
| 3481 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | 3757 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } |
| 3482 | , | 3758 | , |
| 3483 | ".tmp_source.zig:2:11: error: expected type, found 'i32'", | 3759 | ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'", |
| 3484 | ); | 3760 | ); |
| 3485 | 3761 | ||
| 3486 | cases.add( | 3762 | cases.add( |
| ... | @@ -4424,20 +4700,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -4424,20 +4700,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4424 | ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal", | 4700 | ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal", |
| 4425 | ); | 4701 | ); |
| 4426 | 4702 | ||
| 4427 | cases.add( | ||
| 4428 | "@setEvalBranchQuota in non-root comptime execution context", | ||
| 4429 | \\comptime { | ||
| 4430 | \\ foo(); | ||
| 4431 | \\} | ||
| 4432 | \\fn foo() void { | ||
| 4433 | \\ @setEvalBranchQuota(1001); | ||
| 4434 | \\} | ||
| 4435 | , | ||
| 4436 | ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack", | ||
| 4437 | ".tmp_source.zig:2:8: note: called from here", | ||
| 4438 | ".tmp_source.zig:1:10: note: called from here", | ||
| 4439 | ); | ||
| 4440 | |||
| 4441 | cases.add( | 4703 | cases.add( |
| 4442 | "wrong pointer implicitly casted to pointer to @OpaqueType()", | 4704 | "wrong pointer implicitly casted to pointer to @OpaqueType()", |
| 4443 | \\const Derp = @OpaqueType(); | 4705 | \\const Derp = @OpaqueType(); |
| ... | @@ -5272,4 +5534,42 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -5272,4 +5534,42 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5272 | , | 5534 | , |
| 5273 | ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float", | 5535 | ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float", |
| 5274 | ); | 5536 | ); |
| 5537 | |||
| 5538 | cases.add( | ||
| 5539 | "runtime assignment to comptime struct type", | ||
| 5540 | \\const Foo = struct { | ||
| 5541 | \\ Bar: u8, | ||
| 5542 | \\ Baz: type, | ||
| 5543 | \\}; | ||
| 5544 | \\export fn f() void { | ||
| 5545 | \\ var x: u8 = 0; | ||
| 5546 | \\ const foo = Foo { .Bar = x, .Baz = u8 }; | ||
| 5547 | \\} | ||
| 5548 | , | ||
| 5549 | ".tmp_source.zig:7:30: error: unable to evaluate constant expression", | ||
| 5550 | ); | ||
| 5551 | |||
| 5552 | cases.add( | ||
| 5553 | "runtime assignment to comptime union type", | ||
| 5554 | \\const Foo = union { | ||
| 5555 | \\ Bar: u8, | ||
| 5556 | \\ Baz: type, | ||
| 5557 | \\}; | ||
| 5558 | \\export fn f() void { | ||
| 5559 | \\ var x: u8 = 0; | ||
| 5560 | \\ const foo = Foo { .Bar = x }; | ||
| 5561 | \\} | ||
| 5562 | , | ||
| 5563 | ".tmp_source.zig:7:30: error: unable to evaluate constant expression", | ||
| 5564 | ); | ||
| 5565 | |||
| 5566 | cases.addTest( | ||
| 5567 | "nested vectors", | ||
| 5568 | \\export fn entry() void { | ||
| 5569 | \\ const V = @Vector(4, @Vector(4, u8)); | ||
| 5570 | \\ var v: V = undefined; | ||
| 5571 | \\} | ||
| 5572 | , | ||
| 5573 | ".tmp_source.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid", | ||
| 5574 | ); | ||
| 5275 | } | 5575 | } |
test/runtime_safety.zig+41| ... | @@ -1,6 +1,16 @@ | ... | @@ -1,6 +1,16 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { | 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 4 | cases.addRuntimeSafety("pointer casting null to non-optional pointer", | ||
| 5 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | ||
| 6 | \\ @import("std").os.exit(126); | ||
| 7 | \\} | ||
| 8 | \\pub fn main() void { | ||
| 9 | \\ var c_ptr: [*c]u8 = 0; | ||
| 10 | \\ var zig_ptr: *u8 = c_ptr; | ||
| 11 | \\} | ||
| 12 | ); | ||
| 13 | |||
| 4 | cases.addRuntimeSafety("@intToEnum - no matching tag value", | 14 | cases.addRuntimeSafety("@intToEnum - no matching tag value", |
| 5 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | 15 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 6 | \\ @import("std").os.exit(126); | 16 | \\ @import("std").os.exit(126); |
| ... | @@ -94,6 +104,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -94,6 +104,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 94 | \\} | 104 | \\} |
| 95 | ); | 105 | ); |
| 96 | 106 | ||
| 107 | cases.addRuntimeSafety("vector integer addition overflow", | ||
| 108 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | ||
| 109 | \\ @import("std").os.exit(126); | ||
| 110 | \\} | ||
| 111 | \\pub fn main() void { | ||
| 112 | \\ var a: @Vector(4, i32) = []i32{ 1, 2, 2147483643, 4 }; | ||
| 113 | \\ var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 }; | ||
| 114 | \\ const x = add(a, b); | ||
| 115 | \\} | ||
| 116 | \\fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ||
| 117 | \\ return a + b; | ||
| 118 | \\} | ||
| 119 | ); | ||
| 120 | |||
| 97 | cases.addRuntimeSafety("integer subtraction overflow", | 121 | cases.addRuntimeSafety("integer subtraction overflow", |
| 98 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | 122 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 99 | \\ @import("std").os.exit(126); | 123 | \\ @import("std").os.exit(126); |
| ... | @@ -362,6 +386,23 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -362,6 +386,23 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 362 | \\} | 386 | \\} |
| 363 | ); | 387 | ); |
| 364 | 388 | ||
| 389 | // @intCast a runtime integer to u0 actually results in a comptime-known value, | ||
| 390 | // but we still emit a safety check to ensure the integer was 0 and thus | ||
| 391 | // did not truncate information. | ||
| 392 | cases.addRuntimeSafety("@intCast to u0", | ||
| 393 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | ||
| 394 | \\ @import("std").os.exit(126); | ||
| 395 | \\} | ||
| 396 | \\ | ||
| 397 | \\pub fn main() void { | ||
| 398 | \\ bar(1, 1); | ||
| 399 | \\} | ||
| 400 | \\ | ||
| 401 | \\fn bar(one: u1, not_zero: i32) void { | ||
| 402 | \\ var x = one << @intCast(u0, not_zero); | ||
| 403 | \\} | ||
| 404 | ); | ||
| 405 | |||
| 365 | // This case makes sure that the code compiles and runs. There is not actually a special | 406 | // This case makes sure that the code compiles and runs. There is not actually a special |
| 366 | // runtime safety check having to do specifically with error return traces across suspend points. | 407 | // runtime safety check having to do specifically with error return traces across suspend points. |
| 367 | cases.addRuntimeSafety("error return trace across suspend points", | 408 | cases.addRuntimeSafety("error return trace across suspend points", |
test/stage1/behavior.zig created+82| ... | @@ -0,0 +1,82 @@ | ||
| 1 | comptime { | ||
| 2 | _ = @import("behavior/align.zig"); | ||
| 3 | _ = @import("behavior/alignof.zig"); | ||
| 4 | _ = @import("behavior/array.zig"); | ||
| 5 | _ = @import("behavior/asm.zig"); | ||
| 6 | _ = @import("behavior/atomics.zig"); | ||
| 7 | _ = @import("behavior/bit_shifting.zig"); | ||
| 8 | _ = @import("behavior/bitcast.zig"); | ||
| 9 | _ = @import("behavior/bitreverse.zig"); | ||
| 10 | _ = @import("behavior/bool.zig"); | ||
| 11 | _ = @import("behavior/bswap.zig"); | ||
| 12 | _ = @import("behavior/bugs/1076.zig"); | ||
| 13 | _ = @import("behavior/bugs/1111.zig"); | ||
| 14 | _ = @import("behavior/bugs/1277.zig"); | ||
| 15 | _ = @import("behavior/bugs/1322.zig"); | ||
| 16 | _ = @import("behavior/bugs/1381.zig"); | ||
| 17 | _ = @import("behavior/bugs/1421.zig"); | ||
| 18 | _ = @import("behavior/bugs/1442.zig"); | ||
| 19 | _ = @import("behavior/bugs/1486.zig"); | ||
| 20 | _ = @import("behavior/bugs/1851.zig"); | ||
| 21 | _ = @import("behavior/bugs/394.zig"); | ||
| 22 | _ = @import("behavior/bugs/655.zig"); | ||
| 23 | _ = @import("behavior/bugs/656.zig"); | ||
| 24 | _ = @import("behavior/bugs/726.zig"); | ||
| 25 | _ = @import("behavior/bugs/828.zig"); | ||
| 26 | _ = @import("behavior/bugs/920.zig"); | ||
| 27 | _ = @import("behavior/byval_arg_var.zig"); | ||
| 28 | _ = @import("behavior/cancel.zig"); | ||
| 29 | _ = @import("behavior/cast.zig"); | ||
| 30 | _ = @import("behavior/const_slice_child.zig"); | ||
| 31 | _ = @import("behavior/coroutine_await_struct.zig"); | ||
| 32 | _ = @import("behavior/coroutines.zig"); | ||
| 33 | _ = @import("behavior/defer.zig"); | ||
| 34 | _ = @import("behavior/enum.zig"); | ||
| 35 | _ = @import("behavior/enum_with_members.zig"); | ||
| 36 | _ = @import("behavior/error.zig"); | ||
| 37 | _ = @import("behavior/eval.zig"); | ||
| 38 | _ = @import("behavior/field_parent_ptr.zig"); | ||
| 39 | _ = @import("behavior/fn.zig"); | ||
| 40 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | ||
| 41 | _ = @import("behavior/for.zig"); | ||
| 42 | _ = @import("behavior/generics.zig"); | ||
| 43 | _ = @import("behavior/if.zig"); | ||
| 44 | _ = @import("behavior/import.zig"); | ||
| 45 | _ = @import("behavior/incomplete_struct_param_tld.zig"); | ||
| 46 | _ = @import("behavior/inttoptr.zig"); | ||
| 47 | _ = @import("behavior/ir_block_deps.zig"); | ||
| 48 | _ = @import("behavior/math.zig"); | ||
| 49 | _ = @import("behavior/merge_error_sets.zig"); | ||
| 50 | _ = @import("behavior/misc.zig"); | ||
| 51 | _ = @import("behavior/namespace_depends_on_compile_var/index.zig"); | ||
| 52 | _ = @import("behavior/new_stack_call.zig"); | ||
| 53 | _ = @import("behavior/null.zig"); | ||
| 54 | _ = @import("behavior/optional.zig"); | ||
| 55 | _ = @import("behavior/pointers.zig"); | ||
| 56 | _ = @import("behavior/popcount.zig"); | ||
| 57 | _ = @import("behavior/ptrcast.zig"); | ||
| 58 | _ = @import("behavior/pub_enum/index.zig"); | ||
| 59 | _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); | ||
| 60 | _ = @import("behavior/reflection.zig"); | ||
| 61 | _ = @import("behavior/sizeof_and_typeof.zig"); | ||
| 62 | _ = @import("behavior/slice.zig"); | ||
| 63 | _ = @import("behavior/struct.zig"); | ||
| 64 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); | ||
| 65 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); | ||
| 66 | _ = @import("behavior/switch.zig"); | ||
| 67 | _ = @import("behavior/switch_prong_err_enum.zig"); | ||
| 68 | _ = @import("behavior/switch_prong_implicit_cast.zig"); | ||
| 69 | _ = @import("behavior/syntax.zig"); | ||
| 70 | _ = @import("behavior/this.zig"); | ||
| 71 | _ = @import("behavior/truncate.zig"); | ||
| 72 | _ = @import("behavior/try.zig"); | ||
| 73 | _ = @import("behavior/type_info.zig"); | ||
| 74 | _ = @import("behavior/undefined.zig"); | ||
| 75 | _ = @import("behavior/underscore.zig"); | ||
| 76 | _ = @import("behavior/union.zig"); | ||
| 77 | _ = @import("behavior/var_args.zig"); | ||
| 78 | _ = @import("behavior/vector.zig"); | ||
| 79 | _ = @import("behavior/void.zig"); | ||
| 80 | _ = @import("behavior/while.zig"); | ||
| 81 | _ = @import("behavior/widening.zig"); | ||
| 82 | } | ||
test/stage1/behavior/align.zig created+230| ... | @@ -0,0 +1,230 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | var foo: u8 align(4) = 100; | ||
| 5 | |||
| 6 | test "global variable alignment" { | ||
| 7 | expect(@typeOf(&foo).alignment == 4); | ||
| 8 | expect(@typeOf(&foo) == *align(4) u8); | ||
| 9 | const slice = (*[1]u8)(&foo)[0..]; | ||
| 10 | expect(@typeOf(slice) == []align(4) u8); | ||
| 11 | } | ||
| 12 | |||
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { | ||
| 14 | return 1234; | ||
| 15 | } | ||
| 16 | fn noop1() align(1) void {} | ||
| 17 | fn noop4() align(4) void {} | ||
| 18 | |||
| 19 | test "function alignment" { | ||
| 20 | expect(derp() == 1234); | ||
| 21 | expect(@typeOf(noop1) == fn () align(1) void); | ||
| 22 | expect(@typeOf(noop4) == fn () align(4) void); | ||
| 23 | noop1(); | ||
| 24 | noop4(); | ||
| 25 | } | ||
| 26 | |||
| 27 | var baz: packed struct { | ||
| 28 | a: u32, | ||
| 29 | b: u32, | ||
| 30 | } = undefined; | ||
| 31 | |||
| 32 | test "packed struct alignment" { | ||
| 33 | expect(@typeOf(&baz.b) == *align(1) u32); | ||
| 34 | } | ||
| 35 | |||
| 36 | const blah: packed struct { | ||
| 37 | a: u3, | ||
| 38 | b: u3, | ||
| 39 | c: u2, | ||
| 40 | } = undefined; | ||
| 41 | |||
| 42 | test "bit field alignment" { | ||
| 43 | expect(@typeOf(&blah.b) == *align(1:3:1) const u3); | ||
| 44 | } | ||
| 45 | |||
| 46 | test "default alignment allows unspecified in type syntax" { | ||
| 47 | expect(*u32 == *align(@alignOf(u32)) u32); | ||
| 48 | } | ||
| 49 | |||
| 50 | test "implicitly decreasing pointer alignment" { | ||
| 51 | const a: u32 align(4) = 3; | ||
| 52 | const b: u32 align(8) = 4; | ||
| 53 | expect(addUnaligned(&a, &b) == 7); | ||
| 54 | } | ||
| 55 | |||
| 56 | fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | ||
| 57 | return a.* + b.*; | ||
| 58 | } | ||
| 59 | |||
| 60 | test "implicitly decreasing slice alignment" { | ||
| 61 | const a: u32 align(4) = 3; | ||
| 62 | const b: u32 align(8) = 4; | ||
| 63 | expect(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); | ||
| 64 | } | ||
| 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { | ||
| 66 | return a[0] + b[0]; | ||
| 67 | } | ||
| 68 | |||
| 69 | test "specifying alignment allows pointer cast" { | ||
| 70 | testBytesAlign(0x33); | ||
| 71 | } | ||
| 72 | fn testBytesAlign(b: u8) void { | ||
| 73 | var bytes align(4) = []u8{ | ||
| 74 | b, | ||
| 75 | b, | ||
| 76 | b, | ||
| 77 | b, | ||
| 78 | }; | ||
| 79 | const ptr = @ptrCast(*u32, &bytes[0]); | ||
| 80 | expect(ptr.* == 0x33333333); | ||
| 81 | } | ||
| 82 | |||
| 83 | test "specifying alignment allows slice cast" { | ||
| 84 | testBytesAlignSlice(0x33); | ||
| 85 | } | ||
| 86 | fn testBytesAlignSlice(b: u8) void { | ||
| 87 | var bytes align(4) = []u8{ | ||
| 88 | b, | ||
| 89 | b, | ||
| 90 | b, | ||
| 91 | b, | ||
| 92 | }; | ||
| 93 | const slice: []u32 = @bytesToSlice(u32, bytes[0..]); | ||
| 94 | expect(slice[0] == 0x33333333); | ||
| 95 | } | ||
| 96 | |||
| 97 | test "@alignCast pointers" { | ||
| 98 | var x: u32 align(4) = 1; | ||
| 99 | expectsOnly1(&x); | ||
| 100 | expect(x == 2); | ||
| 101 | } | ||
| 102 | fn expectsOnly1(x: *align(1) u32) void { | ||
| 103 | expects4(@alignCast(4, x)); | ||
| 104 | } | ||
| 105 | fn expects4(x: *align(4) u32) void { | ||
| 106 | x.* += 1; | ||
| 107 | } | ||
| 108 | |||
| 109 | test "@alignCast slices" { | ||
| 110 | var array align(4) = []u32{ | ||
| 111 | 1, | ||
| 112 | 1, | ||
| 113 | }; | ||
| 114 | const slice = array[0..]; | ||
| 115 | sliceExpectsOnly1(slice); | ||
| 116 | expect(slice[0] == 2); | ||
| 117 | } | ||
| 118 | fn sliceExpectsOnly1(slice: []align(1) u32) void { | ||
| 119 | sliceExpects4(@alignCast(4, slice)); | ||
| 120 | } | ||
| 121 | fn sliceExpects4(slice: []align(4) u32) void { | ||
| 122 | slice[0] += 1; | ||
| 123 | } | ||
| 124 | |||
| 125 | test "implicitly decreasing fn alignment" { | ||
| 126 | testImplicitlyDecreaseFnAlign(alignedSmall, 1234); | ||
| 127 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); | ||
| 128 | } | ||
| 129 | |||
| 130 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { | ||
| 131 | expect(ptr() == answer); | ||
| 132 | } | ||
| 133 | |||
| 134 | fn alignedSmall() align(8) i32 { | ||
| 135 | return 1234; | ||
| 136 | } | ||
| 137 | fn alignedBig() align(16) i32 { | ||
| 138 | return 5678; | ||
| 139 | } | ||
| 140 | |||
| 141 | test "@alignCast functions" { | ||
| 142 | expect(fnExpectsOnly1(simple4) == 0x19); | ||
| 143 | } | ||
| 144 | fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 { | ||
| 145 | return fnExpects4(@alignCast(4, ptr)); | ||
| 146 | } | ||
| 147 | fn fnExpects4(ptr: fn () align(4) i32) i32 { | ||
| 148 | return ptr(); | ||
| 149 | } | ||
| 150 | fn simple4() align(4) i32 { | ||
| 151 | return 0x19; | ||
| 152 | } | ||
| 153 | |||
| 154 | test "generic function with align param" { | ||
| 155 | expect(whyWouldYouEverDoThis(1) == 0x1); | ||
| 156 | expect(whyWouldYouEverDoThis(4) == 0x1); | ||
| 157 | expect(whyWouldYouEverDoThis(8) == 0x1); | ||
| 158 | } | ||
| 159 | |||
| 160 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { | ||
| 161 | return 0x1; | ||
| 162 | } | ||
| 163 | |||
| 164 | test "@ptrCast preserves alignment of bigger source" { | ||
| 165 | var x: u32 align(16) = 1234; | ||
| 166 | const ptr = @ptrCast(*u8, &x); | ||
| 167 | expect(@typeOf(ptr) == *align(16) u8); | ||
| 168 | } | ||
| 169 | |||
| 170 | test "runtime known array index has best alignment possible" { | ||
| 171 | // take full advantage of over-alignment | ||
| 172 | var array align(4) = []u8{ 1, 2, 3, 4 }; | ||
| 173 | expect(@typeOf(&array[0]) == *align(4) u8); | ||
| 174 | expect(@typeOf(&array[1]) == *u8); | ||
| 175 | expect(@typeOf(&array[2]) == *align(2) u8); | ||
| 176 | expect(@typeOf(&array[3]) == *u8); | ||
| 177 | |||
| 178 | // because align is too small but we still figure out to use 2 | ||
| 179 | var bigger align(2) = []u64{ 1, 2, 3, 4 }; | ||
| 180 | expect(@typeOf(&bigger[0]) == *align(2) u64); | ||
| 181 | expect(@typeOf(&bigger[1]) == *align(2) u64); | ||
| 182 | expect(@typeOf(&bigger[2]) == *align(2) u64); | ||
| 183 | expect(@typeOf(&bigger[3]) == *align(2) u64); | ||
| 184 | |||
| 185 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 | ||
| 186 | var smaller align(2) = []u32{ 1, 2, 3, 4 }; | ||
| 187 | comptime expect(@typeOf(smaller[0..]) == []align(2) u32); | ||
| 188 | comptime expect(@typeOf(smaller[0..].ptr) == [*]align(2) u32); | ||
| 189 | testIndex(smaller[0..].ptr, 0, *align(2) u32); | ||
| 190 | testIndex(smaller[0..].ptr, 1, *align(2) u32); | ||
| 191 | testIndex(smaller[0..].ptr, 2, *align(2) u32); | ||
| 192 | testIndex(smaller[0..].ptr, 3, *align(2) u32); | ||
| 193 | |||
| 194 | // has to use ABI alignment because index known at runtime only | ||
| 195 | testIndex2(array[0..].ptr, 0, *u8); | ||
| 196 | testIndex2(array[0..].ptr, 1, *u8); | ||
| 197 | testIndex2(array[0..].ptr, 2, *u8); | ||
| 198 | testIndex2(array[0..].ptr, 3, *u8); | ||
| 199 | } | ||
| 200 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { | ||
| 201 | comptime expect(@typeOf(&smaller[index]) == T); | ||
| 202 | } | ||
| 203 | fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void { | ||
| 204 | comptime expect(@typeOf(&ptr[index]) == T); | ||
| 205 | } | ||
| 206 | |||
| 207 | test "alignstack" { | ||
| 208 | expect(fnWithAlignedStack() == 1234); | ||
| 209 | } | ||
| 210 | |||
| 211 | fn fnWithAlignedStack() i32 { | ||
| 212 | @setAlignStack(256); | ||
| 213 | return 1234; | ||
| 214 | } | ||
| 215 | |||
| 216 | test "alignment of structs" { | ||
| 217 | expect(@alignOf(struct { | ||
| 218 | a: i32, | ||
| 219 | b: *i32, | ||
| 220 | }) == @alignOf(usize)); | ||
| 221 | } | ||
| 222 | |||
| 223 | test "alignment of extern() void" { | ||
| 224 | var runtime_nothing = nothing; | ||
| 225 | const casted1 = @ptrCast(*const u8, runtime_nothing); | ||
| 226 | const casted2 = @ptrCast(extern fn () void, casted1); | ||
| 227 | casted2(); | ||
| 228 | } | ||
| 229 | |||
| 230 | extern fn nothing() void {} | ||
test/stage1/behavior/alignof.zig created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const maxInt = std.math.maxInt; | ||
| 5 | |||
| 6 | const Foo = struct { | ||
| 7 | x: u32, | ||
| 8 | y: u32, | ||
| 9 | z: u32, | ||
| 10 | }; | ||
| 11 | |||
| 12 | test "@alignOf(T) before referencing T" { | ||
| 13 | comptime expect(@alignOf(Foo) != maxInt(usize)); | ||
| 14 | if (builtin.arch == builtin.Arch.x86_64) { | ||
| 15 | comptime expect(@alignOf(Foo) == 4); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
test/stage1/behavior/array.zig created+270| ... | @@ -0,0 +1,270 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | test "arrays" { | ||
| 5 | var array: [5]u32 = undefined; | ||
| 6 | |||
| 7 | var i: u32 = 0; | ||
| 8 | while (i < 5) { | ||
| 9 | array[i] = i + 1; | ||
| 10 | i = array[i]; | ||
| 11 | } | ||
| 12 | |||
| 13 | i = 0; | ||
| 14 | var accumulator = u32(0); | ||
| 15 | while (i < 5) { | ||
| 16 | accumulator += array[i]; | ||
| 17 | |||
| 18 | i += 1; | ||
| 19 | } | ||
| 20 | |||
| 21 | expect(accumulator == 15); | ||
| 22 | expect(getArrayLen(array) == 5); | ||
| 23 | } | ||
| 24 | fn getArrayLen(a: []const u32) usize { | ||
| 25 | return a.len; | ||
| 26 | } | ||
| 27 | |||
| 28 | test "void arrays" { | ||
| 29 | var array: [4]void = undefined; | ||
| 30 | array[0] = void{}; | ||
| 31 | array[1] = array[2]; | ||
| 32 | expect(@sizeOf(@typeOf(array)) == 0); | ||
| 33 | expect(array.len == 4); | ||
| 34 | } | ||
| 35 | |||
| 36 | test "array literal" { | ||
| 37 | const hex_mult = []u16{ | ||
| 38 | 4096, | ||
| 39 | 256, | ||
| 40 | 16, | ||
| 41 | 1, | ||
| 42 | }; | ||
| 43 | |||
| 44 | expect(hex_mult.len == 4); | ||
| 45 | expect(hex_mult[1] == 256); | ||
| 46 | } | ||
| 47 | |||
| 48 | test "array dot len const expr" { | ||
| 49 | expect(comptime x: { | ||
| 50 | break :x some_array.len == 4; | ||
| 51 | }); | ||
| 52 | } | ||
| 53 | |||
| 54 | const ArrayDotLenConstExpr = struct { | ||
| 55 | y: [some_array.len]u8, | ||
| 56 | }; | ||
| 57 | const some_array = []u8{ | ||
| 58 | 0, | ||
| 59 | 1, | ||
| 60 | 2, | ||
| 61 | 3, | ||
| 62 | }; | ||
| 63 | |||
| 64 | test "nested arrays" { | ||
| 65 | const array_of_strings = [][]const u8{ | ||
| 66 | "hello", | ||
| 67 | "this", | ||
| 68 | "is", | ||
| 69 | "my", | ||
| 70 | "thing", | ||
| 71 | }; | ||
| 72 | for (array_of_strings) |s, i| { | ||
| 73 | if (i == 0) expect(mem.eql(u8, s, "hello")); | ||
| 74 | if (i == 1) expect(mem.eql(u8, s, "this")); | ||
| 75 | if (i == 2) expect(mem.eql(u8, s, "is")); | ||
| 76 | if (i == 3) expect(mem.eql(u8, s, "my")); | ||
| 77 | if (i == 4) expect(mem.eql(u8, s, "thing")); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | var s_array: [8]Sub = undefined; | ||
| 82 | const Sub = struct { | ||
| 83 | b: u8, | ||
| 84 | }; | ||
| 85 | const Str = struct { | ||
| 86 | a: []Sub, | ||
| 87 | }; | ||
| 88 | test "set global var array via slice embedded in struct" { | ||
| 89 | var s = Str{ .a = s_array[0..] }; | ||
| 90 | |||
| 91 | s.a[0].b = 1; | ||
| 92 | s.a[1].b = 2; | ||
| 93 | s.a[2].b = 3; | ||
| 94 | |||
| 95 | expect(s_array[0].b == 1); | ||
| 96 | expect(s_array[1].b == 2); | ||
| 97 | expect(s_array[2].b == 3); | ||
| 98 | } | ||
| 99 | |||
| 100 | test "array literal with specified size" { | ||
| 101 | var array = [2]u8{ | ||
| 102 | 1, | ||
| 103 | 2, | ||
| 104 | }; | ||
| 105 | expect(array[0] == 1); | ||
| 106 | expect(array[1] == 2); | ||
| 107 | } | ||
| 108 | |||
| 109 | test "array child property" { | ||
| 110 | var x: [5]i32 = undefined; | ||
| 111 | expect(@typeOf(x).Child == i32); | ||
| 112 | } | ||
| 113 | |||
| 114 | test "array len property" { | ||
| 115 | var x: [5]i32 = undefined; | ||
| 116 | expect(@typeOf(x).len == 5); | ||
| 117 | } | ||
| 118 | |||
| 119 | test "array len field" { | ||
| 120 | var arr = [4]u8{ 0, 0, 0, 0 }; | ||
| 121 | var ptr = &arr; | ||
| 122 | expect(arr.len == 4); | ||
| 123 | comptime expect(arr.len == 4); | ||
| 124 | expect(ptr.len == 4); | ||
| 125 | comptime expect(ptr.len == 4); | ||
| 126 | } | ||
| 127 | |||
| 128 | test "single-item pointer to array indexing and slicing" { | ||
| 129 | testSingleItemPtrArrayIndexSlice(); | ||
| 130 | comptime testSingleItemPtrArrayIndexSlice(); | ||
| 131 | } | ||
| 132 | |||
| 133 | fn testSingleItemPtrArrayIndexSlice() void { | ||
| 134 | var array = "aaaa"; | ||
| 135 | doSomeMangling(&array); | ||
| 136 | expect(mem.eql(u8, "azya", array)); | ||
| 137 | } | ||
| 138 | |||
| 139 | fn doSomeMangling(array: *[4]u8) void { | ||
| 140 | array[1] = 'z'; | ||
| 141 | array[2..3][0] = 'y'; | ||
| 142 | } | ||
| 143 | |||
| 144 | test "implicit cast single-item pointer" { | ||
| 145 | testImplicitCastSingleItemPtr(); | ||
| 146 | comptime testImplicitCastSingleItemPtr(); | ||
| 147 | } | ||
| 148 | |||
| 149 | fn testImplicitCastSingleItemPtr() void { | ||
| 150 | var byte: u8 = 100; | ||
| 151 | const slice = (*[1]u8)(&byte)[0..]; | ||
| 152 | slice[0] += 1; | ||
| 153 | expect(byte == 101); | ||
| 154 | } | ||
| 155 | |||
| 156 | fn testArrayByValAtComptime(b: [2]u8) u8 { | ||
| 157 | return b[0]; | ||
| 158 | } | ||
| 159 | |||
| 160 | test "comptime evalutating function that takes array by value" { | ||
| 161 | const arr = []u8{ 0, 1 }; | ||
| 162 | _ = comptime testArrayByValAtComptime(arr); | ||
| 163 | _ = comptime testArrayByValAtComptime(arr); | ||
| 164 | } | ||
| 165 | |||
| 166 | test "implicit comptime in array type size" { | ||
| 167 | var arr: [plusOne(10)]bool = undefined; | ||
| 168 | expect(arr.len == 11); | ||
| 169 | } | ||
| 170 | |||
| 171 | fn plusOne(x: u32) u32 { | ||
| 172 | return x + 1; | ||
| 173 | } | ||
| 174 | |||
| 175 | test "array literal as argument to function" { | ||
| 176 | const S = struct { | ||
| 177 | fn entry(two: i32) void { | ||
| 178 | foo([]i32{ | ||
| 179 | 1, | ||
| 180 | 2, | ||
| 181 | 3, | ||
| 182 | }); | ||
| 183 | foo([]i32{ | ||
| 184 | 1, | ||
| 185 | two, | ||
| 186 | 3, | ||
| 187 | }); | ||
| 188 | foo2(true, []i32{ | ||
| 189 | 1, | ||
| 190 | 2, | ||
| 191 | 3, | ||
| 192 | }); | ||
| 193 | foo2(true, []i32{ | ||
| 194 | 1, | ||
| 195 | two, | ||
| 196 | 3, | ||
| 197 | }); | ||
| 198 | } | ||
| 199 | fn foo(x: []const i32) void { | ||
| 200 | expect(x[0] == 1); | ||
| 201 | expect(x[1] == 2); | ||
| 202 | expect(x[2] == 3); | ||
| 203 | } | ||
| 204 | fn foo2(trash: bool, x: []const i32) void { | ||
| 205 | expect(trash); | ||
| 206 | expect(x[0] == 1); | ||
| 207 | expect(x[1] == 2); | ||
| 208 | expect(x[2] == 3); | ||
| 209 | } | ||
| 210 | }; | ||
| 211 | S.entry(2); | ||
| 212 | comptime S.entry(2); | ||
| 213 | } | ||
| 214 | |||
| 215 | test "double nested array to const slice cast in array literal" { | ||
| 216 | const S = struct { | ||
| 217 | fn entry(two: i32) void { | ||
| 218 | const cases = [][]const []const i32{ | ||
| 219 | [][]const i32{[]i32{1}}, | ||
| 220 | [][]const i32{[]i32{ 2, 3 }}, | ||
| 221 | [][]const i32{ | ||
| 222 | []i32{4}, | ||
| 223 | []i32{ 5, 6, 7 }, | ||
| 224 | }, | ||
| 225 | }; | ||
| 226 | check(cases); | ||
| 227 | |||
| 228 | const cases2 = [][]const i32{ | ||
| 229 | []i32{1}, | ||
| 230 | []i32{ two, 3 }, | ||
| 231 | }; | ||
| 232 | expect(cases2.len == 2); | ||
| 233 | expect(cases2[0].len == 1); | ||
| 234 | expect(cases2[0][0] == 1); | ||
| 235 | expect(cases2[1].len == 2); | ||
| 236 | expect(cases2[1][0] == 2); | ||
| 237 | expect(cases2[1][1] == 3); | ||
| 238 | |||
| 239 | const cases3 = [][]const []const i32{ | ||
| 240 | [][]const i32{[]i32{1}}, | ||
| 241 | [][]const i32{[]i32{ two, 3 }}, | ||
| 242 | [][]const i32{ | ||
| 243 | []i32{4}, | ||
| 244 | []i32{ 5, 6, 7 }, | ||
| 245 | }, | ||
| 246 | }; | ||
| 247 | check(cases3); | ||
| 248 | } | ||
| 249 | |||
| 250 | fn check(cases: []const []const []const i32) void { | ||
| 251 | expect(cases.len == 3); | ||
| 252 | expect(cases[0].len == 1); | ||
| 253 | expect(cases[0][0].len == 1); | ||
| 254 | expect(cases[0][0][0] == 1); | ||
| 255 | expect(cases[1].len == 1); | ||
| 256 | expect(cases[1][0].len == 2); | ||
| 257 | expect(cases[1][0][0] == 2); | ||
| 258 | expect(cases[1][0][1] == 3); | ||
| 259 | expect(cases[2].len == 2); | ||
| 260 | expect(cases[2][0].len == 1); | ||
| 261 | expect(cases[2][0][0] == 4); | ||
| 262 | expect(cases[2][1].len == 3); | ||
| 263 | expect(cases[2][1][0] == 5); | ||
| 264 | expect(cases[2][1][1] == 6); | ||
| 265 | expect(cases[2][1][2] == 7); | ||
| 266 | } | ||
| 267 | }; | ||
| 268 | S.entry(2); | ||
| 269 | comptime S.entry(2); | ||
| 270 | } | ||
test/stage1/behavior/asm.zig created+92| ... | @@ -0,0 +1,92 @@ | ||
| 1 | const config = @import("builtin"); | ||
| 2 | const expect = @import("std").testing.expect; | ||
| 3 | |||
| 4 | comptime { | ||
| 5 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | ||
| 6 | asm volatile ( | ||
| 7 | \\.globl aoeu; | ||
| 8 | \\.type aoeu, @function; | ||
| 9 | \\.set aoeu, derp; | ||
| 10 | ); | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | test "module level assembly" { | ||
| 15 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | ||
| 16 | expect(aoeu() == 1234); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | test "output constraint modifiers" { | ||
| 21 | // This is only testing compilation. | ||
| 22 | var a: u32 = 3; | ||
| 23 | asm volatile ("" | ||
| 24 | : [_] "=m,r" (a) | ||
| 25 | : | ||
| 26 | : "" | ||
| 27 | ); | ||
| 28 | asm volatile ("" | ||
| 29 | : [_] "=r,m" (a) | ||
| 30 | : | ||
| 31 | : "" | ||
| 32 | ); | ||
| 33 | } | ||
| 34 | |||
| 35 | test "alternative constraints" { | ||
| 36 | // Make sure we allow commas as a separator for alternative constraints. | ||
| 37 | var a: u32 = 3; | ||
| 38 | asm volatile ("" | ||
| 39 | : [_] "=r,m" (a) | ||
| 40 | : [_] "r,m" (a) | ||
| 41 | : "" | ||
| 42 | ); | ||
| 43 | } | ||
| 44 | |||
| 45 | test "sized integer/float in asm input" { | ||
| 46 | asm volatile ("" | ||
| 47 | : | ||
| 48 | : [_] "m" (usize(3)) | ||
| 49 | : "" | ||
| 50 | ); | ||
| 51 | asm volatile ("" | ||
| 52 | : | ||
| 53 | : [_] "m" (i15(-3)) | ||
| 54 | : "" | ||
| 55 | ); | ||
| 56 | asm volatile ("" | ||
| 57 | : | ||
| 58 | : [_] "m" (u3(3)) | ||
| 59 | : "" | ||
| 60 | ); | ||
| 61 | asm volatile ("" | ||
| 62 | : | ||
| 63 | : [_] "m" (i3(3)) | ||
| 64 | : "" | ||
| 65 | ); | ||
| 66 | asm volatile ("" | ||
| 67 | : | ||
| 68 | : [_] "m" (u121(3)) | ||
| 69 | : "" | ||
| 70 | ); | ||
| 71 | asm volatile ("" | ||
| 72 | : | ||
| 73 | : [_] "m" (i121(3)) | ||
| 74 | : "" | ||
| 75 | ); | ||
| 76 | asm volatile ("" | ||
| 77 | : | ||
| 78 | : [_] "m" (f32(3.17)) | ||
| 79 | : "" | ||
| 80 | ); | ||
| 81 | asm volatile ("" | ||
| 82 | : | ||
| 83 | : [_] "m" (f64(3.17)) | ||
| 84 | : "" | ||
| 85 | ); | ||
| 86 | } | ||
| 87 | |||
| 88 | extern fn aoeu() i32; | ||
| 89 | |||
| 90 | export fn derp() i32 { | ||
| 91 | return 1234; | ||
| 92 | } | ||
test/stage1/behavior/atomics.zig created+71| ... | @@ -0,0 +1,71 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | ||
| 5 | const AtomicOrder = builtin.AtomicOrder; | ||
| 6 | |||
| 7 | test "cmpxchg" { | ||
| 8 | var x: i32 = 1234; | ||
| 9 | if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 10 | expect(x1 == 1234); | ||
| 11 | } else { | ||
| 12 | @panic("cmpxchg should have failed"); | ||
| 13 | } | ||
| 14 | |||
| 15 | while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 16 | expect(x1 == 1234); | ||
| 17 | } | ||
| 18 | expect(x == 5678); | ||
| 19 | |||
| 20 | expect(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | ||
| 21 | expect(x == 42); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "fence" { | ||
| 25 | var x: i32 = 1234; | ||
| 26 | @fence(AtomicOrder.SeqCst); | ||
| 27 | x = 5678; | ||
| 28 | } | ||
| 29 | |||
| 30 | test "atomicrmw and atomicload" { | ||
| 31 | var data: u8 = 200; | ||
| 32 | testAtomicRmw(&data); | ||
| 33 | expect(data == 42); | ||
| 34 | testAtomicLoad(&data); | ||
| 35 | } | ||
| 36 | |||
| 37 | fn testAtomicRmw(ptr: *u8) void { | ||
| 38 | const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); | ||
| 39 | expect(prev_value == 200); | ||
| 40 | comptime { | ||
| 41 | var x: i32 = 1234; | ||
| 42 | const y: i32 = 12345; | ||
| 43 | expect(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); | ||
| 44 | expect(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | fn testAtomicLoad(ptr: *u8) void { | ||
| 49 | const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); | ||
| 50 | expect(x == 42); | ||
| 51 | } | ||
| 52 | |||
| 53 | test "cmpxchg with ptr" { | ||
| 54 | var data1: i32 = 1234; | ||
| 55 | var data2: i32 = 5678; | ||
| 56 | var data3: i32 = 9101; | ||
| 57 | var x: *i32 = &data1; | ||
| 58 | if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 59 | expect(x1 == &data1); | ||
| 60 | } else { | ||
| 61 | @panic("cmpxchg should have failed"); | ||
| 62 | } | ||
| 63 | |||
| 64 | while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 65 | expect(x1 == &data1); | ||
| 66 | } | ||
| 67 | expect(x == &data3); | ||
| 68 | |||
| 69 | expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | ||
| 70 | expect(x == &data2); | ||
| 71 | } | ||
test/stage1/behavior/bit_shifting.zig created+88| ... | @@ -0,0 +1,88 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { | ||
| 5 | expect(Key == @IntType(false, Key.bit_count)); | ||
| 6 | expect(Key.bit_count >= mask_bit_count); | ||
| 7 | const ShardKey = @IntType(false, mask_bit_count); | ||
| 8 | const shift_amount = Key.bit_count - ShardKey.bit_count; | ||
| 9 | return struct { | ||
| 10 | const Self = @This(); | ||
| 11 | shards: [1 << ShardKey.bit_count]?*Node, | ||
| 12 | |||
| 13 | pub fn create() Self { | ||
| 14 | return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) }; | ||
| 15 | } | ||
| 16 | |||
| 17 | fn getShardKey(key: Key) ShardKey { | ||
| 18 | // https://github.com/ziglang/zig/issues/1544 | ||
| 19 | // this special case is needed because you can't u32 >> 32. | ||
| 20 | if (ShardKey == u0) return 0; | ||
| 21 | |||
| 22 | // this can be u1 >> u0 | ||
| 23 | const shard_key = key >> shift_amount; | ||
| 24 | |||
| 25 | // TODO: https://github.com/ziglang/zig/issues/1544 | ||
| 26 | // This cast could be implicit if we teach the compiler that | ||
| 27 | // u32 >> 30 -> u2 | ||
| 28 | return @intCast(ShardKey, shard_key); | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn put(self: *Self, node: *Node) void { | ||
| 32 | const shard_key = Self.getShardKey(node.key); | ||
| 33 | node.next = self.shards[shard_key]; | ||
| 34 | self.shards[shard_key] = node; | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn get(self: *Self, key: Key) ?*Node { | ||
| 38 | const shard_key = Self.getShardKey(key); | ||
| 39 | var maybe_node = self.shards[shard_key]; | ||
| 40 | while (maybe_node) |node| : (maybe_node = node.next) { | ||
| 41 | if (node.key == key) return node; | ||
| 42 | } | ||
| 43 | return null; | ||
| 44 | } | ||
| 45 | |||
| 46 | pub const Node = struct { | ||
| 47 | key: Key, | ||
| 48 | value: V, | ||
| 49 | next: ?*Node, | ||
| 50 | |||
| 51 | pub fn init(self: *Node, key: Key, value: V) void { | ||
| 52 | self.key = key; | ||
| 53 | self.value = value; | ||
| 54 | self.next = null; | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | }; | ||
| 58 | } | ||
| 59 | |||
| 60 | test "sharded table" { | ||
| 61 | // realistic 16-way sharding | ||
| 62 | testShardedTable(u32, 4, 8); | ||
| 63 | |||
| 64 | testShardedTable(u5, 0, 32); // ShardKey == u0 | ||
| 65 | testShardedTable(u5, 2, 32); | ||
| 66 | testShardedTable(u5, 5, 32); | ||
| 67 | |||
| 68 | testShardedTable(u1, 0, 2); | ||
| 69 | testShardedTable(u1, 1, 2); // this does u1 >> u0 | ||
| 70 | |||
| 71 | testShardedTable(u0, 0, 1); | ||
| 72 | } | ||
| 73 | fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void { | ||
| 74 | const Table = ShardedTable(Key, mask_bit_count, void); | ||
| 75 | |||
| 76 | var table = Table.create(); | ||
| 77 | var node_buffer: [node_count]Table.Node = undefined; | ||
| 78 | for (node_buffer) |*node, i| { | ||
| 79 | const key = @intCast(Key, i); | ||
| 80 | expect(table.get(key) == null); | ||
| 81 | node.init(key, {}); | ||
| 82 | table.put(node); | ||
| 83 | } | ||
| 84 | |||
| 85 | for (node_buffer) |*node, i| { | ||
| 86 | expect(table.get(@intCast(Key, i)) == node); | ||
| 87 | } | ||
| 88 | } | ||
test/stage1/behavior/bitcast.zig created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const maxInt = std.math.maxInt; | ||
| 4 | |||
| 5 | test "@bitCast i32 -> u32" { | ||
| 6 | testBitCast_i32_u32(); | ||
| 7 | comptime testBitCast_i32_u32(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testBitCast_i32_u32() void { | ||
| 11 | expect(conv(-1) == maxInt(u32)); | ||
| 12 | expect(conv2(maxInt(u32)) == -1); | ||
| 13 | } | ||
| 14 | |||
| 15 | fn conv(x: i32) u32 { | ||
| 16 | return @bitCast(u32, x); | ||
| 17 | } | ||
| 18 | fn conv2(x: u32) i32 { | ||
| 19 | return @bitCast(i32, x); | ||
| 20 | } | ||
| 21 | |||
| 22 | test "@bitCast extern enum to its integer type" { | ||
| 23 | const SOCK = extern enum { | ||
| 24 | A, | ||
| 25 | B, | ||
| 26 | |||
| 27 | fn testBitCastExternEnum() void { | ||
| 28 | var SOCK_DGRAM = @This().B; | ||
| 29 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | ||
| 30 | expect(sock_dgram == 1); | ||
| 31 | } | ||
| 32 | }; | ||
| 33 | |||
| 34 | SOCK.testBitCastExternEnum(); | ||
| 35 | comptime SOCK.testBitCastExternEnum(); | ||
| 36 | } | ||
test/stage1/behavior/bitreverse.zig created+81| ... | @@ -0,0 +1,81 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const minInt = std.math.minInt; | ||
| 4 | |||
| 5 | test "@bitreverse" { | ||
| 6 | comptime testBitReverse(); | ||
| 7 | testBitReverse(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testBitReverse() void { | ||
| 11 | // using comptime_ints, unsigned | ||
| 12 | expect(@bitreverse(u0, 0) == 0); | ||
| 13 | expect(@bitreverse(u5, 0x12) == 0x9); | ||
| 14 | expect(@bitreverse(u8, 0x12) == 0x48); | ||
| 15 | expect(@bitreverse(u16, 0x1234) == 0x2c48); | ||
| 16 | expect(@bitreverse(u24, 0x123456) == 0x6a2c48); | ||
| 17 | expect(@bitreverse(u32, 0x12345678) == 0x1e6a2c48); | ||
| 18 | expect(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48); | ||
| 19 | expect(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48); | ||
| 20 | expect(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48); | ||
| 21 | expect(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48); | ||
| 22 | expect(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48); | ||
| 23 | |||
| 24 | // using runtime uints, unsigned | ||
| 25 | var num0: u0 = 0; | ||
| 26 | expect(@bitreverse(u0, num0) == 0); | ||
| 27 | var num5: u5 = 0x12; | ||
| 28 | expect(@bitreverse(u5, num5) == 0x9); | ||
| 29 | var num8: u8 = 0x12; | ||
| 30 | expect(@bitreverse(u8, num8) == 0x48); | ||
| 31 | var num16: u16 = 0x1234; | ||
| 32 | expect(@bitreverse(u16, num16) == 0x2c48); | ||
| 33 | var num24: u24 = 0x123456; | ||
| 34 | expect(@bitreverse(u24, num24) == 0x6a2c48); | ||
| 35 | var num32: u32 = 0x12345678; | ||
| 36 | expect(@bitreverse(u32, num32) == 0x1e6a2c48); | ||
| 37 | var num40: u40 = 0x123456789a; | ||
| 38 | expect(@bitreverse(u40, num40) == 0x591e6a2c48); | ||
| 39 | var num48: u48 = 0x123456789abc; | ||
| 40 | expect(@bitreverse(u48, num48) == 0x3d591e6a2c48); | ||
| 41 | var num56: u56 = 0x123456789abcde; | ||
| 42 | expect(@bitreverse(u56, num56) == 0x7b3d591e6a2c48); | ||
| 43 | var num64: u64 = 0x123456789abcdef1; | ||
| 44 | expect(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48); | ||
| 45 | var num128: u128 = 0x123456789abcdef11121314151617181; | ||
| 46 | expect(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48); | ||
| 47 | |||
| 48 | // using comptime_ints, signed, positive | ||
| 49 | expect(@bitreverse(i0, 0) == 0); | ||
| 50 | expect(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49))); | ||
| 51 | expect(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48))); | ||
| 52 | expect(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48))); | ||
| 53 | expect(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48))); | ||
| 54 | expect(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48))); | ||
| 55 | expect(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48))); | ||
| 56 | expect(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48))); | ||
| 57 | expect(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48))); | ||
| 58 | expect(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48))); | ||
| 59 | |||
| 60 | // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm. | ||
| 61 | var neg5: i5 = minInt(i5) + 1; | ||
| 62 | expect(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5)); | ||
| 63 | var neg8: i8 = -18; | ||
| 64 | expect(@bitreverse(i8, -18) == @bitreverse(i8, neg8)); | ||
| 65 | var neg16: i16 = -32694; | ||
| 66 | expect(@bitreverse(i16, -32694) == @bitreverse(i16, neg16)); | ||
| 67 | var neg24: i24 = -6773785; | ||
| 68 | expect(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24)); | ||
| 69 | var neg32: i32 = -16773785; | ||
| 70 | expect(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32)); | ||
| 71 | var neg40: i40 = minInt(i40) + 12345; | ||
| 72 | expect(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40)); | ||
| 73 | var neg48: i48 = minInt(i48) + 12345; | ||
| 74 | expect(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48)); | ||
| 75 | var neg56: i56 = minInt(i56) + 12345; | ||
| 76 | expect(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56)); | ||
| 77 | var neg64: i64 = minInt(i64) + 12345; | ||
| 78 | expect(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64)); | ||
| 79 | var neg128: i128 = minInt(i128) + 12345; | ||
| 80 | expect(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128)); | ||
| 81 | } | ||
test/stage1/behavior/bool.zig created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "bool literals" { | ||
| 4 | expect(true); | ||
| 5 | expect(!false); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "cast bool to int" { | ||
| 9 | const t = true; | ||
| 10 | const f = false; | ||
| 11 | expect(@boolToInt(t) == u32(1)); | ||
| 12 | expect(@boolToInt(f) == u32(0)); | ||
| 13 | nonConstCastBoolToInt(t, f); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn nonConstCastBoolToInt(t: bool, f: bool) void { | ||
| 17 | expect(@boolToInt(t) == u32(1)); | ||
| 18 | expect(@boolToInt(f) == u32(0)); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "bool cmp" { | ||
| 22 | expect(testBoolCmp(true, false) == false); | ||
| 23 | } | ||
| 24 | fn testBoolCmp(a: bool, b: bool) bool { | ||
| 25 | return a == b; | ||
| 26 | } | ||
| 27 | |||
| 28 | const global_f = false; | ||
| 29 | const global_t = true; | ||
| 30 | const not_global_f = !global_f; | ||
| 31 | const not_global_t = !global_t; | ||
| 32 | test "compile time bool not" { | ||
| 33 | expect(not_global_f); | ||
| 34 | expect(!not_global_t); | ||
| 35 | } | ||
test/stage1/behavior/bswap.zig created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | test "@bswap" { | ||
| 5 | comptime testByteSwap(); | ||
| 6 | testByteSwap(); | ||
| 7 | } | ||
| 8 | |||
| 9 | fn testByteSwap() void { | ||
| 10 | expect(@bswap(u0, 0) == 0); | ||
| 11 | expect(@bswap(u8, 0x12) == 0x12); | ||
| 12 | expect(@bswap(u16, 0x1234) == 0x3412); | ||
| 13 | expect(@bswap(u24, 0x123456) == 0x563412); | ||
| 14 | expect(@bswap(u32, 0x12345678) == 0x78563412); | ||
| 15 | expect(@bswap(u40, 0x123456789a) == 0x9a78563412); | ||
| 16 | expect(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); | ||
| 17 | expect(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); | ||
| 18 | expect(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); | ||
| 19 | expect(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); | ||
| 20 | |||
| 21 | expect(@bswap(i0, 0) == 0); | ||
| 22 | expect(@bswap(i8, -50) == -50); | ||
| 23 | expect(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); | ||
| 24 | expect(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); | ||
| 25 | expect(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); | ||
| 26 | expect(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); | ||
| 27 | expect(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); | ||
| 28 | expect(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); | ||
| 29 | expect(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); | ||
| 30 | expect(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == | ||
| 31 | @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); | ||
| 32 | } | ||
test/stage1/behavior/bugs/1076.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | test "comptime code should not modify constant data" { | ||
| 6 | testCastPtrOfArrayToSliceAndPtr(); | ||
| 7 | comptime testCastPtrOfArrayToSliceAndPtr(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testCastPtrOfArrayToSliceAndPtr() void { | ||
| 11 | var array = "aoeu"; | ||
| 12 | const x: [*]u8 = &array; | ||
| 13 | x[0] += 1; | ||
| 14 | expect(mem.eql(u8, array[0..], "boeu")); | ||
| 15 | } | ||
| 16 | |||
test/stage1/behavior/bugs/1111.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const Foo = extern enum { | ||
| 2 | Bar = -1, | ||
| 3 | }; | ||
| 4 | |||
| 5 | test "issue 1111 fixed" { | ||
| 6 | const v = Foo.Bar; | ||
| 7 | |||
| 8 | switch (v) { | ||
| 9 | Foo.Bar => return, | ||
| 10 | else => return, | ||
| 11 | } | ||
| 12 | } | ||
test/stage1/behavior/bugs/1277.zig created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const S = struct { | ||
| 4 | f: ?fn () i32, | ||
| 5 | }; | ||
| 6 | |||
| 7 | const s = S{ .f = f }; | ||
| 8 | |||
| 9 | fn f() i32 { | ||
| 10 | return 1234; | ||
| 11 | } | ||
| 12 | |||
| 13 | test "don't emit an LLVM global for a const function when it's in an optional in a struct" { | ||
| 14 | std.testing.expect(s.f.?() == 1234); | ||
| 15 | } | ||
test/stage1/behavior/bugs/1322.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const B = union(enum) { | ||
| 4 | c: C, | ||
| 5 | None, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const A = struct { | ||
| 9 | b: B, | ||
| 10 | }; | ||
| 11 | |||
| 12 | const C = struct {}; | ||
| 13 | |||
| 14 | test "tagged union with all void fields but a meaningful tag" { | ||
| 15 | var a: A = A{ .b = B{ .c = C{} } }; | ||
| 16 | std.testing.expect(@TagType(B)(a.b) == @TagType(B).c); | ||
| 17 | a = A{ .b = B.None }; | ||
| 18 | std.testing.expect(@TagType(B)(a.b) == @TagType(B).None); | ||
| 19 | } | ||
test/stage1/behavior/bugs/1381.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const B = union(enum) { | ||
| 4 | D: u8, | ||
| 5 | E: u16, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const A = union(enum) { | ||
| 9 | B: B, | ||
| 10 | C: u8, | ||
| 11 | }; | ||
| 12 | |||
| 13 | test "union that needs padding bytes inside an array" { | ||
| 14 | var as = []A{ | ||
| 15 | A{ .B = B{ .D = 1 } }, | ||
| 16 | A{ .B = B{ .D = 1 } }, | ||
| 17 | }; | ||
| 18 | |||
| 19 | const a = as[0].B; | ||
| 20 | std.testing.expect(a.D == 1); | ||
| 21 | } | ||
test/stage1/behavior/bugs/1421.zig created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | const S = struct { | ||
| 6 | fn method() builtin.TypeInfo { | ||
| 7 | return @typeInfo(S); | ||
| 8 | } | ||
| 9 | }; | ||
| 10 | |||
| 11 | test "functions with return type required to be comptime are generic" { | ||
| 12 | const ti = S.method(); | ||
| 13 | expect(builtin.TypeId(ti) == builtin.TypeId.Struct); | ||
| 14 | } | ||
test/stage1/behavior/bugs/1442.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const Union = union(enum) { | ||
| 4 | Text: []const u8, | ||
| 5 | Color: u32, | ||
| 6 | }; | ||
| 7 | |||
| 8 | test "const error union field alignment" { | ||
| 9 | var union_or_err: anyerror!Union = Union{ .Color = 1234 }; | ||
| 10 | std.testing.expect((union_or_err catch unreachable).Color == 1234); | ||
| 11 | } | ||
test/stage1/behavior/bugs/1486.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const ptr = &global; | ||
| 4 | var global: u64 = 123; | ||
| 5 | |||
| 6 | test "constant pointer to global variable causes runtime load" { | ||
| 7 | global = 1234; | ||
| 8 | expect(&global == ptr); | ||
| 9 | expect(ptr.* == 1234); | ||
| 10 | } | ||
| 11 | |||
test/stage1/behavior/bugs/1851.zig created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | test "allocation and looping over 3-byte integer" { | ||
| 5 | expect(@sizeOf(u24) == 4); | ||
| 6 | expect(@sizeOf([1]u24) == 4); | ||
| 7 | expect(@alignOf(u24) == 4); | ||
| 8 | expect(@alignOf([1]u24) == 4); | ||
| 9 | var buffer: [100]u8 = undefined; | ||
| 10 | const a = &std.heap.FixedBufferAllocator.init(&buffer).allocator; | ||
| 11 | |||
| 12 | var x = a.alloc(u24, 2) catch unreachable; | ||
| 13 | expect(x.len == 2); | ||
| 14 | x[0] = 0xFFFFFF; | ||
| 15 | x[1] = 0xFFFFFF; | ||
| 16 | |||
| 17 | const bytes = @sliceToBytes(x); | ||
| 18 | expect(@typeOf(bytes) == []align(4) u8); | ||
| 19 | expect(bytes.len == 8); | ||
| 20 | |||
| 21 | for (bytes) |*b| { | ||
| 22 | b.* = 0x00; | ||
| 23 | } | ||
| 24 | |||
| 25 | expect(x[0] == 0x00); | ||
| 26 | expect(x[1] == 0x00); | ||
| 27 | } | ||
test/stage1/behavior/bugs/394.zig created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const E = union(enum) { | ||
| 2 | A: [9]u8, | ||
| 3 | B: u64, | ||
| 4 | }; | ||
| 5 | const S = struct { | ||
| 6 | x: u8, | ||
| 7 | y: E, | ||
| 8 | }; | ||
| 9 | |||
| 10 | const expect = @import("std").testing.expect; | ||
| 11 | |||
| 12 | test "bug 394 fixed" { | ||
| 13 | const x = S{ | ||
| 14 | .x = 3, | ||
| 15 | .y = E{ .B = 1 }, | ||
| 16 | }; | ||
| 17 | expect(x.x == 3); | ||
| 18 | } | ||
test/stage1/behavior/bugs/655.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const other_file = @import("655_other_file.zig"); | ||
| 3 | |||
| 4 | test "function with *const parameter with type dereferenced by namespace" { | ||
| 5 | const x: other_file.Integer = 1234; | ||
| 6 | comptime std.testing.expect(@typeOf(&x) == *const other_file.Integer); | ||
| 7 | foo(&x); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn foo(x: *const other_file.Integer) void { | ||
| 11 | std.testing.expect(x.* == 1234); | ||
| 12 | } | ||
test/stage1/behavior/bugs/655_other_file.zig created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | pub const Integer = u32; | ||
test/stage1/behavior/bugs/656.zig created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const PrefixOp = union(enum) { | ||
| 4 | Return, | ||
| 5 | AddrOf: Value, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const Value = struct { | ||
| 9 | align_expr: ?u32, | ||
| 10 | }; | ||
| 11 | |||
| 12 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { | ||
| 13 | foo(false, true); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn foo(a: bool, b: bool) void { | ||
| 17 | var prefix_op = PrefixOp{ | ||
| 18 | .AddrOf = Value{ .align_expr = 1234 }, | ||
| 19 | }; | ||
| 20 | if (a) {} else { | ||
| 21 | switch (prefix_op) { | ||
| 22 | PrefixOp.AddrOf => |addr_of_info| { | ||
| 23 | if (b) {} | ||
| 24 | if (addr_of_info.align_expr) |align_expr| { | ||
| 25 | expect(align_expr == 1234); | ||
| 26 | } | ||
| 27 | }, | ||
| 28 | PrefixOp.Return => {}, | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
test/stage1/behavior/bugs/726.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "@ptrCast from const to nullable" { | ||
| 4 | const c: u8 = 4; | ||
| 5 | var x: ?*const u8 = @ptrCast(?*const u8, &c); | ||
| 6 | expect(x.?.* == 4); | ||
| 7 | } | ||
| 8 | |||
| 9 | test "@ptrCast from var in empty struct to nullable" { | ||
| 10 | const container = struct { | ||
| 11 | var c: u8 = 4; | ||
| 12 | }; | ||
| 13 | var x: ?*const u8 = @ptrCast(?*const u8, &container.c); | ||
| 14 | expect(x.?.* == 4); | ||
| 15 | } | ||
| 16 | |||
test/stage1/behavior/bugs/828.zig created+33| ... | @@ -0,0 +1,33 @@ | ||
| 1 | const CountBy = struct { | ||
| 2 | a: usize, | ||
| 3 | |||
| 4 | const One = CountBy{ .a = 1 }; | ||
| 5 | |||
| 6 | pub fn counter(self: *const CountBy) Counter { | ||
| 7 | return Counter{ .i = 0 }; | ||
| 8 | } | ||
| 9 | }; | ||
| 10 | |||
| 11 | const Counter = struct { | ||
| 12 | i: usize, | ||
| 13 | |||
| 14 | pub fn count(self: *Counter) bool { | ||
| 15 | self.i += 1; | ||
| 16 | return self.i <= 10; | ||
| 17 | } | ||
| 18 | }; | ||
| 19 | |||
| 20 | fn constCount(comptime cb: *const CountBy, comptime unused: u32) void { | ||
| 21 | comptime { | ||
| 22 | var cnt = cb.counter(); | ||
| 23 | if (cnt.i != 0) @compileError("Counter instance reused!"); | ||
| 24 | while (cnt.count()) {} | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | test "comptime struct return should not return the same instance" { | ||
| 29 | //the first parameter must be passed by reference to trigger the bug | ||
| 30 | //a second parameter is required to trigger the bug | ||
| 31 | const ValA = constCount(&CountBy.One, 12); | ||
| 32 | const ValB = constCount(&CountBy.One, 15); | ||
| 33 | } | ||
test/stage1/behavior/bugs/920.zig created+65| ... | @@ -0,0 +1,65 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const math = std.math; | ||
| 3 | const Random = std.rand.Random; | ||
| 4 | |||
| 5 | const ZigTable = struct { | ||
| 6 | r: f64, | ||
| 7 | x: [257]f64, | ||
| 8 | f: [257]f64, | ||
| 9 | |||
| 10 | pdf: fn (f64) f64, | ||
| 11 | is_symmetric: bool, | ||
| 12 | zero_case: fn (*Random, f64) f64, | ||
| 13 | }; | ||
| 14 | |||
| 15 | fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable { | ||
| 16 | var tables: ZigTable = undefined; | ||
| 17 | |||
| 18 | tables.is_symmetric = is_symmetric; | ||
| 19 | tables.r = r; | ||
| 20 | tables.pdf = f; | ||
| 21 | tables.zero_case = zero_case; | ||
| 22 | |||
| 23 | tables.x[0] = v / f(r); | ||
| 24 | tables.x[1] = r; | ||
| 25 | |||
| 26 | for (tables.x[2..256]) |*entry, i| { | ||
| 27 | const last = tables.x[2 + i - 1]; | ||
| 28 | entry.* = f_inv(v / last + f(last)); | ||
| 29 | } | ||
| 30 | tables.x[256] = 0; | ||
| 31 | |||
| 32 | for (tables.f[0..]) |*entry, i| { | ||
| 33 | entry.* = f(tables.x[i]); | ||
| 34 | } | ||
| 35 | |||
| 36 | return tables; | ||
| 37 | } | ||
| 38 | |||
| 39 | const norm_r = 3.6541528853610088; | ||
| 40 | const norm_v = 0.00492867323399; | ||
| 41 | |||
| 42 | fn norm_f(x: f64) f64 { | ||
| 43 | return math.exp(-x * x / 2.0); | ||
| 44 | } | ||
| 45 | fn norm_f_inv(y: f64) f64 { | ||
| 46 | return math.sqrt(-2.0 * math.ln(y)); | ||
| 47 | } | ||
| 48 | fn norm_zero_case(random: *Random, u: f64) f64 { | ||
| 49 | return 0.0; | ||
| 50 | } | ||
| 51 | |||
| 52 | const NormalDist = blk: { | ||
| 53 | @setEvalBranchQuota(30000); | ||
| 54 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | ||
| 55 | }; | ||
| 56 | |||
| 57 | test "bug 920 fixed" { | ||
| 58 | const NormalDist1 = blk: { | ||
| 59 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | ||
| 60 | }; | ||
| 61 | |||
| 62 | for (NormalDist1.f) |_, i| { | ||
| 63 | std.testing.expect(NormalDist1.f[i] == NormalDist.f[i]); | ||
| 64 | } | ||
| 65 | } | ||
test/stage1/behavior/byval_arg_var.zig created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | var result: []const u8 = "wrong"; | ||
| 4 | |||
| 5 | test "pass string literal byvalue to a generic var param" { | ||
| 6 | start(); | ||
| 7 | blowUpStack(10); | ||
| 8 | |||
| 9 | std.testing.expect(std.mem.eql(u8, result, "string literal")); | ||
| 10 | } | ||
| 11 | |||
| 12 | fn start() void { | ||
| 13 | foo("string literal"); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn foo(x: var) void { | ||
| 17 | bar(x); | ||
| 18 | } | ||
| 19 | |||
| 20 | fn bar(x: var) void { | ||
| 21 | result = x; | ||
| 22 | } | ||
| 23 | |||
| 24 | fn blowUpStack(x: u32) void { | ||
| 25 | if (x == 0) return; | ||
| 26 | blowUpStack(x - 1); | ||
| 27 | } | ||
test/stage1/behavior/cancel.zig created+92| ... | @@ -0,0 +1,92 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | var defer_f1: bool = false; | ||
| 4 | var defer_f2: bool = false; | ||
| 5 | var defer_f3: bool = false; | ||
| 6 | |||
| 7 | test "cancel forwards" { | ||
| 8 | var da = std.heap.DirectAllocator.init(); | ||
| 9 | defer da.deinit(); | ||
| 10 | |||
| 11 | const p = async<&da.allocator> f1() catch unreachable; | ||
| 12 | cancel p; | ||
| 13 | std.testing.expect(defer_f1); | ||
| 14 | std.testing.expect(defer_f2); | ||
| 15 | std.testing.expect(defer_f3); | ||
| 16 | } | ||
| 17 | |||
| 18 | async fn f1() void { | ||
| 19 | defer { | ||
| 20 | defer_f1 = true; | ||
| 21 | } | ||
| 22 | await (async f2() catch unreachable); | ||
| 23 | } | ||
| 24 | |||
| 25 | async fn f2() void { | ||
| 26 | defer { | ||
| 27 | defer_f2 = true; | ||
| 28 | } | ||
| 29 | await (async f3() catch unreachable); | ||
| 30 | } | ||
| 31 | |||
| 32 | async fn f3() void { | ||
| 33 | defer { | ||
| 34 | defer_f3 = true; | ||
| 35 | } | ||
| 36 | suspend; | ||
| 37 | } | ||
| 38 | |||
| 39 | var defer_b1: bool = false; | ||
| 40 | var defer_b2: bool = false; | ||
| 41 | var defer_b3: bool = false; | ||
| 42 | var defer_b4: bool = false; | ||
| 43 | |||
| 44 | test "cancel backwards" { | ||
| 45 | var da = std.heap.DirectAllocator.init(); | ||
| 46 | defer da.deinit(); | ||
| 47 | |||
| 48 | const p = async<&da.allocator> b1() catch unreachable; | ||
| 49 | cancel p; | ||
| 50 | std.testing.expect(defer_b1); | ||
| 51 | std.testing.expect(defer_b2); | ||
| 52 | std.testing.expect(defer_b3); | ||
| 53 | std.testing.expect(defer_b4); | ||
| 54 | } | ||
| 55 | |||
| 56 | async fn b1() void { | ||
| 57 | defer { | ||
| 58 | defer_b1 = true; | ||
| 59 | } | ||
| 60 | await (async b2() catch unreachable); | ||
| 61 | } | ||
| 62 | |||
| 63 | var b4_handle: promise = undefined; | ||
| 64 | |||
| 65 | async fn b2() void { | ||
| 66 | const b3_handle = async b3() catch unreachable; | ||
| 67 | resume b4_handle; | ||
| 68 | cancel b4_handle; | ||
| 69 | defer { | ||
| 70 | defer_b2 = true; | ||
| 71 | } | ||
| 72 | const value = await b3_handle; | ||
| 73 | @panic("unreachable"); | ||
| 74 | } | ||
| 75 | |||
| 76 | async fn b3() i32 { | ||
| 77 | defer { | ||
| 78 | defer_b3 = true; | ||
| 79 | } | ||
| 80 | await (async b4() catch unreachable); | ||
| 81 | return 1234; | ||
| 82 | } | ||
| 83 | |||
| 84 | async fn b4() void { | ||
| 85 | defer { | ||
| 86 | defer_b4 = true; | ||
| 87 | } | ||
| 88 | suspend { | ||
| 89 | b4_handle = @handle(); | ||
| 90 | } | ||
| 91 | suspend; | ||
| 92 | } | ||
test/stage1/behavior/cast.zig created+484| ... | @@ -0,0 +1,484 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const mem = std.mem; | ||
| 4 | const maxInt = std.math.maxInt; | ||
| 5 | |||
| 6 | test "int to ptr cast" { | ||
| 7 | const x = usize(13); | ||
| 8 | const y = @intToPtr(*u8, x); | ||
| 9 | const z = @ptrToInt(y); | ||
| 10 | expect(z == 13); | ||
| 11 | } | ||
| 12 | |||
| 13 | test "integer literal to pointer cast" { | ||
| 14 | const vga_mem = @intToPtr(*u16, 0xB8000); | ||
| 15 | expect(@ptrToInt(vga_mem) == 0xB8000); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "pointer reinterpret const float to int" { | ||
| 19 | const float: f64 = 5.99999999999994648725e-01; | ||
| 20 | const float_ptr = &float; | ||
| 21 | const int_ptr = @ptrCast(*const i32, float_ptr); | ||
| 22 | const int_val = int_ptr.*; | ||
| 23 | expect(int_val == 858993411); | ||
| 24 | } | ||
| 25 | |||
| 26 | test "implicitly cast indirect pointer to maybe-indirect pointer" { | ||
| 27 | const S = struct { | ||
| 28 | const Self = @This(); | ||
| 29 | x: u8, | ||
| 30 | fn constConst(p: *const *const Self) u8 { | ||
| 31 | return p.*.x; | ||
| 32 | } | ||
| 33 | fn maybeConstConst(p: ?*const *const Self) u8 { | ||
| 34 | return p.?.*.x; | ||
| 35 | } | ||
| 36 | fn constConstConst(p: *const *const *const Self) u8 { | ||
| 37 | return p.*.*.x; | ||
| 38 | } | ||
| 39 | fn maybeConstConstConst(p: ?*const *const *const Self) u8 { | ||
| 40 | return p.?.*.*.x; | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | const s = S{ .x = 42 }; | ||
| 44 | const p = &s; | ||
| 45 | const q = &p; | ||
| 46 | const r = &q; | ||
| 47 | expect(42 == S.constConst(q)); | ||
| 48 | expect(42 == S.maybeConstConst(q)); | ||
| 49 | expect(42 == S.constConstConst(r)); | ||
| 50 | expect(42 == S.maybeConstConstConst(r)); | ||
| 51 | } | ||
| 52 | |||
| 53 | test "explicit cast from integer to error type" { | ||
| 54 | testCastIntToErr(error.ItBroke); | ||
| 55 | comptime testCastIntToErr(error.ItBroke); | ||
| 56 | } | ||
| 57 | fn testCastIntToErr(err: anyerror) void { | ||
| 58 | const x = @errorToInt(err); | ||
| 59 | const y = @intToError(x); | ||
| 60 | expect(error.ItBroke == y); | ||
| 61 | } | ||
| 62 | |||
| 63 | test "peer resolve arrays of different size to const slice" { | ||
| 64 | expect(mem.eql(u8, boolToStr(true), "true")); | ||
| 65 | expect(mem.eql(u8, boolToStr(false), "false")); | ||
| 66 | comptime expect(mem.eql(u8, boolToStr(true), "true")); | ||
| 67 | comptime expect(mem.eql(u8, boolToStr(false), "false")); | ||
| 68 | } | ||
| 69 | fn boolToStr(b: bool) []const u8 { | ||
| 70 | return if (b) "true" else "false"; | ||
| 71 | } | ||
| 72 | |||
| 73 | test "peer resolve array and const slice" { | ||
| 74 | testPeerResolveArrayConstSlice(true); | ||
| 75 | comptime testPeerResolveArrayConstSlice(true); | ||
| 76 | } | ||
| 77 | fn testPeerResolveArrayConstSlice(b: bool) void { | ||
| 78 | const value1 = if (b) "aoeu" else ([]const u8)("zz"); | ||
| 79 | const value2 = if (b) ([]const u8)("zz") else "aoeu"; | ||
| 80 | expect(mem.eql(u8, value1, "aoeu")); | ||
| 81 | expect(mem.eql(u8, value2, "zz")); | ||
| 82 | } | ||
| 83 | |||
| 84 | test "implicitly cast from T to anyerror!?T" { | ||
| 85 | castToOptionalTypeError(1); | ||
| 86 | comptime castToOptionalTypeError(1); | ||
| 87 | } | ||
| 88 | |||
| 89 | const A = struct { | ||
| 90 | a: i32, | ||
| 91 | }; | ||
| 92 | fn castToOptionalTypeError(z: i32) void { | ||
| 93 | const x = i32(1); | ||
| 94 | const y: anyerror!?i32 = x; | ||
| 95 | expect((try y).? == 1); | ||
| 96 | |||
| 97 | const f = z; | ||
| 98 | const g: anyerror!?i32 = f; | ||
| 99 | |||
| 100 | const a = A{ .a = z }; | ||
| 101 | const b: anyerror!?A = a; | ||
| 102 | expect((b catch unreachable).?.a == 1); | ||
| 103 | } | ||
| 104 | |||
| 105 | test "implicitly cast from int to anyerror!?T" { | ||
| 106 | implicitIntLitToOptional(); | ||
| 107 | comptime implicitIntLitToOptional(); | ||
| 108 | } | ||
| 109 | fn implicitIntLitToOptional() void { | ||
| 110 | const f: ?i32 = 1; | ||
| 111 | const g: anyerror!?i32 = 1; | ||
| 112 | } | ||
| 113 | |||
| 114 | test "return null from fn() anyerror!?&T" { | ||
| 115 | const a = returnNullFromOptionalTypeErrorRef(); | ||
| 116 | const b = returnNullLitFromOptionalTypeErrorRef(); | ||
| 117 | expect((try a) == null and (try b) == null); | ||
| 118 | } | ||
| 119 | fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { | ||
| 120 | const a: ?*A = null; | ||
| 121 | return a; | ||
| 122 | } | ||
| 123 | fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | ||
| 124 | return null; | ||
| 125 | } | ||
| 126 | |||
| 127 | test "peer type resolution: ?T and T" { | ||
| 128 | expect(peerTypeTAndOptionalT(true, false).? == 0); | ||
| 129 | expect(peerTypeTAndOptionalT(false, false).? == 3); | ||
| 130 | comptime { | ||
| 131 | expect(peerTypeTAndOptionalT(true, false).? == 0); | ||
| 132 | expect(peerTypeTAndOptionalT(false, false).? == 3); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { | ||
| 136 | if (c) { | ||
| 137 | return if (b) null else usize(0); | ||
| 138 | } | ||
| 139 | |||
| 140 | return usize(3); | ||
| 141 | } | ||
| 142 | |||
| 143 | test "peer type resolution: [0]u8 and []const u8" { | ||
| 144 | expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | ||
| 145 | expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | ||
| 146 | comptime { | ||
| 147 | expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | ||
| 148 | expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | ||
| 152 | if (a) { | ||
| 153 | return []const u8{}; | ||
| 154 | } | ||
| 155 | |||
| 156 | return slice[0..1]; | ||
| 157 | } | ||
| 158 | |||
| 159 | test "implicitly cast from [N]T to ?[]const T" { | ||
| 160 | expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | ||
| 161 | comptime expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | ||
| 162 | } | ||
| 163 | |||
| 164 | fn castToOptionalSlice() ?[]const u8 { | ||
| 165 | return "hi"; | ||
| 166 | } | ||
| 167 | |||
| 168 | test "implicitly cast from [0]T to anyerror![]T" { | ||
| 169 | testCastZeroArrayToErrSliceMut(); | ||
| 170 | comptime testCastZeroArrayToErrSliceMut(); | ||
| 171 | } | ||
| 172 | |||
| 173 | fn testCastZeroArrayToErrSliceMut() void { | ||
| 174 | expect((gimmeErrOrSlice() catch unreachable).len == 0); | ||
| 175 | } | ||
| 176 | |||
| 177 | fn gimmeErrOrSlice() anyerror![]u8 { | ||
| 178 | return []u8{}; | ||
| 179 | } | ||
| 180 | |||
| 181 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | ||
| 182 | { | ||
| 183 | var data = "hi"; | ||
| 184 | const slice = data[0..]; | ||
| 185 | expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | ||
| 186 | expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | ||
| 187 | } | ||
| 188 | comptime { | ||
| 189 | var data = "hi"; | ||
| 190 | const slice = data[0..]; | ||
| 191 | expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | ||
| 192 | expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { | ||
| 196 | if (a) { | ||
| 197 | return []u8{}; | ||
| 198 | } | ||
| 199 | |||
| 200 | return slice[0..1]; | ||
| 201 | } | ||
| 202 | |||
| 203 | test "resolve undefined with integer" { | ||
| 204 | testResolveUndefWithInt(true, 1234); | ||
| 205 | comptime testResolveUndefWithInt(true, 1234); | ||
| 206 | } | ||
| 207 | fn testResolveUndefWithInt(b: bool, x: i32) void { | ||
| 208 | const value = if (b) x else undefined; | ||
| 209 | if (b) { | ||
| 210 | expect(value == x); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | test "implicit cast from &const [N]T to []const T" { | ||
| 215 | testCastConstArrayRefToConstSlice(); | ||
| 216 | comptime testCastConstArrayRefToConstSlice(); | ||
| 217 | } | ||
| 218 | |||
| 219 | fn testCastConstArrayRefToConstSlice() void { | ||
| 220 | const blah = "aoeu"; | ||
| 221 | const const_array_ref = &blah; | ||
| 222 | expect(@typeOf(const_array_ref) == *const [4]u8); | ||
| 223 | const slice: []const u8 = const_array_ref; | ||
| 224 | expect(mem.eql(u8, slice, "aoeu")); | ||
| 225 | } | ||
| 226 | |||
| 227 | test "peer type resolution: error and [N]T" { | ||
| 228 | // TODO: implicit error!T to error!U where T can implicitly cast to U | ||
| 229 | //expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | ||
| 230 | //comptime expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | ||
| 231 | expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | ||
| 232 | comptime expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | ||
| 233 | } | ||
| 234 | |||
| 235 | //fn testPeerErrorAndArray(x: u8) error![]const u8 { | ||
| 236 | // return switch (x) { | ||
| 237 | // 0x00 => "OK", | ||
| 238 | // else => error.BadValue, | ||
| 239 | // }; | ||
| 240 | //} | ||
| 241 | fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 { | ||
| 242 | return switch (x) { | ||
| 243 | 0x00 => "OK", | ||
| 244 | 0x01 => "OKK", | ||
| 245 | else => error.BadValue, | ||
| 246 | }; | ||
| 247 | } | ||
| 248 | |||
| 249 | test "@floatToInt" { | ||
| 250 | testFloatToInts(); | ||
| 251 | comptime testFloatToInts(); | ||
| 252 | } | ||
| 253 | |||
| 254 | fn testFloatToInts() void { | ||
| 255 | const x = i32(1e4); | ||
| 256 | expect(x == 10000); | ||
| 257 | const y = @floatToInt(i32, f32(1e4)); | ||
| 258 | expect(y == 10000); | ||
| 259 | expectFloatToInt(f16, 255.1, u8, 255); | ||
| 260 | expectFloatToInt(f16, 127.2, i8, 127); | ||
| 261 | expectFloatToInt(f16, -128.2, i8, -128); | ||
| 262 | expectFloatToInt(f32, 255.1, u8, 255); | ||
| 263 | expectFloatToInt(f32, 127.2, i8, 127); | ||
| 264 | expectFloatToInt(f32, -128.2, i8, -128); | ||
| 265 | expectFloatToInt(comptime_int, 1234, i16, 1234); | ||
| 266 | } | ||
| 267 | |||
| 268 | fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { | ||
| 269 | expect(@floatToInt(I, f) == i); | ||
| 270 | } | ||
| 271 | |||
| 272 | test "cast u128 to f128 and back" { | ||
| 273 | comptime testCast128(); | ||
| 274 | testCast128(); | ||
| 275 | } | ||
| 276 | |||
| 277 | fn testCast128() void { | ||
| 278 | expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | ||
| 279 | } | ||
| 280 | |||
| 281 | fn cast128Int(x: f128) u128 { | ||
| 282 | return @bitCast(u128, x); | ||
| 283 | } | ||
| 284 | |||
| 285 | fn cast128Float(x: u128) f128 { | ||
| 286 | return @bitCast(f128, x); | ||
| 287 | } | ||
| 288 | |||
| 289 | test "const slice widen cast" { | ||
| 290 | const bytes align(4) = []u8{ | ||
| 291 | 0x12, | ||
| 292 | 0x12, | ||
| 293 | 0x12, | ||
| 294 | 0x12, | ||
| 295 | }; | ||
| 296 | |||
| 297 | const u32_value = @bytesToSlice(u32, bytes[0..])[0]; | ||
| 298 | expect(u32_value == 0x12121212); | ||
| 299 | |||
| 300 | expect(@bitCast(u32, bytes) == 0x12121212); | ||
| 301 | } | ||
| 302 | |||
| 303 | test "single-item pointer of array to slice and to unknown length pointer" { | ||
| 304 | testCastPtrOfArrayToSliceAndPtr(); | ||
| 305 | comptime testCastPtrOfArrayToSliceAndPtr(); | ||
| 306 | } | ||
| 307 | |||
| 308 | fn testCastPtrOfArrayToSliceAndPtr() void { | ||
| 309 | var array = "aoeu"; | ||
| 310 | const x: [*]u8 = &array; | ||
| 311 | x[0] += 1; | ||
| 312 | expect(mem.eql(u8, array[0..], "boeu")); | ||
| 313 | const y: []u8 = &array; | ||
| 314 | y[0] += 1; | ||
| 315 | expect(mem.eql(u8, array[0..], "coeu")); | ||
| 316 | } | ||
| 317 | |||
| 318 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | ||
| 319 | const window_name = [1][*]const u8{c"window name"}; | ||
| 320 | const x: [*]const ?[*]const u8 = &window_name; | ||
| 321 | expect(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); | ||
| 322 | } | ||
| 323 | |||
| 324 | test "@intCast comptime_int" { | ||
| 325 | const result = @intCast(i32, 1234); | ||
| 326 | expect(@typeOf(result) == i32); | ||
| 327 | expect(result == 1234); | ||
| 328 | } | ||
| 329 | |||
| 330 | test "@floatCast comptime_int and comptime_float" { | ||
| 331 | { | ||
| 332 | const result = @floatCast(f16, 1234); | ||
| 333 | expect(@typeOf(result) == f16); | ||
| 334 | expect(result == 1234.0); | ||
| 335 | } | ||
| 336 | { | ||
| 337 | const result = @floatCast(f16, 1234.0); | ||
| 338 | expect(@typeOf(result) == f16); | ||
| 339 | expect(result == 1234.0); | ||
| 340 | } | ||
| 341 | { | ||
| 342 | const result = @floatCast(f32, 1234); | ||
| 343 | expect(@typeOf(result) == f32); | ||
| 344 | expect(result == 1234.0); | ||
| 345 | } | ||
| 346 | { | ||
| 347 | const result = @floatCast(f32, 1234.0); | ||
| 348 | expect(@typeOf(result) == f32); | ||
| 349 | expect(result == 1234.0); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | test "comptime_int @intToFloat" { | ||
| 354 | { | ||
| 355 | const result = @intToFloat(f16, 1234); | ||
| 356 | expect(@typeOf(result) == f16); | ||
| 357 | expect(result == 1234.0); | ||
| 358 | } | ||
| 359 | { | ||
| 360 | const result = @intToFloat(f32, 1234); | ||
| 361 | expect(@typeOf(result) == f32); | ||
| 362 | expect(result == 1234.0); | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | test "@bytesToSlice keeps pointer alignment" { | ||
| 367 | var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 }; | ||
| 368 | const numbers = @bytesToSlice(u32, bytes[0..]); | ||
| 369 | comptime expect(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); | ||
| 370 | } | ||
| 371 | |||
| 372 | test "@intCast i32 to u7" { | ||
| 373 | var x: u128 = maxInt(u128); | ||
| 374 | var y: i32 = 120; | ||
| 375 | var z = x >> @intCast(u7, y); | ||
| 376 | expect(z == 0xff); | ||
| 377 | } | ||
| 378 | |||
| 379 | test "implicit cast undefined to optional" { | ||
| 380 | expect(MakeType(void).getNull() == null); | ||
| 381 | expect(MakeType(void).getNonNull() != null); | ||
| 382 | } | ||
| 383 | |||
| 384 | fn MakeType(comptime T: type) type { | ||
| 385 | return struct { | ||
| 386 | fn getNull() ?T { | ||
| 387 | return null; | ||
| 388 | } | ||
| 389 | |||
| 390 | fn getNonNull() ?T { | ||
| 391 | return T(undefined); | ||
| 392 | } | ||
| 393 | }; | ||
| 394 | } | ||
| 395 | |||
| 396 | test "implicit cast from *[N]T to ?[*]T" { | ||
| 397 | var x: ?[*]u16 = null; | ||
| 398 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | ||
| 399 | |||
| 400 | x = &y; | ||
| 401 | expect(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 402 | x.?[0] = 8; | ||
| 403 | y[3] = 6; | ||
| 404 | expect(std.mem.eql(u16, x.?[0..4], y[0..4])); | ||
| 405 | } | ||
| 406 | |||
| 407 | test "implicit cast from *T to ?*c_void" { | ||
| 408 | var a: u8 = 1; | ||
| 409 | incrementVoidPtrValue(&a); | ||
| 410 | std.testing.expect(a == 2); | ||
| 411 | } | ||
| 412 | |||
| 413 | fn incrementVoidPtrValue(value: ?*c_void) void { | ||
| 414 | @ptrCast(*u8, value.?).* += 1; | ||
| 415 | } | ||
| 416 | |||
| 417 | test "implicit cast from [*]T to ?*c_void" { | ||
| 418 | var a = []u8{ 3, 2, 1 }; | ||
| 419 | incrementVoidPtrArray(a[0..].ptr, 3); | ||
| 420 | expect(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); | ||
| 421 | } | ||
| 422 | |||
| 423 | fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { | ||
| 424 | var n: usize = 0; | ||
| 425 | while (n < len) : (n += 1) { | ||
| 426 | @ptrCast([*]u8, array.?)[n] += 1; | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | test "*usize to *void" { | ||
| 431 | var i = usize(0); | ||
| 432 | var v = @ptrCast(*void, &i); | ||
| 433 | v.* = {}; | ||
| 434 | } | ||
| 435 | |||
| 436 | test "compile time int to ptr of function" { | ||
| 437 | foobar(FUNCTION_CONSTANT); | ||
| 438 | } | ||
| 439 | |||
| 440 | pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); | ||
| 441 | pub const PFN_void = extern fn (*c_void) void; | ||
| 442 | |||
| 443 | fn foobar(func: PFN_void) void { | ||
| 444 | std.testing.expect(@ptrToInt(func) == maxInt(usize)); | ||
| 445 | } | ||
| 446 | |||
| 447 | test "implicit ptr to *c_void" { | ||
| 448 | var a: u32 = 1; | ||
| 449 | var ptr: *c_void = &a; | ||
| 450 | var b: *u32 = @ptrCast(*u32, ptr); | ||
| 451 | expect(b.* == 1); | ||
| 452 | var ptr2: ?*c_void = &a; | ||
| 453 | var c: *u32 = @ptrCast(*u32, ptr2.?); | ||
| 454 | expect(c.* == 1); | ||
| 455 | } | ||
| 456 | |||
| 457 | test "@intCast to comptime_int" { | ||
| 458 | expect(@intCast(comptime_int, 0) == 0); | ||
| 459 | } | ||
| 460 | |||
| 461 | test "implicit cast comptime numbers to any type when the value fits" { | ||
| 462 | const a: u64 = 255; | ||
| 463 | var b: u8 = a; | ||
| 464 | expect(b == 255); | ||
| 465 | } | ||
| 466 | |||
| 467 | test "@intToEnum passed a comptime_int to an enum with one item" { | ||
| 468 | const E = enum { | ||
| 469 | A, | ||
| 470 | }; | ||
| 471 | const x = @intToEnum(E, 0); | ||
| 472 | expect(x == E.A); | ||
| 473 | } | ||
| 474 | |||
| 475 | test "@intCast to u0 and use the result" { | ||
| 476 | const S = struct { | ||
| 477 | fn doTheTest(zero: u1, one: u1, bigzero: i32) void { | ||
| 478 | expect((one << @intCast(u0, bigzero)) == 1); | ||
| 479 | expect((zero << @intCast(u0, bigzero)) == 0); | ||
| 480 | } | ||
| 481 | }; | ||
| 482 | S.doTheTest(0, 1, 0); | ||
| 483 | comptime S.doTheTest(0, 1, 0); | ||
| 484 | } | ||
test/stage1/behavior/const_slice_child.zig created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const debug = std.debug; | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | var argv: [*]const [*]const u8 = undefined; | ||
| 6 | |||
| 7 | test "const slice child" { | ||
| 8 | const strs = ([][*]const u8){ | ||
| 9 | c"one", | ||
| 10 | c"two", | ||
| 11 | c"three", | ||
| 12 | }; | ||
| 13 | // TODO this should implicitly cast | ||
| 14 | argv = @ptrCast([*]const [*]const u8, &strs); | ||
| 15 | bar(strs.len); | ||
| 16 | } | ||
| 17 | |||
| 18 | fn foo(args: [][]const u8) void { | ||
| 19 | expect(args.len == 3); | ||
| 20 | expect(streql(args[0], "one")); | ||
| 21 | expect(streql(args[1], "two")); | ||
| 22 | expect(streql(args[2], "three")); | ||
| 23 | } | ||
| 24 | |||
| 25 | fn bar(argc: usize) void { | ||
| 26 | const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable; | ||
| 27 | for (args) |_, i| { | ||
| 28 | const ptr = argv[i]; | ||
| 29 | args[i] = ptr[0..strlen(ptr)]; | ||
| 30 | } | ||
| 31 | foo(args); | ||
| 32 | } | ||
| 33 | |||
| 34 | fn strlen(ptr: [*]const u8) usize { | ||
| 35 | var count: usize = 0; | ||
| 36 | while (ptr[count] != 0) : (count += 1) {} | ||
| 37 | return count; | ||
| 38 | } | ||
| 39 | |||
| 40 | fn streql(a: []const u8, b: []const u8) bool { | ||
| 41 | if (a.len != b.len) return false; | ||
| 42 | for (a) |item, index| { | ||
| 43 | if (b[index] != item) return false; | ||
| 44 | } | ||
| 45 | return true; | ||
| 46 | } | ||
test/stage1/behavior/coroutine_await_struct.zig created+47| ... | @@ -0,0 +1,47 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | const Foo = struct { | ||
| 6 | x: i32, | ||
| 7 | }; | ||
| 8 | |||
| 9 | var await_a_promise: promise = undefined; | ||
| 10 | var await_final_result = Foo{ .x = 0 }; | ||
| 11 | |||
| 12 | test "coroutine await struct" { | ||
| 13 | var da = std.heap.DirectAllocator.init(); | ||
| 14 | defer da.deinit(); | ||
| 15 | |||
| 16 | await_seq('a'); | ||
| 17 | const p = async<&da.allocator> await_amain() catch unreachable; | ||
| 18 | await_seq('f'); | ||
| 19 | resume await_a_promise; | ||
| 20 | await_seq('i'); | ||
| 21 | expect(await_final_result.x == 1234); | ||
| 22 | expect(std.mem.eql(u8, await_points, "abcdefghi")); | ||
| 23 | } | ||
| 24 | async fn await_amain() void { | ||
| 25 | await_seq('b'); | ||
| 26 | const p = async await_another() catch unreachable; | ||
| 27 | await_seq('e'); | ||
| 28 | await_final_result = await p; | ||
| 29 | await_seq('h'); | ||
| 30 | } | ||
| 31 | async fn await_another() Foo { | ||
| 32 | await_seq('c'); | ||
| 33 | suspend { | ||
| 34 | await_seq('d'); | ||
| 35 | await_a_promise = @handle(); | ||
| 36 | } | ||
| 37 | await_seq('g'); | ||
| 38 | return Foo{ .x = 1234 }; | ||
| 39 | } | ||
| 40 | |||
| 41 | var await_points = []u8{0} ** "abcdefghi".len; | ||
| 42 | var await_seq_index: usize = 0; | ||
| 43 | |||
| 44 | fn await_seq(c: u8) void { | ||
| 45 | await_points[await_seq_index] = c; | ||
| 46 | await_seq_index += 1; | ||
| 47 | } | ||
test/stage1/behavior/coroutines.zig created+258| ... | @@ -0,0 +1,258 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | var x: i32 = 1; | ||
| 6 | |||
| 7 | test "create a coroutine and cancel it" { | ||
| 8 | var da = std.heap.DirectAllocator.init(); | ||
| 9 | defer da.deinit(); | ||
| 10 | |||
| 11 | const p = try async<&da.allocator> simpleAsyncFn(); | ||
| 12 | comptime expect(@typeOf(p) == promise->void); | ||
| 13 | cancel p; | ||
| 14 | expect(x == 2); | ||
| 15 | } | ||
| 16 | async fn simpleAsyncFn() void { | ||
| 17 | x += 1; | ||
| 18 | suspend; | ||
| 19 | x += 1; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "coroutine suspend, resume, cancel" { | ||
| 23 | var da = std.heap.DirectAllocator.init(); | ||
| 24 | defer da.deinit(); | ||
| 25 | |||
| 26 | seq('a'); | ||
| 27 | const p = try async<&da.allocator> testAsyncSeq(); | ||
| 28 | seq('c'); | ||
| 29 | resume p; | ||
| 30 | seq('f'); | ||
| 31 | cancel p; | ||
| 32 | seq('g'); | ||
| 33 | |||
| 34 | expect(std.mem.eql(u8, points, "abcdefg")); | ||
| 35 | } | ||
| 36 | async fn testAsyncSeq() void { | ||
| 37 | defer seq('e'); | ||
| 38 | |||
| 39 | seq('b'); | ||
| 40 | suspend; | ||
| 41 | seq('d'); | ||
| 42 | } | ||
| 43 | var points = []u8{0} ** "abcdefg".len; | ||
| 44 | var index: usize = 0; | ||
| 45 | |||
| 46 | fn seq(c: u8) void { | ||
| 47 | points[index] = c; | ||
| 48 | index += 1; | ||
| 49 | } | ||
| 50 | |||
| 51 | test "coroutine suspend with block" { | ||
| 52 | var da = std.heap.DirectAllocator.init(); | ||
| 53 | defer da.deinit(); | ||
| 54 | |||
| 55 | const p = try async<&da.allocator> testSuspendBlock(); | ||
| 56 | std.testing.expect(!result); | ||
| 57 | resume a_promise; | ||
| 58 | std.testing.expect(result); | ||
| 59 | cancel p; | ||
| 60 | } | ||
| 61 | |||
| 62 | var a_promise: promise = undefined; | ||
| 63 | var result = false; | ||
| 64 | async fn testSuspendBlock() void { | ||
| 65 | suspend { | ||
| 66 | comptime expect(@typeOf(@handle()) == promise->void); | ||
| 67 | a_promise = @handle(); | ||
| 68 | } | ||
| 69 | |||
| 70 | //Test to make sure that @handle() works as advertised (issue #1296) | ||
| 71 | //var our_handle: promise = @handle(); | ||
| 72 | expect(a_promise == @handle()); | ||
| 73 | |||
| 74 | result = true; | ||
| 75 | } | ||
| 76 | |||
| 77 | var await_a_promise: promise = undefined; | ||
| 78 | var await_final_result: i32 = 0; | ||
| 79 | |||
| 80 | test "coroutine await" { | ||
| 81 | var da = std.heap.DirectAllocator.init(); | ||
| 82 | defer da.deinit(); | ||
| 83 | |||
| 84 | await_seq('a'); | ||
| 85 | const p = async<&da.allocator> await_amain() catch unreachable; | ||
| 86 | await_seq('f'); | ||
| 87 | resume await_a_promise; | ||
| 88 | await_seq('i'); | ||
| 89 | expect(await_final_result == 1234); | ||
| 90 | expect(std.mem.eql(u8, await_points, "abcdefghi")); | ||
| 91 | } | ||
| 92 | async fn await_amain() void { | ||
| 93 | await_seq('b'); | ||
| 94 | const p = async await_another() catch unreachable; | ||
| 95 | await_seq('e'); | ||
| 96 | await_final_result = await p; | ||
| 97 | await_seq('h'); | ||
| 98 | } | ||
| 99 | async fn await_another() i32 { | ||
| 100 | await_seq('c'); | ||
| 101 | suspend { | ||
| 102 | await_seq('d'); | ||
| 103 | await_a_promise = @handle(); | ||
| 104 | } | ||
| 105 | await_seq('g'); | ||
| 106 | return 1234; | ||
| 107 | } | ||
| 108 | |||
| 109 | var await_points = []u8{0} ** "abcdefghi".len; | ||
| 110 | var await_seq_index: usize = 0; | ||
| 111 | |||
| 112 | fn await_seq(c: u8) void { | ||
| 113 | await_points[await_seq_index] = c; | ||
| 114 | await_seq_index += 1; | ||
| 115 | } | ||
| 116 | |||
| 117 | var early_final_result: i32 = 0; | ||
| 118 | |||
| 119 | test "coroutine await early return" { | ||
| 120 | var da = std.heap.DirectAllocator.init(); | ||
| 121 | defer da.deinit(); | ||
| 122 | |||
| 123 | early_seq('a'); | ||
| 124 | const p = async<&da.allocator> early_amain() catch @panic("out of memory"); | ||
| 125 | early_seq('f'); | ||
| 126 | expect(early_final_result == 1234); | ||
| 127 | expect(std.mem.eql(u8, early_points, "abcdef")); | ||
| 128 | } | ||
| 129 | async fn early_amain() void { | ||
| 130 | early_seq('b'); | ||
| 131 | const p = async early_another() catch @panic("out of memory"); | ||
| 132 | early_seq('d'); | ||
| 133 | early_final_result = await p; | ||
| 134 | early_seq('e'); | ||
| 135 | } | ||
| 136 | async fn early_another() i32 { | ||
| 137 | early_seq('c'); | ||
| 138 | return 1234; | ||
| 139 | } | ||
| 140 | |||
| 141 | var early_points = []u8{0} ** "abcdef".len; | ||
| 142 | var early_seq_index: usize = 0; | ||
| 143 | |||
| 144 | fn early_seq(c: u8) void { | ||
| 145 | early_points[early_seq_index] = c; | ||
| 146 | early_seq_index += 1; | ||
| 147 | } | ||
| 148 | |||
| 149 | test "coro allocation failure" { | ||
| 150 | var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0); | ||
| 151 | if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) { | ||
| 152 | @panic("expected allocation failure"); | ||
| 153 | } else |err| switch (err) { | ||
| 154 | error.OutOfMemory => {}, | ||
| 155 | } | ||
| 156 | } | ||
| 157 | async fn asyncFuncThatNeverGetsRun() void { | ||
| 158 | @panic("coro frame allocation should fail"); | ||
| 159 | } | ||
| 160 | |||
| 161 | test "async function with dot syntax" { | ||
| 162 | const S = struct { | ||
| 163 | var y: i32 = 1; | ||
| 164 | async fn foo() void { | ||
| 165 | y += 1; | ||
| 166 | suspend; | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | var da = std.heap.DirectAllocator.init(); | ||
| 170 | defer da.deinit(); | ||
| 171 | const p = try async<&da.allocator> S.foo(); | ||
| 172 | cancel p; | ||
| 173 | expect(S.y == 2); | ||
| 174 | } | ||
| 175 | |||
| 176 | test "async fn pointer in a struct field" { | ||
| 177 | var data: i32 = 1; | ||
| 178 | const Foo = struct { | ||
| 179 | bar: async<*std.mem.Allocator> fn (*i32) void, | ||
| 180 | }; | ||
| 181 | var foo = Foo{ .bar = simpleAsyncFn2 }; | ||
| 182 | var da = std.heap.DirectAllocator.init(); | ||
| 183 | defer da.deinit(); | ||
| 184 | const p = (async<&da.allocator> foo.bar(&data)) catch unreachable; | ||
| 185 | expect(data == 2); | ||
| 186 | cancel p; | ||
| 187 | expect(data == 4); | ||
| 188 | } | ||
| 189 | async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { | ||
| 190 | defer y.* += 2; | ||
| 191 | y.* += 1; | ||
| 192 | suspend; | ||
| 193 | } | ||
| 194 | |||
| 195 | test "async fn with inferred error set" { | ||
| 196 | var da = std.heap.DirectAllocator.init(); | ||
| 197 | defer da.deinit(); | ||
| 198 | const p = (async<&da.allocator> failing()) catch unreachable; | ||
| 199 | resume p; | ||
| 200 | cancel p; | ||
| 201 | } | ||
| 202 | |||
| 203 | async fn failing() !void { | ||
| 204 | suspend; | ||
| 205 | return error.Fail; | ||
| 206 | } | ||
| 207 | |||
| 208 | test "error return trace across suspend points - early return" { | ||
| 209 | const p = nonFailing(); | ||
| 210 | resume p; | ||
| 211 | var da = std.heap.DirectAllocator.init(); | ||
| 212 | defer da.deinit(); | ||
| 213 | const p2 = try async<&da.allocator> printTrace(p); | ||
| 214 | cancel p2; | ||
| 215 | } | ||
| 216 | |||
| 217 | test "error return trace across suspend points - async return" { | ||
| 218 | const p = nonFailing(); | ||
| 219 | const p2 = try async<std.debug.global_allocator> printTrace(p); | ||
| 220 | resume p; | ||
| 221 | cancel p2; | ||
| 222 | } | ||
| 223 | |||
| 224 | fn nonFailing() (promise->anyerror!void) { | ||
| 225 | return async<std.debug.global_allocator> suspendThenFail() catch unreachable; | ||
| 226 | } | ||
| 227 | async fn suspendThenFail() anyerror!void { | ||
| 228 | suspend; | ||
| 229 | return error.Fail; | ||
| 230 | } | ||
| 231 | async fn printTrace(p: promise->(anyerror!void)) void { | ||
| 232 | (await p) catch |e| { | ||
| 233 | std.testing.expect(e == error.Fail); | ||
| 234 | if (@errorReturnTrace()) |trace| { | ||
| 235 | expect(trace.index == 1); | ||
| 236 | } else switch (builtin.mode) { | ||
| 237 | builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"), | ||
| 238 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {}, | ||
| 239 | } | ||
| 240 | }; | ||
| 241 | } | ||
| 242 | |||
| 243 | test "break from suspend" { | ||
| 244 | var buf: [500]u8 = undefined; | ||
| 245 | var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; | ||
| 246 | var my_result: i32 = 1; | ||
| 247 | const p = try async<a> testBreakFromSuspend(&my_result); | ||
| 248 | cancel p; | ||
| 249 | std.testing.expect(my_result == 2); | ||
| 250 | } | ||
| 251 | async fn testBreakFromSuspend(my_result: *i32) void { | ||
| 252 | suspend { | ||
| 253 | resume @handle(); | ||
| 254 | } | ||
| 255 | my_result.* += 1; | ||
| 256 | suspend; | ||
| 257 | my_result.* += 1; | ||
| 258 | } | ||
test/stage1/behavior/defer.zig created+78| ... | @@ -0,0 +1,78 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | var result: [3]u8 = undefined; | ||
| 4 | var index: usize = undefined; | ||
| 5 | |||
| 6 | fn runSomeErrorDefers(x: bool) !bool { | ||
| 7 | index = 0; | ||
| 8 | defer { | ||
| 9 | result[index] = 'a'; | ||
| 10 | index += 1; | ||
| 11 | } | ||
| 12 | errdefer { | ||
| 13 | result[index] = 'b'; | ||
| 14 | index += 1; | ||
| 15 | } | ||
| 16 | defer { | ||
| 17 | result[index] = 'c'; | ||
| 18 | index += 1; | ||
| 19 | } | ||
| 20 | return if (x) x else error.FalseNotAllowed; | ||
| 21 | } | ||
| 22 | |||
| 23 | test "mixing normal and error defers" { | ||
| 24 | expect(runSomeErrorDefers(true) catch unreachable); | ||
| 25 | expect(result[0] == 'c'); | ||
| 26 | expect(result[1] == 'a'); | ||
| 27 | |||
| 28 | const ok = runSomeErrorDefers(false) catch |err| x: { | ||
| 29 | expect(err == error.FalseNotAllowed); | ||
| 30 | break :x true; | ||
| 31 | }; | ||
| 32 | expect(ok); | ||
| 33 | expect(result[0] == 'c'); | ||
| 34 | expect(result[1] == 'b'); | ||
| 35 | expect(result[2] == 'a'); | ||
| 36 | } | ||
| 37 | |||
| 38 | test "break and continue inside loop inside defer expression" { | ||
| 39 | testBreakContInDefer(10); | ||
| 40 | comptime testBreakContInDefer(10); | ||
| 41 | } | ||
| 42 | |||
| 43 | fn testBreakContInDefer(x: usize) void { | ||
| 44 | defer { | ||
| 45 | var i: usize = 0; | ||
| 46 | while (i < x) : (i += 1) { | ||
| 47 | if (i < 5) continue; | ||
| 48 | if (i == 5) break; | ||
| 49 | } | ||
| 50 | expect(i == 5); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | test "defer and labeled break" { | ||
| 55 | var i = usize(0); | ||
| 56 | |||
| 57 | blk: { | ||
| 58 | defer i += 1; | ||
| 59 | break :blk; | ||
| 60 | } | ||
| 61 | |||
| 62 | expect(i == 1); | ||
| 63 | } | ||
| 64 | |||
| 65 | test "errdefer does not apply to fn inside fn" { | ||
| 66 | if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| expect(e == error.Bad); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn testNestedFnErrDefer() anyerror!void { | ||
| 70 | var a: i32 = 0; | ||
| 71 | errdefer a += 1; | ||
| 72 | const S = struct { | ||
| 73 | fn baz() anyerror { | ||
| 74 | return error.Bad; | ||
| 75 | } | ||
| 76 | }; | ||
| 77 | return S.baz(); | ||
| 78 | } | ||
test/stage1/behavior/enum.zig created+894| ... | @@ -0,0 +1,894 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | test "enum type" { | ||
| 5 | const foo1 = Foo{ .One = 13 }; | ||
| 6 | const foo2 = Foo{ | ||
| 7 | .Two = Point{ | ||
| 8 | .x = 1234, | ||
| 9 | .y = 5678, | ||
| 10 | }, | ||
| 11 | }; | ||
| 12 | const bar = Bar.B; | ||
| 13 | |||
| 14 | expect(bar == Bar.B); | ||
| 15 | expect(@memberCount(Foo) == 3); | ||
| 16 | expect(@memberCount(Bar) == 4); | ||
| 17 | expect(@sizeOf(Foo) == @sizeOf(FooNoVoid)); | ||
| 18 | expect(@sizeOf(Bar) == 1); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "enum as return value" { | ||
| 22 | switch (returnAnInt(13)) { | ||
| 23 | Foo.One => |value| expect(value == 13), | ||
| 24 | else => unreachable, | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | const Point = struct { | ||
| 29 | x: u64, | ||
| 30 | y: u64, | ||
| 31 | }; | ||
| 32 | const Foo = union(enum) { | ||
| 33 | One: i32, | ||
| 34 | Two: Point, | ||
| 35 | Three: void, | ||
| 36 | }; | ||
| 37 | const FooNoVoid = union(enum) { | ||
| 38 | One: i32, | ||
| 39 | Two: Point, | ||
| 40 | }; | ||
| 41 | const Bar = enum { | ||
| 42 | A, | ||
| 43 | B, | ||
| 44 | C, | ||
| 45 | D, | ||
| 46 | }; | ||
| 47 | |||
| 48 | fn returnAnInt(x: i32) Foo { | ||
| 49 | return Foo{ .One = x }; | ||
| 50 | } | ||
| 51 | |||
| 52 | test "constant enum with payload" { | ||
| 53 | var empty = AnEnumWithPayload{ .Empty = {} }; | ||
| 54 | var full = AnEnumWithPayload{ .Full = 13 }; | ||
| 55 | shouldBeEmpty(empty); | ||
| 56 | shouldBeNotEmpty(full); | ||
| 57 | } | ||
| 58 | |||
| 59 | fn shouldBeEmpty(x: AnEnumWithPayload) void { | ||
| 60 | switch (x) { | ||
| 61 | AnEnumWithPayload.Empty => {}, | ||
| 62 | else => unreachable, | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | fn shouldBeNotEmpty(x: AnEnumWithPayload) void { | ||
| 67 | switch (x) { | ||
| 68 | AnEnumWithPayload.Empty => unreachable, | ||
| 69 | else => {}, | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | const AnEnumWithPayload = union(enum) { | ||
| 74 | Empty: void, | ||
| 75 | Full: i32, | ||
| 76 | }; | ||
| 77 | |||
| 78 | const Number = enum { | ||
| 79 | Zero, | ||
| 80 | One, | ||
| 81 | Two, | ||
| 82 | Three, | ||
| 83 | Four, | ||
| 84 | }; | ||
| 85 | |||
| 86 | test "enum to int" { | ||
| 87 | shouldEqual(Number.Zero, 0); | ||
| 88 | shouldEqual(Number.One, 1); | ||
| 89 | shouldEqual(Number.Two, 2); | ||
| 90 | shouldEqual(Number.Three, 3); | ||
| 91 | shouldEqual(Number.Four, 4); | ||
| 92 | } | ||
| 93 | |||
| 94 | fn shouldEqual(n: Number, expected: u3) void { | ||
| 95 | expect(@enumToInt(n) == expected); | ||
| 96 | } | ||
| 97 | |||
| 98 | test "int to enum" { | ||
| 99 | testIntToEnumEval(3); | ||
| 100 | } | ||
| 101 | fn testIntToEnumEval(x: i32) void { | ||
| 102 | expect(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); | ||
| 103 | } | ||
| 104 | const IntToEnumNumber = enum { | ||
| 105 | Zero, | ||
| 106 | One, | ||
| 107 | Two, | ||
| 108 | Three, | ||
| 109 | Four, | ||
| 110 | }; | ||
| 111 | |||
| 112 | test "@tagName" { | ||
| 113 | expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | ||
| 114 | comptime expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | ||
| 115 | } | ||
| 116 | |||
| 117 | fn testEnumTagNameBare(n: BareNumber) []const u8 { | ||
| 118 | return @tagName(n); | ||
| 119 | } | ||
| 120 | |||
| 121 | const BareNumber = enum { | ||
| 122 | One, | ||
| 123 | Two, | ||
| 124 | Three, | ||
| 125 | }; | ||
| 126 | |||
| 127 | test "enum alignment" { | ||
| 128 | comptime { | ||
| 129 | expect(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); | ||
| 130 | expect(@alignOf(AlignTestEnum) >= @alignOf(u64)); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | const AlignTestEnum = union(enum) { | ||
| 135 | A: [9]u8, | ||
| 136 | B: u64, | ||
| 137 | }; | ||
| 138 | |||
| 139 | const ValueCount1 = enum { | ||
| 140 | I0, | ||
| 141 | }; | ||
| 142 | const ValueCount2 = enum { | ||
| 143 | I0, | ||
| 144 | I1, | ||
| 145 | }; | ||
| 146 | const ValueCount256 = enum { | ||
| 147 | I0, | ||
| 148 | I1, | ||
| 149 | I2, | ||
| 150 | I3, | ||
| 151 | I4, | ||
| 152 | I5, | ||
| 153 | I6, | ||
| 154 | I7, | ||
| 155 | I8, | ||
| 156 | I9, | ||
| 157 | I10, | ||
| 158 | I11, | ||
| 159 | I12, | ||
| 160 | I13, | ||
| 161 | I14, | ||
| 162 | I15, | ||
| 163 | I16, | ||
| 164 | I17, | ||
| 165 | I18, | ||
| 166 | I19, | ||
| 167 | I20, | ||
| 168 | I21, | ||
| 169 | I22, | ||
| 170 | I23, | ||
| 171 | I24, | ||
| 172 | I25, | ||
| 173 | I26, | ||
| 174 | I27, | ||
| 175 | I28, | ||
| 176 | I29, | ||
| 177 | I30, | ||
| 178 | I31, | ||
| 179 | I32, | ||
| 180 | I33, | ||
| 181 | I34, | ||
| 182 | I35, | ||
| 183 | I36, | ||
| 184 | I37, | ||
| 185 | I38, | ||
| 186 | I39, | ||
| 187 | I40, | ||
| 188 | I41, | ||
| 189 | I42, | ||
| 190 | I43, | ||
| 191 | I44, | ||
| 192 | I45, | ||
| 193 | I46, | ||
| 194 | I47, | ||
| 195 | I48, | ||
| 196 | I49, | ||
| 197 | I50, | ||
| 198 | I51, | ||
| 199 | I52, | ||
| 200 | I53, | ||
| 201 | I54, | ||
| 202 | I55, | ||
| 203 | I56, | ||
| 204 | I57, | ||
| 205 | I58, | ||
| 206 | I59, | ||
| 207 | I60, | ||
| 208 | I61, | ||
| 209 | I62, | ||
| 210 | I63, | ||
| 211 | I64, | ||
| 212 | I65, | ||
| 213 | I66, | ||
| 214 | I67, | ||
| 215 | I68, | ||
| 216 | I69, | ||
| 217 | I70, | ||
| 218 | I71, | ||
| 219 | I72, | ||
| 220 | I73, | ||
| 221 | I74, | ||
| 222 | I75, | ||
| 223 | I76, | ||
| 224 | I77, | ||
| 225 | I78, | ||
| 226 | I79, | ||
| 227 | I80, | ||
| 228 | I81, | ||
| 229 | I82, | ||
| 230 | I83, | ||
| 231 | I84, | ||
| 232 | I85, | ||
| 233 | I86, | ||
| 234 | I87, | ||
| 235 | I88, | ||
| 236 | I89, | ||
| 237 | I90, | ||
| 238 | I91, | ||
| 239 | I92, | ||
| 240 | I93, | ||
| 241 | I94, | ||
| 242 | I95, | ||
| 243 | I96, | ||
| 244 | I97, | ||
| 245 | I98, | ||
| 246 | I99, | ||
| 247 | I100, | ||
| 248 | I101, | ||
| 249 | I102, | ||
| 250 | I103, | ||
| 251 | I104, | ||
| 252 | I105, | ||
| 253 | I106, | ||
| 254 | I107, | ||
| 255 | I108, | ||
| 256 | I109, | ||
| 257 | I110, | ||
| 258 | I111, | ||
| 259 | I112, | ||
| 260 | I113, | ||
| 261 | I114, | ||
| 262 | I115, | ||
| 263 | I116, | ||
| 264 | I117, | ||
| 265 | I118, | ||
| 266 | I119, | ||
| 267 | I120, | ||
| 268 | I121, | ||
| 269 | I122, | ||
| 270 | I123, | ||
| 271 | I124, | ||
| 272 | I125, | ||
| 273 | I126, | ||
| 274 | I127, | ||
| 275 | I128, | ||
| 276 | I129, | ||
| 277 | I130, | ||
| 278 | I131, | ||
| 279 | I132, | ||
| 280 | I133, | ||
| 281 | I134, | ||
| 282 | I135, | ||
| 283 | I136, | ||
| 284 | I137, | ||
| 285 | I138, | ||
| 286 | I139, | ||
| 287 | I140, | ||
| 288 | I141, | ||
| 289 | I142, | ||
| 290 | I143, | ||
| 291 | I144, | ||
| 292 | I145, | ||
| 293 | I146, | ||
| 294 | I147, | ||
| 295 | I148, | ||
| 296 | I149, | ||
| 297 | I150, | ||
| 298 | I151, | ||
| 299 | I152, | ||
| 300 | I153, | ||
| 301 | I154, | ||
| 302 | I155, | ||
| 303 | I156, | ||
| 304 | I157, | ||
| 305 | I158, | ||
| 306 | I159, | ||
| 307 | I160, | ||
| 308 | I161, | ||
| 309 | I162, | ||
| 310 | I163, | ||
| 311 | I164, | ||
| 312 | I165, | ||
| 313 | I166, | ||
| 314 | I167, | ||
| 315 | I168, | ||
| 316 | I169, | ||
| 317 | I170, | ||
| 318 | I171, | ||
| 319 | I172, | ||
| 320 | I173, | ||
| 321 | I174, | ||
| 322 | I175, | ||
| 323 | I176, | ||
| 324 | I177, | ||
| 325 | I178, | ||
| 326 | I179, | ||
| 327 | I180, | ||
| 328 | I181, | ||
| 329 | I182, | ||
| 330 | I183, | ||
| 331 | I184, | ||
| 332 | I185, | ||
| 333 | I186, | ||
| 334 | I187, | ||
| 335 | I188, | ||
| 336 | I189, | ||
| 337 | I190, | ||
| 338 | I191, | ||
| 339 | I192, | ||
| 340 | I193, | ||
| 341 | I194, | ||
| 342 | I195, | ||
| 343 | I196, | ||
| 344 | I197, | ||
| 345 | I198, | ||
| 346 | I199, | ||
| 347 | I200, | ||
| 348 | I201, | ||
| 349 | I202, | ||
| 350 | I203, | ||
| 351 | I204, | ||
| 352 | I205, | ||
| 353 | I206, | ||
| 354 | I207, | ||
| 355 | I208, | ||
| 356 | I209, | ||
| 357 | I210, | ||
| 358 | I211, | ||
| 359 | I212, | ||
| 360 | I213, | ||
| 361 | I214, | ||
| 362 | I215, | ||
| 363 | I216, | ||
| 364 | I217, | ||
| 365 | I218, | ||
| 366 | I219, | ||
| 367 | I220, | ||
| 368 | I221, | ||
| 369 | I222, | ||
| 370 | I223, | ||
| 371 | I224, | ||
| 372 | I225, | ||
| 373 | I226, | ||
| 374 | I227, | ||
| 375 | I228, | ||
| 376 | I229, | ||
| 377 | I230, | ||
| 378 | I231, | ||
| 379 | I232, | ||
| 380 | I233, | ||
| 381 | I234, | ||
| 382 | I235, | ||
| 383 | I236, | ||
| 384 | I237, | ||
| 385 | I238, | ||
| 386 | I239, | ||
| 387 | I240, | ||
| 388 | I241, | ||
| 389 | I242, | ||
| 390 | I243, | ||
| 391 | I244, | ||
| 392 | I245, | ||
| 393 | I246, | ||
| 394 | I247, | ||
| 395 | I248, | ||
| 396 | I249, | ||
| 397 | I250, | ||
| 398 | I251, | ||
| 399 | I252, | ||
| 400 | I253, | ||
| 401 | I254, | ||
| 402 | I255, | ||
| 403 | }; | ||
| 404 | const ValueCount257 = enum { | ||
| 405 | I0, | ||
| 406 | I1, | ||
| 407 | I2, | ||
| 408 | I3, | ||
| 409 | I4, | ||
| 410 | I5, | ||
| 411 | I6, | ||
| 412 | I7, | ||
| 413 | I8, | ||
| 414 | I9, | ||
| 415 | I10, | ||
| 416 | I11, | ||
| 417 | I12, | ||
| 418 | I13, | ||
| 419 | I14, | ||
| 420 | I15, | ||
| 421 | I16, | ||
| 422 | I17, | ||
| 423 | I18, | ||
| 424 | I19, | ||
| 425 | I20, | ||
| 426 | I21, | ||
| 427 | I22, | ||
| 428 | I23, | ||
| 429 | I24, | ||
| 430 | I25, | ||
| 431 | I26, | ||
| 432 | I27, | ||
| 433 | I28, | ||
| 434 | I29, | ||
| 435 | I30, | ||
| 436 | I31, | ||
| 437 | I32, | ||
| 438 | I33, | ||
| 439 | I34, | ||
| 440 | I35, | ||
| 441 | I36, | ||
| 442 | I37, | ||
| 443 | I38, | ||
| 444 | I39, | ||
| 445 | I40, | ||
| 446 | I41, | ||
| 447 | I42, | ||
| 448 | I43, | ||
| 449 | I44, | ||
| 450 | I45, | ||
| 451 | I46, | ||
| 452 | I47, | ||
| 453 | I48, | ||
| 454 | I49, | ||
| 455 | I50, | ||
| 456 | I51, | ||
| 457 | I52, | ||
| 458 | I53, | ||
| 459 | I54, | ||
| 460 | I55, | ||
| 461 | I56, | ||
| 462 | I57, | ||
| 463 | I58, | ||
| 464 | I59, | ||
| 465 | I60, | ||
| 466 | I61, | ||
| 467 | I62, | ||
| 468 | I63, | ||
| 469 | I64, | ||
| 470 | I65, | ||
| 471 | I66, | ||
| 472 | I67, | ||
| 473 | I68, | ||
| 474 | I69, | ||
| 475 | I70, | ||
| 476 | I71, | ||
| 477 | I72, | ||
| 478 | I73, | ||
| 479 | I74, | ||
| 480 | I75, | ||
| 481 | I76, | ||
| 482 | I77, | ||
| 483 | I78, | ||
| 484 | I79, | ||
| 485 | I80, | ||
| 486 | I81, | ||
| 487 | I82, | ||
| 488 | I83, | ||
| 489 | I84, | ||
| 490 | I85, | ||
| 491 | I86, | ||
| 492 | I87, | ||
| 493 | I88, | ||
| 494 | I89, | ||
| 495 | I90, | ||
| 496 | I91, | ||
| 497 | I92, | ||
| 498 | I93, | ||
| 499 | I94, | ||
| 500 | I95, | ||
| 501 | I96, | ||
| 502 | I97, | ||
| 503 | I98, | ||
| 504 | I99, | ||
| 505 | I100, | ||
| 506 | I101, | ||
| 507 | I102, | ||
| 508 | I103, | ||
| 509 | I104, | ||
| 510 | I105, | ||
| 511 | I106, | ||
| 512 | I107, | ||
| 513 | I108, | ||
| 514 | I109, | ||
| 515 | I110, | ||
| 516 | I111, | ||
| 517 | I112, | ||
| 518 | I113, | ||
| 519 | I114, | ||
| 520 | I115, | ||
| 521 | I116, | ||
| 522 | I117, | ||
| 523 | I118, | ||
| 524 | I119, | ||
| 525 | I120, | ||
| 526 | I121, | ||
| 527 | I122, | ||
| 528 | I123, | ||
| 529 | I124, | ||
| 530 | I125, | ||
| 531 | I126, | ||
| 532 | I127, | ||
| 533 | I128, | ||
| 534 | I129, | ||
| 535 | I130, | ||
| 536 | I131, | ||
| 537 | I132, | ||
| 538 | I133, | ||
| 539 | I134, | ||
| 540 | I135, | ||
| 541 | I136, | ||
| 542 | I137, | ||
| 543 | I138, | ||
| 544 | I139, | ||
| 545 | I140, | ||
| 546 | I141, | ||
| 547 | I142, | ||
| 548 | I143, | ||
| 549 | I144, | ||
| 550 | I145, | ||
| 551 | I146, | ||
| 552 | I147, | ||
| 553 | I148, | ||
| 554 | I149, | ||
| 555 | I150, | ||
| 556 | I151, | ||
| 557 | I152, | ||
| 558 | I153, | ||
| 559 | I154, | ||
| 560 | I155, | ||
| 561 | I156, | ||
| 562 | I157, | ||
| 563 | I158, | ||
| 564 | I159, | ||
| 565 | I160, | ||
| 566 | I161, | ||
| 567 | I162, | ||
| 568 | I163, | ||
| 569 | I164, | ||
| 570 | I165, | ||
| 571 | I166, | ||
| 572 | I167, | ||
| 573 | I168, | ||
| 574 | I169, | ||
| 575 | I170, | ||
| 576 | I171, | ||
| 577 | I172, | ||
| 578 | I173, | ||
| 579 | I174, | ||
| 580 | I175, | ||
| 581 | I176, | ||
| 582 | I177, | ||
| 583 | I178, | ||
| 584 | I179, | ||
| 585 | I180, | ||
| 586 | I181, | ||
| 587 | I182, | ||
| 588 | I183, | ||
| 589 | I184, | ||
| 590 | I185, | ||
| 591 | I186, | ||
| 592 | I187, | ||
| 593 | I188, | ||
| 594 | I189, | ||
| 595 | I190, | ||
| 596 | I191, | ||
| 597 | I192, | ||
| 598 | I193, | ||
| 599 | I194, | ||
| 600 | I195, | ||
| 601 | I196, | ||
| 602 | I197, | ||
| 603 | I198, | ||
| 604 | I199, | ||
| 605 | I200, | ||
| 606 | I201, | ||
| 607 | I202, | ||
| 608 | I203, | ||
| 609 | I204, | ||
| 610 | I205, | ||
| 611 | I206, | ||
| 612 | I207, | ||
| 613 | I208, | ||
| 614 | I209, | ||
| 615 | I210, | ||
| 616 | I211, | ||
| 617 | I212, | ||
| 618 | I213, | ||
| 619 | I214, | ||
| 620 | I215, | ||
| 621 | I216, | ||
| 622 | I217, | ||
| 623 | I218, | ||
| 624 | I219, | ||
| 625 | I220, | ||
| 626 | I221, | ||
| 627 | I222, | ||
| 628 | I223, | ||
| 629 | I224, | ||
| 630 | I225, | ||
| 631 | I226, | ||
| 632 | I227, | ||
| 633 | I228, | ||
| 634 | I229, | ||
| 635 | I230, | ||
| 636 | I231, | ||
| 637 | I232, | ||
| 638 | I233, | ||
| 639 | I234, | ||
| 640 | I235, | ||
| 641 | I236, | ||
| 642 | I237, | ||
| 643 | I238, | ||
| 644 | I239, | ||
| 645 | I240, | ||
| 646 | I241, | ||
| 647 | I242, | ||
| 648 | I243, | ||
| 649 | I244, | ||
| 650 | I245, | ||
| 651 | I246, | ||
| 652 | I247, | ||
| 653 | I248, | ||
| 654 | I249, | ||
| 655 | I250, | ||
| 656 | I251, | ||
| 657 | I252, | ||
| 658 | I253, | ||
| 659 | I254, | ||
| 660 | I255, | ||
| 661 | I256, | ||
| 662 | }; | ||
| 663 | |||
| 664 | test "enum sizes" { | ||
| 665 | comptime { | ||
| 666 | expect(@sizeOf(ValueCount1) == 0); | ||
| 667 | expect(@sizeOf(ValueCount2) == 1); | ||
| 668 | expect(@sizeOf(ValueCount256) == 1); | ||
| 669 | expect(@sizeOf(ValueCount257) == 2); | ||
| 670 | } | ||
| 671 | } | ||
| 672 | |||
| 673 | const Small2 = enum(u2) { | ||
| 674 | One, | ||
| 675 | Two, | ||
| 676 | }; | ||
| 677 | const Small = enum(u2) { | ||
| 678 | One, | ||
| 679 | Two, | ||
| 680 | Three, | ||
| 681 | Four, | ||
| 682 | }; | ||
| 683 | |||
| 684 | test "set enum tag type" { | ||
| 685 | { | ||
| 686 | var x = Small.One; | ||
| 687 | x = Small.Two; | ||
| 688 | comptime expect(@TagType(Small) == u2); | ||
| 689 | } | ||
| 690 | { | ||
| 691 | var x = Small2.One; | ||
| 692 | x = Small2.Two; | ||
| 693 | comptime expect(@TagType(Small2) == u2); | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 697 | const A = enum(u3) { | ||
| 698 | One, | ||
| 699 | Two, | ||
| 700 | Three, | ||
| 701 | Four, | ||
| 702 | One2, | ||
| 703 | Two2, | ||
| 704 | Three2, | ||
| 705 | Four2, | ||
| 706 | }; | ||
| 707 | |||
| 708 | const B = enum(u3) { | ||
| 709 | One3, | ||
| 710 | Two3, | ||
| 711 | Three3, | ||
| 712 | Four3, | ||
| 713 | One23, | ||
| 714 | Two23, | ||
| 715 | Three23, | ||
| 716 | Four23, | ||
| 717 | }; | ||
| 718 | |||
| 719 | const C = enum(u2) { | ||
| 720 | One4, | ||
| 721 | Two4, | ||
| 722 | Three4, | ||
| 723 | Four4, | ||
| 724 | }; | ||
| 725 | |||
| 726 | const BitFieldOfEnums = packed struct { | ||
| 727 | a: A, | ||
| 728 | b: B, | ||
| 729 | c: C, | ||
| 730 | }; | ||
| 731 | |||
| 732 | const bit_field_1 = BitFieldOfEnums{ | ||
| 733 | .a = A.Two, | ||
| 734 | .b = B.Three3, | ||
| 735 | .c = C.Four4, | ||
| 736 | }; | ||
| 737 | |||
| 738 | test "bit field access with enum fields" { | ||
| 739 | var data = bit_field_1; | ||
| 740 | expect(getA(&data) == A.Two); | ||
| 741 | expect(getB(&data) == B.Three3); | ||
| 742 | expect(getC(&data) == C.Four4); | ||
| 743 | comptime expect(@sizeOf(BitFieldOfEnums) == 1); | ||
| 744 | |||
| 745 | data.b = B.Four3; | ||
| 746 | expect(data.b == B.Four3); | ||
| 747 | |||
| 748 | data.a = A.Three; | ||
| 749 | expect(data.a == A.Three); | ||
| 750 | expect(data.b == B.Four3); | ||
| 751 | } | ||
| 752 | |||
| 753 | fn getA(data: *const BitFieldOfEnums) A { | ||
| 754 | return data.a; | ||
| 755 | } | ||
| 756 | |||
| 757 | fn getB(data: *const BitFieldOfEnums) B { | ||
| 758 | return data.b; | ||
| 759 | } | ||
| 760 | |||
| 761 | fn getC(data: *const BitFieldOfEnums) C { | ||
| 762 | return data.c; | ||
| 763 | } | ||
| 764 | |||
| 765 | test "casting enum to its tag type" { | ||
| 766 | testCastEnumToTagType(Small2.Two); | ||
| 767 | comptime testCastEnumToTagType(Small2.Two); | ||
| 768 | } | ||
| 769 | |||
| 770 | fn testCastEnumToTagType(value: Small2) void { | ||
| 771 | expect(@enumToInt(value) == 1); | ||
| 772 | } | ||
| 773 | |||
| 774 | const MultipleChoice = enum(u32) { | ||
| 775 | A = 20, | ||
| 776 | B = 40, | ||
| 777 | C = 60, | ||
| 778 | D = 1000, | ||
| 779 | }; | ||
| 780 | |||
| 781 | test "enum with specified tag values" { | ||
| 782 | testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 783 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); | ||
| 784 | } | ||
| 785 | |||
| 786 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { | ||
| 787 | expect(@enumToInt(x) == 60); | ||
| 788 | expect(1234 == switch (x) { | ||
| 789 | MultipleChoice.A => 1, | ||
| 790 | MultipleChoice.B => 2, | ||
| 791 | MultipleChoice.C => u32(1234), | ||
| 792 | MultipleChoice.D => 4, | ||
| 793 | }); | ||
| 794 | } | ||
| 795 | |||
| 796 | const MultipleChoice2 = enum(u32) { | ||
| 797 | Unspecified1, | ||
| 798 | A = 20, | ||
| 799 | Unspecified2, | ||
| 800 | B = 40, | ||
| 801 | Unspecified3, | ||
| 802 | C = 60, | ||
| 803 | Unspecified4, | ||
| 804 | D = 1000, | ||
| 805 | Unspecified5, | ||
| 806 | }; | ||
| 807 | |||
| 808 | test "enum with specified and unspecified tag values" { | ||
| 809 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 810 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | ||
| 811 | } | ||
| 812 | |||
| 813 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | ||
| 814 | expect(@enumToInt(x) == 1000); | ||
| 815 | expect(1234 == switch (x) { | ||
| 816 | MultipleChoice2.A => 1, | ||
| 817 | MultipleChoice2.B => 2, | ||
| 818 | MultipleChoice2.C => 3, | ||
| 819 | MultipleChoice2.D => u32(1234), | ||
| 820 | MultipleChoice2.Unspecified1 => 5, | ||
| 821 | MultipleChoice2.Unspecified2 => 6, | ||
| 822 | MultipleChoice2.Unspecified3 => 7, | ||
| 823 | MultipleChoice2.Unspecified4 => 8, | ||
| 824 | MultipleChoice2.Unspecified5 => 9, | ||
| 825 | }); | ||
| 826 | } | ||
| 827 | |||
| 828 | test "cast integer literal to enum" { | ||
| 829 | expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); | ||
| 830 | expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); | ||
| 831 | } | ||
| 832 | |||
| 833 | const EnumWithOneMember = enum { | ||
| 834 | Eof, | ||
| 835 | }; | ||
| 836 | |||
| 837 | fn doALoopThing(id: EnumWithOneMember) void { | ||
| 838 | while (true) { | ||
| 839 | if (id == EnumWithOneMember.Eof) { | ||
| 840 | break; | ||
| 841 | } | ||
| 842 | @compileError("above if condition should be comptime"); | ||
| 843 | } | ||
| 844 | } | ||
| 845 | |||
| 846 | test "comparison operator on enum with one member is comptime known" { | ||
| 847 | doALoopThing(EnumWithOneMember.Eof); | ||
| 848 | } | ||
| 849 | |||
| 850 | const State = enum { | ||
| 851 | Start, | ||
| 852 | }; | ||
| 853 | test "switch on enum with one member is comptime known" { | ||
| 854 | var state = State.Start; | ||
| 855 | switch (state) { | ||
| 856 | State.Start => return, | ||
| 857 | } | ||
| 858 | @compileError("analysis should not reach here"); | ||
| 859 | } | ||
| 860 | |||
| 861 | const EnumWithTagValues = enum(u4) { | ||
| 862 | A = 1 << 0, | ||
| 863 | B = 1 << 1, | ||
| 864 | C = 1 << 2, | ||
| 865 | D = 1 << 3, | ||
| 866 | }; | ||
| 867 | test "enum with tag values don't require parens" { | ||
| 868 | expect(@enumToInt(EnumWithTagValues.C) == 0b0100); | ||
| 869 | } | ||
| 870 | |||
| 871 | test "enum with 1 field but explicit tag type should still have the tag type" { | ||
| 872 | const Enum = enum(u8) { | ||
| 873 | B = 2, | ||
| 874 | }; | ||
| 875 | comptime @import("std").testing.expect(@sizeOf(Enum) == @sizeOf(u8)); | ||
| 876 | } | ||
| 877 | |||
| 878 | test "empty extern enum with members" { | ||
| 879 | const E = extern enum { | ||
| 880 | A, | ||
| 881 | B, | ||
| 882 | C, | ||
| 883 | }; | ||
| 884 | expect(@sizeOf(E) == @sizeOf(c_int)); | ||
| 885 | } | ||
| 886 | |||
| 887 | test "tag name with assigned enum values" { | ||
| 888 | const LocalFoo = enum { | ||
| 889 | A = 1, | ||
| 890 | B = 0, | ||
| 891 | }; | ||
| 892 | var b = LocalFoo.B; | ||
| 893 | expect(mem.eql(u8, @tagName(b), "B")); | ||
| 894 | } | ||
test/stage1/behavior/enum_with_members.zig created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | const fmt = @import("std").fmt; | ||
| 4 | |||
| 5 | const ET = union(enum) { | ||
| 6 | SINT: i32, | ||
| 7 | UINT: u32, | ||
| 8 | |||
| 9 | pub fn print(a: *const ET, buf: []u8) anyerror!usize { | ||
| 10 | return switch (a.*) { | ||
| 11 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | ||
| 12 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | |||
| 17 | test "enum with members" { | ||
| 18 | const a = ET{ .SINT = -42 }; | ||
| 19 | const b = ET{ .UINT = 42 }; | ||
| 20 | var buf: [20]u8 = undefined; | ||
| 21 | |||
| 22 | expect((a.print(buf[0..]) catch unreachable) == 3); | ||
| 23 | expect(mem.eql(u8, buf[0..3], "-42")); | ||
| 24 | |||
| 25 | expect((b.print(buf[0..]) catch unreachable) == 2); | ||
| 26 | expect(mem.eql(u8, buf[0..2], "42")); | ||
| 27 | } | ||
test/stage1/behavior/error.zig created+337| ... | @@ -0,0 +1,337 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const expectError = std.testing.expectError; | ||
| 4 | const mem = std.mem; | ||
| 5 | const builtin = @import("builtin"); | ||
| 6 | |||
| 7 | pub fn foo() anyerror!i32 { | ||
| 8 | const x = try bar(); | ||
| 9 | return x + 1; | ||
| 10 | } | ||
| 11 | |||
| 12 | pub fn bar() anyerror!i32 { | ||
| 13 | return 13; | ||
| 14 | } | ||
| 15 | |||
| 16 | pub fn baz() anyerror!i32 { | ||
| 17 | const y = foo() catch 1234; | ||
| 18 | return y + 1; | ||
| 19 | } | ||
| 20 | |||
| 21 | test "error wrapping" { | ||
| 22 | expect((baz() catch unreachable) == 15); | ||
| 23 | } | ||
| 24 | |||
| 25 | fn gimmeItBroke() []const u8 { | ||
| 26 | return @errorName(error.ItBroke); | ||
| 27 | } | ||
| 28 | |||
| 29 | test "@errorName" { | ||
| 30 | expect(mem.eql(u8, @errorName(error.AnError), "AnError")); | ||
| 31 | expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); | ||
| 32 | } | ||
| 33 | |||
| 34 | test "error values" { | ||
| 35 | const a = @errorToInt(error.err1); | ||
| 36 | const b = @errorToInt(error.err2); | ||
| 37 | expect(a != b); | ||
| 38 | } | ||
| 39 | |||
| 40 | test "redefinition of error values allowed" { | ||
| 41 | shouldBeNotEqual(error.AnError, error.SecondError); | ||
| 42 | } | ||
| 43 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { | ||
| 44 | if (a == b) unreachable; | ||
| 45 | } | ||
| 46 | |||
| 47 | test "error binary operator" { | ||
| 48 | const a = errBinaryOperatorG(true) catch 3; | ||
| 49 | const b = errBinaryOperatorG(false) catch 3; | ||
| 50 | expect(a == 3); | ||
| 51 | expect(b == 10); | ||
| 52 | } | ||
| 53 | fn errBinaryOperatorG(x: bool) anyerror!isize { | ||
| 54 | return if (x) error.ItBroke else isize(10); | ||
| 55 | } | ||
| 56 | |||
| 57 | test "unwrap simple value from error" { | ||
| 58 | const i = unwrapSimpleValueFromErrorDo() catch unreachable; | ||
| 59 | expect(i == 13); | ||
| 60 | } | ||
| 61 | fn unwrapSimpleValueFromErrorDo() anyerror!isize { | ||
| 62 | return 13; | ||
| 63 | } | ||
| 64 | |||
| 65 | test "error return in assignment" { | ||
| 66 | doErrReturnInAssignment() catch unreachable; | ||
| 67 | } | ||
| 68 | |||
| 69 | fn doErrReturnInAssignment() anyerror!void { | ||
| 70 | var x: i32 = undefined; | ||
| 71 | x = try makeANonErr(); | ||
| 72 | } | ||
| 73 | |||
| 74 | fn makeANonErr() anyerror!i32 { | ||
| 75 | return 1; | ||
| 76 | } | ||
| 77 | |||
| 78 | test "error union type " { | ||
| 79 | testErrorUnionType(); | ||
| 80 | comptime testErrorUnionType(); | ||
| 81 | } | ||
| 82 | |||
| 83 | fn testErrorUnionType() void { | ||
| 84 | const x: anyerror!i32 = 1234; | ||
| 85 | if (x) |value| expect(value == 1234) else |_| unreachable; | ||
| 86 | expect(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion); | ||
| 87 | expect(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); | ||
| 88 | expect(@typeOf(x).ErrorSet == anyerror); | ||
| 89 | } | ||
| 90 | |||
| 91 | test "error set type" { | ||
| 92 | testErrorSetType(); | ||
| 93 | comptime testErrorSetType(); | ||
| 94 | } | ||
| 95 | |||
| 96 | const MyErrSet = error{ | ||
| 97 | OutOfMemory, | ||
| 98 | FileNotFound, | ||
| 99 | }; | ||
| 100 | |||
| 101 | fn testErrorSetType() void { | ||
| 102 | expect(@memberCount(MyErrSet) == 2); | ||
| 103 | |||
| 104 | const a: MyErrSet!i32 = 5678; | ||
| 105 | const b: MyErrSet!i32 = MyErrSet.OutOfMemory; | ||
| 106 | |||
| 107 | if (a) |value| expect(value == 5678) else |err| switch (err) { | ||
| 108 | error.OutOfMemory => unreachable, | ||
| 109 | error.FileNotFound => unreachable, | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | test "explicit error set cast" { | ||
| 114 | testExplicitErrorSetCast(Set1.A); | ||
| 115 | comptime testExplicitErrorSetCast(Set1.A); | ||
| 116 | } | ||
| 117 | |||
| 118 | const Set1 = error{ | ||
| 119 | A, | ||
| 120 | B, | ||
| 121 | }; | ||
| 122 | const Set2 = error{ | ||
| 123 | A, | ||
| 124 | C, | ||
| 125 | }; | ||
| 126 | |||
| 127 | fn testExplicitErrorSetCast(set1: Set1) void { | ||
| 128 | var x = @errSetCast(Set2, set1); | ||
| 129 | var y = @errSetCast(Set1, x); | ||
| 130 | expect(y == error.A); | ||
| 131 | } | ||
| 132 | |||
| 133 | test "comptime test error for empty error set" { | ||
| 134 | testComptimeTestErrorEmptySet(1234); | ||
| 135 | comptime testComptimeTestErrorEmptySet(1234); | ||
| 136 | } | ||
| 137 | |||
| 138 | const EmptyErrorSet = error{}; | ||
| 139 | |||
| 140 | fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { | ||
| 141 | if (x) |v| expect(v == 1234) else |err| @compileError("bad"); | ||
| 142 | } | ||
| 143 | |||
| 144 | test "syntax: optional operator in front of error union operator" { | ||
| 145 | comptime { | ||
| 146 | expect(?(anyerror!i32) == ?(anyerror!i32)); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | test "comptime err to int of error set with only 1 possible value" { | ||
| 151 | testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | ||
| 152 | comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | ||
| 153 | } | ||
| 154 | fn testErrToIntWithOnePossibleValue( | ||
| 155 | x: error{A}, | ||
| 156 | comptime value: u32, | ||
| 157 | ) void { | ||
| 158 | if (@errorToInt(x) != value) { | ||
| 159 | @compileError("bad"); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | test "error union peer type resolution" { | ||
| 164 | testErrorUnionPeerTypeResolution(1); | ||
| 165 | } | ||
| 166 | |||
| 167 | fn testErrorUnionPeerTypeResolution(x: i32) void { | ||
| 168 | const y = switch (x) { | ||
| 169 | 1 => bar_1(), | ||
| 170 | 2 => baz_1(), | ||
| 171 | else => quux_1(), | ||
| 172 | }; | ||
| 173 | if (y) |_| { | ||
| 174 | @panic("expected error"); | ||
| 175 | } else |e| { | ||
| 176 | expect(e == error.A); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | fn bar_1() anyerror { | ||
| 181 | return error.A; | ||
| 182 | } | ||
| 183 | |||
| 184 | fn baz_1() !i32 { | ||
| 185 | return error.B; | ||
| 186 | } | ||
| 187 | |||
| 188 | fn quux_1() !i32 { | ||
| 189 | return error.C; | ||
| 190 | } | ||
| 191 | |||
| 192 | test "error: fn returning empty error set can be passed as fn returning any error" { | ||
| 193 | entry(); | ||
| 194 | comptime entry(); | ||
| 195 | } | ||
| 196 | |||
| 197 | fn entry() void { | ||
| 198 | foo2(bar2); | ||
| 199 | } | ||
| 200 | |||
| 201 | fn foo2(f: fn () anyerror!void) void { | ||
| 202 | const x = f(); | ||
| 203 | } | ||
| 204 | |||
| 205 | fn bar2() (error{}!void) {} | ||
| 206 | |||
| 207 | test "error: Zero sized error set returned with value payload crash" { | ||
| 208 | _ = foo3(0); | ||
| 209 | _ = comptime foo3(0); | ||
| 210 | } | ||
| 211 | |||
| 212 | const Error = error{}; | ||
| 213 | fn foo3(b: usize) Error!usize { | ||
| 214 | return b; | ||
| 215 | } | ||
| 216 | |||
| 217 | test "error: Infer error set from literals" { | ||
| 218 | _ = nullLiteral("n") catch |err| handleErrors(err); | ||
| 219 | _ = floatLiteral("n") catch |err| handleErrors(err); | ||
| 220 | _ = intLiteral("n") catch |err| handleErrors(err); | ||
| 221 | _ = comptime nullLiteral("n") catch |err| handleErrors(err); | ||
| 222 | _ = comptime floatLiteral("n") catch |err| handleErrors(err); | ||
| 223 | _ = comptime intLiteral("n") catch |err| handleErrors(err); | ||
| 224 | } | ||
| 225 | |||
| 226 | fn handleErrors(err: var) noreturn { | ||
| 227 | switch (err) { | ||
| 228 | error.T => {}, | ||
| 229 | } | ||
| 230 | |||
| 231 | unreachable; | ||
| 232 | } | ||
| 233 | |||
| 234 | fn nullLiteral(str: []const u8) !?i64 { | ||
| 235 | if (str[0] == 'n') return null; | ||
| 236 | |||
| 237 | return error.T; | ||
| 238 | } | ||
| 239 | |||
| 240 | fn floatLiteral(str: []const u8) !?f64 { | ||
| 241 | if (str[0] == 'n') return 1.0; | ||
| 242 | |||
| 243 | return error.T; | ||
| 244 | } | ||
| 245 | |||
| 246 | fn intLiteral(str: []const u8) !?i64 { | ||
| 247 | if (str[0] == 'n') return 1; | ||
| 248 | |||
| 249 | return error.T; | ||
| 250 | } | ||
| 251 | |||
| 252 | test "nested error union function call in optional unwrap" { | ||
| 253 | const S = struct { | ||
| 254 | const Foo = struct { | ||
| 255 | a: i32, | ||
| 256 | }; | ||
| 257 | |||
| 258 | fn errorable() !i32 { | ||
| 259 | var x: Foo = (try getFoo()) orelse return error.Other; | ||
| 260 | return x.a; | ||
| 261 | } | ||
| 262 | |||
| 263 | fn errorable2() !i32 { | ||
| 264 | var x: Foo = (try getFoo2()) orelse return error.Other; | ||
| 265 | return x.a; | ||
| 266 | } | ||
| 267 | |||
| 268 | fn errorable3() !i32 { | ||
| 269 | var x: Foo = (try getFoo3()) orelse return error.Other; | ||
| 270 | return x.a; | ||
| 271 | } | ||
| 272 | |||
| 273 | fn getFoo() anyerror!?Foo { | ||
| 274 | return Foo{ .a = 1234 }; | ||
| 275 | } | ||
| 276 | |||
| 277 | fn getFoo2() anyerror!?Foo { | ||
| 278 | return error.Failure; | ||
| 279 | } | ||
| 280 | |||
| 281 | fn getFoo3() anyerror!?Foo { | ||
| 282 | return null; | ||
| 283 | } | ||
| 284 | }; | ||
| 285 | expect((try S.errorable()) == 1234); | ||
| 286 | expectError(error.Failure, S.errorable2()); | ||
| 287 | expectError(error.Other, S.errorable3()); | ||
| 288 | comptime { | ||
| 289 | expect((try S.errorable()) == 1234); | ||
| 290 | expectError(error.Failure, S.errorable2()); | ||
| 291 | expectError(error.Other, S.errorable3()); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | test "widen cast integer payload of error union function call" { | ||
| 296 | const S = struct { | ||
| 297 | fn errorable() !u64 { | ||
| 298 | var x = u64(try number()); | ||
| 299 | return x; | ||
| 300 | } | ||
| 301 | |||
| 302 | fn number() anyerror!u32 { | ||
| 303 | return 1234; | ||
| 304 | } | ||
| 305 | }; | ||
| 306 | expect((try S.errorable()) == 1234); | ||
| 307 | } | ||
| 308 | |||
| 309 | test "return function call to error set from error union function" { | ||
| 310 | const S = struct { | ||
| 311 | fn errorable() anyerror!i32 { | ||
| 312 | return fail(); | ||
| 313 | } | ||
| 314 | |||
| 315 | fn fail() anyerror { | ||
| 316 | return error.Failure; | ||
| 317 | } | ||
| 318 | }; | ||
| 319 | expectError(error.Failure, S.errorable()); | ||
| 320 | comptime expectError(error.Failure, S.errorable()); | ||
| 321 | } | ||
| 322 | |||
| 323 | test "optional error set is the same size as error set" { | ||
| 324 | comptime expect(@sizeOf(?anyerror) == @sizeOf(anyerror)); | ||
| 325 | const S = struct { | ||
| 326 | fn returnsOptErrSet() ?anyerror { | ||
| 327 | return null; | ||
| 328 | } | ||
| 329 | }; | ||
| 330 | expect(S.returnsOptErrSet() == null); | ||
| 331 | comptime expect(S.returnsOptErrSet() == null); | ||
| 332 | } | ||
| 333 | |||
| 334 | test "debug info for optional error set" { | ||
| 335 | const SomeError = error{Hello}; | ||
| 336 | var a_local_variable: ?SomeError = null; | ||
| 337 | } | ||
test/stage1/behavior/eval.zig created+778| ... | @@ -0,0 +1,778 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | |||
| 5 | test "compile time recursion" { | ||
| 6 | expect(some_data.len == 21); | ||
| 7 | } | ||
| 8 | var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined; | ||
| 9 | fn fibonacci(x: i32) i32 { | ||
| 10 | if (x <= 1) return 1; | ||
| 11 | return fibonacci(x - 1) + fibonacci(x - 2); | ||
| 12 | } | ||
| 13 | |||
| 14 | fn unwrapAndAddOne(blah: ?i32) i32 { | ||
| 15 | return blah.? + 1; | ||
| 16 | } | ||
| 17 | const should_be_1235 = unwrapAndAddOne(1234); | ||
| 18 | test "static add one" { | ||
| 19 | expect(should_be_1235 == 1235); | ||
| 20 | } | ||
| 21 | |||
| 22 | test "inlined loop" { | ||
| 23 | comptime var i = 0; | ||
| 24 | comptime var sum = 0; | ||
| 25 | inline while (i <= 5) : (i += 1) | ||
| 26 | sum += i; | ||
| 27 | expect(sum == 15); | ||
| 28 | } | ||
| 29 | |||
| 30 | fn gimme1or2(comptime a: bool) i32 { | ||
| 31 | const x: i32 = 1; | ||
| 32 | const y: i32 = 2; | ||
| 33 | comptime var z: i32 = if (a) x else y; | ||
| 34 | return z; | ||
| 35 | } | ||
| 36 | test "inline variable gets result of const if" { | ||
| 37 | expect(gimme1or2(true) == 1); | ||
| 38 | expect(gimme1or2(false) == 2); | ||
| 39 | } | ||
| 40 | |||
| 41 | test "static function evaluation" { | ||
| 42 | expect(statically_added_number == 3); | ||
| 43 | } | ||
| 44 | const statically_added_number = staticAdd(1, 2); | ||
| 45 | fn staticAdd(a: i32, b: i32) i32 { | ||
| 46 | return a + b; | ||
| 47 | } | ||
| 48 | |||
| 49 | test "const expr eval on single expr blocks" { | ||
| 50 | expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3); | ||
| 51 | comptime expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3); | ||
| 52 | } | ||
| 53 | |||
| 54 | fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { | ||
| 55 | const literal = 3; | ||
| 56 | |||
| 57 | const result = if (b) b: { | ||
| 58 | break :b literal; | ||
| 59 | } else b: { | ||
| 60 | break :b x; | ||
| 61 | }; | ||
| 62 | |||
| 63 | return result; | ||
| 64 | } | ||
| 65 | |||
| 66 | test "statically initialized list" { | ||
| 67 | expect(static_point_list[0].x == 1); | ||
| 68 | expect(static_point_list[0].y == 2); | ||
| 69 | expect(static_point_list[1].x == 3); | ||
| 70 | expect(static_point_list[1].y == 4); | ||
| 71 | } | ||
| 72 | const Point = struct { | ||
| 73 | x: i32, | ||
| 74 | y: i32, | ||
| 75 | }; | ||
| 76 | const static_point_list = []Point{ | ||
| 77 | makePoint(1, 2), | ||
| 78 | makePoint(3, 4), | ||
| 79 | }; | ||
| 80 | fn makePoint(x: i32, y: i32) Point { | ||
| 81 | return Point{ | ||
| 82 | .x = x, | ||
| 83 | .y = y, | ||
| 84 | }; | ||
| 85 | } | ||
| 86 | |||
| 87 | test "static eval list init" { | ||
| 88 | expect(static_vec3.data[2] == 1.0); | ||
| 89 | expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0); | ||
| 90 | } | ||
| 91 | const static_vec3 = vec3(0.0, 0.0, 1.0); | ||
| 92 | pub const Vec3 = struct { | ||
| 93 | data: [3]f32, | ||
| 94 | }; | ||
| 95 | pub fn vec3(x: f32, y: f32, z: f32) Vec3 { | ||
| 96 | return Vec3{ .data = []f32{ | ||
| 97 | x, | ||
| 98 | y, | ||
| 99 | z, | ||
| 100 | } }; | ||
| 101 | } | ||
| 102 | |||
| 103 | test "constant expressions" { | ||
| 104 | var array: [array_size]u8 = undefined; | ||
| 105 | expect(@sizeOf(@typeOf(array)) == 20); | ||
| 106 | } | ||
| 107 | const array_size: u8 = 20; | ||
| 108 | |||
| 109 | test "constant struct with negation" { | ||
| 110 | expect(vertices[0].x == -0.6); | ||
| 111 | } | ||
| 112 | const Vertex = struct { | ||
| 113 | x: f32, | ||
| 114 | y: f32, | ||
| 115 | r: f32, | ||
| 116 | g: f32, | ||
| 117 | b: f32, | ||
| 118 | }; | ||
| 119 | const vertices = []Vertex{ | ||
| 120 | Vertex{ | ||
| 121 | .x = -0.6, | ||
| 122 | .y = -0.4, | ||
| 123 | .r = 1.0, | ||
| 124 | .g = 0.0, | ||
| 125 | .b = 0.0, | ||
| 126 | }, | ||
| 127 | Vertex{ | ||
| 128 | .x = 0.6, | ||
| 129 | .y = -0.4, | ||
| 130 | .r = 0.0, | ||
| 131 | .g = 1.0, | ||
| 132 | .b = 0.0, | ||
| 133 | }, | ||
| 134 | Vertex{ | ||
| 135 | .x = 0.0, | ||
| 136 | .y = 0.6, | ||
| 137 | .r = 0.0, | ||
| 138 | .g = 0.0, | ||
| 139 | .b = 1.0, | ||
| 140 | }, | ||
| 141 | }; | ||
| 142 | |||
| 143 | test "statically initialized struct" { | ||
| 144 | st_init_str_foo.x += 1; | ||
| 145 | expect(st_init_str_foo.x == 14); | ||
| 146 | } | ||
| 147 | const StInitStrFoo = struct { | ||
| 148 | x: i32, | ||
| 149 | y: bool, | ||
| 150 | }; | ||
| 151 | var st_init_str_foo = StInitStrFoo{ | ||
| 152 | .x = 13, | ||
| 153 | .y = true, | ||
| 154 | }; | ||
| 155 | |||
| 156 | test "statically initalized array literal" { | ||
| 157 | const y: [4]u8 = st_init_arr_lit_x; | ||
| 158 | expect(y[3] == 4); | ||
| 159 | } | ||
| 160 | const st_init_arr_lit_x = []u8{ | ||
| 161 | 1, | ||
| 162 | 2, | ||
| 163 | 3, | ||
| 164 | 4, | ||
| 165 | }; | ||
| 166 | |||
| 167 | test "const slice" { | ||
| 168 | comptime { | ||
| 169 | const a = "1234567890"; | ||
| 170 | expect(a.len == 10); | ||
| 171 | const b = a[1..2]; | ||
| 172 | expect(b.len == 1); | ||
| 173 | expect(b[0] == '2'); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | test "try to trick eval with runtime if" { | ||
| 178 | expect(testTryToTrickEvalWithRuntimeIf(true) == 10); | ||
| 179 | } | ||
| 180 | |||
| 181 | fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { | ||
| 182 | comptime var i: usize = 0; | ||
| 183 | inline while (i < 10) : (i += 1) { | ||
| 184 | const result = if (b) false else true; | ||
| 185 | } | ||
| 186 | comptime { | ||
| 187 | return i; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | fn max(comptime T: type, a: T, b: T) T { | ||
| 192 | if (T == bool) { | ||
| 193 | return a or b; | ||
| 194 | } else if (a > b) { | ||
| 195 | return a; | ||
| 196 | } else { | ||
| 197 | return b; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | fn letsTryToCompareBools(a: bool, b: bool) bool { | ||
| 201 | return max(bool, a, b); | ||
| 202 | } | ||
| 203 | test "inlined block and runtime block phi" { | ||
| 204 | expect(letsTryToCompareBools(true, true)); | ||
| 205 | expect(letsTryToCompareBools(true, false)); | ||
| 206 | expect(letsTryToCompareBools(false, true)); | ||
| 207 | expect(!letsTryToCompareBools(false, false)); | ||
| 208 | |||
| 209 | comptime { | ||
| 210 | expect(letsTryToCompareBools(true, true)); | ||
| 211 | expect(letsTryToCompareBools(true, false)); | ||
| 212 | expect(letsTryToCompareBools(false, true)); | ||
| 213 | expect(!letsTryToCompareBools(false, false)); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | const CmdFn = struct { | ||
| 218 | name: []const u8, | ||
| 219 | func: fn (i32) i32, | ||
| 220 | }; | ||
| 221 | |||
| 222 | const cmd_fns = []CmdFn{ | ||
| 223 | CmdFn{ | ||
| 224 | .name = "one", | ||
| 225 | .func = one, | ||
| 226 | }, | ||
| 227 | CmdFn{ | ||
| 228 | .name = "two", | ||
| 229 | .func = two, | ||
| 230 | }, | ||
| 231 | CmdFn{ | ||
| 232 | .name = "three", | ||
| 233 | .func = three, | ||
| 234 | }, | ||
| 235 | }; | ||
| 236 | fn one(value: i32) i32 { | ||
| 237 | return value + 1; | ||
| 238 | } | ||
| 239 | fn two(value: i32) i32 { | ||
| 240 | return value + 2; | ||
| 241 | } | ||
| 242 | fn three(value: i32) i32 { | ||
| 243 | return value + 3; | ||
| 244 | } | ||
| 245 | |||
| 246 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { | ||
| 247 | var result: i32 = start_value; | ||
| 248 | comptime var i = 0; | ||
| 249 | inline while (i < cmd_fns.len) : (i += 1) { | ||
| 250 | if (cmd_fns[i].name[0] == prefix_char) { | ||
| 251 | result = cmd_fns[i].func(result); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | return result; | ||
| 255 | } | ||
| 256 | |||
| 257 | test "comptime iterate over fn ptr list" { | ||
| 258 | expect(performFn('t', 1) == 6); | ||
| 259 | expect(performFn('o', 0) == 1); | ||
| 260 | expect(performFn('w', 99) == 99); | ||
| 261 | } | ||
| 262 | |||
| 263 | test "eval @setRuntimeSafety at compile-time" { | ||
| 264 | const result = comptime fnWithSetRuntimeSafety(); | ||
| 265 | expect(result == 1234); | ||
| 266 | } | ||
| 267 | |||
| 268 | fn fnWithSetRuntimeSafety() i32 { | ||
| 269 | @setRuntimeSafety(true); | ||
| 270 | return 1234; | ||
| 271 | } | ||
| 272 | |||
| 273 | test "eval @setFloatMode at compile-time" { | ||
| 274 | const result = comptime fnWithFloatMode(); | ||
| 275 | expect(result == 1234.0); | ||
| 276 | } | ||
| 277 | |||
| 278 | fn fnWithFloatMode() f32 { | ||
| 279 | @setFloatMode(builtin.FloatMode.Strict); | ||
| 280 | return 1234.0; | ||
| 281 | } | ||
| 282 | |||
| 283 | const SimpleStruct = struct { | ||
| 284 | field: i32, | ||
| 285 | |||
| 286 | fn method(self: *const SimpleStruct) i32 { | ||
| 287 | return self.field + 3; | ||
| 288 | } | ||
| 289 | }; | ||
| 290 | |||
| 291 | var simple_struct = SimpleStruct{ .field = 1234 }; | ||
| 292 | |||
| 293 | const bound_fn = simple_struct.method; | ||
| 294 | |||
| 295 | test "call method on bound fn referring to var instance" { | ||
| 296 | expect(bound_fn() == 1237); | ||
| 297 | } | ||
| 298 | |||
| 299 | test "ptr to local array argument at comptime" { | ||
| 300 | comptime { | ||
| 301 | var bytes: [10]u8 = undefined; | ||
| 302 | modifySomeBytes(bytes[0..]); | ||
| 303 | expect(bytes[0] == 'a'); | ||
| 304 | expect(bytes[9] == 'b'); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | fn modifySomeBytes(bytes: []u8) void { | ||
| 309 | bytes[0] = 'a'; | ||
| 310 | bytes[9] = 'b'; | ||
| 311 | } | ||
| 312 | |||
| 313 | test "comparisons 0 <= uint and 0 > uint should be comptime" { | ||
| 314 | testCompTimeUIntComparisons(1234); | ||
| 315 | } | ||
| 316 | fn testCompTimeUIntComparisons(x: u32) void { | ||
| 317 | if (!(0 <= x)) { | ||
| 318 | @compileError("this condition should be comptime known"); | ||
| 319 | } | ||
| 320 | if (0 > x) { | ||
| 321 | @compileError("this condition should be comptime known"); | ||
| 322 | } | ||
| 323 | if (!(x >= 0)) { | ||
| 324 | @compileError("this condition should be comptime known"); | ||
| 325 | } | ||
| 326 | if (x < 0) { | ||
| 327 | @compileError("this condition should be comptime known"); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | test "const ptr to variable data changes at runtime" { | ||
| 332 | expect(foo_ref.name[0] == 'a'); | ||
| 333 | foo_ref.name = "b"; | ||
| 334 | expect(foo_ref.name[0] == 'b'); | ||
| 335 | } | ||
| 336 | |||
| 337 | const Foo = struct { | ||
| 338 | name: []const u8, | ||
| 339 | }; | ||
| 340 | |||
| 341 | var foo_contents = Foo{ .name = "a" }; | ||
| 342 | const foo_ref = &foo_contents; | ||
| 343 | |||
| 344 | test "create global array with for loop" { | ||
| 345 | expect(global_array[5] == 5 * 5); | ||
| 346 | expect(global_array[9] == 9 * 9); | ||
| 347 | } | ||
| 348 | |||
| 349 | const global_array = x: { | ||
| 350 | var result: [10]usize = undefined; | ||
| 351 | for (result) |*item, index| { | ||
| 352 | item.* = index * index; | ||
| 353 | } | ||
| 354 | break :x result; | ||
| 355 | }; | ||
| 356 | |||
| 357 | test "compile-time downcast when the bits fit" { | ||
| 358 | comptime { | ||
| 359 | const spartan_count: u16 = 255; | ||
| 360 | const byte = @intCast(u8, spartan_count); | ||
| 361 | expect(byte == 255); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | const hi1 = "hi"; | ||
| 366 | const hi2 = hi1; | ||
| 367 | test "const global shares pointer with other same one" { | ||
| 368 | assertEqualPtrs(&hi1[0], &hi2[0]); | ||
| 369 | comptime expect(&hi1[0] == &hi2[0]); | ||
| 370 | } | ||
| 371 | fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void { | ||
| 372 | expect(ptr1 == ptr2); | ||
| 373 | } | ||
| 374 | |||
| 375 | test "@setEvalBranchQuota" { | ||
| 376 | comptime { | ||
| 377 | // 1001 for the loop and then 1 more for the expect fn call | ||
| 378 | @setEvalBranchQuota(1002); | ||
| 379 | var i = 0; | ||
| 380 | var sum = 0; | ||
| 381 | while (i < 1001) : (i += 1) { | ||
| 382 | sum += i; | ||
| 383 | } | ||
| 384 | expect(sum == 500500); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | // TODO test "float literal at compile time not lossy" { | ||
| 389 | // TODO expect(16777216.0 + 1.0 == 16777217.0); | ||
| 390 | // TODO expect(9007199254740992.0 + 1.0 == 9007199254740993.0); | ||
| 391 | // TODO } | ||
| 392 | |||
| 393 | test "f32 at compile time is lossy" { | ||
| 394 | expect(f32(1 << 24) + 1 == 1 << 24); | ||
| 395 | } | ||
| 396 | |||
| 397 | test "f64 at compile time is lossy" { | ||
| 398 | expect(f64(1 << 53) + 1 == 1 << 53); | ||
| 399 | } | ||
| 400 | |||
| 401 | test "f128 at compile time is lossy" { | ||
| 402 | expect(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); | ||
| 403 | } | ||
| 404 | |||
| 405 | comptime { | ||
| 406 | expect(f128(1 << 113) == 10384593717069655257060992658440192); | ||
| 407 | } | ||
| 408 | |||
| 409 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { | ||
| 410 | return struct { | ||
| 411 | pub const Node = struct {}; | ||
| 412 | }; | ||
| 413 | } | ||
| 414 | |||
| 415 | test "string literal used as comptime slice is memoized" { | ||
| 416 | const a = "link"; | ||
| 417 | const b = "link"; | ||
| 418 | comptime expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); | ||
| 419 | comptime expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); | ||
| 420 | } | ||
| 421 | |||
| 422 | test "comptime slice of undefined pointer of length 0" { | ||
| 423 | const slice1 = ([*]i32)(undefined)[0..0]; | ||
| 424 | expect(slice1.len == 0); | ||
| 425 | const slice2 = ([*]i32)(undefined)[100..100]; | ||
| 426 | expect(slice2.len == 0); | ||
| 427 | } | ||
| 428 | |||
| 429 | fn copyWithPartialInline(s: []u32, b: []u8) void { | ||
| 430 | comptime var i: usize = 0; | ||
| 431 | inline while (i < 4) : (i += 1) { | ||
| 432 | s[i] = 0; | ||
| 433 | s[i] |= u32(b[i * 4 + 0]) << 24; | ||
| 434 | s[i] |= u32(b[i * 4 + 1]) << 16; | ||
| 435 | s[i] |= u32(b[i * 4 + 2]) << 8; | ||
| 436 | s[i] |= u32(b[i * 4 + 3]) << 0; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | test "binary math operator in partially inlined function" { | ||
| 441 | var s: [4]u32 = undefined; | ||
| 442 | var b: [16]u8 = undefined; | ||
| 443 | |||
| 444 | for (b) |*r, i| | ||
| 445 | r.* = @intCast(u8, i + 1); | ||
| 446 | |||
| 447 | copyWithPartialInline(s[0..], b[0..]); | ||
| 448 | expect(s[0] == 0x1020304); | ||
| 449 | expect(s[1] == 0x5060708); | ||
| 450 | expect(s[2] == 0x90a0b0c); | ||
| 451 | expect(s[3] == 0xd0e0f10); | ||
| 452 | } | ||
| 453 | |||
| 454 | test "comptime function with the same args is memoized" { | ||
| 455 | comptime { | ||
| 456 | expect(MakeType(i32) == MakeType(i32)); | ||
| 457 | expect(MakeType(i32) != MakeType(f64)); | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | fn MakeType(comptime T: type) type { | ||
| 462 | return struct { | ||
| 463 | field: T, | ||
| 464 | }; | ||
| 465 | } | ||
| 466 | |||
| 467 | test "comptime function with mutable pointer is not memoized" { | ||
| 468 | comptime { | ||
| 469 | var x: i32 = 1; | ||
| 470 | const ptr = &x; | ||
| 471 | increment(ptr); | ||
| 472 | increment(ptr); | ||
| 473 | expect(x == 3); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | fn increment(value: *i32) void { | ||
| 478 | value.* += 1; | ||
| 479 | } | ||
| 480 | |||
| 481 | fn generateTable(comptime T: type) [1010]T { | ||
| 482 | var res: [1010]T = undefined; | ||
| 483 | var i: usize = 0; | ||
| 484 | while (i < 1010) : (i += 1) { | ||
| 485 | res[i] = @intCast(T, i); | ||
| 486 | } | ||
| 487 | return res; | ||
| 488 | } | ||
| 489 | |||
| 490 | fn doesAlotT(comptime T: type, value: usize) T { | ||
| 491 | @setEvalBranchQuota(5000); | ||
| 492 | const table = comptime blk: { | ||
| 493 | break :blk generateTable(T); | ||
| 494 | }; | ||
| 495 | return table[value]; | ||
| 496 | } | ||
| 497 | |||
| 498 | test "@setEvalBranchQuota at same scope as generic function call" { | ||
| 499 | expect(doesAlotT(u32, 2) == 2); | ||
| 500 | } | ||
| 501 | |||
| 502 | test "comptime slice of slice preserves comptime var" { | ||
| 503 | comptime { | ||
| 504 | var buff: [10]u8 = undefined; | ||
| 505 | buff[0..][0..][0] = 1; | ||
| 506 | expect(buff[0..][0..][0] == 1); | ||
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | test "comptime slice of pointer preserves comptime var" { | ||
| 511 | comptime { | ||
| 512 | var buff: [10]u8 = undefined; | ||
| 513 | var a = buff[0..].ptr; | ||
| 514 | a[0..1][0] = 1; | ||
| 515 | expect(buff[0..][0..][0] == 1); | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | const SingleFieldStruct = struct { | ||
| 520 | x: i32, | ||
| 521 | |||
| 522 | fn read_x(self: *const SingleFieldStruct) i32 { | ||
| 523 | return self.x; | ||
| 524 | } | ||
| 525 | }; | ||
| 526 | test "const ptr to comptime mutable data is not memoized" { | ||
| 527 | comptime { | ||
| 528 | var foo = SingleFieldStruct{ .x = 1 }; | ||
| 529 | expect(foo.read_x() == 1); | ||
| 530 | foo.x = 2; | ||
| 531 | expect(foo.read_x() == 2); | ||
| 532 | } | ||
| 533 | } | ||
| 534 | |||
| 535 | test "array concat of slices gives slice" { | ||
| 536 | comptime { | ||
| 537 | var a: []const u8 = "aoeu"; | ||
| 538 | var b: []const u8 = "asdf"; | ||
| 539 | const c = a ++ b; | ||
| 540 | expect(std.mem.eql(u8, c, "aoeuasdf")); | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 544 | test "comptime shlWithOverflow" { | ||
| 545 | const ct_shifted: u64 = comptime amt: { | ||
| 546 | var amt = u64(0); | ||
| 547 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | ||
| 548 | break :amt amt; | ||
| 549 | }; | ||
| 550 | |||
| 551 | const rt_shifted: u64 = amt: { | ||
| 552 | var amt = u64(0); | ||
| 553 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | ||
| 554 | break :amt amt; | ||
| 555 | }; | ||
| 556 | |||
| 557 | expect(ct_shifted == rt_shifted); | ||
| 558 | } | ||
| 559 | |||
| 560 | test "runtime 128 bit integer division" { | ||
| 561 | var a: u128 = 152313999999999991610955792383; | ||
| 562 | var b: u128 = 10000000000000000000; | ||
| 563 | var c = a / b; | ||
| 564 | expect(c == 15231399999); | ||
| 565 | } | ||
| 566 | |||
| 567 | pub const Info = struct { | ||
| 568 | version: u8, | ||
| 569 | }; | ||
| 570 | |||
| 571 | pub const diamond_info = Info{ .version = 0 }; | ||
| 572 | |||
| 573 | test "comptime modification of const struct field" { | ||
| 574 | comptime { | ||
| 575 | var res = diamond_info; | ||
| 576 | res.version = 1; | ||
| 577 | expect(diamond_info.version == 0); | ||
| 578 | expect(res.version == 1); | ||
| 579 | } | ||
| 580 | } | ||
| 581 | |||
| 582 | test "pointer to type" { | ||
| 583 | comptime { | ||
| 584 | var T: type = i32; | ||
| 585 | expect(T == i32); | ||
| 586 | var ptr = &T; | ||
| 587 | expect(@typeOf(ptr) == *type); | ||
| 588 | ptr.* = f32; | ||
| 589 | expect(T == f32); | ||
| 590 | expect(*T == *f32); | ||
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | test "slice of type" { | ||
| 595 | comptime { | ||
| 596 | var types_array = []type{ i32, f64, type }; | ||
| 597 | for (types_array) |T, i| { | ||
| 598 | switch (i) { | ||
| 599 | 0 => expect(T == i32), | ||
| 600 | 1 => expect(T == f64), | ||
| 601 | 2 => expect(T == type), | ||
| 602 | else => unreachable, | ||
| 603 | } | ||
| 604 | } | ||
| 605 | for (types_array[0..]) |T, i| { | ||
| 606 | switch (i) { | ||
| 607 | 0 => expect(T == i32), | ||
| 608 | 1 => expect(T == f64), | ||
| 609 | 2 => expect(T == type), | ||
| 610 | else => unreachable, | ||
| 611 | } | ||
| 612 | } | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | const Wrapper = struct { | ||
| 617 | T: type, | ||
| 618 | }; | ||
| 619 | |||
| 620 | fn wrap(comptime T: type) Wrapper { | ||
| 621 | return Wrapper{ .T = T }; | ||
| 622 | } | ||
| 623 | |||
| 624 | test "function which returns struct with type field causes implicit comptime" { | ||
| 625 | const ty = wrap(i32).T; | ||
| 626 | expect(ty == i32); | ||
| 627 | } | ||
| 628 | |||
| 629 | test "call method with comptime pass-by-non-copying-value self parameter" { | ||
| 630 | const S = struct { | ||
| 631 | a: u8, | ||
| 632 | |||
| 633 | fn b(comptime s: @This()) u8 { | ||
| 634 | return s.a; | ||
| 635 | } | ||
| 636 | }; | ||
| 637 | |||
| 638 | const s = S{ .a = 2 }; | ||
| 639 | var b = s.b(); | ||
| 640 | expect(b == 2); | ||
| 641 | } | ||
| 642 | |||
| 643 | test "@tagName of @typeId" { | ||
| 644 | const str = @tagName(@typeId(u8)); | ||
| 645 | expect(std.mem.eql(u8, str, "Int")); | ||
| 646 | } | ||
| 647 | |||
| 648 | test "setting backward branch quota just before a generic fn call" { | ||
| 649 | @setEvalBranchQuota(1001); | ||
| 650 | loopNTimes(1001); | ||
| 651 | } | ||
| 652 | |||
| 653 | fn loopNTimes(comptime n: usize) void { | ||
| 654 | comptime var i = 0; | ||
| 655 | inline while (i < n) : (i += 1) {} | ||
| 656 | } | ||
| 657 | |||
| 658 | test "variable inside inline loop that has different types on different iterations" { | ||
| 659 | testVarInsideInlineLoop(true, u32(42)); | ||
| 660 | } | ||
| 661 | |||
| 662 | fn testVarInsideInlineLoop(args: ...) void { | ||
| 663 | comptime var i = 0; | ||
| 664 | inline while (i < args.len) : (i += 1) { | ||
| 665 | const x = args[i]; | ||
| 666 | if (i == 0) expect(x); | ||
| 667 | if (i == 1) expect(x == 42); | ||
| 668 | } | ||
| 669 | } | ||
| 670 | |||
| 671 | test "inline for with same type but different values" { | ||
| 672 | var res: usize = 0; | ||
| 673 | inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| { | ||
| 674 | var a: T = undefined; | ||
| 675 | res += a.len; | ||
| 676 | } | ||
| 677 | expect(res == 5); | ||
| 678 | } | ||
| 679 | |||
| 680 | test "refer to the type of a generic function" { | ||
| 681 | const Func = fn (type) void; | ||
| 682 | const f: Func = doNothingWithType; | ||
| 683 | f(i32); | ||
| 684 | } | ||
| 685 | |||
| 686 | fn doNothingWithType(comptime T: type) void {} | ||
| 687 | |||
| 688 | test "zero extend from u0 to u1" { | ||
| 689 | var zero_u0: u0 = 0; | ||
| 690 | var zero_u1: u1 = zero_u0; | ||
| 691 | expect(zero_u1 == 0); | ||
| 692 | } | ||
| 693 | |||
| 694 | test "bit shift a u1" { | ||
| 695 | var x: u1 = 1; | ||
| 696 | var y = x << 0; | ||
| 697 | expect(y == 1); | ||
| 698 | } | ||
| 699 | |||
| 700 | test "@bytesToslice on a packed struct" { | ||
| 701 | const F = packed struct { | ||
| 702 | a: u8, | ||
| 703 | }; | ||
| 704 | |||
| 705 | var b = [1]u8{9}; | ||
| 706 | var f = @bytesToSlice(F, b); | ||
| 707 | expect(f[0].a == 9); | ||
| 708 | } | ||
| 709 | |||
| 710 | test "comptime pointer cast array and then slice" { | ||
| 711 | const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; | ||
| 712 | |||
| 713 | const ptrA: [*]const u8 = @ptrCast([*]const u8, &array); | ||
| 714 | const sliceA: []const u8 = ptrA[0..2]; | ||
| 715 | |||
| 716 | const ptrB: [*]const u8 = &array; | ||
| 717 | const sliceB: []const u8 = ptrB[0..2]; | ||
| 718 | |||
| 719 | expect(sliceA[1] == 2); | ||
| 720 | expect(sliceB[1] == 2); | ||
| 721 | } | ||
| 722 | |||
| 723 | test "slice bounds in comptime concatenation" { | ||
| 724 | const bs = comptime blk: { | ||
| 725 | const b = c"........1........"; | ||
| 726 | break :blk b[8..9]; | ||
| 727 | }; | ||
| 728 | const str = "" ++ bs; | ||
| 729 | expect(str.len == 1); | ||
| 730 | expect(std.mem.eql(u8, str, "1")); | ||
| 731 | |||
| 732 | const str2 = bs ++ ""; | ||
| 733 | expect(str2.len == 1); | ||
| 734 | expect(std.mem.eql(u8, str2, "1")); | ||
| 735 | } | ||
| 736 | |||
| 737 | test "comptime bitwise operators" { | ||
| 738 | comptime { | ||
| 739 | expect(3 & 1 == 1); | ||
| 740 | expect(3 & -1 == 3); | ||
| 741 | expect(-3 & -1 == -3); | ||
| 742 | expect(3 | -1 == -1); | ||
| 743 | expect(-3 | -1 == -1); | ||
| 744 | expect(3 ^ -1 == -4); | ||
| 745 | expect(-3 ^ -1 == 2); | ||
| 746 | expect(~i8(-1) == 0); | ||
| 747 | expect(~i128(-1) == 0); | ||
| 748 | expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611); | ||
| 749 | expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); | ||
| 750 | expect(~u128(0) == 0xffffffffffffffffffffffffffffffff); | ||
| 751 | } | ||
| 752 | } | ||
| 753 | |||
| 754 | test "*align(1) u16 is the same as *align(1:0:2) u16" { | ||
| 755 | comptime { | ||
| 756 | expect(*align(1:0:2) u16 == *align(1) u16); | ||
| 757 | // TODO add parsing support for this syntax | ||
| 758 | //expect(*align(:0:2) u16 == *u16); | ||
| 759 | } | ||
| 760 | } | ||
| 761 | |||
| 762 | test "array concatenation forces comptime" { | ||
| 763 | var a = oneItem(3) ++ oneItem(4); | ||
| 764 | expect(std.mem.eql(i32, a, []i32{ 3, 4 })); | ||
| 765 | } | ||
| 766 | |||
| 767 | test "array multiplication forces comptime" { | ||
| 768 | var a = oneItem(3) ** scalar(2); | ||
| 769 | expect(std.mem.eql(i32, a, []i32{ 3, 3 })); | ||
| 770 | } | ||
| 771 | |||
| 772 | fn oneItem(x: i32) [1]i32 { | ||
| 773 | return []i32{x}; | ||
| 774 | } | ||
| 775 | |||
| 776 | fn scalar(x: u32) u32 { | ||
| 777 | return x; | ||
| 778 | } | ||
test/stage1/behavior/field_parent_ptr.zig created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "@fieldParentPtr non-first field" { | ||
| 4 | testParentFieldPtr(&foo.c); | ||
| 5 | comptime testParentFieldPtr(&foo.c); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "@fieldParentPtr first field" { | ||
| 9 | testParentFieldPtrFirst(&foo.a); | ||
| 10 | comptime testParentFieldPtrFirst(&foo.a); | ||
| 11 | } | ||
| 12 | |||
| 13 | const Foo = struct { | ||
| 14 | a: bool, | ||
| 15 | b: f32, | ||
| 16 | c: i32, | ||
| 17 | d: i32, | ||
| 18 | }; | ||
| 19 | |||
| 20 | const foo = Foo{ | ||
| 21 | .a = true, | ||
| 22 | .b = 0.123, | ||
| 23 | .c = 1234, | ||
| 24 | .d = -10, | ||
| 25 | }; | ||
| 26 | |||
| 27 | fn testParentFieldPtr(c: *const i32) void { | ||
| 28 | expect(c == &foo.c); | ||
| 29 | |||
| 30 | const base = @fieldParentPtr(Foo, "c", c); | ||
| 31 | expect(base == &foo); | ||
| 32 | expect(&base.c == c); | ||
| 33 | } | ||
| 34 | |||
| 35 | fn testParentFieldPtrFirst(a: *const bool) void { | ||
| 36 | expect(a == &foo.a); | ||
| 37 | |||
| 38 | const base = @fieldParentPtr(Foo, "a", a); | ||
| 39 | expect(base == &foo); | ||
| 40 | expect(&base.a == a); | ||
| 41 | } | ||
test/stage1/behavior/fn.zig created+208| ... | @@ -0,0 +1,208 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "params" { | ||
| 4 | expect(testParamsAdd(22, 11) == 33); | ||
| 5 | } | ||
| 6 | fn testParamsAdd(a: i32, b: i32) i32 { | ||
| 7 | return a + b; | ||
| 8 | } | ||
| 9 | |||
| 10 | test "local variables" { | ||
| 11 | testLocVars(2); | ||
| 12 | } | ||
| 13 | fn testLocVars(b: i32) void { | ||
| 14 | const a: i32 = 1; | ||
| 15 | if (a + b != 3) unreachable; | ||
| 16 | } | ||
| 17 | |||
| 18 | test "void parameters" { | ||
| 19 | voidFun(1, void{}, 2, {}); | ||
| 20 | } | ||
| 21 | fn voidFun(a: i32, b: void, c: i32, d: void) void { | ||
| 22 | const v = b; | ||
| 23 | const vv: void = if (a == 1) v else {}; | ||
| 24 | expect(a + c == 3); | ||
| 25 | return vv; | ||
| 26 | } | ||
| 27 | |||
| 28 | test "mutable local variables" { | ||
| 29 | var zero: i32 = 0; | ||
| 30 | expect(zero == 0); | ||
| 31 | |||
| 32 | var i = i32(0); | ||
| 33 | while (i != 3) { | ||
| 34 | i += 1; | ||
| 35 | } | ||
| 36 | expect(i == 3); | ||
| 37 | } | ||
| 38 | |||
| 39 | test "separate block scopes" { | ||
| 40 | { | ||
| 41 | const no_conflict: i32 = 5; | ||
| 42 | expect(no_conflict == 5); | ||
| 43 | } | ||
| 44 | |||
| 45 | const c = x: { | ||
| 46 | const no_conflict = i32(10); | ||
| 47 | break :x no_conflict; | ||
| 48 | }; | ||
| 49 | expect(c == 10); | ||
| 50 | } | ||
| 51 | |||
| 52 | test "call function with empty string" { | ||
| 53 | acceptsString(""); | ||
| 54 | } | ||
| 55 | |||
| 56 | fn acceptsString(foo: []u8) void {} | ||
| 57 | |||
| 58 | fn @"weird function name"() i32 { | ||
| 59 | return 1234; | ||
| 60 | } | ||
| 61 | test "weird function name" { | ||
| 62 | expect(@"weird function name"() == 1234); | ||
| 63 | } | ||
| 64 | |||
| 65 | test "implicit cast function unreachable return" { | ||
| 66 | wantsFnWithVoid(fnWithUnreachable); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn wantsFnWithVoid(f: fn () void) void {} | ||
| 70 | |||
| 71 | fn fnWithUnreachable() noreturn { | ||
| 72 | unreachable; | ||
| 73 | } | ||
| 74 | |||
| 75 | test "function pointers" { | ||
| 76 | const fns = []@typeOf(fn1){ | ||
| 77 | fn1, | ||
| 78 | fn2, | ||
| 79 | fn3, | ||
| 80 | fn4, | ||
| 81 | }; | ||
| 82 | for (fns) |f, i| { | ||
| 83 | expect(f() == @intCast(u32, i) + 5); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | fn fn1() u32 { | ||
| 87 | return 5; | ||
| 88 | } | ||
| 89 | fn fn2() u32 { | ||
| 90 | return 6; | ||
| 91 | } | ||
| 92 | fn fn3() u32 { | ||
| 93 | return 7; | ||
| 94 | } | ||
| 95 | fn fn4() u32 { | ||
| 96 | return 8; | ||
| 97 | } | ||
| 98 | |||
| 99 | test "inline function call" { | ||
| 100 | expect(@inlineCall(add, 3, 9) == 12); | ||
| 101 | } | ||
| 102 | |||
| 103 | fn add(a: i32, b: i32) i32 { | ||
| 104 | return a + b; | ||
| 105 | } | ||
| 106 | |||
| 107 | test "number literal as an argument" { | ||
| 108 | numberLiteralArg(3); | ||
| 109 | comptime numberLiteralArg(3); | ||
| 110 | } | ||
| 111 | |||
| 112 | fn numberLiteralArg(a: var) void { | ||
| 113 | expect(a == 3); | ||
| 114 | } | ||
| 115 | |||
| 116 | test "assign inline fn to const variable" { | ||
| 117 | const a = inlineFn; | ||
| 118 | a(); | ||
| 119 | } | ||
| 120 | |||
| 121 | inline fn inlineFn() void {} | ||
| 122 | |||
| 123 | test "pass by non-copying value" { | ||
| 124 | expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); | ||
| 125 | } | ||
| 126 | |||
| 127 | const Point = struct { | ||
| 128 | x: i32, | ||
| 129 | y: i32, | ||
| 130 | }; | ||
| 131 | |||
| 132 | fn addPointCoords(pt: Point) i32 { | ||
| 133 | return pt.x + pt.y; | ||
| 134 | } | ||
| 135 | |||
| 136 | test "pass by non-copying value through var arg" { | ||
| 137 | expect(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); | ||
| 138 | } | ||
| 139 | |||
| 140 | fn addPointCoordsVar(pt: var) i32 { | ||
| 141 | comptime expect(@typeOf(pt) == Point); | ||
| 142 | return pt.x + pt.y; | ||
| 143 | } | ||
| 144 | |||
| 145 | test "pass by non-copying value as method" { | ||
| 146 | var pt = Point2{ .x = 1, .y = 2 }; | ||
| 147 | expect(pt.addPointCoords() == 3); | ||
| 148 | } | ||
| 149 | |||
| 150 | const Point2 = struct { | ||
| 151 | x: i32, | ||
| 152 | y: i32, | ||
| 153 | |||
| 154 | fn addPointCoords(self: Point2) i32 { | ||
| 155 | return self.x + self.y; | ||
| 156 | } | ||
| 157 | }; | ||
| 158 | |||
| 159 | test "pass by non-copying value as method, which is generic" { | ||
| 160 | var pt = Point3{ .x = 1, .y = 2 }; | ||
| 161 | expect(pt.addPointCoords(i32) == 3); | ||
| 162 | } | ||
| 163 | |||
| 164 | const Point3 = struct { | ||
| 165 | x: i32, | ||
| 166 | y: i32, | ||
| 167 | |||
| 168 | fn addPointCoords(self: Point3, comptime T: type) i32 { | ||
| 169 | return self.x + self.y; | ||
| 170 | } | ||
| 171 | }; | ||
| 172 | |||
| 173 | test "pass by non-copying value as method, at comptime" { | ||
| 174 | comptime { | ||
| 175 | var pt = Point2{ .x = 1, .y = 2 }; | ||
| 176 | expect(pt.addPointCoords() == 3); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | fn outer(y: u32) fn (u32) u32 { | ||
| 181 | const Y = @typeOf(y); | ||
| 182 | const st = struct { | ||
| 183 | fn get(z: u32) u32 { | ||
| 184 | return z + @sizeOf(Y); | ||
| 185 | } | ||
| 186 | }; | ||
| 187 | return st.get; | ||
| 188 | } | ||
| 189 | |||
| 190 | test "return inner function which references comptime variable of outer function" { | ||
| 191 | var func = outer(10); | ||
| 192 | expect(func(3) == 7); | ||
| 193 | } | ||
| 194 | |||
| 195 | test "extern struct with stdcallcc fn pointer" { | ||
| 196 | const S = extern struct { | ||
| 197 | ptr: stdcallcc fn () i32, | ||
| 198 | |||
| 199 | stdcallcc fn foo() i32 { | ||
| 200 | return 1234; | ||
| 201 | } | ||
| 202 | }; | ||
| 203 | |||
| 204 | var s: S = undefined; | ||
| 205 | s.ptr = S.foo; | ||
| 206 | expect(s.ptr() == 1234); | ||
| 207 | } | ||
| 208 | |||
test/stage1/behavior/fn_in_struct_in_comptime.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | fn get_foo() fn (*u8) usize { | ||
| 4 | comptime { | ||
| 5 | return struct { | ||
| 6 | fn func(ptr: *u8) usize { | ||
| 7 | var u = @ptrToInt(ptr); | ||
| 8 | return u; | ||
| 9 | } | ||
| 10 | }.func; | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | test "define a function in an anonymous struct in comptime" { | ||
| 15 | const foo = get_foo(); | ||
| 16 | expect(foo(@intToPtr(*u8, 12345)) == 12345); | ||
| 17 | } | ||
test/stage1/behavior/for.zig created+106| ... | @@ -0,0 +1,106 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | test "continue in for loop" { | ||
| 6 | const array = []i32{ | ||
| 7 | 1, | ||
| 8 | 2, | ||
| 9 | 3, | ||
| 10 | 4, | ||
| 11 | 5, | ||
| 12 | }; | ||
| 13 | var sum: i32 = 0; | ||
| 14 | for (array) |x| { | ||
| 15 | sum += x; | ||
| 16 | if (x < 3) { | ||
| 17 | continue; | ||
| 18 | } | ||
| 19 | break; | ||
| 20 | } | ||
| 21 | if (sum != 6) unreachable; | ||
| 22 | } | ||
| 23 | |||
| 24 | test "for loop with pointer elem var" { | ||
| 25 | const source = "abcdefg"; | ||
| 26 | var target: [source.len]u8 = undefined; | ||
| 27 | mem.copy(u8, target[0..], source); | ||
| 28 | mangleString(target[0..]); | ||
| 29 | expect(mem.eql(u8, target, "bcdefgh")); | ||
| 30 | } | ||
| 31 | fn mangleString(s: []u8) void { | ||
| 32 | for (s) |*c| { | ||
| 33 | c.* += 1; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | test "basic for loop" { | ||
| 38 | const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; | ||
| 39 | |||
| 40 | var buffer: [expected_result.len]u8 = undefined; | ||
| 41 | var buf_index: usize = 0; | ||
| 42 | |||
| 43 | const array = []u8{ 9, 8, 7, 6 }; | ||
| 44 | for (array) |item| { | ||
| 45 | buffer[buf_index] = item; | ||
| 46 | buf_index += 1; | ||
| 47 | } | ||
| 48 | for (array) |item, index| { | ||
| 49 | buffer[buf_index] = @intCast(u8, index); | ||
| 50 | buf_index += 1; | ||
| 51 | } | ||
| 52 | const array_ptr = &array; | ||
| 53 | for (array_ptr) |item| { | ||
| 54 | buffer[buf_index] = item; | ||
| 55 | buf_index += 1; | ||
| 56 | } | ||
| 57 | for (array_ptr) |item, index| { | ||
| 58 | buffer[buf_index] = @intCast(u8, index); | ||
| 59 | buf_index += 1; | ||
| 60 | } | ||
| 61 | const unknown_size: []const u8 = array; | ||
| 62 | for (unknown_size) |item| { | ||
| 63 | buffer[buf_index] = item; | ||
| 64 | buf_index += 1; | ||
| 65 | } | ||
| 66 | for (unknown_size) |item, index| { | ||
| 67 | buffer[buf_index] = @intCast(u8, index); | ||
| 68 | buf_index += 1; | ||
| 69 | } | ||
| 70 | |||
| 71 | expect(mem.eql(u8, buffer[0..buf_index], expected_result)); | ||
| 72 | } | ||
| 73 | |||
| 74 | test "break from outer for loop" { | ||
| 75 | testBreakOuter(); | ||
| 76 | comptime testBreakOuter(); | ||
| 77 | } | ||
| 78 | |||
| 79 | fn testBreakOuter() void { | ||
| 80 | var array = "aoeu"; | ||
| 81 | var count: usize = 0; | ||
| 82 | outer: for (array) |_| { | ||
| 83 | for (array) |_| { | ||
| 84 | count += 1; | ||
| 85 | break :outer; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | expect(count == 1); | ||
| 89 | } | ||
| 90 | |||
| 91 | test "continue outer for loop" { | ||
| 92 | testContinueOuter(); | ||
| 93 | comptime testContinueOuter(); | ||
| 94 | } | ||
| 95 | |||
| 96 | fn testContinueOuter() void { | ||
| 97 | var array = "aoeu"; | ||
| 98 | var counter: usize = 0; | ||
| 99 | outer: for (array) |_| { | ||
| 100 | for (array) |_| { | ||
| 101 | counter += 1; | ||
| 102 | continue :outer; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | expect(counter == array.len); | ||
| 106 | } | ||
test/stage1/behavior/generics.zig created+151| ... | @@ -0,0 +1,151 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "simple generic fn" { | ||
| 4 | expect(max(i32, 3, -1) == 3); | ||
| 5 | expect(max(f32, 0.123, 0.456) == 0.456); | ||
| 6 | expect(add(2, 3) == 5); | ||
| 7 | } | ||
| 8 | |||
| 9 | fn max(comptime T: type, a: T, b: T) T { | ||
| 10 | return if (a > b) a else b; | ||
| 11 | } | ||
| 12 | |||
| 13 | fn add(comptime a: i32, b: i32) i32 { | ||
| 14 | return (comptime a) + b; | ||
| 15 | } | ||
| 16 | |||
| 17 | const the_max = max(u32, 1234, 5678); | ||
| 18 | test "compile time generic eval" { | ||
| 19 | expect(the_max == 5678); | ||
| 20 | } | ||
| 21 | |||
| 22 | fn gimmeTheBigOne(a: u32, b: u32) u32 { | ||
| 23 | return max(u32, a, b); | ||
| 24 | } | ||
| 25 | |||
| 26 | fn shouldCallSameInstance(a: u32, b: u32) u32 { | ||
| 27 | return max(u32, a, b); | ||
| 28 | } | ||
| 29 | |||
| 30 | fn sameButWithFloats(a: f64, b: f64) f64 { | ||
| 31 | return max(f64, a, b); | ||
| 32 | } | ||
| 33 | |||
| 34 | test "fn with comptime args" { | ||
| 35 | expect(gimmeTheBigOne(1234, 5678) == 5678); | ||
| 36 | expect(shouldCallSameInstance(34, 12) == 34); | ||
| 37 | expect(sameButWithFloats(0.43, 0.49) == 0.49); | ||
| 38 | } | ||
| 39 | |||
| 40 | test "var params" { | ||
| 41 | expect(max_i32(12, 34) == 34); | ||
| 42 | expect(max_f64(1.2, 3.4) == 3.4); | ||
| 43 | } | ||
| 44 | |||
| 45 | comptime { | ||
| 46 | expect(max_i32(12, 34) == 34); | ||
| 47 | expect(max_f64(1.2, 3.4) == 3.4); | ||
| 48 | } | ||
| 49 | |||
| 50 | fn max_var(a: var, b: var) @typeOf(a + b) { | ||
| 51 | return if (a > b) a else b; | ||
| 52 | } | ||
| 53 | |||
| 54 | fn max_i32(a: i32, b: i32) i32 { | ||
| 55 | return max_var(a, b); | ||
| 56 | } | ||
| 57 | |||
| 58 | fn max_f64(a: f64, b: f64) f64 { | ||
| 59 | return max_var(a, b); | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn List(comptime T: type) type { | ||
| 63 | return SmallList(T, 8); | ||
| 64 | } | ||
| 65 | |||
| 66 | pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { | ||
| 67 | return struct { | ||
| 68 | items: []T, | ||
| 69 | length: usize, | ||
| 70 | prealloc_items: [STATIC_SIZE]T, | ||
| 71 | }; | ||
| 72 | } | ||
| 73 | |||
| 74 | test "function with return type type" { | ||
| 75 | var list: List(i32) = undefined; | ||
| 76 | var list2: List(i32) = undefined; | ||
| 77 | list.length = 10; | ||
| 78 | list2.length = 10; | ||
| 79 | expect(list.prealloc_items.len == 8); | ||
| 80 | expect(list2.prealloc_items.len == 8); | ||
| 81 | } | ||
| 82 | |||
| 83 | test "generic struct" { | ||
| 84 | var a1 = GenNode(i32){ | ||
| 85 | .value = 13, | ||
| 86 | .next = null, | ||
| 87 | }; | ||
| 88 | var b1 = GenNode(bool){ | ||
| 89 | .value = true, | ||
| 90 | .next = null, | ||
| 91 | }; | ||
| 92 | expect(a1.value == 13); | ||
| 93 | expect(a1.value == a1.getVal()); | ||
| 94 | expect(b1.getVal()); | ||
| 95 | } | ||
| 96 | fn GenNode(comptime T: type) type { | ||
| 97 | return struct { | ||
| 98 | value: T, | ||
| 99 | next: ?*GenNode(T), | ||
| 100 | fn getVal(n: *const GenNode(T)) T { | ||
| 101 | return n.value; | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | test "const decls in struct" { | ||
| 107 | expect(GenericDataThing(3).count_plus_one == 4); | ||
| 108 | } | ||
| 109 | fn GenericDataThing(comptime count: isize) type { | ||
| 110 | return struct { | ||
| 111 | const count_plus_one = count + 1; | ||
| 112 | }; | ||
| 113 | } | ||
| 114 | |||
| 115 | test "use generic param in generic param" { | ||
| 116 | expect(aGenericFn(i32, 3, 4) == 7); | ||
| 117 | } | ||
| 118 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { | ||
| 119 | return a + b; | ||
| 120 | } | ||
| 121 | |||
| 122 | test "generic fn with implicit cast" { | ||
| 123 | expect(getFirstByte(u8, []u8{13}) == 13); | ||
| 124 | expect(getFirstByte(u16, []u16{ | ||
| 125 | 0, | ||
| 126 | 13, | ||
| 127 | }) == 0); | ||
| 128 | } | ||
| 129 | fn getByte(ptr: ?*const u8) u8 { | ||
| 130 | return ptr.?.*; | ||
| 131 | } | ||
| 132 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | ||
| 133 | return getByte(@ptrCast(*const u8, &mem[0])); | ||
| 134 | } | ||
| 135 | |||
| 136 | const foos = []fn (var) bool{ | ||
| 137 | foo1, | ||
| 138 | foo2, | ||
| 139 | }; | ||
| 140 | |||
| 141 | fn foo1(arg: var) bool { | ||
| 142 | return arg; | ||
| 143 | } | ||
| 144 | fn foo2(arg: var) bool { | ||
| 145 | return !arg; | ||
| 146 | } | ||
| 147 | |||
| 148 | test "array of generic fns" { | ||
| 149 | expect(foos[0](true)); | ||
| 150 | expect(!foos[1](true)); | ||
| 151 | } | ||
test/stage1/behavior/if.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "if statements" { | ||
| 4 | shouldBeEqual(1, 1); | ||
| 5 | firstEqlThird(2, 1, 2); | ||
| 6 | } | ||
| 7 | fn shouldBeEqual(a: i32, b: i32) void { | ||
| 8 | if (a != b) { | ||
| 9 | unreachable; | ||
| 10 | } else { | ||
| 11 | return; | ||
| 12 | } | ||
| 13 | } | ||
| 14 | fn firstEqlThird(a: i32, b: i32, c: i32) void { | ||
| 15 | if (a == b) { | ||
| 16 | unreachable; | ||
| 17 | } else if (b == c) { | ||
| 18 | unreachable; | ||
| 19 | } else if (a == c) { | ||
| 20 | return; | ||
| 21 | } else { | ||
| 22 | unreachable; | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | test "else if expression" { | ||
| 27 | expect(elseIfExpressionF(1) == 1); | ||
| 28 | } | ||
| 29 | fn elseIfExpressionF(c: u8) u8 { | ||
| 30 | if (c == 0) { | ||
| 31 | return 0; | ||
| 32 | } else if (c == 1) { | ||
| 33 | return 1; | ||
| 34 | } else { | ||
| 35 | return u8(2); | ||
| 36 | } | ||
| 37 | } | ||
test/stage1/behavior/import.zig created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const a_namespace = @import("import/a_namespace.zig"); | ||
| 3 | |||
| 4 | test "call fn via namespace lookup" { | ||
| 5 | expect(a_namespace.foo() == 1234); | ||
| 6 | } | ||
| 7 | |||
| 8 | test "importing the same thing gives the same import" { | ||
| 9 | expect(@import("std") == @import("std")); | ||
| 10 | } | ||
test/stage1/behavior/import/a_namespace.zig created+3| ... | @@ -0,0 +1,3 @@ | ||
| 1 | pub fn foo() i32 { | ||
| 2 | return 1234; | ||
| 3 | } | ||
test/stage1/behavior/incomplete_struct_param_tld.zig created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const A = struct { | ||
| 4 | b: B, | ||
| 5 | }; | ||
| 6 | |||
| 7 | const B = struct { | ||
| 8 | c: C, | ||
| 9 | }; | ||
| 10 | |||
| 11 | const C = struct { | ||
| 12 | x: i32, | ||
| 13 | |||
| 14 | fn d(c: *const C) i32 { | ||
| 15 | return c.x; | ||
| 16 | } | ||
| 17 | }; | ||
| 18 | |||
| 19 | fn foo(a: A) i32 { | ||
| 20 | return a.b.c.d(); | ||
| 21 | } | ||
| 22 | |||
| 23 | test "incomplete struct param top level declaration" { | ||
| 24 | const a = A{ | ||
| 25 | .b = B{ | ||
| 26 | .c = C{ .x = 13 }, | ||
| 27 | }, | ||
| 28 | }; | ||
| 29 | expect(foo(a) == 13); | ||
| 30 | } | ||
test/stage1/behavior/inttoptr.zig created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | test "casting random address to function pointer" { | ||
| 6 | randomAddressToFunction(); | ||
| 7 | comptime randomAddressToFunction(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn randomAddressToFunction() void { | ||
| 11 | var addr: usize = 0xdeadbeef; | ||
| 12 | var ptr = @intToPtr(fn () void, addr); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "mutate through ptr initialized with constant intToPtr value" { | ||
| 16 | forceCompilerAnalyzeBranchHardCodedPtrDereference(false); | ||
| 17 | } | ||
| 18 | |||
| 19 | fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void { | ||
| 20 | const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef); | ||
| 21 | if (x) { | ||
| 22 | hardCodedP.* = hardCodedP.* | 10; | ||
| 23 | } else { | ||
| 24 | return; | ||
| 25 | } | ||
| 26 | } | ||
test/stage1/behavior/ir_block_deps.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | fn foo(id: u64) !i32 { | ||
| 4 | return switch (id) { | ||
| 5 | 1 => getErrInt(), | ||
| 6 | 2 => { | ||
| 7 | const size = try getErrInt(); | ||
| 8 | return try getErrInt(); | ||
| 9 | }, | ||
| 10 | else => error.ItBroke, | ||
| 11 | }; | ||
| 12 | } | ||
| 13 | |||
| 14 | fn getErrInt() anyerror!i32 { | ||
| 15 | return 0; | ||
| 16 | } | ||
| 17 | |||
| 18 | test "ir block deps" { | ||
| 19 | expect((foo(1) catch unreachable) == 0); | ||
| 20 | expect((foo(2) catch unreachable) == 0); | ||
| 21 | } | ||
test/stage1/behavior/math.zig created+517| ... | @@ -0,0 +1,517 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const expectEqual = std.testing.expectEqual; | ||
| 4 | const expectEqualSlices = std.testing.expectEqualSlices; | ||
| 5 | const maxInt = std.math.maxInt; | ||
| 6 | const minInt = std.math.minInt; | ||
| 7 | |||
| 8 | test "division" { | ||
| 9 | testDivision(); | ||
| 10 | comptime testDivision(); | ||
| 11 | } | ||
| 12 | fn testDivision() void { | ||
| 13 | expect(div(u32, 13, 3) == 4); | ||
| 14 | expect(div(f16, 1.0, 2.0) == 0.5); | ||
| 15 | expect(div(f32, 1.0, 2.0) == 0.5); | ||
| 16 | |||
| 17 | expect(divExact(u32, 55, 11) == 5); | ||
| 18 | expect(divExact(i32, -55, 11) == -5); | ||
| 19 | expect(divExact(f16, 55.0, 11.0) == 5.0); | ||
| 20 | expect(divExact(f16, -55.0, 11.0) == -5.0); | ||
| 21 | expect(divExact(f32, 55.0, 11.0) == 5.0); | ||
| 22 | expect(divExact(f32, -55.0, 11.0) == -5.0); | ||
| 23 | |||
| 24 | expect(divFloor(i32, 5, 3) == 1); | ||
| 25 | expect(divFloor(i32, -5, 3) == -2); | ||
| 26 | expect(divFloor(f16, 5.0, 3.0) == 1.0); | ||
| 27 | expect(divFloor(f16, -5.0, 3.0) == -2.0); | ||
| 28 | expect(divFloor(f32, 5.0, 3.0) == 1.0); | ||
| 29 | expect(divFloor(f32, -5.0, 3.0) == -2.0); | ||
| 30 | expect(divFloor(i32, -0x80000000, -2) == 0x40000000); | ||
| 31 | expect(divFloor(i32, 0, -0x80000000) == 0); | ||
| 32 | expect(divFloor(i32, -0x40000001, 0x40000000) == -2); | ||
| 33 | expect(divFloor(i32, -0x80000000, 1) == -0x80000000); | ||
| 34 | |||
| 35 | expect(divTrunc(i32, 5, 3) == 1); | ||
| 36 | expect(divTrunc(i32, -5, 3) == -1); | ||
| 37 | expect(divTrunc(f16, 5.0, 3.0) == 1.0); | ||
| 38 | expect(divTrunc(f16, -5.0, 3.0) == -1.0); | ||
| 39 | expect(divTrunc(f32, 5.0, 3.0) == 1.0); | ||
| 40 | expect(divTrunc(f32, -5.0, 3.0) == -1.0); | ||
| 41 | expect(divTrunc(f64, 5.0, 3.0) == 1.0); | ||
| 42 | expect(divTrunc(f64, -5.0, 3.0) == -1.0); | ||
| 43 | |||
| 44 | comptime { | ||
| 45 | expect( | ||
| 46 | 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, | ||
| 47 | ); | ||
| 48 | expect( | ||
| 49 | @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600, | ||
| 50 | ); | ||
| 51 | expect( | ||
| 52 | 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2, | ||
| 53 | ); | ||
| 54 | expect( | ||
| 55 | @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2, | ||
| 56 | ); | ||
| 57 | expect( | ||
| 58 | @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2, | ||
| 59 | ); | ||
| 60 | expect( | ||
| 61 | @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2, | ||
| 62 | ); | ||
| 63 | expect( | ||
| 64 | 4126227191251978491697987544882340798050766755606969681711 % 10 == 1, | ||
| 65 | ); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | fn div(comptime T: type, a: T, b: T) T { | ||
| 69 | return a / b; | ||
| 70 | } | ||
| 71 | fn divExact(comptime T: type, a: T, b: T) T { | ||
| 72 | return @divExact(a, b); | ||
| 73 | } | ||
| 74 | fn divFloor(comptime T: type, a: T, b: T) T { | ||
| 75 | return @divFloor(a, b); | ||
| 76 | } | ||
| 77 | fn divTrunc(comptime T: type, a: T, b: T) T { | ||
| 78 | return @divTrunc(a, b); | ||
| 79 | } | ||
| 80 | |||
| 81 | test "@addWithOverflow" { | ||
| 82 | var result: u8 = undefined; | ||
| 83 | expect(@addWithOverflow(u8, 250, 100, &result)); | ||
| 84 | expect(!@addWithOverflow(u8, 100, 150, &result)); | ||
| 85 | expect(result == 250); | ||
| 86 | } | ||
| 87 | |||
| 88 | // TODO test mulWithOverflow | ||
| 89 | // TODO test subWithOverflow | ||
| 90 | |||
| 91 | test "@shlWithOverflow" { | ||
| 92 | var result: u16 = undefined; | ||
| 93 | expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); | ||
| 94 | expect(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); | ||
| 95 | expect(result == 0b1011111111111100); | ||
| 96 | } | ||
| 97 | |||
| 98 | test "@clz" { | ||
| 99 | testClz(); | ||
| 100 | comptime testClz(); | ||
| 101 | } | ||
| 102 | |||
| 103 | fn testClz() void { | ||
| 104 | expect(clz(u8(0b00001010)) == 4); | ||
| 105 | expect(clz(u8(0b10001010)) == 0); | ||
| 106 | expect(clz(u8(0b00000000)) == 8); | ||
| 107 | expect(clz(u128(0xffffffffffffffff)) == 64); | ||
| 108 | expect(clz(u128(0x10000000000000000)) == 63); | ||
| 109 | } | ||
| 110 | |||
| 111 | fn clz(x: var) usize { | ||
| 112 | return @clz(x); | ||
| 113 | } | ||
| 114 | |||
| 115 | test "@ctz" { | ||
| 116 | testCtz(); | ||
| 117 | comptime testCtz(); | ||
| 118 | } | ||
| 119 | |||
| 120 | fn testCtz() void { | ||
| 121 | expect(ctz(u8(0b10100000)) == 5); | ||
| 122 | expect(ctz(u8(0b10001010)) == 1); | ||
| 123 | expect(ctz(u8(0b00000000)) == 8); | ||
| 124 | } | ||
| 125 | |||
| 126 | fn ctz(x: var) usize { | ||
| 127 | return @ctz(x); | ||
| 128 | } | ||
| 129 | |||
| 130 | test "assignment operators" { | ||
| 131 | var i: u32 = 0; | ||
| 132 | i += 5; | ||
| 133 | expect(i == 5); | ||
| 134 | i -= 2; | ||
| 135 | expect(i == 3); | ||
| 136 | i *= 20; | ||
| 137 | expect(i == 60); | ||
| 138 | i /= 3; | ||
| 139 | expect(i == 20); | ||
| 140 | i %= 11; | ||
| 141 | expect(i == 9); | ||
| 142 | i <<= 1; | ||
| 143 | expect(i == 18); | ||
| 144 | i >>= 2; | ||
| 145 | expect(i == 4); | ||
| 146 | i = 6; | ||
| 147 | i &= 5; | ||
| 148 | expect(i == 4); | ||
| 149 | i ^= 6; | ||
| 150 | expect(i == 2); | ||
| 151 | i = 6; | ||
| 152 | i |= 3; | ||
| 153 | expect(i == 7); | ||
| 154 | } | ||
| 155 | |||
| 156 | test "three expr in a row" { | ||
| 157 | testThreeExprInARow(false, true); | ||
| 158 | comptime testThreeExprInARow(false, true); | ||
| 159 | } | ||
| 160 | fn testThreeExprInARow(f: bool, t: bool) void { | ||
| 161 | assertFalse(f or f or f); | ||
| 162 | assertFalse(t and t and f); | ||
| 163 | assertFalse(1 | 2 | 4 != 7); | ||
| 164 | assertFalse(3 ^ 6 ^ 8 != 13); | ||
| 165 | assertFalse(7 & 14 & 28 != 4); | ||
| 166 | assertFalse(9 << 1 << 2 != 9 << 3); | ||
| 167 | assertFalse(90 >> 1 >> 2 != 90 >> 3); | ||
| 168 | assertFalse(100 - 1 + 1000 != 1099); | ||
| 169 | assertFalse(5 * 4 / 2 % 3 != 1); | ||
| 170 | assertFalse(i32(i32(5)) != 5); | ||
| 171 | assertFalse(!!false); | ||
| 172 | assertFalse(i32(7) != --(i32(7))); | ||
| 173 | } | ||
| 174 | fn assertFalse(b: bool) void { | ||
| 175 | expect(!b); | ||
| 176 | } | ||
| 177 | |||
| 178 | test "const number literal" { | ||
| 179 | const one = 1; | ||
| 180 | const eleven = ten + one; | ||
| 181 | |||
| 182 | expect(eleven == 11); | ||
| 183 | } | ||
| 184 | const ten = 10; | ||
| 185 | |||
| 186 | test "unsigned wrapping" { | ||
| 187 | testUnsignedWrappingEval(maxInt(u32)); | ||
| 188 | comptime testUnsignedWrappingEval(maxInt(u32)); | ||
| 189 | } | ||
| 190 | fn testUnsignedWrappingEval(x: u32) void { | ||
| 191 | const zero = x +% 1; | ||
| 192 | expect(zero == 0); | ||
| 193 | const orig = zero -% 1; | ||
| 194 | expect(orig == maxInt(u32)); | ||
| 195 | } | ||
| 196 | |||
| 197 | test "signed wrapping" { | ||
| 198 | testSignedWrappingEval(maxInt(i32)); | ||
| 199 | comptime testSignedWrappingEval(maxInt(i32)); | ||
| 200 | } | ||
| 201 | fn testSignedWrappingEval(x: i32) void { | ||
| 202 | const min_val = x +% 1; | ||
| 203 | expect(min_val == minInt(i32)); | ||
| 204 | const max_val = min_val -% 1; | ||
| 205 | expect(max_val == maxInt(i32)); | ||
| 206 | } | ||
| 207 | |||
| 208 | test "negation wrapping" { | ||
| 209 | testNegationWrappingEval(minInt(i16)); | ||
| 210 | comptime testNegationWrappingEval(minInt(i16)); | ||
| 211 | } | ||
| 212 | fn testNegationWrappingEval(x: i16) void { | ||
| 213 | expect(x == -32768); | ||
| 214 | const neg = -%x; | ||
| 215 | expect(neg == -32768); | ||
| 216 | } | ||
| 217 | |||
| 218 | test "unsigned 64-bit division" { | ||
| 219 | test_u64_div(); | ||
| 220 | comptime test_u64_div(); | ||
| 221 | } | ||
| 222 | fn test_u64_div() void { | ||
| 223 | const result = divWithResult(1152921504606846976, 34359738365); | ||
| 224 | expect(result.quotient == 33554432); | ||
| 225 | expect(result.remainder == 100663296); | ||
| 226 | } | ||
| 227 | fn divWithResult(a: u64, b: u64) DivResult { | ||
| 228 | return DivResult{ | ||
| 229 | .quotient = a / b, | ||
| 230 | .remainder = a % b, | ||
| 231 | }; | ||
| 232 | } | ||
| 233 | const DivResult = struct { | ||
| 234 | quotient: u64, | ||
| 235 | remainder: u64, | ||
| 236 | }; | ||
| 237 | |||
| 238 | test "binary not" { | ||
| 239 | expect(comptime x: { | ||
| 240 | break :x ~u16(0b1010101010101010) == 0b0101010101010101; | ||
| 241 | }); | ||
| 242 | expect(comptime x: { | ||
| 243 | break :x ~u64(2147483647) == 18446744071562067968; | ||
| 244 | }); | ||
| 245 | testBinaryNot(0b1010101010101010); | ||
| 246 | } | ||
| 247 | |||
| 248 | fn testBinaryNot(x: u16) void { | ||
| 249 | expect(~x == 0b0101010101010101); | ||
| 250 | } | ||
| 251 | |||
| 252 | test "small int addition" { | ||
| 253 | var x: @IntType(false, 2) = 0; | ||
| 254 | expect(x == 0); | ||
| 255 | |||
| 256 | x += 1; | ||
| 257 | expect(x == 1); | ||
| 258 | |||
| 259 | x += 1; | ||
| 260 | expect(x == 2); | ||
| 261 | |||
| 262 | x += 1; | ||
| 263 | expect(x == 3); | ||
| 264 | |||
| 265 | var result: @typeOf(x) = 3; | ||
| 266 | expect(@addWithOverflow(@typeOf(x), x, 1, &result)); | ||
| 267 | |||
| 268 | expect(result == 0); | ||
| 269 | } | ||
| 270 | |||
| 271 | test "float equality" { | ||
| 272 | const x: f64 = 0.012; | ||
| 273 | const y: f64 = x + 1.0; | ||
| 274 | |||
| 275 | testFloatEqualityImpl(x, y); | ||
| 276 | comptime testFloatEqualityImpl(x, y); | ||
| 277 | } | ||
| 278 | |||
| 279 | fn testFloatEqualityImpl(x: f64, y: f64) void { | ||
| 280 | const y2 = x + 1.0; | ||
| 281 | expect(y == y2); | ||
| 282 | } | ||
| 283 | |||
| 284 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | ||
| 285 | expect(5 / 3 == 1); | ||
| 286 | expect(-5 / -3 == 1); | ||
| 287 | expect(-6 / 3 == -2); | ||
| 288 | |||
| 289 | expect(5 % 3 == 2); | ||
| 290 | expect(-6 % 3 == 0); | ||
| 291 | } | ||
| 292 | |||
| 293 | test "hex float literal parsing" { | ||
| 294 | comptime expect(0x1.0 == 1.0); | ||
| 295 | } | ||
| 296 | |||
| 297 | test "quad hex float literal parsing in range" { | ||
| 298 | const a = 0x1.af23456789bbaaab347645365cdep+5; | ||
| 299 | const b = 0x1.dedafcff354b6ae9758763545432p-9; | ||
| 300 | const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534; | ||
| 301 | const d = 0x1.edcbff8ad76ab5bf46463233214fp-435; | ||
| 302 | } | ||
| 303 | |||
| 304 | test "quad hex float literal parsing accurate" { | ||
| 305 | const a: f128 = 0x1.1111222233334444555566667777p+0; | ||
| 306 | |||
| 307 | // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. | ||
| 308 | const expected: u128 = 0x3fff1111222233334444555566667777; | ||
| 309 | expect(@bitCast(u128, a) == expected); | ||
| 310 | } | ||
| 311 | |||
| 312 | test "hex float literal within range" { | ||
| 313 | const a = 0x1.0p16383; | ||
| 314 | const b = 0x0.1p16387; | ||
| 315 | const c = 0x1.0p-16382; | ||
| 316 | } | ||
| 317 | |||
| 318 | test "truncating shift left" { | ||
| 319 | testShlTrunc(maxInt(u16)); | ||
| 320 | comptime testShlTrunc(maxInt(u16)); | ||
| 321 | } | ||
| 322 | fn testShlTrunc(x: u16) void { | ||
| 323 | const shifted = x << 1; | ||
| 324 | expect(shifted == 65534); | ||
| 325 | } | ||
| 326 | |||
| 327 | test "truncating shift right" { | ||
| 328 | testShrTrunc(maxInt(u16)); | ||
| 329 | comptime testShrTrunc(maxInt(u16)); | ||
| 330 | } | ||
| 331 | fn testShrTrunc(x: u16) void { | ||
| 332 | const shifted = x >> 1; | ||
| 333 | expect(shifted == 32767); | ||
| 334 | } | ||
| 335 | |||
| 336 | test "exact shift left" { | ||
| 337 | testShlExact(0b00110101); | ||
| 338 | comptime testShlExact(0b00110101); | ||
| 339 | } | ||
| 340 | fn testShlExact(x: u8) void { | ||
| 341 | const shifted = @shlExact(x, 2); | ||
| 342 | expect(shifted == 0b11010100); | ||
| 343 | } | ||
| 344 | |||
| 345 | test "exact shift right" { | ||
| 346 | testShrExact(0b10110100); | ||
| 347 | comptime testShrExact(0b10110100); | ||
| 348 | } | ||
| 349 | fn testShrExact(x: u8) void { | ||
| 350 | const shifted = @shrExact(x, 2); | ||
| 351 | expect(shifted == 0b00101101); | ||
| 352 | } | ||
| 353 | |||
| 354 | test "comptime_int addition" { | ||
| 355 | comptime { | ||
| 356 | expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); | ||
| 357 | expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | test "comptime_int multiplication" { | ||
| 362 | comptime { | ||
| 363 | expect( | ||
| 364 | 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567, | ||
| 365 | ); | ||
| 366 | expect( | ||
| 367 | 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016, | ||
| 368 | ); | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | test "comptime_int shifting" { | ||
| 373 | comptime { | ||
| 374 | expect((u128(1) << 127) == 0x80000000000000000000000000000000); | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | test "comptime_int multi-limb shift and mask" { | ||
| 379 | comptime { | ||
| 380 | var a = 0xefffffffa0000001eeeeeeefaaaaaaab; | ||
| 381 | |||
| 382 | expect(u32(a & 0xffffffff) == 0xaaaaaaab); | ||
| 383 | a >>= 32; | ||
| 384 | expect(u32(a & 0xffffffff) == 0xeeeeeeef); | ||
| 385 | a >>= 32; | ||
| 386 | expect(u32(a & 0xffffffff) == 0xa0000001); | ||
| 387 | a >>= 32; | ||
| 388 | expect(u32(a & 0xffffffff) == 0xefffffff); | ||
| 389 | a >>= 32; | ||
| 390 | |||
| 391 | expect(a == 0); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | test "comptime_int multi-limb partial shift right" { | ||
| 396 | comptime { | ||
| 397 | var a = 0x1ffffffffeeeeeeee; | ||
| 398 | a >>= 16; | ||
| 399 | expect(a == 0x1ffffffffeeee); | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | test "xor" { | ||
| 404 | test_xor(); | ||
| 405 | comptime test_xor(); | ||
| 406 | } | ||
| 407 | |||
| 408 | fn test_xor() void { | ||
| 409 | expect(0xFF ^ 0x00 == 0xFF); | ||
| 410 | expect(0xF0 ^ 0x0F == 0xFF); | ||
| 411 | expect(0xFF ^ 0xF0 == 0x0F); | ||
| 412 | expect(0xFF ^ 0x0F == 0xF0); | ||
| 413 | expect(0xFF ^ 0xFF == 0x00); | ||
| 414 | } | ||
| 415 | |||
| 416 | test "comptime_int xor" { | ||
| 417 | comptime { | ||
| 418 | expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 419 | expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 420 | expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF); | ||
| 421 | expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000); | ||
| 422 | expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000); | ||
| 423 | expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | ||
| 424 | expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF); | ||
| 425 | expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | test "f128" { | ||
| 430 | test_f128(); | ||
| 431 | comptime test_f128(); | ||
| 432 | } | ||
| 433 | |||
| 434 | fn make_f128(x: f128) f128 { | ||
| 435 | return x; | ||
| 436 | } | ||
| 437 | |||
| 438 | fn test_f128() void { | ||
| 439 | expect(@sizeOf(f128) == 16); | ||
| 440 | expect(make_f128(1.0) == 1.0); | ||
| 441 | expect(make_f128(1.0) != 1.1); | ||
| 442 | expect(make_f128(1.0) > 0.9); | ||
| 443 | expect(make_f128(1.0) >= 0.9); | ||
| 444 | expect(make_f128(1.0) >= 1.0); | ||
| 445 | should_not_be_zero(1.0); | ||
| 446 | } | ||
| 447 | |||
| 448 | fn should_not_be_zero(x: f128) void { | ||
| 449 | expect(x != 0.0); | ||
| 450 | } | ||
| 451 | |||
| 452 | test "comptime float rem int" { | ||
| 453 | comptime { | ||
| 454 | var x = f32(1) % 2; | ||
| 455 | expect(x == 1.0); | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | test "remainder division" { | ||
| 460 | comptime remdiv(f16); | ||
| 461 | comptime remdiv(f32); | ||
| 462 | comptime remdiv(f64); | ||
| 463 | comptime remdiv(f128); | ||
| 464 | remdiv(f16); | ||
| 465 | remdiv(f64); | ||
| 466 | remdiv(f128); | ||
| 467 | } | ||
| 468 | |||
| 469 | fn remdiv(comptime T: type) void { | ||
| 470 | expect(T(1) == T(1) % T(2)); | ||
| 471 | expect(T(1) == T(7) % T(3)); | ||
| 472 | } | ||
| 473 | |||
| 474 | test "@sqrt" { | ||
| 475 | testSqrt(f64, 12.0); | ||
| 476 | comptime testSqrt(f64, 12.0); | ||
| 477 | testSqrt(f32, 13.0); | ||
| 478 | comptime testSqrt(f32, 13.0); | ||
| 479 | testSqrt(f16, 13.0); | ||
| 480 | comptime testSqrt(f16, 13.0); | ||
| 481 | |||
| 482 | const x = 14.0; | ||
| 483 | const y = x * x; | ||
| 484 | const z = @sqrt(@typeOf(y), y); | ||
| 485 | comptime expect(z == x); | ||
| 486 | } | ||
| 487 | |||
| 488 | fn testSqrt(comptime T: type, x: T) void { | ||
| 489 | expect(@sqrt(T, x * x) == x); | ||
| 490 | } | ||
| 491 | |||
| 492 | test "comptime_int param and return" { | ||
| 493 | const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); | ||
| 494 | expect(a == 137114567242441932203689521744947848950); | ||
| 495 | |||
| 496 | const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768); | ||
| 497 | expect(b == 985095453608931032642182098849559179469148836107390954364380); | ||
| 498 | } | ||
| 499 | |||
| 500 | fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int { | ||
| 501 | return a + b; | ||
| 502 | } | ||
| 503 | |||
| 504 | test "vector integer addition" { | ||
| 505 | const S = struct { | ||
| 506 | fn doTheTest() void { | ||
| 507 | var a: @Vector(4, i32) = []i32{ 1, 2, 3, 4 }; | ||
| 508 | var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 }; | ||
| 509 | var result = a + b; | ||
| 510 | var result_array: [4]i32 = result; | ||
| 511 | const expected = []i32{ 6, 8, 10, 12 }; | ||
| 512 | expectEqualSlices(i32, &expected, &result_array); | ||
| 513 | } | ||
| 514 | }; | ||
| 515 | S.doTheTest(); | ||
| 516 | comptime S.doTheTest(); | ||
| 517 | } | ||
test/stage1/behavior/merge_error_sets.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const A = error{ | ||
| 2 | FileNotFound, | ||
| 3 | NotDir, | ||
| 4 | }; | ||
| 5 | const B = error{OutOfMemory}; | ||
| 6 | |||
| 7 | const C = A || B; | ||
| 8 | |||
| 9 | fn foo() C!void { | ||
| 10 | return error.NotDir; | ||
| 11 | } | ||
| 12 | |||
| 13 | test "merge error sets" { | ||
| 14 | if (foo()) { | ||
| 15 | @panic("unexpected"); | ||
| 16 | } else |err| switch (err) { | ||
| 17 | error.OutOfMemory => @panic("unexpected"), | ||
| 18 | error.FileNotFound => @panic("unexpected"), | ||
| 19 | error.NotDir => {}, | ||
| 20 | } | ||
| 21 | } | ||
test/stage1/behavior/misc.zig created+695| ... | @@ -0,0 +1,695 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const mem = std.mem; | ||
| 4 | const cstr = std.cstr; | ||
| 5 | const builtin = @import("builtin"); | ||
| 6 | const maxInt = std.math.maxInt; | ||
| 7 | |||
| 8 | // normal comment | ||
| 9 | |||
| 10 | /// this is a documentation comment | ||
| 11 | /// doc comment line 2 | ||
| 12 | fn emptyFunctionWithComments() void {} | ||
| 13 | |||
| 14 | test "empty function with comments" { | ||
| 15 | emptyFunctionWithComments(); | ||
| 16 | } | ||
| 17 | |||
| 18 | comptime { | ||
| 19 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); | ||
| 20 | } | ||
| 21 | |||
| 22 | extern fn disabledExternFn() void {} | ||
| 23 | |||
| 24 | test "call disabled extern fn" { | ||
| 25 | disabledExternFn(); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "@IntType builtin" { | ||
| 29 | expect(@IntType(true, 8) == i8); | ||
| 30 | expect(@IntType(true, 16) == i16); | ||
| 31 | expect(@IntType(true, 32) == i32); | ||
| 32 | expect(@IntType(true, 64) == i64); | ||
| 33 | |||
| 34 | expect(@IntType(false, 8) == u8); | ||
| 35 | expect(@IntType(false, 16) == u16); | ||
| 36 | expect(@IntType(false, 32) == u32); | ||
| 37 | expect(@IntType(false, 64) == u64); | ||
| 38 | |||
| 39 | expect(i8.bit_count == 8); | ||
| 40 | expect(i16.bit_count == 16); | ||
| 41 | expect(i32.bit_count == 32); | ||
| 42 | expect(i64.bit_count == 64); | ||
| 43 | |||
| 44 | expect(i8.is_signed); | ||
| 45 | expect(i16.is_signed); | ||
| 46 | expect(i32.is_signed); | ||
| 47 | expect(i64.is_signed); | ||
| 48 | expect(isize.is_signed); | ||
| 49 | |||
| 50 | expect(!u8.is_signed); | ||
| 51 | expect(!u16.is_signed); | ||
| 52 | expect(!u32.is_signed); | ||
| 53 | expect(!u64.is_signed); | ||
| 54 | expect(!usize.is_signed); | ||
| 55 | } | ||
| 56 | |||
| 57 | test "floating point primitive bit counts" { | ||
| 58 | expect(f16.bit_count == 16); | ||
| 59 | expect(f32.bit_count == 32); | ||
| 60 | expect(f64.bit_count == 64); | ||
| 61 | } | ||
| 62 | |||
| 63 | test "short circuit" { | ||
| 64 | testShortCircuit(false, true); | ||
| 65 | comptime testShortCircuit(false, true); | ||
| 66 | } | ||
| 67 | |||
| 68 | fn testShortCircuit(f: bool, t: bool) void { | ||
| 69 | var hit_1 = f; | ||
| 70 | var hit_2 = f; | ||
| 71 | var hit_3 = f; | ||
| 72 | var hit_4 = f; | ||
| 73 | |||
| 74 | if (t or x: { | ||
| 75 | expect(f); | ||
| 76 | break :x f; | ||
| 77 | }) { | ||
| 78 | hit_1 = t; | ||
| 79 | } | ||
| 80 | if (f or x: { | ||
| 81 | hit_2 = t; | ||
| 82 | break :x f; | ||
| 83 | }) { | ||
| 84 | expect(f); | ||
| 85 | } | ||
| 86 | |||
| 87 | if (t and x: { | ||
| 88 | hit_3 = t; | ||
| 89 | break :x f; | ||
| 90 | }) { | ||
| 91 | expect(f); | ||
| 92 | } | ||
| 93 | if (f and x: { | ||
| 94 | expect(f); | ||
| 95 | break :x f; | ||
| 96 | }) { | ||
| 97 | expect(f); | ||
| 98 | } else { | ||
| 99 | hit_4 = t; | ||
| 100 | } | ||
| 101 | expect(hit_1); | ||
| 102 | expect(hit_2); | ||
| 103 | expect(hit_3); | ||
| 104 | expect(hit_4); | ||
| 105 | } | ||
| 106 | |||
| 107 | test "truncate" { | ||
| 108 | expect(testTruncate(0x10fd) == 0xfd); | ||
| 109 | } | ||
| 110 | fn testTruncate(x: u32) u8 { | ||
| 111 | return @truncate(u8, x); | ||
| 112 | } | ||
| 113 | |||
| 114 | fn first4KeysOfHomeRow() []const u8 { | ||
| 115 | return "aoeu"; | ||
| 116 | } | ||
| 117 | |||
| 118 | test "return string from function" { | ||
| 119 | expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); | ||
| 120 | } | ||
| 121 | |||
| 122 | const g1: i32 = 1233 + 1; | ||
| 123 | var g2: i32 = 0; | ||
| 124 | |||
| 125 | test "global variables" { | ||
| 126 | expect(g2 == 0); | ||
| 127 | g2 = g1; | ||
| 128 | expect(g2 == 1234); | ||
| 129 | } | ||
| 130 | |||
| 131 | test "memcpy and memset intrinsics" { | ||
| 132 | var foo: [20]u8 = undefined; | ||
| 133 | var bar: [20]u8 = undefined; | ||
| 134 | |||
| 135 | @memset(foo[0..].ptr, 'A', foo.len); | ||
| 136 | @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); | ||
| 137 | |||
| 138 | if (bar[11] != 'A') unreachable; | ||
| 139 | } | ||
| 140 | |||
| 141 | test "builtin static eval" { | ||
| 142 | const x: i32 = comptime x: { | ||
| 143 | break :x 1 + 2 + 3; | ||
| 144 | }; | ||
| 145 | expect(x == comptime 6); | ||
| 146 | } | ||
| 147 | |||
| 148 | test "slicing" { | ||
| 149 | var array: [20]i32 = undefined; | ||
| 150 | |||
| 151 | array[5] = 1234; | ||
| 152 | |||
| 153 | var slice = array[5..10]; | ||
| 154 | |||
| 155 | if (slice.len != 5) unreachable; | ||
| 156 | |||
| 157 | const ptr = &slice[0]; | ||
| 158 | if (ptr.* != 1234) unreachable; | ||
| 159 | |||
| 160 | var slice_rest = array[10..]; | ||
| 161 | if (slice_rest.len != 10) unreachable; | ||
| 162 | } | ||
| 163 | |||
| 164 | test "constant equal function pointers" { | ||
| 165 | const alias = emptyFn; | ||
| 166 | expect(comptime x: { | ||
| 167 | break :x emptyFn == alias; | ||
| 168 | }); | ||
| 169 | } | ||
| 170 | |||
| 171 | fn emptyFn() void {} | ||
| 172 | |||
| 173 | test "hex escape" { | ||
| 174 | expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); | ||
| 175 | } | ||
| 176 | |||
| 177 | test "string concatenation" { | ||
| 178 | expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | ||
| 179 | } | ||
| 180 | |||
| 181 | test "array mult operator" { | ||
| 182 | expect(mem.eql(u8, "ab" ** 5, "ababababab")); | ||
| 183 | } | ||
| 184 | |||
| 185 | test "string escapes" { | ||
| 186 | expect(mem.eql(u8, "\"", "\x22")); | ||
| 187 | expect(mem.eql(u8, "\'", "\x27")); | ||
| 188 | expect(mem.eql(u8, "\n", "\x0a")); | ||
| 189 | expect(mem.eql(u8, "\r", "\x0d")); | ||
| 190 | expect(mem.eql(u8, "\t", "\x09")); | ||
| 191 | expect(mem.eql(u8, "\\", "\x5c")); | ||
| 192 | expect(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); | ||
| 193 | } | ||
| 194 | |||
| 195 | test "multiline string" { | ||
| 196 | const s1 = | ||
| 197 | \\one | ||
| 198 | \\two) | ||
| 199 | \\three | ||
| 200 | ; | ||
| 201 | const s2 = "one\ntwo)\nthree"; | ||
| 202 | expect(mem.eql(u8, s1, s2)); | ||
| 203 | } | ||
| 204 | |||
| 205 | test "multiline C string" { | ||
| 206 | const s1 = | ||
| 207 | c\\one | ||
| 208 | c\\two) | ||
| 209 | c\\three | ||
| 210 | ; | ||
| 211 | const s2 = c"one\ntwo)\nthree"; | ||
| 212 | expect(cstr.cmp(s1, s2) == 0); | ||
| 213 | } | ||
| 214 | |||
| 215 | test "type equality" { | ||
| 216 | expect(*const u8 != *u8); | ||
| 217 | } | ||
| 218 | |||
| 219 | const global_a: i32 = 1234; | ||
| 220 | const global_b: *const i32 = &global_a; | ||
| 221 | const global_c: *const f32 = @ptrCast(*const f32, global_b); | ||
| 222 | test "compile time global reinterpret" { | ||
| 223 | const d = @ptrCast(*const i32, global_c); | ||
| 224 | expect(d.* == 1234); | ||
| 225 | } | ||
| 226 | |||
| 227 | test "explicit cast maybe pointers" { | ||
| 228 | const a: ?*i32 = undefined; | ||
| 229 | const b: ?*f32 = @ptrCast(?*f32, a); | ||
| 230 | } | ||
| 231 | |||
| 232 | test "generic malloc free" { | ||
| 233 | const a = memAlloc(u8, 10) catch unreachable; | ||
| 234 | memFree(u8, a); | ||
| 235 | } | ||
| 236 | var some_mem: [100]u8 = undefined; | ||
| 237 | fn memAlloc(comptime T: type, n: usize) anyerror![]T { | ||
| 238 | return @ptrCast([*]T, &some_mem[0])[0..n]; | ||
| 239 | } | ||
| 240 | fn memFree(comptime T: type, memory: []T) void {} | ||
| 241 | |||
| 242 | test "cast undefined" { | ||
| 243 | const array: [100]u8 = undefined; | ||
| 244 | const slice = ([]const u8)(array); | ||
| 245 | testCastUndefined(slice); | ||
| 246 | } | ||
| 247 | fn testCastUndefined(x: []const u8) void {} | ||
| 248 | |||
| 249 | test "cast small unsigned to larger signed" { | ||
| 250 | expect(castSmallUnsignedToLargerSigned1(200) == i16(200)); | ||
| 251 | expect(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); | ||
| 252 | } | ||
| 253 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | ||
| 254 | return x; | ||
| 255 | } | ||
| 256 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | ||
| 257 | return x; | ||
| 258 | } | ||
| 259 | |||
| 260 | test "implicit cast after unreachable" { | ||
| 261 | expect(outer() == 1234); | ||
| 262 | } | ||
| 263 | fn inner() i32 { | ||
| 264 | return 1234; | ||
| 265 | } | ||
| 266 | fn outer() i64 { | ||
| 267 | return inner(); | ||
| 268 | } | ||
| 269 | |||
| 270 | test "pointer dereferencing" { | ||
| 271 | var x = i32(3); | ||
| 272 | const y = &x; | ||
| 273 | |||
| 274 | y.* += 1; | ||
| 275 | |||
| 276 | expect(x == 4); | ||
| 277 | expect(y.* == 4); | ||
| 278 | } | ||
| 279 | |||
| 280 | test "call result of if else expression" { | ||
| 281 | expect(mem.eql(u8, f2(true), "a")); | ||
| 282 | expect(mem.eql(u8, f2(false), "b")); | ||
| 283 | } | ||
| 284 | fn f2(x: bool) []const u8 { | ||
| 285 | return (if (x) fA else fB)(); | ||
| 286 | } | ||
| 287 | fn fA() []const u8 { | ||
| 288 | return "a"; | ||
| 289 | } | ||
| 290 | fn fB() []const u8 { | ||
| 291 | return "b"; | ||
| 292 | } | ||
| 293 | |||
| 294 | test "const expression eval handling of variables" { | ||
| 295 | var x = true; | ||
| 296 | while (x) { | ||
| 297 | x = false; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | test "constant enum initialization with differing sizes" { | ||
| 302 | test3_1(test3_foo); | ||
| 303 | test3_2(test3_bar); | ||
| 304 | } | ||
| 305 | const Test3Foo = union(enum) { | ||
| 306 | One: void, | ||
| 307 | Two: f32, | ||
| 308 | Three: Test3Point, | ||
| 309 | }; | ||
| 310 | const Test3Point = struct { | ||
| 311 | x: i32, | ||
| 312 | y: i32, | ||
| 313 | }; | ||
| 314 | const test3_foo = Test3Foo{ | ||
| 315 | .Three = Test3Point{ | ||
| 316 | .x = 3, | ||
| 317 | .y = 4, | ||
| 318 | }, | ||
| 319 | }; | ||
| 320 | const test3_bar = Test3Foo{ .Two = 13 }; | ||
| 321 | fn test3_1(f: Test3Foo) void { | ||
| 322 | switch (f) { | ||
| 323 | Test3Foo.Three => |pt| { | ||
| 324 | expect(pt.x == 3); | ||
| 325 | expect(pt.y == 4); | ||
| 326 | }, | ||
| 327 | else => unreachable, | ||
| 328 | } | ||
| 329 | } | ||
| 330 | fn test3_2(f: Test3Foo) void { | ||
| 331 | switch (f) { | ||
| 332 | Test3Foo.Two => |x| { | ||
| 333 | expect(x == 13); | ||
| 334 | }, | ||
| 335 | else => unreachable, | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | test "character literals" { | ||
| 340 | expect('\'' == single_quote); | ||
| 341 | } | ||
| 342 | const single_quote = '\''; | ||
| 343 | |||
| 344 | test "take address of parameter" { | ||
| 345 | testTakeAddressOfParameter(12.34); | ||
| 346 | } | ||
| 347 | fn testTakeAddressOfParameter(f: f32) void { | ||
| 348 | const f_ptr = &f; | ||
| 349 | expect(f_ptr.* == 12.34); | ||
| 350 | } | ||
| 351 | |||
| 352 | test "pointer comparison" { | ||
| 353 | const a = ([]const u8)("a"); | ||
| 354 | const b = &a; | ||
| 355 | expect(ptrEql(b, b)); | ||
| 356 | } | ||
| 357 | fn ptrEql(a: *const []const u8, b: *const []const u8) bool { | ||
| 358 | return a == b; | ||
| 359 | } | ||
| 360 | |||
| 361 | test "C string concatenation" { | ||
| 362 | const a = c"OK" ++ c" IT " ++ c"WORKED"; | ||
| 363 | const b = c"OK IT WORKED"; | ||
| 364 | |||
| 365 | const len = cstr.len(b); | ||
| 366 | const len_with_null = len + 1; | ||
| 367 | { | ||
| 368 | var i: u32 = 0; | ||
| 369 | while (i < len_with_null) : (i += 1) { | ||
| 370 | expect(a[i] == b[i]); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | expect(a[len] == 0); | ||
| 374 | expect(b[len] == 0); | ||
| 375 | } | ||
| 376 | |||
| 377 | test "cast slice to u8 slice" { | ||
| 378 | expect(@sizeOf(i32) == 4); | ||
| 379 | var big_thing_array = []i32{ 1, 2, 3, 4 }; | ||
| 380 | const big_thing_slice: []i32 = big_thing_array[0..]; | ||
| 381 | const bytes = @sliceToBytes(big_thing_slice); | ||
| 382 | expect(bytes.len == 4 * 4); | ||
| 383 | bytes[4] = 0; | ||
| 384 | bytes[5] = 0; | ||
| 385 | bytes[6] = 0; | ||
| 386 | bytes[7] = 0; | ||
| 387 | expect(big_thing_slice[1] == 0); | ||
| 388 | const big_thing_again = @bytesToSlice(i32, bytes); | ||
| 389 | expect(big_thing_again[2] == 3); | ||
| 390 | big_thing_again[2] = -1; | ||
| 391 | expect(bytes[8] == maxInt(u8)); | ||
| 392 | expect(bytes[9] == maxInt(u8)); | ||
| 393 | expect(bytes[10] == maxInt(u8)); | ||
| 394 | expect(bytes[11] == maxInt(u8)); | ||
| 395 | } | ||
| 396 | |||
| 397 | test "pointer to void return type" { | ||
| 398 | testPointerToVoidReturnType() catch unreachable; | ||
| 399 | } | ||
| 400 | fn testPointerToVoidReturnType() anyerror!void { | ||
| 401 | const a = testPointerToVoidReturnType2(); | ||
| 402 | return a.*; | ||
| 403 | } | ||
| 404 | const test_pointer_to_void_return_type_x = void{}; | ||
| 405 | fn testPointerToVoidReturnType2() *const void { | ||
| 406 | return &test_pointer_to_void_return_type_x; | ||
| 407 | } | ||
| 408 | |||
| 409 | test "non const ptr to aliased type" { | ||
| 410 | const int = i32; | ||
| 411 | expect(?*int == ?*i32); | ||
| 412 | } | ||
| 413 | |||
| 414 | test "array 2D const double ptr" { | ||
| 415 | const rect_2d_vertexes = [][1]f32{ | ||
| 416 | []f32{1.0}, | ||
| 417 | []f32{2.0}, | ||
| 418 | }; | ||
| 419 | testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); | ||
| 420 | } | ||
| 421 | |||
| 422 | fn testArray2DConstDoublePtr(ptr: *const f32) void { | ||
| 423 | const ptr2 = @ptrCast([*]const f32, ptr); | ||
| 424 | expect(ptr2[0] == 1.0); | ||
| 425 | expect(ptr2[1] == 2.0); | ||
| 426 | } | ||
| 427 | |||
| 428 | const Tid = builtin.TypeId; | ||
| 429 | const AStruct = struct { | ||
| 430 | x: i32, | ||
| 431 | }; | ||
| 432 | const AnEnum = enum { | ||
| 433 | One, | ||
| 434 | Two, | ||
| 435 | }; | ||
| 436 | const AUnionEnum = union(enum) { | ||
| 437 | One: i32, | ||
| 438 | Two: void, | ||
| 439 | }; | ||
| 440 | const AUnion = union { | ||
| 441 | One: void, | ||
| 442 | Two: void, | ||
| 443 | }; | ||
| 444 | |||
| 445 | test "@typeId" { | ||
| 446 | comptime { | ||
| 447 | expect(@typeId(type) == Tid.Type); | ||
| 448 | expect(@typeId(void) == Tid.Void); | ||
| 449 | expect(@typeId(bool) == Tid.Bool); | ||
| 450 | expect(@typeId(noreturn) == Tid.NoReturn); | ||
| 451 | expect(@typeId(i8) == Tid.Int); | ||
| 452 | expect(@typeId(u8) == Tid.Int); | ||
| 453 | expect(@typeId(i64) == Tid.Int); | ||
| 454 | expect(@typeId(u64) == Tid.Int); | ||
| 455 | expect(@typeId(f32) == Tid.Float); | ||
| 456 | expect(@typeId(f64) == Tid.Float); | ||
| 457 | expect(@typeId(*f32) == Tid.Pointer); | ||
| 458 | expect(@typeId([2]u8) == Tid.Array); | ||
| 459 | expect(@typeId(AStruct) == Tid.Struct); | ||
| 460 | expect(@typeId(@typeOf(1)) == Tid.ComptimeInt); | ||
| 461 | expect(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); | ||
| 462 | expect(@typeId(@typeOf(undefined)) == Tid.Undefined); | ||
| 463 | expect(@typeId(@typeOf(null)) == Tid.Null); | ||
| 464 | expect(@typeId(?i32) == Tid.Optional); | ||
| 465 | expect(@typeId(anyerror!i32) == Tid.ErrorUnion); | ||
| 466 | expect(@typeId(anyerror) == Tid.ErrorSet); | ||
| 467 | expect(@typeId(AnEnum) == Tid.Enum); | ||
| 468 | expect(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); | ||
| 469 | expect(@typeId(AUnionEnum) == Tid.Union); | ||
| 470 | expect(@typeId(AUnion) == Tid.Union); | ||
| 471 | expect(@typeId(fn () void) == Tid.Fn); | ||
| 472 | expect(@typeId(@typeOf(builtin)) == Tid.Namespace); | ||
| 473 | // TODO bound fn | ||
| 474 | // TODO arg tuple | ||
| 475 | // TODO opaque | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | test "@typeName" { | ||
| 480 | const Struct = struct {}; | ||
| 481 | const Union = union { | ||
| 482 | unused: u8, | ||
| 483 | }; | ||
| 484 | const Enum = enum { | ||
| 485 | Unused, | ||
| 486 | }; | ||
| 487 | comptime { | ||
| 488 | expect(mem.eql(u8, @typeName(i64), "i64")); | ||
| 489 | expect(mem.eql(u8, @typeName(*usize), "*usize")); | ||
| 490 | // https://github.com/ziglang/zig/issues/675 | ||
| 491 | expect(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); | ||
| 492 | expect(mem.eql(u8, @typeName(Struct), "Struct")); | ||
| 493 | expect(mem.eql(u8, @typeName(Union), "Union")); | ||
| 494 | expect(mem.eql(u8, @typeName(Enum), "Enum")); | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | fn TypeFromFn(comptime T: type) type { | ||
| 499 | return struct {}; | ||
| 500 | } | ||
| 501 | |||
| 502 | test "double implicit cast in same expression" { | ||
| 503 | var x = i32(u16(nine())); | ||
| 504 | expect(x == 9); | ||
| 505 | } | ||
| 506 | fn nine() u8 { | ||
| 507 | return 9; | ||
| 508 | } | ||
| 509 | |||
| 510 | test "global variable initialized to global variable array element" { | ||
| 511 | expect(global_ptr == &gdt[0]); | ||
| 512 | } | ||
| 513 | const GDTEntry = struct { | ||
| 514 | field: i32, | ||
| 515 | }; | ||
| 516 | var gdt = []GDTEntry{ | ||
| 517 | GDTEntry{ .field = 1 }, | ||
| 518 | GDTEntry{ .field = 2 }, | ||
| 519 | }; | ||
| 520 | var global_ptr = &gdt[0]; | ||
| 521 | |||
| 522 | // can't really run this test but we can make sure it has no compile error | ||
| 523 | // and generates code | ||
| 524 | const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000]; | ||
| 525 | export fn writeToVRam() void { | ||
| 526 | vram[0] = 'X'; | ||
| 527 | } | ||
| 528 | |||
| 529 | const OpaqueA = @OpaqueType(); | ||
| 530 | const OpaqueB = @OpaqueType(); | ||
| 531 | test "@OpaqueType" { | ||
| 532 | expect(*OpaqueA != *OpaqueB); | ||
| 533 | expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); | ||
| 534 | expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); | ||
| 535 | } | ||
| 536 | |||
| 537 | test "variable is allowed to be a pointer to an opaque type" { | ||
| 538 | var x: i32 = 1234; | ||
| 539 | _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); | ||
| 540 | } | ||
| 541 | fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { | ||
| 542 | var a = ptr; | ||
| 543 | return a; | ||
| 544 | } | ||
| 545 | |||
| 546 | test "comptime if inside runtime while which unconditionally breaks" { | ||
| 547 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | ||
| 548 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | ||
| 549 | } | ||
| 550 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | ||
| 551 | while (cond) { | ||
| 552 | if (false) {} | ||
| 553 | break; | ||
| 554 | } | ||
| 555 | } | ||
| 556 | |||
| 557 | test "implicit comptime while" { | ||
| 558 | while (false) { | ||
| 559 | @compileError("bad"); | ||
| 560 | } | ||
| 561 | } | ||
| 562 | |||
| 563 | fn fnThatClosesOverLocalConst() type { | ||
| 564 | const c = 1; | ||
| 565 | return struct { | ||
| 566 | fn g() i32 { | ||
| 567 | return c; | ||
| 568 | } | ||
| 569 | }; | ||
| 570 | } | ||
| 571 | |||
| 572 | test "function closes over local const" { | ||
| 573 | const x = fnThatClosesOverLocalConst().g(); | ||
| 574 | expect(x == 1); | ||
| 575 | } | ||
| 576 | |||
| 577 | test "cold function" { | ||
| 578 | thisIsAColdFn(); | ||
| 579 | comptime thisIsAColdFn(); | ||
| 580 | } | ||
| 581 | |||
| 582 | fn thisIsAColdFn() void { | ||
| 583 | @setCold(true); | ||
| 584 | } | ||
| 585 | |||
| 586 | const PackedStruct = packed struct { | ||
| 587 | a: u8, | ||
| 588 | b: u8, | ||
| 589 | }; | ||
| 590 | const PackedUnion = packed union { | ||
| 591 | a: u8, | ||
| 592 | b: u32, | ||
| 593 | }; | ||
| 594 | const PackedEnum = packed enum { | ||
| 595 | A, | ||
| 596 | B, | ||
| 597 | }; | ||
| 598 | |||
| 599 | test "packed struct, enum, union parameters in extern function" { | ||
| 600 | testPackedStuff(&(PackedStruct{ | ||
| 601 | .a = 1, | ||
| 602 | .b = 2, | ||
| 603 | }), &(PackedUnion{ .a = 1 }), PackedEnum.A); | ||
| 604 | } | ||
| 605 | |||
| 606 | export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {} | ||
| 607 | |||
| 608 | test "slicing zero length array" { | ||
| 609 | const s1 = ""[0..]; | ||
| 610 | const s2 = ([]u32{})[0..]; | ||
| 611 | expect(s1.len == 0); | ||
| 612 | expect(s2.len == 0); | ||
| 613 | expect(mem.eql(u8, s1, "")); | ||
| 614 | expect(mem.eql(u32, s2, []u32{})); | ||
| 615 | } | ||
| 616 | |||
| 617 | const addr1 = @ptrCast(*const u8, emptyFn); | ||
| 618 | test "comptime cast fn to ptr" { | ||
| 619 | const addr2 = @ptrCast(*const u8, emptyFn); | ||
| 620 | comptime expect(addr1 == addr2); | ||
| 621 | } | ||
| 622 | |||
| 623 | test "equality compare fn ptrs" { | ||
| 624 | var a = emptyFn; | ||
| 625 | expect(a == a); | ||
| 626 | } | ||
| 627 | |||
| 628 | test "self reference through fn ptr field" { | ||
| 629 | const S = struct { | ||
| 630 | const A = struct { | ||
| 631 | f: fn (A) u8, | ||
| 632 | }; | ||
| 633 | |||
| 634 | fn foo(a: A) u8 { | ||
| 635 | return 12; | ||
| 636 | } | ||
| 637 | }; | ||
| 638 | var a: S.A = undefined; | ||
| 639 | a.f = S.foo; | ||
| 640 | expect(a.f(a) == 12); | ||
| 641 | } | ||
| 642 | |||
| 643 | test "volatile load and store" { | ||
| 644 | var number: i32 = 1234; | ||
| 645 | const ptr = (*volatile i32)(&number); | ||
| 646 | ptr.* += 1; | ||
| 647 | expect(ptr.* == 1235); | ||
| 648 | } | ||
| 649 | |||
| 650 | test "slice string literal has type []const u8" { | ||
| 651 | comptime { | ||
| 652 | expect(@typeOf("aoeu"[0..]) == []const u8); | ||
| 653 | const array = []i32{ 1, 2, 3, 4 }; | ||
| 654 | expect(@typeOf(array[0..]) == []const i32); | ||
| 655 | } | ||
| 656 | } | ||
| 657 | |||
| 658 | test "pointer child field" { | ||
| 659 | expect((*u32).Child == u32); | ||
| 660 | } | ||
| 661 | |||
| 662 | test "struct inside function" { | ||
| 663 | testStructInFn(); | ||
| 664 | comptime testStructInFn(); | ||
| 665 | } | ||
| 666 | |||
| 667 | fn testStructInFn() void { | ||
| 668 | const BlockKind = u32; | ||
| 669 | |||
| 670 | const Block = struct { | ||
| 671 | kind: BlockKind, | ||
| 672 | }; | ||
| 673 | |||
| 674 | var block = Block{ .kind = 1234 }; | ||
| 675 | |||
| 676 | block.kind += 1; | ||
| 677 | |||
| 678 | expect(block.kind == 1235); | ||
| 679 | } | ||
| 680 | |||
| 681 | test "fn call returning scalar optional in equality expression" { | ||
| 682 | expect(getNull() == null); | ||
| 683 | } | ||
| 684 | |||
| 685 | fn getNull() ?*i32 { | ||
| 686 | return null; | ||
| 687 | } | ||
| 688 | |||
| 689 | test "thread local variable" { | ||
| 690 | const S = struct { | ||
| 691 | threadlocal var t: i32 = 1234; | ||
| 692 | }; | ||
| 693 | S.t += 1; | ||
| 694 | expect(S.t == 1235); | ||
| 695 | } | ||
test/stage1/behavior/namespace_depends_on_compile_var/a.zig created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | pub const a_bool = true; | ||
test/stage1/behavior/namespace_depends_on_compile_var/b.zig created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | pub const a_bool = false; | ||
test/stage1/behavior/namespace_depends_on_compile_var/index.zig created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const expect = @import("std").testing.expect; | ||
| 3 | |||
| 4 | test "namespace depends on compile var" { | ||
| 5 | if (some_namespace.a_bool) { | ||
| 6 | expect(some_namespace.a_bool); | ||
| 7 | } else { | ||
| 8 | expect(!some_namespace.a_bool); | ||
| 9 | } | ||
| 10 | } | ||
| 11 | const some_namespace = switch (builtin.os) { | ||
| 12 | builtin.Os.linux => @import("a.zig"), | ||
| 13 | else => @import("b.zig"), | ||
| 14 | }; | ||
test/stage1/behavior/new_stack_call.zig created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | var new_stack_bytes: [1024]u8 = undefined; | ||
| 5 | |||
| 6 | test "calling a function with a new stack" { | ||
| 7 | const arg = 1234; | ||
| 8 | |||
| 9 | const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); | ||
| 10 | const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); | ||
| 11 | _ = targetFunction(arg); | ||
| 12 | |||
| 13 | expect(arg == 1234); | ||
| 14 | expect(a < b); | ||
| 15 | } | ||
| 16 | |||
| 17 | fn targetFunction(x: i32) usize { | ||
| 18 | expect(x == 1234); | ||
| 19 | |||
| 20 | var local_variable: i32 = 42; | ||
| 21 | const ptr = &local_variable; | ||
| 22 | ptr.* += 1; | ||
| 23 | |||
| 24 | expect(local_variable == 43); | ||
| 25 | return @ptrToInt(ptr); | ||
| 26 | } | ||
test/stage1/behavior/null.zig created+162| ... | @@ -0,0 +1,162 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "optional type" { | ||
| 4 | const x: ?bool = true; | ||
| 5 | |||
| 6 | if (x) |y| { | ||
| 7 | if (y) { | ||
| 8 | // OK | ||
| 9 | } else { | ||
| 10 | unreachable; | ||
| 11 | } | ||
| 12 | } else { | ||
| 13 | unreachable; | ||
| 14 | } | ||
| 15 | |||
| 16 | const next_x: ?i32 = null; | ||
| 17 | |||
| 18 | const z = next_x orelse 1234; | ||
| 19 | |||
| 20 | expect(z == 1234); | ||
| 21 | |||
| 22 | const final_x: ?i32 = 13; | ||
| 23 | |||
| 24 | const num = final_x orelse unreachable; | ||
| 25 | |||
| 26 | expect(num == 13); | ||
| 27 | } | ||
| 28 | |||
| 29 | test "test maybe object and get a pointer to the inner value" { | ||
| 30 | var maybe_bool: ?bool = true; | ||
| 31 | |||
| 32 | if (maybe_bool) |*b| { | ||
| 33 | b.* = false; | ||
| 34 | } | ||
| 35 | |||
| 36 | expect(maybe_bool.? == false); | ||
| 37 | } | ||
| 38 | |||
| 39 | test "rhs maybe unwrap return" { | ||
| 40 | const x: ?bool = true; | ||
| 41 | const y = x orelse return; | ||
| 42 | } | ||
| 43 | |||
| 44 | test "maybe return" { | ||
| 45 | maybeReturnImpl(); | ||
| 46 | comptime maybeReturnImpl(); | ||
| 47 | } | ||
| 48 | |||
| 49 | fn maybeReturnImpl() void { | ||
| 50 | expect(foo(1235).?); | ||
| 51 | if (foo(null) != null) unreachable; | ||
| 52 | expect(!foo(1234).?); | ||
| 53 | } | ||
| 54 | |||
| 55 | fn foo(x: ?i32) ?bool { | ||
| 56 | const value = x orelse return null; | ||
| 57 | return value > 1234; | ||
| 58 | } | ||
| 59 | |||
| 60 | test "if var maybe pointer" { | ||
| 61 | expect(shouldBeAPlus1(Particle{ | ||
| 62 | .a = 14, | ||
| 63 | .b = 1, | ||
| 64 | .c = 1, | ||
| 65 | .d = 1, | ||
| 66 | }) == 15); | ||
| 67 | } | ||
| 68 | fn shouldBeAPlus1(p: Particle) u64 { | ||
| 69 | var maybe_particle: ?Particle = p; | ||
| 70 | if (maybe_particle) |*particle| { | ||
| 71 | particle.a += 1; | ||
| 72 | } | ||
| 73 | if (maybe_particle) |particle| { | ||
| 74 | return particle.a; | ||
| 75 | } | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | const Particle = struct { | ||
| 79 | a: u64, | ||
| 80 | b: u64, | ||
| 81 | c: u64, | ||
| 82 | d: u64, | ||
| 83 | }; | ||
| 84 | |||
| 85 | test "null literal outside function" { | ||
| 86 | const is_null = here_is_a_null_literal.context == null; | ||
| 87 | expect(is_null); | ||
| 88 | |||
| 89 | const is_non_null = here_is_a_null_literal.context != null; | ||
| 90 | expect(!is_non_null); | ||
| 91 | } | ||
| 92 | const SillyStruct = struct { | ||
| 93 | context: ?i32, | ||
| 94 | }; | ||
| 95 | const here_is_a_null_literal = SillyStruct{ .context = null }; | ||
| 96 | |||
| 97 | test "test null runtime" { | ||
| 98 | testTestNullRuntime(null); | ||
| 99 | } | ||
| 100 | fn testTestNullRuntime(x: ?i32) void { | ||
| 101 | expect(x == null); | ||
| 102 | expect(!(x != null)); | ||
| 103 | } | ||
| 104 | |||
| 105 | test "optional void" { | ||
| 106 | optionalVoidImpl(); | ||
| 107 | comptime optionalVoidImpl(); | ||
| 108 | } | ||
| 109 | |||
| 110 | fn optionalVoidImpl() void { | ||
| 111 | expect(bar(null) == null); | ||
| 112 | expect(bar({}) != null); | ||
| 113 | } | ||
| 114 | |||
| 115 | fn bar(x: ?void) ?void { | ||
| 116 | if (x) |_| { | ||
| 117 | return {}; | ||
| 118 | } else { | ||
| 119 | return null; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | const StructWithOptional = struct { | ||
| 124 | field: ?i32, | ||
| 125 | }; | ||
| 126 | |||
| 127 | var struct_with_optional: StructWithOptional = undefined; | ||
| 128 | |||
| 129 | test "unwrap optional which is field of global var" { | ||
| 130 | struct_with_optional.field = null; | ||
| 131 | if (struct_with_optional.field) |payload| { | ||
| 132 | unreachable; | ||
| 133 | } | ||
| 134 | struct_with_optional.field = 1234; | ||
| 135 | if (struct_with_optional.field) |payload| { | ||
| 136 | expect(payload == 1234); | ||
| 137 | } else { | ||
| 138 | unreachable; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | test "null with default unwrap" { | ||
| 143 | const x: i32 = null orelse 1; | ||
| 144 | expect(x == 1); | ||
| 145 | } | ||
| 146 | |||
| 147 | test "optional types" { | ||
| 148 | comptime { | ||
| 149 | const opt_type_struct = StructWithOptionalType{ .t = u8 }; | ||
| 150 | expect(opt_type_struct.t != null and opt_type_struct.t.? == u8); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | const StructWithOptionalType = struct { | ||
| 155 | t: ?type, | ||
| 156 | }; | ||
| 157 | |||
| 158 | test "optional pointer to 0 bit type null value at runtime" { | ||
| 159 | const EmptyStruct = struct {}; | ||
| 160 | var x: ?*EmptyStruct = null; | ||
| 161 | expect(x == null); | ||
| 162 | } | ||
test/stage1/behavior/optional.zig created+81| ... | @@ -0,0 +1,81 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | pub const EmptyStruct = struct {}; | ||
| 4 | |||
| 5 | test "optional pointer to size zero struct" { | ||
| 6 | var e = EmptyStruct{}; | ||
| 7 | var o: ?*EmptyStruct = &e; | ||
| 8 | expect(o != null); | ||
| 9 | } | ||
| 10 | |||
| 11 | test "equality compare nullable pointers" { | ||
| 12 | testNullPtrsEql(); | ||
| 13 | comptime testNullPtrsEql(); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn testNullPtrsEql() void { | ||
| 17 | var number: i32 = 1234; | ||
| 18 | |||
| 19 | var x: ?*i32 = null; | ||
| 20 | var y: ?*i32 = null; | ||
| 21 | expect(x == y); | ||
| 22 | y = &number; | ||
| 23 | expect(x != y); | ||
| 24 | expect(x != &number); | ||
| 25 | expect(&number != x); | ||
| 26 | x = &number; | ||
| 27 | expect(x == y); | ||
| 28 | expect(x == &number); | ||
| 29 | expect(&number == x); | ||
| 30 | } | ||
| 31 | |||
| 32 | test "address of unwrap optional" { | ||
| 33 | const S = struct { | ||
| 34 | const Foo = struct { | ||
| 35 | a: i32, | ||
| 36 | }; | ||
| 37 | |||
| 38 | var global: ?Foo = null; | ||
| 39 | |||
| 40 | pub fn getFoo() anyerror!*Foo { | ||
| 41 | return &global.?; | ||
| 42 | } | ||
| 43 | }; | ||
| 44 | S.global = S.Foo{ .a = 1234 }; | ||
| 45 | const foo = S.getFoo() catch unreachable; | ||
| 46 | expect(foo.a == 1234); | ||
| 47 | } | ||
| 48 | |||
| 49 | test "passing an optional integer as a parameter" { | ||
| 50 | const S = struct { | ||
| 51 | fn entry() bool { | ||
| 52 | var x: i32 = 1234; | ||
| 53 | return foo(x); | ||
| 54 | } | ||
| 55 | |||
| 56 | fn foo(x: ?i32) bool { | ||
| 57 | return x.? == 1234; | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | expect(S.entry()); | ||
| 61 | comptime expect(S.entry()); | ||
| 62 | } | ||
| 63 | |||
| 64 | test "unwrap function call with optional pointer return value" { | ||
| 65 | const S = struct { | ||
| 66 | fn entry() void { | ||
| 67 | expect(foo().?.* == 1234); | ||
| 68 | expect(bar() == null); | ||
| 69 | } | ||
| 70 | const global: i32 = 1234; | ||
| 71 | fn foo() ?*const i32 { | ||
| 72 | return &global; | ||
| 73 | } | ||
| 74 | fn bar() ?*i32 { | ||
| 75 | return null; | ||
| 76 | } | ||
| 77 | }; | ||
| 78 | S.entry(); | ||
| 79 | // TODO https://github.com/ziglang/zig/issues/1901 | ||
| 80 | //comptime S.entry(); | ||
| 81 | } | ||
test/stage1/behavior/pointers.zig created+126| ... | @@ -0,0 +1,126 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const expectError = std.testing.expectError; | ||
| 4 | |||
| 5 | test "dereference pointer" { | ||
| 6 | comptime testDerefPtr(); | ||
| 7 | testDerefPtr(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testDerefPtr() void { | ||
| 11 | var x: i32 = 1234; | ||
| 12 | var y = &x; | ||
| 13 | y.* += 1; | ||
| 14 | expect(x == 1235); | ||
| 15 | } | ||
| 16 | |||
| 17 | test "pointer arithmetic" { | ||
| 18 | var ptr = c"abcd"; | ||
| 19 | |||
| 20 | expect(ptr[0] == 'a'); | ||
| 21 | ptr += 1; | ||
| 22 | expect(ptr[0] == 'b'); | ||
| 23 | ptr += 1; | ||
| 24 | expect(ptr[0] == 'c'); | ||
| 25 | ptr += 1; | ||
| 26 | expect(ptr[0] == 'd'); | ||
| 27 | ptr += 1; | ||
| 28 | expect(ptr[0] == 0); | ||
| 29 | ptr -= 1; | ||
| 30 | expect(ptr[0] == 'd'); | ||
| 31 | ptr -= 1; | ||
| 32 | expect(ptr[0] == 'c'); | ||
| 33 | ptr -= 1; | ||
| 34 | expect(ptr[0] == 'b'); | ||
| 35 | ptr -= 1; | ||
| 36 | expect(ptr[0] == 'a'); | ||
| 37 | } | ||
| 38 | |||
| 39 | test "double pointer parsing" { | ||
| 40 | comptime expect(PtrOf(PtrOf(i32)) == **i32); | ||
| 41 | } | ||
| 42 | |||
| 43 | fn PtrOf(comptime T: type) type { | ||
| 44 | return *T; | ||
| 45 | } | ||
| 46 | |||
| 47 | test "assigning integer to C pointer" { | ||
| 48 | var x: i32 = 0; | ||
| 49 | var ptr: [*c]u8 = 0; | ||
| 50 | var ptr2: [*c]u8 = x; | ||
| 51 | } | ||
| 52 | |||
| 53 | test "implicit cast single item pointer to C pointer and back" { | ||
| 54 | var y: u8 = 11; | ||
| 55 | var x: [*c]u8 = &y; | ||
| 56 | var z: *u8 = x; | ||
| 57 | z.* += 1; | ||
| 58 | expect(y == 12); | ||
| 59 | } | ||
| 60 | |||
| 61 | test "C pointer comparison and arithmetic" { | ||
| 62 | const S = struct { | ||
| 63 | fn doTheTest() void { | ||
| 64 | var one: usize = 1; | ||
| 65 | var ptr1: [*c]u32 = 0; | ||
| 66 | var ptr2 = ptr1 + 10; | ||
| 67 | expect(ptr1 == 0); | ||
| 68 | expect(ptr1 >= 0); | ||
| 69 | expect(ptr1 <= 0); | ||
| 70 | expect(ptr1 < 1); | ||
| 71 | expect(ptr1 < one); | ||
| 72 | expect(1 > ptr1); | ||
| 73 | expect(one > ptr1); | ||
| 74 | expect(ptr1 < ptr2); | ||
| 75 | expect(ptr2 > ptr1); | ||
| 76 | expect(ptr2 >= 40); | ||
| 77 | expect(ptr2 == 40); | ||
| 78 | expect(ptr2 <= 40); | ||
| 79 | ptr2 -= 10; | ||
| 80 | expect(ptr1 == ptr2); | ||
| 81 | } | ||
| 82 | }; | ||
| 83 | S.doTheTest(); | ||
| 84 | comptime S.doTheTest(); | ||
| 85 | } | ||
| 86 | |||
| 87 | test "peer type resolution with C pointers" { | ||
| 88 | var ptr_one: *u8 = undefined; | ||
| 89 | var ptr_many: [*]u8 = undefined; | ||
| 90 | var ptr_c: [*c]u8 = undefined; | ||
| 91 | var t = true; | ||
| 92 | var x1 = if (t) ptr_one else ptr_c; | ||
| 93 | var x2 = if (t) ptr_many else ptr_c; | ||
| 94 | var x3 = if (t) ptr_c else ptr_one; | ||
| 95 | var x4 = if (t) ptr_c else ptr_many; | ||
| 96 | expect(@typeOf(x1) == [*c]u8); | ||
| 97 | expect(@typeOf(x2) == [*c]u8); | ||
| 98 | expect(@typeOf(x3) == [*c]u8); | ||
| 99 | expect(@typeOf(x4) == [*c]u8); | ||
| 100 | } | ||
| 101 | |||
| 102 | test "implicit casting between C pointer and optional non-C pointer" { | ||
| 103 | var slice: []const u8 = "aoeu"; | ||
| 104 | const opt_many_ptr: ?[*]const u8 = slice.ptr; | ||
| 105 | var ptr_opt_many_ptr = &opt_many_ptr; | ||
| 106 | var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr; | ||
| 107 | expect(c_ptr.*.* == 'a'); | ||
| 108 | ptr_opt_many_ptr = c_ptr; | ||
| 109 | expect(ptr_opt_many_ptr.*.?[1] == 'o'); | ||
| 110 | } | ||
| 111 | |||
| 112 | test "implicit cast error unions with non-optional to optional pointer" { | ||
| 113 | const S = struct { | ||
| 114 | fn doTheTest() void { | ||
| 115 | expectError(error.Fail, foo()); | ||
| 116 | } | ||
| 117 | fn foo() anyerror!?*u8 { | ||
| 118 | return bar() orelse error.Fail; | ||
| 119 | } | ||
| 120 | fn bar() ?*u8 { | ||
| 121 | return null; | ||
| 122 | } | ||
| 123 | }; | ||
| 124 | S.doTheTest(); | ||
| 125 | comptime S.doTheTest(); | ||
| 126 | } | ||
test/stage1/behavior/popcount.zig created+25| ... | @@ -0,0 +1,25 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "@popCount" { | ||
| 4 | comptime testPopCount(); | ||
| 5 | testPopCount(); | ||
| 6 | } | ||
| 7 | |||
| 8 | fn testPopCount() void { | ||
| 9 | { | ||
| 10 | var x: u32 = 0xaa; | ||
| 11 | expect(@popCount(x) == 4); | ||
| 12 | } | ||
| 13 | { | ||
| 14 | var x: u32 = 0xaaaaaaaa; | ||
| 15 | expect(@popCount(x) == 16); | ||
| 16 | } | ||
| 17 | { | ||
| 18 | var x: i16 = -1; | ||
| 19 | expect(@popCount(x) == 16); | ||
| 20 | } | ||
| 21 | comptime { | ||
| 22 | expect(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
test/stage1/behavior/ptrcast.zig created+52| ... | @@ -0,0 +1,52 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | test "reinterpret bytes as integer with nonzero offset" { | ||
| 6 | testReinterpretBytesAsInteger(); | ||
| 7 | comptime testReinterpretBytesAsInteger(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn testReinterpretBytesAsInteger() void { | ||
| 11 | const bytes = "\x12\x34\x56\x78\xab"; | ||
| 12 | const expected = switch (builtin.endian) { | ||
| 13 | builtin.Endian.Little => 0xab785634, | ||
| 14 | builtin.Endian.Big => 0x345678ab, | ||
| 15 | }; | ||
| 16 | expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); | ||
| 17 | } | ||
| 18 | |||
| 19 | test "reinterpret bytes of an array into an extern struct" { | ||
| 20 | testReinterpretBytesAsExternStruct(); | ||
| 21 | comptime testReinterpretBytesAsExternStruct(); | ||
| 22 | } | ||
| 23 | |||
| 24 | fn testReinterpretBytesAsExternStruct() void { | ||
| 25 | var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 }; | ||
| 26 | |||
| 27 | const S = extern struct { | ||
| 28 | a: u8, | ||
| 29 | b: u16, | ||
| 30 | c: u8, | ||
| 31 | }; | ||
| 32 | |||
| 33 | var ptr = @ptrCast(*const S, &bytes); | ||
| 34 | var val = ptr.c; | ||
| 35 | expect(val == 5); | ||
| 36 | } | ||
| 37 | |||
| 38 | test "reinterpret struct field at comptime" { | ||
| 39 | const numLittle = comptime Bytes.init(0x12345678); | ||
| 40 | expect(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes)); | ||
| 41 | } | ||
| 42 | |||
| 43 | const Bytes = struct { | ||
| 44 | bytes: [4]u8, | ||
| 45 | |||
| 46 | pub fn init(v: u32) Bytes { | ||
| 47 | var res: Bytes = undefined; | ||
| 48 | @ptrCast(*align(1) u32, &res.bytes).* = v; | ||
| 49 | |||
| 50 | return res; | ||
| 51 | } | ||
| 52 | }; | ||
test/stage1/behavior/pub_enum/index.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const other = @import("other.zig"); | ||
| 2 | const expect = @import("std").testing.expect; | ||
| 3 | |||
| 4 | test "pub enum" { | ||
| 5 | pubEnumTest(other.APubEnum.Two); | ||
| 6 | } | ||
| 7 | fn pubEnumTest(foo: other.APubEnum) void { | ||
| 8 | expect(foo == other.APubEnum.Two); | ||
| 9 | } | ||
| 10 | |||
| 11 | test "cast with imported symbol" { | ||
| 12 | expect(other.size_t(42) == 42); | ||
| 13 | } | ||
test/stage1/behavior/pub_enum/other.zig created+6| ... | @@ -0,0 +1,6 @@ | ||
| 1 | pub const APubEnum = enum { | ||
| 2 | One, | ||
| 3 | Two, | ||
| 4 | Three, | ||
| 5 | }; | ||
| 6 | pub const size_t = u64; | ||
test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | var ok: bool = false; | ||
| 5 | test "reference a variable in an if after an if in the 2nd switch prong" { | ||
| 6 | foo(true, Num.Two, false, "aoeu"); | ||
| 7 | expect(!ok); | ||
| 8 | foo(false, Num.One, false, "aoeu"); | ||
| 9 | expect(!ok); | ||
| 10 | foo(true, Num.One, false, "aoeu"); | ||
| 11 | expect(ok); | ||
| 12 | } | ||
| 13 | |||
| 14 | const Num = enum { | ||
| 15 | One, | ||
| 16 | Two, | ||
| 17 | }; | ||
| 18 | |||
| 19 | fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { | ||
| 20 | switch (k) { | ||
| 21 | Num.Two => {}, | ||
| 22 | Num.One => { | ||
| 23 | if (c) { | ||
| 24 | const output_path = b; | ||
| 25 | |||
| 26 | if (c2) {} | ||
| 27 | |||
| 28 | a(output_path); | ||
| 29 | } | ||
| 30 | }, | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | fn a(x: []const u8) void { | ||
| 35 | expect(mem.eql(u8, x, "aoeu")); | ||
| 36 | ok = true; | ||
| 37 | } | ||
test/stage1/behavior/reflection.zig created+96| ... | @@ -0,0 +1,96 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | const reflection = @This(); | ||
| 4 | |||
| 5 | test "reflection: array, pointer, optional, error union type child" { | ||
| 6 | comptime { | ||
| 7 | expect(([10]u8).Child == u8); | ||
| 8 | expect((*u8).Child == u8); | ||
| 9 | expect((anyerror!u8).Payload == u8); | ||
| 10 | expect((?u8).Child == u8); | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | test "reflection: function return type, var args, and param types" { | ||
| 15 | comptime { | ||
| 16 | expect(@typeOf(dummy).ReturnType == i32); | ||
| 17 | expect(!@typeOf(dummy).is_var_args); | ||
| 18 | expect(@typeOf(dummy_varargs).is_var_args); | ||
| 19 | expect(@typeOf(dummy).arg_count == 3); | ||
| 20 | expect(@ArgType(@typeOf(dummy), 0) == bool); | ||
| 21 | expect(@ArgType(@typeOf(dummy), 1) == i32); | ||
| 22 | expect(@ArgType(@typeOf(dummy), 2) == f32); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | fn dummy(a: bool, b: i32, c: f32) i32 { | ||
| 27 | return 1234; | ||
| 28 | } | ||
| 29 | fn dummy_varargs(args: ...) void {} | ||
| 30 | |||
| 31 | test "reflection: struct member types and names" { | ||
| 32 | comptime { | ||
| 33 | expect(@memberCount(Foo) == 3); | ||
| 34 | |||
| 35 | expect(@memberType(Foo, 0) == i32); | ||
| 36 | expect(@memberType(Foo, 1) == bool); | ||
| 37 | expect(@memberType(Foo, 2) == void); | ||
| 38 | |||
| 39 | expect(mem.eql(u8, @memberName(Foo, 0), "one")); | ||
| 40 | expect(mem.eql(u8, @memberName(Foo, 1), "two")); | ||
| 41 | expect(mem.eql(u8, @memberName(Foo, 2), "three")); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | test "reflection: enum member types and names" { | ||
| 46 | comptime { | ||
| 47 | expect(@memberCount(Bar) == 4); | ||
| 48 | |||
| 49 | expect(@memberType(Bar, 0) == void); | ||
| 50 | expect(@memberType(Bar, 1) == i32); | ||
| 51 | expect(@memberType(Bar, 2) == bool); | ||
| 52 | expect(@memberType(Bar, 3) == f64); | ||
| 53 | |||
| 54 | expect(mem.eql(u8, @memberName(Bar, 0), "One")); | ||
| 55 | expect(mem.eql(u8, @memberName(Bar, 1), "Two")); | ||
| 56 | expect(mem.eql(u8, @memberName(Bar, 2), "Three")); | ||
| 57 | expect(mem.eql(u8, @memberName(Bar, 3), "Four")); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | test "reflection: @field" { | ||
| 62 | var f = Foo{ | ||
| 63 | .one = 42, | ||
| 64 | .two = true, | ||
| 65 | .three = void{}, | ||
| 66 | }; | ||
| 67 | |||
| 68 | expect(f.one == f.one); | ||
| 69 | expect(@field(f, "o" ++ "ne") == f.one); | ||
| 70 | expect(@field(f, "t" ++ "wo") == f.two); | ||
| 71 | expect(@field(f, "th" ++ "ree") == f.three); | ||
| 72 | expect(@field(Foo, "const" ++ "ant") == Foo.constant); | ||
| 73 | expect(@field(Bar, "O" ++ "ne") == Bar.One); | ||
| 74 | expect(@field(Bar, "T" ++ "wo") == Bar.Two); | ||
| 75 | expect(@field(Bar, "Th" ++ "ree") == Bar.Three); | ||
| 76 | expect(@field(Bar, "F" ++ "our") == Bar.Four); | ||
| 77 | expect(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); | ||
| 78 | @field(f, "o" ++ "ne") = 4; | ||
| 79 | expect(f.one == 4); | ||
| 80 | } | ||
| 81 | |||
| 82 | const Foo = struct { | ||
| 83 | const constant = 52; | ||
| 84 | |||
| 85 | one: i32, | ||
| 86 | two: bool, | ||
| 87 | three: void, | ||
| 88 | }; | ||
| 89 | |||
| 90 | const Bar = union(enum) { | ||
| 91 | One: void, | ||
| 92 | Two: i32, | ||
| 93 | Three: bool, | ||
| 94 | Four: f64, | ||
| 95 | }; | ||
| 96 | |||
test/stage1/behavior/sizeof_and_typeof.zig created+69| ... | @@ -0,0 +1,69 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const expect = @import("std").testing.expect; | ||
| 3 | |||
| 4 | test "@sizeOf and @typeOf" { | ||
| 5 | const y: @typeOf(x) = 120; | ||
| 6 | expect(@sizeOf(@typeOf(y)) == 2); | ||
| 7 | } | ||
| 8 | const x: u16 = 13; | ||
| 9 | const z: @typeOf(x) = 19; | ||
| 10 | |||
| 11 | const A = struct { | ||
| 12 | a: u8, | ||
| 13 | b: u32, | ||
| 14 | c: u8, | ||
| 15 | d: u3, | ||
| 16 | e: u5, | ||
| 17 | f: u16, | ||
| 18 | g: u16, | ||
| 19 | }; | ||
| 20 | |||
| 21 | const P = packed struct { | ||
| 22 | a: u8, | ||
| 23 | b: u32, | ||
| 24 | c: u8, | ||
| 25 | d: u3, | ||
| 26 | e: u5, | ||
| 27 | f: u16, | ||
| 28 | g: u16, | ||
| 29 | }; | ||
| 30 | |||
| 31 | test "@byteOffsetOf" { | ||
| 32 | // Packed structs have fixed memory layout | ||
| 33 | expect(@byteOffsetOf(P, "a") == 0); | ||
| 34 | expect(@byteOffsetOf(P, "b") == 1); | ||
| 35 | expect(@byteOffsetOf(P, "c") == 5); | ||
| 36 | expect(@byteOffsetOf(P, "d") == 6); | ||
| 37 | expect(@byteOffsetOf(P, "e") == 6); | ||
| 38 | expect(@byteOffsetOf(P, "f") == 7); | ||
| 39 | expect(@byteOffsetOf(P, "g") == 9); | ||
| 40 | |||
| 41 | // Normal struct fields can be moved/padded | ||
| 42 | var a: A = undefined; | ||
| 43 | expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a")); | ||
| 44 | expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b")); | ||
| 45 | expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c")); | ||
| 46 | expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d")); | ||
| 47 | expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e")); | ||
| 48 | expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f")); | ||
| 49 | expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g")); | ||
| 50 | } | ||
| 51 | |||
| 52 | test "@bitOffsetOf" { | ||
| 53 | // Packed structs have fixed memory layout | ||
| 54 | expect(@bitOffsetOf(P, "a") == 0); | ||
| 55 | expect(@bitOffsetOf(P, "b") == 8); | ||
| 56 | expect(@bitOffsetOf(P, "c") == 40); | ||
| 57 | expect(@bitOffsetOf(P, "d") == 48); | ||
| 58 | expect(@bitOffsetOf(P, "e") == 51); | ||
| 59 | expect(@bitOffsetOf(P, "f") == 56); | ||
| 60 | expect(@bitOffsetOf(P, "g") == 72); | ||
| 61 | |||
| 62 | expect(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); | ||
| 63 | expect(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); | ||
| 64 | expect(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); | ||
| 65 | expect(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); | ||
| 66 | expect(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); | ||
| 67 | expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); | ||
| 68 | expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); | ||
| 69 | } | ||
test/stage1/behavior/slice.zig created+40| ... | @@ -0,0 +1,40 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | ||
| 5 | const y = x[0x100..]; | ||
| 6 | test "compile time slice of pointer to hard coded address" { | ||
| 7 | expect(@ptrToInt(x.ptr) == 0x1000); | ||
| 8 | expect(x.len == 0x500); | ||
| 9 | |||
| 10 | expect(@ptrToInt(y.ptr) == 0x1100); | ||
| 11 | expect(y.len == 0x400); | ||
| 12 | } | ||
| 13 | |||
| 14 | test "slice child property" { | ||
| 15 | var array: [5]i32 = undefined; | ||
| 16 | var slice = array[0..]; | ||
| 17 | expect(@typeOf(slice).Child == i32); | ||
| 18 | } | ||
| 19 | |||
| 20 | test "runtime safety lets us slice from len..len" { | ||
| 21 | var an_array = []u8{ | ||
| 22 | 1, | ||
| 23 | 2, | ||
| 24 | 3, | ||
| 25 | }; | ||
| 26 | expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); | ||
| 27 | } | ||
| 28 | |||
| 29 | fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { | ||
| 30 | return a_slice[start..end]; | ||
| 31 | } | ||
| 32 | |||
| 33 | test "implicitly cast array of size 0 to slice" { | ||
| 34 | var msg = []u8{}; | ||
| 35 | assertLenIsZero(msg); | ||
| 36 | } | ||
| 37 | |||
| 38 | fn assertLenIsZero(msg: []const u8) void { | ||
| 39 | expect(msg.len == 0); | ||
| 40 | } | ||
test/stage1/behavior/struct.zig created+470| ... | @@ -0,0 +1,470 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const maxInt = std.math.maxInt; | ||
| 5 | |||
| 6 | const StructWithNoFields = struct { | ||
| 7 | fn add(a: i32, b: i32) i32 { | ||
| 8 | return a + b; | ||
| 9 | } | ||
| 10 | }; | ||
| 11 | const empty_global_instance = StructWithNoFields{}; | ||
| 12 | |||
| 13 | test "call struct static method" { | ||
| 14 | const result = StructWithNoFields.add(3, 4); | ||
| 15 | expect(result == 7); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "return empty struct instance" { | ||
| 19 | _ = returnEmptyStructInstance(); | ||
| 20 | } | ||
| 21 | fn returnEmptyStructInstance() StructWithNoFields { | ||
| 22 | return empty_global_instance; | ||
| 23 | } | ||
| 24 | |||
| 25 | const should_be_11 = StructWithNoFields.add(5, 6); | ||
| 26 | |||
| 27 | test "invoke static method in global scope" { | ||
| 28 | expect(should_be_11 == 11); | ||
| 29 | } | ||
| 30 | |||
| 31 | test "void struct fields" { | ||
| 32 | const foo = VoidStructFieldsFoo{ | ||
| 33 | .a = void{}, | ||
| 34 | .b = 1, | ||
| 35 | .c = void{}, | ||
| 36 | }; | ||
| 37 | expect(foo.b == 1); | ||
| 38 | expect(@sizeOf(VoidStructFieldsFoo) == 4); | ||
| 39 | } | ||
| 40 | const VoidStructFieldsFoo = struct { | ||
| 41 | a: void, | ||
| 42 | b: i32, | ||
| 43 | c: void, | ||
| 44 | }; | ||
| 45 | |||
| 46 | test "structs" { | ||
| 47 | var foo: StructFoo = undefined; | ||
| 48 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | ||
| 49 | foo.a += 1; | ||
| 50 | foo.b = foo.a == 1; | ||
| 51 | testFoo(foo); | ||
| 52 | testMutation(&foo); | ||
| 53 | expect(foo.c == 100); | ||
| 54 | } | ||
| 55 | const StructFoo = struct { | ||
| 56 | a: i32, | ||
| 57 | b: bool, | ||
| 58 | c: f32, | ||
| 59 | }; | ||
| 60 | fn testFoo(foo: StructFoo) void { | ||
| 61 | expect(foo.b); | ||
| 62 | } | ||
| 63 | fn testMutation(foo: *StructFoo) void { | ||
| 64 | foo.c = 100; | ||
| 65 | } | ||
| 66 | |||
| 67 | const Node = struct { | ||
| 68 | val: Val, | ||
| 69 | next: *Node, | ||
| 70 | }; | ||
| 71 | |||
| 72 | const Val = struct { | ||
| 73 | x: i32, | ||
| 74 | }; | ||
| 75 | |||
| 76 | test "struct point to self" { | ||
| 77 | var root: Node = undefined; | ||
| 78 | root.val.x = 1; | ||
| 79 | |||
| 80 | var node: Node = undefined; | ||
| 81 | node.next = &root; | ||
| 82 | node.val.x = 2; | ||
| 83 | |||
| 84 | root.next = &node; | ||
| 85 | |||
| 86 | expect(node.next.next.next.val.x == 1); | ||
| 87 | } | ||
| 88 | |||
| 89 | test "struct byval assign" { | ||
| 90 | var foo1: StructFoo = undefined; | ||
| 91 | var foo2: StructFoo = undefined; | ||
| 92 | |||
| 93 | foo1.a = 1234; | ||
| 94 | foo2.a = 0; | ||
| 95 | expect(foo2.a == 0); | ||
| 96 | foo2 = foo1; | ||
| 97 | expect(foo2.a == 1234); | ||
| 98 | } | ||
| 99 | |||
| 100 | fn structInitializer() void { | ||
| 101 | const val = Val{ .x = 42 }; | ||
| 102 | expect(val.x == 42); | ||
| 103 | } | ||
| 104 | |||
| 105 | test "fn call of struct field" { | ||
| 106 | expect(callStructField(Foo{ .ptr = aFunc }) == 13); | ||
| 107 | } | ||
| 108 | |||
| 109 | const Foo = struct { | ||
| 110 | ptr: fn () i32, | ||
| 111 | }; | ||
| 112 | |||
| 113 | fn aFunc() i32 { | ||
| 114 | return 13; | ||
| 115 | } | ||
| 116 | |||
| 117 | fn callStructField(foo: Foo) i32 { | ||
| 118 | return foo.ptr(); | ||
| 119 | } | ||
| 120 | |||
| 121 | test "store member function in variable" { | ||
| 122 | const instance = MemberFnTestFoo{ .x = 1234 }; | ||
| 123 | const memberFn = MemberFnTestFoo.member; | ||
| 124 | const result = memberFn(instance); | ||
| 125 | expect(result == 1234); | ||
| 126 | } | ||
| 127 | const MemberFnTestFoo = struct { | ||
| 128 | x: i32, | ||
| 129 | fn member(foo: MemberFnTestFoo) i32 { | ||
| 130 | return foo.x; | ||
| 131 | } | ||
| 132 | }; | ||
| 133 | |||
| 134 | test "call member function directly" { | ||
| 135 | const instance = MemberFnTestFoo{ .x = 1234 }; | ||
| 136 | const result = MemberFnTestFoo.member(instance); | ||
| 137 | expect(result == 1234); | ||
| 138 | } | ||
| 139 | |||
| 140 | test "member functions" { | ||
| 141 | const r = MemberFnRand{ .seed = 1234 }; | ||
| 142 | expect(r.getSeed() == 1234); | ||
| 143 | } | ||
| 144 | const MemberFnRand = struct { | ||
| 145 | seed: u32, | ||
| 146 | pub fn getSeed(r: *const MemberFnRand) u32 { | ||
| 147 | return r.seed; | ||
| 148 | } | ||
| 149 | }; | ||
| 150 | |||
| 151 | test "return struct byval from function" { | ||
| 152 | const bar = makeBar(1234, 5678); | ||
| 153 | expect(bar.y == 5678); | ||
| 154 | } | ||
| 155 | const Bar = struct { | ||
| 156 | x: i32, | ||
| 157 | y: i32, | ||
| 158 | }; | ||
| 159 | fn makeBar(x: i32, y: i32) Bar { | ||
| 160 | return Bar{ | ||
| 161 | .x = x, | ||
| 162 | .y = y, | ||
| 163 | }; | ||
| 164 | } | ||
| 165 | |||
| 166 | test "empty struct method call" { | ||
| 167 | const es = EmptyStruct{}; | ||
| 168 | expect(es.method() == 1234); | ||
| 169 | } | ||
| 170 | const EmptyStruct = struct { | ||
| 171 | fn method(es: *const EmptyStruct) i32 { | ||
| 172 | return 1234; | ||
| 173 | } | ||
| 174 | }; | ||
| 175 | |||
| 176 | test "return empty struct from fn" { | ||
| 177 | _ = testReturnEmptyStructFromFn(); | ||
| 178 | } | ||
| 179 | const EmptyStruct2 = struct {}; | ||
| 180 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | ||
| 181 | return EmptyStruct2{}; | ||
| 182 | } | ||
| 183 | |||
| 184 | test "pass slice of empty struct to fn" { | ||
| 185 | expect(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); | ||
| 186 | } | ||
| 187 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | ||
| 188 | return slice.len; | ||
| 189 | } | ||
| 190 | |||
| 191 | const APackedStruct = packed struct { | ||
| 192 | x: u8, | ||
| 193 | y: u8, | ||
| 194 | }; | ||
| 195 | |||
| 196 | test "packed struct" { | ||
| 197 | var foo = APackedStruct{ | ||
| 198 | .x = 1, | ||
| 199 | .y = 2, | ||
| 200 | }; | ||
| 201 | foo.y += 1; | ||
| 202 | const four = foo.x + foo.y; | ||
| 203 | expect(four == 4); | ||
| 204 | } | ||
| 205 | |||
| 206 | const BitField1 = packed struct { | ||
| 207 | a: u3, | ||
| 208 | b: u3, | ||
| 209 | c: u2, | ||
| 210 | }; | ||
| 211 | |||
| 212 | const bit_field_1 = BitField1{ | ||
| 213 | .a = 1, | ||
| 214 | .b = 2, | ||
| 215 | .c = 3, | ||
| 216 | }; | ||
| 217 | |||
| 218 | test "bit field access" { | ||
| 219 | var data = bit_field_1; | ||
| 220 | expect(getA(&data) == 1); | ||
| 221 | expect(getB(&data) == 2); | ||
| 222 | expect(getC(&data) == 3); | ||
| 223 | comptime expect(@sizeOf(BitField1) == 1); | ||
| 224 | |||
| 225 | data.b += 1; | ||
| 226 | expect(data.b == 3); | ||
| 227 | |||
| 228 | data.a += 1; | ||
| 229 | expect(data.a == 2); | ||
| 230 | expect(data.b == 3); | ||
| 231 | } | ||
| 232 | |||
| 233 | fn getA(data: *const BitField1) u3 { | ||
| 234 | return data.a; | ||
| 235 | } | ||
| 236 | |||
| 237 | fn getB(data: *const BitField1) u3 { | ||
| 238 | return data.b; | ||
| 239 | } | ||
| 240 | |||
| 241 | fn getC(data: *const BitField1) u2 { | ||
| 242 | return data.c; | ||
| 243 | } | ||
| 244 | |||
| 245 | const Foo24Bits = packed struct { | ||
| 246 | field: u24, | ||
| 247 | }; | ||
| 248 | const Foo96Bits = packed struct { | ||
| 249 | a: u24, | ||
| 250 | b: u24, | ||
| 251 | c: u24, | ||
| 252 | d: u24, | ||
| 253 | }; | ||
| 254 | |||
| 255 | test "packed struct 24bits" { | ||
| 256 | comptime { | ||
| 257 | expect(@sizeOf(Foo24Bits) == 3); | ||
| 258 | expect(@sizeOf(Foo96Bits) == 12); | ||
| 259 | } | ||
| 260 | |||
| 261 | var value = Foo96Bits{ | ||
| 262 | .a = 0, | ||
| 263 | .b = 0, | ||
| 264 | .c = 0, | ||
| 265 | .d = 0, | ||
| 266 | }; | ||
| 267 | value.a += 1; | ||
| 268 | expect(value.a == 1); | ||
| 269 | expect(value.b == 0); | ||
| 270 | expect(value.c == 0); | ||
| 271 | expect(value.d == 0); | ||
| 272 | |||
| 273 | value.b += 1; | ||
| 274 | expect(value.a == 1); | ||
| 275 | expect(value.b == 1); | ||
| 276 | expect(value.c == 0); | ||
| 277 | expect(value.d == 0); | ||
| 278 | |||
| 279 | value.c += 1; | ||
| 280 | expect(value.a == 1); | ||
| 281 | expect(value.b == 1); | ||
| 282 | expect(value.c == 1); | ||
| 283 | expect(value.d == 0); | ||
| 284 | |||
| 285 | value.d += 1; | ||
| 286 | expect(value.a == 1); | ||
| 287 | expect(value.b == 1); | ||
| 288 | expect(value.c == 1); | ||
| 289 | expect(value.d == 1); | ||
| 290 | } | ||
| 291 | |||
| 292 | const FooArray24Bits = packed struct { | ||
| 293 | a: u16, | ||
| 294 | b: [2]Foo24Bits, | ||
| 295 | c: u16, | ||
| 296 | }; | ||
| 297 | |||
| 298 | test "packed array 24bits" { | ||
| 299 | comptime { | ||
| 300 | expect(@sizeOf([9]Foo24Bits) == 9 * 3); | ||
| 301 | expect(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); | ||
| 302 | } | ||
| 303 | |||
| 304 | var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); | ||
| 305 | bytes[bytes.len - 1] = 0xaa; | ||
| 306 | const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; | ||
| 307 | expect(ptr.a == 0); | ||
| 308 | expect(ptr.b[0].field == 0); | ||
| 309 | expect(ptr.b[1].field == 0); | ||
| 310 | expect(ptr.c == 0); | ||
| 311 | |||
| 312 | ptr.a = maxInt(u16); | ||
| 313 | expect(ptr.a == maxInt(u16)); | ||
| 314 | expect(ptr.b[0].field == 0); | ||
| 315 | expect(ptr.b[1].field == 0); | ||
| 316 | expect(ptr.c == 0); | ||
| 317 | |||
| 318 | ptr.b[0].field = maxInt(u24); | ||
| 319 | expect(ptr.a == maxInt(u16)); | ||
| 320 | expect(ptr.b[0].field == maxInt(u24)); | ||
| 321 | expect(ptr.b[1].field == 0); | ||
| 322 | expect(ptr.c == 0); | ||
| 323 | |||
| 324 | ptr.b[1].field = maxInt(u24); | ||
| 325 | expect(ptr.a == maxInt(u16)); | ||
| 326 | expect(ptr.b[0].field == maxInt(u24)); | ||
| 327 | expect(ptr.b[1].field == maxInt(u24)); | ||
| 328 | expect(ptr.c == 0); | ||
| 329 | |||
| 330 | ptr.c = maxInt(u16); | ||
| 331 | expect(ptr.a == maxInt(u16)); | ||
| 332 | expect(ptr.b[0].field == maxInt(u24)); | ||
| 333 | expect(ptr.b[1].field == maxInt(u24)); | ||
| 334 | expect(ptr.c == maxInt(u16)); | ||
| 335 | |||
| 336 | expect(bytes[bytes.len - 1] == 0xaa); | ||
| 337 | } | ||
| 338 | |||
| 339 | const FooStructAligned = packed struct { | ||
| 340 | a: u8, | ||
| 341 | b: u8, | ||
| 342 | }; | ||
| 343 | |||
| 344 | const FooArrayOfAligned = packed struct { | ||
| 345 | a: [2]FooStructAligned, | ||
| 346 | }; | ||
| 347 | |||
| 348 | test "aligned array of packed struct" { | ||
| 349 | comptime { | ||
| 350 | expect(@sizeOf(FooStructAligned) == 2); | ||
| 351 | expect(@sizeOf(FooArrayOfAligned) == 2 * 2); | ||
| 352 | } | ||
| 353 | |||
| 354 | var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); | ||
| 355 | const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; | ||
| 356 | |||
| 357 | expect(ptr.a[0].a == 0xbb); | ||
| 358 | expect(ptr.a[0].b == 0xbb); | ||
| 359 | expect(ptr.a[1].a == 0xbb); | ||
| 360 | expect(ptr.a[1].b == 0xbb); | ||
| 361 | } | ||
| 362 | |||
| 363 | test "runtime struct initialization of bitfield" { | ||
| 364 | const s1 = Nibbles{ | ||
| 365 | .x = x1, | ||
| 366 | .y = x1, | ||
| 367 | }; | ||
| 368 | const s2 = Nibbles{ | ||
| 369 | .x = @intCast(u4, x2), | ||
| 370 | .y = @intCast(u4, x2), | ||
| 371 | }; | ||
| 372 | |||
| 373 | expect(s1.x == x1); | ||
| 374 | expect(s1.y == x1); | ||
| 375 | expect(s2.x == @intCast(u4, x2)); | ||
| 376 | expect(s2.y == @intCast(u4, x2)); | ||
| 377 | } | ||
| 378 | |||
| 379 | var x1 = u4(1); | ||
| 380 | var x2 = u8(2); | ||
| 381 | |||
| 382 | const Nibbles = packed struct { | ||
| 383 | x: u4, | ||
| 384 | y: u4, | ||
| 385 | }; | ||
| 386 | |||
| 387 | const Bitfields = packed struct { | ||
| 388 | f1: u16, | ||
| 389 | f2: u16, | ||
| 390 | f3: u8, | ||
| 391 | f4: u8, | ||
| 392 | f5: u4, | ||
| 393 | f6: u4, | ||
| 394 | f7: u8, | ||
| 395 | }; | ||
| 396 | |||
| 397 | test "native bit field understands endianness" { | ||
| 398 | var all: u64 = 0x7765443322221111; | ||
| 399 | var bytes: [8]u8 = undefined; | ||
| 400 | @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); | ||
| 401 | var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; | ||
| 402 | |||
| 403 | expect(bitfields.f1 == 0x1111); | ||
| 404 | expect(bitfields.f2 == 0x2222); | ||
| 405 | expect(bitfields.f3 == 0x33); | ||
| 406 | expect(bitfields.f4 == 0x44); | ||
| 407 | expect(bitfields.f5 == 0x5); | ||
| 408 | expect(bitfields.f6 == 0x6); | ||
| 409 | expect(bitfields.f7 == 0x77); | ||
| 410 | } | ||
| 411 | |||
| 412 | test "align 1 field before self referential align 8 field as slice return type" { | ||
| 413 | const result = alloc(Expr); | ||
| 414 | expect(result.len == 0); | ||
| 415 | } | ||
| 416 | |||
| 417 | const Expr = union(enum) { | ||
| 418 | Literal: u8, | ||
| 419 | Question: *Expr, | ||
| 420 | }; | ||
| 421 | |||
| 422 | fn alloc(comptime T: type) []T { | ||
| 423 | return []T{}; | ||
| 424 | } | ||
| 425 | |||
| 426 | test "call method with mutable reference to struct with no fields" { | ||
| 427 | const S = struct { | ||
| 428 | fn doC(s: *const @This()) bool { | ||
| 429 | return true; | ||
| 430 | } | ||
| 431 | fn do(s: *@This()) bool { | ||
| 432 | return true; | ||
| 433 | } | ||
| 434 | }; | ||
| 435 | |||
| 436 | var s = S{}; | ||
| 437 | expect(S.doC(&s)); | ||
| 438 | expect(s.doC()); | ||
| 439 | expect(S.do(&s)); | ||
| 440 | expect(s.do()); | ||
| 441 | } | ||
| 442 | |||
| 443 | test "implicit cast packed struct field to const ptr" { | ||
| 444 | const LevelUpMove = packed struct { | ||
| 445 | move_id: u9, | ||
| 446 | level: u7, | ||
| 447 | |||
| 448 | fn toInt(value: u7) u7 { | ||
| 449 | return value; | ||
| 450 | } | ||
| 451 | }; | ||
| 452 | |||
| 453 | var lup: LevelUpMove = undefined; | ||
| 454 | lup.level = 12; | ||
| 455 | const res = LevelUpMove.toInt(lup.level); | ||
| 456 | expect(res == 12); | ||
| 457 | } | ||
| 458 | |||
| 459 | test "pointer to packed struct member in a stack variable" { | ||
| 460 | const S = packed struct { | ||
| 461 | a: u2, | ||
| 462 | b: u2, | ||
| 463 | }; | ||
| 464 | |||
| 465 | var s = S{ .a = 2, .b = 0 }; | ||
| 466 | var b_ptr = &s.b; | ||
| 467 | expect(s.b == 0); | ||
| 468 | b_ptr.* = 2; | ||
| 469 | expect(s.b == 2); | ||
| 470 | } | ||
test/stage1/behavior/struct_contains_null_ptr_itself.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | test "struct contains null pointer which contains original struct" { | ||
| 5 | var x: ?*NodeLineComment = null; | ||
| 6 | expect(x == null); | ||
| 7 | } | ||
| 8 | |||
| 9 | pub const Node = struct { | ||
| 10 | id: Id, | ||
| 11 | comment: ?*NodeLineComment, | ||
| 12 | |||
| 13 | pub const Id = enum { | ||
| 14 | Root, | ||
| 15 | LineComment, | ||
| 16 | }; | ||
| 17 | }; | ||
| 18 | |||
| 19 | pub const NodeLineComment = struct { | ||
| 20 | base: Node, | ||
| 21 | }; | ||
test/stage1/behavior/struct_contains_slice_of_itself.zig created+85| ... | @@ -0,0 +1,85 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const Node = struct { | ||
| 4 | payload: i32, | ||
| 5 | children: []Node, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const NodeAligned = struct { | ||
| 9 | payload: i32, | ||
| 10 | children: []align(@alignOf(NodeAligned)) NodeAligned, | ||
| 11 | }; | ||
| 12 | |||
| 13 | test "struct contains slice of itself" { | ||
| 14 | var other_nodes = []Node{ | ||
| 15 | Node{ | ||
| 16 | .payload = 31, | ||
| 17 | .children = []Node{}, | ||
| 18 | }, | ||
| 19 | Node{ | ||
| 20 | .payload = 32, | ||
| 21 | .children = []Node{}, | ||
| 22 | }, | ||
| 23 | }; | ||
| 24 | var nodes = []Node{ | ||
| 25 | Node{ | ||
| 26 | .payload = 1, | ||
| 27 | .children = []Node{}, | ||
| 28 | }, | ||
| 29 | Node{ | ||
| 30 | .payload = 2, | ||
| 31 | .children = []Node{}, | ||
| 32 | }, | ||
| 33 | Node{ | ||
| 34 | .payload = 3, | ||
| 35 | .children = other_nodes[0..], | ||
| 36 | }, | ||
| 37 | }; | ||
| 38 | const root = Node{ | ||
| 39 | .payload = 1234, | ||
| 40 | .children = nodes[0..], | ||
| 41 | }; | ||
| 42 | expect(root.payload == 1234); | ||
| 43 | expect(root.children[0].payload == 1); | ||
| 44 | expect(root.children[1].payload == 2); | ||
| 45 | expect(root.children[2].payload == 3); | ||
| 46 | expect(root.children[2].children[0].payload == 31); | ||
| 47 | expect(root.children[2].children[1].payload == 32); | ||
| 48 | } | ||
| 49 | |||
| 50 | test "struct contains aligned slice of itself" { | ||
| 51 | var other_nodes = []NodeAligned{ | ||
| 52 | NodeAligned{ | ||
| 53 | .payload = 31, | ||
| 54 | .children = []NodeAligned{}, | ||
| 55 | }, | ||
| 56 | NodeAligned{ | ||
| 57 | .payload = 32, | ||
| 58 | .children = []NodeAligned{}, | ||
| 59 | }, | ||
| 60 | }; | ||
| 61 | var nodes = []NodeAligned{ | ||
| 62 | NodeAligned{ | ||
| 63 | .payload = 1, | ||
| 64 | .children = []NodeAligned{}, | ||
| 65 | }, | ||
| 66 | NodeAligned{ | ||
| 67 | .payload = 2, | ||
| 68 | .children = []NodeAligned{}, | ||
| 69 | }, | ||
| 70 | NodeAligned{ | ||
| 71 | .payload = 3, | ||
| 72 | .children = other_nodes[0..], | ||
| 73 | }, | ||
| 74 | }; | ||
| 75 | const root = NodeAligned{ | ||
| 76 | .payload = 1234, | ||
| 77 | .children = nodes[0..], | ||
| 78 | }; | ||
| 79 | expect(root.payload == 1234); | ||
| 80 | expect(root.children[0].payload == 1); | ||
| 81 | expect(root.children[1].payload == 2); | ||
| 82 | expect(root.children[2].payload == 3); | ||
| 83 | expect(root.children[2].children[0].payload == 31); | ||
| 84 | expect(root.children[2].children[1].payload == 32); | ||
| 85 | } | ||
test/stage1/behavior/switch.zig created+271| ... | @@ -0,0 +1,271 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "switch with numbers" { | ||
| 4 | testSwitchWithNumbers(13); | ||
| 5 | } | ||
| 6 | |||
| 7 | fn testSwitchWithNumbers(x: u32) void { | ||
| 8 | const result = switch (x) { | ||
| 9 | 1, 2, 3, 4...8 => false, | ||
| 10 | 13 => true, | ||
| 11 | else => false, | ||
| 12 | }; | ||
| 13 | expect(result); | ||
| 14 | } | ||
| 15 | |||
| 16 | test "switch with all ranges" { | ||
| 17 | expect(testSwitchWithAllRanges(50, 3) == 1); | ||
| 18 | expect(testSwitchWithAllRanges(101, 0) == 2); | ||
| 19 | expect(testSwitchWithAllRanges(300, 5) == 3); | ||
| 20 | expect(testSwitchWithAllRanges(301, 6) == 6); | ||
| 21 | } | ||
| 22 | |||
| 23 | fn testSwitchWithAllRanges(x: u32, y: u32) u32 { | ||
| 24 | return switch (x) { | ||
| 25 | 0...100 => 1, | ||
| 26 | 101...200 => 2, | ||
| 27 | 201...300 => 3, | ||
| 28 | else => y, | ||
| 29 | }; | ||
| 30 | } | ||
| 31 | |||
| 32 | test "implicit comptime switch" { | ||
| 33 | const x = 3 + 4; | ||
| 34 | const result = switch (x) { | ||
| 35 | 3 => 10, | ||
| 36 | 4 => 11, | ||
| 37 | 5, 6 => 12, | ||
| 38 | 7, 8 => 13, | ||
| 39 | else => 14, | ||
| 40 | }; | ||
| 41 | |||
| 42 | comptime { | ||
| 43 | expect(result + 1 == 14); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | test "switch on enum" { | ||
| 48 | const fruit = Fruit.Orange; | ||
| 49 | nonConstSwitchOnEnum(fruit); | ||
| 50 | } | ||
| 51 | const Fruit = enum { | ||
| 52 | Apple, | ||
| 53 | Orange, | ||
| 54 | Banana, | ||
| 55 | }; | ||
| 56 | fn nonConstSwitchOnEnum(fruit: Fruit) void { | ||
| 57 | switch (fruit) { | ||
| 58 | Fruit.Apple => unreachable, | ||
| 59 | Fruit.Orange => {}, | ||
| 60 | Fruit.Banana => unreachable, | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | test "switch statement" { | ||
| 65 | nonConstSwitch(SwitchStatmentFoo.C); | ||
| 66 | } | ||
| 67 | fn nonConstSwitch(foo: SwitchStatmentFoo) void { | ||
| 68 | const val = switch (foo) { | ||
| 69 | SwitchStatmentFoo.A => i32(1), | ||
| 70 | SwitchStatmentFoo.B => 2, | ||
| 71 | SwitchStatmentFoo.C => 3, | ||
| 72 | SwitchStatmentFoo.D => 4, | ||
| 73 | }; | ||
| 74 | expect(val == 3); | ||
| 75 | } | ||
| 76 | const SwitchStatmentFoo = enum { | ||
| 77 | A, | ||
| 78 | B, | ||
| 79 | C, | ||
| 80 | D, | ||
| 81 | }; | ||
| 82 | |||
| 83 | test "switch prong with variable" { | ||
| 84 | switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 }); | ||
| 85 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 }); | ||
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} }); | ||
| 87 | } | ||
| 88 | const SwitchProngWithVarEnum = union(enum) { | ||
| 89 | One: i32, | ||
| 90 | Two: f32, | ||
| 91 | Meh: void, | ||
| 92 | }; | ||
| 93 | fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void { | ||
| 94 | switch (a) { | ||
| 95 | SwitchProngWithVarEnum.One => |x| { | ||
| 96 | expect(x == 13); | ||
| 97 | }, | ||
| 98 | SwitchProngWithVarEnum.Two => |x| { | ||
| 99 | expect(x == 13.0); | ||
| 100 | }, | ||
| 101 | SwitchProngWithVarEnum.Meh => |x| { | ||
| 102 | const v: void = x; | ||
| 103 | }, | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | test "switch on enum using pointer capture" { | ||
| 108 | testSwitchEnumPtrCapture(); | ||
| 109 | comptime testSwitchEnumPtrCapture(); | ||
| 110 | } | ||
| 111 | |||
| 112 | fn testSwitchEnumPtrCapture() void { | ||
| 113 | var value = SwitchProngWithVarEnum{ .One = 1234 }; | ||
| 114 | switch (value) { | ||
| 115 | SwitchProngWithVarEnum.One => |*x| x.* += 1, | ||
| 116 | else => unreachable, | ||
| 117 | } | ||
| 118 | switch (value) { | ||
| 119 | SwitchProngWithVarEnum.One => |x| expect(x == 1235), | ||
| 120 | else => unreachable, | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | test "switch with multiple expressions" { | ||
| 125 | const x = switch (returnsFive()) { | ||
| 126 | 1, 2, 3 => 1, | ||
| 127 | 4, 5, 6 => 2, | ||
| 128 | else => i32(3), | ||
| 129 | }; | ||
| 130 | expect(x == 2); | ||
| 131 | } | ||
| 132 | fn returnsFive() i32 { | ||
| 133 | return 5; | ||
| 134 | } | ||
| 135 | |||
| 136 | const Number = union(enum) { | ||
| 137 | One: u64, | ||
| 138 | Two: u8, | ||
| 139 | Three: f32, | ||
| 140 | }; | ||
| 141 | |||
| 142 | const number = Number{ .Three = 1.23 }; | ||
| 143 | |||
| 144 | fn returnsFalse() bool { | ||
| 145 | switch (number) { | ||
| 146 | Number.One => |x| return x > 1234, | ||
| 147 | Number.Two => |x| return x == 'a', | ||
| 148 | Number.Three => |x| return x > 12.34, | ||
| 149 | } | ||
| 150 | } | ||
| 151 | test "switch on const enum with var" { | ||
| 152 | expect(!returnsFalse()); | ||
| 153 | } | ||
| 154 | |||
| 155 | test "switch on type" { | ||
| 156 | expect(trueIfBoolFalseOtherwise(bool)); | ||
| 157 | expect(!trueIfBoolFalseOtherwise(i32)); | ||
| 158 | } | ||
| 159 | |||
| 160 | fn trueIfBoolFalseOtherwise(comptime T: type) bool { | ||
| 161 | return switch (T) { | ||
| 162 | bool => true, | ||
| 163 | else => false, | ||
| 164 | }; | ||
| 165 | } | ||
| 166 | |||
| 167 | test "switch handles all cases of number" { | ||
| 168 | testSwitchHandleAllCases(); | ||
| 169 | comptime testSwitchHandleAllCases(); | ||
| 170 | } | ||
| 171 | |||
| 172 | fn testSwitchHandleAllCases() void { | ||
| 173 | expect(testSwitchHandleAllCasesExhaustive(0) == 3); | ||
| 174 | expect(testSwitchHandleAllCasesExhaustive(1) == 2); | ||
| 175 | expect(testSwitchHandleAllCasesExhaustive(2) == 1); | ||
| 176 | expect(testSwitchHandleAllCasesExhaustive(3) == 0); | ||
| 177 | |||
| 178 | expect(testSwitchHandleAllCasesRange(100) == 0); | ||
| 179 | expect(testSwitchHandleAllCasesRange(200) == 1); | ||
| 180 | expect(testSwitchHandleAllCasesRange(201) == 2); | ||
| 181 | expect(testSwitchHandleAllCasesRange(202) == 4); | ||
| 182 | expect(testSwitchHandleAllCasesRange(230) == 3); | ||
| 183 | } | ||
| 184 | |||
| 185 | fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { | ||
| 186 | return switch (x) { | ||
| 187 | 0 => u2(3), | ||
| 188 | 1 => 2, | ||
| 189 | 2 => 1, | ||
| 190 | 3 => 0, | ||
| 191 | }; | ||
| 192 | } | ||
| 193 | |||
| 194 | fn testSwitchHandleAllCasesRange(x: u8) u8 { | ||
| 195 | return switch (x) { | ||
| 196 | 0...100 => u8(0), | ||
| 197 | 101...200 => 1, | ||
| 198 | 201, 203 => 2, | ||
| 199 | 202 => 4, | ||
| 200 | 204...255 => 3, | ||
| 201 | }; | ||
| 202 | } | ||
| 203 | |||
| 204 | test "switch all prongs unreachable" { | ||
| 205 | testAllProngsUnreachable(); | ||
| 206 | comptime testAllProngsUnreachable(); | ||
| 207 | } | ||
| 208 | |||
| 209 | fn testAllProngsUnreachable() void { | ||
| 210 | expect(switchWithUnreachable(1) == 2); | ||
| 211 | expect(switchWithUnreachable(2) == 10); | ||
| 212 | } | ||
| 213 | |||
| 214 | fn switchWithUnreachable(x: i32) i32 { | ||
| 215 | while (true) { | ||
| 216 | switch (x) { | ||
| 217 | 1 => return 2, | ||
| 218 | 2 => break, | ||
| 219 | else => continue, | ||
| 220 | } | ||
| 221 | } | ||
| 222 | return 10; | ||
| 223 | } | ||
| 224 | |||
| 225 | fn return_a_number() anyerror!i32 { | ||
| 226 | return 1; | ||
| 227 | } | ||
| 228 | |||
| 229 | test "capture value of switch with all unreachable prongs" { | ||
| 230 | const x = return_a_number() catch |err| switch (err) { | ||
| 231 | else => unreachable, | ||
| 232 | }; | ||
| 233 | expect(x == 1); | ||
| 234 | } | ||
| 235 | |||
| 236 | test "switching on booleans" { | ||
| 237 | testSwitchOnBools(); | ||
| 238 | comptime testSwitchOnBools(); | ||
| 239 | } | ||
| 240 | |||
| 241 | fn testSwitchOnBools() void { | ||
| 242 | expect(testSwitchOnBoolsTrueAndFalse(true) == false); | ||
| 243 | expect(testSwitchOnBoolsTrueAndFalse(false) == true); | ||
| 244 | |||
| 245 | expect(testSwitchOnBoolsTrueWithElse(true) == false); | ||
| 246 | expect(testSwitchOnBoolsTrueWithElse(false) == true); | ||
| 247 | |||
| 248 | expect(testSwitchOnBoolsFalseWithElse(true) == false); | ||
| 249 | expect(testSwitchOnBoolsFalseWithElse(false) == true); | ||
| 250 | } | ||
| 251 | |||
| 252 | fn testSwitchOnBoolsTrueAndFalse(x: bool) bool { | ||
| 253 | return switch (x) { | ||
| 254 | true => false, | ||
| 255 | false => true, | ||
| 256 | }; | ||
| 257 | } | ||
| 258 | |||
| 259 | fn testSwitchOnBoolsTrueWithElse(x: bool) bool { | ||
| 260 | return switch (x) { | ||
| 261 | true => false, | ||
| 262 | else => true, | ||
| 263 | }; | ||
| 264 | } | ||
| 265 | |||
| 266 | fn testSwitchOnBoolsFalseWithElse(x: bool) bool { | ||
| 267 | return switch (x) { | ||
| 268 | false => true, | ||
| 269 | else => false, | ||
| 270 | }; | ||
| 271 | } | ||
test/stage1/behavior/switch_prong_err_enum.zig created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | var read_count: u64 = 0; | ||
| 4 | |||
| 5 | fn readOnce() anyerror!u64 { | ||
| 6 | read_count += 1; | ||
| 7 | return read_count; | ||
| 8 | } | ||
| 9 | |||
| 10 | const FormValue = union(enum) { | ||
| 11 | Address: u64, | ||
| 12 | Other: bool, | ||
| 13 | }; | ||
| 14 | |||
| 15 | fn doThing(form_id: u64) anyerror!FormValue { | ||
| 16 | return switch (form_id) { | ||
| 17 | 17 => FormValue{ .Address = try readOnce() }, | ||
| 18 | else => error.InvalidDebugInfo, | ||
| 19 | }; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "switch prong returns error enum" { | ||
| 23 | switch (doThing(17) catch unreachable) { | ||
| 24 | FormValue.Address => |payload| { | ||
| 25 | expect(payload == 1); | ||
| 26 | }, | ||
| 27 | else => unreachable, | ||
| 28 | } | ||
| 29 | expect(read_count == 1); | ||
| 30 | } | ||
test/stage1/behavior/switch_prong_implicit_cast.zig created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const FormValue = union(enum) { | ||
| 4 | One: void, | ||
| 5 | Two: bool, | ||
| 6 | }; | ||
| 7 | |||
| 8 | fn foo(id: u64) !FormValue { | ||
| 9 | return switch (id) { | ||
| 10 | 2 => FormValue{ .Two = true }, | ||
| 11 | 1 => FormValue{ .One = {} }, | ||
| 12 | else => return error.Whatever, | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | |||
| 16 | test "switch prong implicit cast" { | ||
| 17 | const result = switch (foo(2) catch unreachable) { | ||
| 18 | FormValue.One => false, | ||
| 19 | FormValue.Two => |x| x, | ||
| 20 | }; | ||
| 21 | expect(result); | ||
| 22 | } | ||
test/stage1/behavior/syntax.zig created+60| ... | @@ -0,0 +1,60 @@ | ||
| 1 | // Test trailing comma syntax | ||
| 2 | // zig fmt: off | ||
| 3 | |||
| 4 | const struct_trailing_comma = struct { x: i32, y: i32, }; | ||
| 5 | const struct_no_comma = struct { x: i32, y: i32 }; | ||
| 6 | const struct_fn_no_comma = struct { fn m() void {} y: i32 }; | ||
| 7 | |||
| 8 | const enum_no_comma = enum { A, B }; | ||
| 9 | |||
| 10 | fn container_init() void { | ||
| 11 | const S = struct { x: i32, y: i32 }; | ||
| 12 | _ = S { .x = 1, .y = 2 }; | ||
| 13 | _ = S { .x = 1, .y = 2, }; | ||
| 14 | } | ||
| 15 | |||
| 16 | fn type_expr_return1() if (true) A {} | ||
| 17 | fn type_expr_return2() for (true) |_| A {} | ||
| 18 | fn type_expr_return3() while (true) A {} | ||
| 19 | fn type_expr_return4() comptime A {} | ||
| 20 | |||
| 21 | fn switch_cases(x: i32) void { | ||
| 22 | switch (x) { | ||
| 23 | 1,2,3 => {}, | ||
| 24 | 4,5, => {}, | ||
| 25 | 6...8, => {}, | ||
| 26 | else => {}, | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | fn switch_prongs(x: i32) void { | ||
| 31 | switch (x) { | ||
| 32 | 0 => {}, | ||
| 33 | else => {}, | ||
| 34 | } | ||
| 35 | switch (x) { | ||
| 36 | 0 => {}, | ||
| 37 | else => {} | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | const fn_no_comma = fn(i32, i32)void; | ||
| 42 | const fn_trailing_comma = fn(i32, i32,)void; | ||
| 43 | |||
| 44 | fn fn_calls() void { | ||
| 45 | fn add(x: i32, y: i32,) i32 { x + y }; | ||
| 46 | _ = add(1, 2); | ||
| 47 | _ = add(1, 2,); | ||
| 48 | } | ||
| 49 | |||
| 50 | fn asm_lists() void { | ||
| 51 | if (false) { // Build AST but don't analyze | ||
| 52 | asm ("not real assembly" | ||
| 53 | :[a] "x" (x),); | ||
| 54 | asm ("not real assembly" | ||
| 55 | :[a] "x" (->i32),:[a] "x" (1),); | ||
| 56 | asm ("still not real assembly" | ||
| 57 | :::"a","b",); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
test/stage1/behavior/this.zig created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const module = @This(); | ||
| 4 | |||
| 5 | fn Point(comptime T: type) type { | ||
| 6 | return struct { | ||
| 7 | const Self = @This(); | ||
| 8 | x: T, | ||
| 9 | y: T, | ||
| 10 | |||
| 11 | fn addOne(self: *Self) void { | ||
| 12 | self.x += 1; | ||
| 13 | self.y += 1; | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | fn add(x: i32, y: i32) i32 { | ||
| 19 | return x + y; | ||
| 20 | } | ||
| 21 | |||
| 22 | test "this refer to module call private fn" { | ||
| 23 | expect(module.add(1, 2) == 3); | ||
| 24 | } | ||
| 25 | |||
| 26 | test "this refer to container" { | ||
| 27 | var pt = Point(i32){ | ||
| 28 | .x = 12, | ||
| 29 | .y = 34, | ||
| 30 | }; | ||
| 31 | pt.addOne(); | ||
| 32 | expect(pt.x == 13); | ||
| 33 | expect(pt.y == 35); | ||
| 34 | } | ||
| 35 | |||
test/stage1/behavior/truncate.zig created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | test "truncate u0 to larger integer allowed and has comptime known result" { | ||
| 5 | var x: u0 = 0; | ||
| 6 | const y = @truncate(u8, x); | ||
| 7 | comptime expect(y == 0); | ||
| 8 | } | ||
| 9 | |||
| 10 | test "truncate.u0.literal" { | ||
| 11 | var z = @truncate(u0, 0); | ||
| 12 | expect(z == 0); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "truncate.u0.const" { | ||
| 16 | const c0: usize = 0; | ||
| 17 | var z = @truncate(u0, c0); | ||
| 18 | expect(z == 0); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "truncate.u0.var" { | ||
| 22 | var d: u8 = 2; | ||
| 23 | var z = @truncate(u0, d); | ||
| 24 | expect(z == 0); | ||
| 25 | } | ||
| 26 | |||
| 27 | test "truncate sign mismatch but comptime known so it works anyway" { | ||
| 28 | const x: u32 = 10; | ||
| 29 | var result = @truncate(i8, x); | ||
| 30 | expect(result == 10); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "truncate on comptime integer" { | ||
| 34 | var x = @truncate(u16, 9999); | ||
| 35 | expect(x == 9999); | ||
| 36 | } | ||
test/stage1/behavior/try.zig created+43| ... | @@ -0,0 +1,43 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "try on error union" { | ||
| 4 | tryOnErrorUnionImpl(); | ||
| 5 | comptime tryOnErrorUnionImpl(); | ||
| 6 | } | ||
| 7 | |||
| 8 | fn tryOnErrorUnionImpl() void { | ||
| 9 | const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { | ||
| 10 | error.ItBroke, error.NoMem => 1, | ||
| 11 | error.CrappedOut => i32(2), | ||
| 12 | else => unreachable, | ||
| 13 | }; | ||
| 14 | expect(x == 11); | ||
| 15 | } | ||
| 16 | |||
| 17 | fn returnsTen() anyerror!i32 { | ||
| 18 | return 10; | ||
| 19 | } | ||
| 20 | |||
| 21 | test "try without vars" { | ||
| 22 | const result1 = if (failIfTrue(true)) 1 else |_| i32(2); | ||
| 23 | expect(result1 == 2); | ||
| 24 | |||
| 25 | const result2 = if (failIfTrue(false)) 1 else |_| i32(2); | ||
| 26 | expect(result2 == 1); | ||
| 27 | } | ||
| 28 | |||
| 29 | fn failIfTrue(ok: bool) anyerror!void { | ||
| 30 | if (ok) { | ||
| 31 | return error.ItBroke; | ||
| 32 | } else { | ||
| 33 | return; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | test "try then not executed with assignment" { | ||
| 38 | if (failIfTrue(true)) { | ||
| 39 | unreachable; | ||
| 40 | } else |err| { | ||
| 41 | expect(err == error.ItBroke); | ||
| 42 | } | ||
| 43 | } | ||
test/stage1/behavior/type_info.zig created+291| ... | @@ -0,0 +1,291 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | const TypeInfo = @import("builtin").TypeInfo; | ||
| 4 | const TypeId = @import("builtin").TypeId; | ||
| 5 | |||
| 6 | test "type info: tag type, void info" { | ||
| 7 | testBasic(); | ||
| 8 | comptime testBasic(); | ||
| 9 | } | ||
| 10 | |||
| 11 | fn testBasic() void { | ||
| 12 | expect(@TagType(TypeInfo) == TypeId); | ||
| 13 | const void_info = @typeInfo(void); | ||
| 14 | expect(TypeId(void_info) == TypeId.Void); | ||
| 15 | expect(void_info.Void == {}); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "type info: integer, floating point type info" { | ||
| 19 | testIntFloat(); | ||
| 20 | comptime testIntFloat(); | ||
| 21 | } | ||
| 22 | |||
| 23 | fn testIntFloat() void { | ||
| 24 | const u8_info = @typeInfo(u8); | ||
| 25 | expect(TypeId(u8_info) == TypeId.Int); | ||
| 26 | expect(!u8_info.Int.is_signed); | ||
| 27 | expect(u8_info.Int.bits == 8); | ||
| 28 | |||
| 29 | const f64_info = @typeInfo(f64); | ||
| 30 | expect(TypeId(f64_info) == TypeId.Float); | ||
| 31 | expect(f64_info.Float.bits == 64); | ||
| 32 | } | ||
| 33 | |||
| 34 | test "type info: pointer type info" { | ||
| 35 | testPointer(); | ||
| 36 | comptime testPointer(); | ||
| 37 | } | ||
| 38 | |||
| 39 | fn testPointer() void { | ||
| 40 | const u32_ptr_info = @typeInfo(*u32); | ||
| 41 | expect(TypeId(u32_ptr_info) == TypeId.Pointer); | ||
| 42 | expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); | ||
| 43 | expect(u32_ptr_info.Pointer.is_const == false); | ||
| 44 | expect(u32_ptr_info.Pointer.is_volatile == false); | ||
| 45 | expect(u32_ptr_info.Pointer.alignment == @alignOf(u32)); | ||
| 46 | expect(u32_ptr_info.Pointer.child == u32); | ||
| 47 | } | ||
| 48 | |||
| 49 | test "type info: unknown length pointer type info" { | ||
| 50 | testUnknownLenPtr(); | ||
| 51 | comptime testUnknownLenPtr(); | ||
| 52 | } | ||
| 53 | |||
| 54 | fn testUnknownLenPtr() void { | ||
| 55 | const u32_ptr_info = @typeInfo([*]const volatile f64); | ||
| 56 | expect(TypeId(u32_ptr_info) == TypeId.Pointer); | ||
| 57 | expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); | ||
| 58 | expect(u32_ptr_info.Pointer.is_const == true); | ||
| 59 | expect(u32_ptr_info.Pointer.is_volatile == true); | ||
| 60 | expect(u32_ptr_info.Pointer.alignment == @alignOf(f64)); | ||
| 61 | expect(u32_ptr_info.Pointer.child == f64); | ||
| 62 | } | ||
| 63 | |||
| 64 | test "type info: C pointer type info" { | ||
| 65 | testCPtr(); | ||
| 66 | comptime testCPtr(); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn testCPtr() void { | ||
| 70 | const ptr_info = @typeInfo([*c]align(4) const i8); | ||
| 71 | expect(TypeId(ptr_info) == TypeId.Pointer); | ||
| 72 | expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C); | ||
| 73 | expect(ptr_info.Pointer.is_const); | ||
| 74 | expect(!ptr_info.Pointer.is_volatile); | ||
| 75 | expect(ptr_info.Pointer.alignment == 4); | ||
| 76 | expect(ptr_info.Pointer.child == i8); | ||
| 77 | } | ||
| 78 | |||
| 79 | test "type info: slice type info" { | ||
| 80 | testSlice(); | ||
| 81 | comptime testSlice(); | ||
| 82 | } | ||
| 83 | |||
| 84 | fn testSlice() void { | ||
| 85 | const u32_slice_info = @typeInfo([]u32); | ||
| 86 | expect(TypeId(u32_slice_info) == TypeId.Pointer); | ||
| 87 | expect(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); | ||
| 88 | expect(u32_slice_info.Pointer.is_const == false); | ||
| 89 | expect(u32_slice_info.Pointer.is_volatile == false); | ||
| 90 | expect(u32_slice_info.Pointer.alignment == 4); | ||
| 91 | expect(u32_slice_info.Pointer.child == u32); | ||
| 92 | } | ||
| 93 | |||
| 94 | test "type info: array type info" { | ||
| 95 | testArray(); | ||
| 96 | comptime testArray(); | ||
| 97 | } | ||
| 98 | |||
| 99 | fn testArray() void { | ||
| 100 | const arr_info = @typeInfo([42]bool); | ||
| 101 | expect(TypeId(arr_info) == TypeId.Array); | ||
| 102 | expect(arr_info.Array.len == 42); | ||
| 103 | expect(arr_info.Array.child == bool); | ||
| 104 | } | ||
| 105 | |||
| 106 | test "type info: optional type info" { | ||
| 107 | testOptional(); | ||
| 108 | comptime testOptional(); | ||
| 109 | } | ||
| 110 | |||
| 111 | fn testOptional() void { | ||
| 112 | const null_info = @typeInfo(?void); | ||
| 113 | expect(TypeId(null_info) == TypeId.Optional); | ||
| 114 | expect(null_info.Optional.child == void); | ||
| 115 | } | ||
| 116 | |||
| 117 | test "type info: promise info" { | ||
| 118 | testPromise(); | ||
| 119 | comptime testPromise(); | ||
| 120 | } | ||
| 121 | |||
| 122 | fn testPromise() void { | ||
| 123 | const null_promise_info = @typeInfo(promise); | ||
| 124 | expect(TypeId(null_promise_info) == TypeId.Promise); | ||
| 125 | expect(null_promise_info.Promise.child == null); | ||
| 126 | |||
| 127 | const promise_info = @typeInfo(promise->usize); | ||
| 128 | expect(TypeId(promise_info) == TypeId.Promise); | ||
| 129 | expect(promise_info.Promise.child.? == usize); | ||
| 130 | } | ||
| 131 | |||
| 132 | test "type info: error set, error union info" { | ||
| 133 | testErrorSet(); | ||
| 134 | comptime testErrorSet(); | ||
| 135 | } | ||
| 136 | |||
| 137 | fn testErrorSet() void { | ||
| 138 | const TestErrorSet = error{ | ||
| 139 | First, | ||
| 140 | Second, | ||
| 141 | Third, | ||
| 142 | }; | ||
| 143 | |||
| 144 | const error_set_info = @typeInfo(TestErrorSet); | ||
| 145 | expect(TypeId(error_set_info) == TypeId.ErrorSet); | ||
| 146 | expect(error_set_info.ErrorSet.errors.len == 3); | ||
| 147 | expect(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); | ||
| 148 | expect(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); | ||
| 149 | |||
| 150 | const error_union_info = @typeInfo(TestErrorSet!usize); | ||
| 151 | expect(TypeId(error_union_info) == TypeId.ErrorUnion); | ||
| 152 | expect(error_union_info.ErrorUnion.error_set == TestErrorSet); | ||
| 153 | expect(error_union_info.ErrorUnion.payload == usize); | ||
| 154 | } | ||
| 155 | |||
| 156 | test "type info: enum info" { | ||
| 157 | testEnum(); | ||
| 158 | comptime testEnum(); | ||
| 159 | } | ||
| 160 | |||
| 161 | fn testEnum() void { | ||
| 162 | const Os = enum { | ||
| 163 | Windows, | ||
| 164 | Macos, | ||
| 165 | Linux, | ||
| 166 | FreeBSD, | ||
| 167 | }; | ||
| 168 | |||
| 169 | const os_info = @typeInfo(Os); | ||
| 170 | expect(TypeId(os_info) == TypeId.Enum); | ||
| 171 | expect(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); | ||
| 172 | expect(os_info.Enum.fields.len == 4); | ||
| 173 | expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); | ||
| 174 | expect(os_info.Enum.fields[3].value == 3); | ||
| 175 | expect(os_info.Enum.tag_type == u2); | ||
| 176 | expect(os_info.Enum.defs.len == 0); | ||
| 177 | } | ||
| 178 | |||
| 179 | test "type info: union info" { | ||
| 180 | testUnion(); | ||
| 181 | comptime testUnion(); | ||
| 182 | } | ||
| 183 | |||
| 184 | fn testUnion() void { | ||
| 185 | const typeinfo_info = @typeInfo(TypeInfo); | ||
| 186 | expect(TypeId(typeinfo_info) == TypeId.Union); | ||
| 187 | expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); | ||
| 188 | expect(typeinfo_info.Union.tag_type.? == TypeId); | ||
| 189 | expect(typeinfo_info.Union.fields.len == 25); | ||
| 190 | expect(typeinfo_info.Union.fields[4].enum_field != null); | ||
| 191 | expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4); | ||
| 192 | expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); | ||
| 193 | expect(typeinfo_info.Union.defs.len == 21); | ||
| 194 | |||
| 195 | const TestNoTagUnion = union { | ||
| 196 | Foo: void, | ||
| 197 | Bar: u32, | ||
| 198 | }; | ||
| 199 | |||
| 200 | const notag_union_info = @typeInfo(TestNoTagUnion); | ||
| 201 | expect(TypeId(notag_union_info) == TypeId.Union); | ||
| 202 | expect(notag_union_info.Union.tag_type == null); | ||
| 203 | expect(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); | ||
| 204 | expect(notag_union_info.Union.fields.len == 2); | ||
| 205 | expect(notag_union_info.Union.fields[0].enum_field == null); | ||
| 206 | expect(notag_union_info.Union.fields[1].field_type == u32); | ||
| 207 | |||
| 208 | const TestExternUnion = extern union { | ||
| 209 | foo: *c_void, | ||
| 210 | }; | ||
| 211 | |||
| 212 | const extern_union_info = @typeInfo(TestExternUnion); | ||
| 213 | expect(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); | ||
| 214 | expect(extern_union_info.Union.tag_type == null); | ||
| 215 | expect(extern_union_info.Union.fields[0].enum_field == null); | ||
| 216 | expect(extern_union_info.Union.fields[0].field_type == *c_void); | ||
| 217 | } | ||
| 218 | |||
| 219 | test "type info: struct info" { | ||
| 220 | testStruct(); | ||
| 221 | comptime testStruct(); | ||
| 222 | } | ||
| 223 | |||
| 224 | fn testStruct() void { | ||
| 225 | const struct_info = @typeInfo(TestStruct); | ||
| 226 | expect(TypeId(struct_info) == TypeId.Struct); | ||
| 227 | expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); | ||
| 228 | expect(struct_info.Struct.fields.len == 3); | ||
| 229 | expect(struct_info.Struct.fields[1].offset == null); | ||
| 230 | expect(struct_info.Struct.fields[2].field_type == *TestStruct); | ||
| 231 | expect(struct_info.Struct.defs.len == 2); | ||
| 232 | expect(struct_info.Struct.defs[0].is_pub); | ||
| 233 | expect(!struct_info.Struct.defs[0].data.Fn.is_extern); | ||
| 234 | expect(struct_info.Struct.defs[0].data.Fn.lib_name == null); | ||
| 235 | expect(struct_info.Struct.defs[0].data.Fn.return_type == void); | ||
| 236 | expect(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); | ||
| 237 | } | ||
| 238 | |||
| 239 | const TestStruct = packed struct { | ||
| 240 | const Self = @This(); | ||
| 241 | |||
| 242 | fieldA: usize, | ||
| 243 | fieldB: void, | ||
| 244 | fieldC: *Self, | ||
| 245 | |||
| 246 | pub fn foo(self: *const Self) void {} | ||
| 247 | }; | ||
| 248 | |||
| 249 | test "type info: function type info" { | ||
| 250 | testFunction(); | ||
| 251 | comptime testFunction(); | ||
| 252 | } | ||
| 253 | |||
| 254 | fn testFunction() void { | ||
| 255 | const fn_info = @typeInfo(@typeOf(foo)); | ||
| 256 | expect(TypeId(fn_info) == TypeId.Fn); | ||
| 257 | expect(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); | ||
| 258 | expect(fn_info.Fn.is_generic); | ||
| 259 | expect(fn_info.Fn.args.len == 2); | ||
| 260 | expect(fn_info.Fn.is_var_args); | ||
| 261 | expect(fn_info.Fn.return_type == null); | ||
| 262 | expect(fn_info.Fn.async_allocator_type == null); | ||
| 263 | |||
| 264 | const test_instance: TestStruct = undefined; | ||
| 265 | const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); | ||
| 266 | expect(TypeId(bound_fn_info) == TypeId.BoundFn); | ||
| 267 | expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); | ||
| 268 | } | ||
| 269 | |||
| 270 | fn foo(comptime a: usize, b: bool, args: ...) usize { | ||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | test "typeInfo with comptime parameter in struct fn def" { | ||
| 275 | const S = struct { | ||
| 276 | pub fn func(comptime x: f32) void {} | ||
| 277 | }; | ||
| 278 | comptime var info = @typeInfo(S); | ||
| 279 | } | ||
| 280 | |||
| 281 | test "type info: vectors" { | ||
| 282 | testVector(); | ||
| 283 | comptime testVector(); | ||
| 284 | } | ||
| 285 | |||
| 286 | fn testVector() void { | ||
| 287 | const vec_info = @typeInfo(@Vector(4, i32)); | ||
| 288 | expect(TypeId(vec_info) == TypeId.Vector); | ||
| 289 | expect(vec_info.Vector.len == 4); | ||
| 290 | expect(vec_info.Vector.child == i32); | ||
| 291 | } | ||
test/stage1/behavior/undefined.zig created+69| ... | @@ -0,0 +1,69 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const mem = @import("std").mem; | ||
| 3 | |||
| 4 | fn initStaticArray() [10]i32 { | ||
| 5 | var array: [10]i32 = undefined; | ||
| 6 | array[0] = 1; | ||
| 7 | array[4] = 2; | ||
| 8 | array[7] = 3; | ||
| 9 | array[9] = 4; | ||
| 10 | return array; | ||
| 11 | } | ||
| 12 | const static_array = initStaticArray(); | ||
| 13 | test "init static array to undefined" { | ||
| 14 | expect(static_array[0] == 1); | ||
| 15 | expect(static_array[4] == 2); | ||
| 16 | expect(static_array[7] == 3); | ||
| 17 | expect(static_array[9] == 4); | ||
| 18 | |||
| 19 | comptime { | ||
| 20 | expect(static_array[0] == 1); | ||
| 21 | expect(static_array[4] == 2); | ||
| 22 | expect(static_array[7] == 3); | ||
| 23 | expect(static_array[9] == 4); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | const Foo = struct { | ||
| 28 | x: i32, | ||
| 29 | |||
| 30 | fn setFooXMethod(foo: *Foo) void { | ||
| 31 | foo.x = 3; | ||
| 32 | } | ||
| 33 | }; | ||
| 34 | |||
| 35 | fn setFooX(foo: *Foo) void { | ||
| 36 | foo.x = 2; | ||
| 37 | } | ||
| 38 | |||
| 39 | test "assign undefined to struct" { | ||
| 40 | comptime { | ||
| 41 | var foo: Foo = undefined; | ||
| 42 | setFooX(&foo); | ||
| 43 | expect(foo.x == 2); | ||
| 44 | } | ||
| 45 | { | ||
| 46 | var foo: Foo = undefined; | ||
| 47 | setFooX(&foo); | ||
| 48 | expect(foo.x == 2); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | test "assign undefined to struct with method" { | ||
| 53 | comptime { | ||
| 54 | var foo: Foo = undefined; | ||
| 55 | foo.setFooXMethod(); | ||
| 56 | expect(foo.x == 3); | ||
| 57 | } | ||
| 58 | { | ||
| 59 | var foo: Foo = undefined; | ||
| 60 | foo.setFooXMethod(); | ||
| 61 | expect(foo.x == 3); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | test "type name of undefined" { | ||
| 66 | const x = undefined; | ||
| 67 | expect(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); | ||
| 68 | } | ||
| 69 | |||
test/stage1/behavior/underscore.zig created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | |||
| 4 | test "ignore lval with underscore" { | ||
| 5 | _ = false; | ||
| 6 | } | ||
| 7 | |||
| 8 | test "ignore lval with underscore (for loop)" { | ||
| 9 | for ([]void{}) |_, i| { | ||
| 10 | for ([]void{}) |_, j| { | ||
| 11 | break; | ||
| 12 | } | ||
| 13 | break; | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | test "ignore lval with underscore (while loop)" { | ||
| 18 | while (optionalReturnError()) |_| { | ||
| 19 | while (optionalReturnError()) |_| { | ||
| 20 | break; | ||
| 21 | } else |_| {} | ||
| 22 | break; | ||
| 23 | } else |_| {} | ||
| 24 | } | ||
| 25 | |||
| 26 | fn optionalReturnError() !?u32 { | ||
| 27 | return error.optionalReturnError; | ||
| 28 | } | ||
test/stage1/behavior/union.zig created+352| ... | @@ -0,0 +1,352 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const Value = union(enum) { | ||
| 4 | Int: u64, | ||
| 5 | Array: [9]u8, | ||
| 6 | }; | ||
| 7 | |||
| 8 | const Agg = struct { | ||
| 9 | val1: Value, | ||
| 10 | val2: Value, | ||
| 11 | }; | ||
| 12 | |||
| 13 | const v1 = Value{ .Int = 1234 }; | ||
| 14 | const v2 = Value{ .Array = []u8{3} ** 9 }; | ||
| 15 | |||
| 16 | const err = (anyerror!Agg)(Agg{ | ||
| 17 | .val1 = v1, | ||
| 18 | .val2 = v2, | ||
| 19 | }); | ||
| 20 | |||
| 21 | const array = []Value{ | ||
| 22 | v1, | ||
| 23 | v2, | ||
| 24 | v1, | ||
| 25 | v2, | ||
| 26 | }; | ||
| 27 | |||
| 28 | test "unions embedded in aggregate types" { | ||
| 29 | switch (array[1]) { | ||
| 30 | Value.Array => |arr| expect(arr[4] == 3), | ||
| 31 | else => unreachable, | ||
| 32 | } | ||
| 33 | switch ((err catch unreachable).val1) { | ||
| 34 | Value.Int => |x| expect(x == 1234), | ||
| 35 | else => unreachable, | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | const Foo = union { | ||
| 40 | float: f64, | ||
| 41 | int: i32, | ||
| 42 | }; | ||
| 43 | |||
| 44 | test "basic unions" { | ||
| 45 | var foo = Foo{ .int = 1 }; | ||
| 46 | expect(foo.int == 1); | ||
| 47 | foo = Foo{ .float = 12.34 }; | ||
| 48 | expect(foo.float == 12.34); | ||
| 49 | } | ||
| 50 | |||
| 51 | test "comptime union field access" { | ||
| 52 | comptime { | ||
| 53 | var foo = Foo{ .int = 0 }; | ||
| 54 | expect(foo.int == 0); | ||
| 55 | |||
| 56 | foo = Foo{ .float = 42.42 }; | ||
| 57 | expect(foo.float == 42.42); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | test "init union with runtime value" { | ||
| 62 | var foo: Foo = undefined; | ||
| 63 | |||
| 64 | setFloat(&foo, 12.34); | ||
| 65 | expect(foo.float == 12.34); | ||
| 66 | |||
| 67 | setInt(&foo, 42); | ||
| 68 | expect(foo.int == 42); | ||
| 69 | } | ||
| 70 | |||
| 71 | fn setFloat(foo: *Foo, x: f64) void { | ||
| 72 | foo.* = Foo{ .float = x }; | ||
| 73 | } | ||
| 74 | |||
| 75 | fn setInt(foo: *Foo, x: i32) void { | ||
| 76 | foo.* = Foo{ .int = x }; | ||
| 77 | } | ||
| 78 | |||
| 79 | const FooExtern = extern union { | ||
| 80 | float: f64, | ||
| 81 | int: i32, | ||
| 82 | }; | ||
| 83 | |||
| 84 | test "basic extern unions" { | ||
| 85 | var foo = FooExtern{ .int = 1 }; | ||
| 86 | expect(foo.int == 1); | ||
| 87 | foo.float = 12.34; | ||
| 88 | expect(foo.float == 12.34); | ||
| 89 | } | ||
| 90 | |||
| 91 | const Letter = enum { | ||
| 92 | A, | ||
| 93 | B, | ||
| 94 | C, | ||
| 95 | }; | ||
| 96 | const Payload = union(Letter) { | ||
| 97 | A: i32, | ||
| 98 | B: f64, | ||
| 99 | C: bool, | ||
| 100 | }; | ||
| 101 | |||
| 102 | test "union with specified enum tag" { | ||
| 103 | doTest(); | ||
| 104 | comptime doTest(); | ||
| 105 | } | ||
| 106 | |||
| 107 | fn doTest() void { | ||
| 108 | expect(bar(Payload{ .A = 1234 }) == -10); | ||
| 109 | } | ||
| 110 | |||
| 111 | fn bar(value: Payload) i32 { | ||
| 112 | expect(Letter(value) == Letter.A); | ||
| 113 | return switch (value) { | ||
| 114 | Payload.A => |x| return x - 1244, | ||
| 115 | Payload.B => |x| if (x == 12.34) i32(20) else 21, | ||
| 116 | Payload.C => |x| if (x) i32(30) else 31, | ||
| 117 | }; | ||
| 118 | } | ||
| 119 | |||
| 120 | const MultipleChoice = union(enum(u32)) { | ||
| 121 | A = 20, | ||
| 122 | B = 40, | ||
| 123 | C = 60, | ||
| 124 | D = 1000, | ||
| 125 | }; | ||
| 126 | test "simple union(enum(u32))" { | ||
| 127 | var x = MultipleChoice.C; | ||
| 128 | expect(x == MultipleChoice.C); | ||
| 129 | expect(@enumToInt(@TagType(MultipleChoice)(x)) == 60); | ||
| 130 | } | ||
| 131 | |||
| 132 | const MultipleChoice2 = union(enum(u32)) { | ||
| 133 | Unspecified1: i32, | ||
| 134 | A: f32 = 20, | ||
| 135 | Unspecified2: void, | ||
| 136 | B: bool = 40, | ||
| 137 | Unspecified3: i32, | ||
| 138 | C: i8 = 60, | ||
| 139 | Unspecified4: void, | ||
| 140 | D: void = 1000, | ||
| 141 | Unspecified5: i32, | ||
| 142 | }; | ||
| 143 | |||
| 144 | test "union(enum(u32)) with specified and unspecified tag values" { | ||
| 145 | comptime expect(@TagType(@TagType(MultipleChoice2)) == u32); | ||
| 146 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 147 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 148 | } | ||
| 149 | |||
| 150 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | ||
| 151 | expect(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); | ||
| 152 | expect(1123 == switch (x) { | ||
| 153 | MultipleChoice2.A => 1, | ||
| 154 | MultipleChoice2.B => 2, | ||
| 155 | MultipleChoice2.C => |v| i32(1000) + v, | ||
| 156 | MultipleChoice2.D => 4, | ||
| 157 | MultipleChoice2.Unspecified1 => 5, | ||
| 158 | MultipleChoice2.Unspecified2 => 6, | ||
| 159 | MultipleChoice2.Unspecified3 => 7, | ||
| 160 | MultipleChoice2.Unspecified4 => 8, | ||
| 161 | MultipleChoice2.Unspecified5 => 9, | ||
| 162 | }); | ||
| 163 | } | ||
| 164 | |||
| 165 | const ExternPtrOrInt = extern union { | ||
| 166 | ptr: *u8, | ||
| 167 | int: u64, | ||
| 168 | }; | ||
| 169 | test "extern union size" { | ||
| 170 | comptime expect(@sizeOf(ExternPtrOrInt) == 8); | ||
| 171 | } | ||
| 172 | |||
| 173 | const PackedPtrOrInt = packed union { | ||
| 174 | ptr: *u8, | ||
| 175 | int: u64, | ||
| 176 | }; | ||
| 177 | test "extern union size" { | ||
| 178 | comptime expect(@sizeOf(PackedPtrOrInt) == 8); | ||
| 179 | } | ||
| 180 | |||
| 181 | const ZeroBits = union { | ||
| 182 | OnlyField: void, | ||
| 183 | }; | ||
| 184 | test "union with only 1 field which is void should be zero bits" { | ||
| 185 | comptime expect(@sizeOf(ZeroBits) == 0); | ||
| 186 | } | ||
| 187 | |||
| 188 | const TheTag = enum { | ||
| 189 | A, | ||
| 190 | B, | ||
| 191 | C, | ||
| 192 | }; | ||
| 193 | const TheUnion = union(TheTag) { | ||
| 194 | A: i32, | ||
| 195 | B: i32, | ||
| 196 | C: i32, | ||
| 197 | }; | ||
| 198 | test "union field access gives the enum values" { | ||
| 199 | expect(TheUnion.A == TheTag.A); | ||
| 200 | expect(TheUnion.B == TheTag.B); | ||
| 201 | expect(TheUnion.C == TheTag.C); | ||
| 202 | } | ||
| 203 | |||
| 204 | test "cast union to tag type of union" { | ||
| 205 | testCastUnionToTagType(TheUnion{ .B = 1234 }); | ||
| 206 | comptime testCastUnionToTagType(TheUnion{ .B = 1234 }); | ||
| 207 | } | ||
| 208 | |||
| 209 | fn testCastUnionToTagType(x: TheUnion) void { | ||
| 210 | expect(TheTag(x) == TheTag.B); | ||
| 211 | } | ||
| 212 | |||
| 213 | test "cast tag type of union to union" { | ||
| 214 | var x: Value2 = Letter2.B; | ||
| 215 | expect(Letter2(x) == Letter2.B); | ||
| 216 | } | ||
| 217 | const Letter2 = enum { | ||
| 218 | A, | ||
| 219 | B, | ||
| 220 | C, | ||
| 221 | }; | ||
| 222 | const Value2 = union(Letter2) { | ||
| 223 | A: i32, | ||
| 224 | B, | ||
| 225 | C, | ||
| 226 | }; | ||
| 227 | |||
| 228 | test "implicit cast union to its tag type" { | ||
| 229 | var x: Value2 = Letter2.B; | ||
| 230 | expect(x == Letter2.B); | ||
| 231 | giveMeLetterB(x); | ||
| 232 | } | ||
| 233 | fn giveMeLetterB(x: Letter2) void { | ||
| 234 | expect(x == Value2.B); | ||
| 235 | } | ||
| 236 | |||
| 237 | pub const PackThis = union(enum) { | ||
| 238 | Invalid: bool, | ||
| 239 | StringLiteral: u2, | ||
| 240 | }; | ||
| 241 | |||
| 242 | test "constant packed union" { | ||
| 243 | testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); | ||
| 244 | } | ||
| 245 | |||
| 246 | fn testConstPackedUnion(expected_tokens: []const PackThis) void { | ||
| 247 | expect(expected_tokens[0].StringLiteral == 1); | ||
| 248 | } | ||
| 249 | |||
| 250 | test "switch on union with only 1 field" { | ||
| 251 | var r: PartialInst = undefined; | ||
| 252 | r = PartialInst.Compiled; | ||
| 253 | switch (r) { | ||
| 254 | PartialInst.Compiled => { | ||
| 255 | var z: PartialInstWithPayload = undefined; | ||
| 256 | z = PartialInstWithPayload{ .Compiled = 1234 }; | ||
| 257 | switch (z) { | ||
| 258 | PartialInstWithPayload.Compiled => |x| { | ||
| 259 | expect(x == 1234); | ||
| 260 | return; | ||
| 261 | }, | ||
| 262 | } | ||
| 263 | }, | ||
| 264 | } | ||
| 265 | unreachable; | ||
| 266 | } | ||
| 267 | |||
| 268 | const PartialInst = union(enum) { | ||
| 269 | Compiled, | ||
| 270 | }; | ||
| 271 | |||
| 272 | const PartialInstWithPayload = union(enum) { | ||
| 273 | Compiled: i32, | ||
| 274 | }; | ||
| 275 | |||
| 276 | test "access a member of tagged union with conflicting enum tag name" { | ||
| 277 | const Bar = union(enum) { | ||
| 278 | A: A, | ||
| 279 | B: B, | ||
| 280 | |||
| 281 | const A = u8; | ||
| 282 | const B = void; | ||
| 283 | }; | ||
| 284 | |||
| 285 | comptime expect(Bar.A == u8); | ||
| 286 | } | ||
| 287 | |||
| 288 | test "tagged union initialization with runtime void" { | ||
| 289 | expect(testTaggedUnionInit({})); | ||
| 290 | } | ||
| 291 | |||
| 292 | const TaggedUnionWithAVoid = union(enum) { | ||
| 293 | A, | ||
| 294 | B: i32, | ||
| 295 | }; | ||
| 296 | |||
| 297 | fn testTaggedUnionInit(x: var) bool { | ||
| 298 | const y = TaggedUnionWithAVoid{ .A = x }; | ||
| 299 | return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; | ||
| 300 | } | ||
| 301 | |||
| 302 | pub const UnionEnumNoPayloads = union(enum) { | ||
| 303 | A, | ||
| 304 | B, | ||
| 305 | }; | ||
| 306 | |||
| 307 | test "tagged union with no payloads" { | ||
| 308 | const a = UnionEnumNoPayloads{ .B = {} }; | ||
| 309 | switch (a) { | ||
| 310 | @TagType(UnionEnumNoPayloads).A => @panic("wrong"), | ||
| 311 | @TagType(UnionEnumNoPayloads).B => {}, | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | test "union with only 1 field casted to its enum type" { | ||
| 316 | const Literal = union(enum) { | ||
| 317 | Number: f64, | ||
| 318 | Bool: bool, | ||
| 319 | }; | ||
| 320 | |||
| 321 | const Expr = union(enum) { | ||
| 322 | Literal: Literal, | ||
| 323 | }; | ||
| 324 | |||
| 325 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 326 | const Tag = @TagType(Expr); | ||
| 327 | comptime expect(@TagType(Tag) == comptime_int); | ||
| 328 | var t = Tag(e); | ||
| 329 | expect(t == Expr.Literal); | ||
| 330 | } | ||
| 331 | |||
| 332 | test "union with only 1 field casted to its enum type which has enum value specified" { | ||
| 333 | const Literal = union(enum) { | ||
| 334 | Number: f64, | ||
| 335 | Bool: bool, | ||
| 336 | }; | ||
| 337 | |||
| 338 | const Tag = enum { | ||
| 339 | Literal = 33, | ||
| 340 | }; | ||
| 341 | |||
| 342 | const Expr = union(Tag) { | ||
| 343 | Literal: Literal, | ||
| 344 | }; | ||
| 345 | |||
| 346 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 347 | comptime expect(@TagType(Tag) == comptime_int); | ||
| 348 | var t = Tag(e); | ||
| 349 | expect(t == Expr.Literal); | ||
| 350 | expect(@enumToInt(t) == 33); | ||
| 351 | comptime expect(@enumToInt(t) == 33); | ||
| 352 | } | ||
test/stage1/behavior/var_args.zig created+84| ... | @@ -0,0 +1,84 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | fn add(args: ...) i32 { | ||
| 4 | var sum = i32(0); | ||
| 5 | { | ||
| 6 | comptime var i: usize = 0; | ||
| 7 | inline while (i < args.len) : (i += 1) { | ||
| 8 | sum += args[i]; | ||
| 9 | } | ||
| 10 | } | ||
| 11 | return sum; | ||
| 12 | } | ||
| 13 | |||
| 14 | test "add arbitrary args" { | ||
| 15 | expect(add(i32(1), i32(2), i32(3), i32(4)) == 10); | ||
| 16 | expect(add(i32(1234)) == 1234); | ||
| 17 | expect(add() == 0); | ||
| 18 | } | ||
| 19 | |||
| 20 | fn readFirstVarArg(args: ...) void { | ||
| 21 | const value = args[0]; | ||
| 22 | } | ||
| 23 | |||
| 24 | test "send void arg to var args" { | ||
| 25 | readFirstVarArg({}); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "pass args directly" { | ||
| 29 | expect(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); | ||
| 30 | expect(addSomeStuff(i32(1234)) == 1234); | ||
| 31 | expect(addSomeStuff() == 0); | ||
| 32 | } | ||
| 33 | |||
| 34 | fn addSomeStuff(args: ...) i32 { | ||
| 35 | return add(args); | ||
| 36 | } | ||
| 37 | |||
| 38 | test "runtime parameter before var args" { | ||
| 39 | expect(extraFn(10) == 0); | ||
| 40 | expect(extraFn(10, false) == 1); | ||
| 41 | expect(extraFn(10, false, true) == 2); | ||
| 42 | |||
| 43 | // TODO issue #313 | ||
| 44 | //comptime { | ||
| 45 | // expect(extraFn(10) == 0); | ||
| 46 | // expect(extraFn(10, false) == 1); | ||
| 47 | // expect(extraFn(10, false, true) == 2); | ||
| 48 | //} | ||
| 49 | } | ||
| 50 | |||
| 51 | fn extraFn(extra: u32, args: ...) usize { | ||
| 52 | if (args.len >= 1) { | ||
| 53 | expect(args[0] == false); | ||
| 54 | } | ||
| 55 | if (args.len >= 2) { | ||
| 56 | expect(args[1] == true); | ||
| 57 | } | ||
| 58 | return args.len; | ||
| 59 | } | ||
| 60 | |||
| 61 | const foos = []fn (...) bool{ | ||
| 62 | foo1, | ||
| 63 | foo2, | ||
| 64 | }; | ||
| 65 | |||
| 66 | fn foo1(args: ...) bool { | ||
| 67 | return true; | ||
| 68 | } | ||
| 69 | fn foo2(args: ...) bool { | ||
| 70 | return false; | ||
| 71 | } | ||
| 72 | |||
| 73 | test "array of var args functions" { | ||
| 74 | expect(foos[0]()); | ||
| 75 | expect(!foos[1]()); | ||
| 76 | } | ||
| 77 | |||
| 78 | test "pass zero length array to var args param" { | ||
| 79 | doNothingWithFirstArg(""); | ||
| 80 | } | ||
| 81 | |||
| 82 | fn doNothingWithFirstArg(args: ...) void { | ||
| 83 | const a = args[0]; | ||
| 84 | } | ||
test/stage1/behavior/vector.zig created+45| ... | @@ -0,0 +1,45 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | test "vector wrap operators" { | ||
| 6 | const S = struct { | ||
| 7 | fn doTheTest() void { | ||
| 8 | const v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 }; | ||
| 9 | const x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 }; | ||
| 10 | expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ 11, 22, 33, 44 })); | ||
| 11 | expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 9, 18, 27, 36 })); | ||
| 12 | expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 10, 40, 90, 160 })); | ||
| 13 | } | ||
| 14 | }; | ||
| 15 | S.doTheTest(); | ||
| 16 | comptime S.doTheTest(); | ||
| 17 | } | ||
| 18 | |||
| 19 | test "vector float operators" { | ||
| 20 | const S = struct { | ||
| 21 | fn doTheTest() void { | ||
| 22 | const v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 }; | ||
| 23 | const x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 }; | ||
| 24 | expect(mem.eql(f32, ([4]f32)(v + x), [4]f32{ 11, 22, 33, 44 })); | ||
| 25 | expect(mem.eql(f32, ([4]f32)(v - x), [4]f32{ 9, 18, 27, 36 })); | ||
| 26 | expect(mem.eql(f32, ([4]f32)(v * x), [4]f32{ 10, 40, 90, 160 })); | ||
| 27 | } | ||
| 28 | }; | ||
| 29 | S.doTheTest(); | ||
| 30 | comptime S.doTheTest(); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "vector bit operators" { | ||
| 34 | const S = struct { | ||
| 35 | fn doTheTest() void { | ||
| 36 | const v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 }; | ||
| 37 | const x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 }; | ||
| 38 | expect(mem.eql(u8, ([4]u8)(v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 })); | ||
| 39 | expect(mem.eql(u8, ([4]u8)(v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 })); | ||
| 40 | expect(mem.eql(u8, ([4]u8)(v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 })); | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | S.doTheTest(); | ||
| 44 | comptime S.doTheTest(); | ||
| 45 | } | ||
test/stage1/behavior/void.zig created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const Foo = struct { | ||
| 4 | a: void, | ||
| 5 | b: i32, | ||
| 6 | c: void, | ||
| 7 | }; | ||
| 8 | |||
| 9 | test "compare void with void compile time known" { | ||
| 10 | comptime { | ||
| 11 | const foo = Foo{ | ||
| 12 | .a = {}, | ||
| 13 | .b = 1, | ||
| 14 | .c = {}, | ||
| 15 | }; | ||
| 16 | expect(foo.a == {}); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | test "iterate over a void slice" { | ||
| 21 | var j: usize = 0; | ||
| 22 | for (times(10)) |_, i| { | ||
| 23 | expect(i == j); | ||
| 24 | j += 1; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | fn times(n: usize) []const void { | ||
| 29 | return ([*]void)(undefined)[0..n]; | ||
| 30 | } | ||
| 31 | |||
| 32 | test "void optional" { | ||
| 33 | var x: ?void = {}; | ||
| 34 | expect(x != null); | ||
| 35 | } | ||
test/stage1/behavior/while.zig created+228| ... | @@ -0,0 +1,228 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | test "while loop" { | ||
| 4 | var i: i32 = 0; | ||
| 5 | while (i < 4) { | ||
| 6 | i += 1; | ||
| 7 | } | ||
| 8 | expect(i == 4); | ||
| 9 | expect(whileLoop1() == 1); | ||
| 10 | } | ||
| 11 | fn whileLoop1() i32 { | ||
| 12 | return whileLoop2(); | ||
| 13 | } | ||
| 14 | fn whileLoop2() i32 { | ||
| 15 | while (true) { | ||
| 16 | return 1; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | test "static eval while" { | ||
| 21 | expect(static_eval_while_number == 1); | ||
| 22 | } | ||
| 23 | const static_eval_while_number = staticWhileLoop1(); | ||
| 24 | fn staticWhileLoop1() i32 { | ||
| 25 | return whileLoop2(); | ||
| 26 | } | ||
| 27 | fn staticWhileLoop2() i32 { | ||
| 28 | while (true) { | ||
| 29 | return 1; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | test "continue and break" { | ||
| 34 | runContinueAndBreakTest(); | ||
| 35 | expect(continue_and_break_counter == 8); | ||
| 36 | } | ||
| 37 | var continue_and_break_counter: i32 = 0; | ||
| 38 | fn runContinueAndBreakTest() void { | ||
| 39 | var i: i32 = 0; | ||
| 40 | while (true) { | ||
| 41 | continue_and_break_counter += 2; | ||
| 42 | i += 1; | ||
| 43 | if (i < 4) { | ||
| 44 | continue; | ||
| 45 | } | ||
| 46 | break; | ||
| 47 | } | ||
| 48 | expect(i == 4); | ||
| 49 | } | ||
| 50 | |||
| 51 | test "return with implicit cast from while loop" { | ||
| 52 | returnWithImplicitCastFromWhileLoopTest() catch unreachable; | ||
| 53 | } | ||
| 54 | fn returnWithImplicitCastFromWhileLoopTest() anyerror!void { | ||
| 55 | while (true) { | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | test "while with continue expression" { | ||
| 61 | var sum: i32 = 0; | ||
| 62 | { | ||
| 63 | var i: i32 = 0; | ||
| 64 | while (i < 10) : (i += 1) { | ||
| 65 | if (i == 5) continue; | ||
| 66 | sum += i; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | expect(sum == 40); | ||
| 70 | } | ||
| 71 | |||
| 72 | test "while with else" { | ||
| 73 | var sum: i32 = 0; | ||
| 74 | var i: i32 = 0; | ||
| 75 | var got_else: i32 = 0; | ||
| 76 | while (i < 10) : (i += 1) { | ||
| 77 | sum += 1; | ||
| 78 | } else { | ||
| 79 | got_else += 1; | ||
| 80 | } | ||
| 81 | expect(sum == 10); | ||
| 82 | expect(got_else == 1); | ||
| 83 | } | ||
| 84 | |||
| 85 | test "while with optional as condition" { | ||
| 86 | numbers_left = 10; | ||
| 87 | var sum: i32 = 0; | ||
| 88 | while (getNumberOrNull()) |value| { | ||
| 89 | sum += value; | ||
| 90 | } | ||
| 91 | expect(sum == 45); | ||
| 92 | } | ||
| 93 | |||
| 94 | test "while with optional as condition with else" { | ||
| 95 | numbers_left = 10; | ||
| 96 | var sum: i32 = 0; | ||
| 97 | var got_else: i32 = 0; | ||
| 98 | while (getNumberOrNull()) |value| { | ||
| 99 | sum += value; | ||
| 100 | expect(got_else == 0); | ||
| 101 | } else { | ||
| 102 | got_else += 1; | ||
| 103 | } | ||
| 104 | expect(sum == 45); | ||
| 105 | expect(got_else == 1); | ||
| 106 | } | ||
| 107 | |||
| 108 | test "while with error union condition" { | ||
| 109 | numbers_left = 10; | ||
| 110 | var sum: i32 = 0; | ||
| 111 | var got_else: i32 = 0; | ||
| 112 | while (getNumberOrErr()) |value| { | ||
| 113 | sum += value; | ||
| 114 | } else |err| { | ||
| 115 | expect(err == error.OutOfNumbers); | ||
| 116 | got_else += 1; | ||
| 117 | } | ||
| 118 | expect(sum == 45); | ||
| 119 | expect(got_else == 1); | ||
| 120 | } | ||
| 121 | |||
| 122 | var numbers_left: i32 = undefined; | ||
| 123 | fn getNumberOrErr() anyerror!i32 { | ||
| 124 | return if (numbers_left == 0) error.OutOfNumbers else x: { | ||
| 125 | numbers_left -= 1; | ||
| 126 | break :x numbers_left; | ||
| 127 | }; | ||
| 128 | } | ||
| 129 | fn getNumberOrNull() ?i32 { | ||
| 130 | return if (numbers_left == 0) null else x: { | ||
| 131 | numbers_left -= 1; | ||
| 132 | break :x numbers_left; | ||
| 133 | }; | ||
| 134 | } | ||
| 135 | |||
| 136 | test "while on optional with else result follow else prong" { | ||
| 137 | const result = while (returnNull()) |value| { | ||
| 138 | break value; | ||
| 139 | } else | ||
| 140 | i32(2); | ||
| 141 | expect(result == 2); | ||
| 142 | } | ||
| 143 | |||
| 144 | test "while on optional with else result follow break prong" { | ||
| 145 | const result = while (returnOptional(10)) |value| { | ||
| 146 | break value; | ||
| 147 | } else | ||
| 148 | i32(2); | ||
| 149 | expect(result == 10); | ||
| 150 | } | ||
| 151 | |||
| 152 | test "while on error union with else result follow else prong" { | ||
| 153 | const result = while (returnError()) |value| { | ||
| 154 | break value; | ||
| 155 | } else |err| | ||
| 156 | i32(2); | ||
| 157 | expect(result == 2); | ||
| 158 | } | ||
| 159 | |||
| 160 | test "while on error union with else result follow break prong" { | ||
| 161 | const result = while (returnSuccess(10)) |value| { | ||
| 162 | break value; | ||
| 163 | } else |err| | ||
| 164 | i32(2); | ||
| 165 | expect(result == 10); | ||
| 166 | } | ||
| 167 | |||
| 168 | test "while on bool with else result follow else prong" { | ||
| 169 | const result = while (returnFalse()) { | ||
| 170 | break i32(10); | ||
| 171 | } else | ||
| 172 | i32(2); | ||
| 173 | expect(result == 2); | ||
| 174 | } | ||
| 175 | |||
| 176 | test "while on bool with else result follow break prong" { | ||
| 177 | const result = while (returnTrue()) { | ||
| 178 | break i32(10); | ||
| 179 | } else | ||
| 180 | i32(2); | ||
| 181 | expect(result == 10); | ||
| 182 | } | ||
| 183 | |||
| 184 | test "break from outer while loop" { | ||
| 185 | testBreakOuter(); | ||
| 186 | comptime testBreakOuter(); | ||
| 187 | } | ||
| 188 | |||
| 189 | fn testBreakOuter() void { | ||
| 190 | outer: while (true) { | ||
| 191 | while (true) { | ||
| 192 | break :outer; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | test "continue outer while loop" { | ||
| 198 | testContinueOuter(); | ||
| 199 | comptime testContinueOuter(); | ||
| 200 | } | ||
| 201 | |||
| 202 | fn testContinueOuter() void { | ||
| 203 | var i: usize = 0; | ||
| 204 | outer: while (i < 10) : (i += 1) { | ||
| 205 | while (true) { | ||
| 206 | continue :outer; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | fn returnNull() ?i32 { | ||
| 212 | return null; | ||
| 213 | } | ||
| 214 | fn returnOptional(x: i32) ?i32 { | ||
| 215 | return x; | ||
| 216 | } | ||
| 217 | fn returnError() anyerror!i32 { | ||
| 218 | return error.YouWantedAnError; | ||
| 219 | } | ||
| 220 | fn returnSuccess(x: i32) anyerror!i32 { | ||
| 221 | return x; | ||
| 222 | } | ||
| 223 | fn returnFalse() bool { | ||
| 224 | return false; | ||
| 225 | } | ||
| 226 | fn returnTrue() bool { | ||
| 227 | return true; | ||
| 228 | } | ||
test/stage1/behavior/widening.zig created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | test "integer widening" { | ||
| 6 | var a: u8 = 250; | ||
| 7 | var b: u16 = a; | ||
| 8 | var c: u32 = b; | ||
| 9 | var d: u64 = c; | ||
| 10 | var e: u64 = d; | ||
| 11 | var f: u128 = e; | ||
| 12 | expect(f == a); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "implicit unsigned integer to signed integer" { | ||
| 16 | var a: u8 = 250; | ||
| 17 | var b: i16 = a; | ||
| 18 | expect(b == 250); | ||
| 19 | } | ||
| 20 | |||
| 21 | test "float widening" { | ||
| 22 | var a: f16 = 12.34; | ||
| 23 | var b: f32 = a; | ||
| 24 | var c: f64 = b; | ||
| 25 | var d: f128 = c; | ||
| 26 | expect(d == a); | ||
| 27 | } | ||
| 28 | |||
test/stage1/c_abi/main.zig+41-41| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | 2 | const expect = std.testing.expect; |
| 3 | 3 | ||
| 4 | extern fn run_c_tests() void; | 4 | extern fn run_c_tests() void; |
| 5 | 5 | ||
| ... | @@ -33,28 +33,28 @@ test "C ABI integers" { | ... | @@ -33,28 +33,28 @@ test "C ABI integers" { |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | export fn zig_u8(x: u8) void { | 35 | export fn zig_u8(x: u8) void { |
| 36 | assertOrPanic(x == 0xff); | 36 | expect(x == 0xff); |
| 37 | } | 37 | } |
| 38 | export fn zig_u16(x: u16) void { | 38 | export fn zig_u16(x: u16) void { |
| 39 | assertOrPanic(x == 0xfffe); | 39 | expect(x == 0xfffe); |
| 40 | } | 40 | } |
| 41 | export fn zig_u32(x: u32) void { | 41 | export fn zig_u32(x: u32) void { |
| 42 | assertOrPanic(x == 0xfffffffd); | 42 | expect(x == 0xfffffffd); |
| 43 | } | 43 | } |
| 44 | export fn zig_u64(x: u64) void { | 44 | export fn zig_u64(x: u64) void { |
| 45 | assertOrPanic(x == 0xfffffffffffffffc); | 45 | expect(x == 0xfffffffffffffffc); |
| 46 | } | 46 | } |
| 47 | export fn zig_i8(x: i8) void { | 47 | export fn zig_i8(x: i8) void { |
| 48 | assertOrPanic(x == -1); | 48 | expect(x == -1); |
| 49 | } | 49 | } |
| 50 | export fn zig_i16(x: i16) void { | 50 | export fn zig_i16(x: i16) void { |
| 51 | assertOrPanic(x == -2); | 51 | expect(x == -2); |
| 52 | } | 52 | } |
| 53 | export fn zig_i32(x: i32) void { | 53 | export fn zig_i32(x: i32) void { |
| 54 | assertOrPanic(x == -3); | 54 | expect(x == -3); |
| 55 | } | 55 | } |
| 56 | export fn zig_i64(x: i64) void { | 56 | export fn zig_i64(x: i64) void { |
| 57 | assertOrPanic(x == -4); | 57 | expect(x == -4); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | extern fn c_f32(f32) void; | 60 | extern fn c_f32(f32) void; |
| ... | @@ -66,10 +66,10 @@ test "C ABI floats" { | ... | @@ -66,10 +66,10 @@ test "C ABI floats" { |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | export fn zig_f32(x: f32) void { | 68 | export fn zig_f32(x: f32) void { |
| 69 | assertOrPanic(x == 12.34); | 69 | expect(x == 12.34); |
| 70 | } | 70 | } |
| 71 | export fn zig_f64(x: f64) void { | 71 | export fn zig_f64(x: f64) void { |
| 72 | assertOrPanic(x == 56.78); | 72 | expect(x == 56.78); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | extern fn c_ptr(*c_void) void; | 75 | extern fn c_ptr(*c_void) void; |
| ... | @@ -79,7 +79,7 @@ test "C ABI pointer" { | ... | @@ -79,7 +79,7 @@ test "C ABI pointer" { |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | export fn zig_ptr(x: *c_void) void { | 81 | export fn zig_ptr(x: *c_void) void { |
| 82 | assertOrPanic(@ptrToInt(x) == 0xdeadbeef); | 82 | expect(@ptrToInt(x) == 0xdeadbeef); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | extern fn c_bool(bool) void; | 85 | extern fn c_bool(bool) void; |
| ... | @@ -89,7 +89,7 @@ test "C ABI bool" { | ... | @@ -89,7 +89,7 @@ test "C ABI bool" { |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | export fn zig_bool(x: bool) void { | 91 | export fn zig_bool(x: bool) void { |
| 92 | assertOrPanic(x); | 92 | expect(x); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | extern fn c_array([10]u8) void; | 95 | extern fn c_array([10]u8) void; |
| ... | @@ -100,7 +100,7 @@ test "C ABI array" { | ... | @@ -100,7 +100,7 @@ test "C ABI array" { |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | export fn zig_array(x: [10]u8) void { | 102 | export fn zig_array(x: [10]u8) void { |
| 103 | assertOrPanic(std.mem.eql(u8, x, "1234567890")); | 103 | expect(std.mem.eql(u8, x, "1234567890")); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | const BigStruct = extern struct { | 106 | const BigStruct = extern struct { |
| ... | @@ -124,11 +124,11 @@ test "C ABI big struct" { | ... | @@ -124,11 +124,11 @@ test "C ABI big struct" { |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | export fn zig_big_struct(x: BigStruct) void { | 126 | export fn zig_big_struct(x: BigStruct) void { |
| 127 | assertOrPanic(x.a == 1); | 127 | expect(x.a == 1); |
| 128 | assertOrPanic(x.b == 2); | 128 | expect(x.b == 2); |
| 129 | assertOrPanic(x.c == 3); | 129 | expect(x.c == 3); |
| 130 | assertOrPanic(x.d == 4); | 130 | expect(x.d == 4); |
| 131 | assertOrPanic(x.e == 5); | 131 | expect(x.e == 5); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | const BigUnion = extern union { | 134 | const BigUnion = extern union { |
| ... | @@ -150,11 +150,11 @@ test "C ABI big union" { | ... | @@ -150,11 +150,11 @@ test "C ABI big union" { |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | export fn zig_big_union(x: BigUnion) void { | 152 | export fn zig_big_union(x: BigUnion) void { |
| 153 | assertOrPanic(x.a.a == 1); | 153 | expect(x.a.a == 1); |
| 154 | assertOrPanic(x.a.b == 2); | 154 | expect(x.a.b == 2); |
| 155 | assertOrPanic(x.a.c == 3); | 155 | expect(x.a.c == 3); |
| 156 | assertOrPanic(x.a.d == 4); | 156 | expect(x.a.d == 4); |
| 157 | assertOrPanic(x.a.e == 5); | 157 | expect(x.a.e == 5); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | const SmallStructInts = extern struct { | 160 | const SmallStructInts = extern struct { |
| ... | @@ -176,10 +176,10 @@ test "C ABI small struct of ints" { | ... | @@ -176,10 +176,10 @@ test "C ABI small struct of ints" { |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | export fn zig_small_struct_ints(x: SmallStructInts) void { | 178 | export fn zig_small_struct_ints(x: SmallStructInts) void { |
| 179 | assertOrPanic(x.a == 1); | 179 | expect(x.a == 1); |
| 180 | assertOrPanic(x.b == 2); | 180 | expect(x.b == 2); |
| 181 | assertOrPanic(x.c == 3); | 181 | expect(x.c == 3); |
| 182 | assertOrPanic(x.d == 4); | 182 | expect(x.d == 4); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | const SplitStructInt = extern struct { | 185 | const SplitStructInt = extern struct { |
| ... | @@ -199,9 +199,9 @@ test "C ABI split struct of ints" { | ... | @@ -199,9 +199,9 @@ test "C ABI split struct of ints" { |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | export fn zig_split_struct_ints(x: SplitStructInt) void { | 201 | export fn zig_split_struct_ints(x: SplitStructInt) void { |
| 202 | assertOrPanic(x.a == 1234); | 202 | expect(x.a == 1234); |
| 203 | assertOrPanic(x.b == 100); | 203 | expect(x.b == 100); |
| 204 | assertOrPanic(x.c == 1337); | 204 | expect(x.c == 1337); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | extern fn c_big_struct_both(BigStruct) BigStruct; | 207 | extern fn c_big_struct_both(BigStruct) BigStruct; |
| ... | @@ -215,19 +215,19 @@ test "C ABI sret and byval together" { | ... | @@ -215,19 +215,19 @@ test "C ABI sret and byval together" { |
| 215 | .e = 5, | 215 | .e = 5, |
| 216 | }; | 216 | }; |
| 217 | var y = c_big_struct_both(s); | 217 | var y = c_big_struct_both(s); |
| 218 | assertOrPanic(y.a == 10); | 218 | expect(y.a == 10); |
| 219 | assertOrPanic(y.b == 11); | 219 | expect(y.b == 11); |
| 220 | assertOrPanic(y.c == 12); | 220 | expect(y.c == 12); |
| 221 | assertOrPanic(y.d == 13); | 221 | expect(y.d == 13); |
| 222 | assertOrPanic(y.e == 14); | 222 | expect(y.e == 14); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | export fn zig_big_struct_both(x: BigStruct) BigStruct { | 225 | export fn zig_big_struct_both(x: BigStruct) BigStruct { |
| 226 | assertOrPanic(x.a == 30); | 226 | expect(x.a == 30); |
| 227 | assertOrPanic(x.b == 31); | 227 | expect(x.b == 31); |
| 228 | assertOrPanic(x.c == 32); | 228 | expect(x.c == 32); |
| 229 | assertOrPanic(x.d == 33); | 229 | expect(x.d == 33); |
| 230 | assertOrPanic(x.e == 34); | 230 | expect(x.e == 34); |
| 231 | var s = BigStruct{ | 231 | var s = BigStruct{ |
| 232 | .a = 20, | 232 | .a = 20, |
| 233 | .b = 21, | 233 | .b = 21, |
test/standalone/brace_expansion/main.zig+3-6| ... | @@ -3,6 +3,7 @@ const io = std.io; | ... | @@ -3,6 +3,7 @@ const io = std.io; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const debug = std.debug; | 4 | const debug = std.debug; |
| 5 | const assert = debug.assert; | 5 | const assert = debug.assert; |
| 6 | const testing = std.testing; | ||
| 6 | const Buffer = std.Buffer; | 7 | const Buffer = std.Buffer; |
| 7 | const ArrayList = std.ArrayList; | 8 | const ArrayList = std.ArrayList; |
| 8 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| ... | @@ -220,11 +221,7 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void { | ... | @@ -220,11 +221,7 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void { |
| 220 | var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable; | 221 | var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable; |
| 221 | defer output_buf.deinit(); | 222 | defer output_buf.deinit(); |
| 222 | 223 | ||
| 223 | if (expandString(test_input, &output_buf)) { | 224 | testing.expectError(expected_err, expandString(test_input, &output_buf)); |
| 224 | unreachable; | ||
| 225 | } else |err| { | ||
| 226 | assert(expected_err == err); | ||
| 227 | } | ||
| 228 | } | 225 | } |
| 229 | 226 | ||
| 230 | test "valid inputs" { | 227 | test "valid inputs" { |
| ... | @@ -256,5 +253,5 @@ fn expectExpansion(test_input: []const u8, expected_result: []const u8) void { | ... | @@ -256,5 +253,5 @@ fn expectExpansion(test_input: []const u8, expected_result: []const u8) void { |
| 256 | 253 | ||
| 257 | expandString(test_input, &result) catch unreachable; | 254 | expandString(test_input, &result) catch unreachable; |
| 258 | 255 | ||
| 259 | assert(mem.eql(u8, result.toSlice(), expected_result)); | 256 | testing.expectEqualSlices(u8, expected_result, result.toSlice()); |
| 260 | } | 257 | } |
test/standalone/issue_794/main.zig+2-2| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const c = @cImport(@cInclude("foo.h")); | 1 | const c = @cImport(@cInclude("foo.h")); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const assert = std.debug.assert; | 3 | const testing = std.testing; |
| 4 | 4 | ||
| 5 | test "c import" { | 5 | test "c import" { |
| 6 | comptime assert(c.NUMBER == 1234); | 6 | comptime testing.expect(c.NUMBER == 1234); |
| 7 | } | 7 | } |
test/tests.zig+132-60| ... | @@ -48,13 +48,14 @@ const test_targets = []TestTarget{ | ... | @@ -48,13 +48,14 @@ const test_targets = []TestTarget{ |
| 48 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB | 48 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB |
| 49 | 49 | ||
| 50 | pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | 50 | pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { |
| 51 | const cases = b.allocator.create(CompareOutputContext{ | 51 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 52 | cases.* = CompareOutputContext{ | ||
| 52 | .b = b, | 53 | .b = b, |
| 53 | .step = b.step("test-compare-output", "Run the compare output tests"), | 54 | .step = b.step("test-compare-output", "Run the compare output tests"), |
| 54 | .test_index = 0, | 55 | .test_index = 0, |
| 55 | .test_filter = test_filter, | 56 | .test_filter = test_filter, |
| 56 | .modes = modes, | 57 | .modes = modes, |
| 57 | }) catch unreachable; | 58 | }; |
| 58 | 59 | ||
| 59 | compare_output.addCases(cases); | 60 | compare_output.addCases(cases); |
| 60 | 61 | ||
| ... | @@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: | ... | @@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | 65 | pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { |
| 65 | const cases = b.allocator.create(CompareOutputContext{ | 66 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 67 | cases.* = CompareOutputContext{ | ||
| 66 | .b = b, | 68 | .b = b, |
| 67 | .step = b.step("test-runtime-safety", "Run the runtime safety tests"), | 69 | .step = b.step("test-runtime-safety", "Run the runtime safety tests"), |
| 68 | .test_index = 0, | 70 | .test_index = 0, |
| 69 | .test_filter = test_filter, | 71 | .test_filter = test_filter, |
| 70 | .modes = modes, | 72 | .modes = modes, |
| 71 | }) catch unreachable; | 73 | }; |
| 72 | 74 | ||
| 73 | runtime_safety.addCases(cases); | 75 | runtime_safety.addCases(cases); |
| 74 | 76 | ||
| ... | @@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: | ... | @@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | 80 | pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { |
| 79 | const cases = b.allocator.create(CompileErrorContext{ | 81 | const cases = b.allocator.create(CompileErrorContext) catch unreachable; |
| 82 | cases.* = CompileErrorContext{ | ||
| 80 | .b = b, | 83 | .b = b, |
| 81 | .step = b.step("test-compile-errors", "Run the compile error tests"), | 84 | .step = b.step("test-compile-errors", "Run the compile error tests"), |
| 82 | .test_index = 0, | 85 | .test_index = 0, |
| 83 | .test_filter = test_filter, | 86 | .test_filter = test_filter, |
| 84 | .modes = modes, | 87 | .modes = modes, |
| 85 | }) catch unreachable; | 88 | }; |
| 86 | 89 | ||
| 87 | compile_errors.addCases(cases); | 90 | compile_errors.addCases(cases); |
| 88 | 91 | ||
| ... | @@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: | ... | @@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: |
| 90 | } | 93 | } |
| 91 | 94 | ||
| 92 | pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | 95 | pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { |
| 93 | const cases = b.allocator.create(BuildExamplesContext{ | 96 | const cases = b.allocator.create(BuildExamplesContext) catch unreachable; |
| 97 | cases.* = BuildExamplesContext{ | ||
| 94 | .b = b, | 98 | .b = b, |
| 95 | .step = b.step("test-build-examples", "Build the examples"), | 99 | .step = b.step("test-build-examples", "Build the examples"), |
| 96 | .test_index = 0, | 100 | .test_index = 0, |
| 97 | .test_filter = test_filter, | 101 | .test_filter = test_filter, |
| 98 | .modes = modes, | 102 | .modes = modes, |
| 99 | }) catch unreachable; | 103 | }; |
| 100 | 104 | ||
| 101 | build_examples.addCases(cases); | 105 | build_examples.addCases(cases); |
| 102 | 106 | ||
| ... | @@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M | ... | @@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M |
| 119 | } | 123 | } |
| 120 | 124 | ||
| 121 | pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | 125 | pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { |
| 122 | const cases = b.allocator.create(CompareOutputContext{ | 126 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 127 | cases.* = CompareOutputContext{ | ||
| 123 | .b = b, | 128 | .b = b, |
| 124 | .step = b.step("test-asm-link", "Run the assemble and link tests"), | 129 | .step = b.step("test-asm-link", "Run the assemble and link tests"), |
| 125 | .test_index = 0, | 130 | .test_index = 0, |
| 126 | .test_filter = test_filter, | 131 | .test_filter = test_filter, |
| 127 | .modes = modes, | 132 | .modes = modes, |
| 128 | }) catch unreachable; | 133 | }; |
| 129 | 134 | ||
| 130 | assemble_and_link.addCases(cases); | 135 | assemble_and_link.addCases(cases); |
| 131 | 136 | ||
| ... | @@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode | ... | @@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode |
| 133 | } | 138 | } |
| 134 | 139 | ||
| 135 | pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { | 140 | pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { |
| 136 | const cases = b.allocator.create(TranslateCContext{ | 141 | const cases = b.allocator.create(TranslateCContext) catch unreachable; |
| 142 | cases.* = TranslateCContext{ | ||
| 137 | .b = b, | 143 | .b = b, |
| 138 | .step = b.step("test-translate-c", "Run the C transation tests"), | 144 | .step = b.step("test-translate-c", "Run the C transation tests"), |
| 139 | .test_index = 0, | 145 | .test_index = 0, |
| 140 | .test_filter = test_filter, | 146 | .test_filter = test_filter, |
| 141 | }) catch unreachable; | 147 | }; |
| 142 | 148 | ||
| 143 | translate_c.addCases(cases); | 149 | translate_c.addCases(cases); |
| 144 | 150 | ||
| ... | @@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St | ... | @@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St |
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { | 154 | pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { |
| 149 | const cases = b.allocator.create(GenHContext{ | 155 | const cases = b.allocator.create(GenHContext) catch unreachable; |
| 156 | cases.* = GenHContext{ | ||
| 150 | .b = b, | 157 | .b = b, |
| 151 | .step = b.step("test-gen-h", "Run the C header file generation tests"), | 158 | .step = b.step("test-gen-h", "Run the C header file generation tests"), |
| 152 | .test_index = 0, | 159 | .test_index = 0, |
| 153 | .test_filter = test_filter, | 160 | .test_filter = test_filter, |
| 154 | }) catch unreachable; | 161 | }; |
| 155 | 162 | ||
| 156 | gen_h.addCases(cases); | 163 | gen_h.addCases(cases); |
| 157 | 164 | ||
| ... | @@ -163,25 +170,35 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons | ... | @@ -163,25 +170,35 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons |
| 163 | for (test_targets) |test_target| { | 170 | for (test_targets) |test_target| { |
| 164 | const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch); | 171 | const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch); |
| 165 | for (modes) |mode| { | 172 | for (modes) |mode| { |
| 166 | for ([]bool{ | 173 | for ([]bool{ false, true }) |link_libc| { |
| 167 | false, | 174 | for ([]bool{ false, true }) |single_threaded| { |
| 168 | true, | 175 | if (link_libc and !is_native) { |
| 169 | }) |link_libc| { | 176 | // don't assume we have a cross-compiling libc set up |
| 170 | if (link_libc and !is_native) { | 177 | continue; |
| 171 | // don't assume we have a cross-compiling libc set up | 178 | } |
| 172 | continue; | 179 | const these_tests = b.addTest(root_src); |
| 173 | } | 180 | these_tests.setNamePrefix(b.fmt( |
| 174 | const these_tests = b.addTest(root_src); | 181 | "{}-{}-{}-{}-{}-{} ", |
| 175 | these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare")); | 182 | name, |
| 176 | these_tests.setFilter(test_filter); | 183 | @tagName(test_target.os), |
| 177 | these_tests.setBuildMode(mode); | 184 | @tagName(test_target.arch), |
| 178 | if (!is_native) { | 185 | @tagName(mode), |
| 179 | these_tests.setTarget(test_target.arch, test_target.os, test_target.environ); | 186 | if (link_libc) "c" else "bare", |
| 180 | } | 187 | if (single_threaded) "single" else "multi", |
| 181 | if (link_libc) { | 188 | )); |
| 182 | these_tests.linkSystemLibrary("c"); | 189 | these_tests.setFilter(test_filter); |
| 190 | these_tests.setBuildMode(mode); | ||
| 191 | if (!is_native) { | ||
| 192 | these_tests.setTarget(test_target.arch, test_target.os, test_target.environ); | ||
| 193 | } | ||
| 194 | if (link_libc) { | ||
| 195 | these_tests.linkSystemLibrary("c"); | ||
| 196 | } | ||
| 197 | if (mem.eql(u8, name, "std")) { | ||
| 198 | these_tests.overrideStdDir("std"); | ||
| 199 | } | ||
| 200 | step.dependOn(&these_tests.step); | ||
| 183 | } | 201 | } |
| 184 | step.dependOn(&these_tests.step); | ||
| 185 | } | 202 | } |
| 186 | } | 203 | } |
| 187 | } | 204 | } |
| ... | @@ -237,7 +254,8 @@ pub const CompareOutputContext = struct { | ... | @@ -237,7 +254,8 @@ pub const CompareOutputContext = struct { |
| 237 | 254 | ||
| 238 | pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep { | 255 | pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep { |
| 239 | const allocator = context.b.allocator; | 256 | const allocator = context.b.allocator; |
| 240 | const ptr = allocator.create(RunCompareOutputStep{ | 257 | const ptr = allocator.create(RunCompareOutputStep) catch unreachable; |
| 258 | ptr.* = RunCompareOutputStep{ | ||
| 241 | .context = context, | 259 | .context = context, |
| 242 | .exe_path = exe_path, | 260 | .exe_path = exe_path, |
| 243 | .name = name, | 261 | .name = name, |
| ... | @@ -245,7 +263,7 @@ pub const CompareOutputContext = struct { | ... | @@ -245,7 +263,7 @@ pub const CompareOutputContext = struct { |
| 245 | .test_index = context.test_index, | 263 | .test_index = context.test_index, |
| 246 | .step = build.Step.init("RunCompareOutput", allocator, make), | 264 | .step = build.Step.init("RunCompareOutput", allocator, make), |
| 247 | .cli_args = cli_args, | 265 | .cli_args = cli_args, |
| 248 | }) catch unreachable; | 266 | }; |
| 249 | context.test_index += 1; | 267 | context.test_index += 1; |
| 250 | return ptr; | 268 | return ptr; |
| 251 | } | 269 | } |
| ... | @@ -324,13 +342,14 @@ pub const CompareOutputContext = struct { | ... | @@ -324,13 +342,14 @@ pub const CompareOutputContext = struct { |
| 324 | 342 | ||
| 325 | pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep { | 343 | pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep { |
| 326 | const allocator = context.b.allocator; | 344 | const allocator = context.b.allocator; |
| 327 | const ptr = allocator.create(RuntimeSafetyRunStep{ | 345 | const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable; |
| 346 | ptr.* = RuntimeSafetyRunStep{ | ||
| 328 | .context = context, | 347 | .context = context, |
| 329 | .exe_path = exe_path, | 348 | .exe_path = exe_path, |
| 330 | .name = name, | 349 | .name = name, |
| 331 | .test_index = context.test_index, | 350 | .test_index = context.test_index, |
| 332 | .step = build.Step.init("RuntimeSafetyRun", allocator, make), | 351 | .step = build.Step.init("RuntimeSafetyRun", allocator, make), |
| 333 | }) catch unreachable; | 352 | }; |
| 334 | 353 | ||
| 335 | context.test_index += 1; | 354 | context.test_index += 1; |
| 336 | return ptr; | 355 | return ptr; |
| ... | @@ -420,7 +439,10 @@ pub const CompareOutputContext = struct { | ... | @@ -420,7 +439,10 @@ pub const CompareOutputContext = struct { |
| 420 | pub fn addCase(self: *CompareOutputContext, case: TestCase) void { | 439 | pub fn addCase(self: *CompareOutputContext, case: TestCase) void { |
| 421 | const b = self.b; | 440 | const b = self.b; |
| 422 | 441 | ||
| 423 | const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; | 442 | const root_src = os.path.join( |
| 443 | b.allocator, | ||
| 444 | [][]const u8{ b.cache_root, case.sources.items[0].filename }, | ||
| 445 | ) catch unreachable; | ||
| 424 | 446 | ||
| 425 | switch (case.special) { | 447 | switch (case.special) { |
| 426 | Special.Asm => { | 448 | Special.Asm => { |
| ... | @@ -433,7 +455,10 @@ pub const CompareOutputContext = struct { | ... | @@ -433,7 +455,10 @@ pub const CompareOutputContext = struct { |
| 433 | exe.addAssemblyFile(root_src); | 455 | exe.addAssemblyFile(root_src); |
| 434 | 456 | ||
| 435 | for (case.sources.toSliceConst()) |src_file| { | 457 | for (case.sources.toSliceConst()) |src_file| { |
| 436 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | 458 | const expanded_src_path = os.path.join( |
| 459 | b.allocator, | ||
| 460 | [][]const u8{ b.cache_root, src_file.filename }, | ||
| 461 | ) catch unreachable; | ||
| 437 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 462 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 438 | exe.step.dependOn(&write_src.step); | 463 | exe.step.dependOn(&write_src.step); |
| 439 | } | 464 | } |
| ... | @@ -457,7 +482,10 @@ pub const CompareOutputContext = struct { | ... | @@ -457,7 +482,10 @@ pub const CompareOutputContext = struct { |
| 457 | } | 482 | } |
| 458 | 483 | ||
| 459 | for (case.sources.toSliceConst()) |src_file| { | 484 | for (case.sources.toSliceConst()) |src_file| { |
| 460 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | 485 | const expanded_src_path = os.path.join( |
| 486 | b.allocator, | ||
| 487 | [][]const u8{ b.cache_root, src_file.filename }, | ||
| 488 | ) catch unreachable; | ||
| 461 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 489 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 462 | exe.step.dependOn(&write_src.step); | 490 | exe.step.dependOn(&write_src.step); |
| 463 | } | 491 | } |
| ... | @@ -480,7 +508,10 @@ pub const CompareOutputContext = struct { | ... | @@ -480,7 +508,10 @@ pub const CompareOutputContext = struct { |
| 480 | } | 508 | } |
| 481 | 509 | ||
| 482 | for (case.sources.toSliceConst()) |src_file| { | 510 | for (case.sources.toSliceConst()) |src_file| { |
| 483 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | 511 | const expanded_src_path = os.path.join( |
| 512 | b.allocator, | ||
| 513 | [][]const u8{ b.cache_root, src_file.filename }, | ||
| 514 | ) catch unreachable; | ||
| 484 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 515 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 485 | exe.step.dependOn(&write_src.step); | 516 | exe.step.dependOn(&write_src.step); |
| 486 | } | 517 | } |
| ... | @@ -507,6 +538,7 @@ pub const CompileErrorContext = struct { | ... | @@ -507,6 +538,7 @@ pub const CompileErrorContext = struct { |
| 507 | expected_errors: ArrayList([]const u8), | 538 | expected_errors: ArrayList([]const u8), |
| 508 | link_libc: bool, | 539 | link_libc: bool, |
| 509 | is_exe: bool, | 540 | is_exe: bool, |
| 541 | is_test: bool, | ||
| 510 | 542 | ||
| 511 | const SourceFile = struct { | 543 | const SourceFile = struct { |
| 512 | filename: []const u8, | 544 | filename: []const u8, |
| ... | @@ -535,14 +567,15 @@ pub const CompileErrorContext = struct { | ... | @@ -535,14 +567,15 @@ pub const CompileErrorContext = struct { |
| 535 | 567 | ||
| 536 | pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep { | 568 | pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep { |
| 537 | const allocator = context.b.allocator; | 569 | const allocator = context.b.allocator; |
| 538 | const ptr = allocator.create(CompileCmpOutputStep{ | 570 | const ptr = allocator.create(CompileCmpOutputStep) catch unreachable; |
| 571 | ptr.* = CompileCmpOutputStep{ | ||
| 539 | .step = build.Step.init("CompileCmpOutput", allocator, make), | 572 | .step = build.Step.init("CompileCmpOutput", allocator, make), |
| 540 | .context = context, | 573 | .context = context, |
| 541 | .name = name, | 574 | .name = name, |
| 542 | .test_index = context.test_index, | 575 | .test_index = context.test_index, |
| 543 | .case = case, | 576 | .case = case, |
| 544 | .build_mode = build_mode, | 577 | .build_mode = build_mode, |
| 545 | }) catch unreachable; | 578 | }; |
| 546 | 579 | ||
| 547 | context.test_index += 1; | 580 | context.test_index += 1; |
| 548 | return ptr; | 581 | return ptr; |
| ... | @@ -552,13 +585,25 @@ pub const CompileErrorContext = struct { | ... | @@ -552,13 +585,25 @@ pub const CompileErrorContext = struct { |
| 552 | const self = @fieldParentPtr(CompileCmpOutputStep, "step", step); | 585 | const self = @fieldParentPtr(CompileCmpOutputStep, "step", step); |
| 553 | const b = self.context.b; | 586 | const b = self.context.b; |
| 554 | 587 | ||
| 555 | const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable; | 588 | const root_src = os.path.join( |
| 556 | const obj_path = os.path.join(b.allocator, b.cache_root, "test.o") catch unreachable; | 589 | b.allocator, |
| 590 | [][]const u8{ b.cache_root, self.case.sources.items[0].filename }, | ||
| 591 | ) catch unreachable; | ||
| 592 | const obj_path = os.path.join( | ||
| 593 | b.allocator, | ||
| 594 | [][]const u8{ b.cache_root, "test.o" }, | ||
| 595 | ) catch unreachable; | ||
| 557 | 596 | ||
| 558 | var zig_args = ArrayList([]const u8).init(b.allocator); | 597 | var zig_args = ArrayList([]const u8).init(b.allocator); |
| 559 | zig_args.append(b.zig_exe) catch unreachable; | 598 | zig_args.append(b.zig_exe) catch unreachable; |
| 560 | 599 | ||
| 561 | zig_args.append(if (self.case.is_exe) "build-exe" else "build-obj") catch unreachable; | 600 | if (self.case.is_exe) { |
| 601 | try zig_args.append("build-exe"); | ||
| 602 | } else if (self.case.is_test) { | ||
| 603 | try zig_args.append("test"); | ||
| 604 | } else { | ||
| 605 | try zig_args.append("build-obj"); | ||
| 606 | } | ||
| 562 | zig_args.append(b.pathFromRoot(root_src)) catch unreachable; | 607 | zig_args.append(b.pathFromRoot(root_src)) catch unreachable; |
| 563 | 608 | ||
| 564 | zig_args.append("--name") catch unreachable; | 609 | zig_args.append("--name") catch unreachable; |
| ... | @@ -654,13 +699,15 @@ pub const CompileErrorContext = struct { | ... | @@ -654,13 +699,15 @@ pub const CompileErrorContext = struct { |
| 654 | } | 699 | } |
| 655 | 700 | ||
| 656 | pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { | 701 | pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { |
| 657 | const tc = self.b.allocator.create(TestCase{ | 702 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 703 | tc.* = TestCase{ | ||
| 658 | .name = name, | 704 | .name = name, |
| 659 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), | 705 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 660 | .expected_errors = ArrayList([]const u8).init(self.b.allocator), | 706 | .expected_errors = ArrayList([]const u8).init(self.b.allocator), |
| 661 | .link_libc = false, | 707 | .link_libc = false, |
| 662 | .is_exe = false, | 708 | .is_exe = false, |
| 663 | }) catch unreachable; | 709 | .is_test = false, |
| 710 | }; | ||
| 664 | 711 | ||
| 665 | tc.addSourceFile(".tmp_source.zig", source); | 712 | tc.addSourceFile(".tmp_source.zig", source); |
| 666 | comptime var arg_i = 0; | 713 | comptime var arg_i = 0; |
| ... | @@ -687,6 +734,12 @@ pub const CompileErrorContext = struct { | ... | @@ -687,6 +734,12 @@ pub const CompileErrorContext = struct { |
| 687 | self.addCase(tc); | 734 | self.addCase(tc); |
| 688 | } | 735 | } |
| 689 | 736 | ||
| 737 | pub fn addTest(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { | ||
| 738 | const tc = self.create(name, source, expected_lines); | ||
| 739 | tc.is_test = true; | ||
| 740 | self.addCase(tc); | ||
| 741 | } | ||
| 742 | |||
| 690 | pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void { | 743 | pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void { |
| 691 | const b = self.b; | 744 | const b = self.b; |
| 692 | 745 | ||
| ... | @@ -700,7 +753,10 @@ pub const CompileErrorContext = struct { | ... | @@ -700,7 +753,10 @@ pub const CompileErrorContext = struct { |
| 700 | self.step.dependOn(&compile_and_cmp_errors.step); | 753 | self.step.dependOn(&compile_and_cmp_errors.step); |
| 701 | 754 | ||
| 702 | for (case.sources.toSliceConst()) |src_file| { | 755 | for (case.sources.toSliceConst()) |src_file| { |
| 703 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | 756 | const expanded_src_path = os.path.join( |
| 757 | b.allocator, | ||
| 758 | [][]const u8{ b.cache_root, src_file.filename }, | ||
| 759 | ) catch unreachable; | ||
| 704 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 760 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 705 | compile_and_cmp_errors.step.dependOn(&write_src.step); | 761 | compile_and_cmp_errors.step.dependOn(&write_src.step); |
| 706 | } | 762 | } |
| ... | @@ -814,13 +870,14 @@ pub const TranslateCContext = struct { | ... | @@ -814,13 +870,14 @@ pub const TranslateCContext = struct { |
| 814 | 870 | ||
| 815 | pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep { | 871 | pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep { |
| 816 | const allocator = context.b.allocator; | 872 | const allocator = context.b.allocator; |
| 817 | const ptr = allocator.create(TranslateCCmpOutputStep{ | 873 | const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable; |
| 874 | ptr.* = TranslateCCmpOutputStep{ | ||
| 818 | .step = build.Step.init("ParseCCmpOutput", allocator, make), | 875 | .step = build.Step.init("ParseCCmpOutput", allocator, make), |
| 819 | .context = context, | 876 | .context = context, |
| 820 | .name = name, | 877 | .name = name, |
| 821 | .test_index = context.test_index, | 878 | .test_index = context.test_index, |
| 822 | .case = case, | 879 | .case = case, |
| 823 | }) catch unreachable; | 880 | }; |
| 824 | 881 | ||
| 825 | context.test_index += 1; | 882 | context.test_index += 1; |
| 826 | return ptr; | 883 | return ptr; |
| ... | @@ -830,7 +887,10 @@ pub const TranslateCContext = struct { | ... | @@ -830,7 +887,10 @@ pub const TranslateCContext = struct { |
| 830 | const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step); | 887 | const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step); |
| 831 | const b = self.context.b; | 888 | const b = self.context.b; |
| 832 | 889 | ||
| 833 | const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable; | 890 | const root_src = os.path.join( |
| 891 | b.allocator, | ||
| 892 | [][]const u8{ b.cache_root, self.case.sources.items[0].filename }, | ||
| 893 | ) catch unreachable; | ||
| 834 | 894 | ||
| 835 | var zig_args = ArrayList([]const u8).init(b.allocator); | 895 | var zig_args = ArrayList([]const u8).init(b.allocator); |
| 836 | zig_args.append(b.zig_exe) catch unreachable; | 896 | zig_args.append(b.zig_exe) catch unreachable; |
| ... | @@ -921,12 +981,13 @@ pub const TranslateCContext = struct { | ... | @@ -921,12 +981,13 @@ pub const TranslateCContext = struct { |
| 921 | } | 981 | } |
| 922 | 982 | ||
| 923 | pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { | 983 | pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { |
| 924 | const tc = self.b.allocator.create(TestCase{ | 984 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 985 | tc.* = TestCase{ | ||
| 925 | .name = name, | 986 | .name = name, |
| 926 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), | 987 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 927 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), | 988 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), |
| 928 | .allow_warnings = allow_warnings, | 989 | .allow_warnings = allow_warnings, |
| 929 | }) catch unreachable; | 990 | }; |
| 930 | 991 | ||
| 931 | tc.addSourceFile(filename, source); | 992 | tc.addSourceFile(filename, source); |
| 932 | comptime var arg_i = 0; | 993 | comptime var arg_i = 0; |
| ... | @@ -963,7 +1024,10 @@ pub const TranslateCContext = struct { | ... | @@ -963,7 +1024,10 @@ pub const TranslateCContext = struct { |
| 963 | self.step.dependOn(&translate_c_and_cmp.step); | 1024 | self.step.dependOn(&translate_c_and_cmp.step); |
| 964 | 1025 | ||
| 965 | for (case.sources.toSliceConst()) |src_file| { | 1026 | for (case.sources.toSliceConst()) |src_file| { |
| 966 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | 1027 | const expanded_src_path = os.path.join( |
| 1028 | b.allocator, | ||
| 1029 | [][]const u8{ b.cache_root, src_file.filename }, | ||
| 1030 | ) catch unreachable; | ||
| 967 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 1031 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 968 | translate_c_and_cmp.step.dependOn(&write_src.step); | 1032 | translate_c_and_cmp.step.dependOn(&write_src.step); |
| 969 | } | 1033 | } |
| ... | @@ -1008,14 +1072,15 @@ pub const GenHContext = struct { | ... | @@ -1008,14 +1072,15 @@ pub const GenHContext = struct { |
| 1008 | 1072 | ||
| 1009 | pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep { | 1073 | pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep { |
| 1010 | const allocator = context.b.allocator; | 1074 | const allocator = context.b.allocator; |
| 1011 | const ptr = allocator.create(GenHCmpOutputStep{ | 1075 | const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; |
| 1076 | ptr.* = GenHCmpOutputStep{ | ||
| 1012 | .step = build.Step.init("ParseCCmpOutput", allocator, make), | 1077 | .step = build.Step.init("ParseCCmpOutput", allocator, make), |
| 1013 | .context = context, | 1078 | .context = context, |
| 1014 | .h_path = h_path, | 1079 | .h_path = h_path, |
| 1015 | .name = name, | 1080 | .name = name, |
| 1016 | .test_index = context.test_index, | 1081 | .test_index = context.test_index, |
| 1017 | .case = case, | 1082 | .case = case, |
| 1018 | }) catch unreachable; | 1083 | }; |
| 1019 | 1084 | ||
| 1020 | context.test_index += 1; | 1085 | context.test_index += 1; |
| 1021 | return ptr; | 1086 | return ptr; |
| ... | @@ -1055,11 +1120,12 @@ pub const GenHContext = struct { | ... | @@ -1055,11 +1120,12 @@ pub const GenHContext = struct { |
| 1055 | } | 1120 | } |
| 1056 | 1121 | ||
| 1057 | pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { | 1122 | pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase { |
| 1058 | const tc = self.b.allocator.create(TestCase{ | 1123 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 1124 | tc.* = TestCase{ | ||
| 1059 | .name = name, | 1125 | .name = name, |
| 1060 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), | 1126 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 1061 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), | 1127 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), |
| 1062 | }) catch unreachable; | 1128 | }; |
| 1063 | 1129 | ||
| 1064 | tc.addSourceFile(filename, source); | 1130 | tc.addSourceFile(filename, source); |
| 1065 | comptime var arg_i = 0; | 1131 | comptime var arg_i = 0; |
| ... | @@ -1076,7 +1142,10 @@ pub const GenHContext = struct { | ... | @@ -1076,7 +1142,10 @@ pub const GenHContext = struct { |
| 1076 | 1142 | ||
| 1077 | pub fn addCase(self: *GenHContext, case: *const TestCase) void { | 1143 | pub fn addCase(self: *GenHContext, case: *const TestCase) void { |
| 1078 | const b = self.b; | 1144 | const b = self.b; |
| 1079 | const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; | 1145 | const root_src = os.path.join( |
| 1146 | b.allocator, | ||
| 1147 | [][]const u8{ b.cache_root, case.sources.items[0].filename }, | ||
| 1148 | ) catch unreachable; | ||
| 1080 | 1149 | ||
| 1081 | const mode = builtin.Mode.Debug; | 1150 | const mode = builtin.Mode.Debug; |
| 1082 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; | 1151 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; |
| ... | @@ -1088,7 +1157,10 @@ pub const GenHContext = struct { | ... | @@ -1088,7 +1157,10 @@ pub const GenHContext = struct { |
| 1088 | obj.setBuildMode(mode); | 1157 | obj.setBuildMode(mode); |
| 1089 | 1158 | ||
| 1090 | for (case.sources.toSliceConst()) |src_file| { | 1159 | for (case.sources.toSliceConst()) |src_file| { |
| 1091 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | 1160 | const expanded_src_path = os.path.join( |
| 1161 | b.allocator, | ||
| 1162 | [][]const u8{ b.cache_root, src_file.filename }, | ||
| 1163 | ) catch unreachable; | ||
| 1092 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 1164 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 1093 | obj.step.dependOn(&write_src.step); | 1165 | obj.step.dependOn(&write_src.step); |
| 1094 | } | 1166 | } |
test/translate_c.zig+61-31| ... | @@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 117 | \\}; | 117 | \\}; |
| 118 | , | 118 | , |
| 119 | \\pub const struct_Foo = extern struct { | 119 | \\pub const struct_Foo = extern struct { |
| 120 | \\ a: ?[*]Foo, | 120 | \\ a: [*c]Foo, |
| 121 | \\}; | 121 | \\}; |
| 122 | \\pub const Foo = struct_Foo; | 122 | \\pub const Foo = struct_Foo; |
| 123 | \\pub const struct_Bar = extern struct { | 123 | \\pub const struct_Bar = extern struct { |
| 124 | \\ a: ?[*]Foo, | 124 | \\ a: [*c]Foo, |
| 125 | \\}; | 125 | \\}; |
| 126 | ); | 126 | ); |
| 127 | 127 | ||
| ... | @@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 213 | , | 213 | , |
| 214 | \\const struct_Foo = extern struct { | 214 | \\const struct_Foo = extern struct { |
| 215 | \\ x: c_int, | 215 | \\ x: c_int, |
| 216 | \\ y: ?[*]u8, | 216 | \\ y: [*c]u8, |
| 217 | \\}; | 217 | \\}; |
| 218 | , | 218 | , |
| 219 | \\pub const Foo = struct_Foo; | 219 | \\pub const Foo = struct_Foo; |
| ... | @@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 244 | , | 244 | , |
| 245 | \\pub const BarB = enum_Bar.B; | 245 | \\pub const BarB = enum_Bar.B; |
| 246 | , | 246 | , |
| 247 | \\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void; | 247 | \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void; |
| 248 | , | 248 | , |
| 249 | \\pub const Foo = struct_Foo; | 249 | \\pub const Foo = struct_Foo; |
| 250 | , | 250 | , |
| ... | @@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 254 | cases.add("constant size array", | 254 | cases.add("constant size array", |
| 255 | \\void func(int array[20]); | 255 | \\void func(int array[20]); |
| 256 | , | 256 | , |
| 257 | \\pub extern fn func(array: ?[*]c_int) void; | 257 | \\pub extern fn func(array: [*c]c_int) void; |
| 258 | ); | 258 | ); |
| 259 | 259 | ||
| 260 | cases.add("self referential struct with function pointer", | 260 | cases.add("self referential struct with function pointer", |
| ... | @@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 263 | \\}; | 263 | \\}; |
| 264 | , | 264 | , |
| 265 | \\pub const struct_Foo = extern struct { | 265 | \\pub const struct_Foo = extern struct { |
| 266 | \\ derp: ?extern fn(?[*]struct_Foo) void, | 266 | \\ derp: ?extern fn([*c]struct_Foo) void, |
| 267 | \\}; | 267 | \\}; |
| 268 | , | 268 | , |
| 269 | \\pub const Foo = struct_Foo; | 269 | \\pub const Foo = struct_Foo; |
| ... | @@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 322 | \\}; | 322 | \\}; |
| 323 | , | 323 | , |
| 324 | \\pub const struct_Bar = extern struct { | 324 | \\pub const struct_Bar = extern struct { |
| 325 | \\ next: ?[*]struct_Foo, | 325 | \\ next: [*c]struct_Foo, |
| 326 | \\}; | 326 | \\}; |
| 327 | , | 327 | , |
| 328 | \\pub const struct_Foo = extern struct { | 328 | \\pub const struct_Foo = extern struct { |
| 329 | \\ next: ?[*]struct_Bar, | 329 | \\ next: [*c]struct_Bar, |
| 330 | \\}; | 330 | \\}; |
| 331 | ); | 331 | ); |
| 332 | 332 | ||
| ... | @@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 610 | , | 610 | , |
| 611 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { | 611 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 612 | \\ if ((a != 0) and (b != 0)) return 0; | 612 | \\ if ((a != 0) and (b != 0)) return 0; |
| 613 | \\ if ((b != 0) and (c != null)) return 1; | 613 | \\ if ((b != 0) and (c != 0)) return 1; |
| 614 | \\ if ((a != 0) and (c != null)) return 2; | 614 | \\ if ((a != 0) and (c != 0)) return 2; |
| 615 | \\ if ((a != 0) or (b != 0)) return 3; | 615 | \\ if ((a != 0) or (b != 0)) return 3; |
| 616 | \\ if ((b != 0) or (c != null)) return 4; | 616 | \\ if ((b != 0) or (c != 0)) return 4; |
| 617 | \\ if ((a != 0) or (c != null)) return 5; | 617 | \\ if ((a != 0) or (c != 0)) return 5; |
| 618 | \\ return 6; | 618 | \\ return 6; |
| 619 | \\} | 619 | \\} |
| 620 | ); | 620 | ); |
| ... | @@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 710 | \\pub const struct_Foo = extern struct { | 710 | \\pub const struct_Foo = extern struct { |
| 711 | \\ field: c_int, | 711 | \\ field: c_int, |
| 712 | \\}; | 712 | \\}; |
| 713 | \\pub export fn read_field(foo: ?[*]struct_Foo) c_int { | 713 | \\pub export fn read_field(foo: [*c]struct_Foo) c_int { |
| 714 | \\ return foo.?.field; | 714 | \\ return foo.?.field; |
| 715 | \\} | 715 | \\} |
| 716 | ); | 716 | ); |
| ... | @@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 756 | \\ return x; | 756 | \\ return x; |
| 757 | \\} | 757 | \\} |
| 758 | , | 758 | , |
| 759 | \\pub export fn foo(x: ?[*]c_ushort) ?*c_void { | 759 | \\pub export fn foo(x: [*c]c_ushort) ?*c_void { |
| 760 | \\ return @ptrCast(?*c_void, x); | 760 | \\ return @ptrCast(?*c_void, x); |
| 761 | \\} | 761 | \\} |
| 762 | ); | 762 | ); |
| ... | @@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 777 | \\ return 0; | 777 | \\ return 0; |
| 778 | \\} | 778 | \\} |
| 779 | , | 779 | , |
| 780 | \\pub export fn foo() ?[*]c_int { | 780 | \\pub export fn foo() [*c]c_int { |
| 781 | \\ return null; | 781 | \\ return 0; |
| 782 | \\} | 782 | \\} |
| 783 | ); | 783 | ); |
| 784 | 784 | ||
| ... | @@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1086 | \\ *x = 1; | 1086 | \\ *x = 1; |
| 1087 | \\} | 1087 | \\} |
| 1088 | , | 1088 | , |
| 1089 | \\pub export fn foo(x: ?[*]c_int) void { | 1089 | \\pub export fn foo(x: [*c]c_int) void { |
| 1090 | \\ x.?.* = 1; | 1090 | \\ x.?.* = 1; |
| 1091 | \\} | 1091 | \\} |
| 1092 | ); | 1092 | ); |
| ... | @@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1114 | , | 1114 | , |
| 1115 | \\pub fn foo() c_int { | 1115 | \\pub fn foo() c_int { |
| 1116 | \\ var x: c_int = 1234; | 1116 | \\ var x: c_int = 1234; |
| 1117 | \\ var ptr: ?[*]c_int = &x; | 1117 | \\ var ptr: [*c]c_int = &x; |
| 1118 | \\ return ptr.?.*; | 1118 | \\ return ptr.?.*; |
| 1119 | \\} | 1119 | \\} |
| 1120 | ); | 1120 | ); |
| ... | @@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1124 | \\ return "bar"; | 1124 | \\ return "bar"; |
| 1125 | \\} | 1125 | \\} |
| 1126 | , | 1126 | , |
| 1127 | \\pub fn foo() ?[*]const u8 { | 1127 | \\pub fn foo() [*c]const u8 { |
| 1128 | \\ return c"bar"; | 1128 | \\ return c"bar"; |
| 1129 | \\} | 1129 | \\} |
| 1130 | ); | 1130 | ); |
| ... | @@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1253 | \\ return (float *)a; | 1253 | \\ return (float *)a; |
| 1254 | \\} | 1254 | \\} |
| 1255 | , | 1255 | , |
| 1256 | \\fn ptrcast(a: ?[*]c_int) ?[*]f32 { | 1256 | \\fn ptrcast(a: [*c]c_int) [*c]f32 { |
| 1257 | \\ return @ptrCast(?[*]f32, a); | 1257 | \\ return @ptrCast([*c]f32, a); |
| 1258 | \\} | 1258 | \\} |
| 1259 | ); | 1259 | ); |
| 1260 | 1260 | ||
| ... | @@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1280 | \\ return !(a == 0); | 1280 | \\ return !(a == 0); |
| 1281 | \\ return !(a != 0); | 1281 | \\ return !(a != 0); |
| 1282 | \\ return !(b != 0); | 1282 | \\ return !(b != 0); |
| 1283 | \\ return !(c != null); | 1283 | \\ return !(c != 0); |
| 1284 | \\} | 1284 | \\} |
| 1285 | ); | 1285 | ); |
| 1286 | 1286 | ||
| ... | @@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1297 | cases.add("const ptr initializer", | 1297 | cases.add("const ptr initializer", |
| 1298 | \\static const char *v0 = "0.0.0"; | 1298 | \\static const char *v0 = "0.0.0"; |
| 1299 | , | 1299 | , |
| 1300 | \\pub var v0: ?[*]const u8 = c"0.0.0"; | 1300 | \\pub var v0: [*c]const u8 = c"0.0.0"; |
| 1301 | ); | 1301 | ); |
| 1302 | 1302 | ||
| 1303 | cases.add("static incomplete array inside function", | 1303 | cases.add("static incomplete array inside function", |
| ... | @@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1306 | \\} | 1306 | \\} |
| 1307 | , | 1307 | , |
| 1308 | \\pub fn foo() void { | 1308 | \\pub fn foo() void { |
| 1309 | \\ const v2: [*]const u8 = c"2.2.2"; | 1309 | \\ const v2: [*c]const u8 = c"2.2.2"; |
| 1310 | \\} | 1310 | \\} |
| 1311 | ); | 1311 | ); |
| 1312 | 1312 | ||
| 1313 | cases.add("macro pointer cast", | 1313 | cases.add("macro pointer cast", |
| 1314 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) | 1314 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) |
| 1315 | , | 1315 | , |
| 1316 | \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE); | 1316 | \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*c]NRF_GPIO_Type)(NRF_GPIO_BASE); |
| 1317 | ); | 1317 | ); |
| 1318 | 1318 | ||
| 1319 | cases.add("if on none bool", | 1319 | cases.add("if on non-bool", |
| 1320 | \\enum SomeEnum { A, B, C }; | 1320 | \\enum SomeEnum { A, B, C }; |
| 1321 | \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) { | 1321 | \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) { |
| 1322 | \\ if (a) return 0; | 1322 | \\ if (a) return 0; |
| ... | @@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1337 | \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { | 1337 | \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { |
| 1338 | \\ if (a != 0) return 0; | 1338 | \\ if (a != 0) return 0; |
| 1339 | \\ if (b != 0) return 1; | 1339 | \\ if (b != 0) return 1; |
| 1340 | \\ if (c != null) return 2; | 1340 | \\ if (c != 0) return 2; |
| 1341 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; | 1341 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; |
| 1342 | \\ return 4; | 1342 | \\ return 4; |
| 1343 | \\} | 1343 | \\} |
| 1344 | ); | 1344 | ); |
| 1345 | 1345 | ||
| 1346 | cases.add("while on none bool", | 1346 | cases.add("while on non-bool", |
| 1347 | \\int while_none_bool(int a, float b, void *c) { | 1347 | \\int while_none_bool(int a, float b, void *c) { |
| 1348 | \\ while (a) return 0; | 1348 | \\ while (a) return 0; |
| 1349 | \\ while (b) return 1; | 1349 | \\ while (b) return 1; |
| ... | @@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1354 | \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { | 1354 | \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 1355 | \\ while (a != 0) return 0; | 1355 | \\ while (a != 0) return 0; |
| 1356 | \\ while (b != 0) return 1; | 1356 | \\ while (b != 0) return 1; |
| 1357 | \\ while (c != null) return 2; | 1357 | \\ while (c != 0) return 2; |
| 1358 | \\ return 3; | 1358 | \\ return 3; |
| 1359 | \\} | 1359 | \\} |
| 1360 | ); | 1360 | ); |
| 1361 | 1361 | ||
| 1362 | cases.add("for on none bool", | 1362 | cases.add("for on non-bool", |
| 1363 | \\int for_none_bool(int a, float b, void *c) { | 1363 | \\int for_none_bool(int a, float b, void *c) { |
| 1364 | \\ for (;a;) return 0; | 1364 | \\ for (;a;) return 0; |
| 1365 | \\ for (;b;) return 1; | 1365 | \\ for (;b;) return 1; |
| ... | @@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1370 | \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { | 1370 | \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { |
| 1371 | \\ while (a != 0) return 0; | 1371 | \\ while (a != 0) return 0; |
| 1372 | \\ while (b != 0) return 1; | 1372 | \\ while (b != 0) return 1; |
| 1373 | \\ while (c != null) return 2; | 1373 | \\ while (c != 0) return 2; |
| 1374 | \\ return 3; | 1374 | \\ return 3; |
| 1375 | \\} | 1375 | \\} |
| 1376 | ); | 1376 | ); |
| ... | @@ -1416,4 +1416,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1416,4 +1416,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1416 | \\ } | 1416 | \\ } |
| 1417 | \\} | 1417 | \\} |
| 1418 | ); | 1418 | ); |
| 1419 | |||
| 1420 | // cases.add("empty array with initializer", | ||
| 1421 | // "int a[4] = {};" | ||
| 1422 | // , | ||
| 1423 | // "pub var a: [4]c_int = [1]c_int{0} ** 4;" | ||
| 1424 | // ); | ||
| 1425 | |||
| 1426 | // cases.add("array with initialization", | ||
| 1427 | // "int a[4] = {1, 2, 3, 4};" | ||
| 1428 | // , | ||
| 1429 | // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};" | ||
| 1430 | // ); | ||
| 1431 | |||
| 1432 | // cases.add("array with incomplete initialization", | ||
| 1433 | // "int a[4] = {3, 4};" | ||
| 1434 | // , | ||
| 1435 | // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);" | ||
| 1436 | // ); | ||
| 1437 | |||
| 1438 | // cases.add("2D array with initialization", | ||
| 1439 | // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };" | ||
| 1440 | // , | ||
| 1441 | // "pub var a: [3][3]c_int = [3][3]c_int{[3]c_int{1, 2, 3}, [3]c_int{4, 5, 6}, [3]c_int{7, 8, 9}};" | ||
| 1442 | // ); | ||
| 1443 | |||
| 1444 | // cases.add("2D array with incomplete initialization", | ||
| 1445 | // "int a[3][3] = { {1, 2}, {4, 5, 6} };" | ||
| 1446 | // , | ||
| 1447 | // "pub var a: [3][3]c_int = [2][3]c_int{[2]c_int{1, 2} ++ [1]c_int{0}, [3]c_int{4, 5, 6}} ++ [1][3]c_int{[1]c_int{0} ** 3};" | ||
| 1448 | // ); | ||
| 1419 | } | 1449 | } |