| 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 | 444 | "buffer.zig" |
| 445 | 445 | "build.zig" |
| 446 | 446 | "c/darwin.zig" |
| 447 | "c/freebsd.zig" | |
| 447 | 448 | "c/index.zig" |
| 448 | 449 | "c/linux.zig" |
| 449 | 450 | "c/windows.zig" |
| ... | ... | @@ -490,6 +491,7 @@ set(ZIG_STD_FILES |
| 490 | 491 | "heap.zig" |
| 491 | 492 | "index.zig" |
| 492 | 493 | "io.zig" |
| 494 | "io/seekable_stream.zig" | |
| 493 | 495 | "json.zig" |
| 494 | 496 | "lazy_init.zig" |
| 495 | 497 | "linked_list.zig" |
| ... | ... | @@ -582,6 +584,10 @@ set(ZIG_STD_FILES |
| 582 | 584 | "os/linux/vdso.zig" |
| 583 | 585 | "os/linux/x86_64.zig" |
| 584 | 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 | 591 | "os/path.zig" |
| 586 | 592 | "os/time.zig" |
| 587 | 593 | "os/windows/advapi32.zig" |
| ... | ... | @@ -617,6 +623,16 @@ set(ZIG_STD_FILES |
| 617 | 623 | "special/compiler_rt/fixunstfdi.zig" |
| 618 | 624 | "special/compiler_rt/fixunstfsi.zig" |
| 619 | 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 | 636 | "special/compiler_rt/floattidf.zig" |
| 621 | 637 | "special/compiler_rt/floattisf.zig" |
| 622 | 638 | "special/compiler_rt/floattitf.zig" |
README.md+71-30| ... | ... | @@ -42,33 +42,71 @@ clarity. |
| 42 | 42 | * In addition to creating executables, creating a C library is a primary use |
| 43 | 43 | case. You can export an auto-generated .h file. |
| 44 | 44 | |
| 45 | ### Support Table | |
| 46 | ||
| 47 | Freestanding means that you do not directly interact with the OS | |
| 48 | or you are writing your own OS. | |
| 49 | ||
| 50 | Note that if you use libc or other libraries to interact with the OS, | |
| 51 | that counts as "freestanding" for the purposes of this table. | |
| 52 | ||
| 53 | | | freestanding | linux | macosx | windows | other | | |
| 54 | |-------------|--------------|---------|---------|---------|---------| | |
| 55 | |i386 | OK | planned | OK | planned | planned | | |
| 56 | |x86_64 | OK | OK | OK | OK | planned | | |
| 57 | |arm | OK | planned | planned | planned | planned | | |
| 58 | |bpf | OK | planned | N/A | N/A | planned | | |
| 59 | |hexagon | OK | planned | N/A | N/A | planned | | |
| 60 | |mips | OK | planned | N/A | N/A | planned | | |
| 61 | |powerpc | OK | planned | N/A | N/A | planned | | |
| 62 | |r600 | OK | planned | N/A | N/A | planned | | |
| 63 | |amdgcn | OK | planned | N/A | N/A | planned | | |
| 64 | |sparc | OK | planned | N/A | N/A | planned | | |
| 65 | |s390x | OK | planned | N/A | N/A | planned | | |
| 66 | |spir | OK | planned | N/A | N/A | planned | | |
| 67 | |lanai | OK | planned | N/A | N/A | planned | | |
| 68 | |wasm32 | planned | N/A | N/A | N/A | N/A | | |
| 69 | |wasm64 | planned | N/A | N/A | N/A | N/A | | |
| 70 | |riscv32 | planned | planned | N/A | N/A | planned | | |
| 71 | |riscv64 | planned | planned | N/A | N/A | planned | | |
| 45 | ### Supported Targets | |
| 46 | ||
| 47 | #### Tier 1 Support | |
| 48 | ||
| 49 | * Not only can Zig generate machine code for these targets, but the standard | |
| 50 | library cross-platform abstractions have implementations for these targets. | |
| 51 | Thus it is practical to write a pure Zig application with no dependency on | |
| 52 | libc. | |
| 53 | * The CI server automatically tests these targets on every commit to master | |
| 54 | branch, and updates ziglang.org/download with links to pre-built binaries. | |
| 55 | * These targets have debug info capabilities and therefore produce stack | |
| 56 | traces on failed assertions. | |
| 57 | ||
| 58 | #### Tier 2 Support | |
| 59 | ||
| 60 | * There may be some standard library implementations, but many abstractions | |
| 61 | will give an "Unsupported OS" compile error. One can link with libc or other | |
| 62 | libraries to fill in the gaps in the standard library. | |
| 63 | * These targets are known to work, but are not automatically tested, so there | |
| 64 | are occasional regressions. | |
| 65 | * Some tests may be disabled for these targets as we work toward Tier 1 | |
| 66 | support. | |
| 67 | ||
| 68 | #### Tier 3 Support | |
| 69 | ||
| 70 | * The standard library has little to no knowledge of the existence of this | |
| 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 | 111 | ## Community |
| 74 | 112 | |
| ... | ... | @@ -133,7 +171,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows |
| 133 | 171 | *Note: Stage 2 compiler is not complete. Beta users of Zig should use the |
| 134 | 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 | 178 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install |
| ... | ... | @@ -145,11 +184,13 @@ binary. |
| 145 | 184 | |
| 146 | 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 | 187 | *Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is |
| 151 | 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 | 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 | 297 | ); |
| 298 | 298 | |
| 299 | 299 | exe.linkSystemLibrary("pthread"); |
| 300 | } else if (exe.target.isDarwin()) { | |
| 300 | } else if (exe.target.isDarwin() or exe.target.isFreeBSD()) { | |
| 301 | 301 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { |
| 302 | 302 | // Compiler is GCC. |
| 303 | 303 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); |
ci/azure/linux_script+3| ... | ... | @@ -34,6 +34,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 34 | 34 | |
| 35 | 35 | SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1) |
| 36 | 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 | 40 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" |
| 38 | 41 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" |
| 39 | 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 | 98 | |
| 99 | 99 | SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1) |
| 100 | 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 | 104 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" |
| 102 | 105 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" |
| 103 | 106 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" |
ci/azure/windows_install+1| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | set -x |
| 4 | 4 | set -e |
| 5 | 5 | |
| 6 | pacman -Su --needed --noconfirm | |
| 6 | 7 | pacman -S --needed --noconfirm wget p7zip python3-pip |
| 7 | 8 | pip install s3cmd |
| 8 | 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 | 25 | |
| 26 | 26 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) |
| 27 | 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 | 31 | echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL" |
| 29 | 32 | echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM" |
| 30 | 33 | echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE" |
cmake/Findclang.cmake+2| ... | ... | @@ -30,6 +30,7 @@ else() |
| 30 | 30 | /usr/lib/llvm/8/include |
| 31 | 31 | /usr/lib/llvm-8/include |
| 32 | 32 | /usr/lib/llvm-8.0/include |
| 33 | /usr/local/llvm80/include | |
| 33 | 34 | /mingw64/include) |
| 34 | 35 | |
| 35 | 36 | macro(FIND_AND_ADD_CLANG_LIB _libname_) |
| ... | ... | @@ -40,6 +41,7 @@ else() |
| 40 | 41 | /usr/lib/llvm/8/lib |
| 41 | 42 | /usr/lib/llvm-8/lib |
| 42 | 43 | /usr/lib/llvm-8.0/lib |
| 44 | /usr/local/llvm80/lib | |
| 43 | 45 | /mingw64/lib |
| 44 | 46 | /c/msys64/mingw64/lib |
| 45 | 47 | c:\\msys64\\mingw64\\lib) |
cmake/Findlld.cmake+7-1| ... | ... | @@ -9,9 +9,14 @@ |
| 9 | 9 | find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h |
| 10 | 10 | PATHS |
| 11 | 11 | /usr/lib/llvm-8.0/include |
| 12 | /usr/local/llvm80/include | |
| 12 | 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 | 20 | if(EXISTS ${LLD_LIBRARY}) |
| 16 | 21 | set(LLD_LIBRARIES ${LLD_LIBRARY}) |
| 17 | 22 | else() |
| ... | ... | @@ -20,6 +25,7 @@ else() |
| 20 | 25 | find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_} |
| 21 | 26 | PATHS |
| 22 | 27 | /usr/lib/llvm-8.0/lib |
| 28 | /usr/local/llvm80/lib | |
| 23 | 29 | /mingw64/lib |
| 24 | 30 | /c/msys64/mingw64/lib |
| 25 | 31 | c:/msys64/mingw64/lib) |
cmake/Findllvm.cmake+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | # LLVM_LIBDIRS |
| 9 | 9 | |
| 10 | 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 | 12 | PATHS |
| 13 | 13 | "/mingw64/bin" |
| 14 | 14 | "/c/msys64/mingw64/bin" |
deps/lld/ELF/OutputSections.cpp+1-1| ... | ... | @@ -95,7 +95,7 @@ void OutputSection::addSection(InputSection *IS) { |
| 95 | 95 | Flags = IS->Flags; |
| 96 | 96 | } else { |
| 97 | 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 | 99 | if ((Flags & Mask) != (IS->Flags & Mask)) |
| 100 | 100 | error("incompatible section flags for " + Name + "\n>>> " + toString(IS) + |
| 101 | 101 | ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name + |
doc/langref.html.in+166-101| ... | ... | @@ -8,7 +8,13 @@ |
| 8 | 8 | body{ |
| 9 | 9 | background-color:#111; |
| 10 | 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 | 19 | a { |
| 14 | 20 | color: #88f; |
| ... | ... | @@ -159,7 +165,7 @@ const std = @import("std"); |
| 159 | 165 | |
| 160 | 166 | pub fn main() !void { |
| 161 | 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 | 169 | // If this program encounters pipe failure when printing to stdout, exit |
| 164 | 170 | // with an error. |
| 165 | 171 | try stdout_file.write("Hello, world!\n"); |
| ... | ... | @@ -3273,13 +3279,13 @@ const err = (error {FileNotFound}).FileNotFound; |
| 3273 | 3279 | This becomes useful when using {#link|Inferred Error Sets#}. |
| 3274 | 3280 | </p> |
| 3275 | 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 | 3283 | This is the error set that contains all errors in the entire compilation unit. |
| 3278 | 3284 | It is a superset of all other error sets and a subset of none of them. |
| 3279 | 3285 | </p> |
| 3280 | 3286 | <p> |
| 3281 | 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 | 3289 | assert to make sure the error value is in fact in the destination error set. |
| 3284 | 3290 | </p> |
| 3285 | 3291 | <p> |
| ... | ... | @@ -4264,13 +4270,21 @@ fn foo() i32 { |
| 4264 | 4270 | return 1234; |
| 4265 | 4271 | } |
| 4266 | 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 | 4274 | {#code_begin|test#} |
| 4269 | test "ignoring expression value" { | |
| 4270 | foo(); | |
| 4275 | test "void is ignored" { | |
| 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 | 4288 | {#code_end#} |
| 4275 | 4289 | {#header_close#} |
| 4276 | 4290 | |
| ... | ... | @@ -5155,6 +5169,34 @@ fn seq(c: u8) void { |
| 5155 | 5169 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 5156 | 5170 | </p> |
| 5157 | 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 | 5200 | {#header_open|@ArgType#} |
| 5159 | 5201 | <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre> |
| 5160 | 5202 | <p> |
| ... | ... | @@ -5227,6 +5269,7 @@ fn seq(c: u8) void { |
| 5227 | 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 | 5270 | </p> |
| 5229 | 5271 | {#header_close#} |
| 5272 | ||
| 5230 | 5273 | {#header_open|@bitOffsetOf#} |
| 5231 | 5274 | <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> |
| 5232 | 5275 | <p> |
| ... | ... | @@ -5239,6 +5282,19 @@ fn seq(c: u8) void { |
| 5239 | 5282 | </p> |
| 5240 | 5283 | {#see_also|@byteOffsetOf#} |
| 5241 | 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 | 5298 | {#header_open|@breakpoint#} |
| 5243 | 5299 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> |
| 5244 | 5300 | <p> |
| ... | ... | @@ -5250,52 +5306,22 @@ fn seq(c: u8) void { |
| 5250 | 5306 | </p> |
| 5251 | 5307 | |
| 5252 | 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#} | |
| 5271 | {#header_open|@alignOf#} | |
| 5272 | <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre> | |
| 5310 | {#header_open|@bswap#} | |
| 5311 | <pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre> | |
| 5312 | <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p> | |
| 5273 | 5313 | <p> |
| 5274 | This function returns the number of bytes that this type should be aligned to | |
| 5275 | for the current target to match the C ABI. When the child type of a pointer has | |
| 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#}. | |
| 5314 | Swaps the byte order of the integer. This converts a big endian integer to a little endian integer, | |
| 5315 | and converts a little endian integer to a big endian integer. | |
| 5285 | 5316 | </p> |
| 5286 | {#see_also|Alignment#} | |
| 5287 | 5317 | {#header_close#} |
| 5288 | 5318 | |
| 5289 | {#header_open|@boolToInt#} | |
| 5290 | <pre>{#syntax#}@boolToInt(value: bool) u1{#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> | |
| 5319 | {#header_open|@byteOffsetOf#} | |
| 5320 | <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre> | |
| 5295 | 5321 | <p> |
| 5296 | If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#} | |
| 5297 | instead of {#syntax#}u1{#endsyntax#}. | |
| 5322 | Returns the byte offset of a field relative to its containing struct. | |
| 5298 | 5323 | </p> |
| 5324 | {#see_also|@bitOffsetOf#} | |
| 5299 | 5325 | {#header_close#} |
| 5300 | 5326 | |
| 5301 | 5327 | {#header_open|@bytesToSlice#} |
| ... | ... | @@ -5364,17 +5390,7 @@ comptime { |
| 5364 | 5390 | </p> |
| 5365 | 5391 | {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#} |
| 5366 | 5392 | {#header_close#} |
| 5367 | {#header_open|@cUndef#} | |
| 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#} | |
| 5393 | ||
| 5378 | 5394 | {#header_open|@clz#} |
| 5379 | 5395 | <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre> |
| 5380 | 5396 | <p> |
| ... | ... | @@ -5390,6 +5406,7 @@ comptime { |
| 5390 | 5406 | </p> |
| 5391 | 5407 | {#see_also|@ctz|@popCount#} |
| 5392 | 5408 | {#header_close#} |
| 5409 | ||
| 5393 | 5410 | {#header_open|@cmpxchgStrong#} |
| 5394 | 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 | 5412 | <p> |
| ... | ... | @@ -5445,6 +5462,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5445 | 5462 | <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 5446 | 5463 | {#see_also|Compile Variables|cmpxchgStrong#} |
| 5447 | 5464 | {#header_close#} |
| 5465 | ||
| 5448 | 5466 | {#header_open|@compileError#} |
| 5449 | 5467 | <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre> |
| 5450 | 5468 | <p> |
| ... | ... | @@ -5457,6 +5475,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5457 | 5475 | and {#syntax#}comptime{#endsyntax#} functions. |
| 5458 | 5476 | </p> |
| 5459 | 5477 | {#header_close#} |
| 5478 | ||
| 5460 | 5479 | {#header_open|@compileLog#} |
| 5461 | 5480 | <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre> |
| 5462 | 5481 | <p> |
| ... | ... | @@ -5511,6 +5530,7 @@ test "main" { |
| 5511 | 5530 | } |
| 5512 | 5531 | {#code_end#} |
| 5513 | 5532 | {#header_close#} |
| 5533 | ||
| 5514 | 5534 | {#header_open|@ctz#} |
| 5515 | 5535 | <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre> |
| 5516 | 5536 | <p> |
| ... | ... | @@ -5526,6 +5546,19 @@ test "main" { |
| 5526 | 5546 | </p> |
| 5527 | 5547 | {#see_also|@clz|@popCount#} |
| 5528 | 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 | 5562 | {#header_open|@divExact#} |
| 5530 | 5563 | <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 5531 | 5564 | <p> |
| ... | ... | @@ -5592,27 +5625,15 @@ test "main" { |
| 5592 | 5625 | {#see_also|@intToEnum#} |
| 5593 | 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 | 5628 | {#header_open|@errorName#} |
| 5604 | <pre>{#syntax#}@errorName(err: error) []u8{#endsyntax#}</pre> | |
| 5629 | <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre> | |
| 5605 | 5630 | <p> |
| 5606 | This function returns the string representation of an error. If an error | |
| 5607 | declaration is: | |
| 5608 | </p> | |
| 5609 | <pre>{#syntax#}error OutOfMem{#endsyntax#}</pre> | |
| 5610 | <p> | |
| 5611 | Then the string representation is {#syntax#}"OutOfMem"{#endsyntax#}. | |
| 5631 | This function returns the string representation of an error. The string representation | |
| 5632 | of {#syntax#}error.OutOfMem{#endsyntax#} is {#syntax#}"OutOfMem"{#endsyntax#}. | |
| 5612 | 5633 | </p> |
| 5613 | 5634 | <p> |
| 5614 | 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 | 5637 | error name table will be generated. |
| 5617 | 5638 | </p> |
| 5618 | 5639 | {#header_close#} |
| ... | ... | @@ -5627,13 +5648,14 @@ test "main" { |
| 5627 | 5648 | {#header_close#} |
| 5628 | 5649 | |
| 5629 | 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 | 5652 | <p> |
| 5632 | 5653 | Supports the following types: |
| 5633 | 5654 | </p> |
| 5634 | 5655 | <ul> |
| 5635 | <li>error unions</li> | |
| 5636 | <li>{#syntax#}E!void{#endsyntax#}</li> | |
| 5656 | <li>{#link|The Global Error Set#}</li> | |
| 5657 | <li>{#link|Error Set Type#}</li> | |
| 5658 | <li>{#link|Error Union Type#}</li> | |
| 5637 | 5659 | </ul> |
| 5638 | 5660 | <p> |
| 5639 | 5661 | Converts an error to the integer representation of an error. |
| ... | ... | @@ -5645,6 +5667,14 @@ test "main" { |
| 5645 | 5667 | {#see_also|@intToError#} |
| 5646 | 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 | 5678 | {#header_open|@export#} |
| 5649 | 5679 | <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre> |
| 5650 | 5680 | <p> |
| ... | ... | @@ -5713,6 +5743,7 @@ test "main" { |
| 5713 | 5743 | This function is only valid within function scope. |
| 5714 | 5744 | </p> |
| 5715 | 5745 | {#header_close#} |
| 5746 | ||
| 5716 | 5747 | {#header_open|@handle#} |
| 5717 | 5748 | <pre>{#syntax#}@handle(){#endsyntax#}</pre> |
| 5718 | 5749 | <p> |
| ... | ... | @@ -5723,6 +5754,7 @@ test "main" { |
| 5723 | 5754 | This function is only valid within an async function scope. |
| 5724 | 5755 | </p> |
| 5725 | 5756 | {#header_close#} |
| 5757 | ||
| 5726 | 5758 | {#header_open|@import#} |
| 5727 | 5759 | <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre> |
| 5728 | 5760 | <p> |
| ... | ... | @@ -5743,6 +5775,7 @@ test "main" { |
| 5743 | 5775 | </ul> |
| 5744 | 5776 | {#see_also|Compile Variables|@embedFile#} |
| 5745 | 5777 | {#header_close#} |
| 5778 | ||
| 5746 | 5779 | {#header_open|@inlineCall#} |
| 5747 | 5780 | <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre> |
| 5748 | 5781 | <p> |
| ... | ... | @@ -5788,7 +5821,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5788 | 5821 | {#header_open|@intToError#} |
| 5789 | 5822 | <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre> |
| 5790 | 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 | 5825 | </p> |
| 5793 | 5826 | <p> |
| 5794 | 5827 | It is generally recommended to avoid this |
| ... | ... | @@ -5822,6 +5855,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5822 | 5855 | bit count for an integer type is {#syntax#}65535{#endsyntax#}. |
| 5823 | 5856 | </p> |
| 5824 | 5857 | {#header_close#} |
| 5858 | ||
| 5825 | 5859 | {#header_open|@memberCount#} |
| 5826 | 5860 | <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre> |
| 5827 | 5861 | <p> |
| ... | ... | @@ -5848,6 +5882,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5848 | 5882 | <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre> |
| 5849 | 5883 | <p>Returns the field type of a struct or union.</p> |
| 5850 | 5884 | {#header_close#} |
| 5885 | ||
| 5851 | 5886 | {#header_open|@memcpy#} |
| 5852 | 5887 | <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre> |
| 5853 | 5888 | <p> |
| ... | ... | @@ -5866,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5866 | 5901 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5867 | 5902 | mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5868 | 5903 | {#header_close#} |
| 5904 | ||
| 5869 | 5905 | {#header_open|@memset#} |
| 5870 | 5906 | <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre> |
| 5871 | 5907 | <p> |
| ... | ... | @@ -5883,6 +5919,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5883 | 5919 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5884 | 5920 | mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5885 | 5921 | {#header_close#} |
| 5922 | ||
| 5886 | 5923 | {#header_open|@mod#} |
| 5887 | 5924 | <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 5888 | 5925 | <p> |
| ... | ... | @@ -5896,6 +5933,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5896 | 5933 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p> |
| 5897 | 5934 | {#see_also|@rem#} |
| 5898 | 5935 | {#header_close#} |
| 5936 | ||
| 5899 | 5937 | {#header_open|@mulWithOverflow#} |
| 5900 | 5938 | <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> |
| 5901 | 5939 | <p> |
| ... | ... | @@ -5904,6 +5942,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre> |
| 5904 | 5942 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 5905 | 5943 | </p> |
| 5906 | 5944 | {#header_close#} |
| 5945 | ||
| 5907 | 5946 | {#header_open|@newStackCall#} |
| 5908 | 5947 | <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre> |
| 5909 | 5948 | <p> |
| ... | ... | @@ -5940,6 +5979,7 @@ fn targetFunction(x: i32) usize { |
| 5940 | 5979 | } |
| 5941 | 5980 | {#code_end#} |
| 5942 | 5981 | {#header_close#} |
| 5982 | ||
| 5943 | 5983 | {#header_open|@noInlineCall#} |
| 5944 | 5984 | <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre> |
| 5945 | 5985 | <p> |
| ... | ... | @@ -5962,6 +6002,7 @@ fn add(a: i32, b: i32) i32 { |
| 5962 | 6002 | </p> |
| 5963 | 6003 | {#see_also|@inlineCall#} |
| 5964 | 6004 | {#header_close#} |
| 6005 | ||
| 5965 | 6006 | {#header_open|@OpaqueType#} |
| 5966 | 6007 | <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre> |
| 5967 | 6008 | <p> |
| ... | ... | @@ -5985,6 +6026,7 @@ test "call foo" { |
| 5985 | 6026 | } |
| 5986 | 6027 | {#code_end#} |
| 5987 | 6028 | {#header_close#} |
| 6029 | ||
| 5988 | 6030 | {#header_open|@panic#} |
| 5989 | 6031 | <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre> |
| 5990 | 6032 | <p> |
| ... | ... | @@ -6001,6 +6043,7 @@ test "call foo" { |
| 6001 | 6043 | </ul> |
| 6002 | 6044 | {#see_also|Root Source File#} |
| 6003 | 6045 | {#header_close#} |
| 6046 | ||
| 6004 | 6047 | {#header_open|@popCount#} |
| 6005 | 6048 | <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre> |
| 6006 | 6049 | <p>Counts the number of bits set in an integer.</p> |
| ... | ... | @@ -6011,12 +6054,14 @@ test "call foo" { |
| 6011 | 6054 | </p> |
| 6012 | 6055 | {#see_also|@ctz|@clz#} |
| 6013 | 6056 | {#header_close#} |
| 6057 | ||
| 6014 | 6058 | {#header_open|@ptrCast#} |
| 6015 | 6059 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> |
| 6016 | 6060 | <p> |
| 6017 | 6061 | Converts a pointer of one type to a pointer of another type. |
| 6018 | 6062 | </p> |
| 6019 | 6063 | {#header_close#} |
| 6064 | ||
| 6020 | 6065 | {#header_open|@ptrToInt#} |
| 6021 | 6066 | <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre> |
| 6022 | 6067 | <p> |
| ... | ... | @@ -6031,6 +6076,7 @@ test "call foo" { |
| 6031 | 6076 | <p>To convert the other way, use {#link|@intToPtr#}</p> |
| 6032 | 6077 | |
| 6033 | 6078 | {#header_close#} |
| 6079 | ||
| 6034 | 6080 | {#header_open|@rem#} |
| 6035 | 6081 | <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre> |
| 6036 | 6082 | <p> |
| ... | ... | @@ -6044,6 +6090,7 @@ test "call foo" { |
| 6044 | 6090 | <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p> |
| 6045 | 6091 | {#see_also|@mod#} |
| 6046 | 6092 | {#header_close#} |
| 6093 | ||
| 6047 | 6094 | {#header_open|@returnAddress#} |
| 6048 | 6095 | <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre> |
| 6049 | 6096 | <p> |
| ... | ... | @@ -6064,19 +6111,14 @@ test "call foo" { |
| 6064 | 6111 | Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes. |
| 6065 | 6112 | </p> |
| 6066 | 6113 | {#header_close#} |
| 6114 | ||
| 6067 | 6115 | {#header_open|@setCold#} |
| 6068 | 6116 | <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre> |
| 6069 | 6117 | <p> |
| 6070 | 6118 | Tells the optimizer that a function is rarely called. |
| 6071 | 6119 | </p> |
| 6072 | 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 | 6122 | {#header_open|@setEvalBranchQuota#} |
| 6081 | 6123 | <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre> |
| 6082 | 6124 | <p> |
| ... | ... | @@ -6111,6 +6153,7 @@ test "foo" { |
| 6111 | 6153 | |
| 6112 | 6154 | {#see_also|comptime#} |
| 6113 | 6155 | {#header_close#} |
| 6156 | ||
| 6114 | 6157 | {#header_open|@setFloatMode#} |
| 6115 | 6158 | <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre> |
| 6116 | 6159 | <p> |
| ... | ... | @@ -6145,6 +6188,7 @@ pub const FloatMode = enum { |
| 6145 | 6188 | </p> |
| 6146 | 6189 | {#see_also|Floating Point Operations#} |
| 6147 | 6190 | {#header_close#} |
| 6191 | ||
| 6148 | 6192 | {#header_open|@setGlobalLinkage#} |
| 6149 | 6193 | <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre> |
| 6150 | 6194 | <p> |
| ... | ... | @@ -6152,6 +6196,15 @@ pub const FloatMode = enum { |
| 6152 | 6196 | </p> |
| 6153 | 6197 | {#see_also|Compile Variables#} |
| 6154 | 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 | 6208 | {#header_open|@shlExact#} |
| 6156 | 6209 | <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> |
| 6157 | 6210 | <p> |
| ... | ... | @@ -6164,6 +6217,7 @@ pub const FloatMode = enum { |
| 6164 | 6217 | </p> |
| 6165 | 6218 | {#see_also|@shrExact|@shlWithOverflow#} |
| 6166 | 6219 | {#header_close#} |
| 6220 | ||
| 6167 | 6221 | {#header_open|@shlWithOverflow#} |
| 6168 | 6222 | <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre> |
| 6169 | 6223 | <p> |
| ... | ... | @@ -6177,6 +6231,7 @@ pub const FloatMode = enum { |
| 6177 | 6231 | </p> |
| 6178 | 6232 | {#see_also|@shlExact|@shrExact#} |
| 6179 | 6233 | {#header_close#} |
| 6234 | ||
| 6180 | 6235 | {#header_open|@shrExact#} |
| 6181 | 6236 | <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre> |
| 6182 | 6237 | <p> |
| ... | ... | @@ -6218,6 +6273,7 @@ pub const FloatMode = enum { |
| 6218 | 6273 | This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead. |
| 6219 | 6274 | </p> |
| 6220 | 6275 | {#header_close#} |
| 6276 | ||
| 6221 | 6277 | {#header_open|@subWithOverflow#} |
| 6222 | 6278 | <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre> |
| 6223 | 6279 | <p> |
| ... | ... | @@ -6226,12 +6282,14 @@ pub const FloatMode = enum { |
| 6226 | 6282 | If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. |
| 6227 | 6283 | </p> |
| 6228 | 6284 | {#header_close#} |
| 6285 | ||
| 6229 | 6286 | {#header_open|@tagName#} |
| 6230 | 6287 | <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre> |
| 6231 | 6288 | <p> |
| 6232 | 6289 | Converts an enum value or union value to a slice of bytes representing the name. |
| 6233 | 6290 | </p> |
| 6234 | 6291 | {#header_close#} |
| 6292 | ||
| 6235 | 6293 | {#header_open|@TagType#} |
| 6236 | 6294 | <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre> |
| 6237 | 6295 | <p> |
| ... | ... | @@ -6241,6 +6299,7 @@ pub const FloatMode = enum { |
| 6241 | 6299 | For a union, returns the enum type that is used to store the tag value. |
| 6242 | 6300 | </p> |
| 6243 | 6301 | {#header_close#} |
| 6302 | ||
| 6244 | 6303 | {#header_open|@This#} |
| 6245 | 6304 | <pre>{#syntax#}@This() type{#endsyntax#}</pre> |
| 6246 | 6305 | <p> |
| ... | ... | @@ -6276,6 +6335,7 @@ fn List(comptime T: type) type { |
| 6276 | 6335 | <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details. |
| 6277 | 6336 | </p> |
| 6278 | 6337 | {#header_close#} |
| 6338 | ||
| 6279 | 6339 | {#header_open|@truncate#} |
| 6280 | 6340 | <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre> |
| 6281 | 6341 | <p> |
| ... | ... | @@ -6300,6 +6360,7 @@ const b: u8 = @truncate(u8, a); |
| 6300 | 6360 | </p> |
| 6301 | 6361 | |
| 6302 | 6362 | {#header_close#} |
| 6363 | ||
| 6303 | 6364 | {#header_open|@typeId#} |
| 6304 | 6365 | <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre> |
| 6305 | 6366 | <p> |
| ... | ... | @@ -6334,6 +6395,7 @@ pub const TypeId = enum { |
| 6334 | 6395 | }; |
| 6335 | 6396 | {#code_end#} |
| 6336 | 6397 | {#header_close#} |
| 6398 | ||
| 6337 | 6399 | {#header_open|@typeInfo#} |
| 6338 | 6400 | <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre> |
| 6339 | 6401 | <p> |
| ... | ... | @@ -6516,6 +6578,7 @@ pub const TypeInfo = union(TypeId) { |
| 6516 | 6578 | }; |
| 6517 | 6579 | {#code_end#} |
| 6518 | 6580 | {#header_close#} |
| 6581 | ||
| 6519 | 6582 | {#header_open|@typeName#} |
| 6520 | 6583 | <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre> |
| 6521 | 6584 | <p> |
| ... | ... | @@ -6523,6 +6586,7 @@ pub const TypeInfo = union(TypeId) { |
| 6523 | 6586 | </p> |
| 6524 | 6587 | |
| 6525 | 6588 | {#header_close#} |
| 6589 | ||
| 6526 | 6590 | {#header_open|@typeOf#} |
| 6527 | 6591 | <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre> |
| 6528 | 6592 | <p> |
| ... | ... | @@ -6532,6 +6596,7 @@ pub const TypeInfo = union(TypeId) { |
| 6532 | 6596 | |
| 6533 | 6597 | {#header_close#} |
| 6534 | 6598 | {#header_close#} |
| 6599 | ||
| 6535 | 6600 | {#header_open|Build Mode#} |
| 6536 | 6601 | <p> |
| 6537 | 6602 | Zig has four build modes: |
| ... | ... | @@ -6659,7 +6724,7 @@ fn foo(x: []const u8) u8 { |
| 6659 | 6724 | {#header_close#} |
| 6660 | 6725 | {#header_open|Cast Negative Number to Unsigned Integer#} |
| 6661 | 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 | 6728 | comptime { |
| 6664 | 6729 | const value: i32 = -1; |
| 6665 | 6730 | const unsigned = @intCast(u32, value); |
| ... | ... | @@ -6681,7 +6746,7 @@ pub fn main() void { |
| 6681 | 6746 | {#header_close#} |
| 6682 | 6747 | {#header_open|Cast Truncates Data#} |
| 6683 | 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 | 6750 | comptime { |
| 6686 | 6751 | const spartan_count: u16 = 300; |
| 6687 | 6752 | const byte = @intCast(u8, spartan_count); |
| ... | ... | @@ -7830,11 +7895,11 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr |
| 7830 | 7895 | ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)? |
| 7831 | 7896 | |
| 7832 | 7897 | SuffixExpr |
| 7833 | &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets | |
| 7834 | / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)* | |
| 7898 | &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments | |
| 7899 | / PrimaryTypeExpr (SuffixOp / FnCallArguments)* | |
| 7835 | 7900 | |
| 7836 | 7901 | PrimaryTypeExpr |
| 7837 | &lt;- BUILTININDENTIFIER FnCallArgumnets | |
| 7902 | &lt;- BUILTINIDENTIFIER FnCallArguments | |
| 7838 | 7903 | / CHAR_LITERAL |
| 7839 | 7904 | / ContainerDecl |
| 7840 | 7905 | / ErrorSetDecl |
| ... | ... | @@ -7884,11 +7949,11 @@ AsmOutput &lt;- COLON AsmOutputList AsmInput? |
| 7884 | 7949 | |
| 7885 | 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 | 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 | 7958 | # *** Helper grammar *** |
| 7894 | 7959 | BreakLabel &lt;- COLON IDENTIFIER |
| ... | ... | @@ -8013,7 +8078,7 @@ SuffixOp |
| 8013 | 8078 | |
| 8014 | 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 | 8083 | # Ptr specific |
| 8019 | 8084 | ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET |
| ... | ... | @@ -8090,7 +8155,7 @@ STRINGLITERAL |
| 8090 | 8155 | IDENTIFIER |
| 8091 | 8156 | &lt;- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip |
| 8092 | 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 | 8161 | AMPERSAND &lt;- '&' ![=] skip |
| ... | ... | @@ -8109,9 +8174,9 @@ DOT2 &lt;- '..' ![.] skip |
| 8109 | 8174 | DOT3 &lt;- '...' skip |
| 8110 | 8175 | DOTASTERISK &lt;- '.*' skip |
| 8111 | 8176 | DOTQUESTIONMARK &lt;- '.?' skip |
| 8112 | EQUAL &lt;- '=' ![>=] skip | |
| 8177 | EQUAL &lt;- '=' ![&gt;=] skip | |
| 8113 | 8178 | EQUALEQUAL &lt;- '==' skip |
| 8114 | EQUALRARROW &lt;- '=>' skip | |
| 8179 | EQUALRARROW &lt;- '=&gt;' skip | |
| 8115 | 8180 | EXCLAMATIONMARK &lt;- '!' ![=] skip |
| 8116 | 8181 | EXCLAMATIONMARKEQUAL &lt;- '!=' skip |
| 8117 | 8182 | LARROW &lt;- '&lt;' ![&lt;=] skip |
| ... | ... | @@ -8121,11 +8186,11 @@ LARROWEQUAL &lt;- '&lt;=' skip |
| 8121 | 8186 | LBRACE &lt;- '{' skip |
| 8122 | 8187 | LBRACKET &lt;- '[' skip |
| 8123 | 8188 | LPAREN &lt;- '(' skip |
| 8124 | MINUS &lt;- '-' ![%=>] skip | |
| 8189 | MINUS &lt;- '-' ![%=&gt;] skip | |
| 8125 | 8190 | MINUSEQUAL &lt;- '-=' skip |
| 8126 | 8191 | MINUSPERCENT &lt;- '-%' ![=] skip |
| 8127 | 8192 | MINUSPERCENTEQUAL &lt;- '-%=' skip |
| 8128 | MINUSRARROW &lt;- '->' skip | |
| 8193 | MINUSRARROW &lt;- '-&gt;' skip | |
| 8129 | 8194 | PERCENT &lt;- '%' ![=] skip |
| 8130 | 8195 | PERCENTEQUAL &lt;- '%=' skip |
| 8131 | 8196 | PIPE &lt;- '|' ![|=] skip |
| ... | ... | @@ -8137,10 +8202,10 @@ PLUSEQUAL &lt;- '+=' skip |
| 8137 | 8202 | PLUSPERCENT &lt;- '+%' ![=] skip |
| 8138 | 8203 | PLUSPERCENTEQUAL &lt;- '+%=' skip |
| 8139 | 8204 | QUESTIONMARK &lt;- '?' skip |
| 8140 | RARROW &lt;- '>' ![>=] skip | |
| 8141 | RARROW2 &lt;- '>>' ![=] skip | |
| 8142 | RARROW2EQUAL &lt;- '>>=' skip | |
| 8143 | RARROWEQUAL &lt;- '>=' skip | |
| 8205 | RARROW &lt;- '&gt;' ![&gt;=] skip | |
| 8206 | RARROW2 &lt;- '&gt;&gt;' ![=] skip | |
| 8207 | RARROW2EQUAL &lt;- '&gt;&gt;=' skip | |
| 8208 | RARROWEQUAL &lt;- '&gt;=' skip | |
| 8144 | 8209 | RBRACE &lt;- '}' skip |
| 8145 | 8210 | RBRACKET &lt;- ']' skip |
| 8146 | 8211 | RPAREN &lt;- ')' skip |
example/guess_number/main.zig+5-5| ... | ... | @@ -15,7 +15,7 @@ pub fn main() !void { |
| 15 | 15 | std.debug.warn("unable to seed random number generator: {}", err); |
| 16 | 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 | 19 | var prng = std.rand.DefaultPrng.init(seed); |
| 20 | 20 | |
| 21 | 21 | const answer = prng.random.range(u8, 0, 100) + 1; |
| ... | ... | @@ -24,15 +24,15 @@ pub fn main() !void { |
| 24 | 24 | try stdout.print("\nGuess a number between 1 and 100: "); |
| 25 | 25 | var line_buf: [20]u8 = undefined; |
| 26 | 26 | |
| 27 | const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) { | |
| 28 | error.InputTooLong => { | |
| 27 | const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) { | |
| 28 | error.OutOfMemory => { | |
| 29 | 29 | try stdout.print("Input too long.\n"); |
| 30 | 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 | 36 | try stdout.print("Invalid number.\n"); |
| 37 | 37 | continue; |
| 38 | 38 | }; |
example/hello_world/hello.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn main() !void { |
| 4 | 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 | 6 | // If this program encounters pipe failure when printing to stdout, exit |
| 7 | 7 | // with an error. |
| 8 | 8 | try stdout_file.write("Hello, world!\n"); |
src-self-hosted/compilation.zig+2-1| ... | ... | @@ -55,7 +55,7 @@ pub const ZigCompiler = struct { |
| 55 | 55 | |
| 56 | 56 | var seed_bytes: [@sizeOf(u64)]u8 = undefined; |
| 57 | 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 | 60 | return ZigCompiler{ |
| 61 | 61 | .loop = loop, |
| ... | ... | @@ -300,6 +300,7 @@ pub const Compilation = struct { |
| 300 | 300 | UserResourceLimitReached, |
| 301 | 301 | InvalidUtf8, |
| 302 | 302 | BadPathName, |
| 303 | DeviceBusy, | |
| 303 | 304 | }; |
| 304 | 305 | |
| 305 | 306 | pub const Event = union(enum) { |
src-self-hosted/libc_installation.zig+1-1| ... | ... | @@ -172,7 +172,7 @@ pub const LibCInstallation = struct { |
| 172 | 172 | try group.call(findNativeStaticLibDir, self, loop); |
| 173 | 173 | try group.call(findNativeDynamicLinker, self, loop); |
| 174 | 174 | }, |
| 175 | builtin.Os.macosx => { | |
| 175 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 176 | 176 | self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); |
| 177 | 177 | }, |
| 178 | 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 | 311 | pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { |
| 312 | 312 | const env = self.getEnviron(); |
| 313 | 313 | const arch = self.getArch(); |
| 314 | switch (env) { | |
| 315 | builtin.Environ.android => { | |
| 316 | if (self.is64bit()) { | |
| 317 | return "/system/bin/linker64"; | |
| 318 | } else { | |
| 319 | return "/system/bin/linker"; | |
| 320 | } | |
| 314 | const os = self.getOs(); | |
| 315 | switch (os) { | |
| 316 | builtin.Os.freebsd => { | |
| 317 | return "/libexec/ld-elf.so.1"; | |
| 321 | 318 | }, |
| 322 | builtin.Environ.gnux32 => { | |
| 323 | if (arch == builtin.Arch.x86_64) { | |
| 324 | return "/libx32/ld-linux-x32.so.2"; | |
| 319 | builtin.Os.linux => { | |
| 320 | switch (env) { | |
| 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 | }, | |
| 327 | builtin.Environ.musl, | |
| 328 | builtin.Environ.musleabi, | |
| 329 | builtin.Environ.musleabihf, | |
| 330 | => { | |
| 331 | if (arch == builtin.Arch.x86_64) { | |
| 332 | return "/lib/ld-musl-x86_64.so.1"; | |
| 343 | switch (arch) { | |
| 344 | builtin.Arch.i386, | |
| 345 | builtin.Arch.sparc, | |
| 346 | builtin.Arch.sparcel, | |
| 347 | => return "/lib/ld-linux.so.2", | |
| 348 | ||
| 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 => {}, | |
| 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, | |
| 471 | else => return null, | |
| 468 | 472 | } |
| 469 | 473 | } |
| 470 | 474 | |
| ... | ... | @@ -513,6 +517,7 @@ pub const Target = union(enum) { |
| 513 | 517 | |
| 514 | 518 | builtin.Os.linux, |
| 515 | 519 | builtin.Os.macosx, |
| 520 | builtin.Os.freebsd, | |
| 516 | 521 | builtin.Os.openbsd, |
| 517 | 522 | builtin.Os.zen, |
| 518 | 523 | => switch (id) { |
| ... | ... | @@ -547,7 +552,6 @@ pub const Target = union(enum) { |
| 547 | 552 | builtin.Os.ananas, |
| 548 | 553 | builtin.Os.cloudabi, |
| 549 | 554 | builtin.Os.dragonfly, |
| 550 | builtin.Os.freebsd, | |
| 551 | 555 | builtin.Os.fuchsia, |
| 552 | 556 | builtin.Os.ios, |
| 553 | 557 | builtin.Os.kfreebsd, |
src/all_types.hpp+13-1| ... | ... | @@ -605,7 +605,6 @@ enum CastOp { |
| 605 | 605 | CastOpFloatToInt, |
| 606 | 606 | CastOpBoolToInt, |
| 607 | 607 | CastOpResizeSlice, |
| 608 | CastOpBytesToSlice, | |
| 609 | 608 | CastOpNumLitToConcrete, |
| 610 | 609 | CastOpErrSet, |
| 611 | 610 | CastOpBitCast, |
| ... | ... | @@ -1415,6 +1414,7 @@ enum BuiltinFnId { |
| 1415 | 1414 | BuiltinFnIdErrorReturnTrace, |
| 1416 | 1415 | BuiltinFnIdAtomicRmw, |
| 1417 | 1416 | BuiltinFnIdAtomicLoad, |
| 1417 | BuiltinFnIdBswap, | |
| 1418 | 1418 | }; |
| 1419 | 1419 | |
| 1420 | 1420 | struct BuiltinFnEntry { |
| ... | ... | @@ -1487,6 +1487,7 @@ enum ZigLLVMFnId { |
| 1487 | 1487 | ZigLLVMFnIdFloor, |
| 1488 | 1488 | ZigLLVMFnIdCeil, |
| 1489 | 1489 | ZigLLVMFnIdSqrt, |
| 1490 | ZigLLVMFnIdBswap, | |
| 1490 | 1491 | }; |
| 1491 | 1492 | |
| 1492 | 1493 | enum AddSubMul { |
| ... | ... | @@ -1516,6 +1517,9 @@ struct ZigLLVMFnKey { |
| 1516 | 1517 | uint32_t bit_count; |
| 1517 | 1518 | bool is_signed; |
| 1518 | 1519 | } overflow_arithmetic; |
| 1520 | struct { | |
| 1521 | uint32_t bit_count; | |
| 1522 | } bswap; | |
| 1519 | 1523 | } data; |
| 1520 | 1524 | }; |
| 1521 | 1525 | |
| ... | ... | @@ -2158,6 +2162,7 @@ enum IrInstructionId { |
| 2158 | 2162 | IrInstructionIdMergeErrRetTraces, |
| 2159 | 2163 | IrInstructionIdMarkErrRetTracePtr, |
| 2160 | 2164 | IrInstructionIdSqrt, |
| 2165 | IrInstructionIdBswap, | |
| 2161 | 2166 | IrInstructionIdErrSetCast, |
| 2162 | 2167 | IrInstructionIdToBytes, |
| 2163 | 2168 | IrInstructionIdFromBytes, |
| ... | ... | @@ -3251,6 +3256,13 @@ struct IrInstructionCheckRuntimeScope { |
| 3251 | 3256 | IrInstruction *is_comptime; |
| 3252 | 3257 | }; |
| 3253 | 3258 | |
| 3259 | struct IrInstructionBswap { | |
| 3260 | IrInstruction base; | |
| 3261 | ||
| 3262 | IrInstruction *type; | |
| 3263 | IrInstruction *op; | |
| 3264 | }; | |
| 3265 | ||
| 3254 | 3266 | static const size_t slice_ptr_index = 0; |
| 3255 | 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 | 401 | } |
| 402 | 402 | |
| 403 | 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 | 407 | assert(!type_is_invalid(child_type)); |
| 407 | 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 | 1060 | } |
| 1060 | 1061 | zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481", |
| 1061 | 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 | 1064 | return type_size(g, fn_type_id->return_type) > 16; |
| 1064 | 1065 | } |
| 1065 | 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 | 1620 | case ZigTypeIdUnion: |
| 1620 | 1621 | case ZigTypeIdFn: |
| 1621 | 1622 | case ZigTypeIdPromise: |
| 1622 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | |
| 1623 | return g->builtin_types.entry_invalid; | |
| 1624 | if (type_requires_comptime(type_entry)) { | |
| 1625 | add_node_error(g, param_node->data.param_decl.type, | |
| 1626 | buf_sprintf("parameter of type '%s' must be declared comptime", | |
| 1627 | buf_ptr(&type_entry->name))); | |
| 1628 | return g->builtin_types.entry_invalid; | |
| 1623 | switch (type_requires_comptime(g, type_entry)) { | |
| 1624 | case ReqCompTimeNo: | |
| 1625 | break; | |
| 1626 | case ReqCompTimeYes: | |
| 1627 | add_node_error(g, param_node->data.param_decl.type, | |
| 1628 | buf_sprintf("parameter of type '%s' must be declared comptime", | |
| 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 | 1634 | break; |
| 1631 | 1635 | } |
| ... | ... | @@ -1711,10 +1715,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1711 | 1715 | case ZigTypeIdUnion: |
| 1712 | 1716 | case ZigTypeIdFn: |
| 1713 | 1717 | case ZigTypeIdPromise: |
| 1714 | if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown))) | |
| 1715 | return g->builtin_types.entry_invalid; | |
| 1716 | if (type_requires_comptime(fn_type_id.return_type)) { | |
| 1717 | return get_generic_fn_type(g, &fn_type_id); | |
| 1718 | switch (type_requires_comptime(g, fn_type_id.return_type)) { | |
| 1719 | case ReqCompTimeInvalid: | |
| 1720 | return g->builtin_types.entry_invalid; | |
| 1721 | case ReqCompTimeYes: | |
| 1722 | return get_generic_fn_type(g, &fn_type_id); | |
| 1723 | case ReqCompTimeNo: | |
| 1724 | break; | |
| 1718 | 1725 | } |
| 1719 | 1726 | break; |
| 1720 | 1727 | } |
| ... | ... | @@ -2560,8 +2567,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2560 | 2567 | static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2561 | 2568 | assert(struct_type->id == ZigTypeIdStruct); |
| 2562 | 2569 | |
| 2563 | Error err; | |
| 2564 | ||
| 2565 | 2570 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) |
| 2566 | 2571 | return ErrorSemanticAnalyzeFail; |
| 2567 | 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 | 2624 | buf_sprintf("enums, not structs, support field assignment")); |
| 2620 | 2625 | } |
| 2621 | 2626 | |
| 2622 | if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) { | |
| 2623 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | |
| 2624 | continue; | |
| 2625 | } | |
| 2626 | ||
| 2627 | if (type_requires_comptime(field_type)) { | |
| 2628 | struct_type->data.structure.requires_comptime = true; | |
| 2627 | switch (type_requires_comptime(g, field_type)) { | |
| 2628 | case ReqCompTimeYes: | |
| 2629 | struct_type->data.structure.requires_comptime = true; | |
| 2630 | break; | |
| 2631 | case ReqCompTimeInvalid: | |
| 2632 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | |
| 2633 | continue; | |
| 2634 | case ReqCompTimeNo: | |
| 2635 | break; | |
| 2629 | 2636 | } |
| 2630 | 2637 | |
| 2631 | 2638 | if (!type_has_bits(field_type)) |
| ... | ... | @@ -2674,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2674 | 2681 | assert(decl_node->type == NodeTypeContainerDecl); |
| 2675 | 2682 | assert(struct_type->di_type); |
| 2676 | 2683 | |
| 2684 | size_t field_count = struct_type->data.structure.src_field_count; | |
| 2677 | 2685 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2678 | 2686 | struct_type->data.structure.abi_alignment = 1; |
| 2679 | } | |
| 2680 | ||
| 2681 | size_t field_count = struct_type->data.structure.src_field_count; | |
| 2682 | for (size_t i = 0; i < field_count; i += 1) { | |
| 2683 | TypeStructField *field = &struct_type->data.structure.fields[i]; | |
| 2684 | ||
| 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; | |
| 2687 | for (size_t i = 0; i < field_count; i += 1) { | |
| 2688 | TypeStructField *field = &struct_type->data.structure.fields[i]; | |
| 2689 | if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { | |
| 2690 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | |
| 2691 | break; | |
| 2692 | } | |
| 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)) | |
| 2696 | continue; | |
| 2714 | if (!type_has_bits(field->type_entry)) | |
| 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 | 2717 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { |
| 2701 | 2718 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2702 | 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 | 2723 | assert(this_field_align != 0); |
| 2707 | if (this_field_align > struct_type->data.structure.abi_alignment) { | |
| 2708 | struct_type->data.structure.abi_alignment = this_field_align; | |
| 2709 | } | |
| 2724 | } | |
| 2725 | // alignment of structs is the alignment of the most-aligned field | |
| 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 | 2908 | } |
| 2891 | 2909 | union_field->type_entry = field_type; |
| 2892 | 2910 | |
| 2893 | if (type_requires_comptime(field_type)) { | |
| 2894 | union_type->data.unionation.requires_comptime = true; | |
| 2911 | switch (type_requires_comptime(g, field_type)) { | |
| 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 | 2922 | if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { |
| 2899 | 2923 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, |
| 2900 | 2924 | buf_sprintf("non-enum union field assignment")); |
| ... | ... | @@ -4579,7 +4603,10 @@ void find_libc_include_path(CodeGen *g) { |
| 4579 | 4603 | fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); |
| 4580 | 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 | 4610 | g->libc_include_dir = get_posix_libc_include_path(); |
| 4584 | 4611 | } else { |
| 4585 | 4612 | fprintf(stderr, "Unable to determine libc include path.\n" |
| ... | ... | @@ -4627,6 +4654,8 @@ void find_libc_lib_path(CodeGen *g) { |
| 4627 | 4654 | |
| 4628 | 4655 | } else if (g->zig_target.os == OsLinux) { |
| 4629 | 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 | 4659 | } else { |
| 4631 | 4660 | zig_panic("Unable to determine libc lib path."); |
| 4632 | 4661 | } |
| ... | ... | @@ -4639,6 +4668,8 @@ void find_libc_lib_path(CodeGen *g) { |
| 4639 | 4668 | return; |
| 4640 | 4669 | } else if (g->zig_target.os == OsLinux) { |
| 4641 | 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 | 4673 | } else { |
| 4643 | 4674 | zig_panic("Unable to determine libc static lib path."); |
| 4644 | 4675 | } |
| ... | ... | @@ -5089,7 +5120,10 @@ bool type_has_bits(ZigType *type_entry) { |
| 5089 | 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 | 5127 | switch (type_entry->id) { |
| 5094 | 5128 | case ZigTypeIdInvalid: |
| 5095 | 5129 | case ZigTypeIdOpaque: |
| ... | ... | @@ -5102,27 +5136,25 @@ bool type_requires_comptime(ZigType *type_entry) { |
| 5102 | 5136 | case ZigTypeIdNamespace: |
| 5103 | 5137 | case ZigTypeIdBoundFn: |
| 5104 | 5138 | case ZigTypeIdArgTuple: |
| 5105 | return true; | |
| 5139 | return ReqCompTimeYes; | |
| 5106 | 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 | 5142 | case ZigTypeIdStruct: |
| 5109 | assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); | |
| 5110 | return type_entry->data.structure.requires_comptime; | |
| 5143 | return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; | |
| 5111 | 5144 | case ZigTypeIdUnion: |
| 5112 | assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); | |
| 5113 | return type_entry->data.unionation.requires_comptime; | |
| 5145 | return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; | |
| 5114 | 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 | 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 | 5150 | case ZigTypeIdPointer: |
| 5119 | 5151 | if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { |
| 5120 | return false; | |
| 5152 | return ReqCompTimeNo; | |
| 5121 | 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 | 5156 | case ZigTypeIdFn: |
| 5125 | return type_entry->data.fn.is_generic; | |
| 5157 | return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo; | |
| 5126 | 5158 | case ZigTypeIdEnum: |
| 5127 | 5159 | case ZigTypeIdErrorSet: |
| 5128 | 5160 | case ZigTypeIdBool: |
| ... | ... | @@ -5131,7 +5163,7 @@ bool type_requires_comptime(ZigType *type_entry) { |
| 5131 | 5163 | case ZigTypeIdVoid: |
| 5132 | 5164 | case ZigTypeIdUnreachable: |
| 5133 | 5165 | case ZigTypeIdPromise: |
| 5134 | return false; | |
| 5166 | return ReqCompTimeNo; | |
| 5135 | 5167 | } |
| 5136 | 5168 | zig_unreachable(); |
| 5137 | 5169 | } |
| ... | ... | @@ -6090,6 +6122,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { |
| 6090 | 6122 | return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089; |
| 6091 | 6123 | case ZigLLVMFnIdSqrt: |
| 6092 | 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 | 6127 | case ZigLLVMFnIdOverflowArithmetic: |
| 6094 | 6128 | return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) + |
| 6095 | 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 | 6142 | return a.data.clz.bit_count == b.data.clz.bit_count; |
| 6109 | 6143 | case ZigLLVMFnIdPopCount: |
| 6110 | 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 | 6147 | case ZigLLVMFnIdFloor: |
| 6112 | 6148 | case ZigLLVMFnIdCeil: |
| 6113 | 6149 | case ZigLLVMFnIdSqrt: |
src/analyze.hpp+7-1| ... | ... | @@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node); |
| 87 | 87 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); |
| 88 | 88 | void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); |
| 89 | 89 | AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); |
| 90 | bool type_requires_comptime(ZigType *type_entry); | |
| 91 | 90 | Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); |
| 92 | 91 | Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); |
| 93 | 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 | 215 | |
| 217 | 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 | 225 | #endif |
src/buffer.hpp+10| ... | ... | @@ -181,5 +181,15 @@ static inline Slice<uint8_t> buf_to_slice(Buf *buf) { |
| 181 | 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 | 195 | #endif |
src/cache_hash.cpp+4-2| ... | ... | @@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 352 | 352 | // if the mtime matches we can trust the digest |
| 353 | 353 | OsFile this_file; |
| 354 | 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 | 356 | os_file_close(ch->manifest_file); |
| 356 | return err; | |
| 357 | return ErrorCacheUnavailable; | |
| 357 | 358 | } |
| 358 | 359 | OsTimeStamp actual_mtime; |
| 359 | 360 | if ((err = os_file_mtime(this_file, &actual_mtime))) { |
| ... | ... | @@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 392 | 393 | for (; file_i < input_file_count; file_i += 1) { |
| 393 | 394 | CacheHashFile *chf = &ch->files.at(file_i); |
| 394 | 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 | 397 | os_file_close(ch->manifest_file); |
| 396 | return err; | |
| 398 | return ErrorCacheUnavailable; | |
| 397 | 399 | } |
| 398 | 400 | } |
| 399 | 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 | 129 | Buf *src_dir = buf_alloc(); |
| 130 | 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 | 137 | g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename)); |
| 133 | 138 | g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig"); |
| 134 | 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 | 1650 | zig_unreachable(); |
| 1646 | 1651 | } |
| 1647 | 1652 | |
| 1648 | if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt && | |
| 1653 | if (actual_type->id == ZigTypeIdInt && | |
| 1649 | 1654 | !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && |
| 1650 | 1655 | want_runtime_safety) |
| 1651 | 1656 | { |
| ... | ... | @@ -2877,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2877 | 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 | 2885 | return cast_instruction->tmp_ptr; |
| 2907 | 2886 | } |
| 2908 | 2887 | case CastOpIntToFloat: |
| ... | ... | @@ -3660,6 +3639,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru |
| 3660 | 3639 | AsmOutput *asm_output = asm_expr->output_list.at(i); |
| 3661 | 3640 | bool is_return = (asm_output->return_type != nullptr); |
| 3662 | 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 | 3649 | if (is_return) { |
| 3664 | 3650 | buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); |
| 3665 | 3651 | } else { |
| ... | ... | @@ -3679,14 +3665,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru |
| 3679 | 3665 | } |
| 3680 | 3666 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { |
| 3681 | 3667 | AsmInput *asm_input = asm_expr->input_list.at(i); |
| 3668 | buf_replace(asm_input->constraint, ',', '|'); | |
| 3682 | 3669 | IrInstruction *ir_input = instruction->input_list[i]; |
| 3683 | 3670 | buf_append_buf(&constraint_buf, asm_input->constraint); |
| 3684 | 3671 | if (total_index + 1 < total_constraint_count) { |
| 3685 | 3672 | buf_append_char(&constraint_buf, ','); |
| 3686 | 3673 | } |
| 3687 | 3674 | |
| 3688 | param_types[param_index] = ir_input->value.type->type_ref; | |
| 3689 | param_values[param_index] = ir_llvm_value(g, ir_input); | |
| 3675 | ZigType *const type = ir_input->value.type; | |
| 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 | 3693 | for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { |
| 3692 | 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 | 3707 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false); |
| 3706 | 3708 | |
| 3707 | 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), | |
| 3709 | buf_ptr(&constraint_buf), is_volatile, false); | |
| 3710 | LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), | |
| 3711 | buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT); | |
| 3710 | 3712 | |
| 3711 | 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 | 3788 | n_args = 1; |
| 3787 | 3789 | key.id = ZigLLVMFnIdPopCount; |
| 3788 | 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 | 3796 | } else { |
| 3790 | 3797 | zig_unreachable(); |
| 3791 | 3798 | } |
| ... | ... | @@ -5070,6 +5077,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr |
| 5070 | 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 | 5103 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 5074 | 5104 | AstNode *source_node = instruction->source_node; |
| 5075 | 5105 | Scope *scope = instruction->scope; |
| ... | ... | @@ -5307,6 +5337,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5307 | 5337 | return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); |
| 5308 | 5338 | case IrInstructionIdSqrt: |
| 5309 | 5339 | return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); |
| 5340 | case IrInstructionIdBswap: | |
| 5341 | return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); | |
| 5310 | 5342 | } |
| 5311 | 5343 | zig_unreachable(); |
| 5312 | 5344 | } |
| ... | ... | @@ -6258,8 +6290,14 @@ static void do_code_gen(CodeGen *g) { |
| 6258 | 6290 | } |
| 6259 | 6291 | if (ir_get_var_is_comptime(var)) |
| 6260 | 6292 | continue; |
| 6261 | if (type_requires_comptime(var->value->type)) | |
| 6262 | continue; | |
| 6293 | switch (type_requires_comptime(g, var->value->type)) { | |
| 6294 | case ReqCompTimeInvalid: | |
| 6295 | zig_unreachable(); | |
| 6296 | case ReqCompTimeYes: | |
| 6297 | continue; | |
| 6298 | case ReqCompTimeNo: | |
| 6299 | break; | |
| 6300 | } | |
| 6263 | 6301 | |
| 6264 | 6302 | if (var->src_arg_index == SIZE_MAX) { |
| 6265 | 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 | 6761 | create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); |
| 6724 | 6762 | create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); |
| 6725 | 6763 | create_builtin_fn(g, BuiltinFnIdThis, "This", 0); |
| 6764 | create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2); | |
| 6726 | 6765 | } |
| 6727 | 6766 | |
| 6728 | 6767 | static const char *bool_to_str(bool b) { |
| ... | ... | @@ -8149,7 +8188,11 @@ void codegen_build_and_link(CodeGen *g) { |
| 8149 | 8188 | os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); |
| 8150 | 8189 | |
| 8151 | 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 | 8196 | exit(1); |
| 8154 | 8197 | } |
| 8155 | 8198 |
src/error.cpp+1| ... | ... | @@ -33,6 +33,7 @@ const char *err_str(Error err) { |
| 33 | 33 | case ErrorSharingViolation: return "sharing violation"; |
| 34 | 34 | case ErrorPipeBusy: return "pipe busy"; |
| 35 | 35 | case ErrorPrimitiveTypeNotFound: return "primitive type not found"; |
| 36 | case ErrorCacheUnavailable: return "cache unavailable"; | |
| 36 | 37 | } |
| 37 | 38 | return "(invalid error)"; |
| 38 | 39 | } |
src/error.hpp+1| ... | ... | @@ -35,6 +35,7 @@ enum Error { |
| 35 | 35 | ErrorSharingViolation, |
| 36 | 36 | ErrorPipeBusy, |
| 37 | 37 | ErrorPrimitiveTypeNotFound, |
| 38 | ErrorCacheUnavailable, | |
| 38 | 39 | }; |
| 39 | 40 | |
| 40 | 41 | const char *err_str(Error err); |
src/ir.cpp+601-206| ... | ... | @@ -34,6 +34,7 @@ struct IrAnalyze { |
| 34 | 34 | size_t old_bb_index; |
| 35 | 35 | size_t instruction_index; |
| 36 | 36 | ZigType *explicit_return_type; |
| 37 | AstNode *explicit_return_type_source_node; | |
| 37 | 38 | ZigList<IrInstruction *> src_implicit_return_type_list; |
| 38 | 39 | IrBasicBlock *const_predecessor_bb; |
| 39 | 40 | }; |
| ... | ... | @@ -66,6 +67,8 @@ enum ConstCastResultId { |
| 66 | 67 | struct ConstCastOnly; |
| 67 | 68 | struct ConstCastArg { |
| 68 | 69 | size_t arg_index; |
| 70 | ZigType *actual_param_type; | |
| 71 | ZigType *expected_param_type; | |
| 69 | 72 | ConstCastOnly *child; |
| 70 | 73 | }; |
| 71 | 74 | |
| ... | ... | @@ -138,6 +141,11 @@ struct ConstCastErrSetMismatch { |
| 138 | 141 | ZigList<ErrorTableEntry *> missing_errors; |
| 139 | 142 | }; |
| 140 | 143 | |
| 144 | enum UndefAllowed { | |
| 145 | UndefOk, | |
| 146 | UndefBad, | |
| 147 | }; | |
| 148 | ||
| 141 | 149 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); |
| 142 | 150 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); |
| 143 | 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 | 159 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); |
| 152 | 160 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); |
| 153 | 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 | 163 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 156 | 164 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 157 | 165 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| 158 | 166 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| 159 | 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 | 171 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 162 | 172 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | ... | @@ -847,6 +857,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { |
| 847 | 857 | return IrInstructionIdSqrt; |
| 848 | 858 | } |
| 849 | 859 | |
| 860 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { | |
| 861 | return IrInstructionIdBswap; | |
| 862 | } | |
| 863 | ||
| 850 | 864 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { |
| 851 | 865 | return IrInstructionIdCheckRuntimeScope; |
| 852 | 866 | } |
| ... | ... | @@ -2696,6 +2710,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 2696 | 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 | 2724 | static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { |
| 2700 | 2725 | IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node); |
| 2701 | 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 | 4705 | IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); |
| 4681 | 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 | 4724 | zig_unreachable(); |
| 4685 | 4725 | } |
| ... | ... | @@ -5530,6 +5570,15 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5530 | 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 | 5583 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) { |
| 5535 | 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 | 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 | 7383 | static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) { |
| 7384 | Error err; | |
| 7320 | 7385 | ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val); |
| 7321 | 7386 | assert(val != nullptr); |
| 7322 | 7387 | assert(const_val->type->id == ZigTypeIdPointer); |
| 7323 | 7388 | ZigType *expected_type = const_val->type->data.pointer.child_type; |
| 7324 | 7389 | if (!types_have_same_zig_comptime_repr(val->type, expected_type)) { |
| 7325 | ir_add_error_node(ira, source_node, | |
| 7326 | buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955")); | |
| 7327 | return nullptr; | |
| 7390 | if ((err = eval_comptime_ptr_reinterpret(ira, source_node, const_val))) | |
| 7391 | return nullptr; | |
| 7392 | return const_ptr_pointee_unchecked(ira->codegen, const_val); | |
| 7328 | 7393 | } |
| 7329 | 7394 | return val; |
| 7330 | 7395 | } |
| ... | ... | @@ -8063,15 +8128,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 8063 | 8128 | return false; |
| 8064 | 8129 | } |
| 8065 | 8130 | |
| 8066 | ConstExprValue *const_val = &instruction->value; | |
| 8067 | assert(const_val->special != ConstValSpecialRuntime); | |
| 8131 | ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad); | |
| 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 | 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 | 8278 | } else if (other_type->id == ZigTypeIdInt && const_val_is_int) { |
| 8076 | 8279 | if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) { |
| 8077 | 8280 | Buf *val_buf = buf_alloc(); |
| ... | ... | @@ -8484,6 +8687,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8484 | 8687 | if (arg_child.id != ConstCastResultIdOk) { |
| 8485 | 8688 | result.id = ConstCastResultIdFnArg; |
| 8486 | 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 | 8692 | result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1); |
| 8488 | 8693 | *result.data.fn_arg.child = arg_child; |
| 8489 | 8694 | return result; |
| ... | ... | @@ -9134,7 +9339,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9134 | 9339 | const_val->type = new_type; |
| 9135 | 9340 | break; |
| 9136 | 9341 | case CastOpResizeSlice: |
| 9137 | case CastOpBytesToSlice: | |
| 9138 | 9342 | // can't do it |
| 9139 | 9343 | zig_unreachable(); |
| 9140 | 9344 | case CastOpIntToFloat: |
| ... | ... | @@ -9191,7 +9395,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 9191 | 9395 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) |
| 9192 | 9396 | { |
| 9193 | 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 | 9400 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 9197 | 9401 | source_instr->source_node, wanted_type); |
| ... | ... | @@ -9453,11 +9657,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio |
| 9453 | 9657 | return const_instr; |
| 9454 | 9658 | } |
| 9455 | 9659 | |
| 9456 | enum UndefAllowed { | |
| 9457 | UndefOk, | |
| 9458 | UndefBad, | |
| 9459 | }; | |
| 9460 | ||
| 9461 | 9660 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { |
| 9462 | 9661 | switch (value->value.special) { |
| 9463 | 9662 | case ConstValSpecialStatic: |
| ... | ... | @@ -10014,7 +10213,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 10014 | 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 | 10218 | if (instr_is_comptime(target)) { |
| 10020 | 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 | 10533 | } |
| 10335 | 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 | 10545 | case ConstCastResultIdFnAlign: // TODO |
| 10338 | 10546 | case ConstCastResultIdFnCC: // TODO |
| 10339 | 10547 | case ConstCastResultIdFnVarArgs: // TODO |
| ... | ... | @@ -10341,7 +10549,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10341 | 10549 | case ConstCastResultIdFnReturnType: // TODO |
| 10342 | 10550 | case ConstCastResultIdFnArgCount: // TODO |
| 10343 | 10551 | case ConstCastResultIdFnGenericArgCount: // TODO |
| 10344 | case ConstCastResultIdFnArg: // TODO | |
| 10345 | 10552 | case ConstCastResultIdFnArgNoAlias: // TODO |
| 10346 | 10553 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO |
| 10347 | 10554 | case ConstCastResultIdAsyncAllocatorType: // TODO |
| ... | ... | @@ -10370,6 +10577,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10370 | 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 | 10695 | // widening conversion |
| 10374 | 10696 | if (wanted_type->id == ZigTypeIdInt && |
| 10375 | 10697 | actual_type->id == ZigTypeIdInt && |
| ... | ... | @@ -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 | 10797 | // cast from null literal to maybe type |
| 10517 | 10798 | if (wanted_type->id == ZigTypeIdOptional && |
| 10518 | 10799 | actual_type->id == ZigTypeIdNull) |
| ... | ... | @@ -10520,23 +10801,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10520 | 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 | 10804 | // cast from [N]T to E![]const T |
| 10541 | 10805 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| 10542 | 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 | 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 | 10835 | // cast from typed number to integer or float literal. |
| 10620 | 10836 | // works when the number is known at compile time |
| 10621 | 10837 | if (instr_is_comptime(value) && |
| ... | ... | @@ -11014,8 +11230,12 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 11014 | 11230 | return ir_unreach_error(ira); |
| 11015 | 11231 | |
| 11016 | 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 | 11237 | return ir_unreach_error(ira); |
| 11238 | } | |
| 11019 | 11239 | |
| 11020 | 11240 | if (casted_value->value.special == ConstValSpecialRuntime && |
| 11021 | 11241 | casted_value->value.type->id == ZigTypeIdPointer && |
| ... | ... | @@ -11114,7 +11334,6 @@ static bool optional_value_is_null(ConstExprValue *val) { |
| 11114 | 11334 | } |
| 11115 | 11335 | |
| 11116 | 11336 | static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 11117 | Error err; | |
| 11118 | 11337 | IrInstruction *op1 = bin_op_instruction->op1->child; |
| 11119 | 11338 | if (type_is_invalid(op1->value.type)) |
| 11120 | 11339 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -11308,10 +11527,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11308 | 11527 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 11309 | 11528 | return ira->codegen->invalid_instruction; |
| 11310 | 11529 | |
| 11311 | if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown))) | |
| 11312 | return ira->codegen->invalid_instruction; | |
| 11530 | bool requires_comptime; | |
| 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 | 11543 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 11316 | 11544 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 11317 | 11545 | if (op1_val == nullptr) |
| ... | ... | @@ -12244,42 +12472,42 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12244 | 12472 | ZigType *result_type = casted_init_value->value.type; |
| 12245 | 12473 | if (type_is_invalid(result_type)) { |
| 12246 | 12474 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12247 | } else { | |
| 12248 | if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) { | |
| 12249 | result_type = ira->codegen->builtin_types.entry_invalid; | |
| 12250 | } | |
| 12475 | } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) { | |
| 12476 | ir_add_error_node(ira, source_node, | |
| 12477 | buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); | |
| 12478 | result_type = ira->codegen->builtin_types.entry_invalid; | |
| 12251 | 12479 | } |
| 12252 | 12480 | |
| 12253 | if (!type_is_invalid(result_type)) { | |
| 12254 | if (result_type->id == ZigTypeIdUnreachable || | |
| 12255 | result_type->id == ZigTypeIdOpaque) | |
| 12256 | { | |
| 12481 | switch (type_requires_comptime(ira->codegen, result_type)) { | |
| 12482 | case ReqCompTimeInvalid: | |
| 12483 | result_type = ira->codegen->builtin_types.entry_invalid; | |
| 12484 | break; | |
| 12485 | case ReqCompTimeYes: { | |
| 12486 | var_class_requires_const = true; | |
| 12487 | if (!var->gen_is_const && !is_comptime_var) { | |
| 12257 | 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 | 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 | 12501 | var_class_requires_const = true; |
| 12262 | if (!var->gen_is_const && !is_comptime_var) { | |
| 12263 | ir_add_error_node(ira, source_node, | |
| 12264 | buf_sprintf("variable of type '%s' must be const or comptime", | |
| 12265 | buf_ptr(&result_type->name))); | |
| 12502 | if (!var->src_is_const && !is_comptime_var) { | |
| 12503 | ErrorMsg *msg = ir_add_error_node(ira, source_node, | |
| 12504 | buf_sprintf("functions marked inline must be stored in const or comptime var")); | |
| 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 | 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 | 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 | 12978 | } |
| 12751 | 12979 | |
| 12752 | 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 | 12983 | ir_add_error(ira, casted_arg, |
| 12755 | 12984 | buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name))); |
| 12756 | 12985 | return false; |
| 12986 | case ReqCompTimeInvalid: | |
| 12987 | return false; | |
| 12988 | case ReqCompTimeNo: | |
| 12989 | break; | |
| 12757 | 12990 | } |
| 12758 | 12991 | |
| 12759 | 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 | 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))) | |
| 13230 | return ira->codegen->invalid_instruction; | |
| 13231 | ||
| 13232 | if (type_requires_comptime(specified_return_type)) { | |
| 13462 | switch (type_requires_comptime(ira->codegen, specified_return_type)) { | |
| 13463 | case ReqCompTimeYes: | |
| 13233 | 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 | 13473 | IrInstruction *async_allocator_inst = nullptr; |
| ... | ... | @@ -13485,18 +13721,56 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13485 | 13721 | return ErrorNone; |
| 13486 | 13722 | } |
| 13487 | 13723 | |
| 13488 | if (dst_size > src_size) { | |
| 13489 | ir_add_error_node(ira, source_node, | |
| 13490 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", | |
| 13491 | dst_size, buf_ptr(&pointee->type->name), src_size)); | |
| 13492 | return ErrorSemanticAnalyzeFail; | |
| 13724 | if (dst_size <= src_size) { | |
| 13725 | Buf buf = BUF_INIT; | |
| 13726 | buf_resize(&buf, src_size); | |
| 13727 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); | |
| 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; | |
| 13496 | buf_resize(&buf, src_size); | |
| 13497 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); | |
| 13498 | buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); | |
| 13499 | return ErrorNone; | |
| 13733 | switch (ptr_val->data.x_ptr.special) { | |
| 13734 | case ConstPtrSpecialInvalid: | |
| 13735 | zig_unreachable(); | |
| 13736 | case ConstPtrSpecialRef: { | |
| 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 | 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 | 14446 | |
| 14173 | 14447 | } else { |
| 14174 | 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 | 14451 | ir_add_error(ira, elem_index, |
| 14177 | 14452 | buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", |
| 14178 | 14453 | buf_ptr(&return_type->data.pointer.child_type->name))); |
| 14179 | 14454 | return ira->codegen->invalid_instruction; |
| 14455 | case ReqCompTimeInvalid: | |
| 14456 | return ira->codegen->invalid_instruction; | |
| 14457 | case ReqCompTimeNo: | |
| 14458 | break; | |
| 14180 | 14459 | } |
| 14181 | 14460 | if (ptr_align < abi_align) { |
| 14182 | 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 | 15512 | } |
| 15234 | 15513 | |
| 15235 | 15514 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { |
| 15236 | input_list[i] = asm_instruction->input_list[i]->child; | |
| 15237 | if (type_is_invalid(input_list[i]->value.type)) | |
| 15515 | IrInstruction *const input_value = asm_instruction->input_list[i]->child; | |
| 15516 | if (type_is_invalid(input_value->value.type)) | |
| 15238 | 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 | 15530 | IrInstruction *result = ir_build_asm(&ira->new_irb, |
| ... | ... | @@ -17850,6 +18139,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct |
| 17850 | 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 | 18148 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { |
| 17854 | 18149 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; |
| 17855 | 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 | 18173 | if (type_is_invalid(dest_type)) |
| 17879 | 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 | 18177 | ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); |
| 17883 | 18178 | return ira->codegen->invalid_instruction; |
| 17884 | 18179 | } |
| ... | ... | @@ -17887,20 +18182,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct |
| 17887 | 18182 | if (type_is_invalid(target->value.type)) |
| 17888 | 18183 | return ira->codegen->invalid_instruction; |
| 17889 | 18184 | |
| 17890 | if (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) { | |
| 18185 | if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) { | |
| 17899 | 18186 | ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'", |
| 17900 | 18187 | buf_ptr(&target->value.type->name))); |
| 17901 | 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 | 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 | 19513 | } |
| 19217 | 19514 | |
| 19218 | 19515 | static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { |
| 19219 | Error err; | |
| 19220 | 19516 | AstNode *proto_node = instruction->base.source_node; |
| 19221 | 19517 | assert(proto_node->type == NodeTypeFnProto); |
| 19222 | 19518 | |
| ... | ... | @@ -19255,11 +19551,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct |
| 19255 | 19551 | if (type_is_invalid(param_type_value->value.type)) |
| 19256 | 19552 | return ira->codegen->invalid_instruction; |
| 19257 | 19553 | ZigType *param_type = ir_resolve_type(ira, param_type_value); |
| 19258 | if (type_is_invalid(param_type)) | |
| 19259 | return ira->codegen->invalid_instruction; | |
| 19260 | if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown))) | |
| 19261 | return ira->codegen->invalid_instruction; | |
| 19262 | if (type_requires_comptime(param_type)) { | |
| 19554 | switch (type_requires_comptime(ira->codegen, param_type)) { | |
| 19555 | case ReqCompTimeYes: | |
| 19263 | 19556 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 19264 | 19557 | ir_add_error(ira, param_type_value, |
| 19265 | 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 | 19562 | param_info->type = param_type; |
| 19270 | 19563 | fn_type_id.next_param_index += 1; |
| 19271 | 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 | 19570 | if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 19274 | 19571 | ir_add_error(ira, param_type_value, |
| ... | ... | @@ -19711,6 +20008,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct |
| 19711 | 20008 | } |
| 19712 | 20009 | |
| 19713 | 20010 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { |
| 20011 | if (val->special == ConstValSpecialUndef) | |
| 20012 | val->special = ConstValSpecialStatic; | |
| 19714 | 20013 | assert(val->special == ConstValSpecialStatic); |
| 19715 | 20014 | switch (val->type->id) { |
| 19716 | 20015 | case ZigTypeIdInvalid: |
| ... | ... | @@ -19780,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19780 | 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 | 20084 | assert(val->special == ConstValSpecialStatic); |
| 19785 | 20085 | switch (val->type->id) { |
| 19786 | 20086 | case ZigTypeIdInvalid: |
| ... | ... | @@ -19797,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19797 | 20097 | case ZigTypeIdPromise: |
| 19798 | 20098 | zig_unreachable(); |
| 19799 | 20099 | case ZigTypeIdVoid: |
| 19800 | return; | |
| 20100 | return ErrorNone; | |
| 19801 | 20101 | case ZigTypeIdBool: |
| 19802 | 20102 | val->data.x_bool = (buf[0] != 0); |
| 19803 | return; | |
| 20103 | return ErrorNone; | |
| 19804 | 20104 | case ZigTypeIdInt: |
| 19805 | 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); | |
| 19807 | return; | |
| 20106 | ira->codegen->is_big_endian, val->type->data.integral.is_signed); | |
| 20107 | return ErrorNone; | |
| 19808 | 20108 | case ZigTypeIdFloat: |
| 19809 | float_read_ieee597(val, buf, codegen->is_big_endian); | |
| 19810 | return; | |
| 20109 | float_read_ieee597(val, buf, ira->codegen->is_big_endian); | |
| 20110 | return ErrorNone; | |
| 19811 | 20111 | case ZigTypeIdPointer: |
| 19812 | 20112 | { |
| 19813 | 20113 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 19814 | 20114 | BigInt bn; |
| 19815 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, | |
| 19816 | codegen->is_big_endian, false); | |
| 20115 | bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count, | |
| 20116 | ira->codegen->is_big_endian, false); | |
| 19817 | 20117 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); |
| 19818 | return; | |
| 20118 | return ErrorNone; | |
| 19819 | 20119 | } |
| 19820 | 20120 | case ZigTypeIdArray: |
| 19821 | 20121 | zig_panic("TODO buf_read_value_bytes array type"); |
| 19822 | 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 | 20154 | case ZigTypeIdOptional: |
| 19825 | 20155 | zig_panic("TODO buf_read_value_bytes maybe type"); |
| 19826 | 20156 | case ZigTypeIdErrorUnion: |
| ... | ... | @@ -19923,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 19923 | 20253 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); |
| 19924 | 20254 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); |
| 19925 | 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 | 20258 | return result; |
| 19928 | 20259 | } |
| 19929 | 20260 | |
| ... | ... | @@ -20093,6 +20424,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct |
| 20093 | 20424 | return ira->codegen->invalid_instruction; |
| 20094 | 20425 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) |
| 20095 | 20426 | return ira->codegen->invalid_instruction; |
| 20427 | if (!type_has_bits(child_type)) { | |
| 20428 | align_bytes = 0; | |
| 20429 | } | |
| 20096 | 20430 | } else { |
| 20097 | 20431 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) |
| 20098 | 20432 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -20692,6 +21026,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS |
| 20692 | 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 | 21086 | static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { |
| 20696 | 21087 | Error err; |
| 20697 | 21088 | IrInstruction *target = instruction->target->child; |
| ... | ... | @@ -21027,6 +21418,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21027 | 21418 | return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); |
| 21028 | 21419 | case IrInstructionIdSqrt: |
| 21029 | 21420 | return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); |
| 21421 | case IrInstructionIdBswap: | |
| 21422 | return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); | |
| 21030 | 21423 | case IrInstructionIdIntToErr: |
| 21031 | 21424 | return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); |
| 21032 | 21425 | case IrInstructionIdErrToInt: |
| ... | ... | @@ -21063,6 +21456,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ |
| 21063 | 21456 | ZigFn *fn_entry = exec_fn_entry(old_exec); |
| 21064 | 21457 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 21065 | 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 | 21461 | ira->old_irb.codegen = codegen; |
| 21068 | 21462 | ira->old_irb.exec = old_exec; |
| ... | ... | @@ -21247,6 +21641,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21247 | 21641 | case IrInstructionIdCoroPromise: |
| 21248 | 21642 | case IrInstructionIdPromiseResultType: |
| 21249 | 21643 | case IrInstructionIdSqrt: |
| 21644 | case IrInstructionIdBswap: | |
| 21250 | 21645 | case IrInstructionIdAtomicLoad: |
| 21251 | 21646 | case IrInstructionIdIntCast: |
| 21252 | 21647 | case IrInstructionIdFloatCast: |
src/ir_print.cpp+15| ... | ... | @@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { |
| 1323 | 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 | 1338 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1327 | 1339 | ir_print_prefix(irp, instruction); |
| 1328 | 1340 | switch (instruction->id) { |
| ... | ... | @@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1736 | 1748 | case IrInstructionIdSqrt: |
| 1737 | 1749 | ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); |
| 1738 | 1750 | break; |
| 1751 | case IrInstructionIdBswap: | |
| 1752 | ir_print_bswap(irp, (IrInstructionBswap *)instruction); | |
| 1753 | break; | |
| 1739 | 1754 | case IrInstructionIdAtomicLoad: |
| 1740 | 1755 | ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); |
| 1741 | 1756 | break; |
src/link.cpp+7| ... | ... | @@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) { |
| 150 | 150 | if (t->env_type == ZigLLVM_GNUX32) { |
| 151 | 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 | 157 | return "elf_x86_64"; |
| 154 | 158 | default: |
| 155 | 159 | zig_unreachable(); |
| ... | ... | @@ -191,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) { |
| 191 | 195 | } |
| 192 | 196 | |
| 193 | 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 | 201 | if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) { |
| 195 | 202 | static const char *ld_names[] = { |
| 196 | 203 | "ld-linux-x86-64.so.2", |
src/main.cpp+1-8| ... | ... | @@ -466,16 +466,9 @@ int main(int argc, char **argv) { |
| 466 | 466 | "\n" |
| 467 | 467 | "General Options:\n" |
| 468 | 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 | 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 | 470 | " --prefix [path] Override default install prefix\n" |
| 471 | " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" | |
| 479 | 472 | "\n" |
| 480 | 473 | "Project-specific options become available when the build file is found.\n" |
| 481 | 474 | "\n" |
src/os.cpp+29-9| ... | ... | @@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t; |
| 50 | 50 | |
| 51 | 51 | #endif |
| 52 | 52 | |
| 53 | #if defined(ZIG_OS_LINUX) | |
| 53 | #if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) | |
| 54 | 54 | #include <link.h> |
| 55 | 55 | #endif |
| 56 | 56 | |
| 57 | #if defined(ZIG_OS_FREEBSD) | |
| 58 | #include <sys/sysctl.h> | |
| 59 | #endif | |
| 57 | 60 | |
| 58 | 61 | #if defined(__MACH__) |
| 59 | 62 | #include <mach/clock.h> |
| ... | ... | @@ -75,7 +78,9 @@ static clock_serv_t cclock; |
| 75 | 78 | #if defined(__APPLE__) && !defined(environ) |
| 76 | 79 | #include <crt_externs.h> |
| 77 | 80 | #define environ (*_NSGetEnviron()) |
| 78 | #endif | |
| 81 | #elif defined(ZIG_OS_FREEBSD) | |
| 82 | extern char **environ; | |
| 83 | #endif | |
| 79 | 84 | |
| 80 | 85 | #if defined(ZIG_OS_POSIX) |
| 81 | 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 | 193 | size_t len = buf_len(full_path); |
| 189 | 194 | if (len != 0) { |
| 190 | 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 | 203 | last_index -= 1; |
| 193 | 204 | } |
| 194 | 205 | for (size_t i = last_index;;) { |
| 195 | 206 | uint8_t c = buf_ptr(full_path)[i]; |
| 196 | 207 | if (os_is_sep(c)) { |
| 197 | 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 | 211 | if (out_basename) { |
| 201 | 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 | 1449 | } |
| 1439 | 1450 | buf_resize(out_path, amt); |
| 1440 | 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 | 1461 | #endif |
| 1442 | 1462 | return ErrorFileNotFound; |
| 1443 | 1463 | } |
| ... | ... | @@ -1743,7 +1763,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { |
| 1743 | 1763 | buf_resize(out_path, 0); |
| 1744 | 1764 | buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname); |
| 1745 | 1765 | return ErrorNone; |
| 1746 | #elif defined(ZIG_OS_LINUX) | |
| 1766 | #elif defined(ZIG_OS_POSIX) | |
| 1747 | 1767 | const char *home_dir = getenv("HOME"); |
| 1748 | 1768 | if (home_dir == nullptr) { |
| 1749 | 1769 | // TODO use /etc/passwd |
| ... | ... | @@ -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 | 1780 | static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) { |
| 1761 | 1781 | ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data); |
| 1762 | 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 | 1787 | #endif |
| 1768 | 1788 | |
| 1769 | 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 | 1791 | paths.resize(0); |
| 1772 | 1792 | dl_iterate_phdr(self_exe_shared_libs_callback, &paths); |
| 1773 | 1793 | return ErrorNone; |
| ... | ... | @@ -1936,7 +1956,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) { |
| 1936 | 1956 | mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; |
| 1937 | 1957 | mtime->nsec = 0; |
| 1938 | 1958 | return ErrorNone; |
| 1939 | #elif defined(ZIG_OS_LINUX) | |
| 1959 | #elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) | |
| 1940 | 1960 | struct stat statbuf; |
| 1941 | 1961 | if (fstat(file, &statbuf) == -1) |
| 1942 | 1962 | return ErrorFileSystem; |
| ... | ... | @@ -1976,7 +1996,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) { |
| 1976 | 1996 | case EFAULT: |
| 1977 | 1997 | zig_unreachable(); |
| 1978 | 1998 | case EISDIR: |
| 1979 | zig_unreachable(); | |
| 1999 | return ErrorIsDir; | |
| 1980 | 2000 | default: |
| 1981 | 2001 | return ErrorFileSystem; |
| 1982 | 2002 | } |
src/os.hpp+2| ... | ... | @@ -23,6 +23,8 @@ |
| 23 | 23 | #define ZIG_OS_WINDOWS |
| 24 | 24 | #elif defined(__linux__) |
| 25 | 25 | #define ZIG_OS_LINUX |
| 26 | #elif defined(__FreeBSD__) | |
| 27 | #define ZIG_OS_FREEBSD | |
| 26 | 28 | #else |
| 27 | 29 | #define ZIG_OS_UNKNOWN |
| 28 | 30 | #endif |
src/parser.cpp+13-13| ... | ... | @@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc); |
| 91 | 91 | static Token *ast_parse_block_label(ParseContext *pc); |
| 92 | 92 | static AstNode *ast_parse_field_init(ParseContext *pc); |
| 93 | 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 | 95 | static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc); |
| 96 | 96 | static AstNode *ast_parse_param_decl(ParseContext *pc); |
| 97 | 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 | 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 | 779 | static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 780 | 780 | Token *first = peek_token(pc); |
| 781 | 781 | AstNodeFnProto fn_cc; |
| ... | ... | @@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 806 | 806 | expect_token(pc, TokenIdRParen); |
| 807 | 807 | |
| 808 | 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 | 810 | Token *var = eat_token_if(pc, TokenIdKeywordVar); |
| 811 | 811 | Token *exmark = nullptr; |
| 812 | 812 | AstNode *return_type = nullptr; |
| ... | ... | @@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 842 | 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 | 846 | static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 847 | 847 | Token *first = eat_token_if(pc, TokenIdKeywordConst); |
| 848 | 848 | if (first == nullptr) |
| ... | ... | @@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 856 | 856 | type_expr = ast_expect(pc, ast_parse_type_expr); |
| 857 | 857 | |
| 858 | 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 | 860 | AstNode *expr = nullptr; |
| 861 | 861 | if (eat_token_if(pc, TokenIdEq) != nullptr) |
| 862 | 862 | expr = ast_expect(pc, ast_parse_expr); |
| ... | ... | @@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { |
| 1490 | 1490 | } |
| 1491 | 1491 | |
| 1492 | 1492 | // SuffixExpr |
| 1493 | // <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets | |
| 1494 | // / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)* | |
| 1493 | // <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments | |
| 1494 | // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* | |
| 1495 | 1495 | static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1496 | 1496 | AstNode *async_call = ast_parse_async_prefix(pc); |
| 1497 | 1497 | if (async_call != nullptr) { |
| ... | ... | @@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1599 | 1599 | } |
| 1600 | 1600 | |
| 1601 | 1601 | // PrimaryTypeExpr |
| 1602 | // <- BUILTININDENTIFIER FnCallArgumnets | |
| 1602 | // <- BUILTINIDENTIFIER FnCallArguments | |
| 1603 | 1603 | // / CHAR_LITERAL |
| 1604 | 1604 | // / ContainerDecl |
| 1605 | 1605 | // / ErrorSetDecl |
| ... | ... | @@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { |
| 1978 | 1978 | return res; |
| 1979 | 1979 | } |
| 1980 | 1980 | |
| 1981 | // AsmInput <- COLON AsmInputList AsmCloppers? | |
| 1981 | // AsmInput <- COLON AsmInputList AsmClobbers? | |
| 1982 | 1982 | static AstNode *ast_parse_asm_input(ParseContext *pc) { |
| 1983 | 1983 | if (eat_token_if(pc, TokenIdColon) == nullptr) |
| 1984 | 1984 | return nullptr; |
| ... | ... | @@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { |
| 2011 | 2011 | return res; |
| 2012 | 2012 | } |
| 2013 | 2013 | |
| 2014 | // AsmCloppers <- COLON StringList | |
| 2014 | // AsmClobbers <- COLON StringList | |
| 2015 | 2015 | static AstNode *ast_parse_asm_cloppers(ParseContext *pc) { |
| 2016 | 2016 | if (eat_token_if(pc, TokenIdColon) == nullptr) |
| 2017 | 2017 | return nullptr; |
| ... | ... | @@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { |
| 2080 | 2080 | return expr; |
| 2081 | 2081 | } |
| 2082 | 2082 | |
| 2083 | // Section <- KEYWORD_section LPAREN Expr RPAREN | |
| 2084 | static AstNode *ast_parse_section(ParseContext *pc) { | |
| 2083 | // LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN | |
| 2084 | static AstNode *ast_parse_link_section(ParseContext *pc) { | |
| 2085 | 2085 | Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); |
| 2086 | 2086 | if (first == nullptr) |
| 2087 | 2087 | return nullptr; |
| ... | ... | @@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) { |
| 2742 | 2742 | return res; |
| 2743 | 2743 | } |
| 2744 | 2744 | |
| 2745 | // FnCallArgumnets <- LPAREN ExprList RPAREN | |
| 2745 | // FnCallArguments <- LPAREN ExprList RPAREN | |
| 2746 | 2746 | static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { |
| 2747 | 2747 | Token *paren = eat_token_if(pc, TokenIdLParen); |
| 2748 | 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 | 754 | case OsLinux: |
| 755 | 755 | case OsMacOSX: |
| 756 | 756 | case OsZen: |
| 757 | case OsFreeBSD: | |
| 757 | 758 | case OsOpenBSD: |
| 758 | 759 | switch (id) { |
| 759 | 760 | case CIntTypeShort: |
| ... | ... | @@ -790,7 +791,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 790 | 791 | case OsAnanas: |
| 791 | 792 | case OsCloudABI: |
| 792 | 793 | case OsDragonFly: |
| 793 | case OsFreeBSD: | |
| 794 | 794 | case OsIOS: |
| 795 | 795 | case OsKFreeBSD: |
| 796 | 796 | case OsLv2: |
| ... | ... | @@ -1028,3 +1028,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) { |
| 1028 | 1028 | } |
| 1029 | 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 | 122 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); |
| 123 | 123 | ZigLLVM_OSType get_llvm_os_type(Os os_type); |
| 124 | 124 | |
| 125 | bool target_is_arm(const ZigTarget *target); | |
| 126 | ||
| 125 | 127 | #endif |
src/translate_c.cpp+8| ... | ... | @@ -4784,6 +4784,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4784 | 4784 | |
| 4785 | 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 | 4795 | // to make the [start...end] argument work |
| 4788 | 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 | 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 | 172 | uint32_t int_hash(int i); |
| 162 | 173 | bool int_eq(int a, int b); |
| 163 | 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 | 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 | 683 | const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { |
| 698 | 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 | 910 | assert(false); // unreachable |
| 925 | 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 | 398 | assert(list.len == 6); |
| 399 | 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 | 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 | 33 | pub fn xchg(self: *Self, new_value: T) T { |
| 30 | 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 | 16 | return self; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | pub fn deinit(self: *const BufMap) void { | |
| 19 | pub fn deinit(self: *BufMap) void { | |
| 20 | 20 | var it = self.hash_map.iterator(); |
| 21 | 21 | while (true) { |
| 22 | 22 | const entry = it.next() orelse break; |
| ... | ... | @@ -27,16 +27,34 @@ pub const BufMap = struct { |
| 27 | 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 | 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 | 44 | const value_copy = try self.copy(value); |
| 35 | 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 | 58 | const entry = self.hash_map.get(key) orelse return null; |
| 41 | 59 | return entry.value; |
| 42 | 60 | } |
| ... | ... | @@ -47,7 +65,7 @@ pub const BufMap = struct { |
| 47 | 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 | 69 | return self.hash_map.count(); |
| 52 | 70 | } |
| 53 | 71 | |
| ... | ... | @@ -55,11 +73,11 @@ pub const BufMap = struct { |
| 55 | 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 | 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 | 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 | 150 | } |
| 151 | 151 | |
| 152 | 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 | 160 | pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep { |
| ... | ... | @@ -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 | 809 | pub fn wantSharedLibSymLinks(self: *const Target) bool { |
| 799 | 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 | 819 | pub const LibExeObjStep = struct { |
| 804 | 820 | step: Step, |
| 805 | 821 | builder: *Builder, |
| ... | ... | @@ -842,11 +858,6 @@ pub const LibExeObjStep = struct { |
| 842 | 858 | source_files: ArrayList([]const u8), |
| 843 | 859 | object_src: []const u8, |
| 844 | 860 | |
| 845 | const Pkg = struct { | |
| 846 | name: []const u8, | |
| 847 | path: []const u8, | |
| 848 | }; | |
| 849 | ||
| 850 | 861 | const Kind = enum { |
| 851 | 862 | Exe, |
| 852 | 863 | Lib, |
| ... | ... | @@ -884,8 +895,8 @@ pub const LibExeObjStep = struct { |
| 884 | 895 | return self; |
| 885 | 896 | } |
| 886 | 897 | |
| 887 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | |
| 888 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0))) catch unreachable; | |
| 898 | pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep { | |
| 899 | const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable; | |
| 889 | 900 | return self; |
| 890 | 901 | } |
| 891 | 902 | |
| ... | ... | @@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct { |
| 1263 | 1274 | zig_args.append("--ver-patch") catch unreachable; |
| 1264 | 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 | 1281 | switch (self.target) { |
| 1268 | 1282 | Target.Native => {}, |
| ... | ... | @@ -1653,6 +1667,7 @@ pub const TestStep = struct { |
| 1653 | 1667 | exec_cmd_args: ?[]const ?[]const u8, |
| 1654 | 1668 | include_dirs: ArrayList([]const u8), |
| 1655 | 1669 | lib_paths: ArrayList([]const u8), |
| 1670 | packages: ArrayList(Pkg), | |
| 1656 | 1671 | object_files: ArrayList([]const u8), |
| 1657 | 1672 | no_rosegment: bool, |
| 1658 | 1673 | output_path: ?[]const u8, |
| ... | ... | @@ -1673,6 +1688,7 @@ pub const TestStep = struct { |
| 1673 | 1688 | .exec_cmd_args = null, |
| 1674 | 1689 | .include_dirs = ArrayList([]const u8).init(builder.allocator), |
| 1675 | 1690 | .lib_paths = ArrayList([]const u8).init(builder.allocator), |
| 1691 | .packages = ArrayList(Pkg).init(builder.allocator), | |
| 1676 | 1692 | .object_files = ArrayList([]const u8).init(builder.allocator), |
| 1677 | 1693 | .no_rosegment = false, |
| 1678 | 1694 | .output_path = null, |
| ... | ... | @@ -1688,6 +1704,13 @@ pub const TestStep = struct { |
| 1688 | 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 | 1714 | pub fn setVerbose(self: *TestStep, value: bool) void { |
| 1692 | 1715 | self.verbose = value; |
| 1693 | 1716 | } |
| ... | ... | @@ -1864,6 +1887,13 @@ pub const TestStep = struct { |
| 1864 | 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 | 1897 | if (self.no_rosegment) { |
| 1868 | 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 | 5 | Os.linux => @import("linux.zig"), |
| 6 | 6 | Os.windows => @import("windows.zig"), |
| 7 | 7 | Os.macosx, Os.ios => @import("darwin.zig"), |
| 8 | Os.freebsd => @import("freebsd.zig"), | |
| 8 | 9 | else => empty_import, |
| 9 | 10 | }; |
| 10 | 11 | const empty_import = @import("../empty.zig"); |
std/coff.zig+22-22| ... | ... | @@ -51,7 +51,7 @@ pub const Coff = struct { |
| 51 | 51 | |
| 52 | 52 | // Seek to PE File Header (coff header) |
| 53 | 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 | 55 | try self.in_file.seekTo(pe_magic_offset); |
| 56 | 56 | |
| 57 | 57 | var pe_header_magic: [4]u8 = undefined; |
| ... | ... | @@ -60,13 +60,13 @@ pub const Coff = struct { |
| 60 | 60 | return error.InvalidPEHeader; |
| 61 | 61 | |
| 62 | 62 | self.coff_header = CoffHeader{ |
| 63 | .machine = try in.readIntLe(u16), | |
| 64 | .number_of_sections = try in.readIntLe(u16), | |
| 65 | .timedate_stamp = try in.readIntLe(u32), | |
| 66 | .pointer_to_symbol_table = try in.readIntLe(u32), | |
| 67 | .number_of_symbols = try in.readIntLe(u32), | |
| 68 | .size_of_optional_header = try in.readIntLe(u16), | |
| 69 | .characteristics = try in.readIntLe(u16), | |
| 63 | .machine = try in.readIntLittle(u16), | |
| 64 | .number_of_sections = try in.readIntLittle(u16), | |
| 65 | .timedate_stamp = try in.readIntLittle(u32), | |
| 66 | .pointer_to_symbol_table = try in.readIntLittle(u32), | |
| 67 | .number_of_symbols = try in.readIntLittle(u32), | |
| 68 | .size_of_optional_header = try in.readIntLittle(u16), | |
| 69 | .characteristics = try in.readIntLittle(u16), | |
| 70 | 70 | }; |
| 71 | 71 | |
| 72 | 72 | switch (self.coff_header.machine) { |
| ... | ... | @@ -79,7 +79,7 @@ pub const Coff = struct { |
| 79 | 79 | |
| 80 | 80 | fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void { |
| 81 | 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 | 83 | // For now we're only interested in finding the reference to the .pdb, |
| 84 | 84 | // so we'll skip most of this header, which size is different in 32 |
| 85 | 85 | // 64 bits by the way. |
| ... | ... | @@ -93,14 +93,14 @@ pub const Coff = struct { |
| 93 | 93 | |
| 94 | 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 | 97 | if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) |
| 98 | 98 | return error.InvalidPEHeader; |
| 99 | 99 | |
| 100 | 100 | for (self.pe_header.data_directory) |*data_dir| { |
| 101 | 101 | data_dir.* = OptionalHeader.DataDirectory{ |
| 102 | .virtual_address = try in.readIntLe(u32), | |
| 103 | .size = try in.readIntLe(u32), | |
| 102 | .virtual_address = try in.readIntLittle(u32), | |
| 103 | .size = try in.readIntLittle(u32), | |
| 104 | 104 | }; |
| 105 | 105 | } |
| 106 | 106 | } |
| ... | ... | @@ -124,7 +124,7 @@ pub const Coff = struct { |
| 124 | 124 | if (!mem.eql(u8, cv_signature, "RSDS")) |
| 125 | 125 | return error.InvalidPEMagic; |
| 126 | 126 | try in.readNoEof(self.guid[0..]); |
| 127 | self.age = try in.readIntLe(u32); | |
| 127 | self.age = try in.readIntLittle(u32); | |
| 128 | 128 | |
| 129 | 129 | // Finally read the null-terminated string. |
| 130 | 130 | var byte = try in.readByte(); |
| ... | ... | @@ -157,15 +157,15 @@ pub const Coff = struct { |
| 157 | 157 | try self.sections.append(Section{ |
| 158 | 158 | .header = SectionHeader{ |
| 159 | 159 | .name = name, |
| 160 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) }, | |
| 161 | .virtual_address = try in.readIntLe(u32), | |
| 162 | .size_of_raw_data = try in.readIntLe(u32), | |
| 163 | .pointer_to_raw_data = try in.readIntLe(u32), | |
| 164 | .pointer_to_relocations = try in.readIntLe(u32), | |
| 165 | .pointer_to_line_numbers = try in.readIntLe(u32), | |
| 166 | .number_of_relocations = try in.readIntLe(u16), | |
| 167 | .number_of_line_numbers = try in.readIntLe(u16), | |
| 168 | .characteristics = try in.readIntLe(u32), | |
| 160 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) }, | |
| 161 | .virtual_address = try in.readIntLittle(u32), | |
| 162 | .size_of_raw_data = try in.readIntLittle(u32), | |
| 163 | .pointer_to_raw_data = try in.readIntLittle(u32), | |
| 164 | .pointer_to_relocations = try in.readIntLittle(u32), | |
| 165 | .pointer_to_line_numbers = try in.readIntLittle(u32), | |
| 166 | .number_of_relocations = try in.readIntLittle(u16), | |
| 167 | .number_of_line_numbers = try in.readIntLittle(u16), | |
| 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 | 123 | const rr = d.h[0 .. out_len / 32]; |
| 124 | 124 | |
| 125 | 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 | 135 | var v: [16]u32 = undefined; |
| 135 | 136 | |
| 136 | 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 | 142 | var k: usize = 0; |
| ... | ... | @@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type { |
| 356 | 358 | const rr = d.h[0 .. out_len / 64]; |
| 357 | 359 | |
| 358 | 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 | 370 | var v: [16]u64 = undefined; |
| 368 | 371 | |
| 369 | 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 | 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 | 59 | } |
| 60 | 60 | |
| 61 | 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 | 71 | |
| 71 | 72 | const c = "expand 32-byte k"; |
| 72 | 73 | const constant_le = []u32{ |
| 73 | mem.readIntLE(u32, c[0..4]), | |
| 74 | mem.readIntLE(u32, c[4..8]), | |
| 75 | mem.readIntLE(u32, c[8..12]), | |
| 76 | mem.readIntLE(u32, c[12..16]), | |
| 74 | mem.readIntSliceLittle(u32, c[0..4]), | |
| 75 | mem.readIntSliceLittle(u32, c[4..8]), | |
| 76 | mem.readIntSliceLittle(u32, c[8..12]), | |
| 77 | mem.readIntSliceLittle(u32, c[12..16]), | |
| 77 | 78 | }; |
| 78 | 79 | |
| 79 | 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 | 118 | var k: [8]u32 = undefined; |
| 118 | 119 | var c: [4]u32 = undefined; |
| 119 | 120 | |
| 120 | k[0] = mem.readIntLE(u32, key[0..4]); | |
| 121 | k[1] = mem.readIntLE(u32, key[4..8]); | |
| 122 | k[2] = mem.readIntLE(u32, key[8..12]); | |
| 123 | k[3] = mem.readIntLE(u32, key[12..16]); | |
| 124 | k[4] = mem.readIntLE(u32, key[16..20]); | |
| 125 | k[5] = mem.readIntLE(u32, key[20..24]); | |
| 126 | k[6] = mem.readIntLE(u32, key[24..28]); | |
| 127 | k[7] = mem.readIntLE(u32, key[28..32]); | |
| 121 | k[0] = mem.readIntSliceLittle(u32, key[0..4]); | |
| 122 | k[1] = mem.readIntSliceLittle(u32, key[4..8]); | |
| 123 | k[2] = mem.readIntSliceLittle(u32, key[8..12]); | |
| 124 | k[3] = mem.readIntSliceLittle(u32, key[12..16]); | |
| 125 | k[4] = mem.readIntSliceLittle(u32, key[16..20]); | |
| 126 | k[5] = mem.readIntSliceLittle(u32, key[20..24]); | |
| 127 | k[6] = mem.readIntSliceLittle(u32, key[24..28]); | |
| 128 | k[7] = mem.readIntSliceLittle(u32, key[28..32]); | |
| 128 | 129 | |
| 129 | 130 | c[0] = counter; |
| 130 | c[1] = mem.readIntLE(u32, nonce[0..4]); | |
| 131 | c[2] = mem.readIntLE(u32, nonce[4..8]); | |
| 132 | c[3] = mem.readIntLE(u32, nonce[8..12]); | |
| 131 | c[1] = mem.readIntSliceLittle(u32, nonce[0..4]); | |
| 132 | c[2] = mem.readIntSliceLittle(u32, nonce[4..8]); | |
| 133 | c[3] = mem.readIntSliceLittle(u32, nonce[8..12]); | |
| 133 | 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 | 145 | var k: [8]u32 = undefined; |
| 145 | 146 | var c: [4]u32 = undefined; |
| 146 | 147 | |
| 147 | k[0] = mem.readIntLE(u32, key[0..4]); | |
| 148 | k[1] = mem.readIntLE(u32, key[4..8]); | |
| 149 | k[2] = mem.readIntLE(u32, key[8..12]); | |
| 150 | k[3] = mem.readIntLE(u32, key[12..16]); | |
| 151 | k[4] = mem.readIntLE(u32, key[16..20]); | |
| 152 | k[5] = mem.readIntLE(u32, key[20..24]); | |
| 153 | k[6] = mem.readIntLE(u32, key[24..28]); | |
| 154 | k[7] = mem.readIntLE(u32, key[28..32]); | |
| 148 | k[0] = mem.readIntSliceLittle(u32, key[0..4]); | |
| 149 | k[1] = mem.readIntSliceLittle(u32, key[4..8]); | |
| 150 | k[2] = mem.readIntSliceLittle(u32, key[8..12]); | |
| 151 | k[3] = mem.readIntSliceLittle(u32, key[12..16]); | |
| 152 | k[4] = mem.readIntSliceLittle(u32, key[16..20]); | |
| 153 | k[5] = mem.readIntSliceLittle(u32, key[20..24]); | |
| 154 | k[6] = mem.readIntSliceLittle(u32, key[24..28]); | |
| 155 | k[7] = mem.readIntSliceLittle(u32, key[28..32]); | |
| 155 | 156 | |
| 156 | 157 | c[0] = @truncate(u32, counter); |
| 157 | 158 | c[1] = @truncate(u32, counter >> 32); |
| 158 | c[2] = mem.readIntLE(u32, nonce[0..4]); | |
| 159 | c[3] = mem.readIntLE(u32, nonce[4..8]); | |
| 159 | c[2] = mem.readIntSliceLittle(u32, nonce[0..4]); | |
| 160 | c[3] = mem.readIntSliceLittle(u32, nonce[4..8]); | |
| 160 | 161 | |
| 161 | 162 | const block_size = (1 << 6); |
| 162 | 163 | const big_block = (block_size << 32); |
std/crypto/md5.zig+2-1| ... | ... | @@ -112,7 +112,8 @@ pub const Md5 = struct { |
| 112 | 112 | d.round(d.buf[0..]); |
| 113 | 113 | |
| 114 | 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 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | |
| 8 | 8 | const Endian = builtin.Endian; |
| 9 | const readInt = std.mem.readInt; | |
| 10 | const writeInt = std.mem.writeInt; | |
| 9 | const readIntSliceLittle = std.mem.readIntSliceLittle; | |
| 10 | const writeIntSliceLittle = std.mem.writeIntSliceLittle; | |
| 11 | 11 | |
| 12 | 12 | pub const Poly1305 = struct { |
| 13 | 13 | const Self = @This(); |
| ... | ... | @@ -59,19 +59,19 @@ pub const Poly1305 = struct { |
| 59 | 59 | { |
| 60 | 60 | var i: usize = 0; |
| 61 | 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 | 66 | var i: usize = 1; |
| 67 | 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 | 72 | var i: usize = 0; |
| 73 | 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 | 168 | const nb_blocks = nmsg.len >> 4; |
| 169 | 169 | var i: usize = 0; |
| 170 | 170 | while (i < nb_blocks) : (i += 1) { |
| 171 | ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little); | |
| 172 | ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little); | |
| 173 | ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little); | |
| 174 | ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little); | |
| 171 | ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]); | |
| 172 | ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]); | |
| 173 | ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]); | |
| 174 | ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]); | |
| 175 | 175 | polyBlock(ctx); |
| 176 | 176 | nmsg = nmsg[16..]; |
| 177 | 177 | } |
| ... | ... | @@ -210,10 +210,11 @@ pub const Poly1305 = struct { |
| 210 | 210 | const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000 |
| 211 | 211 | const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000 |
| 212 | 212 | |
| 213 | writeInt(out[0..], @truncate(u32, uu0), Endian.Little); | |
| 214 | writeInt(out[4..], @truncate(u32, uu1), Endian.Little); | |
| 215 | writeInt(out[8..], @truncate(u32, uu2), Endian.Little); | |
| 216 | writeInt(out[12..], @truncate(u32, uu3), Endian.Little); | |
| 213 | // TODO https://github.com/ziglang/zig/issues/863 | |
| 214 | writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0)); | |
| 215 | writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1)); | |
| 216 | writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2)); | |
| 217 | writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3)); | |
| 217 | 218 | |
| 218 | 219 | ctx.secureZero(); |
| 219 | 220 | } |
std/crypto/sha1.zig+2-1| ... | ... | @@ -109,7 +109,8 @@ pub const Sha1 = struct { |
| 109 | 109 | d.round(d.buf[0..]); |
| 110 | 110 | |
| 111 | 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 | 167 | const rr = d.s[0 .. params.out_len / 32]; |
| 168 | 168 | |
| 169 | 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 | 509 | const rr = d.s[0 .. params.out_len / 64]; |
| 509 | 510 | |
| 510 | 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 | 120 | var c = []const u64{0} ** 5; |
| 121 | 121 | |
| 122 | 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 | 126 | comptime var x: usize = 0; |
| ... | ... | @@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void { |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 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 | 7 | const fmt = std.fmt; |
| 8 | 8 | |
| 9 | 9 | const Endian = builtin.Endian; |
| 10 | const readInt = std.mem.readInt; | |
| 11 | const writeInt = std.mem.writeInt; | |
| 10 | const readIntSliceLittle = std.mem.readIntSliceLittle; | |
| 11 | const writeIntSliceLittle = std.mem.writeIntSliceLittle; | |
| 12 | 12 | |
| 13 | 13 | // Based on Supercop's ref10 implementation. |
| 14 | 14 | pub const X25519 = struct { |
| ... | ... | @@ -255,16 +255,16 @@ const Fe = struct { |
| 255 | 255 | |
| 256 | 256 | var t: [10]i64 = undefined; |
| 257 | 257 | |
| 258 | t[0] = readInt(s[0..4], u32, Endian.Little); | |
| 259 | t[1] = readInt(s[4..7], u32, Endian.Little) << 6; | |
| 260 | t[2] = readInt(s[7..10], u32, Endian.Little) << 5; | |
| 261 | t[3] = readInt(s[10..13], u32, Endian.Little) << 3; | |
| 262 | t[4] = readInt(s[13..16], u32, Endian.Little) << 2; | |
| 263 | t[5] = readInt(s[16..20], u32, Endian.Little); | |
| 264 | t[6] = readInt(s[20..23], u32, Endian.Little) << 7; | |
| 265 | t[7] = readInt(s[23..26], u32, Endian.Little) << 5; | |
| 266 | t[8] = readInt(s[26..29], u32, Endian.Little) << 4; | |
| 267 | t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2; | |
| 258 | t[0] = readIntSliceLittle(u32, s[0..4]); | |
| 259 | t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6; | |
| 260 | t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5; | |
| 261 | t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3; | |
| 262 | t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2; | |
| 263 | t[5] = readIntSliceLittle(u32, s[16..20]); | |
| 264 | t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7; | |
| 265 | t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5; | |
| 266 | t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4; | |
| 267 | t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2; | |
| 268 | 268 | |
| 269 | 269 | carry1(h, t[0..]); |
| 270 | 270 | } |
| ... | ... | @@ -544,14 +544,15 @@ const Fe = struct { |
| 544 | 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); | |
| 548 | writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little); | |
| 549 | writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little); | |
| 550 | writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little); | |
| 551 | writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little); | |
| 552 | writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little); | |
| 553 | writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little); | |
| 554 | writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little); | |
| 547 | // TODO https://github.com/ziglang/zig/issues/863 | |
| 548 | writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26)); | |
| 549 | writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19)); | |
| 550 | writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13)); | |
| 551 | writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6)); | |
| 552 | writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25)); | |
| 553 | writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19)); | |
| 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 | 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 | 198 | } |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | pub inline fn getReturnAddress(frame_count: usize) usize { | |
| 202 | var fp = @ptrToInt(@frameAddress()); | |
| 203 | var i: usize = 0; | |
| 204 | while (fp != 0 and i < frame_count) { | |
| 205 | fp = @intToPtr(*const usize, fp).*; | |
| 206 | i += 1; | |
| 201 | pub const StackIterator = struct { | |
| 202 | first_addr: ?usize, | |
| 203 | fp: usize, | |
| 204 | ||
| 205 | pub fn init(first_addr: ?usize) StackIterator { | |
| 206 | return StackIterator{ | |
| 207 | .first_addr = first_addr, | |
| 208 | .fp = @ptrToInt(@frameAddress()), | |
| 209 | }; | |
| 207 | 210 | } |
| 208 | return @intToPtr(*const usize, fp + @sizeOf(usize)).*; | |
| 209 | } | |
| 211 | ||
| 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 | 232 | pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { |
| 212 | 233 | switch (builtin.os) { |
| 213 | 234 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), |
| 214 | 235 | else => {}, |
| 215 | 236 | } |
| 216 | const AddressState = union(enum) { | |
| 217 | NotLookingForStartAddress, | |
| 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 | } | |
| 237 | var it = StackIterator.init(start_addr); | |
| 238 | while (it.next()) |return_address| { | |
| 244 | 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 | 277 | |
| 283 | 278 | var coff_section: *coff.Section = undefined; |
| 284 | 279 | const mod_index = for (di.sect_contribs) |sect_contrib| { |
| 285 | if (sect_contrib.Section >= di.coff.sections.len) continue; | |
| 286 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section]; | |
| 280 | if (sect_contrib.Section > di.coff.sections.len) continue; | |
| 281 | // Remember that SectionContribEntry.Section is 1-based. | |
| 282 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1]; | |
| 287 | 283 | |
| 288 | 284 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| 289 | 285 | const vaddr_end = vaddr_start + sect_contrib.Size; |
| ... | ... | @@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 413 | 409 | |
| 414 | 410 | if (opt_line_info) |line_info| { |
| 415 | 411 | try out_stream.print("\n"); |
| 416 | if (printLineFromFile(out_stream, line_info)) { | |
| 412 | if (printLineFromFileAnyOs(out_stream, line_info)) { | |
| 417 | 413 | if (line_info.column == 0) { |
| 418 | 414 | try out_stream.write("\n"); |
| 419 | 415 | } else { |
| ... | ... | @@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { |
| 527 | 523 | |
| 528 | 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 | 527 | if (signature != 4) |
| 532 | 528 | return error.InvalidDebugInfo; |
| 533 | 529 | |
| ... | ... | @@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt |
| 597 | 593 | } else "???"; |
| 598 | 594 | if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| { |
| 599 | 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 | 605 | } else |err| switch (err) { |
| 602 | 606 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 603 | 607 | if (tty_color) { |
| ... | ... | @@ -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 | 626 | const compile_unit = findCompileUnit(debug_info, address) catch { |
| 615 | 627 | if (tty_color) { |
| 616 | 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 | 632 | return; |
| 621 | 633 | }; |
| 622 | 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 | 636 | defer line_info.deinit(); |
| 625 | 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 | 647 | } else |err| switch (err) { |
| 628 | 648 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 629 | 649 | if (tty_color) { |
| ... | ... | @@ -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 | 663 | fn printLineInfo( |
| 640 | debug_info: *DebugInfo, | |
| 641 | 664 | out_stream: var, |
| 642 | 665 | line_info: LineInfo, |
| 643 | 666 | address: usize, |
| 644 | 667 | symbol_name: []const u8, |
| 645 | 668 | compile_unit_name: []const u8, |
| 646 | 669 | tty_color: bool, |
| 670 | comptime printLineFromFile: var, | |
| 647 | 671 | ) !void { |
| 648 | 672 | if (tty_color) { |
| 649 | 673 | try out_stream.print( |
| ... | ... | @@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 733 | 757 | try di.pdb.openFile(di.coff, path); |
| 734 | 758 | |
| 735 | 759 | var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo; |
| 736 | const version = try pdb_stream.stream.readIntLe(u32); | |
| 737 | const signature = try pdb_stream.stream.readIntLe(u32); | |
| 738 | const age = try pdb_stream.stream.readIntLe(u32); | |
| 760 | const version = try pdb_stream.stream.readIntLittle(u32); | |
| 761 | const signature = try pdb_stream.stream.readIntLittle(u32); | |
| 762 | const age = try pdb_stream.stream.readIntLittle(u32); | |
| 739 | 763 | var guid: [16]u8 = undefined; |
| 740 | 764 | try pdb_stream.stream.readNoEof(guid[0..]); |
| 741 | 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 | 767 | // We validated the executable and pdb match. |
| 744 | 768 | |
| 745 | 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 | 771 | const name_bytes = try allocator.alloc(u8, name_bytes_len); |
| 748 | 772 | try pdb_stream.stream.readNoEof(name_bytes); |
| 749 | 773 | |
| ... | ... | @@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 773 | 797 | }; |
| 774 | 798 | const bucket_list = try allocator.alloc(Bucket, present.len); |
| 775 | 799 | for (present) |_| { |
| 776 | const name_offset = try pdb_stream.stream.readIntLe(u32); | |
| 777 | const name_index = try pdb_stream.stream.readIntLe(u32); | |
| 800 | const name_offset = try pdb_stream.stream.readIntLittle(u32); | |
| 801 | const name_index = try pdb_stream.stream.readIntLittle(u32); | |
| 778 | 802 | const name = mem.toSlice(u8, name_bytes.ptr + name_offset); |
| 779 | 803 | if (mem.eql(u8, name, "/names")) { |
| 780 | 804 | break :str_tab_index name_index; |
| ... | ... | @@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 835 | 859 | var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); |
| 836 | 860 | var sect_cont_offset: usize = 0; |
| 837 | 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 | 863 | if (ver != pdb.SectionContrSubstreamVersion.Ver60) |
| 840 | 864 | return error.InvalidDebugInfo; |
| 841 | 865 | sect_cont_offset += @sizeOf(u32); |
| ... | ... | @@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 855 | 879 | } |
| 856 | 880 | |
| 857 | 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 | 883 | var word_i: usize = 0; |
| 860 | 884 | var list = ArrayList(usize).init(allocator); |
| 861 | 885 | while (word_i != num_words) : (word_i += 1) { |
| 862 | const word = try stream.readIntLe(u32); | |
| 886 | const word = try stream.readIntLittle(u32); | |
| 863 | 887 | var bit_i: u5 = 0; |
| 864 | 888 | while (true) : (bit_i += 1) { |
| 865 | 889 | if (word & (u32(1) << bit_i) != 0) { |
| ... | ... | @@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 871 | 895 | return list.toOwnedSlice(); |
| 872 | 896 | } |
| 873 | 897 | |
| 874 | fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { | |
| 875 | var di = DebugInfo{ | |
| 876 | .self_exe_file = undefined, | |
| 877 | .elf = undefined, | |
| 878 | .debug_info = undefined, | |
| 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), | |
| 898 | fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { | |
| 899 | const elf_header = (try elf_file.findSection(name)) orelse return null; | |
| 900 | return DwarfInfo.Section{ | |
| 901 | .offset = elf_header.offset, | |
| 902 | .size = elf_header.size, | |
| 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 { | |
| 902 | var file_stream = elf.in_file.inStream(); | |
| 903 | const in = &file_stream.stream; | |
| 904 | ||
| 905 | section_loop: for (elf.section_headers) |*elf_section| { | |
| 906 | if (elf_section.sh_type == SHT_NULL) continue; | |
| 907 | ||
| 908 | const name_offset = elf.string_section.offset + elf_section.name; | |
| 909 | try elf.in_file.seekTo(name_offset); | |
| 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 | } | |
| 906 | /// Initialize DWARF info. The caller has the responsibility to initialize most | |
| 907 | /// the DwarfInfo fields before calling. These fields can be left undefined: | |
| 908 | /// * abbrev_table_list | |
| 909 | /// * compile_unit_list | |
| 910 | pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void { | |
| 911 | di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator); | |
| 912 | di.compile_unit_list = ArrayList(CompileUnit).init(allocator); | |
| 913 | try scanAllCompileUnits(di); | |
| 914 | } | |
| 915 | 915 | |
| 916 | { | |
| 917 | const null_byte = try in.readByte(); | |
| 918 | if (null_byte == 0) return elf_section; | |
| 919 | } | |
| 920 | } | |
| 916 | pub fn openElfDebugInfo( | |
| 917 | allocator: *mem.Allocator, | |
| 918 | elf_seekable_stream: *DwarfSeekableStream, | |
| 919 | elf_in_stream: *DwarfInStream, | |
| 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 | 962 | 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 | 1040 | var f = try os.File.openRead(line_info.file_name); |
| 1004 | 1041 | defer f.close(); |
| 1005 | 1042 | // TODO fstat and make sure that the file has the correct size |
| ... | ... | @@ -1052,6 +1089,35 @@ const MachOFile = struct { |
| 1052 | 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 | 1121 | pub const DebugInfo = switch (builtin.os) { |
| 1056 | 1122 | builtin.Os.macosx => struct { |
| 1057 | 1123 | symbols: []const MachoSymbol, |
| ... | ... | @@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) { |
| 1075 | 1141 | sect_contribs: []pdb.SectionContribEntry, |
| 1076 | 1142 | modules: []Module, |
| 1077 | 1143 | }, |
| 1078 | builtin.Os.linux => struct { | |
| 1079 | self_exe_file: os.File, | |
| 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 | }, | |
| 1144 | builtin.Os.linux => DwarfInfo, | |
| 1145 | builtin.Os.freebsd => struct {}, | |
| 1104 | 1146 | else => @compileError("Unsupported OS"), |
| 1105 | 1147 | }; |
| 1106 | 1148 | |
| ... | ... | @@ -1158,7 +1200,7 @@ const Constant = struct { |
| 1158 | 1200 | fn asUnsignedLe(self: *const Constant) !u64 { |
| 1159 | 1201 | if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; |
| 1160 | 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 | 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 | 1250 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; |
| 1209 | 1251 | return switch (form_value.*) { |
| 1210 | 1252 | FormValue.String => |value| value, |
| 1211 | FormValue.StrPtr => |offset| getString(st, offset), | |
| 1253 | FormValue.StrPtr => |offset| getString(di, offset), | |
| 1212 | 1254 | else => error.InvalidDebugInfo, |
| 1213 | 1255 | }; |
| 1214 | 1256 | } |
| ... | ... | @@ -1221,14 +1263,15 @@ const FileEntry = struct { |
| 1221 | 1263 | len_bytes: usize, |
| 1222 | 1264 | }; |
| 1223 | 1265 | |
| 1224 | const LineInfo = struct { | |
| 1266 | pub const LineInfo = struct { | |
| 1225 | 1267 | line: usize, |
| 1226 | 1268 | column: usize, |
| 1227 | file_name: []u8, | |
| 1228 | allocator: *mem.Allocator, | |
| 1269 | file_name: []const u8, | |
| 1270 | allocator: ?*mem.Allocator, | |
| 1229 | 1271 | |
| 1230 | fn deinit(self: *const LineInfo) void { | |
| 1231 | self.allocator.free(self.file_name); | |
| 1272 | fn deinit(self: LineInfo) void { | |
| 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 | 1362 | return buf.toSlice(); |
| 1320 | 1363 | } |
| 1321 | 1364 | |
| 1322 | fn getString(st: *DebugInfo, offset: u64) ![]u8 { | |
| 1323 | const pos = st.debug_str.offset + offset; | |
| 1324 | try st.self_exe_file.seekTo(pos); | |
| 1325 | return st.readString(); | |
| 1365 | fn getString(di: *DwarfInfo, offset: u64) ![]u8 { | |
| 1366 | const pos = di.debug_str.offset + offset; | |
| 1367 | try di.dwarf_seekable_stream.seekTo(pos); | |
| 1368 | return di.readString(); | |
| 1326 | 1369 | } |
| 1327 | 1370 | |
| 1328 | 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 | 1381 | } |
| 1339 | 1382 | |
| 1340 | 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 | 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 | 1395 | } |
| 1353 | 1396 | |
| 1354 | 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 | 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 | 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 | 1408 | } |
| 1366 | 1409 | |
| 1367 | 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 | 1412 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 1370 | 1413 | } |
| 1371 | 1414 | |
| 1372 | const ParseFormValueError = error{ | |
| 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 { | |
| 1415 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { | |
| 1380 | 1416 | return switch (form_id) { |
| 1381 | 1417 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 1382 | 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 | 1450 | }, |
| 1415 | 1451 | |
| 1416 | 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 | 1455 | DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, |
| 1420 | 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 | 1462 | }; |
| 1427 | 1463 | } |
| 1428 | 1464 | |
| 1429 | fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { | |
| 1430 | const in_file = st.self_exe_file; | |
| 1431 | var in_file_stream = in_file.inStream(); | |
| 1432 | const in_stream = &in_file_stream.stream; | |
| 1433 | var result = AbbrevTable.init(st.allocator()); | |
| 1465 | fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable { | |
| 1466 | var result = AbbrevTable.init(di.allocator()); | |
| 1434 | 1467 | while (true) { |
| 1435 | const abbrev_code = try readULeb128(in_stream); | |
| 1468 | const abbrev_code = try readULeb128(di.dwarf_in_stream); | |
| 1436 | 1469 | if (abbrev_code == 0) return result; |
| 1437 | 1470 | try result.append(AbbrevTableEntry{ |
| 1438 | 1471 | .abbrev_code = abbrev_code, |
| 1439 | .tag_id = try readULeb128(in_stream), | |
| 1440 | .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, | |
| 1441 | .attrs = ArrayList(AbbrevAttr).init(st.allocator()), | |
| 1472 | .tag_id = try readULeb128(di.dwarf_in_stream), | |
| 1473 | .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, | |
| 1474 | .attrs = ArrayList(AbbrevAttr).init(di.allocator()), | |
| 1442 | 1475 | }); |
| 1443 | 1476 | const attrs = &result.items[result.len - 1].attrs; |
| 1444 | 1477 | |
| 1445 | 1478 | while (true) { |
| 1446 | const attr_id = try readULeb128(in_stream); | |
| 1447 | const form_id = try readULeb128(in_stream); | |
| 1479 | const attr_id = try readULeb128(di.dwarf_in_stream); | |
| 1480 | const form_id = try readULeb128(di.dwarf_in_stream); | |
| 1448 | 1481 | if (attr_id == 0 and form_id == 0) break; |
| 1449 | 1482 | try attrs.append(AbbrevAttr{ |
| 1450 | 1483 | .attr_id = attr_id, |
| ... | ... | @@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { |
| 1456 | 1489 | |
| 1457 | 1490 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, |
| 1458 | 1491 | /// seeks in the stream and parses it. |
| 1459 | fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { | |
| 1460 | for (st.abbrev_table_list.toSlice()) |*header| { | |
| 1492 | fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable { | |
| 1493 | for (di.abbrev_table_list.toSlice()) |*header| { | |
| 1461 | 1494 | if (header.offset == abbrev_offset) { |
| 1462 | 1495 | return &header.table; |
| 1463 | 1496 | } |
| 1464 | 1497 | } |
| 1465 | try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); | |
| 1466 | try st.abbrev_table_list.append(AbbrevTableHeader{ | |
| 1498 | try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset); | |
| 1499 | try di.abbrev_table_list.append(AbbrevTableHeader{ | |
| 1467 | 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 | 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 | 1510 | return null; |
| 1478 | 1511 | } |
| 1479 | 1512 | |
| 1480 | fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { | |
| 1481 | const in_file = st.self_exe_file; | |
| 1482 | var in_file_stream = in_file.inStream(); | |
| 1483 | const in_stream = &in_file_stream.stream; | |
| 1484 | const abbrev_code = try readULeb128(in_stream); | |
| 1513 | fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { | |
| 1514 | const abbrev_code = try readULeb128(di.dwarf_in_stream); | |
| 1485 | 1515 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1486 | 1516 | |
| 1487 | 1517 | var result = Die{ |
| 1488 | 1518 | .tag_id = table_entry.tag_id, |
| 1489 | 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 | 1522 | try result.attrs.resize(table_entry.attrs.len); |
| 1493 | 1523 | for (table_entry.attrs.toSliceConst()) |attr, i| { |
| 1494 | 1524 | result.attrs.items[i] = Die.Attr{ |
| 1495 | 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 | 1529 | return result; |
| ... | ... | @@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1697 | 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 | 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 | 1733 | const debug_line_end = di.debug_line.offset + di.debug_line.size; |
| 1705 | 1734 | var this_offset = di.debug_line.offset; |
| 1706 | 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 | 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 | 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 | 1742 | if (unit_length == 0) return error.MissingDebugInfo; |
| 1717 | 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 | 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 | 1751 | // TODO support 3 and 5 |
| 1726 | 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); | |
| 1729 | const prog_start_offset = (try in_file.getPos()) + prologue_length; | |
| 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); | |
| 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 | 1758 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; |
| 1733 | 1759 | |
| 1734 | 1760 | if (version >= 4) { |
| 1735 | 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; | |
| 1740 | const line_base = try in_stream.readByteSigned(); | |
| 1765 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; | |
| 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 | 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 | 1773 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); |
| 1748 | 1774 | |
| 1749 | 1775 | { |
| 1750 | 1776 | var i: usize = 0; |
| 1751 | 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 | 1793 | while (true) { |
| 1768 | 1794 | const file_name = try di.readString(); |
| 1769 | 1795 | if (file_name.len == 0) break; |
| 1770 | const dir_index = try readULeb128(in_stream); | |
| 1771 | const mtime = try readULeb128(in_stream); | |
| 1772 | const len_bytes = try readULeb128(in_stream); | |
| 1796 | const dir_index = try readULeb128(di.dwarf_in_stream); | |
| 1797 | const mtime = try readULeb128(di.dwarf_in_stream); | |
| 1798 | const len_bytes = try readULeb128(di.dwarf_in_stream); | |
| 1773 | 1799 | try file_entries.append(FileEntry{ |
| 1774 | 1800 | .file_name = file_name, |
| 1775 | 1801 | .dir_index = dir_index, |
| ... | ... | @@ -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 | 1809 | while (true) { |
| 1784 | const opcode = try in_stream.readByte(); | |
| 1810 | const opcode = try di.dwarf_in_stream.readByte(); | |
| 1785 | 1811 | |
| 1786 | 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 | 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 | 1816 | switch (sub_op) { |
| 1791 | 1817 | DW.LNE_end_sequence => { |
| 1792 | 1818 | prog.end_sequence = true; |
| ... | ... | @@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1794 | 1820 | return error.MissingDebugInfo; |
| 1795 | 1821 | }, |
| 1796 | 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 | 1824 | prog.address = addr; |
| 1799 | 1825 | }, |
| 1800 | 1826 | DW.LNE_define_file => { |
| 1801 | 1827 | const file_name = try di.readString(); |
| 1802 | const dir_index = try readULeb128(in_stream); | |
| 1803 | const mtime = try readULeb128(in_stream); | |
| 1804 | const len_bytes = try readULeb128(in_stream); | |
| 1828 | const dir_index = try readULeb128(di.dwarf_in_stream); | |
| 1829 | const mtime = try readULeb128(di.dwarf_in_stream); | |
| 1830 | const len_bytes = try readULeb128(di.dwarf_in_stream); | |
| 1805 | 1831 | try file_entries.append(FileEntry{ |
| 1806 | 1832 | .file_name = file_name, |
| 1807 | 1833 | .dir_index = dir_index, |
| ... | ... | @@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1811 | 1837 | }, |
| 1812 | 1838 | else => { |
| 1813 | 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 | 1843 | } else if (opcode >= opcode_base) { |
| ... | ... | @@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1830 | 1856 | prog.basic_block = false; |
| 1831 | 1857 | }, |
| 1832 | 1858 | DW.LNS_advance_pc => { |
| 1833 | const arg = try readULeb128(in_stream); | |
| 1859 | const arg = try readULeb128(di.dwarf_in_stream); | |
| 1834 | 1860 | prog.address += arg * minimum_instruction_length; |
| 1835 | 1861 | }, |
| 1836 | 1862 | DW.LNS_advance_line => { |
| 1837 | const arg = try readILeb128(in_stream); | |
| 1863 | const arg = try readILeb128(di.dwarf_in_stream); | |
| 1838 | 1864 | prog.line += arg; |
| 1839 | 1865 | }, |
| 1840 | 1866 | DW.LNS_set_file => { |
| 1841 | const arg = try readULeb128(in_stream); | |
| 1867 | const arg = try readULeb128(di.dwarf_in_stream); | |
| 1842 | 1868 | prog.file = arg; |
| 1843 | 1869 | }, |
| 1844 | 1870 | DW.LNS_set_column => { |
| 1845 | const arg = try readULeb128(in_stream); | |
| 1871 | const arg = try readULeb128(di.dwarf_in_stream); | |
| 1846 | 1872 | prog.column = arg; |
| 1847 | 1873 | }, |
| 1848 | 1874 | DW.LNS_negate_stmt => { |
| ... | ... | @@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1856 | 1882 | prog.address += inc_addr; |
| 1857 | 1883 | }, |
| 1858 | 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 | 1886 | prog.address += arg; |
| 1861 | 1887 | }, |
| 1862 | 1888 | DW.LNS_set_prologue_end => {}, |
| 1863 | 1889 | else => { |
| 1864 | 1890 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; |
| 1865 | 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 | 1901 | return error.MissingDebugInfo; |
| 1876 | 1902 | } |
| 1877 | 1903 | |
| 1878 | fn scanAllCompileUnits(st: *DebugInfo) !void { | |
| 1879 | const debug_info_end = st.debug_info.offset + st.debug_info.size; | |
| 1880 | var this_unit_offset = st.debug_info.offset; | |
| 1904 | fn scanAllCompileUnits(di: *DwarfInfo) !void { | |
| 1905 | const debug_info_end = di.debug_info.offset + di.debug_info.size; | |
| 1906 | var this_unit_offset = di.debug_info.offset; | |
| 1881 | 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 | 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 | 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 | 1914 | if (unit_length == 0) return; |
| 1892 | 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 | 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 | 1923 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| 1901 | 1924 | |
| 1902 | const compile_unit_pos = try st.self_exe_file.getPos(); | |
| 1903 | const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset); | |
| 1925 | const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); | |
| 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 | 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 | 1955 | } |
| 1933 | 1956 | }; |
| 1934 | 1957 | |
| 1935 | try st.compile_unit_list.append(CompileUnit{ | |
| 1958 | try di.compile_unit_list.append(CompileUnit{ | |
| 1936 | 1959 | .version = version, |
| 1937 | 1960 | .is_64 = is_64, |
| 1938 | 1961 | .pc_range = pc_range, |
| ... | ... | @@ -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 { | |
| 1949 | var in_file_stream = st.self_exe_file.inStream(); | |
| 1950 | const in_stream = &in_file_stream.stream; | |
| 1951 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | |
| 1971 | fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { | |
| 1972 | for (di.compile_unit_list.toSlice()) |*compile_unit| { | |
| 1952 | 1973 | if (compile_unit.pc_range) |range| { |
| 1953 | 1974 | if (target_address >= range.start and target_address < range.end) return compile_unit; |
| 1954 | 1975 | } |
| 1955 | 1976 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { |
| 1956 | 1977 | var base_address: usize = 0; |
| 1957 | if (st.debug_ranges) |debug_ranges| { | |
| 1958 | try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); | |
| 1978 | if (di.debug_ranges) |debug_ranges| { | |
| 1979 | try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); | |
| 1959 | 1980 | while (true) { |
| 1960 | const begin_addr = try in_stream.readIntLe(usize); | |
| 1961 | const end_addr = try in_stream.readIntLe(usize); | |
| 1981 | const begin_addr = try di.dwarf_in_stream.readIntLittle(usize); | |
| 1982 | const end_addr = try di.dwarf_in_stream.readIntLittle(usize); | |
| 1962 | 1983 | if (begin_addr == 0 and end_addr == 0) { |
| 1963 | 1984 | break; |
| 1964 | 1985 | } |
| ... | ... | @@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit { |
| 1980 | 2001 | } |
| 1981 | 2002 | |
| 1982 | 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 | 2006 | ptr.* += @sizeOf(T); |
| 1985 | 2007 | return result; |
| 1986 | 2008 | } |
| ... | ... | @@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 { |
| 1996 | 2018 | } |
| 1997 | 2019 | |
| 1998 | 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 | 2023 | is_64.* = (first_32_bits == 0xffffffff); |
| 2001 | 2024 | if (is_64.*) { |
| 2002 | 2025 | ptr.* += 4; |
| 2003 | const result = mem.readIntLE(u64, ptr.*[0..8]); | |
| 2026 | const result = mem.readIntSliceLittle(u64, ptr.*[0..8]); | |
| 2004 | 2027 | ptr.* += 8; |
| 2005 | 2028 | return result; |
| 2006 | 2029 | } else { |
| ... | ... | @@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { |
| 2063 | 2086 | } |
| 2064 | 2087 | |
| 2065 | 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 | 2090 | is_64.* = (first_32_bits == 0xffffffff); |
| 2068 | 2091 | if (is_64.*) { |
| 2069 | return in_stream.readIntLe(u64); | |
| 2092 | return in_stream.readIntLittle(u64); | |
| 2070 | 2093 | } else { |
| 2071 | 2094 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; |
| 2072 | 2095 | return u64(first_32_bits); |
std/dynamic_library.zig+1-3| ... | ... | @@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) { |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | 21 | pub const LinuxDynLib = struct { |
| 22 | allocator: *mem.Allocator, | |
| 23 | 22 | elf_lib: ElfLib, |
| 24 | 23 | fd: i32, |
| 25 | 24 | map_addr: usize, |
| ... | ... | @@ -27,7 +26,7 @@ pub const LinuxDynLib = struct { |
| 27 | 26 | |
| 28 | 27 | /// Trusts the file |
| 29 | 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 | 30 | errdefer std.os.close(fd); |
| 32 | 31 | |
| 33 | 32 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); |
| ... | ... | @@ -45,7 +44,6 @@ pub const LinuxDynLib = struct { |
| 45 | 44 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; |
| 46 | 45 | |
| 47 | 46 | return DynLib{ |
| 48 | .allocator = allocator, | |
| 49 | 47 | .elf_lib = try ElfLib.init(bytes), |
| 50 | 48 | .fd = fd, |
| 51 | 49 | .map_addr = addr, |
std/elf.zig+59-56| ... | ... | @@ -353,7 +353,8 @@ pub const SectionHeader = struct { |
| 353 | 353 | }; |
| 354 | 354 | |
| 355 | 355 | pub const Elf = struct { |
| 356 | in_file: os.File, | |
| 356 | seekable_stream: *io.SeekableStream(anyerror, anyerror), | |
| 357 | in_stream: *io.InStream(anyerror), | |
| 357 | 358 | auto_close_stream: bool, |
| 358 | 359 | is_64: bool, |
| 359 | 360 | endian: builtin.Endian, |
| ... | ... | @@ -370,19 +371,24 @@ pub const Elf = struct { |
| 370 | 371 | |
| 371 | 372 | /// Call close when done. |
| 372 | 373 | pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void { |
| 373 | try elf.prealloc_file.open(path); | |
| 374 | try elf.openFile(allocator, *elf.prealloc_file); | |
| 375 | elf.auto_close_stream = true; | |
| 374 | @compileError("TODO implement"); | |
| 376 | 375 | } |
| 377 | 376 | |
| 378 | 377 | /// Call close when done. |
| 379 | 378 | pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void { |
| 380 | elf.allocator = allocator; | |
| 381 | elf.in_file = file; | |
| 382 | elf.auto_close_stream = false; | |
| 379 | @compileError("TODO implement"); | |
| 380 | } | |
| 383 | 381 | |
| 384 | var file_stream = elf.in_file.inStream(); | |
| 385 | const in = &file_stream.stream; | |
| 382 | pub fn openStream( | |
| 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 | 393 | var magic: [4]u8 = undefined; |
| 388 | 394 | try in.readNoEof(magic[0..]); |
| ... | ... | @@ -404,9 +410,9 @@ pub const Elf = struct { |
| 404 | 410 | if (version_byte != 1) return error.InvalidFormat; |
| 405 | 411 | |
| 406 | 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 | 416 | 1 => FileType.Relocatable, |
| 411 | 417 | 2 => FileType.Executable, |
| 412 | 418 | 3 => FileType.Shared, |
| ... | ... | @@ -414,7 +420,7 @@ pub const Elf = struct { |
| 414 | 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 | 424 | 0x02 => Arch.Sparc, |
| 419 | 425 | 0x03 => Arch.x86, |
| 420 | 426 | 0x08 => Arch.Mips, |
| ... | ... | @@ -427,32 +433,32 @@ pub const Elf = struct { |
| 427 | 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 | 437 | if (elf_version != 1) return error.InvalidFormat; |
| 432 | 438 | |
| 433 | 439 | if (elf.is_64) { |
| 434 | elf.entry_addr = try in.readInt(elf.endian, u64); | |
| 435 | elf.program_header_offset = try in.readInt(elf.endian, u64); | |
| 436 | elf.section_header_offset = try in.readInt(elf.endian, u64); | |
| 440 | elf.entry_addr = try in.readInt(u64, elf.endian); | |
| 441 | elf.program_header_offset = try in.readInt(u64, elf.endian); | |
| 442 | elf.section_header_offset = try in.readInt(u64, elf.endian); | |
| 437 | 443 | } else { |
| 438 | elf.entry_addr = u64(try in.readInt(elf.endian, u32)); | |
| 439 | elf.program_header_offset = u64(try in.readInt(elf.endian, u32)); | |
| 440 | elf.section_header_offset = u64(try in.readInt(elf.endian, u32)); | |
| 444 | elf.entry_addr = u64(try in.readInt(u32, elf.endian)); | |
| 445 | elf.program_header_offset = u64(try in.readInt(u32, elf.endian)); | |
| 446 | elf.section_header_offset = u64(try in.readInt(u32, elf.endian)); | |
| 441 | 447 | } |
| 442 | 448 | |
| 443 | 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 | 453 | if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { |
| 448 | 454 | return error.InvalidFormat; |
| 449 | 455 | } |
| 450 | 456 | |
| 451 | const ph_entry_size = try in.readInt(elf.endian, u16); | |
| 452 | const ph_entry_count = try in.readInt(elf.endian, u16); | |
| 453 | const sh_entry_size = try in.readInt(elf.endian, u16); | |
| 454 | const sh_entry_count = try in.readInt(elf.endian, u16); | |
| 455 | elf.string_section_index = u64(try in.readInt(elf.endian, u16)); | |
| 457 | const ph_entry_size = try in.readInt(u16, elf.endian); | |
| 458 | const ph_entry_count = try in.readInt(u16, elf.endian); | |
| 459 | const sh_entry_size = try in.readInt(u16, elf.endian); | |
| 460 | const sh_entry_count = try in.readInt(u16, elf.endian); | |
| 461 | elf.string_section_index = u64(try in.readInt(u16, elf.endian)); | |
| 456 | 462 | |
| 457 | 463 | if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; |
| 458 | 464 | |
| ... | ... | @@ -461,12 +467,12 @@ pub const Elf = struct { |
| 461 | 467 | const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count); |
| 462 | 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 | 471 | if (stream_end < end_sh or stream_end < end_ph) { |
| 466 | 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 | 477 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); |
| 472 | 478 | errdefer elf.allocator.free(elf.section_headers); |
| ... | ... | @@ -475,32 +481,32 @@ pub const Elf = struct { |
| 475 | 481 | if (sh_entry_size != 64) return error.InvalidFormat; |
| 476 | 482 | |
| 477 | 483 | for (elf.section_headers) |*elf_section| { |
| 478 | elf_section.name = try in.readInt(elf.endian, u32); | |
| 479 | elf_section.sh_type = try in.readInt(elf.endian, u32); | |
| 480 | elf_section.flags = try in.readInt(elf.endian, u64); | |
| 481 | elf_section.addr = try in.readInt(elf.endian, u64); | |
| 482 | elf_section.offset = try in.readInt(elf.endian, u64); | |
| 483 | elf_section.size = try in.readInt(elf.endian, u64); | |
| 484 | elf_section.link = try in.readInt(elf.endian, u32); | |
| 485 | elf_section.info = try in.readInt(elf.endian, u32); | |
| 486 | elf_section.addr_align = try in.readInt(elf.endian, u64); | |
| 487 | elf_section.ent_size = try in.readInt(elf.endian, u64); | |
| 484 | elf_section.name = try in.readInt(u32, elf.endian); | |
| 485 | elf_section.sh_type = try in.readInt(u32, elf.endian); | |
| 486 | elf_section.flags = try in.readInt(u64, elf.endian); | |
| 487 | elf_section.addr = try in.readInt(u64, elf.endian); | |
| 488 | elf_section.offset = try in.readInt(u64, elf.endian); | |
| 489 | elf_section.size = try in.readInt(u64, elf.endian); | |
| 490 | elf_section.link = try in.readInt(u32, elf.endian); | |
| 491 | elf_section.info = try in.readInt(u32, elf.endian); | |
| 492 | elf_section.addr_align = try in.readInt(u64, elf.endian); | |
| 493 | elf_section.ent_size = try in.readInt(u64, elf.endian); | |
| 488 | 494 | } |
| 489 | 495 | } else { |
| 490 | 496 | if (sh_entry_size != 40) return error.InvalidFormat; |
| 491 | 497 | |
| 492 | 498 | for (elf.section_headers) |*elf_section| { |
| 493 | 499 | // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? |
| 494 | elf_section.name = try in.readInt(elf.endian, u32); | |
| 495 | elf_section.sh_type = try in.readInt(elf.endian, u32); | |
| 496 | elf_section.flags = u64(try in.readInt(elf.endian, u32)); | |
| 497 | elf_section.addr = u64(try in.readInt(elf.endian, u32)); | |
| 498 | elf_section.offset = u64(try in.readInt(elf.endian, u32)); | |
| 499 | elf_section.size = u64(try in.readInt(elf.endian, u32)); | |
| 500 | elf_section.link = try in.readInt(elf.endian, u32); | |
| 501 | elf_section.info = try in.readInt(elf.endian, u32); | |
| 502 | elf_section.addr_align = u64(try in.readInt(elf.endian, u32)); | |
| 503 | elf_section.ent_size = u64(try in.readInt(elf.endian, u32)); | |
| 500 | elf_section.name = try in.readInt(u32, elf.endian); | |
| 501 | elf_section.sh_type = try in.readInt(u32, elf.endian); | |
| 502 | elf_section.flags = u64(try in.readInt(u32, elf.endian)); | |
| 503 | elf_section.addr = u64(try in.readInt(u32, elf.endian)); | |
| 504 | elf_section.offset = u64(try in.readInt(u32, elf.endian)); | |
| 505 | elf_section.size = u64(try in.readInt(u32, elf.endian)); | |
| 506 | elf_section.link = try in.readInt(u32, elf.endian); | |
| 507 | elf_section.info = try in.readInt(u32, elf.endian); | |
| 508 | elf_section.addr_align = u64(try in.readInt(u32, elf.endian)); | |
| 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 | 527 | pub fn close(elf: *Elf) void { |
| 522 | 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 | 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 | 534 | section_loop: for (elf.section_headers) |*elf_section| { |
| 532 | 535 | if (elf_section.sh_type == SHT_NULL) continue; |
| 533 | 536 | |
| 534 | 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 | 540 | for (name) |expected_c| { |
| 538 | const target_c = try in.readByte(); | |
| 541 | const target_c = try elf.in_stream.readByte(); | |
| 539 | 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 | 547 | if (null_byte == 0) return elf_section; |
| 545 | 548 | } |
| 546 | 549 | } |
| ... | ... | @@ -549,7 +552,7 @@ pub const Elf = struct { |
| 549 | 552 | } |
| 550 | 553 | |
| 551 | 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 | 83 | switch (builtin.os) { |
| 84 | 84 | builtin.Os.macosx, |
| 85 | 85 | builtin.Os.linux, |
| 86 | builtin.Os.freebsd, | |
| 86 | 87 | => { |
| 87 | 88 | const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len); |
| 88 | 89 | defer loop.allocator.free(iovecs); |
| ... | ... | @@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: |
| 219 | 220 | switch (builtin.os) { |
| 220 | 221 | builtin.Os.macosx, |
| 221 | 222 | builtin.Os.linux, |
| 223 | builtin.Os.freebsd, | |
| 222 | 224 | => { |
| 223 | 225 | const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len); |
| 224 | 226 | defer loop.allocator.free(iovecs); |
| ... | ... | @@ -399,7 +401,7 @@ pub async fn openPosix( |
| 399 | 401 | |
| 400 | 402 | pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle { |
| 401 | 403 | switch (builtin.os) { |
| 402 | builtin.Os.macosx, builtin.Os.linux => { | |
| 404 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => { | |
| 403 | 405 | const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC; |
| 404 | 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 | 429 | switch (builtin.os) { |
| 428 | 430 | builtin.Os.macosx, |
| 429 | 431 | builtin.Os.linux, |
| 432 | builtin.Os.freebsd, | |
| 430 | 433 | => { |
| 431 | 434 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC; |
| 432 | 435 | return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable); |
| ... | ... | @@ -449,7 +452,7 @@ pub async fn openReadWrite( |
| 449 | 452 | mode: os.File.Mode, |
| 450 | 453 | ) os.File.OpenError!os.FileHandle { |
| 451 | 454 | switch (builtin.os) { |
| 452 | builtin.Os.macosx, builtin.Os.linux => { | |
| 455 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => { | |
| 453 | 456 | const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC; |
| 454 | 457 | return await (async openPosix(loop, path, flags, mode) catch unreachable); |
| 455 | 458 | }, |
| ... | ... | @@ -477,7 +480,7 @@ pub const CloseOperation = struct { |
| 477 | 480 | os_data: OsData, |
| 478 | 481 | |
| 479 | 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 | 485 | builtin.Os.windows => struct { |
| 483 | 486 | handle: ?os.FileHandle, |
| ... | ... | @@ -496,7 +499,7 @@ pub const CloseOperation = struct { |
| 496 | 499 | self.* = CloseOperation{ |
| 497 | 500 | .loop = loop, |
| 498 | 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 | 503 | builtin.Os.windows => OsData{ .handle = null }, |
| 501 | 504 | else => @compileError("Unsupported OS"), |
| 502 | 505 | }, |
| ... | ... | @@ -525,6 +528,7 @@ pub const CloseOperation = struct { |
| 525 | 528 | switch (builtin.os) { |
| 526 | 529 | builtin.Os.linux, |
| 527 | 530 | builtin.Os.macosx, |
| 531 | builtin.Os.freebsd, | |
| 528 | 532 | => { |
| 529 | 533 | if (self.os_data.have_fd) { |
| 530 | 534 | self.loop.posixFsRequest(&self.os_data.close_req_node); |
| ... | ... | @@ -546,6 +550,7 @@ pub const CloseOperation = struct { |
| 546 | 550 | switch (builtin.os) { |
| 547 | 551 | builtin.Os.linux, |
| 548 | 552 | builtin.Os.macosx, |
| 553 | builtin.Os.freebsd, | |
| 549 | 554 | => { |
| 550 | 555 | self.os_data.close_req_node.data.msg.Close.fd = handle; |
| 551 | 556 | self.os_data.have_fd = true; |
| ... | ... | @@ -562,6 +567,7 @@ pub const CloseOperation = struct { |
| 562 | 567 | switch (builtin.os) { |
| 563 | 568 | builtin.Os.linux, |
| 564 | 569 | builtin.Os.macosx, |
| 570 | builtin.Os.freebsd, | |
| 565 | 571 | => { |
| 566 | 572 | self.os_data.have_fd = false; |
| 567 | 573 | }, |
| ... | ... | @@ -576,6 +582,7 @@ pub const CloseOperation = struct { |
| 576 | 582 | switch (builtin.os) { |
| 577 | 583 | builtin.Os.linux, |
| 578 | 584 | builtin.Os.macosx, |
| 585 | builtin.Os.freebsd, | |
| 579 | 586 | => { |
| 580 | 587 | assert(self.os_data.have_fd); |
| 581 | 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 | 606 | switch (builtin.os) { |
| 600 | 607 | builtin.Os.linux, |
| 601 | 608 | builtin.Os.macosx, |
| 609 | builtin.Os.freebsd, | |
| 602 | 610 | => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable), |
| 603 | 611 | builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable), |
| 604 | 612 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type { |
| 704 | 712 | os_data: OsData, |
| 705 | 713 | |
| 706 | 714 | const OsData = switch (builtin.os) { |
| 707 | builtin.Os.macosx => struct { | |
| 715 | builtin.Os.macosx, builtin.Os.freebsd => struct { | |
| 708 | 716 | file_table: FileTable, |
| 709 | 717 | table_lock: event.Lock, |
| 710 | 718 | |
| ... | ... | @@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type { |
| 793 | 801 | return self; |
| 794 | 802 | }, |
| 795 | 803 | |
| 796 | builtin.Os.macosx => { | |
| 804 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 797 | 805 | const self = try loop.allocator.createOne(Self); |
| 798 | 806 | errdefer loop.allocator.destroy(self); |
| 799 | 807 | |
| ... | ... | @@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type { |
| 813 | 821 | /// All addFile calls and removeFile calls must have completed. |
| 814 | 822 | pub fn destroy(self: *Self) void { |
| 815 | 823 | switch (builtin.os) { |
| 816 | builtin.Os.macosx => { | |
| 824 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 817 | 825 | // TODO we need to cancel the coroutines before destroying the lock |
| 818 | 826 | self.os_data.table_lock.deinit(); |
| 819 | 827 | var it = self.os_data.file_table.iterator(); |
| ... | ... | @@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type { |
| 855 | 863 | |
| 856 | 864 | pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V { |
| 857 | 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 | 867 | builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable), |
| 860 | 868 | builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable), |
| 861 | 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 | 874 | const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path); |
| 867 | 875 | var resolved_path_consumed = false; |
| 868 | 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 | 879 | var close_op_consumed = false; |
| 872 | 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 | 886 | const mode = 0; |
| 876 | 887 | const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable); |
| 877 | 888 | close_op.setHandle(fd); |
std/event/io.zig+9-5| ... | ... | @@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type { |
| 39 | 39 | if (amt_read < buf.len) return error.EndOfStream; |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | pub async fn readIntLe(self: *Self, comptime T: type) !T { | |
| 43 | return await (async self.readInt(builtin.Endian.Little, T) catch unreachable); | |
| 42 | pub async fn readIntLittle(self: *Self, comptime T: type) !T { | |
| 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 | 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 | 55 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 52 | 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 | 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 | 49 | }; |
| 50 | 50 | |
| 51 | 51 | pub const EventFd = switch (builtin.os) { |
| 52 | builtin.Os.macosx => MacOsEventFd, | |
| 52 | builtin.Os.macosx, builtin.Os.freebsd => KEventFd, | |
| 53 | 53 | builtin.Os.linux => struct { |
| 54 | 54 | base: ResumeNode, |
| 55 | 55 | epoll_op: u32, |
| ... | ... | @@ -62,13 +62,13 @@ pub const Loop = struct { |
| 62 | 62 | else => @compileError("unsupported OS"), |
| 63 | 63 | }; |
| 64 | 64 | |
| 65 | const MacOsEventFd = struct { | |
| 65 | const KEventFd = struct { | |
| 66 | 66 | base: ResumeNode, |
| 67 | 67 | kevent: posix.Kevent, |
| 68 | 68 | }; |
| 69 | 69 | |
| 70 | 70 | pub const Basic = switch (builtin.os) { |
| 71 | builtin.Os.macosx => MacOsBasic, | |
| 71 | builtin.Os.macosx, builtin.Os.freebsd => KEventBasic, | |
| 72 | 72 | builtin.Os.linux => struct { |
| 73 | 73 | base: ResumeNode, |
| 74 | 74 | }, |
| ... | ... | @@ -78,7 +78,7 @@ pub const Loop = struct { |
| 78 | 78 | else => @compileError("unsupported OS"), |
| 79 | 79 | }; |
| 80 | 80 | |
| 81 | const MacOsBasic = struct { | |
| 81 | const KEventBasic = struct { | |
| 82 | 82 | base: ResumeNode, |
| 83 | 83 | kev: posix.Kevent, |
| 84 | 84 | }; |
| ... | ... | @@ -214,7 +214,7 @@ pub const Loop = struct { |
| 214 | 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 | 218 | self.os_data.kqfd = try os.bsdKQueue(); |
| 219 | 219 | errdefer os.close(self.os_data.kqfd); |
| 220 | 220 | |
| ... | ... | @@ -369,7 +369,7 @@ pub const Loop = struct { |
| 369 | 369 | os.close(self.os_data.epollfd); |
| 370 | 370 | self.allocator.free(self.eventfd_resume_nodes); |
| 371 | 371 | }, |
| 372 | builtin.Os.macosx => { | |
| 372 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 373 | 373 | os.close(self.os_data.kqfd); |
| 374 | 374 | os.close(self.os_data.fs_kqfd); |
| 375 | 375 | }, |
| ... | ... | @@ -484,7 +484,7 @@ pub const Loop = struct { |
| 484 | 484 | const eventfd_node = &resume_stack_node.data; |
| 485 | 485 | eventfd_node.base.handle = next_tick_node.data; |
| 486 | 486 | switch (builtin.os) { |
| 487 | builtin.Os.macosx => { | |
| 487 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 488 | 488 | const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent); |
| 489 | 489 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 490 | 490 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { |
| ... | ... | @@ -546,6 +546,7 @@ pub const Loop = struct { |
| 546 | 546 | switch (builtin.os) { |
| 547 | 547 | builtin.Os.linux, |
| 548 | 548 | builtin.Os.macosx, |
| 549 | builtin.Os.freebsd, | |
| 549 | 550 | => self.os_data.fs_thread.wait(), |
| 550 | 551 | else => {}, |
| 551 | 552 | } |
| ... | ... | @@ -610,7 +611,7 @@ pub const Loop = struct { |
| 610 | 611 | os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable; |
| 611 | 612 | return; |
| 612 | 613 | }, |
| 613 | builtin.Os.macosx => { | |
| 614 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 614 | 615 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 615 | 616 | const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent); |
| 616 | 617 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| ... | ... | @@ -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 | 673 | var eventlist: [1]posix.Kevent = undefined; |
| 673 | 674 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 674 | 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 | 732 | self.beginOneEvent(); // finished in posixFsRun after processing the msg |
| 732 | 733 | self.os_data.fs_queue.put(request_node); |
| 733 | 734 | switch (builtin.os) { |
| 734 | builtin.Os.macosx => { | |
| 735 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 735 | 736 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake); |
| 736 | 737 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; |
| 737 | 738 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; |
| ... | ... | @@ -801,7 +802,7 @@ pub const Loop = struct { |
| 801 | 802 | else => unreachable, |
| 802 | 803 | } |
| 803 | 804 | }, |
| 804 | builtin.Os.macosx => { | |
| 805 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 805 | 806 | const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait); |
| 806 | 807 | var out_kevs: [1]posix.Kevent = undefined; |
| 807 | 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 | 814 | |
| 814 | 815 | const OsData = switch (builtin.os) { |
| 815 | 816 | builtin.Os.linux => LinuxOsData, |
| 816 | builtin.Os.macosx => MacOsData, | |
| 817 | builtin.Os.macosx, builtin.Os.freebsd => KEventData, | |
| 817 | 818 | builtin.Os.windows => struct { |
| 818 | 819 | io_port: windows.HANDLE, |
| 819 | 820 | extra_thread_count: usize, |
| ... | ... | @@ -821,7 +822,7 @@ pub const Loop = struct { |
| 821 | 822 | else => struct {}, |
| 822 | 823 | }; |
| 823 | 824 | |
| 824 | const MacOsData = struct { | |
| 825 | const KEventData = struct { | |
| 825 | 826 | kqfd: i32, |
| 826 | 827 | final_kevent: posix.Kevent, |
| 827 | 828 | fs_kevent_wake: posix.Kevent, |
std/fmt/index.zig+72-8| ... | ... | @@ -2,6 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const debug = std.debug; |
| 4 | 4 | const assert = debug.assert; |
| 5 | const assertError = debug.assertError; | |
| 5 | 6 | const mem = std.mem; |
| 6 | 7 | const builtin = @import("builtin"); |
| 7 | 8 | const errol = @import("errol/index.zig"); |
| ... | ... | @@ -116,7 +117,7 @@ pub fn formatType( |
| 116 | 117 | return output(context, @errorName(value)); |
| 117 | 118 | } |
| 118 | 119 | switch (@typeInfo(T)) { |
| 119 | builtin.TypeId.Int, builtin.TypeId.Float => { | |
| 120 | builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => { | |
| 120 | 121 | return formatValue(value, fmt, context, Errors, output); |
| 121 | 122 | }, |
| 122 | 123 | builtin.TypeId.Void => { |
| ... | ... | @@ -242,6 +243,9 @@ pub fn formatType( |
| 242 | 243 | } |
| 243 | 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 | 249 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), |
| 246 | 250 | } |
| 247 | 251 | } |
| ... | ... | @@ -267,11 +271,15 @@ fn formatValue( |
| 267 | 271 | } |
| 268 | 272 | } |
| 269 | 273 | |
| 270 | comptime var T = @typeOf(value); | |
| 274 | const T = @typeOf(value); | |
| 271 | 275 | switch (@typeId(T)) { |
| 272 | 276 | builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output), |
| 273 | 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 | 296 | if (fmt.len > 0) { |
| 289 | 297 | switch (fmt[0]) { |
| 290 | 298 | 'c' => { |
| 291 | if (@typeOf(value) == u8) { | |
| 292 | if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]}); | |
| 293 | return formatAsciiChar(value, context, Errors, output); | |
| 299 | if (@typeOf(value).bit_count <= 8) { | |
| 300 | if (fmt.len > 1) | |
| 301 | @compileError("Unknown format character: " ++ []u8{fmt[1]}); | |
| 302 | return formatAsciiChar(u8(value), context, Errors, output); | |
| 294 | 303 | } |
| 295 | 304 | }, |
| 296 | 305 | 'b' => { |
| ... | ... | @@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned |
| 811 | 820 | |
| 812 | 821 | for (buf) |c| { |
| 813 | 822 | const digit = try charToDigit(c, radix); |
| 814 | x = try math.mul(T, x, radix); | |
| 815 | x = try math.add(T, x, digit); | |
| 823 | ||
| 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 | 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 | 858 | pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { |
| 822 | 859 | const value = switch (c) { |
| 823 | 860 | '0'...'9' => c - '0', |
| ... | ... | @@ -935,6 +972,25 @@ test "fmt.format" { |
| 935 | 972 | const value: u8 = 0b1100; |
| 936 | 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 | 995 | const value: [3]u8 = "abc"; |
| 940 | 996 | try testFmt("array: abc\n", "array: {}\n", value); |
| ... | ... | @@ -956,6 +1012,14 @@ test "fmt.format" { |
| 956 | 1012 | try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value); |
| 957 | 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 | 1023 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); |
| 960 | 1024 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); |
| 961 | 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 | 42 | pub fn init(key: []const u8) Self { |
| 43 | 43 | debug.assert(key.len >= 16); |
| 44 | 44 | |
| 45 | const k0 = mem.readInt(key[0..8], u64, Endian.Little); | |
| 46 | const k1 = mem.readInt(key[8..16], u64, Endian.Little); | |
| 45 | const k0 = mem.readIntSliceLittle(u64, key[0..8]); | |
| 46 | const k1 = mem.readIntSliceLittle(u64, key[8..16]); | |
| 47 | 47 | |
| 48 | 48 | var d = Self{ |
| 49 | 49 | .v0 = k0 ^ 0x736f6d6570736575, |
| ... | ... | @@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 121 | 121 | fn round(d: *Self, b: []const u8) void { |
| 122 | 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 | 125 | d.v3 ^= m; |
| 126 | 126 | |
| 127 | 127 | comptime var i: usize = 0; |
| ... | ... | @@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 162 | 162 | const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; |
| 163 | 163 | |
| 164 | 164 | test "siphash64-2-4 sanity" { |
| 165 | const vectors = [][]const u8{ | |
| 165 | const vectors = [][8]u8{ | |
| 166 | 166 | "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" |
| 167 | 167 | "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" |
| 168 | 168 | "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc |
| ... | ... | @@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" { |
| 235 | 235 | for (vectors) |vector, i| { |
| 236 | 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 | 239 | debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); |
| 240 | 240 | } |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | 243 | test "siphash128-2-4 sanity" { |
| 244 | const vectors = [][]const u8{ | |
| 244 | const vectors = [][16]u8{ | |
| 245 | 245 | "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93", |
| 246 | 246 | "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45", |
| 247 | 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 | 314 | for (vectors) |vector, i| { |
| 315 | 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 | 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 | 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 | 137 | fn ensureCapacity(self: *Self) !void { |
| 130 | 138 | if (self.entries.len == 0) { |
| 131 | 139 | return self.initCapacity(16); |
| ... | ... | @@ -354,6 +362,12 @@ test "basic hash map usage" { |
| 354 | 362 | gop2.kv.value = 42; |
| 355 | 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 | 371 | assert(map.contains(2)); |
| 358 | 372 | assert(map.get(2).?.value == 22); |
| 359 | 373 | _ = map.remove(2); |
std/heap.zig+4-4| ... | ... | @@ -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 | 70 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 71 | 71 | |
| 72 | 72 | switch (builtin.os) { |
| 73 | Os.linux, Os.macosx, Os.ios => { | |
| 73 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 74 | 74 | const p = os.posix; |
| 75 | 75 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; |
| 76 | 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 | 121 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 122 | 122 | |
| 123 | 123 | switch (builtin.os) { |
| 124 | Os.linux, Os.macosx, Os.ios => { | |
| 124 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 125 | 125 | if (new_size <= old_mem.len) { |
| 126 | 126 | const base_addr = @ptrToInt(old_mem.ptr); |
| 127 | 127 | const old_addr_end = base_addr + old_mem.len; |
| ... | ... | @@ -166,7 +166,7 @@ pub const DirectAllocator = struct { |
| 166 | 166 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 167 | 167 | |
| 168 | 168 | switch (builtin.os) { |
| 169 | Os.linux, Os.macosx, Os.ios => { | |
| 169 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 170 | 170 | _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len); |
| 171 | 171 | }, |
| 172 | 172 | Os.windows => { |
std/index.zig+2-1| ... | ... | @@ -57,7 +57,8 @@ test "std" { |
| 57 | 57 | _ = @import("mutex.zig"); |
| 58 | 58 | _ = @import("segmented_list.zig"); |
| 59 | 59 | _ = @import("spinlock.zig"); |
| 60 | ||
| 60 | ||
| 61 | _ = @import("dynamic_library.zig"); | |
| 61 | 62 | _ = @import("base64.zig"); |
| 62 | 63 | _ = @import("build.zig"); |
| 63 | 64 | _ = @import("c/index.zig"); |
std/io.zig+104-37| ... | ... | @@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File { |
| 32 | 32 | return File.openHandle(handle); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; | |
| 36 | ||
| 35 | 37 | pub fn InStream(comptime ReadError: type) type { |
| 36 | 38 | return struct { |
| 37 | 39 | const Self = @This(); |
| ... | ... | @@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type { |
| 150 | 152 | } |
| 151 | 153 | |
| 152 | 154 | /// Reads a native-endian integer |
| 153 | pub fn readIntNe(self: *Self, comptime T: type) !T { | |
| 154 | return self.readInt(builtin.endian, T); | |
| 155 | pub fn readIntNative(self: *Self, comptime T: type) !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 | 169 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 159 | 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 | 175 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 165 | 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 | 181 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 171 | 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 { | |
| 176 | assert(size <= @sizeOf(T)); | |
| 177 | assert(size <= 8); | |
| 178 | var input_buf: [8]u8 = undefined; | |
| 179 | const input_slice = input_buf[0..size]; | |
| 180 | try self.readNoEof(input_slice); | |
| 181 | return mem.readInt(input_slice, T, endian); | |
| 186 | pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { | |
| 187 | assert(size <= @sizeOf(ReturnType)); | |
| 188 | var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; | |
| 189 | const bytes = bytes_buf[0..size]; | |
| 190 | try self.readNoEof(bytes); | |
| 191 | return mem.readVarInt(ReturnType, bytes, endian); | |
| 182 | 192 | } |
| 183 | 193 | |
| 184 | 194 | pub fn skipBytes(self: *Self, num_bytes: usize) !void { |
| ... | ... | @@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type { |
| 227 | 237 | } |
| 228 | 238 | |
| 229 | 239 | /// Write a native-endian integer. |
| 230 | pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void { | |
| 231 | return self.writeInt(builtin.endian, T, value); | |
| 240 | pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void { | |
| 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 | 254 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 236 | mem.writeIntLE(T, &bytes, value); | |
| 255 | mem.writeIntLittle(T, &bytes, value); | |
| 237 | 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 | 260 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 242 | mem.writeIntBE(T, &bytes, value); | |
| 261 | mem.writeIntBig(T, &bytes, value); | |
| 243 | 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 | 266 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 248 | mem.writeInt(bytes[0..], value, endian); | |
| 267 | mem.writeInt(T, &bytes, value, endian); | |
| 249 | 268 | return self.writeFn(self, bytes); |
| 250 | 269 | } |
| 251 | 270 | }; |
| ... | ... | @@ -683,25 +702,73 @@ test "import io tests" { |
| 683 | 702 | } |
| 684 | 703 | } |
| 685 | 704 | |
| 686 | pub fn readLine(buf: []u8) !usize { | |
| 687 | var stdin = getStdIn() catch return error.StdInUnavailable; | |
| 688 | var adapter = stdin.inStream(); | |
| 689 | var stream = &adapter.stream; | |
| 690 | var index: usize = 0; | |
| 705 | pub fn readLine(buf: *std.Buffer) ![]u8 { | |
| 706 | var stdin = try getStdIn(); | |
| 707 | var stdin_stream = stdin.inStream(); | |
| 708 | return readLineFrom(&stdin_stream.stream, buf); | |
| 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 | 715 | while (true) { |
| 692 | const byte = stream.readByte() catch return error.EndOfFile; | |
| 716 | const byte = try stream.readByte(); | |
| 693 | 717 | switch (byte) { |
| 694 | 718 | '\r' => { |
| 695 | 719 | // trash the following \n |
| 696 | _ = stream.readByte() catch return error.EndOfFile; | |
| 697 | return index; | |
| 698 | }, | |
| 699 | '\n' => return index, | |
| 700 | else => { | |
| 701 | if (index == buf.len) return error.InputTooLong; | |
| 702 | buf[index] = byte; | |
| 703 | index += 1; | |
| 720 | _ = try stream.readByte(); | |
| 721 | return buf.toSlice()[start..]; | |
| 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 | 910 | debug.assert(token.id == id); |
| 911 | 911 | } |
| 912 | 912 | |
| 913 | test "token" { | |
| 913 | test "json.token" { | |
| 914 | 914 | const s = |
| 915 | 915 | \\{ |
| 916 | 916 | \\ "Image": { |
| ... | ... | @@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool { |
| 980 | 980 | return p.complete; |
| 981 | 981 | } |
| 982 | 982 | |
| 983 | test "json validate" { | |
| 983 | test "json.validate" { | |
| 984 | 984 | debug.assert(validate("{}")); |
| 985 | 985 | } |
| 986 | 986 | |
| ... | ... | @@ -1188,7 +1188,7 @@ pub const Parser = struct { |
| 1188 | 1188 | } |
| 1189 | 1189 | |
| 1190 | 1190 | var value = p.stack.pop(); |
| 1191 | try p.pushToParent(value); | |
| 1191 | try p.pushToParent(&value); | |
| 1192 | 1192 | }, |
| 1193 | 1193 | Token.Id.String => { |
| 1194 | 1194 | try p.stack.append(try p.parseString(allocator, token, input, i)); |
| ... | ... | @@ -1251,7 +1251,7 @@ pub const Parser = struct { |
| 1251 | 1251 | } |
| 1252 | 1252 | |
| 1253 | 1253 | var value = p.stack.pop(); |
| 1254 | try p.pushToParent(value); | |
| 1254 | try p.pushToParent(&value); | |
| 1255 | 1255 | }, |
| 1256 | 1256 | Token.Id.ObjectBegin => { |
| 1257 | 1257 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); |
| ... | ... | @@ -1312,19 +1312,19 @@ pub const Parser = struct { |
| 1312 | 1312 | } |
| 1313 | 1313 | } |
| 1314 | 1314 | |
| 1315 | fn pushToParent(p: *Parser, value: Value) !void { | |
| 1316 | switch (p.stack.at(p.stack.len - 1)) { | |
| 1315 | fn pushToParent(p: *Parser, value: *const Value) !void { | |
| 1316 | switch (p.stack.toSlice()[p.stack.len - 1]) { | |
| 1317 | 1317 | // Object Parent -> [ ..., object, <key>, value ] |
| 1318 | 1318 | Value.String => |key| { |
| 1319 | 1319 | _ = p.stack.pop(); |
| 1320 | 1320 | |
| 1321 | 1321 | var object = &p.stack.items[p.stack.len - 1].Object; |
| 1322 | _ = try object.put(key, value); | |
| 1322 | _ = try object.put(key, value.*); | |
| 1323 | 1323 | p.state = State.ObjectKey; |
| 1324 | 1324 | }, |
| 1325 | 1325 | // Array Parent -> [ ..., <array>, value ] |
| 1326 | 1326 | Value.Array => |*array| { |
| 1327 | try array.append(value); | |
| 1327 | try array.append(value.*); | |
| 1328 | 1328 | p.state = State.ArrayValue; |
| 1329 | 1329 | }, |
| 1330 | 1330 | else => { |
| ... | ... | @@ -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 | 1352 | var p = Parser.init(debug.global_allocator, false); |
| 1353 | 1353 | defer p.deinit(); |
| 1354 | 1354 | |
| ... | ... | @@ -1364,7 +1364,8 @@ test "json parser dynamic" { |
| 1364 | 1364 | \\ "Width": 100 |
| 1365 | 1365 | \\ }, |
| 1366 | 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 | 1388 | |
| 1388 | 1389 | const animated = image.Object.get("Animated").?.value; |
| 1389 | 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 | 21 | // |
| 22 | 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 | 25 | ok( |
| 26 | 26 | \\{"1":[],"2":{},"3":"4"} |
| 27 | 27 | ); |
| ... | ... | @@ -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 | 33 | ok( |
| 34 | 34 | \\[[] ] |
| 35 | 35 | ); |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | test "y_array_empty" { | |
| 38 | test "json.test.y_array_empty" { | |
| 39 | 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 | 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 | 51 | ok( |
| 52 | 52 | \\["a"] |
| 53 | 53 | ); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | test "y_array_false" { | |
| 56 | test "json.test.y_array_false" { | |
| 57 | 57 | ok( |
| 58 | 58 | \\[false] |
| 59 | 59 | ); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | test "y_array_heterogeneous" { | |
| 62 | test "json.test.y_array_heterogeneous" { | |
| 63 | 63 | ok( |
| 64 | 64 | \\[null, 1, "1", {}] |
| 65 | 65 | ); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | test "y_array_null" { | |
| 68 | test "json.test.y_array_null" { | |
| 69 | 69 | ok( |
| 70 | 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 | 75 | ok( |
| 76 | 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 | 82 | ok( |
| 83 | 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 | 88 | ok( |
| 89 | 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 | 94 | ok("[2] "); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | test "y_number_0e+1" { | |
| 97 | test "json.test.y_number_0e+1" { | |
| 98 | 98 | ok( |
| 99 | 99 | \\[0e+1] |
| 100 | 100 | ); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | test "y_number_0e1" { | |
| 103 | test "json.test.y_number_0e1" { | |
| 104 | 104 | ok( |
| 105 | 105 | \\[0e1] |
| 106 | 106 | ); |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | test "y_number_after_space" { | |
| 109 | test "json.test.y_number_after_space" { | |
| 110 | 110 | ok( |
| 111 | 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 | 116 | ok( |
| 117 | 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 | 122 | ok( |
| 123 | 123 | \\[20e1] |
| 124 | 124 | ); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | test "y_number" { | |
| 127 | test "json.test.y_number" { | |
| 128 | 128 | ok( |
| 129 | 129 | \\[123e65] |
| 130 | 130 | ); |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | test "y_number_minus_zero" { | |
| 133 | test "json.test.y_number_minus_zero" { | |
| 134 | 134 | ok( |
| 135 | 135 | \\[-0] |
| 136 | 136 | ); |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | test "y_number_negative_int" { | |
| 139 | test "json.test.y_number_negative_int" { | |
| 140 | 140 | ok( |
| 141 | 141 | \\[-123] |
| 142 | 142 | ); |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | test "y_number_negative_one" { | |
| 145 | test "json.test.y_number_negative_one" { | |
| 146 | 146 | ok( |
| 147 | 147 | \\[-1] |
| 148 | 148 | ); |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | test "y_number_negative_zero" { | |
| 151 | test "json.test.y_number_negative_zero" { | |
| 152 | 152 | ok( |
| 153 | 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 | 158 | ok( |
| 159 | 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 | 164 | ok( |
| 165 | 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 | 170 | ok( |
| 171 | 171 | \\[1E+2] |
| 172 | 172 | ); |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | test "y_number_real_exponent" { | |
| 175 | test "json.test.y_number_real_exponent" { | |
| 176 | 176 | ok( |
| 177 | 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 | 182 | ok( |
| 183 | 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 | 188 | ok( |
| 189 | 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 | 194 | ok( |
| 195 | 195 | \\[1e+2] |
| 196 | 196 | ); |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | test "y_number_simple_int" { | |
| 199 | test "json.test.y_number_simple_int" { | |
| 200 | 200 | ok( |
| 201 | 201 | \\[123] |
| 202 | 202 | ); |
| 203 | 203 | } |
| 204 | 204 | |
| 205 | test "y_number_simple_real" { | |
| 205 | test "json.test.y_number_simple_real" { | |
| 206 | 206 | ok( |
| 207 | 207 | \\[123.456789] |
| 208 | 208 | ); |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | test "y_object_basic" { | |
| 211 | test "json.test.y_object_basic" { | |
| 212 | 212 | ok( |
| 213 | 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 | 218 | ok( |
| 219 | 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 | 224 | ok( |
| 225 | 225 | \\{"a":"b","a":"c"} |
| 226 | 226 | ); |
| 227 | 227 | } |
| 228 | 228 | |
| 229 | test "y_object_empty" { | |
| 229 | test "json.test.y_object_empty" { | |
| 230 | 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 | 236 | ok( |
| 237 | 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 | 242 | ok( |
| 243 | 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 | 248 | ok( |
| 249 | 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 | 254 | ok( |
| 255 | 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 | 260 | ok( |
| 261 | 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 | 266 | ok( |
| 267 | 267 | \\{"a":[]} |
| 268 | 268 | ); |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | test "y_object_string_unicode" { | |
| 271 | test "json.test.y_object_string_unicode" { | |
| 272 | 272 | ok( |
| 273 | 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 | 278 | ok( |
| 279 | 279 | \\{ |
| 280 | 280 | \\"a": "b" |
| ... | ... | @@ -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 | 286 | ok( |
| 287 | 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 | 292 | ok( |
| 293 | 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 | 298 | ok( |
| 299 | 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 | 304 | ok( |
| 305 | 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 | 310 | ok( |
| 311 | 311 | \\["\\u0000"] |
| 312 | 312 | ); |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | test "y_string_backslash_doublequotes" { | |
| 315 | test "json.test.y_string_backslash_doublequotes" { | |
| 316 | 316 | ok( |
| 317 | 317 | \\["\""] |
| 318 | 318 | ); |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | test "y_string_comments" { | |
| 321 | test "json.test.y_string_comments" { | |
| 322 | 322 | ok( |
| 323 | 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 | 328 | ok( |
| 329 | 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 | 334 | ok( |
| 335 | 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 | 340 | ok( |
| 341 | 341 | \\["\u0012"] |
| 342 | 342 | ); |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | test "y_string_escaped_noncharacter" { | |
| 345 | test "json.test.y_string_escaped_noncharacter" { | |
| 346 | 346 | ok( |
| 347 | 347 | \\["\uFFFF"] |
| 348 | 348 | ); |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | test "y_string_in_array" { | |
| 351 | test "json.test.y_string_in_array" { | |
| 352 | 352 | ok( |
| 353 | 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 | 358 | ok( |
| 359 | 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 | 364 | ok( |
| 365 | 365 | \\["\uDBFF\uDFFF"] |
| 366 | 366 | ); |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | test "y_string_nbsp_uescaped" { | |
| 369 | test "json.test.y_string_nbsp_uescaped" { | |
| 370 | 370 | ok( |
| 371 | 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 | 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 | 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 | 388 | ok( |
| 389 | 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 | 394 | ok( |
| 395 | 395 | \\["\u002c"] |
| 396 | 396 | ); |
| 397 | 397 | } |
| 398 | 398 | |
| 399 | test "y_string_pi" { | |
| 399 | test "json.test.y_string_pi" { | |
| 400 | 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 | 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 | 412 | ok( |
| 413 | 413 | \\["asd "] |
| 414 | 414 | ); |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | test "y_string_space" { | |
| 417 | test "json.test.y_string_space" { | |
| 418 | 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 | 424 | ok( |
| 425 | 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 | 430 | ok( |
| 431 | 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 | 436 | ok( |
| 437 | 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 | 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 | 446 | ok("[\"\xe2\x80\xa9\"]"); |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | test "y_string_uescaped_newline" { | |
| 449 | test "json.test.y_string_uescaped_newline" { | |
| 450 | 450 | ok( |
| 451 | 451 | \\["new\u000Aline"] |
| 452 | 452 | ); |
| 453 | 453 | } |
| 454 | 454 | |
| 455 | test "y_string_uEscape" { | |
| 455 | test "json.test.y_string_uEscape" { | |
| 456 | 456 | ok( |
| 457 | 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 | 462 | ok("[\"\x7f\"]"); |
| 463 | 463 | } |
| 464 | 464 | |
| 465 | test "y_string_unicode_2" { | |
| 465 | test "json.test.y_string_unicode_2" { | |
| 466 | 466 | ok( |
| 467 | 467 | \\["⍂㈴⍂"] |
| 468 | 468 | ); |
| 469 | 469 | } |
| 470 | 470 | |
| 471 | test "y_string_unicodeEscapedBackslash" { | |
| 471 | test "json.test.y_string_unicodeEscapedBackslash" { | |
| 472 | 472 | ok( |
| 473 | 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 | 478 | ok( |
| 479 | 479 | \\["\u0022"] |
| 480 | 480 | ); |
| 481 | 481 | } |
| 482 | 482 | |
| 483 | test "y_string_unicode" { | |
| 483 | test "json.test.y_string_unicode" { | |
| 484 | 484 | ok( |
| 485 | 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 | 490 | ok( |
| 491 | 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 | 496 | ok( |
| 497 | 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 | 502 | ok( |
| 503 | 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 | 508 | ok( |
| 509 | 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 | 514 | ok( |
| 515 | 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 | 520 | ok( |
| 521 | 521 | \\["\uFFFE"] |
| 522 | 522 | ); |
| 523 | 523 | } |
| 524 | 524 | |
| 525 | test "y_string_utf8" { | |
| 525 | test "json.test.y_string_utf8" { | |
| 526 | 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 | 532 | ok("[\"a\x7fa\"]"); |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | test "y_structure_lonely_false" { | |
| 535 | test "json.test.y_structure_lonely_false" { | |
| 536 | 536 | ok( |
| 537 | 537 | \\false |
| 538 | 538 | ); |
| 539 | 539 | } |
| 540 | 540 | |
| 541 | test "y_structure_lonely_int" { | |
| 541 | test "json.test.y_structure_lonely_int" { | |
| 542 | 542 | ok( |
| 543 | 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 | 548 | ok( |
| 549 | 549 | \\-0.1 |
| 550 | 550 | ); |
| 551 | 551 | } |
| 552 | 552 | |
| 553 | test "y_structure_lonely_null" { | |
| 553 | test "json.test.y_structure_lonely_null" { | |
| 554 | 554 | ok( |
| 555 | 555 | \\null |
| 556 | 556 | ); |
| 557 | 557 | } |
| 558 | 558 | |
| 559 | test "y_structure_lonely_string" { | |
| 559 | test "json.test.y_structure_lonely_string" { | |
| 560 | 560 | ok( |
| 561 | 561 | \\"asd" |
| 562 | 562 | ); |
| 563 | 563 | } |
| 564 | 564 | |
| 565 | test "y_structure_lonely_true" { | |
| 565 | test "json.test.y_structure_lonely_true" { | |
| 566 | 566 | ok( |
| 567 | 567 | \\true |
| 568 | 568 | ); |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | test "y_structure_string_empty" { | |
| 571 | test "json.test.y_structure_string_empty" { | |
| 572 | 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 | 578 | ok( |
| 579 | 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 | 584 | ok( |
| 585 | 585 | \\[true] |
| 586 | 586 | ); |
| 587 | 587 | } |
| 588 | 588 | |
| 589 | test "y_structure_whitespace_array" { | |
| 589 | test "json.test.y_structure_whitespace_array" { | |
| 590 | 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 | 596 | err( |
| 597 | 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 | 602 | err( |
| 603 | 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 | 608 | err( |
| 609 | 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 | 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 | 620 | err( |
| 621 | 621 | \\[,1] |
| 622 | 622 | ); |
| 623 | 623 | } |
| 624 | 624 | |
| 625 | test "n_array_double_comma" { | |
| 625 | test "json.test.n_array_double_comma" { | |
| 626 | 626 | err( |
| 627 | 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 | 632 | err( |
| 633 | 633 | \\["x",,] |
| 634 | 634 | ); |
| 635 | 635 | } |
| 636 | 636 | |
| 637 | test "n_array_extra_close" { | |
| 637 | test "json.test.n_array_extra_close" { | |
| 638 | 638 | err( |
| 639 | 639 | \\["x"]] |
| 640 | 640 | ); |
| 641 | 641 | } |
| 642 | 642 | |
| 643 | test "n_array_extra_comma" { | |
| 643 | test "json.test.n_array_extra_comma" { | |
| 644 | 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 | 650 | err( |
| 651 | 651 | \\[x |
| 652 | 652 | ); |
| 653 | 653 | } |
| 654 | 654 | |
| 655 | test "n_array_incomplete" { | |
| 655 | test "json.test.n_array_incomplete" { | |
| 656 | 656 | err( |
| 657 | 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 | 662 | err( |
| 663 | 663 | \\[3[4]] |
| 664 | 664 | ); |
| 665 | 665 | } |
| 666 | 666 | |
| 667 | test "n_array_invalid_utf8" { | |
| 667 | test "json.test.n_array_invalid_utf8" { | |
| 668 | 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 | 674 | err( |
| 675 | 675 | \\[1:2] |
| 676 | 676 | ); |
| 677 | 677 | } |
| 678 | 678 | |
| 679 | test "n_array_just_comma" { | |
| 679 | test "json.test.n_array_just_comma" { | |
| 680 | 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 | 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 | 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 | 698 | err( |
| 699 | 699 | \\["a", |
| 700 | 700 | \\4 |
| ... | ... | @@ -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 | 706 | err( |
| 707 | 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 | 712 | err( |
| 713 | 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 | 718 | err("[\"\x0aa\"\\f]"); |
| 719 | 719 | } |
| 720 | 720 | |
| 721 | test "n_array_star_inside" { | |
| 721 | test "json.test.n_array_star_inside" { | |
| 722 | 722 | err( |
| 723 | 723 | \\[*] |
| 724 | 724 | ); |
| 725 | 725 | } |
| 726 | 726 | |
| 727 | test "n_array_unclosed" { | |
| 727 | test "json.test.n_array_unclosed" { | |
| 728 | 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 | 734 | err( |
| 735 | 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 | 740 | err( |
| 741 | 741 | \\[1, |
| 742 | 742 | \\1 |
| ... | ... | @@ -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 | 748 | err( |
| 749 | 749 | \\[{} |
| 750 | 750 | ); |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | test "n_incomplete_false" { | |
| 753 | test "json.test.n_incomplete_false" { | |
| 754 | 754 | err( |
| 755 | 755 | \\[fals] |
| 756 | 756 | ); |
| 757 | 757 | } |
| 758 | 758 | |
| 759 | test "n_incomplete_null" { | |
| 759 | test "json.test.n_incomplete_null" { | |
| 760 | 760 | err( |
| 761 | 761 | \\[nul] |
| 762 | 762 | ); |
| 763 | 763 | } |
| 764 | 764 | |
| 765 | test "n_incomplete_true" { | |
| 765 | test "json.test.n_incomplete_true" { | |
| 766 | 766 | err( |
| 767 | 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 | 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 | 776 | err( |
| 777 | 777 | \\[0.1.2] |
| 778 | 778 | ); |
| 779 | 779 | } |
| 780 | 780 | |
| 781 | test "n_number_-01" { | |
| 781 | test "json.test.n_number_-01" { | |
| 782 | 782 | err( |
| 783 | 783 | \\[-01] |
| 784 | 784 | ); |
| 785 | 785 | } |
| 786 | 786 | |
| 787 | test "n_number_0.3e" { | |
| 787 | test "json.test.n_number_0.3e" { | |
| 788 | 788 | err( |
| 789 | 789 | \\[0.3e] |
| 790 | 790 | ); |
| 791 | 791 | } |
| 792 | 792 | |
| 793 | test "n_number_0.3e+" { | |
| 793 | test "json.test.n_number_0.3e+" { | |
| 794 | 794 | err( |
| 795 | 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 | 800 | err( |
| 801 | 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 | 806 | err( |
| 807 | 807 | \\[0E+] |
| 808 | 808 | ); |
| 809 | 809 | } |
| 810 | 810 | |
| 811 | test "n_number_0.e1" { | |
| 811 | test "json.test.n_number_0.e1" { | |
| 812 | 812 | err( |
| 813 | 813 | \\[0.e1] |
| 814 | 814 | ); |
| 815 | 815 | } |
| 816 | 816 | |
| 817 | test "n_number_0e" { | |
| 817 | test "json.test.n_number_0e" { | |
| 818 | 818 | err( |
| 819 | 819 | \\[0e] |
| 820 | 820 | ); |
| 821 | 821 | } |
| 822 | 822 | |
| 823 | test "n_number_0e+" { | |
| 823 | test "json.test.n_number_0e+" { | |
| 824 | 824 | err( |
| 825 | 825 | \\[0e+] |
| 826 | 826 | ); |
| 827 | 827 | } |
| 828 | 828 | |
| 829 | test "n_number_1_000" { | |
| 829 | test "json.test.n_number_1_000" { | |
| 830 | 830 | err( |
| 831 | 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 | 836 | err( |
| 837 | 837 | \\[1.0e-] |
| 838 | 838 | ); |
| 839 | 839 | } |
| 840 | 840 | |
| 841 | test "n_number_1.0e" { | |
| 841 | test "json.test.n_number_1.0e" { | |
| 842 | 842 | err( |
| 843 | 843 | \\[1.0e] |
| 844 | 844 | ); |
| 845 | 845 | } |
| 846 | 846 | |
| 847 | test "n_number_1.0e+" { | |
| 847 | test "json.test.n_number_1.0e+" { | |
| 848 | 848 | err( |
| 849 | 849 | \\[1.0e+] |
| 850 | 850 | ); |
| 851 | 851 | } |
| 852 | 852 | |
| 853 | test "n_number_-1.0." { | |
| 853 | test "json.test.n_number_-1.0." { | |
| 854 | 854 | err( |
| 855 | 855 | \\[-1.0.] |
| 856 | 856 | ); |
| 857 | 857 | } |
| 858 | 858 | |
| 859 | test "n_number_1eE2" { | |
| 859 | test "json.test.n_number_1eE2" { | |
| 860 | 860 | err( |
| 861 | 861 | \\[1eE2] |
| 862 | 862 | ); |
| 863 | 863 | } |
| 864 | 864 | |
| 865 | test "n_number_.-1" { | |
| 865 | test "json.test.n_number_.-1" { | |
| 866 | 866 | err( |
| 867 | 867 | \\[.-1] |
| 868 | 868 | ); |
| 869 | 869 | } |
| 870 | 870 | |
| 871 | test "n_number_+1" { | |
| 871 | test "json.test.n_number_+1" { | |
| 872 | 872 | err( |
| 873 | 873 | \\[+1] |
| 874 | 874 | ); |
| 875 | 875 | } |
| 876 | 876 | |
| 877 | test "n_number_.2e-3" { | |
| 877 | test "json.test.n_number_.2e-3" { | |
| 878 | 878 | err( |
| 879 | 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 | 884 | err( |
| 885 | 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 | 890 | err( |
| 891 | 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 | 896 | err( |
| 897 | 897 | \\[2.e3] |
| 898 | 898 | ); |
| 899 | 899 | } |
| 900 | 900 | |
| 901 | test "n_number_-2." { | |
| 901 | test "json.test.n_number_-2." { | |
| 902 | 902 | err( |
| 903 | 903 | \\[-2.] |
| 904 | 904 | ); |
| 905 | 905 | } |
| 906 | 906 | |
| 907 | test "n_number_9.e+" { | |
| 907 | test "json.test.n_number_9.e+" { | |
| 908 | 908 | err( |
| 909 | 909 | \\[9.e+] |
| 910 | 910 | ); |
| 911 | 911 | } |
| 912 | 912 | |
| 913 | test "n_number_expression" { | |
| 913 | test "json.test.n_number_expression" { | |
| 914 | 914 | err( |
| 915 | 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 | 920 | err( |
| 921 | 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 | 926 | err( |
| 927 | 927 | \\[0x42] |
| 928 | 928 | ); |
| 929 | 929 | } |
| 930 | 930 | |
| 931 | test "n_number_infinity" { | |
| 931 | test "json.test.n_number_infinity" { | |
| 932 | 932 | err( |
| 933 | 933 | \\[Infinity] |
| 934 | 934 | ); |
| 935 | 935 | } |
| 936 | 936 | |
| 937 | test "n_number_+Inf" { | |
| 937 | test "json.test.n_number_+Inf" { | |
| 938 | 938 | err( |
| 939 | 939 | \\[+Inf] |
| 940 | 940 | ); |
| 941 | 941 | } |
| 942 | 942 | |
| 943 | test "n_number_Inf" { | |
| 943 | test "json.test.n_number_Inf" { | |
| 944 | 944 | err( |
| 945 | 945 | \\[Inf] |
| 946 | 946 | ); |
| 947 | 947 | } |
| 948 | 948 | |
| 949 | test "n_number_invalid+-" { | |
| 949 | test "json.test.n_number_invalid+-" { | |
| 950 | 950 | err( |
| 951 | 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 | 956 | err( |
| 957 | 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 | 962 | err( |
| 963 | 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 | 968 | err( |
| 969 | 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 | 974 | err( |
| 975 | 975 | \\[0å] |
| 976 | 976 | ); |
| 977 | 977 | } |
| 978 | 978 | |
| 979 | test "n_number_++" { | |
| 979 | test "json.test.n_number_++" { | |
| 980 | 980 | err( |
| 981 | 981 | \\[++1234] |
| 982 | 982 | ); |
| 983 | 983 | } |
| 984 | 984 | |
| 985 | test "n_number_minus_infinity" { | |
| 985 | test "json.test.n_number_minus_infinity" { | |
| 986 | 986 | err( |
| 987 | 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 | 992 | err( |
| 993 | 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 | 998 | err( |
| 999 | 999 | \\[- 1] |
| 1000 | 1000 | ); |
| 1001 | 1001 | } |
| 1002 | 1002 | |
| 1003 | test "n_number_-NaN" { | |
| 1003 | test "json.test.n_number_-NaN" { | |
| 1004 | 1004 | err( |
| 1005 | 1005 | \\[-NaN] |
| 1006 | 1006 | ); |
| 1007 | 1007 | } |
| 1008 | 1008 | |
| 1009 | test "n_number_NaN" { | |
| 1009 | test "json.test.n_number_NaN" { | |
| 1010 | 1010 | err( |
| 1011 | 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 | 1016 | err( |
| 1017 | 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 | 1022 | err( |
| 1023 | 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 | 1028 | err( |
| 1029 | 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 | 1034 | err( |
| 1035 | 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 | 1040 | err( |
| 1041 | 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 | 1046 | err( |
| 1047 | 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 | 1052 | err( |
| 1053 | 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 | 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 | 1064 | err( |
| 1065 | 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 | 1070 | err( |
| 1071 | 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 | 1076 | err( |
| 1077 | 1077 | \\[012] |
| 1078 | 1078 | ); |
| 1079 | 1079 | } |
| 1080 | 1080 | |
| 1081 | test "n_object_bad_value" { | |
| 1081 | test "json.test.n_object_bad_value" { | |
| 1082 | 1082 | err( |
| 1083 | 1083 | \\["x", truth] |
| 1084 | 1084 | ); |
| 1085 | 1085 | } |
| 1086 | 1086 | |
| 1087 | test "n_object_bracket_key" { | |
| 1087 | test "json.test.n_object_bracket_key" { | |
| 1088 | 1088 | err( |
| 1089 | 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 | 1094 | err( |
| 1095 | 1095 | \\{"x", null} |
| 1096 | 1096 | ); |
| 1097 | 1097 | } |
| 1098 | 1098 | |
| 1099 | test "n_object_double_colon" { | |
| 1099 | test "json.test.n_object_double_colon" { | |
| 1100 | 1100 | err( |
| 1101 | 1101 | \\{"x"::"b"} |
| 1102 | 1102 | ); |
| 1103 | 1103 | } |
| 1104 | 1104 | |
| 1105 | test "n_object_emoji" { | |
| 1105 | test "json.test.n_object_emoji" { | |
| 1106 | 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 | 1112 | err( |
| 1113 | 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 | 1118 | err( |
| 1119 | 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 | 1124 | err( |
| 1125 | 1125 | \\{"¹":"0",} |
| 1126 | 1126 | ); |
| 1127 | 1127 | } |
| 1128 | 1128 | |
| 1129 | test "n_object_missing_colon" { | |
| 1129 | test "json.test.n_object_missing_colon" { | |
| 1130 | 1130 | err( |
| 1131 | 1131 | \\{"a" b} |
| 1132 | 1132 | ); |
| 1133 | 1133 | } |
| 1134 | 1134 | |
| 1135 | test "n_object_missing_key" { | |
| 1135 | test "json.test.n_object_missing_key" { | |
| 1136 | 1136 | err( |
| 1137 | 1137 | \\{:"b"} |
| 1138 | 1138 | ); |
| 1139 | 1139 | } |
| 1140 | 1140 | |
| 1141 | test "n_object_missing_semicolon" { | |
| 1141 | test "json.test.n_object_missing_semicolon" { | |
| 1142 | 1142 | err( |
| 1143 | 1143 | \\{"a" "b"} |
| 1144 | 1144 | ); |
| 1145 | 1145 | } |
| 1146 | 1146 | |
| 1147 | test "n_object_missing_value" { | |
| 1147 | test "json.test.n_object_missing_value" { | |
| 1148 | 1148 | err( |
| 1149 | 1149 | \\{"a": |
| 1150 | 1150 | ); |
| 1151 | 1151 | } |
| 1152 | 1152 | |
| 1153 | test "n_object_no-colon" { | |
| 1153 | test "json.test.n_object_no-colon" { | |
| 1154 | 1154 | err( |
| 1155 | 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 | 1160 | err( |
| 1161 | 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 | 1166 | err( |
| 1167 | 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 | 1172 | err( |
| 1173 | 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 | 1178 | err( |
| 1179 | 1179 | \\{"id":0,,,,,} |
| 1180 | 1180 | ); |
| 1181 | 1181 | } |
| 1182 | 1182 | |
| 1183 | test "n_object_single_quote" { | |
| 1183 | test "json.test.n_object_single_quote" { | |
| 1184 | 1184 | err( |
| 1185 | 1185 | \\{'a':0} |
| 1186 | 1186 | ); |
| 1187 | 1187 | } |
| 1188 | 1188 | |
| 1189 | test "n_object_trailing_comma" { | |
| 1189 | test "json.test.n_object_trailing_comma" { | |
| 1190 | 1190 | err( |
| 1191 | 1191 | \\{"id":0,} |
| 1192 | 1192 | ); |
| 1193 | 1193 | } |
| 1194 | 1194 | |
| 1195 | test "n_object_trailing_comment" { | |
| 1195 | test "json.test.n_object_trailing_comment" { | |
| 1196 | 1196 | err( |
| 1197 | 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 | 1202 | err( |
| 1203 | 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 | 1208 | err( |
| 1209 | 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 | 1214 | err( |
| 1215 | 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 | 1220 | err( |
| 1221 | 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 | 1226 | err( |
| 1227 | 1227 | \\{a: "b"} |
| 1228 | 1228 | ); |
| 1229 | 1229 | } |
| 1230 | 1230 | |
| 1231 | test "n_object_unterminated-value" { | |
| 1231 | test "json.test.n_object_unterminated-value" { | |
| 1232 | 1232 | err( |
| 1233 | 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 | 1238 | err( |
| 1239 | 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 | 1244 | err( |
| 1245 | 1245 | \\{"a":"b"}# |
| 1246 | 1246 | ); |
| 1247 | 1247 | } |
| 1248 | 1248 | |
| 1249 | test "n_single_space" { | |
| 1249 | test "json.test.n_single_space" { | |
| 1250 | 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 | 1254 | err( |
| 1255 | 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 | 1260 | err( |
| 1261 | 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 | 1266 | err( |
| 1267 | 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 | 1272 | err( |
| 1273 | 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 | 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 | 1284 | err("[\"\x00\"]"); |
| 1285 | 1285 | } |
| 1286 | 1286 | |
| 1287 | test "n_string_escaped_backslash_bad" { | |
| 1287 | test "json.test.n_string_escaped_backslash_bad" { | |
| 1288 | 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 | 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 | 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 | 1302 | err( |
| 1303 | 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 | 1308 | err( |
| 1309 | 1309 | \\["\u00A"] |
| 1310 | 1310 | ); |
| 1311 | 1311 | } |
| 1312 | 1312 | |
| 1313 | test "n_string_incomplete_escape" { | |
| 1313 | test "json.test.n_string_incomplete_escape" { | |
| 1314 | 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 | 1320 | err( |
| 1321 | 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 | 1326 | err( |
| 1327 | 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 | 1332 | err( |
| 1333 | 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 | 1338 | err( |
| 1339 | 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 | 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 | 1348 | err( |
| 1349 | 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 | 1354 | err( |
| 1355 | 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 | 1360 | err( |
| 1361 | 1361 | \\[\n] |
| 1362 | 1362 | ); |
| 1363 | 1363 | } |
| 1364 | 1364 | |
| 1365 | test "n_string_single_doublequote" { | |
| 1365 | test "json.test.n_string_single_doublequote" { | |
| 1366 | 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 | 1372 | err( |
| 1373 | 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 | 1378 | err( |
| 1379 | 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 | 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 | 1390 | err("[\"a\x00a\"]"); |
| 1391 | 1391 | } |
| 1392 | 1392 | |
| 1393 | test "n_string_unescaped_newline" { | |
| 1393 | test "json.test.n_string_unescaped_newline" { | |
| 1394 | 1394 | err( |
| 1395 | 1395 | \\["new |
| 1396 | 1396 | \\line"] |
| 1397 | 1397 | ); |
| 1398 | 1398 | } |
| 1399 | 1399 | |
| 1400 | test "n_string_unescaped_tab" { | |
| 1400 | test "json.test.n_string_unescaped_tab" { | |
| 1401 | 1401 | err("[\"\t\"]"); |
| 1402 | 1402 | } |
| 1403 | 1403 | |
| 1404 | test "n_string_unicode_CapitalU" { | |
| 1404 | test "json.test.n_string_unicode_CapitalU" { | |
| 1405 | 1405 | err( |
| 1406 | 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 | 1411 | err( |
| 1412 | 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 | 1417 | err("[" ** 100000); |
| 1418 | 1418 | } |
| 1419 | 1419 | |
| 1420 | test "n_structure_angle_bracket_." { | |
| 1420 | test "json.test.n_structure_angle_bracket_." { | |
| 1421 | 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 | 1427 | err( |
| 1428 | 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 | 1433 | err( |
| 1434 | 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 | 1439 | err( |
| 1440 | 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 | 1445 | err( |
| 1446 | 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 | 1451 | err( |
| 1452 | 1452 | \\aå |
| 1453 | 1453 | ); |
| 1454 | 1454 | } |
| 1455 | 1455 | |
| 1456 | test "n_structure_capitalized_True" { | |
| 1456 | test "json.test.n_structure_capitalized_True" { | |
| 1457 | 1457 | err( |
| 1458 | 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 | 1463 | err( |
| 1464 | 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 | 1469 | err( |
| 1470 | 1470 | \\{"x": true, |
| 1471 | 1471 | ); |
| 1472 | 1472 | } |
| 1473 | 1473 | |
| 1474 | test "n_structure_double_array" { | |
| 1474 | test "json.test.n_structure_double_array" { | |
| 1475 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1515 | err( |
| 1516 | 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 | 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 | 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 | 1533 | err( |
| 1534 | 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 | 1539 | err( |
| 1540 | 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 | 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 | 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 | 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 | 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 | 1567 | err( |
| 1568 | 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 | 1573 | err( |
| 1574 | 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 | 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 | 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 | 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 | 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 | 1603 | err( |
| 1604 | 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 | 1609 | err( |
| 1610 | 1610 | \\{'a' |
| 1611 | 1611 | ); |
| 1612 | 1612 | } |
| 1613 | 1613 | |
| 1614 | test "n_structure_open_open" { | |
| 1614 | test "json.test.n_structure_open_open" { | |
| 1615 | 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 | 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 | 1627 | err( |
| 1628 | 1628 | \\* |
| 1629 | 1629 | ); |
| 1630 | 1630 | } |
| 1631 | 1631 | |
| 1632 | test "n_structure_trailing_#" { | |
| 1632 | test "json.test.n_structure_trailing_#" { | |
| 1633 | 1633 | err( |
| 1634 | 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 | 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 | 1645 | err( |
| 1646 | 1646 | \\[\u000A""] |
| 1647 | 1647 | ); |
| 1648 | 1648 | } |
| 1649 | 1649 | |
| 1650 | test "n_structure_unclosed_array" { | |
| 1650 | test "json.test.n_structure_unclosed_array" { | |
| 1651 | 1651 | err( |
| 1652 | 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 | 1657 | err( |
| 1658 | 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 | 1663 | err( |
| 1664 | 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 | 1669 | err( |
| 1670 | 1670 | \\[ false, tru |
| 1671 | 1671 | ); |
| 1672 | 1672 | } |
| 1673 | 1673 | |
| 1674 | test "n_structure_unclosed_object" { | |
| 1674 | test "json.test.n_structure_unclosed_object" { | |
| 1675 | 1675 | err( |
| 1676 | 1676 | \\{"asd":"asd" |
| 1677 | 1677 | ); |
| 1678 | 1678 | } |
| 1679 | 1679 | |
| 1680 | test "n_structure_unicode-identifier" { | |
| 1680 | test "json.test.n_structure_unicode-identifier" { | |
| 1681 | 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 | 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 | 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 | 1697 | err( |
| 1698 | 1698 | \\[â ] |
| 1699 | 1699 | ); |
| ... | ... | @@ -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 | 1705 | any( |
| 1706 | 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 | 1711 | any( |
| 1712 | 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 | 1717 | any( |
| 1718 | 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 | 1723 | any( |
| 1724 | 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 | 1729 | any( |
| 1730 | 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 | 1735 | any( |
| 1736 | 1736 | \\[123123e100000] |
| 1737 | 1737 | ); |
| 1738 | 1738 | } |
| 1739 | 1739 | |
| 1740 | test "i_number_real_underflow" { | |
| 1740 | test "json.test.i_number_real_underflow" { | |
| 1741 | 1741 | any( |
| 1742 | 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 | 1747 | any( |
| 1748 | 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 | 1753 | any( |
| 1754 | 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 | 1759 | any( |
| 1760 | 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 | 1765 | any( |
| 1766 | 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 | 1771 | any( |
| 1772 | 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 | 1777 | any( |
| 1778 | 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 | 1783 | any( |
| 1784 | 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 | 1789 | any( |
| 1790 | 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 | 1795 | any( |
| 1796 | 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 | 1801 | any( |
| 1802 | 1802 | \\["\ud800"] |
| 1803 | 1803 | ); |
| 1804 | 1804 | } |
| 1805 | 1805 | |
| 1806 | test "i_string_invalid_surrogate" { | |
| 1806 | test "json.test.i_string_invalid_surrogate" { | |
| 1807 | 1807 | any( |
| 1808 | 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 | 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 | 1819 | any( |
| 1820 | 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 | 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 | 1831 | any( |
| 1832 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1901 | any( |
| 1902 | 1902 | \\{} |
| 1903 | 1903 | ); |
std/linked_list.zig+96| ... | ... | @@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type { |
| 82 | 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 | 107 | /// Insert a new node at the end of the list. |
| 86 | 108 | /// |
| 87 | 109 | /// Arguments: |
| ... | ... | @@ -247,3 +269,77 @@ test "basic linked list test" { |
| 247 | 269 | assert(list.last.?.data == 4); |
| 248 | 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 | pub const e = 2.71828182845904523536028747135266249775724709369995; |
| 7 | 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 | 16 | // float.h details |
| 10 | 17 | pub const f64_true_min = 4.94065645841246544177e-324; |
| 11 | 18 | pub const f64_min = 2.2250738585072014e-308; |
| ... | ... | @@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type { |
| 365 | 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 | 438 | test "math overflow functions" { |
| 369 | 439 | testOverflow(); |
| 370 | 440 | comptime testOverflow(); |
std/mem.zig+277-148| ... | ... | @@ -410,12 +410,8 @@ test "mem.indexOf" { |
| 410 | 410 | /// Reads an integer from memory with size equal to bytes.len. |
| 411 | 411 | /// T specifies the return type, which must be large enough to store |
| 412 | 412 | /// the result. |
| 413 | /// See also ::readIntBE or ::readIntLE. | |
| 414 | pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { | |
| 415 | if (T.bit_count == 8) { | |
| 416 | return bytes[0]; | |
| 417 | } | |
| 418 | var result: T = 0; | |
| 413 | pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType { | |
| 414 | var result: ReturnType = 0; | |
| 419 | 415 | switch (endian) { |
| 420 | 416 | builtin.Endian.Big => { |
| 421 | 417 | for (bytes) |b| { |
| ... | ... | @@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { |
| 423 | 419 | } |
| 424 | 420 | }, |
| 425 | 421 | builtin.Endian.Little => { |
| 426 | const ShiftType = math.Log2Int(T); | |
| 422 | const ShiftType = math.Log2Int(ReturnType); | |
| 427 | 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 | 428 | return result; |
| 433 | 429 | } |
| 434 | 430 | |
| 435 | /// Reads a big-endian int of type T from bytes. | |
| 436 | /// bytes.len must be exactly @sizeOf(T). | |
| 437 | pub fn readIntBE(comptime T: type, bytes: []const u8) T { | |
| 438 | if (T.is_signed) { | |
| 439 | return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); | |
| 440 | } | |
| 441 | assert(bytes.len == @sizeOf(T)); | |
| 442 | if (T == u8) return bytes[0]; | |
| 443 | var result: T = 0; | |
| 444 | { | |
| 445 | comptime var i = 0; | |
| 446 | inline while (i < @sizeOf(T)) : (i += 1) { | |
| 447 | result = (result << 8) | T(bytes[i]); | |
| 448 | } | |
| 431 | /// Reads an integer from memory with bit count specified by T. | |
| 432 | /// The bit count of T must be evenly divisible by 8. | |
| 433 | /// This function cannot fail and cannot cause undefined behavior. | |
| 434 | /// Assumes the endianness of memory is native. This means the function can | |
| 435 | /// simply pointer cast memory. | |
| 436 | pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { | |
| 437 | comptime assert(T.bit_count % 8 == 0); | |
| 438 | return @ptrCast(*align(1) const T, bytes).*; | |
| 439 | } | |
| 440 | ||
| 441 | /// Reads an integer from memory with bit count specified by T. | |
| 442 | /// The bit count of T must be evenly divisible by 8. | |
| 443 | /// This function cannot fail and cannot cause undefined behavior. | |
| 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. | |
| 454 | /// bytes.len must be exactly @sizeOf(T). | |
| 455 | pub fn readIntLE(comptime T: type, bytes: []const u8) T { | |
| 456 | if (T.is_signed) { | |
| 457 | return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); | |
| 502 | /// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 | |
| 503 | /// and ignores extra bytes. | |
| 504 | /// Note that @sizeOf(u24) is 3. | |
| 505 | /// The bit count of T must be evenly divisible by 8. | |
| 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)); | |
| 460 | if (T == u8) return bytes[0]; | |
| 461 | var result: T = 0; | |
| 462 | { | |
| 463 | comptime var i = 0; | |
| 464 | inline while (i < @sizeOf(T)) : (i += 1) { | |
| 465 | result |= T(bytes[i]) << i * 8; | |
| 466 | } | |
| 520 | comptime { | |
| 521 | var bytes: [2]u8 = undefined; | |
| 522 | std.mem.writeIntBig(u16, &bytes, 0x1234); | |
| 523 | const result = std.mem.readIntLittle(u16, &bytes); | |
| 524 | std.debug.assert(result == 0x3412); | |
| 467 | 525 | } |
| 468 | return result; | |
| 469 | 526 | } |
| 470 | 527 | |
| 471 | test "readIntBE/LE" { | |
| 472 | assert(readIntBE(u0, []u8{}) == 0x0); | |
| 473 | assert(readIntLE(u0, []u8{}) == 0x0); | |
| 528 | test "readIntBig and readIntLittle" { | |
| 529 | assert(readIntSliceBig(u0, []u8{}) == 0x0); | |
| 530 | assert(readIntSliceLittle(u0, []u8{}) == 0x0); | |
| 474 | 531 | |
| 475 | assert(readIntBE(u8, []u8{0x32}) == 0x32); | |
| 476 | assert(readIntLE(u8, []u8{0x12}) == 0x12); | |
| 532 | assert(readIntSliceBig(u8, []u8{0x32}) == 0x32); | |
| 533 | assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12); | |
| 477 | 534 | |
| 478 | assert(readIntBE(u16, []u8{0x12, 0x34}) == 0x1234); | |
| 479 | assert(readIntLE(u16, []u8{0x12, 0x34}) == 0x3412); | |
| 535 | assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234); | |
| 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); | |
| 482 | assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); | |
| 538 | assert(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024); | |
| 539 | assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); | |
| 483 | 540 | |
| 484 | assert(readIntBE(i8, []u8{0xff}) == -1); | |
| 485 | assert(readIntLE(i8, []u8{0xfe}) == -2); | |
| 541 | assert(readIntSliceBig(i8, []u8{0xff}) == -1); | |
| 542 | assert(readIntSliceLittle(i8, []u8{0xfe}) == -2); | |
| 486 | 543 | |
| 487 | assert(readIntBE(i16, []u8{0xff, 0xfd}) == -3); | |
| 488 | assert(readIntLE(i16, []u8{0xfc, 0xff}) == -4); | |
| 544 | assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3); | |
| 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 | |
| 492 | /// to fill the entire buffer provided. | |
| 493 | /// value must be an integer. | |
| 494 | pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { | |
| 495 | const uint = @IntType(false, @typeOf(value).bit_count); | |
| 496 | var bits = @truncate(uint, value); | |
| 497 | switch (endian) { | |
| 498 | builtin.Endian.Big => { | |
| 499 | var index: usize = buf.len; | |
| 500 | while (index != 0) { | |
| 501 | index -= 1; | |
| 548 | /// Writes an integer to memory, storing it in twos-complement. | |
| 549 | /// This function always succeeds, has defined behavior for all inputs, and | |
| 550 | /// accepts any integer bit width. | |
| 551 | /// This function stores in native endian, which means it is implemented as a simple | |
| 552 | /// memory store. | |
| 553 | pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | |
| 554 | @ptrCast(*align(1) T, buf).* = value; | |
| 555 | } | |
| 502 | 556 | |
| 503 | buf[index] = @truncate(u8, bits); | |
| 504 | bits >>= 8; | |
| 505 | } | |
| 506 | }, | |
| 507 | builtin.Endian.Little => { | |
| 508 | for (buf) |*b| { | |
| 509 | b.* = @truncate(u8, bits); | |
| 510 | bits >>= 8; | |
| 511 | } | |
| 512 | }, | |
| 557 | /// Writes an integer to memory, storing it in twos-complement. | |
| 558 | /// This function always succeeds, has defined behavior for all inputs, but | |
| 559 | /// the integer bit width must be divisible by 8. | |
| 560 | /// This function stores in foreign endian, which means it does a @bswap first. | |
| 561 | pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { | |
| 562 | writeIntNative(T, buf, @bswap(T, value)); | |
| 563 | } | |
| 564 | ||
| 565 | pub const writeIntLittle = switch (builtin.endian) { | |
| 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 { | |
| 518 | assert(T.bit_count % 8 == 0); | |
| 587 | /// Writes a twos-complement little-endian integer to memory. | |
| 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 | 599 | const uint = @IntType(false, T.bit_count); |
| 520 | if (uint == u0) { | |
| 521 | return; | |
| 522 | } | |
| 523 | var bits = @bitCast(uint, value); | |
| 524 | if (uint == u8) { | |
| 525 | buf[0] = bits; | |
| 526 | return; | |
| 600 | var bits = @truncate(uint, value); | |
| 601 | for (buffer) |*b| { | |
| 602 | b.* = @truncate(u8, bits); | |
| 603 | bits >>= 8; | |
| 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 | 621 | while (index != 0) { |
| 530 | 622 | index -= 1; |
| 531 | ||
| 532 | buf[index] = @truncate(u8, bits); | |
| 623 | buffer[index] = @truncate(u8, bits); | |
| 533 | 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 { | |
| 539 | assert(T.bit_count % 8 == 0); | |
| 540 | const uint = @IntType(false, T.bit_count); | |
| 541 | if (uint == u0) { | |
| 542 | return; | |
| 543 | } | |
| 544 | var bits = @bitCast(uint, value); | |
| 545 | if (uint == u8) { | |
| 546 | buf[0] = bits; | |
| 547 | return; | |
| 548 | } | |
| 549 | // FIXME: this should just be for (buf). | |
| 550 | // See https://github.com/ziglang/zig/issues/1663 | |
| 551 | for (buf.*) |*b| { | |
| 552 | b.* = @truncate(u8, bits); | |
| 553 | bits >>= 8; | |
| 628 | pub const writeIntSliceNative = switch (builtin.endian) { | |
| 629 | builtin.Endian.Little => writeIntSliceLittle, | |
| 630 | builtin.Endian.Big => writeIntSliceBig, | |
| 631 | }; | |
| 632 | ||
| 633 | pub const writeIntSliceForeign = switch (builtin.endian) { | |
| 634 | builtin.Endian.Little => writeIntSliceBig, | |
| 635 | builtin.Endian.Big => writeIntSliceLittle, | |
| 636 | }; | |
| 637 | ||
| 638 | /// Writes a twos-complement integer to memory, with the specified endianness. | |
| 639 | /// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. | |
| 640 | /// The bit count of T must be evenly divisible by 8. | |
| 641 | /// Any extra bytes in buffer not part of the integer are set to zero, with | |
| 642 | /// respect to endianness. To avoid the branch to check for extra buffer bytes, | |
| 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 | 653 | var buf0: [0]u8 = undefined; |
| 560 | 654 | var buf1: [1]u8 = undefined; |
| 561 | 655 | var buf2: [2]u8 = undefined; |
| 562 | 656 | var buf9: [9]u8 = undefined; |
| 563 | 657 | |
| 564 | writeIntBE(u0, &buf0, 0x0); | |
| 658 | writeIntBig(u0, &buf0, 0x0); | |
| 565 | 659 | assert(eql_slice_u8(buf0[0..], []u8{})); |
| 566 | writeIntLE(u0, &buf0, 0x0); | |
| 660 | writeIntLittle(u0, &buf0, 0x0); | |
| 567 | 661 | assert(eql_slice_u8(buf0[0..], []u8{})); |
| 568 | 662 | |
| 569 | writeIntBE(u8, &buf1, 0x12); | |
| 663 | writeIntBig(u8, &buf1, 0x12); | |
| 570 | 664 | assert(eql_slice_u8(buf1[0..], []u8{0x12})); |
| 571 | writeIntLE(u8, &buf1, 0x34); | |
| 665 | writeIntLittle(u8, &buf1, 0x34); | |
| 572 | 666 | assert(eql_slice_u8(buf1[0..], []u8{0x34})); |
| 573 | 667 | |
| 574 | writeIntBE(u16, &buf2, 0x1234); | |
| 668 | writeIntBig(u16, &buf2, 0x1234); | |
| 575 | 669 | assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 })); |
| 576 | writeIntLE(u16, &buf2, 0x5678); | |
| 670 | writeIntLittle(u16, &buf2, 0x5678); | |
| 577 | 671 | assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 })); |
| 578 | 672 | |
| 579 | writeIntBE(u72, &buf9, 0x123456789abcdef024); | |
| 673 | writeIntBig(u72, &buf9, 0x123456789abcdef024); | |
| 580 | 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 | 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 | 679 | assert(eql_slice_u8(buf1[0..], []u8{0xff})); |
| 586 | writeIntLE(i8, &buf1, -2); | |
| 680 | writeIntLittle(i8, &buf1, -2); | |
| 587 | 681 | assert(eql_slice_u8(buf1[0..], []u8{0xfe})); |
| 588 | 682 | |
| 589 | writeIntBE(i16, &buf2, -3); | |
| 683 | writeIntBig(i16, &buf2, -3); | |
| 590 | 684 | assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd })); |
| 591 | writeIntLE(i16, &buf2, -4); | |
| 685 | writeIntLittle(i16, &buf2, -4); | |
| 592 | 686 | assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff })); |
| 593 | 687 | } |
| 594 | 688 | |
| ... | ... | @@ -737,12 +831,12 @@ fn testReadIntImpl() void { |
| 737 | 831 | 0x56, |
| 738 | 832 | 0x78, |
| 739 | 833 | }; |
| 740 | assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); | |
| 741 | assert(readIntBE(u32, bytes) == 0x12345678); | |
| 742 | assert(readIntBE(i32, bytes) == 0x12345678); | |
| 743 | assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412); | |
| 744 | assert(readIntLE(u32, bytes) == 0x78563412); | |
| 745 | assert(readIntLE(i32, bytes) == 0x78563412); | |
| 834 | assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678); | |
| 835 | assert(readIntBig(u32, &bytes) == 0x12345678); | |
| 836 | assert(readIntBig(i32, &bytes) == 0x12345678); | |
| 837 | assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412); | |
| 838 | assert(readIntLittle(u32, &bytes) == 0x78563412); | |
| 839 | assert(readIntLittle(i32, &bytes) == 0x78563412); | |
| 746 | 840 | } |
| 747 | 841 | { |
| 748 | 842 | const buf = []u8{ |
| ... | ... | @@ -751,7 +845,7 @@ fn testReadIntImpl() void { |
| 751 | 845 | 0x12, |
| 752 | 846 | 0x34, |
| 753 | 847 | }; |
| 754 | const answer = readInt(buf, u64, builtin.Endian.Big); | |
| 848 | const answer = readInt(u32, &buf, builtin.Endian.Big); | |
| 755 | 849 | assert(answer == 0x00001234); |
| 756 | 850 | } |
| 757 | 851 | { |
| ... | ... | @@ -761,7 +855,7 @@ fn testReadIntImpl() void { |
| 761 | 855 | 0x00, |
| 762 | 856 | 0x00, |
| 763 | 857 | }; |
| 764 | const answer = readInt(buf, u64, builtin.Endian.Little); | |
| 858 | const answer = readInt(u32, &buf, builtin.Endian.Little); | |
| 765 | 859 | assert(answer == 0x00003412); |
| 766 | 860 | } |
| 767 | 861 | { |
| ... | ... | @@ -769,21 +863,33 @@ fn testReadIntImpl() void { |
| 769 | 863 | 0xff, |
| 770 | 864 | 0xfe, |
| 771 | 865 | }; |
| 772 | assert(readIntBE(u16, bytes) == 0xfffe); | |
| 773 | assert(readIntBE(i16, bytes) == -0x0002); | |
| 774 | assert(readIntLE(u16, bytes) == 0xfeff); | |
| 775 | assert(readIntLE(i16, bytes) == -0x0101); | |
| 866 | assert(readIntBig(u16, &bytes) == 0xfffe); | |
| 867 | assert(readIntBig(i16, &bytes) == -0x0002); | |
| 868 | assert(readIntLittle(u16, &bytes) == 0xfeff); | |
| 869 | assert(readIntLittle(i16, &bytes) == -0x0101); | |
| 776 | 870 | } |
| 777 | 871 | } |
| 778 | 872 | |
| 779 | test "testWriteInt" { | |
| 873 | test "std.mem.writeIntSlice" { | |
| 780 | 874 | testWriteIntImpl(); |
| 781 | 875 | comptime testWriteIntImpl(); |
| 782 | 876 | } |
| 783 | 877 | fn testWriteIntImpl() void { |
| 784 | 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 | 893 | assert(eql(u8, bytes, []u8{ |
| 788 | 894 | 0x12, |
| 789 | 895 | 0x34, |
| ... | ... | @@ -795,7 +901,7 @@ fn testWriteIntImpl() void { |
| 795 | 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 | 905 | assert(eql(u8, bytes, []u8{ |
| 800 | 906 | 0x12, |
| 801 | 907 | 0x34, |
| ... | ... | @@ -807,7 +913,7 @@ fn testWriteIntImpl() void { |
| 807 | 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 | 917 | assert(eql(u8, bytes, []u8{ |
| 812 | 918 | 0x00, |
| 813 | 919 | 0x00, |
| ... | ... | @@ -819,7 +925,7 @@ fn testWriteIntImpl() void { |
| 819 | 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 | 929 | assert(eql(u8, bytes, []u8{ |
| 824 | 930 | 0x12, |
| 825 | 931 | 0x34, |
| ... | ... | @@ -831,7 +937,7 @@ fn testWriteIntImpl() void { |
| 831 | 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 | 941 | assert(eql(u8, bytes, []u8{ |
| 836 | 942 | 0x00, |
| 837 | 943 | 0x00, |
| ... | ... | @@ -843,7 +949,7 @@ fn testWriteIntImpl() void { |
| 843 | 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 | 953 | assert(eql(u8, bytes, []u8{ |
| 848 | 954 | 0x34, |
| 849 | 955 | 0x12, |
| ... | ... | @@ -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 | |
| 945 | // endian-casting the pointer and then dereferencing | |
| 1050 | /// Converts a little-endian integer to host endianness. | |
| 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 { | |
| 948 | return endianSwapIf(builtin.Endian.Little, T, x); | |
| 1058 | /// Converts a big-endian integer to host endianness. | |
| 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 { | |
| 952 | return endianSwapIf(builtin.Endian.Big, T, x); | |
| 1066 | /// Converts an integer from specified endianness to host endianness. | |
| 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 { | |
| 956 | return if (builtin.endian == endian) endianSwap(T, x) else x; | |
| 1074 | /// Converts an integer which has host endianness to the desired endianness. | |
| 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 { | |
| 960 | var buf: [@sizeOf(T)]u8 = undefined; | |
| 961 | mem.writeInt(buf[0..], x, builtin.Endian.Little); | |
| 962 | return mem.readInt(buf, T, builtin.Endian.Big); | |
| 1082 | /// Converts an integer which has host endianness to little endian. | |
| 1083 | pub fn nativeToLittle(comptime T: type, x: T) T { | |
| 1084 | return switch (builtin.endian) { | |
| 1085 | builtin.Endian.Little => x, | |
| 1086 | builtin.Endian.Big => @bswap(T, x), | |
| 1087 | }; | |
| 963 | 1088 | } |
| 964 | 1089 | |
| 965 | test "std.mem.endianSwap" { | |
| 966 | assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE); | |
| 1090 | /// Converts an integer which has host endianness to big endian. | |
| 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 | 1098 | fn AsBytesReturnType(comptime P: type) type { |
std/meta/index.zig+48| ... | ... | @@ -76,6 +76,25 @@ test "std.meta.tagName" { |
| 76 | 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 | 98 | pub fn bitCount(comptime T: type) u32 { |
| 80 | 99 | return switch (@typeInfo(T)) { |
| 81 | 100 | TypeId.Int => |info| info.bits, |
| ... | ... | @@ -483,3 +502,32 @@ test "std.meta.eql" { |
| 483 | 502 | debug.assert(eql(EU.tst(false), EU.tst(false))); |
| 484 | 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 | 23 | .os_addr = posix.sockaddr{ |
| 24 | 24 | .in = posix.sockaddr_in{ |
| 25 | 25 | .family = posix.AF_INET, |
| 26 | .port = std.mem.endianSwapIfLe(u16, _port), | |
| 26 | .port = mem.nativeToBig(u16, _port), | |
| 27 | 27 | .addr = ip4, |
| 28 | 28 | .zero = []u8{0} ** 8, |
| 29 | 29 | }, |
| ... | ... | @@ -37,7 +37,7 @@ pub const Address = struct { |
| 37 | 37 | .os_addr = posix.sockaddr{ |
| 38 | 38 | .in6 = posix.sockaddr_in6{ |
| 39 | 39 | .family = posix.AF_INET6, |
| 40 | .port = std.mem.endianSwapIfLe(u16, _port), | |
| 40 | .port = mem.nativeToBig(u16, _port), | |
| 41 | 41 | .flowinfo = 0, |
| 42 | 42 | .addr = ip6.addr, |
| 43 | 43 | .scope_id = ip6.scope_id, |
| ... | ... | @@ -47,7 +47,7 @@ pub const Address = struct { |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 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 | 53 | pub fn initPosix(addr: posix.sockaddr) Address { |
| ... | ... | @@ -57,12 +57,12 @@ pub const Address = struct { |
| 57 | 57 | pub fn format(self: *const Address, out_stream: var) !void { |
| 58 | 58 | switch (self.os_addr.in.family) { |
| 59 | 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 | 61 | const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); |
| 62 | 62 | try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); |
| 63 | 63 | }, |
| 64 | 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 | 66 | try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); |
| 67 | 67 | }, |
| 68 | 68 | else => try out_stream.write("(unrecognized address family)"), |
| ... | ... | @@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr { |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | 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 | 198 | testParseIp4Fail("256.0.0.1", error.Overflow); |
| 199 | 199 | testParseIp4Fail("x.0.0.1", error.InvalidCharacter); |
std/os/child_process.zig+15-2| ... | ... | @@ -390,6 +390,19 @@ pub const ChildProcess = struct { |
| 390 | 390 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 391 | 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 | 406 | if (self.cwd) |cwd| { |
| 394 | 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 | 807 | |
| 795 | 808 | fn writeIntFd(fd: i32, value: ErrInt) !void { |
| 796 | 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 | 813 | fn readIntFd(fd: i32) !ErrInt { |
| 801 | 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 | 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 | 239 | switch (builtin.os) { |
| 233 | Os.linux, Os.macosx, Os.ios => { | |
| 240 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 234 | 241 | const result = posix.lseek(self.handle, amount, posix.SEEK_CUR); |
| 235 | 242 | const err = posix.getErrno(result); |
| 236 | 243 | if (err > 0) { |
| ... | ... | @@ -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 | 270 | switch (builtin.os) { |
| 264 | Os.linux, Os.macosx, Os.ios => { | |
| 271 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 265 | 272 | const ipos = try math.cast(isize, pos); |
| 266 | 273 | const result = posix.lseek(self.handle, ipos, posix.SEEK_SET); |
| 267 | 274 | const err = posix.getErrno(result); |
| ... | ... | @@ -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 | 311 | switch (builtin.os) { |
| 298 | Os.linux, Os.macosx, Os.ios => { | |
| 312 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 299 | 313 | const result = posix.lseek(self.handle, 0, posix.SEEK_CUR); |
| 300 | 314 | const err = posix.getErrno(result); |
| 301 | 315 | if (err > 0) { |
| ... | ... | @@ -323,13 +337,13 @@ pub const File = struct { |
| 323 | 337 | } |
| 324 | 338 | |
| 325 | 339 | assert(pos >= 0); |
| 326 | return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange; | |
| 340 | return math.cast(usize, pos); | |
| 327 | 341 | }, |
| 328 | 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 | 347 | if (is_posix) { |
| 334 | 348 | const stat = try os.posixFStat(self.handle); |
| 335 | 349 | return @intCast(usize, stat.size); |
| ... | ... | @@ -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 | 460 | /// Implementation of io.InStream trait for File |
| 435 | 461 | pub const InStream = struct { |
| 436 | 462 | file: File, |
| ... | ... | @@ -458,4 +484,32 @@ pub const File = struct { |
| 458 | 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 | 43 | }; |
| 44 | 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 | 47 | const home_dir = os.getEnvPosix("HOME") orelse { |
| 48 | 48 | // TODO look in /etc/passwd |
| 49 | 49 | return error.AppDataDirUnavailable; |
std/os/get_user_id.zig+1-1| ... | ... | @@ -11,7 +11,7 @@ pub const UserInfo = struct { |
| 11 | 11 | /// POSIX function which gets a uid from username. |
| 12 | 12 | pub fn getUserInfo(name: []const u8) !UserInfo { |
| 13 | 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 | 15 | else => @compileError("Unsupported OS"), |
| 16 | 16 | }; |
| 17 | 17 | } |
std/os/index.zig+67-28| ... | ... | @@ -3,7 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const Os = builtin.Os; |
| 4 | 4 | const is_windows = builtin.os == Os.windows; |
| 5 | 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 | 7 | else => false, |
| 8 | 8 | }; |
| 9 | 9 | const os = @This(); |
| ... | ... | @@ -24,10 +24,12 @@ test "std.os" { |
| 24 | 24 | pub const windows = @import("windows/index.zig"); |
| 25 | 25 | pub const darwin = @import("darwin.zig"); |
| 26 | 26 | pub const linux = @import("linux/index.zig"); |
| 27 | pub const freebsd = @import("freebsd/index.zig"); | |
| 27 | 28 | pub const zen = @import("zen.zig"); |
| 28 | 29 | pub const posix = switch (builtin.os) { |
| 29 | 30 | Os.linux => linux, |
| 30 | 31 | Os.macosx, Os.ios => darwin, |
| 32 | Os.freebsd => freebsd, | |
| 31 | 33 | Os.zen => zen, |
| 32 | 34 | else => @compileError("Unsupported OS"), |
| 33 | 35 | }; |
| ... | ... | @@ -40,7 +42,7 @@ pub const time = @import("time.zig"); |
| 40 | 42 | |
| 41 | 43 | pub const page_size = 4 * 1024; |
| 42 | 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 | 46 | // Each UTF-16LE character may be expanded to 3 UTF-8 bytes. |
| 45 | 47 | // If it would require 4 UTF-8 bytes, then there would be a surrogate |
| 46 | 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 | 103 | /// library implementation. |
| 102 | 104 | pub fn getRandomBytes(buf: []u8) !void { |
| 103 | 105 | switch (builtin.os) { |
| 104 | Os.linux => while (true) { | |
| 106 | Os.linux, Os.freebsd => while (true) { | |
| 105 | 107 | // TODO check libc version and potentially call c.getrandom. |
| 106 | 108 | // See #397 |
| 107 | 109 | const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0)); |
| ... | ... | @@ -174,7 +176,7 @@ pub fn abort() noreturn { |
| 174 | 176 | c.abort(); |
| 175 | 177 | } |
| 176 | 178 | switch (builtin.os) { |
| 177 | Os.linux, Os.macosx, Os.ios => { | |
| 179 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 178 | 180 | _ = posix.raise(posix.SIGABRT); |
| 179 | 181 | _ = posix.raise(posix.SIGKILL); |
| 180 | 182 | while (true) {} |
| ... | ... | @@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn { |
| 196 | 198 | c.exit(status); |
| 197 | 199 | } |
| 198 | 200 | switch (builtin.os) { |
| 199 | Os.linux, Os.macosx, Os.ios => { | |
| 201 | Os.linux, Os.macosx, Os.ios, Os.freebsd => { | |
| 200 | 202 | posix.exit(status); |
| 201 | 203 | }, |
| 202 | 204 | Os.windows => { |
| ... | ... | @@ -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 | 425 | const rc = posix.pwritev(fd, iov, count, offset); |
| 424 | 426 | const err = posix.getErrno(rc); |
| 425 | 427 | switch (err) { |
| ... | ... | @@ -457,6 +459,7 @@ pub const PosixOpenError = error{ |
| 457 | 459 | NoSpaceLeft, |
| 458 | 460 | NotDir, |
| 459 | 461 | PathAlreadyExists, |
| 462 | DeviceBusy, | |
| 460 | 463 | |
| 461 | 464 | /// See https://github.com/ziglang/zig/issues/1396 |
| 462 | 465 | Unexpected, |
| ... | ... | @@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { |
| 495 | 498 | posix.ENOTDIR => return PosixOpenError.NotDir, |
| 496 | 499 | posix.EPERM => return PosixOpenError.AccessDenied, |
| 497 | 500 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, |
| 501 | posix.EBUSY => return PosixOpenError.DeviceBusy, | |
| 498 | 502 | else => return unexpectedErrorPosix(err), |
| 499 | 503 | } |
| 500 | 504 | } |
| ... | ... | @@ -687,7 +691,7 @@ pub fn getBaseAddress() usize { |
| 687 | 691 | }; |
| 688 | 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 | 695 | builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), |
| 692 | 696 | else => @compileError("Unsupported OS"), |
| 693 | 697 | } |
| ... | ... | @@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 700 | 704 | errdefer result.deinit(); |
| 701 | 705 | |
| 702 | 706 | if (is_windows) { |
| 703 | const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory; | |
| 704 | defer assert(windows.FreeEnvironmentStringsA(ptr) != 0); | |
| 707 | const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory; | |
| 708 | defer assert(windows.FreeEnvironmentStringsW(ptr) != 0); | |
| 705 | 709 | |
| 706 | 710 | var i: usize = 0; |
| 707 | 711 | while (true) { |
| ... | ... | @@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 710 | 714 | const key_start = i; |
| 711 | 715 | |
| 712 | 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 | 721 | if (ptr[i] == '=') i += 1; |
| 716 | 722 | |
| 717 | 723 | const value_start = i; |
| 718 | 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 | 729 | i += 1; // skip over null byte |
| 722 | 730 | |
| 723 | try result.set(key, value); | |
| 731 | try result.setMove(key, value); | |
| 724 | 732 | } |
| 725 | 733 | } else { |
| 726 | 734 | for (posix_environ_raw) |ptr| { |
| ... | ... | @@ -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 | 754 | /// TODO make this go through libc when we have it |
| 742 | 755 | pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 743 | 756 | for (posix_environ_raw) |ptr| { |
| ... | ... | @@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 758 | 771 | pub const GetEnvVarOwnedError = error{ |
| 759 | 772 | OutOfMemory, |
| 760 | 773 | EnvironmentVariableNotFound, |
| 774 | ||
| 775 | /// See https://github.com/ziglang/zig/issues/1774 | |
| 776 | InvalidUtf8, | |
| 761 | 777 | }; |
| 762 | 778 | |
| 763 | 779 | /// Caller must free returned memory. |
| 764 | 780 | /// TODO make this go through libc when we have it |
| 765 | 781 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 766 | 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 | 784 | defer allocator.free(key_with_null); |
| 769 | 785 | |
| 770 | var buf = try allocator.alloc(u8, 256); | |
| 771 | errdefer allocator.free(buf); | |
| 786 | var buf = try allocator.alloc(u16, 256); | |
| 787 | defer allocator.free(buf); | |
| 772 | 788 | |
| 773 | 789 | while (true) { |
| 774 | 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 | 793 | if (result == 0) { |
| 778 | 794 | const err = windows.GetLastError(); |
| ... | ... | @@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned |
| 786 | 802 | } |
| 787 | 803 | |
| 788 | 804 | if (result > buf.len) { |
| 789 | buf = try allocator.realloc(u8, buf, result); | |
| 805 | buf = try allocator.realloc(u16, buf, result); | |
| 790 | 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 | 816 | } else { |
| 796 | 817 | const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound; |
| ... | ... | @@ -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 | 827 | /// Caller must free the returned memory. |
| 802 | 828 | pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { |
| 803 | 829 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| ... | ... | @@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void { |
| 1305 | 1331 | const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path); |
| 1306 | 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 | 1335 | const err = posix.getErrno(posix.rmdir(dir_path)); |
| 1310 | 1336 | switch (err) { |
| 1311 | 1337 | 0 => return, |
| ... | ... | @@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void { |
| 1348 | 1374 | const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path); |
| 1349 | 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 | 1378 | const dir_path_c = try toPosixPath(dir_path); |
| 1353 | 1379 | return deleteDirC(&dir_path_c); |
| 1354 | 1380 | }, |
| ... | ... | @@ -1378,6 +1404,7 @@ const DeleteTreeError = error{ |
| 1378 | 1404 | FileSystem, |
| 1379 | 1405 | FileBusy, |
| 1380 | 1406 | DirNotEmpty, |
| 1407 | DeviceBusy, | |
| 1381 | 1408 | |
| 1382 | 1409 | /// On Windows, file paths must be valid Unicode. |
| 1383 | 1410 | InvalidUtf8, |
| ... | ... | @@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 1439 | 1466 | error.Unexpected, |
| 1440 | 1467 | error.InvalidUtf8, |
| 1441 | 1468 | error.BadPathName, |
| 1469 | error.DeviceBusy, | |
| 1442 | 1470 | => return err, |
| 1443 | 1471 | }; |
| 1444 | 1472 | defer dir.close(); |
| ... | ... | @@ -1465,7 +1493,7 @@ pub const Dir = struct { |
| 1465 | 1493 | allocator: *Allocator, |
| 1466 | 1494 | |
| 1467 | 1495 | pub const Handle = switch (builtin.os) { |
| 1468 | Os.macosx, Os.ios => struct { | |
| 1496 | Os.macosx, Os.ios, Os.freebsd => struct { | |
| 1469 | 1497 | fd: i32, |
| 1470 | 1498 | seek: i64, |
| 1471 | 1499 | buf: []u8, |
| ... | ... | @@ -1521,6 +1549,7 @@ pub const Dir = struct { |
| 1521 | 1549 | OutOfMemory, |
| 1522 | 1550 | InvalidUtf8, |
| 1523 | 1551 | BadPathName, |
| 1552 | DeviceBusy, | |
| 1524 | 1553 | |
| 1525 | 1554 | /// See https://github.com/ziglang/zig/issues/1396 |
| 1526 | 1555 | Unexpected, |
| ... | ... | @@ -1541,7 +1570,7 @@ pub const Dir = struct { |
| 1541 | 1570 | .name_data = undefined, |
| 1542 | 1571 | }; |
| 1543 | 1572 | }, |
| 1544 | Os.macosx, Os.ios => Handle{ | |
| 1573 | Os.macosx, Os.ios, Os.freebsd => Handle{ | |
| 1545 | 1574 | .fd = try posixOpen( |
| 1546 | 1575 | dir_path, |
| 1547 | 1576 | posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC, |
| ... | ... | @@ -1572,7 +1601,7 @@ pub const Dir = struct { |
| 1572 | 1601 | Os.windows => { |
| 1573 | 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 | 1605 | self.allocator.free(self.handle.buf); |
| 1577 | 1606 | os.close(self.handle.fd); |
| 1578 | 1607 | }, |
| ... | ... | @@ -1587,6 +1616,7 @@ pub const Dir = struct { |
| 1587 | 1616 | Os.linux => return self.nextLinux(), |
| 1588 | 1617 | Os.macosx, Os.ios => return self.nextDarwin(), |
| 1589 | 1618 | Os.windows => return self.nextWindows(), |
| 1619 | Os.freebsd => return self.nextFreebsd(), | |
| 1590 | 1620 | else => @compileError("unimplemented"), |
| 1591 | 1621 | } |
| 1592 | 1622 | } |
| ... | ... | @@ -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 | 1766 | pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void { |
| ... | ... | @@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError { |
| 2164 | 2199 | pub fn openSelfExe() !os.File { |
| 2165 | 2200 | switch (builtin.os) { |
| 2166 | 2201 | Os.linux => return os.File.openReadC(c"/proc/self/exe"), |
| 2167 | Os.macosx, Os.ios => { | |
| 2202 | Os.macosx, Os.ios, Os.freebsd => { | |
| 2168 | 2203 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| 2169 | 2204 | const self_exe_path = try selfExePath(&buf); |
| 2170 | 2205 | buf[self_exe_path.len] = 0; |
| ... | ... | @@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File { |
| 2181 | 2216 | |
| 2182 | 2217 | test "openSelfExe" { |
| 2183 | 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 | 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 | 2247 | pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 { |
| 2213 | 2248 | switch (builtin.os) { |
| 2214 | 2249 | Os.linux => return readLink(out_buffer, "/proc/self/exe"), |
| 2250 | Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"), | |
| 2215 | 2251 | Os.windows => { |
| 2216 | 2252 | var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined; |
| 2217 | 2253 | const utf16le_slice = try selfExePathW(&utf16le_buf); |
| ... | ... | @@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 { |
| 2250 | 2286 | // will not return null. |
| 2251 | 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 | 2290 | const self_exe_path = try selfExePath(out_buffer); |
| 2255 | 2291 | // Assume that the OS APIs return absolute paths, and therefore dirname |
| 2256 | 2292 | // will not return null. |
| ... | ... | @@ -3095,10 +3131,13 @@ pub const CpuCountError = error{ |
| 3095 | 3131 | |
| 3096 | 3132 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { |
| 3097 | 3133 | switch (builtin.os) { |
| 3098 | builtin.Os.macosx => { | |
| 3134 | builtin.Os.macosx, builtin.Os.freebsd => { | |
| 3099 | 3135 | var count: c_int = undefined; |
| 3100 | 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 | 3141 | const err = posix.getErrno(rc); |
| 3103 | 3142 | switch (err) { |
| 3104 | 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 | 703 | } |
| 704 | 704 | |
| 705 | 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 | 709 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize { |
| 747 | 747 | } |
| 748 | 748 | |
| 749 | 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 | 753 | pub fn inotify_init1(flags: u32) usize { |
| ... | ... | @@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize { |
| 755 | 755 | } |
| 756 | 756 | |
| 757 | 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 | 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 | 765 | pub fn isatty(fd: i32) bool { |
| 766 | 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 | 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 | 774 | |
| 775 | 775 | // TODO https://github.com/ziglang/zig/issues/265 |
| 776 | 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 | 780 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize { |
| 784 | 784 | |
| 785 | 785 | // TODO https://github.com/ziglang/zig/issues/265 |
| 786 | 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 | 790 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize { |
| 803 | 803 | } |
| 804 | 804 | |
| 805 | 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 | 809 | 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 | 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 | 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 | 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 | 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 | 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 | 833 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { |
| 842 | 842 | |
| 843 | 843 | // TODO https://github.com/ziglang/zig/issues/265 |
| 844 | 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 | 848 | // TODO https://github.com/ziglang/zig/issues/265 |
| 849 | 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 | 853 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize { |
| 856 | 856 | } |
| 857 | 857 | |
| 858 | 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 | 862 | pub fn pipe(fd: *[2]i32) usize { |
| ... | ... | @@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize { |
| 868 | 868 | } |
| 869 | 869 | |
| 870 | 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 | 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 | 878 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize { |
| 882 | 882 | |
| 883 | 883 | // TODO https://github.com/ziglang/zig/issues/265 |
| 884 | 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 | 888 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize { |
| 897 | 897 | |
| 898 | 898 | // TODO https://github.com/ziglang/zig/issues/265 |
| 899 | 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 | 904 | /// See also `clone` (from the arch-specific include) |
| ... | ... | @@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize { |
| 911 | 912 | } |
| 912 | 913 | |
| 913 | 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 | 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 | 922 | pub fn exit(status: i32) noreturn { |
| ... | ... | @@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { |
| 933 | 934 | } |
| 934 | 935 | |
| 935 | 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 | 940 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize { |
| 943 | 944 | |
| 944 | 945 | // TODO https://github.com/ziglang/zig/issues/265 |
| 945 | 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 | 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 | 1121 | pub fn raise(sig: i32) usize { |
| 1121 | 1122 | var set: sigset_t = undefined; |
| 1122 | 1123 | blockAppSignals(&set); |
| 1123 | const tid = @intCast(i32, syscall0(SYS_gettid)); | |
| 1124 | const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig)); | |
| 1124 | const tid = syscall0(SYS_gettid); | |
| 1125 | const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig))); | |
| 1125 | 1126 | restoreSignals(&set); |
| 1126 | 1127 | return ret; |
| 1127 | 1128 | } |
| ... | ... | @@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct { |
| 1189 | 1190 | }; |
| 1190 | 1191 | |
| 1191 | 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 | 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 | 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 | 1202 | } |
| 1202 | 1203 | |
| 1203 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1250 | } |
| 1250 | 1251 | |
| 1251 | 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 | 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 | 1260 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize { |
| 1268 | 1269 | |
| 1269 | 1270 | // TODO https://github.com/ziglang/zig/issues/265 |
| 1270 | 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 | 1275 | // TODO https://github.com/ziglang/zig/issues/265 |
| ... | ... | @@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize { |
| 1355 | 1356 | } |
| 1356 | 1357 | |
| 1357 | 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 | 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 | 1364 | } |
| 1364 | 1365 | |
| 1365 | 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 | 1378 | 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 | 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 | 1386 | pub const itimerspec = extern struct { |
| ... | ... | @@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct { |
| 1380 | 1389 | }; |
| 1381 | 1390 | |
| 1382 | 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 | 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 | 1399 | pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330; |
std/os/path.zig+12-2| ... | ... | @@ -1093,6 +1093,7 @@ pub const RealError = error{ |
| 1093 | 1093 | NoSpaceLeft, |
| 1094 | 1094 | FileSystem, |
| 1095 | 1095 | BadPathName, |
| 1096 | DeviceBusy, | |
| 1096 | 1097 | |
| 1097 | 1098 | /// On Windows, file paths must be valid Unicode. |
| 1098 | 1099 | InvalidUtf8, |
| ... | ... | @@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro |
| 1183 | 1184 | const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0); |
| 1184 | 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 | 1188 | const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable; |
| 1188 | 1189 | |
| 1189 | 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 | 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 | 1212 | const pathname_w = try windows_util.sliceToPrefixedFileW(pathname); |
| 1203 | 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 | 1216 | const pathname_c = try os.toPosixPath(pathname); |
| 1207 | 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 | 50 | pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL; |
| 51 | 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 | 55 | pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR; |
| 56 | 56 | |
| ... | ... | @@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp |
| 63 | 63 | pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE; |
| 64 | 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 | 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 | 12 | args: [5]usize, |
| 13 | 13 | payload: ?[]const u8, |
| 14 | 14 | |
| 15 | pub fn from(mailbox_id: *const MailboxId) Message { | |
| 15 | pub fn from(mailbox_id: MailboxId) Message { | |
| 16 | 16 | return Message{ |
| 17 | 17 | .sender = MailboxId.Undefined, |
| 18 | .receiver = mailbox_id.*, | |
| 18 | .receiver = mailbox_id, | |
| 19 | 19 | .code = undefined, |
| 20 | 20 | .args = undefined, |
| 21 | 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 | 26 | var message = Message{ |
| 27 | 27 | .sender = MailboxId.This, |
| 28 | .receiver = mailbox_id.*, | |
| 28 | .receiver = mailbox_id, | |
| 29 | 29 | .code = msg_code, |
| 30 | 30 | .args = undefined, |
| 31 | 31 | .payload = null, |
| ... | ... | @@ -40,14 +40,14 @@ pub const Message = struct { |
| 40 | 40 | return message; |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | pub fn as(self: *const Message, sender: *const MailboxId) Message { | |
| 44 | var message = self.*; | |
| 45 | message.sender = sender.*; | |
| 43 | pub fn as(self: Message, sender: MailboxId) Message { | |
| 44 | var message = self; | |
| 45 | message.sender = sender; | |
| 46 | 46 | return message; |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | pub fn withPayload(self: *const Message, payload: []const u8) Message { | |
| 50 | var message = self.*; | |
| 49 | pub fn withPayload(self: Message, payload: []const u8) Message { | |
| 50 | var message = self; | |
| 51 | 51 | message.payload = payload; |
| 52 | 52 | return message; |
| 53 | 53 | } |
| ... | ... | @@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { |
| 93 | 93 | STDIN_FILENO => { |
| 94 | 94 | var i: usize = 0; |
| 95 | 95 | while (i < count) : (i += 1) { |
| 96 | send(Message.to(Server.Keyboard, 0)); | |
| 96 | send(&Message.to(Server.Keyboard, 0)); | |
| 97 | 97 | |
| 98 | 98 | // FIXME: we should be certain that we are receiving from Keyboard. |
| 99 | 99 | var message = Message.from(MailboxId.This); |
| ... | ... | @@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { |
| 111 | 111 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 112 | 112 | switch (fd) { |
| 113 | 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 | 116 | else => unreachable, |
| 117 | 117 | } |
std/pdb.zig+4-3| ... | ... | @@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct { |
| 34 | 34 | }; |
| 35 | 35 | |
| 36 | 36 | pub const SectionContribEntry = packed struct { |
| 37 | /// COFF Section index, 1-based | |
| 37 | 38 | Section: u16, |
| 38 | 39 | Padding1: [2]u8, |
| 39 | 40 | Offset: u32, |
| ... | ... | @@ -507,11 +508,11 @@ const Msf = struct { |
| 507 | 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 | 513 | const stream_sizes = try allocator.alloc(u32, stream_count); |
| 513 | 514 | for (stream_sizes) |*s| { |
| 514 | const size = try self.directory.stream.readIntLe(u32); | |
| 515 | const size = try self.directory.stream.readIntLittle(u32); | |
| 515 | 516 | s.* = blockCountFromSize(size, superblock.BlockSize); |
| 516 | 517 | } |
| 517 | 518 | |
| ... | ... | @@ -602,7 +603,7 @@ const MsfStream = struct { |
| 602 | 603 | |
| 603 | 604 | var i: u32 = 0; |
| 604 | 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 | 609 | return stream; |
std/rand/index.zig+160-41| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | // ``` |
| 6 | 6 | // var buf: [8]u8 = undefined; |
| 7 | 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 | 10 | // var r = DefaultPrng.init(seed); |
| 11 | 11 | // |
| ... | ... | @@ -52,11 +52,24 @@ pub const Random = struct { |
| 52 | 52 | // use LE instead of native endian for better portability maybe? |
| 53 | 53 | // TODO: endian portability is pointless if the underlying prng isn't endian portable. |
| 54 | 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 | 56 | const unsigned_result = @truncate(UnsignedT, byte_aligned_result); |
| 57 | 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 | 73 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. |
| 61 | 74 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. |
| 62 | 75 | /// Within this assumption, the runtime of this function is exponentially distributed. |
| ... | ... | @@ -64,27 +77,52 @@ pub const Random = struct { |
| 64 | 77 | /// the runtime of this function would technically be unbounded. |
| 65 | 78 | /// However, if ::fillFn is backed by any evenly distributed pseudo random number generator, |
| 66 | 79 | /// this function is guaranteed to return. |
| 67 | /// If you need deterministic runtime bounds, consider instead using `r.int(T) % less_than`, | |
| 68 | /// which will usually be biased toward smaller values. | |
| 80 | /// If you need deterministic runtime bounds, use `::uintLessThanBiased`. | |
| 69 | 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 | 84 | assert(0 < less_than); |
| 72 | ||
| 73 | const last_group_size_minus_one: T = maxInt(T) % less_than; | |
| 74 | if (last_group_size_minus_one == less_than - 1) { | |
| 75 | // less_than is a power of two. | |
| 76 | assert(math.floorPowerOfTwo(T, less_than) == less_than); | |
| 77 | // There is no retry zone. The optimal retry_zone_start would be maxInt(T) + 1. | |
| 78 | return r.int(T) % less_than; | |
| 85 | // Small is typically u32 | |
| 86 | const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32); | |
| 87 | // Large is typically u64 | |
| 88 | const Large = @IntType(false, Small.bit_count * 2); | |
| 89 | ||
| 90 | // adapted from: | |
| 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) { | |
| 83 | const rand_val = r.int(T); | |
| 84 | if (rand_val < retry_zone_start) { | |
| 85 | return rand_val % less_than; | |
| 86 | } | |
| 117 | /// Constant-time implementation off ::uintAtMost. | |
| 118 | /// The results of this function may be biased. | |
| 119 | pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T { | |
| 120 | assert(T.is_signed == false); | |
| 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 | 128 | /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. |
| ... | ... | @@ -99,6 +137,23 @@ pub const Random = struct { |
| 99 | 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 | 157 | /// Returns an evenly distributed random integer `at_least <= i < less_than`. |
| 103 | 158 | /// See ::uintLessThan, which this function uses in most cases, |
| 104 | 159 | /// for commentary on the runtime of this function. |
| ... | ... | @@ -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 | 192 | /// Returns an evenly distributed random integer `at_least <= i <= at_most`. |
| 121 | 193 | /// See ::uintLessThan, which this function uses in most cases, |
| 122 | 194 | /// for commentary on the runtime of this function. |
| ... | ... | @@ -135,15 +207,11 @@ pub const Random = struct { |
| 135 | 207 | } |
| 136 | 208 | } |
| 137 | 209 | |
| 138 | /// Return a random integer/boolean type. | |
| 139 | 210 | /// TODO: deprecated. use ::boolean or ::int instead. |
| 140 | 211 | pub fn scalar(r: *Random, comptime T: type) T { |
| 141 | if (T == bool) return r.boolean(); | |
| 142 | return r.int(T); | |
| 212 | return if (T == bool) r.boolean() else 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 | 215 | /// TODO: deprecated. renamed to ::intRangeLessThan |
| 148 | 216 | pub fn range(r: *Random, comptime T: type, start: T, end: T) T { |
| 149 | 217 | return r.intRangeLessThan(T, start, end); |
| ... | ... | @@ -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 | 291 | const SequentialPrng = struct { |
| 210 | 292 | const Self = @This(); |
| 211 | 293 | random: Random, |
| ... | ... | @@ -294,10 +376,19 @@ fn testRandomIntLessThan() void { |
| 294 | 376 | var r = SequentialPrng.init(); |
| 295 | 377 | r.next_value = 0xff; |
| 296 | 378 | assert(r.random.uintLessThan(u8, 4) == 3); |
| 297 | r.next_value = 0xff; | |
| 298 | assert(r.random.uintLessThan(u8, 3) == 0); | |
| 379 | assert(r.next_value == 0); | |
| 380 | assert(r.random.uintLessThan(u8, 4) == 0); | |
| 299 | 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 | 392 | r.next_value = 0xff; |
| 302 | 393 | assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f); |
| 303 | 394 | r.next_value = 0xff; |
| ... | ... | @@ -310,17 +401,10 @@ fn testRandomIntLessThan() void { |
| 310 | 401 | r.next_value = 0xff; |
| 311 | 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 | 404 | r.next_value = 0xff; |
| 316 | 405 | assert(r.random.intRangeLessThan(i3, -4, 0) == -1); |
| 317 | 406 | r.next_value = 0xff; |
| 318 | 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 | 410 | test "Random intAtMost" { |
| ... | ... | @@ -332,9 +416,14 @@ fn testRandomIntAtMost() void { |
| 332 | 416 | var r = SequentialPrng.init(); |
| 333 | 417 | r.next_value = 0xff; |
| 334 | 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 | 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 | 428 | r.next_value = 0xff; |
| 340 | 429 | assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f); |
| ... | ... | @@ -348,17 +437,43 @@ fn testRandomIntAtMost() void { |
| 348 | 437 | r.next_value = 0xff; |
| 349 | 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 | 440 | r.next_value = 0xff; |
| 354 | 441 | assert(r.random.intRangeAtMost(i3, -4, -1) == -1); |
| 355 | 442 | r.next_value = 0xff; |
| 356 | 443 | assert(r.random.intRangeAtMost(i3, -2, 1) == 1); |
| 357 | 444 | |
| 358 | // test retrying and eventually getting a good value | |
| 359 | // start just out of bounds | |
| 360 | r.next_value = 0x81; | |
| 361 | assert(r.random.uintAtMost(u8, 0x80) == 0); | |
| 445 | assert(r.random.uintAtMost(u0, 0) == 0); | |
| 446 | } | |
| 447 | ||
| 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 | 479 | // Generator to extend 64-bit seed values into longer sequences. |
| ... | ... | @@ -870,12 +985,16 @@ test "Random range" { |
| 870 | 985 | } |
| 871 | 986 | |
| 872 | 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 | 992 | const count = @intCast(usize, i32(end) - i32(start)); |
| 874 | 993 | var values_buffer = []bool{false} ** 0x100; |
| 875 | 994 | const values = values_buffer[0..count]; |
| 876 | 995 | var i: usize = 0; |
| 877 | 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 | 998 | const index = @intCast(usize, value - start); |
| 880 | 999 | if (!values[index]) { |
| 881 | 1000 | i += 1; |
std/rand/ziggurat.zig+1-1| ... | ... | @@ -12,7 +12,7 @@ const std = @import("../index.zig"); |
| 12 | 12 | const math = std.math; |
| 13 | 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 | 16 | while (true) { |
| 17 | 17 | // We manually construct a float from parts as we can avoid an extra random lookup here by |
| 18 | 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 | 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 | 209 | pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) { |
| 205 | 210 | if (index < prealloc_item_count) { |
| 206 | 211 | return &self.prealloc_segment[index]; |
std/special/bootstrap.zig+14-4| ... | ... | @@ -20,10 +20,17 @@ comptime { |
| 20 | 20 | |
| 21 | 21 | nakedcc fn _start() noreturn { |
| 22 | 22 | switch (builtin.arch) { |
| 23 | builtin.Arch.x86_64 => { | |
| 24 | argc_ptr = asm ("lea (%%rsp), %[argc]" | |
| 25 | : [argc] "=r" (-> [*]usize) | |
| 26 | ); | |
| 23 | builtin.Arch.x86_64 => switch (builtin.os) { | |
| 24 | builtin.Os.freebsd => { | |
| 25 | argc_ptr = asm ("lea (%%rdi), %[argc]" | |
| 26 | : [argc] "=r" (-> [*]usize) | |
| 27 | ); | |
| 28 | }, | |
| 29 | else => { | |
| 30 | argc_ptr = asm ("lea (%%rsp), %[argc]" | |
| 31 | : [argc] "=r" (-> [*]usize) | |
| 32 | ); | |
| 33 | }, | |
| 27 | 34 | }, |
| 28 | 35 | builtin.Arch.i386 => { |
| 29 | 36 | argc_ptr = asm ("lea (%%esp), %[argc]" |
| ... | ... | @@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn { |
| 50 | 57 | |
| 51 | 58 | // TODO https://github.com/ziglang/zig/issues/265 |
| 52 | 59 | fn posixCallMainAndExit() noreturn { |
| 60 | if (builtin.os == builtin.Os.freebsd) { | |
| 61 | @setAlignStack(16); | |
| 62 | } | |
| 53 | 63 | const argc = argc_ptr[0]; |
| 54 | 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 | 164 | \\ |
| 165 | 165 | \\General Options: |
| 166 | 166 | \\ --help Print this help and exit |
| 167 | \\ --init Generate a build.zig template | |
| 168 | 167 | \\ --verbose Print commands before executing them |
| 169 | 168 | \\ --prefix [path] Override default install prefix |
| 170 | 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 | 52 | @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); |
| 53 | 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 | 65 | @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); |
| 56 | 66 | |
| 57 | 67 | @export("__udivsi3", __udivsi3, linkage); |
| ... | ... | @@ -59,7 +69,7 @@ comptime { |
| 59 | 69 | @export("__umoddi3", __umoddi3, linkage); |
| 60 | 70 | @export("__udivmodsi4", __udivmodsi4, linkage); |
| 61 | 71 | |
| 62 | if (isArmArch()) { | |
| 72 | if (is_arm_arch and !is_arm_64) { | |
| 63 | 73 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); |
| 64 | 74 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); |
| 65 | 75 | @export("__aeabi_uidiv", __udivsi3, linkage); |
| ... | ... | @@ -149,68 +159,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult |
| 149 | 159 | return result; |
| 150 | 160 | } |
| 151 | 161 | |
| 152 | fn isArmArch() bool { | |
| 153 | return switch (builtin.arch) { | |
| 154 | builtin.Arch.armv8_3a, | |
| 155 | builtin.Arch.armv8_2a, | |
| 156 | builtin.Arch.armv8_1a, | |
| 157 | builtin.Arch.armv8, | |
| 158 | builtin.Arch.armv8r, | |
| 159 | builtin.Arch.armv8m_baseline, | |
| 160 | builtin.Arch.armv8m_mainline, | |
| 161 | builtin.Arch.armv7, | |
| 162 | builtin.Arch.armv7em, | |
| 163 | builtin.Arch.armv7m, | |
| 164 | builtin.Arch.armv7s, | |
| 165 | builtin.Arch.armv7k, | |
| 166 | builtin.Arch.armv7ve, | |
| 167 | builtin.Arch.armv6, | |
| 168 | builtin.Arch.armv6m, | |
| 169 | builtin.Arch.armv6k, | |
| 170 | builtin.Arch.armv6t2, | |
| 171 | builtin.Arch.armv5, | |
| 172 | builtin.Arch.armv5te, | |
| 173 | builtin.Arch.armv4t, | |
| 174 | builtin.Arch.armebv8_3a, | |
| 175 | builtin.Arch.armebv8_2a, | |
| 176 | builtin.Arch.armebv8_1a, | |
| 177 | builtin.Arch.armebv8, | |
| 178 | builtin.Arch.armebv8r, | |
| 179 | builtin.Arch.armebv8m_baseline, | |
| 180 | builtin.Arch.armebv8m_mainline, | |
| 181 | builtin.Arch.armebv7, | |
| 182 | builtin.Arch.armebv7em, | |
| 183 | builtin.Arch.armebv7m, | |
| 184 | builtin.Arch.armebv7s, | |
| 185 | builtin.Arch.armebv7k, | |
| 186 | builtin.Arch.armebv7ve, | |
| 187 | builtin.Arch.armebv6, | |
| 188 | builtin.Arch.armebv6m, | |
| 189 | builtin.Arch.armebv6k, | |
| 190 | builtin.Arch.armebv6t2, | |
| 191 | builtin.Arch.armebv5, | |
| 192 | builtin.Arch.armebv5te, | |
| 193 | builtin.Arch.armebv4t, | |
| 194 | builtin.Arch.aarch64v8_3a, | |
| 195 | builtin.Arch.aarch64v8_2a, | |
| 196 | builtin.Arch.aarch64v8_1a, | |
| 197 | builtin.Arch.aarch64v8, | |
| 198 | builtin.Arch.aarch64v8r, | |
| 199 | builtin.Arch.aarch64v8m_baseline, | |
| 200 | builtin.Arch.aarch64v8m_mainline, | |
| 201 | builtin.Arch.aarch64_bev8_3a, | |
| 202 | builtin.Arch.aarch64_bev8_2a, | |
| 203 | builtin.Arch.aarch64_bev8_1a, | |
| 204 | builtin.Arch.aarch64_bev8, | |
| 205 | builtin.Arch.aarch64_bev8r, | |
| 206 | builtin.Arch.aarch64_bev8m_baseline, | |
| 207 | builtin.Arch.aarch64_bev8m_mainline, | |
| 208 | builtin.Arch.thumb, | |
| 209 | builtin.Arch.thumbeb, | |
| 210 | => true, | |
| 211 | else => false, | |
| 212 | }; | |
| 213 | } | |
| 162 | const is_arm_64 = switch (builtin.arch) { | |
| 163 | builtin.Arch.aarch64v8_3a, | |
| 164 | builtin.Arch.aarch64v8_2a, | |
| 165 | builtin.Arch.aarch64v8_1a, | |
| 166 | builtin.Arch.aarch64v8, | |
| 167 | builtin.Arch.aarch64v8r, | |
| 168 | builtin.Arch.aarch64v8m_baseline, | |
| 169 | builtin.Arch.aarch64v8m_mainline, | |
| 170 | builtin.Arch.aarch64_bev8_3a, | |
| 171 | builtin.Arch.aarch64_bev8_2a, | |
| 172 | builtin.Arch.aarch64_bev8_1a, | |
| 173 | builtin.Arch.aarch64_bev8, | |
| 174 | builtin.Arch.aarch64_bev8r, | |
| 175 | builtin.Arch.aarch64_bev8m_baseline, | |
| 176 | builtin.Arch.aarch64_bev8m_mainline, | |
| 177 | => true, | |
| 178 | else => false, | |
| 179 | }; | |
| 180 | ||
| 181 | const is_arm_arch = switch (builtin.arch) { | |
| 182 | builtin.Arch.armv8_3a, | |
| 183 | builtin.Arch.armv8_2a, | |
| 184 | builtin.Arch.armv8_1a, | |
| 185 | builtin.Arch.armv8, | |
| 186 | builtin.Arch.armv8r, | |
| 187 | builtin.Arch.armv8m_baseline, | |
| 188 | builtin.Arch.armv8m_mainline, | |
| 189 | builtin.Arch.armv7, | |
| 190 | builtin.Arch.armv7em, | |
| 191 | builtin.Arch.armv7m, | |
| 192 | builtin.Arch.armv7s, | |
| 193 | builtin.Arch.armv7k, | |
| 194 | builtin.Arch.armv7ve, | |
| 195 | builtin.Arch.armv6, | |
| 196 | builtin.Arch.armv6m, | |
| 197 | builtin.Arch.armv6k, | |
| 198 | builtin.Arch.armv6t2, | |
| 199 | builtin.Arch.armv5, | |
| 200 | builtin.Arch.armv5te, | |
| 201 | builtin.Arch.armv4t, | |
| 202 | builtin.Arch.armebv8_3a, | |
| 203 | builtin.Arch.armebv8_2a, | |
| 204 | builtin.Arch.armebv8_1a, | |
| 205 | builtin.Arch.armebv8, | |
| 206 | builtin.Arch.armebv8r, | |
| 207 | builtin.Arch.armebv8m_baseline, | |
| 208 | builtin.Arch.armebv8m_mainline, | |
| 209 | builtin.Arch.armebv7, | |
| 210 | builtin.Arch.armebv7em, | |
| 211 | builtin.Arch.armebv7m, | |
| 212 | builtin.Arch.armebv7s, | |
| 213 | builtin.Arch.armebv7k, | |
| 214 | builtin.Arch.armebv7ve, | |
| 215 | builtin.Arch.armebv6, | |
| 216 | builtin.Arch.armebv6m, | |
| 217 | builtin.Arch.armebv6k, | |
| 218 | builtin.Arch.armebv6t2, | |
| 219 | builtin.Arch.armebv5, | |
| 220 | builtin.Arch.armebv5te, | |
| 221 | builtin.Arch.armebv4t, | |
| 222 | builtin.Arch.aarch64v8_3a, | |
| 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 | 242 | nakedcc fn __aeabi_uidivmod() void { |
| 216 | 243 | @setRuntimeSafety(false); |
std/unicode.zig+16-16| ... | ... | @@ -208,7 +208,7 @@ pub const Utf8View = struct { |
| 208 | 208 | } |
| 209 | 209 | }; |
| 210 | 210 | |
| 211 | const Utf8Iterator = struct { | |
| 211 | pub const Utf8Iterator = struct { | |
| 212 | 212 | bytes: []const u8, |
| 213 | 213 | i: usize, |
| 214 | 214 | |
| ... | ... | @@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct { |
| 249 | 249 | pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 { |
| 250 | 250 | assert(it.i <= it.bytes.len); |
| 251 | 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 | 253 | if (c0 & ~u32(0x03ff) == 0xd800) { |
| 254 | 254 | // surrogate pair |
| 255 | 255 | it.i += 2; |
| 256 | 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 | 258 | if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf; |
| 259 | 259 | it.i += 2; |
| 260 | 260 | return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)); |
| ... | ... | @@ -510,46 +510,46 @@ test "utf16leToUtf8" { |
| 510 | 510 | const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); |
| 511 | 511 | |
| 512 | 512 | { |
| 513 | mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little); | |
| 514 | mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little); | |
| 513 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A'); | |
| 514 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a'); | |
| 515 | 515 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 516 | 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); | |
| 521 | mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little); | |
| 520 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80); | |
| 521 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff); | |
| 522 | 522 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 523 | 523 | assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf")); |
| 524 | 524 | } |
| 525 | 525 | |
| 526 | 526 | { |
| 527 | 527 | // the values just outside the surrogate half range |
| 528 | mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little); | |
| 529 | mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little); | |
| 528 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff); | |
| 529 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000); | |
| 530 | 530 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 531 | 531 | assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80")); |
| 532 | 532 | } |
| 533 | 533 | |
| 534 | 534 | { |
| 535 | 535 | // smallest surrogate pair |
| 536 | mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little); | |
| 537 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); | |
| 536 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800); | |
| 537 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); | |
| 538 | 538 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 539 | 539 | assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80")); |
| 540 | 540 | } |
| 541 | 541 | |
| 542 | 542 | { |
| 543 | 543 | // largest surrogate pair |
| 544 | mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); | |
| 545 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little); | |
| 544 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); | |
| 545 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff); | |
| 546 | 546 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 547 | 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); | |
| 552 | mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); | |
| 551 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); | |
| 552 | mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); | |
| 553 | 553 | const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); |
| 554 | 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 | 583 | while (it.nextCodepoint()) |codepoint| { |
| 584 | 584 | if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1; |
| 585 | 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 | 587 | end_index += 2; |
| 588 | 588 | } |
| 589 | 589 | return end_index / 2; |
test/behavior.zig+4| ... | ... | @@ -8,6 +8,7 @@ comptime { |
| 8 | 8 | _ = @import("cases/atomics.zig"); |
| 9 | 9 | _ = @import("cases/bitcast.zig"); |
| 10 | 10 | _ = @import("cases/bool.zig"); |
| 11 | _ = @import("cases/bswap.zig"); | |
| 11 | 12 | _ = @import("cases/bugs/1076.zig"); |
| 12 | 13 | _ = @import("cases/bugs/1111.zig"); |
| 13 | 14 | _ = @import("cases/bugs/1277.zig"); |
| ... | ... | @@ -41,6 +42,7 @@ comptime { |
| 41 | 42 | _ = @import("cases/if.zig"); |
| 42 | 43 | _ = @import("cases/import.zig"); |
| 43 | 44 | _ = @import("cases/incomplete_struct_param_tld.zig"); |
| 45 | _ = @import("cases/inttoptr.zig"); | |
| 44 | 46 | _ = @import("cases/ir_block_deps.zig"); |
| 45 | 47 | _ = @import("cases/math.zig"); |
| 46 | 48 | _ = @import("cases/merge_error_sets.zig"); |
| ... | ... | @@ -51,6 +53,7 @@ comptime { |
| 51 | 53 | _ = @import("cases/optional.zig"); |
| 52 | 54 | _ = @import("cases/pointers.zig"); |
| 53 | 55 | _ = @import("cases/popcount.zig"); |
| 56 | _ = @import("cases/ptrcast.zig"); | |
| 54 | 57 | _ = @import("cases/pub_enum/index.zig"); |
| 55 | 58 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); |
| 56 | 59 | _ = @import("cases/reflection.zig"); |
| ... | ... | @@ -64,6 +67,7 @@ comptime { |
| 64 | 67 | _ = @import("cases/switch_prong_implicit_cast.zig"); |
| 65 | 68 | _ = @import("cases/syntax.zig"); |
| 66 | 69 | _ = @import("cases/this.zig"); |
| 70 | _ = @import("cases/truncate.zig"); | |
| 67 | 71 | _ = @import("cases/try.zig"); |
| 68 | 72 | _ = @import("cases/type_info.zig"); |
| 69 | 73 | _ = @import("cases/undefined.zig"); |
test/cases/asm.zig+24| ... | ... | @@ -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 | 44 | extern fn aoeu() i32; |
| 21 | 45 | |
| 22 | 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 | 452 | var c: *u32 = @ptrCast(*u32, ptr2.?); |
| 453 | 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 | 5 | children: []Node, |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | const NodeAligned = struct { | |
| 9 | payload: i32, | |
| 10 | children: []align(@alignOf(NodeAligned)) NodeAligned, | |
| 11 | }; | |
| 12 | ||
| 8 | 13 | test "struct contains slice of itself" { |
| 9 | 14 | var other_nodes = []Node{ |
| 10 | 15 | Node{ |
| ... | ... | @@ -41,3 +46,40 @@ test "struct contains slice of itself" { |
| 41 | 46 | assert(root.children[2].children[0].payload == 31); |
| 42 | 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 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | 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 | 83 | cases.add( |
| 5 | 84 | "exceeded maximum bit width of integer", |
| 6 | 85 | \\export fn entry1() void { |
| ... | ... | @@ -1819,7 +1898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1819 | 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 | 1904 | cases.add( |
| ... | ... | @@ -2422,16 +2501,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2422 | 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 | 2504 | cases.add( |
| 2436 | 2505 | "colliding invalid top level functions", |
| 2437 | 2506 | \\fn func() bogus {} |
| ... | ... | @@ -3174,6 +3243,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3174 | 3243 | \\fn something() anyerror!void { } |
| 3175 | 3244 | , |
| 3176 | 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 | 3249 | cases.add( |
| ... | ... | @@ -4049,16 +4119,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4049 | 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 | 4122 | cases.add( |
| 4063 | 4123 | "compile-time division by zero", |
| 4064 | 4124 | \\comptime { |
| ... | ... | @@ -4081,16 +4141,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4081 | 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 | 4144 | cases.add( |
| 4095 | 4145 | "@setRuntimeSafety twice for same scope", |
| 4096 | 4146 | \\export fn foo() void { |
| ... | ... | @@ -5206,4 +5256,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5206 | 5256 | , |
| 5207 | 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 | 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 | 288 | cases.addRuntimeSafety("unwrap error", |
| 279 | 289 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 280 | 290 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { |