| author | |
| committer | |
| log | c00216701c64269a2395e84f3ccff99d6fb89ffc |
| tree | 9fa071b9e96f9eadc5069b71634b11fc13b00839 |
| parent | c21884e1d64e4193e03be4f3064917a26b34b142 |
| parent | 45081c1e9cc28757cb563c77553631f7a92b29d8 |
124 files changed, 6574 insertions(+), 1880 deletions(-)
.builds/freebsd.yml created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | arch: x86_64 | ||
| 2 | image: freebsd | ||
| 3 | packages: | ||
| 4 | - cmake | ||
| 5 | - ninja | ||
| 6 | - llvm70 | ||
| 7 | sources: | ||
| 8 | - https://github.com/ziglang/zig.git | ||
| 9 | tasks: | ||
| 10 | - build: | | ||
| 11 | cd zig && mkdir build && cd build | ||
| 12 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release | ||
| 13 | ninja install | ||
| 14 | - test: | | ||
| 15 | cd zig/build | ||
| 16 | bin/zig test ../test/behavior.zig | ||
| 17 | # TODO enable all tests | ||
| 18 | #bin/zig build --build-file ../build.zig test | ||
| 19 | # TODO integrate with the download page updater and make a | ||
| 20 | # static build available to download for FreeBSD. | ||
| 21 | # This will require setting up a cache of LLVM/Clang built | ||
| 22 | # statically. | ||
CMakeLists.txt+16| ... | @@ -444,6 +444,7 @@ set(ZIG_STD_FILES | ... | @@ -444,6 +444,7 @@ set(ZIG_STD_FILES |
| 444 | "buffer.zig" | 444 | "buffer.zig" |
| 445 | "build.zig" | 445 | "build.zig" |
| 446 | "c/darwin.zig" | 446 | "c/darwin.zig" |
| 447 | "c/freebsd.zig" | ||
| 447 | "c/index.zig" | 448 | "c/index.zig" |
| 448 | "c/linux.zig" | 449 | "c/linux.zig" |
| 449 | "c/windows.zig" | 450 | "c/windows.zig" |
| ... | @@ -490,6 +491,7 @@ set(ZIG_STD_FILES | ... | @@ -490,6 +491,7 @@ set(ZIG_STD_FILES |
| 490 | "heap.zig" | 491 | "heap.zig" |
| 491 | "index.zig" | 492 | "index.zig" |
| 492 | "io.zig" | 493 | "io.zig" |
| 494 | "io/seekable_stream.zig" | ||
| 493 | "json.zig" | 495 | "json.zig" |
| 494 | "lazy_init.zig" | 496 | "lazy_init.zig" |
| 495 | "linked_list.zig" | 497 | "linked_list.zig" |
| ... | @@ -582,6 +584,10 @@ set(ZIG_STD_FILES | ... | @@ -582,6 +584,10 @@ set(ZIG_STD_FILES |
| 582 | "os/linux/vdso.zig" | 584 | "os/linux/vdso.zig" |
| 583 | "os/linux/x86_64.zig" | 585 | "os/linux/x86_64.zig" |
| 584 | "os/linux/arm64.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" | ||
| 585 | "os/path.zig" | 591 | "os/path.zig" |
| 586 | "os/time.zig" | 592 | "os/time.zig" |
| 587 | "os/windows/advapi32.zig" | 593 | "os/windows/advapi32.zig" |
| ... | @@ -617,6 +623,16 @@ set(ZIG_STD_FILES | ... | @@ -617,6 +623,16 @@ set(ZIG_STD_FILES |
| 617 | "special/compiler_rt/fixunstfdi.zig" | 623 | "special/compiler_rt/fixunstfdi.zig" |
| 618 | "special/compiler_rt/fixunstfsi.zig" | 624 | "special/compiler_rt/fixunstfsi.zig" |
| 619 | "special/compiler_rt/fixunstfti.zig" | 625 | "special/compiler_rt/fixunstfti.zig" |
| 626 | "special/compiler_rt/fixint.zig" | ||
| 627 | "special/compiler_rt/fixdfdi.zig" | ||
| 628 | "special/compiler_rt/fixdfsi.zig" | ||
| 629 | "special/compiler_rt/fixdfti.zig" | ||
| 630 | "special/compiler_rt/fixsfdi.zig" | ||
| 631 | "special/compiler_rt/fixsfsi.zig" | ||
| 632 | "special/compiler_rt/fixsfti.zig" | ||
| 633 | "special/compiler_rt/fixtfdi.zig" | ||
| 634 | "special/compiler_rt/fixtfsi.zig" | ||
| 635 | "special/compiler_rt/fixtfti.zig" | ||
| 620 | "special/compiler_rt/floattidf.zig" | 636 | "special/compiler_rt/floattidf.zig" |
| 621 | "special/compiler_rt/floattisf.zig" | 637 | "special/compiler_rt/floattisf.zig" |
| 622 | "special/compiler_rt/floattitf.zig" | 638 | "special/compiler_rt/floattitf.zig" |
README.md+71-30| ... | @@ -42,33 +42,71 @@ clarity. | ... | @@ -42,33 +42,71 @@ clarity. |
| 42 | * In addition to creating executables, creating a C library is a primary use | 42 | * In addition to creating executables, creating a C library is a primary use |
| 43 | case. You can export an auto-generated .h file. | 43 | case. You can export an auto-generated .h file. |
| 44 | 44 | ||
| 45 | ### Support Table | 45 | ### Supported Targets |
| 46 | 46 | ||
| 47 | Freestanding means that you do not directly interact with the OS | 47 | #### Tier 1 Support |
| 48 | or you are writing your own OS. | 48 | |
| 49 | 49 | * Not only can Zig generate machine code for these targets, but the standard | |
| 50 | Note that if you use libc or other libraries to interact with the OS, | 50 | library cross-platform abstractions have implementations for these targets. |
| 51 | that counts as "freestanding" for the purposes of this table. | 51 | Thus it is practical to write a pure Zig application with no dependency on |
| 52 | 52 | libc. | |
| 53 | | | freestanding | linux | macosx | windows | other | | 53 | * The CI server automatically tests these targets on every commit to master |
| 54 | |-------------|--------------|---------|---------|---------|---------| | 54 | branch, and updates ziglang.org/download with links to pre-built binaries. |
| 55 | |i386 | OK | planned | OK | planned | planned | | 55 | * These targets have debug info capabilities and therefore produce stack |
| 56 | |x86_64 | OK | OK | OK | OK | planned | | 56 | traces on failed assertions. |
| 57 | |arm | OK | planned | planned | planned | planned | | 57 | |
| 58 | |bpf | OK | planned | N/A | N/A | planned | | 58 | #### Tier 2 Support |
| 59 | |hexagon | OK | planned | N/A | N/A | planned | | 59 | |
| 60 | |mips | OK | planned | N/A | N/A | planned | | 60 | * There may be some standard library implementations, but many abstractions |
| 61 | |powerpc | OK | planned | N/A | N/A | planned | | 61 | will give an "Unsupported OS" compile error. One can link with libc or other |
| 62 | |r600 | OK | planned | N/A | N/A | planned | | 62 | libraries to fill in the gaps in the standard library. |
| 63 | |amdgcn | OK | planned | N/A | N/A | planned | | 63 | * These targets are known to work, but are not automatically tested, so there |
| 64 | |sparc | OK | planned | N/A | N/A | planned | | 64 | are occasional regressions. |
| 65 | |s390x | OK | planned | N/A | N/A | planned | | 65 | * Some tests may be disabled for these targets as we work toward Tier 1 |
| 66 | |spir | OK | planned | N/A | N/A | planned | | 66 | support. |
| 67 | |lanai | OK | planned | N/A | N/A | planned | | 67 | |
| 68 | |wasm32 | planned | N/A | N/A | N/A | N/A | | 68 | #### Tier 3 Support |
| 69 | |wasm64 | planned | N/A | N/A | N/A | N/A | | 69 | |
| 70 | |riscv32 | planned | planned | N/A | N/A | planned | | 70 | * The standard library has little to no knowledge of the existence of this |
| 71 | |riscv64 | planned | planned | N/A | N/A | planned | | 71 | target. |
| 72 | * Because Zig is based on LLVM, it has the capability to build for these | ||
| 73 | targets, and LLVM has the target enabled by default. | ||
| 74 | * These targets are not frequently tested; one will likely need to contribute | ||
| 75 | to Zig in order to build for these targets. | ||
| 76 | * The Zig compiler might need to be updated with a few things such as | ||
| 77 | - what sizes are the C integer types | ||
| 78 | - C ABI calling convention for this target | ||
| 79 | - bootstrap code and default panic handler | ||
| 80 | |||
| 81 | #### Tier 4 Support | ||
| 82 | |||
| 83 | * Support for these targets is entirely experimental. | ||
| 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 | ||
| 86 | build LLVM from source with special configure flags. | ||
| 87 | |||
| 88 | #### Support Table | ||
| 89 | |||
| 90 | | | freestanding | linux | macosx | windows | freebsd | other | | ||
| 91 | |--------|--------------|--------|--------|---------|---------|--------| | ||
| 92 | |x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 | | ||
| 93 | |i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | | ||
| 94 | |arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | ||
| 95 | |arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | | ||
| 96 | |bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 97 | |hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 98 | |mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 99 | |powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 100 | |r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 101 | |amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 102 | |sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 103 | |s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 104 | |spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 105 | |lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | | ||
| 106 | |wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | | ||
| 107 | |wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | | ||
| 108 | |riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | | ||
| 109 | |riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | | ||
| 72 | 110 | ||
| 73 | ## Community | 111 | ## Community |
| 74 | 112 | ||
| ... | @@ -133,7 +171,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows | ... | @@ -133,7 +171,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows |
| 133 | *Note: Stage 2 compiler is not complete. Beta users of Zig should use the | 171 | *Note: Stage 2 compiler is not complete. Beta users of Zig should use the |
| 134 | Stage 1 compiler for now.* | 172 | Stage 1 compiler for now.* |
| 135 | 173 | ||
| 136 | Dependencies are the same as Stage 1, except now you have a working zig compiler. | 174 | Dependencies are the same as Stage 1, except now you can use stage 1 to compile |
| 175 | Zig code. | ||
| 137 | 176 | ||
| 138 | ``` | 177 | ``` |
| 139 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install | 178 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install |
| ... | @@ -145,11 +184,13 @@ binary. | ... | @@ -145,11 +184,13 @@ binary. |
| 145 | 184 | ||
| 146 | ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler | 185 | ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler |
| 147 | 186 | ||
| 148 | This is the actual compiler binary that we will install to the system. | ||
| 149 | |||
| 150 | *Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is | 187 | *Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is |
| 151 | not yet supported.* | 188 | not yet supported.* |
| 152 | 189 | ||
| 190 | Once the self-hosted compiler can build itself, this will be the actual | ||
| 191 | compiler binary that we will install to the system. Until then, users should | ||
| 192 | use stage 1. | ||
| 193 | |||
| 153 | #### Debug / Development Build | 194 | #### Debug / Development Build |
| 154 | 195 | ||
| 155 | ``` | 196 | ``` |
build.zig+1-1| ... | @@ -297,7 +297,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | ... | @@ -297,7 +297,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 297 | ); | 297 | ); |
| 298 | 298 | ||
| 299 | exe.linkSystemLibrary("pthread"); | 299 | exe.linkSystemLibrary("pthread"); |
| 300 | } else if (exe.target.isDarwin()) { | 300 | } else if (exe.target.isDarwin() or exe.target.isFreeBSD()) { |
| 301 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { | 301 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { |
| 302 | // Compiler is GCC. | 302 | // Compiler is GCC. |
| 303 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); | 303 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); |
ci/azure/linux_script+3| ... | @@ -34,6 +34,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then | ... | @@ -34,6 +34,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 34 | 34 | ||
| 35 | SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1) | 35 | SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1) |
| 36 | BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL) | 36 | BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL) |
| 37 | # `set -x` causes these variables to be mangled. | ||
| 38 | # See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html | ||
| 39 | set +x | ||
| 37 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" | 40 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" |
| 38 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" | 41 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" |
| 39 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" | 42 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" |
ci/azure/macos_script+3| ... | @@ -98,6 +98,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then | ... | @@ -98,6 +98,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 98 | 98 | ||
| 99 | SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1) | 99 | SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1) |
| 100 | BYTESIZE=$(wc -c < $TARBALL) | 100 | BYTESIZE=$(wc -c < $TARBALL) |
| 101 | # `set -x` causes these variables to be mangled. | ||
| 102 | # See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html | ||
| 103 | set +x | ||
| 101 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" | 104 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" |
| 102 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" | 105 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" |
| 103 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" | 106 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" |
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-8.0.0-win64-msvc-release.tar.xz" | 9 | wget -nv "https://ziglang.org/deps/llvm%2bclang-8.0.0-win64-msvc-release.tar.xz" |
ci/azure/windows_upload+3| ... | @@ -25,6 +25,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then | ... | @@ -25,6 +25,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 25 | 25 | ||
| 26 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) | 26 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) |
| 27 | BYTESIZE=$(wc -c < $TARBALL) | 27 | BYTESIZE=$(wc -c < $TARBALL) |
| 28 | # `set -x` causes these variables to be mangled. | ||
| 29 | # See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html | ||
| 30 | set +x | ||
| 28 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" | 31 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" |
| 29 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" | 32 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" |
| 30 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" | 33 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" |
cmake/Findclang.cmake+2| ... | @@ -30,6 +30,7 @@ else() | ... | @@ -30,6 +30,7 @@ else() |
| 30 | /usr/lib/llvm/8/include | 30 | /usr/lib/llvm/8/include |
| 31 | /usr/lib/llvm-8/include | 31 | /usr/lib/llvm-8/include |
| 32 | /usr/lib/llvm-8.0/include | 32 | /usr/lib/llvm-8.0/include |
| 33 | /usr/local/llvm80/include | ||
| 33 | /mingw64/include) | 34 | /mingw64/include) |
| 34 | 35 | ||
| 35 | macro(FIND_AND_ADD_CLANG_LIB _libname_) | 36 | macro(FIND_AND_ADD_CLANG_LIB _libname_) |
| ... | @@ -40,6 +41,7 @@ else() | ... | @@ -40,6 +41,7 @@ else() |
| 40 | /usr/lib/llvm/8/lib | 41 | /usr/lib/llvm/8/lib |
| 41 | /usr/lib/llvm-8/lib | 42 | /usr/lib/llvm-8/lib |
| 42 | /usr/lib/llvm-8.0/lib | 43 | /usr/lib/llvm-8.0/lib |
| 44 | /usr/local/llvm80/lib | ||
| 43 | /mingw64/lib | 45 | /mingw64/lib |
| 44 | /c/msys64/mingw64/lib | 46 | /c/msys64/mingw64/lib |
| 45 | c:\\msys64\\mingw64\\lib) | 47 | c:\\msys64\\mingw64\\lib) |
cmake/Findlld.cmake+7-1| ... | @@ -9,9 +9,14 @@ | ... | @@ -9,9 +9,14 @@ |
| 9 | find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h | 9 | find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h |
| 10 | PATHS | 10 | PATHS |
| 11 | /usr/lib/llvm-8.0/include | 11 | /usr/lib/llvm-8.0/include |
| 12 | /usr/local/llvm80/include | ||
| 12 | /mingw64/include) | 13 | /mingw64/include) |
| 13 | 14 | ||
| 14 | find_library(LLD_LIBRARY NAMES lld-8.0 lld PATHS /usr/lib/llvm-8.0/lib) | 15 | find_library(LLD_LIBRARY NAMES lld-8.0 lld80 lld |
| 16 | PATHS | ||
| 17 | /usr/lib/llvm-8.0/lib | ||
| 18 | /usr/local/llvm80/lib | ||
| 19 | ) | ||
| 15 | if(EXISTS ${LLD_LIBRARY}) | 20 | if(EXISTS ${LLD_LIBRARY}) |
| 16 | set(LLD_LIBRARIES ${LLD_LIBRARY}) | 21 | set(LLD_LIBRARIES ${LLD_LIBRARY}) |
| 17 | else() | 22 | else() |
| ... | @@ -20,6 +25,7 @@ else() | ... | @@ -20,6 +25,7 @@ else() |
| 20 | find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_} | 25 | find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_} |
| 21 | PATHS | 26 | PATHS |
| 22 | /usr/lib/llvm-8.0/lib | 27 | /usr/lib/llvm-8.0/lib |
| 28 | /usr/local/llvm80/lib | ||
| 23 | /mingw64/lib | 29 | /mingw64/lib |
| 24 | /c/msys64/mingw64/lib | 30 | /c/msys64/mingw64/lib |
| 25 | c:/msys64/mingw64/lib) | 31 | c:/msys64/mingw64/lib) |
cmake/Findllvm.cmake+1-1| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | # LLVM_LIBDIRS | 8 | # LLVM_LIBDIRS |
| 9 | 9 | ||
| 10 | find_program(LLVM_CONFIG_EXE | 10 | find_program(LLVM_CONFIG_EXE |
| 11 | NAMES llvm-config-8 llvm-config-8.0 llvm-config | 11 | NAMES llvm-config-8 llvm-config-8.0 llvm-config80 llvm-config |
| 12 | PATHS | 12 | PATHS |
| 13 | "/mingw64/bin" | 13 | "/mingw64/bin" |
| 14 | "/c/msys64/mingw64/bin" | 14 | "/c/msys64/mingw64/bin" |
deps/lld/ELF/OutputSections.cpp+1-1| ... | @@ -95,7 +95,7 @@ void OutputSection::addSection(InputSection *IS) { | ... | @@ -95,7 +95,7 @@ void OutputSection::addSection(InputSection *IS) { |
| 95 | Flags = IS->Flags; | 95 | Flags = IS->Flags; |
| 96 | } else { | 96 | } else { |
| 97 | // Otherwise, check if new type or flags are compatible with existing ones. | 97 | // Otherwise, check if new type or flags are compatible with existing ones. |
| 98 | unsigned Mask = SHF_ALLOC | SHF_TLS | SHF_LINK_ORDER; | 98 | unsigned Mask = SHF_TLS | SHF_LINK_ORDER; |
| 99 | if ((Flags & Mask) != (IS->Flags & Mask)) | 99 | if ((Flags & Mask) != (IS->Flags & Mask)) |
| 100 | error("incompatible section flags for " + Name + "\n>>> " + toString(IS) + | 100 | error("incompatible section flags for " + Name + "\n>>> " + toString(IS) + |
| 101 | ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name + | 101 | ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name + |
doc/langref.html.in+166-101| ... | @@ -8,7 +8,13 @@ | ... | @@ -8,7 +8,13 @@ |
| 8 | body{ | 8 | body{ |
| 9 | background-color:#111; | 9 | background-color:#111; |
| 10 | color: #bbb; | 10 | color: #bbb; |
| 11 | font-family: sans-serif; | 11 | font-family: system-ui, |
| 12 | /* Fallbacks for browsers that don't support system-ui */ | ||
| 13 | /* https://caniuse.com/#search=system-ui */ | ||
| 14 | -apple-system, /* iOS and macOS */ | ||
| 15 | Roboto, /* Android */ | ||
| 16 | "Segoe UI", /* Windows */ | ||
| 17 | sans-serif; | ||
| 12 | } | 18 | } |
| 13 | a { | 19 | a { |
| 14 | color: #88f; | 20 | color: #88f; |
| ... | @@ -159,7 +165,7 @@ const std = @import("std"); | ... | @@ -159,7 +165,7 @@ const std = @import("std"); |
| 159 | 165 | ||
| 160 | pub fn main() !void { | 166 | pub fn main() !void { |
| 161 | // 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. |
| 162 | var stdout_file = try std.io.getStdOut(); | 168 | const stdout_file = try std.io.getStdOut(); |
| 163 | // If this program encounters pipe failure when printing to stdout, exit | 169 | // If this program encounters pipe failure when printing to stdout, exit |
| 164 | // with an error. | 170 | // with an error. |
| 165 | try stdout_file.write("Hello, world!\n"); | 171 | try stdout_file.write("Hello, world!\n"); |
| ... | @@ -3273,13 +3279,13 @@ const err = (error {FileNotFound}).FileNotFound; | ... | @@ -3273,13 +3279,13 @@ const err = (error {FileNotFound}).FileNotFound; |
| 3273 | This becomes useful when using {#link|Inferred Error Sets#}. | 3279 | This becomes useful when using {#link|Inferred Error Sets#}. |
| 3274 | </p> | 3280 | </p> |
| 3275 | {#header_open|The Global Error Set#} | 3281 | {#header_open|The Global Error Set#} |
| 3276 | <p>{#syntax#}error{#endsyntax#} refers to the global error set. | 3282 | <p>{#syntax#}anyerror{#endsyntax#} refers to the global error set. |
| 3277 | This is the error set that contains all errors in the entire compilation unit. | 3283 | This is the error set that contains all errors in the entire compilation unit. |
| 3278 | It is a superset of all other error sets and a subset of none of them. | 3284 | It is a superset of all other error sets and a subset of none of them. |
| 3279 | </p> | 3285 | </p> |
| 3280 | <p> | 3286 | <p> |
| 3281 | You can implicitly cast any error set to the global one, and you can explicitly | 3287 | You can implicitly cast any error set to the global one, and you can explicitly |
| 3282 | cast an error of global error set to a non-global one. This inserts a language-level | 3288 | cast an error of the global error set to a non-global one. This inserts a language-level |
| 3283 | assert to make sure the error value is in fact in the destination error set. | 3289 | assert to make sure the error value is in fact in the destination error set. |
| 3284 | </p> | 3290 | </p> |
| 3285 | <p> | 3291 | <p> |
| ... | @@ -4264,13 +4270,21 @@ fn foo() i32 { | ... | @@ -4264,13 +4270,21 @@ fn foo() i32 { |
| 4264 | return 1234; | 4270 | return 1234; |
| 4265 | } | 4271 | } |
| 4266 | {#code_end#} | 4272 | {#code_end#} |
| 4267 | <p>However, if the expression has type {#syntax#}void{#endsyntax#}:</p> | 4273 | <p>However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Function return values can also be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}. </p> |
| 4268 | {#code_begin|test#} | 4274 | {#code_begin|test#} |
| 4269 | test "ignoring expression value" { | 4275 | test "void is ignored" { |
| 4270 | foo(); | 4276 | returnsVoid(); |
| 4277 | } | ||
| 4278 | |||
| 4279 | test "explicitly ignoring expression value" { | ||
| 4280 | _ = foo(); | ||
| 4271 | } | 4281 | } |
| 4272 | 4282 | ||
| 4273 | fn foo() void {} | 4283 | fn returnsVoid() void {} |
| 4284 | |||
| 4285 | fn foo() i32 { | ||
| 4286 | return 1234; | ||
| 4287 | } | ||
| 4274 | {#code_end#} | 4288 | {#code_end#} |
| 4275 | {#header_close#} | 4289 | {#header_close#} |
| 4276 | 4290 | ||
| ... | @@ -5155,6 +5169,34 @@ fn seq(c: u8) void { | ... | @@ -5155,6 +5169,34 @@ fn seq(c: u8) void { |
| 5155 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. | 5169 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 5156 | </p> | 5170 | </p> |
| 5157 | {#header_close#} | 5171 | {#header_close#} |
| 5172 | {#header_open|@alignCast#} | ||
| 5173 | <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre> | ||
| 5174 | <p> | ||
| 5175 | {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#}, | ||
| 5176 | {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#} | ||
| 5177 | except with the alignment adjusted to the new value. | ||
| 5178 | </p> | ||
| 5179 | <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added | ||
| 5180 | to the generated code to make sure the pointer is aligned as promised.</p> | ||
| 5181 | |||
| 5182 | {#header_close#} | ||
| 5183 | {#header_open|@alignOf#} | ||
| 5184 | <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre> | ||
| 5185 | <p> | ||
| 5186 | This function returns the number of bytes that this type should be aligned to | ||
| 5187 | for the current target to match the C ABI. When the child type of a pointer has | ||
| 5188 | this alignment, the alignment can be omitted from the type. | ||
| 5189 | </p> | ||
| 5190 | <pre>{#syntax#}const assert = @import("std").debug.assert; | ||
| 5191 | comptime { | ||
| 5192 | assert(*u32 == *align(@alignOf(u32)) u32); | ||
| 5193 | }{#endsyntax#}</pre> | ||
| 5194 | <p> | ||
| 5195 | The result is a target-specific compile time constant. It is guaranteed to be | ||
| 5196 | less than or equal to {#link|@sizeOf(T)|@sizeOf#}. | ||
| 5197 | </p> | ||
| 5198 | {#see_also|Alignment#} | ||
| 5199 | {#header_close#} | ||
| 5158 | {#header_open|@ArgType#} | 5200 | {#header_open|@ArgType#} |
| 5159 | <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre> | 5201 | <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre> |
| 5160 | <p> | 5202 | <p> |
| ... | @@ -5227,6 +5269,7 @@ fn seq(c: u8) void { | ... | @@ -5227,6 +5269,7 @@ fn seq(c: u8) void { |
| 5227 | 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. | 5269 | 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. |
| 5228 | </p> | 5270 | </p> |
| 5229 | {#header_close#} | 5271 | {#header_close#} |
| 5272 | |||
| 5230 | {#header_open|@bitOffsetOf#} | 5273 | {#header_open|@bitOffsetOf#} |
| 5231 | <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> | 5274 | <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> |
| 5232 | <p> | 5275 | <p> |
| ... | @@ -5239,6 +5282,19 @@ fn seq(c: u8) void { | ... | @@ -5239,6 +5282,19 @@ fn seq(c: u8) void { |
| 5239 | </p> | 5282 | </p> |
| 5240 | {#see_also|@byteOffsetOf#} | 5283 | {#see_also|@byteOffsetOf#} |
| 5241 | {#header_close#} | 5284 | {#header_close#} |
| 5285 | |||
| 5286 | {#header_open|@boolToInt#} | ||
| 5287 | <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre> | ||
| 5288 | <p> | ||
| 5289 | Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to | ||
| 5290 | {#syntax#}u1(0){#endsyntax#}. | ||
| 5291 | </p> | ||
| 5292 | <p> | ||
| 5293 | If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#} | ||
| 5294 | instead of {#syntax#}u1{#endsyntax#}. | ||
| 5295 | </p> | ||
| 5296 | {#header_close#} | ||
| 5297 | |||
| 5242 | {#header_open|@breakpoint#} | 5298 | {#header_open|@breakpoint#} |
| 5243 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> | 5299 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> |
| 5244 | <p> | 5300 | <p> |
| ... | @@ -5250,52 +5306,22 @@ fn seq(c: u8) void { | ... | @@ -5250,52 +5306,22 @@ fn seq(c: u8) void { |
| 5250 | </p> | 5306 | </p> |
| 5251 | 5307 | ||
| 5252 | {#header_close#} | 5308 | {#header_close#} |
| 5253 | {#header_open|@byteOffsetOf#} | ||
| 5254 | <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> | ||
| 5255 | <p> | ||
| 5256 | Returns the byte offset of a field relative to its containing struct. | ||
| 5257 | </p> | ||
| 5258 | {#see_also|@bitOffsetOf#} | ||
| 5259 | {#header_close#} | ||
| 5260 | {#header_open|@alignCast#} | ||
| 5261 | <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre> | ||
| 5262 | <p> | ||
| 5263 | {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#}, | ||
| 5264 | {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#} | ||
| 5265 | except with the alignment adjusted to the new value. | ||
| 5266 | </p> | ||
| 5267 | <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added | ||
| 5268 | to the generated code to make sure the pointer is aligned as promised.</p> | ||
| 5269 | 5309 | ||
| 5270 | {#header_close#} | 5310 | {#header_open|@bswap#} |
| 5271 | {#header_open|@alignOf#} | 5311 | <pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre> |
| 5272 | <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre> | 5312 | <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p> |
| 5273 | <p> | 5313 | <p> |
| 5274 | This function returns the number of bytes that this type should be aligned to | 5314 | Swaps the byte order of the integer. This converts a big endian integer to a little endian integer, |
| 5275 | for the current target to match the C ABI. When the child type of a pointer has | 5315 | and converts a little endian integer to a big endian integer. |
| 5276 | this alignment, the alignment can be omitted from the type. | ||
| 5277 | </p> | ||
| 5278 | <pre>{#syntax#}const assert = @import("std").debug.assert; | ||
| 5279 | comptime { | ||
| 5280 | assert(*u32 == *align(@alignOf(u32)) u32); | ||
| 5281 | }{#endsyntax#}</pre> | ||
| 5282 | <p> | ||
| 5283 | The result is a target-specific compile time constant. It is guaranteed to be | ||
| 5284 | less than or equal to {#link|@sizeOf(T)|@sizeOf#}. | ||
| 5285 | </p> | 5316 | </p> |
| 5286 | {#see_also|Alignment#} | ||
| 5287 | {#header_close#} | 5317 | {#header_close#} |
| 5288 | 5318 | ||
| 5289 | {#header_open|@boolToInt#} | 5319 | {#header_open|@byteOffsetOf#} |
| 5290 | <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre> | 5320 | <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> |
| 5291 | <p> | ||
| 5292 | Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to | ||
| 5293 | {#syntax#}u1(0){#endsyntax#}. | ||
| 5294 | </p> | ||
| 5295 | <p> | 5321 | <p> |
| 5296 | If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#} | 5322 | Returns the byte offset of a field relative to its containing struct. |
| 5297 | instead of {#syntax#}u1{#endsyntax#}. | ||
| 5298 | </p> | 5323 | </p> |
| 5324 | {#see_also|@bitOffsetOf#} | ||
| 5299 | {#header_close#} | 5325 | {#header_close#} |
| 5300 | 5326 | ||
| 5301 | {#header_open|@bytesToSlice#} | 5327 | {#header_open|@bytesToSlice#} |
| ... | @@ -5364,17 +5390,7 @@ comptime { | ... | @@ -5364,17 +5390,7 @@ comptime { |
| 5364 | </p> | 5390 | </p> |
| 5365 | {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#} | 5391 | {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#} |
| 5366 | {#header_close#} | 5392 | {#header_close#} |
| 5367 | {#header_open|@cUndef#} | 5393 | |
| 5368 | <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre> | ||
| 5369 | <p> | ||
| 5370 | This function can only occur inside {#syntax#}@cImport{#endsyntax#}. | ||
| 5371 | </p> | ||
| 5372 | <p> | ||
| 5373 | This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#} | ||
| 5374 | temporary buffer. | ||
| 5375 | </p> | ||
| 5376 | {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#} | ||
| 5377 | {#header_close#} | ||
| 5378 | {#header_open|@clz#} | 5394 | {#header_open|@clz#} |
| 5379 | <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre> | 5395 | <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre> |
| 5380 | <p> | 5396 | <p> |
| ... | @@ -5390,6 +5406,7 @@ comptime { | ... | @@ -5390,6 +5406,7 @@ comptime { |
| 5390 | </p> | 5406 | </p> |
| 5391 | {#see_also|@ctz|@popCount#} | 5407 | {#see_also|@ctz|@popCount#} |
| 5392 | {#header_close#} | 5408 | {#header_close#} |
| 5409 | |||
| 5393 | {#header_open|@cmpxchgStrong#} | 5410 | {#header_open|@cmpxchgStrong#} |
| 5394 | <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> | 5411 | <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> |
| 5395 | <p> | 5412 | <p> |
| ... | @@ -5445,6 +5462,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5445,6 +5462,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5445 | <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> | 5462 | <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 5446 | {#see_also|Compile Variables|cmpxchgStrong#} | 5463 | {#see_also|Compile Variables|cmpxchgStrong#} |
| 5447 | {#header_close#} | 5464 | {#header_close#} |
| 5465 | |||
| 5448 | {#header_open|@compileError#} | 5466 | {#header_open|@compileError#} |
| 5449 | <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre> | 5467 | <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre> |
| 5450 | <p> | 5468 | <p> |
| ... | @@ -5457,6 +5475,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -5457,6 +5475,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5457 | and {#syntax#}comptime{#endsyntax#} functions. | 5475 | and {#syntax#}comptime{#endsyntax#} functions. |
| 5458 | </p> | 5476 | </p> |
| 5459 | {#header_close#} | 5477 | {#header_close#} |
| 5478 | |||
| 5460 | {#header_open|@compileLog#} | 5479 | {#header_open|@compileLog#} |
| 5461 | <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre> | 5480 | <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre> |
| 5462 | <p> | 5481 | <p> |
| ... | @@ -5511,6 +5530,7 @@ test "main" { | ... | @@ -5511,6 +5530,7 @@ test "main" { |
| 5511 | } | 5530 | } |
| 5512 | {#code_end#} | 5531 | {#code_end#} |
| 5513 | {#header_close#} | 5532 | {#header_close#} |
| 5533 | |||
| 5514 | {#header_open|@ctz#} | 5534 | {#header_open|@ctz#} |
| 5515 | <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre> | 5535 | <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre> |
| 5516 | <p> | 5536 | <p> |
| ... | @@ -5526,6 +5546,19 @@ test "main" { | ... | @@ -5526,6 +5546,19 @@ test "main" { |
| 5526 | </p> | 5546 | </p> |
| 5527 | {#see_also|@clz|@popCount#} | 5547 | {#see_also|@clz|@popCount#} |
| 5528 | {#header_close#} | 5548 | {#header_close#} |
| 5549 | |||
| 5550 | {#header_open|@cUndef#} | ||
| 5551 | <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre> | ||
| 5552 | <p> | ||
| 5553 | This function can only occur inside {#syntax#}@cImport{#endsyntax#}. | ||
| 5554 | </p> | ||
| 5555 | <p> | ||
| 5556 | This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#} | ||
| 5557 | temporary buffer. | ||
| 5558 | </p> | ||
| 5559 | {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#} | ||
| 5560 | {#header_close#} | ||
| 5561 | |||
| 5529 | {#header_open|@divExact#} | 5562 | {#header_open|@divExact#} |
| 5530 | <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre> | 5563 | <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 5531 | <p> | 5564 | <p> |
| ... | @@ -5592,27 +5625,15 @@ test "main" { | ... | @@ -5592,27 +5625,15 @@ test "main" { |
| 5592 | {#see_also|@intToEnum#} | 5625 | {#see_also|@intToEnum#} |
| 5593 | {#header_close#} | 5626 | {#header_close#} |
| 5594 | 5627 | ||
| 5595 | {#header_open|@errSetCast#} | ||
| 5596 | <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre> | ||
| 5597 | <p> | ||
| 5598 | Converts an error value from one error set to another error set. Attempting to convert an error | ||
| 5599 | which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}. | ||
| 5600 | </p> | ||
| 5601 | {#header_close#} | ||
| 5602 | |||
| 5603 | {#header_open|@errorName#} | 5628 | {#header_open|@errorName#} |
| 5604 | <pre>{#syntax#}@errorName(err: error) []u8{#endsyntax#}</pre> | 5629 | <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre> |
| 5605 | <p> | 5630 | <p> |
| 5606 | This function returns the string representation of an error. If an error | 5631 | This function returns the string representation of an error. The string representation |
| 5607 | declaration is: | 5632 | of {#syntax#}error.OutOfMem{#endsyntax#} is {#syntax#}"OutOfMem"{#endsyntax#}. |
| 5608 | </p> | ||
| 5609 | <pre>{#syntax#}error OutOfMem{#endsyntax#}</pre> | ||
| 5610 | <p> | ||
| 5611 | Then the string representation is {#syntax#}"OutOfMem"{#endsyntax#}. | ||
| 5612 | </p> | 5633 | </p> |
| 5613 | <p> | 5634 | <p> |
| 5614 | If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application, | 5635 | If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application, |
| 5615 | or all calls have a compile-time known value for {#syntax#}err{#endsyntax#}, then no | 5636 | or all calls have a compile-time known value for {#syntax#}err{#endsyntax#}, then no |
| 5616 | error name table will be generated. | 5637 | error name table will be generated. |
| 5617 | </p> | 5638 | </p> |
| 5618 | {#header_close#} | 5639 | {#header_close#} |
| ... | @@ -5627,13 +5648,14 @@ test "main" { | ... | @@ -5627,13 +5648,14 @@ test "main" { |
| 5627 | {#header_close#} | 5648 | {#header_close#} |
| 5628 | 5649 | ||
| 5629 | {#header_open|@errorToInt#} | 5650 | {#header_open|@errorToInt#} |
| 5630 | <pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8){#endsyntax#}</pre> | 5651 | <pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}</pre> |
| 5631 | <p> | 5652 | <p> |
| 5632 | Supports the following types: | 5653 | Supports the following types: |
| 5633 | </p> | 5654 | </p> |
| 5634 | <ul> | 5655 | <ul> |
| 5635 | <li>error unions</li> | 5656 | <li>{#link|The Global Error Set#}</li> |
| 5636 | <li>{#syntax#}E!void{#endsyntax#}</li> | 5657 | <li>{#link|Error Set Type#}</li> |
| 5658 | <li>{#link|Error Union Type#}</li> | ||
| 5637 | </ul> | 5659 | </ul> |
| 5638 | <p> | 5660 | <p> |
| 5639 | Converts an error to the integer representation of an error. | 5661 | Converts an error to the integer representation of an error. |
| ... | @@ -5645,6 +5667,14 @@ test "main" { | ... | @@ -5645,6 +5667,14 @@ test "main" { |
| 5645 | {#see_also|@intToError#} | 5667 | {#see_also|@intToError#} |
| 5646 | {#header_close#} | 5668 | {#header_close#} |
| 5647 | 5669 | ||
| 5670 | {#header_open|@errSetCast#} | ||
| 5671 | <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre> | ||
| 5672 | <p> | ||
| 5673 | Converts an error value from one error set to another error set. Attempting to convert an error | ||
| 5674 | which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}. | ||
| 5675 | </p> | ||
| 5676 | {#header_close#} | ||
| 5677 | |||
| 5648 | {#header_open|@export#} | 5678 | {#header_open|@export#} |
| 5649 | <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre> | 5679 | <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre> |
| 5650 | <p> | 5680 | <p> |
| ... | @@ -5713,6 +5743,7 @@ test "main" { | ... | @@ -5713,6 +5743,7 @@ test "main" { |
| 5713 | This function is only valid within function scope. | 5743 | This function is only valid within function scope. |
| 5714 | </p> | 5744 | </p> |
| 5715 | {#header_close#} | 5745 | {#header_close#} |
| 5746 | |||
| 5716 | {#header_open|@handle#} | 5747 | {#header_open|@handle#} |
| 5717 | <pre>{#syntax#}@handle(){#endsyntax#}</pre> | 5748 | <pre>{#syntax#}@handle(){#endsyntax#}</pre> |
| 5718 | <p> | 5749 | <p> |
| ... | @@ -5723,6 +5754,7 @@ test "main" { | ... | @@ -5723,6 +5754,7 @@ test "main" { |
| 5723 | This function is only valid within an async function scope. | 5754 | This function is only valid within an async function scope. |
| 5724 | </p> | 5755 | </p> |
| 5725 | {#header_close#} | 5756 | {#header_close#} |
| 5757 | |||
| 5726 | {#header_open|@import#} | 5758 | {#header_open|@import#} |
| 5727 | <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre> | 5759 | <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre> |
| 5728 | <p> | 5760 | <p> |
| ... | @@ -5743,6 +5775,7 @@ test "main" { | ... | @@ -5743,6 +5775,7 @@ test "main" { |
| 5743 | </ul> | 5775 | </ul> |
| 5744 | {#see_also|Compile Variables|@embedFile#} | 5776 | {#see_also|Compile Variables|@embedFile#} |
| 5745 | {#header_close#} | 5777 | {#header_close#} |
| 5778 | |||
| 5746 | {#header_open|@inlineCall#} | 5779 | {#header_open|@inlineCall#} |
| 5747 | <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre> | 5780 | <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre> |
| 5748 | <p> | 5781 | <p> |
| ... | @@ -5788,7 +5821,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5788,7 +5821,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5788 | {#header_open|@intToError#} | 5821 | {#header_open|@intToError#} |
| 5789 | <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre> | 5822 | <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre> |
| 5790 | <p> | 5823 | <p> |
| 5791 | Converts from the integer representation of an error into the global error set type. | 5824 | Converts from the integer representation of an error into {#link|The Global Error Set#} type. |
| 5792 | </p> | 5825 | </p> |
| 5793 | <p> | 5826 | <p> |
| 5794 | It is generally recommended to avoid this | 5827 | It is generally recommended to avoid this |
| ... | @@ -5822,6 +5855,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5822,6 +5855,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5822 | bit count for an integer type is {#syntax#}65535{#endsyntax#}. | 5855 | bit count for an integer type is {#syntax#}65535{#endsyntax#}. |
| 5823 | </p> | 5856 | </p> |
| 5824 | {#header_close#} | 5857 | {#header_close#} |
| 5858 | |||
| 5825 | {#header_open|@memberCount#} | 5859 | {#header_open|@memberCount#} |
| 5826 | <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre> | 5860 | <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre> |
| 5827 | <p> | 5861 | <p> |
| ... | @@ -5848,6 +5882,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5848,6 +5882,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5848 | <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre> | 5882 | <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre> |
| 5849 | <p>Returns the field type of a struct or union.</p> | 5883 | <p>Returns the field type of a struct or union.</p> |
| 5850 | {#header_close#} | 5884 | {#header_close#} |
| 5885 | |||
| 5851 | {#header_open|@memcpy#} | 5886 | {#header_open|@memcpy#} |
| 5852 | <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre> | 5887 | <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre> |
| 5853 | <p> | 5888 | <p> |
| ... | @@ -5866,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } | ... | @@ -5866,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5866 | <pre>{#syntax#}const mem = @import("std").mem; | 5901 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5867 | mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> | 5902 | mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5868 | {#header_close#} | 5903 | {#header_close#} |
| 5904 | |||
| 5869 | {#header_open|@memset#} | 5905 | {#header_open|@memset#} |
| 5870 | <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre> | 5906 | <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre> |
| 5871 | <p> | 5907 | <p> |
| ... | @@ -5883,6 +5919,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> | ... | @@ -5883,6 +5919,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5883 | <pre>{#syntax#}const mem = @import("std").mem; | 5919 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5884 | mem.set(u8, dest, c);{#endsyntax#}</pre> | 5920 | mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5885 | {#header_close#} | 5921 | {#header_close#} |
| 5922 | |||
| 5886 | {#header_open|@mod#} | 5923 | {#header_open|@mod#} |
| 5887 | <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre> | 5924 | <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 5888 | <p> | 5925 | <p> |
| ... | @@ -5896,6 +5933,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> | ... | @@ -5896,6 +5933,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5896 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p> | 5933 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p> |
| 5897 | {#see_also|@rem#} | 5934 | {#see_also|@rem#} |
| 5898 | {#header_close#} | 5935 | {#header_close#} |
| 5936 | |||
| 5899 | {#header_open|@mulWithOverflow#} | 5937 | {#header_open|@mulWithOverflow#} |
| 5900 | <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> | 5938 | <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> |
| 5901 | <p> | 5939 | <p> |
| ... | @@ -5904,6 +5942,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> | ... | @@ -5904,6 +5942,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5904 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. | 5942 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 5905 | </p> | 5943 | </p> |
| 5906 | {#header_close#} | 5944 | {#header_close#} |
| 5945 | |||
| 5907 | {#header_open|@newStackCall#} | 5946 | {#header_open|@newStackCall#} |
| 5908 | <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre> | 5947 | <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre> |
| 5909 | <p> | 5948 | <p> |
| ... | @@ -5940,6 +5979,7 @@ fn targetFunction(x: i32) usize { | ... | @@ -5940,6 +5979,7 @@ fn targetFunction(x: i32) usize { |
| 5940 | } | 5979 | } |
| 5941 | {#code_end#} | 5980 | {#code_end#} |
| 5942 | {#header_close#} | 5981 | {#header_close#} |
| 5982 | |||
| 5943 | {#header_open|@noInlineCall#} | 5983 | {#header_open|@noInlineCall#} |
| 5944 | <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre> | 5984 | <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre> |
| 5945 | <p> | 5985 | <p> |
| ... | @@ -5962,6 +6002,7 @@ fn add(a: i32, b: i32) i32 { | ... | @@ -5962,6 +6002,7 @@ fn add(a: i32, b: i32) i32 { |
| 5962 | </p> | 6002 | </p> |
| 5963 | {#see_also|@inlineCall#} | 6003 | {#see_also|@inlineCall#} |
| 5964 | {#header_close#} | 6004 | {#header_close#} |
| 6005 | |||
| 5965 | {#header_open|@OpaqueType#} | 6006 | {#header_open|@OpaqueType#} |
| 5966 | <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre> | 6007 | <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre> |
| 5967 | <p> | 6008 | <p> |
| ... | @@ -5985,6 +6026,7 @@ test "call foo" { | ... | @@ -5985,6 +6026,7 @@ test "call foo" { |
| 5985 | } | 6026 | } |
| 5986 | {#code_end#} | 6027 | {#code_end#} |
| 5987 | {#header_close#} | 6028 | {#header_close#} |
| 6029 | |||
| 5988 | {#header_open|@panic#} | 6030 | {#header_open|@panic#} |
| 5989 | <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre> | 6031 | <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre> |
| 5990 | <p> | 6032 | <p> |
| ... | @@ -6001,6 +6043,7 @@ test "call foo" { | ... | @@ -6001,6 +6043,7 @@ test "call foo" { |
| 6001 | </ul> | 6043 | </ul> |
| 6002 | {#see_also|Root Source File#} | 6044 | {#see_also|Root Source File#} |
| 6003 | {#header_close#} | 6045 | {#header_close#} |
| 6046 | |||
| 6004 | {#header_open|@popCount#} | 6047 | {#header_open|@popCount#} |
| 6005 | <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre> | 6048 | <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre> |
| 6006 | <p>Counts the number of bits set in an integer.</p> | 6049 | <p>Counts the number of bits set in an integer.</p> |
| ... | @@ -6011,12 +6054,14 @@ test "call foo" { | ... | @@ -6011,12 +6054,14 @@ test "call foo" { |
| 6011 | </p> | 6054 | </p> |
| 6012 | {#see_also|@ctz|@clz#} | 6055 | {#see_also|@ctz|@clz#} |
| 6013 | {#header_close#} | 6056 | {#header_close#} |
| 6057 | |||
| 6014 | {#header_open|@ptrCast#} | 6058 | {#header_open|@ptrCast#} |
| 6015 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> | 6059 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> |
| 6016 | <p> | 6060 | <p> |
| 6017 | Converts a pointer of one type to a pointer of another type. | 6061 | Converts a pointer of one type to a pointer of another type. |
| 6018 | </p> | 6062 | </p> |
| 6019 | {#header_close#} | 6063 | {#header_close#} |
| 6064 | |||
| 6020 | {#header_open|@ptrToInt#} | 6065 | {#header_open|@ptrToInt#} |
| 6021 | <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre> | 6066 | <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre> |
| 6022 | <p> | 6067 | <p> |
| ... | @@ -6031,6 +6076,7 @@ test "call foo" { | ... | @@ -6031,6 +6076,7 @@ test "call foo" { |
| 6031 | <p>To convert the other way, use {#link|@intToPtr#}</p> | 6076 | <p>To convert the other way, use {#link|@intToPtr#}</p> |
| 6032 | 6077 | ||
| 6033 | {#header_close#} | 6078 | {#header_close#} |
| 6079 | |||
| 6034 | {#header_open|@rem#} | 6080 | {#header_open|@rem#} |
| 6035 | <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre> | 6081 | <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 6036 | <p> | 6082 | <p> |
| ... | @@ -6044,6 +6090,7 @@ test "call foo" { | ... | @@ -6044,6 +6090,7 @@ test "call foo" { |
| 6044 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p> | 6090 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p> |
| 6045 | {#see_also|@mod#} | 6091 | {#see_also|@mod#} |
| 6046 | {#header_close#} | 6092 | {#header_close#} |
| 6093 | |||
| 6047 | {#header_open|@returnAddress#} | 6094 | {#header_open|@returnAddress#} |
| 6048 | <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre> | 6095 | <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre> |
| 6049 | <p> | 6096 | <p> |
| ... | @@ -6064,19 +6111,14 @@ test "call foo" { | ... | @@ -6064,19 +6111,14 @@ test "call foo" { |
| 6064 | Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes. | 6111 | Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes. |
| 6065 | </p> | 6112 | </p> |
| 6066 | {#header_close#} | 6113 | {#header_close#} |
| 6114 | |||
| 6067 | {#header_open|@setCold#} | 6115 | {#header_open|@setCold#} |
| 6068 | <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre> | 6116 | <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre> |
| 6069 | <p> | 6117 | <p> |
| 6070 | Tells the optimizer that a function is rarely called. | 6118 | Tells the optimizer that a function is rarely called. |
| 6071 | </p> | 6119 | </p> |
| 6072 | {#header_close#} | 6120 | {#header_close#} |
| 6073 | {#header_open|@setRuntimeSafety#} | ||
| 6074 | <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre> | ||
| 6075 | <p> | ||
| 6076 | Sets whether runtime safety checks are on for the scope that contains the function call. | ||
| 6077 | </p> | ||
| 6078 | 6121 | ||
| 6079 | {#header_close#} | ||
| 6080 | {#header_open|@setEvalBranchQuota#} | 6122 | {#header_open|@setEvalBranchQuota#} |
| 6081 | <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre> | 6123 | <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre> |
| 6082 | <p> | 6124 | <p> |
| ... | @@ -6111,6 +6153,7 @@ test "foo" { | ... | @@ -6111,6 +6153,7 @@ test "foo" { |
| 6111 | 6153 | ||
| 6112 | {#see_also|comptime#} | 6154 | {#see_also|comptime#} |
| 6113 | {#header_close#} | 6155 | {#header_close#} |
| 6156 | |||
| 6114 | {#header_open|@setFloatMode#} | 6157 | {#header_open|@setFloatMode#} |
| 6115 | <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre> | 6158 | <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre> |
| 6116 | <p> | 6159 | <p> |
| ... | @@ -6145,6 +6188,7 @@ pub const FloatMode = enum { | ... | @@ -6145,6 +6188,7 @@ pub const FloatMode = enum { |
| 6145 | </p> | 6188 | </p> |
| 6146 | {#see_also|Floating Point Operations#} | 6189 | {#see_also|Floating Point Operations#} |
| 6147 | {#header_close#} | 6190 | {#header_close#} |
| 6191 | |||
| 6148 | {#header_open|@setGlobalLinkage#} | 6192 | {#header_open|@setGlobalLinkage#} |
| 6149 | <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre> | 6193 | <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre> |
| 6150 | <p> | 6194 | <p> |
| ... | @@ -6152,6 +6196,15 @@ pub const FloatMode = enum { | ... | @@ -6152,6 +6196,15 @@ pub const FloatMode = enum { |
| 6152 | </p> | 6196 | </p> |
| 6153 | {#see_also|Compile Variables#} | 6197 | {#see_also|Compile Variables#} |
| 6154 | {#header_close#} | 6198 | {#header_close#} |
| 6199 | |||
| 6200 | {#header_open|@setRuntimeSafety#} | ||
| 6201 | <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre> | ||
| 6202 | <p> | ||
| 6203 | Sets whether runtime safety checks are on for the scope that contains the function call. | ||
| 6204 | </p> | ||
| 6205 | |||
| 6206 | {#header_close#} | ||
| 6207 | |||
| 6155 | {#header_open|@shlExact#} | 6208 | {#header_open|@shlExact#} |
| 6156 | <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> | 6209 | <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> |
| 6157 | <p> | 6210 | <p> |
| ... | @@ -6164,6 +6217,7 @@ pub const FloatMode = enum { | ... | @@ -6164,6 +6217,7 @@ pub const FloatMode = enum { |
| 6164 | </p> | 6217 | </p> |
| 6165 | {#see_also|@shrExact|@shlWithOverflow#} | 6218 | {#see_also|@shrExact|@shlWithOverflow#} |
| 6166 | {#header_close#} | 6219 | {#header_close#} |
| 6220 | |||
| 6167 | {#header_open|@shlWithOverflow#} | 6221 | {#header_open|@shlWithOverflow#} |
| 6168 | <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre> | 6222 | <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre> |
| 6169 | <p> | 6223 | <p> |
| ... | @@ -6177,6 +6231,7 @@ pub const FloatMode = enum { | ... | @@ -6177,6 +6231,7 @@ pub const FloatMode = enum { |
| 6177 | </p> | 6231 | </p> |
| 6178 | {#see_also|@shlExact|@shrExact#} | 6232 | {#see_also|@shlExact|@shrExact#} |
| 6179 | {#header_close#} | 6233 | {#header_close#} |
| 6234 | |||
| 6180 | {#header_open|@shrExact#} | 6235 | {#header_open|@shrExact#} |
| 6181 | <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> | 6236 | <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> |
| 6182 | <p> | 6237 | <p> |
| ... | @@ -6218,6 +6273,7 @@ pub const FloatMode = enum { | ... | @@ -6218,6 +6273,7 @@ pub const FloatMode = enum { |
| 6218 | This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead. | 6273 | This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead. |
| 6219 | </p> | 6274 | </p> |
| 6220 | {#header_close#} | 6275 | {#header_close#} |
| 6276 | |||
| 6221 | {#header_open|@subWithOverflow#} | 6277 | {#header_open|@subWithOverflow#} |
| 6222 | <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> | 6278 | <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> |
| 6223 | <p> | 6279 | <p> |
| ... | @@ -6226,12 +6282,14 @@ pub const FloatMode = enum { | ... | @@ -6226,12 +6282,14 @@ pub const FloatMode = enum { |
| 6226 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. | 6282 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 6227 | </p> | 6283 | </p> |
| 6228 | {#header_close#} | 6284 | {#header_close#} |
| 6285 | |||
| 6229 | {#header_open|@tagName#} | 6286 | {#header_open|@tagName#} |
| 6230 | <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre> | 6287 | <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre> |
| 6231 | <p> | 6288 | <p> |
| 6232 | Converts an enum value or union value to a slice of bytes representing the name. | 6289 | Converts an enum value or union value to a slice of bytes representing the name. |
| 6233 | </p> | 6290 | </p> |
| 6234 | {#header_close#} | 6291 | {#header_close#} |
| 6292 | |||
| 6235 | {#header_open|@TagType#} | 6293 | {#header_open|@TagType#} |
| 6236 | <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre> | 6294 | <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre> |
| 6237 | <p> | 6295 | <p> |
| ... | @@ -6241,6 +6299,7 @@ pub const FloatMode = enum { | ... | @@ -6241,6 +6299,7 @@ pub const FloatMode = enum { |
| 6241 | For a union, returns the enum type that is used to store the tag value. | 6299 | For a union, returns the enum type that is used to store the tag value. |
| 6242 | </p> | 6300 | </p> |
| 6243 | {#header_close#} | 6301 | {#header_close#} |
| 6302 | |||
| 6244 | {#header_open|@This#} | 6303 | {#header_open|@This#} |
| 6245 | <pre>{#syntax#}@This() type{#endsyntax#}</pre> | 6304 | <pre>{#syntax#}@This() type{#endsyntax#}</pre> |
| 6246 | <p> | 6305 | <p> |
| ... | @@ -6276,6 +6335,7 @@ fn List(comptime T: type) type { | ... | @@ -6276,6 +6335,7 @@ fn List(comptime T: type) type { |
| 6276 | <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details. | 6335 | <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details. |
| 6277 | </p> | 6336 | </p> |
| 6278 | {#header_close#} | 6337 | {#header_close#} |
| 6338 | |||
| 6279 | {#header_open|@truncate#} | 6339 | {#header_open|@truncate#} |
| 6280 | <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre> | 6340 | <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre> |
| 6281 | <p> | 6341 | <p> |
| ... | @@ -6300,6 +6360,7 @@ const b: u8 = @truncate(u8, a); | ... | @@ -6300,6 +6360,7 @@ const b: u8 = @truncate(u8, a); |
| 6300 | </p> | 6360 | </p> |
| 6301 | 6361 | ||
| 6302 | {#header_close#} | 6362 | {#header_close#} |
| 6363 | |||
| 6303 | {#header_open|@typeId#} | 6364 | {#header_open|@typeId#} |
| 6304 | <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre> | 6365 | <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre> |
| 6305 | <p> | 6366 | <p> |
| ... | @@ -6334,6 +6395,7 @@ pub const TypeId = enum { | ... | @@ -6334,6 +6395,7 @@ pub const TypeId = enum { |
| 6334 | }; | 6395 | }; |
| 6335 | {#code_end#} | 6396 | {#code_end#} |
| 6336 | {#header_close#} | 6397 | {#header_close#} |
| 6398 | |||
| 6337 | {#header_open|@typeInfo#} | 6399 | {#header_open|@typeInfo#} |
| 6338 | <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre> | 6400 | <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre> |
| 6339 | <p> | 6401 | <p> |
| ... | @@ -6516,6 +6578,7 @@ pub const TypeInfo = union(TypeId) { | ... | @@ -6516,6 +6578,7 @@ pub const TypeInfo = union(TypeId) { |
| 6516 | }; | 6578 | }; |
| 6517 | {#code_end#} | 6579 | {#code_end#} |
| 6518 | {#header_close#} | 6580 | {#header_close#} |
| 6581 | |||
| 6519 | {#header_open|@typeName#} | 6582 | {#header_open|@typeName#} |
| 6520 | <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre> | 6583 | <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre> |
| 6521 | <p> | 6584 | <p> |
| ... | @@ -6523,6 +6586,7 @@ pub const TypeInfo = union(TypeId) { | ... | @@ -6523,6 +6586,7 @@ pub const TypeInfo = union(TypeId) { |
| 6523 | </p> | 6586 | </p> |
| 6524 | 6587 | ||
| 6525 | {#header_close#} | 6588 | {#header_close#} |
| 6589 | |||
| 6526 | {#header_open|@typeOf#} | 6590 | {#header_open|@typeOf#} |
| 6527 | <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre> | 6591 | <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre> |
| 6528 | <p> | 6592 | <p> |
| ... | @@ -6532,6 +6596,7 @@ pub const TypeInfo = union(TypeId) { | ... | @@ -6532,6 +6596,7 @@ pub const TypeInfo = union(TypeId) { |
| 6532 | 6596 | ||
| 6533 | {#header_close#} | 6597 | {#header_close#} |
| 6534 | {#header_close#} | 6598 | {#header_close#} |
| 6599 | |||
| 6535 | {#header_open|Build Mode#} | 6600 | {#header_open|Build Mode#} |
| 6536 | <p> | 6601 | <p> |
| 6537 | Zig has four build modes: | 6602 | Zig has four build modes: |
| ... | @@ -6659,7 +6724,7 @@ fn foo(x: []const u8) u8 { | ... | @@ -6659,7 +6724,7 @@ fn foo(x: []const u8) u8 { |
| 6659 | {#header_close#} | 6724 | {#header_close#} |
| 6660 | {#header_open|Cast Negative Number to Unsigned Integer#} | 6725 | {#header_open|Cast Negative Number to Unsigned Integer#} |
| 6661 | <p>At compile-time:</p> | 6726 | <p>At compile-time:</p> |
| 6662 | {#code_begin|test_err|attempt to cast negative value to unsigned integer#} | 6727 | {#code_begin|test_err|cannot cast negative value -1 to unsigned integer type 'u32'#} |
| 6663 | comptime { | 6728 | comptime { |
| 6664 | const value: i32 = -1; | 6729 | const value: i32 = -1; |
| 6665 | const unsigned = @intCast(u32, value); | 6730 | const unsigned = @intCast(u32, value); |
| ... | @@ -6681,7 +6746,7 @@ pub fn main() void { | ... | @@ -6681,7 +6746,7 @@ pub fn main() void { |
| 6681 | {#header_close#} | 6746 | {#header_close#} |
| 6682 | {#header_open|Cast Truncates Data#} | 6747 | {#header_open|Cast Truncates Data#} |
| 6683 | <p>At compile-time:</p> | 6748 | <p>At compile-time:</p> |
| 6684 | {#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#} | 6749 | {#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#} |
| 6685 | comptime { | 6750 | comptime { |
| 6686 | const spartan_count: u16 = 300; | 6751 | const spartan_count: u16 = 300; |
| 6687 | const byte = @intCast(u8, spartan_count); | 6752 | const byte = @intCast(u8, spartan_count); |
| ... | @@ -7830,11 +7895,11 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr | ... | @@ -7830,11 +7895,11 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr |
| 7830 | ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)? | 7895 | ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)? |
| 7831 | 7896 | ||
| 7832 | SuffixExpr | 7897 | SuffixExpr |
| 7833 | &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets | 7898 | &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments |
| 7834 | / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)* | 7899 | / PrimaryTypeExpr (SuffixOp / FnCallArguments)* |
| 7835 | 7900 | ||
| 7836 | PrimaryTypeExpr | 7901 | PrimaryTypeExpr |
| 7837 | &lt;- BUILTININDENTIFIER FnCallArgumnets | 7902 | &lt;- BUILTINIDENTIFIER FnCallArguments |
| 7838 | / CHAR_LITERAL | 7903 | / CHAR_LITERAL |
| 7839 | / ContainerDecl | 7904 | / ContainerDecl |
| 7840 | / ErrorSetDecl | 7905 | / ErrorSetDecl |
| ... | @@ -7884,11 +7949,11 @@ AsmOutput &lt;- COLON AsmOutputList AsmInput? | ... | @@ -7884,11 +7949,11 @@ AsmOutput &lt;- COLON AsmOutputList AsmInput? |
| 7884 | 7949 | ||
| 7885 | AsmOutputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN | 7950 | AsmOutputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN |
| 7886 | 7951 | ||
| 7887 | AsmInput &lt;- COLON AsmInputList AsmCloppers? | 7952 | AsmInput &lt;- COLON AsmInputList AsmClobbers? |
| 7888 | 7953 | ||
| 7889 | AsmInputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN | 7954 | AsmInputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN |
| 7890 | 7955 | ||
| 7891 | AsmCloppers &lt;- COLON StringList | 7956 | AsmClobbers &lt;- COLON StringList |
| 7892 | 7957 | ||
| 7893 | # *** Helper grammar *** | 7958 | # *** Helper grammar *** |
| 7894 | BreakLabel &lt;- COLON IDENTIFIER | 7959 | BreakLabel &lt;- COLON IDENTIFIER |
| ... | @@ -8013,7 +8078,7 @@ SuffixOp | ... | @@ -8013,7 +8078,7 @@ SuffixOp |
| 8013 | 8078 | ||
| 8014 | AsyncPrefix &lt;- KEYWORD_async (LARROW PrefixExpr RARROW)? | 8079 | AsyncPrefix &lt;- KEYWORD_async (LARROW PrefixExpr RARROW)? |
| 8015 | 8080 | ||
| 8016 | FnCallArgumnets &lt;- LPAREN ExprList RPAREN | 8081 | FnCallArguments &lt;- LPAREN ExprList RPAREN |
| 8017 | 8082 | ||
| 8018 | # Ptr specific | 8083 | # Ptr specific |
| 8019 | ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET | 8084 | ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET |
| ... | @@ -8090,7 +8155,7 @@ STRINGLITERAL | ... | @@ -8090,7 +8155,7 @@ STRINGLITERAL |
| 8090 | IDENTIFIER | 8155 | IDENTIFIER |
| 8091 | &lt;- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip | 8156 | &lt;- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip |
| 8092 | / "@\"" string_char* "\"" skip | 8157 | / "@\"" string_char* "\"" skip |
| 8093 | BUILTININDENTIFIER &lt;- "@"[A-Za-z_][A-Za-z0-9_]* skip | 8158 | BUILTINIDENTIFIER &lt;- "@"[A-Za-z_][A-Za-z0-9_]* skip |
| 8094 | 8159 | ||
| 8095 | 8160 | ||
| 8096 | AMPERSAND &lt;- '&' ![=] skip | 8161 | AMPERSAND &lt;- '&' ![=] skip |
| ... | @@ -8109,9 +8174,9 @@ DOT2 &lt;- '..' ![.] skip | ... | @@ -8109,9 +8174,9 @@ DOT2 &lt;- '..' ![.] skip |
| 8109 | DOT3 &lt;- '...' skip | 8174 | DOT3 &lt;- '...' skip |
| 8110 | DOTASTERISK &lt;- '.*' skip | 8175 | DOTASTERISK &lt;- '.*' skip |
| 8111 | DOTQUESTIONMARK &lt;- '.?' skip | 8176 | DOTQUESTIONMARK &lt;- '.?' skip |
| 8112 | EQUAL &lt;- '=' ![>=] skip | 8177 | EQUAL &lt;- '=' ![&gt;=] skip |
| 8113 | EQUALEQUAL &lt;- '==' skip | 8178 | EQUALEQUAL &lt;- '==' skip |
| 8114 | EQUALRARROW &lt;- '=>' skip | 8179 | EQUALRARROW &lt;- '=&gt;' skip |
| 8115 | EXCLAMATIONMARK &lt;- '!' ![=] skip | 8180 | EXCLAMATIONMARK &lt;- '!' ![=] skip |
| 8116 | EXCLAMATIONMARKEQUAL &lt;- '!=' skip | 8181 | EXCLAMATIONMARKEQUAL &lt;- '!=' skip |
| 8117 | LARROW &lt;- '&lt;' ![&lt;=] skip | 8182 | LARROW &lt;- '&lt;' ![&lt;=] skip |
| ... | @@ -8121,11 +8186,11 @@ LARROWEQUAL &lt;- '&lt;=' skip | ... | @@ -8121,11 +8186,11 @@ LARROWEQUAL &lt;- '&lt;=' skip |
| 8121 | LBRACE &lt;- '{' skip | 8186 | LBRACE &lt;- '{' skip |
| 8122 | LBRACKET &lt;- '[' skip | 8187 | LBRACKET &lt;- '[' skip |
| 8123 | LPAREN &lt;- '(' skip | 8188 | LPAREN &lt;- '(' skip |
| 8124 | MINUS &lt;- '-' ![%=>] skip | 8189 | MINUS &lt;- '-' ![%=&gt;] skip |
| 8125 | MINUSEQUAL &lt;- '-=' skip | 8190 | MINUSEQUAL &lt;- '-=' skip |
| 8126 | MINUSPERCENT &lt;- '-%' ![=] skip | 8191 | MINUSPERCENT &lt;- '-%' ![=] skip |
| 8127 | MINUSPERCENTEQUAL &lt;- '-%=' skip | 8192 | MINUSPERCENTEQUAL &lt;- '-%=' skip |
| 8128 | MINUSRARROW &lt;- '->' skip | 8193 | MINUSRARROW &lt;- '-&gt;' skip |
| 8129 | PERCENT &lt;- '%' ![=] skip | 8194 | PERCENT &lt;- '%' ![=] skip |
| 8130 | PERCENTEQUAL &lt;- '%=' skip | 8195 | PERCENTEQUAL &lt;- '%=' skip |
| 8131 | PIPE &lt;- '|' ![|=] skip | 8196 | PIPE &lt;- '|' ![|=] skip |
| ... | @@ -8137,10 +8202,10 @@ PLUSEQUAL &lt;- '+=' skip | ... | @@ -8137,10 +8202,10 @@ PLUSEQUAL &lt;- '+=' skip |
| 8137 | PLUSPERCENT &lt;- '+%' ![=] skip | 8202 | PLUSPERCENT &lt;- '+%' ![=] skip |
| 8138 | PLUSPERCENTEQUAL &lt;- '+%=' skip | 8203 | PLUSPERCENTEQUAL &lt;- '+%=' skip |
| 8139 | QUESTIONMARK &lt;- '?' skip | 8204 | QUESTIONMARK &lt;- '?' skip |
| 8140 | RARROW &lt;- '>' ![>=] skip | 8205 | RARROW &lt;- '&gt;' ![&gt;=] skip |
| 8141 | RARROW2 &lt;- '>>' ![=] skip | 8206 | RARROW2 &lt;- '&gt;&gt;' ![=] skip |
| 8142 | RARROW2EQUAL &lt;- '>>=' skip | 8207 | RARROW2EQUAL &lt;- '&gt;&gt;=' skip |
| 8143 | RARROWEQUAL &lt;- '>=' skip | 8208 | RARROWEQUAL &lt;- '&gt;=' skip |
| 8144 | RBRACE &lt;- '}' skip | 8209 | RBRACE &lt;- '}' skip |
| 8145 | RBRACKET &lt;- ']' skip | 8210 | RBRACKET &lt;- ']' skip |
| 8146 | RPAREN &lt;- ')' skip | 8211 | RPAREN &lt;- ')' skip |
example/guess_number/main.zig+5-5| ... | @@ -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; |
| ... | @@ -24,15 +24,15 @@ pub fn main() !void { | ... | @@ -24,15 +24,15 @@ pub fn main() !void { |
| 24 | try stdout.print("\nGuess a number between 1 and 100: "); | 24 | try stdout.print("\nGuess a number between 1 and 100: "); |
| 25 | var line_buf: [20]u8 = undefined; | 25 | var line_buf: [20]u8 = undefined; |
| 26 | 26 | ||
| 27 | const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) { | 27 | const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) { |
| 28 | error.InputTooLong => { | 28 | error.OutOfMemory => { |
| 29 | try stdout.print("Input too long.\n"); | 29 | try stdout.print("Input too long.\n"); |
| 30 | continue; | 30 | continue; |
| 31 | }, | 31 | }, |
| 32 | error.EndOfFile, error.StdInUnavailable => return err, | 32 | else => return err, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | const guess = fmt.parseUnsigned(u8, line_buf[0..line_len], 10) catch { | 35 | const guess = fmt.parseUnsigned(u8, line, 10) catch { |
| 36 | try stdout.print("Invalid number.\n"); | 36 | try stdout.print("Invalid number.\n"); |
| 37 | continue; | 37 | continue; |
| 38 | }; | 38 | }; |
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/compilation.zig+2-1| ... | @@ -55,7 +55,7 @@ pub const ZigCompiler = struct { | ... | @@ -55,7 +55,7 @@ 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, |
| ... | @@ -300,6 +300,7 @@ pub const Compilation = struct { | ... | @@ -300,6 +300,7 @@ pub const Compilation = struct { |
| 300 | UserResourceLimitReached, | 300 | UserResourceLimitReached, |
| 301 | InvalidUtf8, | 301 | InvalidUtf8, |
| 302 | BadPathName, | 302 | BadPathName, |
| 303 | DeviceBusy, | ||
| 303 | }; | 304 | }; |
| 304 | 305 | ||
| 305 | pub const Event = union(enum) { | 306 | pub const Event = union(enum) { |
src-self-hosted/libc_installation.zig+1-1| ... | @@ -172,7 +172,7 @@ pub const LibCInstallation = struct { | ... | @@ -172,7 +172,7 @@ pub const LibCInstallation = struct { |
| 172 | try group.call(findNativeStaticLibDir, self, loop); | 172 | try group.call(findNativeStaticLibDir, self, loop); |
| 173 | try group.call(findNativeDynamicLinker, self, loop); | 173 | try group.call(findNativeDynamicLinker, self, loop); |
| 174 | }, | 174 | }, |
| 175 | builtin.Os.macosx => { | 175 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 176 | self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); | 176 | self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); |
| 177 | }, | 177 | }, |
| 178 | else => @compileError("unimplemented: find libc for this OS"), | 178 | else => @compileError("unimplemented: find libc for this OS"), |
src-self-hosted/target.zig+155-151| ... | @@ -311,160 +311,164 @@ pub const Target = union(enum) { | ... | @@ -311,160 +311,164 @@ pub const Target = union(enum) { |
| 311 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { | 311 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { |
| 312 | const env = self.getEnviron(); | 312 | const env = self.getEnviron(); |
| 313 | const arch = self.getArch(); | 313 | const arch = self.getArch(); |
| 314 | switch (env) { | 314 | const os = self.getOs(); |
| 315 | builtin.Environ.android => { | 315 | switch (os) { |
| 316 | if (self.is64bit()) { | 316 | builtin.Os.freebsd => { |
| 317 | return "/system/bin/linker64"; | 317 | return "/libexec/ld-elf.so.1"; |
| 318 | } else { | ||
| 319 | return "/system/bin/linker"; | ||
| 320 | } | ||
| 321 | }, | 318 | }, |
| 322 | builtin.Environ.gnux32 => { | 319 | builtin.Os.linux => { |
| 323 | if (arch == builtin.Arch.x86_64) { | 320 | switch (env) { |
| 324 | return "/libx32/ld-linux-x32.so.2"; | 321 | builtin.Environ.android => { |
| 322 | if (self.is64bit()) { | ||
| 323 | return "/system/bin/linker64"; | ||
| 324 | } else { | ||
| 325 | return "/system/bin/linker"; | ||
| 326 | } | ||
| 327 | }, | ||
| 328 | builtin.Environ.gnux32 => { | ||
| 329 | if (arch == builtin.Arch.x86_64) { | ||
| 330 | return "/libx32/ld-linux-x32.so.2"; | ||
| 331 | } | ||
| 332 | }, | ||
| 333 | builtin.Environ.musl, | ||
| 334 | builtin.Environ.musleabi, | ||
| 335 | builtin.Environ.musleabihf, | ||
| 336 | => { | ||
| 337 | if (arch == builtin.Arch.x86_64) { | ||
| 338 | return "/lib/ld-musl-x86_64.so.1"; | ||
| 339 | } | ||
| 340 | }, | ||
| 341 | else => {}, | ||
| 325 | } | 342 | } |
| 326 | }, | 343 | switch (arch) { |
| 327 | builtin.Environ.musl, | 344 | builtin.Arch.i386, |
| 328 | builtin.Environ.musleabi, | 345 | builtin.Arch.sparc, |
| 329 | builtin.Environ.musleabihf, | 346 | builtin.Arch.sparcel, |
| 330 | => { | 347 | => return "/lib/ld-linux.so.2", |
| 331 | if (arch == builtin.Arch.x86_64) { | 348 | |
| 332 | return "/lib/ld-musl-x86_64.so.1"; | 349 | builtin.Arch.aarch64v8_5a, |
| 350 | builtin.Arch.aarch64v8_4a, | ||
| 351 | builtin.Arch.aarch64v8_3a, | ||
| 352 | builtin.Arch.aarch64v8_2a, | ||
| 353 | builtin.Arch.aarch64v8_1a, | ||
| 354 | builtin.Arch.aarch64v8, | ||
| 355 | builtin.Arch.aarch64v8r, | ||
| 356 | builtin.Arch.aarch64v8m_baseline, | ||
| 357 | builtin.Arch.aarch64v8m_mainline, | ||
| 358 | => return "/lib/ld-linux-aarch64.so.1", | ||
| 359 | |||
| 360 | builtin.Arch.aarch64_bev8_5a, | ||
| 361 | builtin.Arch.aarch64_bev8_4a, | ||
| 362 | builtin.Arch.aarch64_bev8_3a, | ||
| 363 | builtin.Arch.aarch64_bev8_2a, | ||
| 364 | builtin.Arch.aarch64_bev8_1a, | ||
| 365 | builtin.Arch.aarch64_bev8, | ||
| 366 | builtin.Arch.aarch64_bev8r, | ||
| 367 | builtin.Arch.aarch64_bev8m_baseline, | ||
| 368 | builtin.Arch.aarch64_bev8m_mainline, | ||
| 369 | => return "/lib/ld-linux-aarch64_be.so.1", | ||
| 370 | |||
| 371 | builtin.Arch.armv8_5a, | ||
| 372 | builtin.Arch.armv8_4a, | ||
| 373 | builtin.Arch.armv8_3a, | ||
| 374 | builtin.Arch.armv8_2a, | ||
| 375 | builtin.Arch.armv8_1a, | ||
| 376 | builtin.Arch.armv8, | ||
| 377 | builtin.Arch.armv8r, | ||
| 378 | builtin.Arch.armv8m_baseline, | ||
| 379 | builtin.Arch.armv8m_mainline, | ||
| 380 | builtin.Arch.armv7, | ||
| 381 | builtin.Arch.armv7em, | ||
| 382 | builtin.Arch.armv7m, | ||
| 383 | builtin.Arch.armv7s, | ||
| 384 | builtin.Arch.armv7k, | ||
| 385 | builtin.Arch.armv7ve, | ||
| 386 | builtin.Arch.armv6, | ||
| 387 | builtin.Arch.armv6m, | ||
| 388 | builtin.Arch.armv6k, | ||
| 389 | builtin.Arch.armv6t2, | ||
| 390 | builtin.Arch.armv5, | ||
| 391 | builtin.Arch.armv5te, | ||
| 392 | builtin.Arch.armv4t, | ||
| 393 | builtin.Arch.thumb, | ||
| 394 | builtin.Arch.armebv8_5a, | ||
| 395 | builtin.Arch.armebv8_4a, | ||
| 396 | builtin.Arch.armebv8_3a, | ||
| 397 | builtin.Arch.armebv8_2a, | ||
| 398 | builtin.Arch.armebv8_1a, | ||
| 399 | builtin.Arch.armebv8, | ||
| 400 | builtin.Arch.armebv8r, | ||
| 401 | builtin.Arch.armebv8m_baseline, | ||
| 402 | builtin.Arch.armebv8m_mainline, | ||
| 403 | builtin.Arch.armebv7, | ||
| 404 | builtin.Arch.armebv7em, | ||
| 405 | builtin.Arch.armebv7m, | ||
| 406 | builtin.Arch.armebv7s, | ||
| 407 | builtin.Arch.armebv7k, | ||
| 408 | builtin.Arch.armebv7ve, | ||
| 409 | builtin.Arch.armebv6, | ||
| 410 | builtin.Arch.armebv6m, | ||
| 411 | builtin.Arch.armebv6k, | ||
| 412 | builtin.Arch.armebv6t2, | ||
| 413 | builtin.Arch.armebv5, | ||
| 414 | builtin.Arch.armebv5te, | ||
| 415 | builtin.Arch.armebv4t, | ||
| 416 | builtin.Arch.thumbeb, | ||
| 417 | => return switch (self.getFloatAbi()) { | ||
| 418 | FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", | ||
| 419 | else => return "/lib/ld-linux.so.3", | ||
| 420 | }, | ||
| 421 | |||
| 422 | builtin.Arch.mipsr6, | ||
| 423 | builtin.Arch.mipselr6, | ||
| 424 | builtin.Arch.mips64r6, | ||
| 425 | builtin.Arch.mips64elr6, | ||
| 426 | => return null, | ||
| 427 | |||
| 428 | builtin.Arch.powerpc => return "/lib/ld.so.1", | ||
| 429 | builtin.Arch.powerpc64 => return "/lib64/ld64.so.2", | ||
| 430 | builtin.Arch.powerpc64le => return "/lib64/ld64.so.2", | ||
| 431 | builtin.Arch.s390x => return "/lib64/ld64.so.1", | ||
| 432 | builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2", | ||
| 433 | builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2", | ||
| 434 | |||
| 435 | builtin.Arch.arc, | ||
| 436 | builtin.Arch.avr, | ||
| 437 | builtin.Arch.bpfel, | ||
| 438 | builtin.Arch.bpfeb, | ||
| 439 | builtin.Arch.hexagon, | ||
| 440 | builtin.Arch.msp430, | ||
| 441 | builtin.Arch.nios2, | ||
| 442 | builtin.Arch.r600, | ||
| 443 | builtin.Arch.amdgcn, | ||
| 444 | builtin.Arch.riscv32, | ||
| 445 | builtin.Arch.riscv64, | ||
| 446 | builtin.Arch.tce, | ||
| 447 | builtin.Arch.tcele, | ||
| 448 | builtin.Arch.xcore, | ||
| 449 | builtin.Arch.nvptx, | ||
| 450 | builtin.Arch.nvptx64, | ||
| 451 | builtin.Arch.le32, | ||
| 452 | builtin.Arch.le64, | ||
| 453 | builtin.Arch.amdil, | ||
| 454 | builtin.Arch.amdil64, | ||
| 455 | builtin.Arch.hsail, | ||
| 456 | builtin.Arch.hsail64, | ||
| 457 | builtin.Arch.spir, | ||
| 458 | builtin.Arch.spir64, | ||
| 459 | builtin.Arch.kalimbav3, | ||
| 460 | builtin.Arch.kalimbav4, | ||
| 461 | builtin.Arch.kalimbav5, | ||
| 462 | builtin.Arch.shave, | ||
| 463 | builtin.Arch.lanai, | ||
| 464 | builtin.Arch.wasm32, | ||
| 465 | builtin.Arch.wasm64, | ||
| 466 | builtin.Arch.renderscript32, | ||
| 467 | builtin.Arch.renderscript64, | ||
| 468 | => return null, | ||
| 333 | } | 469 | } |
| 334 | }, | 470 | }, |
| 335 | else => {}, | 471 | else => return null, |
| 336 | } | ||
| 337 | switch (arch) { | ||
| 338 | builtin.Arch.i386, | ||
| 339 | builtin.Arch.sparc, | ||
| 340 | builtin.Arch.sparcel, | ||
| 341 | => return "/lib/ld-linux.so.2", | ||
| 342 | |||
| 343 | builtin.Arch.aarch64v8_5a, | ||
| 344 | builtin.Arch.aarch64v8_4a, | ||
| 345 | builtin.Arch.aarch64v8_3a, | ||
| 346 | builtin.Arch.aarch64v8_2a, | ||
| 347 | builtin.Arch.aarch64v8_1a, | ||
| 348 | builtin.Arch.aarch64v8, | ||
| 349 | builtin.Arch.aarch64v8r, | ||
| 350 | builtin.Arch.aarch64v8m_baseline, | ||
| 351 | builtin.Arch.aarch64v8m_mainline, | ||
| 352 | => return "/lib/ld-linux-aarch64.so.1", | ||
| 353 | |||
| 354 | builtin.Arch.aarch64_bev8_5a, | ||
| 355 | builtin.Arch.aarch64_bev8_4a, | ||
| 356 | builtin.Arch.aarch64_bev8_3a, | ||
| 357 | builtin.Arch.aarch64_bev8_2a, | ||
| 358 | builtin.Arch.aarch64_bev8_1a, | ||
| 359 | builtin.Arch.aarch64_bev8, | ||
| 360 | builtin.Arch.aarch64_bev8r, | ||
| 361 | builtin.Arch.aarch64_bev8m_baseline, | ||
| 362 | builtin.Arch.aarch64_bev8m_mainline, | ||
| 363 | => return "/lib/ld-linux-aarch64_be.so.1", | ||
| 364 | |||
| 365 | builtin.Arch.armv8_5a, | ||
| 366 | builtin.Arch.armv8_4a, | ||
| 367 | builtin.Arch.armv8_3a, | ||
| 368 | builtin.Arch.armv8_2a, | ||
| 369 | builtin.Arch.armv8_1a, | ||
| 370 | builtin.Arch.armv8, | ||
| 371 | builtin.Arch.armv8r, | ||
| 372 | builtin.Arch.armv8m_baseline, | ||
| 373 | builtin.Arch.armv8m_mainline, | ||
| 374 | builtin.Arch.armv7, | ||
| 375 | builtin.Arch.armv7em, | ||
| 376 | builtin.Arch.armv7m, | ||
| 377 | builtin.Arch.armv7s, | ||
| 378 | builtin.Arch.armv7k, | ||
| 379 | builtin.Arch.armv7ve, | ||
| 380 | builtin.Arch.armv6, | ||
| 381 | builtin.Arch.armv6m, | ||
| 382 | builtin.Arch.armv6k, | ||
| 383 | builtin.Arch.armv6t2, | ||
| 384 | builtin.Arch.armv5, | ||
| 385 | builtin.Arch.armv5te, | ||
| 386 | builtin.Arch.armv4t, | ||
| 387 | builtin.Arch.thumb, | ||
| 388 | => return switch (self.getFloatAbi()) { | ||
| 389 | FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", | ||
| 390 | else => return "/lib/ld-linux.so.3", | ||
| 391 | }, | ||
| 392 | |||
| 393 | builtin.Arch.armebv8_5a, | ||
| 394 | builtin.Arch.armebv8_4a, | ||
| 395 | builtin.Arch.armebv8_3a, | ||
| 396 | builtin.Arch.armebv8_2a, | ||
| 397 | builtin.Arch.armebv8_1a, | ||
| 398 | builtin.Arch.armebv8, | ||
| 399 | builtin.Arch.armebv8r, | ||
| 400 | builtin.Arch.armebv8m_baseline, | ||
| 401 | builtin.Arch.armebv8m_mainline, | ||
| 402 | builtin.Arch.armebv7, | ||
| 403 | builtin.Arch.armebv7em, | ||
| 404 | builtin.Arch.armebv7m, | ||
| 405 | builtin.Arch.armebv7s, | ||
| 406 | builtin.Arch.armebv7k, | ||
| 407 | builtin.Arch.armebv7ve, | ||
| 408 | builtin.Arch.armebv6, | ||
| 409 | builtin.Arch.armebv6m, | ||
| 410 | builtin.Arch.armebv6k, | ||
| 411 | builtin.Arch.armebv6t2, | ||
| 412 | builtin.Arch.armebv5, | ||
| 413 | builtin.Arch.armebv5te, | ||
| 414 | builtin.Arch.armebv4t, | ||
| 415 | builtin.Arch.thumbeb, | ||
| 416 | => return switch (self.getFloatAbi()) { | ||
| 417 | FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", | ||
| 418 | else => return "/lib/ld-linux.so.3", | ||
| 419 | }, | ||
| 420 | |||
| 421 | builtin.Arch.mipsr6, | ||
| 422 | builtin.Arch.mipselr6, | ||
| 423 | builtin.Arch.mips64r6, | ||
| 424 | builtin.Arch.mips64elr6, | ||
| 425 | => return null, | ||
| 426 | |||
| 427 | builtin.Arch.powerpc => return "/lib/ld.so.1", | ||
| 428 | builtin.Arch.powerpc64 => return "/lib64/ld64.so.2", | ||
| 429 | builtin.Arch.powerpc64le => return "/lib64/ld64.so.2", | ||
| 430 | builtin.Arch.s390x => return "/lib64/ld64.so.1", | ||
| 431 | builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2", | ||
| 432 | builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2", | ||
| 433 | |||
| 434 | builtin.Arch.arc, | ||
| 435 | builtin.Arch.avr, | ||
| 436 | builtin.Arch.bpfel, | ||
| 437 | builtin.Arch.bpfeb, | ||
| 438 | builtin.Arch.hexagon, | ||
| 439 | builtin.Arch.msp430, | ||
| 440 | builtin.Arch.nios2, | ||
| 441 | builtin.Arch.r600, | ||
| 442 | builtin.Arch.amdgcn, | ||
| 443 | builtin.Arch.riscv32, | ||
| 444 | builtin.Arch.riscv64, | ||
| 445 | builtin.Arch.tce, | ||
| 446 | builtin.Arch.tcele, | ||
| 447 | builtin.Arch.xcore, | ||
| 448 | builtin.Arch.nvptx, | ||
| 449 | builtin.Arch.nvptx64, | ||
| 450 | builtin.Arch.le32, | ||
| 451 | builtin.Arch.le64, | ||
| 452 | builtin.Arch.amdil, | ||
| 453 | builtin.Arch.amdil64, | ||
| 454 | builtin.Arch.hsail, | ||
| 455 | builtin.Arch.hsail64, | ||
| 456 | builtin.Arch.spir, | ||
| 457 | builtin.Arch.spir64, | ||
| 458 | builtin.Arch.kalimbav3, | ||
| 459 | builtin.Arch.kalimbav4, | ||
| 460 | builtin.Arch.kalimbav5, | ||
| 461 | builtin.Arch.shave, | ||
| 462 | builtin.Arch.lanai, | ||
| 463 | builtin.Arch.wasm32, | ||
| 464 | builtin.Arch.wasm64, | ||
| 465 | builtin.Arch.renderscript32, | ||
| 466 | builtin.Arch.renderscript64, | ||
| 467 | => return null, | ||
| 468 | } | 472 | } |
| 469 | } | 473 | } |
| 470 | 474 | ||
| ... | @@ -513,6 +517,7 @@ pub const Target = union(enum) { | ... | @@ -513,6 +517,7 @@ pub const Target = union(enum) { |
| 513 | 517 | ||
| 514 | builtin.Os.linux, | 518 | builtin.Os.linux, |
| 515 | builtin.Os.macosx, | 519 | builtin.Os.macosx, |
| 520 | builtin.Os.freebsd, | ||
| 516 | builtin.Os.openbsd, | 521 | builtin.Os.openbsd, |
| 517 | builtin.Os.zen, | 522 | builtin.Os.zen, |
| 518 | => switch (id) { | 523 | => switch (id) { |
| ... | @@ -547,7 +552,6 @@ pub const Target = union(enum) { | ... | @@ -547,7 +552,6 @@ pub const Target = union(enum) { |
| 547 | builtin.Os.ananas, | 552 | builtin.Os.ananas, |
| 548 | builtin.Os.cloudabi, | 553 | builtin.Os.cloudabi, |
| 549 | builtin.Os.dragonfly, | 554 | builtin.Os.dragonfly, |
| 550 | builtin.Os.freebsd, | ||
| 551 | builtin.Os.fuchsia, | 555 | builtin.Os.fuchsia, |
| 552 | builtin.Os.ios, | 556 | builtin.Os.ios, |
| 553 | builtin.Os.kfreebsd, | 557 | builtin.Os.kfreebsd, |
src/all_types.hpp+13-1| ... | @@ -605,7 +605,6 @@ enum CastOp { | ... | @@ -605,7 +605,6 @@ enum CastOp { |
| 605 | CastOpFloatToInt, | 605 | CastOpFloatToInt, |
| 606 | CastOpBoolToInt, | 606 | CastOpBoolToInt, |
| 607 | CastOpResizeSlice, | 607 | CastOpResizeSlice, |
| 608 | CastOpBytesToSlice, | ||
| 609 | CastOpNumLitToConcrete, | 608 | CastOpNumLitToConcrete, |
| 610 | CastOpErrSet, | 609 | CastOpErrSet, |
| 611 | CastOpBitCast, | 610 | CastOpBitCast, |
| ... | @@ -1415,6 +1414,7 @@ enum BuiltinFnId { | ... | @@ -1415,6 +1414,7 @@ enum BuiltinFnId { |
| 1415 | BuiltinFnIdErrorReturnTrace, | 1414 | BuiltinFnIdErrorReturnTrace, |
| 1416 | BuiltinFnIdAtomicRmw, | 1415 | BuiltinFnIdAtomicRmw, |
| 1417 | BuiltinFnIdAtomicLoad, | 1416 | BuiltinFnIdAtomicLoad, |
| 1417 | BuiltinFnIdBswap, | ||
| 1418 | }; | 1418 | }; |
| 1419 | 1419 | ||
| 1420 | struct BuiltinFnEntry { | 1420 | struct BuiltinFnEntry { |
| ... | @@ -1487,6 +1487,7 @@ enum ZigLLVMFnId { | ... | @@ -1487,6 +1487,7 @@ enum ZigLLVMFnId { |
| 1487 | ZigLLVMFnIdFloor, | 1487 | ZigLLVMFnIdFloor, |
| 1488 | ZigLLVMFnIdCeil, | 1488 | ZigLLVMFnIdCeil, |
| 1489 | ZigLLVMFnIdSqrt, | 1489 | ZigLLVMFnIdSqrt, |
| 1490 | ZigLLVMFnIdBswap, | ||
| 1490 | }; | 1491 | }; |
| 1491 | 1492 | ||
| 1492 | enum AddSubMul { | 1493 | enum AddSubMul { |
| ... | @@ -1516,6 +1517,9 @@ struct ZigLLVMFnKey { | ... | @@ -1516,6 +1517,9 @@ struct ZigLLVMFnKey { |
| 1516 | uint32_t bit_count; | 1517 | uint32_t bit_count; |
| 1517 | bool is_signed; | 1518 | bool is_signed; |
| 1518 | } overflow_arithmetic; | 1519 | } overflow_arithmetic; |
| 1520 | struct { | ||
| 1521 | uint32_t bit_count; | ||
| 1522 | } bswap; | ||
| 1519 | } data; | 1523 | } data; |
| 1520 | }; | 1524 | }; |
| 1521 | 1525 | ||
| ... | @@ -2158,6 +2162,7 @@ enum IrInstructionId { | ... | @@ -2158,6 +2162,7 @@ enum IrInstructionId { |
| 2158 | IrInstructionIdMergeErrRetTraces, | 2162 | IrInstructionIdMergeErrRetTraces, |
| 2159 | IrInstructionIdMarkErrRetTracePtr, | 2163 | IrInstructionIdMarkErrRetTracePtr, |
| 2160 | IrInstructionIdSqrt, | 2164 | IrInstructionIdSqrt, |
| 2165 | IrInstructionIdBswap, | ||
| 2161 | IrInstructionIdErrSetCast, | 2166 | IrInstructionIdErrSetCast, |
| 2162 | IrInstructionIdToBytes, | 2167 | IrInstructionIdToBytes, |
| 2163 | IrInstructionIdFromBytes, | 2168 | IrInstructionIdFromBytes, |
| ... | @@ -3251,6 +3256,13 @@ struct IrInstructionCheckRuntimeScope { | ... | @@ -3251,6 +3256,13 @@ struct IrInstructionCheckRuntimeScope { |
| 3251 | IrInstruction *is_comptime; | 3256 | IrInstruction *is_comptime; |
| 3252 | }; | 3257 | }; |
| 3253 | 3258 | ||
| 3259 | struct IrInstructionBswap { | ||
| 3260 | IrInstruction base; | ||
| 3261 | |||
| 3262 | IrInstruction *type; | ||
| 3263 | IrInstruction *op; | ||
| 3264 | }; | ||
| 3265 | |||
| 3254 | static const size_t slice_ptr_index = 0; | 3266 | static const size_t slice_ptr_index = 0; |
| 3255 | static const size_t slice_len_index = 1; | 3267 | static const size_t slice_len_index = 1; |
| 3256 | 3268 |
src/analyze.cpp+97-61| ... | @@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { | ... | @@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 403 | 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) | 404 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, |
| 405 | uint32_t bit_offset_in_host, uint32_t host_int_bytes) | ||
| 405 | { | 406 | { |
| 406 | assert(!type_is_invalid(child_type)); | 407 | assert(!type_is_invalid(child_type)); |
| 407 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); | 408 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); |
| ... | @@ -1059,7 +1060,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -1059,7 +1060,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 1059 | } | 1060 | } |
| 1060 | zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481", | 1061 | 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 | buf_ptr(&fn_type_id->return_type->name)); |
| 1062 | } else if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb) { | 1063 | } else if (target_is_arm(&g->zig_target)) { |
| 1063 | return type_size(g, fn_type_id->return_type) > 16; | 1064 | return type_size(g, fn_type_id->return_type) > 16; |
| 1064 | } | 1065 | } |
| 1065 | zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481"); | 1066 | zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481"); |
| ... | @@ -1619,13 +1620,16 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -1619,13 +1620,16 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1619 | case ZigTypeIdUnion: | 1620 | case ZigTypeIdUnion: |
| 1620 | case ZigTypeIdFn: | 1621 | case ZigTypeIdFn: |
| 1621 | case ZigTypeIdPromise: | 1622 | case ZigTypeIdPromise: |
| 1622 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | 1623 | switch (type_requires_comptime(g, type_entry)) { |
| 1623 | return g->builtin_types.entry_invalid; | 1624 | case ReqCompTimeNo: |
| 1624 | if (type_requires_comptime(type_entry)) { | 1625 | break; |
| 1625 | add_node_error(g, param_node->data.param_decl.type, | 1626 | case ReqCompTimeYes: |
| 1626 | buf_sprintf("parameter of type '%s' must be declared comptime", | 1627 | add_node_error(g, param_node->data.param_decl.type, |
| 1627 | buf_ptr(&type_entry->name))); | 1628 | buf_sprintf("parameter of type '%s' must be declared comptime", |
| 1628 | return g->builtin_types.entry_invalid; | 1629 | buf_ptr(&type_entry->name))); |
| 1630 | return g->builtin_types.entry_invalid; | ||
| 1631 | case ReqCompTimeInvalid: | ||
| 1632 | return g->builtin_types.entry_invalid; | ||
| 1629 | } | 1633 | } |
| 1630 | break; | 1634 | break; |
| 1631 | } | 1635 | } |
| ... | @@ -1711,10 +1715,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -1711,10 +1715,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1711 | case ZigTypeIdUnion: | 1715 | case ZigTypeIdUnion: |
| 1712 | case ZigTypeIdFn: | 1716 | case ZigTypeIdFn: |
| 1713 | case ZigTypeIdPromise: | 1717 | case ZigTypeIdPromise: |
| 1714 | if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown))) | 1718 | switch (type_requires_comptime(g, fn_type_id.return_type)) { |
| 1715 | return g->builtin_types.entry_invalid; | 1719 | case ReqCompTimeInvalid: |
| 1716 | if (type_requires_comptime(fn_type_id.return_type)) { | 1720 | return g->builtin_types.entry_invalid; |
| 1717 | return get_generic_fn_type(g, &fn_type_id); | 1721 | case ReqCompTimeYes: |
| 1722 | return get_generic_fn_type(g, &fn_type_id); | ||
| 1723 | case ReqCompTimeNo: | ||
| 1724 | break; | ||
| 1718 | } | 1725 | } |
| 1719 | break; | 1726 | break; |
| 1720 | } | 1727 | } |
| ... | @@ -2560,8 +2567,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2560,8 +2567,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2560 | static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | 2567 | static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2561 | assert(struct_type->id == ZigTypeIdStruct); | 2568 | assert(struct_type->id == ZigTypeIdStruct); |
| 2562 | 2569 | ||
| 2563 | Error err; | ||
| 2564 | |||
| 2565 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) | 2570 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) |
| 2566 | return ErrorSemanticAnalyzeFail; | 2571 | return ErrorSemanticAnalyzeFail; |
| 2567 | if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) | 2572 | if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) |
| ... | @@ -2619,13 +2624,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2619,13 +2624,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2619 | buf_sprintf("enums, not structs, support field assignment")); | 2624 | buf_sprintf("enums, not structs, support field assignment")); |
| 2620 | } | 2625 | } |
| 2621 | 2626 | ||
| 2622 | if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) { | 2627 | switch (type_requires_comptime(g, field_type)) { |
| 2623 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2628 | case ReqCompTimeYes: |
| 2624 | continue; | 2629 | struct_type->data.structure.requires_comptime = true; |
| 2625 | } | 2630 | break; |
| 2626 | 2631 | case ReqCompTimeInvalid: | |
| 2627 | if (type_requires_comptime(field_type)) { | 2632 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2628 | struct_type->data.structure.requires_comptime = true; | 2633 | continue; |
| 2634 | case ReqCompTimeNo: | ||
| 2635 | break; | ||
| 2629 | } | 2636 | } |
| 2630 | 2637 | ||
| 2631 | if (!type_has_bits(field_type)) | 2638 | if (!type_has_bits(field_type)) |
| ... | @@ -2674,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2674,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2674 | assert(decl_node->type == NodeTypeContainerDecl); | 2681 | assert(decl_node->type == NodeTypeContainerDecl); |
| 2675 | assert(struct_type->di_type); | 2682 | assert(struct_type->di_type); |
| 2676 | 2683 | ||
| 2684 | size_t field_count = struct_type->data.structure.src_field_count; | ||
| 2677 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | 2685 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2678 | struct_type->data.structure.abi_alignment = 1; | 2686 | struct_type->data.structure.abi_alignment = 1; |
| 2679 | } | 2687 | for (size_t i = 0; i < field_count; i += 1) { |
| 2680 | 2688 | TypeStructField *field = &struct_type->data.structure.fields[i]; | |
| 2681 | size_t field_count = struct_type->data.structure.src_field_count; | 2689 | if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { |
| 2682 | for (size_t i = 0; i < field_count; i += 1) { | 2690 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2683 | TypeStructField *field = &struct_type->data.structure.fields[i]; | 2691 | break; |
| 2684 | 2692 | } | |
| 2685 | // If this assertion trips, look up the call stack. Probably something is | ||
| 2686 | // calling type_resolve with ResolveStatusAlignmentKnown when it should only | ||
| 2687 | // be resolving ResolveStatusZeroBitsKnown | ||
| 2688 | assert(field->type_entry != nullptr); | ||
| 2689 | |||
| 2690 | if (type_is_invalid(field->type_entry)) { | ||
| 2691 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2692 | break; | ||
| 2693 | } | 2693 | } |
| 2694 | } else for (size_t i = 0; i < field_count; i += 1) { | ||
| 2695 | TypeStructField *field = &struct_type->data.structure.fields[i]; | ||
| 2696 | uint32_t this_field_align; | ||
| 2697 | |||
| 2698 | // TODO If we have no type_entry for the field, we've already failed to | ||
| 2699 | // compile the program correctly. This stage1 compiler needs a deeper | ||
| 2700 | // reworking to make this correct, or we can ignore the problem | ||
| 2701 | // and make sure it is fixed in stage2. This workaround is for when | ||
| 2702 | // there is a false positive of a dependency loop, of alignment depending | ||
| 2703 | // on itself. When this false positive happens we assume a pointer-aligned | ||
| 2704 | // field, which is usually fine but could be incorrectly over-aligned or | ||
| 2705 | // even under-aligned. See https://github.com/ziglang/zig/issues/1512 | ||
| 2706 | if (field->type_entry == nullptr) { | ||
| 2707 | this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); | ||
| 2708 | } else { | ||
| 2709 | if (type_is_invalid(field->type_entry)) { | ||
| 2710 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2711 | break; | ||
| 2712 | } | ||
| 2694 | 2713 | ||
| 2695 | if (!type_has_bits(field->type_entry)) | 2714 | if (!type_has_bits(field->type_entry)) |
| 2696 | continue; | 2715 | continue; |
| 2697 | 2716 | ||
| 2698 | // alignment of structs is the alignment of the most-aligned field | ||
| 2699 | if (struct_type->data.structure.layout != ContainerLayoutPacked) { | ||
| 2700 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { | 2717 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { |
| 2701 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2718 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2702 | break; | 2719 | break; |
| 2703 | } | 2720 | } |
| 2704 | 2721 | ||
| 2705 | uint32_t this_field_align = get_abi_alignment(g, field->type_entry); | 2722 | this_field_align = get_abi_alignment(g, field->type_entry); |
| 2706 | assert(this_field_align != 0); | 2723 | assert(this_field_align != 0); |
| 2707 | if (this_field_align > struct_type->data.structure.abi_alignment) { | 2724 | } |
| 2708 | struct_type->data.structure.abi_alignment = this_field_align; | 2725 | // alignment of structs is the alignment of the most-aligned field |
| 2709 | } | 2726 | if (this_field_align > struct_type->data.structure.abi_alignment) { |
| 2727 | struct_type->data.structure.abi_alignment = this_field_align; | ||
| 2710 | } | 2728 | } |
| 2711 | } | 2729 | } |
| 2712 | 2730 | ||
| ... | @@ -2890,11 +2908,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { | ... | @@ -2890,11 +2908,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 2890 | } | 2908 | } |
| 2891 | union_field->type_entry = field_type; | 2909 | union_field->type_entry = field_type; |
| 2892 | 2910 | ||
| 2893 | if (type_requires_comptime(field_type)) { | 2911 | switch (type_requires_comptime(g, field_type)) { |
| 2894 | union_type->data.unionation.requires_comptime = true; | 2912 | case ReqCompTimeInvalid: |
| 2913 | union_type->data.unionation.is_invalid = true; | ||
| 2914 | continue; | ||
| 2915 | case ReqCompTimeYes: | ||
| 2916 | union_type->data.unionation.requires_comptime = true; | ||
| 2917 | break; | ||
| 2918 | case ReqCompTimeNo: | ||
| 2919 | break; | ||
| 2895 | } | 2920 | } |
| 2896 | 2921 | ||
| 2897 | |||
| 2898 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { | 2922 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { |
| 2899 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, | 2923 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, |
| 2900 | buf_sprintf("non-enum union field assignment")); | 2924 | buf_sprintf("non-enum union field assignment")); |
| ... | @@ -4579,7 +4603,10 @@ void find_libc_include_path(CodeGen *g) { | ... | @@ -4579,7 +4603,10 @@ void find_libc_include_path(CodeGen *g) { |
| 4579 | fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); | 4603 | fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); |
| 4580 | exit(1); | 4604 | exit(1); |
| 4581 | } | 4605 | } |
| 4582 | } else if (g->zig_target.os == OsLinux || g->zig_target.os == OsMacOSX) { | 4606 | } else if (g->zig_target.os == OsLinux || |
| 4607 | g->zig_target.os == OsMacOSX || | ||
| 4608 | g->zig_target.os == OsFreeBSD) | ||
| 4609 | { | ||
| 4583 | g->libc_include_dir = get_posix_libc_include_path(); | 4610 | g->libc_include_dir = get_posix_libc_include_path(); |
| 4584 | } else { | 4611 | } else { |
| 4585 | fprintf(stderr, "Unable to determine libc include path.\n" | 4612 | fprintf(stderr, "Unable to determine libc include path.\n" |
| ... | @@ -4627,6 +4654,8 @@ void find_libc_lib_path(CodeGen *g) { | ... | @@ -4627,6 +4654,8 @@ void find_libc_lib_path(CodeGen *g) { |
| 4627 | 4654 | ||
| 4628 | } else if (g->zig_target.os == OsLinux) { | 4655 | } else if (g->zig_target.os == OsLinux) { |
| 4629 | g->libc_lib_dir = get_linux_libc_lib_path("crt1.o"); | 4656 | g->libc_lib_dir = get_linux_libc_lib_path("crt1.o"); |
| 4657 | } else if (g->zig_target.os == OsFreeBSD) { | ||
| 4658 | g->libc_lib_dir = buf_create_from_str("/usr/lib"); | ||
| 4630 | } else { | 4659 | } else { |
| 4631 | zig_panic("Unable to determine libc lib path."); | 4660 | zig_panic("Unable to determine libc lib path."); |
| 4632 | } | 4661 | } |
| ... | @@ -4639,6 +4668,8 @@ void find_libc_lib_path(CodeGen *g) { | ... | @@ -4639,6 +4668,8 @@ void find_libc_lib_path(CodeGen *g) { |
| 4639 | return; | 4668 | return; |
| 4640 | } else if (g->zig_target.os == OsLinux) { | 4669 | } else if (g->zig_target.os == OsLinux) { |
| 4641 | g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o"); | 4670 | g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o"); |
| 4671 | } else if (g->zig_target.os == OsFreeBSD) { | ||
| 4672 | g->libc_static_lib_dir = buf_create_from_str("/usr/lib"); | ||
| 4642 | } else { | 4673 | } else { |
| 4643 | zig_panic("Unable to determine libc static lib path."); | 4674 | zig_panic("Unable to determine libc static lib path."); |
| 4644 | } | 4675 | } |
| ... | @@ -5089,7 +5120,10 @@ bool type_has_bits(ZigType *type_entry) { | ... | @@ -5089,7 +5120,10 @@ bool type_has_bits(ZigType *type_entry) { |
| 5089 | return !type_entry->zero_bits; | 5120 | return !type_entry->zero_bits; |
| 5090 | } | 5121 | } |
| 5091 | 5122 | ||
| 5092 | bool type_requires_comptime(ZigType *type_entry) { | 5123 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 5124 | Error err; | ||
| 5125 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | ||
| 5126 | return ReqCompTimeInvalid; | ||
| 5093 | switch (type_entry->id) { | 5127 | switch (type_entry->id) { |
| 5094 | case ZigTypeIdInvalid: | 5128 | case ZigTypeIdInvalid: |
| 5095 | case ZigTypeIdOpaque: | 5129 | case ZigTypeIdOpaque: |
| ... | @@ -5102,27 +5136,25 @@ bool type_requires_comptime(ZigType *type_entry) { | ... | @@ -5102,27 +5136,25 @@ bool type_requires_comptime(ZigType *type_entry) { |
| 5102 | case ZigTypeIdNamespace: | 5136 | case ZigTypeIdNamespace: |
| 5103 | case ZigTypeIdBoundFn: | 5137 | case ZigTypeIdBoundFn: |
| 5104 | case ZigTypeIdArgTuple: | 5138 | case ZigTypeIdArgTuple: |
| 5105 | return true; | 5139 | return ReqCompTimeYes; |
| 5106 | case ZigTypeIdArray: | 5140 | case ZigTypeIdArray: |
| 5107 | return type_requires_comptime(type_entry->data.array.child_type); | 5141 | return type_requires_comptime(g, type_entry->data.array.child_type); |
| 5108 | case ZigTypeIdStruct: | 5142 | case ZigTypeIdStruct: |
| 5109 | assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); | 5143 | return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; |
| 5110 | return type_entry->data.structure.requires_comptime; | ||
| 5111 | case ZigTypeIdUnion: | 5144 | case ZigTypeIdUnion: |
| 5112 | assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); | 5145 | return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; |
| 5113 | return type_entry->data.unionation.requires_comptime; | ||
| 5114 | case ZigTypeIdOptional: | 5146 | case ZigTypeIdOptional: |
| 5115 | return type_requires_comptime(type_entry->data.maybe.child_type); | 5147 | return type_requires_comptime(g, type_entry->data.maybe.child_type); |
| 5116 | case ZigTypeIdErrorUnion: | 5148 | case ZigTypeIdErrorUnion: |
| 5117 | return type_requires_comptime(type_entry->data.error_union.payload_type); | 5149 | return type_requires_comptime(g, type_entry->data.error_union.payload_type); |
| 5118 | case ZigTypeIdPointer: | 5150 | case ZigTypeIdPointer: |
| 5119 | if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { | 5151 | if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { |
| 5120 | return false; | 5152 | return ReqCompTimeNo; |
| 5121 | } else { | 5153 | } else { |
| 5122 | return type_requires_comptime(type_entry->data.pointer.child_type); | 5154 | return type_requires_comptime(g, type_entry->data.pointer.child_type); |
| 5123 | } | 5155 | } |
| 5124 | case ZigTypeIdFn: | 5156 | case ZigTypeIdFn: |
| 5125 | return type_entry->data.fn.is_generic; | 5157 | return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo; |
| 5126 | case ZigTypeIdEnum: | 5158 | case ZigTypeIdEnum: |
| 5127 | case ZigTypeIdErrorSet: | 5159 | case ZigTypeIdErrorSet: |
| 5128 | case ZigTypeIdBool: | 5160 | case ZigTypeIdBool: |
| ... | @@ -5131,7 +5163,7 @@ bool type_requires_comptime(ZigType *type_entry) { | ... | @@ -5131,7 +5163,7 @@ bool type_requires_comptime(ZigType *type_entry) { |
| 5131 | case ZigTypeIdVoid: | 5163 | case ZigTypeIdVoid: |
| 5132 | case ZigTypeIdUnreachable: | 5164 | case ZigTypeIdUnreachable: |
| 5133 | case ZigTypeIdPromise: | 5165 | case ZigTypeIdPromise: |
| 5134 | return false; | 5166 | return ReqCompTimeNo; |
| 5135 | } | 5167 | } |
| 5136 | zig_unreachable(); | 5168 | zig_unreachable(); |
| 5137 | } | 5169 | } |
| ... | @@ -6090,6 +6122,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { | ... | @@ -6090,6 +6122,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { |
| 6090 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089; | 6122 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089; |
| 6091 | case ZigLLVMFnIdSqrt: | 6123 | case ZigLLVMFnIdSqrt: |
| 6092 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385; | 6124 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385; |
| 6125 | case ZigLLVMFnIdBswap: | ||
| 6126 | return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335; | ||
| 6093 | case ZigLLVMFnIdOverflowArithmetic: | 6127 | case ZigLLVMFnIdOverflowArithmetic: |
| 6094 | return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) + | 6128 | return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) + |
| 6095 | ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) + | 6129 | ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) + |
| ... | @@ -6108,6 +6142,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { | ... | @@ -6108,6 +6142,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { |
| 6108 | return a.data.clz.bit_count == b.data.clz.bit_count; | 6142 | return a.data.clz.bit_count == b.data.clz.bit_count; |
| 6109 | case ZigLLVMFnIdPopCount: | 6143 | case ZigLLVMFnIdPopCount: |
| 6110 | return a.data.pop_count.bit_count == b.data.pop_count.bit_count; | 6144 | return a.data.pop_count.bit_count == b.data.pop_count.bit_count; |
| 6145 | case ZigLLVMFnIdBswap: | ||
| 6146 | return a.data.bswap.bit_count == b.data.bswap.bit_count; | ||
| 6111 | case ZigLLVMFnIdFloor: | 6147 | case ZigLLVMFnIdFloor: |
| 6112 | case ZigLLVMFnIdCeil: | 6148 | case ZigLLVMFnIdCeil: |
| 6113 | case ZigLLVMFnIdSqrt: | 6149 | case ZigLLVMFnIdSqrt: |
src/analyze.hpp+7-1| ... | @@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node); | ... | @@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node); |
| 87 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); | 87 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); |
| 88 | void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); | 88 | void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); |
| 89 | AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); | 89 | AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); |
| 90 | bool type_requires_comptime(ZigType *type_entry); | ||
| 91 | Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); | 90 | Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); |
| 92 | Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); | 91 | Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); |
| 93 | void complete_enum(CodeGen *g, ZigType *enum_type); | 92 | void complete_enum(CodeGen *g, ZigType *enum_type); |
| ... | @@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); | ... | @@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); |
| 216 | 215 | ||
| 217 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); | 216 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); |
| 218 | 217 | ||
| 218 | enum ReqCompTime { | ||
| 219 | ReqCompTimeInvalid, | ||
| 220 | ReqCompTimeNo, | ||
| 221 | ReqCompTimeYes, | ||
| 222 | }; | ||
| 223 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); | ||
| 224 | |||
| 219 | #endif | 225 | #endif |
src/buffer.hpp+10| ... | @@ -181,5 +181,15 @@ static inline Slice<uint8_t> buf_to_slice(Buf *buf) { | ... | @@ -181,5 +181,15 @@ static inline Slice<uint8_t> buf_to_slice(Buf *buf) { |
| 181 | return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)}; | 181 | return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)}; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static inline void buf_replace(Buf* buf, char from, char to) { | ||
| 185 | const size_t count = buf_len(buf); | ||
| 186 | char* ptr = buf_ptr(buf); | ||
| 187 | for (size_t i = 0; i < count; ++i) { | ||
| 188 | char& l = ptr[i]; | ||
| 189 | if (l == from) | ||
| 190 | l = to; | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 184 | 194 | ||
| 185 | #endif | 195 | #endif |
src/cache_hash.cpp+4-2| ... | @@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { | ... | @@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 352 | // if the mtime matches we can trust the digest | 352 | // if the mtime matches we can trust the digest |
| 353 | OsFile this_file; | 353 | OsFile this_file; |
| 354 | if ((err = os_file_open_r(chf->path, &this_file))) { | 354 | if ((err = os_file_open_r(chf->path, &this_file))) { |
| 355 | fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err)); | ||
| 355 | os_file_close(ch->manifest_file); | 356 | os_file_close(ch->manifest_file); |
| 356 | return err; | 357 | return ErrorCacheUnavailable; |
| 357 | } | 358 | } |
| 358 | OsTimeStamp actual_mtime; | 359 | OsTimeStamp actual_mtime; |
| 359 | if ((err = os_file_mtime(this_file, &actual_mtime))) { | 360 | if ((err = os_file_mtime(this_file, &actual_mtime))) { |
| ... | @@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { | ... | @@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 392 | for (; file_i < input_file_count; file_i += 1) { | 393 | for (; file_i < input_file_count; file_i += 1) { |
| 393 | CacheHashFile *chf = &ch->files.at(file_i); | 394 | CacheHashFile *chf = &ch->files.at(file_i); |
| 394 | if ((err = populate_file_hash(ch, chf, nullptr))) { | 395 | if ((err = populate_file_hash(ch, chf, nullptr))) { |
| 396 | fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err)); | ||
| 395 | os_file_close(ch->manifest_file); | 397 | os_file_close(ch->manifest_file); |
| 396 | return err; | 398 | return ErrorCacheUnavailable; |
| 397 | } | 399 | } |
| 398 | } | 400 | } |
| 399 | return ErrorNone; | 401 | return ErrorNone; |
src/codegen.cpp+77-34| ... | @@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out | ... | @@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 129 | Buf *src_dir = buf_alloc(); | 129 | Buf *src_dir = buf_alloc(); |
| 130 | os_path_split(root_src_path, src_dir, src_basename); | 130 | os_path_split(root_src_path, src_dir, src_basename); |
| 131 | 131 | ||
| 132 | if (buf_len(src_basename) == 0) { | ||
| 133 | fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); | ||
| 134 | exit(1); | ||
| 135 | } | ||
| 136 | |||
| 132 | g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename)); | 137 | g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename)); |
| 133 | g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig"); | 138 | g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig"); |
| 134 | g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); | 139 | g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); |
| ... | @@ -1645,7 +1650,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z | ... | @@ -1645,7 +1650,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1645 | zig_unreachable(); | 1650 | zig_unreachable(); |
| 1646 | } | 1651 | } |
| 1647 | 1652 | ||
| 1648 | if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt && | 1653 | if (actual_type->id == ZigTypeIdInt && |
| 1649 | !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && | 1654 | !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && |
| 1650 | want_runtime_safety) | 1655 | want_runtime_safety) |
| 1651 | { | 1656 | { |
| ... | @@ -2877,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, | ... | @@ -2877,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2877 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); | 2882 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); |
| 2878 | 2883 | ||
| 2879 | 2884 | ||
| 2880 | return cast_instruction->tmp_ptr; | ||
| 2881 | } | ||
| 2882 | case CastOpBytesToSlice: | ||
| 2883 | { | ||
| 2884 | assert(cast_instruction->tmp_ptr); | ||
| 2885 | assert(wanted_type->id == ZigTypeIdStruct); | ||
| 2886 | assert(wanted_type->data.structure.is_slice); | ||
| 2887 | assert(actual_type->id == ZigTypeIdArray); | ||
| 2888 | |||
| 2889 | ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; | ||
| 2890 | ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; | ||
| 2891 | |||
| 2892 | |||
| 2893 | size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; | ||
| 2894 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | ||
| 2895 | (unsigned)wanted_ptr_index, ""); | ||
| 2896 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, ""); | ||
| 2897 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); | ||
| 2898 | |||
| 2899 | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; | ||
| 2900 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | ||
| 2901 | (unsigned)wanted_len_index, ""); | ||
| 2902 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, | ||
| 2903 | actual_type->data.array.len / type_size(g, wanted_child_type), false); | ||
| 2904 | gen_store_untyped(g, len_val, len_ptr, 0, false); | ||
| 2905 | |||
| 2906 | return cast_instruction->tmp_ptr; | 2885 | return cast_instruction->tmp_ptr; |
| 2907 | } | 2886 | } |
| 2908 | case CastOpIntToFloat: | 2887 | case CastOpIntToFloat: |
| ... | @@ -3660,6 +3639,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru | ... | @@ -3660,6 +3639,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru |
| 3660 | AsmOutput *asm_output = asm_expr->output_list.at(i); | 3639 | AsmOutput *asm_output = asm_expr->output_list.at(i); |
| 3661 | bool is_return = (asm_output->return_type != nullptr); | 3640 | bool is_return = (asm_output->return_type != nullptr); |
| 3662 | assert(*buf_ptr(asm_output->constraint) == '='); | 3641 | assert(*buf_ptr(asm_output->constraint) == '='); |
| 3642 | // LLVM uses commas internally to separate different constraints, | ||
| 3643 | // alternative constraints are achieved with pipes. | ||
| 3644 | // We still allow the user to use commas in a way that is similar | ||
| 3645 | // to GCC's inline assembly. | ||
| 3646 | // http://llvm.org/docs/LangRef.html#constraint-codes | ||
| 3647 | buf_replace(asm_output->constraint, ',', '|'); | ||
| 3648 | |||
| 3663 | if (is_return) { | 3649 | if (is_return) { |
| 3664 | buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); | 3650 | buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); |
| 3665 | } else { | 3651 | } else { |
| ... | @@ -3679,14 +3665,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru | ... | @@ -3679,14 +3665,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru |
| 3679 | } | 3665 | } |
| 3680 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { | 3666 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { |
| 3681 | AsmInput *asm_input = asm_expr->input_list.at(i); | 3667 | AsmInput *asm_input = asm_expr->input_list.at(i); |
| 3668 | buf_replace(asm_input->constraint, ',', '|'); | ||
| 3682 | IrInstruction *ir_input = instruction->input_list[i]; | 3669 | IrInstruction *ir_input = instruction->input_list[i]; |
| 3683 | buf_append_buf(&constraint_buf, asm_input->constraint); | 3670 | buf_append_buf(&constraint_buf, asm_input->constraint); |
| 3684 | if (total_index + 1 < total_constraint_count) { | 3671 | if (total_index + 1 < total_constraint_count) { |
| 3685 | buf_append_char(&constraint_buf, ','); | 3672 | buf_append_char(&constraint_buf, ','); |
| 3686 | } | 3673 | } |
| 3687 | 3674 | ||
| 3688 | param_types[param_index] = ir_input->value.type->type_ref; | 3675 | ZigType *const type = ir_input->value.type; |
| 3689 | param_values[param_index] = ir_llvm_value(g, ir_input); | 3676 | LLVMTypeRef type_ref = type->type_ref; |
| 3677 | LLVMValueRef value_ref = ir_llvm_value(g, ir_input); | ||
| 3678 | // Handle integers of non pot bitsize by widening them. | ||
| 3679 | if (type->id == ZigTypeIdInt) { | ||
| 3680 | const size_t bitsize = type->data.integral.bit_count; | ||
| 3681 | if (bitsize < 8 || !is_power_of_2(bitsize)) { | ||
| 3682 | const bool is_signed = type->data.integral.is_signed; | ||
| 3683 | const size_t wider_bitsize = bitsize < 8 ? 8 : round_to_next_power_of_2(bitsize); | ||
| 3684 | ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize); | ||
| 3685 | type_ref = wider_type->type_ref; | ||
| 3686 | value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref); | ||
| 3687 | } | ||
| 3688 | } | ||
| 3689 | |||
| 3690 | param_types[param_index] = type_ref; | ||
| 3691 | param_values[param_index] = value_ref; | ||
| 3690 | } | 3692 | } |
| 3691 | for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { | 3693 | for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { |
| 3692 | Buf *clobber_buf = asm_expr->clobber_list.at(i); | 3694 | Buf *clobber_buf = asm_expr->clobber_list.at(i); |
| ... | @@ -3705,8 +3707,8 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru | ... | @@ -3705,8 +3707,8 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru |
| 3705 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false); | 3707 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false); |
| 3706 | 3708 | ||
| 3707 | bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0); | 3709 | bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0); |
| 3708 | LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template), | 3710 | LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), |
| 3709 | buf_ptr(&constraint_buf), is_volatile, false); | 3711 | buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT); |
| 3710 | 3712 | ||
| 3711 | return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, ""); | 3713 | return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, ""); |
| 3712 | } | 3714 | } |
| ... | @@ -3786,6 +3788,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI | ... | @@ -3786,6 +3788,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI |
| 3786 | n_args = 1; | 3788 | n_args = 1; |
| 3787 | key.id = ZigLLVMFnIdPopCount; | 3789 | key.id = ZigLLVMFnIdPopCount; |
| 3788 | key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count; | 3790 | key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count; |
| 3791 | } else if (fn_id == BuiltinFnIdBswap) { | ||
| 3792 | fn_name = "bswap"; | ||
| 3793 | n_args = 1; | ||
| 3794 | key.id = ZigLLVMFnIdBswap; | ||
| 3795 | key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count; | ||
| 3789 | } else { | 3796 | } else { |
| 3790 | zig_unreachable(); | 3797 | zig_unreachable(); |
| 3791 | } | 3798 | } |
| ... | @@ -5070,6 +5077,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -5070,6 +5077,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr |
| 5070 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | 5077 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); |
| 5071 | } | 5078 | } |
| 5072 | 5079 | ||
| 5080 | static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) { | ||
| 5081 | LLVMValueRef op = ir_llvm_value(g, instruction->op); | ||
| 5082 | ZigType *int_type = instruction->base.value.type; | ||
| 5083 | assert(int_type->id == ZigTypeIdInt); | ||
| 5084 | if (int_type->data.integral.bit_count % 16 == 0) { | ||
| 5085 | LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap); | ||
| 5086 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | ||
| 5087 | } | ||
| 5088 | // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate | ||
| 5089 | ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, | ||
| 5090 | int_type->data.integral.bit_count + 8); | ||
| 5091 | // aabbcc | ||
| 5092 | LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, ""); | ||
| 5093 | // 00aabbcc | ||
| 5094 | LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); | ||
| 5095 | LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); | ||
| 5096 | // ccbbaa00 | ||
| 5097 | LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, | ||
| 5098 | LLVMConstInt(extended_type->type_ref, 8, false), ""); | ||
| 5099 | // 00ccbbaa | ||
| 5100 | return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, ""); | ||
| 5101 | } | ||
| 5102 | |||
| 5073 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | 5103 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 5074 | AstNode *source_node = instruction->source_node; | 5104 | AstNode *source_node = instruction->source_node; |
| 5075 | Scope *scope = instruction->scope; | 5105 | Scope *scope = instruction->scope; |
| ... | @@ -5307,6 +5337,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5307,6 +5337,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5307 | return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); | 5337 | return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); |
| 5308 | case IrInstructionIdSqrt: | 5338 | case IrInstructionIdSqrt: |
| 5309 | return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); | 5339 | return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); |
| 5340 | case IrInstructionIdBswap: | ||
| 5341 | return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); | ||
| 5310 | } | 5342 | } |
| 5311 | zig_unreachable(); | 5343 | zig_unreachable(); |
| 5312 | } | 5344 | } |
| ... | @@ -6258,8 +6290,14 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6258,8 +6290,14 @@ static void do_code_gen(CodeGen *g) { |
| 6258 | } | 6290 | } |
| 6259 | if (ir_get_var_is_comptime(var)) | 6291 | if (ir_get_var_is_comptime(var)) |
| 6260 | continue; | 6292 | continue; |
| 6261 | if (type_requires_comptime(var->value->type)) | 6293 | switch (type_requires_comptime(g, var->value->type)) { |
| 6262 | continue; | 6294 | case ReqCompTimeInvalid: |
| 6295 | zig_unreachable(); | ||
| 6296 | case ReqCompTimeYes: | ||
| 6297 | continue; | ||
| 6298 | case ReqCompTimeNo: | ||
| 6299 | break; | ||
| 6300 | } | ||
| 6263 | 6301 | ||
| 6264 | if (var->src_arg_index == SIZE_MAX) { | 6302 | if (var->src_arg_index == SIZE_MAX) { |
| 6265 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | 6303 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); |
| ... | @@ -6723,6 +6761,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -6723,6 +6761,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 6723 | create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); | 6761 | create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); |
| 6724 | create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); | 6762 | create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); |
| 6725 | create_builtin_fn(g, BuiltinFnIdThis, "This", 0); | 6763 | create_builtin_fn(g, BuiltinFnIdThis, "This", 0); |
| 6764 | create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2); | ||
| 6726 | } | 6765 | } |
| 6727 | 6766 | ||
| 6728 | static const char *bool_to_str(bool b) { | 6767 | static const char *bool_to_str(bool b) { |
| ... | @@ -8149,7 +8188,11 @@ void codegen_build_and_link(CodeGen *g) { | ... | @@ -8149,7 +8188,11 @@ void codegen_build_and_link(CodeGen *g) { |
| 8149 | os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); | 8188 | os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); |
| 8150 | 8189 | ||
| 8151 | if ((err = check_cache(g, manifest_dir, &digest))) { | 8190 | if ((err = check_cache(g, manifest_dir, &digest))) { |
| 8152 | fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); | 8191 | if (err == ErrorCacheUnavailable) { |
| 8192 | // message already printed | ||
| 8193 | } else { | ||
| 8194 | fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); | ||
| 8195 | } | ||
| 8153 | exit(1); | 8196 | exit(1); |
| 8154 | } | 8197 | } |
| 8155 | 8198 |
src/error.cpp+1| ... | @@ -33,6 +33,7 @@ const char *err_str(Error err) { | ... | @@ -33,6 +33,7 @@ const char *err_str(Error err) { |
| 33 | case ErrorSharingViolation: return "sharing violation"; | 33 | case ErrorSharingViolation: return "sharing violation"; |
| 34 | case ErrorPipeBusy: return "pipe busy"; | 34 | case ErrorPipeBusy: return "pipe busy"; |
| 35 | case ErrorPrimitiveTypeNotFound: return "primitive type not found"; | 35 | case ErrorPrimitiveTypeNotFound: return "primitive type not found"; |
| 36 | case ErrorCacheUnavailable: return "cache unavailable"; | ||
| 36 | } | 37 | } |
| 37 | return "(invalid error)"; | 38 | return "(invalid error)"; |
| 38 | } | 39 | } |
src/error.hpp+1| ... | @@ -35,6 +35,7 @@ enum Error { | ... | @@ -35,6 +35,7 @@ enum Error { |
| 35 | ErrorSharingViolation, | 35 | ErrorSharingViolation, |
| 36 | ErrorPipeBusy, | 36 | ErrorPipeBusy, |
| 37 | ErrorPrimitiveTypeNotFound, | 37 | ErrorPrimitiveTypeNotFound, |
| 38 | ErrorCacheUnavailable, | ||
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | const char *err_str(Error err); | 41 | const char *err_str(Error err); |
src/ir.cpp+601-206| ... | @@ -34,6 +34,7 @@ struct IrAnalyze { | ... | @@ -34,6 +34,7 @@ struct IrAnalyze { |
| 34 | size_t old_bb_index; | 34 | size_t old_bb_index; |
| 35 | size_t instruction_index; | 35 | size_t instruction_index; |
| 36 | ZigType *explicit_return_type; | 36 | ZigType *explicit_return_type; |
| 37 | AstNode *explicit_return_type_source_node; | ||
| 37 | ZigList<IrInstruction *> src_implicit_return_type_list; | 38 | ZigList<IrInstruction *> src_implicit_return_type_list; |
| 38 | IrBasicBlock *const_predecessor_bb; | 39 | IrBasicBlock *const_predecessor_bb; |
| 39 | }; | 40 | }; |
| ... | @@ -66,6 +67,8 @@ enum ConstCastResultId { | ... | @@ -66,6 +67,8 @@ enum ConstCastResultId { |
| 66 | struct ConstCastOnly; | 67 | struct ConstCastOnly; |
| 67 | struct ConstCastArg { | 68 | struct ConstCastArg { |
| 68 | size_t arg_index; | 69 | size_t arg_index; |
| 70 | ZigType *actual_param_type; | ||
| 71 | ZigType *expected_param_type; | ||
| 69 | ConstCastOnly *child; | 72 | ConstCastOnly *child; |
| 70 | }; | 73 | }; |
| 71 | 74 | ||
| ... | @@ -138,6 +141,11 @@ struct ConstCastErrSetMismatch { | ... | @@ -138,6 +141,11 @@ struct ConstCastErrSetMismatch { |
| 138 | ZigList<ErrorTableEntry *> missing_errors; | 141 | ZigList<ErrorTableEntry *> missing_errors; |
| 139 | }; | 142 | }; |
| 140 | 143 | ||
| 144 | enum UndefAllowed { | ||
| 145 | UndefOk, | ||
| 146 | UndefBad, | ||
| 147 | }; | ||
| 148 | |||
| 141 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); | 149 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); |
| 142 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); | 150 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); |
| 143 | static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); | 151 | static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| ... | @@ -151,12 +159,14 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op | ... | @@ -151,12 +159,14 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op |
| 151 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); | 159 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); |
| 152 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); | 160 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); |
| 153 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); | 161 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); |
| 154 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 162 | static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val); |
| 155 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 163 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 156 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | 164 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 157 | ConstExprValue *out_val, ConstExprValue *ptr_val); | 165 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| 158 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, | 166 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| 159 | ZigType *dest_type, IrInstruction *dest_type_src); | 167 | ZigType *dest_type, IrInstruction *dest_type_src); |
| 168 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); | ||
| 169 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); | ||
| 160 | 170 | ||
| 161 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 171 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 162 | assert(get_src_ptr_type(const_val->type) != nullptr); | 172 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -847,6 +857,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { | ... | @@ -847,6 +857,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { |
| 847 | return IrInstructionIdSqrt; | 857 | return IrInstructionIdSqrt; |
| 848 | } | 858 | } |
| 849 | 859 | ||
| 860 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { | ||
| 861 | return IrInstructionIdBswap; | ||
| 862 | } | ||
| 863 | |||
| 850 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { | 864 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { |
| 851 | return IrInstructionIdCheckRuntimeScope; | 865 | return IrInstructionIdCheckRuntimeScope; |
| 852 | } | 866 | } |
| ... | @@ -2696,6 +2710,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc | ... | @@ -2696,6 +2710,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 2696 | return &instruction->base; | 2710 | return &instruction->base; |
| 2697 | } | 2711 | } |
| 2698 | 2712 | ||
| 2713 | static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { | ||
| 2714 | IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node); | ||
| 2715 | instruction->type = type; | ||
| 2716 | instruction->op = op; | ||
| 2717 | |||
| 2718 | if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); | ||
| 2719 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 2720 | |||
| 2721 | return &instruction->base; | ||
| 2722 | } | ||
| 2723 | |||
| 2699 | static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { | 2724 | static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { |
| 2700 | IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node); | 2725 | IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node); |
| 2701 | instruction->scope_is_comptime = scope_is_comptime; | 2726 | instruction->scope_is_comptime = scope_is_comptime; |
| ... | @@ -4680,6 +4705,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4680,6 +4705,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4680 | IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); | 4705 | IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); |
| 4681 | return ir_lval_wrap(irb, scope, result, lval); | 4706 | return ir_lval_wrap(irb, scope, result, lval); |
| 4682 | } | 4707 | } |
| 4708 | case BuiltinFnIdBswap: | ||
| 4709 | { | ||
| 4710 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4711 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4712 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4713 | return arg0_value; | ||
| 4714 | |||
| 4715 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4716 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 4717 | if (arg1_value == irb->codegen->invalid_instruction) | ||
| 4718 | return arg1_value; | ||
| 4719 | |||
| 4720 | IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); | ||
| 4721 | return ir_lval_wrap(irb, scope, result, lval); | ||
| 4722 | } | ||
| 4683 | } | 4723 | } |
| 4684 | zig_unreachable(); | 4724 | zig_unreachable(); |
| 4685 | } | 4725 | } |
| ... | @@ -5530,6 +5570,15 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5530,6 +5570,15 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5530 | return irb->codegen->invalid_instruction; | 5570 | return irb->codegen->invalid_instruction; |
| 5531 | } | 5571 | } |
| 5532 | } | 5572 | } |
| 5573 | |||
| 5574 | const char modifier = *buf_ptr(asm_output->constraint); | ||
| 5575 | if (modifier != '=') { | ||
| 5576 | add_node_error(irb->codegen, node, | ||
| 5577 | buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." | ||
| 5578 | " Compiler TODO: see https://github.com/ziglang/zig/issues/215", | ||
| 5579 | buf_ptr(asm_output->asm_symbolic_name), modifier)); | ||
| 5580 | return irb->codegen->invalid_instruction; | ||
| 5581 | } | ||
| 5533 | } | 5582 | } |
| 5534 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) { | 5583 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) { |
| 5535 | AsmInput *asm_input = node->data.asm_expr.input_list.at(i); | 5584 | AsmInput *asm_input = node->data.asm_expr.input_list.at(i); |
| ... | @@ -7316,15 +7365,31 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, | ... | @@ -7316,15 +7365,31 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, |
| 7316 | return ir_add_error_node(ira, source_instruction->source_node, msg); | 7365 | return ir_add_error_node(ira, source_instruction->source_node, msg); |
| 7317 | } | 7366 | } |
| 7318 | 7367 | ||
| 7368 | // This function takes a comptime ptr and makes the child const value conform to the type | ||
| 7369 | // described by the pointer. | ||
| 7370 | static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, AstNode *source_node, ConstExprValue *ptr_val) { | ||
| 7371 | Error err; | ||
| 7372 | assert(ptr_val->type->id == ZigTypeIdPointer); | ||
| 7373 | ConstExprValue tmp = {}; | ||
| 7374 | tmp.special = ConstValSpecialStatic; | ||
| 7375 | tmp.type = ptr_val->type->data.pointer.child_type; | ||
| 7376 | if ((err = ir_read_const_ptr(ira, source_node, &tmp, ptr_val))) | ||
| 7377 | return err; | ||
| 7378 | ConstExprValue *child_val = const_ptr_pointee_unchecked(ira->codegen, ptr_val); | ||
| 7379 | copy_const_val(child_val, &tmp, false); | ||
| 7380 | return ErrorNone; | ||
| 7381 | } | ||
| 7382 | |||
| 7319 | static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) { | 7383 | static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) { |
| 7384 | Error err; | ||
| 7320 | ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val); | 7385 | ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val); |
| 7321 | assert(val != nullptr); | 7386 | assert(val != nullptr); |
| 7322 | assert(const_val->type->id == ZigTypeIdPointer); | 7387 | assert(const_val->type->id == ZigTypeIdPointer); |
| 7323 | ZigType *expected_type = const_val->type->data.pointer.child_type; | 7388 | ZigType *expected_type = const_val->type->data.pointer.child_type; |
| 7324 | if (!types_have_same_zig_comptime_repr(val->type, expected_type)) { | 7389 | if (!types_have_same_zig_comptime_repr(val->type, expected_type)) { |
| 7325 | ir_add_error_node(ira, source_node, | 7390 | if ((err = eval_comptime_ptr_reinterpret(ira, source_node, const_val))) |
| 7326 | buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955")); | 7391 | return nullptr; |
| 7327 | return nullptr; | 7392 | return const_ptr_pointee_unchecked(ira->codegen, const_val); |
| 7328 | } | 7393 | } |
| 7329 | return val; | 7394 | return val; |
| 7330 | } | 7395 | } |
| ... | @@ -8063,15 +8128,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8063,15 +8128,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 8063 | return false; | 8128 | return false; |
| 8064 | } | 8129 | } |
| 8065 | 8130 | ||
| 8066 | ConstExprValue *const_val = &instruction->value; | 8131 | ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad); |
| 8067 | assert(const_val->special != ConstValSpecialRuntime); | 8132 | assert(const_val != nullptr); |
| 8133 | |||
| 8134 | bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt); | ||
| 8135 | bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat); | ||
| 8068 | 8136 | ||
| 8069 | bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || | ||
| 8070 | const_val->type->id == ZigTypeIdComptimeInt); | ||
| 8071 | bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || | ||
| 8072 | const_val->type->id == ZigTypeIdComptimeFloat); | ||
| 8073 | if (other_type->id == ZigTypeIdFloat) { | 8137 | if (other_type->id == ZigTypeIdFloat) { |
| 8074 | return true; | 8138 | if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) { |
| 8139 | return true; | ||
| 8140 | } | ||
| 8141 | if (const_val->type->id == ZigTypeIdInt) { | ||
| 8142 | BigFloat tmp_bf; | ||
| 8143 | bigfloat_init_bigint(&tmp_bf, &const_val->data.x_bigint); | ||
| 8144 | BigFloat orig_bf; | ||
| 8145 | switch (other_type->data.floating.bit_count) { | ||
| 8146 | case 16: { | ||
| 8147 | float16_t tmp = bigfloat_to_f16(&tmp_bf); | ||
| 8148 | bigfloat_init_16(&orig_bf, tmp); | ||
| 8149 | break; | ||
| 8150 | } | ||
| 8151 | case 32: { | ||
| 8152 | float tmp = bigfloat_to_f32(&tmp_bf); | ||
| 8153 | bigfloat_init_32(&orig_bf, tmp); | ||
| 8154 | break; | ||
| 8155 | } | ||
| 8156 | case 64: { | ||
| 8157 | double tmp = bigfloat_to_f64(&tmp_bf); | ||
| 8158 | bigfloat_init_64(&orig_bf, tmp); | ||
| 8159 | break; | ||
| 8160 | } | ||
| 8161 | case 80: | ||
| 8162 | zig_panic("TODO"); | ||
| 8163 | case 128: { | ||
| 8164 | float128_t tmp = bigfloat_to_f128(&tmp_bf); | ||
| 8165 | bigfloat_init_128(&orig_bf, tmp); | ||
| 8166 | break; | ||
| 8167 | } | ||
| 8168 | default: | ||
| 8169 | zig_unreachable(); | ||
| 8170 | } | ||
| 8171 | BigInt orig_bi; | ||
| 8172 | bigint_init_bigfloat(&orig_bi, &orig_bf); | ||
| 8173 | if (bigint_cmp(&orig_bi, &const_val->data.x_bigint) == CmpEQ) { | ||
| 8174 | return true; | ||
| 8175 | } | ||
| 8176 | Buf *val_buf = buf_alloc(); | ||
| 8177 | bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); | ||
| 8178 | ir_add_error(ira, instruction, | ||
| 8179 | buf_sprintf("integer value %s has no representation in type '%s'", | ||
| 8180 | buf_ptr(val_buf), | ||
| 8181 | buf_ptr(&other_type->name))); | ||
| 8182 | return false; | ||
| 8183 | } | ||
| 8184 | if (other_type->data.floating.bit_count >= const_val->type->data.floating.bit_count) { | ||
| 8185 | return true; | ||
| 8186 | } | ||
| 8187 | switch (other_type->data.floating.bit_count) { | ||
| 8188 | case 16: | ||
| 8189 | switch (const_val->type->data.floating.bit_count) { | ||
| 8190 | case 32: { | ||
| 8191 | float16_t tmp = zig_double_to_f16(const_val->data.x_f32); | ||
| 8192 | float orig = zig_f16_to_double(tmp); | ||
| 8193 | if (const_val->data.x_f32 == orig) { | ||
| 8194 | return true; | ||
| 8195 | } | ||
| 8196 | break; | ||
| 8197 | } | ||
| 8198 | case 64: { | ||
| 8199 | float16_t tmp = zig_double_to_f16(const_val->data.x_f64); | ||
| 8200 | double orig = zig_f16_to_double(tmp); | ||
| 8201 | if (const_val->data.x_f64 == orig) { | ||
| 8202 | return true; | ||
| 8203 | } | ||
| 8204 | break; | ||
| 8205 | } | ||
| 8206 | case 80: | ||
| 8207 | zig_panic("TODO"); | ||
| 8208 | case 128: { | ||
| 8209 | float16_t tmp = f128M_to_f16(&const_val->data.x_f128); | ||
| 8210 | float128_t orig; | ||
| 8211 | f16_to_f128M(tmp, &orig); | ||
| 8212 | if (f128M_eq(&orig, &const_val->data.x_f128)) { | ||
| 8213 | return true; | ||
| 8214 | } | ||
| 8215 | break; | ||
| 8216 | } | ||
| 8217 | default: | ||
| 8218 | zig_unreachable(); | ||
| 8219 | } | ||
| 8220 | break; | ||
| 8221 | case 32: | ||
| 8222 | switch (const_val->type->data.floating.bit_count) { | ||
| 8223 | case 64: { | ||
| 8224 | float tmp = const_val->data.x_f64; | ||
| 8225 | double orig = tmp; | ||
| 8226 | if (const_val->data.x_f64 == orig) { | ||
| 8227 | return true; | ||
| 8228 | } | ||
| 8229 | break; | ||
| 8230 | } | ||
| 8231 | case 80: | ||
| 8232 | zig_panic("TODO"); | ||
| 8233 | case 128: { | ||
| 8234 | float32_t tmp = f128M_to_f32(&const_val->data.x_f128); | ||
| 8235 | float128_t orig; | ||
| 8236 | f32_to_f128M(tmp, &orig); | ||
| 8237 | if (f128M_eq(&orig, &const_val->data.x_f128)) { | ||
| 8238 | return true; | ||
| 8239 | } | ||
| 8240 | break; | ||
| 8241 | } | ||
| 8242 | default: | ||
| 8243 | zig_unreachable(); | ||
| 8244 | } | ||
| 8245 | break; | ||
| 8246 | case 64: | ||
| 8247 | switch (const_val->type->data.floating.bit_count) { | ||
| 8248 | case 80: | ||
| 8249 | zig_panic("TODO"); | ||
| 8250 | case 128: { | ||
| 8251 | float64_t tmp = f128M_to_f64(&const_val->data.x_f128); | ||
| 8252 | float128_t orig; | ||
| 8253 | f64_to_f128M(tmp, &orig); | ||
| 8254 | if (f128M_eq(&orig, &const_val->data.x_f128)) { | ||
| 8255 | return true; | ||
| 8256 | } | ||
| 8257 | break; | ||
| 8258 | } | ||
| 8259 | default: | ||
| 8260 | zig_unreachable(); | ||
| 8261 | } | ||
| 8262 | break; | ||
| 8263 | case 80: | ||
| 8264 | assert(const_val->type->data.floating.bit_count == 128); | ||
| 8265 | zig_panic("TODO"); | ||
| 8266 | case 128: | ||
| 8267 | return true; | ||
| 8268 | default: | ||
| 8269 | zig_unreachable(); | ||
| 8270 | } | ||
| 8271 | Buf *val_buf = buf_alloc(); | ||
| 8272 | float_append_buf(val_buf, const_val); | ||
| 8273 | ir_add_error(ira, instruction, | ||
| 8274 | buf_sprintf("cast of value %s to type '%s' loses information", | ||
| 8275 | buf_ptr(val_buf), | ||
| 8276 | buf_ptr(&other_type->name))); | ||
| 8277 | return false; | ||
| 8075 | } else if (other_type->id == ZigTypeIdInt && const_val_is_int) { | 8278 | } else if (other_type->id == ZigTypeIdInt && const_val_is_int) { |
| 8076 | if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) { | 8279 | if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) { |
| 8077 | Buf *val_buf = buf_alloc(); | 8280 | Buf *val_buf = buf_alloc(); |
| ... | @@ -8484,6 +8687,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted | ... | @@ -8484,6 +8687,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8484 | if (arg_child.id != ConstCastResultIdOk) { | 8687 | if (arg_child.id != ConstCastResultIdOk) { |
| 8485 | result.id = ConstCastResultIdFnArg; | 8688 | result.id = ConstCastResultIdFnArg; |
| 8486 | result.data.fn_arg.arg_index = i; | 8689 | result.data.fn_arg.arg_index = i; |
| 8690 | result.data.fn_arg.actual_param_type = actual_param_info->type; | ||
| 8691 | result.data.fn_arg.expected_param_type = expected_param_info->type; | ||
| 8487 | result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1); | 8692 | result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1); |
| 8488 | *result.data.fn_arg.child = arg_child; | 8693 | *result.data.fn_arg.child = arg_child; |
| 8489 | return result; | 8694 | return result; |
| ... | @@ -9134,7 +9339,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -9134,7 +9339,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9134 | const_val->type = new_type; | 9339 | const_val->type = new_type; |
| 9135 | break; | 9340 | break; |
| 9136 | case CastOpResizeSlice: | 9341 | case CastOpResizeSlice: |
| 9137 | case CastOpBytesToSlice: | ||
| 9138 | // can't do it | 9342 | // can't do it |
| 9139 | zig_unreachable(); | 9343 | zig_unreachable(); |
| 9140 | case CastOpIntToFloat: | 9344 | case CastOpIntToFloat: |
| ... | @@ -9191,7 +9395,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -9191,7 +9395,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 9191 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) | 9395 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) |
| 9192 | { | 9396 | { |
| 9193 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && | 9397 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && |
| 9194 | cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice) | 9398 | cast_op != CastOpResizeSlice) |
| 9195 | { | 9399 | { |
| 9196 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 9400 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 9197 | source_instr->source_node, wanted_type); | 9401 | source_instr->source_node, wanted_type); |
| ... | @@ -9453,11 +9657,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -9453,11 +9657,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio |
| 9453 | return const_instr; | 9657 | return const_instr; |
| 9454 | } | 9658 | } |
| 9455 | 9659 | ||
| 9456 | enum UndefAllowed { | ||
| 9457 | UndefOk, | ||
| 9458 | UndefBad, | ||
| 9459 | }; | ||
| 9460 | |||
| 9461 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { | 9660 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { |
| 9462 | switch (value->value.special) { | 9661 | switch (value->value.special) { |
| 9463 | case ConstValSpecialStatic: | 9662 | case ConstValSpecialStatic: |
| ... | @@ -10014,7 +10213,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -10014,7 +10213,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 10014 | return ira->codegen->invalid_instruction; | 10213 | return ira->codegen->invalid_instruction; |
| 10015 | } | 10214 | } |
| 10016 | 10215 | ||
| 10017 | assert(actual_type->id == ZigTypeIdInt); | 10216 | assert(actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt); |
| 10018 | 10217 | ||
| 10019 | if (instr_is_comptime(target)) { | 10218 | if (instr_is_comptime(target)) { |
| 10020 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 10219 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| ... | @@ -10334,6 +10533,15 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa | ... | @@ -10334,6 +10533,15 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10334 | } | 10533 | } |
| 10335 | break; | 10534 | break; |
| 10336 | } | 10535 | } |
| 10536 | case ConstCastResultIdFnArg: { | ||
| 10537 | ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node, | ||
| 10538 | buf_sprintf("parameter %" ZIG_PRI_usize ": '%s' cannot cast into '%s'", | ||
| 10539 | cast_result->data.fn_arg.arg_index, | ||
| 10540 | buf_ptr(&cast_result->data.fn_arg.actual_param_type->name), | ||
| 10541 | buf_ptr(&cast_result->data.fn_arg.expected_param_type->name))); | ||
| 10542 | report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg); | ||
| 10543 | break; | ||
| 10544 | } | ||
| 10337 | case ConstCastResultIdFnAlign: // TODO | 10545 | case ConstCastResultIdFnAlign: // TODO |
| 10338 | case ConstCastResultIdFnCC: // TODO | 10546 | case ConstCastResultIdFnCC: // TODO |
| 10339 | case ConstCastResultIdFnVarArgs: // TODO | 10547 | case ConstCastResultIdFnVarArgs: // TODO |
| ... | @@ -10341,7 +10549,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa | ... | @@ -10341,7 +10549,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10341 | case ConstCastResultIdFnReturnType: // TODO | 10549 | case ConstCastResultIdFnReturnType: // TODO |
| 10342 | case ConstCastResultIdFnArgCount: // TODO | 10550 | case ConstCastResultIdFnArgCount: // TODO |
| 10343 | case ConstCastResultIdFnGenericArgCount: // TODO | 10551 | case ConstCastResultIdFnGenericArgCount: // TODO |
| 10344 | case ConstCastResultIdFnArg: // TODO | ||
| 10345 | case ConstCastResultIdFnArgNoAlias: // TODO | 10552 | case ConstCastResultIdFnArgNoAlias: // TODO |
| 10346 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO | 10553 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO |
| 10347 | case ConstCastResultIdAsyncAllocatorType: // TODO | 10554 | case ConstCastResultIdAsyncAllocatorType: // TODO |
| ... | @@ -10370,6 +10577,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10370,6 +10577,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10370 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); | 10577 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); |
| 10371 | } | 10578 | } |
| 10372 | 10579 | ||
| 10580 | // cast from T to ?T | ||
| 10581 | // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism | ||
| 10582 | if (wanted_type->id == ZigTypeIdOptional) { | ||
| 10583 | ZigType *wanted_child_type = wanted_type->data.maybe.child_type; | ||
| 10584 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, | ||
| 10585 | false).id == ConstCastResultIdOk) | ||
| 10586 | { | ||
| 10587 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | ||
| 10588 | } else if (actual_type->id == ZigTypeIdComptimeInt || | ||
| 10589 | actual_type->id == ZigTypeIdComptimeFloat) | ||
| 10590 | { | ||
| 10591 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { | ||
| 10592 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | ||
| 10593 | } else { | ||
| 10594 | return ira->codegen->invalid_instruction; | ||
| 10595 | } | ||
| 10596 | } else if ( | ||
| 10597 | wanted_child_type->id == ZigTypeIdPointer && | ||
| 10598 | wanted_child_type->data.pointer.ptr_len == PtrLenUnknown && | ||
| 10599 | actual_type->id == ZigTypeIdPointer && | ||
| 10600 | actual_type->data.pointer.ptr_len == PtrLenSingle && | ||
| 10601 | actual_type->data.pointer.child_type->id == ZigTypeIdArray) | ||
| 10602 | { | ||
| 10603 | if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) | ||
| 10604 | return ira->codegen->invalid_instruction; | ||
| 10605 | if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) | ||
| 10606 | return ira->codegen->invalid_instruction; | ||
| 10607 | if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) && | ||
| 10608 | types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, | ||
| 10609 | actual_type->data.pointer.child_type->data.array.child_type, source_node, | ||
| 10610 | !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) | ||
| 10611 | { | ||
| 10612 | IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, | ||
| 10613 | wanted_child_type); | ||
| 10614 | if (type_is_invalid(cast1->value.type)) | ||
| 10615 | return ira->codegen->invalid_instruction; | ||
| 10616 | return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); | ||
| 10617 | } | ||
| 10618 | } | ||
| 10619 | } | ||
| 10620 | |||
| 10621 | // T to E!T | ||
| 10622 | if (wanted_type->id == ZigTypeIdErrorUnion) { | ||
| 10623 | if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type, | ||
| 10624 | source_node, false).id == ConstCastResultIdOk) | ||
| 10625 | { | ||
| 10626 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); | ||
| 10627 | } else if (actual_type->id == ZigTypeIdComptimeInt || | ||
| 10628 | actual_type->id == ZigTypeIdComptimeFloat) | ||
| 10629 | { | ||
| 10630 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) { | ||
| 10631 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); | ||
| 10632 | } else { | ||
| 10633 | return ira->codegen->invalid_instruction; | ||
| 10634 | } | ||
| 10635 | } | ||
| 10636 | } | ||
| 10637 | |||
| 10638 | // cast from T to E!?T | ||
| 10639 | if (wanted_type->id == ZigTypeIdErrorUnion && | ||
| 10640 | wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional && | ||
| 10641 | actual_type->id != ZigTypeIdOptional) | ||
| 10642 | { | ||
| 10643 | ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type; | ||
| 10644 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk || | ||
| 10645 | actual_type->id == ZigTypeIdNull || | ||
| 10646 | actual_type->id == ZigTypeIdComptimeInt || | ||
| 10647 | actual_type->id == ZigTypeIdComptimeFloat) | ||
| 10648 | { | ||
| 10649 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); | ||
| 10650 | if (type_is_invalid(cast1->value.type)) | ||
| 10651 | return ira->codegen->invalid_instruction; | ||
| 10652 | |||
| 10653 | IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); | ||
| 10654 | if (type_is_invalid(cast2->value.type)) | ||
| 10655 | return ira->codegen->invalid_instruction; | ||
| 10656 | |||
| 10657 | return cast2; | ||
| 10658 | } | ||
| 10659 | } | ||
| 10660 | |||
| 10661 | |||
| 10662 | // cast from comptime-known number to another number type | ||
| 10663 | if (instr_is_comptime(value) && | ||
| 10664 | (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt || | ||
| 10665 | actual_type->id == ZigTypeIdFloat || actual_type->id == ZigTypeIdComptimeFloat) && | ||
| 10666 | (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt || | ||
| 10667 | wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) | ||
| 10668 | { | ||
| 10669 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { | ||
| 10670 | if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { | ||
| 10671 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | ||
| 10672 | if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { | ||
| 10673 | bigint_init_bigint(&result->value.data.x_bigint, &value->value.data.x_bigint); | ||
| 10674 | } else { | ||
| 10675 | float_init_bigint(&result->value.data.x_bigint, &value->value); | ||
| 10676 | } | ||
| 10677 | return result; | ||
| 10678 | } else if (wanted_type->id == ZigTypeIdComptimeFloat || wanted_type->id == ZigTypeIdFloat) { | ||
| 10679 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | ||
| 10680 | if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { | ||
| 10681 | BigFloat bf; | ||
| 10682 | bigfloat_init_bigint(&bf, &value->value.data.x_bigint); | ||
| 10683 | float_init_bigfloat(&result->value, &bf); | ||
| 10684 | } else { | ||
| 10685 | float_init_float(&result->value, &value->value); | ||
| 10686 | } | ||
| 10687 | return result; | ||
| 10688 | } | ||
| 10689 | zig_unreachable(); | ||
| 10690 | } else { | ||
| 10691 | return ira->codegen->invalid_instruction; | ||
| 10692 | } | ||
| 10693 | } | ||
| 10694 | |||
| 10373 | // widening conversion | 10695 | // widening conversion |
| 10374 | if (wanted_type->id == ZigTypeIdInt && | 10696 | if (wanted_type->id == ZigTypeIdInt && |
| 10375 | actual_type->id == ZigTypeIdInt && | 10697 | actual_type->id == ZigTypeIdInt && |
| ... | @@ -10472,47 +10794,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10472,47 +10794,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10472 | } | 10794 | } |
| 10473 | 10795 | ||
| 10474 | 10796 | ||
| 10475 | // cast from T to ?T | ||
| 10476 | // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism | ||
| 10477 | if (wanted_type->id == ZigTypeIdOptional) { | ||
| 10478 | ZigType *wanted_child_type = wanted_type->data.maybe.child_type; | ||
| 10479 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, | ||
| 10480 | false).id == ConstCastResultIdOk) | ||
| 10481 | { | ||
| 10482 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | ||
| 10483 | } else if (actual_type->id == ZigTypeIdComptimeInt || | ||
| 10484 | actual_type->id == ZigTypeIdComptimeFloat) | ||
| 10485 | { | ||
| 10486 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { | ||
| 10487 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | ||
| 10488 | } else { | ||
| 10489 | return ira->codegen->invalid_instruction; | ||
| 10490 | } | ||
| 10491 | } else if ( | ||
| 10492 | wanted_child_type->id == ZigTypeIdPointer && | ||
| 10493 | wanted_child_type->data.pointer.ptr_len == PtrLenUnknown && | ||
| 10494 | actual_type->id == ZigTypeIdPointer && | ||
| 10495 | actual_type->data.pointer.ptr_len == PtrLenSingle && | ||
| 10496 | actual_type->data.pointer.child_type->id == ZigTypeIdArray) | ||
| 10497 | { | ||
| 10498 | if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) | ||
| 10499 | return ira->codegen->invalid_instruction; | ||
| 10500 | if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) | ||
| 10501 | return ira->codegen->invalid_instruction; | ||
| 10502 | if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) && | ||
| 10503 | types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, | ||
| 10504 | actual_type->data.pointer.child_type->data.array.child_type, source_node, | ||
| 10505 | !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) | ||
| 10506 | { | ||
| 10507 | IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, | ||
| 10508 | wanted_child_type); | ||
| 10509 | if (type_is_invalid(cast1->value.type)) | ||
| 10510 | return ira->codegen->invalid_instruction; | ||
| 10511 | return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); | ||
| 10512 | } | ||
| 10513 | } | ||
| 10514 | } | ||
| 10515 | |||
| 10516 | // cast from null literal to maybe type | 10797 | // cast from null literal to maybe type |
| 10517 | if (wanted_type->id == ZigTypeIdOptional && | 10798 | if (wanted_type->id == ZigTypeIdOptional && |
| 10518 | actual_type->id == ZigTypeIdNull) | 10799 | actual_type->id == ZigTypeIdNull) |
| ... | @@ -10520,23 +10801,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10520,23 +10801,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10520 | return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); | 10801 | return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); |
| 10521 | } | 10802 | } |
| 10522 | 10803 | ||
| 10523 | // cast from child type of error type to error type | ||
| 10524 | if (wanted_type->id == ZigTypeIdErrorUnion) { | ||
| 10525 | if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type, | ||
| 10526 | source_node, false).id == ConstCastResultIdOk) | ||
| 10527 | { | ||
| 10528 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); | ||
| 10529 | } else if (actual_type->id == ZigTypeIdComptimeInt || | ||
| 10530 | actual_type->id == ZigTypeIdComptimeFloat) | ||
| 10531 | { | ||
| 10532 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) { | ||
| 10533 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); | ||
| 10534 | } else { | ||
| 10535 | return ira->codegen->invalid_instruction; | ||
| 10536 | } | ||
| 10537 | } | ||
| 10538 | } | ||
| 10539 | |||
| 10540 | // cast from [N]T to E![]const T | 10804 | // cast from [N]T to E![]const T |
| 10541 | if (wanted_type->id == ZigTypeIdErrorUnion && | 10805 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| 10542 | is_slice(wanted_type->data.error_union.payload_type) && | 10806 | is_slice(wanted_type->data.error_union.payload_type) && |
| ... | @@ -10568,54 +10832,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10568,54 +10832,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10568 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); | 10832 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); |
| 10569 | } | 10833 | } |
| 10570 | 10834 | ||
| 10571 | // cast from T to E!?T | ||
| 10572 | if (wanted_type->id == ZigTypeIdErrorUnion && | ||
| 10573 | wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional && | ||
| 10574 | actual_type->id != ZigTypeIdOptional) | ||
| 10575 | { | ||
| 10576 | ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type; | ||
| 10577 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk || | ||
| 10578 | actual_type->id == ZigTypeIdNull || | ||
| 10579 | actual_type->id == ZigTypeIdComptimeInt || | ||
| 10580 | actual_type->id == ZigTypeIdComptimeFloat) | ||
| 10581 | { | ||
| 10582 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); | ||
| 10583 | if (type_is_invalid(cast1->value.type)) | ||
| 10584 | return ira->codegen->invalid_instruction; | ||
| 10585 | |||
| 10586 | IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); | ||
| 10587 | if (type_is_invalid(cast2->value.type)) | ||
| 10588 | return ira->codegen->invalid_instruction; | ||
| 10589 | |||
| 10590 | return cast2; | ||
| 10591 | } | ||
| 10592 | } | ||
| 10593 | |||
| 10594 | // cast from number literal to another type | ||
| 10595 | if (actual_type->id == ZigTypeIdComptimeFloat || | ||
| 10596 | actual_type->id == ZigTypeIdComptimeInt) | ||
| 10597 | { | ||
| 10598 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { | ||
| 10599 | CastOp op; | ||
| 10600 | if ((actual_type->id == ZigTypeIdComptimeFloat && | ||
| 10601 | wanted_type->id == ZigTypeIdFloat) || | ||
| 10602 | (actual_type->id == ZigTypeIdComptimeInt && | ||
| 10603 | wanted_type->id == ZigTypeIdInt)) | ||
| 10604 | { | ||
| 10605 | op = CastOpNumLitToConcrete; | ||
| 10606 | } else if (wanted_type->id == ZigTypeIdInt) { | ||
| 10607 | op = CastOpFloatToInt; | ||
| 10608 | } else if (wanted_type->id == ZigTypeIdFloat) { | ||
| 10609 | op = CastOpIntToFloat; | ||
| 10610 | } else { | ||
| 10611 | zig_unreachable(); | ||
| 10612 | } | ||
| 10613 | return ir_resolve_cast(ira, source_instr, value, wanted_type, op, false); | ||
| 10614 | } else { | ||
| 10615 | return ira->codegen->invalid_instruction; | ||
| 10616 | } | ||
| 10617 | } | ||
| 10618 | |||
| 10619 | // cast from typed number to integer or float literal. | 10835 | // cast from typed number to integer or float literal. |
| 10620 | // works when the number is known at compile time | 10836 | // works when the number is known at compile time |
| 10621 | if (instr_is_comptime(value) && | 10837 | if (instr_is_comptime(value) && |
| ... | @@ -11014,8 +11230,12 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio | ... | @@ -11014,8 +11230,12 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 11014 | return ir_unreach_error(ira); | 11230 | return ir_unreach_error(ira); |
| 11015 | 11231 | ||
| 11016 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); | 11232 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); |
| 11017 | if (type_is_invalid(casted_value->value.type)) | 11233 | if (type_is_invalid(casted_value->value.type) && ira->explicit_return_type_source_node != nullptr) { |
| 11234 | ErrorMsg *msg = ira->codegen->errors.last(); | ||
| 11235 | add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node, | ||
| 11236 | buf_sprintf("return type declared here")); | ||
| 11018 | return ir_unreach_error(ira); | 11237 | return ir_unreach_error(ira); |
| 11238 | } | ||
| 11019 | 11239 | ||
| 11020 | if (casted_value->value.special == ConstValSpecialRuntime && | 11240 | if (casted_value->value.special == ConstValSpecialRuntime && |
| 11021 | casted_value->value.type->id == ZigTypeIdPointer && | 11241 | casted_value->value.type->id == ZigTypeIdPointer && |
| ... | @@ -11114,7 +11334,6 @@ static bool optional_value_is_null(ConstExprValue *val) { | ... | @@ -11114,7 +11334,6 @@ static bool optional_value_is_null(ConstExprValue *val) { |
| 11114 | } | 11334 | } |
| 11115 | 11335 | ||
| 11116 | static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 11336 | static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 11117 | Error err; | ||
| 11118 | IrInstruction *op1 = bin_op_instruction->op1->child; | 11337 | IrInstruction *op1 = bin_op_instruction->op1->child; |
| 11119 | if (type_is_invalid(op1->value.type)) | 11338 | if (type_is_invalid(op1->value.type)) |
| 11120 | return ira->codegen->invalid_instruction; | 11339 | return ira->codegen->invalid_instruction; |
| ... | @@ -11308,10 +11527,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -11308,10 +11527,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11308 | if (casted_op2 == ira->codegen->invalid_instruction) | 11527 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 11309 | return ira->codegen->invalid_instruction; | 11528 | return ira->codegen->invalid_instruction; |
| 11310 | 11529 | ||
| 11311 | if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown))) | 11530 | bool requires_comptime; |
| 11312 | return ira->codegen->invalid_instruction; | 11531 | switch (type_requires_comptime(ira->codegen, resolved_type)) { |
| 11532 | case ReqCompTimeYes: | ||
| 11533 | requires_comptime = true; | ||
| 11534 | break; | ||
| 11535 | case ReqCompTimeNo: | ||
| 11536 | requires_comptime = false; | ||
| 11537 | break; | ||
| 11538 | case ReqCompTimeInvalid: | ||
| 11539 | return ira->codegen->invalid_instruction; | ||
| 11540 | } | ||
| 11313 | 11541 | ||
| 11314 | bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type); | 11542 | bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type); |
| 11315 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { | 11543 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 11316 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); | 11544 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 11317 | if (op1_val == nullptr) | 11545 | if (op1_val == nullptr) |
| ... | @@ -12244,42 +12472,42 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12244,42 +12472,42 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12244 | ZigType *result_type = casted_init_value->value.type; | 12472 | ZigType *result_type = casted_init_value->value.type; |
| 12245 | if (type_is_invalid(result_type)) { | 12473 | if (type_is_invalid(result_type)) { |
| 12246 | result_type = ira->codegen->builtin_types.entry_invalid; | 12474 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12247 | } else { | 12475 | } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) { |
| 12248 | if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) { | 12476 | ir_add_error_node(ira, source_node, |
| 12249 | result_type = ira->codegen->builtin_types.entry_invalid; | 12477 | buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); |
| 12250 | } | 12478 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12251 | } | 12479 | } |
| 12252 | 12480 | ||
| 12253 | if (!type_is_invalid(result_type)) { | 12481 | switch (type_requires_comptime(ira->codegen, result_type)) { |
| 12254 | if (result_type->id == ZigTypeIdUnreachable || | 12482 | case ReqCompTimeInvalid: |
| 12255 | result_type->id == ZigTypeIdOpaque) | 12483 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12256 | { | 12484 | break; |
| 12485 | case ReqCompTimeYes: { | ||
| 12486 | var_class_requires_const = true; | ||
| 12487 | if (!var->gen_is_const && !is_comptime_var) { | ||
| 12257 | ir_add_error_node(ira, source_node, | 12488 | ir_add_error_node(ira, source_node, |
| 12258 | buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); | 12489 | buf_sprintf("variable of type '%s' must be const or comptime", |
| 12490 | buf_ptr(&result_type->name))); | ||
| 12259 | result_type = ira->codegen->builtin_types.entry_invalid; | 12491 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12260 | } else if (type_requires_comptime(result_type)) { | 12492 | } |
| 12493 | break; | ||
| 12494 | } | ||
| 12495 | case ReqCompTimeNo: | ||
| 12496 | if (casted_init_value->value.special == ConstValSpecialStatic && | ||
| 12497 | casted_init_value->value.type->id == ZigTypeIdFn && | ||
| 12498 | casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr && | ||
| 12499 | casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) | ||
| 12500 | { | ||
| 12261 | var_class_requires_const = true; | 12501 | var_class_requires_const = true; |
| 12262 | if (!var->gen_is_const && !is_comptime_var) { | 12502 | if (!var->src_is_const && !is_comptime_var) { |
| 12263 | ir_add_error_node(ira, source_node, | 12503 | ErrorMsg *msg = ir_add_error_node(ira, source_node, |
| 12264 | buf_sprintf("variable of type '%s' must be const or comptime", | 12504 | buf_sprintf("functions marked inline must be stored in const or comptime var")); |
| 12265 | buf_ptr(&result_type->name))); | 12505 | AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; |
| 12506 | add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); | ||
| 12266 | result_type = ira->codegen->builtin_types.entry_invalid; | 12507 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12267 | } | 12508 | } |
| 12268 | } else { | ||
| 12269 | if (casted_init_value->value.special == ConstValSpecialStatic && | ||
| 12270 | casted_init_value->value.type->id == ZigTypeIdFn && | ||
| 12271 | casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) | ||
| 12272 | { | ||
| 12273 | var_class_requires_const = true; | ||
| 12274 | if (!var->src_is_const && !is_comptime_var) { | ||
| 12275 | ErrorMsg *msg = ir_add_error_node(ira, source_node, | ||
| 12276 | buf_sprintf("functions marked inline must be stored in const or comptime var")); | ||
| 12277 | AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; | ||
| 12278 | add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); | ||
| 12279 | result_type = ira->codegen->builtin_types.entry_invalid; | ||
| 12280 | } | ||
| 12281 | } | ||
| 12282 | } | 12509 | } |
| 12510 | break; | ||
| 12283 | } | 12511 | } |
| 12284 | 12512 | ||
| 12285 | if (var->value->type != nullptr && !is_comptime_var) { | 12513 | if (var->value->type != nullptr && !is_comptime_var) { |
| ... | @@ -12750,10 +12978,15 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -12750,10 +12978,15 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 12750 | } | 12978 | } |
| 12751 | 12979 | ||
| 12752 | if (!comptime_arg) { | 12980 | if (!comptime_arg) { |
| 12753 | if (type_requires_comptime(casted_arg->value.type)) { | 12981 | switch (type_requires_comptime(ira->codegen, casted_arg->value.type)) { |
| 12982 | case ReqCompTimeYes: | ||
| 12754 | ir_add_error(ira, casted_arg, | 12983 | ir_add_error(ira, casted_arg, |
| 12755 | buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name))); | 12984 | buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name))); |
| 12756 | return false; | 12985 | return false; |
| 12986 | case ReqCompTimeInvalid: | ||
| 12987 | return false; | ||
| 12988 | case ReqCompTimeNo: | ||
| 12989 | break; | ||
| 12757 | } | 12990 | } |
| 12758 | 12991 | ||
| 12759 | casted_args[fn_type_id->param_count] = casted_arg; | 12992 | casted_args[fn_type_id->param_count] = casted_arg; |
| ... | @@ -13226,12 +13459,15 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call | ... | @@ -13226,12 +13459,15 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13226 | inst_fn_type_id.return_type = specified_return_type; | 13459 | inst_fn_type_id.return_type = specified_return_type; |
| 13227 | } | 13460 | } |
| 13228 | 13461 | ||
| 13229 | if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown))) | 13462 | switch (type_requires_comptime(ira->codegen, specified_return_type)) { |
| 13230 | return ira->codegen->invalid_instruction; | 13463 | case ReqCompTimeYes: |
| 13231 | |||
| 13232 | if (type_requires_comptime(specified_return_type)) { | ||
| 13233 | // Throw out our work and call the function as if it were comptime. | 13464 | // Throw out our work and call the function as if it were comptime. |
| 13234 | return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto); | 13465 | return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, |
| 13466 | true, FnInlineAuto); | ||
| 13467 | case ReqCompTimeInvalid: | ||
| 13468 | return ira->codegen->invalid_instruction; | ||
| 13469 | case ReqCompTimeNo: | ||
| 13470 | break; | ||
| 13235 | } | 13471 | } |
| 13236 | } | 13472 | } |
| 13237 | IrInstruction *async_allocator_inst = nullptr; | 13473 | IrInstruction *async_allocator_inst = nullptr; |
| ... | @@ -13485,18 +13721,56 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | ... | @@ -13485,18 +13721,56 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13485 | return ErrorNone; | 13721 | return ErrorNone; |
| 13486 | } | 13722 | } |
| 13487 | 13723 | ||
| 13488 | if (dst_size > src_size) { | 13724 | if (dst_size <= src_size) { |
| 13489 | ir_add_error_node(ira, source_node, | 13725 | Buf buf = BUF_INIT; |
| 13490 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", | 13726 | buf_resize(&buf, src_size); |
| 13491 | dst_size, buf_ptr(&pointee->type->name), src_size)); | 13727 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); |
| 13492 | return ErrorSemanticAnalyzeFail; | 13728 | if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val))) |
| 13729 | return err; | ||
| 13730 | return ErrorNone; | ||
| 13493 | } | 13731 | } |
| 13494 | 13732 | ||
| 13495 | Buf buf = BUF_INIT; | 13733 | switch (ptr_val->data.x_ptr.special) { |
| 13496 | buf_resize(&buf, src_size); | 13734 | case ConstPtrSpecialInvalid: |
| 13497 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); | 13735 | zig_unreachable(); |
| 13498 | buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); | 13736 | case ConstPtrSpecialRef: { |
| 13499 | return ErrorNone; | 13737 | ir_add_error_node(ira, source_node, |
| 13738 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", | ||
| 13739 | dst_size, buf_ptr(&pointee->type->name), src_size)); | ||
| 13740 | return ErrorSemanticAnalyzeFail; | ||
| 13741 | } | ||
| 13742 | case ConstPtrSpecialBaseArray: { | ||
| 13743 | ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val; | ||
| 13744 | assert(array_val->type->id == ZigTypeIdArray); | ||
| 13745 | if (array_val->data.x_array.special != ConstArraySpecialNone) | ||
| 13746 | zig_panic("TODO"); | ||
| 13747 | size_t elem_size = src_size; | ||
| 13748 | size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index; | ||
| 13749 | src_size = elem_size * (array_val->type->data.array.len - elem_index); | ||
| 13750 | if (dst_size > src_size) { | ||
| 13751 | ir_add_error_node(ira, source_node, | ||
| 13752 | buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes", | ||
| 13753 | dst_size, buf_ptr(&array_val->type->name), elem_index, src_size)); | ||
| 13754 | return ErrorSemanticAnalyzeFail; | ||
| 13755 | } | ||
| 13756 | size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1); | ||
| 13757 | Buf buf = BUF_INIT; | ||
| 13758 | buf_resize(&buf, elem_count * elem_size); | ||
| 13759 | for (size_t i = 0; i < elem_count; i += 1) { | ||
| 13760 | ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; | ||
| 13761 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); | ||
| 13762 | } | ||
| 13763 | if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val))) | ||
| 13764 | return err; | ||
| 13765 | return ErrorNone; | ||
| 13766 | } | ||
| 13767 | case ConstPtrSpecialBaseStruct: | ||
| 13768 | case ConstPtrSpecialDiscard: | ||
| 13769 | case ConstPtrSpecialHardCodedAddr: | ||
| 13770 | case ConstPtrSpecialFunction: | ||
| 13771 | zig_panic("TODO"); | ||
| 13772 | } | ||
| 13773 | zig_unreachable(); | ||
| 13500 | } | 13774 | } |
| 13501 | 13775 | ||
| 13502 | static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | 13776 | static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| ... | @@ -14172,11 +14446,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -14172,11 +14446,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14172 | 14446 | ||
| 14173 | } else { | 14447 | } else { |
| 14174 | // runtime known element index | 14448 | // runtime known element index |
| 14175 | if (type_requires_comptime(return_type)) { | 14449 | switch (type_requires_comptime(ira->codegen, return_type)) { |
| 14450 | case ReqCompTimeYes: | ||
| 14176 | ir_add_error(ira, elem_index, | 14451 | ir_add_error(ira, elem_index, |
| 14177 | buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", | 14452 | buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", |
| 14178 | buf_ptr(&return_type->data.pointer.child_type->name))); | 14453 | buf_ptr(&return_type->data.pointer.child_type->name))); |
| 14179 | return ira->codegen->invalid_instruction; | 14454 | return ira->codegen->invalid_instruction; |
| 14455 | case ReqCompTimeInvalid: | ||
| 14456 | return ira->codegen->invalid_instruction; | ||
| 14457 | case ReqCompTimeNo: | ||
| 14458 | break; | ||
| 14180 | } | 14459 | } |
| 14181 | if (ptr_align < abi_align) { | 14460 | if (ptr_align < abi_align) { |
| 14182 | if (elem_size >= ptr_align && elem_size % ptr_align == 0) { | 14461 | if (elem_size >= ptr_align && elem_size % ptr_align == 0) { |
| ... | @@ -15233,9 +15512,19 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs | ... | @@ -15233,9 +15512,19 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs |
| 15233 | } | 15512 | } |
| 15234 | 15513 | ||
| 15235 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { | 15514 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { |
| 15236 | input_list[i] = asm_instruction->input_list[i]->child; | 15515 | IrInstruction *const input_value = asm_instruction->input_list[i]->child; |
| 15237 | if (type_is_invalid(input_list[i]->value.type)) | 15516 | if (type_is_invalid(input_value->value.type)) |
| 15238 | return ira->codegen->invalid_instruction; | 15517 | return ira->codegen->invalid_instruction; |
| 15518 | |||
| 15519 | if (instr_is_comptime(input_value) && | ||
| 15520 | (input_value->value.type->id == ZigTypeIdComptimeInt || | ||
| 15521 | input_value->value.type->id == ZigTypeIdComptimeFloat)) { | ||
| 15522 | ir_add_error_node(ira, input_value->source_node, | ||
| 15523 | buf_sprintf("expected sized integer or sized float, found %s", buf_ptr(&input_value->value.type->name))); | ||
| 15524 | return ira->codegen->invalid_instruction; | ||
| 15525 | } | ||
| 15526 | |||
| 15527 | input_list[i] = input_value; | ||
| 15239 | } | 15528 | } |
| 15240 | 15529 | ||
| 15241 | IrInstruction *result = ir_build_asm(&ira->new_irb, | 15530 | IrInstruction *result = ir_build_asm(&ira->new_irb, |
| ... | @@ -17850,6 +18139,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct | ... | @@ -17850,6 +18139,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct |
| 17850 | return ira->codegen->invalid_instruction; | 18139 | return ira->codegen->invalid_instruction; |
| 17851 | } | 18140 | } |
| 17852 | 18141 | ||
| 18142 | if (src_type->data.integral.bit_count == 0) { | ||
| 18143 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | ||
| 18144 | bigint_init_unsigned(&result->value.data.x_bigint, 0); | ||
| 18145 | return result; | ||
| 18146 | } | ||
| 18147 | |||
| 17853 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { | 18148 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { |
| 17854 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; | 18149 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; |
| 17855 | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); | 18150 | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); |
| ... | @@ -17878,7 +18173,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct | ... | @@ -17878,7 +18173,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct |
| 17878 | if (type_is_invalid(dest_type)) | 18173 | if (type_is_invalid(dest_type)) |
| 17879 | return ira->codegen->invalid_instruction; | 18174 | return ira->codegen->invalid_instruction; |
| 17880 | 18175 | ||
| 17881 | if (dest_type->id != ZigTypeIdInt) { | 18176 | if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) { |
| 17882 | ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); | 18177 | ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); |
| 17883 | return ira->codegen->invalid_instruction; | 18178 | return ira->codegen->invalid_instruction; |
| 17884 | } | 18179 | } |
| ... | @@ -17887,20 +18182,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct | ... | @@ -17887,20 +18182,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct |
| 17887 | if (type_is_invalid(target->value.type)) | 18182 | if (type_is_invalid(target->value.type)) |
| 17888 | return ira->codegen->invalid_instruction; | 18183 | return ira->codegen->invalid_instruction; |
| 17889 | 18184 | ||
| 17890 | if (target->value.type->id == ZigTypeIdComptimeInt) { | 18185 | if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) { |
| 17891 | if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) { | ||
| 17892 | return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpNumLitToConcrete, false); | ||
| 17893 | } else { | ||
| 17894 | return ira->codegen->invalid_instruction; | ||
| 17895 | } | ||
| 17896 | } | ||
| 17897 | |||
| 17898 | if (target->value.type->id != ZigTypeIdInt) { | ||
| 17899 | ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'", | 18186 | ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'", |
| 17900 | buf_ptr(&target->value.type->name))); | 18187 | buf_ptr(&target->value.type->name))); |
| 17901 | return ira->codegen->invalid_instruction; | 18188 | return ira->codegen->invalid_instruction; |
| 17902 | } | 18189 | } |
| 17903 | 18190 | ||
| 18191 | if (instr_is_comptime(target)) { | ||
| 18192 | return ir_implicit_cast(ira, target, dest_type); | ||
| 18193 | } | ||
| 18194 | |||
| 18195 | if (dest_type->id == ZigTypeIdComptimeInt) { | ||
| 18196 | ir_add_error(ira, instruction->target, buf_sprintf("attempt to cast runtime value to '%s'", | ||
| 18197 | buf_ptr(&dest_type->name))); | ||
| 18198 | return ira->codegen->invalid_instruction; | ||
| 18199 | } | ||
| 18200 | |||
| 17904 | return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type); | 18201 | return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type); |
| 17905 | } | 18202 | } |
| 17906 | 18203 | ||
| ... | @@ -19216,7 +19513,6 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, | ... | @@ -19216,7 +19513,6 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 19216 | } | 19513 | } |
| 19217 | 19514 | ||
| 19218 | static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { | 19515 | static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { |
| 19219 | Error err; | ||
| 19220 | AstNode *proto_node = instruction->base.source_node; | 19516 | AstNode *proto_node = instruction->base.source_node; |
| 19221 | assert(proto_node->type == NodeTypeFnProto); | 19517 | assert(proto_node->type == NodeTypeFnProto); |
| 19222 | 19518 | ||
| ... | @@ -19255,11 +19551,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct | ... | @@ -19255,11 +19551,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct |
| 19255 | if (type_is_invalid(param_type_value->value.type)) | 19551 | if (type_is_invalid(param_type_value->value.type)) |
| 19256 | return ira->codegen->invalid_instruction; | 19552 | return ira->codegen->invalid_instruction; |
| 19257 | ZigType *param_type = ir_resolve_type(ira, param_type_value); | 19553 | ZigType *param_type = ir_resolve_type(ira, param_type_value); |
| 19258 | if (type_is_invalid(param_type)) | 19554 | switch (type_requires_comptime(ira->codegen, param_type)) { |
| 19259 | return ira->codegen->invalid_instruction; | 19555 | case ReqCompTimeYes: |
| 19260 | if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown))) | ||
| 19261 | return ira->codegen->invalid_instruction; | ||
| 19262 | if (type_requires_comptime(param_type)) { | ||
| 19263 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { | 19556 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 19264 | ir_add_error(ira, param_type_value, | 19557 | ir_add_error(ira, param_type_value, |
| 19265 | buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", | 19558 | buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", |
| ... | @@ -19269,6 +19562,10 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct | ... | @@ -19269,6 +19562,10 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct |
| 19269 | param_info->type = param_type; | 19562 | param_info->type = param_type; |
| 19270 | fn_type_id.next_param_index += 1; | 19563 | fn_type_id.next_param_index += 1; |
| 19271 | return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); | 19564 | return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); |
| 19565 | case ReqCompTimeInvalid: | ||
| 19566 | return ira->codegen->invalid_instruction; | ||
| 19567 | case ReqCompTimeNo: | ||
| 19568 | break; | ||
| 19272 | } | 19569 | } |
| 19273 | if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { | 19570 | if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 19274 | ir_add_error(ira, param_type_value, | 19571 | ir_add_error(ira, param_type_value, |
| ... | @@ -19711,6 +20008,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct | ... | @@ -19711,6 +20008,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct |
| 19711 | } | 20008 | } |
| 19712 | 20009 | ||
| 19713 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { | 20010 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { |
| 20011 | if (val->special == ConstValSpecialUndef) | ||
| 20012 | val->special = ConstValSpecialStatic; | ||
| 19714 | assert(val->special == ConstValSpecialStatic); | 20013 | assert(val->special == ConstValSpecialStatic); |
| 19715 | switch (val->type->id) { | 20014 | switch (val->type->id) { |
| 19716 | case ZigTypeIdInvalid: | 20015 | case ZigTypeIdInvalid: |
| ... | @@ -19780,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -19780,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19780 | zig_unreachable(); | 20079 | zig_unreachable(); |
| 19781 | } | 20080 | } |
| 19782 | 20081 | ||
| 19783 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { | 20082 | static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { |
| 20083 | Error err; | ||
| 19784 | assert(val->special == ConstValSpecialStatic); | 20084 | assert(val->special == ConstValSpecialStatic); |
| 19785 | switch (val->type->id) { | 20085 | switch (val->type->id) { |
| 19786 | case ZigTypeIdInvalid: | 20086 | case ZigTypeIdInvalid: |
| ... | @@ -19797,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -19797,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19797 | case ZigTypeIdPromise: | 20097 | case ZigTypeIdPromise: |
| 19798 | zig_unreachable(); | 20098 | zig_unreachable(); |
| 19799 | case ZigTypeIdVoid: | 20099 | case ZigTypeIdVoid: |
| 19800 | return; | 20100 | return ErrorNone; |
| 19801 | case ZigTypeIdBool: | 20101 | case ZigTypeIdBool: |
| 19802 | val->data.x_bool = (buf[0] != 0); | 20102 | val->data.x_bool = (buf[0] != 0); |
| 19803 | return; | 20103 | return ErrorNone; |
| 19804 | case ZigTypeIdInt: | 20104 | case ZigTypeIdInt: |
| 19805 | bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, | 20105 | bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, |
| 19806 | codegen->is_big_endian, val->type->data.integral.is_signed); | 20106 | ira->codegen->is_big_endian, val->type->data.integral.is_signed); |
| 19807 | return; | 20107 | return ErrorNone; |
| 19808 | case ZigTypeIdFloat: | 20108 | case ZigTypeIdFloat: |
| 19809 | float_read_ieee597(val, buf, codegen->is_big_endian); | 20109 | float_read_ieee597(val, buf, ira->codegen->is_big_endian); |
| 19810 | return; | 20110 | return ErrorNone; |
| 19811 | case ZigTypeIdPointer: | 20111 | case ZigTypeIdPointer: |
| 19812 | { | 20112 | { |
| 19813 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 20113 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 19814 | BigInt bn; | 20114 | BigInt bn; |
| 19815 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, | 20115 | bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count, |
| 19816 | codegen->is_big_endian, false); | 20116 | ira->codegen->is_big_endian, false); |
| 19817 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); | 20117 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); |
| 19818 | return; | 20118 | return ErrorNone; |
| 19819 | } | 20119 | } |
| 19820 | case ZigTypeIdArray: | 20120 | case ZigTypeIdArray: |
| 19821 | zig_panic("TODO buf_read_value_bytes array type"); | 20121 | zig_panic("TODO buf_read_value_bytes array type"); |
| 19822 | case ZigTypeIdStruct: | 20122 | case ZigTypeIdStruct: |
| 19823 | zig_panic("TODO buf_read_value_bytes struct type"); | 20123 | switch (val->type->data.structure.layout) { |
| 20124 | case ContainerLayoutAuto: { | ||
| 20125 | ErrorMsg *msg = ir_add_error_node(ira, source_node, | ||
| 20126 | buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted", | ||
| 20127 | buf_ptr(&val->type->name))); | ||
| 20128 | add_error_note(ira->codegen, msg, val->type->data.structure.decl_node, | ||
| 20129 | buf_sprintf("declared here")); | ||
| 20130 | return ErrorSemanticAnalyzeFail; | ||
| 20131 | } | ||
| 20132 | case ContainerLayoutExtern: { | ||
| 20133 | size_t src_field_count = val->type->data.structure.src_field_count; | ||
| 20134 | val->data.x_struct.fields = create_const_vals(src_field_count); | ||
| 20135 | for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { | ||
| 20136 | ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; | ||
| 20137 | field_val->special = ConstValSpecialStatic; | ||
| 20138 | TypeStructField *type_field = &val->type->data.structure.fields[field_i]; | ||
| 20139 | field_val->type = type_field->type_entry; | ||
| 20140 | if (type_field->gen_index == SIZE_MAX) | ||
| 20141 | continue; | ||
| 20142 | size_t offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, val->type->type_ref, | ||
| 20143 | type_field->gen_index); | ||
| 20144 | uint8_t *new_buf = buf + offset; | ||
| 20145 | if ((err = buf_read_value_bytes(ira, source_node, new_buf, field_val))) | ||
| 20146 | return err; | ||
| 20147 | } | ||
| 20148 | return ErrorNone; | ||
| 20149 | } | ||
| 20150 | case ContainerLayoutPacked: | ||
| 20151 | zig_panic("TODO buf_read_value_bytes packed struct"); | ||
| 20152 | } | ||
| 20153 | zig_unreachable(); | ||
| 19824 | case ZigTypeIdOptional: | 20154 | case ZigTypeIdOptional: |
| 19825 | zig_panic("TODO buf_read_value_bytes maybe type"); | 20155 | zig_panic("TODO buf_read_value_bytes maybe type"); |
| 19826 | case ZigTypeIdErrorUnion: | 20156 | case ZigTypeIdErrorUnion: |
| ... | @@ -19923,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct | ... | @@ -19923,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 19923 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | 20253 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); |
| 19924 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); | 20254 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); |
| 19925 | buf_write_value_bytes(ira->codegen, buf, val); | 20255 | buf_write_value_bytes(ira->codegen, buf, val); |
| 19926 | buf_read_value_bytes(ira->codegen, buf, &result->value); | 20256 | if ((err = buf_read_value_bytes(ira, instruction->base.source_node, buf, &result->value))) |
| 20257 | return ira->codegen->invalid_instruction; | ||
| 19927 | return result; | 20258 | return result; |
| 19928 | } | 20259 | } |
| 19929 | 20260 | ||
| ... | @@ -20093,6 +20424,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct | ... | @@ -20093,6 +20424,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct |
| 20093 | return ira->codegen->invalid_instruction; | 20424 | return ira->codegen->invalid_instruction; |
| 20094 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) | 20425 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) |
| 20095 | return ira->codegen->invalid_instruction; | 20426 | return ira->codegen->invalid_instruction; |
| 20427 | if (!type_has_bits(child_type)) { | ||
| 20428 | align_bytes = 0; | ||
| 20429 | } | ||
| 20096 | } else { | 20430 | } else { |
| 20097 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) | 20431 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) |
| 20098 | return ira->codegen->invalid_instruction; | 20432 | return ira->codegen->invalid_instruction; |
| ... | @@ -20692,6 +21026,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS | ... | @@ -20692,6 +21026,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS |
| 20692 | return result; | 21026 | return result; |
| 20693 | } | 21027 | } |
| 20694 | 21028 | ||
| 21029 | static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { | ||
| 21030 | ZigType *int_type = ir_resolve_type(ira, instruction->type->child); | ||
| 21031 | if (type_is_invalid(int_type)) | ||
| 21032 | return ira->codegen->invalid_instruction; | ||
| 21033 | |||
| 21034 | IrInstruction *op = instruction->op->child; | ||
| 21035 | if (type_is_invalid(op->value.type)) | ||
| 21036 | return ira->codegen->invalid_instruction; | ||
| 21037 | |||
| 21038 | if (int_type->id != ZigTypeIdInt) { | ||
| 21039 | ir_add_error(ira, instruction->type, | ||
| 21040 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); | ||
| 21041 | return ira->codegen->invalid_instruction; | ||
| 21042 | } | ||
| 21043 | |||
| 21044 | if (int_type->data.integral.bit_count % 8 != 0) { | ||
| 21045 | ir_add_error(ira, instruction->type, | ||
| 21046 | buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", | ||
| 21047 | buf_ptr(&int_type->name), int_type->data.integral.bit_count)); | ||
| 21048 | return ira->codegen->invalid_instruction; | ||
| 21049 | } | ||
| 21050 | |||
| 21051 | IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); | ||
| 21052 | if (type_is_invalid(casted_op->value.type)) | ||
| 21053 | return ira->codegen->invalid_instruction; | ||
| 21054 | |||
| 21055 | if (int_type->data.integral.bit_count == 0) { | ||
| 21056 | IrInstruction *result = ir_const(ira, &instruction->base, int_type); | ||
| 21057 | bigint_init_unsigned(&result->value.data.x_bigint, 0); | ||
| 21058 | return result; | ||
| 21059 | } | ||
| 21060 | |||
| 21061 | if (int_type->data.integral.bit_count == 8) { | ||
| 21062 | return casted_op; | ||
| 21063 | } | ||
| 21064 | |||
| 21065 | if (instr_is_comptime(casted_op)) { | ||
| 21066 | ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); | ||
| 21067 | if (!val) | ||
| 21068 | return ira->codegen->invalid_instruction; | ||
| 21069 | |||
| 21070 | IrInstruction *result = ir_const(ira, &instruction->base, int_type); | ||
| 21071 | size_t buf_size = int_type->data.integral.bit_count / 8; | ||
| 21072 | uint8_t *buf = allocate_nonzero<uint8_t>(buf_size); | ||
| 21073 | bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true); | ||
| 21074 | bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false, | ||
| 21075 | int_type->data.integral.is_signed); | ||
| 21076 | return result; | ||
| 21077 | } | ||
| 21078 | |||
| 21079 | IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, | ||
| 21080 | instruction->base.source_node, nullptr, casted_op); | ||
| 21081 | result->value.type = int_type; | ||
| 21082 | return result; | ||
| 21083 | } | ||
| 21084 | |||
| 21085 | |||
| 20695 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { | 21086 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { |
| 20696 | Error err; | 21087 | Error err; |
| 20697 | IrInstruction *target = instruction->target->child; | 21088 | IrInstruction *target = instruction->target->child; |
| ... | @@ -21027,6 +21418,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -21027,6 +21418,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21027 | return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); | 21418 | return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); |
| 21028 | case IrInstructionIdSqrt: | 21419 | case IrInstructionIdSqrt: |
| 21029 | return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); | 21420 | return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); |
| 21421 | case IrInstructionIdBswap: | ||
| 21422 | return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); | ||
| 21030 | case IrInstructionIdIntToErr: | 21423 | case IrInstructionIdIntToErr: |
| 21031 | return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); | 21424 | return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); |
| 21032 | case IrInstructionIdErrToInt: | 21425 | case IrInstructionIdErrToInt: |
| ... | @@ -21063,6 +21456,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ | ... | @@ -21063,6 +21456,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ |
| 21063 | ZigFn *fn_entry = exec_fn_entry(old_exec); | 21456 | ZigFn *fn_entry = exec_fn_entry(old_exec); |
| 21064 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | 21457 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 21065 | ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type; | 21458 | ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type; |
| 21459 | ira->explicit_return_type_source_node = expected_type_source_node; | ||
| 21066 | 21460 | ||
| 21067 | ira->old_irb.codegen = codegen; | 21461 | ira->old_irb.codegen = codegen; |
| 21068 | ira->old_irb.exec = old_exec; | 21462 | ira->old_irb.exec = old_exec; |
| ... | @@ -21247,6 +21641,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -21247,6 +21641,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21247 | case IrInstructionIdCoroPromise: | 21641 | case IrInstructionIdCoroPromise: |
| 21248 | case IrInstructionIdPromiseResultType: | 21642 | case IrInstructionIdPromiseResultType: |
| 21249 | case IrInstructionIdSqrt: | 21643 | case IrInstructionIdSqrt: |
| 21644 | case IrInstructionIdBswap: | ||
| 21250 | case IrInstructionIdAtomicLoad: | 21645 | case IrInstructionIdAtomicLoad: |
| 21251 | case IrInstructionIdIntCast: | 21646 | case IrInstructionIdIntCast: |
| 21252 | case IrInstructionIdFloatCast: | 21647 | case IrInstructionIdFloatCast: |
src/ir_print.cpp+15| ... | @@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { | ... | @@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { |
| 1323 | fprintf(irp->f, ")"); | 1323 | fprintf(irp->f, ")"); |
| 1324 | } | 1324 | } |
| 1325 | 1325 | ||
| 1326 | static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { | ||
| 1327 | fprintf(irp->f, "@bswap("); | ||
| 1328 | if (instruction->type != nullptr) { | ||
| 1329 | ir_print_other_instruction(irp, instruction->type); | ||
| 1330 | } else { | ||
| 1331 | fprintf(irp->f, "null"); | ||
| 1332 | } | ||
| 1333 | fprintf(irp->f, ","); | ||
| 1334 | ir_print_other_instruction(irp, instruction->op); | ||
| 1335 | fprintf(irp->f, ")"); | ||
| 1336 | } | ||
| 1337 | |||
| 1326 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1338 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1327 | ir_print_prefix(irp, instruction); | 1339 | ir_print_prefix(irp, instruction); |
| 1328 | switch (instruction->id) { | 1340 | switch (instruction->id) { |
| ... | @@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1736 | case IrInstructionIdSqrt: | 1748 | case IrInstructionIdSqrt: |
| 1737 | ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); | 1749 | ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); |
| 1738 | break; | 1750 | break; |
| 1751 | case IrInstructionIdBswap: | ||
| 1752 | ir_print_bswap(irp, (IrInstructionBswap *)instruction); | ||
| 1753 | break; | ||
| 1739 | case IrInstructionIdAtomicLoad: | 1754 | case IrInstructionIdAtomicLoad: |
| 1740 | ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); | 1755 | ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); |
| 1741 | break; | 1756 | break; |
src/link.cpp+7| ... | @@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) { | ... | @@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) { |
| 150 | if (t->env_type == ZigLLVM_GNUX32) { | 150 | if (t->env_type == ZigLLVM_GNUX32) { |
| 151 | return "elf32_x86_64"; | 151 | return "elf32_x86_64"; |
| 152 | } | 152 | } |
| 153 | // Any target elf will use the freebsd osabi if suffixed with "_fbsd". | ||
| 154 | if (t->os == OsFreeBSD) { | ||
| 155 | return "elf_x86_64_fbsd"; | ||
| 156 | } | ||
| 153 | return "elf_x86_64"; | 157 | return "elf_x86_64"; |
| 154 | default: | 158 | default: |
| 155 | zig_unreachable(); | 159 | zig_unreachable(); |
| ... | @@ -191,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) { | ... | @@ -191,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) { |
| 191 | } | 195 | } |
| 192 | 196 | ||
| 193 | static Buf *get_dynamic_linker_path(CodeGen *g) { | 197 | static Buf *get_dynamic_linker_path(CodeGen *g) { |
| 198 | if (g->zig_target.os == OsFreeBSD) { | ||
| 199 | return buf_create_from_str("/libexec/ld-elf.so.1"); | ||
| 200 | } | ||
| 194 | if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) { | 201 | if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) { |
| 195 | static const char *ld_names[] = { | 202 | static const char *ld_names[] = { |
| 196 | "ld-linux-x86-64.so.2", | 203 | "ld-linux-x86-64.so.2", |
src/main.cpp+1-8| ... | @@ -466,16 +466,9 @@ int main(int argc, char **argv) { | ... | @@ -466,16 +466,9 @@ int main(int argc, char **argv) { |
| 466 | "\n" | 466 | "\n" |
| 467 | "General Options:\n" | 467 | "General Options:\n" |
| 468 | " --help Print this help and exit\n" | 468 | " --help Print this help and exit\n" |
| 469 | " --build-file [file] Override path to build.zig\n" | ||
| 470 | " --cache-dir [path] Override path to cache directory\n" | ||
| 471 | " --verbose Print commands before executing them\n" | 469 | " --verbose Print commands before executing them\n" |
| 472 | " --verbose-tokenize Enable compiler debug output for tokenization\n" | ||
| 473 | " --verbose-ast Enable compiler debug output for parsing into an AST\n" | ||
| 474 | " --verbose-link Enable compiler debug output for linking\n" | ||
| 475 | " --verbose-ir Enable compiler debug output for Zig IR\n" | ||
| 476 | " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n" | ||
| 477 | " --verbose-cimport Enable compiler debug output for C imports\n" | ||
| 478 | " --prefix [path] Override default install prefix\n" | 470 | " --prefix [path] Override default install prefix\n" |
| 471 | " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" | ||
| 479 | "\n" | 472 | "\n" |
| 480 | "Project-specific options become available when the build file is found.\n" | 473 | "Project-specific options become available when the build file is found.\n" |
| 481 | "\n" | 474 | "\n" |
src/os.cpp+29-9| ... | @@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t; | ... | @@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t; |
| 50 | 50 | ||
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | #if defined(ZIG_OS_LINUX) | 53 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) |
| 54 | #include <link.h> | 54 | #include <link.h> |
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | #if defined(ZIG_OS_FREEBSD) | ||
| 58 | #include <sys/sysctl.h> | ||
| 59 | #endif | ||
| 57 | 60 | ||
| 58 | #if defined(__MACH__) | 61 | #if defined(__MACH__) |
| 59 | #include <mach/clock.h> | 62 | #include <mach/clock.h> |
| ... | @@ -75,7 +78,9 @@ static clock_serv_t cclock; | ... | @@ -75,7 +78,9 @@ static clock_serv_t cclock; |
| 75 | #if defined(__APPLE__) && !defined(environ) | 78 | #if defined(__APPLE__) && !defined(environ) |
| 76 | #include <crt_externs.h> | 79 | #include <crt_externs.h> |
| 77 | #define environ (*_NSGetEnviron()) | 80 | #define environ (*_NSGetEnviron()) |
| 78 | #endif | 81 | #elif defined(ZIG_OS_FREEBSD) |
| 82 | extern char **environ; | ||
| 83 | #endif | ||
| 79 | 84 | ||
| 80 | #if defined(ZIG_OS_POSIX) | 85 | #if defined(ZIG_OS_POSIX) |
| 81 | static void populate_termination(Termination *term, int status) { | 86 | static void populate_termination(Termination *term, int status) { |
| ... | @@ -188,14 +193,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) { | ... | @@ -188,14 +193,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) { |
| 188 | size_t len = buf_len(full_path); | 193 | size_t len = buf_len(full_path); |
| 189 | if (len != 0) { | 194 | if (len != 0) { |
| 190 | size_t last_index = len - 1; | 195 | size_t last_index = len - 1; |
| 191 | if (os_is_sep(buf_ptr(full_path)[last_index])) { | 196 | char last_char = buf_ptr(full_path)[last_index]; |
| 197 | if (os_is_sep(last_char)) { | ||
| 198 | if (last_index == 0) { | ||
| 199 | if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1); | ||
| 200 | if (out_basename) buf_init_from_str(out_basename, ""); | ||
| 201 | return; | ||
| 202 | } | ||
| 192 | last_index -= 1; | 203 | last_index -= 1; |
| 193 | } | 204 | } |
| 194 | for (size_t i = last_index;;) { | 205 | for (size_t i = last_index;;) { |
| 195 | uint8_t c = buf_ptr(full_path)[i]; | 206 | uint8_t c = buf_ptr(full_path)[i]; |
| 196 | if (os_is_sep(c)) { | 207 | if (os_is_sep(c)) { |
| 197 | if (out_dirname) { | 208 | if (out_dirname) { |
| 198 | buf_init_from_mem(out_dirname, buf_ptr(full_path), i); | 209 | buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i); |
| 199 | } | 210 | } |
| 200 | if (out_basename) { | 211 | if (out_basename) { |
| 201 | buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1)); | 212 | buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1)); |
| ... | @@ -1438,6 +1449,15 @@ Error os_self_exe_path(Buf *out_path) { | ... | @@ -1438,6 +1449,15 @@ Error os_self_exe_path(Buf *out_path) { |
| 1438 | } | 1449 | } |
| 1439 | buf_resize(out_path, amt); | 1450 | buf_resize(out_path, amt); |
| 1440 | return ErrorNone; | 1451 | return ErrorNone; |
| 1452 | #elif defined(ZIG_OS_FREEBSD) | ||
| 1453 | buf_resize(out_path, PATH_MAX); | ||
| 1454 | int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; | ||
| 1455 | size_t cb = PATH_MAX; | ||
| 1456 | if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { | ||
| 1457 | return ErrorUnexpected; | ||
| 1458 | } | ||
| 1459 | buf_resize(out_path, cb - 1); | ||
| 1460 | return ErrorNone; | ||
| 1441 | #endif | 1461 | #endif |
| 1442 | return ErrorFileNotFound; | 1462 | return ErrorFileNotFound; |
| 1443 | } | 1463 | } |
| ... | @@ -1743,7 +1763,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { | ... | @@ -1743,7 +1763,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { |
| 1743 | buf_resize(out_path, 0); | 1763 | buf_resize(out_path, 0); |
| 1744 | buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname); | 1764 | buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname); |
| 1745 | return ErrorNone; | 1765 | return ErrorNone; |
| 1746 | #elif defined(ZIG_OS_LINUX) | 1766 | #elif defined(ZIG_OS_POSIX) |
| 1747 | const char *home_dir = getenv("HOME"); | 1767 | const char *home_dir = getenv("HOME"); |
| 1748 | if (home_dir == nullptr) { | 1768 | if (home_dir == nullptr) { |
| 1749 | // TODO use /etc/passwd | 1769 | // TODO use /etc/passwd |
| ... | @@ -1756,7 +1776,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { | ... | @@ -1756,7 +1776,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { |
| 1756 | } | 1776 | } |
| 1757 | 1777 | ||
| 1758 | 1778 | ||
| 1759 | #if defined(ZIG_OS_LINUX) | 1779 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) |
| 1760 | static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) { | 1780 | static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) { |
| 1761 | ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data); | 1781 | ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data); |
| 1762 | if (info->dlpi_name[0] == '/') { | 1782 | if (info->dlpi_name[0] == '/') { |
| ... | @@ -1767,7 +1787,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, | ... | @@ -1767,7 +1787,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, |
| 1767 | #endif | 1787 | #endif |
| 1768 | 1788 | ||
| 1769 | Error os_self_exe_shared_libs(ZigList<Buf *> &paths) { | 1789 | Error os_self_exe_shared_libs(ZigList<Buf *> &paths) { |
| 1770 | #if defined(ZIG_OS_LINUX) | 1790 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) |
| 1771 | paths.resize(0); | 1791 | paths.resize(0); |
| 1772 | dl_iterate_phdr(self_exe_shared_libs_callback, &paths); | 1792 | dl_iterate_phdr(self_exe_shared_libs_callback, &paths); |
| 1773 | return ErrorNone; | 1793 | return ErrorNone; |
| ... | @@ -1936,7 +1956,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) { | ... | @@ -1936,7 +1956,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) { |
| 1936 | mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; | 1956 | mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; |
| 1937 | mtime->nsec = 0; | 1957 | mtime->nsec = 0; |
| 1938 | return ErrorNone; | 1958 | return ErrorNone; |
| 1939 | #elif defined(ZIG_OS_LINUX) | 1959 | #elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) |
| 1940 | struct stat statbuf; | 1960 | struct stat statbuf; |
| 1941 | if (fstat(file, &statbuf) == -1) | 1961 | if (fstat(file, &statbuf) == -1) |
| 1942 | return ErrorFileSystem; | 1962 | return ErrorFileSystem; |
| ... | @@ -1976,7 +1996,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) { | ... | @@ -1976,7 +1996,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) { |
| 1976 | case EFAULT: | 1996 | case EFAULT: |
| 1977 | zig_unreachable(); | 1997 | zig_unreachable(); |
| 1978 | case EISDIR: | 1998 | case EISDIR: |
| 1979 | zig_unreachable(); | 1999 | return ErrorIsDir; |
| 1980 | default: | 2000 | default: |
| 1981 | return ErrorFileSystem; | 2001 | return ErrorFileSystem; |
| 1982 | } | 2002 | } |
src/os.hpp+2| ... | @@ -23,6 +23,8 @@ | ... | @@ -23,6 +23,8 @@ |
| 23 | #define ZIG_OS_WINDOWS | 23 | #define ZIG_OS_WINDOWS |
| 24 | #elif defined(__linux__) | 24 | #elif defined(__linux__) |
| 25 | #define ZIG_OS_LINUX | 25 | #define ZIG_OS_LINUX |
| 26 | #elif defined(__FreeBSD__) | ||
| 27 | #define ZIG_OS_FREEBSD | ||
| 26 | #else | 28 | #else |
| 27 | #define ZIG_OS_UNKNOWN | 29 | #define ZIG_OS_UNKNOWN |
| 28 | #endif | 30 | #endif |
src/parser.cpp+13-13| ... | @@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc); | ... | @@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc); |
| 91 | static Token *ast_parse_block_label(ParseContext *pc); | 91 | static Token *ast_parse_block_label(ParseContext *pc); |
| 92 | static AstNode *ast_parse_field_init(ParseContext *pc); | 92 | static AstNode *ast_parse_field_init(ParseContext *pc); |
| 93 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc); | 93 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc); |
| 94 | static AstNode *ast_parse_section(ParseContext *pc); | 94 | static AstNode *ast_parse_link_section(ParseContext *pc); |
| 95 | static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc); | 95 | static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc); |
| 96 | static AstNode *ast_parse_param_decl(ParseContext *pc); | 96 | static AstNode *ast_parse_param_decl(ParseContext *pc); |
| 97 | static AstNode *ast_parse_param_type(ParseContext *pc); | 97 | static AstNode *ast_parse_param_type(ParseContext *pc); |
| ... | @@ -775,7 +775,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { | ... | @@ -775,7 +775,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 775 | return nullptr; | 775 | return nullptr; |
| 776 | } | 776 | } |
| 777 | 777 | ||
| 778 | // FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? Section? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) | 778 | // FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) |
| 779 | static AstNode *ast_parse_fn_proto(ParseContext *pc) { | 779 | static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 780 | Token *first = peek_token(pc); | 780 | Token *first = peek_token(pc); |
| 781 | AstNodeFnProto fn_cc; | 781 | AstNodeFnProto fn_cc; |
| ... | @@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { | ... | @@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 806 | expect_token(pc, TokenIdRParen); | 806 | expect_token(pc, TokenIdRParen); |
| 807 | 807 | ||
| 808 | AstNode *align_expr = ast_parse_byte_align(pc); | 808 | AstNode *align_expr = ast_parse_byte_align(pc); |
| 809 | AstNode *section_expr = ast_parse_section(pc); | 809 | AstNode *section_expr = ast_parse_link_section(pc); |
| 810 | Token *var = eat_token_if(pc, TokenIdKeywordVar); | 810 | Token *var = eat_token_if(pc, TokenIdKeywordVar); |
| 811 | Token *exmark = nullptr; | 811 | Token *exmark = nullptr; |
| 812 | AstNode *return_type = nullptr; | 812 | AstNode *return_type = nullptr; |
| ... | @@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { | ... | @@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 842 | return res; | 842 | return res; |
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? Section? (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 *first = eat_token_if(pc, TokenIdKeywordConst); |
| 848 | if (first == nullptr) | 848 | if (first == nullptr) |
| ... | @@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { | ... | @@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 856 | type_expr = ast_expect(pc, ast_parse_type_expr); | 856 | type_expr = ast_expect(pc, ast_parse_type_expr); |
| 857 | 857 | ||
| 858 | AstNode *align_expr = ast_parse_byte_align(pc); | 858 | AstNode *align_expr = ast_parse_byte_align(pc); |
| 859 | AstNode *section_expr = ast_parse_section(pc); | 859 | AstNode *section_expr = ast_parse_link_section(pc); |
| 860 | AstNode *expr = nullptr; | 860 | AstNode *expr = nullptr; |
| 861 | if (eat_token_if(pc, TokenIdEq) != nullptr) | 861 | if (eat_token_if(pc, TokenIdEq) != nullptr) |
| 862 | expr = ast_expect(pc, ast_parse_expr); | 862 | expr = ast_expect(pc, ast_parse_expr); |
| ... | @@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { | ... | @@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | // SuffixExpr | 1492 | // SuffixExpr |
| 1493 | // <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets | 1493 | // <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments |
| 1494 | // / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)* | 1494 | // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* |
| 1495 | static AstNode *ast_parse_suffix_expr(ParseContext *pc) { | 1495 | static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1496 | AstNode *async_call = ast_parse_async_prefix(pc); | 1496 | AstNode *async_call = ast_parse_async_prefix(pc); |
| 1497 | if (async_call != nullptr) { | 1497 | if (async_call != nullptr) { |
| ... | @@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { | ... | @@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1599 | } | 1599 | } |
| 1600 | 1600 | ||
| 1601 | // PrimaryTypeExpr | 1601 | // PrimaryTypeExpr |
| 1602 | // <- BUILTININDENTIFIER FnCallArgumnets | 1602 | // <- BUILTINIDENTIFIER FnCallArguments |
| 1603 | // / CHAR_LITERAL | 1603 | // / CHAR_LITERAL |
| 1604 | // / ContainerDecl | 1604 | // / ContainerDecl |
| 1605 | // / ErrorSetDecl | 1605 | // / ErrorSetDecl |
| ... | @@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { | ... | @@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { |
| 1978 | return res; | 1978 | return res; |
| 1979 | } | 1979 | } |
| 1980 | 1980 | ||
| 1981 | // AsmInput <- COLON AsmInputList AsmCloppers? | 1981 | // AsmInput <- COLON AsmInputList AsmClobbers? |
| 1982 | static AstNode *ast_parse_asm_input(ParseContext *pc) { | 1982 | static AstNode *ast_parse_asm_input(ParseContext *pc) { |
| 1983 | if (eat_token_if(pc, TokenIdColon) == nullptr) | 1983 | if (eat_token_if(pc, TokenIdColon) == nullptr) |
| 1984 | return nullptr; | 1984 | return nullptr; |
| ... | @@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { | ... | @@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { |
| 2011 | return res; | 2011 | return res; |
| 2012 | } | 2012 | } |
| 2013 | 2013 | ||
| 2014 | // AsmCloppers <- COLON StringList | 2014 | // AsmClobbers <- COLON StringList |
| 2015 | static AstNode *ast_parse_asm_cloppers(ParseContext *pc) { | 2015 | static AstNode *ast_parse_asm_cloppers(ParseContext *pc) { |
| 2016 | if (eat_token_if(pc, TokenIdColon) == nullptr) | 2016 | if (eat_token_if(pc, TokenIdColon) == nullptr) |
| 2017 | return nullptr; | 2017 | return nullptr; |
| ... | @@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { | ... | @@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { |
| 2080 | return expr; | 2080 | return expr; |
| 2081 | } | 2081 | } |
| 2082 | 2082 | ||
| 2083 | // Section <- KEYWORD_section LPAREN Expr RPAREN | 2083 | // LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN |
| 2084 | static AstNode *ast_parse_section(ParseContext *pc) { | 2084 | static AstNode *ast_parse_link_section(ParseContext *pc) { |
| 2085 | Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); | 2085 | Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); |
| 2086 | if (first == nullptr) | 2086 | if (first == nullptr) |
| 2087 | return nullptr; | 2087 | return nullptr; |
| ... | @@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) { | ... | @@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) { |
| 2742 | return res; | 2742 | return res; |
| 2743 | } | 2743 | } |
| 2744 | 2744 | ||
| 2745 | // FnCallArgumnets <- LPAREN ExprList RPAREN | 2745 | // FnCallArguments <- LPAREN ExprList RPAREN |
| 2746 | static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { | 2746 | static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { |
| 2747 | Token *paren = eat_token_if(pc, TokenIdLParen); | 2747 | Token *paren = eat_token_if(pc, TokenIdLParen); |
| 2748 | if (paren == nullptr) | 2748 | if (paren == nullptr) |
src/target.cpp+62-1| ... | @@ -754,6 +754,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { | ... | @@ -754,6 +754,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 754 | case OsLinux: | 754 | case OsLinux: |
| 755 | case OsMacOSX: | 755 | case OsMacOSX: |
| 756 | case OsZen: | 756 | case OsZen: |
| 757 | case OsFreeBSD: | ||
| 757 | case OsOpenBSD: | 758 | case OsOpenBSD: |
| 758 | switch (id) { | 759 | switch (id) { |
| 759 | case CIntTypeShort: | 760 | case CIntTypeShort: |
| ... | @@ -790,7 +791,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { | ... | @@ -790,7 +791,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 790 | case OsAnanas: | 791 | case OsAnanas: |
| 791 | case OsCloudABI: | 792 | case OsCloudABI: |
| 792 | case OsDragonFly: | 793 | case OsDragonFly: |
| 793 | case OsFreeBSD: | ||
| 794 | case OsIOS: | 794 | case OsIOS: |
| 795 | case OsKFreeBSD: | 795 | case OsKFreeBSD: |
| 796 | case OsLv2: | 796 | case OsLv2: |
| ... | @@ -1028,3 +1028,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) { | ... | @@ -1028,3 +1028,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) { |
| 1028 | } | 1028 | } |
| 1029 | zig_unreachable(); | 1029 | zig_unreachable(); |
| 1030 | } | 1030 | } |
| 1031 | |||
| 1032 | bool target_is_arm(const ZigTarget *target) { | ||
| 1033 | switch (target->arch.arch) { | ||
| 1034 | case ZigLLVM_UnknownArch: | ||
| 1035 | zig_unreachable(); | ||
| 1036 | case ZigLLVM_aarch64: | ||
| 1037 | case ZigLLVM_arm: | ||
| 1038 | case ZigLLVM_thumb: | ||
| 1039 | case ZigLLVM_aarch64_be: | ||
| 1040 | case ZigLLVM_armeb: | ||
| 1041 | case ZigLLVM_thumbeb: | ||
| 1042 | return true; | ||
| 1043 | |||
| 1044 | case ZigLLVM_x86: | ||
| 1045 | case ZigLLVM_x86_64: | ||
| 1046 | case ZigLLVM_amdgcn: | ||
| 1047 | case ZigLLVM_amdil: | ||
| 1048 | case ZigLLVM_amdil64: | ||
| 1049 | case ZigLLVM_arc: | ||
| 1050 | case ZigLLVM_avr: | ||
| 1051 | case ZigLLVM_bpfeb: | ||
| 1052 | case ZigLLVM_bpfel: | ||
| 1053 | case ZigLLVM_hexagon: | ||
| 1054 | case ZigLLVM_lanai: | ||
| 1055 | case ZigLLVM_hsail: | ||
| 1056 | case ZigLLVM_hsail64: | ||
| 1057 | case ZigLLVM_kalimba: | ||
| 1058 | case ZigLLVM_le32: | ||
| 1059 | case ZigLLVM_le64: | ||
| 1060 | case ZigLLVM_mips: | ||
| 1061 | case ZigLLVM_mips64: | ||
| 1062 | case ZigLLVM_mips64el: | ||
| 1063 | case ZigLLVM_mipsel: | ||
| 1064 | case ZigLLVM_msp430: | ||
| 1065 | case ZigLLVM_nios2: | ||
| 1066 | case ZigLLVM_nvptx: | ||
| 1067 | case ZigLLVM_nvptx64: | ||
| 1068 | case ZigLLVM_ppc64le: | ||
| 1069 | case ZigLLVM_r600: | ||
| 1070 | case ZigLLVM_renderscript32: | ||
| 1071 | case ZigLLVM_renderscript64: | ||
| 1072 | case ZigLLVM_riscv32: | ||
| 1073 | case ZigLLVM_riscv64: | ||
| 1074 | case ZigLLVM_shave: | ||
| 1075 | case ZigLLVM_sparc: | ||
| 1076 | case ZigLLVM_sparcel: | ||
| 1077 | case ZigLLVM_sparcv9: | ||
| 1078 | case ZigLLVM_spir: | ||
| 1079 | case ZigLLVM_spir64: | ||
| 1080 | case ZigLLVM_systemz: | ||
| 1081 | case ZigLLVM_tce: | ||
| 1082 | case ZigLLVM_tcele: | ||
| 1083 | case ZigLLVM_wasm32: | ||
| 1084 | case ZigLLVM_wasm64: | ||
| 1085 | case ZigLLVM_xcore: | ||
| 1086 | case ZigLLVM_ppc: | ||
| 1087 | case ZigLLVM_ppc64: | ||
| 1088 | return false; | ||
| 1089 | } | ||
| 1090 | zig_unreachable(); | ||
| 1091 | } |
src/target.hpp+2| ... | @@ -122,4 +122,6 @@ Buf *target_dynamic_linker(ZigTarget *target); | ... | @@ -122,4 +122,6 @@ Buf *target_dynamic_linker(ZigTarget *target); |
| 122 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); | 122 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); |
| 123 | ZigLLVM_OSType get_llvm_os_type(Os os_type); | 123 | ZigLLVM_OSType get_llvm_os_type(Os os_type); |
| 124 | 124 | ||
| 125 | bool target_is_arm(const ZigTarget *target); | ||
| 126 | |||
| 125 | #endif | 127 | #endif |
src/translate_c.cpp+8| ... | @@ -4784,6 +4784,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4784,6 +4784,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4784 | 4784 | ||
| 4785 | clang_argv.append(target_file); | 4785 | clang_argv.append(target_file); |
| 4786 | 4786 | ||
| 4787 | if (codegen->verbose_cimport) { | ||
| 4788 | fprintf(stderr, "clang"); | ||
| 4789 | for (size_t i = 0; i < clang_argv.length; i += 1) { | ||
| 4790 | fprintf(stderr, " %s", clang_argv.at(i)); | ||
| 4791 | } | ||
| 4792 | fprintf(stderr, "\n"); | ||
| 4793 | } | ||
| 4794 | |||
| 4787 | // to make the [start...end] argument work | 4795 | // to make the [start...end] argument work |
| 4788 | clang_argv.append(nullptr); | 4796 | clang_argv.append(nullptr); |
| 4789 | 4797 |
src/util.hpp+11| ... | @@ -158,6 +158,17 @@ static inline bool is_power_of_2(uint64_t x) { | ... | @@ -158,6 +158,17 @@ static inline bool is_power_of_2(uint64_t x) { |
| 158 | return x != 0 && ((x & (~x + 1)) == x); | 158 | return x != 0 && ((x & (~x + 1)) == x); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | static inline uint64_t round_to_next_power_of_2(uint64_t x) { | ||
| 162 | --x; | ||
| 163 | x |= x >> 1; | ||
| 164 | x |= x >> 2; | ||
| 165 | x |= x >> 4; | ||
| 166 | x |= x >> 8; | ||
| 167 | x |= x >> 16; | ||
| 168 | x |= x >> 32; | ||
| 169 | return x + 1; | ||
| 170 | } | ||
| 171 | |||
| 161 | uint32_t int_hash(int i); | 172 | uint32_t int_hash(int i); |
| 162 | bool int_eq(int a, int b); | 173 | bool int_eq(int a, int b); |
| 163 | uint32_t uint64_hash(uint64_t i); | 174 | uint32_t uint64_hash(uint64_t i); |
src/zig_llvm.cpp+161-14| ... | @@ -680,20 +680,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { | ... | @@ -680,20 +680,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { |
| 680 | llvm::cl::ParseCommandLineOptions(argc, argv); | 680 | llvm::cl::ParseCommandLineOptions(argc, argv); |
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | |||
| 684 | static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); | ||
| 685 | static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, ""); | ||
| 686 | static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); | ||
| 687 | static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); | ||
| 688 | static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); | ||
| 689 | static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, ""); | ||
| 690 | |||
| 691 | static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, ""); | ||
| 692 | static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, ""); | ||
| 693 | static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, ""); | ||
| 694 | static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, ""); | ||
| 695 | static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, ""); | ||
| 696 | |||
| 697 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { | 683 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { |
| 698 | return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin(); | 684 | return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin(); |
| 699 | } | 685 | } |
| ... | @@ -924,3 +910,164 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_ | ... | @@ -924,3 +910,164 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_ |
| 924 | assert(false); // unreachable | 910 | assert(false); // unreachable |
| 925 | abort(); | 911 | abort(); |
| 926 | } | 912 | } |
| 913 | |||
| 914 | static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, ""); | ||
| 915 | static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, ""); | ||
| 916 | static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, ""); | ||
| 917 | static_assert((Triple::ArchType)ZigLLVM_aarch64 == Triple::aarch64, ""); | ||
| 918 | static_assert((Triple::ArchType)ZigLLVM_aarch64_be == Triple::aarch64_be, ""); | ||
| 919 | static_assert((Triple::ArchType)ZigLLVM_arc == Triple::arc, ""); | ||
| 920 | static_assert((Triple::ArchType)ZigLLVM_avr == Triple::avr, ""); | ||
| 921 | static_assert((Triple::ArchType)ZigLLVM_bpfel == Triple::bpfel, ""); | ||
| 922 | static_assert((Triple::ArchType)ZigLLVM_bpfeb == Triple::bpfeb, ""); | ||
| 923 | static_assert((Triple::ArchType)ZigLLVM_hexagon == Triple::hexagon, ""); | ||
| 924 | static_assert((Triple::ArchType)ZigLLVM_mips == Triple::mips, ""); | ||
| 925 | static_assert((Triple::ArchType)ZigLLVM_mipsel == Triple::mipsel, ""); | ||
| 926 | static_assert((Triple::ArchType)ZigLLVM_mips64 == Triple::mips64, ""); | ||
| 927 | static_assert((Triple::ArchType)ZigLLVM_mips64el == Triple::mips64el, ""); | ||
| 928 | static_assert((Triple::ArchType)ZigLLVM_msp430 == Triple::msp430, ""); | ||
| 929 | static_assert((Triple::ArchType)ZigLLVM_nios2 == Triple::nios2, ""); | ||
| 930 | static_assert((Triple::ArchType)ZigLLVM_ppc == Triple::ppc, ""); | ||
| 931 | static_assert((Triple::ArchType)ZigLLVM_ppc64 == Triple::ppc64, ""); | ||
| 932 | static_assert((Triple::ArchType)ZigLLVM_ppc64le == Triple::ppc64le, ""); | ||
| 933 | static_assert((Triple::ArchType)ZigLLVM_r600 == Triple::r600, ""); | ||
| 934 | static_assert((Triple::ArchType)ZigLLVM_amdgcn == Triple::amdgcn, ""); | ||
| 935 | static_assert((Triple::ArchType)ZigLLVM_riscv32 == Triple::riscv32, ""); | ||
| 936 | static_assert((Triple::ArchType)ZigLLVM_riscv64 == Triple::riscv64, ""); | ||
| 937 | static_assert((Triple::ArchType)ZigLLVM_sparc == Triple::sparc, ""); | ||
| 938 | static_assert((Triple::ArchType)ZigLLVM_sparcv9 == Triple::sparcv9, ""); | ||
| 939 | static_assert((Triple::ArchType)ZigLLVM_sparcel == Triple::sparcel, ""); | ||
| 940 | static_assert((Triple::ArchType)ZigLLVM_systemz == Triple::systemz, ""); | ||
| 941 | static_assert((Triple::ArchType)ZigLLVM_tce == Triple::tce, ""); | ||
| 942 | static_assert((Triple::ArchType)ZigLLVM_tcele == Triple::tcele, ""); | ||
| 943 | static_assert((Triple::ArchType)ZigLLVM_thumb == Triple::thumb, ""); | ||
| 944 | static_assert((Triple::ArchType)ZigLLVM_thumbeb == Triple::thumbeb, ""); | ||
| 945 | static_assert((Triple::ArchType)ZigLLVM_x86 == Triple::x86, ""); | ||
| 946 | static_assert((Triple::ArchType)ZigLLVM_x86_64 == Triple::x86_64, ""); | ||
| 947 | static_assert((Triple::ArchType)ZigLLVM_xcore == Triple::xcore, ""); | ||
| 948 | static_assert((Triple::ArchType)ZigLLVM_nvptx == Triple::nvptx, ""); | ||
| 949 | static_assert((Triple::ArchType)ZigLLVM_nvptx64 == Triple::nvptx64, ""); | ||
| 950 | static_assert((Triple::ArchType)ZigLLVM_le32 == Triple::le32, ""); | ||
| 951 | static_assert((Triple::ArchType)ZigLLVM_le64 == Triple::le64, ""); | ||
| 952 | static_assert((Triple::ArchType)ZigLLVM_amdil == Triple::amdil, ""); | ||
| 953 | static_assert((Triple::ArchType)ZigLLVM_amdil64 == Triple::amdil64, ""); | ||
| 954 | static_assert((Triple::ArchType)ZigLLVM_hsail == Triple::hsail, ""); | ||
| 955 | static_assert((Triple::ArchType)ZigLLVM_hsail64 == Triple::hsail64, ""); | ||
| 956 | static_assert((Triple::ArchType)ZigLLVM_spir == Triple::spir, ""); | ||
| 957 | static_assert((Triple::ArchType)ZigLLVM_spir64 == Triple::spir64, ""); | ||
| 958 | static_assert((Triple::ArchType)ZigLLVM_kalimba == Triple::kalimba, ""); | ||
| 959 | static_assert((Triple::ArchType)ZigLLVM_shave == Triple::shave, ""); | ||
| 960 | static_assert((Triple::ArchType)ZigLLVM_lanai == Triple::lanai, ""); | ||
| 961 | static_assert((Triple::ArchType)ZigLLVM_wasm32 == Triple::wasm32, ""); | ||
| 962 | static_assert((Triple::ArchType)ZigLLVM_wasm64 == Triple::wasm64, ""); | ||
| 963 | static_assert((Triple::ArchType)ZigLLVM_renderscript32 == Triple::renderscript32, ""); | ||
| 964 | static_assert((Triple::ArchType)ZigLLVM_renderscript64 == Triple::renderscript64, ""); | ||
| 965 | static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); | ||
| 966 | |||
| 967 | static_assert((Triple::SubArchType)ZigLLVM_NoSubArch == Triple::NoSubArch, ""); | ||
| 968 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_4a == Triple::ARMSubArch_v8_4a, ""); | ||
| 969 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_3a == Triple::ARMSubArch_v8_3a, ""); | ||
| 970 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_2a == Triple::ARMSubArch_v8_2a, ""); | ||
| 971 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1a == Triple::ARMSubArch_v8_1a, ""); | ||
| 972 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8 == Triple::ARMSubArch_v8, ""); | ||
| 973 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8r == Triple::ARMSubArch_v8r, ""); | ||
| 974 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_baseline == Triple::ARMSubArch_v8m_baseline, ""); | ||
| 975 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_mainline == Triple::ARMSubArch_v8m_mainline, ""); | ||
| 976 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7 == Triple::ARMSubArch_v7, ""); | ||
| 977 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7em == Triple::ARMSubArch_v7em, ""); | ||
| 978 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7m == Triple::ARMSubArch_v7m, ""); | ||
| 979 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7s == Triple::ARMSubArch_v7s, ""); | ||
| 980 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7k == Triple::ARMSubArch_v7k, ""); | ||
| 981 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7ve == Triple::ARMSubArch_v7ve, ""); | ||
| 982 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6 == Triple::ARMSubArch_v6, ""); | ||
| 983 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6m == Triple::ARMSubArch_v6m, ""); | ||
| 984 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6k == Triple::ARMSubArch_v6k, ""); | ||
| 985 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6t2 == Triple::ARMSubArch_v6t2, ""); | ||
| 986 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5 == Triple::ARMSubArch_v5, ""); | ||
| 987 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5te == Triple::ARMSubArch_v5te, ""); | ||
| 988 | static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v4t == Triple::ARMSubArch_v4t, ""); | ||
| 989 | static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v3 == Triple::KalimbaSubArch_v3, ""); | ||
| 990 | static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v4 == Triple::KalimbaSubArch_v4, ""); | ||
| 991 | static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); | ||
| 992 | static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); | ||
| 993 | static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, ""); | ||
| 994 | |||
| 995 | static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor, ""); | ||
| 996 | static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, ""); | ||
| 997 | static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, ""); | ||
| 998 | static_assert((Triple::VendorType)ZigLLVM_SCEI == Triple::SCEI, ""); | ||
| 999 | static_assert((Triple::VendorType)ZigLLVM_BGP == Triple::BGP, ""); | ||
| 1000 | static_assert((Triple::VendorType)ZigLLVM_BGQ == Triple::BGQ, ""); | ||
| 1001 | static_assert((Triple::VendorType)ZigLLVM_Freescale == Triple::Freescale, ""); | ||
| 1002 | static_assert((Triple::VendorType)ZigLLVM_IBM == Triple::IBM, ""); | ||
| 1003 | static_assert((Triple::VendorType)ZigLLVM_ImaginationTechnologies == Triple::ImaginationTechnologies, ""); | ||
| 1004 | static_assert((Triple::VendorType)ZigLLVM_MipsTechnologies == Triple::MipsTechnologies, ""); | ||
| 1005 | static_assert((Triple::VendorType)ZigLLVM_NVIDIA == Triple::NVIDIA, ""); | ||
| 1006 | static_assert((Triple::VendorType)ZigLLVM_CSR == Triple::CSR, ""); | ||
| 1007 | static_assert((Triple::VendorType)ZigLLVM_Myriad == Triple::Myriad, ""); | ||
| 1008 | static_assert((Triple::VendorType)ZigLLVM_AMD == Triple::AMD, ""); | ||
| 1009 | static_assert((Triple::VendorType)ZigLLVM_Mesa == Triple::Mesa, ""); | ||
| 1010 | static_assert((Triple::VendorType)ZigLLVM_SUSE == Triple::SUSE, ""); | ||
| 1011 | static_assert((Triple::VendorType)ZigLLVM_OpenEmbedded == Triple::OpenEmbedded, ""); | ||
| 1012 | static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, ""); | ||
| 1013 | |||
| 1014 | static_assert((Triple::OSType)ZigLLVM_UnknownOS == Triple::UnknownOS, ""); | ||
| 1015 | static_assert((Triple::OSType)ZigLLVM_Ananas == Triple::Ananas, ""); | ||
| 1016 | static_assert((Triple::OSType)ZigLLVM_CloudABI == Triple::CloudABI, ""); | ||
| 1017 | static_assert((Triple::OSType)ZigLLVM_Darwin == Triple::Darwin, ""); | ||
| 1018 | static_assert((Triple::OSType)ZigLLVM_DragonFly == Triple::DragonFly, ""); | ||
| 1019 | static_assert((Triple::OSType)ZigLLVM_FreeBSD == Triple::FreeBSD, ""); | ||
| 1020 | static_assert((Triple::OSType)ZigLLVM_Fuchsia == Triple::Fuchsia, ""); | ||
| 1021 | static_assert((Triple::OSType)ZigLLVM_IOS == Triple::IOS, ""); | ||
| 1022 | static_assert((Triple::OSType)ZigLLVM_KFreeBSD == Triple::KFreeBSD, ""); | ||
| 1023 | static_assert((Triple::OSType)ZigLLVM_Linux == Triple::Linux, ""); | ||
| 1024 | static_assert((Triple::OSType)ZigLLVM_Lv2 == Triple::Lv2, ""); | ||
| 1025 | static_assert((Triple::OSType)ZigLLVM_MacOSX == Triple::MacOSX, ""); | ||
| 1026 | static_assert((Triple::OSType)ZigLLVM_NetBSD == Triple::NetBSD, ""); | ||
| 1027 | static_assert((Triple::OSType)ZigLLVM_OpenBSD == Triple::OpenBSD, ""); | ||
| 1028 | static_assert((Triple::OSType)ZigLLVM_Solaris == Triple::Solaris, ""); | ||
| 1029 | static_assert((Triple::OSType)ZigLLVM_Win32 == Triple::Win32, ""); | ||
| 1030 | static_assert((Triple::OSType)ZigLLVM_Haiku == Triple::Haiku, ""); | ||
| 1031 | static_assert((Triple::OSType)ZigLLVM_Minix == Triple::Minix, ""); | ||
| 1032 | static_assert((Triple::OSType)ZigLLVM_RTEMS == Triple::RTEMS, ""); | ||
| 1033 | static_assert((Triple::OSType)ZigLLVM_NaCl == Triple::NaCl, ""); | ||
| 1034 | static_assert((Triple::OSType)ZigLLVM_CNK == Triple::CNK, ""); | ||
| 1035 | static_assert((Triple::OSType)ZigLLVM_AIX == Triple::AIX, ""); | ||
| 1036 | static_assert((Triple::OSType)ZigLLVM_CUDA == Triple::CUDA, ""); | ||
| 1037 | static_assert((Triple::OSType)ZigLLVM_NVCL == Triple::NVCL, ""); | ||
| 1038 | static_assert((Triple::OSType)ZigLLVM_AMDHSA == Triple::AMDHSA, ""); | ||
| 1039 | static_assert((Triple::OSType)ZigLLVM_PS4 == Triple::PS4, ""); | ||
| 1040 | static_assert((Triple::OSType)ZigLLVM_ELFIAMCU == Triple::ELFIAMCU, ""); | ||
| 1041 | static_assert((Triple::OSType)ZigLLVM_TvOS == Triple::TvOS, ""); | ||
| 1042 | static_assert((Triple::OSType)ZigLLVM_WatchOS == Triple::WatchOS, ""); | ||
| 1043 | static_assert((Triple::OSType)ZigLLVM_Mesa3D == Triple::Mesa3D, ""); | ||
| 1044 | static_assert((Triple::OSType)ZigLLVM_Contiki == Triple::Contiki, ""); | ||
| 1045 | static_assert((Triple::OSType)ZigLLVM_AMDPAL == Triple::AMDPAL, ""); | ||
| 1046 | static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); | ||
| 1047 | |||
| 1048 | static_assert((Triple::EnvironmentType)ZigLLVM_UnknownEnvironment == Triple::UnknownEnvironment, ""); | ||
| 1049 | static_assert((Triple::EnvironmentType)ZigLLVM_GNU == Triple::GNU, ""); | ||
| 1050 | static_assert((Triple::EnvironmentType)ZigLLVM_GNUABIN32 == Triple::GNUABIN32, ""); | ||
| 1051 | static_assert((Triple::EnvironmentType)ZigLLVM_GNUABI64 == Triple::GNUABI64, ""); | ||
| 1052 | static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABI == Triple::GNUEABI, ""); | ||
| 1053 | static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABIHF == Triple::GNUEABIHF, ""); | ||
| 1054 | static_assert((Triple::EnvironmentType)ZigLLVM_GNUX32 == Triple::GNUX32, ""); | ||
| 1055 | static_assert((Triple::EnvironmentType)ZigLLVM_CODE16 == Triple::CODE16, ""); | ||
| 1056 | static_assert((Triple::EnvironmentType)ZigLLVM_EABI == Triple::EABI, ""); | ||
| 1057 | static_assert((Triple::EnvironmentType)ZigLLVM_EABIHF == Triple::EABIHF, ""); | ||
| 1058 | static_assert((Triple::EnvironmentType)ZigLLVM_Android == Triple::Android, ""); | ||
| 1059 | static_assert((Triple::EnvironmentType)ZigLLVM_Musl == Triple::Musl, ""); | ||
| 1060 | static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABI == Triple::MuslEABI, ""); | ||
| 1061 | static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABIHF == Triple::MuslEABIHF, ""); | ||
| 1062 | static_assert((Triple::EnvironmentType)ZigLLVM_MSVC == Triple::MSVC, ""); | ||
| 1063 | static_assert((Triple::EnvironmentType)ZigLLVM_Itanium == Triple::Itanium, ""); | ||
| 1064 | static_assert((Triple::EnvironmentType)ZigLLVM_Cygnus == Triple::Cygnus, ""); | ||
| 1065 | static_assert((Triple::EnvironmentType)ZigLLVM_CoreCLR == Triple::CoreCLR, ""); | ||
| 1066 | static_assert((Triple::EnvironmentType)ZigLLVM_Simulator == Triple::Simulator, ""); | ||
| 1067 | static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); | ||
| 1068 | |||
| 1069 | static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, ""); | ||
| 1070 | static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, ""); | ||
| 1071 | static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, ""); | ||
| 1072 | static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, ""); | ||
| 1073 | static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, ""); |
std/array_list.zig+11| ... | @@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" { | ... | @@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" { |
| 398 | assert(list.len == 6); | 398 | assert(list.len == 6); |
| 399 | assert(list.items[0] == 1); | 399 | assert(list.items[0] == 1); |
| 400 | } | 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 | assert(root.sub_items.items[0].integer == 42); | ||
| 411 | } |
std/atomic/int.zig+4| ... | @@ -26,6 +26,10 @@ pub fn Int(comptime T: type) type { | ... | @@ -26,6 +26,10 @@ pub fn Int(comptime T: type) type { |
| 26 | return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst); | 26 | return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | pub fn set(self: *Self, new_value: T) void { | ||
| 30 | _ = self.xchg(new_value); | ||
| 31 | } | ||
| 32 | |||
| 29 | pub fn xchg(self: *Self, new_value: T) T { | 33 | pub fn xchg(self: *Self, new_value: T) T { |
| 30 | return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst); | 34 | return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst); |
| 31 | } | 35 | } |
std/buf_map.zig+27-9| ... | @@ -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 | }; |
std/build.zig+38-8| ... | @@ -150,7 +150,11 @@ pub const Builder = struct { | ... | @@ -150,7 +150,11 @@ pub const Builder = struct { |
| 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 { |
| 153 | return LibExeObjStep.createExecutable(self, name, root_src); | 153 | return LibExeObjStep.createExecutable(self, name, root_src, false); |
| 154 | } | ||
| 155 | |||
| 156 | pub fn addStaticExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | ||
| 157 | return LibExeObjStep.createExecutable(self, name, root_src, true); | ||
| 154 | } | 158 | } |
| 155 | 159 | ||
| 156 | pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { | 160 | pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { |
| ... | @@ -795,11 +799,23 @@ pub const Target = union(enum) { | ... | @@ -795,11 +799,23 @@ pub const Target = union(enum) { |
| 795 | }; | 799 | }; |
| 796 | } | 800 | } |
| 797 | 801 | ||
| 802 | pub fn isFreeBSD(self: *const Target) bool { | ||
| 803 | return switch (self.getOs()) { | ||
| 804 | builtin.Os.freebsd => true, | ||
| 805 | else => false, | ||
| 806 | }; | ||
| 807 | } | ||
| 808 | |||
| 798 | pub fn wantSharedLibSymLinks(self: *const Target) bool { | 809 | pub fn wantSharedLibSymLinks(self: *const Target) bool { |
| 799 | return !self.isWindows(); | 810 | return !self.isWindows(); |
| 800 | } | 811 | } |
| 801 | }; | 812 | }; |
| 802 | 813 | ||
| 814 | const Pkg = struct { | ||
| 815 | name: []const u8, | ||
| 816 | path: []const u8, | ||
| 817 | }; | ||
| 818 | |||
| 803 | pub const LibExeObjStep = struct { | 819 | pub const LibExeObjStep = struct { |
| 804 | step: Step, | 820 | step: Step, |
| 805 | builder: *Builder, | 821 | builder: *Builder, |
| ... | @@ -842,11 +858,6 @@ pub const LibExeObjStep = struct { | ... | @@ -842,11 +858,6 @@ pub const LibExeObjStep = struct { |
| 842 | source_files: ArrayList([]const u8), | 858 | source_files: ArrayList([]const u8), |
| 843 | object_src: []const u8, | 859 | object_src: []const u8, |
| 844 | 860 | ||
| 845 | const Pkg = struct { | ||
| 846 | name: []const u8, | ||
| 847 | path: []const u8, | ||
| 848 | }; | ||
| 849 | |||
| 850 | const Kind = enum { | 861 | const Kind = enum { |
| 851 | Exe, | 862 | Exe, |
| 852 | Lib, | 863 | Lib, |
| ... | @@ -884,8 +895,8 @@ pub const LibExeObjStep = struct { | ... | @@ -884,8 +895,8 @@ pub const LibExeObjStep = struct { |
| 884 | return self; | 895 | return self; |
| 885 | } | 896 | } |
| 886 | 897 | ||
| 887 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | 898 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep { |
| 888 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0))) catch unreachable; | 899 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable; |
| 889 | return self; | 900 | return self; |
| 890 | } | 901 | } |
| 891 | 902 | ||
| ... | @@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct { | ... | @@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct { |
| 1263 | zig_args.append("--ver-patch") catch unreachable; | 1274 | zig_args.append("--ver-patch") catch unreachable; |
| 1264 | zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable; | 1275 | zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable; |
| 1265 | } | 1276 | } |
| 1277 | if (self.kind == Kind.Exe and self.static) { | ||
| 1278 | zig_args.append("--static") catch unreachable; | ||
| 1279 | } | ||
| 1266 | 1280 | ||
| 1267 | switch (self.target) { | 1281 | switch (self.target) { |
| 1268 | Target.Native => {}, | 1282 | Target.Native => {}, |
| ... | @@ -1653,6 +1667,7 @@ pub const TestStep = struct { | ... | @@ -1653,6 +1667,7 @@ pub const TestStep = struct { |
| 1653 | exec_cmd_args: ?[]const ?[]const u8, | 1667 | exec_cmd_args: ?[]const ?[]const u8, |
| 1654 | include_dirs: ArrayList([]const u8), | 1668 | include_dirs: ArrayList([]const u8), |
| 1655 | lib_paths: ArrayList([]const u8), | 1669 | lib_paths: ArrayList([]const u8), |
| 1670 | packages: ArrayList(Pkg), | ||
| 1656 | object_files: ArrayList([]const u8), | 1671 | object_files: ArrayList([]const u8), |
| 1657 | no_rosegment: bool, | 1672 | no_rosegment: bool, |
| 1658 | output_path: ?[]const u8, | 1673 | output_path: ?[]const u8, |
| ... | @@ -1673,6 +1688,7 @@ pub const TestStep = struct { | ... | @@ -1673,6 +1688,7 @@ pub const TestStep = struct { |
| 1673 | .exec_cmd_args = null, | 1688 | .exec_cmd_args = null, |
| 1674 | .include_dirs = ArrayList([]const u8).init(builder.allocator), | 1689 | .include_dirs = ArrayList([]const u8).init(builder.allocator), |
| 1675 | .lib_paths = ArrayList([]const u8).init(builder.allocator), | 1690 | .lib_paths = ArrayList([]const u8).init(builder.allocator), |
| 1691 | .packages = ArrayList(Pkg).init(builder.allocator), | ||
| 1676 | .object_files = ArrayList([]const u8).init(builder.allocator), | 1692 | .object_files = ArrayList([]const u8).init(builder.allocator), |
| 1677 | .no_rosegment = false, | 1693 | .no_rosegment = false, |
| 1678 | .output_path = null, | 1694 | .output_path = null, |
| ... | @@ -1688,6 +1704,13 @@ pub const TestStep = struct { | ... | @@ -1688,6 +1704,13 @@ pub const TestStep = struct { |
| 1688 | self.lib_paths.append(path) catch unreachable; | 1704 | self.lib_paths.append(path) catch unreachable; |
| 1689 | } | 1705 | } |
| 1690 | 1706 | ||
| 1707 | pub fn addPackagePath(self: *TestStep, name: []const u8, pkg_index_path: []const u8) void { | ||
| 1708 | self.packages.append(Pkg{ | ||
| 1709 | .name = name, | ||
| 1710 | .path = pkg_index_path, | ||
| 1711 | }) catch unreachable; | ||
| 1712 | } | ||
| 1713 | |||
| 1691 | pub fn setVerbose(self: *TestStep, value: bool) void { | 1714 | pub fn setVerbose(self: *TestStep, value: bool) void { |
| 1692 | self.verbose = value; | 1715 | self.verbose = value; |
| 1693 | } | 1716 | } |
| ... | @@ -1864,6 +1887,13 @@ pub const TestStep = struct { | ... | @@ -1864,6 +1887,13 @@ pub const TestStep = struct { |
| 1864 | try zig_args.append(lib_path); | 1887 | try zig_args.append(lib_path); |
| 1865 | } | 1888 | } |
| 1866 | 1889 | ||
| 1890 | for (self.packages.toSliceConst()) |pkg| { | ||
| 1891 | zig_args.append("--pkg-begin") catch unreachable; | ||
| 1892 | zig_args.append(pkg.name) catch unreachable; | ||
| 1893 | zig_args.append(builder.pathFromRoot(pkg.path)) catch unreachable; | ||
| 1894 | zig_args.append("--pkg-end") catch unreachable; | ||
| 1895 | } | ||
| 1896 | |||
| 1867 | if (self.no_rosegment) { | 1897 | if (self.no_rosegment) { |
| 1868 | try zig_args.append("--no-rosegment"); | 1898 | try zig_args.append("--no-rosegment"); |
| 1869 | } | 1899 | } |
std/c/freebsd.zig created+33| ... | @@ -0,0 +1,33 @@ | ||
| 1 | const timespec = @import("../os/freebsd/index.zig").timespec; | ||
| 2 | |||
| 3 | extern "c" fn __error() *c_int; | ||
| 4 | pub const _errno = __error; | ||
| 5 | |||
| 6 | pub extern "c" fn kqueue() c_int; | ||
| 7 | pub extern "c" fn kevent( | ||
| 8 | kq: c_int, | ||
| 9 | changelist: [*]const Kevent, | ||
| 10 | nchanges: c_int, | ||
| 11 | eventlist: [*]Kevent, | ||
| 12 | nevents: c_int, | ||
| 13 | timeout: ?*const timespec, | ||
| 14 | ) c_int; | ||
| 15 | 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; | ||
| 17 | pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int; | ||
| 18 | |||
| 19 | /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. | ||
| 20 | pub const Kevent = extern struct { | ||
| 21 | ident: usize, | ||
| 22 | filter: i16, | ||
| 23 | flags: u16, | ||
| 24 | fflags: u32, | ||
| 25 | data: i64, | ||
| 26 | udata: usize, | ||
| 27 | // TODO ext | ||
| 28 | }; | ||
| 29 | |||
| 30 | pub const pthread_attr_t = extern struct { | ||
| 31 | __size: [56]u8, | ||
| 32 | __align: c_long, | ||
| 33 | }; | ||
std/c/index.zig+1| ... | @@ -5,6 +5,7 @@ pub use switch (builtin.os) { | ... | @@ -5,6 +5,7 @@ pub use switch (builtin.os) { |
| 5 | Os.linux => @import("linux.zig"), | 5 | Os.linux => @import("linux.zig"), |
| 6 | Os.windows => @import("windows.zig"), | 6 | Os.windows => @import("windows.zig"), |
| 7 | Os.macosx, Os.ios => @import("darwin.zig"), | 7 | Os.macosx, Os.ios => @import("darwin.zig"), |
| 8 | Os.freebsd => @import("freebsd.zig"), | ||
| 8 | else => empty_import, | 9 | else => empty_import, |
| 9 | }; | 10 | }; |
| 10 | const empty_import = @import("../empty.zig"); | 11 | const empty_import = @import("../empty.zig"); |
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+27-26| ... | @@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { | ... | @@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | for (x) |_, i| { | 61 | for (x) |_, i| { |
| 62 | mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little); | 62 | // TODO https://github.com/ziglang/zig/issues/863 |
| 63 | mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]); | ||
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| 65 | 66 | ||
| ... | @@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo | ... | @@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo |
| 70 | 71 | ||
| 71 | const c = "expand 32-byte k"; | 72 | const c = "expand 32-byte k"; |
| 72 | const constant_le = []u32{ | 73 | const constant_le = []u32{ |
| 73 | mem.readIntLE(u32, c[0..4]), | 74 | mem.readIntSliceLittle(u32, c[0..4]), |
| 74 | mem.readIntLE(u32, c[4..8]), | 75 | mem.readIntSliceLittle(u32, c[4..8]), |
| 75 | mem.readIntLE(u32, c[8..12]), | 76 | mem.readIntSliceLittle(u32, c[8..12]), |
| 76 | mem.readIntLE(u32, c[12..16]), | 77 | mem.readIntSliceLittle(u32, c[12..16]), |
| 77 | }; | 78 | }; |
| 78 | 79 | ||
| 79 | mem.copy(u32, ctx[0..], constant_le[0..4]); | 80 | mem.copy(u32, ctx[0..], constant_le[0..4]); |
| ... | @@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: | ... | @@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: |
| 117 | var k: [8]u32 = undefined; | 118 | var k: [8]u32 = undefined; |
| 118 | var c: [4]u32 = undefined; | 119 | var c: [4]u32 = undefined; |
| 119 | 120 | ||
| 120 | k[0] = mem.readIntLE(u32, key[0..4]); | 121 | k[0] = mem.readIntSliceLittle(u32, key[0..4]); |
| 121 | k[1] = mem.readIntLE(u32, key[4..8]); | 122 | k[1] = mem.readIntSliceLittle(u32, key[4..8]); |
| 122 | k[2] = mem.readIntLE(u32, key[8..12]); | 123 | k[2] = mem.readIntSliceLittle(u32, key[8..12]); |
| 123 | k[3] = mem.readIntLE(u32, key[12..16]); | 124 | k[3] = mem.readIntSliceLittle(u32, key[12..16]); |
| 124 | k[4] = mem.readIntLE(u32, key[16..20]); | 125 | k[4] = mem.readIntSliceLittle(u32, key[16..20]); |
| 125 | k[5] = mem.readIntLE(u32, key[20..24]); | 126 | k[5] = mem.readIntSliceLittle(u32, key[20..24]); |
| 126 | k[6] = mem.readIntLE(u32, key[24..28]); | 127 | k[6] = mem.readIntSliceLittle(u32, key[24..28]); |
| 127 | k[7] = mem.readIntLE(u32, key[28..32]); | 128 | k[7] = mem.readIntSliceLittle(u32, key[28..32]); |
| 128 | 129 | ||
| 129 | c[0] = counter; | 130 | c[0] = counter; |
| 130 | c[1] = mem.readIntLE(u32, nonce[0..4]); | 131 | c[1] = mem.readIntSliceLittle(u32, nonce[0..4]); |
| 131 | c[2] = mem.readIntLE(u32, nonce[4..8]); | 132 | c[2] = mem.readIntSliceLittle(u32, nonce[4..8]); |
| 132 | c[3] = mem.readIntLE(u32, nonce[8..12]); | 133 | c[3] = mem.readIntSliceLittle(u32, nonce[8..12]); |
| 133 | chaCha20_internal(out, in, k, c); | 134 | chaCha20_internal(out, in, k, c); |
| 134 | } | 135 | } |
| 135 | 136 | ||
| ... | @@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] | ... | @@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] |
| 144 | var k: [8]u32 = undefined; | 145 | var k: [8]u32 = undefined; |
| 145 | var c: [4]u32 = undefined; | 146 | var c: [4]u32 = undefined; |
| 146 | 147 | ||
| 147 | k[0] = mem.readIntLE(u32, key[0..4]); | 148 | k[0] = mem.readIntSliceLittle(u32, key[0..4]); |
| 148 | k[1] = mem.readIntLE(u32, key[4..8]); | 149 | k[1] = mem.readIntSliceLittle(u32, key[4..8]); |
| 149 | k[2] = mem.readIntLE(u32, key[8..12]); | 150 | k[2] = mem.readIntSliceLittle(u32, key[8..12]); |
| 150 | k[3] = mem.readIntLE(u32, key[12..16]); | 151 | k[3] = mem.readIntSliceLittle(u32, key[12..16]); |
| 151 | k[4] = mem.readIntLE(u32, key[16..20]); | 152 | k[4] = mem.readIntSliceLittle(u32, key[16..20]); |
| 152 | k[5] = mem.readIntLE(u32, key[20..24]); | 153 | k[5] = mem.readIntSliceLittle(u32, key[20..24]); |
| 153 | k[6] = mem.readIntLE(u32, key[24..28]); | 154 | k[6] = mem.readIntSliceLittle(u32, key[24..28]); |
| 154 | k[7] = mem.readIntLE(u32, key[28..32]); | 155 | k[7] = mem.readIntSliceLittle(u32, key[28..32]); |
| 155 | 156 | ||
| 156 | c[0] = @truncate(u32, counter); | 157 | c[0] = @truncate(u32, counter); |
| 157 | c[1] = @truncate(u32, counter >> 32); | 158 | c[1] = @truncate(u32, counter >> 32); |
| 158 | c[2] = mem.readIntLE(u32, nonce[0..4]); | 159 | c[2] = mem.readIntSliceLittle(u32, nonce[0..4]); |
| 159 | c[3] = mem.readIntLE(u32, nonce[4..8]); | 160 | c[3] = mem.readIntSliceLittle(u32, nonce[4..8]); |
| 160 | 161 | ||
| 161 | const block_size = (1 << 6); | 162 | const block_size = (1 << 6); |
| 162 | const big_block = (block_size << 32); | 163 | const big_block = (block_size << 32); |
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+14-13| ... | @@ -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 | } |
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/x25519.zig+21-20| ... | @@ -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 | } |
std/debug/index.zig+261-238| ... | @@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, | ... | @@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, |
| 198 | } | 198 | } |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | pub inline fn getReturnAddress(frame_count: usize) usize { | 201 | pub const StackIterator = struct { |
| 202 | var fp = @ptrToInt(@frameAddress()); | 202 | first_addr: ?usize, |
| 203 | var i: usize = 0; | 203 | fp: usize, |
| 204 | while (fp != 0 and i < frame_count) { | 204 | |
| 205 | fp = @intToPtr(*const usize, fp).*; | 205 | pub fn init(first_addr: ?usize) StackIterator { |
| 206 | i += 1; | 206 | return StackIterator{ |
| 207 | .first_addr = first_addr, | ||
| 208 | .fp = @ptrToInt(@frameAddress()), | ||
| 209 | }; | ||
| 207 | } | 210 | } |
| 208 | return @intToPtr(*const usize, fp + @sizeOf(usize)).*; | 211 | |
| 209 | } | 212 | fn next(self: *StackIterator) ?usize { |
| 213 | if (self.fp == 0) return null; | ||
| 214 | self.fp = @intToPtr(*const usize, self.fp).*; | ||
| 215 | if (self.fp == 0) return null; | ||
| 216 | |||
| 217 | if (self.first_addr) |addr| { | ||
| 218 | while (self.fp != 0) : (self.fp = @intToPtr(*const usize, self.fp).*) { | ||
| 219 | const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*; | ||
| 220 | if (addr == return_address) { | ||
| 221 | self.first_addr = null; | ||
| 222 | return return_address; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*; | ||
| 228 | return return_address; | ||
| 229 | } | ||
| 230 | }; | ||
| 210 | 231 | ||
| 211 | pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { | 232 | pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { |
| 212 | switch (builtin.os) { | 233 | switch (builtin.os) { |
| 213 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), | 234 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), |
| 214 | else => {}, | 235 | else => {}, |
| 215 | } | 236 | } |
| 216 | const AddressState = union(enum) { | 237 | var it = StackIterator.init(start_addr); |
| 217 | NotLookingForStartAddress, | 238 | while (it.next()) |return_address| { |
| 218 | LookingForStartAddress: usize, | ||
| 219 | }; | ||
| 220 | // TODO: I want to express like this: | ||
| 221 | //var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr } | ||
| 222 | // else AddressState.NotLookingForStartAddress; | ||
| 223 | var addr_state: AddressState = undefined; | ||
| 224 | if (start_addr) |addr| { | ||
| 225 | addr_state = AddressState{ .LookingForStartAddress = addr }; | ||
| 226 | } else { | ||
| 227 | addr_state = AddressState.NotLookingForStartAddress; | ||
| 228 | } | ||
| 229 | |||
| 230 | var fp = @ptrToInt(@frameAddress()); | ||
| 231 | while (fp != 0) : (fp = @intToPtr(*const usize, fp).*) { | ||
| 232 | const return_address = @intToPtr(*const usize, fp + @sizeOf(usize)).*; | ||
| 233 | |||
| 234 | switch (addr_state) { | ||
| 235 | AddressState.NotLookingForStartAddress => {}, | ||
| 236 | AddressState.LookingForStartAddress => |addr| { | ||
| 237 | if (return_address == addr) { | ||
| 238 | addr_state = AddressState.NotLookingForStartAddress; | ||
| 239 | } else { | ||
| 240 | continue; | ||
| 241 | } | ||
| 242 | }, | ||
| 243 | } | ||
| 244 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); | 239 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); |
| 245 | } | 240 | } |
| 246 | } | 241 | } |
| ... | @@ -282,8 +277,9 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres | ... | @@ -282,8 +277,9 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 282 | 277 | ||
| 283 | var coff_section: *coff.Section = undefined; | 278 | var coff_section: *coff.Section = undefined; |
| 284 | const mod_index = for (di.sect_contribs) |sect_contrib| { | 279 | const mod_index = for (di.sect_contribs) |sect_contrib| { |
| 285 | if (sect_contrib.Section >= di.coff.sections.len) continue; | 280 | if (sect_contrib.Section > di.coff.sections.len) continue; |
| 286 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section]; | 281 | // Remember that SectionContribEntry.Section is 1-based. |
| 282 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1]; | ||
| 287 | 283 | ||
| 288 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; | 284 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| 289 | const vaddr_end = vaddr_start + sect_contrib.Size; | 285 | const vaddr_end = vaddr_start + sect_contrib.Size; |
| ... | @@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres | ... | @@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 413 | 409 | ||
| 414 | if (opt_line_info) |line_info| { | 410 | if (opt_line_info) |line_info| { |
| 415 | try out_stream.print("\n"); | 411 | try out_stream.print("\n"); |
| 416 | if (printLineFromFile(out_stream, line_info)) { | 412 | if (printLineFromFileAnyOs(out_stream, line_info)) { |
| 417 | if (line_info.column == 0) { | 413 | if (line_info.column == 0) { |
| 418 | try out_stream.write("\n"); | 414 | try out_stream.write("\n"); |
| 419 | } else { | 415 | } else { |
| ... | @@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { | ... | @@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 527 | 523 | ||
| 528 | 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; |
| 529 | 525 | ||
| 530 | const signature = try modi.stream.readIntLe(u32); | 526 | const signature = try modi.stream.readIntLittle(u32); |
| 531 | if (signature != 4) | 527 | if (signature != 4) |
| 532 | return error.InvalidDebugInfo; | 528 | return error.InvalidDebugInfo; |
| 533 | 529 | ||
| ... | @@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt | ... | @@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt |
| 597 | } else "???"; | 593 | } else "???"; |
| 598 | if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| { | 594 | if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| { |
| 599 | defer line_info.deinit(); | 595 | defer line_info.deinit(); |
| 600 | try printLineInfo(di, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color); | 596 | try printLineInfo( |
| 597 | out_stream, | ||
| 598 | line_info, | ||
| 599 | address, | ||
| 600 | symbol_name, | ||
| 601 | compile_unit_name, | ||
| 602 | tty_color, | ||
| 603 | printLineFromFileAnyOs, | ||
| 604 | ); | ||
| 601 | } else |err| switch (err) { | 605 | } else |err| switch (err) { |
| 602 | error.MissingDebugInfo, error.InvalidDebugInfo => { | 606 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 603 | if (tty_color) { | 607 | if (tty_color) { |
| ... | @@ -610,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt | ... | @@ -610,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt |
| 610 | } | 614 | } |
| 611 | } | 615 | } |
| 612 | 616 | ||
| 613 | pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { | 617 | /// This function works in freestanding mode. |
| 618 | /// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void | ||
| 619 | pub fn printSourceAtAddressDwarf( | ||
| 620 | debug_info: *DwarfInfo, | ||
| 621 | out_stream: var, | ||
| 622 | address: usize, | ||
| 623 | tty_color: bool, | ||
| 624 | comptime printLineFromFile: var, | ||
| 625 | ) !void { | ||
| 614 | const compile_unit = findCompileUnit(debug_info, address) catch { | 626 | const compile_unit = findCompileUnit(debug_info, address) catch { |
| 615 | if (tty_color) { | 627 | if (tty_color) { |
| 616 | try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address); | 628 | try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address); |
| ... | @@ -620,10 +632,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres | ... | @@ -620,10 +632,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres |
| 620 | return; | 632 | return; |
| 621 | }; | 633 | }; |
| 622 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); | 634 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); |
| 623 | if (getLineNumberInfoLinux(debug_info, compile_unit, address - 1)) |line_info| { | 635 | if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| { |
| 624 | defer line_info.deinit(); | 636 | defer line_info.deinit(); |
| 625 | const symbol_name = "???"; | 637 | const symbol_name = "???"; |
| 626 | try printLineInfo(debug_info, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color); | 638 | try printLineInfo( |
| 639 | out_stream, | ||
| 640 | line_info, | ||
| 641 | address, | ||
| 642 | symbol_name, | ||
| 643 | compile_unit_name, | ||
| 644 | tty_color, | ||
| 645 | printLineFromFile, | ||
| 646 | ); | ||
| 627 | } else |err| switch (err) { | 647 | } else |err| switch (err) { |
| 628 | error.MissingDebugInfo, error.InvalidDebugInfo => { | 648 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 629 | if (tty_color) { | 649 | if (tty_color) { |
| ... | @@ -636,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres | ... | @@ -636,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres |
| 636 | } | 656 | } |
| 637 | } | 657 | } |
| 638 | 658 | ||
| 659 | pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { | ||
| 660 | return printSourceAtAddressDwarf(debug_info, out_stream, address, tty_color, printLineFromFileAnyOs); | ||
| 661 | } | ||
| 662 | |||
| 639 | fn printLineInfo( | 663 | fn printLineInfo( |
| 640 | debug_info: *DebugInfo, | ||
| 641 | out_stream: var, | 664 | out_stream: var, |
| 642 | line_info: LineInfo, | 665 | line_info: LineInfo, |
| 643 | address: usize, | 666 | address: usize, |
| 644 | symbol_name: []const u8, | 667 | symbol_name: []const u8, |
| 645 | compile_unit_name: []const u8, | 668 | compile_unit_name: []const u8, |
| 646 | tty_color: bool, | 669 | tty_color: bool, |
| 670 | comptime printLineFromFile: var, | ||
| 647 | ) !void { | 671 | ) !void { |
| 648 | if (tty_color) { | 672 | if (tty_color) { |
| 649 | try out_stream.print( | 673 | try out_stream.print( |
| ... | @@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 733 | try di.pdb.openFile(di.coff, path); | 757 | try di.pdb.openFile(di.coff, path); |
| 734 | 758 | ||
| 735 | 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; |
| 736 | const version = try pdb_stream.stream.readIntLe(u32); | 760 | const version = try pdb_stream.stream.readIntLittle(u32); |
| 737 | const signature = try pdb_stream.stream.readIntLe(u32); | 761 | const signature = try pdb_stream.stream.readIntLittle(u32); |
| 738 | const age = try pdb_stream.stream.readIntLe(u32); | 762 | const age = try pdb_stream.stream.readIntLittle(u32); |
| 739 | var guid: [16]u8 = undefined; | 763 | var guid: [16]u8 = undefined; |
| 740 | try pdb_stream.stream.readNoEof(guid[0..]); | 764 | try pdb_stream.stream.readNoEof(guid[0..]); |
| 741 | 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) |
| ... | @@ -743,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -743,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 743 | // We validated the executable and pdb match. | 767 | // We validated the executable and pdb match. |
| 744 | 768 | ||
| 745 | const string_table_index = str_tab_index: { | 769 | const string_table_index = str_tab_index: { |
| 746 | const name_bytes_len = try pdb_stream.stream.readIntLe(u32); | 770 | const name_bytes_len = try pdb_stream.stream.readIntLittle(u32); |
| 747 | const name_bytes = try allocator.alloc(u8, name_bytes_len); | 771 | const name_bytes = try allocator.alloc(u8, name_bytes_len); |
| 748 | try pdb_stream.stream.readNoEof(name_bytes); | 772 | try pdb_stream.stream.readNoEof(name_bytes); |
| 749 | 773 | ||
| ... | @@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 773 | }; | 797 | }; |
| 774 | const bucket_list = try allocator.alloc(Bucket, present.len); | 798 | const bucket_list = try allocator.alloc(Bucket, present.len); |
| 775 | for (present) |_| { | 799 | for (present) |_| { |
| 776 | const name_offset = try pdb_stream.stream.readIntLe(u32); | 800 | const name_offset = try pdb_stream.stream.readIntLittle(u32); |
| 777 | const name_index = try pdb_stream.stream.readIntLe(u32); | 801 | const name_index = try pdb_stream.stream.readIntLittle(u32); |
| 778 | const name = mem.toSlice(u8, name_bytes.ptr + name_offset); | 802 | const name = mem.toSlice(u8, name_bytes.ptr + name_offset); |
| 779 | if (mem.eql(u8, name, "/names")) { | 803 | if (mem.eql(u8, name, "/names")) { |
| 780 | break :str_tab_index name_index; | 804 | break :str_tab_index name_index; |
| ... | @@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 835 | var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); | 859 | var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); |
| 836 | var sect_cont_offset: usize = 0; | 860 | var sect_cont_offset: usize = 0; |
| 837 | if (section_contrib_size != 0) { | 861 | if (section_contrib_size != 0) { |
| 838 | const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32)); | 862 | const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32)); |
| 839 | if (ver != pdb.SectionContrSubstreamVersion.Ver60) | 863 | if (ver != pdb.SectionContrSubstreamVersion.Ver60) |
| 840 | return error.InvalidDebugInfo; | 864 | return error.InvalidDebugInfo; |
| 841 | sect_cont_offset += @sizeOf(u32); | 865 | sect_cont_offset += @sizeOf(u32); |
| ... | @@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 855 | } | 879 | } |
| 856 | 880 | ||
| 857 | fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { | 881 | fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 858 | const num_words = try stream.readIntLe(u32); | 882 | const num_words = try stream.readIntLittle(u32); |
| 859 | var word_i: usize = 0; | 883 | var word_i: usize = 0; |
| 860 | var list = ArrayList(usize).init(allocator); | 884 | var list = ArrayList(usize).init(allocator); |
| 861 | while (word_i != num_words) : (word_i += 1) { | 885 | while (word_i != num_words) : (word_i += 1) { |
| 862 | const word = try stream.readIntLe(u32); | 886 | const word = try stream.readIntLittle(u32); |
| 863 | var bit_i: u5 = 0; | 887 | var bit_i: u5 = 0; |
| 864 | while (true) : (bit_i += 1) { | 888 | while (true) : (bit_i += 1) { |
| 865 | if (word & (u32(1) << bit_i) != 0) { | 889 | if (word & (u32(1) << bit_i) != 0) { |
| ... | @@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { | ... | @@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 871 | return list.toOwnedSlice(); | 895 | return list.toOwnedSlice(); |
| 872 | } | 896 | } |
| 873 | 897 | ||
| 874 | fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { | 898 | fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { |
| 875 | var di = DebugInfo{ | 899 | const elf_header = (try elf_file.findSection(name)) orelse return null; |
| 876 | .self_exe_file = undefined, | 900 | return DwarfInfo.Section{ |
| 877 | .elf = undefined, | 901 | .offset = elf_header.offset, |
| 878 | .debug_info = undefined, | 902 | .size = elf_header.size, |
| 879 | .debug_abbrev = undefined, | ||
| 880 | .debug_str = undefined, | ||
| 881 | .debug_line = undefined, | ||
| 882 | .debug_ranges = null, | ||
| 883 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | ||
| 884 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | ||
| 885 | }; | 903 | }; |
| 886 | di.self_exe_file = try os.openSelfExe(); | ||
| 887 | errdefer di.self_exe_file.close(); | ||
| 888 | |||
| 889 | try di.elf.openFile(allocator, di.self_exe_file); | ||
| 890 | errdefer di.elf.close(); | ||
| 891 | |||
| 892 | di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo; | ||
| 893 | di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo; | ||
| 894 | di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo; | ||
| 895 | di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo; | ||
| 896 | di.debug_ranges = (try di.elf.findSection(".debug_ranges")); | ||
| 897 | try scanAllCompileUnits(&di); | ||
| 898 | return di; | ||
| 899 | } | 904 | } |
| 900 | 905 | ||
| 901 | pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr { | 906 | /// Initialize DWARF info. The caller has the responsibility to initialize most |
| 902 | var file_stream = elf.in_file.inStream(); | 907 | /// the DwarfInfo fields before calling. These fields can be left undefined: |
| 903 | const in = &file_stream.stream; | 908 | /// * abbrev_table_list |
| 904 | 909 | /// * compile_unit_list | |
| 905 | section_loop: for (elf.section_headers) |*elf_section| { | 910 | pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void { |
| 906 | if (elf_section.sh_type == SHT_NULL) continue; | 911 | di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator); |
| 907 | 912 | di.compile_unit_list = ArrayList(CompileUnit).init(allocator); | |
| 908 | const name_offset = elf.string_section.offset + elf_section.name; | 913 | try scanAllCompileUnits(di); |
| 909 | try elf.in_file.seekTo(name_offset); | 914 | } |
| 910 | |||
| 911 | for (name) |expected_c| { | ||
| 912 | const target_c = try in.readByte(); | ||
| 913 | if (target_c == 0 or expected_c != target_c) continue :section_loop; | ||
| 914 | } | ||
| 915 | 915 | ||
| 916 | { | 916 | pub fn openElfDebugInfo( |
| 917 | const null_byte = try in.readByte(); | 917 | allocator: *mem.Allocator, |
| 918 | if (null_byte == 0) return elf_section; | 918 | elf_seekable_stream: *DwarfSeekableStream, |
| 919 | } | 919 | elf_in_stream: *DwarfInStream, |
| 920 | } | 920 | ) !DwarfInfo { |
| 921 | var efile: elf.Elf = undefined; | ||
| 922 | try efile.openStream(allocator, elf_seekable_stream, elf_in_stream); | ||
| 923 | errdefer efile.close(); | ||
| 924 | |||
| 925 | var di = DwarfInfo{ | ||
| 926 | .dwarf_seekable_stream = elf_seekable_stream, | ||
| 927 | .dwarf_in_stream = elf_in_stream, | ||
| 928 | .endian = efile.endian, | ||
| 929 | .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo, | ||
| 930 | .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo, | ||
| 931 | .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo, | ||
| 932 | .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo, | ||
| 933 | .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")), | ||
| 934 | .abbrev_table_list = undefined, | ||
| 935 | .compile_unit_list = undefined, | ||
| 936 | }; | ||
| 937 | try openDwarfDebugInfo(&di, allocator); | ||
| 938 | return di; | ||
| 939 | } | ||
| 921 | 940 | ||
| 922 | return null; | 941 | fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo { |
| 942 | const S = struct { | ||
| 943 | var self_exe_file: os.File = undefined; | ||
| 944 | var self_exe_seekable_stream: os.File.SeekableStream = undefined; | ||
| 945 | var self_exe_in_stream: os.File.InStream = undefined; | ||
| 946 | }; | ||
| 947 | S.self_exe_file = try os.openSelfExe(); | ||
| 948 | errdefer S.self_exe_file.close(); | ||
| 949 | |||
| 950 | S.self_exe_seekable_stream = S.self_exe_file.seekableStream(); | ||
| 951 | S.self_exe_in_stream = S.self_exe_file.inStream(); | ||
| 952 | |||
| 953 | return openElfDebugInfo( | ||
| 954 | allocator, | ||
| 955 | // TODO https://github.com/ziglang/zig/issues/764 | ||
| 956 | @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream), | ||
| 957 | // TODO https://github.com/ziglang/zig/issues/764 | ||
| 958 | @ptrCast(*DwarfInStream, &S.self_exe_in_stream.stream), | ||
| 959 | ); | ||
| 923 | } | 960 | } |
| 924 | 961 | ||
| 925 | fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { | 962 | fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| ... | @@ -999,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -999,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| 999 | }; | 1036 | }; |
| 1000 | } | 1037 | } |
| 1001 | 1038 | ||
| 1002 | fn printLineFromFile(out_stream: var, line_info: LineInfo) !void { | 1039 | fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void { |
| 1003 | var f = try os.File.openRead(line_info.file_name); | 1040 | var f = try os.File.openRead(line_info.file_name); |
| 1004 | defer f.close(); | 1041 | defer f.close(); |
| 1005 | // TODO fstat and make sure that the file has the correct size | 1042 | // TODO fstat and make sure that the file has the correct size |
| ... | @@ -1052,6 +1089,35 @@ const MachOFile = struct { | ... | @@ -1052,6 +1089,35 @@ const MachOFile = struct { |
| 1052 | sect_debug_line: ?*const macho.section_64, | 1089 | sect_debug_line: ?*const macho.section_64, |
| 1053 | }; | 1090 | }; |
| 1054 | 1091 | ||
| 1092 | pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror); | ||
| 1093 | pub const DwarfInStream = io.InStream(anyerror); | ||
| 1094 | |||
| 1095 | pub const DwarfInfo = struct { | ||
| 1096 | dwarf_seekable_stream: *DwarfSeekableStream, | ||
| 1097 | dwarf_in_stream: *DwarfInStream, | ||
| 1098 | endian: builtin.Endian, | ||
| 1099 | debug_info: Section, | ||
| 1100 | debug_abbrev: Section, | ||
| 1101 | debug_str: Section, | ||
| 1102 | debug_line: Section, | ||
| 1103 | debug_ranges: ?Section, | ||
| 1104 | abbrev_table_list: ArrayList(AbbrevTableHeader), | ||
| 1105 | compile_unit_list: ArrayList(CompileUnit), | ||
| 1106 | |||
| 1107 | pub const Section = struct { | ||
| 1108 | offset: usize, | ||
| 1109 | size: usize, | ||
| 1110 | }; | ||
| 1111 | |||
| 1112 | pub fn allocator(self: DwarfInfo) *mem.Allocator { | ||
| 1113 | return self.abbrev_table_list.allocator; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | pub fn readString(self: *DwarfInfo) ![]u8 { | ||
| 1117 | return readStringRaw(self.allocator(), self.dwarf_in_stream); | ||
| 1118 | } | ||
| 1119 | }; | ||
| 1120 | |||
| 1055 | pub const DebugInfo = switch (builtin.os) { | 1121 | pub const DebugInfo = switch (builtin.os) { |
| 1056 | builtin.Os.macosx => struct { | 1122 | builtin.Os.macosx => struct { |
| 1057 | symbols: []const MachoSymbol, | 1123 | symbols: []const MachoSymbol, |
| ... | @@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) { | ... | @@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) { |
| 1075 | sect_contribs: []pdb.SectionContribEntry, | 1141 | sect_contribs: []pdb.SectionContribEntry, |
| 1076 | modules: []Module, | 1142 | modules: []Module, |
| 1077 | }, | 1143 | }, |
| 1078 | builtin.Os.linux => struct { | 1144 | builtin.Os.linux => DwarfInfo, |
| 1079 | self_exe_file: os.File, | 1145 | builtin.Os.freebsd => struct {}, |
| 1080 | elf: elf.Elf, | ||
| 1081 | debug_info: *elf.SectionHeader, | ||
| 1082 | debug_abbrev: *elf.SectionHeader, | ||
| 1083 | debug_str: *elf.SectionHeader, | ||
| 1084 | debug_line: *elf.SectionHeader, | ||
| 1085 | debug_ranges: ?*elf.SectionHeader, | ||
| 1086 | abbrev_table_list: ArrayList(AbbrevTableHeader), | ||
| 1087 | compile_unit_list: ArrayList(CompileUnit), | ||
| 1088 | |||
| 1089 | pub fn allocator(self: DebugInfo) *mem.Allocator { | ||
| 1090 | return self.abbrev_table_list.allocator; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | pub fn readString(self: *DebugInfo) ![]u8 { | ||
| 1094 | var in_file_stream = self.self_exe_file.inStream(); | ||
| 1095 | const in_stream = &in_file_stream.stream; | ||
| 1096 | return readStringRaw(self.allocator(), in_stream); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | pub fn close(self: *DebugInfo) void { | ||
| 1100 | self.self_exe_file.close(); | ||
| 1101 | self.elf.close(); | ||
| 1102 | } | ||
| 1103 | }, | ||
| 1104 | else => @compileError("Unsupported OS"), | 1146 | else => @compileError("Unsupported OS"), |
| 1105 | }; | 1147 | }; |
| 1106 | 1148 | ||
| ... | @@ -1158,7 +1200,7 @@ const Constant = struct { | ... | @@ -1158,7 +1200,7 @@ const Constant = struct { |
| 1158 | fn asUnsignedLe(self: *const Constant) !u64 { | 1200 | fn asUnsignedLe(self: *const Constant) !u64 { |
| 1159 | if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; | 1201 | if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; |
| 1160 | if (self.signed) return error.InvalidDebugInfo; | 1202 | if (self.signed) return error.InvalidDebugInfo; |
| 1161 | return mem.readInt(self.payload, u64, builtin.Endian.Little); | 1203 | return mem.readVarInt(u64, self.payload, builtin.Endian.Little); |
| 1162 | } | 1204 | } |
| 1163 | }; | 1205 | }; |
| 1164 | 1206 | ||
| ... | @@ -1204,11 +1246,11 @@ const Die = struct { | ... | @@ -1204,11 +1246,11 @@ const Die = struct { |
| 1204 | }; | 1246 | }; |
| 1205 | } | 1247 | } |
| 1206 | 1248 | ||
| 1207 | fn getAttrString(self: *const Die, st: *DebugInfo, id: u64) ![]u8 { | 1249 | fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 { |
| 1208 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; | 1250 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; |
| 1209 | return switch (form_value.*) { | 1251 | return switch (form_value.*) { |
| 1210 | FormValue.String => |value| value, | 1252 | FormValue.String => |value| value, |
| 1211 | FormValue.StrPtr => |offset| getString(st, offset), | 1253 | FormValue.StrPtr => |offset| getString(di, offset), |
| 1212 | else => error.InvalidDebugInfo, | 1254 | else => error.InvalidDebugInfo, |
| 1213 | }; | 1255 | }; |
| 1214 | } | 1256 | } |
| ... | @@ -1221,14 +1263,15 @@ const FileEntry = struct { | ... | @@ -1221,14 +1263,15 @@ const FileEntry = struct { |
| 1221 | len_bytes: usize, | 1263 | len_bytes: usize, |
| 1222 | }; | 1264 | }; |
| 1223 | 1265 | ||
| 1224 | const LineInfo = struct { | 1266 | pub const LineInfo = struct { |
| 1225 | line: usize, | 1267 | line: usize, |
| 1226 | column: usize, | 1268 | column: usize, |
| 1227 | file_name: []u8, | 1269 | file_name: []const u8, |
| 1228 | allocator: *mem.Allocator, | 1270 | allocator: ?*mem.Allocator, |
| 1229 | 1271 | ||
| 1230 | fn deinit(self: *const LineInfo) void { | 1272 | fn deinit(self: LineInfo) void { |
| 1231 | self.allocator.free(self.file_name); | 1273 | const allocator = self.allocator orelse return; |
| 1274 | allocator.free(self.file_name); | ||
| 1232 | } | 1275 | } |
| 1233 | }; | 1276 | }; |
| 1234 | 1277 | ||
| ... | @@ -1319,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 { | ... | @@ -1319,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 { |
| 1319 | return buf.toSlice(); | 1362 | return buf.toSlice(); |
| 1320 | } | 1363 | } |
| 1321 | 1364 | ||
| 1322 | fn getString(st: *DebugInfo, offset: u64) ![]u8 { | 1365 | fn getString(di: *DwarfInfo, offset: u64) ![]u8 { |
| 1323 | const pos = st.debug_str.offset + offset; | 1366 | const pos = di.debug_str.offset + offset; |
| 1324 | try st.self_exe_file.seekTo(pos); | 1367 | try di.dwarf_seekable_stream.seekTo(pos); |
| 1325 | return st.readString(); | 1368 | return di.readString(); |
| 1326 | } | 1369 | } |
| 1327 | 1370 | ||
| 1328 | fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { | 1371 | fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { |
| ... | @@ -1338,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize | ... | @@ -1338,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize |
| 1338 | } | 1381 | } |
| 1339 | 1382 | ||
| 1340 | fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { | 1383 | fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { |
| 1341 | const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size); | 1384 | const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size); |
| 1342 | return parseFormValueBlockLen(allocator, in_stream, block_len); | 1385 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 1343 | } | 1386 | } |
| 1344 | 1387 | ||
| ... | @@ -1352,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo | ... | @@ -1352,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo |
| 1352 | } | 1395 | } |
| 1353 | 1396 | ||
| 1354 | fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { | 1397 | fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { |
| 1355 | return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32)); | 1398 | return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32)); |
| 1356 | } | 1399 | } |
| 1357 | 1400 | ||
| 1358 | fn parseFormValueTargetAddrSize(in_stream: var) !u64 { | 1401 | fn parseFormValueTargetAddrSize(in_stream: var) !u64 { |
| 1359 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable; | 1402 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable; |
| 1360 | } | 1403 | } |
| 1361 | 1404 | ||
| 1362 | fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { | 1405 | fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { |
| ... | @@ -1365,18 +1408,11 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) | ... | @@ -1365,18 +1408,11 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) |
| 1365 | } | 1408 | } |
| 1366 | 1409 | ||
| 1367 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { | 1410 | fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { |
| 1368 | const block_len = try in_stream.readIntLe(T); | 1411 | const block_len = try in_stream.readIntLittle(T); |
| 1369 | return parseFormValueRefLen(allocator, in_stream, block_len); | 1412 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 1370 | } | 1413 | } |
| 1371 | 1414 | ||
| 1372 | const ParseFormValueError = error{ | 1415 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { |
| 1373 | EndOfStream, | ||
| 1374 | InvalidDebugInfo, | ||
| 1375 | EndOfFile, | ||
| 1376 | OutOfMemory, | ||
| 1377 | } || std.os.File.ReadError; | ||
| 1378 | |||
| 1379 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue { | ||
| 1380 | return switch (form_id) { | 1416 | return switch (form_id) { |
| 1381 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, | 1417 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 1382 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), | 1418 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| ... | @@ -1414,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 | ... | @@ -1414,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1414 | }, | 1450 | }, |
| 1415 | 1451 | ||
| 1416 | DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, | 1452 | DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| 1417 | DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) }, | 1453 | DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) }, |
| 1418 | 1454 | ||
| 1419 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, | 1455 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, |
| 1420 | DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, | 1456 | DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, |
| ... | @@ -1426,25 +1462,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 | ... | @@ -1426,25 +1462,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1426 | }; | 1462 | }; |
| 1427 | } | 1463 | } |
| 1428 | 1464 | ||
| 1429 | fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { | 1465 | fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable { |
| 1430 | const in_file = st.self_exe_file; | 1466 | var result = AbbrevTable.init(di.allocator()); |
| 1431 | var in_file_stream = in_file.inStream(); | ||
| 1432 | const in_stream = &in_file_stream.stream; | ||
| 1433 | var result = AbbrevTable.init(st.allocator()); | ||
| 1434 | while (true) { | 1467 | while (true) { |
| 1435 | const abbrev_code = try readULeb128(in_stream); | 1468 | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1436 | if (abbrev_code == 0) return result; | 1469 | if (abbrev_code == 0) return result; |
| 1437 | try result.append(AbbrevTableEntry{ | 1470 | try result.append(AbbrevTableEntry{ |
| 1438 | .abbrev_code = abbrev_code, | 1471 | .abbrev_code = abbrev_code, |
| 1439 | .tag_id = try readULeb128(in_stream), | 1472 | .tag_id = try readULeb128(di.dwarf_in_stream), |
| 1440 | .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, | 1473 | .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, |
| 1441 | .attrs = ArrayList(AbbrevAttr).init(st.allocator()), | 1474 | .attrs = ArrayList(AbbrevAttr).init(di.allocator()), |
| 1442 | }); | 1475 | }); |
| 1443 | const attrs = &result.items[result.len - 1].attrs; | 1476 | const attrs = &result.items[result.len - 1].attrs; |
| 1444 | 1477 | ||
| 1445 | while (true) { | 1478 | while (true) { |
| 1446 | const attr_id = try readULeb128(in_stream); | 1479 | const attr_id = try readULeb128(di.dwarf_in_stream); |
| 1447 | const form_id = try readULeb128(in_stream); | 1480 | const form_id = try readULeb128(di.dwarf_in_stream); |
| 1448 | if (attr_id == 0 and form_id == 0) break; | 1481 | if (attr_id == 0 and form_id == 0) break; |
| 1449 | try attrs.append(AbbrevAttr{ | 1482 | try attrs.append(AbbrevAttr{ |
| 1450 | .attr_id = attr_id, | 1483 | .attr_id = attr_id, |
| ... | @@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { | ... | @@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { |
| 1456 | 1489 | ||
| 1457 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, | 1490 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, |
| 1458 | /// seeks in the stream and parses it. | 1491 | /// seeks in the stream and parses it. |
| 1459 | fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { | 1492 | fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable { |
| 1460 | for (st.abbrev_table_list.toSlice()) |*header| { | 1493 | for (di.abbrev_table_list.toSlice()) |*header| { |
| 1461 | if (header.offset == abbrev_offset) { | 1494 | if (header.offset == abbrev_offset) { |
| 1462 | return &header.table; | 1495 | return &header.table; |
| 1463 | } | 1496 | } |
| 1464 | } | 1497 | } |
| 1465 | try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); | 1498 | try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset); |
| 1466 | try st.abbrev_table_list.append(AbbrevTableHeader{ | 1499 | try di.abbrev_table_list.append(AbbrevTableHeader{ |
| 1467 | .offset = abbrev_offset, | 1500 | .offset = abbrev_offset, |
| 1468 | .table = try parseAbbrevTable(st), | 1501 | .table = try parseAbbrevTable(di), |
| 1469 | }); | 1502 | }); |
| 1470 | return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table; | 1503 | return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table; |
| 1471 | } | 1504 | } |
| 1472 | 1505 | ||
| 1473 | fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry { | 1506 | fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry { |
| ... | @@ -1477,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con | ... | @@ -1477,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con |
| 1477 | return null; | 1510 | return null; |
| 1478 | } | 1511 | } |
| 1479 | 1512 | ||
| 1480 | fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { | 1513 | fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { |
| 1481 | const in_file = st.self_exe_file; | 1514 | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1482 | var in_file_stream = in_file.inStream(); | ||
| 1483 | const in_stream = &in_file_stream.stream; | ||
| 1484 | const abbrev_code = try readULeb128(in_stream); | ||
| 1485 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; | 1515 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1486 | 1516 | ||
| 1487 | var result = Die{ | 1517 | var result = Die{ |
| 1488 | .tag_id = table_entry.tag_id, | 1518 | .tag_id = table_entry.tag_id, |
| 1489 | .has_children = table_entry.has_children, | 1519 | .has_children = table_entry.has_children, |
| 1490 | .attrs = ArrayList(Die.Attr).init(st.allocator()), | 1520 | .attrs = ArrayList(Die.Attr).init(di.allocator()), |
| 1491 | }; | 1521 | }; |
| 1492 | try result.attrs.resize(table_entry.attrs.len); | 1522 | try result.attrs.resize(table_entry.attrs.len); |
| 1493 | for (table_entry.attrs.toSliceConst()) |attr, i| { | 1523 | for (table_entry.attrs.toSliceConst()) |attr, i| { |
| 1494 | result.attrs.items[i] = Die.Attr{ | 1524 | result.attrs.items[i] = Die.Attr{ |
| 1495 | .id = attr.attr_id, | 1525 | .id = attr.attr_id, |
| 1496 | .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), | 1526 | .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64), |
| 1497 | }; | 1527 | }; |
| 1498 | } | 1528 | } |
| 1499 | return result; | 1529 | return result; |
| ... | @@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u | ... | @@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1697 | return error.MissingDebugInfo; | 1727 | return error.MissingDebugInfo; |
| 1698 | } | 1728 | } |
| 1699 | 1729 | ||
| 1700 | fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo { | 1730 | fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { |
| 1701 | const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); | 1731 | const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); |
| 1702 | 1732 | ||
| 1703 | const in_file = di.self_exe_file; | ||
| 1704 | const debug_line_end = di.debug_line.offset + di.debug_line.size; | 1733 | const debug_line_end = di.debug_line.offset + di.debug_line.size; |
| 1705 | var this_offset = di.debug_line.offset; | 1734 | var this_offset = di.debug_line.offset; |
| 1706 | var this_index: usize = 0; | 1735 | var this_index: usize = 0; |
| 1707 | 1736 | ||
| 1708 | var in_file_stream = in_file.inStream(); | ||
| 1709 | const in_stream = &in_file_stream.stream; | ||
| 1710 | |||
| 1711 | while (this_offset < debug_line_end) : (this_index += 1) { | 1737 | while (this_offset < debug_line_end) : (this_index += 1) { |
| 1712 | try in_file.seekTo(this_offset); | 1738 | try di.dwarf_seekable_stream.seekTo(this_offset); |
| 1713 | 1739 | ||
| 1714 | var is_64: bool = undefined; | 1740 | var is_64: bool = undefined; |
| 1715 | const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); | 1741 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); |
| 1716 | if (unit_length == 0) return error.MissingDebugInfo; | 1742 | if (unit_length == 0) return error.MissingDebugInfo; |
| 1717 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 1743 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 1718 | 1744 | ||
| ... | @@ -1721,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1721,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1721 | continue; | 1747 | continue; |
| 1722 | } | 1748 | } |
| 1723 | 1749 | ||
| 1724 | const version = try in_stream.readInt(di.elf.endian, u16); | 1750 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1725 | // TODO support 3 and 5 | 1751 | // TODO support 3 and 5 |
| 1726 | if (version != 2 and version != 4) return error.InvalidDebugInfo; | 1752 | if (version != 2 and version != 4) return error.InvalidDebugInfo; |
| 1727 | 1753 | ||
| 1728 | const prologue_length = if (is_64) try in_stream.readInt(di.elf.endian, u64) else try in_stream.readInt(di.elf.endian, u32); | 1754 | 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); |
| 1729 | const prog_start_offset = (try in_file.getPos()) + prologue_length; | 1755 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; |
| 1730 | 1756 | ||
| 1731 | const minimum_instruction_length = try in_stream.readByte(); | 1757 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); |
| 1732 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; | 1758 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; |
| 1733 | 1759 | ||
| 1734 | if (version >= 4) { | 1760 | if (version >= 4) { |
| 1735 | // maximum_operations_per_instruction | 1761 | // maximum_operations_per_instruction |
| 1736 | _ = try in_stream.readByte(); | 1762 | _ = try di.dwarf_in_stream.readByte(); |
| 1737 | } | 1763 | } |
| 1738 | 1764 | ||
| 1739 | const default_is_stmt = (try in_stream.readByte()) != 0; | 1765 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; |
| 1740 | const line_base = try in_stream.readByteSigned(); | 1766 | const line_base = try di.dwarf_in_stream.readByteSigned(); |
| 1741 | 1767 | ||
| 1742 | const line_range = try in_stream.readByte(); | 1768 | const line_range = try di.dwarf_in_stream.readByte(); |
| 1743 | if (line_range == 0) return error.InvalidDebugInfo; | 1769 | if (line_range == 0) return error.InvalidDebugInfo; |
| 1744 | 1770 | ||
| 1745 | const opcode_base = try in_stream.readByte(); | 1771 | const opcode_base = try di.dwarf_in_stream.readByte(); |
| 1746 | 1772 | ||
| 1747 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); | 1773 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); |
| 1748 | 1774 | ||
| 1749 | { | 1775 | { |
| 1750 | var i: usize = 0; | 1776 | var i: usize = 0; |
| 1751 | while (i < opcode_base - 1) : (i += 1) { | 1777 | while (i < opcode_base - 1) : (i += 1) { |
| 1752 | standard_opcode_lengths[i] = try in_stream.readByte(); | 1778 | standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); |
| 1753 | } | 1779 | } |
| 1754 | } | 1780 | } |
| 1755 | 1781 | ||
| ... | @@ -1767,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1767,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1767 | while (true) { | 1793 | while (true) { |
| 1768 | const file_name = try di.readString(); | 1794 | const file_name = try di.readString(); |
| 1769 | if (file_name.len == 0) break; | 1795 | if (file_name.len == 0) break; |
| 1770 | const dir_index = try readULeb128(in_stream); | 1796 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1771 | const mtime = try readULeb128(in_stream); | 1797 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1772 | const len_bytes = try readULeb128(in_stream); | 1798 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1773 | try file_entries.append(FileEntry{ | 1799 | try file_entries.append(FileEntry{ |
| 1774 | .file_name = file_name, | 1800 | .file_name = file_name, |
| 1775 | .dir_index = dir_index, | 1801 | .dir_index = dir_index, |
| ... | @@ -1778,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1778,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1778 | }); | 1804 | }); |
| 1779 | } | 1805 | } |
| 1780 | 1806 | ||
| 1781 | try in_file.seekTo(prog_start_offset); | 1807 | try di.dwarf_seekable_stream.seekTo(prog_start_offset); |
| 1782 | 1808 | ||
| 1783 | while (true) { | 1809 | while (true) { |
| 1784 | const opcode = try in_stream.readByte(); | 1810 | const opcode = try di.dwarf_in_stream.readByte(); |
| 1785 | 1811 | ||
| 1786 | if (opcode == DW.LNS_extended_op) { | 1812 | if (opcode == DW.LNS_extended_op) { |
| 1787 | const op_size = try readULeb128(in_stream); | 1813 | const op_size = try readULeb128(di.dwarf_in_stream); |
| 1788 | if (op_size < 1) return error.InvalidDebugInfo; | 1814 | if (op_size < 1) return error.InvalidDebugInfo; |
| 1789 | var sub_op = try in_stream.readByte(); | 1815 | var sub_op = try di.dwarf_in_stream.readByte(); |
| 1790 | switch (sub_op) { | 1816 | switch (sub_op) { |
| 1791 | DW.LNE_end_sequence => { | 1817 | DW.LNE_end_sequence => { |
| 1792 | prog.end_sequence = true; | 1818 | prog.end_sequence = true; |
| ... | @@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1794 | return error.MissingDebugInfo; | 1820 | return error.MissingDebugInfo; |
| 1795 | }, | 1821 | }, |
| 1796 | DW.LNE_set_address => { | 1822 | DW.LNE_set_address => { |
| 1797 | const addr = try in_stream.readInt(di.elf.endian, usize); | 1823 | const addr = try di.dwarf_in_stream.readInt(usize, di.endian); |
| 1798 | prog.address = addr; | 1824 | prog.address = addr; |
| 1799 | }, | 1825 | }, |
| 1800 | DW.LNE_define_file => { | 1826 | DW.LNE_define_file => { |
| 1801 | const file_name = try di.readString(); | 1827 | const file_name = try di.readString(); |
| 1802 | const dir_index = try readULeb128(in_stream); | 1828 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1803 | const mtime = try readULeb128(in_stream); | 1829 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1804 | const len_bytes = try readULeb128(in_stream); | 1830 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1805 | try file_entries.append(FileEntry{ | 1831 | try file_entries.append(FileEntry{ |
| 1806 | .file_name = file_name, | 1832 | .file_name = file_name, |
| 1807 | .dir_index = dir_index, | 1833 | .dir_index = dir_index, |
| ... | @@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1811 | }, | 1837 | }, |
| 1812 | else => { | 1838 | else => { |
| 1813 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; | 1839 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; |
| 1814 | try in_file.seekForward(fwd_amt); | 1840 | try di.dwarf_seekable_stream.seekForward(fwd_amt); |
| 1815 | }, | 1841 | }, |
| 1816 | } | 1842 | } |
| 1817 | } else if (opcode >= opcode_base) { | 1843 | } else if (opcode >= opcode_base) { |
| ... | @@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1830 | prog.basic_block = false; | 1856 | prog.basic_block = false; |
| 1831 | }, | 1857 | }, |
| 1832 | DW.LNS_advance_pc => { | 1858 | DW.LNS_advance_pc => { |
| 1833 | const arg = try readULeb128(in_stream); | 1859 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1834 | prog.address += arg * minimum_instruction_length; | 1860 | prog.address += arg * minimum_instruction_length; |
| 1835 | }, | 1861 | }, |
| 1836 | DW.LNS_advance_line => { | 1862 | DW.LNS_advance_line => { |
| 1837 | const arg = try readILeb128(in_stream); | 1863 | const arg = try readILeb128(di.dwarf_in_stream); |
| 1838 | prog.line += arg; | 1864 | prog.line += arg; |
| 1839 | }, | 1865 | }, |
| 1840 | DW.LNS_set_file => { | 1866 | DW.LNS_set_file => { |
| 1841 | const arg = try readULeb128(in_stream); | 1867 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1842 | prog.file = arg; | 1868 | prog.file = arg; |
| 1843 | }, | 1869 | }, |
| 1844 | DW.LNS_set_column => { | 1870 | DW.LNS_set_column => { |
| 1845 | const arg = try readULeb128(in_stream); | 1871 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1846 | prog.column = arg; | 1872 | prog.column = arg; |
| 1847 | }, | 1873 | }, |
| 1848 | DW.LNS_negate_stmt => { | 1874 | DW.LNS_negate_stmt => { |
| ... | @@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1856 | prog.address += inc_addr; | 1882 | prog.address += inc_addr; |
| 1857 | }, | 1883 | }, |
| 1858 | DW.LNS_fixed_advance_pc => { | 1884 | DW.LNS_fixed_advance_pc => { |
| 1859 | const arg = try in_stream.readInt(di.elf.endian, u16); | 1885 | const arg = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1860 | prog.address += arg; | 1886 | prog.address += arg; |
| 1861 | }, | 1887 | }, |
| 1862 | DW.LNS_set_prologue_end => {}, | 1888 | DW.LNS_set_prologue_end => {}, |
| 1863 | else => { | 1889 | else => { |
| 1864 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; | 1890 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; |
| 1865 | const len_bytes = standard_opcode_lengths[opcode - 1]; | 1891 | const len_bytes = standard_opcode_lengths[opcode - 1]; |
| 1866 | try in_file.seekForward(len_bytes); | 1892 | try di.dwarf_seekable_stream.seekForward(len_bytes); |
| 1867 | }, | 1893 | }, |
| 1868 | } | 1894 | } |
| 1869 | } | 1895 | } |
| ... | @@ -1875,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1875,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1875 | return error.MissingDebugInfo; | 1901 | return error.MissingDebugInfo; |
| 1876 | } | 1902 | } |
| 1877 | 1903 | ||
| 1878 | fn scanAllCompileUnits(st: *DebugInfo) !void { | 1904 | fn scanAllCompileUnits(di: *DwarfInfo) !void { |
| 1879 | const debug_info_end = st.debug_info.offset + st.debug_info.size; | 1905 | const debug_info_end = di.debug_info.offset + di.debug_info.size; |
| 1880 | var this_unit_offset = st.debug_info.offset; | 1906 | var this_unit_offset = di.debug_info.offset; |
| 1881 | var cu_index: usize = 0; | 1907 | var cu_index: usize = 0; |
| 1882 | 1908 | ||
| 1883 | var in_file_stream = st.self_exe_file.inStream(); | ||
| 1884 | const in_stream = &in_file_stream.stream; | ||
| 1885 | |||
| 1886 | while (this_unit_offset < debug_info_end) { | 1909 | while (this_unit_offset < debug_info_end) { |
| 1887 | try st.self_exe_file.seekTo(this_unit_offset); | 1910 | try di.dwarf_seekable_stream.seekTo(this_unit_offset); |
| 1888 | 1911 | ||
| 1889 | var is_64: bool = undefined; | 1912 | var is_64: bool = undefined; |
| 1890 | const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); | 1913 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); |
| 1891 | if (unit_length == 0) return; | 1914 | if (unit_length == 0) return; |
| 1892 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 1915 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 1893 | 1916 | ||
| 1894 | const version = try in_stream.readInt(st.elf.endian, u16); | 1917 | const version = try di.dwarf_in_stream.readInt(u16, di.endian); |
| 1895 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | 1918 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 1896 | 1919 | ||
| 1897 | const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32); | 1920 | 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); |
| 1898 | 1921 | ||
| 1899 | const address_size = try in_stream.readByte(); | 1922 | const address_size = try di.dwarf_in_stream.readByte(); |
| 1900 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; | 1923 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| 1901 | 1924 | ||
| 1902 | const compile_unit_pos = try st.self_exe_file.getPos(); | 1925 | const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); |
| 1903 | const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset); | 1926 | const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset); |
| 1904 | 1927 | ||
| 1905 | try st.self_exe_file.seekTo(compile_unit_pos); | 1928 | try di.dwarf_seekable_stream.seekTo(compile_unit_pos); |
| 1906 | 1929 | ||
| 1907 | const compile_unit_die = try st.allocator().create(try parseDie(st, abbrev_table, is_64)); | 1930 | const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64)); |
| 1908 | 1931 | ||
| 1909 | 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; |
| 1910 | 1933 | ||
| ... | @@ -1932,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { | ... | @@ -1932,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { |
| 1932 | } | 1955 | } |
| 1933 | }; | 1956 | }; |
| 1934 | 1957 | ||
| 1935 | try st.compile_unit_list.append(CompileUnit{ | 1958 | try di.compile_unit_list.append(CompileUnit{ |
| 1936 | .version = version, | 1959 | .version = version, |
| 1937 | .is_64 = is_64, | 1960 | .is_64 = is_64, |
| 1938 | .pc_range = pc_range, | 1961 | .pc_range = pc_range, |
| ... | @@ -1945,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { | ... | @@ -1945,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { |
| 1945 | } | 1968 | } |
| 1946 | } | 1969 | } |
| 1947 | 1970 | ||
| 1948 | fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit { | 1971 | fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { |
| 1949 | var in_file_stream = st.self_exe_file.inStream(); | 1972 | for (di.compile_unit_list.toSlice()) |*compile_unit| { |
| 1950 | const in_stream = &in_file_stream.stream; | ||
| 1951 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | ||
| 1952 | if (compile_unit.pc_range) |range| { | 1973 | if (compile_unit.pc_range) |range| { |
| 1953 | if (target_address >= range.start and target_address < range.end) return compile_unit; | 1974 | if (target_address >= range.start and target_address < range.end) return compile_unit; |
| 1954 | } | 1975 | } |
| 1955 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { | 1976 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { |
| 1956 | var base_address: usize = 0; | 1977 | var base_address: usize = 0; |
| 1957 | if (st.debug_ranges) |debug_ranges| { | 1978 | if (di.debug_ranges) |debug_ranges| { |
| 1958 | try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); | 1979 | try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); |
| 1959 | while (true) { | 1980 | while (true) { |
| 1960 | const begin_addr = try in_stream.readIntLe(usize); | 1981 | const begin_addr = try di.dwarf_in_stream.readIntLittle(usize); |
| 1961 | const end_addr = try in_stream.readIntLe(usize); | 1982 | const end_addr = try di.dwarf_in_stream.readIntLittle(usize); |
| 1962 | if (begin_addr == 0 and end_addr == 0) { | 1983 | if (begin_addr == 0 and end_addr == 0) { |
| 1963 | break; | 1984 | break; |
| 1964 | } | 1985 | } |
| ... | @@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit { | ... | @@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit { |
| 1980 | } | 2001 | } |
| 1981 | 2002 | ||
| 1982 | 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 { |
| 1983 | 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); | ||
| 1984 | ptr.* += @sizeOf(T); | 2006 | ptr.* += @sizeOf(T); |
| 1985 | return result; | 2007 | return result; |
| 1986 | } | 2008 | } |
| ... | @@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 { | ... | @@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 { |
| 1996 | } | 2018 | } |
| 1997 | 2019 | ||
| 1998 | fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { | 2020 | fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { |
| 1999 | 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]); | ||
| 2000 | is_64.* = (first_32_bits == 0xffffffff); | 2023 | is_64.* = (first_32_bits == 0xffffffff); |
| 2001 | if (is_64.*) { | 2024 | if (is_64.*) { |
| 2002 | ptr.* += 4; | 2025 | ptr.* += 4; |
| 2003 | const result = mem.readIntLE(u64, ptr.*[0..8]); | 2026 | const result = mem.readIntSliceLittle(u64, ptr.*[0..8]); |
| 2004 | ptr.* += 8; | 2027 | ptr.* += 8; |
| 2005 | return result; | 2028 | return result; |
| 2006 | } else { | 2029 | } else { |
| ... | @@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { | ... | @@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { |
| 2063 | } | 2086 | } |
| 2064 | 2087 | ||
| 2065 | 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 { |
| 2066 | const first_32_bits = try in_stream.readIntLe(u32); | 2089 | const first_32_bits = try in_stream.readIntLittle(u32); |
| 2067 | is_64.* = (first_32_bits == 0xffffffff); | 2090 | is_64.* = (first_32_bits == 0xffffffff); |
| 2068 | if (is_64.*) { | 2091 | if (is_64.*) { |
| 2069 | return in_stream.readIntLe(u64); | 2092 | return in_stream.readIntLittle(u64); |
| 2070 | } else { | 2093 | } else { |
| 2071 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; | 2094 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; |
| 2072 | return u64(first_32_bits); | 2095 | return u64(first_32_bits); |
std/dynamic_library.zig+1-3| ... | @@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) { | ... | @@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) { |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | pub const LinuxDynLib = struct { | 21 | pub const LinuxDynLib = struct { |
| 22 | allocator: *mem.Allocator, | ||
| 23 | elf_lib: ElfLib, | 22 | elf_lib: ElfLib, |
| 24 | fd: i32, | 23 | fd: i32, |
| 25 | map_addr: usize, | 24 | map_addr: usize, |
| ... | @@ -27,7 +26,7 @@ pub const LinuxDynLib = struct { | ... | @@ -27,7 +26,7 @@ pub const LinuxDynLib = struct { |
| 27 | 26 | ||
| 28 | /// Trusts the file | 27 | /// Trusts the file |
| 29 | pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib { | 28 | 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); | 29 | const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC); |
| 31 | errdefer std.os.close(fd); | 30 | errdefer std.os.close(fd); |
| 32 | 31 | ||
| 33 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); | 32 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); |
| ... | @@ -45,7 +44,6 @@ pub const LinuxDynLib = struct { | ... | @@ -45,7 +44,6 @@ pub const LinuxDynLib = struct { |
| 45 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; | 44 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; |
| 46 | 45 | ||
| 47 | return DynLib{ | 46 | return DynLib{ |
| 48 | .allocator = allocator, | ||
| 49 | .elf_lib = try ElfLib.init(bytes), | 47 | .elf_lib = try ElfLib.init(bytes), |
| 50 | .fd = fd, | 48 | .fd = fd, |
| 51 | .map_addr = addr, | 49 | .map_addr = addr, |
std/elf.zig+59-56| ... | @@ -353,7 +353,8 @@ pub const SectionHeader = struct { | ... | @@ -353,7 +353,8 @@ pub const SectionHeader = struct { |
| 353 | }; | 353 | }; |
| 354 | 354 | ||
| 355 | pub const Elf = struct { | 355 | pub const Elf = struct { |
| 356 | in_file: os.File, | 356 | seekable_stream: *io.SeekableStream(anyerror, anyerror), |
| 357 | in_stream: *io.InStream(anyerror), | ||
| 357 | auto_close_stream: bool, | 358 | auto_close_stream: bool, |
| 358 | is_64: bool, | 359 | is_64: bool, |
| 359 | endian: builtin.Endian, | 360 | endian: builtin.Endian, |
| ... | @@ -370,19 +371,24 @@ pub const Elf = struct { | ... | @@ -370,19 +371,24 @@ pub const Elf = struct { |
| 370 | 371 | ||
| 371 | /// Call close when done. | 372 | /// Call close when done. |
| 372 | pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void { | 373 | pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void { |
| 373 | try elf.prealloc_file.open(path); | 374 | @compileError("TODO implement"); |
| 374 | try elf.openFile(allocator, *elf.prealloc_file); | ||
| 375 | elf.auto_close_stream = true; | ||
| 376 | } | 375 | } |
| 377 | 376 | ||
| 378 | /// Call close when done. | 377 | /// Call close when done. |
| 379 | pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void { | 378 | pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void { |
| 380 | elf.allocator = allocator; | 379 | @compileError("TODO implement"); |
| 381 | elf.in_file = file; | 380 | } |
| 382 | elf.auto_close_stream = false; | ||
| 383 | 381 | ||
| 384 | var file_stream = elf.in_file.inStream(); | 382 | pub fn openStream( |
| 385 | const in = &file_stream.stream; | 383 | elf: *Elf, |
| 384 | allocator: *mem.Allocator, | ||
| 385 | seekable_stream: *io.SeekableStream(anyerror, anyerror), | ||
| 386 | in: *io.InStream(anyerror), | ||
| 387 | ) !void { | ||
| 388 | elf.auto_close_stream = false; | ||
| 389 | elf.allocator = allocator; | ||
| 390 | elf.seekable_stream = seekable_stream; | ||
| 391 | elf.in_stream = in; | ||
| 386 | 392 | ||
| 387 | var magic: [4]u8 = undefined; | 393 | var magic: [4]u8 = undefined; |
| 388 | try in.readNoEof(magic[0..]); | 394 | try in.readNoEof(magic[0..]); |
| ... | @@ -404,9 +410,9 @@ pub const Elf = struct { | ... | @@ -404,9 +410,9 @@ pub const Elf = struct { |
| 404 | if (version_byte != 1) return error.InvalidFormat; | 410 | if (version_byte != 1) return error.InvalidFormat; |
| 405 | 411 | ||
| 406 | // skip over padding | 412 | // skip over padding |
| 407 | try elf.in_file.seekForward(9); | 413 | try seekable_stream.seekForward(9); |
| 408 | 414 | ||
| 409 | elf.file_type = switch (try in.readInt(elf.endian, u16)) { | 415 | elf.file_type = switch (try in.readInt(u16, elf.endian)) { |
| 410 | 1 => FileType.Relocatable, | 416 | 1 => FileType.Relocatable, |
| 411 | 2 => FileType.Executable, | 417 | 2 => FileType.Executable, |
| 412 | 3 => FileType.Shared, | 418 | 3 => FileType.Shared, |
| ... | @@ -414,7 +420,7 @@ pub const Elf = struct { | ... | @@ -414,7 +420,7 @@ pub const Elf = struct { |
| 414 | else => return error.InvalidFormat, | 420 | else => return error.InvalidFormat, |
| 415 | }; | 421 | }; |
| 416 | 422 | ||
| 417 | elf.arch = switch (try in.readInt(elf.endian, u16)) { | 423 | elf.arch = switch (try in.readInt(u16, elf.endian)) { |
| 418 | 0x02 => Arch.Sparc, | 424 | 0x02 => Arch.Sparc, |
| 419 | 0x03 => Arch.x86, | 425 | 0x03 => Arch.x86, |
| 420 | 0x08 => Arch.Mips, | 426 | 0x08 => Arch.Mips, |
| ... | @@ -427,32 +433,32 @@ pub const Elf = struct { | ... | @@ -427,32 +433,32 @@ pub const Elf = struct { |
| 427 | else => return error.InvalidFormat, | 433 | else => return error.InvalidFormat, |
| 428 | }; | 434 | }; |
| 429 | 435 | ||
| 430 | const elf_version = try in.readInt(elf.endian, u32); | 436 | const elf_version = try in.readInt(u32, elf.endian); |
| 431 | if (elf_version != 1) return error.InvalidFormat; | 437 | if (elf_version != 1) return error.InvalidFormat; |
| 432 | 438 | ||
| 433 | if (elf.is_64) { | 439 | if (elf.is_64) { |
| 434 | elf.entry_addr = try in.readInt(elf.endian, u64); | 440 | elf.entry_addr = try in.readInt(u64, elf.endian); |
| 435 | elf.program_header_offset = try in.readInt(elf.endian, u64); | 441 | elf.program_header_offset = try in.readInt(u64, elf.endian); |
| 436 | elf.section_header_offset = try in.readInt(elf.endian, u64); | 442 | elf.section_header_offset = try in.readInt(u64, elf.endian); |
| 437 | } else { | 443 | } else { |
| 438 | elf.entry_addr = u64(try in.readInt(elf.endian, u32)); | 444 | elf.entry_addr = u64(try in.readInt(u32, elf.endian)); |
| 439 | elf.program_header_offset = u64(try in.readInt(elf.endian, u32)); | 445 | elf.program_header_offset = u64(try in.readInt(u32, elf.endian)); |
| 440 | elf.section_header_offset = u64(try in.readInt(elf.endian, u32)); | 446 | elf.section_header_offset = u64(try in.readInt(u32, elf.endian)); |
| 441 | } | 447 | } |
| 442 | 448 | ||
| 443 | // skip over flags | 449 | // skip over flags |
| 444 | try elf.in_file.seekForward(4); | 450 | try seekable_stream.seekForward(4); |
| 445 | 451 | ||
| 446 | const header_size = try in.readInt(elf.endian, u16); | 452 | const header_size = try in.readInt(u16, elf.endian); |
| 447 | 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)) { |
| 448 | return error.InvalidFormat; | 454 | return error.InvalidFormat; |
| 449 | } | 455 | } |
| 450 | 456 | ||
| 451 | const ph_entry_size = try in.readInt(elf.endian, u16); | 457 | const ph_entry_size = try in.readInt(u16, elf.endian); |
| 452 | const ph_entry_count = try in.readInt(elf.endian, u16); | 458 | const ph_entry_count = try in.readInt(u16, elf.endian); |
| 453 | const sh_entry_size = try in.readInt(elf.endian, u16); | 459 | const sh_entry_size = try in.readInt(u16, elf.endian); |
| 454 | const sh_entry_count = try in.readInt(elf.endian, u16); | 460 | const sh_entry_count = try in.readInt(u16, elf.endian); |
| 455 | elf.string_section_index = u64(try in.readInt(elf.endian, u16)); | 461 | elf.string_section_index = u64(try in.readInt(u16, elf.endian)); |
| 456 | 462 | ||
| 457 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; | 463 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; |
| 458 | 464 | ||
| ... | @@ -461,12 +467,12 @@ pub const Elf = struct { | ... | @@ -461,12 +467,12 @@ pub const Elf = struct { |
| 461 | const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count); | 467 | const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count); |
| 462 | const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count); | 468 | const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count); |
| 463 | 469 | ||
| 464 | const stream_end = try elf.in_file.getEndPos(); | 470 | const stream_end = try seekable_stream.getEndPos(); |
| 465 | if (stream_end < end_sh or stream_end < end_ph) { | 471 | if (stream_end < end_sh or stream_end < end_ph) { |
| 466 | return error.InvalidFormat; | 472 | return error.InvalidFormat; |
| 467 | } | 473 | } |
| 468 | 474 | ||
| 469 | try elf.in_file.seekTo(elf.section_header_offset); | 475 | try seekable_stream.seekTo(elf.section_header_offset); |
| 470 | 476 | ||
| 471 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); | 477 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); |
| 472 | errdefer elf.allocator.free(elf.section_headers); | 478 | errdefer elf.allocator.free(elf.section_headers); |
| ... | @@ -475,32 +481,32 @@ pub const Elf = struct { | ... | @@ -475,32 +481,32 @@ pub const Elf = struct { |
| 475 | if (sh_entry_size != 64) return error.InvalidFormat; | 481 | if (sh_entry_size != 64) return error.InvalidFormat; |
| 476 | 482 | ||
| 477 | for (elf.section_headers) |*elf_section| { | 483 | for (elf.section_headers) |*elf_section| { |
| 478 | elf_section.name = try in.readInt(elf.endian, u32); | 484 | elf_section.name = try in.readInt(u32, elf.endian); |
| 479 | elf_section.sh_type = try in.readInt(elf.endian, u32); | 485 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 480 | elf_section.flags = try in.readInt(elf.endian, u64); | 486 | elf_section.flags = try in.readInt(u64, elf.endian); |
| 481 | elf_section.addr = try in.readInt(elf.endian, u64); | 487 | elf_section.addr = try in.readInt(u64, elf.endian); |
| 482 | elf_section.offset = try in.readInt(elf.endian, u64); | 488 | elf_section.offset = try in.readInt(u64, elf.endian); |
| 483 | elf_section.size = try in.readInt(elf.endian, u64); | 489 | elf_section.size = try in.readInt(u64, elf.endian); |
| 484 | elf_section.link = try in.readInt(elf.endian, u32); | 490 | elf_section.link = try in.readInt(u32, elf.endian); |
| 485 | elf_section.info = try in.readInt(elf.endian, u32); | 491 | elf_section.info = try in.readInt(u32, elf.endian); |
| 486 | elf_section.addr_align = try in.readInt(elf.endian, u64); | 492 | elf_section.addr_align = try in.readInt(u64, elf.endian); |
| 487 | elf_section.ent_size = try in.readInt(elf.endian, u64); | 493 | elf_section.ent_size = try in.readInt(u64, elf.endian); |
| 488 | } | 494 | } |
| 489 | } else { | 495 | } else { |
| 490 | if (sh_entry_size != 40) return error.InvalidFormat; | 496 | if (sh_entry_size != 40) return error.InvalidFormat; |
| 491 | 497 | ||
| 492 | for (elf.section_headers) |*elf_section| { | 498 | for (elf.section_headers) |*elf_section| { |
| 493 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? | 499 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? |
| 494 | elf_section.name = try in.readInt(elf.endian, u32); | 500 | elf_section.name = try in.readInt(u32, elf.endian); |
| 495 | elf_section.sh_type = try in.readInt(elf.endian, u32); | 501 | elf_section.sh_type = try in.readInt(u32, elf.endian); |
| 496 | elf_section.flags = u64(try in.readInt(elf.endian, u32)); | 502 | elf_section.flags = u64(try in.readInt(u32, elf.endian)); |
| 497 | elf_section.addr = u64(try in.readInt(elf.endian, u32)); | 503 | elf_section.addr = u64(try in.readInt(u32, elf.endian)); |
| 498 | elf_section.offset = u64(try in.readInt(elf.endian, u32)); | 504 | elf_section.offset = u64(try in.readInt(u32, elf.endian)); |
| 499 | elf_section.size = u64(try in.readInt(elf.endian, u32)); | 505 | elf_section.size = u64(try in.readInt(u32, elf.endian)); |
| 500 | elf_section.link = try in.readInt(elf.endian, u32); | 506 | elf_section.link = try in.readInt(u32, elf.endian); |
| 501 | elf_section.info = try in.readInt(elf.endian, u32); | 507 | elf_section.info = try in.readInt(u32, elf.endian); |
| 502 | elf_section.addr_align = u64(try in.readInt(elf.endian, u32)); | 508 | elf_section.addr_align = u64(try in.readInt(u32, elf.endian)); |
| 503 | elf_section.ent_size = u64(try in.readInt(elf.endian, u32)); | 509 | elf_section.ent_size = u64(try in.readInt(u32, elf.endian)); |
| 504 | } | 510 | } |
| 505 | } | 511 | } |
| 506 | 512 | ||
| ... | @@ -521,26 +527,23 @@ pub const Elf = struct { | ... | @@ -521,26 +527,23 @@ pub const Elf = struct { |
| 521 | pub fn close(elf: *Elf) void { | 527 | pub fn close(elf: *Elf) void { |
| 522 | elf.allocator.free(elf.section_headers); | 528 | elf.allocator.free(elf.section_headers); |
| 523 | 529 | ||
| 524 | if (elf.auto_close_stream) elf.in_file.close(); | 530 | if (elf.auto_close_stream) elf.prealloc_file.close(); |
| 525 | } | 531 | } |
| 526 | 532 | ||
| 527 | pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader { | 533 | pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader { |
| 528 | var file_stream = elf.in_file.inStream(); | ||
| 529 | const in = &file_stream.stream; | ||
| 530 | |||
| 531 | section_loop: for (elf.section_headers) |*elf_section| { | 534 | section_loop: for (elf.section_headers) |*elf_section| { |
| 532 | if (elf_section.sh_type == SHT_NULL) continue; | 535 | if (elf_section.sh_type == SHT_NULL) continue; |
| 533 | 536 | ||
| 534 | const name_offset = elf.string_section.offset + elf_section.name; | 537 | const name_offset = elf.string_section.offset + elf_section.name; |
| 535 | try elf.in_file.seekTo(name_offset); | 538 | try elf.seekable_stream.seekTo(name_offset); |
| 536 | 539 | ||
| 537 | for (name) |expected_c| { | 540 | for (name) |expected_c| { |
| 538 | const target_c = try in.readByte(); | 541 | const target_c = try elf.in_stream.readByte(); |
| 539 | if (target_c == 0 or expected_c != target_c) continue :section_loop; | 542 | if (target_c == 0 or expected_c != target_c) continue :section_loop; |
| 540 | } | 543 | } |
| 541 | 544 | ||
| 542 | { | 545 | { |
| 543 | const null_byte = try in.readByte(); | 546 | const null_byte = try elf.in_stream.readByte(); |
| 544 | if (null_byte == 0) return elf_section; | 547 | if (null_byte == 0) return elf_section; |
| 545 | } | 548 | } |
| 546 | } | 549 | } |
| ... | @@ -549,7 +552,7 @@ pub const Elf = struct { | ... | @@ -549,7 +552,7 @@ pub const Elf = struct { |
| 549 | } | 552 | } |
| 550 | 553 | ||
| 551 | pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void { | 554 | pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void { |
| 552 | try elf.in_file.seekTo(elf_section.offset); | 555 | try elf.seekable_stream.seekTo(elf_section.offset); |
| 553 | } | 556 | } |
| 554 | }; | 557 | }; |
| 555 | 558 |
std/event/fs.zig+21-10| ... | @@ -83,6 +83,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o | ... | @@ -83,6 +83,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o |
| 83 | switch (builtin.os) { | 83 | switch (builtin.os) { |
| 84 | builtin.Os.macosx, | 84 | builtin.Os.macosx, |
| 85 | builtin.Os.linux, | 85 | builtin.Os.linux, |
| 86 | builtin.Os.freebsd, | ||
| 86 | => { | 87 | => { |
| 87 | const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len); | 88 | const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len); |
| 88 | defer loop.allocator.free(iovecs); | 89 | defer loop.allocator.free(iovecs); |
| ... | @@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: | ... | @@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: |
| 219 | switch (builtin.os) { | 220 | switch (builtin.os) { |
| 220 | builtin.Os.macosx, | 221 | builtin.Os.macosx, |
| 221 | builtin.Os.linux, | 222 | builtin.Os.linux, |
| 223 | builtin.Os.freebsd, | ||
| 222 | => { | 224 | => { |
| 223 | const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len); | 225 | const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len); |
| 224 | defer loop.allocator.free(iovecs); | 226 | defer loop.allocator.free(iovecs); |
| ... | @@ -399,7 +401,7 @@ pub async fn openPosix( | ... | @@ -399,7 +401,7 @@ pub async fn openPosix( |
| 399 | 401 | ||
| 400 | pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle { | 402 | pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle { |
| 401 | switch (builtin.os) { | 403 | switch (builtin.os) { |
| 402 | builtin.Os.macosx, builtin.Os.linux => { | 404 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => { |
| 403 | const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC; | 405 | const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC; |
| 404 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); | 406 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); |
| 405 | }, | 407 | }, |
| ... | @@ -427,6 +429,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os | ... | @@ -427,6 +429,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os |
| 427 | switch (builtin.os) { | 429 | switch (builtin.os) { |
| 428 | builtin.Os.macosx, | 430 | builtin.Os.macosx, |
| 429 | builtin.Os.linux, | 431 | builtin.Os.linux, |
| 432 | builtin.Os.freebsd, | ||
| 430 | => { | 433 | => { |
| 431 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC; | 434 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC; |
| 432 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); | 435 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); |
| ... | @@ -449,7 +452,7 @@ pub async fn openReadWrite( | ... | @@ -449,7 +452,7 @@ pub async fn openReadWrite( |
| 449 | mode: os.File.Mode, | 452 | mode: os.File.Mode, |
| 450 | ) os.File.OpenError!os.FileHandle { | 453 | ) os.File.OpenError!os.FileHandle { |
| 451 | switch (builtin.os) { | 454 | switch (builtin.os) { |
| 452 | builtin.Os.macosx, builtin.Os.linux => { | 455 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => { |
| 453 | const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC; | 456 | const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC; |
| 454 | return await (async openPosix(loop, path, flags, mode) catch unreachable); | 457 | return await (async openPosix(loop, path, flags, mode) catch unreachable); |
| 455 | }, | 458 | }, |
| ... | @@ -477,7 +480,7 @@ pub const CloseOperation = struct { | ... | @@ -477,7 +480,7 @@ pub const CloseOperation = struct { |
| 477 | os_data: OsData, | 480 | os_data: OsData, |
| 478 | 481 | ||
| 479 | const OsData = switch (builtin.os) { | 482 | const OsData = switch (builtin.os) { |
| 480 | builtin.Os.linux, builtin.Os.macosx => OsDataPosix, | 483 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => OsDataPosix, |
| 481 | 484 | ||
| 482 | builtin.Os.windows => struct { | 485 | builtin.Os.windows => struct { |
| 483 | handle: ?os.FileHandle, | 486 | handle: ?os.FileHandle, |
| ... | @@ -496,7 +499,7 @@ pub const CloseOperation = struct { | ... | @@ -496,7 +499,7 @@ pub const CloseOperation = struct { |
| 496 | self.* = CloseOperation{ | 499 | self.* = CloseOperation{ |
| 497 | .loop = loop, | 500 | .loop = loop, |
| 498 | .os_data = switch (builtin.os) { | 501 | .os_data = switch (builtin.os) { |
| 499 | builtin.Os.linux, builtin.Os.macosx => initOsDataPosix(self), | 502 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => initOsDataPosix(self), |
| 500 | builtin.Os.windows => OsData{ .handle = null }, | 503 | builtin.Os.windows => OsData{ .handle = null }, |
| 501 | else => @compileError("Unsupported OS"), | 504 | else => @compileError("Unsupported OS"), |
| 502 | }, | 505 | }, |
| ... | @@ -525,6 +528,7 @@ pub const CloseOperation = struct { | ... | @@ -525,6 +528,7 @@ pub const CloseOperation = struct { |
| 525 | switch (builtin.os) { | 528 | switch (builtin.os) { |
| 526 | builtin.Os.linux, | 529 | builtin.Os.linux, |
| 527 | builtin.Os.macosx, | 530 | builtin.Os.macosx, |
| 531 | builtin.Os.freebsd, | ||
| 528 | => { | 532 | => { |
| 529 | if (self.os_data.have_fd) { | 533 | if (self.os_data.have_fd) { |
| 530 | self.loop.posixFsRequest(&self.os_data.close_req_node); | 534 | self.loop.posixFsRequest(&self.os_data.close_req_node); |
| ... | @@ -546,6 +550,7 @@ pub const CloseOperation = struct { | ... | @@ -546,6 +550,7 @@ pub const CloseOperation = struct { |
| 546 | switch (builtin.os) { | 550 | switch (builtin.os) { |
| 547 | builtin.Os.linux, | 551 | builtin.Os.linux, |
| 548 | builtin.Os.macosx, | 552 | builtin.Os.macosx, |
| 553 | builtin.Os.freebsd, | ||
| 549 | => { | 554 | => { |
| 550 | self.os_data.close_req_node.data.msg.Close.fd = handle; | 555 | self.os_data.close_req_node.data.msg.Close.fd = handle; |
| 551 | self.os_data.have_fd = true; | 556 | self.os_data.have_fd = true; |
| ... | @@ -562,6 +567,7 @@ pub const CloseOperation = struct { | ... | @@ -562,6 +567,7 @@ pub const CloseOperation = struct { |
| 562 | switch (builtin.os) { | 567 | switch (builtin.os) { |
| 563 | builtin.Os.linux, | 568 | builtin.Os.linux, |
| 564 | builtin.Os.macosx, | 569 | builtin.Os.macosx, |
| 570 | builtin.Os.freebsd, | ||
| 565 | => { | 571 | => { |
| 566 | self.os_data.have_fd = false; | 572 | self.os_data.have_fd = false; |
| 567 | }, | 573 | }, |
| ... | @@ -576,6 +582,7 @@ pub const CloseOperation = struct { | ... | @@ -576,6 +582,7 @@ pub const CloseOperation = struct { |
| 576 | switch (builtin.os) { | 582 | switch (builtin.os) { |
| 577 | builtin.Os.linux, | 583 | builtin.Os.linux, |
| 578 | builtin.Os.macosx, | 584 | builtin.Os.macosx, |
| 585 | builtin.Os.freebsd, | ||
| 579 | => { | 586 | => { |
| 580 | assert(self.os_data.have_fd); | 587 | assert(self.os_data.have_fd); |
| 581 | return self.os_data.close_req_node.data.msg.Close.fd; | 588 | return self.os_data.close_req_node.data.msg.Close.fd; |
| ... | @@ -599,6 +606,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, | ... | @@ -599,6 +606,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, |
| 599 | switch (builtin.os) { | 606 | switch (builtin.os) { |
| 600 | builtin.Os.linux, | 607 | builtin.Os.linux, |
| 601 | builtin.Os.macosx, | 608 | builtin.Os.macosx, |
| 609 | builtin.Os.freebsd, | ||
| 602 | => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable), | 610 | => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable), |
| 603 | builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable), | 611 | builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable), |
| 604 | else => @compileError("Unsupported OS"), | 612 | else => @compileError("Unsupported OS"), |
| ... | @@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type { |
| 704 | os_data: OsData, | 712 | os_data: OsData, |
| 705 | 713 | ||
| 706 | const OsData = switch (builtin.os) { | 714 | const OsData = switch (builtin.os) { |
| 707 | builtin.Os.macosx => struct { | 715 | builtin.Os.macosx, builtin.Os.freebsd => struct { |
| 708 | file_table: FileTable, | 716 | file_table: FileTable, |
| 709 | table_lock: event.Lock, | 717 | table_lock: event.Lock, |
| 710 | 718 | ||
| ... | @@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type { |
| 793 | return self; | 801 | return self; |
| 794 | }, | 802 | }, |
| 795 | 803 | ||
| 796 | builtin.Os.macosx => { | 804 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 797 | const self = try loop.allocator.createOne(Self); | 805 | const self = try loop.allocator.createOne(Self); |
| 798 | errdefer loop.allocator.destroy(self); | 806 | errdefer loop.allocator.destroy(self); |
| 799 | 807 | ||
| ... | @@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type { |
| 813 | /// All addFile calls and removeFile calls must have completed. | 821 | /// All addFile calls and removeFile calls must have completed. |
| 814 | pub fn destroy(self: *Self) void { | 822 | pub fn destroy(self: *Self) void { |
| 815 | switch (builtin.os) { | 823 | switch (builtin.os) { |
| 816 | builtin.Os.macosx => { | 824 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 817 | // TODO we need to cancel the coroutines before destroying the lock | 825 | // TODO we need to cancel the coroutines before destroying the lock |
| 818 | self.os_data.table_lock.deinit(); | 826 | self.os_data.table_lock.deinit(); |
| 819 | var it = self.os_data.file_table.iterator(); | 827 | var it = self.os_data.file_table.iterator(); |
| ... | @@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type { | ... | @@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type { |
| 855 | 863 | ||
| 856 | pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V { | 864 | pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V { |
| 857 | switch (builtin.os) { | 865 | switch (builtin.os) { |
| 858 | builtin.Os.macosx => return await (async addFileMacosx(self, file_path, value) catch unreachable), | 866 | builtin.Os.macosx, builtin.Os.freebsd => return await (async addFileKEvent(self, file_path, value) catch unreachable), |
| 859 | builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable), | 867 | builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable), |
| 860 | builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable), | 868 | builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable), |
| 861 | else => @compileError("Unsupported OS"), | 869 | else => @compileError("Unsupported OS"), |
| 862 | } | 870 | } |
| 863 | } | 871 | } |
| 864 | 872 | ||
| 865 | async fn addFileMacosx(self: *Self, file_path: []const u8, value: V) !?V { | 873 | async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V { |
| 866 | const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path); | 874 | const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path); |
| 867 | var resolved_path_consumed = false; | 875 | var resolved_path_consumed = false; |
| 868 | defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path); | 876 | defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path); |
| ... | @@ -871,7 +879,10 @@ pub fn Watch(comptime V: type) type { | ... | @@ -871,7 +879,10 @@ pub fn Watch(comptime V: type) type { |
| 871 | var close_op_consumed = false; | 879 | var close_op_consumed = false; |
| 872 | defer if (!close_op_consumed) close_op.finish(); | 880 | defer if (!close_op_consumed) close_op.finish(); |
| 873 | 881 | ||
| 874 | const flags = posix.O_SYMLINK | posix.O_EVTONLY; | 882 | const flags = switch (builtin.os) { |
| 883 | builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY, | ||
| 884 | else => 0, | ||
| 885 | }; | ||
| 875 | const mode = 0; | 886 | const mode = 0; |
| 876 | const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable); | 887 | const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable); |
| 877 | close_op.setHandle(fd); | 888 | close_op.setHandle(fd); |
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/loop.zig+14-13| ... | @@ -49,7 +49,7 @@ pub const Loop = struct { | ... | @@ -49,7 +49,7 @@ pub const Loop = struct { |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | pub const EventFd = switch (builtin.os) { | 51 | pub const EventFd = switch (builtin.os) { |
| 52 | builtin.Os.macosx => MacOsEventFd, | 52 | builtin.Os.macosx, builtin.Os.freebsd => KEventFd, |
| 53 | builtin.Os.linux => struct { | 53 | builtin.Os.linux => struct { |
| 54 | base: ResumeNode, | 54 | base: ResumeNode, |
| 55 | epoll_op: u32, | 55 | epoll_op: u32, |
| ... | @@ -62,13 +62,13 @@ pub const Loop = struct { | ... | @@ -62,13 +62,13 @@ pub const Loop = struct { |
| 62 | else => @compileError("unsupported OS"), | 62 | else => @compileError("unsupported OS"), |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | const MacOsEventFd = struct { | 65 | const KEventFd = struct { |
| 66 | base: ResumeNode, | 66 | base: ResumeNode, |
| 67 | kevent: posix.Kevent, | 67 | kevent: posix.Kevent, |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | pub const Basic = switch (builtin.os) { | 70 | pub const Basic = switch (builtin.os) { |
| 71 | builtin.Os.macosx => MacOsBasic, | 71 | builtin.Os.macosx, builtin.Os.freebsd => KEventBasic, |
| 72 | builtin.Os.linux => struct { | 72 | builtin.Os.linux => struct { |
| 73 | base: ResumeNode, | 73 | base: ResumeNode, |
| 74 | }, | 74 | }, |
| ... | @@ -78,7 +78,7 @@ pub const Loop = struct { | ... | @@ -78,7 +78,7 @@ pub const Loop = struct { |
| 78 | else => @compileError("unsupported OS"), | 78 | else => @compileError("unsupported OS"), |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const MacOsBasic = struct { | 81 | const KEventBasic = struct { |
| 82 | base: ResumeNode, | 82 | base: ResumeNode, |
| 83 | kev: posix.Kevent, | 83 | kev: posix.Kevent, |
| 84 | }; | 84 | }; |
| ... | @@ -214,7 +214,7 @@ pub const Loop = struct { | ... | @@ -214,7 +214,7 @@ pub const Loop = struct { |
| 214 | self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun); | 214 | self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun); |
| 215 | } | 215 | } |
| 216 | }, | 216 | }, |
| 217 | builtin.Os.macosx => { | 217 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 218 | self.os_data.kqfd = try os.bsdKQueue(); | 218 | self.os_data.kqfd = try os.bsdKQueue(); |
| 219 | errdefer os.close(self.os_data.kqfd); | 219 | errdefer os.close(self.os_data.kqfd); |
| 220 | 220 | ||
| ... | @@ -369,7 +369,7 @@ pub const Loop = struct { | ... | @@ -369,7 +369,7 @@ pub const Loop = struct { |
| 369 | os.close(self.os_data.epollfd); | 369 | os.close(self.os_data.epollfd); |
| 370 | self.allocator.free(self.eventfd_resume_nodes); | 370 | self.allocator.free(self.eventfd_resume_nodes); |
| 371 | }, | 371 | }, |
| 372 | builtin.Os.macosx => { | 372 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 373 | os.close(self.os_data.kqfd); | 373 | os.close(self.os_data.kqfd); |
| 374 | os.close(self.os_data.fs_kqfd); | 374 | os.close(self.os_data.fs_kqfd); |
| 375 | }, | 375 | }, |
| ... | @@ -484,7 +484,7 @@ pub const Loop = struct { | ... | @@ -484,7 +484,7 @@ pub const Loop = struct { |
| 484 | const eventfd_node = &resume_stack_node.data; | 484 | const eventfd_node = &resume_stack_node.data; |
| 485 | eventfd_node.base.handle = next_tick_node.data; | 485 | eventfd_node.base.handle = next_tick_node.data; |
| 486 | switch (builtin.os) { | 486 | switch (builtin.os) { |
| 487 | builtin.Os.macosx => { | 487 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 488 | const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent); | 488 | const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent); |
| 489 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 489 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 490 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { | 490 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { |
| ... | @@ -546,6 +546,7 @@ pub const Loop = struct { | ... | @@ -546,6 +546,7 @@ pub const Loop = struct { |
| 546 | switch (builtin.os) { | 546 | switch (builtin.os) { |
| 547 | builtin.Os.linux, | 547 | builtin.Os.linux, |
| 548 | builtin.Os.macosx, | 548 | builtin.Os.macosx, |
| 549 | builtin.Os.freebsd, | ||
| 549 | => self.os_data.fs_thread.wait(), | 550 | => self.os_data.fs_thread.wait(), |
| 550 | else => {}, | 551 | else => {}, |
| 551 | } | 552 | } |
| ... | @@ -610,7 +611,7 @@ pub const Loop = struct { | ... | @@ -610,7 +611,7 @@ pub const Loop = struct { |
| 610 | os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable; | 611 | os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable; |
| 611 | return; | 612 | return; |
| 612 | }, | 613 | }, |
| 613 | builtin.Os.macosx => { | 614 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 614 | self.posixFsRequest(&self.os_data.fs_end_request); | 615 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 615 | const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent); | 616 | const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent); |
| 616 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 617 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| ... | @@ -668,7 +669,7 @@ pub const Loop = struct { | ... | @@ -668,7 +669,7 @@ pub const Loop = struct { |
| 668 | } | 669 | } |
| 669 | } | 670 | } |
| 670 | }, | 671 | }, |
| 671 | builtin.Os.macosx => { | 672 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 672 | var eventlist: [1]posix.Kevent = undefined; | 673 | var eventlist: [1]posix.Kevent = undefined; |
| 673 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 674 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 674 | const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; | 675 | const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; |
| ... | @@ -731,7 +732,7 @@ pub const Loop = struct { | ... | @@ -731,7 +732,7 @@ pub const Loop = struct { |
| 731 | self.beginOneEvent(); // finished in posixFsRun after processing the msg | 732 | self.beginOneEvent(); // finished in posixFsRun after processing the msg |
| 732 | self.os_data.fs_queue.put(request_node); | 733 | self.os_data.fs_queue.put(request_node); |
| 733 | switch (builtin.os) { | 734 | switch (builtin.os) { |
| 734 | builtin.Os.macosx => { | 735 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 735 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake); | 736 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake); |
| 736 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 737 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 737 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; | 738 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; |
| ... | @@ -801,7 +802,7 @@ pub const Loop = struct { | ... | @@ -801,7 +802,7 @@ pub const Loop = struct { |
| 801 | else => unreachable, | 802 | else => unreachable, |
| 802 | } | 803 | } |
| 803 | }, | 804 | }, |
| 804 | builtin.Os.macosx => { | 805 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 805 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait); | 806 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait); |
| 806 | var out_kevs: [1]posix.Kevent = undefined; | 807 | var out_kevs: [1]posix.Kevent = undefined; |
| 807 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; | 808 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; |
| ... | @@ -813,7 +814,7 @@ pub const Loop = struct { | ... | @@ -813,7 +814,7 @@ pub const Loop = struct { |
| 813 | 814 | ||
| 814 | const OsData = switch (builtin.os) { | 815 | const OsData = switch (builtin.os) { |
| 815 | builtin.Os.linux => LinuxOsData, | 816 | builtin.Os.linux => LinuxOsData, |
| 816 | builtin.Os.macosx => MacOsData, | 817 | builtin.Os.macosx, builtin.Os.freebsd => KEventData, |
| 817 | builtin.Os.windows => struct { | 818 | builtin.Os.windows => struct { |
| 818 | io_port: windows.HANDLE, | 819 | io_port: windows.HANDLE, |
| 819 | extra_thread_count: usize, | 820 | extra_thread_count: usize, |
| ... | @@ -821,7 +822,7 @@ pub const Loop = struct { | ... | @@ -821,7 +822,7 @@ pub const Loop = struct { |
| 821 | else => struct {}, | 822 | else => struct {}, |
| 822 | }; | 823 | }; |
| 823 | 824 | ||
| 824 | const MacOsData = struct { | 825 | const KEventData = struct { |
| 825 | kqfd: i32, | 826 | kqfd: i32, |
| 826 | final_kevent: posix.Kevent, | 827 | final_kevent: posix.Kevent, |
| 827 | fs_kevent_wake: posix.Kevent, | 828 | fs_kevent_wake: posix.Kevent, |
std/fmt/index.zig+72-8| ... | @@ -2,6 +2,7 @@ const std = @import("../index.zig"); | ... | @@ -2,6 +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 mem = std.mem; | 6 | const mem = std.mem; |
| 6 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 7 | const errol = @import("errol/index.zig"); | 8 | const errol = @import("errol/index.zig"); |
| ... | @@ -116,7 +117,7 @@ pub fn formatType( | ... | @@ -116,7 +117,7 @@ pub fn formatType( |
| 116 | return output(context, @errorName(value)); | 117 | return output(context, @errorName(value)); |
| 117 | } | 118 | } |
| 118 | switch (@typeInfo(T)) { | 119 | switch (@typeInfo(T)) { |
| 119 | builtin.TypeId.Int, builtin.TypeId.Float => { | 120 | builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => { |
| 120 | return formatValue(value, fmt, context, Errors, output); | 121 | return formatValue(value, fmt, context, Errors, output); |
| 121 | }, | 122 | }, |
| 122 | builtin.TypeId.Void => { | 123 | builtin.TypeId.Void => { |
| ... | @@ -242,6 +243,9 @@ pub fn formatType( | ... | @@ -242,6 +243,9 @@ pub fn formatType( |
| 242 | } | 243 | } |
| 243 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); | 244 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); |
| 244 | }, | 245 | }, |
| 246 | builtin.TypeId.Fn => { | ||
| 247 | return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value)); | ||
| 248 | }, | ||
| 245 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), | 249 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), |
| 246 | } | 250 | } |
| 247 | } | 251 | } |
| ... | @@ -267,11 +271,15 @@ fn formatValue( | ... | @@ -267,11 +271,15 @@ fn formatValue( |
| 267 | } | 271 | } |
| 268 | } | 272 | } |
| 269 | 273 | ||
| 270 | comptime var T = @typeOf(value); | 274 | const T = @typeOf(value); |
| 271 | switch (@typeId(T)) { | 275 | switch (@typeId(T)) { |
| 272 | builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output), | 276 | builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output), |
| 273 | builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output), | 277 | builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output), |
| 274 | else => unreachable, | 278 | builtin.TypeId.ComptimeInt => { |
| 279 | const Int = math.IntFittingRange(value, value); | ||
| 280 | return formatIntValue(Int(value), fmt, context, Errors, output); | ||
| 281 | }, | ||
| 282 | else => comptime unreachable, | ||
| 275 | } | 283 | } |
| 276 | } | 284 | } |
| 277 | 285 | ||
| ... | @@ -288,9 +296,10 @@ pub fn formatIntValue( | ... | @@ -288,9 +296,10 @@ pub fn formatIntValue( |
| 288 | if (fmt.len > 0) { | 296 | if (fmt.len > 0) { |
| 289 | switch (fmt[0]) { | 297 | switch (fmt[0]) { |
| 290 | 'c' => { | 298 | 'c' => { |
| 291 | if (@typeOf(value) == u8) { | 299 | if (@typeOf(value).bit_count <= 8) { |
| 292 | if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]}); | 300 | if (fmt.len > 1) |
| 293 | return formatAsciiChar(value, context, Errors, output); | 301 | @compileError("Unknown format character: " ++ []u8{fmt[1]}); |
| 302 | return formatAsciiChar(u8(value), context, Errors, output); | ||
| 294 | } | 303 | } |
| 295 | }, | 304 | }, |
| 296 | 'b' => { | 305 | 'b' => { |
| ... | @@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned | ... | @@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned |
| 811 | 820 | ||
| 812 | for (buf) |c| { | 821 | for (buf) |c| { |
| 813 | const digit = try charToDigit(c, radix); | 822 | const digit = try charToDigit(c, radix); |
| 814 | x = try math.mul(T, x, radix); | 823 | |
| 815 | x = try math.add(T, x, digit); | 824 | if (x != 0) x = try math.mul(T, x, try math.cast(T, radix)); |
| 825 | x = try math.add(T, x, try math.cast(T, digit)); | ||
| 816 | } | 826 | } |
| 817 | 827 | ||
| 818 | return x; | 828 | return x; |
| 819 | } | 829 | } |
| 820 | 830 | ||
| 831 | test "parseUnsigned" { | ||
| 832 | assert((try parseUnsigned(u16, "050124", 10)) == 50124); | ||
| 833 | assert((try parseUnsigned(u16, "65535", 10)) == 65535); | ||
| 834 | assertError(parseUnsigned(u16, "65536", 10), error.Overflow); | ||
| 835 | |||
| 836 | assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff); | ||
| 837 | assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow); | ||
| 838 | |||
| 839 | assert((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF); | ||
| 840 | |||
| 841 | assert((try parseUnsigned(u7, "1", 10)) == 1); | ||
| 842 | assert((try parseUnsigned(u7, "1000", 2)) == 8); | ||
| 843 | |||
| 844 | assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter); | ||
| 845 | assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter); | ||
| 846 | |||
| 847 | assert((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747); | ||
| 848 | |||
| 849 | // these numbers should fit even though the radix itself doesn't fit in the destination type | ||
| 850 | assert((try parseUnsigned(u1, "0", 10)) == 0); | ||
| 851 | assert((try parseUnsigned(u1, "1", 10)) == 1); | ||
| 852 | assertError(parseUnsigned(u1, "2", 10), error.Overflow); | ||
| 853 | assert((try parseUnsigned(u1, "001", 16)) == 1); | ||
| 854 | assert((try parseUnsigned(u2, "3", 16)) == 3); | ||
| 855 | assertError(parseUnsigned(u2, "4", 16), error.Overflow); | ||
| 856 | } | ||
| 857 | |||
| 821 | pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { | 858 | pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { |
| 822 | const value = switch (c) { | 859 | const value = switch (c) { |
| 823 | '0'...'9' => c - '0', | 860 | '0'...'9' => c - '0', |
| ... | @@ -935,6 +972,25 @@ test "fmt.format" { | ... | @@ -935,6 +972,25 @@ test "fmt.format" { |
| 935 | const value: u8 = 0b1100; | 972 | const value: u8 = 0b1100; |
| 936 | try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value); | 973 | try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value); |
| 937 | } | 974 | } |
| 975 | { | ||
| 976 | var buf1: [32]u8 = undefined; | ||
| 977 | var context = BufPrintContext{ .remaining = buf1[0..] }; | ||
| 978 | try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite); | ||
| 979 | var res = buf1[0 .. buf1.len - context.remaining.len]; | ||
| 980 | assert(mem.eql(u8, res, "1234")); | ||
| 981 | |||
| 982 | context = BufPrintContext{ .remaining = buf1[0..] }; | ||
| 983 | try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite); | ||
| 984 | res = buf1[0 .. buf1.len - context.remaining.len]; | ||
| 985 | debug.warn("{}\n", res); | ||
| 986 | assert(mem.eql(u8, res, "a")); | ||
| 987 | |||
| 988 | context = BufPrintContext{ .remaining = buf1[0..] }; | ||
| 989 | try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite); | ||
| 990 | res = buf1[0 .. buf1.len - context.remaining.len]; | ||
| 991 | debug.warn("{}\n", res); | ||
| 992 | assert(mem.eql(u8, res, "1100")); | ||
| 993 | } | ||
| 938 | { | 994 | { |
| 939 | const value: [3]u8 = "abc"; | 995 | const value: [3]u8 = "abc"; |
| 940 | try testFmt("array: abc\n", "array: {}\n", value); | 996 | try testFmt("array: abc\n", "array: {}\n", value); |
| ... | @@ -956,6 +1012,14 @@ test "fmt.format" { | ... | @@ -956,6 +1012,14 @@ test "fmt.format" { |
| 956 | try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value); | 1012 | try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value); |
| 957 | try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value); | 1013 | try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value); |
| 958 | } | 1014 | } |
| 1015 | { | ||
| 1016 | const value = @intToPtr(fn () void, 0xdeadbeef); | ||
| 1017 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); | ||
| 1018 | } | ||
| 1019 | { | ||
| 1020 | const value = @intToPtr(fn () void, 0xdeadbeef); | ||
| 1021 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); | ||
| 1022 | } | ||
| 959 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); | 1023 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); |
| 960 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); | 1024 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); |
| 961 | try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C"); | 1025 | try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C"); |
std/hash/siphash.zig+7-7| ... | @@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 42 | pub fn init(key: []const u8) Self { | 42 | pub fn init(key: []const u8) Self { |
| 43 | debug.assert(key.len >= 16); | 43 | debug.assert(key.len >= 16); |
| 44 | 44 | ||
| 45 | const k0 = mem.readInt(key[0..8], u64, Endian.Little); | 45 | const k0 = mem.readIntSliceLittle(u64, key[0..8]); |
| 46 | const k1 = mem.readInt(key[8..16], u64, Endian.Little); | 46 | const k1 = mem.readIntSliceLittle(u64, key[8..16]); |
| 47 | 47 | ||
| 48 | var d = Self{ | 48 | var d = Self{ |
| 49 | .v0 = k0 ^ 0x736f6d6570736575, | 49 | .v0 = k0 ^ 0x736f6d6570736575, |
| ... | @@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 121 | fn round(d: *Self, b: []const u8) void { | 121 | fn round(d: *Self, b: []const u8) void { |
| 122 | debug.assert(b.len == 8); | 122 | debug.assert(b.len == 8); |
| 123 | 123 | ||
| 124 | const m = mem.readInt(b[0..], u64, Endian.Little); | 124 | const m = mem.readIntSliceLittle(u64, b[0..]); |
| 125 | d.v3 ^= m; | 125 | d.v3 ^= m; |
| 126 | 126 | ||
| 127 | comptime var i: usize = 0; | 127 | comptime var i: usize = 0; |
| ... | @@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -162,7 +162,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"; | 162 | const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; |
| 163 | 163 | ||
| 164 | test "siphash64-2-4 sanity" { | 164 | test "siphash64-2-4 sanity" { |
| 165 | const vectors = [][]const u8{ | 165 | const vectors = [][8]u8{ |
| 166 | "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" | 166 | "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" |
| 167 | "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" | 167 | "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" |
| 168 | "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc | 168 | "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc |
| ... | @@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" { | ... | @@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" { |
| 235 | for (vectors) |vector, i| { | 235 | for (vectors) |vector, i| { |
| 236 | buffer[i] = @intCast(u8, i); | 236 | buffer[i] = @intCast(u8, i); |
| 237 | 237 | ||
| 238 | const expected = mem.readInt(vector, u64, Endian.Little); | 238 | const expected = mem.readIntLittle(u64, &vector); |
| 239 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); | 239 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); |
| 240 | } | 240 | } |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | test "siphash128-2-4 sanity" { | 243 | test "siphash128-2-4 sanity" { |
| 244 | const vectors = [][]const u8{ | 244 | const vectors = [][16]u8{ |
| 245 | "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93", | 245 | "\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", | 246 | "\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", | 247 | "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4", |
| ... | @@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" { | ... | @@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" { |
| 314 | for (vectors) |vector, i| { | 314 | for (vectors) |vector, i| { |
| 315 | buffer[i] = @intCast(u8, i); | 315 | buffer[i] = @intCast(u8, i); |
| 316 | 316 | ||
| 317 | const expected = mem.readInt(vector, u128, Endian.Little); | 317 | const expected = mem.readIntLittle(u128, &vector); |
| 318 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); | 318 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); |
| 319 | } | 319 | } |
| 320 | } | 320 | } |
std/hash_map.zig+14| ... | @@ -126,6 +126,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -126,6 +126,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 126 | }; | 126 | }; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | pub fn getOrPutValue(self: *Self, key: K, value: V) !*KV { | ||
| 130 | const res = try self.getOrPut(key); | ||
| 131 | if (!res.found_existing) | ||
| 132 | res.kv.value = value; | ||
| 133 | |||
| 134 | return res.kv; | ||
| 135 | } | ||
| 136 | |||
| 129 | fn ensureCapacity(self: *Self) !void { | 137 | fn ensureCapacity(self: *Self) !void { |
| 130 | if (self.entries.len == 0) { | 138 | if (self.entries.len == 0) { |
| 131 | return self.initCapacity(16); | 139 | return self.initCapacity(16); |
| ... | @@ -354,6 +362,12 @@ test "basic hash map usage" { | ... | @@ -354,6 +362,12 @@ test "basic hash map usage" { |
| 354 | gop2.kv.value = 42; | 362 | gop2.kv.value = 42; |
| 355 | assert(map.get(99).?.value == 42); | 363 | assert(map.get(99).?.value == 42); |
| 356 | 364 | ||
| 365 | const gop3 = try map.getOrPutValue(5, 5); | ||
| 366 | assert(gop3.value == 77); | ||
| 367 | |||
| 368 | const gop4 = try map.getOrPutValue(100, 41); | ||
| 369 | assert(gop4.value == 41); | ||
| 370 | |||
| 357 | assert(map.contains(2)); | 371 | assert(map.contains(2)); |
| 358 | assert(map.get(2).?.value == 22); | 372 | assert(map.get(2).?.value == 22); |
| 359 | _ = map.remove(2); | 373 | _ = map.remove(2); |
std/heap.zig+4-4| ... | @@ -66,11 +66,11 @@ pub const DirectAllocator = struct { | ... | @@ -66,11 +66,11 @@ pub const DirectAllocator = struct { |
| 66 | } | 66 | } |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { | 69 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 { |
| 70 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); | 70 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 71 | 71 | ||
| 72 | switch (builtin.os) { | 72 | switch (builtin.os) { |
| 73 | Os.linux, Os.macosx, Os.ios => { | 73 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 74 | const p = os.posix; | 74 | const p = os.posix; |
| 75 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; | 75 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; |
| 76 | const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0); | 76 | const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0); |
| ... | @@ -121,7 +121,7 @@ pub const DirectAllocator = struct { | ... | @@ -121,7 +121,7 @@ pub const DirectAllocator = struct { |
| 121 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); | 121 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 122 | 122 | ||
| 123 | switch (builtin.os) { | 123 | switch (builtin.os) { |
| 124 | Os.linux, Os.macosx, Os.ios => { | 124 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 125 | if (new_size <= old_mem.len) { | 125 | if (new_size <= old_mem.len) { |
| 126 | const base_addr = @ptrToInt(old_mem.ptr); | 126 | const base_addr = @ptrToInt(old_mem.ptr); |
| 127 | const old_addr_end = base_addr + old_mem.len; | 127 | const old_addr_end = base_addr + old_mem.len; |
| ... | @@ -166,7 +166,7 @@ pub const DirectAllocator = struct { | ... | @@ -166,7 +166,7 @@ pub const DirectAllocator = struct { |
| 166 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); | 166 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 167 | 167 | ||
| 168 | switch (builtin.os) { | 168 | switch (builtin.os) { |
| 169 | Os.linux, Os.macosx, Os.ios => { | 169 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 170 | _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len); | 170 | _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len); |
| 171 | }, | 171 | }, |
| 172 | Os.windows => { | 172 | Os.windows => { |
std/index.zig+2-1| ... | @@ -57,7 +57,8 @@ test "std" { | ... | @@ -57,7 +57,8 @@ test "std" { |
| 57 | _ = @import("mutex.zig"); | 57 | _ = @import("mutex.zig"); |
| 58 | _ = @import("segmented_list.zig"); | 58 | _ = @import("segmented_list.zig"); |
| 59 | _ = @import("spinlock.zig"); | 59 | _ = @import("spinlock.zig"); |
| 60 | 60 | ||
| 61 | _ = @import("dynamic_library.zig"); | ||
| 61 | _ = @import("base64.zig"); | 62 | _ = @import("base64.zig"); |
| 62 | _ = @import("build.zig"); | 63 | _ = @import("build.zig"); |
| 63 | _ = @import("c/index.zig"); | 64 | _ = @import("c/index.zig"); |
std/io.zig+104-37| ... | @@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File { | ... | @@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File { |
| 32 | return File.openHandle(handle); | 32 | return File.openHandle(handle); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; | ||
| 36 | |||
| 35 | pub fn InStream(comptime ReadError: type) type { | 37 | pub fn InStream(comptime ReadError: type) type { |
| 36 | return struct { | 38 | return struct { |
| 37 | const Self = @This(); | 39 | const Self = @This(); |
| ... | @@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type { |
| 150 | } | 152 | } |
| 151 | 153 | ||
| 152 | /// Reads a native-endian integer | 154 | /// Reads a native-endian integer |
| 153 | pub fn readIntNe(self: *Self, comptime T: type) !T { | 155 | pub fn readIntNative(self: *Self, comptime T: type) !T { |
| 154 | return self.readInt(builtin.endian, T); | 156 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 157 | try self.readNoEof(bytes[0..]); | ||
| 158 | return mem.readIntNative(T, &bytes); | ||
| 159 | } | ||
| 160 | |||
| 161 | /// Reads a foreign-endian integer | ||
| 162 | pub fn readIntForeign(self: *Self, comptime T: type) !T { | ||
| 163 | var bytes: [@sizeOf(T)]u8 = undefined; | ||
| 164 | try self.readNoEof(bytes[0..]); | ||
| 165 | return mem.readIntForeign(T, &bytes); | ||
| 155 | } | 166 | } |
| 156 | 167 | ||
| 157 | pub fn readIntLe(self: *Self, comptime T: type) !T { | 168 | pub fn readIntLittle(self: *Self, comptime T: type) !T { |
| 158 | var bytes: [@sizeOf(T)]u8 = undefined; | 169 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 159 | try self.readNoEof(bytes[0..]); | 170 | try self.readNoEof(bytes[0..]); |
| 160 | return mem.readIntLE(T, bytes); | 171 | return mem.readIntLittle(T, &bytes); |
| 161 | } | 172 | } |
| 162 | 173 | ||
| 163 | pub fn readIntBe(self: *Self, comptime T: type) !T { | 174 | pub fn readIntBig(self: *Self, comptime T: type) !T { |
| 164 | var bytes: [@sizeOf(T)]u8 = undefined; | 175 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 165 | try self.readNoEof(bytes[0..]); | 176 | try self.readNoEof(bytes[0..]); |
| 166 | return mem.readIntBE(T, bytes); | 177 | return mem.readIntBig(T, &bytes); |
| 167 | } | 178 | } |
| 168 | 179 | ||
| 169 | pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T { | 180 | pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { |
| 170 | var bytes: [@sizeOf(T)]u8 = undefined; | 181 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 171 | try self.readNoEof(bytes[0..]); | 182 | try self.readNoEof(bytes[0..]); |
| 172 | return mem.readInt(bytes, T, endian); | 183 | return mem.readInt(T, &bytes, endian); |
| 173 | } | 184 | } |
| 174 | 185 | ||
| 175 | pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T { | 186 | pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { |
| 176 | assert(size <= @sizeOf(T)); | 187 | assert(size <= @sizeOf(ReturnType)); |
| 177 | assert(size <= 8); | 188 | var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; |
| 178 | var input_buf: [8]u8 = undefined; | 189 | const bytes = bytes_buf[0..size]; |
| 179 | const input_slice = input_buf[0..size]; | 190 | try self.readNoEof(bytes); |
| 180 | try self.readNoEof(input_slice); | 191 | return mem.readVarInt(ReturnType, bytes, endian); |
| 181 | return mem.readInt(input_slice, T, endian); | ||
| 182 | } | 192 | } |
| 183 | 193 | ||
| 184 | pub fn skipBytes(self: *Self, num_bytes: usize) !void { | 194 | pub fn skipBytes(self: *Self, num_bytes: usize) !void { |
| ... | @@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type { | ... | @@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type { |
| 227 | } | 237 | } |
| 228 | 238 | ||
| 229 | /// Write a native-endian integer. | 239 | /// Write a native-endian integer. |
| 230 | pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void { | 240 | pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void { |
| 231 | return self.writeInt(builtin.endian, T, value); | 241 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 242 | mem.writeIntNative(T, &bytes, value); | ||
| 243 | return self.writeFn(self, bytes); | ||
| 244 | } | ||
| 245 | |||
| 246 | /// Write a foreign-endian integer. | ||
| 247 | pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void { | ||
| 248 | var bytes: [@sizeOf(T)]u8 = undefined; | ||
| 249 | mem.writeIntForeign(T, &bytes, value); | ||
| 250 | return self.writeFn(self, bytes); | ||
| 232 | } | 251 | } |
| 233 | 252 | ||
| 234 | pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void { | 253 | pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void { |
| 235 | var bytes: [@sizeOf(T)]u8 = undefined; | 254 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 236 | mem.writeIntLE(T, &bytes, value); | 255 | mem.writeIntLittle(T, &bytes, value); |
| 237 | return self.writeFn(self, bytes); | 256 | return self.writeFn(self, bytes); |
| 238 | } | 257 | } |
| 239 | 258 | ||
| 240 | pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void { | 259 | pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void { |
| 241 | var bytes: [@sizeOf(T)]u8 = undefined; | 260 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 242 | mem.writeIntBE(T, &bytes, value); | 261 | mem.writeIntBig(T, &bytes, value); |
| 243 | return self.writeFn(self, bytes); | 262 | return self.writeFn(self, bytes); |
| 244 | } | 263 | } |
| 245 | 264 | ||
| 246 | pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void { | 265 | pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void { |
| 247 | var bytes: [@sizeOf(T)]u8 = undefined; | 266 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 248 | mem.writeInt(bytes[0..], value, endian); | 267 | mem.writeInt(T, &bytes, value, endian); |
| 249 | return self.writeFn(self, bytes); | 268 | return self.writeFn(self, bytes); |
| 250 | } | 269 | } |
| 251 | }; | 270 | }; |
| ... | @@ -683,25 +702,73 @@ test "import io tests" { | ... | @@ -683,25 +702,73 @@ test "import io tests" { |
| 683 | } | 702 | } |
| 684 | } | 703 | } |
| 685 | 704 | ||
| 686 | pub fn readLine(buf: []u8) !usize { | 705 | pub fn readLine(buf: *std.Buffer) ![]u8 { |
| 687 | var stdin = getStdIn() catch return error.StdInUnavailable; | 706 | var stdin = try getStdIn(); |
| 688 | var adapter = stdin.inStream(); | 707 | var stdin_stream = stdin.inStream(); |
| 689 | var stream = &adapter.stream; | 708 | return readLineFrom(&stdin_stream.stream, buf); |
| 690 | var index: usize = 0; | 709 | } |
| 710 | |||
| 711 | /// Reads all characters until the next newline into buf, and returns | ||
| 712 | /// a slice of the characters read (excluding the newline character(s)). | ||
| 713 | pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 { | ||
| 714 | const start = buf.len(); | ||
| 691 | while (true) { | 715 | while (true) { |
| 692 | const byte = stream.readByte() catch return error.EndOfFile; | 716 | const byte = try stream.readByte(); |
| 693 | switch (byte) { | 717 | switch (byte) { |
| 694 | '\r' => { | 718 | '\r' => { |
| 695 | // trash the following \n | 719 | // trash the following \n |
| 696 | _ = stream.readByte() catch return error.EndOfFile; | 720 | _ = try stream.readByte(); |
| 697 | return index; | 721 | return buf.toSlice()[start..]; |
| 698 | }, | ||
| 699 | '\n' => return index, | ||
| 700 | else => { | ||
| 701 | if (index == buf.len) return error.InputTooLong; | ||
| 702 | buf[index] = byte; | ||
| 703 | index += 1; | ||
| 704 | }, | 722 | }, |
| 723 | '\n' => return buf.toSlice()[start..], | ||
| 724 | else => try buf.appendByte(byte), | ||
| 705 | } | 725 | } |
| 706 | } | 726 | } |
| 707 | } | 727 | } |
| 728 | |||
| 729 | test "io.readLineFrom" { | ||
| 730 | var bytes: [128]u8 = undefined; | ||
| 731 | const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; | ||
| 732 | |||
| 733 | var buf = try std.Buffer.initSize(allocator, 0); | ||
| 734 | var mem_stream = SliceInStream.init( | ||
| 735 | \\Line 1 | ||
| 736 | \\Line 22 | ||
| 737 | \\Line 333 | ||
| 738 | ); | ||
| 739 | const stream = &mem_stream.stream; | ||
| 740 | |||
| 741 | debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf))); | ||
| 742 | debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf))); | ||
| 743 | debug.assertError(readLineFrom(stream, &buf), error.EndOfStream); | ||
| 744 | debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333")); | ||
| 745 | } | ||
| 746 | |||
| 747 | pub fn readLineSlice(slice: []u8) ![]u8 { | ||
| 748 | var stdin = try getStdIn(); | ||
| 749 | var stdin_stream = stdin.inStream(); | ||
| 750 | return readLineSliceFrom(&stdin_stream.stream, slice); | ||
| 751 | } | ||
| 752 | |||
| 753 | /// Reads all characters until the next newline into slice, and returns | ||
| 754 | /// a slice of the characters read (excluding the newline character(s)). | ||
| 755 | pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 { | ||
| 756 | // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte | ||
| 757 | // after taking ownership, which would always require an allocation. | ||
| 758 | var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) }; | ||
| 759 | try buf.resize(0); | ||
| 760 | return try readLineFrom(stream, &buf); | ||
| 761 | } | ||
| 762 | |||
| 763 | test "io.readLineSliceFrom" { | ||
| 764 | var buf: [7]u8 = undefined; | ||
| 765 | var mem_stream = SliceInStream.init( | ||
| 766 | \\Line 1 | ||
| 767 | \\Line 22 | ||
| 768 | \\Line 333 | ||
| 769 | ); | ||
| 770 | const stream = &mem_stream.stream; | ||
| 771 | |||
| 772 | debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..]))); | ||
| 773 | debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory); | ||
| 774 | } |
std/io/seekable_stream.zig created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | const std = @import("../index.zig"); | ||
| 2 | const InStream = std.io.InStream; | ||
| 3 | |||
| 4 | pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType: type) type { | ||
| 5 | return struct { | ||
| 6 | const Self = @This(); | ||
| 7 | pub const SeekError = SeekErrorType; | ||
| 8 | pub const GetSeekPosError = GetSeekPosErrorType; | ||
| 9 | |||
| 10 | seekToFn: fn (self: *Self, pos: usize) SeekError!void, | ||
| 11 | seekForwardFn: fn (self: *Self, pos: isize) SeekError!void, | ||
| 12 | |||
| 13 | getPosFn: fn (self: *Self) GetSeekPosError!usize, | ||
| 14 | getEndPosFn: fn (self: *Self) GetSeekPosError!usize, | ||
| 15 | |||
| 16 | pub fn seekTo(self: *Self, pos: usize) SeekError!void { | ||
| 17 | return self.seekToFn(self, pos); | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn seekForward(self: *Self, amt: isize) SeekError!void { | ||
| 21 | return self.seekForwardFn(self, amt); | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn getEndPos(self: *Self) GetSeekPosError!usize { | ||
| 25 | return self.getEndPosFn(self); | ||
| 26 | } | ||
| 27 | |||
| 28 | pub fn getPos(self: *Self) GetSeekPosError!usize { | ||
| 29 | return self.getPosFn(self); | ||
| 30 | } | ||
| 31 | }; | ||
| 32 | } | ||
std/json.zig+17-10| ... | @@ -910,7 +910,7 @@ fn checkNext(p: *TokenStream, id: Token.Id) void { | ... | @@ -910,7 +910,7 @@ fn checkNext(p: *TokenStream, id: Token.Id) void { |
| 910 | debug.assert(token.id == id); | 910 | debug.assert(token.id == id); |
| 911 | } | 911 | } |
| 912 | 912 | ||
| 913 | test "token" { | 913 | test "json.token" { |
| 914 | const s = | 914 | const s = |
| 915 | \\{ | 915 | \\{ |
| 916 | \\ "Image": { | 916 | \\ "Image": { |
| ... | @@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool { | ... | @@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool { |
| 980 | return p.complete; | 980 | return p.complete; |
| 981 | } | 981 | } |
| 982 | 982 | ||
| 983 | test "json validate" { | 983 | test "json.validate" { |
| 984 | debug.assert(validate("{}")); | 984 | debug.assert(validate("{}")); |
| 985 | } | 985 | } |
| 986 | 986 | ||
| ... | @@ -1188,7 +1188,7 @@ pub const Parser = struct { | ... | @@ -1188,7 +1188,7 @@ pub const Parser = struct { |
| 1188 | } | 1188 | } |
| 1189 | 1189 | ||
| 1190 | var value = p.stack.pop(); | 1190 | var value = p.stack.pop(); |
| 1191 | try p.pushToParent(value); | 1191 | try p.pushToParent(&value); |
| 1192 | }, | 1192 | }, |
| 1193 | Token.Id.String => { | 1193 | Token.Id.String => { |
| 1194 | try p.stack.append(try p.parseString(allocator, token, input, i)); | 1194 | try p.stack.append(try p.parseString(allocator, token, input, i)); |
| ... | @@ -1251,7 +1251,7 @@ pub const Parser = struct { | ... | @@ -1251,7 +1251,7 @@ pub const Parser = struct { |
| 1251 | } | 1251 | } |
| 1252 | 1252 | ||
| 1253 | var value = p.stack.pop(); | 1253 | var value = p.stack.pop(); |
| 1254 | try p.pushToParent(value); | 1254 | try p.pushToParent(&value); |
| 1255 | }, | 1255 | }, |
| 1256 | Token.Id.ObjectBegin => { | 1256 | Token.Id.ObjectBegin => { |
| 1257 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | 1257 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| ... | @@ -1312,19 +1312,19 @@ pub const Parser = struct { | ... | @@ -1312,19 +1312,19 @@ pub const Parser = struct { |
| 1312 | } | 1312 | } |
| 1313 | } | 1313 | } |
| 1314 | 1314 | ||
| 1315 | fn pushToParent(p: *Parser, value: Value) !void { | 1315 | fn pushToParent(p: *Parser, value: *const Value) !void { |
| 1316 | switch (p.stack.at(p.stack.len - 1)) { | 1316 | switch (p.stack.toSlice()[p.stack.len - 1]) { |
| 1317 | // Object Parent -> [ ..., object, <key>, value ] | 1317 | // Object Parent -> [ ..., object, <key>, value ] |
| 1318 | Value.String => |key| { | 1318 | Value.String => |key| { |
| 1319 | _ = p.stack.pop(); | 1319 | _ = p.stack.pop(); |
| 1320 | 1320 | ||
| 1321 | var object = &p.stack.items[p.stack.len - 1].Object; | 1321 | var object = &p.stack.items[p.stack.len - 1].Object; |
| 1322 | _ = try object.put(key, value); | 1322 | _ = try object.put(key, value.*); |
| 1323 | p.state = State.ObjectKey; | 1323 | p.state = State.ObjectKey; |
| 1324 | }, | 1324 | }, |
| 1325 | // Array Parent -> [ ..., <array>, value ] | 1325 | // Array Parent -> [ ..., <array>, value ] |
| 1326 | Value.Array => |*array| { | 1326 | Value.Array => |*array| { |
| 1327 | try array.append(value); | 1327 | try array.append(value.*); |
| 1328 | p.state = State.ArrayValue; | 1328 | p.state = State.ArrayValue; |
| 1329 | }, | 1329 | }, |
| 1330 | else => { | 1330 | else => { |
| ... | @@ -1348,7 +1348,7 @@ pub const Parser = struct { | ... | @@ -1348,7 +1348,7 @@ pub const Parser = struct { |
| 1348 | } | 1348 | } |
| 1349 | }; | 1349 | }; |
| 1350 | 1350 | ||
| 1351 | test "json parser dynamic" { | 1351 | test "json.parser.dynamic" { |
| 1352 | var p = Parser.init(debug.global_allocator, false); | 1352 | var p = Parser.init(debug.global_allocator, false); |
| 1353 | defer p.deinit(); | 1353 | defer p.deinit(); |
| 1354 | 1354 | ||
| ... | @@ -1364,7 +1364,8 @@ test "json parser dynamic" { | ... | @@ -1364,7 +1364,8 @@ test "json parser dynamic" { |
| 1364 | \\ "Width": 100 | 1364 | \\ "Width": 100 |
| 1365 | \\ }, | 1365 | \\ }, |
| 1366 | \\ "Animated" : false, | 1366 | \\ "Animated" : false, |
| 1367 | \\ "IDs": [116, 943, 234, 38793] | 1367 | \\ "IDs": [116, 943, 234, 38793], |
| 1368 | \\ "ArrayOfObject": [{"n": "m"}] | ||
| 1368 | \\ } | 1369 | \\ } |
| 1369 | \\} | 1370 | \\} |
| 1370 | ; | 1371 | ; |
| ... | @@ -1387,4 +1388,10 @@ test "json parser dynamic" { | ... | @@ -1387,4 +1388,10 @@ test "json parser dynamic" { |
| 1387 | 1388 | ||
| 1388 | const animated = image.Object.get("Animated").?.value; | 1389 | const animated = image.Object.get("Animated").?.value; |
| 1389 | debug.assert(animated.Bool == false); | 1390 | debug.assert(animated.Bool == false); |
| 1391 | |||
| 1392 | const array_of_object = image.Object.get("ArrayOfObject").?.value; | ||
| 1393 | debug.assert(array_of_object.Array.len == 1); | ||
| 1394 | |||
| 1395 | const obj0 = array_of_object.Array.at(0).Object.get("n").?.value; | ||
| 1396 | debug.assert(mem.eql(u8, obj0.String, "m")); | ||
| 1390 | } | 1397 | } |
std/json_test.zig+319-319| ... | @@ -21,7 +21,7 @@ fn any(comptime s: []const u8) void { | ... | @@ -21,7 +21,7 @@ fn any(comptime s: []const u8) void { |
| 21 | // | 21 | // |
| 22 | // Additional tests not part of test JSONTestSuite. | 22 | // Additional tests not part of test JSONTestSuite. |
| 23 | 23 | ||
| 24 | test "y_trailing_comma_after_empty" { | 24 | test "json.test.y_trailing_comma_after_empty" { |
| 25 | ok( | 25 | ok( |
| 26 | \\{"1":[],"2":{},"3":"4"} | 26 | \\{"1":[],"2":{},"3":"4"} |
| 27 | ); | 27 | ); |
| ... | @@ -29,252 +29,252 @@ test "y_trailing_comma_after_empty" { | ... | @@ -29,252 +29,252 @@ test "y_trailing_comma_after_empty" { |
| 29 | 29 | ||
| 30 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 31 | 31 | ||
| 32 | test "y_array_arraysWithSpaces" { | 32 | test "json.test.y_array_arraysWithSpaces" { |
| 33 | ok( | 33 | ok( |
| 34 | \\[[] ] | 34 | \\[[] ] |
| 35 | ); | 35 | ); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | test "y_array_empty" { | 38 | test "json.test.y_array_empty" { |
| 39 | ok( | 39 | ok( |
| 40 | \\[] | 40 | \\[] |
| 41 | ); | 41 | ); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | test "y_array_empty-string" { | 44 | test "json.test.y_array_empty-string" { |
| 45 | ok( | 45 | ok( |
| 46 | \\[""] | 46 | \\[""] |
| 47 | ); | 47 | ); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | test "y_array_ending_with_newline" { | 50 | test "json.test.y_array_ending_with_newline" { |
| 51 | ok( | 51 | ok( |
| 52 | \\["a"] | 52 | \\["a"] |
| 53 | ); | 53 | ); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | test "y_array_false" { | 56 | test "json.test.y_array_false" { |
| 57 | ok( | 57 | ok( |
| 58 | \\[false] | 58 | \\[false] |
| 59 | ); | 59 | ); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | test "y_array_heterogeneous" { | 62 | test "json.test.y_array_heterogeneous" { |
| 63 | ok( | 63 | ok( |
| 64 | \\[null, 1, "1", {}] | 64 | \\[null, 1, "1", {}] |
| 65 | ); | 65 | ); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | test "y_array_null" { | 68 | test "json.test.y_array_null" { |
| 69 | ok( | 69 | ok( |
| 70 | \\[null] | 70 | \\[null] |
| 71 | ); | 71 | ); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | test "y_array_with_1_and_newline" { | 74 | test "json.test.y_array_with_1_and_newline" { |
| 75 | ok( | 75 | ok( |
| 76 | \\[1 | 76 | \\[1 |
| 77 | \\] | 77 | \\] |
| 78 | ); | 78 | ); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | test "y_array_with_leading_space" { | 81 | test "json.test.y_array_with_leading_space" { |
| 82 | ok( | 82 | ok( |
| 83 | \\ [1] | 83 | \\ [1] |
| 84 | ); | 84 | ); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | test "y_array_with_several_null" { | 87 | test "json.test.y_array_with_several_null" { |
| 88 | ok( | 88 | ok( |
| 89 | \\[1,null,null,null,2] | 89 | \\[1,null,null,null,2] |
| 90 | ); | 90 | ); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | test "y_array_with_trailing_space" { | 93 | test "json.test.y_array_with_trailing_space" { |
| 94 | ok("[2] "); | 94 | ok("[2] "); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | test "y_number_0e+1" { | 97 | test "json.test.y_number_0e+1" { |
| 98 | ok( | 98 | ok( |
| 99 | \\[0e+1] | 99 | \\[0e+1] |
| 100 | ); | 100 | ); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | test "y_number_0e1" { | 103 | test "json.test.y_number_0e1" { |
| 104 | ok( | 104 | ok( |
| 105 | \\[0e1] | 105 | \\[0e1] |
| 106 | ); | 106 | ); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | test "y_number_after_space" { | 109 | test "json.test.y_number_after_space" { |
| 110 | ok( | 110 | ok( |
| 111 | \\[ 4] | 111 | \\[ 4] |
| 112 | ); | 112 | ); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | test "y_number_double_close_to_zero" { | 115 | test "json.test.y_number_double_close_to_zero" { |
| 116 | ok( | 116 | ok( |
| 117 | \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001] | 117 | \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001] |
| 118 | ); | 118 | ); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | test "y_number_int_with_exp" { | 121 | test "json.test.y_number_int_with_exp" { |
| 122 | ok( | 122 | ok( |
| 123 | \\[20e1] | 123 | \\[20e1] |
| 124 | ); | 124 | ); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | test "y_number" { | 127 | test "json.test.y_number" { |
| 128 | ok( | 128 | ok( |
| 129 | \\[123e65] | 129 | \\[123e65] |
| 130 | ); | 130 | ); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | test "y_number_minus_zero" { | 133 | test "json.test.y_number_minus_zero" { |
| 134 | ok( | 134 | ok( |
| 135 | \\[-0] | 135 | \\[-0] |
| 136 | ); | 136 | ); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | test "y_number_negative_int" { | 139 | test "json.test.y_number_negative_int" { |
| 140 | ok( | 140 | ok( |
| 141 | \\[-123] | 141 | \\[-123] |
| 142 | ); | 142 | ); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | test "y_number_negative_one" { | 145 | test "json.test.y_number_negative_one" { |
| 146 | ok( | 146 | ok( |
| 147 | \\[-1] | 147 | \\[-1] |
| 148 | ); | 148 | ); |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | test "y_number_negative_zero" { | 151 | test "json.test.y_number_negative_zero" { |
| 152 | ok( | 152 | ok( |
| 153 | \\[-0] | 153 | \\[-0] |
| 154 | ); | 154 | ); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | test "y_number_real_capital_e" { | 157 | test "json.test.y_number_real_capital_e" { |
| 158 | ok( | 158 | ok( |
| 159 | \\[1E22] | 159 | \\[1E22] |
| 160 | ); | 160 | ); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | test "y_number_real_capital_e_neg_exp" { | 163 | test "json.test.y_number_real_capital_e_neg_exp" { |
| 164 | ok( | 164 | ok( |
| 165 | \\[1E-2] | 165 | \\[1E-2] |
| 166 | ); | 166 | ); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | test "y_number_real_capital_e_pos_exp" { | 169 | test "json.test.y_number_real_capital_e_pos_exp" { |
| 170 | ok( | 170 | ok( |
| 171 | \\[1E+2] | 171 | \\[1E+2] |
| 172 | ); | 172 | ); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | test "y_number_real_exponent" { | 175 | test "json.test.y_number_real_exponent" { |
| 176 | ok( | 176 | ok( |
| 177 | \\[123e45] | 177 | \\[123e45] |
| 178 | ); | 178 | ); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | test "y_number_real_fraction_exponent" { | 181 | test "json.test.y_number_real_fraction_exponent" { |
| 182 | ok( | 182 | ok( |
| 183 | \\[123.456e78] | 183 | \\[123.456e78] |
| 184 | ); | 184 | ); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | test "y_number_real_neg_exp" { | 187 | test "json.test.y_number_real_neg_exp" { |
| 188 | ok( | 188 | ok( |
| 189 | \\[1e-2] | 189 | \\[1e-2] |
| 190 | ); | 190 | ); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | test "y_number_real_pos_exponent" { | 193 | test "json.test.y_number_real_pos_exponent" { |
| 194 | ok( | 194 | ok( |
| 195 | \\[1e+2] | 195 | \\[1e+2] |
| 196 | ); | 196 | ); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | test "y_number_simple_int" { | 199 | test "json.test.y_number_simple_int" { |
| 200 | ok( | 200 | ok( |
| 201 | \\[123] | 201 | \\[123] |
| 202 | ); | 202 | ); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | test "y_number_simple_real" { | 205 | test "json.test.y_number_simple_real" { |
| 206 | ok( | 206 | ok( |
| 207 | \\[123.456789] | 207 | \\[123.456789] |
| 208 | ); | 208 | ); |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | test "y_object_basic" { | 211 | test "json.test.y_object_basic" { |
| 212 | ok( | 212 | ok( |
| 213 | \\{"asd":"sdf"} | 213 | \\{"asd":"sdf"} |
| 214 | ); | 214 | ); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | test "y_object_duplicated_key_and_value" { | 217 | test "json.test.y_object_duplicated_key_and_value" { |
| 218 | ok( | 218 | ok( |
| 219 | \\{"a":"b","a":"b"} | 219 | \\{"a":"b","a":"b"} |
| 220 | ); | 220 | ); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | test "y_object_duplicated_key" { | 223 | test "json.test.y_object_duplicated_key" { |
| 224 | ok( | 224 | ok( |
| 225 | \\{"a":"b","a":"c"} | 225 | \\{"a":"b","a":"c"} |
| 226 | ); | 226 | ); |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | test "y_object_empty" { | 229 | test "json.test.y_object_empty" { |
| 230 | ok( | 230 | ok( |
| 231 | \\{} | 231 | \\{} |
| 232 | ); | 232 | ); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | test "y_object_empty_key" { | 235 | test "json.test.y_object_empty_key" { |
| 236 | ok( | 236 | ok( |
| 237 | \\{"":0} | 237 | \\{"":0} |
| 238 | ); | 238 | ); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | test "y_object_escaped_null_in_key" { | 241 | test "json.test.y_object_escaped_null_in_key" { |
| 242 | ok( | 242 | ok( |
| 243 | \\{"foo\u0000bar": 42} | 243 | \\{"foo\u0000bar": 42} |
| 244 | ); | 244 | ); |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | test "y_object_extreme_numbers" { | 247 | test "json.test.y_object_extreme_numbers" { |
| 248 | ok( | 248 | ok( |
| 249 | \\{ "min": -1.0e+28, "max": 1.0e+28 } | 249 | \\{ "min": -1.0e+28, "max": 1.0e+28 } |
| 250 | ); | 250 | ); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | test "y_object" { | 253 | test "json.test.y_object" { |
| 254 | ok( | 254 | ok( |
| 255 | \\{"asd":"sdf", "dfg":"fgh"} | 255 | \\{"asd":"sdf", "dfg":"fgh"} |
| 256 | ); | 256 | ); |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | test "y_object_long_strings" { | 259 | test "json.test.y_object_long_strings" { |
| 260 | ok( | 260 | ok( |
| 261 | \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} | 261 | \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} |
| 262 | ); | 262 | ); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | test "y_object_simple" { | 265 | test "json.test.y_object_simple" { |
| 266 | ok( | 266 | ok( |
| 267 | \\{"a":[]} | 267 | \\{"a":[]} |
| 268 | ); | 268 | ); |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | test "y_object_string_unicode" { | 271 | test "json.test.y_object_string_unicode" { |
| 272 | ok( | 272 | ok( |
| 273 | \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" } | 273 | \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" } |
| 274 | ); | 274 | ); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | test "y_object_with_newlines" { | 277 | test "json.test.y_object_with_newlines" { |
| 278 | ok( | 278 | ok( |
| 279 | \\{ | 279 | \\{ |
| 280 | \\"a": "b" | 280 | \\"a": "b" |
| ... | @@ -282,419 +282,419 @@ test "y_object_with_newlines" { | ... | @@ -282,419 +282,419 @@ test "y_object_with_newlines" { |
| 282 | ); | 282 | ); |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | test "y_string_1_2_3_bytes_UTF-8_sequences" { | 285 | test "json.test.y_string_1_2_3_bytes_UTF-8_sequences" { |
| 286 | ok( | 286 | ok( |
| 287 | \\["\u0060\u012a\u12AB"] | 287 | \\["\u0060\u012a\u12AB"] |
| 288 | ); | 288 | ); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | test "y_string_accepted_surrogate_pair" { | 291 | test "json.test.y_string_accepted_surrogate_pair" { |
| 292 | ok( | 292 | ok( |
| 293 | \\["\uD801\udc37"] | 293 | \\["\uD801\udc37"] |
| 294 | ); | 294 | ); |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | test "y_string_accepted_surrogate_pairs" { | 297 | test "json.test.y_string_accepted_surrogate_pairs" { |
| 298 | ok( | 298 | ok( |
| 299 | \\["\ud83d\ude39\ud83d\udc8d"] | 299 | \\["\ud83d\ude39\ud83d\udc8d"] |
| 300 | ); | 300 | ); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | test "y_string_allowed_escapes" { | 303 | test "json.test.y_string_allowed_escapes" { |
| 304 | ok( | 304 | ok( |
| 305 | \\["\"\\\/\b\f\n\r\t"] | 305 | \\["\"\\\/\b\f\n\r\t"] |
| 306 | ); | 306 | ); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | test "y_string_backslash_and_u_escaped_zero" { | 309 | test "json.test.y_string_backslash_and_u_escaped_zero" { |
| 310 | ok( | 310 | ok( |
| 311 | \\["\\u0000"] | 311 | \\["\\u0000"] |
| 312 | ); | 312 | ); |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | test "y_string_backslash_doublequotes" { | 315 | test "json.test.y_string_backslash_doublequotes" { |
| 316 | ok( | 316 | ok( |
| 317 | \\["\""] | 317 | \\["\""] |
| 318 | ); | 318 | ); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | test "y_string_comments" { | 321 | test "json.test.y_string_comments" { |
| 322 | ok( | 322 | ok( |
| 323 | \\["a/*b*/c/*d//e"] | 323 | \\["a/*b*/c/*d//e"] |
| 324 | ); | 324 | ); |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | test "y_string_double_escape_a" { | 327 | test "json.test.y_string_double_escape_a" { |
| 328 | ok( | 328 | ok( |
| 329 | \\["\\a"] | 329 | \\["\\a"] |
| 330 | ); | 330 | ); |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | test "y_string_double_escape_n" { | 333 | test "json.test.y_string_double_escape_n" { |
| 334 | ok( | 334 | ok( |
| 335 | \\["\\n"] | 335 | \\["\\n"] |
| 336 | ); | 336 | ); |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | test "y_string_escaped_control_character" { | 339 | test "json.test.y_string_escaped_control_character" { |
| 340 | ok( | 340 | ok( |
| 341 | \\["\u0012"] | 341 | \\["\u0012"] |
| 342 | ); | 342 | ); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | test "y_string_escaped_noncharacter" { | 345 | test "json.test.y_string_escaped_noncharacter" { |
| 346 | ok( | 346 | ok( |
| 347 | \\["\uFFFF"] | 347 | \\["\uFFFF"] |
| 348 | ); | 348 | ); |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | test "y_string_in_array" { | 351 | test "json.test.y_string_in_array" { |
| 352 | ok( | 352 | ok( |
| 353 | \\["asd"] | 353 | \\["asd"] |
| 354 | ); | 354 | ); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | test "y_string_in_array_with_leading_space" { | 357 | test "json.test.y_string_in_array_with_leading_space" { |
| 358 | ok( | 358 | ok( |
| 359 | \\[ "asd"] | 359 | \\[ "asd"] |
| 360 | ); | 360 | ); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | test "y_string_last_surrogates_1_and_2" { | 363 | test "json.test.y_string_last_surrogates_1_and_2" { |
| 364 | ok( | 364 | ok( |
| 365 | \\["\uDBFF\uDFFF"] | 365 | \\["\uDBFF\uDFFF"] |
| 366 | ); | 366 | ); |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | test "y_string_nbsp_uescaped" { | 369 | test "json.test.y_string_nbsp_uescaped" { |
| 370 | ok( | 370 | ok( |
| 371 | \\["new\u00A0line"] | 371 | \\["new\u00A0line"] |
| 372 | ); | 372 | ); |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | test "y_string_nonCharacterInUTF-8_U+10FFFF" { | 375 | test "json.test.y_string_nonCharacterInUTF-8_U+10FFFF" { |
| 376 | ok( | 376 | ok( |
| 377 | \\[""] | 377 | \\[""] |
| 378 | ); | 378 | ); |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | test "y_string_nonCharacterInUTF-8_U+FFFF" { | 381 | test "json.test.y_string_nonCharacterInUTF-8_U+FFFF" { |
| 382 | ok( | 382 | ok( |
| 383 | \\[""] | 383 | \\[""] |
| 384 | ); | 384 | ); |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | test "y_string_null_escape" { | 387 | test "json.test.y_string_null_escape" { |
| 388 | ok( | 388 | ok( |
| 389 | \\["\u0000"] | 389 | \\["\u0000"] |
| 390 | ); | 390 | ); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | test "y_string_one-byte-utf-8" { | 393 | test "json.test.y_string_one-byte-utf-8" { |
| 394 | ok( | 394 | ok( |
| 395 | \\["\u002c"] | 395 | \\["\u002c"] |
| 396 | ); | 396 | ); |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | test "y_string_pi" { | 399 | test "json.test.y_string_pi" { |
| 400 | ok( | 400 | ok( |
| 401 | \\["π"] | 401 | \\["π"] |
| 402 | ); | 402 | ); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | test "y_string_reservedCharacterInUTF-8_U+1BFFF" { | 405 | test "json.test.y_string_reservedCharacterInUTF-8_U+1BFFF" { |
| 406 | ok( | 406 | ok( |
| 407 | \\[""] | 407 | \\[""] |
| 408 | ); | 408 | ); |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | test "y_string_simple_ascii" { | 411 | test "json.test.y_string_simple_ascii" { |
| 412 | ok( | 412 | ok( |
| 413 | \\["asd "] | 413 | \\["asd "] |
| 414 | ); | 414 | ); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | test "y_string_space" { | 417 | test "json.test.y_string_space" { |
| 418 | ok( | 418 | ok( |
| 419 | \\" " | 419 | \\" " |
| 420 | ); | 420 | ); |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | test "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" { | 423 | test "json.test.y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" { |
| 424 | ok( | 424 | ok( |
| 425 | \\["\uD834\uDd1e"] | 425 | \\["\uD834\uDd1e"] |
| 426 | ); | 426 | ); |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | test "y_string_three-byte-utf-8" { | 429 | test "json.test.y_string_three-byte-utf-8" { |
| 430 | ok( | 430 | ok( |
| 431 | \\["\u0821"] | 431 | \\["\u0821"] |
| 432 | ); | 432 | ); |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | test "y_string_two-byte-utf-8" { | 435 | test "json.test.y_string_two-byte-utf-8" { |
| 436 | ok( | 436 | ok( |
| 437 | \\["\u0123"] | 437 | \\["\u0123"] |
| 438 | ); | 438 | ); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | test "y_string_u+2028_line_sep" { | 441 | test "json.test.y_string_u+2028_line_sep" { |
| 442 | ok("[\"\xe2\x80\xa8\"]"); | 442 | ok("[\"\xe2\x80\xa8\"]"); |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | test "y_string_u+2029_par_sep" { | 445 | test "json.test.y_string_u+2029_par_sep" { |
| 446 | ok("[\"\xe2\x80\xa9\"]"); | 446 | ok("[\"\xe2\x80\xa9\"]"); |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | test "y_string_uescaped_newline" { | 449 | test "json.test.y_string_uescaped_newline" { |
| 450 | ok( | 450 | ok( |
| 451 | \\["new\u000Aline"] | 451 | \\["new\u000Aline"] |
| 452 | ); | 452 | ); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | test "y_string_uEscape" { | 455 | test "json.test.y_string_uEscape" { |
| 456 | ok( | 456 | ok( |
| 457 | \\["\u0061\u30af\u30EA\u30b9"] | 457 | \\["\u0061\u30af\u30EA\u30b9"] |
| 458 | ); | 458 | ); |
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | test "y_string_unescaped_char_delete" { | 461 | test "json.test.y_string_unescaped_char_delete" { |
| 462 | ok("[\"\x7f\"]"); | 462 | ok("[\"\x7f\"]"); |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | test "y_string_unicode_2" { | 465 | test "json.test.y_string_unicode_2" { |
| 466 | ok( | 466 | ok( |
| 467 | \\["⍂㈴⍂"] | 467 | \\["⍂㈴⍂"] |
| 468 | ); | 468 | ); |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | test "y_string_unicodeEscapedBackslash" { | 471 | test "json.test.y_string_unicodeEscapedBackslash" { |
| 472 | ok( | 472 | ok( |
| 473 | \\["\u005C"] | 473 | \\["\u005C"] |
| 474 | ); | 474 | ); |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | test "y_string_unicode_escaped_double_quote" { | 477 | test "json.test.y_string_unicode_escaped_double_quote" { |
| 478 | ok( | 478 | ok( |
| 479 | \\["\u0022"] | 479 | \\["\u0022"] |
| 480 | ); | 480 | ); |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | test "y_string_unicode" { | 483 | test "json.test.y_string_unicode" { |
| 484 | ok( | 484 | ok( |
| 485 | \\["\uA66D"] | 485 | \\["\uA66D"] |
| 486 | ); | 486 | ); |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | test "y_string_unicode_U+10FFFE_nonchar" { | 489 | test "json.test.y_string_unicode_U+10FFFE_nonchar" { |
| 490 | ok( | 490 | ok( |
| 491 | \\["\uDBFF\uDFFE"] | 491 | \\["\uDBFF\uDFFE"] |
| 492 | ); | 492 | ); |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | test "y_string_unicode_U+1FFFE_nonchar" { | 495 | test "json.test.y_string_unicode_U+1FFFE_nonchar" { |
| 496 | ok( | 496 | ok( |
| 497 | \\["\uD83F\uDFFE"] | 497 | \\["\uD83F\uDFFE"] |
| 498 | ); | 498 | ); |
| 499 | } | 499 | } |
| 500 | 500 | ||
| 501 | test "y_string_unicode_U+200B_ZERO_WIDTH_SPACE" { | 501 | test "json.test.y_string_unicode_U+200B_ZERO_WIDTH_SPACE" { |
| 502 | ok( | 502 | ok( |
| 503 | \\["\u200B"] | 503 | \\["\u200B"] |
| 504 | ); | 504 | ); |
| 505 | } | 505 | } |
| 506 | 506 | ||
| 507 | test "y_string_unicode_U+2064_invisible_plus" { | 507 | test "json.test.y_string_unicode_U+2064_invisible_plus" { |
| 508 | ok( | 508 | ok( |
| 509 | \\["\u2064"] | 509 | \\["\u2064"] |
| 510 | ); | 510 | ); |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | test "y_string_unicode_U+FDD0_nonchar" { | 513 | test "json.test.y_string_unicode_U+FDD0_nonchar" { |
| 514 | ok( | 514 | ok( |
| 515 | \\["\uFDD0"] | 515 | \\["\uFDD0"] |
| 516 | ); | 516 | ); |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | test "y_string_unicode_U+FFFE_nonchar" { | 519 | test "json.test.y_string_unicode_U+FFFE_nonchar" { |
| 520 | ok( | 520 | ok( |
| 521 | \\["\uFFFE"] | 521 | \\["\uFFFE"] |
| 522 | ); | 522 | ); |
| 523 | } | 523 | } |
| 524 | 524 | ||
| 525 | test "y_string_utf8" { | 525 | test "json.test.y_string_utf8" { |
| 526 | ok( | 526 | ok( |
| 527 | \\["€𝄞"] | 527 | \\["€𝄞"] |
| 528 | ); | 528 | ); |
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | test "y_string_with_del_character" { | 531 | test "json.test.y_string_with_del_character" { |
| 532 | ok("[\"a\x7fa\"]"); | 532 | ok("[\"a\x7fa\"]"); |
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | test "y_structure_lonely_false" { | 535 | test "json.test.y_structure_lonely_false" { |
| 536 | ok( | 536 | ok( |
| 537 | \\false | 537 | \\false |
| 538 | ); | 538 | ); |
| 539 | } | 539 | } |
| 540 | 540 | ||
| 541 | test "y_structure_lonely_int" { | 541 | test "json.test.y_structure_lonely_int" { |
| 542 | ok( | 542 | ok( |
| 543 | \\42 | 543 | \\42 |
| 544 | ); | 544 | ); |
| 545 | } | 545 | } |
| 546 | 546 | ||
| 547 | test "y_structure_lonely_negative_real" { | 547 | test "json.test.y_structure_lonely_negative_real" { |
| 548 | ok( | 548 | ok( |
| 549 | \\-0.1 | 549 | \\-0.1 |
| 550 | ); | 550 | ); |
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | test "y_structure_lonely_null" { | 553 | test "json.test.y_structure_lonely_null" { |
| 554 | ok( | 554 | ok( |
| 555 | \\null | 555 | \\null |
| 556 | ); | 556 | ); |
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | test "y_structure_lonely_string" { | 559 | test "json.test.y_structure_lonely_string" { |
| 560 | ok( | 560 | ok( |
| 561 | \\"asd" | 561 | \\"asd" |
| 562 | ); | 562 | ); |
| 563 | } | 563 | } |
| 564 | 564 | ||
| 565 | test "y_structure_lonely_true" { | 565 | test "json.test.y_structure_lonely_true" { |
| 566 | ok( | 566 | ok( |
| 567 | \\true | 567 | \\true |
| 568 | ); | 568 | ); |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | test "y_structure_string_empty" { | 571 | test "json.test.y_structure_string_empty" { |
| 572 | ok( | 572 | ok( |
| 573 | \\"" | 573 | \\"" |
| 574 | ); | 574 | ); |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | test "y_structure_trailing_newline" { | 577 | test "json.test.y_structure_trailing_newline" { |
| 578 | ok( | 578 | ok( |
| 579 | \\["a"] | 579 | \\["a"] |
| 580 | ); | 580 | ); |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | test "y_structure_true_in_array" { | 583 | test "json.test.y_structure_true_in_array" { |
| 584 | ok( | 584 | ok( |
| 585 | \\[true] | 585 | \\[true] |
| 586 | ); | 586 | ); |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | test "y_structure_whitespace_array" { | 589 | test "json.test.y_structure_whitespace_array" { |
| 590 | ok(" [] "); | 590 | ok(" [] "); |
| 591 | } | 591 | } |
| 592 | 592 | ||
| 593 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 593 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 594 | 594 | ||
| 595 | test "n_array_1_true_without_comma" { | 595 | test "json.test.n_array_1_true_without_comma" { |
| 596 | err( | 596 | err( |
| 597 | \\[1 true] | 597 | \\[1 true] |
| 598 | ); | 598 | ); |
| 599 | } | 599 | } |
| 600 | 600 | ||
| 601 | test "n_array_a_invalid_utf8" { | 601 | test "json.test.n_array_a_invalid_utf8" { |
| 602 | err( | 602 | err( |
| 603 | \\[aå] | 603 | \\[aå] |
| 604 | ); | 604 | ); |
| 605 | } | 605 | } |
| 606 | 606 | ||
| 607 | test "n_array_colon_instead_of_comma" { | 607 | test "json.test.n_array_colon_instead_of_comma" { |
| 608 | err( | 608 | err( |
| 609 | \\["": 1] | 609 | \\["": 1] |
| 610 | ); | 610 | ); |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | test "n_array_comma_after_close" { | 613 | test "json.test.n_array_comma_after_close" { |
| 614 | //err( | 614 | //err( |
| 615 | // \\[""], | 615 | // \\[""], |
| 616 | //); | 616 | //); |
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | test "n_array_comma_and_number" { | 619 | test "json.test.n_array_comma_and_number" { |
| 620 | err( | 620 | err( |
| 621 | \\[,1] | 621 | \\[,1] |
| 622 | ); | 622 | ); |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | test "n_array_double_comma" { | 625 | test "json.test.n_array_double_comma" { |
| 626 | err( | 626 | err( |
| 627 | \\[1,,2] | 627 | \\[1,,2] |
| 628 | ); | 628 | ); |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | test "n_array_double_extra_comma" { | 631 | test "json.test.n_array_double_extra_comma" { |
| 632 | err( | 632 | err( |
| 633 | \\["x",,] | 633 | \\["x",,] |
| 634 | ); | 634 | ); |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | test "n_array_extra_close" { | 637 | test "json.test.n_array_extra_close" { |
| 638 | err( | 638 | err( |
| 639 | \\["x"]] | 639 | \\["x"]] |
| 640 | ); | 640 | ); |
| 641 | } | 641 | } |
| 642 | 642 | ||
| 643 | test "n_array_extra_comma" { | 643 | test "json.test.n_array_extra_comma" { |
| 644 | //err( | 644 | //err( |
| 645 | // \\["",] | 645 | // \\["",] |
| 646 | //); | 646 | //); |
| 647 | } | 647 | } |
| 648 | 648 | ||
| 649 | test "n_array_incomplete_invalid_value" { | 649 | test "json.test.n_array_incomplete_invalid_value" { |
| 650 | err( | 650 | err( |
| 651 | \\[x | 651 | \\[x |
| 652 | ); | 652 | ); |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | test "n_array_incomplete" { | 655 | test "json.test.n_array_incomplete" { |
| 656 | err( | 656 | err( |
| 657 | \\["x" | 657 | \\["x" |
| 658 | ); | 658 | ); |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | test "n_array_inner_array_no_comma" { | 661 | test "json.test.n_array_inner_array_no_comma" { |
| 662 | err( | 662 | err( |
| 663 | \\[3[4]] | 663 | \\[3[4]] |
| 664 | ); | 664 | ); |
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | test "n_array_invalid_utf8" { | 667 | test "json.test.n_array_invalid_utf8" { |
| 668 | err( | 668 | err( |
| 669 | \\[ÿ] | 669 | \\[ÿ] |
| 670 | ); | 670 | ); |
| 671 | } | 671 | } |
| 672 | 672 | ||
| 673 | test "n_array_items_separated_by_semicolon" { | 673 | test "json.test.n_array_items_separated_by_semicolon" { |
| 674 | err( | 674 | err( |
| 675 | \\[1:2] | 675 | \\[1:2] |
| 676 | ); | 676 | ); |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | test "n_array_just_comma" { | 679 | test "json.test.n_array_just_comma" { |
| 680 | err( | 680 | err( |
| 681 | \\[,] | 681 | \\[,] |
| 682 | ); | 682 | ); |
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | test "n_array_just_minus" { | 685 | test "json.test.n_array_just_minus" { |
| 686 | err( | 686 | err( |
| 687 | \\[-] | 687 | \\[-] |
| 688 | ); | 688 | ); |
| 689 | } | 689 | } |
| 690 | 690 | ||
| 691 | test "n_array_missing_value" { | 691 | test "json.test.n_array_missing_value" { |
| 692 | err( | 692 | err( |
| 693 | \\[ , ""] | 693 | \\[ , ""] |
| 694 | ); | 694 | ); |
| 695 | } | 695 | } |
| 696 | 696 | ||
| 697 | test "n_array_newlines_unclosed" { | 697 | test "json.test.n_array_newlines_unclosed" { |
| 698 | err( | 698 | err( |
| 699 | \\["a", | 699 | \\["a", |
| 700 | \\4 | 700 | \\4 |
| ... | @@ -702,41 +702,41 @@ test "n_array_newlines_unclosed" { | ... | @@ -702,41 +702,41 @@ test "n_array_newlines_unclosed" { |
| 702 | ); | 702 | ); |
| 703 | } | 703 | } |
| 704 | 704 | ||
| 705 | test "n_array_number_and_comma" { | 705 | test "json.test.n_array_number_and_comma" { |
| 706 | err( | 706 | err( |
| 707 | \\[1,] | 707 | \\[1,] |
| 708 | ); | 708 | ); |
| 709 | } | 709 | } |
| 710 | 710 | ||
| 711 | test "n_array_number_and_several_commas" { | 711 | test "json.test.n_array_number_and_several_commas" { |
| 712 | err( | 712 | err( |
| 713 | \\[1,,] | 713 | \\[1,,] |
| 714 | ); | 714 | ); |
| 715 | } | 715 | } |
| 716 | 716 | ||
| 717 | test "n_array_spaces_vertical_tab_formfeed" { | 717 | test "json.test.n_array_spaces_vertical_tab_formfeed" { |
| 718 | err("[\"\x0aa\"\\f]"); | 718 | err("[\"\x0aa\"\\f]"); |
| 719 | } | 719 | } |
| 720 | 720 | ||
| 721 | test "n_array_star_inside" { | 721 | test "json.test.n_array_star_inside" { |
| 722 | err( | 722 | err( |
| 723 | \\[*] | 723 | \\[*] |
| 724 | ); | 724 | ); |
| 725 | } | 725 | } |
| 726 | 726 | ||
| 727 | test "n_array_unclosed" { | 727 | test "json.test.n_array_unclosed" { |
| 728 | err( | 728 | err( |
| 729 | \\["" | 729 | \\["" |
| 730 | ); | 730 | ); |
| 731 | } | 731 | } |
| 732 | 732 | ||
| 733 | test "n_array_unclosed_trailing_comma" { | 733 | test "json.test.n_array_unclosed_trailing_comma" { |
| 734 | err( | 734 | err( |
| 735 | \\[1, | 735 | \\[1, |
| 736 | ); | 736 | ); |
| 737 | } | 737 | } |
| 738 | 738 | ||
| 739 | test "n_array_unclosed_with_new_lines" { | 739 | test "json.test.n_array_unclosed_with_new_lines" { |
| 740 | err( | 740 | err( |
| 741 | \\[1, | 741 | \\[1, |
| 742 | \\1 | 742 | \\1 |
| ... | @@ -744,956 +744,956 @@ test "n_array_unclosed_with_new_lines" { | ... | @@ -744,956 +744,956 @@ test "n_array_unclosed_with_new_lines" { |
| 744 | ); | 744 | ); |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | test "n_array_unclosed_with_object_inside" { | 747 | test "json.test.n_array_unclosed_with_object_inside" { |
| 748 | err( | 748 | err( |
| 749 | \\[{} | 749 | \\[{} |
| 750 | ); | 750 | ); |
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | test "n_incomplete_false" { | 753 | test "json.test.n_incomplete_false" { |
| 754 | err( | 754 | err( |
| 755 | \\[fals] | 755 | \\[fals] |
| 756 | ); | 756 | ); |
| 757 | } | 757 | } |
| 758 | 758 | ||
| 759 | test "n_incomplete_null" { | 759 | test "json.test.n_incomplete_null" { |
| 760 | err( | 760 | err( |
| 761 | \\[nul] | 761 | \\[nul] |
| 762 | ); | 762 | ); |
| 763 | } | 763 | } |
| 764 | 764 | ||
| 765 | test "n_incomplete_true" { | 765 | test "json.test.n_incomplete_true" { |
| 766 | err( | 766 | err( |
| 767 | \\[tru] | 767 | \\[tru] |
| 768 | ); | 768 | ); |
| 769 | } | 769 | } |
| 770 | 770 | ||
| 771 | test "n_multidigit_number_then_00" { | 771 | test "json.test.n_multidigit_number_then_00" { |
| 772 | err("123\x00"); | 772 | err("123\x00"); |
| 773 | } | 773 | } |
| 774 | 774 | ||
| 775 | test "n_number_0.1.2" { | 775 | test "json.test.n_number_0.1.2" { |
| 776 | err( | 776 | err( |
| 777 | \\[0.1.2] | 777 | \\[0.1.2] |
| 778 | ); | 778 | ); |
| 779 | } | 779 | } |
| 780 | 780 | ||
| 781 | test "n_number_-01" { | 781 | test "json.test.n_number_-01" { |
| 782 | err( | 782 | err( |
| 783 | \\[-01] | 783 | \\[-01] |
| 784 | ); | 784 | ); |
| 785 | } | 785 | } |
| 786 | 786 | ||
| 787 | test "n_number_0.3e" { | 787 | test "json.test.n_number_0.3e" { |
| 788 | err( | 788 | err( |
| 789 | \\[0.3e] | 789 | \\[0.3e] |
| 790 | ); | 790 | ); |
| 791 | } | 791 | } |
| 792 | 792 | ||
| 793 | test "n_number_0.3e+" { | 793 | test "json.test.n_number_0.3e+" { |
| 794 | err( | 794 | err( |
| 795 | \\[0.3e+] | 795 | \\[0.3e+] |
| 796 | ); | 796 | ); |
| 797 | } | 797 | } |
| 798 | 798 | ||
| 799 | test "n_number_0_capital_E" { | 799 | test "json.test.n_number_0_capital_E" { |
| 800 | err( | 800 | err( |
| 801 | \\[0E] | 801 | \\[0E] |
| 802 | ); | 802 | ); |
| 803 | } | 803 | } |
| 804 | 804 | ||
| 805 | test "n_number_0_capital_E+" { | 805 | test "json.test.n_number_0_capital_E+" { |
| 806 | err( | 806 | err( |
| 807 | \\[0E+] | 807 | \\[0E+] |
| 808 | ); | 808 | ); |
| 809 | } | 809 | } |
| 810 | 810 | ||
| 811 | test "n_number_0.e1" { | 811 | test "json.test.n_number_0.e1" { |
| 812 | err( | 812 | err( |
| 813 | \\[0.e1] | 813 | \\[0.e1] |
| 814 | ); | 814 | ); |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | test "n_number_0e" { | 817 | test "json.test.n_number_0e" { |
| 818 | err( | 818 | err( |
| 819 | \\[0e] | 819 | \\[0e] |
| 820 | ); | 820 | ); |
| 821 | } | 821 | } |
| 822 | 822 | ||
| 823 | test "n_number_0e+" { | 823 | test "json.test.n_number_0e+" { |
| 824 | err( | 824 | err( |
| 825 | \\[0e+] | 825 | \\[0e+] |
| 826 | ); | 826 | ); |
| 827 | } | 827 | } |
| 828 | 828 | ||
| 829 | test "n_number_1_000" { | 829 | test "json.test.n_number_1_000" { |
| 830 | err( | 830 | err( |
| 831 | \\[1 000.0] | 831 | \\[1 000.0] |
| 832 | ); | 832 | ); |
| 833 | } | 833 | } |
| 834 | 834 | ||
| 835 | test "n_number_1.0e-" { | 835 | test "json.test.n_number_1.0e-" { |
| 836 | err( | 836 | err( |
| 837 | \\[1.0e-] | 837 | \\[1.0e-] |
| 838 | ); | 838 | ); |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | test "n_number_1.0e" { | 841 | test "json.test.n_number_1.0e" { |
| 842 | err( | 842 | err( |
| 843 | \\[1.0e] | 843 | \\[1.0e] |
| 844 | ); | 844 | ); |
| 845 | } | 845 | } |
| 846 | 846 | ||
| 847 | test "n_number_1.0e+" { | 847 | test "json.test.n_number_1.0e+" { |
| 848 | err( | 848 | err( |
| 849 | \\[1.0e+] | 849 | \\[1.0e+] |
| 850 | ); | 850 | ); |
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | test "n_number_-1.0." { | 853 | test "json.test.n_number_-1.0." { |
| 854 | err( | 854 | err( |
| 855 | \\[-1.0.] | 855 | \\[-1.0.] |
| 856 | ); | 856 | ); |
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | test "n_number_1eE2" { | 859 | test "json.test.n_number_1eE2" { |
| 860 | err( | 860 | err( |
| 861 | \\[1eE2] | 861 | \\[1eE2] |
| 862 | ); | 862 | ); |
| 863 | } | 863 | } |
| 864 | 864 | ||
| 865 | test "n_number_.-1" { | 865 | test "json.test.n_number_.-1" { |
| 866 | err( | 866 | err( |
| 867 | \\[.-1] | 867 | \\[.-1] |
| 868 | ); | 868 | ); |
| 869 | } | 869 | } |
| 870 | 870 | ||
| 871 | test "n_number_+1" { | 871 | test "json.test.n_number_+1" { |
| 872 | err( | 872 | err( |
| 873 | \\[+1] | 873 | \\[+1] |
| 874 | ); | 874 | ); |
| 875 | } | 875 | } |
| 876 | 876 | ||
| 877 | test "n_number_.2e-3" { | 877 | test "json.test.n_number_.2e-3" { |
| 878 | err( | 878 | err( |
| 879 | \\[.2e-3] | 879 | \\[.2e-3] |
| 880 | ); | 880 | ); |
| 881 | } | 881 | } |
| 882 | 882 | ||
| 883 | test "n_number_2.e-3" { | 883 | test "json.test.n_number_2.e-3" { |
| 884 | err( | 884 | err( |
| 885 | \\[2.e-3] | 885 | \\[2.e-3] |
| 886 | ); | 886 | ); |
| 887 | } | 887 | } |
| 888 | 888 | ||
| 889 | test "n_number_2.e+3" { | 889 | test "json.test.n_number_2.e+3" { |
| 890 | err( | 890 | err( |
| 891 | \\[2.e+3] | 891 | \\[2.e+3] |
| 892 | ); | 892 | ); |
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | test "n_number_2.e3" { | 895 | test "json.test.n_number_2.e3" { |
| 896 | err( | 896 | err( |
| 897 | \\[2.e3] | 897 | \\[2.e3] |
| 898 | ); | 898 | ); |
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | test "n_number_-2." { | 901 | test "json.test.n_number_-2." { |
| 902 | err( | 902 | err( |
| 903 | \\[-2.] | 903 | \\[-2.] |
| 904 | ); | 904 | ); |
| 905 | } | 905 | } |
| 906 | 906 | ||
| 907 | test "n_number_9.e+" { | 907 | test "json.test.n_number_9.e+" { |
| 908 | err( | 908 | err( |
| 909 | \\[9.e+] | 909 | \\[9.e+] |
| 910 | ); | 910 | ); |
| 911 | } | 911 | } |
| 912 | 912 | ||
| 913 | test "n_number_expression" { | 913 | test "json.test.n_number_expression" { |
| 914 | err( | 914 | err( |
| 915 | \\[1+2] | 915 | \\[1+2] |
| 916 | ); | 916 | ); |
| 917 | } | 917 | } |
| 918 | 918 | ||
| 919 | test "n_number_hex_1_digit" { | 919 | test "json.test.n_number_hex_1_digit" { |
| 920 | err( | 920 | err( |
| 921 | \\[0x1] | 921 | \\[0x1] |
| 922 | ); | 922 | ); |
| 923 | } | 923 | } |
| 924 | 924 | ||
| 925 | test "n_number_hex_2_digits" { | 925 | test "json.test.n_number_hex_2_digits" { |
| 926 | err( | 926 | err( |
| 927 | \\[0x42] | 927 | \\[0x42] |
| 928 | ); | 928 | ); |
| 929 | } | 929 | } |
| 930 | 930 | ||
| 931 | test "n_number_infinity" { | 931 | test "json.test.n_number_infinity" { |
| 932 | err( | 932 | err( |
| 933 | \\[Infinity] | 933 | \\[Infinity] |
| 934 | ); | 934 | ); |
| 935 | } | 935 | } |
| 936 | 936 | ||
| 937 | test "n_number_+Inf" { | 937 | test "json.test.n_number_+Inf" { |
| 938 | err( | 938 | err( |
| 939 | \\[+Inf] | 939 | \\[+Inf] |
| 940 | ); | 940 | ); |
| 941 | } | 941 | } |
| 942 | 942 | ||
| 943 | test "n_number_Inf" { | 943 | test "json.test.n_number_Inf" { |
| 944 | err( | 944 | err( |
| 945 | \\[Inf] | 945 | \\[Inf] |
| 946 | ); | 946 | ); |
| 947 | } | 947 | } |
| 948 | 948 | ||
| 949 | test "n_number_invalid+-" { | 949 | test "json.test.n_number_invalid+-" { |
| 950 | err( | 950 | err( |
| 951 | \\[0e+-1] | 951 | \\[0e+-1] |
| 952 | ); | 952 | ); |
| 953 | } | 953 | } |
| 954 | 954 | ||
| 955 | test "n_number_invalid-negative-real" { | 955 | test "json.test.n_number_invalid-negative-real" { |
| 956 | err( | 956 | err( |
| 957 | \\[-123.123foo] | 957 | \\[-123.123foo] |
| 958 | ); | 958 | ); |
| 959 | } | 959 | } |
| 960 | 960 | ||
| 961 | test "n_number_invalid-utf-8-in-bigger-int" { | 961 | test "json.test.n_number_invalid-utf-8-in-bigger-int" { |
| 962 | err( | 962 | err( |
| 963 | \\[123å] | 963 | \\[123å] |
| 964 | ); | 964 | ); |
| 965 | } | 965 | } |
| 966 | 966 | ||
| 967 | test "n_number_invalid-utf-8-in-exponent" { | 967 | test "json.test.n_number_invalid-utf-8-in-exponent" { |
| 968 | err( | 968 | err( |
| 969 | \\[1e1å] | 969 | \\[1e1å] |
| 970 | ); | 970 | ); |
| 971 | } | 971 | } |
| 972 | 972 | ||
| 973 | test "n_number_invalid-utf-8-in-int" { | 973 | test "json.test.n_number_invalid-utf-8-in-int" { |
| 974 | err( | 974 | err( |
| 975 | \\[0å] | 975 | \\[0å] |
| 976 | ); | 976 | ); |
| 977 | } | 977 | } |
| 978 | 978 | ||
| 979 | test "n_number_++" { | 979 | test "json.test.n_number_++" { |
| 980 | err( | 980 | err( |
| 981 | \\[++1234] | 981 | \\[++1234] |
| 982 | ); | 982 | ); |
| 983 | } | 983 | } |
| 984 | 984 | ||
| 985 | test "n_number_minus_infinity" { | 985 | test "json.test.n_number_minus_infinity" { |
| 986 | err( | 986 | err( |
| 987 | \\[-Infinity] | 987 | \\[-Infinity] |
| 988 | ); | 988 | ); |
| 989 | } | 989 | } |
| 990 | 990 | ||
| 991 | test "n_number_minus_sign_with_trailing_garbage" { | 991 | test "json.test.n_number_minus_sign_with_trailing_garbage" { |
| 992 | err( | 992 | err( |
| 993 | \\[-foo] | 993 | \\[-foo] |
| 994 | ); | 994 | ); |
| 995 | } | 995 | } |
| 996 | 996 | ||
| 997 | test "n_number_minus_space_1" { | 997 | test "json.test.n_number_minus_space_1" { |
| 998 | err( | 998 | err( |
| 999 | \\[- 1] | 999 | \\[- 1] |
| 1000 | ); | 1000 | ); |
| 1001 | } | 1001 | } |
| 1002 | 1002 | ||
| 1003 | test "n_number_-NaN" { | 1003 | test "json.test.n_number_-NaN" { |
| 1004 | err( | 1004 | err( |
| 1005 | \\[-NaN] | 1005 | \\[-NaN] |
| 1006 | ); | 1006 | ); |
| 1007 | } | 1007 | } |
| 1008 | 1008 | ||
| 1009 | test "n_number_NaN" { | 1009 | test "json.test.n_number_NaN" { |
| 1010 | err( | 1010 | err( |
| 1011 | \\[NaN] | 1011 | \\[NaN] |
| 1012 | ); | 1012 | ); |
| 1013 | } | 1013 | } |
| 1014 | 1014 | ||
| 1015 | test "n_number_neg_int_starting_with_zero" { | 1015 | test "json.test.n_number_neg_int_starting_with_zero" { |
| 1016 | err( | 1016 | err( |
| 1017 | \\[-012] | 1017 | \\[-012] |
| 1018 | ); | 1018 | ); |
| 1019 | } | 1019 | } |
| 1020 | 1020 | ||
| 1021 | test "n_number_neg_real_without_int_part" { | 1021 | test "json.test.n_number_neg_real_without_int_part" { |
| 1022 | err( | 1022 | err( |
| 1023 | \\[-.123] | 1023 | \\[-.123] |
| 1024 | ); | 1024 | ); |
| 1025 | } | 1025 | } |
| 1026 | 1026 | ||
| 1027 | test "n_number_neg_with_garbage_at_end" { | 1027 | test "json.test.n_number_neg_with_garbage_at_end" { |
| 1028 | err( | 1028 | err( |
| 1029 | \\[-1x] | 1029 | \\[-1x] |
| 1030 | ); | 1030 | ); |
| 1031 | } | 1031 | } |
| 1032 | 1032 | ||
| 1033 | test "n_number_real_garbage_after_e" { | 1033 | test "json.test.n_number_real_garbage_after_e" { |
| 1034 | err( | 1034 | err( |
| 1035 | \\[1ea] | 1035 | \\[1ea] |
| 1036 | ); | 1036 | ); |
| 1037 | } | 1037 | } |
| 1038 | 1038 | ||
| 1039 | test "n_number_real_with_invalid_utf8_after_e" { | 1039 | test "json.test.n_number_real_with_invalid_utf8_after_e" { |
| 1040 | err( | 1040 | err( |
| 1041 | \\[1eå] | 1041 | \\[1eå] |
| 1042 | ); | 1042 | ); |
| 1043 | } | 1043 | } |
| 1044 | 1044 | ||
| 1045 | test "n_number_real_without_fractional_part" { | 1045 | test "json.test.n_number_real_without_fractional_part" { |
| 1046 | err( | 1046 | err( |
| 1047 | \\[1.] | 1047 | \\[1.] |
| 1048 | ); | 1048 | ); |
| 1049 | } | 1049 | } |
| 1050 | 1050 | ||
| 1051 | test "n_number_starting_with_dot" { | 1051 | test "json.test.n_number_starting_with_dot" { |
| 1052 | err( | 1052 | err( |
| 1053 | \\[.123] | 1053 | \\[.123] |
| 1054 | ); | 1054 | ); |
| 1055 | } | 1055 | } |
| 1056 | 1056 | ||
| 1057 | test "n_number_U+FF11_fullwidth_digit_one" { | 1057 | test "json.test.n_number_U+FF11_fullwidth_digit_one" { |
| 1058 | err( | 1058 | err( |
| 1059 | \\[ï¼] | 1059 | \\[ï¼] |
| 1060 | ); | 1060 | ); |
| 1061 | } | 1061 | } |
| 1062 | 1062 | ||
| 1063 | test "n_number_with_alpha_char" { | 1063 | test "json.test.n_number_with_alpha_char" { |
| 1064 | err( | 1064 | err( |
| 1065 | \\[1.8011670033376514H-308] | 1065 | \\[1.8011670033376514H-308] |
| 1066 | ); | 1066 | ); |
| 1067 | } | 1067 | } |
| 1068 | 1068 | ||
| 1069 | test "n_number_with_alpha" { | 1069 | test "json.test.n_number_with_alpha" { |
| 1070 | err( | 1070 | err( |
| 1071 | \\[1.2a-3] | 1071 | \\[1.2a-3] |
| 1072 | ); | 1072 | ); |
| 1073 | } | 1073 | } |
| 1074 | 1074 | ||
| 1075 | test "n_number_with_leading_zero" { | 1075 | test "json.test.n_number_with_leading_zero" { |
| 1076 | err( | 1076 | err( |
| 1077 | \\[012] | 1077 | \\[012] |
| 1078 | ); | 1078 | ); |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 1081 | test "n_object_bad_value" { | 1081 | test "json.test.n_object_bad_value" { |
| 1082 | err( | 1082 | err( |
| 1083 | \\["x", truth] | 1083 | \\["x", truth] |
| 1084 | ); | 1084 | ); |
| 1085 | } | 1085 | } |
| 1086 | 1086 | ||
| 1087 | test "n_object_bracket_key" { | 1087 | test "json.test.n_object_bracket_key" { |
| 1088 | err( | 1088 | err( |
| 1089 | \\{[: "x"} | 1089 | \\{[: "x"} |
| 1090 | ); | 1090 | ); |
| 1091 | } | 1091 | } |
| 1092 | 1092 | ||
| 1093 | test "n_object_comma_instead_of_colon" { | 1093 | test "json.test.n_object_comma_instead_of_colon" { |
| 1094 | err( | 1094 | err( |
| 1095 | \\{"x", null} | 1095 | \\{"x", null} |
| 1096 | ); | 1096 | ); |
| 1097 | } | 1097 | } |
| 1098 | 1098 | ||
| 1099 | test "n_object_double_colon" { | 1099 | test "json.test.n_object_double_colon" { |
| 1100 | err( | 1100 | err( |
| 1101 | \\{"x"::"b"} | 1101 | \\{"x"::"b"} |
| 1102 | ); | 1102 | ); |
| 1103 | } | 1103 | } |
| 1104 | 1104 | ||
| 1105 | test "n_object_emoji" { | 1105 | test "json.test.n_object_emoji" { |
| 1106 | err( | 1106 | err( |
| 1107 | \\{ð¨ð} | 1107 | \\{ð¨ð} |
| 1108 | ); | 1108 | ); |
| 1109 | } | 1109 | } |
| 1110 | 1110 | ||
| 1111 | test "n_object_garbage_at_end" { | 1111 | test "json.test.n_object_garbage_at_end" { |
| 1112 | err( | 1112 | err( |
| 1113 | \\{"a":"a" 123} | 1113 | \\{"a":"a" 123} |
| 1114 | ); | 1114 | ); |
| 1115 | } | 1115 | } |
| 1116 | 1116 | ||
| 1117 | test "n_object_key_with_single_quotes" { | 1117 | test "json.test.n_object_key_with_single_quotes" { |
| 1118 | err( | 1118 | err( |
| 1119 | \\{key: 'value'} | 1119 | \\{key: 'value'} |
| 1120 | ); | 1120 | ); |
| 1121 | } | 1121 | } |
| 1122 | 1122 | ||
| 1123 | test "n_object_lone_continuation_byte_in_key_and_trailing_comma" { | 1123 | test "json.test.n_object_lone_continuation_byte_in_key_and_trailing_comma" { |
| 1124 | err( | 1124 | err( |
| 1125 | \\{"¹":"0",} | 1125 | \\{"¹":"0",} |
| 1126 | ); | 1126 | ); |
| 1127 | } | 1127 | } |
| 1128 | 1128 | ||
| 1129 | test "n_object_missing_colon" { | 1129 | test "json.test.n_object_missing_colon" { |
| 1130 | err( | 1130 | err( |
| 1131 | \\{"a" b} | 1131 | \\{"a" b} |
| 1132 | ); | 1132 | ); |
| 1133 | } | 1133 | } |
| 1134 | 1134 | ||
| 1135 | test "n_object_missing_key" { | 1135 | test "json.test.n_object_missing_key" { |
| 1136 | err( | 1136 | err( |
| 1137 | \\{:"b"} | 1137 | \\{:"b"} |
| 1138 | ); | 1138 | ); |
| 1139 | } | 1139 | } |
| 1140 | 1140 | ||
| 1141 | test "n_object_missing_semicolon" { | 1141 | test "json.test.n_object_missing_semicolon" { |
| 1142 | err( | 1142 | err( |
| 1143 | \\{"a" "b"} | 1143 | \\{"a" "b"} |
| 1144 | ); | 1144 | ); |
| 1145 | } | 1145 | } |
| 1146 | 1146 | ||
| 1147 | test "n_object_missing_value" { | 1147 | test "json.test.n_object_missing_value" { |
| 1148 | err( | 1148 | err( |
| 1149 | \\{"a": | 1149 | \\{"a": |
| 1150 | ); | 1150 | ); |
| 1151 | } | 1151 | } |
| 1152 | 1152 | ||
| 1153 | test "n_object_no-colon" { | 1153 | test "json.test.n_object_no-colon" { |
| 1154 | err( | 1154 | err( |
| 1155 | \\{"a" | 1155 | \\{"a" |
| 1156 | ); | 1156 | ); |
| 1157 | } | 1157 | } |
| 1158 | 1158 | ||
| 1159 | test "n_object_non_string_key_but_huge_number_instead" { | 1159 | test "json.test.n_object_non_string_key_but_huge_number_instead" { |
| 1160 | err( | 1160 | err( |
| 1161 | \\{9999E9999:1} | 1161 | \\{9999E9999:1} |
| 1162 | ); | 1162 | ); |
| 1163 | } | 1163 | } |
| 1164 | 1164 | ||
| 1165 | test "n_object_non_string_key" { | 1165 | test "json.test.n_object_non_string_key" { |
| 1166 | err( | 1166 | err( |
| 1167 | \\{1:1} | 1167 | \\{1:1} |
| 1168 | ); | 1168 | ); |
| 1169 | } | 1169 | } |
| 1170 | 1170 | ||
| 1171 | test "n_object_repeated_null_null" { | 1171 | test "json.test.n_object_repeated_null_null" { |
| 1172 | err( | 1172 | err( |
| 1173 | \\{null:null,null:null} | 1173 | \\{null:null,null:null} |
| 1174 | ); | 1174 | ); |
| 1175 | } | 1175 | } |
| 1176 | 1176 | ||
| 1177 | test "n_object_several_trailing_commas" { | 1177 | test "json.test.n_object_several_trailing_commas" { |
| 1178 | err( | 1178 | err( |
| 1179 | \\{"id":0,,,,,} | 1179 | \\{"id":0,,,,,} |
| 1180 | ); | 1180 | ); |
| 1181 | } | 1181 | } |
| 1182 | 1182 | ||
| 1183 | test "n_object_single_quote" { | 1183 | test "json.test.n_object_single_quote" { |
| 1184 | err( | 1184 | err( |
| 1185 | \\{'a':0} | 1185 | \\{'a':0} |
| 1186 | ); | 1186 | ); |
| 1187 | } | 1187 | } |
| 1188 | 1188 | ||
| 1189 | test "n_object_trailing_comma" { | 1189 | test "json.test.n_object_trailing_comma" { |
| 1190 | err( | 1190 | err( |
| 1191 | \\{"id":0,} | 1191 | \\{"id":0,} |
| 1192 | ); | 1192 | ); |
| 1193 | } | 1193 | } |
| 1194 | 1194 | ||
| 1195 | test "n_object_trailing_comment" { | 1195 | test "json.test.n_object_trailing_comment" { |
| 1196 | err( | 1196 | err( |
| 1197 | \\{"a":"b"}/**/ | 1197 | \\{"a":"b"}/**/ |
| 1198 | ); | 1198 | ); |
| 1199 | } | 1199 | } |
| 1200 | 1200 | ||
| 1201 | test "n_object_trailing_comment_open" { | 1201 | test "json.test.n_object_trailing_comment_open" { |
| 1202 | err( | 1202 | err( |
| 1203 | \\{"a":"b"}/**// | 1203 | \\{"a":"b"}/**// |
| 1204 | ); | 1204 | ); |
| 1205 | } | 1205 | } |
| 1206 | 1206 | ||
| 1207 | test "n_object_trailing_comment_slash_open_incomplete" { | 1207 | test "json.test.n_object_trailing_comment_slash_open_incomplete" { |
| 1208 | err( | 1208 | err( |
| 1209 | \\{"a":"b"}/ | 1209 | \\{"a":"b"}/ |
| 1210 | ); | 1210 | ); |
| 1211 | } | 1211 | } |
| 1212 | 1212 | ||
| 1213 | test "n_object_trailing_comment_slash_open" { | 1213 | test "json.test.n_object_trailing_comment_slash_open" { |
| 1214 | err( | 1214 | err( |
| 1215 | \\{"a":"b"}// | 1215 | \\{"a":"b"}// |
| 1216 | ); | 1216 | ); |
| 1217 | } | 1217 | } |
| 1218 | 1218 | ||
| 1219 | test "n_object_two_commas_in_a_row" { | 1219 | test "json.test.n_object_two_commas_in_a_row" { |
| 1220 | err( | 1220 | err( |
| 1221 | \\{"a":"b",,"c":"d"} | 1221 | \\{"a":"b",,"c":"d"} |
| 1222 | ); | 1222 | ); |
| 1223 | } | 1223 | } |
| 1224 | 1224 | ||
| 1225 | test "n_object_unquoted_key" { | 1225 | test "json.test.n_object_unquoted_key" { |
| 1226 | err( | 1226 | err( |
| 1227 | \\{a: "b"} | 1227 | \\{a: "b"} |
| 1228 | ); | 1228 | ); |
| 1229 | } | 1229 | } |
| 1230 | 1230 | ||
| 1231 | test "n_object_unterminated-value" { | 1231 | test "json.test.n_object_unterminated-value" { |
| 1232 | err( | 1232 | err( |
| 1233 | \\{"a":"a | 1233 | \\{"a":"a |
| 1234 | ); | 1234 | ); |
| 1235 | } | 1235 | } |
| 1236 | 1236 | ||
| 1237 | test "n_object_with_single_string" { | 1237 | test "json.test.n_object_with_single_string" { |
| 1238 | err( | 1238 | err( |
| 1239 | \\{ "foo" : "bar", "a" } | 1239 | \\{ "foo" : "bar", "a" } |
| 1240 | ); | 1240 | ); |
| 1241 | } | 1241 | } |
| 1242 | 1242 | ||
| 1243 | test "n_object_with_trailing_garbage" { | 1243 | test "json.test.n_object_with_trailing_garbage" { |
| 1244 | err( | 1244 | err( |
| 1245 | \\{"a":"b"}# | 1245 | \\{"a":"b"}# |
| 1246 | ); | 1246 | ); |
| 1247 | } | 1247 | } |
| 1248 | 1248 | ||
| 1249 | test "n_single_space" { | 1249 | test "json.test.n_single_space" { |
| 1250 | err(" "); | 1250 | err(" "); |
| 1251 | } | 1251 | } |
| 1252 | 1252 | ||
| 1253 | test "n_string_1_surrogate_then_escape" { | 1253 | test "json.test.n_string_1_surrogate_then_escape" { |
| 1254 | err( | 1254 | err( |
| 1255 | \\["\uD800\"] | 1255 | \\["\uD800\"] |
| 1256 | ); | 1256 | ); |
| 1257 | } | 1257 | } |
| 1258 | 1258 | ||
| 1259 | test "n_string_1_surrogate_then_escape_u1" { | 1259 | test "json.test.n_string_1_surrogate_then_escape_u1" { |
| 1260 | err( | 1260 | err( |
| 1261 | \\["\uD800\u1"] | 1261 | \\["\uD800\u1"] |
| 1262 | ); | 1262 | ); |
| 1263 | } | 1263 | } |
| 1264 | 1264 | ||
| 1265 | test "n_string_1_surrogate_then_escape_u1x" { | 1265 | test "json.test.n_string_1_surrogate_then_escape_u1x" { |
| 1266 | err( | 1266 | err( |
| 1267 | \\["\uD800\u1x"] | 1267 | \\["\uD800\u1x"] |
| 1268 | ); | 1268 | ); |
| 1269 | } | 1269 | } |
| 1270 | 1270 | ||
| 1271 | test "n_string_1_surrogate_then_escape_u" { | 1271 | test "json.test.n_string_1_surrogate_then_escape_u" { |
| 1272 | err( | 1272 | err( |
| 1273 | \\["\uD800\u"] | 1273 | \\["\uD800\u"] |
| 1274 | ); | 1274 | ); |
| 1275 | } | 1275 | } |
| 1276 | 1276 | ||
| 1277 | test "n_string_accentuated_char_no_quotes" { | 1277 | test "json.test.n_string_accentuated_char_no_quotes" { |
| 1278 | err( | 1278 | err( |
| 1279 | \\[é] | 1279 | \\[é] |
| 1280 | ); | 1280 | ); |
| 1281 | } | 1281 | } |
| 1282 | 1282 | ||
| 1283 | test "n_string_backslash_00" { | 1283 | test "json.test.n_string_backslash_00" { |
| 1284 | err("[\"\x00\"]"); | 1284 | err("[\"\x00\"]"); |
| 1285 | } | 1285 | } |
| 1286 | 1286 | ||
| 1287 | test "n_string_escaped_backslash_bad" { | 1287 | test "json.test.n_string_escaped_backslash_bad" { |
| 1288 | err( | 1288 | err( |
| 1289 | \\["\\\"] | 1289 | \\["\\\"] |
| 1290 | ); | 1290 | ); |
| 1291 | } | 1291 | } |
| 1292 | 1292 | ||
| 1293 | test "n_string_escaped_ctrl_char_tab" { | 1293 | test "json.test.n_string_escaped_ctrl_char_tab" { |
| 1294 | err("\x5b\x22\x5c\x09\x22\x5d"); | 1294 | err("\x5b\x22\x5c\x09\x22\x5d"); |
| 1295 | } | 1295 | } |
| 1296 | 1296 | ||
| 1297 | test "n_string_escaped_emoji" { | 1297 | test "json.test.n_string_escaped_emoji" { |
| 1298 | err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]"); | 1298 | err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]"); |
| 1299 | } | 1299 | } |
| 1300 | 1300 | ||
| 1301 | test "n_string_escape_x" { | 1301 | test "json.test.n_string_escape_x" { |
| 1302 | err( | 1302 | err( |
| 1303 | \\["\x00"] | 1303 | \\["\x00"] |
| 1304 | ); | 1304 | ); |
| 1305 | } | 1305 | } |
| 1306 | 1306 | ||
| 1307 | test "n_string_incomplete_escaped_character" { | 1307 | test "json.test.n_string_incomplete_escaped_character" { |
| 1308 | err( | 1308 | err( |
| 1309 | \\["\u00A"] | 1309 | \\["\u00A"] |
| 1310 | ); | 1310 | ); |
| 1311 | } | 1311 | } |
| 1312 | 1312 | ||
| 1313 | test "n_string_incomplete_escape" { | 1313 | test "json.test.n_string_incomplete_escape" { |
| 1314 | err( | 1314 | err( |
| 1315 | \\["\"] | 1315 | \\["\"] |
| 1316 | ); | 1316 | ); |
| 1317 | } | 1317 | } |
| 1318 | 1318 | ||
| 1319 | test "n_string_incomplete_surrogate_escape_invalid" { | 1319 | test "json.test.n_string_incomplete_surrogate_escape_invalid" { |
| 1320 | err( | 1320 | err( |
| 1321 | \\["\uD800\uD800\x"] | 1321 | \\["\uD800\uD800\x"] |
| 1322 | ); | 1322 | ); |
| 1323 | } | 1323 | } |
| 1324 | 1324 | ||
| 1325 | test "n_string_incomplete_surrogate" { | 1325 | test "json.test.n_string_incomplete_surrogate" { |
| 1326 | err( | 1326 | err( |
| 1327 | \\["\uD834\uDd"] | 1327 | \\["\uD834\uDd"] |
| 1328 | ); | 1328 | ); |
| 1329 | } | 1329 | } |
| 1330 | 1330 | ||
| 1331 | test "n_string_invalid_backslash_esc" { | 1331 | test "json.test.n_string_invalid_backslash_esc" { |
| 1332 | err( | 1332 | err( |
| 1333 | \\["\a"] | 1333 | \\["\a"] |
| 1334 | ); | 1334 | ); |
| 1335 | } | 1335 | } |
| 1336 | 1336 | ||
| 1337 | test "n_string_invalid_unicode_escape" { | 1337 | test "json.test.n_string_invalid_unicode_escape" { |
| 1338 | err( | 1338 | err( |
| 1339 | \\["\uqqqq"] | 1339 | \\["\uqqqq"] |
| 1340 | ); | 1340 | ); |
| 1341 | } | 1341 | } |
| 1342 | 1342 | ||
| 1343 | test "n_string_invalid_utf8_after_escape" { | 1343 | test "json.test.n_string_invalid_utf8_after_escape" { |
| 1344 | err("[\"\\\x75\xc3\xa5\"]"); | 1344 | err("[\"\\\x75\xc3\xa5\"]"); |
| 1345 | } | 1345 | } |
| 1346 | 1346 | ||
| 1347 | test "n_string_invalid-utf-8-in-escape" { | 1347 | test "json.test.n_string_invalid-utf-8-in-escape" { |
| 1348 | err( | 1348 | err( |
| 1349 | \\["\uå"] | 1349 | \\["\uå"] |
| 1350 | ); | 1350 | ); |
| 1351 | } | 1351 | } |
| 1352 | 1352 | ||
| 1353 | test "n_string_leading_uescaped_thinspace" { | 1353 | test "json.test.n_string_leading_uescaped_thinspace" { |
| 1354 | err( | 1354 | err( |
| 1355 | \\[\u0020"asd"] | 1355 | \\[\u0020"asd"] |
| 1356 | ); | 1356 | ); |
| 1357 | } | 1357 | } |
| 1358 | 1358 | ||
| 1359 | test "n_string_no_quotes_with_bad_escape" { | 1359 | test "json.test.n_string_no_quotes_with_bad_escape" { |
| 1360 | err( | 1360 | err( |
| 1361 | \\[\n] | 1361 | \\[\n] |
| 1362 | ); | 1362 | ); |
| 1363 | } | 1363 | } |
| 1364 | 1364 | ||
| 1365 | test "n_string_single_doublequote" { | 1365 | test "json.test.n_string_single_doublequote" { |
| 1366 | err( | 1366 | err( |
| 1367 | \\" | 1367 | \\" |
| 1368 | ); | 1368 | ); |
| 1369 | } | 1369 | } |
| 1370 | 1370 | ||
| 1371 | test "n_string_single_quote" { | 1371 | test "json.test.n_string_single_quote" { |
| 1372 | err( | 1372 | err( |
| 1373 | \\['single quote'] | 1373 | \\['single quote'] |
| 1374 | ); | 1374 | ); |
| 1375 | } | 1375 | } |
| 1376 | 1376 | ||
| 1377 | test "n_string_single_string_no_double_quotes" { | 1377 | test "json.test.n_string_single_string_no_double_quotes" { |
| 1378 | err( | 1378 | err( |
| 1379 | \\abc | 1379 | \\abc |
| 1380 | ); | 1380 | ); |
| 1381 | } | 1381 | } |
| 1382 | 1382 | ||
| 1383 | test "n_string_start_escape_unclosed" { | 1383 | test "json.test.n_string_start_escape_unclosed" { |
| 1384 | err( | 1384 | err( |
| 1385 | \\["\ | 1385 | \\["\ |
| 1386 | ); | 1386 | ); |
| 1387 | } | 1387 | } |
| 1388 | 1388 | ||
| 1389 | test "n_string_unescaped_crtl_char" { | 1389 | test "json.test.n_string_unescaped_crtl_char" { |
| 1390 | err("[\"a\x00a\"]"); | 1390 | err("[\"a\x00a\"]"); |
| 1391 | } | 1391 | } |
| 1392 | 1392 | ||
| 1393 | test "n_string_unescaped_newline" { | 1393 | test "json.test.n_string_unescaped_newline" { |
| 1394 | err( | 1394 | err( |
| 1395 | \\["new | 1395 | \\["new |
| 1396 | \\line"] | 1396 | \\line"] |
| 1397 | ); | 1397 | ); |
| 1398 | } | 1398 | } |
| 1399 | 1399 | ||
| 1400 | test "n_string_unescaped_tab" { | 1400 | test "json.test.n_string_unescaped_tab" { |
| 1401 | err("[\"\t\"]"); | 1401 | err("[\"\t\"]"); |
| 1402 | } | 1402 | } |
| 1403 | 1403 | ||
| 1404 | test "n_string_unicode_CapitalU" { | 1404 | test "json.test.n_string_unicode_CapitalU" { |
| 1405 | err( | 1405 | err( |
| 1406 | \\"\UA66D" | 1406 | \\"\UA66D" |
| 1407 | ); | 1407 | ); |
| 1408 | } | 1408 | } |
| 1409 | 1409 | ||
| 1410 | test "n_string_with_trailing_garbage" { | 1410 | test "json.test.n_string_with_trailing_garbage" { |
| 1411 | err( | 1411 | err( |
| 1412 | \\""x | 1412 | \\""x |
| 1413 | ); | 1413 | ); |
| 1414 | } | 1414 | } |
| 1415 | 1415 | ||
| 1416 | test "n_structure_100000_opening_arrays" { | 1416 | test "json.test.n_structure_100000_opening_arrays" { |
| 1417 | err("[" ** 100000); | 1417 | err("[" ** 100000); |
| 1418 | } | 1418 | } |
| 1419 | 1419 | ||
| 1420 | test "n_structure_angle_bracket_." { | 1420 | test "json.test.n_structure_angle_bracket_." { |
| 1421 | err( | 1421 | err( |
| 1422 | \\<.> | 1422 | \\<.> |
| 1423 | ); | 1423 | ); |
| 1424 | } | 1424 | } |
| 1425 | 1425 | ||
| 1426 | test "n_structure_angle_bracket_null" { | 1426 | test "json.test.n_structure_angle_bracket_null" { |
| 1427 | err( | 1427 | err( |
| 1428 | \\[<null>] | 1428 | \\[<null>] |
| 1429 | ); | 1429 | ); |
| 1430 | } | 1430 | } |
| 1431 | 1431 | ||
| 1432 | test "n_structure_array_trailing_garbage" { | 1432 | test "json.test.n_structure_array_trailing_garbage" { |
| 1433 | err( | 1433 | err( |
| 1434 | \\[1]x | 1434 | \\[1]x |
| 1435 | ); | 1435 | ); |
| 1436 | } | 1436 | } |
| 1437 | 1437 | ||
| 1438 | test "n_structure_array_with_extra_array_close" { | 1438 | test "json.test.n_structure_array_with_extra_array_close" { |
| 1439 | err( | 1439 | err( |
| 1440 | \\[1]] | 1440 | \\[1]] |
| 1441 | ); | 1441 | ); |
| 1442 | } | 1442 | } |
| 1443 | 1443 | ||
| 1444 | test "n_structure_array_with_unclosed_string" { | 1444 | test "json.test.n_structure_array_with_unclosed_string" { |
| 1445 | err( | 1445 | err( |
| 1446 | \\["asd] | 1446 | \\["asd] |
| 1447 | ); | 1447 | ); |
| 1448 | } | 1448 | } |
| 1449 | 1449 | ||
| 1450 | test "n_structure_ascii-unicode-identifier" { | 1450 | test "json.test.n_structure_ascii-unicode-identifier" { |
| 1451 | err( | 1451 | err( |
| 1452 | \\aå | 1452 | \\aå |
| 1453 | ); | 1453 | ); |
| 1454 | } | 1454 | } |
| 1455 | 1455 | ||
| 1456 | test "n_structure_capitalized_True" { | 1456 | test "json.test.n_structure_capitalized_True" { |
| 1457 | err( | 1457 | err( |
| 1458 | \\[True] | 1458 | \\[True] |
| 1459 | ); | 1459 | ); |
| 1460 | } | 1460 | } |
| 1461 | 1461 | ||
| 1462 | test "n_structure_close_unopened_array" { | 1462 | test "json.test.n_structure_close_unopened_array" { |
| 1463 | err( | 1463 | err( |
| 1464 | \\1] | 1464 | \\1] |
| 1465 | ); | 1465 | ); |
| 1466 | } | 1466 | } |
| 1467 | 1467 | ||
| 1468 | test "n_structure_comma_instead_of_closing_brace" { | 1468 | test "json.test.n_structure_comma_instead_of_closing_brace" { |
| 1469 | err( | 1469 | err( |
| 1470 | \\{"x": true, | 1470 | \\{"x": true, |
| 1471 | ); | 1471 | ); |
| 1472 | } | 1472 | } |
| 1473 | 1473 | ||
| 1474 | test "n_structure_double_array" { | 1474 | test "json.test.n_structure_double_array" { |
| 1475 | err( | 1475 | err( |
| 1476 | \\[][] | 1476 | \\[][] |
| 1477 | ); | 1477 | ); |
| 1478 | } | 1478 | } |
| 1479 | 1479 | ||
| 1480 | test "n_structure_end_array" { | 1480 | test "json.test.n_structure_end_array" { |
| 1481 | err( | 1481 | err( |
| 1482 | \\] | 1482 | \\] |
| 1483 | ); | 1483 | ); |
| 1484 | } | 1484 | } |
| 1485 | 1485 | ||
| 1486 | test "n_structure_incomplete_UTF8_BOM" { | 1486 | test "json.test.n_structure_incomplete_UTF8_BOM" { |
| 1487 | err( | 1487 | err( |
| 1488 | \\ï»{} | 1488 | \\ï»{} |
| 1489 | ); | 1489 | ); |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | test "n_structure_lone-invalid-utf-8" { | 1492 | test "json.test.n_structure_lone-invalid-utf-8" { |
| 1493 | err( | 1493 | err( |
| 1494 | \\å | 1494 | \\å |
| 1495 | ); | 1495 | ); |
| 1496 | } | 1496 | } |
| 1497 | 1497 | ||
| 1498 | test "n_structure_lone-open-bracket" { | 1498 | test "json.test.n_structure_lone-open-bracket" { |
| 1499 | err( | 1499 | err( |
| 1500 | \\[ | 1500 | \\[ |
| 1501 | ); | 1501 | ); |
| 1502 | } | 1502 | } |
| 1503 | 1503 | ||
| 1504 | test "n_structure_no_data" { | 1504 | test "json.test.n_structure_no_data" { |
| 1505 | err( | 1505 | err( |
| 1506 | \\ | 1506 | \\ |
| 1507 | ); | 1507 | ); |
| 1508 | } | 1508 | } |
| 1509 | 1509 | ||
| 1510 | test "n_structure_null-byte-outside-string" { | 1510 | test "json.test.n_structure_null-byte-outside-string" { |
| 1511 | err("[\x00]"); | 1511 | err("[\x00]"); |
| 1512 | } | 1512 | } |
| 1513 | 1513 | ||
| 1514 | test "n_structure_number_with_trailing_garbage" { | 1514 | test "json.test.n_structure_number_with_trailing_garbage" { |
| 1515 | err( | 1515 | err( |
| 1516 | \\2@ | 1516 | \\2@ |
| 1517 | ); | 1517 | ); |
| 1518 | } | 1518 | } |
| 1519 | 1519 | ||
| 1520 | test "n_structure_object_followed_by_closing_object" { | 1520 | test "json.test.n_structure_object_followed_by_closing_object" { |
| 1521 | err( | 1521 | err( |
| 1522 | \\{}} | 1522 | \\{}} |
| 1523 | ); | 1523 | ); |
| 1524 | } | 1524 | } |
| 1525 | 1525 | ||
| 1526 | test "n_structure_object_unclosed_no_value" { | 1526 | test "json.test.n_structure_object_unclosed_no_value" { |
| 1527 | err( | 1527 | err( |
| 1528 | \\{"": | 1528 | \\{"": |
| 1529 | ); | 1529 | ); |
| 1530 | } | 1530 | } |
| 1531 | 1531 | ||
| 1532 | test "n_structure_object_with_comment" { | 1532 | test "json.test.n_structure_object_with_comment" { |
| 1533 | err( | 1533 | err( |
| 1534 | \\{"a":/*comment*/"b"} | 1534 | \\{"a":/*comment*/"b"} |
| 1535 | ); | 1535 | ); |
| 1536 | } | 1536 | } |
| 1537 | 1537 | ||
| 1538 | test "n_structure_object_with_trailing_garbage" { | 1538 | test "json.test.n_structure_object_with_trailing_garbage" { |
| 1539 | err( | 1539 | err( |
| 1540 | \\{"a": true} "x" | 1540 | \\{"a": true} "x" |
| 1541 | ); | 1541 | ); |
| 1542 | } | 1542 | } |
| 1543 | 1543 | ||
| 1544 | test "n_structure_open_array_apostrophe" { | 1544 | test "json.test.n_structure_open_array_apostrophe" { |
| 1545 | err( | 1545 | err( |
| 1546 | \\[' | 1546 | \\[' |
| 1547 | ); | 1547 | ); |
| 1548 | } | 1548 | } |
| 1549 | 1549 | ||
| 1550 | test "n_structure_open_array_comma" { | 1550 | test "json.test.n_structure_open_array_comma" { |
| 1551 | err( | 1551 | err( |
| 1552 | \\[, | 1552 | \\[, |
| 1553 | ); | 1553 | ); |
| 1554 | } | 1554 | } |
| 1555 | 1555 | ||
| 1556 | test "n_structure_open_array_object" { | 1556 | test "json.test.n_structure_open_array_object" { |
| 1557 | err("[{\"\":" ** 50000); | 1557 | err("[{\"\":" ** 50000); |
| 1558 | } | 1558 | } |
| 1559 | 1559 | ||
| 1560 | test "n_structure_open_array_open_object" { | 1560 | test "json.test.n_structure_open_array_open_object" { |
| 1561 | err( | 1561 | err( |
| 1562 | \\[{ | 1562 | \\[{ |
| 1563 | ); | 1563 | ); |
| 1564 | } | 1564 | } |
| 1565 | 1565 | ||
| 1566 | test "n_structure_open_array_open_string" { | 1566 | test "json.test.n_structure_open_array_open_string" { |
| 1567 | err( | 1567 | err( |
| 1568 | \\["a | 1568 | \\["a |
| 1569 | ); | 1569 | ); |
| 1570 | } | 1570 | } |
| 1571 | 1571 | ||
| 1572 | test "n_structure_open_array_string" { | 1572 | test "json.test.n_structure_open_array_string" { |
| 1573 | err( | 1573 | err( |
| 1574 | \\["a" | 1574 | \\["a" |
| 1575 | ); | 1575 | ); |
| 1576 | } | 1576 | } |
| 1577 | 1577 | ||
| 1578 | test "n_structure_open_object_close_array" { | 1578 | test "json.test.n_structure_open_object_close_array" { |
| 1579 | err( | 1579 | err( |
| 1580 | \\{] | 1580 | \\{] |
| 1581 | ); | 1581 | ); |
| 1582 | } | 1582 | } |
| 1583 | 1583 | ||
| 1584 | test "n_structure_open_object_comma" { | 1584 | test "json.test.n_structure_open_object_comma" { |
| 1585 | err( | 1585 | err( |
| 1586 | \\{, | 1586 | \\{, |
| 1587 | ); | 1587 | ); |
| 1588 | } | 1588 | } |
| 1589 | 1589 | ||
| 1590 | test "n_structure_open_object" { | 1590 | test "json.test.n_structure_open_object" { |
| 1591 | err( | 1591 | err( |
| 1592 | \\{ | 1592 | \\{ |
| 1593 | ); | 1593 | ); |
| 1594 | } | 1594 | } |
| 1595 | 1595 | ||
| 1596 | test "n_structure_open_object_open_array" { | 1596 | test "json.test.n_structure_open_object_open_array" { |
| 1597 | err( | 1597 | err( |
| 1598 | \\{[ | 1598 | \\{[ |
| 1599 | ); | 1599 | ); |
| 1600 | } | 1600 | } |
| 1601 | 1601 | ||
| 1602 | test "n_structure_open_object_open_string" { | 1602 | test "json.test.n_structure_open_object_open_string" { |
| 1603 | err( | 1603 | err( |
| 1604 | \\{"a | 1604 | \\{"a |
| 1605 | ); | 1605 | ); |
| 1606 | } | 1606 | } |
| 1607 | 1607 | ||
| 1608 | test "n_structure_open_object_string_with_apostrophes" { | 1608 | test "json.test.n_structure_open_object_string_with_apostrophes" { |
| 1609 | err( | 1609 | err( |
| 1610 | \\{'a' | 1610 | \\{'a' |
| 1611 | ); | 1611 | ); |
| 1612 | } | 1612 | } |
| 1613 | 1613 | ||
| 1614 | test "n_structure_open_open" { | 1614 | test "json.test.n_structure_open_open" { |
| 1615 | err( | 1615 | err( |
| 1616 | \\["\{["\{["\{["\{ | 1616 | \\["\{["\{["\{["\{ |
| 1617 | ); | 1617 | ); |
| 1618 | } | 1618 | } |
| 1619 | 1619 | ||
| 1620 | test "n_structure_single_eacute" { | 1620 | test "json.test.n_structure_single_eacute" { |
| 1621 | err( | 1621 | err( |
| 1622 | \\é | 1622 | \\é |
| 1623 | ); | 1623 | ); |
| 1624 | } | 1624 | } |
| 1625 | 1625 | ||
| 1626 | test "n_structure_single_star" { | 1626 | test "json.test.n_structure_single_star" { |
| 1627 | err( | 1627 | err( |
| 1628 | \\* | 1628 | \\* |
| 1629 | ); | 1629 | ); |
| 1630 | } | 1630 | } |
| 1631 | 1631 | ||
| 1632 | test "n_structure_trailing_#" { | 1632 | test "json.test.n_structure_trailing_#" { |
| 1633 | err( | 1633 | err( |
| 1634 | \\{"a":"b"}#{} | 1634 | \\{"a":"b"}#{} |
| 1635 | ); | 1635 | ); |
| 1636 | } | 1636 | } |
| 1637 | 1637 | ||
| 1638 | test "n_structure_U+2060_word_joined" { | 1638 | test "json.test.n_structure_U+2060_word_joined" { |
| 1639 | err( | 1639 | err( |
| 1640 | \\[â ] | 1640 | \\[â ] |
| 1641 | ); | 1641 | ); |
| 1642 | } | 1642 | } |
| 1643 | 1643 | ||
| 1644 | test "n_structure_uescaped_LF_before_string" { | 1644 | test "json.test.n_structure_uescaped_LF_before_string" { |
| 1645 | err( | 1645 | err( |
| 1646 | \\[\u000A""] | 1646 | \\[\u000A""] |
| 1647 | ); | 1647 | ); |
| 1648 | } | 1648 | } |
| 1649 | 1649 | ||
| 1650 | test "n_structure_unclosed_array" { | 1650 | test "json.test.n_structure_unclosed_array" { |
| 1651 | err( | 1651 | err( |
| 1652 | \\[1 | 1652 | \\[1 |
| 1653 | ); | 1653 | ); |
| 1654 | } | 1654 | } |
| 1655 | 1655 | ||
| 1656 | test "n_structure_unclosed_array_partial_null" { | 1656 | test "json.test.n_structure_unclosed_array_partial_null" { |
| 1657 | err( | 1657 | err( |
| 1658 | \\[ false, nul | 1658 | \\[ false, nul |
| 1659 | ); | 1659 | ); |
| 1660 | } | 1660 | } |
| 1661 | 1661 | ||
| 1662 | test "n_structure_unclosed_array_unfinished_false" { | 1662 | test "json.test.n_structure_unclosed_array_unfinished_false" { |
| 1663 | err( | 1663 | err( |
| 1664 | \\[ true, fals | 1664 | \\[ true, fals |
| 1665 | ); | 1665 | ); |
| 1666 | } | 1666 | } |
| 1667 | 1667 | ||
| 1668 | test "n_structure_unclosed_array_unfinished_true" { | 1668 | test "json.test.n_structure_unclosed_array_unfinished_true" { |
| 1669 | err( | 1669 | err( |
| 1670 | \\[ false, tru | 1670 | \\[ false, tru |
| 1671 | ); | 1671 | ); |
| 1672 | } | 1672 | } |
| 1673 | 1673 | ||
| 1674 | test "n_structure_unclosed_object" { | 1674 | test "json.test.n_structure_unclosed_object" { |
| 1675 | err( | 1675 | err( |
| 1676 | \\{"asd":"asd" | 1676 | \\{"asd":"asd" |
| 1677 | ); | 1677 | ); |
| 1678 | } | 1678 | } |
| 1679 | 1679 | ||
| 1680 | test "n_structure_unicode-identifier" { | 1680 | test "json.test.n_structure_unicode-identifier" { |
| 1681 | err( | 1681 | err( |
| 1682 | \\Ã¥ | 1682 | \\Ã¥ |
| 1683 | ); | 1683 | ); |
| 1684 | } | 1684 | } |
| 1685 | 1685 | ||
| 1686 | test "n_structure_UTF8_BOM_no_data" { | 1686 | test "json.test.n_structure_UTF8_BOM_no_data" { |
| 1687 | err( | 1687 | err( |
| 1688 | \\ | 1688 | \\ |
| 1689 | ); | 1689 | ); |
| 1690 | } | 1690 | } |
| 1691 | 1691 | ||
| 1692 | test "n_structure_whitespace_formfeed" { | 1692 | test "json.test.n_structure_whitespace_formfeed" { |
| 1693 | err("[\x0c]"); | 1693 | err("[\x0c]"); |
| 1694 | } | 1694 | } |
| 1695 | 1695 | ||
| 1696 | test "n_structure_whitespace_U+2060_word_joiner" { | 1696 | test "json.test.n_structure_whitespace_U+2060_word_joiner" { |
| 1697 | err( | 1697 | err( |
| 1698 | \\[â ] | 1698 | \\[â ] |
| 1699 | ); | 1699 | ); |
| ... | @@ -1701,203 +1701,203 @@ test "n_structure_whitespace_U+2060_word_joiner" { | ... | @@ -1701,203 +1701,203 @@ test "n_structure_whitespace_U+2060_word_joiner" { |
| 1701 | 1701 | ||
| 1702 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 1702 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 1703 | 1703 | ||
| 1704 | test "i_number_double_huge_neg_exp" { | 1704 | test "json.test.i_number_double_huge_neg_exp" { |
| 1705 | any( | 1705 | any( |
| 1706 | \\[123.456e-789] | 1706 | \\[123.456e-789] |
| 1707 | ); | 1707 | ); |
| 1708 | } | 1708 | } |
| 1709 | 1709 | ||
| 1710 | test "i_number_huge_exp" { | 1710 | test "json.test.i_number_huge_exp" { |
| 1711 | any( | 1711 | any( |
| 1712 | \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] | 1712 | \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] |
| 1713 | ); | 1713 | ); |
| 1714 | } | 1714 | } |
| 1715 | 1715 | ||
| 1716 | test "i_number_neg_int_huge_exp" { | 1716 | test "json.test.i_number_neg_int_huge_exp" { |
| 1717 | any( | 1717 | any( |
| 1718 | \\[-1e+9999] | 1718 | \\[-1e+9999] |
| 1719 | ); | 1719 | ); |
| 1720 | } | 1720 | } |
| 1721 | 1721 | ||
| 1722 | test "i_number_pos_double_huge_exp" { | 1722 | test "json.test.i_number_pos_double_huge_exp" { |
| 1723 | any( | 1723 | any( |
| 1724 | \\[1.5e+9999] | 1724 | \\[1.5e+9999] |
| 1725 | ); | 1725 | ); |
| 1726 | } | 1726 | } |
| 1727 | 1727 | ||
| 1728 | test "i_number_real_neg_overflow" { | 1728 | test "json.test.i_number_real_neg_overflow" { |
| 1729 | any( | 1729 | any( |
| 1730 | \\[-123123e100000] | 1730 | \\[-123123e100000] |
| 1731 | ); | 1731 | ); |
| 1732 | } | 1732 | } |
| 1733 | 1733 | ||
| 1734 | test "i_number_real_pos_overflow" { | 1734 | test "json.test.i_number_real_pos_overflow" { |
| 1735 | any( | 1735 | any( |
| 1736 | \\[123123e100000] | 1736 | \\[123123e100000] |
| 1737 | ); | 1737 | ); |
| 1738 | } | 1738 | } |
| 1739 | 1739 | ||
| 1740 | test "i_number_real_underflow" { | 1740 | test "json.test.i_number_real_underflow" { |
| 1741 | any( | 1741 | any( |
| 1742 | \\[123e-10000000] | 1742 | \\[123e-10000000] |
| 1743 | ); | 1743 | ); |
| 1744 | } | 1744 | } |
| 1745 | 1745 | ||
| 1746 | test "i_number_too_big_neg_int" { | 1746 | test "json.test.i_number_too_big_neg_int" { |
| 1747 | any( | 1747 | any( |
| 1748 | \\[-123123123123123123123123123123] | 1748 | \\[-123123123123123123123123123123] |
| 1749 | ); | 1749 | ); |
| 1750 | } | 1750 | } |
| 1751 | 1751 | ||
| 1752 | test "i_number_too_big_pos_int" { | 1752 | test "json.test.i_number_too_big_pos_int" { |
| 1753 | any( | 1753 | any( |
| 1754 | \\[100000000000000000000] | 1754 | \\[100000000000000000000] |
| 1755 | ); | 1755 | ); |
| 1756 | } | 1756 | } |
| 1757 | 1757 | ||
| 1758 | test "i_number_very_big_negative_int" { | 1758 | test "json.test.i_number_very_big_negative_int" { |
| 1759 | any( | 1759 | any( |
| 1760 | \\[-237462374673276894279832749832423479823246327846] | 1760 | \\[-237462374673276894279832749832423479823246327846] |
| 1761 | ); | 1761 | ); |
| 1762 | } | 1762 | } |
| 1763 | 1763 | ||
| 1764 | test "i_object_key_lone_2nd_surrogate" { | 1764 | test "json.test.i_object_key_lone_2nd_surrogate" { |
| 1765 | any( | 1765 | any( |
| 1766 | \\{"\uDFAA":0} | 1766 | \\{"\uDFAA":0} |
| 1767 | ); | 1767 | ); |
| 1768 | } | 1768 | } |
| 1769 | 1769 | ||
| 1770 | test "i_string_1st_surrogate_but_2nd_missing" { | 1770 | test "json.test.i_string_1st_surrogate_but_2nd_missing" { |
| 1771 | any( | 1771 | any( |
| 1772 | \\["\uDADA"] | 1772 | \\["\uDADA"] |
| 1773 | ); | 1773 | ); |
| 1774 | } | 1774 | } |
| 1775 | 1775 | ||
| 1776 | test "i_string_1st_valid_surrogate_2nd_invalid" { | 1776 | test "json.test.i_string_1st_valid_surrogate_2nd_invalid" { |
| 1777 | any( | 1777 | any( |
| 1778 | \\["\uD888\u1234"] | 1778 | \\["\uD888\u1234"] |
| 1779 | ); | 1779 | ); |
| 1780 | } | 1780 | } |
| 1781 | 1781 | ||
| 1782 | test "i_string_incomplete_surrogate_and_escape_valid" { | 1782 | test "json.test.i_string_incomplete_surrogate_and_escape_valid" { |
| 1783 | any( | 1783 | any( |
| 1784 | \\["\uD800\n"] | 1784 | \\["\uD800\n"] |
| 1785 | ); | 1785 | ); |
| 1786 | } | 1786 | } |
| 1787 | 1787 | ||
| 1788 | test "i_string_incomplete_surrogate_pair" { | 1788 | test "json.test.i_string_incomplete_surrogate_pair" { |
| 1789 | any( | 1789 | any( |
| 1790 | \\["\uDd1ea"] | 1790 | \\["\uDd1ea"] |
| 1791 | ); | 1791 | ); |
| 1792 | } | 1792 | } |
| 1793 | 1793 | ||
| 1794 | test "i_string_incomplete_surrogates_escape_valid" { | 1794 | test "json.test.i_string_incomplete_surrogates_escape_valid" { |
| 1795 | any( | 1795 | any( |
| 1796 | \\["\uD800\uD800\n"] | 1796 | \\["\uD800\uD800\n"] |
| 1797 | ); | 1797 | ); |
| 1798 | } | 1798 | } |
| 1799 | 1799 | ||
| 1800 | test "i_string_invalid_lonely_surrogate" { | 1800 | test "json.test.i_string_invalid_lonely_surrogate" { |
| 1801 | any( | 1801 | any( |
| 1802 | \\["\ud800"] | 1802 | \\["\ud800"] |
| 1803 | ); | 1803 | ); |
| 1804 | } | 1804 | } |
| 1805 | 1805 | ||
| 1806 | test "i_string_invalid_surrogate" { | 1806 | test "json.test.i_string_invalid_surrogate" { |
| 1807 | any( | 1807 | any( |
| 1808 | \\["\ud800abc"] | 1808 | \\["\ud800abc"] |
| 1809 | ); | 1809 | ); |
| 1810 | } | 1810 | } |
| 1811 | 1811 | ||
| 1812 | test "i_string_invalid_utf-8" { | 1812 | test "json.test.i_string_invalid_utf-8" { |
| 1813 | any( | 1813 | any( |
| 1814 | \\["ÿ"] | 1814 | \\["ÿ"] |
| 1815 | ); | 1815 | ); |
| 1816 | } | 1816 | } |
| 1817 | 1817 | ||
| 1818 | test "i_string_inverted_surrogates_U+1D11E" { | 1818 | test "json.test.i_string_inverted_surrogates_U+1D11E" { |
| 1819 | any( | 1819 | any( |
| 1820 | \\["\uDd1e\uD834"] | 1820 | \\["\uDd1e\uD834"] |
| 1821 | ); | 1821 | ); |
| 1822 | } | 1822 | } |
| 1823 | 1823 | ||
| 1824 | test "i_string_iso_latin_1" { | 1824 | test "json.test.i_string_iso_latin_1" { |
| 1825 | any( | 1825 | any( |
| 1826 | \\["é"] | 1826 | \\["é"] |
| 1827 | ); | 1827 | ); |
| 1828 | } | 1828 | } |
| 1829 | 1829 | ||
| 1830 | test "i_string_lone_second_surrogate" { | 1830 | test "json.test.i_string_lone_second_surrogate" { |
| 1831 | any( | 1831 | any( |
| 1832 | \\["\uDFAA"] | 1832 | \\["\uDFAA"] |
| 1833 | ); | 1833 | ); |
| 1834 | } | 1834 | } |
| 1835 | 1835 | ||
| 1836 | test "i_string_lone_utf8_continuation_byte" { | 1836 | test "json.test.i_string_lone_utf8_continuation_byte" { |
| 1837 | any( | 1837 | any( |
| 1838 | \\[""] | 1838 | \\[""] |
| 1839 | ); | 1839 | ); |
| 1840 | } | 1840 | } |
| 1841 | 1841 | ||
| 1842 | test "i_string_not_in_unicode_range" { | 1842 | test "json.test.i_string_not_in_unicode_range" { |
| 1843 | any( | 1843 | any( |
| 1844 | \\["ô¿¿¿"] | 1844 | \\["ô¿¿¿"] |
| 1845 | ); | 1845 | ); |
| 1846 | } | 1846 | } |
| 1847 | 1847 | ||
| 1848 | test "i_string_overlong_sequence_2_bytes" { | 1848 | test "json.test.i_string_overlong_sequence_2_bytes" { |
| 1849 | any( | 1849 | any( |
| 1850 | \\["À¯"] | 1850 | \\["À¯"] |
| 1851 | ); | 1851 | ); |
| 1852 | } | 1852 | } |
| 1853 | 1853 | ||
| 1854 | test "i_string_overlong_sequence_6_bytes" { | 1854 | test "json.test.i_string_overlong_sequence_6_bytes" { |
| 1855 | any( | 1855 | any( |
| 1856 | \\["ü¿¿¿¿"] | 1856 | \\["ü¿¿¿¿"] |
| 1857 | ); | 1857 | ); |
| 1858 | } | 1858 | } |
| 1859 | 1859 | ||
| 1860 | test "i_string_overlong_sequence_6_bytes_null" { | 1860 | test "json.test.i_string_overlong_sequence_6_bytes_null" { |
| 1861 | any( | 1861 | any( |
| 1862 | \\["ü"] | 1862 | \\["ü"] |
| 1863 | ); | 1863 | ); |
| 1864 | } | 1864 | } |
| 1865 | 1865 | ||
| 1866 | test "i_string_truncated-utf-8" { | 1866 | test "json.test.i_string_truncated-utf-8" { |
| 1867 | any( | 1867 | any( |
| 1868 | \\["àÿ"] | 1868 | \\["àÿ"] |
| 1869 | ); | 1869 | ); |
| 1870 | } | 1870 | } |
| 1871 | 1871 | ||
| 1872 | test "i_string_utf16BE_no_BOM" { | 1872 | test "json.test.i_string_utf16BE_no_BOM" { |
| 1873 | any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d"); | 1873 | any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d"); |
| 1874 | } | 1874 | } |
| 1875 | 1875 | ||
| 1876 | test "i_string_utf16LE_no_BOM" { | 1876 | test "json.test.i_string_utf16LE_no_BOM" { |
| 1877 | any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00"); | 1877 | any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00"); |
| 1878 | } | 1878 | } |
| 1879 | 1879 | ||
| 1880 | test "i_string_UTF-16LE_with_BOM" { | 1880 | test "json.test.i_string_UTF-16LE_with_BOM" { |
| 1881 | any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00"); | 1881 | any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00"); |
| 1882 | } | 1882 | } |
| 1883 | 1883 | ||
| 1884 | test "i_string_UTF-8_invalid_sequence" { | 1884 | test "json.test.i_string_UTF-8_invalid_sequence" { |
| 1885 | any( | 1885 | any( |
| 1886 | \\["æ¥Ñú"] | 1886 | \\["æ¥Ñú"] |
| 1887 | ); | 1887 | ); |
| 1888 | } | 1888 | } |
| 1889 | 1889 | ||
| 1890 | test "i_string_UTF8_surrogate_U+D800" { | 1890 | test "json.test.i_string_UTF8_surrogate_U+D800" { |
| 1891 | any( | 1891 | any( |
| 1892 | \\["í "] | 1892 | \\["í "] |
| 1893 | ); | 1893 | ); |
| 1894 | } | 1894 | } |
| 1895 | 1895 | ||
| 1896 | test "i_structure_500_nested_arrays" { | 1896 | test "json.test.i_structure_500_nested_arrays" { |
| 1897 | any(("[" ** 500) ++ ("]" ** 500)); | 1897 | any(("[" ** 500) ++ ("]" ** 500)); |
| 1898 | } | 1898 | } |
| 1899 | 1899 | ||
| 1900 | test "i_structure_UTF-8_BOM_empty_object" { | 1900 | test "json.test.i_structure_UTF-8_BOM_empty_object" { |
| 1901 | any( | 1901 | any( |
| 1902 | \\{} | 1902 | \\{} |
| 1903 | ); | 1903 | ); |
std/linked_list.zig+96| ... | @@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type { | ... | @@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type { |
| 82 | list.len += 1; | 82 | list.len += 1; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | /// Concatenate list2 onto the end of list1, removing all entries from the former. | ||
| 86 | /// | ||
| 87 | /// Arguments: | ||
| 88 | /// list1: the list to concatenate onto | ||
| 89 | /// list2: the list to be concatenated | ||
| 90 | pub fn concatByMoving(list1: *Self, list2: *Self) void { | ||
| 91 | const l2_first = list2.first orelse return; | ||
| 92 | if (list1.last) |l1_last| { | ||
| 93 | l1_last.next = list2.first; | ||
| 94 | l2_first.prev = list1.last; | ||
| 95 | list1.len += list2.len; | ||
| 96 | } else { | ||
| 97 | // list1 was empty | ||
| 98 | list1.first = list2.first; | ||
| 99 | list1.len = list2.len; | ||
| 100 | } | ||
| 101 | list1.last = list2.last; | ||
| 102 | list2.first = null; | ||
| 103 | list2.last = null; | ||
| 104 | list2.len = 0; | ||
| 105 | } | ||
| 106 | |||
| 85 | /// Insert a new node at the end of the list. | 107 | /// Insert a new node at the end of the list. |
| 86 | /// | 108 | /// |
| 87 | /// Arguments: | 109 | /// Arguments: |
| ... | @@ -247,3 +269,77 @@ test "basic linked list test" { | ... | @@ -247,3 +269,77 @@ test "basic linked list test" { |
| 247 | assert(list.last.?.data == 4); | 269 | assert(list.last.?.data == 4); |
| 248 | assert(list.len == 2); | 270 | assert(list.len == 2); |
| 249 | } | 271 | } |
| 272 | |||
| 273 | test "linked list concatenation" { | ||
| 274 | const allocator = debug.global_allocator; | ||
| 275 | var list1 = LinkedList(u32).init(); | ||
| 276 | var list2 = LinkedList(u32).init(); | ||
| 277 | |||
| 278 | var one = try list1.createNode(1, allocator); | ||
| 279 | defer list1.destroyNode(one, allocator); | ||
| 280 | var two = try list1.createNode(2, allocator); | ||
| 281 | defer list1.destroyNode(two, allocator); | ||
| 282 | var three = try list1.createNode(3, allocator); | ||
| 283 | defer list1.destroyNode(three, allocator); | ||
| 284 | var four = try list1.createNode(4, allocator); | ||
| 285 | defer list1.destroyNode(four, allocator); | ||
| 286 | var five = try list1.createNode(5, allocator); | ||
| 287 | defer list1.destroyNode(five, allocator); | ||
| 288 | |||
| 289 | list1.append(one); | ||
| 290 | list1.append(two); | ||
| 291 | list2.append(three); | ||
| 292 | list2.append(four); | ||
| 293 | list2.append(five); | ||
| 294 | |||
| 295 | list1.concatByMoving(&list2); | ||
| 296 | |||
| 297 | assert(list1.last == five); | ||
| 298 | assert(list1.len == 5); | ||
| 299 | assert(list2.first == null); | ||
| 300 | assert(list2.last == null); | ||
| 301 | assert(list2.len == 0); | ||
| 302 | |||
| 303 | // Traverse forwards. | ||
| 304 | { | ||
| 305 | var it = list1.first; | ||
| 306 | var index: u32 = 1; | ||
| 307 | while (it) |node| : (it = node.next) { | ||
| 308 | assert(node.data == index); | ||
| 309 | index += 1; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | // Traverse backwards. | ||
| 314 | { | ||
| 315 | var it = list1.last; | ||
| 316 | var index: u32 = 1; | ||
| 317 | while (it) |node| : (it = node.prev) { | ||
| 318 | assert(node.data == (6 - index)); | ||
| 319 | index += 1; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | // Swap them back, this verifies that concating to an empty list works. | ||
| 324 | list2.concatByMoving(&list1); | ||
| 325 | |||
| 326 | // Traverse forwards. | ||
| 327 | { | ||
| 328 | var it = list2.first; | ||
| 329 | var index: u32 = 1; | ||
| 330 | while (it) |node| : (it = node.next) { | ||
| 331 | assert(node.data == index); | ||
| 332 | index += 1; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | // Traverse backwards. | ||
| 337 | { | ||
| 338 | var it = list2.last; | ||
| 339 | var index: u32 = 1; | ||
| 340 | while (it) |node| : (it = node.prev) { | ||
| 341 | assert(node.data == (6 - index)); | ||
| 342 | index += 1; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | } |
std/math/index.zig+70| ... | @@ -6,6 +6,13 @@ const assert = std.debug.assert; | ... | @@ -6,6 +6,13 @@ const assert = std.debug.assert; |
| 6 | pub const e = 2.71828182845904523536028747135266249775724709369995; | 6 | pub const e = 2.71828182845904523536028747135266249775724709369995; |
| 7 | pub const pi = 3.14159265358979323846264338327950288419716939937510; | 7 | pub const pi = 3.14159265358979323846264338327950288419716939937510; |
| 8 | 8 | ||
| 9 | // From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128) | ||
| 10 | pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001)); | ||
| 11 | pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000)); | ||
| 12 | pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); | ||
| 13 | pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000)); | ||
| 14 | pub const f128_toint = 1.0 / f128_epsilon; | ||
| 15 | |||
| 9 | // float.h details | 16 | // float.h details |
| 10 | pub const f64_true_min = 4.94065645841246544177e-324; | 17 | pub const f64_true_min = 4.94065645841246544177e-324; |
| 11 | pub const f64_min = 2.2250738585072014e-308; | 18 | pub const f64_min = 2.2250738585072014e-308; |
| ... | @@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type { | ... | @@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type { |
| 365 | return @IntType(false, count); | 372 | return @IntType(false, count); |
| 366 | } | 373 | } |
| 367 | 374 | ||
| 375 | pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { | ||
| 376 | assert(from <= to); | ||
| 377 | if (from == 0 and to == 0) { | ||
| 378 | return u0; | ||
| 379 | } | ||
| 380 | const is_signed = from < 0; | ||
| 381 | const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement | ||
| 382 | const base = log2(largest_positive_integer); | ||
| 383 | const upper = (1 << base) - 1; | ||
| 384 | var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1; | ||
| 385 | if (is_signed) { | ||
| 386 | magnitude_bits += 1; | ||
| 387 | } | ||
| 388 | return @IntType(is_signed, magnitude_bits); | ||
| 389 | } | ||
| 390 | |||
| 391 | test "math.IntFittingRange" { | ||
| 392 | assert(IntFittingRange(0, 0) == u0); | ||
| 393 | assert(IntFittingRange(0, 1) == u1); | ||
| 394 | assert(IntFittingRange(0, 2) == u2); | ||
| 395 | assert(IntFittingRange(0, 3) == u2); | ||
| 396 | assert(IntFittingRange(0, 4) == u3); | ||
| 397 | assert(IntFittingRange(0, 7) == u3); | ||
| 398 | assert(IntFittingRange(0, 8) == u4); | ||
| 399 | assert(IntFittingRange(0, 9) == u4); | ||
| 400 | assert(IntFittingRange(0, 15) == u4); | ||
| 401 | assert(IntFittingRange(0, 16) == u5); | ||
| 402 | assert(IntFittingRange(0, 17) == u5); | ||
| 403 | assert(IntFittingRange(0, 4095) == u12); | ||
| 404 | assert(IntFittingRange(2000, 4095) == u12); | ||
| 405 | assert(IntFittingRange(0, 4096) == u13); | ||
| 406 | assert(IntFittingRange(2000, 4096) == u13); | ||
| 407 | assert(IntFittingRange(0, 4097) == u13); | ||
| 408 | assert(IntFittingRange(2000, 4097) == u13); | ||
| 409 | assert(IntFittingRange(0, 123456789123456798123456789) == u87); | ||
| 410 | assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177); | ||
| 411 | |||
| 412 | assert(IntFittingRange(-1, -1) == i1); | ||
| 413 | assert(IntFittingRange(-1, 0) == i1); | ||
| 414 | assert(IntFittingRange(-1, 1) == i2); | ||
| 415 | assert(IntFittingRange(-2, -2) == i2); | ||
| 416 | assert(IntFittingRange(-2, -1) == i2); | ||
| 417 | assert(IntFittingRange(-2, 0) == i2); | ||
| 418 | assert(IntFittingRange(-2, 1) == i2); | ||
| 419 | assert(IntFittingRange(-2, 2) == i3); | ||
| 420 | assert(IntFittingRange(-1, 2) == i3); | ||
| 421 | assert(IntFittingRange(-1, 3) == i3); | ||
| 422 | assert(IntFittingRange(-1, 4) == i4); | ||
| 423 | assert(IntFittingRange(-1, 7) == i4); | ||
| 424 | assert(IntFittingRange(-1, 8) == i5); | ||
| 425 | assert(IntFittingRange(-1, 9) == i5); | ||
| 426 | assert(IntFittingRange(-1, 15) == i5); | ||
| 427 | assert(IntFittingRange(-1, 16) == i6); | ||
| 428 | assert(IntFittingRange(-1, 17) == i6); | ||
| 429 | assert(IntFittingRange(-1, 4095) == i13); | ||
| 430 | assert(IntFittingRange(-4096, 4095) == i13); | ||
| 431 | assert(IntFittingRange(-1, 4096) == i14); | ||
| 432 | assert(IntFittingRange(-4097, 4095) == i14); | ||
| 433 | assert(IntFittingRange(-1, 4097) == i14); | ||
| 434 | assert(IntFittingRange(-1, 123456789123456798123456789) == i88); | ||
| 435 | assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178); | ||
| 436 | } | ||
| 437 | |||
| 368 | test "math overflow functions" { | 438 | test "math overflow functions" { |
| 369 | testOverflow(); | 439 | testOverflow(); |
| 370 | comptime testOverflow(); | 440 | comptime testOverflow(); |
std/mem.zig+277-148| ... | @@ -410,12 +410,8 @@ test "mem.indexOf" { | ... | @@ -410,12 +410,8 @@ test "mem.indexOf" { |
| 410 | /// Reads an integer from memory with size equal to bytes.len. | 410 | /// Reads an integer from memory with size equal to bytes.len. |
| 411 | /// T specifies the return type, which must be large enough to store | 411 | /// T specifies the return type, which must be large enough to store |
| 412 | /// the result. | 412 | /// the result. |
| 413 | /// See also ::readIntBE or ::readIntLE. | 413 | 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 { | 414 | var result: ReturnType = 0; |
| 415 | if (T.bit_count == 8) { | ||
| 416 | return bytes[0]; | ||
| 417 | } | ||
| 418 | var result: T = 0; | ||
| 419 | switch (endian) { | 415 | switch (endian) { |
| 420 | builtin.Endian.Big => { | 416 | builtin.Endian.Big => { |
| 421 | for (bytes) |b| { | 417 | for (bytes) |b| { |
| ... | @@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { | ... | @@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { |
| 423 | } | 419 | } |
| 424 | }, | 420 | }, |
| 425 | builtin.Endian.Little => { | 421 | builtin.Endian.Little => { |
| 426 | const ShiftType = math.Log2Int(T); | 422 | const ShiftType = math.Log2Int(ReturnType); |
| 427 | for (bytes) |b, index| { | 423 | for (bytes) |b, index| { |
| 428 | result = result | (T(b) << @intCast(ShiftType, index * 8)); | 424 | result = result | (ReturnType(b) << @intCast(ShiftType, index * 8)); |
| 429 | } | 425 | } |
| 430 | }, | 426 | }, |
| 431 | } | 427 | } |
| 432 | return result; | 428 | return result; |
| 433 | } | 429 | } |
| 434 | 430 | ||
| 435 | /// Reads a big-endian int of type T from bytes. | 431 | /// Reads an integer from memory with bit count specified by T. |
| 436 | /// bytes.len must be exactly @sizeOf(T). | 432 | /// The bit count of T must be evenly divisible by 8. |
| 437 | pub fn readIntBE(comptime T: type, bytes: []const u8) T { | 433 | /// This function cannot fail and cannot cause undefined behavior. |
| 438 | if (T.is_signed) { | 434 | /// Assumes the endianness of memory is native. This means the function can |
| 439 | return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); | 435 | /// simply pointer cast memory. |
| 440 | } | 436 | pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { |
| 441 | assert(bytes.len == @sizeOf(T)); | 437 | comptime assert(T.bit_count % 8 == 0); |
| 442 | if (T == u8) return bytes[0]; | 438 | return @ptrCast(*align(1) const T, bytes).*; |
| 443 | var result: T = 0; | 439 | } |
| 444 | { | 440 | |
| 445 | comptime var i = 0; | 441 | /// Reads an integer from memory with bit count specified by T. |
| 446 | inline while (i < @sizeOf(T)) : (i += 1) { | 442 | /// The bit count of T must be evenly divisible by 8. |
| 447 | result = (result << 8) | T(bytes[i]); | 443 | /// This function cannot fail and cannot cause undefined behavior. |
| 448 | } | 444 | /// Assumes the endianness of memory is foreign, so it must byte-swap. |
| 445 | pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { | ||
| 446 | return @bswap(T, readIntNative(T, bytes)); | ||
| 447 | } | ||
| 448 | |||
| 449 | pub const readIntLittle = switch (builtin.endian) { | ||
| 450 | builtin.Endian.Little => readIntNative, | ||
| 451 | builtin.Endian.Big => readIntForeign, | ||
| 452 | }; | ||
| 453 | |||
| 454 | pub const readIntBig = switch (builtin.endian) { | ||
| 455 | builtin.Endian.Little => readIntForeign, | ||
| 456 | builtin.Endian.Big => readIntNative, | ||
| 457 | }; | ||
| 458 | |||
| 459 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 | ||
| 460 | /// and ignores extra bytes. | ||
| 461 | /// Note that @sizeOf(u24) is 3. | ||
| 462 | /// The bit count of T must be evenly divisible by 8. | ||
| 463 | /// Assumes the endianness of memory is native. This means the function can | ||
| 464 | /// simply pointer cast memory. | ||
| 465 | pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T { | ||
| 466 | assert(@sizeOf(u24) == 3); | ||
| 467 | assert(bytes.len >= @sizeOf(T)); | ||
| 468 | // TODO https://github.com/ziglang/zig/issues/863 | ||
| 469 | return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr)); | ||
| 470 | } | ||
| 471 | |||
| 472 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 | ||
| 473 | /// and ignores extra bytes. | ||
| 474 | /// Note that @sizeOf(u24) is 3. | ||
| 475 | /// The bit count of T must be evenly divisible by 8. | ||
| 476 | /// Assumes the endianness of memory is foreign, so it must byte-swap. | ||
| 477 | pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T { | ||
| 478 | return @bswap(T, readIntSliceNative(T, bytes)); | ||
| 479 | } | ||
| 480 | |||
| 481 | pub const readIntSliceLittle = switch (builtin.endian) { | ||
| 482 | builtin.Endian.Little => readIntSliceNative, | ||
| 483 | builtin.Endian.Big => readIntSliceForeign, | ||
| 484 | }; | ||
| 485 | |||
| 486 | pub const readIntSliceBig = switch (builtin.endian) { | ||
| 487 | builtin.Endian.Little => readIntSliceForeign, | ||
| 488 | builtin.Endian.Big => readIntSliceNative, | ||
| 489 | }; | ||
| 490 | |||
| 491 | /// Reads an integer from memory with bit count specified by T. | ||
| 492 | /// The bit count of T must be evenly divisible by 8. | ||
| 493 | /// This function cannot fail and cannot cause undefined behavior. | ||
| 494 | pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T { | ||
| 495 | if (endian == builtin.endian) { | ||
| 496 | return readIntNative(T, bytes); | ||
| 497 | } else { | ||
| 498 | return readIntForeign(T, bytes); | ||
| 449 | } | 499 | } |
| 450 | return result; | ||
| 451 | } | 500 | } |
| 452 | 501 | ||
| 453 | /// Reads a little-endian int of type T from bytes. | 502 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 |
| 454 | /// bytes.len must be exactly @sizeOf(T). | 503 | /// and ignores extra bytes. |
| 455 | pub fn readIntLE(comptime T: type, bytes: []const u8) T { | 504 | /// Note that @sizeOf(u24) is 3. |
| 456 | if (T.is_signed) { | 505 | /// The bit count of T must be evenly divisible by 8. |
| 457 | return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); | 506 | pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T { |
| 507 | assert(@sizeOf(u24) == 3); | ||
| 508 | assert(bytes.len >= @sizeOf(T)); | ||
| 509 | // TODO https://github.com/ziglang/zig/issues/863 | ||
| 510 | return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian); | ||
| 511 | } | ||
| 512 | |||
| 513 | test "comptime read/write int" { | ||
| 514 | comptime { | ||
| 515 | var bytes: [2]u8 = undefined; | ||
| 516 | std.mem.writeIntLittle(u16, &bytes, 0x1234); | ||
| 517 | const result = std.mem.readIntBig(u16, &bytes); | ||
| 518 | std.debug.assert(result == 0x3412); | ||
| 458 | } | 519 | } |
| 459 | assert(bytes.len == @sizeOf(T)); | 520 | comptime { |
| 460 | if (T == u8) return bytes[0]; | 521 | var bytes: [2]u8 = undefined; |
| 461 | var result: T = 0; | 522 | std.mem.writeIntBig(u16, &bytes, 0x1234); |
| 462 | { | 523 | const result = std.mem.readIntLittle(u16, &bytes); |
| 463 | comptime var i = 0; | 524 | std.debug.assert(result == 0x3412); |
| 464 | inline while (i < @sizeOf(T)) : (i += 1) { | ||
| 465 | result |= T(bytes[i]) << i * 8; | ||
| 466 | } | ||
| 467 | } | 525 | } |
| 468 | return result; | ||
| 469 | } | 526 | } |
| 470 | 527 | ||
| 471 | test "readIntBE/LE" { | 528 | test "readIntBig and readIntLittle" { |
| 472 | assert(readIntBE(u0, []u8{}) == 0x0); | 529 | assert(readIntSliceBig(u0, []u8{}) == 0x0); |
| 473 | assert(readIntLE(u0, []u8{}) == 0x0); | 530 | assert(readIntSliceLittle(u0, []u8{}) == 0x0); |
| 474 | 531 | ||
| 475 | assert(readIntBE(u8, []u8{0x32}) == 0x32); | 532 | assert(readIntSliceBig(u8, []u8{0x32}) == 0x32); |
| 476 | assert(readIntLE(u8, []u8{0x12}) == 0x12); | 533 | assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12); |
| 477 | 534 | ||
| 478 | assert(readIntBE(u16, []u8{0x12, 0x34}) == 0x1234); | 535 | assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234); |
| 479 | assert(readIntLE(u16, []u8{0x12, 0x34}) == 0x3412); | 536 | assert(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412); |
| 480 | 537 | ||
| 481 | assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024); | 538 | assert(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); | 539 | assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); |
| 483 | 540 | ||
| 484 | assert(readIntBE(i8, []u8{0xff}) == -1); | 541 | assert(readIntSliceBig(i8, []u8{0xff}) == -1); |
| 485 | assert(readIntLE(i8, []u8{0xfe}) == -2); | 542 | assert(readIntSliceLittle(i8, []u8{0xfe}) == -2); |
| 486 | 543 | ||
| 487 | assert(readIntBE(i16, []u8{0xff, 0xfd}) == -3); | 544 | assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3); |
| 488 | assert(readIntLE(i16, []u8{0xfc, 0xff}) == -4); | 545 | assert(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4); |
| 489 | } | 546 | } |
| 490 | 547 | ||
| 491 | /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes | 548 | /// Writes an integer to memory, storing it in twos-complement. |
| 492 | /// to fill the entire buffer provided. | 549 | /// This function always succeeds, has defined behavior for all inputs, and |
| 493 | /// value must be an integer. | 550 | /// accepts any integer bit width. |
| 494 | pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { | 551 | /// This function stores in native endian, which means it is implemented as a simple |
| 495 | const uint = @IntType(false, @typeOf(value).bit_count); | 552 | /// memory store. |
| 496 | var bits = @truncate(uint, value); | 553 | pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { |
| 497 | switch (endian) { | 554 | @ptrCast(*align(1) T, buf).* = value; |
| 498 | builtin.Endian.Big => { | 555 | } |
| 499 | var index: usize = buf.len; | ||
| 500 | while (index != 0) { | ||
| 501 | index -= 1; | ||
| 502 | 556 | ||
| 503 | buf[index] = @truncate(u8, bits); | 557 | /// Writes an integer to memory, storing it in twos-complement. |
| 504 | bits >>= 8; | 558 | /// This function always succeeds, has defined behavior for all inputs, but |
| 505 | } | 559 | /// the integer bit width must be divisible by 8. |
| 506 | }, | 560 | /// This function stores in foreign endian, which means it does a @bswap first. |
| 507 | builtin.Endian.Little => { | 561 | pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { |
| 508 | for (buf) |*b| { | 562 | writeIntNative(T, buf, @bswap(T, value)); |
| 509 | b.* = @truncate(u8, bits); | 563 | } |
| 510 | bits >>= 8; | 564 | |
| 511 | } | 565 | pub const writeIntLittle = switch (builtin.endian) { |
| 512 | }, | 566 | builtin.Endian.Little => writeIntNative, |
| 567 | builtin.Endian.Big => writeIntForeign, | ||
| 568 | }; | ||
| 569 | |||
| 570 | pub const writeIntBig = switch (builtin.endian) { | ||
| 571 | builtin.Endian.Little => writeIntForeign, | ||
| 572 | builtin.Endian.Big => writeIntNative, | ||
| 573 | }; | ||
| 574 | |||
| 575 | /// Writes an integer to memory, storing it in twos-complement. | ||
| 576 | /// This function always succeeds, has defined behavior for all inputs, but | ||
| 577 | /// the integer bit width must be divisible by 8. | ||
| 578 | pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void { | ||
| 579 | comptime assert(T.bit_count % 8 == 0); | ||
| 580 | if (endian == builtin.endian) { | ||
| 581 | return writeIntNative(T, buffer, value); | ||
| 582 | } else { | ||
| 583 | return writeIntForeign(T, buffer, value); | ||
| 513 | } | 584 | } |
| 514 | assert(bits == 0); | ||
| 515 | } | 585 | } |
| 516 | 586 | ||
| 517 | pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | 587 | /// Writes a twos-complement little-endian integer to memory. |
| 518 | assert(T.bit_count % 8 == 0); | 588 | /// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. |
| 589 | /// The bit count of T must be divisible by 8. | ||
| 590 | /// Any extra bytes in buffer after writing the integer are set to zero. To | ||
| 591 | /// avoid the branch to check for extra buffer bytes, use writeIntLittle | ||
| 592 | /// instead. | ||
| 593 | pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { | ||
| 594 | comptime assert(@sizeOf(u24) == 3); | ||
| 595 | comptime assert(T.bit_count % 8 == 0); | ||
| 596 | assert(buffer.len >= @sizeOf(T)); | ||
| 597 | |||
| 598 | // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough | ||
| 519 | const uint = @IntType(false, T.bit_count); | 599 | const uint = @IntType(false, T.bit_count); |
| 520 | if (uint == u0) { | 600 | var bits = @truncate(uint, value); |
| 521 | return; | 601 | for (buffer) |*b| { |
| 522 | } | 602 | b.* = @truncate(u8, bits); |
| 523 | var bits = @bitCast(uint, value); | 603 | bits >>= 8; |
| 524 | if (uint == u8) { | ||
| 525 | buf[0] = bits; | ||
| 526 | return; | ||
| 527 | } | 604 | } |
| 528 | var index: usize = buf.len; | 605 | } |
| 606 | |||
| 607 | /// Writes a twos-complement big-endian integer to memory. | ||
| 608 | /// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. | ||
| 609 | /// The bit count of T must be divisible by 8. | ||
| 610 | /// Any extra bytes in buffer before writing the integer are set to zero. To | ||
| 611 | /// avoid the branch to check for extra buffer bytes, use writeIntBig instead. | ||
| 612 | pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { | ||
| 613 | comptime assert(@sizeOf(u24) == 3); | ||
| 614 | comptime assert(T.bit_count % 8 == 0); | ||
| 615 | assert(buffer.len >= @sizeOf(T)); | ||
| 616 | |||
| 617 | // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough | ||
| 618 | const uint = @IntType(false, T.bit_count); | ||
| 619 | var bits = @truncate(uint, value); | ||
| 620 | var index: usize = buffer.len; | ||
| 529 | while (index != 0) { | 621 | while (index != 0) { |
| 530 | index -= 1; | 622 | index -= 1; |
| 531 | 623 | buffer[index] = @truncate(u8, bits); | |
| 532 | buf[index] = @truncate(u8, bits); | ||
| 533 | bits >>= 8; | 624 | bits >>= 8; |
| 534 | } | 625 | } |
| 535 | assert(bits == 0); | ||
| 536 | } | 626 | } |
| 537 | 627 | ||
| 538 | pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | 628 | pub const writeIntSliceNative = switch (builtin.endian) { |
| 539 | assert(T.bit_count % 8 == 0); | 629 | builtin.Endian.Little => writeIntSliceLittle, |
| 540 | const uint = @IntType(false, T.bit_count); | 630 | builtin.Endian.Big => writeIntSliceBig, |
| 541 | if (uint == u0) { | 631 | }; |
| 542 | return; | 632 | |
| 543 | } | 633 | pub const writeIntSliceForeign = switch (builtin.endian) { |
| 544 | var bits = @bitCast(uint, value); | 634 | builtin.Endian.Little => writeIntSliceBig, |
| 545 | if (uint == u8) { | 635 | builtin.Endian.Big => writeIntSliceLittle, |
| 546 | buf[0] = bits; | 636 | }; |
| 547 | return; | 637 | |
| 548 | } | 638 | /// Writes a twos-complement integer to memory, with the specified endianness. |
| 549 | // FIXME: this should just be for (buf). | 639 | /// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. |
| 550 | // See https://github.com/ziglang/zig/issues/1663 | 640 | /// The bit count of T must be evenly divisible by 8. |
| 551 | for (buf.*) |*b| { | 641 | /// Any extra bytes in buffer not part of the integer are set to zero, with |
| 552 | b.* = @truncate(u8, bits); | 642 | /// respect to endianness. To avoid the branch to check for extra buffer bytes, |
| 553 | bits >>= 8; | 643 | /// use writeInt instead. |
| 644 | pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void { | ||
| 645 | comptime assert(T.bit_count % 8 == 0); | ||
| 646 | switch (endian) { | ||
| 647 | builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value), | ||
| 648 | builtin.Endian.Big => return writeIntSliceBig(T, buffer, value), | ||
| 554 | } | 649 | } |
| 555 | assert(bits == 0); | ||
| 556 | } | 650 | } |
| 557 | 651 | ||
| 558 | test "writeIntBE/LE" { | 652 | test "writeIntBig and writeIntLittle" { |
| 559 | var buf0: [0]u8 = undefined; | 653 | var buf0: [0]u8 = undefined; |
| 560 | var buf1: [1]u8 = undefined; | 654 | var buf1: [1]u8 = undefined; |
| 561 | var buf2: [2]u8 = undefined; | 655 | var buf2: [2]u8 = undefined; |
| 562 | var buf9: [9]u8 = undefined; | 656 | var buf9: [9]u8 = undefined; |
| 563 | 657 | ||
| 564 | writeIntBE(u0, &buf0, 0x0); | 658 | writeIntBig(u0, &buf0, 0x0); |
| 565 | assert(eql_slice_u8(buf0[0..], []u8{})); | 659 | assert(eql_slice_u8(buf0[0..], []u8{})); |
| 566 | writeIntLE(u0, &buf0, 0x0); | 660 | writeIntLittle(u0, &buf0, 0x0); |
| 567 | assert(eql_slice_u8(buf0[0..], []u8{})); | 661 | assert(eql_slice_u8(buf0[0..], []u8{})); |
| 568 | 662 | ||
| 569 | writeIntBE(u8, &buf1, 0x12); | 663 | writeIntBig(u8, &buf1, 0x12); |
| 570 | assert(eql_slice_u8(buf1[0..], []u8{0x12})); | 664 | assert(eql_slice_u8(buf1[0..], []u8{0x12})); |
| 571 | writeIntLE(u8, &buf1, 0x34); | 665 | writeIntLittle(u8, &buf1, 0x34); |
| 572 | assert(eql_slice_u8(buf1[0..], []u8{0x34})); | 666 | assert(eql_slice_u8(buf1[0..], []u8{0x34})); |
| 573 | 667 | ||
| 574 | writeIntBE(u16, &buf2, 0x1234); | 668 | writeIntBig(u16, &buf2, 0x1234); |
| 575 | assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 })); | 669 | assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 })); |
| 576 | writeIntLE(u16, &buf2, 0x5678); | 670 | writeIntLittle(u16, &buf2, 0x5678); |
| 577 | assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 })); | 671 | assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 })); |
| 578 | 672 | ||
| 579 | writeIntBE(u72, &buf9, 0x123456789abcdef024); | 673 | writeIntBig(u72, &buf9, 0x123456789abcdef024); |
| 580 | assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); | 674 | assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); |
| 581 | writeIntLE(u72, &buf9, 0xfedcba9876543210ec); | 675 | writeIntLittle(u72, &buf9, 0xfedcba9876543210ec); |
| 582 | assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); | 676 | assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); |
| 583 | 677 | ||
| 584 | writeIntBE(i8, &buf1, -1); | 678 | writeIntBig(i8, &buf1, -1); |
| 585 | assert(eql_slice_u8(buf1[0..], []u8{0xff})); | 679 | assert(eql_slice_u8(buf1[0..], []u8{0xff})); |
| 586 | writeIntLE(i8, &buf1, -2); | 680 | writeIntLittle(i8, &buf1, -2); |
| 587 | assert(eql_slice_u8(buf1[0..], []u8{0xfe})); | 681 | assert(eql_slice_u8(buf1[0..], []u8{0xfe})); |
| 588 | 682 | ||
| 589 | writeIntBE(i16, &buf2, -3); | 683 | writeIntBig(i16, &buf2, -3); |
| 590 | assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd })); | 684 | assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd })); |
| 591 | writeIntLE(i16, &buf2, -4); | 685 | writeIntLittle(i16, &buf2, -4); |
| 592 | assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff })); | 686 | assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff })); |
| 593 | } | 687 | } |
| 594 | 688 | ||
| ... | @@ -737,12 +831,12 @@ fn testReadIntImpl() void { | ... | @@ -737,12 +831,12 @@ fn testReadIntImpl() void { |
| 737 | 0x56, | 831 | 0x56, |
| 738 | 0x78, | 832 | 0x78, |
| 739 | }; | 833 | }; |
| 740 | assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); | 834 | assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678); |
| 741 | assert(readIntBE(u32, bytes) == 0x12345678); | 835 | assert(readIntBig(u32, &bytes) == 0x12345678); |
| 742 | assert(readIntBE(i32, bytes) == 0x12345678); | 836 | assert(readIntBig(i32, &bytes) == 0x12345678); |
| 743 | assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412); | 837 | assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412); |
| 744 | assert(readIntLE(u32, bytes) == 0x78563412); | 838 | assert(readIntLittle(u32, &bytes) == 0x78563412); |
| 745 | assert(readIntLE(i32, bytes) == 0x78563412); | 839 | assert(readIntLittle(i32, &bytes) == 0x78563412); |
| 746 | } | 840 | } |
| 747 | { | 841 | { |
| 748 | const buf = []u8{ | 842 | const buf = []u8{ |
| ... | @@ -751,7 +845,7 @@ fn testReadIntImpl() void { | ... | @@ -751,7 +845,7 @@ fn testReadIntImpl() void { |
| 751 | 0x12, | 845 | 0x12, |
| 752 | 0x34, | 846 | 0x34, |
| 753 | }; | 847 | }; |
| 754 | const answer = readInt(buf, u64, builtin.Endian.Big); | 848 | const answer = readInt(u32, &buf, builtin.Endian.Big); |
| 755 | assert(answer == 0x00001234); | 849 | assert(answer == 0x00001234); |
| 756 | } | 850 | } |
| 757 | { | 851 | { |
| ... | @@ -761,7 +855,7 @@ fn testReadIntImpl() void { | ... | @@ -761,7 +855,7 @@ fn testReadIntImpl() void { |
| 761 | 0x00, | 855 | 0x00, |
| 762 | 0x00, | 856 | 0x00, |
| 763 | }; | 857 | }; |
| 764 | const answer = readInt(buf, u64, builtin.Endian.Little); | 858 | const answer = readInt(u32, &buf, builtin.Endian.Little); |
| 765 | assert(answer == 0x00003412); | 859 | assert(answer == 0x00003412); |
| 766 | } | 860 | } |
| 767 | { | 861 | { |
| ... | @@ -769,21 +863,33 @@ fn testReadIntImpl() void { | ... | @@ -769,21 +863,33 @@ fn testReadIntImpl() void { |
| 769 | 0xff, | 863 | 0xff, |
| 770 | 0xfe, | 864 | 0xfe, |
| 771 | }; | 865 | }; |
| 772 | assert(readIntBE(u16, bytes) == 0xfffe); | 866 | assert(readIntBig(u16, &bytes) == 0xfffe); |
| 773 | assert(readIntBE(i16, bytes) == -0x0002); | 867 | assert(readIntBig(i16, &bytes) == -0x0002); |
| 774 | assert(readIntLE(u16, bytes) == 0xfeff); | 868 | assert(readIntLittle(u16, &bytes) == 0xfeff); |
| 775 | assert(readIntLE(i16, bytes) == -0x0101); | 869 | assert(readIntLittle(i16, &bytes) == -0x0101); |
| 776 | } | 870 | } |
| 777 | } | 871 | } |
| 778 | 872 | ||
| 779 | test "testWriteInt" { | 873 | test "std.mem.writeIntSlice" { |
| 780 | testWriteIntImpl(); | 874 | testWriteIntImpl(); |
| 781 | comptime testWriteIntImpl(); | 875 | comptime testWriteIntImpl(); |
| 782 | } | 876 | } |
| 783 | fn testWriteIntImpl() void { | 877 | fn testWriteIntImpl() void { |
| 784 | var bytes: [8]u8 = undefined; | 878 | var bytes: [8]u8 = undefined; |
| 785 | 879 | ||
| 786 | writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big); | 880 | writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big); |
| 881 | assert(eql(u8, bytes, []u8{ | ||
| 882 | 0x00, 0x00, 0x00, 0x00, | ||
| 883 | 0x00, 0x00, 0x00, 0x00, | ||
| 884 | })); | ||
| 885 | |||
| 886 | writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little); | ||
| 887 | assert(eql(u8, bytes, []u8{ | ||
| 888 | 0x00, 0x00, 0x00, 0x00, | ||
| 889 | 0x00, 0x00, 0x00, 0x00, | ||
| 890 | })); | ||
| 891 | |||
| 892 | writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big); | ||
| 787 | assert(eql(u8, bytes, []u8{ | 893 | assert(eql(u8, bytes, []u8{ |
| 788 | 0x12, | 894 | 0x12, |
| 789 | 0x34, | 895 | 0x34, |
| ... | @@ -795,7 +901,7 @@ fn testWriteIntImpl() void { | ... | @@ -795,7 +901,7 @@ fn testWriteIntImpl() void { |
| 795 | 0xBE, | 901 | 0xBE, |
| 796 | })); | 902 | })); |
| 797 | 903 | ||
| 798 | writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little); | 904 | writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little); |
| 799 | assert(eql(u8, bytes, []u8{ | 905 | assert(eql(u8, bytes, []u8{ |
| 800 | 0x12, | 906 | 0x12, |
| 801 | 0x34, | 907 | 0x34, |
| ... | @@ -807,7 +913,7 @@ fn testWriteIntImpl() void { | ... | @@ -807,7 +913,7 @@ fn testWriteIntImpl() void { |
| 807 | 0xBE, | 913 | 0xBE, |
| 808 | })); | 914 | })); |
| 809 | 915 | ||
| 810 | writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big); | 916 | writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big); |
| 811 | assert(eql(u8, bytes, []u8{ | 917 | assert(eql(u8, bytes, []u8{ |
| 812 | 0x00, | 918 | 0x00, |
| 813 | 0x00, | 919 | 0x00, |
| ... | @@ -819,7 +925,7 @@ fn testWriteIntImpl() void { | ... | @@ -819,7 +925,7 @@ fn testWriteIntImpl() void { |
| 819 | 0x78, | 925 | 0x78, |
| 820 | })); | 926 | })); |
| 821 | 927 | ||
| 822 | writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little); | 928 | writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little); |
| 823 | assert(eql(u8, bytes, []u8{ | 929 | assert(eql(u8, bytes, []u8{ |
| 824 | 0x12, | 930 | 0x12, |
| 825 | 0x34, | 931 | 0x34, |
| ... | @@ -831,7 +937,7 @@ fn testWriteIntImpl() void { | ... | @@ -831,7 +937,7 @@ fn testWriteIntImpl() void { |
| 831 | 0x00, | 937 | 0x00, |
| 832 | })); | 938 | })); |
| 833 | 939 | ||
| 834 | writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big); | 940 | writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big); |
| 835 | assert(eql(u8, bytes, []u8{ | 941 | assert(eql(u8, bytes, []u8{ |
| 836 | 0x00, | 942 | 0x00, |
| 837 | 0x00, | 943 | 0x00, |
| ... | @@ -843,7 +949,7 @@ fn testWriteIntImpl() void { | ... | @@ -843,7 +949,7 @@ fn testWriteIntImpl() void { |
| 843 | 0x34, | 949 | 0x34, |
| 844 | })); | 950 | })); |
| 845 | 951 | ||
| 846 | writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little); | 952 | writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little); |
| 847 | assert(eql(u8, bytes, []u8{ | 953 | assert(eql(u8, bytes, []u8{ |
| 848 | 0x34, | 954 | 0x34, |
| 849 | 0x12, | 955 | 0x12, |
| ... | @@ -941,29 +1047,52 @@ test "std.mem.rotate" { | ... | @@ -941,29 +1047,52 @@ test "std.mem.rotate" { |
| 941 | })); | 1047 | })); |
| 942 | } | 1048 | } |
| 943 | 1049 | ||
| 944 | // TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by | 1050 | /// Converts a little-endian integer to host endianness. |
| 945 | // endian-casting the pointer and then dereferencing | 1051 | pub fn littleToNative(comptime T: type, x: T) T { |
| 1052 | return switch (builtin.endian) { | ||
| 1053 | builtin.Endian.Little => x, | ||
| 1054 | builtin.Endian.Big => @bswap(T, x), | ||
| 1055 | }; | ||
| 1056 | } | ||
| 946 | 1057 | ||
| 947 | pub fn endianSwapIfLe(comptime T: type, x: T) T { | 1058 | /// Converts a big-endian integer to host endianness. |
| 948 | return endianSwapIf(builtin.Endian.Little, T, x); | 1059 | pub fn bigToNative(comptime T: type, x: T) T { |
| 1060 | return switch (builtin.endian) { | ||
| 1061 | builtin.Endian.Little => @bswap(T, x), | ||
| 1062 | builtin.Endian.Big => x, | ||
| 1063 | }; | ||
| 949 | } | 1064 | } |
| 950 | 1065 | ||
| 951 | pub fn endianSwapIfBe(comptime T: type, x: T) T { | 1066 | /// Converts an integer from specified endianness to host endianness. |
| 952 | return endianSwapIf(builtin.Endian.Big, T, x); | 1067 | pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T { |
| 1068 | return switch (endianness_of_x) { | ||
| 1069 | builtin.Endian.Little => littleToNative(T, x), | ||
| 1070 | builtin.Endian.Big => bigToNative(T, x), | ||
| 1071 | }; | ||
| 953 | } | 1072 | } |
| 954 | 1073 | ||
| 955 | pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T { | 1074 | /// Converts an integer which has host endianness to the desired endianness. |
| 956 | return if (builtin.endian == endian) endianSwap(T, x) else x; | 1075 | pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T { |
| 1076 | return switch (desired_endianness) { | ||
| 1077 | builtin.Endian.Little => nativeToLittle(T, x), | ||
| 1078 | builtin.Endian.Big => nativeToBig(T, x), | ||
| 1079 | }; | ||
| 957 | } | 1080 | } |
| 958 | 1081 | ||
| 959 | pub fn endianSwap(comptime T: type, x: T) T { | 1082 | /// Converts an integer which has host endianness to little endian. |
| 960 | var buf: [@sizeOf(T)]u8 = undefined; | 1083 | pub fn nativeToLittle(comptime T: type, x: T) T { |
| 961 | mem.writeInt(buf[0..], x, builtin.Endian.Little); | 1084 | return switch (builtin.endian) { |
| 962 | return mem.readInt(buf, T, builtin.Endian.Big); | 1085 | builtin.Endian.Little => x, |
| 1086 | builtin.Endian.Big => @bswap(T, x), | ||
| 1087 | }; | ||
| 963 | } | 1088 | } |
| 964 | 1089 | ||
| 965 | test "std.mem.endianSwap" { | 1090 | /// Converts an integer which has host endianness to big endian. |
| 966 | assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE); | 1091 | pub fn nativeToBig(comptime T: type, x: T) T { |
| 1092 | return switch (builtin.endian) { | ||
| 1093 | builtin.Endian.Little => @bswap(T, x), | ||
| 1094 | builtin.Endian.Big => x, | ||
| 1095 | }; | ||
| 967 | } | 1096 | } |
| 968 | 1097 | ||
| 969 | fn AsBytesReturnType(comptime P: type) type { | 1098 | fn AsBytesReturnType(comptime P: type) type { |
std/meta/index.zig+48| ... | @@ -76,6 +76,25 @@ test "std.meta.tagName" { | ... | @@ -76,6 +76,25 @@ test "std.meta.tagName" { |
| 76 | debug.assert(mem.eql(u8, tagName(u2b), "D")); | 76 | debug.assert(mem.eql(u8, tagName(u2b), "D")); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | pub fn stringToEnum(comptime T: type, str: []const u8) ?T { | ||
| 80 | inline for (@typeInfo(T).Enum.fields) |enumField| { | ||
| 81 | if (std.mem.eql(u8, str, enumField.name)) { | ||
| 82 | return @field(T, enumField.name); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | return null; | ||
| 86 | } | ||
| 87 | |||
| 88 | test "std.meta.stringToEnum" { | ||
| 89 | const E1 = enum { | ||
| 90 | A, | ||
| 91 | B, | ||
| 92 | }; | ||
| 93 | debug.assert(E1.A == stringToEnum(E1, "A").?); | ||
| 94 | debug.assert(E1.B == stringToEnum(E1, "B").?); | ||
| 95 | debug.assert(null == stringToEnum(E1, "C")); | ||
| 96 | } | ||
| 97 | |||
| 79 | pub fn bitCount(comptime T: type) u32 { | 98 | pub fn bitCount(comptime T: type) u32 { |
| 80 | return switch (@typeInfo(T)) { | 99 | return switch (@typeInfo(T)) { |
| 81 | TypeId.Int => |info| info.bits, | 100 | TypeId.Int => |info| info.bits, |
| ... | @@ -483,3 +502,32 @@ test "std.meta.eql" { | ... | @@ -483,3 +502,32 @@ test "std.meta.eql" { |
| 483 | debug.assert(eql(EU.tst(false), EU.tst(false))); | 502 | debug.assert(eql(EU.tst(false), EU.tst(false))); |
| 484 | debug.assert(!eql(EU.tst(false), EU.tst(true))); | 503 | debug.assert(!eql(EU.tst(false), EU.tst(true))); |
| 485 | } | 504 | } |
| 505 | |||
| 506 | test "intToEnum with error return" { | ||
| 507 | const E1 = enum { | ||
| 508 | A, | ||
| 509 | }; | ||
| 510 | const E2 = enum { | ||
| 511 | A, | ||
| 512 | B, | ||
| 513 | }; | ||
| 514 | |||
| 515 | var zero: u8 = 0; | ||
| 516 | var one: u16 = 1; | ||
| 517 | debug.assert(intToEnum(E1, zero) catch unreachable == E1.A); | ||
| 518 | debug.assert(intToEnum(E2, one) catch unreachable == E2.B); | ||
| 519 | debug.assertError(intToEnum(E1, one), error.InvalidEnumTag); | ||
| 520 | } | ||
| 521 | |||
| 522 | pub const IntToEnumError = error{InvalidEnumTag}; | ||
| 523 | |||
| 524 | pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag { | ||
| 525 | comptime var i = 0; | ||
| 526 | inline while (i != @memberCount(Tag)) : (i += 1) { | ||
| 527 | const this_tag_value = @field(Tag, @memberName(Tag, i)); | ||
| 528 | if (tag_int == @enumToInt(this_tag_value)) { | ||
| 529 | return this_tag_value; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | return error.InvalidEnumTag; | ||
| 533 | } |
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+15-2| ... | @@ -390,6 +390,19 @@ pub const ChildProcess = struct { | ... | @@ -390,6 +390,19 @@ pub const ChildProcess = struct { |
| 390 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | 390 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 391 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | 391 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 392 | 392 | ||
| 393 | if (self.stdin_behavior == StdIo.Pipe) { | ||
| 394 | os.close(stdin_pipe[0]); | ||
| 395 | os.close(stdin_pipe[1]); | ||
| 396 | } | ||
| 397 | if (self.stdout_behavior == StdIo.Pipe) { | ||
| 398 | os.close(stdout_pipe[0]); | ||
| 399 | os.close(stdout_pipe[1]); | ||
| 400 | } | ||
| 401 | if (self.stderr_behavior == StdIo.Pipe) { | ||
| 402 | os.close(stderr_pipe[0]); | ||
| 403 | os.close(stderr_pipe[1]); | ||
| 404 | } | ||
| 405 | |||
| 393 | if (self.cwd) |cwd| { | 406 | if (self.cwd) |cwd| { |
| 394 | os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err); | 407 | os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 395 | } | 408 | } |
| ... | @@ -794,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); | ... | @@ -794,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); |
| 794 | 807 | ||
| 795 | fn writeIntFd(fd: i32, value: ErrInt) !void { | 808 | fn writeIntFd(fd: i32, value: ErrInt) !void { |
| 796 | const stream = &os.File.openHandle(fd).outStream().stream; | 809 | const stream = &os.File.openHandle(fd).outStream().stream; |
| 797 | stream.writeIntNe(ErrInt, value) catch return error.SystemResources; | 810 | stream.writeIntNative(ErrInt, value) catch return error.SystemResources; |
| 798 | } | 811 | } |
| 799 | 812 | ||
| 800 | fn readIntFd(fd: i32) !ErrInt { | 813 | fn readIntFd(fd: i32) !ErrInt { |
| 801 | const stream = &os.File.openHandle(fd).inStream().stream; | 814 | const stream = &os.File.openHandle(fd).inStream().stream; |
| 802 | return stream.readIntNe(ErrInt) catch return error.SystemResources; | 815 | return stream.readIntNative(ErrInt) catch return error.SystemResources; |
| 803 | } | 816 | } |
std/os/file.zig+62-8| ... | @@ -228,9 +228,16 @@ pub const File = struct { | ... | @@ -228,9 +228,16 @@ pub const File = struct { |
| 228 | return os.isTty(self.handle); | 228 | return os.isTty(self.handle); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | pub fn seekForward(self: File, amount: isize) !void { | 231 | pub const SeekError = error{ |
| 232 | /// TODO make this error impossible to get | ||
| 233 | Overflow, | ||
| 234 | Unseekable, | ||
| 235 | Unexpected, | ||
| 236 | }; | ||
| 237 | |||
| 238 | pub fn seekForward(self: File, amount: isize) SeekError!void { | ||
| 232 | switch (builtin.os) { | 239 | switch (builtin.os) { |
| 233 | Os.linux, Os.macosx, Os.ios => { | 240 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 234 | const result = posix.lseek(self.handle, amount, posix.SEEK_CUR); | 241 | const result = posix.lseek(self.handle, amount, posix.SEEK_CUR); |
| 235 | const err = posix.getErrno(result); | 242 | const err = posix.getErrno(result); |
| 236 | if (err > 0) { | 243 | if (err > 0) { |
| ... | @@ -259,9 +266,9 @@ pub const File = struct { | ... | @@ -259,9 +266,9 @@ pub const File = struct { |
| 259 | } | 266 | } |
| 260 | } | 267 | } |
| 261 | 268 | ||
| 262 | pub fn seekTo(self: File, pos: usize) !void { | 269 | pub fn seekTo(self: File, pos: usize) SeekError!void { |
| 263 | switch (builtin.os) { | 270 | switch (builtin.os) { |
| 264 | Os.linux, Os.macosx, Os.ios => { | 271 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 265 | const ipos = try math.cast(isize, pos); | 272 | const ipos = try math.cast(isize, pos); |
| 266 | const result = posix.lseek(self.handle, ipos, posix.SEEK_SET); | 273 | const result = posix.lseek(self.handle, ipos, posix.SEEK_SET); |
| 267 | const err = posix.getErrno(result); | 274 | const err = posix.getErrno(result); |
| ... | @@ -293,9 +300,16 @@ pub const File = struct { | ... | @@ -293,9 +300,16 @@ pub const File = struct { |
| 293 | } | 300 | } |
| 294 | } | 301 | } |
| 295 | 302 | ||
| 296 | pub fn getPos(self: File) !usize { | 303 | pub const GetSeekPosError = error{ |
| 304 | Overflow, | ||
| 305 | SystemResources, | ||
| 306 | Unseekable, | ||
| 307 | Unexpected, | ||
| 308 | }; | ||
| 309 | |||
| 310 | pub fn getPos(self: File) GetSeekPosError!usize { | ||
| 297 | switch (builtin.os) { | 311 | switch (builtin.os) { |
| 298 | Os.linux, Os.macosx, Os.ios => { | 312 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 299 | const result = posix.lseek(self.handle, 0, posix.SEEK_CUR); | 313 | const result = posix.lseek(self.handle, 0, posix.SEEK_CUR); |
| 300 | const err = posix.getErrno(result); | 314 | const err = posix.getErrno(result); |
| 301 | if (err > 0) { | 315 | if (err > 0) { |
| ... | @@ -323,13 +337,13 @@ pub const File = struct { | ... | @@ -323,13 +337,13 @@ pub const File = struct { |
| 323 | } | 337 | } |
| 324 | 338 | ||
| 325 | assert(pos >= 0); | 339 | assert(pos >= 0); |
| 326 | return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange; | 340 | return math.cast(usize, pos); |
| 327 | }, | 341 | }, |
| 328 | else => @compileError("unsupported OS"), | 342 | else => @compileError("unsupported OS"), |
| 329 | } | 343 | } |
| 330 | } | 344 | } |
| 331 | 345 | ||
| 332 | pub fn getEndPos(self: File) !usize { | 346 | pub fn getEndPos(self: File) GetSeekPosError!usize { |
| 333 | if (is_posix) { | 347 | if (is_posix) { |
| 334 | const stat = try os.posixFStat(self.handle); | 348 | const stat = try os.posixFStat(self.handle); |
| 335 | return @intCast(usize, stat.size); | 349 | return @intCast(usize, stat.size); |
| ... | @@ -431,6 +445,18 @@ pub const File = struct { | ... | @@ -431,6 +445,18 @@ pub const File = struct { |
| 431 | }; | 445 | }; |
| 432 | } | 446 | } |
| 433 | 447 | ||
| 448 | pub fn seekableStream(file: File) SeekableStream { | ||
| 449 | return SeekableStream{ | ||
| 450 | .file = file, | ||
| 451 | .stream = SeekableStream.Stream{ | ||
| 452 | .seekToFn = SeekableStream.seekToFn, | ||
| 453 | .seekForwardFn = SeekableStream.seekForwardFn, | ||
| 454 | .getPosFn = SeekableStream.getPosFn, | ||
| 455 | .getEndPosFn = SeekableStream.getEndPosFn, | ||
| 456 | }, | ||
| 457 | }; | ||
| 458 | } | ||
| 459 | |||
| 434 | /// Implementation of io.InStream trait for File | 460 | /// Implementation of io.InStream trait for File |
| 435 | pub const InStream = struct { | 461 | pub const InStream = struct { |
| 436 | file: File, | 462 | file: File, |
| ... | @@ -458,4 +484,32 @@ pub const File = struct { | ... | @@ -458,4 +484,32 @@ pub const File = struct { |
| 458 | return self.file.write(bytes); | 484 | return self.file.write(bytes); |
| 459 | } | 485 | } |
| 460 | }; | 486 | }; |
| 487 | |||
| 488 | /// Implementation of io.SeekableStream trait for File | ||
| 489 | pub const SeekableStream = struct { | ||
| 490 | file: File, | ||
| 491 | stream: Stream, | ||
| 492 | |||
| 493 | pub const Stream = io.SeekableStream(SeekError, GetSeekPosError); | ||
| 494 | |||
| 495 | pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void { | ||
| 496 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); | ||
| 497 | return self.file.seekTo(pos); | ||
| 498 | } | ||
| 499 | |||
| 500 | pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void { | ||
| 501 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); | ||
| 502 | return self.file.seekForward(amt); | ||
| 503 | } | ||
| 504 | |||
| 505 | pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize { | ||
| 506 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); | ||
| 507 | return self.file.getEndPos(); | ||
| 508 | } | ||
| 509 | |||
| 510 | pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize { | ||
| 511 | const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream); | ||
| 512 | return self.file.getPos(); | ||
| 513 | } | ||
| 514 | }; | ||
| 461 | }; | 515 | }; |
std/os/freebsd/errno.zig created+121| ... | @@ -0,0 +1,121 @@ | ||
| 1 | pub const EPERM = 1; // Operation not permitted | ||
| 2 | pub const ENOENT = 2; // No such file or directory | ||
| 3 | pub const ESRCH = 3; // No such process | ||
| 4 | pub const EINTR = 4; // Interrupted system call | ||
| 5 | pub const EIO = 5; // Input/output error | ||
| 6 | pub const ENXIO = 6; // Device not configured | ||
| 7 | pub const E2BIG = 7; // Argument list too long | ||
| 8 | pub const ENOEXEC = 8; // Exec format error | ||
| 9 | pub const EBADF = 9; // Bad file descriptor | ||
| 10 | pub const ECHILD = 10; // No child processes | ||
| 11 | pub const EDEADLK = 11; // Resource deadlock avoided | ||
| 12 | // 11 was EAGAIN | ||
| 13 | pub const ENOMEM = 12; // Cannot allocate memory | ||
| 14 | pub const EACCES = 13; // Permission denied | ||
| 15 | pub const EFAULT = 14; // Bad address | ||
| 16 | pub const ENOTBLK = 15; // Block device required | ||
| 17 | pub const EBUSY = 16; // Device busy | ||
| 18 | pub const EEXIST = 17; // File exists | ||
| 19 | pub const EXDEV = 18; // Cross-device link | ||
| 20 | pub const ENODEV = 19; // Operation not supported by device | ||
| 21 | pub const ENOTDIR = 20; // Not a directory | ||
| 22 | pub const EISDIR = 21; // Is a directory | ||
| 23 | pub const EINVAL = 22; // Invalid argument | ||
| 24 | pub const ENFILE = 23; // Too many open files in system | ||
| 25 | pub const EMFILE = 24; // Too many open files | ||
| 26 | pub const ENOTTY = 25; // Inappropriate ioctl for device | ||
| 27 | pub const ETXTBSY = 26; // Text file busy | ||
| 28 | pub const EFBIG = 27; // File too large | ||
| 29 | pub const ENOSPC = 28; // No space left on device | ||
| 30 | pub const ESPIPE = 29; // Illegal seek | ||
| 31 | pub const EROFS = 30; // Read-only filesystem | ||
| 32 | pub const EMLINK = 31; // Too many links | ||
| 33 | pub const EPIPE = 32; // Broken pipe | ||
| 34 | |||
| 35 | // math software | ||
| 36 | pub const EDOM = 33; // Numerical argument out of domain | ||
| 37 | pub const ERANGE = 34; // Result too large | ||
| 38 | |||
| 39 | // non-blocking and interrupt i/o | ||
| 40 | pub const EAGAIN = 35; // Resource temporarily unavailable | ||
| 41 | pub const EWOULDBLOCK = EAGAIN; // Operation would block | ||
| 42 | pub const EINPROGRESS = 36; // Operation now in progress | ||
| 43 | pub const EALREADY = 37; // Operation already in progress | ||
| 44 | |||
| 45 | // ipc/network software -- argument errors | ||
| 46 | pub const ENOTSOCK = 38; // Socket operation on non-socket | ||
| 47 | pub const EDESTADDRREQ = 39; // Destination address required | ||
| 48 | pub const EMSGSIZE = 40; // Message too long | ||
| 49 | pub const EPROTOTYPE = 41; // Protocol wrong type for socket | ||
| 50 | pub const ENOPROTOOPT = 42; // Protocol not available | ||
| 51 | pub const EPROTONOSUPPORT = 43; // Protocol not supported | ||
| 52 | pub const ESOCKTNOSUPPORT = 44; // Socket type not supported | ||
| 53 | pub const EOPNOTSUPP = 45; // Operation not supported | ||
| 54 | pub const ENOTSUP = EOPNOTSUPP; // Operation not supported | ||
| 55 | pub const EPFNOSUPPORT = 46; // Protocol family not supported | ||
| 56 | pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family | ||
| 57 | pub const EADDRINUSE = 48; // Address already in use | ||
| 58 | pub const EADDRNOTAVAIL = 49; // Can't assign requested address | ||
| 59 | |||
| 60 | // ipc/network software -- operational errors | ||
| 61 | pub const ENETDOWN = 50; // Network is down | ||
| 62 | pub const ENETUNREACH = 51; // Network is unreachable | ||
| 63 | pub const ENETRESET = 52; // Network dropped connection on reset | ||
| 64 | pub const ECONNABORTED = 53; // Software caused connection abort | ||
| 65 | pub const ECONNRESET = 54; // Connection reset by peer | ||
| 66 | pub const ENOBUFS = 55; // No buffer space available | ||
| 67 | pub const EISCONN = 56; // Socket is already connected | ||
| 68 | pub const ENOTCONN = 57; // Socket is not connected | ||
| 69 | pub const ESHUTDOWN = 58; // Can't send after socket shutdown | ||
| 70 | pub const ETOOMANYREFS = 59; // Too many references: can't splice | ||
| 71 | pub const ETIMEDOUT = 60; // Operation timed out | ||
| 72 | pub const ECONNREFUSED = 61; // Connection refused | ||
| 73 | |||
| 74 | pub const ELOOP = 62; // Too many levels of symbolic links | ||
| 75 | pub const ENAMETOOLONG = 63; // File name too long | ||
| 76 | |||
| 77 | // should be rearranged | ||
| 78 | pub const EHOSTDOWN = 64; // Host is down | ||
| 79 | pub const EHOSTUNREACH = 65; // No route to host | ||
| 80 | pub const ENOTEMPTY = 66; // Directory not empty | ||
| 81 | |||
| 82 | // quotas & mush | ||
| 83 | pub const EPROCLIM = 67; // Too many processes | ||
| 84 | pub const EUSERS = 68; // Too many users | ||
| 85 | pub const EDQUOT = 69; // Disc quota exceeded | ||
| 86 | |||
| 87 | // Network File System | ||
| 88 | pub const ESTALE = 70; // Stale NFS file handle | ||
| 89 | pub const EREMOTE = 71; // Too many levels of remote in path | ||
| 90 | pub const EBADRPC = 72; // RPC struct is bad | ||
| 91 | pub const ERPCMISMATCH = 73; // RPC version wrong | ||
| 92 | pub const EPROGUNAVAIL = 74; // RPC prog. not avail | ||
| 93 | pub const EPROGMISMATCH = 75; // Program version wrong | ||
| 94 | pub const EPROCUNAVAIL = 76; // Bad procedure for program | ||
| 95 | |||
| 96 | pub const ENOLCK = 77; // No locks available | ||
| 97 | pub const ENOSYS = 78; // Function not implemented | ||
| 98 | |||
| 99 | pub const EFTYPE = 79; // Inappropriate file type or format | ||
| 100 | pub const EAUTH = 80; // Authentication error | ||
| 101 | pub const ENEEDAUTH = 81; // Need authenticator | ||
| 102 | pub const EIDRM = 82; // Identifier removed | ||
| 103 | pub const ENOMSG = 83; // No message of desired type | ||
| 104 | pub const EOVERFLOW = 84; // Value too large to be stored in data type | ||
| 105 | pub const ECANCELED = 85; // Operation canceled | ||
| 106 | pub const EILSEQ = 86; // Illegal byte sequence | ||
| 107 | pub const ENOATTR = 87; // Attribute not found | ||
| 108 | |||
| 109 | pub const EDOOFUS = 88; // Programming error | ||
| 110 | |||
| 111 | pub const EBADMSG = 89; // Bad message | ||
| 112 | pub const EMULTIHOP = 90; // Multihop attempted | ||
| 113 | pub const ENOLINK = 91; // Link has been severed | ||
| 114 | pub const EPROTO = 92; // Protocol error | ||
| 115 | |||
| 116 | pub const ENOTCAPABLE = 93; // Capabilities insufficient | ||
| 117 | pub const ECAPMODE = 94; // Not permitted in capability mode | ||
| 118 | pub const ENOTRECOVERABLE = 95; // State not recoverable | ||
| 119 | pub const EOWNERDEAD = 96; // Previous owner died | ||
| 120 | |||
| 121 | pub const ELAST = 96; // Must be equal largest errno | ||
std/os/freebsd/index.zig created+801| ... | @@ -0,0 +1,801 @@ | ||
| 1 | const assert = @import("../debug.zig").assert; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const arch = switch (builtin.arch) { | ||
| 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"); | ||
| 9 | |||
| 10 | const std = @import("../../index.zig"); | ||
| 11 | const c = std.c; | ||
| 12 | const maxInt = std.math.maxInt; | ||
| 13 | pub const Kevent = c.Kevent; | ||
| 14 | |||
| 15 | pub const PATH_MAX = 1024; | ||
| 16 | |||
| 17 | pub const STDIN_FILENO = 0; | ||
| 18 | pub const STDOUT_FILENO = 1; | ||
| 19 | pub const STDERR_FILENO = 2; | ||
| 20 | |||
| 21 | pub const PROT_NONE = 0; | ||
| 22 | pub const PROT_READ = 1; | ||
| 23 | pub const PROT_WRITE = 2; | ||
| 24 | pub const PROT_EXEC = 4; | ||
| 25 | |||
| 26 | pub const MAP_FAILED = maxInt(usize); | ||
| 27 | pub const MAP_SHARED = 0x0001; | ||
| 28 | pub const MAP_PRIVATE = 0x0002; | ||
| 29 | pub const MAP_FIXED = 0x0010; | ||
| 30 | pub const MAP_STACK = 0x0400; | ||
| 31 | pub const MAP_NOSYNC = 0x0800; | ||
| 32 | pub const MAP_ANON = 0x1000; | ||
| 33 | pub const MAP_ANONYMOUS = MAP_ANON; | ||
| 34 | pub const MAP_FILE = 0; | ||
| 35 | pub const MAP_NORESERVE = 0; | ||
| 36 | |||
| 37 | pub const MAP_GUARD = 0x00002000; | ||
| 38 | pub const MAP_EXCL = 0x00004000; | ||
| 39 | pub const MAP_NOCORE = 0x00020000; | ||
| 40 | pub const MAP_PREFAULT_READ = 0x00040000; | ||
| 41 | pub const MAP_32BIT = 0x00080000; | ||
| 42 | |||
| 43 | pub const WNOHANG = 1; | ||
| 44 | pub const WUNTRACED = 2; | ||
| 45 | pub const WSTOPPED = WUNTRACED; | ||
| 46 | pub const WCONTINUED = 4; | ||
| 47 | pub const WNOWAIT = 8; | ||
| 48 | pub const WEXITED = 16; | ||
| 49 | pub const WTRAPPED = 32; | ||
| 50 | |||
| 51 | pub const SA_ONSTACK = 0x0001; | ||
| 52 | pub const SA_RESTART = 0x0002; | ||
| 53 | pub const SA_RESETHAND = 0x0004; | ||
| 54 | pub const SA_NOCLDSTOP = 0x0008; | ||
| 55 | pub const SA_NODEFER = 0x0010; | ||
| 56 | pub const SA_NOCLDWAIT = 0x0020; | ||
| 57 | pub const SA_SIGINFO = 0x0040; | ||
| 58 | |||
| 59 | pub const SIGHUP = 1; | ||
| 60 | pub const SIGINT = 2; | ||
| 61 | pub const SIGQUIT = 3; | ||
| 62 | pub const SIGILL = 4; | ||
| 63 | pub const SIGTRAP = 5; | ||
| 64 | pub const SIGABRT = 6; | ||
| 65 | pub const SIGIOT = SIGABRT; | ||
| 66 | pub const SIGEMT = 7; | ||
| 67 | pub const SIGFPE = 8; | ||
| 68 | pub const SIGKILL = 9; | ||
| 69 | pub const SIGBUS = 10; | ||
| 70 | pub const SIGSEGV = 11; | ||
| 71 | pub const SIGSYS = 12; | ||
| 72 | pub const SIGPIPE = 13; | ||
| 73 | pub const SIGALRM = 14; | ||
| 74 | pub const SIGTERM = 15; | ||
| 75 | pub const SIGURG = 16; | ||
| 76 | pub const SIGSTOP = 17; | ||
| 77 | pub const SIGTSTP = 18; | ||
| 78 | pub const SIGCONT = 19; | ||
| 79 | pub const SIGCHLD = 20; | ||
| 80 | pub const SIGTTIN = 21; | ||
| 81 | pub const SIGTTOU = 22; | ||
| 82 | pub const SIGIO = 23; | ||
| 83 | pub const SIGXCPU = 24; | ||
| 84 | pub const SIGXFSZ = 25; | ||
| 85 | pub const SIGVTALRM = 26; | ||
| 86 | pub const SIGPROF = 27; | ||
| 87 | pub const SIGWINCH = 28; | ||
| 88 | pub const SIGINFO = 29; | ||
| 89 | pub const SIGUSR1 = 30; | ||
| 90 | pub const SIGUSR2 = 31; | ||
| 91 | pub const SIGTHR = 32; | ||
| 92 | pub const SIGLWP = SIGTHR; | ||
| 93 | pub const SIGLIBRT = 33; | ||
| 94 | |||
| 95 | pub const SIGRTMIN = 65; | ||
| 96 | pub const SIGRTMAX = 126; | ||
| 97 | |||
| 98 | pub const O_RDONLY = 0o0; | ||
| 99 | pub const O_WRONLY = 0o1; | ||
| 100 | pub const O_RDWR = 0o2; | ||
| 101 | pub const O_ACCMODE = 0o3; | ||
| 102 | |||
| 103 | pub const O_CREAT = 0o100; | ||
| 104 | pub const O_EXCL = 0o200; | ||
| 105 | pub const O_NOCTTY = 0o400; | ||
| 106 | pub const O_TRUNC = 0o1000; | ||
| 107 | pub const O_APPEND = 0o2000; | ||
| 108 | pub const O_NONBLOCK = 0o4000; | ||
| 109 | pub const O_DSYNC = 0o10000; | ||
| 110 | pub const O_SYNC = 0o4010000; | ||
| 111 | pub const O_RSYNC = 0o4010000; | ||
| 112 | pub const O_DIRECTORY = 0o200000; | ||
| 113 | pub const O_NOFOLLOW = 0o400000; | ||
| 114 | pub const O_CLOEXEC = 0o2000000; | ||
| 115 | |||
| 116 | pub const O_ASYNC = 0o20000; | ||
| 117 | pub const O_DIRECT = 0o40000; | ||
| 118 | pub const O_LARGEFILE = 0; | ||
| 119 | pub const O_NOATIME = 0o1000000; | ||
| 120 | pub const O_PATH = 0o10000000; | ||
| 121 | pub const O_TMPFILE = 0o20200000; | ||
| 122 | pub const O_NDELAY = O_NONBLOCK; | ||
| 123 | |||
| 124 | pub const F_DUPFD = 0; | ||
| 125 | pub const F_GETFD = 1; | ||
| 126 | pub const F_SETFD = 2; | ||
| 127 | pub const F_GETFL = 3; | ||
| 128 | pub const F_SETFL = 4; | ||
| 129 | |||
| 130 | pub const F_SETOWN = 8; | ||
| 131 | pub const F_GETOWN = 9; | ||
| 132 | pub const F_SETSIG = 10; | ||
| 133 | pub const F_GETSIG = 11; | ||
| 134 | |||
| 135 | pub const F_GETLK = 5; | ||
| 136 | pub const F_SETLK = 6; | ||
| 137 | pub const F_SETLKW = 7; | ||
| 138 | |||
| 139 | pub const F_SETOWN_EX = 15; | ||
| 140 | pub const F_GETOWN_EX = 16; | ||
| 141 | |||
| 142 | pub const F_GETOWNER_UIDS = 17; | ||
| 143 | |||
| 144 | pub const SEEK_SET = 0; | ||
| 145 | pub const SEEK_CUR = 1; | ||
| 146 | pub const SEEK_END = 2; | ||
| 147 | |||
| 148 | pub const SIG_BLOCK = 1; | ||
| 149 | pub const SIG_UNBLOCK = 2; | ||
| 150 | pub const SIG_SETMASK = 3; | ||
| 151 | |||
| 152 | pub const SOCK_STREAM = 1; | ||
| 153 | pub const SOCK_DGRAM = 2; | ||
| 154 | pub const SOCK_RAW = 3; | ||
| 155 | pub const SOCK_RDM = 4; | ||
| 156 | pub const SOCK_SEQPACKET = 5; | ||
| 157 | |||
| 158 | pub const SOCK_CLOEXEC = 0x10000000; | ||
| 159 | pub const SOCK_NONBLOCK = 0x20000000; | ||
| 160 | |||
| 161 | pub const PROTO_ip = 0o000; | ||
| 162 | pub const PROTO_icmp = 0o001; | ||
| 163 | pub const PROTO_igmp = 0o002; | ||
| 164 | pub const PROTO_ggp = 0o003; | ||
| 165 | pub const PROTO_ipencap = 0o004; | ||
| 166 | pub const PROTO_st = 0o005; | ||
| 167 | pub const PROTO_tcp = 0o006; | ||
| 168 | pub const PROTO_egp = 0o010; | ||
| 169 | pub const PROTO_pup = 0o014; | ||
| 170 | pub const PROTO_udp = 0o021; | ||
| 171 | pub const PROTO_hmp = 0o024; | ||
| 172 | pub const PROTO_xns_idp = 0o026; | ||
| 173 | pub const PROTO_rdp = 0o033; | ||
| 174 | pub const PROTO_iso_tp4 = 0o035; | ||
| 175 | pub const PROTO_xtp = 0o044; | ||
| 176 | pub const PROTO_ddp = 0o045; | ||
| 177 | pub const PROTO_idpr_cmtp = 0o046; | ||
| 178 | pub const PROTO_ipv6 = 0o051; | ||
| 179 | pub const PROTO_ipv6_route = 0o053; | ||
| 180 | pub const PROTO_ipv6_frag = 0o054; | ||
| 181 | pub const PROTO_idrp = 0o055; | ||
| 182 | pub const PROTO_rsvp = 0o056; | ||
| 183 | pub const PROTO_gre = 0o057; | ||
| 184 | pub const PROTO_esp = 0o062; | ||
| 185 | pub const PROTO_ah = 0o063; | ||
| 186 | pub const PROTO_skip = 0o071; | ||
| 187 | pub const PROTO_ipv6_icmp = 0o072; | ||
| 188 | pub const PROTO_ipv6_nonxt = 0o073; | ||
| 189 | pub const PROTO_ipv6_opts = 0o074; | ||
| 190 | pub const PROTO_rspf = 0o111; | ||
| 191 | pub const PROTO_vmtp = 0o121; | ||
| 192 | pub const PROTO_ospf = 0o131; | ||
| 193 | pub const PROTO_ipip = 0o136; | ||
| 194 | pub const PROTO_encap = 0o142; | ||
| 195 | pub const PROTO_pim = 0o147; | ||
| 196 | pub const PROTO_raw = 0o377; | ||
| 197 | |||
| 198 | pub const PF_UNSPEC = 0; | ||
| 199 | pub const PF_LOCAL = 1; | ||
| 200 | pub const PF_UNIX = PF_LOCAL; | ||
| 201 | pub const PF_FILE = PF_LOCAL; | ||
| 202 | pub const PF_INET = 2; | ||
| 203 | pub const PF_AX25 = 3; | ||
| 204 | pub const PF_IPX = 4; | ||
| 205 | pub const PF_APPLETALK = 5; | ||
| 206 | pub const PF_NETROM = 6; | ||
| 207 | pub const PF_BRIDGE = 7; | ||
| 208 | pub const PF_ATMPVC = 8; | ||
| 209 | pub const PF_X25 = 9; | ||
| 210 | pub const PF_INET6 = 10; | ||
| 211 | pub const PF_ROSE = 11; | ||
| 212 | pub const PF_DECnet = 12; | ||
| 213 | pub const PF_NETBEUI = 13; | ||
| 214 | pub const PF_SECURITY = 14; | ||
| 215 | pub const PF_KEY = 15; | ||
| 216 | pub const PF_NETLINK = 16; | ||
| 217 | pub const PF_ROUTE = PF_NETLINK; | ||
| 218 | pub const PF_PACKET = 17; | ||
| 219 | pub const PF_ASH = 18; | ||
| 220 | pub const PF_ECONET = 19; | ||
| 221 | pub const PF_ATMSVC = 20; | ||
| 222 | pub const PF_RDS = 21; | ||
| 223 | pub const PF_SNA = 22; | ||
| 224 | pub const PF_IRDA = 23; | ||
| 225 | pub const PF_PPPOX = 24; | ||
| 226 | pub const PF_WANPIPE = 25; | ||
| 227 | pub const PF_LLC = 26; | ||
| 228 | pub const PF_IB = 27; | ||
| 229 | pub const PF_MPLS = 28; | ||
| 230 | pub const PF_CAN = 29; | ||
| 231 | pub const PF_TIPC = 30; | ||
| 232 | pub const PF_BLUETOOTH = 31; | ||
| 233 | pub const PF_IUCV = 32; | ||
| 234 | pub const PF_RXRPC = 33; | ||
| 235 | pub const PF_ISDN = 34; | ||
| 236 | pub const PF_PHONET = 35; | ||
| 237 | pub const PF_IEEE802154 = 36; | ||
| 238 | pub const PF_CAIF = 37; | ||
| 239 | pub const PF_ALG = 38; | ||
| 240 | pub const PF_NFC = 39; | ||
| 241 | pub const PF_VSOCK = 40; | ||
| 242 | pub const PF_MAX = 41; | ||
| 243 | |||
| 244 | pub const AF_UNSPEC = PF_UNSPEC; | ||
| 245 | pub const AF_LOCAL = PF_LOCAL; | ||
| 246 | pub const AF_UNIX = AF_LOCAL; | ||
| 247 | pub const AF_FILE = AF_LOCAL; | ||
| 248 | pub const AF_INET = PF_INET; | ||
| 249 | pub const AF_AX25 = PF_AX25; | ||
| 250 | pub const AF_IPX = PF_IPX; | ||
| 251 | pub const AF_APPLETALK = PF_APPLETALK; | ||
| 252 | pub const AF_NETROM = PF_NETROM; | ||
| 253 | pub const AF_BRIDGE = PF_BRIDGE; | ||
| 254 | pub const AF_ATMPVC = PF_ATMPVC; | ||
| 255 | pub const AF_X25 = PF_X25; | ||
| 256 | pub const AF_INET6 = PF_INET6; | ||
| 257 | pub const AF_ROSE = PF_ROSE; | ||
| 258 | pub const AF_DECnet = PF_DECnet; | ||
| 259 | pub const AF_NETBEUI = PF_NETBEUI; | ||
| 260 | pub const AF_SECURITY = PF_SECURITY; | ||
| 261 | pub const AF_KEY = PF_KEY; | ||
| 262 | pub const AF_NETLINK = PF_NETLINK; | ||
| 263 | pub const AF_ROUTE = PF_ROUTE; | ||
| 264 | pub const AF_PACKET = PF_PACKET; | ||
| 265 | pub const AF_ASH = PF_ASH; | ||
| 266 | pub const AF_ECONET = PF_ECONET; | ||
| 267 | pub const AF_ATMSVC = PF_ATMSVC; | ||
| 268 | pub const AF_RDS = PF_RDS; | ||
| 269 | pub const AF_SNA = PF_SNA; | ||
| 270 | pub const AF_IRDA = PF_IRDA; | ||
| 271 | pub const AF_PPPOX = PF_PPPOX; | ||
| 272 | pub const AF_WANPIPE = PF_WANPIPE; | ||
| 273 | pub const AF_LLC = PF_LLC; | ||
| 274 | pub const AF_IB = PF_IB; | ||
| 275 | pub const AF_MPLS = PF_MPLS; | ||
| 276 | pub const AF_CAN = PF_CAN; | ||
| 277 | pub const AF_TIPC = PF_TIPC; | ||
| 278 | pub const AF_BLUETOOTH = PF_BLUETOOTH; | ||
| 279 | pub const AF_IUCV = PF_IUCV; | ||
| 280 | pub const AF_RXRPC = PF_RXRPC; | ||
| 281 | pub const AF_ISDN = PF_ISDN; | ||
| 282 | pub const AF_PHONET = PF_PHONET; | ||
| 283 | pub const AF_IEEE802154 = PF_IEEE802154; | ||
| 284 | pub const AF_CAIF = PF_CAIF; | ||
| 285 | pub const AF_ALG = PF_ALG; | ||
| 286 | pub const AF_NFC = PF_NFC; | ||
| 287 | pub const AF_VSOCK = PF_VSOCK; | ||
| 288 | pub const AF_MAX = PF_MAX; | ||
| 289 | |||
| 290 | pub const DT_UNKNOWN = 0; | ||
| 291 | pub const DT_FIFO = 1; | ||
| 292 | pub const DT_CHR = 2; | ||
| 293 | pub const DT_DIR = 4; | ||
| 294 | pub const DT_BLK = 6; | ||
| 295 | pub const DT_REG = 8; | ||
| 296 | pub const DT_LNK = 10; | ||
| 297 | pub const DT_SOCK = 12; | ||
| 298 | pub const DT_WHT = 14; | ||
| 299 | |||
| 300 | /// add event to kq (implies enable) | ||
| 301 | pub const EV_ADD = 0x0001; | ||
| 302 | |||
| 303 | /// delete event from kq | ||
| 304 | pub const EV_DELETE = 0x0002; | ||
| 305 | |||
| 306 | /// enable event | ||
| 307 | pub const EV_ENABLE = 0x0004; | ||
| 308 | |||
| 309 | /// disable event (not reported) | ||
| 310 | pub const EV_DISABLE = 0x0008; | ||
| 311 | |||
| 312 | /// only report one occurrence | ||
| 313 | pub const EV_ONESHOT = 0x0010; | ||
| 314 | |||
| 315 | /// clear event state after reporting | ||
| 316 | pub const EV_CLEAR = 0x0020; | ||
| 317 | |||
| 318 | /// force immediate event output | ||
| 319 | /// ... with or without EV_ERROR | ||
| 320 | /// ... use KEVENT_FLAG_ERROR_EVENTS | ||
| 321 | /// on syscalls supporting flags | ||
| 322 | pub const EV_RECEIPT = 0x0040; | ||
| 323 | |||
| 324 | /// disable event after reporting | ||
| 325 | pub const EV_DISPATCH = 0x0080; | ||
| 326 | |||
| 327 | pub const EVFILT_READ = -1; | ||
| 328 | pub const EVFILT_WRITE = -2; | ||
| 329 | |||
| 330 | /// attached to aio requests | ||
| 331 | pub const EVFILT_AIO = -3; | ||
| 332 | |||
| 333 | /// attached to vnodes | ||
| 334 | pub const EVFILT_VNODE = -4; | ||
| 335 | |||
| 336 | /// attached to struct proc | ||
| 337 | pub const EVFILT_PROC = -5; | ||
| 338 | |||
| 339 | /// attached to struct proc | ||
| 340 | pub const EVFILT_SIGNAL = -6; | ||
| 341 | |||
| 342 | /// timers | ||
| 343 | pub const EVFILT_TIMER = -7; | ||
| 344 | |||
| 345 | /// Process descriptors | ||
| 346 | pub const EVFILT_PROCDESC = -8; | ||
| 347 | |||
| 348 | /// Filesystem events | ||
| 349 | pub const EVFILT_FS = -9; | ||
| 350 | |||
| 351 | pub const EVFILT_LIO = -10; | ||
| 352 | |||
| 353 | /// User events | ||
| 354 | pub const EVFILT_USER = -11; | ||
| 355 | |||
| 356 | /// Sendfile events | ||
| 357 | pub const EVFILT_SENDFILE = -12; | ||
| 358 | |||
| 359 | pub const EVFILT_EMPTY = -13; | ||
| 360 | |||
| 361 | /// On input, NOTE_TRIGGER causes the event to be triggered for output. | ||
| 362 | pub const NOTE_TRIGGER = 0x01000000; | ||
| 363 | |||
| 364 | /// ignore input fflags | ||
| 365 | pub const NOTE_FFNOP = 0x00000000; | ||
| 366 | |||
| 367 | /// and fflags | ||
| 368 | pub const NOTE_FFAND = 0x40000000; | ||
| 369 | |||
| 370 | /// or fflags | ||
| 371 | pub const NOTE_FFOR = 0x80000000; | ||
| 372 | |||
| 373 | /// copy fflags | ||
| 374 | pub const NOTE_FFCOPY = 0xc0000000; | ||
| 375 | |||
| 376 | /// mask for operations | ||
| 377 | pub const NOTE_FFCTRLMASK = 0xc0000000; | ||
| 378 | pub const NOTE_FFLAGSMASK = 0x00ffffff; | ||
| 379 | |||
| 380 | /// low water mark | ||
| 381 | pub const NOTE_LOWAT = 0x00000001; | ||
| 382 | |||
| 383 | /// behave like poll() | ||
| 384 | pub const NOTE_FILE_POLL = 0x00000002; | ||
| 385 | |||
| 386 | /// vnode was removed | ||
| 387 | pub const NOTE_DELETE = 0x00000001; | ||
| 388 | |||
| 389 | /// data contents changed | ||
| 390 | pub const NOTE_WRITE = 0x00000002; | ||
| 391 | |||
| 392 | /// size increased | ||
| 393 | pub const NOTE_EXTEND = 0x00000004; | ||
| 394 | |||
| 395 | /// attributes changed | ||
| 396 | pub const NOTE_ATTRIB = 0x00000008; | ||
| 397 | |||
| 398 | /// link count changed | ||
| 399 | pub const NOTE_LINK = 0x00000010; | ||
| 400 | |||
| 401 | /// vnode was renamed | ||
| 402 | pub const NOTE_RENAME = 0x00000020; | ||
| 403 | |||
| 404 | /// vnode access was revoked | ||
| 405 | pub const NOTE_REVOKE = 0x00000040; | ||
| 406 | |||
| 407 | /// vnode was opened | ||
| 408 | pub const NOTE_OPEN = 0x00000080; | ||
| 409 | |||
| 410 | /// file closed, fd did not allow write | ||
| 411 | pub const NOTE_CLOSE = 0x00000100; | ||
| 412 | |||
| 413 | /// file closed, fd did allow write | ||
| 414 | pub const NOTE_CLOSE_WRITE = 0x00000200; | ||
| 415 | |||
| 416 | /// file was read | ||
| 417 | pub const NOTE_READ = 0x00000400; | ||
| 418 | |||
| 419 | /// process exited | ||
| 420 | pub const NOTE_EXIT = 0x80000000; | ||
| 421 | |||
| 422 | /// process forked | ||
| 423 | pub const NOTE_FORK = 0x40000000; | ||
| 424 | |||
| 425 | /// process exec'd | ||
| 426 | pub const NOTE_EXEC = 0x20000000; | ||
| 427 | |||
| 428 | /// mask for signal & exit status | ||
| 429 | pub const NOTE_PDATAMASK = 0x000fffff; | ||
| 430 | pub const NOTE_PCTRLMASK = (~NOTE_PDATAMASK); | ||
| 431 | |||
| 432 | /// data is seconds | ||
| 433 | pub const NOTE_SECONDS = 0x00000001; | ||
| 434 | |||
| 435 | /// data is milliseconds | ||
| 436 | pub const NOTE_MSECONDS = 0x00000002; | ||
| 437 | |||
| 438 | /// data is microseconds | ||
| 439 | pub const NOTE_USECONDS = 0x00000004; | ||
| 440 | |||
| 441 | /// data is nanoseconds | ||
| 442 | pub const NOTE_NSECONDS = 0x00000008; | ||
| 443 | |||
| 444 | /// timeout is absolute | ||
| 445 | pub const NOTE_ABSTIME = 0x00000010; | ||
| 446 | |||
| 447 | pub const TCGETS = 0x5401; | ||
| 448 | pub const TCSETS = 0x5402; | ||
| 449 | pub const TCSETSW = 0x5403; | ||
| 450 | pub const TCSETSF = 0x5404; | ||
| 451 | pub const TCGETA = 0x5405; | ||
| 452 | pub const TCSETA = 0x5406; | ||
| 453 | pub const TCSETAW = 0x5407; | ||
| 454 | pub const TCSETAF = 0x5408; | ||
| 455 | pub const TCSBRK = 0x5409; | ||
| 456 | pub const TCXONC = 0x540A; | ||
| 457 | pub const TCFLSH = 0x540B; | ||
| 458 | pub const TIOCEXCL = 0x540C; | ||
| 459 | pub const TIOCNXCL = 0x540D; | ||
| 460 | pub const TIOCSCTTY = 0x540E; | ||
| 461 | pub const TIOCGPGRP = 0x540F; | ||
| 462 | pub const TIOCSPGRP = 0x5410; | ||
| 463 | pub const TIOCOUTQ = 0x5411; | ||
| 464 | pub const TIOCSTI = 0x5412; | ||
| 465 | pub const TIOCGWINSZ = 0x5413; | ||
| 466 | pub const TIOCSWINSZ = 0x5414; | ||
| 467 | pub const TIOCMGET = 0x5415; | ||
| 468 | pub const TIOCMBIS = 0x5416; | ||
| 469 | pub const TIOCMBIC = 0x5417; | ||
| 470 | pub const TIOCMSET = 0x5418; | ||
| 471 | pub const TIOCGSOFTCAR = 0x5419; | ||
| 472 | pub const TIOCSSOFTCAR = 0x541A; | ||
| 473 | pub const FIONREAD = 0x541B; | ||
| 474 | pub const TIOCINQ = FIONREAD; | ||
| 475 | pub const TIOCLINUX = 0x541C; | ||
| 476 | pub const TIOCCONS = 0x541D; | ||
| 477 | pub const TIOCGSERIAL = 0x541E; | ||
| 478 | pub const TIOCSSERIAL = 0x541F; | ||
| 479 | pub const TIOCPKT = 0x5420; | ||
| 480 | pub const FIONBIO = 0x5421; | ||
| 481 | pub const TIOCNOTTY = 0x5422; | ||
| 482 | pub const TIOCSETD = 0x5423; | ||
| 483 | pub const TIOCGETD = 0x5424; | ||
| 484 | pub const TCSBRKP = 0x5425; | ||
| 485 | pub const TIOCSBRK = 0x5427; | ||
| 486 | pub const TIOCCBRK = 0x5428; | ||
| 487 | pub const TIOCGSID = 0x5429; | ||
| 488 | pub const TIOCGRS485 = 0x542E; | ||
| 489 | pub const TIOCSRS485 = 0x542F; | ||
| 490 | pub const TIOCGPTN = 0x80045430; | ||
| 491 | pub const TIOCSPTLCK = 0x40045431; | ||
| 492 | pub const TIOCGDEV = 0x80045432; | ||
| 493 | pub const TCGETX = 0x5432; | ||
| 494 | pub const TCSETX = 0x5433; | ||
| 495 | pub const TCSETXF = 0x5434; | ||
| 496 | pub const TCSETXW = 0x5435; | ||
| 497 | pub const TIOCSIG = 0x40045436; | ||
| 498 | pub const TIOCVHANGUP = 0x5437; | ||
| 499 | pub const TIOCGPKT = 0x80045438; | ||
| 500 | pub const TIOCGPTLCK = 0x80045439; | ||
| 501 | pub const TIOCGEXCL = 0x80045440; | ||
| 502 | |||
| 503 | fn unsigned(s: i32) u32 { | ||
| 504 | return @bitCast(u32, s); | ||
| 505 | } | ||
| 506 | fn signed(s: u32) i32 { | ||
| 507 | return @bitCast(i32, s); | ||
| 508 | } | ||
| 509 | pub fn WEXITSTATUS(s: i32) i32 { | ||
| 510 | return signed((unsigned(s) & 0xff00) >> 8); | ||
| 511 | } | ||
| 512 | pub fn WTERMSIG(s: i32) i32 { | ||
| 513 | return signed(unsigned(s) & 0x7f); | ||
| 514 | } | ||
| 515 | pub fn WSTOPSIG(s: i32) i32 { | ||
| 516 | return WEXITSTATUS(s); | ||
| 517 | } | ||
| 518 | pub fn WIFEXITED(s: i32) bool { | ||
| 519 | return WTERMSIG(s) == 0; | ||
| 520 | } | ||
| 521 | pub fn WIFSTOPPED(s: i32) bool { | ||
| 522 | return @intCast(u16, (((unsigned(s) & 0xffff) *% 0x10001) >> 8)) > 0x7f00; | ||
| 523 | } | ||
| 524 | pub fn WIFSIGNALED(s: i32) bool { | ||
| 525 | return (unsigned(s) & 0xffff) -% 1 < 0xff; | ||
| 526 | } | ||
| 527 | |||
| 528 | pub const winsize = extern struct { | ||
| 529 | ws_row: u16, | ||
| 530 | ws_col: u16, | ||
| 531 | ws_xpixel: u16, | ||
| 532 | ws_ypixel: u16, | ||
| 533 | }; | ||
| 534 | |||
| 535 | /// Get the errno from a syscall return value, or 0 for no error. | ||
| 536 | pub fn getErrno(r: usize) usize { | ||
| 537 | const signed_r = @bitCast(isize, r); | ||
| 538 | return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0; | ||
| 539 | } | ||
| 540 | |||
| 541 | pub fn dup2(old: i32, new: i32) usize { | ||
| 542 | return arch.syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new))); | ||
| 543 | } | ||
| 544 | |||
| 545 | pub fn chdir(path: [*]const u8) usize { | ||
| 546 | return arch.syscall1(SYS_chdir, @ptrToInt(path)); | ||
| 547 | } | ||
| 548 | |||
| 549 | 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)); | ||
| 551 | } | ||
| 552 | |||
| 553 | pub fn fork() usize { | ||
| 554 | return arch.syscall0(SYS_fork); | ||
| 555 | } | ||
| 556 | |||
| 557 | pub fn getcwd(buf: [*]u8, size: usize) usize { | ||
| 558 | return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size); | ||
| 559 | } | ||
| 560 | |||
| 561 | pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize { | ||
| 562 | return arch.syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); | ||
| 563 | } | ||
| 564 | |||
| 565 | pub fn isatty(fd: i32) bool { | ||
| 566 | var wsz: winsize = undefined; | ||
| 567 | return arch.syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | 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); | ||
| 572 | } | ||
| 573 | |||
| 574 | pub fn mkdir(path: [*]const u8, mode: u32) usize { | ||
| 575 | return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode); | ||
| 576 | } | ||
| 577 | |||
| 578 | pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize { | ||
| 579 | return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset)); | ||
| 580 | } | ||
| 581 | |||
| 582 | pub fn munmap(address: usize, length: usize) usize { | ||
| 583 | return arch.syscall2(SYS_munmap, address, length); | ||
| 584 | } | ||
| 585 | |||
| 586 | pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | ||
| 587 | return arch.syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); | ||
| 588 | } | ||
| 589 | |||
| 590 | pub fn rmdir(path: [*]const u8) usize { | ||
| 591 | return arch.syscall1(SYS_rmdir, @ptrToInt(path)); | ||
| 592 | } | ||
| 593 | |||
| 594 | pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { | ||
| 595 | return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new)); | ||
| 596 | } | ||
| 597 | |||
| 598 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize { | ||
| 599 | return arch.syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); | ||
| 600 | } | ||
| 601 | |||
| 602 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize { | ||
| 603 | return arch.syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); | ||
| 604 | } | ||
| 605 | |||
| 606 | pub fn pipe(fd: *[2]i32) usize { | ||
| 607 | return pipe2(fd, 0); | ||
| 608 | } | ||
| 609 | |||
| 610 | pub fn pipe2(fd: *[2]i32, flags: usize) usize { | ||
| 611 | return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags); | ||
| 612 | } | ||
| 613 | |||
| 614 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | ||
| 615 | return arch.syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); | ||
| 616 | } | ||
| 617 | |||
| 618 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { | ||
| 619 | return arch.syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); | ||
| 620 | } | ||
| 621 | |||
| 622 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize { | ||
| 623 | return arch.syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); | ||
| 624 | } | ||
| 625 | |||
| 626 | pub fn rename(old: [*]const u8, new: [*]const u8) usize { | ||
| 627 | return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new)); | ||
| 628 | } | ||
| 629 | |||
| 630 | pub fn open(path: [*]const u8, flags: u32, perm: usize) usize { | ||
| 631 | return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm); | ||
| 632 | } | ||
| 633 | |||
| 634 | pub fn create(path: [*]const u8, perm: usize) usize { | ||
| 635 | return arch.syscall2(SYS_creat, @ptrToInt(path), perm); | ||
| 636 | } | ||
| 637 | |||
| 638 | pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize { | ||
| 639 | return arch.syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode); | ||
| 640 | } | ||
| 641 | |||
| 642 | pub fn close(fd: i32) usize { | ||
| 643 | return arch.syscall1(SYS_close, @bitCast(usize, isize(fd))); | ||
| 644 | } | ||
| 645 | |||
| 646 | pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize { | ||
| 647 | return arch.syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos); | ||
| 648 | } | ||
| 649 | |||
| 650 | pub fn exit(status: i32) noreturn { | ||
| 651 | _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status))); | ||
| 652 | unreachable; | ||
| 653 | } | ||
| 654 | |||
| 655 | pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { | ||
| 656 | return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, usize(flags)); | ||
| 657 | } | ||
| 658 | |||
| 659 | pub fn kill(pid: i32, sig: i32) usize { | ||
| 660 | return arch.syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig))); | ||
| 661 | } | ||
| 662 | |||
| 663 | pub fn unlink(path: [*]const u8) usize { | ||
| 664 | return arch.syscall1(SYS_unlink, @ptrToInt(path)); | ||
| 665 | } | ||
| 666 | |||
| 667 | pub fn waitpid(pid: i32, status: *i32, options: i32) usize { | ||
| 668 | return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0); | ||
| 669 | } | ||
| 670 | |||
| 671 | pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { | ||
| 672 | return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); | ||
| 673 | } | ||
| 674 | |||
| 675 | pub fn setuid(uid: u32) usize { | ||
| 676 | return arch.syscall1(SYS_setuid, uid); | ||
| 677 | } | ||
| 678 | |||
| 679 | pub fn setgid(gid: u32) usize { | ||
| 680 | return arch.syscall1(SYS_setgid, gid); | ||
| 681 | } | ||
| 682 | |||
| 683 | pub fn setreuid(ruid: u32, euid: u32) usize { | ||
| 684 | return arch.syscall2(SYS_setreuid, ruid, euid); | ||
| 685 | } | ||
| 686 | |||
| 687 | pub fn setregid(rgid: u32, egid: u32) usize { | ||
| 688 | return arch.syscall2(SYS_setregid, rgid, egid); | ||
| 689 | } | ||
| 690 | |||
| 691 | const NSIG = 32; | ||
| 692 | |||
| 693 | pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize)); | ||
| 694 | pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); | ||
| 695 | pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); | ||
| 696 | |||
| 697 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | ||
| 698 | pub const Sigaction = extern struct { | ||
| 699 | /// signal handler | ||
| 700 | __sigaction_u: extern union { | ||
| 701 | __sa_handler: extern fn (i32) void, | ||
| 702 | __sa_sigaction: extern fn (i32, *__siginfo, usize) void, | ||
| 703 | }, | ||
| 704 | |||
| 705 | /// see signal options | ||
| 706 | sa_flags: u32, | ||
| 707 | |||
| 708 | /// signal mask to apply | ||
| 709 | sa_mask: sigset_t, | ||
| 710 | }; | ||
| 711 | |||
| 712 | pub const _SIG_WORDS = 4; | ||
| 713 | pub const _SIG_MAXSIG = 128; | ||
| 714 | |||
| 715 | pub inline fn _SIG_IDX(sig: usize) usize { | ||
| 716 | return sig - 1; | ||
| 717 | } | ||
| 718 | pub inline fn _SIG_WORD(sig: usize) usize { | ||
| 719 | return_SIG_IDX(sig) >> 5; | ||
| 720 | } | ||
| 721 | pub inline fn _SIG_BIT(sig: usize) usize { | ||
| 722 | return 1 << (_SIG_IDX(sig) & 31); | ||
| 723 | } | ||
| 724 | pub inline fn _SIG_VALID(sig: usize) usize { | ||
| 725 | return sig <= _SIG_MAXSIG and sig > 0; | ||
| 726 | } | ||
| 727 | |||
| 728 | pub const sigset_t = extern struct { | ||
| 729 | __bits: [_SIG_WORDS]u32, | ||
| 730 | }; | ||
| 731 | |||
| 732 | pub fn raise(sig: i32) usize { | ||
| 733 | // TODO have a chat with the freebsd folks and make sure there's no bug in | ||
| 734 | // their libc. musl-libc blocks signals in between these calls because | ||
| 735 | // if a signal handler runs and forks between the gettid and sending the | ||
| 736 | // signal, the parent will get 2 signals, one from itself and one from the child | ||
| 737 | // if the protection does not belong here, then it belongs in abort(), | ||
| 738 | // like it does in freebsd's libc. | ||
| 739 | var id: usize = undefined; | ||
| 740 | const rc = arch.syscall1(SYS_thr_self, @ptrToInt(&id)); | ||
| 741 | if (getErrno(rc) != 0) return rc; | ||
| 742 | return arch.syscall2(SYS_thr_kill, id, @bitCast(usize, isize(sig))); | ||
| 743 | } | ||
| 744 | |||
| 745 | pub const Stat = arch.Stat; | ||
| 746 | pub const timespec = arch.timespec; | ||
| 747 | |||
| 748 | pub fn fstat(fd: i32, stat_buf: *Stat) usize { | ||
| 749 | return arch.syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); | ||
| 750 | } | ||
| 751 | |||
| 752 | pub const iovec = extern struct { | ||
| 753 | iov_base: [*]u8, | ||
| 754 | iov_len: usize, | ||
| 755 | }; | ||
| 756 | |||
| 757 | pub const iovec_const = extern struct { | ||
| 758 | iov_base: [*]const u8, | ||
| 759 | iov_len: usize, | ||
| 760 | }; | ||
| 761 | |||
| 762 | // TODO avoid libc dependency | ||
| 763 | pub fn kqueue() usize { | ||
| 764 | return errnoWrap(c.kqueue()); | ||
| 765 | } | ||
| 766 | |||
| 767 | // TODO avoid libc dependency | ||
| 768 | pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize { | ||
| 769 | return errnoWrap(c.kevent( | ||
| 770 | kq, | ||
| 771 | changelist.ptr, | ||
| 772 | @intCast(c_int, changelist.len), | ||
| 773 | eventlist.ptr, | ||
| 774 | @intCast(c_int, eventlist.len), | ||
| 775 | timeout, | ||
| 776 | )); | ||
| 777 | } | ||
| 778 | |||
| 779 | // TODO avoid libc dependency | ||
| 780 | pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { | ||
| 781 | return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen)); | ||
| 782 | } | ||
| 783 | |||
| 784 | // TODO avoid libc dependency | ||
| 785 | pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize { | ||
| 786 | return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen)); | ||
| 787 | } | ||
| 788 | |||
| 789 | // TODO avoid libc dependency | ||
| 790 | pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize { | ||
| 791 | return errnoWrap(c.sysctlnametomib(name, wibp, sizep)); | ||
| 792 | } | ||
| 793 | |||
| 794 | // TODO avoid libc dependency | ||
| 795 | |||
| 796 | /// Takes the return value from a syscall and formats it back in the way | ||
| 797 | /// that the kernel represents it to libc. Errno was a mistake, let's make | ||
| 798 | /// it go away forever. | ||
| 799 | fn errnoWrap(value: isize) usize { | ||
| 800 | return @bitCast(usize, if (value == -1) -isize(c._errno().*) else value); | ||
| 801 | } | ||
std/os/freebsd/syscall.zig created+493| ... | @@ -0,0 +1,493 @@ | ||
| 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 created+136| ... | @@ -0,0 +1,136 @@ | ||
| 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+1-1| ... | @@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD | ... | @@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD |
| 43 | }; | 43 | }; |
| 44 | return os.path.join(allocator, home_dir, "Library", "Application Support", appname); | 44 | return os.path.join(allocator, home_dir, "Library", "Application Support", appname); |
| 45 | }, | 45 | }, |
| 46 | builtin.Os.linux => { | 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; |
std/os/get_user_id.zig+1-1| ... | @@ -11,7 +11,7 @@ pub const UserInfo = struct { | ... | @@ -11,7 +11,7 @@ pub const UserInfo = struct { |
| 11 | /// POSIX function which gets a uid from username. | 11 | /// POSIX function which gets a uid from username. |
| 12 | pub fn getUserInfo(name: []const u8) !UserInfo { | 12 | pub fn getUserInfo(name: []const u8) !UserInfo { |
| 13 | return switch (builtin.os) { | 13 | return switch (builtin.os) { |
| 14 | Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name), | 14 | Os.linux, Os.macosx, Os.ios, Os.freebsd => posixGetUserInfo(name), |
| 15 | else => @compileError("Unsupported OS"), | 15 | else => @compileError("Unsupported OS"), |
| 16 | }; | 16 | }; |
| 17 | } | 17 | } |
std/os/index.zig+67-28| ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const Os = builtin.Os; | 3 | const Os = builtin.Os; |
| 4 | const is_windows = builtin.os == Os.windows; | 4 | const is_windows = builtin.os == Os.windows; |
| 5 | const is_posix = switch (builtin.os) { | 5 | const is_posix = switch (builtin.os) { |
| 6 | builtin.Os.linux, builtin.Os.macosx => true, | 6 | builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => true, |
| 7 | else => false, | 7 | else => false, |
| 8 | }; | 8 | }; |
| 9 | const os = @This(); | 9 | const os = @This(); |
| ... | @@ -24,10 +24,12 @@ test "std.os" { | ... | @@ -24,10 +24,12 @@ test "std.os" { |
| 24 | pub const windows = @import("windows/index.zig"); | 24 | pub const windows = @import("windows/index.zig"); |
| 25 | pub const darwin = @import("darwin.zig"); | 25 | pub const darwin = @import("darwin.zig"); |
| 26 | pub const linux = @import("linux/index.zig"); | 26 | pub const linux = @import("linux/index.zig"); |
| 27 | pub const freebsd = @import("freebsd/index.zig"); | ||
| 27 | pub const zen = @import("zen.zig"); | 28 | pub const zen = @import("zen.zig"); |
| 28 | pub const posix = switch (builtin.os) { | 29 | pub const posix = switch (builtin.os) { |
| 29 | Os.linux => linux, | 30 | Os.linux => linux, |
| 30 | Os.macosx, Os.ios => darwin, | 31 | Os.macosx, Os.ios => darwin, |
| 32 | Os.freebsd => freebsd, | ||
| 31 | Os.zen => zen, | 33 | Os.zen => zen, |
| 32 | else => @compileError("Unsupported OS"), | 34 | else => @compileError("Unsupported OS"), |
| 33 | }; | 35 | }; |
| ... | @@ -40,7 +42,7 @@ pub const time = @import("time.zig"); | ... | @@ -40,7 +42,7 @@ pub const time = @import("time.zig"); |
| 40 | 42 | ||
| 41 | pub const page_size = 4 * 1024; | 43 | pub const page_size = 4 * 1024; |
| 42 | pub const MAX_PATH_BYTES = switch (builtin.os) { | 44 | pub const MAX_PATH_BYTES = switch (builtin.os) { |
| 43 | Os.linux, Os.macosx, Os.ios => posix.PATH_MAX, | 45 | Os.linux, Os.macosx, Os.ios, Os.freebsd => posix.PATH_MAX, |
| 44 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. | 46 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| 45 | // If it would require 4 UTF-8 bytes, then there would be a surrogate | 47 | // If it would require 4 UTF-8 bytes, then there would be a surrogate |
| 46 | // pair in the UTF-16LE, and we (over)account 3 bytes for it that way. | 48 | // pair in the UTF-16LE, and we (over)account 3 bytes for it that way. |
| ... | @@ -101,7 +103,7 @@ const math = std.math; | ... | @@ -101,7 +103,7 @@ const math = std.math; |
| 101 | /// library implementation. | 103 | /// library implementation. |
| 102 | pub fn getRandomBytes(buf: []u8) !void { | 104 | pub fn getRandomBytes(buf: []u8) !void { |
| 103 | switch (builtin.os) { | 105 | switch (builtin.os) { |
| 104 | Os.linux => while (true) { | 106 | Os.linux, Os.freebsd => while (true) { |
| 105 | // TODO check libc version and potentially call c.getrandom. | 107 | // TODO check libc version and potentially call c.getrandom. |
| 106 | // See #397 | 108 | // See #397 |
| 107 | const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0)); | 109 | const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0)); |
| ... | @@ -174,7 +176,7 @@ pub fn abort() noreturn { | ... | @@ -174,7 +176,7 @@ pub fn abort() noreturn { |
| 174 | c.abort(); | 176 | c.abort(); |
| 175 | } | 177 | } |
| 176 | switch (builtin.os) { | 178 | switch (builtin.os) { |
| 177 | Os.linux, Os.macosx, Os.ios => { | 179 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 178 | _ = posix.raise(posix.SIGABRT); | 180 | _ = posix.raise(posix.SIGABRT); |
| 179 | _ = posix.raise(posix.SIGKILL); | 181 | _ = posix.raise(posix.SIGKILL); |
| 180 | while (true) {} | 182 | while (true) {} |
| ... | @@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn { | ... | @@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn { |
| 196 | c.exit(status); | 198 | c.exit(status); |
| 197 | } | 199 | } |
| 198 | switch (builtin.os) { | 200 | switch (builtin.os) { |
| 199 | Os.linux, Os.macosx, Os.ios => { | 201 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 200 | posix.exit(status); | 202 | posix.exit(status); |
| 201 | }, | 203 | }, |
| 202 | Os.windows => { | 204 | Os.windows => { |
| ... | @@ -419,7 +421,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off | ... | @@ -419,7 +421,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off |
| 419 | } | 421 | } |
| 420 | } | 422 | } |
| 421 | }, | 423 | }, |
| 422 | builtin.Os.linux => while (true) { | 424 | builtin.Os.linux, builtin.Os.freebsd => while (true) { |
| 423 | const rc = posix.pwritev(fd, iov, count, offset); | 425 | const rc = posix.pwritev(fd, iov, count, offset); |
| 424 | const err = posix.getErrno(rc); | 426 | const err = posix.getErrno(rc); |
| 425 | switch (err) { | 427 | switch (err) { |
| ... | @@ -457,6 +459,7 @@ pub const PosixOpenError = error{ | ... | @@ -457,6 +459,7 @@ pub const PosixOpenError = error{ |
| 457 | NoSpaceLeft, | 459 | NoSpaceLeft, |
| 458 | NotDir, | 460 | NotDir, |
| 459 | PathAlreadyExists, | 461 | PathAlreadyExists, |
| 462 | DeviceBusy, | ||
| 460 | 463 | ||
| 461 | /// See https://github.com/ziglang/zig/issues/1396 | 464 | /// See https://github.com/ziglang/zig/issues/1396 |
| 462 | Unexpected, | 465 | Unexpected, |
| ... | @@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { | ... | @@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { |
| 495 | posix.ENOTDIR => return PosixOpenError.NotDir, | 498 | posix.ENOTDIR => return PosixOpenError.NotDir, |
| 496 | posix.EPERM => return PosixOpenError.AccessDenied, | 499 | posix.EPERM => return PosixOpenError.AccessDenied, |
| 497 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, | 500 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, |
| 501 | posix.EBUSY => return PosixOpenError.DeviceBusy, | ||
| 498 | else => return unexpectedErrorPosix(err), | 502 | else => return unexpectedErrorPosix(err), |
| 499 | } | 503 | } |
| 500 | } | 504 | } |
| ... | @@ -687,7 +691,7 @@ pub fn getBaseAddress() usize { | ... | @@ -687,7 +691,7 @@ pub fn getBaseAddress() usize { |
| 687 | }; | 691 | }; |
| 688 | return phdr - @sizeOf(ElfHeader); | 692 | return phdr - @sizeOf(ElfHeader); |
| 689 | }, | 693 | }, |
| 690 | builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header), | 694 | builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header), |
| 691 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), | 695 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), |
| 692 | else => @compileError("Unsupported OS"), | 696 | else => @compileError("Unsupported OS"), |
| 693 | } | 697 | } |
| ... | @@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 700 | errdefer result.deinit(); | 704 | errdefer result.deinit(); |
| 701 | 705 | ||
| 702 | if (is_windows) { | 706 | if (is_windows) { |
| 703 | const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory; | 707 | const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory; |
| 704 | defer assert(windows.FreeEnvironmentStringsA(ptr) != 0); | 708 | defer assert(windows.FreeEnvironmentStringsW(ptr) != 0); |
| 705 | 709 | ||
| 706 | var i: usize = 0; | 710 | var i: usize = 0; |
| 707 | while (true) { | 711 | while (true) { |
| ... | @@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 710 | const key_start = i; | 714 | const key_start = i; |
| 711 | 715 | ||
| 712 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} | 716 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| 713 | const key = ptr[key_start..i]; | 717 | const key_w = ptr[key_start..i]; |
| 718 | const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w); | ||
| 719 | errdefer allocator.free(key); | ||
| 714 | 720 | ||
| 715 | if (ptr[i] == '=') i += 1; | 721 | if (ptr[i] == '=') i += 1; |
| 716 | 722 | ||
| 717 | const value_start = i; | 723 | const value_start = i; |
| 718 | while (ptr[i] != 0) : (i += 1) {} | 724 | while (ptr[i] != 0) : (i += 1) {} |
| 719 | const value = ptr[value_start..i]; | 725 | const value_w = ptr[value_start..i]; |
| 726 | const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w); | ||
| 727 | errdefer allocator.free(value); | ||
| 720 | 728 | ||
| 721 | i += 1; // skip over null byte | 729 | i += 1; // skip over null byte |
| 722 | 730 | ||
| 723 | try result.set(key, value); | 731 | try result.setMove(key, value); |
| 724 | } | 732 | } |
| 725 | } else { | 733 | } else { |
| 726 | for (posix_environ_raw) |ptr| { | 734 | for (posix_environ_raw) |ptr| { |
| ... | @@ -738,6 +746,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -738,6 +746,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 738 | } | 746 | } |
| 739 | } | 747 | } |
| 740 | 748 | ||
| 749 | test "os.getEnvMap" { | ||
| 750 | var env = try getEnvMap(std.debug.global_allocator); | ||
| 751 | defer env.deinit(); | ||
| 752 | } | ||
| 753 | |||
| 741 | /// TODO make this go through libc when we have it | 754 | /// TODO make this go through libc when we have it |
| 742 | pub fn getEnvPosix(key: []const u8) ?[]const u8 { | 755 | pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 743 | for (posix_environ_raw) |ptr| { | 756 | for (posix_environ_raw) |ptr| { |
| ... | @@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { | ... | @@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 758 | pub const GetEnvVarOwnedError = error{ | 771 | pub const GetEnvVarOwnedError = error{ |
| 759 | OutOfMemory, | 772 | OutOfMemory, |
| 760 | EnvironmentVariableNotFound, | 773 | EnvironmentVariableNotFound, |
| 774 | |||
| 775 | /// See https://github.com/ziglang/zig/issues/1774 | ||
| 776 | InvalidUtf8, | ||
| 761 | }; | 777 | }; |
| 762 | 778 | ||
| 763 | /// Caller must free returned memory. | 779 | /// Caller must free returned memory. |
| 764 | /// TODO make this go through libc when we have it | 780 | /// TODO make this go through libc when we have it |
| 765 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { | 781 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 766 | if (is_windows) { | 782 | if (is_windows) { |
| 767 | const key_with_null = try cstr.addNullByte(allocator, key); | 783 | const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); |
| 768 | defer allocator.free(key_with_null); | 784 | defer allocator.free(key_with_null); |
| 769 | 785 | ||
| 770 | var buf = try allocator.alloc(u8, 256); | 786 | var buf = try allocator.alloc(u16, 256); |
| 771 | errdefer allocator.free(buf); | 787 | defer allocator.free(buf); |
| 772 | 788 | ||
| 773 | while (true) { | 789 | while (true) { |
| 774 | const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory; | 790 | const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory; |
| 775 | const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len); | 791 | const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len); |
| 776 | 792 | ||
| 777 | if (result == 0) { | 793 | if (result == 0) { |
| 778 | const err = windows.GetLastError(); | 794 | const err = windows.GetLastError(); |
| ... | @@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned | ... | @@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned |
| 786 | } | 802 | } |
| 787 | 803 | ||
| 788 | if (result > buf.len) { | 804 | if (result > buf.len) { |
| 789 | buf = try allocator.realloc(u8, buf, result); | 805 | buf = try allocator.realloc(u16, buf, result); |
| 790 | continue; | 806 | continue; |
| 791 | } | 807 | } |
| 792 | 808 | ||
| 793 | return allocator.shrink(u8, buf, result); | 809 | return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) { |
| 810 | error.DanglingSurrogateHalf => return error.InvalidUtf8, | ||
| 811 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, | ||
| 812 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, | ||
| 813 | error.OutOfMemory => return error.OutOfMemory, | ||
| 814 | }; | ||
| 794 | } | 815 | } |
| 795 | } else { | 816 | } else { |
| 796 | const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound; | 817 | const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound; |
| ... | @@ -798,6 +819,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned | ... | @@ -798,6 +819,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned |
| 798 | } | 819 | } |
| 799 | } | 820 | } |
| 800 | 821 | ||
| 822 | test "os.getEnvVarOwned" { | ||
| 823 | var ga = debug.global_allocator; | ||
| 824 | debug.assertError(getEnvVarOwned(ga, "BADENV"), error.EnvironmentVariableNotFound); | ||
| 825 | } | ||
| 826 | |||
| 801 | /// Caller must free the returned memory. | 827 | /// Caller must free the returned memory. |
| 802 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { | 828 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { |
| 803 | var buf: [MAX_PATH_BYTES]u8 = undefined; | 829 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| ... | @@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void { | ... | @@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void { |
| 1305 | const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path); | 1331 | const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path); |
| 1306 | return deleteDirW(&dir_path_w); | 1332 | return deleteDirW(&dir_path_w); |
| 1307 | }, | 1333 | }, |
| 1308 | Os.linux, Os.macosx, Os.ios => { | 1334 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 1309 | const err = posix.getErrno(posix.rmdir(dir_path)); | 1335 | const err = posix.getErrno(posix.rmdir(dir_path)); |
| 1310 | switch (err) { | 1336 | switch (err) { |
| 1311 | 0 => return, | 1337 | 0 => return, |
| ... | @@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void { | ... | @@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void { |
| 1348 | const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path); | 1374 | const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path); |
| 1349 | return deleteDirW(&dir_path_w); | 1375 | return deleteDirW(&dir_path_w); |
| 1350 | }, | 1376 | }, |
| 1351 | Os.linux, Os.macosx, Os.ios => { | 1377 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { |
| 1352 | const dir_path_c = try toPosixPath(dir_path); | 1378 | const dir_path_c = try toPosixPath(dir_path); |
| 1353 | return deleteDirC(&dir_path_c); | 1379 | return deleteDirC(&dir_path_c); |
| 1354 | }, | 1380 | }, |
| ... | @@ -1378,6 +1404,7 @@ const DeleteTreeError = error{ | ... | @@ -1378,6 +1404,7 @@ const DeleteTreeError = error{ |
| 1378 | FileSystem, | 1404 | FileSystem, |
| 1379 | FileBusy, | 1405 | FileBusy, |
| 1380 | DirNotEmpty, | 1406 | DirNotEmpty, |
| 1407 | DeviceBusy, | ||
| 1381 | 1408 | ||
| 1382 | /// On Windows, file paths must be valid Unicode. | 1409 | /// On Windows, file paths must be valid Unicode. |
| 1383 | InvalidUtf8, | 1410 | InvalidUtf8, |
| ... | @@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 1439 | error.Unexpected, | 1466 | error.Unexpected, |
| 1440 | error.InvalidUtf8, | 1467 | error.InvalidUtf8, |
| 1441 | error.BadPathName, | 1468 | error.BadPathName, |
| 1469 | error.DeviceBusy, | ||
| 1442 | => return err, | 1470 | => return err, |
| 1443 | }; | 1471 | }; |
| 1444 | defer dir.close(); | 1472 | defer dir.close(); |
| ... | @@ -1465,7 +1493,7 @@ pub const Dir = struct { | ... | @@ -1465,7 +1493,7 @@ pub const Dir = struct { |
| 1465 | allocator: *Allocator, | 1493 | allocator: *Allocator, |
| 1466 | 1494 | ||
| 1467 | pub const Handle = switch (builtin.os) { | 1495 | pub const Handle = switch (builtin.os) { |
| 1468 | Os.macosx, Os.ios => struct { | 1496 | Os.macosx, Os.ios, Os.freebsd => struct { |
| 1469 | fd: i32, | 1497 | fd: i32, |
| 1470 | seek: i64, | 1498 | seek: i64, |
| 1471 | buf: []u8, | 1499 | buf: []u8, |
| ... | @@ -1521,6 +1549,7 @@ pub const Dir = struct { | ... | @@ -1521,6 +1549,7 @@ pub const Dir = struct { |
| 1521 | OutOfMemory, | 1549 | OutOfMemory, |
| 1522 | InvalidUtf8, | 1550 | InvalidUtf8, |
| 1523 | BadPathName, | 1551 | BadPathName, |
| 1552 | DeviceBusy, | ||
| 1524 | 1553 | ||
| 1525 | /// See https://github.com/ziglang/zig/issues/1396 | 1554 | /// See https://github.com/ziglang/zig/issues/1396 |
| 1526 | Unexpected, | 1555 | Unexpected, |
| ... | @@ -1541,7 +1570,7 @@ pub const Dir = struct { | ... | @@ -1541,7 +1570,7 @@ pub const Dir = struct { |
| 1541 | .name_data = undefined, | 1570 | .name_data = undefined, |
| 1542 | }; | 1571 | }; |
| 1543 | }, | 1572 | }, |
| 1544 | Os.macosx, Os.ios => Handle{ | 1573 | Os.macosx, Os.ios, Os.freebsd => Handle{ |
| 1545 | .fd = try posixOpen( | 1574 | .fd = try posixOpen( |
| 1546 | dir_path, | 1575 | dir_path, |
| 1547 | posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC, | 1576 | posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC, |
| ... | @@ -1572,7 +1601,7 @@ pub const Dir = struct { | ... | @@ -1572,7 +1601,7 @@ pub const Dir = struct { |
| 1572 | Os.windows => { | 1601 | Os.windows => { |
| 1573 | _ = windows.FindClose(self.handle.handle); | 1602 | _ = windows.FindClose(self.handle.handle); |
| 1574 | }, | 1603 | }, |
| 1575 | Os.macosx, Os.ios, Os.linux => { | 1604 | Os.macosx, Os.ios, Os.linux, Os.freebsd => { |
| 1576 | self.allocator.free(self.handle.buf); | 1605 | self.allocator.free(self.handle.buf); |
| 1577 | os.close(self.handle.fd); | 1606 | os.close(self.handle.fd); |
| 1578 | }, | 1607 | }, |
| ... | @@ -1587,6 +1616,7 @@ pub const Dir = struct { | ... | @@ -1587,6 +1616,7 @@ pub const Dir = struct { |
| 1587 | Os.linux => return self.nextLinux(), | 1616 | Os.linux => return self.nextLinux(), |
| 1588 | Os.macosx, Os.ios => return self.nextDarwin(), | 1617 | Os.macosx, Os.ios => return self.nextDarwin(), |
| 1589 | Os.windows => return self.nextWindows(), | 1618 | Os.windows => return self.nextWindows(), |
| 1619 | Os.freebsd => return self.nextFreebsd(), | ||
| 1590 | else => @compileError("unimplemented"), | 1620 | else => @compileError("unimplemented"), |
| 1591 | } | 1621 | } |
| 1592 | } | 1622 | } |
| ... | @@ -1726,6 +1756,11 @@ pub const Dir = struct { | ... | @@ -1726,6 +1756,11 @@ pub const Dir = struct { |
| 1726 | }; | 1756 | }; |
| 1727 | } | 1757 | } |
| 1728 | } | 1758 | } |
| 1759 | |||
| 1760 | fn nextFreebsd(self: *Dir) !?Entry { | ||
| 1761 | //self.handle.buf = try self.allocator.alloc(u8, page_size); | ||
| 1762 | @compileError("TODO implement dirs for FreeBSD"); | ||
| 1763 | } | ||
| 1729 | }; | 1764 | }; |
| 1730 | 1765 | ||
| 1731 | pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void { | 1766 | pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void { |
| ... | @@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { | ... | @@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { |
| 2164 | pub fn openSelfExe() !os.File { | 2199 | pub fn openSelfExe() !os.File { |
| 2165 | switch (builtin.os) { | 2200 | switch (builtin.os) { |
| 2166 | Os.linux => return os.File.openReadC(c"/proc/self/exe"), | 2201 | Os.linux => return os.File.openReadC(c"/proc/self/exe"), |
| 2167 | Os.macosx, Os.ios => { | 2202 | Os.macosx, Os.ios, Os.freebsd => { |
| 2168 | var buf: [MAX_PATH_BYTES]u8 = undefined; | 2203 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| 2169 | const self_exe_path = try selfExePath(&buf); | 2204 | const self_exe_path = try selfExePath(&buf); |
| 2170 | buf[self_exe_path.len] = 0; | 2205 | buf[self_exe_path.len] = 0; |
| ... | @@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File { | ... | @@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File { |
| 2181 | 2216 | ||
| 2182 | test "openSelfExe" { | 2217 | test "openSelfExe" { |
| 2183 | switch (builtin.os) { | 2218 | switch (builtin.os) { |
| 2184 | Os.linux, Os.macosx, Os.ios, Os.windows => (try openSelfExe()).close(), | 2219 | Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(), |
| 2185 | else => return error.SkipZigTest, // Unsupported OS. | 2220 | else => return error.SkipZigTest, // Unsupported OS. |
| 2186 | } | 2221 | } |
| 2187 | } | 2222 | } |
| ... | @@ -2212,6 +2247,7 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 { | ... | @@ -2212,6 +2247,7 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 { |
| 2212 | pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 { | 2247 | pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 { |
| 2213 | switch (builtin.os) { | 2248 | switch (builtin.os) { |
| 2214 | Os.linux => return readLink(out_buffer, "/proc/self/exe"), | 2249 | Os.linux => return readLink(out_buffer, "/proc/self/exe"), |
| 2250 | Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"), | ||
| 2215 | Os.windows => { | 2251 | Os.windows => { |
| 2216 | var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined; | 2252 | var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined; |
| 2217 | const utf16le_slice = try selfExePathW(&utf16le_buf); | 2253 | const utf16le_slice = try selfExePathW(&utf16le_buf); |
| ... | @@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 { | ... | @@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 { |
| 2250 | // will not return null. | 2286 | // will not return null. |
| 2251 | return path.dirname(full_exe_path).?; | 2287 | return path.dirname(full_exe_path).?; |
| 2252 | }, | 2288 | }, |
| 2253 | Os.windows, Os.macosx, Os.ios => { | 2289 | Os.windows, Os.macosx, Os.ios, Os.freebsd => { |
| 2254 | const self_exe_path = try selfExePath(out_buffer); | 2290 | const self_exe_path = try selfExePath(out_buffer); |
| 2255 | // Assume that the OS APIs return absolute paths, and therefore dirname | 2291 | // Assume that the OS APIs return absolute paths, and therefore dirname |
| 2256 | // will not return null. | 2292 | // will not return null. |
| ... | @@ -3095,10 +3131,13 @@ pub const CpuCountError = error{ | ... | @@ -3095,10 +3131,13 @@ pub const CpuCountError = error{ |
| 3095 | 3131 | ||
| 3096 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { | 3132 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { |
| 3097 | switch (builtin.os) { | 3133 | switch (builtin.os) { |
| 3098 | builtin.Os.macosx => { | 3134 | builtin.Os.macosx, builtin.Os.freebsd => { |
| 3099 | var count: c_int = undefined; | 3135 | var count: c_int = undefined; |
| 3100 | var count_len: usize = @sizeOf(c_int); | 3136 | var count_len: usize = @sizeOf(c_int); |
| 3101 | const rc = posix.sysctlbyname(c"hw.logicalcpu", @ptrCast(*c_void, &count), &count_len, null, 0); | 3137 | const rc = posix.sysctlbyname(switch (builtin.os) { |
| 3138 | builtin.Os.macosx => c"hw.logicalcpu", | ||
| 3139 | else => c"hw.ncpu", | ||
| 3140 | }, @ptrCast(*c_void, &count), &count_len, null, 0); | ||
| 3102 | const err = posix.getErrno(rc); | 3141 | const err = posix.getErrno(rc); |
| 3103 | switch (err) { | 3142 | switch (err) { |
| 3104 | 0 => return @intCast(usize, count), | 3143 | 0 => return @intCast(usize, count), |
std/os/linux/index.zig+56-47| ... | @@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize { | ... | @@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize { |
| 703 | } | 703 | } |
| 704 | 704 | ||
| 705 | pub fn dup3(old: i32, new: i32, flags: u32) usize { | 705 | pub fn dup3(old: i32, new: i32, flags: u32) usize { |
| 706 | return syscall3(SYS_dup3, @intCast(usize, old), @intCast(usize, new), flags); | 706 | return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags); |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | // TODO https://github.com/ziglang/zig/issues/265 | 709 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize { | ... | @@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize { |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize { | 749 | pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize { |
| 750 | return syscall3(SYS_getdents64, @intCast(usize, fd), @ptrToInt(dirp), count); | 750 | return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); |
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | pub fn inotify_init1(flags: u32) usize { | 753 | pub fn inotify_init1(flags: u32) usize { |
| ... | @@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize { | ... | @@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize { |
| 755 | } | 755 | } |
| 756 | 756 | ||
| 757 | pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize { | 757 | pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize { |
| 758 | return syscall3(SYS_inotify_add_watch, @intCast(usize, fd), @ptrToInt(pathname), mask); | 758 | return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask); |
| 759 | } | 759 | } |
| 760 | 760 | ||
| 761 | pub fn inotify_rm_watch(fd: i32, wd: i32) usize { | 761 | pub fn inotify_rm_watch(fd: i32, wd: i32) usize { |
| 762 | return syscall2(SYS_inotify_rm_watch, @intCast(usize, fd), @intCast(usize, wd)); | 762 | return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd))); |
| 763 | } | 763 | } |
| 764 | 764 | ||
| 765 | pub fn isatty(fd: i32) bool { | 765 | pub fn isatty(fd: i32) bool { |
| 766 | var wsz: winsize = undefined; | 766 | var wsz: winsize = undefined; |
| 767 | return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; | 767 | return syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; |
| 768 | } | 768 | } |
| 769 | 769 | ||
| 770 | // TODO https://github.com/ziglang/zig/issues/265 | 770 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz | ... | @@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz |
| 774 | 774 | ||
| 775 | // TODO https://github.com/ziglang/zig/issues/265 | 775 | // TODO https://github.com/ziglang/zig/issues/265 |
| 776 | pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { | 776 | pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { |
| 777 | return syscall4(SYS_readlinkat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); | 777 | return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); |
| 778 | } | 778 | } |
| 779 | 779 | ||
| 780 | // TODO https://github.com/ziglang/zig/issues/265 | 780 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize { | ... | @@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize { |
| 784 | 784 | ||
| 785 | // TODO https://github.com/ziglang/zig/issues/265 | 785 | // TODO https://github.com/ziglang/zig/issues/265 |
| 786 | pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize { | 786 | pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize { |
| 787 | return syscall3(SYS_mkdirat, @intCast(usize, dirfd), @ptrToInt(path), mode); | 787 | return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); |
| 788 | } | 788 | } |
| 789 | 789 | ||
| 790 | // TODO https://github.com/ziglang/zig/issues/265 | 790 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize { | ... | @@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize { |
| 803 | } | 803 | } |
| 804 | 804 | ||
| 805 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { | 805 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { |
| 806 | return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset)); | 806 | return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset)); |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | pub fn munmap(address: usize, length: usize) usize { | 809 | pub fn munmap(address: usize, length: usize) usize { |
| ... | @@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize { | ... | @@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize { |
| 811 | } | 811 | } |
| 812 | 812 | ||
| 813 | pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | 813 | pub fn read(fd: i32, buf: [*]u8, count: usize) usize { |
| 814 | return syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count); | 814 | return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { | 817 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { |
| 818 | return syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset); | 818 | return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); |
| 819 | } | 819 | } |
| 820 | 820 | ||
| 821 | pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { | 821 | pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { |
| 822 | return syscall3(SYS_readv, @intCast(usize, fd), @ptrToInt(iov), count); | 822 | return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); |
| 823 | } | 823 | } |
| 824 | 824 | ||
| 825 | pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { | 825 | pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { |
| 826 | return syscall3(SYS_writev, @intCast(usize, fd), @ptrToInt(iov), count); | 826 | return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); |
| 827 | } | 827 | } |
| 828 | 828 | ||
| 829 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { | 829 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { |
| 830 | return syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset); | 830 | return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); |
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | // TODO https://github.com/ziglang/zig/issues/265 | 833 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { | ... | @@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { |
| 842 | 842 | ||
| 843 | // TODO https://github.com/ziglang/zig/issues/265 | 843 | // TODO https://github.com/ziglang/zig/issues/265 |
| 844 | pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize { | 844 | pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize { |
| 845 | return syscall3(SYS_symlinkat, @ptrToInt(existing), @intCast(usize, newfd), @ptrToInt(newpath)); | 845 | return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath)); |
| 846 | } | 846 | } |
| 847 | 847 | ||
| 848 | // TODO https://github.com/ziglang/zig/issues/265 | 848 | // TODO https://github.com/ziglang/zig/issues/265 |
| 849 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize { | 849 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize { |
| 850 | return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset); | 850 | return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); |
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | // TODO https://github.com/ziglang/zig/issues/265 | 853 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize { | ... | @@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize { |
| 856 | } | 856 | } |
| 857 | 857 | ||
| 858 | pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize { | 858 | pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize { |
| 859 | return syscall3(SYS_faccessat, @intCast(usize, dirfd), @ptrToInt(path), mode); | 859 | return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); |
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | pub fn pipe(fd: *[2]i32) usize { | 862 | pub fn pipe(fd: *[2]i32) usize { |
| ... | @@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize { | ... | @@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize { |
| 868 | } | 868 | } |
| 869 | 869 | ||
| 870 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | 870 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 871 | return syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count); | 871 | return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); |
| 872 | } | 872 | } |
| 873 | 873 | ||
| 874 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { | 874 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { |
| 875 | return syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset); | 875 | return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); |
| 876 | } | 876 | } |
| 877 | 877 | ||
| 878 | // TODO https://github.com/ziglang/zig/issues/265 | 878 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize { | ... | @@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize { |
| 882 | 882 | ||
| 883 | // TODO https://github.com/ziglang/zig/issues/265 | 883 | // TODO https://github.com/ziglang/zig/issues/265 |
| 884 | pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize { | 884 | pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize { |
| 885 | return syscall5(SYS_renameat2, @intCast(usize, oldfd), @ptrToInt(oldpath), @intCast(usize, newfd), @ptrToInt(newpath), flags); | 885 | return syscall5(SYS_renameat2, @bitCast(usize, isize(oldfd)), @ptrToInt(oldpath), @bitCast(usize, isize(newfd)), @ptrToInt(newpath), flags); |
| 886 | } | 886 | } |
| 887 | 887 | ||
| 888 | // TODO https://github.com/ziglang/zig/issues/265 | 888 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize { | ... | @@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize { |
| 897 | 897 | ||
| 898 | // TODO https://github.com/ziglang/zig/issues/265 | 898 | // TODO https://github.com/ziglang/zig/issues/265 |
| 899 | pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize { | 899 | pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize { |
| 900 | return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode); | 900 | // dirfd could be negative, for example AT_FDCWD is -100 |
| 901 | return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode); | ||
| 901 | } | 902 | } |
| 902 | 903 | ||
| 903 | /// See also `clone` (from the arch-specific include) | 904 | /// See also `clone` (from the arch-specific include) |
| ... | @@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize { | ... | @@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize { |
| 911 | } | 912 | } |
| 912 | 913 | ||
| 913 | pub fn close(fd: i32) usize { | 914 | pub fn close(fd: i32) usize { |
| 914 | return syscall1(SYS_close, @intCast(usize, fd)); | 915 | return syscall1(SYS_close, @bitCast(usize, isize(fd))); |
| 915 | } | 916 | } |
| 916 | 917 | ||
| 917 | pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize { | 918 | pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize { |
| 918 | return syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos); | 919 | return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos); |
| 919 | } | 920 | } |
| 920 | 921 | ||
| 921 | pub fn exit(status: i32) noreturn { | 922 | pub fn exit(status: i32) noreturn { |
| ... | @@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { | ... | @@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { |
| 933 | } | 934 | } |
| 934 | 935 | ||
| 935 | pub fn kill(pid: i32, sig: i32) usize { | 936 | pub fn kill(pid: i32, sig: i32) usize { |
| 936 | return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @intCast(usize, sig)); | 937 | return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig))); |
| 937 | } | 938 | } |
| 938 | 939 | ||
| 939 | // TODO https://github.com/ziglang/zig/issues/265 | 940 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize { | ... | @@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize { |
| 943 | 944 | ||
| 944 | // TODO https://github.com/ziglang/zig/issues/265 | 945 | // TODO https://github.com/ziglang/zig/issues/265 |
| 945 | pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize { | 946 | pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize { |
| 946 | return syscall3(SYS_unlinkat, @intCast(usize, dirfd), @ptrToInt(path), flags); | 947 | return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags); |
| 947 | } | 948 | } |
| 948 | 949 | ||
| 949 | pub fn waitpid(pid: i32, status: *i32, options: i32) usize { | 950 | pub fn waitpid(pid: i32, status: *i32, options: i32) usize { |
| ... | @@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len; | ... | @@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len; |
| 1120 | pub fn raise(sig: i32) usize { | 1121 | pub fn raise(sig: i32) usize { |
| 1121 | var set: sigset_t = undefined; | 1122 | var set: sigset_t = undefined; |
| 1122 | blockAppSignals(&set); | 1123 | blockAppSignals(&set); |
| 1123 | const tid = @intCast(i32, syscall0(SYS_gettid)); | 1124 | const tid = syscall0(SYS_gettid); |
| 1124 | const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig)); | 1125 | const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig))); |
| 1125 | restoreSignals(&set); | 1126 | restoreSignals(&set); |
| 1126 | return ret; | 1127 | return ret; |
| 1127 | } | 1128 | } |
| ... | @@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct { | ... | @@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct { |
| 1189 | }; | 1190 | }; |
| 1190 | 1191 | ||
| 1191 | pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | 1192 | pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { |
| 1192 | return syscall3(SYS_getsockname, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len)); | 1193 | return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len)); |
| 1193 | } | 1194 | } |
| 1194 | 1195 | ||
| 1195 | pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | 1196 | pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { |
| 1196 | return syscall3(SYS_getpeername, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len)); | 1197 | return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len)); |
| 1197 | } | 1198 | } |
| 1198 | 1199 | ||
| 1199 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { | 1200 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { |
| ... | @@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { | ... | @@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { |
| 1201 | } | 1202 | } |
| 1202 | 1203 | ||
| 1203 | pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize { | 1204 | pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize { |
| 1204 | return syscall5(SYS_setsockopt, @intCast(usize, fd), level, optname, @intCast(usize, optval), @ptrToInt(optlen)); | 1205 | return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen)); |
| 1205 | } | 1206 | } |
| 1206 | 1207 | ||
| 1207 | pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize { | 1208 | pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize { |
| 1208 | return syscall5(SYS_getsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); | 1209 | return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); |
| 1209 | } | 1210 | } |
| 1210 | 1211 | ||
| 1211 | pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize { | 1212 | pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize { |
| 1212 | return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags); | 1213 | return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); |
| 1213 | } | 1214 | } |
| 1214 | 1215 | ||
| 1215 | pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { | 1216 | pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { |
| 1216 | return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len); | 1217 | return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len); |
| 1217 | } | 1218 | } |
| 1218 | 1219 | ||
| 1219 | pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { | 1220 | pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { |
| 1220 | return syscall3(SYS_recvmsg, @intCast(usize, fd), @ptrToInt(msg), flags); | 1221 | return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); |
| 1221 | } | 1222 | } |
| 1222 | 1223 | ||
| 1223 | pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize { | 1224 | pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize { |
| 1224 | return syscall6(SYS_recvfrom, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); | 1225 | return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); |
| 1225 | } | 1226 | } |
| 1226 | 1227 | ||
| 1227 | pub fn shutdown(fd: i32, how: i32) usize { | 1228 | pub fn shutdown(fd: i32, how: i32) usize { |
| 1228 | return syscall2(SYS_shutdown, @intCast(usize, fd), @intCast(usize, how)); | 1229 | return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how))); |
| 1229 | } | 1230 | } |
| 1230 | 1231 | ||
| 1231 | pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize { | 1232 | pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize { |
| 1232 | return syscall3(SYS_bind, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len)); | 1233 | return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len)); |
| 1233 | } | 1234 | } |
| 1234 | 1235 | ||
| 1235 | pub fn listen(fd: i32, backlog: u32) usize { | 1236 | pub fn listen(fd: i32, backlog: u32) usize { |
| 1236 | return syscall2(SYS_listen, @intCast(usize, fd), backlog); | 1237 | return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog); |
| 1237 | } | 1238 | } |
| 1238 | 1239 | ||
| 1239 | pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize { | 1240 | pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize { |
| 1240 | return syscall6(SYS_sendto, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen)); | 1241 | return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen)); |
| 1241 | } | 1242 | } |
| 1242 | 1243 | ||
| 1243 | pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize { | 1244 | pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize { |
| 1244 | return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(*fd[0])); | 1245 | return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0])); |
| 1245 | } | 1246 | } |
| 1246 | 1247 | ||
| 1247 | pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | 1248 | pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { |
| ... | @@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | ... | @@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { |
| 1249 | } | 1250 | } |
| 1250 | 1251 | ||
| 1251 | pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize { | 1252 | pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize { |
| 1252 | return syscall4(SYS_accept4, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len), flags); | 1253 | return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags); |
| 1253 | } | 1254 | } |
| 1254 | 1255 | ||
| 1255 | pub fn fstat(fd: i32, stat_buf: *Stat) usize { | 1256 | pub fn fstat(fd: i32, stat_buf: *Stat) usize { |
| 1256 | return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf)); | 1257 | return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); |
| 1257 | } | 1258 | } |
| 1258 | 1259 | ||
| 1259 | // TODO https://github.com/ziglang/zig/issues/265 | 1260 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize { | ... | @@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize { |
| 1268 | 1269 | ||
| 1269 | // TODO https://github.com/ziglang/zig/issues/265 | 1270 | // TODO https://github.com/ziglang/zig/issues/265 |
| 1270 | pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize { | 1271 | pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize { |
| 1271 | return syscall4(SYS_fstatat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(stat_buf), flags); | 1272 | return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); |
| 1272 | } | 1273 | } |
| 1273 | 1274 | ||
| 1274 | // TODO https://github.com/ziglang/zig/issues/265 | 1275 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | @@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize { | ... | @@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize { |
| 1355 | } | 1356 | } |
| 1356 | 1357 | ||
| 1357 | pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize { | 1358 | pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize { |
| 1358 | return syscall4(SYS_epoll_ctl, @intCast(usize, epoll_fd), @intCast(usize, op), @intCast(usize, fd), @ptrToInt(ev)); | 1359 | return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev)); |
| 1359 | } | 1360 | } |
| 1360 | 1361 | ||
| 1361 | pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize { | 1362 | pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize { |
| ... | @@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout | ... | @@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout |
| 1363 | } | 1364 | } |
| 1364 | 1365 | ||
| 1365 | pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize { | 1366 | pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize { |
| 1366 | return syscall6(SYS_epoll_pwait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout), @ptrToInt(sigmask), @sizeOf(sigset_t)); | 1367 | return syscall6( |
| 1368 | SYS_epoll_pwait, | ||
| 1369 | @bitCast(usize, isize(epoll_fd)), | ||
| 1370 | @ptrToInt(events), | ||
| 1371 | @intCast(usize, maxevents), | ||
| 1372 | @bitCast(usize, isize(timeout)), | ||
| 1373 | @ptrToInt(sigmask), | ||
| 1374 | @sizeOf(sigset_t), | ||
| 1375 | ); | ||
| 1367 | } | 1376 | } |
| 1368 | 1377 | ||
| 1369 | pub fn eventfd(count: u32, flags: u32) usize { | 1378 | pub fn eventfd(count: u32, flags: u32) usize { |
| ... | @@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize { | ... | @@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize { |
| 1371 | } | 1380 | } |
| 1372 | 1381 | ||
| 1373 | pub fn timerfd_create(clockid: i32, flags: u32) usize { | 1382 | pub fn timerfd_create(clockid: i32, flags: u32) usize { |
| 1374 | return syscall2(SYS_timerfd_create, @intCast(usize, clockid), flags); | 1383 | return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags); |
| 1375 | } | 1384 | } |
| 1376 | 1385 | ||
| 1377 | pub const itimerspec = extern struct { | 1386 | pub const itimerspec = extern struct { |
| ... | @@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct { | ... | @@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct { |
| 1380 | }; | 1389 | }; |
| 1381 | 1390 | ||
| 1382 | pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { | 1391 | pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { |
| 1383 | return syscall2(SYS_timerfd_gettime, @intCast(usize, fd), @ptrToInt(curr_value)); | 1392 | return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value)); |
| 1384 | } | 1393 | } |
| 1385 | 1394 | ||
| 1386 | pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize { | 1395 | pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize { |
| 1387 | return syscall4(SYS_timerfd_settime, @intCast(usize, fd), flags, @ptrToInt(new_value), @ptrToInt(old_value)); | 1396 | return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value)); |
| 1388 | } | 1397 | } |
| 1389 | 1398 | ||
| 1390 | pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330; | 1399 | pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330; |
std/os/path.zig+12-2| ... | @@ -1093,6 +1093,7 @@ pub const RealError = error{ | ... | @@ -1093,6 +1093,7 @@ pub const RealError = error{ |
| 1093 | NoSpaceLeft, | 1093 | NoSpaceLeft, |
| 1094 | FileSystem, | 1094 | FileSystem, |
| 1095 | BadPathName, | 1095 | BadPathName, |
| 1096 | DeviceBusy, | ||
| 1096 | 1097 | ||
| 1097 | /// On Windows, file paths must be valid Unicode. | 1098 | /// On Windows, file paths must be valid Unicode. |
| 1098 | InvalidUtf8, | 1099 | InvalidUtf8, |
| ... | @@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro | ... | @@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro |
| 1183 | const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0); | 1184 | const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0); |
| 1184 | defer os.close(fd); | 1185 | defer os.close(fd); |
| 1185 | 1186 | ||
| 1186 | var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined; | 1187 | var buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; |
| 1187 | const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable; | 1188 | const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable; |
| 1188 | 1189 | ||
| 1189 | return os.readLinkC(out_buffer, proc_path.ptr); | 1190 | return os.readLinkC(out_buffer, proc_path.ptr); |
| 1190 | }, | 1191 | }, |
| 1192 | Os.freebsd => { // XXX requires fdescfs | ||
| 1193 | const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0); | ||
| 1194 | defer os.close(fd); | ||
| 1195 | |||
| 1196 | var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined; | ||
| 1197 | const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable; | ||
| 1198 | |||
| 1199 | return os.readLinkC(out_buffer, proc_path.ptr); | ||
| 1200 | }, | ||
| 1191 | else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)), | 1201 | else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)), |
| 1192 | } | 1202 | } |
| 1193 | } | 1203 | } |
| ... | @@ -1202,7 +1212,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError! | ... | @@ -1202,7 +1212,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError! |
| 1202 | const pathname_w = try windows_util.sliceToPrefixedFileW(pathname); | 1212 | const pathname_w = try windows_util.sliceToPrefixedFileW(pathname); |
| 1203 | return realW(out_buffer, &pathname_w); | 1213 | return realW(out_buffer, &pathname_w); |
| 1204 | }, | 1214 | }, |
| 1205 | Os.macosx, Os.ios, Os.linux => { | 1215 | Os.macosx, Os.ios, Os.linux, Os.freebsd => { |
| 1206 | const pathname_c = try os.toPosixPath(pathname); | 1216 | const pathname_c = try os.toPosixPath(pathname); |
| 1207 | return realC(out_buffer, &pathname_c); | 1217 | return realC(out_buffer, &pathname_c); |
| 1208 | }, | 1218 | }, |
std/os/windows/kernel32.zig+3-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 |
std/os/zen.zig+11-11| ... | @@ -12,20 +12,20 @@ pub const Message = struct { | ... | @@ -12,20 +12,20 @@ pub const Message = struct { |
| 12 | args: [5]usize, | 12 | args: [5]usize, |
| 13 | payload: ?[]const u8, | 13 | payload: ?[]const u8, |
| 14 | 14 | ||
| 15 | pub fn from(mailbox_id: *const MailboxId) Message { | 15 | pub fn from(mailbox_id: MailboxId) Message { |
| 16 | return Message{ | 16 | return Message{ |
| 17 | .sender = MailboxId.Undefined, | 17 | .sender = MailboxId.Undefined, |
| 18 | .receiver = mailbox_id.*, | 18 | .receiver = mailbox_id, |
| 19 | .code = undefined, | 19 | .code = undefined, |
| 20 | .args = undefined, | 20 | .args = undefined, |
| 21 | .payload = null, | 21 | .payload = null, |
| 22 | }; | 22 | }; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | pub fn to(mailbox_id: *const MailboxId, msg_code: usize, args: ...) Message { | 25 | pub fn to(mailbox_id: MailboxId, msg_code: usize, args: ...) Message { |
| 26 | var message = Message{ | 26 | var message = Message{ |
| 27 | .sender = MailboxId.This, | 27 | .sender = MailboxId.This, |
| 28 | .receiver = mailbox_id.*, | 28 | .receiver = mailbox_id, |
| 29 | .code = msg_code, | 29 | .code = msg_code, |
| 30 | .args = undefined, | 30 | .args = undefined, |
| 31 | .payload = null, | 31 | .payload = null, |
| ... | @@ -40,14 +40,14 @@ pub const Message = struct { | ... | @@ -40,14 +40,14 @@ pub const Message = struct { |
| 40 | return message; | 40 | return message; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | pub fn as(self: *const Message, sender: *const MailboxId) Message { | 43 | pub fn as(self: Message, sender: MailboxId) Message { |
| 44 | var message = self.*; | 44 | var message = self; |
| 45 | message.sender = sender.*; | 45 | message.sender = sender; |
| 46 | return message; | 46 | return message; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | pub fn withPayload(self: *const Message, payload: []const u8) Message { | 49 | pub fn withPayload(self: Message, payload: []const u8) Message { |
| 50 | var message = self.*; | 50 | var message = self; |
| 51 | message.payload = payload; | 51 | message.payload = payload; |
| 52 | return message; | 52 | return message; |
| 53 | } | 53 | } |
| ... | @@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | ... | @@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { |
| 93 | STDIN_FILENO => { | 93 | STDIN_FILENO => { |
| 94 | var i: usize = 0; | 94 | var i: usize = 0; |
| 95 | while (i < count) : (i += 1) { | 95 | while (i < count) : (i += 1) { |
| 96 | send(Message.to(Server.Keyboard, 0)); | 96 | send(&Message.to(Server.Keyboard, 0)); |
| 97 | 97 | ||
| 98 | // FIXME: we should be certain that we are receiving from Keyboard. | 98 | // FIXME: we should be certain that we are receiving from Keyboard. |
| 99 | var message = Message.from(MailboxId.This); | 99 | var message = Message.from(MailboxId.This); |
| ... | @@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | ... | @@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { |
| 111 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | 111 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 112 | switch (fd) { | 112 | switch (fd) { |
| 113 | STDOUT_FILENO, STDERR_FILENO => { | 113 | STDOUT_FILENO, STDERR_FILENO => { |
| 114 | send(Message.to(Server.Terminal, 1).withPayload(buf[0..count])); | 114 | send(&Message.to(Server.Terminal, 1).withPayload(buf[0..count])); |
| 115 | }, | 115 | }, |
| 116 | else => unreachable, | 116 | else => unreachable, |
| 117 | } | 117 | } |
std/pdb.zig+4-3| ... | @@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct { | ... | @@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct { |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | pub const SectionContribEntry = packed struct { | 36 | pub const SectionContribEntry = packed struct { |
| 37 | /// COFF Section index, 1-based | ||
| 37 | Section: u16, | 38 | Section: u16, |
| 38 | Padding1: [2]u8, | 39 | Padding1: [2]u8, |
| 39 | Offset: u32, | 40 | Offset: u32, |
| ... | @@ -507,11 +508,11 @@ const Msf = struct { | ... | @@ -507,11 +508,11 @@ const Msf = struct { |
| 507 | allocator, | 508 | allocator, |
| 508 | ); | 509 | ); |
| 509 | 510 | ||
| 510 | const stream_count = try self.directory.stream.readIntLe(u32); | 511 | const stream_count = try self.directory.stream.readIntLittle(u32); |
| 511 | 512 | ||
| 512 | const stream_sizes = try allocator.alloc(u32, stream_count); | 513 | const stream_sizes = try allocator.alloc(u32, stream_count); |
| 513 | for (stream_sizes) |*s| { | 514 | for (stream_sizes) |*s| { |
| 514 | const size = try self.directory.stream.readIntLe(u32); | 515 | const size = try self.directory.stream.readIntLittle(u32); |
| 515 | s.* = blockCountFromSize(size, superblock.BlockSize); | 516 | s.* = blockCountFromSize(size, superblock.BlockSize); |
| 516 | } | 517 | } |
| 517 | 518 | ||
| ... | @@ -602,7 +603,7 @@ const MsfStream = struct { | ... | @@ -602,7 +603,7 @@ const MsfStream = struct { |
| 602 | 603 | ||
| 603 | var i: u32 = 0; | 604 | var i: u32 = 0; |
| 604 | while (i < block_count) : (i += 1) { | 605 | while (i < block_count) : (i += 1) { |
| 605 | stream.blocks[i] = try in.readIntLe(u32); | 606 | stream.blocks[i] = try in.readIntLittle(u32); |
| 606 | } | 607 | } |
| 607 | 608 | ||
| 608 | return stream; | 609 | return stream; |
std/rand/index.zig+160-41| ... | @@ -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 | // |
| ... | @@ -52,11 +52,24 @@ pub const Random = struct { | ... | @@ -52,11 +52,24 @@ pub const Random = struct { |
| 52 | // use LE instead of native endian for better portability maybe? | 52 | // use LE instead of native endian for better portability maybe? |
| 53 | // TODO: endian portability is pointless if the underlying prng isn't endian portable. | 53 | // TODO: endian portability is pointless if the underlying prng isn't endian portable. |
| 54 | // TODO: document the endian portability of this library. | 54 | // TODO: document the endian portability of this library. |
| 55 | const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes); | 55 | const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes); |
| 56 | const unsigned_result = @truncate(UnsignedT, byte_aligned_result); | 56 | const unsigned_result = @truncate(UnsignedT, byte_aligned_result); |
| 57 | return @bitCast(T, unsigned_result); | 57 | return @bitCast(T, unsigned_result); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /// Constant-time implementation off ::uintLessThan. | ||
| 61 | /// The results of this function may be biased. | ||
| 62 | pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T { | ||
| 63 | comptime assert(T.is_signed == false); | ||
| 64 | comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! | ||
| 65 | assert(0 < less_than); | ||
| 66 | if (T.bit_count <= 32) { | ||
| 67 | return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than)); | ||
| 68 | } else { | ||
| 69 | return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than)); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 60 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. | 73 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. |
| 61 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. | 74 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. |
| 62 | /// Within this assumption, the runtime of this function is exponentially distributed. | 75 | /// Within this assumption, the runtime of this function is exponentially distributed. |
| ... | @@ -64,27 +77,52 @@ pub const Random = struct { | ... | @@ -64,27 +77,52 @@ pub const Random = struct { |
| 64 | /// the runtime of this function would technically be unbounded. | 77 | /// the runtime of this function would technically be unbounded. |
| 65 | /// However, if ::fillFn is backed by any evenly distributed pseudo random number generator, | 78 | /// However, if ::fillFn is backed by any evenly distributed pseudo random number generator, |
| 66 | /// this function is guaranteed to return. | 79 | /// this function is guaranteed to return. |
| 67 | /// If you need deterministic runtime bounds, consider instead using `r.int(T) % less_than`, | 80 | /// If you need deterministic runtime bounds, use `::uintLessThanBiased`. |
| 68 | /// which will usually be biased toward smaller values. | ||
| 69 | pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T { | 81 | pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T { |
| 70 | assert(T.is_signed == false); | 82 | comptime assert(T.is_signed == false); |
| 83 | comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! | ||
| 71 | assert(0 < less_than); | 84 | assert(0 < less_than); |
| 72 | 85 | // Small is typically u32 | |
| 73 | const last_group_size_minus_one: T = maxInt(T) % less_than; | 86 | const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32); |
| 74 | if (last_group_size_minus_one == less_than - 1) { | 87 | // Large is typically u64 |
| 75 | // less_than is a power of two. | 88 | const Large = @IntType(false, Small.bit_count * 2); |
| 76 | assert(math.floorPowerOfTwo(T, less_than) == less_than); | 89 | |
| 77 | // There is no retry zone. The optimal retry_zone_start would be maxInt(T) + 1. | 90 | // adapted from: |
| 78 | return r.int(T) % less_than; | 91 | // http://www.pcg-random.org/posts/bounded-rands.html |
| 92 | // "Lemire's (with an extra tweak from me)" | ||
| 93 | var x: Small = r.int(Small); | ||
| 94 | var m: Large = Large(x) * Large(less_than); | ||
| 95 | var l: Small = @truncate(Small, m); | ||
| 96 | if (l < less_than) { | ||
| 97 | // TODO: workaround for https://github.com/ziglang/zig/issues/1770 | ||
| 98 | // should be: | ||
| 99 | // var t: Small = -%less_than; | ||
| 100 | var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), Small(less_than))); | ||
| 101 | |||
| 102 | if (t >= less_than) { | ||
| 103 | t -= less_than; | ||
| 104 | if (t >= less_than) { | ||
| 105 | t %= less_than; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | while (l < t) { | ||
| 109 | x = r.int(Small); | ||
| 110 | m = Large(x) * Large(less_than); | ||
| 111 | l = @truncate(Small, m); | ||
| 112 | } | ||
| 79 | } | 113 | } |
| 80 | const retry_zone_start = maxInt(T) - last_group_size_minus_one; | 114 | return @intCast(T, m >> Small.bit_count); |
| 115 | } | ||
| 81 | 116 | ||
| 82 | while (true) { | 117 | /// Constant-time implementation off ::uintAtMost. |
| 83 | const rand_val = r.int(T); | 118 | /// The results of this function may be biased. |
| 84 | if (rand_val < retry_zone_start) { | 119 | pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T { |
| 85 | return rand_val % less_than; | 120 | assert(T.is_signed == false); |
| 86 | } | 121 | if (at_most == maxInt(T)) { |
| 122 | // have the full range | ||
| 123 | return r.int(T); | ||
| 87 | } | 124 | } |
| 125 | return r.uintLessThanBiased(T, at_most + 1); | ||
| 88 | } | 126 | } |
| 89 | 127 | ||
| 90 | /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. | 128 | /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. |
| ... | @@ -99,6 +137,23 @@ pub const Random = struct { | ... | @@ -99,6 +137,23 @@ pub const Random = struct { |
| 99 | return r.uintLessThan(T, at_most + 1); | 137 | return r.uintLessThan(T, at_most + 1); |
| 100 | } | 138 | } |
| 101 | 139 | ||
| 140 | /// Constant-time implementation off ::intRangeLessThan. | ||
| 141 | /// The results of this function may be biased. | ||
| 142 | pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T { | ||
| 143 | assert(at_least < less_than); | ||
| 144 | if (T.is_signed) { | ||
| 145 | // Two's complement makes this math pretty easy. | ||
| 146 | const UnsignedT = @IntType(false, T.bit_count); | ||
| 147 | const lo = @bitCast(UnsignedT, at_least); | ||
| 148 | const hi = @bitCast(UnsignedT, less_than); | ||
| 149 | const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo); | ||
| 150 | return @bitCast(T, result); | ||
| 151 | } else { | ||
| 152 | // The signed implementation would work fine, but we can use stricter arithmetic operators here. | ||
| 153 | return at_least + r.uintLessThanBiased(T, less_than - at_least); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 102 | /// Returns an evenly distributed random integer `at_least <= i < less_than`. | 157 | /// Returns an evenly distributed random integer `at_least <= i < less_than`. |
| 103 | /// See ::uintLessThan, which this function uses in most cases, | 158 | /// See ::uintLessThan, which this function uses in most cases, |
| 104 | /// for commentary on the runtime of this function. | 159 | /// for commentary on the runtime of this function. |
| ... | @@ -117,6 +172,23 @@ pub const Random = struct { | ... | @@ -117,6 +172,23 @@ pub const Random = struct { |
| 117 | } | 172 | } |
| 118 | } | 173 | } |
| 119 | 174 | ||
| 175 | /// Constant-time implementation off ::intRangeAtMostBiased. | ||
| 176 | /// The results of this function may be biased. | ||
| 177 | pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T { | ||
| 178 | assert(at_least <= at_most); | ||
| 179 | if (T.is_signed) { | ||
| 180 | // Two's complement makes this math pretty easy. | ||
| 181 | const UnsignedT = @IntType(false, T.bit_count); | ||
| 182 | const lo = @bitCast(UnsignedT, at_least); | ||
| 183 | const hi = @bitCast(UnsignedT, at_most); | ||
| 184 | const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo); | ||
| 185 | return @bitCast(T, result); | ||
| 186 | } else { | ||
| 187 | // The signed implementation would work fine, but we can use stricter arithmetic operators here. | ||
| 188 | return at_least + r.uintAtMostBiased(T, at_most - at_least); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 120 | /// Returns an evenly distributed random integer `at_least <= i <= at_most`. | 192 | /// Returns an evenly distributed random integer `at_least <= i <= at_most`. |
| 121 | /// See ::uintLessThan, which this function uses in most cases, | 193 | /// See ::uintLessThan, which this function uses in most cases, |
| 122 | /// for commentary on the runtime of this function. | 194 | /// for commentary on the runtime of this function. |
| ... | @@ -135,15 +207,11 @@ pub const Random = struct { | ... | @@ -135,15 +207,11 @@ pub const Random = struct { |
| 135 | } | 207 | } |
| 136 | } | 208 | } |
| 137 | 209 | ||
| 138 | /// Return a random integer/boolean type. | ||
| 139 | /// TODO: deprecated. use ::boolean or ::int instead. | 210 | /// TODO: deprecated. use ::boolean or ::int instead. |
| 140 | pub fn scalar(r: *Random, comptime T: type) T { | 211 | pub fn scalar(r: *Random, comptime T: type) T { |
| 141 | if (T == bool) return r.boolean(); | 212 | return if (T == bool) r.boolean() else r.int(T); |
| 142 | return r.int(T); | ||
| 143 | } | 213 | } |
| 144 | 214 | ||
| 145 | /// Return a random integer with even distribution between `start` | ||
| 146 | /// inclusive and `end` exclusive. `start` must be less than `end`. | ||
| 147 | /// TODO: deprecated. renamed to ::intRangeLessThan | 215 | /// TODO: deprecated. renamed to ::intRangeLessThan |
| 148 | pub fn range(r: *Random, comptime T: type, start: T, end: T) T { | 216 | pub fn range(r: *Random, comptime T: type, start: T, end: T) T { |
| 149 | return r.intRangeLessThan(T, start, end); | 217 | return r.intRangeLessThan(T, start, end); |
| ... | @@ -206,6 +274,20 @@ pub const Random = struct { | ... | @@ -206,6 +274,20 @@ pub const Random = struct { |
| 206 | } | 274 | } |
| 207 | }; | 275 | }; |
| 208 | 276 | ||
| 277 | /// Convert a random integer 0 <= random_int <= maxValue(T), | ||
| 278 | /// into an integer 0 <= result < less_than. | ||
| 279 | /// This function introduces a minor bias. | ||
| 280 | pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { | ||
| 281 | comptime assert(T.is_signed == false); | ||
| 282 | const T2 = @IntType(false, T.bit_count * 2); | ||
| 283 | |||
| 284 | // adapted from: | ||
| 285 | // http://www.pcg-random.org/posts/bounded-rands.html | ||
| 286 | // "Integer Multiplication (Biased)" | ||
| 287 | var m: T2 = T2(random_int) * T2(less_than); | ||
| 288 | return @intCast(T, m >> T.bit_count); | ||
| 289 | } | ||
| 290 | |||
| 209 | const SequentialPrng = struct { | 291 | const SequentialPrng = struct { |
| 210 | const Self = @This(); | 292 | const Self = @This(); |
| 211 | random: Random, | 293 | random: Random, |
| ... | @@ -294,10 +376,19 @@ fn testRandomIntLessThan() void { | ... | @@ -294,10 +376,19 @@ fn testRandomIntLessThan() void { |
| 294 | var r = SequentialPrng.init(); | 376 | var r = SequentialPrng.init(); |
| 295 | r.next_value = 0xff; | 377 | r.next_value = 0xff; |
| 296 | assert(r.random.uintLessThan(u8, 4) == 3); | 378 | assert(r.random.uintLessThan(u8, 4) == 3); |
| 297 | r.next_value = 0xff; | 379 | assert(r.next_value == 0); |
| 298 | assert(r.random.uintLessThan(u8, 3) == 0); | 380 | assert(r.random.uintLessThan(u8, 4) == 0); |
| 299 | assert(r.next_value == 1); | 381 | assert(r.next_value == 1); |
| 300 | 382 | ||
| 383 | r.next_value = 0; | ||
| 384 | assert(r.random.uintLessThan(u64, 32) == 0); | ||
| 385 | |||
| 386 | // trigger the bias rejection code path | ||
| 387 | r.next_value = 0; | ||
| 388 | assert(r.random.uintLessThan(u8, 3) == 0); | ||
| 389 | // verify we incremented twice | ||
| 390 | assert(r.next_value == 2); | ||
| 391 | |||
| 301 | r.next_value = 0xff; | 392 | r.next_value = 0xff; |
| 302 | assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f); | 393 | assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f); |
| 303 | r.next_value = 0xff; | 394 | r.next_value = 0xff; |
| ... | @@ -310,17 +401,10 @@ fn testRandomIntLessThan() void { | ... | @@ -310,17 +401,10 @@ fn testRandomIntLessThan() void { |
| 310 | r.next_value = 0xff; | 401 | r.next_value = 0xff; |
| 311 | assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1); | 402 | assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1); |
| 312 | 403 | ||
| 313 | r.next_value = 0xff; | ||
| 314 | assert(r.random.intRangeLessThan(i64, -0x8000000000000000, 0) == -1); | ||
| 315 | r.next_value = 0xff; | 404 | r.next_value = 0xff; |
| 316 | assert(r.random.intRangeLessThan(i3, -4, 0) == -1); | 405 | assert(r.random.intRangeLessThan(i3, -4, 0) == -1); |
| 317 | r.next_value = 0xff; | 406 | r.next_value = 0xff; |
| 318 | assert(r.random.intRangeLessThan(i3, -2, 2) == 1); | 407 | assert(r.random.intRangeLessThan(i3, -2, 2) == 1); |
| 319 | |||
| 320 | // test retrying and eventually getting a good value | ||
| 321 | // start just out of bounds | ||
| 322 | r.next_value = 0x81; | ||
| 323 | assert(r.random.uintLessThan(u8, 0x81) == 0); | ||
| 324 | } | 408 | } |
| 325 | 409 | ||
| 326 | test "Random intAtMost" { | 410 | test "Random intAtMost" { |
| ... | @@ -332,9 +416,14 @@ fn testRandomIntAtMost() void { | ... | @@ -332,9 +416,14 @@ fn testRandomIntAtMost() void { |
| 332 | var r = SequentialPrng.init(); | 416 | var r = SequentialPrng.init(); |
| 333 | r.next_value = 0xff; | 417 | r.next_value = 0xff; |
| 334 | assert(r.random.uintAtMost(u8, 3) == 3); | 418 | assert(r.random.uintAtMost(u8, 3) == 3); |
| 335 | r.next_value = 0xff; | 419 | assert(r.next_value == 0); |
| 420 | assert(r.random.uintAtMost(u8, 3) == 0); | ||
| 421 | |||
| 422 | // trigger the bias rejection code path | ||
| 423 | r.next_value = 0; | ||
| 336 | assert(r.random.uintAtMost(u8, 2) == 0); | 424 | assert(r.random.uintAtMost(u8, 2) == 0); |
| 337 | assert(r.next_value == 1); | 425 | // verify we incremented twice |
| 426 | assert(r.next_value == 2); | ||
| 338 | 427 | ||
| 339 | r.next_value = 0xff; | 428 | r.next_value = 0xff; |
| 340 | assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f); | 429 | assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f); |
| ... | @@ -348,17 +437,43 @@ fn testRandomIntAtMost() void { | ... | @@ -348,17 +437,43 @@ fn testRandomIntAtMost() void { |
| 348 | r.next_value = 0xff; | 437 | r.next_value = 0xff; |
| 349 | assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1); | 438 | assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1); |
| 350 | 439 | ||
| 351 | r.next_value = 0xff; | ||
| 352 | assert(r.random.intRangeAtMost(i64, -0x8000000000000000, -1) == -1); | ||
| 353 | r.next_value = 0xff; | 440 | r.next_value = 0xff; |
| 354 | assert(r.random.intRangeAtMost(i3, -4, -1) == -1); | 441 | assert(r.random.intRangeAtMost(i3, -4, -1) == -1); |
| 355 | r.next_value = 0xff; | 442 | r.next_value = 0xff; |
| 356 | assert(r.random.intRangeAtMost(i3, -2, 1) == 1); | 443 | assert(r.random.intRangeAtMost(i3, -2, 1) == 1); |
| 357 | 444 | ||
| 358 | // test retrying and eventually getting a good value | 445 | assert(r.random.uintAtMost(u0, 0) == 0); |
| 359 | // start just out of bounds | 446 | } |
| 360 | r.next_value = 0x81; | 447 | |
| 361 | assert(r.random.uintAtMost(u8, 0x80) == 0); | 448 | test "Random Biased" { |
| 449 | var r = DefaultPrng.init(0); | ||
| 450 | // Not thoroughly checking the logic here. | ||
| 451 | // Just want to execute all the paths with different types. | ||
| 452 | |||
| 453 | assert(r.random.uintLessThanBiased(u1, 1) == 0); | ||
| 454 | assert(r.random.uintLessThanBiased(u32, 10) < 10); | ||
| 455 | assert(r.random.uintLessThanBiased(u64, 20) < 20); | ||
| 456 | |||
| 457 | assert(r.random.uintAtMostBiased(u0, 0) == 0); | ||
| 458 | assert(r.random.uintAtMostBiased(u1, 0) <= 0); | ||
| 459 | assert(r.random.uintAtMostBiased(u32, 10) <= 10); | ||
| 460 | assert(r.random.uintAtMostBiased(u64, 20) <= 20); | ||
| 461 | |||
| 462 | assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0); | ||
| 463 | assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1); | ||
| 464 | assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10); | ||
| 465 | assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10); | ||
| 466 | assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20); | ||
| 467 | assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20); | ||
| 468 | |||
| 469 | // uncomment for broken module error: | ||
| 470 | //assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0); | ||
| 471 | assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0); | ||
| 472 | assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1); | ||
| 473 | assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10); | ||
| 474 | assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10); | ||
| 475 | assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20); | ||
| 476 | assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20); | ||
| 362 | } | 477 | } |
| 363 | 478 | ||
| 364 | // Generator to extend 64-bit seed values into longer sequences. | 479 | // Generator to extend 64-bit seed values into longer sequences. |
| ... | @@ -870,12 +985,16 @@ test "Random range" { | ... | @@ -870,12 +985,16 @@ test "Random range" { |
| 870 | } | 985 | } |
| 871 | 986 | ||
| 872 | fn testRange(r: *Random, start: i8, end: i8) void { | 987 | fn testRange(r: *Random, start: i8, end: i8) void { |
| 988 | testRangeBias(r, start, end, true); | ||
| 989 | testRangeBias(r, start, end, false); | ||
| 990 | } | ||
| 991 | fn testRangeBias(r: *Random, start: i8, end: i8, biased: bool) void { | ||
| 873 | const count = @intCast(usize, i32(end) - i32(start)); | 992 | const count = @intCast(usize, i32(end) - i32(start)); |
| 874 | var values_buffer = []bool{false} ** 0x100; | 993 | var values_buffer = []bool{false} ** 0x100; |
| 875 | const values = values_buffer[0..count]; | 994 | const values = values_buffer[0..count]; |
| 876 | var i: usize = 0; | 995 | var i: usize = 0; |
| 877 | while (i < count) { | 996 | while (i < count) { |
| 878 | const value: i32 = r.intRangeLessThan(i8, start, end); | 997 | const value: i32 = if (biased) r.intRangeLessThanBiased(i8, start, end) else r.intRangeLessThan(i8, start, end); |
| 879 | const index = @intCast(usize, value - start); | 998 | const index = @intCast(usize, value - start); |
| 880 | if (!values[index]) { | 999 | if (!values[index]) { |
| 881 | i += 1; | 1000 | i += 1; |
std/rand/ziggurat.zig+1-1| ... | @@ -12,7 +12,7 @@ const std = @import("../index.zig"); | ... | @@ -12,7 +12,7 @@ const std = @import("../index.zig"); |
| 12 | const math = std.math; | 12 | const math = std.math; |
| 13 | const Random = std.rand.Random; | 13 | const Random = std.rand.Random; |
| 14 | 14 | ||
| 15 | pub fn next_f64(random: *Random, comptime tables: *const ZigTable) f64 { | 15 | pub fn next_f64(random: *Random, comptime tables: ZigTable) f64 { |
| 16 | while (true) { | 16 | while (true) { |
| 17 | // We manually construct a float from parts as we can avoid an extra random lookup here by | 17 | // We manually construct a float from parts as we can avoid an extra random lookup here by |
| 18 | // using the unused exponent for the lookup table entry. | 18 | // using the unused exponent for the lookup table entry. |
std/segmented_list.zig+5| ... | @@ -201,6 +201,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type | ... | @@ -201,6 +201,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 201 | self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count); | 201 | self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | pub fn shrink(self: *Self, new_len: usize) void { | ||
| 205 | assert(new_len <= self.len); | ||
| 206 | self.len = new_len; | ||
| 207 | } | ||
| 208 | |||
| 204 | pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) { | 209 | pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) { |
| 205 | if (index < prealloc_item_count) { | 210 | if (index < prealloc_item_count) { |
| 206 | return &self.prealloc_segment[index]; | 211 | return &self.prealloc_segment[index]; |
std/special/bootstrap.zig+14-4| ... | @@ -20,10 +20,17 @@ comptime { | ... | @@ -20,10 +20,17 @@ comptime { |
| 20 | 20 | ||
| 21 | nakedcc fn _start() noreturn { | 21 | nakedcc fn _start() noreturn { |
| 22 | switch (builtin.arch) { | 22 | switch (builtin.arch) { |
| 23 | builtin.Arch.x86_64 => { | 23 | builtin.Arch.x86_64 => switch (builtin.os) { |
| 24 | argc_ptr = asm ("lea (%%rsp), %[argc]" | 24 | builtin.Os.freebsd => { |
| 25 | : [argc] "=r" (-> [*]usize) | 25 | argc_ptr = asm ("lea (%%rdi), %[argc]" |
| 26 | ); | 26 | : [argc] "=r" (-> [*]usize) |
| 27 | ); | ||
| 28 | }, | ||
| 29 | else => { | ||
| 30 | argc_ptr = asm ("lea (%%rsp), %[argc]" | ||
| 31 | : [argc] "=r" (-> [*]usize) | ||
| 32 | ); | ||
| 33 | }, | ||
| 27 | }, | 34 | }, |
| 28 | builtin.Arch.i386 => { | 35 | builtin.Arch.i386 => { |
| 29 | argc_ptr = asm ("lea (%%esp), %[argc]" | 36 | argc_ptr = asm ("lea (%%esp), %[argc]" |
| ... | @@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn { | ... | @@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn { |
| 50 | 57 | ||
| 51 | // TODO https://github.com/ziglang/zig/issues/265 | 58 | // TODO https://github.com/ziglang/zig/issues/265 |
| 52 | fn posixCallMainAndExit() noreturn { | 59 | fn posixCallMainAndExit() noreturn { |
| 60 | if (builtin.os == builtin.Os.freebsd) { | ||
| 61 | @setAlignStack(16); | ||
| 62 | } | ||
| 53 | const argc = argc_ptr[0]; | 63 | const argc = argc_ptr[0]; |
| 54 | const argv = @ptrCast([*][*]u8, argc_ptr + 1); | 64 | const argv = @ptrCast([*][*]u8, argc_ptr + 1); |
| 55 | 65 |
std/special/build_runner.zig-1| ... | @@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { | ... | @@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { |
| 164 | \\ | 164 | \\ |
| 165 | \\General Options: | 165 | \\General Options: |
| 166 | \\ --help Print this help and exit | 166 | \\ --help Print this help and exit |
| 167 | \\ --init Generate a build.zig template | ||
| 168 | \\ --verbose Print commands before executing them | 167 | \\ --verbose Print commands before executing them |
| 169 | \\ --prefix [path] Override default install prefix | 168 | \\ --prefix [path] Override default install prefix |
| 170 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers | 169 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers |
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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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 assert = std.debug.assert; | ||
| 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 | assert(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/index.zig+90-63| ... | @@ -52,6 +52,16 @@ comptime { | ... | @@ -52,6 +52,16 @@ comptime { |
| 52 | @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); | 52 | @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); |
| 53 | @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); | 53 | @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); |
| 54 | 54 | ||
| 55 | @export("__fixdfdi", @import("fixdfdi.zig").__fixdfdi, linkage); | ||
| 56 | @export("__fixdfsi", @import("fixdfsi.zig").__fixdfsi, linkage); | ||
| 57 | @export("__fixdfti", @import("fixdfti.zig").__fixdfti, linkage); | ||
| 58 | @export("__fixsfdi", @import("fixsfdi.zig").__fixsfdi, linkage); | ||
| 59 | @export("__fixsfsi", @import("fixsfsi.zig").__fixsfsi, linkage); | ||
| 60 | @export("__fixsfti", @import("fixsfti.zig").__fixsfti, linkage); | ||
| 61 | @export("__fixtfdi", @import("fixtfdi.zig").__fixtfdi, linkage); | ||
| 62 | @export("__fixtfsi", @import("fixtfsi.zig").__fixtfsi, linkage); | ||
| 63 | @export("__fixtfti", @import("fixtfti.zig").__fixtfti, linkage); | ||
| 64 | |||
| 55 | @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); | 65 | @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); |
| 56 | 66 | ||
| 57 | @export("__udivsi3", __udivsi3, linkage); | 67 | @export("__udivsi3", __udivsi3, linkage); |
| ... | @@ -59,7 +69,7 @@ comptime { | ... | @@ -59,7 +69,7 @@ comptime { |
| 59 | @export("__umoddi3", __umoddi3, linkage); | 69 | @export("__umoddi3", __umoddi3, linkage); |
| 60 | @export("__udivmodsi4", __udivmodsi4, linkage); | 70 | @export("__udivmodsi4", __udivmodsi4, linkage); |
| 61 | 71 | ||
| 62 | if (isArmArch()) { | 72 | if (is_arm_arch and !is_arm_64) { |
| 63 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); | 73 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); |
| 64 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); | 74 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); |
| 65 | @export("__aeabi_uidiv", __udivsi3, linkage); | 75 | @export("__aeabi_uidiv", __udivsi3, linkage); |
| ... | @@ -149,68 +159,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult | ... | @@ -149,68 +159,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult |
| 149 | return result; | 159 | return result; |
| 150 | } | 160 | } |
| 151 | 161 | ||
| 152 | fn isArmArch() bool { | 162 | const is_arm_64 = switch (builtin.arch) { |
| 153 | return switch (builtin.arch) { | 163 | builtin.Arch.aarch64v8_3a, |
| 154 | builtin.Arch.armv8_3a, | 164 | builtin.Arch.aarch64v8_2a, |
| 155 | builtin.Arch.armv8_2a, | 165 | builtin.Arch.aarch64v8_1a, |
| 156 | builtin.Arch.armv8_1a, | 166 | builtin.Arch.aarch64v8, |
| 157 | builtin.Arch.armv8, | 167 | builtin.Arch.aarch64v8r, |
| 158 | builtin.Arch.armv8r, | 168 | builtin.Arch.aarch64v8m_baseline, |
| 159 | builtin.Arch.armv8m_baseline, | 169 | builtin.Arch.aarch64v8m_mainline, |
| 160 | builtin.Arch.armv8m_mainline, | 170 | builtin.Arch.aarch64_bev8_3a, |
| 161 | builtin.Arch.armv7, | 171 | builtin.Arch.aarch64_bev8_2a, |
| 162 | builtin.Arch.armv7em, | 172 | builtin.Arch.aarch64_bev8_1a, |
| 163 | builtin.Arch.armv7m, | 173 | builtin.Arch.aarch64_bev8, |
| 164 | builtin.Arch.armv7s, | 174 | builtin.Arch.aarch64_bev8r, |
| 165 | builtin.Arch.armv7k, | 175 | builtin.Arch.aarch64_bev8m_baseline, |
| 166 | builtin.Arch.armv7ve, | 176 | builtin.Arch.aarch64_bev8m_mainline, |
| 167 | builtin.Arch.armv6, | 177 | => true, |
| 168 | builtin.Arch.armv6m, | 178 | else => false, |
| 169 | builtin.Arch.armv6k, | 179 | }; |
| 170 | builtin.Arch.armv6t2, | 180 | |
| 171 | builtin.Arch.armv5, | 181 | const is_arm_arch = switch (builtin.arch) { |
| 172 | builtin.Arch.armv5te, | 182 | builtin.Arch.armv8_3a, |
| 173 | builtin.Arch.armv4t, | 183 | builtin.Arch.armv8_2a, |
| 174 | builtin.Arch.armebv8_3a, | 184 | builtin.Arch.armv8_1a, |
| 175 | builtin.Arch.armebv8_2a, | 185 | builtin.Arch.armv8, |
| 176 | builtin.Arch.armebv8_1a, | 186 | builtin.Arch.armv8r, |
| 177 | builtin.Arch.armebv8, | 187 | builtin.Arch.armv8m_baseline, |
| 178 | builtin.Arch.armebv8r, | 188 | builtin.Arch.armv8m_mainline, |
| 179 | builtin.Arch.armebv8m_baseline, | 189 | builtin.Arch.armv7, |
| 180 | builtin.Arch.armebv8m_mainline, | 190 | builtin.Arch.armv7em, |
| 181 | builtin.Arch.armebv7, | 191 | builtin.Arch.armv7m, |
| 182 | builtin.Arch.armebv7em, | 192 | builtin.Arch.armv7s, |
| 183 | builtin.Arch.armebv7m, | 193 | builtin.Arch.armv7k, |
| 184 | builtin.Arch.armebv7s, | 194 | builtin.Arch.armv7ve, |
| 185 | builtin.Arch.armebv7k, | 195 | builtin.Arch.armv6, |
| 186 | builtin.Arch.armebv7ve, | 196 | builtin.Arch.armv6m, |
| 187 | builtin.Arch.armebv6, | 197 | builtin.Arch.armv6k, |
| 188 | builtin.Arch.armebv6m, | 198 | builtin.Arch.armv6t2, |
| 189 | builtin.Arch.armebv6k, | 199 | builtin.Arch.armv5, |
| 190 | builtin.Arch.armebv6t2, | 200 | builtin.Arch.armv5te, |
| 191 | builtin.Arch.armebv5, | 201 | builtin.Arch.armv4t, |
| 192 | builtin.Arch.armebv5te, | 202 | builtin.Arch.armebv8_3a, |
| 193 | builtin.Arch.armebv4t, | 203 | builtin.Arch.armebv8_2a, |
| 194 | builtin.Arch.aarch64v8_3a, | 204 | builtin.Arch.armebv8_1a, |
| 195 | builtin.Arch.aarch64v8_2a, | 205 | builtin.Arch.armebv8, |
| 196 | builtin.Arch.aarch64v8_1a, | 206 | builtin.Arch.armebv8r, |
| 197 | builtin.Arch.aarch64v8, | 207 | builtin.Arch.armebv8m_baseline, |
| 198 | builtin.Arch.aarch64v8r, | 208 | builtin.Arch.armebv8m_mainline, |
| 199 | builtin.Arch.aarch64v8m_baseline, | 209 | builtin.Arch.armebv7, |
| 200 | builtin.Arch.aarch64v8m_mainline, | 210 | builtin.Arch.armebv7em, |
| 201 | builtin.Arch.aarch64_bev8_3a, | 211 | builtin.Arch.armebv7m, |
| 202 | builtin.Arch.aarch64_bev8_2a, | 212 | builtin.Arch.armebv7s, |
| 203 | builtin.Arch.aarch64_bev8_1a, | 213 | builtin.Arch.armebv7k, |
| 204 | builtin.Arch.aarch64_bev8, | 214 | builtin.Arch.armebv7ve, |
| 205 | builtin.Arch.aarch64_bev8r, | 215 | builtin.Arch.armebv6, |
| 206 | builtin.Arch.aarch64_bev8m_baseline, | 216 | builtin.Arch.armebv6m, |
| 207 | builtin.Arch.aarch64_bev8m_mainline, | 217 | builtin.Arch.armebv6k, |
| 208 | builtin.Arch.thumb, | 218 | builtin.Arch.armebv6t2, |
| 209 | builtin.Arch.thumbeb, | 219 | builtin.Arch.armebv5, |
| 210 | => true, | 220 | builtin.Arch.armebv5te, |
| 211 | else => false, | 221 | builtin.Arch.armebv4t, |
| 212 | }; | 222 | builtin.Arch.aarch64v8_3a, |
| 213 | } | 223 | builtin.Arch.aarch64v8_2a, |
| 224 | builtin.Arch.aarch64v8_1a, | ||
| 225 | builtin.Arch.aarch64v8, | ||
| 226 | builtin.Arch.aarch64v8r, | ||
| 227 | builtin.Arch.aarch64v8m_baseline, | ||
| 228 | builtin.Arch.aarch64v8m_mainline, | ||
| 229 | builtin.Arch.aarch64_bev8_3a, | ||
| 230 | builtin.Arch.aarch64_bev8_2a, | ||
| 231 | builtin.Arch.aarch64_bev8_1a, | ||
| 232 | builtin.Arch.aarch64_bev8, | ||
| 233 | builtin.Arch.aarch64_bev8r, | ||
| 234 | builtin.Arch.aarch64_bev8m_baseline, | ||
| 235 | builtin.Arch.aarch64_bev8m_mainline, | ||
| 236 | builtin.Arch.thumb, | ||
| 237 | builtin.Arch.thumbeb, | ||
| 238 | => true, | ||
| 239 | else => false, | ||
| 240 | }; | ||
| 214 | 241 | ||
| 215 | nakedcc fn __aeabi_uidivmod() void { | 242 | nakedcc fn __aeabi_uidivmod() void { |
| 216 | @setRuntimeSafety(false); | 243 | @setRuntimeSafety(false); |
std/unicode.zig+16-16| ... | @@ -208,7 +208,7 @@ pub const Utf8View = struct { | ... | @@ -208,7 +208,7 @@ pub const Utf8View = struct { |
| 208 | } | 208 | } |
| 209 | }; | 209 | }; |
| 210 | 210 | ||
| 211 | const Utf8Iterator = struct { | 211 | pub const Utf8Iterator = struct { |
| 212 | bytes: []const u8, | 212 | bytes: []const u8, |
| 213 | i: usize, | 213 | i: usize, |
| 214 | 214 | ||
| ... | @@ -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)); |
| ... | @@ -510,46 +510,46 @@ test "utf16leToUtf8" { | ... | @@ -510,46 +510,46 @@ test "utf16leToUtf8" { |
| 510 | const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); | 510 | const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); |
| 511 | 511 | ||
| 512 | { | 512 | { |
| 513 | mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little); | 513 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A'); |
| 514 | mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little); | 514 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a'); |
| 515 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 515 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 516 | assert(mem.eql(u8, utf8, "Aa")); | 516 | assert(mem.eql(u8, utf8, "Aa")); |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | { | 519 | { |
| 520 | mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little); | 520 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80); |
| 521 | mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little); | 521 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff); |
| 522 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 522 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 523 | assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf")); | 523 | assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf")); |
| 524 | } | 524 | } |
| 525 | 525 | ||
| 526 | { | 526 | { |
| 527 | // the values just outside the surrogate half range | 527 | // the values just outside the surrogate half range |
| 528 | mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little); | 528 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff); |
| 529 | mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little); | 529 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000); |
| 530 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 530 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 531 | assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80")); | 531 | assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80")); |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | { | 534 | { |
| 535 | // smallest surrogate pair | 535 | // smallest surrogate pair |
| 536 | mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little); | 536 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800); |
| 537 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); | 537 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); |
| 538 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 538 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 539 | assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80")); | 539 | assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80")); |
| 540 | } | 540 | } |
| 541 | 541 | ||
| 542 | { | 542 | { |
| 543 | // largest surrogate pair | 543 | // largest surrogate pair |
| 544 | mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); | 544 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); |
| 545 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little); | 545 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff); |
| 546 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 546 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 547 | assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf")); | 547 | assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf")); |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | { | 550 | { |
| 551 | mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); | 551 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); |
| 552 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); | 552 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); |
| 553 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); | 553 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 554 | assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80")); | 554 | assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80")); |
| 555 | } | 555 | } |
| ... | @@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize { | ... | @@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize { |
| 583 | while (it.nextCodepoint()) |codepoint| { | 583 | while (it.nextCodepoint()) |codepoint| { |
| 584 | if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1; | 584 | if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1; |
| 585 | // TODO surrogate pairs | 585 | // TODO surrogate pairs |
| 586 | mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little); | 586 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint)); |
| 587 | end_index += 2; | 587 | end_index += 2; |
| 588 | } | 588 | } |
| 589 | return end_index / 2; | 589 | return end_index / 2; |
test/behavior.zig+4| ... | @@ -8,6 +8,7 @@ comptime { | ... | @@ -8,6 +8,7 @@ comptime { |
| 8 | _ = @import("cases/atomics.zig"); | 8 | _ = @import("cases/atomics.zig"); |
| 9 | _ = @import("cases/bitcast.zig"); | 9 | _ = @import("cases/bitcast.zig"); |
| 10 | _ = @import("cases/bool.zig"); | 10 | _ = @import("cases/bool.zig"); |
| 11 | _ = @import("cases/bswap.zig"); | ||
| 11 | _ = @import("cases/bugs/1076.zig"); | 12 | _ = @import("cases/bugs/1076.zig"); |
| 12 | _ = @import("cases/bugs/1111.zig"); | 13 | _ = @import("cases/bugs/1111.zig"); |
| 13 | _ = @import("cases/bugs/1277.zig"); | 14 | _ = @import("cases/bugs/1277.zig"); |
| ... | @@ -41,6 +42,7 @@ comptime { | ... | @@ -41,6 +42,7 @@ comptime { |
| 41 | _ = @import("cases/if.zig"); | 42 | _ = @import("cases/if.zig"); |
| 42 | _ = @import("cases/import.zig"); | 43 | _ = @import("cases/import.zig"); |
| 43 | _ = @import("cases/incomplete_struct_param_tld.zig"); | 44 | _ = @import("cases/incomplete_struct_param_tld.zig"); |
| 45 | _ = @import("cases/inttoptr.zig"); | ||
| 44 | _ = @import("cases/ir_block_deps.zig"); | 46 | _ = @import("cases/ir_block_deps.zig"); |
| 45 | _ = @import("cases/math.zig"); | 47 | _ = @import("cases/math.zig"); |
| 46 | _ = @import("cases/merge_error_sets.zig"); | 48 | _ = @import("cases/merge_error_sets.zig"); |
| ... | @@ -51,6 +53,7 @@ comptime { | ... | @@ -51,6 +53,7 @@ comptime { |
| 51 | _ = @import("cases/optional.zig"); | 53 | _ = @import("cases/optional.zig"); |
| 52 | _ = @import("cases/pointers.zig"); | 54 | _ = @import("cases/pointers.zig"); |
| 53 | _ = @import("cases/popcount.zig"); | 55 | _ = @import("cases/popcount.zig"); |
| 56 | _ = @import("cases/ptrcast.zig"); | ||
| 54 | _ = @import("cases/pub_enum/index.zig"); | 57 | _ = @import("cases/pub_enum/index.zig"); |
| 55 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); | 58 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); |
| 56 | _ = @import("cases/reflection.zig"); | 59 | _ = @import("cases/reflection.zig"); |
| ... | @@ -64,6 +67,7 @@ comptime { | ... | @@ -64,6 +67,7 @@ comptime { |
| 64 | _ = @import("cases/switch_prong_implicit_cast.zig"); | 67 | _ = @import("cases/switch_prong_implicit_cast.zig"); |
| 65 | _ = @import("cases/syntax.zig"); | 68 | _ = @import("cases/syntax.zig"); |
| 66 | _ = @import("cases/this.zig"); | 69 | _ = @import("cases/this.zig"); |
| 70 | _ = @import("cases/truncate.zig"); | ||
| 67 | _ = @import("cases/try.zig"); | 71 | _ = @import("cases/try.zig"); |
| 68 | _ = @import("cases/type_info.zig"); | 72 | _ = @import("cases/type_info.zig"); |
| 69 | _ = @import("cases/undefined.zig"); | 73 | _ = @import("cases/undefined.zig"); |
test/cases/asm.zig+24| ... | @@ -17,6 +17,30 @@ test "module level assembly" { | ... | @@ -17,6 +17,30 @@ test "module level assembly" { |
| 17 | } | 17 | } |
| 18 | } | 18 | } |
| 19 | 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 | |||
| 20 | extern fn aoeu() i32; | 44 | extern fn aoeu() i32; |
| 21 | 45 | ||
| 22 | export fn derp() i32 { | 46 | export fn derp() i32 { |
test/cases/bswap.zig created+32| ... | @@ -0,0 +1,32 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | |||
| 4 | test "@bswap" { | ||
| 5 | comptime testByteSwap(); | ||
| 6 | testByteSwap(); | ||
| 7 | } | ||
| 8 | |||
| 9 | fn testByteSwap() void { | ||
| 10 | assert(@bswap(u0, 0) == 0); | ||
| 11 | assert(@bswap(u8, 0x12) == 0x12); | ||
| 12 | assert(@bswap(u16, 0x1234) == 0x3412); | ||
| 13 | assert(@bswap(u24, 0x123456) == 0x563412); | ||
| 14 | assert(@bswap(u32, 0x12345678) == 0x78563412); | ||
| 15 | assert(@bswap(u40, 0x123456789a) == 0x9a78563412); | ||
| 16 | assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); | ||
| 17 | assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); | ||
| 18 | assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); | ||
| 19 | assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); | ||
| 20 | |||
| 21 | assert(@bswap(i0, 0) == 0); | ||
| 22 | assert(@bswap(i8, -50) == -50); | ||
| 23 | assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); | ||
| 24 | assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); | ||
| 25 | assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); | ||
| 26 | assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); | ||
| 27 | assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); | ||
| 28 | assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); | ||
| 29 | assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); | ||
| 30 | assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == | ||
| 31 | @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); | ||
| 32 | } | ||
test/cases/cast.zig+18| ... | @@ -452,3 +452,21 @@ test "implicit ptr to *c_void" { | ... | @@ -452,3 +452,21 @@ test "implicit ptr to *c_void" { |
| 452 | var c: *u32 = @ptrCast(*u32, ptr2.?); | 452 | var c: *u32 = @ptrCast(*u32, ptr2.?); |
| 453 | assert(c.* == 1); | 453 | assert(c.* == 1); |
| 454 | } | 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/inttoptr.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const assertOrPanic = std.debug.assertOrPanic; | ||
| 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 | } | ||
test/cases/ptrcast.zig created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const assertOrPanic = std.debug.assertOrPanic; | ||
| 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 | assertOrPanic(@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 | assertOrPanic(val == 5); | ||
| 36 | } | ||
test/cases/struct_contains_slice_of_itself.zig+42| ... | @@ -5,6 +5,11 @@ const Node = struct { | ... | @@ -5,6 +5,11 @@ const Node = struct { |
| 5 | children: []Node, | 5 | children: []Node, |
| 6 | }; | 6 | }; |
| 7 | 7 | ||
| 8 | const NodeAligned = struct { | ||
| 9 | payload: i32, | ||
| 10 | children: []align(@alignOf(NodeAligned)) NodeAligned, | ||
| 11 | }; | ||
| 12 | |||
| 8 | test "struct contains slice of itself" { | 13 | test "struct contains slice of itself" { |
| 9 | var other_nodes = []Node{ | 14 | var other_nodes = []Node{ |
| 10 | Node{ | 15 | Node{ |
| ... | @@ -41,3 +46,40 @@ test "struct contains slice of itself" { | ... | @@ -41,3 +46,40 @@ test "struct contains slice of itself" { |
| 41 | assert(root.children[2].children[0].payload == 31); | 46 | assert(root.children[2].children[0].payload == 31); |
| 42 | assert(root.children[2].children[1].payload == 32); | 47 | assert(root.children[2].children[1].payload == 32); |
| 43 | } | 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 | assert(root.payload == 1234); | ||
| 80 | assert(root.children[0].payload == 1); | ||
| 81 | assert(root.children[1].payload == 2); | ||
| 82 | assert(root.children[2].payload == 3); | ||
| 83 | assert(root.children[2].children[0].payload == 31); | ||
| 84 | assert(root.children[2].children[1].payload == 32); | ||
| 85 | } |
test/cases/truncate.zig created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const assert = std.debug.assert; | ||
| 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 assert(y == 0); | ||
| 8 | } | ||
test/compile_errors.zig+109-31| ... | @@ -1,6 +1,85 @@ | ... | @@ -1,6 +1,85 @@ |
| 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.add( | ||
| 5 | "reading past end of pointer casted array", | ||
| 6 | \\comptime { | ||
| 7 | \\ const array = "aoeu"; | ||
| 8 | \\ const slice = array[2..]; | ||
| 9 | \\ const int_ptr = @ptrCast(*const u24, slice.ptr); | ||
| 10 | \\ const deref = int_ptr.*; | ||
| 11 | \\} | ||
| 12 | , | ||
| 13 | ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes", | ||
| 14 | ); | ||
| 15 | |||
| 16 | cases.add( | ||
| 17 | "error note for function parameter incompatibility", | ||
| 18 | \\fn do_the_thing(func: fn (arg: i32) void) void {} | ||
| 19 | \\fn bar(arg: bool) void {} | ||
| 20 | \\export fn entry() void { | ||
| 21 | \\ do_the_thing(bar); | ||
| 22 | \\} | ||
| 23 | , | ||
| 24 | ".tmp_source.zig:4:18: error: expected type 'fn(i32) void', found 'fn(bool) void", | ||
| 25 | ".tmp_source.zig:4:18: note: parameter 0: 'bool' cannot cast into 'i32'", | ||
| 26 | ); | ||
| 27 | |||
| 28 | cases.add( | ||
| 29 | "cast negative value to unsigned integer", | ||
| 30 | \\comptime { | ||
| 31 | \\ const value: i32 = -1; | ||
| 32 | \\ const unsigned = @intCast(u32, value); | ||
| 33 | \\} | ||
| 34 | \\export fn entry1() void { | ||
| 35 | \\ const value: i32 = -1; | ||
| 36 | \\ const unsigned: u32 = value; | ||
| 37 | \\} | ||
| 38 | , | ||
| 39 | ".tmp_source.zig:3:36: error: cannot cast negative value -1 to unsigned integer type 'u32'", | ||
| 40 | ".tmp_source.zig:7:27: error: cannot cast negative value -1 to unsigned integer type 'u32'", | ||
| 41 | ); | ||
| 42 | |||
| 43 | cases.add( | ||
| 44 | "integer cast truncates bits", | ||
| 45 | \\export fn entry1() void { | ||
| 46 | \\ const spartan_count: u16 = 300; | ||
| 47 | \\ const byte = @intCast(u8, spartan_count); | ||
| 48 | \\} | ||
| 49 | \\export fn entry2() void { | ||
| 50 | \\ const spartan_count: u16 = 300; | ||
| 51 | \\ const byte: u8 = spartan_count; | ||
| 52 | \\} | ||
| 53 | \\export fn entry3() void { | ||
| 54 | \\ var spartan_count: u16 = 300; | ||
| 55 | \\ var byte: u8 = spartan_count; | ||
| 56 | \\} | ||
| 57 | , | ||
| 58 | ".tmp_source.zig:3:31: error: integer value 300 cannot be implicitly casted to type 'u8'", | ||
| 59 | ".tmp_source.zig:7:22: error: integer value 300 cannot be implicitly casted to type 'u8'", | ||
| 60 | ".tmp_source.zig:11:20: error: expected type 'u8', found 'u16'", | ||
| 61 | ); | ||
| 62 | |||
| 63 | cases.add( | ||
| 64 | "comptime implicit cast f64 to f32", | ||
| 65 | \\export fn entry() void { | ||
| 66 | \\ const x: f64 = 16777217; | ||
| 67 | \\ const y: f32 = x; | ||
| 68 | \\} | ||
| 69 | , | ||
| 70 | ".tmp_source.zig:3:20: error: cast of value 16777217.000000 to type 'f32' loses information", | ||
| 71 | ); | ||
| 72 | |||
| 73 | cases.add( | ||
| 74 | "implicit cast from f64 to f32", | ||
| 75 | \\var x: f64 = 1.0; | ||
| 76 | \\var y: f32 = x; | ||
| 77 | \\ | ||
| 78 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | ||
| 79 | , | ||
| 80 | ".tmp_source.zig:2:14: error: expected type 'f32', found 'f64'", | ||
| 81 | ); | ||
| 82 | |||
| 4 | cases.add( | 83 | cases.add( |
| 5 | "exceeded maximum bit width of integer", | 84 | "exceeded maximum bit width of integer", |
| 6 | \\export fn entry1() void { | 85 | \\export fn entry1() void { |
| ... | @@ -1819,7 +1898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -1819,7 +1898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1819 | \\ if (0) {} | 1898 | \\ if (0) {} |
| 1820 | \\} | 1899 | \\} |
| 1821 | , | 1900 | , |
| 1822 | ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'", | 1901 | ".tmp_source.zig:2:9: error: expected type 'bool', found 'comptime_int'", |
| 1823 | ); | 1902 | ); |
| 1824 | 1903 | ||
| 1825 | cases.add( | 1904 | cases.add( |
| ... | @@ -2422,16 +2501,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2422,16 +2501,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2422 | ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'", | 2501 | ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'", |
| 2423 | ); | 2502 | ); |
| 2424 | 2503 | ||
| 2425 | cases.add( | ||
| 2426 | "implicit cast from f64 to f32", | ||
| 2427 | \\const x : f64 = 1.0; | ||
| 2428 | \\const y : f32 = x; | ||
| 2429 | \\ | ||
| 2430 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | ||
| 2431 | , | ||
| 2432 | ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'", | ||
| 2433 | ); | ||
| 2434 | |||
| 2435 | cases.add( | 2504 | cases.add( |
| 2436 | "colliding invalid top level functions", | 2505 | "colliding invalid top level functions", |
| 2437 | \\fn func() bogus {} | 2506 | \\fn func() bogus {} |
| ... | @@ -3174,6 +3243,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3174,6 +3243,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3174 | \\fn something() anyerror!void { } | 3243 | \\fn something() anyerror!void { } |
| 3175 | , | 3244 | , |
| 3176 | ".tmp_source.zig:2:5: error: expected type 'void', found 'anyerror'", | 3245 | ".tmp_source.zig:2:5: error: expected type 'void', found 'anyerror'", |
| 3246 | ".tmp_source.zig:1:15: note: return type declared here", | ||
| 3177 | ); | 3247 | ); |
| 3178 | 3248 | ||
| 3179 | cases.add( | 3249 | cases.add( |
| ... | @@ -4049,16 +4119,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -4049,16 +4119,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4049 | ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod", | 4119 | ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod", |
| 4050 | ); | 4120 | ); |
| 4051 | 4121 | ||
| 4052 | cases.add( | ||
| 4053 | "cast negative value to unsigned integer", | ||
| 4054 | \\comptime { | ||
| 4055 | \\ const value: i32 = -1; | ||
| 4056 | \\ const unsigned = @intCast(u32, value); | ||
| 4057 | \\} | ||
| 4058 | , | ||
| 4059 | ".tmp_source.zig:3:22: error: attempt to cast negative value to unsigned integer", | ||
| 4060 | ); | ||
| 4061 | |||
| 4062 | cases.add( | 4122 | cases.add( |
| 4063 | "compile-time division by zero", | 4123 | "compile-time division by zero", |
| 4064 | \\comptime { | 4124 | \\comptime { |
| ... | @@ -4081,16 +4141,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -4081,16 +4141,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4081 | ".tmp_source.zig:4:17: error: division by zero", | 4141 | ".tmp_source.zig:4:17: error: division by zero", |
| 4082 | ); | 4142 | ); |
| 4083 | 4143 | ||
| 4084 | cases.add( | ||
| 4085 | "compile-time integer cast truncates bits", | ||
| 4086 | \\comptime { | ||
| 4087 | \\ const spartan_count: u16 = 300; | ||
| 4088 | \\ const byte = @intCast(u8, spartan_count); | ||
| 4089 | \\} | ||
| 4090 | , | ||
| 4091 | ".tmp_source.zig:3:18: error: cast from 'u16' to 'u8' truncates bits", | ||
| 4092 | ); | ||
| 4093 | |||
| 4094 | cases.add( | 4144 | cases.add( |
| 4095 | "@setRuntimeSafety twice for same scope", | 4145 | "@setRuntimeSafety twice for same scope", |
| 4096 | \\export fn foo() void { | 4146 | \\export fn foo() void { |
| ... | @@ -5206,4 +5256,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -5206,4 +5256,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5206 | , | 5256 | , |
| 5207 | ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic", | 5257 | ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic", |
| 5208 | ); | 5258 | ); |
| 5259 | |||
| 5260 | cases.add( | ||
| 5261 | "unsupported modifier at start of asm output constraint", | ||
| 5262 | \\export fn foo() void { | ||
| 5263 | \\ var bar: u32 = 3; | ||
| 5264 | \\ asm volatile ("" : [baz]"+r"(bar) : : ""); | ||
| 5265 | \\} | ||
| 5266 | , | ||
| 5267 | ".tmp_source.zig:3:5: error: invalid modifier starting output constraint for 'baz': '+', only '=' is supported. Compiler TODO: see https://github.com/ziglang/zig/issues/215", | ||
| 5268 | ); | ||
| 5269 | |||
| 5270 | cases.add( | ||
| 5271 | "comptime_int in asm input", | ||
| 5272 | \\export fn foo() void { | ||
| 5273 | \\ asm volatile ("" : : [bar]"r"(3) : ""); | ||
| 5274 | \\} | ||
| 5275 | , | ||
| 5276 | ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_int", | ||
| 5277 | ); | ||
| 5278 | |||
| 5279 | cases.add( | ||
| 5280 | "comptime_float in asm input", | ||
| 5281 | \\export fn foo() void { | ||
| 5282 | \\ asm volatile ("" : : [bar]"r"(3.17) : ""); | ||
| 5283 | \\} | ||
| 5284 | , | ||
| 5285 | ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float", | ||
| 5286 | ); | ||
| 5209 | } | 5287 | } |
test/runtime_safety.zig+10| ... | @@ -275,6 +275,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { | ... | @@ -275,6 +275,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 275 | \\} | 275 | \\} |
| 276 | ); | 276 | ); |
| 277 | 277 | ||
| 278 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening", | ||
| 279 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | ||
| 280 | \\ @import("std").os.exit(126); | ||
| 281 | \\} | ||
| 282 | \\pub fn main() void { | ||
| 283 | \\ var value: c_short = -1; | ||
| 284 | \\ var casted = @intCast(u32, value); | ||
| 285 | \\} | ||
| 286 | ); | ||
| 287 | |||
| 278 | cases.addRuntimeSafety("unwrap error", | 288 | cases.addRuntimeSafety("unwrap error", |
| 279 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | 289 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 280 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | 290 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { |